Subject: [tcpm] Linux doesn't do ZWP correctly???

From: David Borman <[email-masked]>
Date: Thu, 7 Nov 2013 20:46:53 +0000

I’ve been doing some testing of crossing Zero Window Probes, and it appears that the Linux TCP doesn’t do ZWP properly.  It is missing the 1 byte of data.

My test program creates a pair of sockets, sets SO_RCVBUF to 20K and SO_SNDBUF to 80K on both sides, then writes 40K of data in both directions.  It then pauses for 20 seconds to allow some ZWP packets, reads 1 byte of data from both sides, pauses another 20 seconds and then reads all the data from both sockets.  I ran tcpdump to watch the packet traffic.  Below are packet traces from both a Fedora Core 19 and a FreeBSD 9.2 system.  The FreeBSD trace has what I would expect to see, the Linux trace doesn’t send any data on the probes.

Any thoughts on this?

			-David Borman

# uname -a
Linux dab-fc17-vm.mdh.quantum.com 3.11.6-200.fc19.x86_64 #1 SMP Fri Oct 18 22:34:18 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
# tcpdump -i lo
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 65535 bytes
14:52:24.676876 IP localhost.56771 > localhost.57737: Flags [S], seq 1095762115, win 20480, options [mss 65495,sackOK,TS val 106278 ecr 0,nop,wscale 0], length 0
14:52:24.676905 IP localhost.57737 > localhost.56771: Flags [S.], seq 894566307, ack 1095762116, win 20480, options [mss 65495,sackOK,TS val 106278 ecr 106278,nop,wscale 0], length 0
14:52:24.676920 IP localhost.56771 > localhost.57737: Flags [.], ack 1, win 20480, options [nop,nop,TS val 106278 ecr 106278], length 0
14:52:24.677292 IP localhost.56771 > localhost.57737: Flags [.], seq 1:10241, ack 1, win 20480, options [nop,nop,TS val 106278 ecr 106278], length 10240
14:52:24.677303 IP localhost.57737 > localhost.56771: Flags [.], ack 10241, win 10240, options [nop,nop,TS val 106278 ecr 106278], length 0
14:52:24.677316 IP localhost.56771 > localhost.57737: Flags [P.], seq 10241:20481, ack 1, win 20480, options [nop,nop,TS val 106278 ecr 106278], length 10240
14:52:24.678314 IP localhost.57737 > localhost.56771: Flags [.], seq 1:10241, ack 20481, win 0, options [nop,nop,TS val 106279 ecr 106278], length 10240
14:52:24.678340 IP localhost.56771 > localhost.57737: Flags [.], ack 10241, win 10240, options [nop,nop,TS val 106279 ecr 106279], length 0
14:52:24.678360 IP localhost.57737 > localhost.56771: Flags [P.], seq 10241:20481, ack 20481, win 0, options [nop,nop,TS val 106279 ecr 106278], length 10240
14:52:24.717804 IP localhost.56771 > localhost.57737: Flags [.], ack 20481, win 0, options [nop,nop,TS val 106319 ecr 106279], length 0
14:52:24.879723 IP localhost.56771 > localhost.57737: Flags [.], ack 20481, win 0, options [nop,nop,TS val 106481 ecr 106279], length 0
14:52:24.879833 IP localhost.57737 > localhost.56771: Flags [.], ack 20481, win 0, options [nop,nop,TS val 106481 ecr 106319], length 0
14:52:24.923707 IP localhost.57737 > localhost.56771: Flags [.], ack 20481, win 0, options [nop,nop,TS val 106525 ecr 106319], length 0
14:52:24.923820 IP localhost.56771 > localhost.57737: Flags [.], ack 20481, win 0, options [nop,nop,TS val 106525 ecr 106481], length 0
14:52:25.283492 IP localhost.56771 > localhost.57737: Flags [.], ack 20481, win 0, options [nop,nop,TS val 106884 ecr 106481], length 0
14:52:25.283599 IP localhost.57737 > localhost.56771: Flags [.], ack 20481, win 0, options [nop,nop,TS val 106885 ecr 106525], length 0
14:52:25.335722 IP localhost.57737 > localhost.56771: Flags [.], ack 20481, win 0, options [nop,nop,TS val 106937 ecr 106525], length 0
14:52:25.335839 IP localhost.56771 > localhost.57737: Flags [.], ack 20481, win 0, options [nop,nop,TS val 106937 ecr 106885], length 0
14:52:26.090812 IP localhost.56771 > localhost.57737: Flags [.], ack 20481, win 0, options [nop,nop,TS val 107692 ecr 106885], length 0
14:52:26.090919 IP localhost.57737 > localhost.56771: Flags [.], ack 20481, win 0, options [nop,nop,TS val 107692 ecr 106937], length 0
14:52:26.159642 IP localhost.57737 > localhost.56771: Flags [.], ack 20481, win 0, options [nop,nop,TS val 107761 ecr 106937], length 0
14:52:26.159686 IP localhost.56771 > localhost.57737: Flags [.], ack 20481, win 0, options [nop,nop,TS val 107761 ecr 107692], length 0
14:52:27.703494 IP localhost.56771 > localhost.57737: Flags [.], ack 20481, win 0, options [nop,nop,TS val 109304 ecr 107692], length 0
14:52:27.703541 IP localhost.57737 > localhost.56771: Flags [.], ack 20481, win 0, options [nop,nop,TS val 109304 ecr 107761], length 0
14:52:27.803683 IP localhost.57737 > localhost.56771: Flags [.], ack 20481, win 0, options [nop,nop,TS val 109405 ecr 107761], length 0
14:52:27.803792 IP localhost.56771 > localhost.57737: Flags [.], ack 20481, win 0, options [nop,nop,TS val 109405 ecr 109304], length 0
14:52:30.927667 IP localhost.56771 > localhost.57737: Flags [.], ack 20481, win 0, options [nop,nop,TS val 112529 ecr 109304], length 0
14:52:30.927712 IP localhost.57737 > localhost.56771: Flags [.], ack 20481, win 0, options [nop,nop,TS val 112529 ecr 109405], length 0
14:52:31.087676 IP localhost.57737 > localhost.56771: Flags [.], ack 20481, win 0, options [nop,nop,TS val 112689 ecr 109405], length 0
14:52:31.087788 IP localhost.56771 > localhost.57737: Flags [.], ack 20481, win 0, options [nop,nop,TS val 112689 ecr 112529], length 0
14:52:37.375727 IP localhost.56771 > localhost.57737: Flags [.], ack 20481, win 0, options [nop,nop,TS val 118977 ecr 112529], length 0
14:52:37.375832 IP localhost.57737 > localhost.56771: Flags [.], ack 20481, win 0, options [nop,nop,TS val 118977 ecr 112689], length 0
14:52:37.664034 IP localhost.57737 > localhost.56771: Flags [.], ack 20481, win 0, options [nop,nop,TS val 119265 ecr 112689], length 0
14:52:37.664358 IP localhost.56771 > localhost.57737: Flags [.], ack 20481, win 0, options [nop,nop,TS val 119265 ecr 118977], length 0
14:52:50.271699 IP localhost.56771 > localhost.57737: Flags [.], ack 20481, win 0, options [nop,nop,TS val 131873 ecr 118977], length 0
14:52:50.271807 IP localhost.57737 > localhost.56771: Flags [.], ack 20481, win 0, options [nop,nop,TS val 131873 ecr 119265], length 0
14:52:50.815486 IP localhost.57737 > localhost.56771: Flags [.], ack 20481, win 0, options [nop,nop,TS val 132416 ecr 119265], length 0
14:52:50.815600 IP localhost.56771 > localhost.57737: Flags [.], ack 20481, win 0, options [nop,nop,TS val 132416 ecr 131873], length 0
14:53:04.679770 IP localhost.57737 > localhost.56771: Flags [.], ack 20481, win 20480, options [nop,nop,TS val 146281 ecr 132416], length 0
14:53:04.679790 IP localhost.56771 > localhost.57737: Flags [.], seq 20481:30721, ack 20481, win 0, options [nop,nop,TS val 146281 ecr 146281], length 10240
14:53:04.679795 IP localhost.56771 > localhost.57737: Flags [P.], seq 30721:40961, ack 20481, win 0, options [nop,nop,TS val 146281 ecr 146281], length 10240
14:53:04.679908 IP localhost.56771 > localhost.57737: Flags [.], ack 20481, win 20480, options [nop,nop,TS val 146281 ecr 146281], length 0
14:53:04.679916 IP localhost.57737 > localhost.56771: Flags [.], seq 20481:30721, ack 40961, win 0, options [nop,nop,TS val 146281 ecr 146281], length 10240
14:53:04.679926 IP localhost.57737 > localhost.56771: Flags [P.], seq 30721:40961, ack 40961, win 0, options [nop,nop,TS val 146281 ecr 146281], length 10240
14:53:04.679941 IP localhost.56771 > localhost.57737: Flags [.], ack 30721, win 10240, options [nop,nop,TS val 146281 ecr 146281], length 0
14:53:04.679966 IP localhost.57737 > localhost.56771: Flags [.], ack 40961, win 20480, options [nop,nop,TS val 146281 ecr 146281], length 0
14:53:04.679974 IP localhost.56771 > localhost.57737: Flags [.], seq 40961:51201, ack 40961, win 0, options [nop,nop,TS val 146281 ecr 146281], length 10240
14:53:04.679978 IP localhost.56771 > localhost.57737: Flags [P.], seq 51201:61441, ack 40961, win 0, options [nop,nop,TS val 146281 ecr 146281], length 10240
14:53:04.680002 IP localhost.56771 > localhost.57737: Flags [.], ack 40961, win 20480, options [nop,nop,TS val 146281 ecr 146281], length 0
14:53:04.680013 IP localhost.57737 > localhost.56771: Flags [.], seq 40961:51201, ack 61441, win 0, options [nop,nop,TS val 146281 ecr 146281], length 10240
14:53:04.680018 IP localhost.57737 > localhost.56771: Flags [P.], seq 51201:61441, ack 61441, win 0, options [nop,nop,TS val 146281 ecr 146281], length 10240
14:53:04.680042 IP localhost.57737 > localhost.56771: Flags [.], ack 61441, win 20480, options [nop,nop,TS val 146281 ecr 146281], length 0
14:53:04.680049 IP localhost.56771 > localhost.57737: Flags [.], seq 61441:71681, ack 61441, win 0, options [nop,nop,TS val 146281 ecr 146281], length 10240

The trace from a FreeBSD 9.2 system looks like this:

# uname -a
FreeBSD fbsd90-64 9.2-RELEASE FreeBSD 9.2-RELEASE #0 r255898: Thu Sep 26 22:50:31 UTC 2013    [email-masked]:/usr/obj/usr/src/sys/GENERIC  amd64
# tcpdump -i lo0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo0, link-type NULL (BSD loopback), capture size 65535 bytes
13:44:43.912939 IP localhost.22111 > localhost.49248: Flags [S], seq 1589925916, win 20480, options [mss 16344,nop,wscale 6,sackOK,TS val 120482 ecr 0], length 0
13:44:43.912987 IP localhost.49248 > localhost.22111: Flags [S.], seq 1752403575, ack 1589925917, win 20480, options [mss 16344,nop,wscale 6,sackOK,TS val 2357200578 ecr 120482], length 0
13:44:43.912999 IP localhost.22111 > localhost.49248: Flags [.], ack 1, win 510, options [nop,nop,TS val 120482 ecr 2357200578], length 0
13:44:43.913456 IP localhost.22111 > localhost.49248: Flags [.], seq 1:16333, ack 1, win 510, options [nop,nop,TS val 120482 ecr 2357200578], length 16332
13:44:43.914272 IP localhost.49248 > localhost.22111: Flags [.], seq 1:16333, ack 16333, win 255, options [nop,nop,TS val 2357200578 ecr 120482], length 16332
13:44:43.914377 IP localhost.22111 > localhost.49248: Flags [.], seq 16333:32653, ack 16333, win 255, options [nop,nop,TS val 120482 ecr 2357200578], length 16320
13:44:43.914460 IP localhost.49248 > localhost.22111: Flags [.], seq 16333:32653, ack 32653, win 0, options [nop,nop,TS val 2357200578 ecr 120482], length 16320
13:44:44.012989 IP localhost.22111 > localhost.49248: Flags [.], ack 32653, win 0, options [nop,nop,TS val 120583 ecr 2357200578], length 0
13:44:48.912031 IP localhost.22111 > localhost.49248: Flags [.], seq 32653:32654, ack 32653, win 0, options [nop,nop,TS val 125482 ecr 2357200578], length 1
13:44:48.912056 IP localhost.49248 > localhost.22111: Flags [.], ack 32654, win 0, options [nop,nop,TS val 2357205578 ecr 125482], length 0
13:44:49.012049 IP localhost.49248 > localhost.22111: Flags [.], seq 32653:32654, ack 32654, win 0, options [nop,nop,TS val 2357205678 ecr 125482], length 1
13:44:49.012074 IP localhost.22111 > localhost.49248: Flags [.], ack 32654, win 0, options [nop,nop,TS val 125582 ecr 2357205678], length 0
13:44:53.913015 IP localhost.22111 > localhost.49248: Flags [.], seq 32654:32655, ack 32654, win 0, options [nop,nop,TS val 130483 ecr 2357205678], length 1
13:44:53.913059 IP localhost.49248 > localhost.22111: Flags [.], ack 32655, win 0, options [nop,nop,TS val 2357210579 ecr 130483], length 0
13:44:54.013017 IP localhost.49248 > localhost.22111: Flags [.], seq 32654:32655, ack 32655, win 0, options [nop,nop,TS val 2357210679 ecr 130483], length 1
13:44:54.013042 IP localhost.22111 > localhost.49248: Flags [.], ack 32655, win 0, options [nop,nop,TS val 130583 ecr 2357210679], length 0
13:44:58.913034 IP localhost.22111 > localhost.49248: Flags [.], seq 32655:32656, ack 32655, win 0, options [nop,nop,TS val 135483 ecr 2357210679], length 1
13:44:58.913060 IP localhost.49248 > localhost.22111: Flags [.], ack 32656, win 0, options [nop,nop,TS val 2357215579 ecr 135483], length 0
13:44:59.012397 IP localhost.49248 > localhost.22111: Flags [.], seq 32655:32656, ack 32656, win 0, options [nop,nop,TS val 2357215679 ecr 135483], length 1
13:44:59.012421 IP localhost.22111 > localhost.49248: Flags [.], ack 32656, win 0, options [nop,nop,TS val 135583 ecr 2357215679], length 0
13:45:03.913033 IP localhost.22111 > localhost.49248: Flags [.], seq 32656:32657, ack 32656, win 0, options [nop,nop,TS val 140483 ecr 2357215679], length 1
13:45:03.913063 IP localhost.49248 > localhost.22111: Flags [.], ack 32657, win 0, options [nop,nop,TS val 2357220579 ecr 140483], length 0
13:45:04.013019 IP localhost.49248 > localhost.22111: Flags [.], seq 32656:32657, ack 32657, win 0, options [nop,nop,TS val 2357220679 ecr 140483], length 1
13:45:04.013044 IP localhost.22111 > localhost.49248: Flags [.], ack 32657, win 0, options [nop,nop,TS val 140583 ecr 2357220679], length 0
13:45:08.913018 IP localhost.22111 > localhost.49248: Flags [.], seq 32657:32658, ack 32657, win 0, options [nop,nop,TS val 145483 ecr 2357220679], length 1
13:45:08.913043 IP localhost.49248 > localhost.22111: Flags [.], ack 32658, win 0, options [nop,nop,TS val 2357225579 ecr 145483], length 0
13:45:09.013017 IP localhost.49248 > localhost.22111: Flags [.], seq 32657:32658, ack 32658, win 0, options [nop,nop,TS val 2357225679 ecr 145483], length 1
13:45:09.013042 IP localhost.22111 > localhost.49248: Flags [.], ack 32658, win 0, options [nop,nop,TS val 145583 ecr 2357225679], length 0
13:45:13.913009 IP localhost.22111 > localhost.49248: Flags [.], seq 32658:32659, ack 32658, win 0, options [nop,nop,TS val 150483 ecr 2357225679], length 1
13:45:13.913034 IP localhost.49248 > localhost.22111: Flags [.], ack 32659, win 0, options [nop,nop,TS val 2357230579 ecr 150483], length 0
13:45:14.012980 IP localhost.49248 > localhost.22111: Flags [.], seq 32658:32659, ack 32659, win 0, options [nop,nop,TS val 2357230679 ecr 150483], length 1
13:45:14.013005 IP localhost.22111 > localhost.49248: Flags [.], ack 32659, win 0, options [nop,nop,TS val 150583 ecr 2357230679], length 0
13:45:18.912690 IP localhost.22111 > localhost.49248: Flags [.], seq 32659:32660, ack 32659, win 0, options [nop,nop,TS val 155483 ecr 2357230679], length 1
13:45:18.912717 IP localhost.49248 > localhost.22111: Flags [.], ack 32660, win 0, options [nop,nop,TS val 2357235579 ecr 155483], length 0
13:45:19.012811 IP localhost.49248 > localhost.22111: Flags [.], seq 32659:32660, ack 32660, win 0, options [nop,nop,TS val 2357235679 ecr 155483], length 1
13:45:19.012828 IP localhost.22111 > localhost.49248: Flags [.], ack 32660, win 0, options [nop,nop,TS val 155583 ecr 2357235679], length 0
13:45:23.912288 IP localhost.22111 > localhost.49248: Flags [.], seq 32660:32661, ack 32660, win 0, options [nop,nop,TS val 160482 ecr 2357235679], length 1
13:45:23.912316 IP localhost.49248 > localhost.22111: Flags [.], ack 32661, win 0, options [nop,nop,TS val 2357240578 ecr 160482], length 0
13:45:24.013018 IP localhost.49248 > localhost.22111: Flags [.], seq 32660:32661, ack 32661, win 510, options [nop,nop,TS val 2357240679 ecr 160482], length 1
13:45:24.013046 IP localhost.22111 > localhost.49248: Flags [.], seq 32661:48993, ack 32661, win 510, options [nop,nop,TS val 160583 ecr 2357240679], length 16332
13:45:24.013195 IP localhost.49248 > localhost.22111: Flags [.], seq 32661:48993, ack 48993, win 255, options [nop,nop,TS val 2357240679 ecr 160583], length 16332
13:45:24.013207 IP localhost.22111 > localhost.49248: Flags [.], seq 48993:65313, ack 48993, win 255, options [nop,nop,TS val 160583 ecr 2357240679], length 16320
13:45:24.013215 IP localhost.49248 > localhost.22111: Flags [.], seq 48993:65313, ack 65313, win 0, options [nop,nop,TS val 2357240679 ecr 160583], length 16320
13:45:24.112038 IP localhost.22111 > localhost.49248: Flags [.], ack 65313, win 510, options [nop,nop,TS val 160682 ecr 2357240679], length 0
13:45:24.112075 IP localhost.49248 > localhost.22111: Flags [.], seq 65313:81645, ack 65313, win 510, options [nop,nop,TS val 2357240778 ecr 160682], length 16332
13:45:24.112333 IP localhost.49248 > localhost.22111: Flags [P.], seq 81645:81921, ack 65313, win 510, options [nop,nop,TS val 2357240778 ecr 160682], length 276
13:45:24.112354 IP localhost.22111 > localhost.49248: Flags [.], seq 65313:81645, ack 81645, win 255, options [nop,nop,TS val 160682 ecr 2357240778], length 16332
13:45:24.112505 IP localhost.22111 > localhost.49248: Flags [P.], seq 81645:81921, ack 81645, win 255, options [nop,nop,TS val 160682 ecr 2357240778], length 276
13:45:24.112520 IP localhost.49248 > localhost.22111: Flags [.], ack 81921, win 250, options [nop,nop,TS val 2357240778 ecr 160682], length 0
13:45:24.112596 IP localhost.49248 > localhost.22111: Flags [F.], seq 81921, ack 81921, win 510, options [nop,nop,TS val 2357240778 ecr 160682], length 0
13:45:24.112606 IP localhost.22111 > localhost.49248: Flags [.], ack 81922, win 510, options [nop,nop,TS val 160682 ecr 2357240778], length 0
13:45:24.112624 IP localhost.22111 > localhost.49248: Flags [F.], seq 81921, ack 81922, win 510, options [nop,nop,TS val 160682 ecr 2357240778], length 0
13:45:24.112646 IP localhost.49248 > localhost.22111: Flags [.], ack 81922, win 510, options [nop,nop,TS val 2357240778 ecr 160682], length 0

----------------------------------------------------------------------
The information contained in this transmission may be confidential. Any disclosure, copying, or further distribution of confidential information is not permitted unless such privilege is explicitly granted in writing by Quantum. Quantum reserves the right to have electronic communications, including email and attachments, sent across its networks filtered through anti virus and spam software programs and retain such messages in order to comply with applicable data security and retention requirements. Quantum is not responsible for the proper and complete transmission of the substance of this communication or for any delay in its receipt.

---

From: Hagen Paul Pfeifer <[email-masked]>
Date: Thu, 7 Nov 2013 23:18:02 +0100

* David Borman | 2013-11-07 20:46:53 [+0000]:

>I’ve been doing some testing of crossing Zero Window Probes, and it appears
>that the Linux TCP doesn’t do ZWP properly.  It is missing the 1 byte of
>data.
>
>My test program creates a pair of sockets, sets SO_RCVBUF to 20K and
>SO_SNDBUF to 80K on both sides, then writes 40K of data in both directions.
>It then pauses for 20 seconds to allow some ZWP packets, reads 1 byte of data
>from both sides, pauses another 20 seconds and then reads all the data from
>both sockets.  I ran tcpdump to watch the packet traffic.  Below are packet
>traces from both a Fedora Core 19 and a FreeBSD 9.2 system.  The FreeBSD
>trace has what I would expect to see, the Linux trace doesn’t send any data
>on the probes.
>
>Any thoughts on this?

Why 1 byte of data, the probe itself is not required to carry payload. The
sender must accept one byte probe packets, but there is no requirement to
probe with 1 byte packets.

Hagen

---

From: David Borman <[email-masked]>
Date: Thu, 7 Nov 2013 22:30:21 +0000

> probe with 1 byte packets.

Ugh, RFC 793 and RFC 1122 aren’t explicit on this, but in RFC 793, page 43:
    If a segment containing a single data octet sent to probe a zero window...

Without at least one byte of data, it just looks like a regular ACK packet and it won’t be guaranteed to elicit a response, which is the whole point of the Zero Window Probe, to elicit a response.

Also, the sender isn’t required to accept the 1 byte probe if the window is truly zero, but it is required to send back an ACK.

			-David Borman

---

From: Hagen Paul Pfeifer <[email-masked]>
Date: Thu, 7 Nov 2013 23:44:13 +0100

* David Borman | 2013-11-07 22:30:21 [+0000]:

>Without at least one byte of data, it just looks like a regular ACK packet
>and it won’t be guaranteed to elicit a response, which is the whole point of
>the Zero Window Probe, to elicit a response.

If the receiver do not open the window for 0 byte zero probes this operating
system may not work in the wild. The receiver must response with the actual
window for every payloaded packet. "Be conservative in what you send and
_liberal in what you accept_".

Hagen

---

From: Jakob Heitz <[email-masked]>
Date: Thu, 7 Nov 2013 22:49:05 +0000

An ACK for an ACK causes an ACK war.
--

Jakob Heitz.

________________________________________
From: [email-masked] [[email-masked]] on behalf of Hagen Paul Pfeifer [[email-masked]]
Sent: Thursday, 07 November 2013 2:44 PM
To: David Borman
Cc: [email-masked] ([email-masked])
Subject: Re: [tcpm] Linux doesn't do ZWP correctly???

Hagen
_______________________________________________
tcpm mailing list
[email-masked]
https://www.ietf.org/mailman/listinfo/tcpm

---

From: John Heffner <[email-masked]>
Date: Thu, 7 Nov 2013 18:11:53 -0500

Linux sends ZWPs by using a sequence number one before SND_UNA with
zero payload, which should elicit an ack.

---

From: Neal Cardwell <[email-masked]>
Date: Thu, 7 Nov 2013 18:25:36 -0500

> zero payload, which should elicit an ack.

Yes, RFC 793 (page 69) requires receivers to respond with an ACK in
response to an ACK when the incoming sequence number of the ACK is
invalid due to being below RCV.NXT:

"""
        There are four cases for the acceptability test for an incoming
        segment:

        Segment Receive  Test
        Length  Window
        ------- -------  -------------------------------------------
...
           0      >0     RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND
...

        If an incoming segment is not acceptable, an acknowledgment
        should be sent in reply (unless the RST bit is set, if so drop
        the segment and return):

          <SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>

        After sending the acknowledgment, drop the unacceptable segment
        and return.
"""

neal

---

From: David Borman <[email-masked]>
Date: Fri, 8 Nov 2013 16:05:17 +0000

> zero payload, which should elicit an ack.

Ah, the sequence number of packets without data doesn’t show up in the tcpdump traces, unless you use -vv.  So, Linux is using the same packet format for ZWP as for Keep-Alive packets.  Interesting.  Years ago this could have been an issue, as noted in RFC 1122 page 102, when talking about Keep-Alives:

                 Such a segment generally contains SEG.SEQ =
                 SND.NXT-1 and may or may not contain one garbage octet
                 of data.
...
            An implementation SHOULD send a keep-alive segment with no
            data; however, it MAY be configurable to send a keep-alive
            segment containing one garbage octet, for compatibility with
            erroneous TCP implementations.
...
                 Unfortunately, some misbehaved TCP implementations fail
                 to respond to a segment with SEG.SEQ = SND.NXT-1 unless
                 the segment contains data. ...

Hopefully those misbehaved TCP implementations are long since fixed or dead. :-)

Running the test again, using -vv on tcpdump, I see that the zero-length probe packets have seq-1.

			-David Borman

...