tech-net archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Reliability issues with BPF



Michael Richardson wrote:
"Greg" == Greg Troxel <gdt%ir.bbn.com@localhost> writes:
    >> For example, if I start tcpdump in the background
    >> and then run an ipv6 ping generating 2000 byte
    >> packets with a command like "ping6 -nc3 -s2000 fec0::1",
    >> the ping ends successfully but terminating the
    >> tcpdump may show as few as 8 packets rather than
    >> 12. 3 packets going in each direction (echo plus
    >> echo reply) makes 6, doubled for fragments gives
    >> 12. I can't for the life of me think why this
    >> should be.

    Greg> Are you waiting long enough?  IIRC there are two buffers, and read
    Greg> returns when they get full or timeout, and I don't know that ^C causes
    Greg> the final read.

This sounds reasonable to me.
ktruss it and see.

Perhaps libpcap needs some changes, or perhaps the kernel needs some.
Send patches to tcpdump.org via github please.

I've added this on sourceforge:
https://sourceforge.net/tracker/?func=detail&aid=3546396&group_id=53067&atid=469579

It seems like a relatively straight forward change:
- if pcap loop has been broken because of EINTR
 and if pcap is working in blocking mode,
 set non-blocking mode and attempt to read any
 packets that are currently buffered.

It solved 93% of the issues I saw with tcpdump not
returning the correct number of packets (13 out of
14 tests showed improvement.) The last one seemed
like a more complex timing issue.

A copy of the patch and problem has been filed with GNATS:
bin/46729: tcpdump does not read all buffered packets on Ctrl-C
http://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=46729

... Note that patches have been copy-pasted, so there will
be a lack of TABS...

In reflection, it might be tempting to approach the solution
with a different patch: if the current behaviour is blocking
and non-blocking can be successfully set, continue looping
unti there is no more data (would then flush both buffers)
and then return EINTR. However that behaviour is much more
dependent on the reader not returning 0 (e.g. because of
EWOULDBLOCK) and thus loop'ing around the read(), so I'm
not entirely sure that it is sensible. A similar question
might be asked about whether to do the read_op() twice as
BPF has two buffers where data might be present, but then
that behaviour is specific to BPF.
read

Darren



Home | Main Index | Thread Index | Old Index