Mailing List Archive

work queue support
Attached is an early, still very rough patch to add support for 'work
queues' to quagga. Along with second patch to convert rib_process'ing
in zebra_rib.c to use work_queues. These patches are a generic rework
of an earlier proof-of-concept version i had hacked directly into
zebra_rib.c. The proof-of-concept worked, but i havnt tested this
rework, it very likely has bugs :) (be glad to hear results of
testing - but dont try on anything but unimportant machine). I hope
to next look at converting code in bgpd to work_queues - which
hopefully would alleviate the bgp idle timeout problem.

Work queues allow often repeated work to be put onto a queue, to be
dealt with by the threads subsystem, rather than have to potentially
spend a long time on repeated work (and blocking the current thread).

The work queued, by default, is processed in a serial fashion. While
ideally a work_queue should be processable by one (user supplied)
work function, individual queue items can provide their own (useful
for serialising work to some object, where bulk of work is done via
one function, but occassionally an item may need to be worked in some
other way.) When processing work queues, the threads subsystem will
periodically check how much time has elapsed and yield control if
neccessary.

Code that currently spend long amounts of time iterating through a
list or route_table, processing each node and hence taking up lots
of time (and causing response problems in quagga) are ideal
candidates for porting to work queues. (eg zebra's rib processing,
bgpd's rib processing).

the basic units are:

work_queue_t - defines a work queue

work_queue_spec_t - the specification for a work queue, user
defines work function, default error strategy, optional error
handler, etc..

work_queue_item_t - an item of work, may optionally define its own
work_queue_spec_t to override the default work_queue spec.

Process is:

- initialises a new work queue, work_queue_new(). A work queue will
typically be long lived - length of the process - and be specific to
some task. Fill in the spec (esp the caller data deletion callback!)

- as and when needed, submit a work_queue_item_t to the queue:
- prepare some caller specific data structure
- work_queue_item_new()
- work_queue_spec_new() - /if/ item specific spec is required
- fill in spec, attach it to item
- attach caller specific data structure to item
- submit the item to the work_queue, work_queue_item_add

deletion of items and specs is done by the thread subsystem.

thats it.. thread subsystem takes care of rest. user's provided work
function will be called for each item submitted at some later stage
as the queue is processed. User's provided del_item_data callback
will be used when deleting items.

The work function can indicate by its return status what action the
work queue processing subsystem should take:

WQ_ERROR - run error handler, if provided
WQ_RETRY_NOW - retry immediately
WQ_RETRY_LATER - cease processing this work queue,
leave item on the queue.
WQ_REQUEUE - requeue the item for later processing, continue
on with queue

note that a retry counter is incremented for the item in the cases of
RETRY_NOW, RETRY_LATER and REQUEUE. If an item exceeds the
max_retries value in the spec, it is treated as an error, error
handler (if provided) is run and item is removed from queue.

thats about it really.. the thread.c scheduler will need more
tweaking i think (eg process_fd's shouldnt put an unlimited amount of
threads onto the ready list, perhaps max of 10 or 20 or so? also
events have top priority - they can starve the ready thread_list -
perhaps events should be queued onto the ready list).

regards,
--
Paul Jakma paul@clubi.ie paul@jakma.org Key ID: 64A2FF6A
warning: do not ever send email to spam@dishone.st
Fortune:
if (argc > 1 && strcmp(argv[1], "-advice") == 0) {
printf("Don't Panic!\n");
exit(42);
}
(Arnold Robbins in the LJ of February '95, describing RCS)
Re: work queue support [ In reply to ]
On Fri, 8 Aug 2003 11:54:09 +0100 (IST)
Paul Jakma <paul@clubi.ie> wrote:

> [some stuff about work queues]

Hello Paul,

I don't want to stop or even slow down your great activities, but reading your
description of the matter I think there is some re-invention of wheels inside.
Specifically I cannot imagine why you start to do kind of an own scheduling and
"handmade" threading.
If I had to somehow group the work of quaggad and the rest of the daemons I
would say there are simply synchronous and asynchronous jobs to do. As an sync
part I would see everything dealing with timeouts, keepalives and the like.
Therefore you need some sort of (high prio) time-event driven logic.
The async parts (entering routes, deleting routes, searching around in rib and
the like) looks like being queuable and some (or more) thread(s) can happily
work on that whenever there is time (low prio) and work.
Async looks like serialised work, one after another (looks more located in
quaggad). The (time-)sync parts look like one thread per peer session to me
(more located in bgpd or ospfd).
This is obviously only a very rough idea and you are far ahead of this with
your implementation, but anyway maybe a useful point for discussion.

Regards,
Stephan
Re: work queue support [ In reply to ]
On Fri, 8 Aug 2003, Stephan von Krawczynski wrote:

> Hello Paul,
>
> I don't want to stop or even slow down your great activities, but
> reading your description of the matter I think there is some
> re-invention of wheels inside. Specifically I cannot imagine why
> you start to do kind of an own scheduling and "handmade" threading.

I'm not starting anything, zebra^Wquagga already implements its own
internal, non-preemptible threading. look at lib/thread.{c,h} :) its
the very core of zebra. Look at thread_fetch() - thats a scheduler,
i'm just adding one line to it. :)

> daemons I would say there are simply synchronous and asynchronous
> jobs to do.

and polling for pending IO and timers (called 'events' in
zebra^Wquagga) and, with this patch, work queues. Indeed,
a framework to allow 'asynchronous' work is what this patch adds :) -
prime benefit being ability for a work queue to yield control of the
cpu.

> As an sync part I would see everything dealing with timeouts,
> keepalives and the like.

?

> Therefore you need some sort of (high prio) time-event driven
> logic. The async parts (entering routes, deleting routes, searching
> around in rib and the like) looks like being queuable

they are indeed. fact they are not causes huge problems.

> and some (or more) thread(s) can happily work on that whenever
> there is time (low prio) and work. Async looks like serialised
> work, one after another (looks more located in quaggad). The
> (time-)sync parts look like one thread per peer session to me (more
> located in bgpd or ospfd).

GNU Zebra^W^WQuagga is IO-event driven mostly. Most of the time a
good Quagga daemon should be asleep in kernel, waiting for IO to
occur, with a timeout set to correspond to next due timer event.
(again, see lib/thread.c, thread_fetch()).

All work, presently, occurs due to IO or timer events which have to
be serviced.

Yon Uriarte's Zebra Hacking Howto is a good introduction - an
archived a copy of it is on quagga.net - see the resources section.

> This is obviously only a very rough idea and you are far ahead of
> this with your implementation, but anyway maybe a useful point for
> discussion.

possibly.. but you need to come up with more specific ideas though.
:)

> Regards,
> Stephan

regards,
--
Paul Jakma paul@clubi.ie paul@jakma.org Key ID: 64A2FF6A
warning: do not ever send email to spam@dishone.st
Fortune:
In specifications, Murphy's Law supersedes Ohm's.
Re: work queue support [ In reply to ]
ok,

here's an updated patch, it even works. :)

would be really nice if someone would test this on a machine with a
protocol daemon that sees good bit of activity. (eg bgpd with busy
feeds talking to a zebra compiled with attached patches - bgpd can
be stock).

i'd like to trash out the lib/ changes and make sure their solid
enough before attacking bgpd/ -> the zebra/ changes have had prior
testing (one day of BGP 4xfeed load) and survived - the lib/ changes
are what need testing.

regards,
--
Paul Jakma paul@clubi.ie paul@jakma.org Key ID: 64A2FF6A
warning: do not ever send email to spam@dishone.st
Fortune:
With Congress, every time they make a joke it's a law; and every time
they make a law it's a joke.
-- Will Rogers