CVSROOT:        /cvs
Module name:    src
Changes by:     [email protected] 2020/12/26 09:30:59

Modified files:
        sys/net        : bpf.c bpfdesc.h 

Log message:
bpf(4): bpf_d struct: replace bd_rdStart member with bd_nreaders member

bd_rdStart is strange.  It nominally represents the start of a read(2)
on a given bpf(4) descriptor, but there are several problems with it:

1. If there are multiple readers, the bd_rdStart is not set by subsequent
readers, so their timeout is screwed up.  The read timeout should really
be tracked on a per-thread basis in bpfread().

2. We set bd_rdStart for poll(2), select(2), and kevent(2), even though
that makes no sense.  We should not be setting bd_rdStart in bpfpoll()
or bpfkqfilter().

3. bd_rdStart is buggy.  If ticks is 0 when the read starts then
bpf_catchpacket() won't wake up the reader.  This is a problem
inherent to the design of bd_rdStart: it serves as both a boolean
and a scalar value, even though 0 is a valid value in the scalar
range.

So let's replace it with a better struct member.  "bd_nreaders" is a
count of threads sleeping in bpfread().  It is incremented before a
thread goes to sleep in bpfread() and decremented when a thread wakes
up.  If bd_nreaders is greater than zero when we reach bpf_catchpacket()
and fbuf is non-NULL we wake up all readers.

The read timeout, if any, is now tracked locally by the thread in
bpfread().

Unlike bd_rdStart, bpfpoll() and bpfkqfilter() don't touch
bd_nreaders.

Prompted by mpi@.  Basic idea from dlg@.  Lots of input from dlg@.

Tested by dlg@ with tcpdump(8) (blocking read) and flow-collector
(https://github.com/eait-itig/flow-collector, non-blocking read).

ok dlg@

Reply via email to