[tcpdump-workers] Re: Flush OS buffer before termination

2024-10-20 Thread Garri Djavadyan
On Sat, 2024-10-19 at 23:58 -0700, Guy Harris wrote:
> On Oct 19, 2024, at 5:01 PM, Garri Djavadyan 
> wrote:
> 
> > I am looking for a way to force tcpdump flush Linux OS buffer
> > before
> > terminating. I have checked the man page and the mailing list
> > archives
> > but did not manage to find anything related.
> > 
> > When I terminate tcpdump process with SIGINT or SIGTERM, the
> > process
> > quits immediately, leaving packets in the buffer. I know that the
> > signal USR2 forces the buffer to be flushed, but it does stop
> > filling
> > the buffer and the process remains active.
> > 
> > I have to use a very big buffer with a very slow storage, much
> > slower
> > than the rate of coming packets received by the filter, and it is
> > preferred not to lose a single packet after initiating termination
> > the
> > process.
> 
> OK, so is the buffer to which you're referring the buffer that holds
> captured packets for tcpdump to read, i.e. the *input* buffer for
> tcpdump, rather than, for example, the standard I/O buffer containing
> packet dissection text to be printed or the I/O buffer containing
> packets to be written to the file specified by -w, i.e. an *output*
> buffer for tcpdump?

Correct. I meant the input buffer, specified with the -B flag.

Regards,
Garri
___
tcpdump-workers mailing list -- tcpdump-workers@lists.tcpdump.org
To unsubscribe send an email to tcpdump-workers-le...@lists.tcpdump.org
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s


[tcpdump-workers] Flush OS buffer before termination

2024-10-19 Thread Garri Djavadyan
Hello everyone,

I am looking for a way to force tcpdump flush Linux OS buffer before
terminating. I have checked the man page and the mailing list archives
but did not manage to find anything related.

When I terminate tcpdump process with SIGINT or SIGTERM, the process
quits immediately, leaving packets in the buffer. I know that the
signal USR2 forces the buffer to be flushed, but it does stop filling
the buffer and the process remains active.

I have to use a very big buffer with a very slow storage, much slower
than the rate of coming packets received by the filter, and it is
preferred not to lose a single packet after initiating termination the
process. There are a few options to overcome the problem. For example,
by dumping packets to the memory storage first (e.g. /dev/shm) or to
keep the process active for sufficient amount of time after was is
decided to stop the activity. Still, I wonder if this can be done by
tcpdump itself.

I was checking the behaviour using Linux kernel version 6.11.3 and
tcpdump/libpcap version 4.99.5/1.10.5. 

Thank you.

Regards,
Garri
___
tcpdump-workers mailing list -- tcpdump-workers@lists.tcpdump.org
To unsubscribe send an email to tcpdump-workers-le...@lists.tcpdump.org
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s


[tcpdump-workers] Re: Flush OS buffer before termination

2024-10-20 Thread Garri Djavadyan
On Sun, 2024-10-20 at 10:27 -0700, Guy Harris wrote:
> On Oct 20, 2024, at 2:57 AM, Garri Djavadyan 
> wrote:
> 
> > > > I have to use a very big buffer with a very slow storage, much
> > > > slower
> > > > than the rate of coming packets received by the filter, and it
> > > > is
> > > > preferred not to lose a single packet after initiating
> > > > termination
> > > > the
> > > > process.
> > > 
> > > What do you mean by "with a very slow storage"?  You can set the
> > > size
> > > with -B, but that just tells the capture mechanism in the kernel
> > > how
> > > big a buffer to allocate.  It's not as if it tells it to be
> > > stored in
> > > some slower form of memory.
> > 
> > Let me show an example. To demonstrate the issue, I am generating
> > 2MB/s
> > stream of dummy packets:
> > 
> > [src]# pv -L 2M /dev/zero | dd bs=1472 > /dev/udp/192.168.0.1/12345
> > 
> > 
> > and dumping them to a storage, with cgroup-v2-restricted write
> > speed of
> > 1MB/s:
> > 
> > [dst]# lsblk /dev/loop0
> > NAME  MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
> > loop0   7:0    0  3.9G  0 loop /mnt/test
> > 
> > [dst]# cat /sys/fs/cgroup/test/io.max
> > 7:0 rbps=max wbps=1024000 riops=max wiops=max
> > 
> > 
> > To temporarily avoid kernel-level drops,
> 
> Emphasis on *temporarily* - 2MB/s worth of packet data can only be
> saved in its entirety if you have 2MB/s or greater write speed.

That is right. However, it also depends on how long one needs to
mediate mismatching rates using a large input buffer. For example, with
a 2GB input buffer and 1MB/s rate difference, one could safely be
filling the buffer for more than half an hour. Safe buffer draining
would help a lot in such situations.


> > it is clearly seen that the input buffer is being filled at 1MB/s
> > rate
> > (the diff between the generated traffic rate (2MB/s) and the
> > writing
> > speed of the storage (1MB/s):
> > 
> > tcpdump: 0 packets captured, 0 packets received by filter, 0
> > packets
> > dropped by kernel
> > tcpdump: 218 packets captured, 715 packets received by filter, 0
> > packets dropped by kernel
> 
> On all platforms, "packets captured" means "packets read from libpcap
> and written to the capture file".
> 
> On Linux, "packets received by filter" means "packets that passed the
> filter" (rather than "packets that were run through the filter,
> whether or not they passed the filter", which is what it means on
> *BSD/macOS/Solaris 11/AIX; unfortunately, you can't get the latter
> value from Linux and can't get the former value from BSD, so that
> value *can't* be made to mean the same thing on all platforms).  It
> includes packets that passed the filter but could not be added to the
> buffer because the buffer was full.
> 
> On Linux, "packets dropped by kernel" means "packets that passed he
> filter but could not be added to the buffer because the buffer was
> full".
> 
> (The pcap_stats man page has an entire paragraph devoted to giving
> the message that the meaning of the statistics differs between
> platforms.)
> 
> I.e., when tcpdump exits, the difference, on Linux, between "packets
> received by filter" and "packets captured" is, indeed, "packets
> dropped because tcpdump exited without draining the packet buffer". 
> (On *BSD/macOS/Solaris 11/AIX, the latter value cannot be determined,
> as per the above.)
> 
> > > > There are a few options to overcome the problem. For example,
> > > > by dumping packets to the memory storage first (e.g. /dev/shm)
> > > 
> > > Presumably meaning you specified "-w /dev/shm" or something such
> > > as
> > > that?
> > > 
> > > If so, how does that make a difference?
> > 
> > I mean I can first dump packets to the lightning-fast RAM storage
> > and
> > after being done with the capturing part, copy the dump to the slow
> > storage.
> 
> I.e., it means that, when you signal tcpdump to exit, it's not as far
> behind the capture mechanism with regards to writing to the capture
> file, because it's stalling less waiting for write() calls to finish
> (if the write rate limitation you mention limits the rate at which
> write() calls can push data to the file descriptor), so the "packets
> captured" count is larger.

Exactly.


> > I see. Thank you so much for the expl

[tcpdump-workers] Re: Flush OS buffer before termination

2024-10-20 Thread Garri Djavadyan
On Sun, 2024-10-20 at 01:03 -0700, Guy Harris wrote:
> 
> 
> > On Oct 20, 2024, at 12:11 AM, Garri Djavadyan
> >  wrote:
> > 
> > On Sat, 2024-10-19 at 23:58 -0700, Guy Harris wrote:
> > > On Oct 19, 2024, at 5:01 PM, Garri Djavadyan
> > > 
> > > wrote:
> > > 
> > > > I am looking for a way to force tcpdump flush Linux OS buffer
> > > > before
> > > > terminating. I have checked the man page and the mailing list
> > > > archives
> > > > but did not manage to find anything related.
> > > > 
> > > > When I terminate tcpdump process with SIGINT or SIGTERM, the
> > > > process
> > > > quits immediately, leaving packets in the buffer. I know that
> > > > the
> > > > signal USR2 forces the buffer to be flushed, but it does stop
> > > > filling
> > > > the buffer and the process remains active.
> > > > 
> > > > I have to use a very big buffer with a very slow storage, much
> > > > slower
> > > > than the rate of coming packets received by the filter, and it
> > > > is
> > > > preferred not to lose a single packet after initiating
> > > > termination
> > > > the
> > > > process.
> > > 
> > > OK, so is the buffer to which you're referring the buffer that
> > > holds
> > > captured packets for tcpdump to read, i.e. the *input* buffer for
> > > tcpdump, rather than, for example, the standard I/O buffer
> > > containing
> > > packet dissection text to be printed or the I/O buffer containing
> > > packets to be written to the file specified by -w, i.e. an
> > > *output*
> > > buffer for tcpdump?
> > 
> > Correct. I meant the input buffer, specified with the -B flag.
> 
> OK, so by "flushing" the buffer - which, for an input buffer, usually
> means discarding everything that's in the buffer and, for an output
> buffer, usually means writing the buffer contents to the target file
> - you meant "draining" the buffer, as in "processing all the packets
> in the buffer".

Thank you for the correction. Indeed, I should have used "draining"
here.


> > When I terminate tcpdump process with SIGINT or SIGTERM, the
> > process
> > quits immediately, leaving packets in the buffer. I know that the
> > signal USR2 forces the buffer to be flushed, but it does stop
> > filling
> > the buffer and the process remains active.
> 
> No, SIGUSR2 flushes the *output* buffer for the file being written to
> with -w.  The tcpdump man page does not make that clear; I will
> update it to do so.

Hmm. I see. Thank you in advance for updating the man page.


> > I have to use a very big buffer with a very slow storage, much
> > slower
> > than the rate of coming packets received by the filter, and it is
> > preferred not to lose a single packet after initiating termination
> > the
> > process.
> 
> What do you mean by "with a very slow storage"?  You can set the size
> with -B, but that just tells the capture mechanism in the kernel how
> big a buffer to allocate.  It's not as if it tells it to be stored in
> some slower form of memory.

Let me show an example. To demonstrate the issue, I am generating 2MB/s
stream of dummy packets:

[src]# pv -L 2M /dev/zero | dd bs=1472 > /dev/udp/192.168.0.1/12345


and dumping them to a storage, with cgroup-v2-restricted write speed of
1MB/s:

[dst]# lsblk /dev/loop0
NAME  MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
loop0   7:00  3.9G  0 loop /mnt/test

[dst]# cat /sys/fs/cgroup/test/io.max
7:0 rbps=max wbps=1024000 riops=max wiops=max


To temporarily avoid kernel-level drops, I set a 1GB (sufficient to get
needed packets before it overflows) input buffer:

[dst]# tcpdump -i veth0 -w /mnt/test/udp.pcap -B 1024000


Now, if start inspecting tcpdump's stats every second:

[dst]# while true; do killall -10 tcpdump; sleep 1; done


it is clearly seen that the input buffer is being filled at 1MB/s rate
(the diff between the generated traffic rate (2MB/s) and the writing
speed of the storage (1MB/s):

tcpdump: 0 packets captured, 0 packets received by filter, 0 packets
dropped by kernel
tcpdump: 218 packets captured, 715 packets received by filter, 0
packets dropped by kernel
tcpdump: 890 packets captured, 2145 packets received by filter, 0
packets dropped by kernel
tcpdump: 1575 packets captured, 3575 packets received by filter, 0
packets dropped by kernel
tcpdump: 2246 packets captured, 5005 packets received by filter, 0
packets dropped by kernel
tcpdump: 2931 packets captured, 6435 packets received