Bug 252263 - [tcp] Should we reject packets with the nonmonotonic timestamp?
Summary: [tcp] Should we reject packets with the nonmonotonic timestamp?
Status: Closed Works As Intended
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 12.1-RELEASE
Hardware: Any Any
: --- Affects Some People
Assignee: Michael Tuexen
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-12-29 09:44 UTC by Yonghao Zou
Modified: 2021-01-01 11:51 UTC (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Yonghao Zou 2020-12-29 09:44:33 UTC
The following packetdrill shows different result of last read between Linux and FreeBSD

```
0   socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0  setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
+0  bind(3, ..., ...) = 0
+0  listen(3, 1) = 0

+0  < S 0:0(0) win 1000 <TS val 100 ecr 0,eol,eol>
+.5  > S. 0:0(0) ack 1 <...>
+.1 < . 1:1(0) ack 1 win 1000
+0.1 accept(3, ..., ...) = 4
+0 fcntl(4, F_SETFL, O_RDWR|O_NONBLOCK) = 0

+0 < . 1:1001(1000) ack 1 win 1000 <TS val 100 ecr 0,eol,eol>
+0.1 read(4, ..., 1000) = 1000

// Linux accept this packet, while FreeBSD reject.
// But if we set the TS val to 50, they both reject it.
+0 < . 1001:2001(1000) ack 1 win 1000 <TS val 99 ecr 0,eol,eol>

+0.1 read(4, ..., 1000) =  1000
```
Comment 1 Michael Tuexen freebsd_committer freebsd_triage 2021-01-01 11:51:22 UTC
I modified the test to run on FreeBSD head and think it works as it should according to https://tools.ietf.org/html/rfc7323#section-5.3
The rule R1 specifies to drop a segment with SEG.TSval < TS.Recent and send an ACK. Since TS.Recent is 100, the segment with SEG.TSval = 99 should be dropped. The same applies to a segment with SEG.TSval = 50.

I'm closing this issues as 'Works as intended'. If you disagree, please re-open.

Here is the updated script, which runs on FreeBSD head:

--tolerance_usecs=25000
// This script runs against FreeBSD head.
 0.000 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0.000 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0.000 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
+0.000 bind(3, ..., ...) = 0
+0.000 listen(3, 1) = 0
+0.000 < S     0:0(0)                win 65535 <mss 1400,sackOK,TS val 100 ecr   0>
+0.000 > S.    0:0(0)       ack    1 win 65535 <mss 1460,sackOK,TS val 200 ecr 100>
// The following segments needs to have the timestamp option.
// See https://tools.ietf.org/html/rfc7323#section-3.2
// This is enforced in https://svnweb.freebsd.org/changeset/base/367530
+0.100 <  .    1:1(0)       ack    1 win 65535 <nop,nop,TS val 200 ecr 200>
+0.100 accept(3, ..., ...) = 4
+0 fcntl(4, F_SETFL, O_RDWR|O_NONBLOCK) = 0
// The following segment with SEG.TSval=300 enforces TS.Recent=300.
+0.000 <  .    1:1001(1000) ack    1 win 65535 <nop,nop,TS val 300 ecr 200>
+0.000 read(4, ..., 2000) = 1000
+0.040 >  .    1:1(0)       ack 1001 win 65535 <nop,nop,TS val 440 ecr 300>
// The following segment with SEG.TSval < TS.Recent should be dropped.
+0.000 <  . 1001:2001(1000) ack 1    win 65535 <nop,nop,TS val 299 ecr 440>
+0.000 >  .    1:1(0)       ack 1001 win 65535 <nop,nop,TS val 440 ecr 300>
+0.000 read(4, ..., 2000) =  -1 EWOULDBLOCK (Operation would block)
// The following segment with SEG.TSval == TS.Recent should be accepted.
+0.000 <  . 1001:2001(1000) ack    1 win 65535 <nop,nop,TS val 300 ecr 440>
+0.000 read(4, ..., 2000) =  1000 
+0.040 >  .    1:1(0)       ack 2001 win 65535 <nop,nop,TS val 480 ecr 300>