On Mar 27, 2014, at 1:50 PM, John Farnsworth <john.farnswo...@imc-chicago.com> wrote:
>> If your application is expecting a low rate of packet delivery and needs to >> see packets as soon as they arrive, it should simply call >> pcap_set_immediate_mode() if it is available, regardless of what operating >> system it's running on or what version of libpcap it's using (as long as >> that version *has* pcap_set_immediate_mode()); "show me packets as soon as >> they arrive" is *exactly* what "immediate mode" means. (On systems with >> BPF, it turns on BPF's "immediate mode" - the name for it in libpcap was >> taken from BPF! - which disables the buffering and timeout.) > > This is where my problem lives: if you use an older version of libpcap such > as many Linux distributions still provide, you will get the behavior using > pcap_open_live equivalent to immediate mode. Perhaps better phrased as "you happen to get behavior equivalent to immediate mode"; this isn't by design, it's by lack of a timeout-based buffering mechanism in TPACKET_V2, TPACKET_V1, and the pre-turbopacket "read a packet at a time with recvmsg()" kernel code paths. At least as far back as libpcap 0.7, the pcap man page said: The read timeout is used to arrange that the read not necessarily return immediately when a packet is seen, but that it wait for some amount of time to allow more packets to arrive and to read multiple packets from the OS kernel in one operation. Not all platforms support a read timeout; on platforms that don't, the read timeout is ignored. which indicates that there's no guarantee of immediate packet delivery - and no explicit claim that some *particular* platforms provide immediate packet delivery in all cases. > However, I don't see a method to place logic into code to invoke > pcap_set_immediate_mode only if it exists, as I can't trust it to exist, > since it is new. Yet I must specify it to retain legacy behavior. This puts > me in an odd dependency loop that I must make I suppose 2 versions of the > application, one against libpcap 1.5 and one against libpcap 1.2 and expect > the newer one to fail to compile against the older lib. Another alternative, if your app is linked dynamically with libpcap, is to try using dlopen() to load libpcap.so (I *think* the glibc dynamic loader is smart enough to recognize that the library is already loaded, and just give you a handle for it), use dlsym() to find a pointer to pcap_set_immediate_mode(), and, if the pointer is found, call through that pointer with the appropriate arguments. (This is a technique commonly used on Windows with its equivalent APIs, LoadLibrary()/GetModuleHandle() and GetProcAddress(), to handle APIs present in some OS versions but not others, and was also used on Linux, with libpcap, in Wireshark at one point.) > I was hoping there was some sort of API version that I could identify using a > #ifdef to macro out the code rather than doing ugly things like autoconf > external version identification, but I couldn't find it, just the > pcap_lib_version, which doesn't help for that situation. Whether using compile-time version-number #ifdefs is less ugly than using autoconf is a matter of opinion. :-) The autoconf developers, not surprisingly :-), would suggest using autoconf, as what you *really* want to know is "does this version of libpcap support pcap_set_immediate_mode()", not "what version of libpcap is this" - determining the libpcap version is just a way to discover whether it has pcap_set_immediate_mode(). > I realize this behavior is not guaranteed cross-platform, and that there are > very much 2 different expectations for the result of the pcap_loop. One should not expect immediate delivery on *any* platform unless the code calls pcap_set_immediate_mode(); one should, however, expect delivery within N milliseconds if a timeout of N was specified in pcap_open_live(), or was specified pcap_set_timeout() before calling pcap_activate(). > In my case, I'm looking for pcap_loop to trigger without a delay as soon as a > packet is available - and this is the behavior that existed in previous > versions ...*on Linux* (and some other platforms, such as IRIX). It was *not* the behavior that existed in *BSD or OS X or Solaris, for example; those platforms have *always* buffered packets and delivered them only if the buffer filled or the timeout expired. > I don't suggest this to be a bug - it's not, it's just a change in default > behavior from before which has some pretty significant impact. ...on applications that implicitly depended on a quirk of the implementation. _______________________________________________ tcpdump-workers mailing list tcpdump-workers@lists.tcpdump.org https://lists.sandelman.ca/mailman/listinfo/tcpdump-workers