Re: bpf/pcap are weird

From: Guy Harris (guy_at_alum.mit.edu)
Date: 11/06/03

  • Next message: Bruce Evans: "Re: >0x7fffffff blocksize filesystem reporting"
    Date: Thu, 6 Nov 2003 00:38:48 -0800
    To: Bruce Evans <bde@zeta.org.au>
    
    

    > bpfpoll() is reported to be broken; see PR 36219.

    Yes, that's the PR that indicated that "select()"/"poll()" don't, in
    fact, work correctly with timeouts.

    That was fixed in 4.5...

    > Rev.1.113 of bpf.c may have disturbed this.

    ...but might have been re-broken.

    > It removed the comment which said that
    > bpf_ready() doesn't acually imitate resultof(FIONREAD) != 0.

    ...and it also removed the check for "d->bd_state == BPF_TIMED_OUT" that
    made "select()"/"poll()" work with timeouts.

    And, unfortunately, it looks as if that's in 4.9 - revision 1.59.2.13
    has it, and that's tagged with RELENG_4_9_0_RELEASE.

    If non-blocking reads *do* cause buffer rotation if necessary, this can,
    at least for "select()"/"poll()"-based applications that can control the
    timeout in their select loop, be worked around by making the timeout
    timer be a timeout in "select()" or "poll()", putting the BPF device in
    non-blocking mode (for which there is an API in recent versions of
    libpcap, and in older versions you can just set the flag on the
    descriptor you get from "pcap_fileno()"), and reading from the BPF
    device (or the pcap_t) either if "select()"/"poll()" says you can *or*
    the "select()"/"poll()" timer has expired.

    If they don't cause a buffer rotation, however, you're screwed unless
    there's some other way to force the buffer rotation.

    Turning BIOCIMMEDIATE mode on would take care of that - but it would
    also turn off packet buffering, which might cause too much CPU overhead
    when capturing on a busy network. (Or it might not; I don't know
    whether anybody's measured it.)

    However, in 4.9, a buffer rotation will be done in "bpf_read()" if a
    timeout has occurred, so it looks as if that workaround would work.

    In 4.x releases from 4.5 through 4.8, "select()"/"poll()" should, I
    thihnk, work with timeouts, and reads after a timeout has occurred
    should rotate the buffers even if the timeout occurred before the
    "read()" (such as in a "select()"/"poll()").

    In releases prior to 4.4, "select()"/"poll()" won't work with timeouts -
    but non-blocking reads will force a buffer rotation; if the hold buffer
    is empty, and IO_NDELAY is set in "ioflag", "error" will be set to
    EWOULDBLOCK, and it'll eventually fall through to the "rotate buffers if
    EWOULDBLOCK is true, the hold buffer is empty, and the store buffer
    isn't" code.

    In 4.4, "bpf_read()" was changed (revision 1.59.2.5, MFC of 1.72) so
    that if the hold buffer is empty, and IO_NDELAY is set in "ioflag",
    it'll return EWOULDBLOCK. I.e., it was changed so that non-blocking
    reads *won't* force a buffer rotation; the comment for 1.72 is

            Fix bug: a read() on a bpf device which was in non-blocking mode
            and had no data available returned 0. Now it returns -1 with
            errno set to EWOULDBLOCK (== EAGAIN) as it should. This fix
            makes the bpf device usable in threaded programs.

    (It didn't make it usable, as far as I know, because the
    "select()"/"poll()" behavior also had to be fixed.)

    I don't know whether there's a PR for that bug or not. I have vague
    memories of seeing the problem reported, but it might've been in one of
    the mailing lists. I don't remember what the symptoms were, but it
    *might* mean that making non-blocking reads always rotate the buffers
    might cause a regression.

    Unfortunately, having non-blocking reads not force a buffer rotation
    means that the workaround for the BPF "select()"/"poll()" will, I think,
    not work - and it's not obvious how to make it work.

    (This means that if I make Ethereal register the pcap_t descriptor in
    the GTK+ main loop, and have the main loop wait both for UI events and
    packet arrival, that probably won't work on FreeBSD 4.4....)
    _______________________________________________
    freebsd-arch@freebsd.org mailing list
    http://lists.freebsd.org/mailman/listinfo/freebsd-arch
    To unsubscribe, send any mail to "freebsd-arch-unsubscribe@freebsd.org"


  • Next message: Bruce Evans: "Re: >0x7fffffff blocksize filesystem reporting"

    Relevant Pages

    • Re: Some questions on writing data to a serial port?
      ... int serial_write ... while (nbytes < count) { ... O_NONBLOCK) to implement a timeout. ... buffer cache, which is flushed to the server asynchronously. ...
      (comp.unix.programmer)
    • Re: Programmatically using ping (IcmpSendcho2 and IcmpParseReplies)
      ... The biggest problem is the documentation. ... When you use IcmpSendcho2 asynchronously, with IcmpParseReplies, ... this buffer must exist until the ping attempt is completed. ... timeout is expired, your program will crash in Vista. ...
      (microsoft.public.win32.programmer.networks)
    • Programmatically using ping (IcmpSendcho2 and IcmpParseReplies)
      ... The "blessed" way to send ping messages, and the only nonprivileged way to ... When you use IcmpSendcho2 asynchronously, with IcmpParseReplies, ... this buffer must exist until the ping attempt is completed. ... timeout is expired, your program will crash in Vista. ...
      (microsoft.public.win32.programmer.networks)
    • Re: setvbuf accross exec
      ... buffer, e.g. a pty. ... if an application is flushing each buffer? ... that the output isn't being flushed if the timeout isn't ... There is no timeout value for a flush. ...
      (comp.unix.programmer)

  • Quantcast