Re: [tcpdump-workers] What's the correct new API to request pcap_linux to not open an eventfd

2022-07-05 Thread Bill Fenner via tcpdump-workers
--- Begin Message ---
Hi Denis,

Thanks for pointing out the manpage update.  I had old man pages (my work
is being done in the context of the 1.10 release).  What confused me is the
asymmetry of the API.  If you call pcap_setnonblock() on an
un-activated socket, it sets a flag and doesn't return an error.  But
pcap_getnonblock() returns an error, so you can not check the value on an
un-activated socket.

This is not a flaw, necessarily, just confusing.

Now that I understand this flow (I did not realize there were two different
implementations of pcap_setnonblock(), because I was focused on
pcap-linux.c and not on the important stuff in pcap.c) I think it's
straightforward to defer the opening of the eventfd to pcap_activate(), so
that we can avoid opening the eventfd altogether in nonblock mode.  I'll
see if I can update my changes accordingly.  Thank you for pointing out the
extra detail that helped me to understand.

  Bill
--- End Message ---
___
tcpdump-workers mailing list
tcpdump-workers@lists.tcpdump.org
https://lists.sandelman.ca/mailman/listinfo/tcpdump-workers


Re: [tcpdump-workers] What's the correct new API to request pcap_linux to not open an eventfd

2022-07-05 Thread Denis Ovsienko via tcpdump-workers
--- Begin Message ---
On Fri, 1 Jul 2022 13:55:30 -0400
Bill Fenner via tcpdump-workers 
wrote:

> If we set
> pcap_nonblock after pcap_create and before pcap_activate, we get -3 -
> which I don't get at all, unless, -3 means "you didn't activate the
> pcap yet". My naive reading of the Linux pcap_getnonblock code says
> it'll return the integer value of a bool, and I don't know how that
> can be -3.

Hello Bill.

The pcap_setnonblock(3PCAP) man page describes two functions:

int pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf);
int pcap_getnonblock(pcap_t *p, char *errbuf);

If your comments concern pcap_getnonblock(), what you describe is
consistent with the documented behaviour:

In pcap/pcap.h:

#define PCAP_ERROR_NOT_ACTIVATED-3  /* the capture needs to
be activated */

In the man page:

RETURN VALUE
   pcap_getnonblock()  returns  the  current ``non-blocking''
   state of the capture descriptor; it always  returns  0  on
   ``savefiles''.   If  called  on  a capture handle that has
   been created but not  activated,  PCAP_ERROR_NOT_ACTIVATED
   is returned.  If there is another error, PCAP_ERROR is re‐
   turned and errbuf is filled in with an  appropriate  error
   message.

Did you mean there is an issue with pcap_setnonblock()?

-- 
Denis Ovsienko
--- End Message ---
___
tcpdump-workers mailing list
tcpdump-workers@lists.tcpdump.org
https://lists.sandelman.ca/mailman/listinfo/tcpdump-workers


Re: [tcpdump-workers] What's the correct new API to request pcap_linux to not open an eventfd

2022-07-01 Thread Bill Fenner via tcpdump-workers
--- Begin Message ---
On Fri, May 20, 2022 at 6:10 PM Bill Fenner  wrote:

> On Fri, May 20, 2022 at 12:36 PM Guy Harris  wrote:
>
>> If it's putting them in non-blocking mode, and using some
>> select/poll/epoll/etc. mechanism in a single event loop, then the right
>> name for the API is pcap_setnonblock().  There's no need for an eventfd to
>> wake up the blocking poll() if there *is* no blocking poll(), so:
>>
>> if non-blocking mode is on before pcap_activate() is called, no
>> eventfd should be opened, and poll_breakloop_fd should be set to -1;
>>
>> if non-blocking mode is turned on after pcap_activate() is
>> called, the eventfd should be closed, and poll_breakloop_fd should be set
>> to -1;
>>
>> if non-blocking mode is turned *off* afterwards, an eventfd
>> should be opened, and poll_breakloop_fd should be set to it;
>>
>> if poll_breakloop_fd is -1, the poll() should only wait on the
>> socket FD;
>>
>> so this can be handled without API changes.
>>
>
> Thank you for the excellent observation, Guy.  It is indeed setting
> non-block before pcap_activate().  I'll work on this plan.
>

A slight variation of this plan is at
https://github.com/the-tcpdump-group/libpcap/pull/1113

I wrote a test program that doesn't do much, but does demonstrate that the
blocking-ness API on Linux is at least a little weird.  If we set
pcap_nonblock after pcap_create and before pcap_activate, we get -3 - which
I don't get at all, unless, -3 means "you didn't activate the pcap yet".
My naive reading of the Linux pcap_getnonblock code says it'll return the
integer value of a bool, and I don't know how that can be -3.

The sequence ends up being:
pcap_create() -> open eventfd
pcap_setnonblock() -> close eventfd
pcap_activate()

I didn't want to move the eventfd creation out of pcap_create without
having a deeper understanding of the strangeness around the nonblock API.

I ran 15,645 internal Arista tests using these changes, in an
infrastructure that relies on nonblocking pcap for packet exchange, and
they all passed.  Obviously this doesn't really say much about its general
applicability, and kind of is a no-brainer "when you don't need the eventfd
you don't notice if it's not there", but at least it says that things
aren't drastically broken.

  Bill
--- End Message ---
___
tcpdump-workers mailing list
tcpdump-workers@lists.tcpdump.org
https://lists.sandelman.ca/mailman/listinfo/tcpdump-workers


Re: [tcpdump-workers] What's the correct new API to request pcap_linux to not open an eventfd

2022-06-01 Thread Bill Fenner via tcpdump-workers
--- Begin Message ---
On Fri, May 20, 2022 at 6:10 PM Bill Fenner  wrote:

> On Fri, May 20, 2022 at 12:36 PM Guy Harris  wrote:
>
>> If it's putting them in non-blocking mode, and using some
>> select/poll/epoll/etc. mechanism in a single event loop, then the right
>> name for the API is pcap_setnonblock().  There's no need for an eventfd to
>> wake up the blocking poll() if there *is* no blocking poll(), so:
>>
>> if non-blocking mode is on before pcap_activate() is called, no
>> eventfd should be opened, and poll_breakloop_fd should be set to -1;
>>
>> if non-blocking mode is turned on after pcap_activate() is
>> called, the eventfd should be closed, and poll_breakloop_fd should be set
>> to -1;
>>
>> if non-blocking mode is turned *off* afterwards, an eventfd
>> should be opened, and poll_breakloop_fd should be set to it;
>>
>> if poll_breakloop_fd is -1, the poll() should only wait on the
>> socket FD;
>>
>> so this can be handled without API changes.
>>
>
> Thank you for the excellent observation, Guy.  It is indeed setting
> non-block before pcap_activate().  I'll work on this plan.
>

Actually, I confused myself.  It turns out that pcap_linux is buggy when
you set non-block before pcap_activate() -- it uses the handlep->timeout
value to remember whether or not non-block was set, but, pcap_activate()
unconditionally overwrites handlep->timeout.  So it just comes down to, for
now, we always open the eventfd and then can close it when non-blocking
mode is turned on.  This just means the first item on your list is not
done, but the last 3 are enough.

(I think that the right fix for setting nonblock before activate could be
to add a bool to the handlep, to separate the nonblock status from the
timeout, but that can be a separate fix.)

  Bill
--- End Message ---
___
tcpdump-workers mailing list
tcpdump-workers@lists.tcpdump.org
https://lists.sandelman.ca/mailman/listinfo/tcpdump-workers


Re: [tcpdump-workers] What's the correct new API to request pcap_linux to not open an eventfd

2022-05-20 Thread Bill Fenner via tcpdump-workers
--- Begin Message ---
On Fri, May 20, 2022 at 12:36 PM Guy Harris  wrote:

> If it's putting them in non-blocking mode, and using some
> select/poll/epoll/etc. mechanism in a single event loop, then the right
> name for the API is pcap_setnonblock().  There's no need for an eventfd to
> wake up the blocking poll() if there *is* no blocking poll(), so:
>
> if non-blocking mode is on before pcap_activate() is called, no
> eventfd should be opened, and poll_breakloop_fd should be set to -1;
>
> if non-blocking mode is turned on after pcap_activate() is called,
> the eventfd should be closed, and poll_breakloop_fd should be set to -1;
>
> if non-blocking mode is turned *off* afterwards, an eventfd should
> be opened, and poll_breakloop_fd should be set to it;
>
> if poll_breakloop_fd is -1, the poll() should only wait on the
> socket FD;
>
> so this can be handled without API changes.
>

Thank you for the excellent observation, Guy.  It is indeed setting
non-block before pcap_activate().  I'll work on this plan.

  Bill
--- End Message ---
___
tcpdump-workers mailing list
tcpdump-workers@lists.tcpdump.org
https://lists.sandelman.ca/mailman/listinfo/tcpdump-workers


Re: [tcpdump-workers] What's the correct new API to request pcap_linux to not open an eventfd

2022-05-20 Thread Guy Harris via tcpdump-workers
--- Begin Message ---
On May 20, 2022, at 10:56 AM, Bill Fenner via tcpdump-workers 
 wrote:

> I'm helping to debug a system that uses many many pcap handles, and never
> calls pcap_loop - only ever pcap_next.

Both pcap_loop() and pcap_next() ultimately go to the same place.

Note, BTW, that pcap_next() sucks; it's impossible to know whether it returns 
NULL because of an error or because the timeout expired and no packets had 
arrived during that time.  pcap_next_ex() doesn't have that problem.  (On 
Linux, the turbopacket timer doesn't expire if no packets have arrived, so, *on 
Linux*, NULL should, as far as I know, be returned only on errors.)

> We've found that each pcap handle has an associated eventfd, which is used to 
> make sure to wake up when
> pcap_breakloop() is called.  Since this code doesn't call pcap_loop or
> pcap_breakloop, the eventfd is unneeded.

If it called pcap_breakloop(), the eventfd would still be needed; otherwise, a 
call could remain indefinitely stuck in pcap_next() until a packet finally 
arrives.  Only the lack of a pcap_breakloop() call renders the eventfd 
unnecessary.

So how is this system handling those pcap handles?

If it's putting them in non-blocking mode, and using some 
select/poll/epoll/etc. mechanism in a single event loop, then the right name 
for the API is pcap_setnonblock().  There's no need for an eventfd to wake up 
the blocking poll() if there *is* no blocking poll(), so:

if non-blocking mode is on before pcap_activate() is called, no eventfd 
should be opened, and poll_breakloop_fd should be set to -1;

if non-blocking mode is turned on after pcap_activate() is called, the 
eventfd should be closed, and poll_breakloop_fd should be set to -1;

if non-blocking mode is turned *off* afterwards, an eventfd should be 
opened, and poll_breakloop_fd should be set to it;

if poll_breakloop_fd is -1, the poll() should only wait on the socket 
FD;

so this can be handled without API changes.

If it's doing something else, e.g. using multiple threads, then:

> I'm willing to write and test the code that skips creating the breakloop_fd
> - but, I wanted to discuss what the API should be.  Should there be a
> pcap.c "pcap_breakloop_not_needed( pcap_t * )" that dispatches to the
> implementation, or should there be a linux-specific
> "pcap_linux_dont_create_eventfd( pcap_t * )"?

...it should be called pcap_breakloop_not_needed() (or something such as that), 
with a per-type implementation, and a *default* implementation that does 
nothing, so only implementations that need to do something different would need 
to do so.
--- End Message ---
___
tcpdump-workers mailing list
tcpdump-workers@lists.tcpdump.org
https://lists.sandelman.ca/mailman/listinfo/tcpdump-workers


[tcpdump-workers] What's the correct new API to request pcap_linux to not open an eventfd

2022-05-20 Thread Bill Fenner via tcpdump-workers
--- Begin Message ---
I'm helping to debug a system that uses many many pcap handles, and never
calls pcap_loop - only ever pcap_next.  We've found that each pcap handle
has an associated eventfd, which is used to make sure to wake up when
pcap_breakloop() is called.  Since this code doesn't call pcap_loop or
pcap_breakloop, the eventfd is unneeded.

I'm willing to write and test the code that skips creating the breakloop_fd
- but, I wanted to discuss what the API should be.  Should there be a
pcap.c "pcap_breakloop_not_needed( pcap_t * )" that dispatches to the
implementation, or should there be a linux-specific
"pcap_linux_dont_create_eventfd( pcap_t * )"?

For this use case, portability is not important, so I would be fine with
either. I'd also be fine with less ridiculous name suggestions :-)

Thanks,
  Bill
--- End Message ---
___
tcpdump-workers mailing list
tcpdump-workers@lists.tcpdump.org
https://lists.sandelman.ca/mailman/listinfo/tcpdump-workers