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@