[Click] Queues and notifications

Eddie Kohler kohler at cs.ucla.edu
Thu Jan 25 18:56:22 EST 2007


Hi guys,

Thanks for continuing to report this problem.  I did manage to reproduce 
it and, hopefully, fix it.  But I wonder whether we could fix it in a 
better way.

Mike, RawSocket did use notifiers.  This is all about notifiers.

Here's the deal.  Consider this configuration containing DelayShaper.

        ... -> q::Queue -> d::DelayShaper(10s) -> x::ToDevice;

Say that "q" has a packet in it.  Then q's notifier is active.  Should 
"x" poll to get that packet?  NO!  Because it will poll for 10 solid 
seconds before "d" will release the first packet!

Instead, Click introduces another notifier, in the DelayShaper d.  This 
notifier turns on **only when d is ready to release a packet**.  In our 
config above, then, x has d's notifier, not q's notifier.

Initially we have this status

        ... -> q::Queue -> d::DelayShaper(10s) -> x::ToDevice;
               INACTIVE         INACTIVE          UNSCHEDULED

What happens when q gets a packet??  We want q to wake up x; since d is 
a shaper, it should be passive, and x is the eventual packet consumer. 
But x points at d's notifier!!  No problem; the 
upstream_empty_notifier() process actually searches the graph TWICE, 
once to develop a signal and once for registering wakeups.  That creates 
this situation:

        ... -> q::Queue -> d::DelayShaper(10s) -> x::ToDevice;
               INACTIVE         INACTIVE          UNSCHEDULED
                   |               ^                  |   ^
                   |               +-------signal-----+   |
                   +-------------wakes up-----------------+

q will wake up x, which will then poll d.  Right?

Except that at the time x wakes up, **d's signal is still inactive.**

Most Click elements, including Discard, handled this case correctly. 
When the task was rescheduled, they would pull upstream *before* 
checking the signal.  But some Click elements did NOT handle this case 
correctly.  They checked the signal *before* pulling upstream, which 
meant (since d's signal is inactive here) that they never worked with 
DelayShaper.  The elements: LinkUnqueue, RawSocket, Socket, and 
userlevel ToDevice.

A related problem afflicted schedulers; a scheduler element, such as 
RoundRobinSched, that had DelayUnqueues upstream would NEVER work 
correctly since it looked at the wrong notifier.

I've fixed this in one way, namely by changing code like RawSocket to 
pull before checking notifiers.  But now I think it would be better for 
q to update d's signal when it wakes up x.  Not completely sure how to 
implement this.... But Mike, Geoffrey, others using CVS, could you 
update and see if you are still having scheduling problems?

Eddie







Mike Wilson wrote:
> I've got a large, complex click config where I read from UDP sockets and 
> write to a raw socket, routing packets from UDP tunnels.  Unfortunately, I 
> can't seem to get notifications working in the Queues.
> 
> I've stripped the config down to a fairly simple case that replicates the 
> problem, at least on my system.  If I use Queue or NotifierQueue 
> components for the queues, I either get nothing out the interface, or I 
> get 1-2 packets and then nothing.  If I use a SimpleQueue, everything 
> works just fine.
> 
> My limited understanding is that the SimpleQueue doesn't do notifiers, so 
> the pull components downstream must use polling.  In other words, it's a 
> massive CPU hog - I get 99% utilization to click with a SimpleQueue.  With 
> Queue, I don't even see click in my top(1) list.
> 
> Am I mis-using the queue components somehow, or is this a bug?  Do 
> RawSockets use notifiers?
> 
> -Mike Wilson
> 
> ---replication example---
> 
> // Warning, this config will send bogus UDP packets to 172.16.46.20.
> // Unfortunately, the problem doesn't manifest with a Discard at the end.
> 
> AddressInfo(myip  128.252.160.209,
>              NetRtr 172.16.46.12,
>              HostRtr 172.16.46.20,
>              NetRoute 172.16.46.0/24);
> 
> PortInfo(NetTun 0xA121,
>           HostTun 0xA122);
> 
> out :: RawSocket("UDP");
> rt :: RangeIPLookup(NetRoute  0, HostRtr 1);
> sched :: DRRSched();
> 
> TimedSource -> UDPIPEncap(HostRtr, 5005, HostRtr, 5005) -> 
> IPPrint("Injecting Packet") -> check :: CheckIPHeader;
> Idle -> rt;
> 
> check[1] -> Print("Injected Bad packet") -> Discard;
> check[0] -> IPPrint("Injected Valid Packet") -> GetIPAddress(16) -> rt;
> 
> rt[0] -> UDPIPEncap(myip, NetTun, NetRtr, NetTun) -> IPPrint("Net Route") 
> -> SimpleQueue -> [0]sched;
> rt[1] -> UDPIPEncap(myip, HostTun, HostRtr, HostTun) -> IPPrint("Host 
> Route") -> SimpleQueue -> [1]sched;
> 
> sched -> IPPrint("Sending") -> out;
> 
> _______________________________________________
> click mailing list
> click at amsterdam.lcs.mit.edu
> https://amsterdam.lcs.mit.edu/mailman/listinfo/click


More information about the click mailing list