Skip to content

Commit

Permalink
net-test: packetdrill: add support of tcp option wildcard "wscale *"
Browse files Browse the repository at this point in the history
Summary:
In current script, we can either specify every tcp option of a packet,
or use <...> for "any tcp options". This is not flexible enough, as
some script may have requirements for some tcp options; while be
flexible
with other options.

This patch tries to address this by adding wildcard for option wscale.
Specifically, "wscale *" in the tcp option list means any wscale value.

To mark a tcp option in the script as wildcard, we leverage the highest
bit of tcp_option->kind, as TCPOPT_WILDCARD (0x80). tcp_option->kind of
TCPOPT_WILDCARD | TCPOPT_WINDOW (0x83) means wscale option of any value.

verify_outbound_live_tcp_options() is updated to be able to understand
TCPOPT_WILDCARD when set on the script packet and with TCPOPT_WINDOW.

Testing:
Using a script that currently fail on my environment with wscale:
```
$ sudo ./packetdrill/run_all.py -S -v  -L -l
tcp/zerocopy/fastopen-client.pkt
FAIL
[/data/users/chantra/google-packetdrill/gtests/net/tcp/zerocopy/fastopen-client.pkt
(ipv4)]
stdout:
stderr:
fastopen-client.pkt:17: error handling packet: bad value outbound TCP
option 3
script packet:  0.000105 S 0:0(0) <mss 1460,sackOK,TS val 1000 ecr
0,nop,wscale 8,FO,nop,nop>
actual packet:  0.000095 S 0:0(0) win 65535 <mss 1460,sackOK,TS val 1000
ecr 0,nop,wscale 9,FO,nop,nop>
FAIL
[/data/users/chantra/google-packetdrill/gtests/net/tcp/zerocopy/fastopen-client.pkt
(ipv6)]
stdout:
stderr:
fastopen-client.pkt:17: error handling packet: bad value outbound TCP
option 3
script packet:  0.000157 S 0:0(0) <mss 1460,sackOK,TS val 1000 ecr
0,nop,wscale 8,FO,nop,nop>
actual packet:  0.000145 S 0:0(0) win 65535 <mss 1460,sackOK,TS val 1000
ecr 0,nop,wscale 9,FO,nop,nop>
FAIL
[/data/users/chantra/google-packetdrill/gtests/net/tcp/zerocopy/fastopen-client.pkt
(ipv4-mapped-v6)]
stdout:
stderr:
fastopen-client.pkt:17: error handling packet: bad value outbound TCP
option 3
script packet:  0.000118 S 0:0(0) <mss 1460,sackOK,TS val 1000 ecr
0,nop,wscale 8,FO,nop,nop>
actual packet:  0.000106 S 0:0(0) win 65535 <mss 1460,sackOK,TS val 1000
ecr 0,nop,wscale 9,FO,nop,nop>
Ran    3 tests:    0 passing,    3 failing,    0 timed out (2.69 sec):
tcp/zerocopy/fastopen-client.pkt
```

Changed the wscale to wildcard:
```
$ diff -ruN tcp/zerocopy/fastopen-client.pkt
tcp/zerocopy/fastopen-client-wscale-wildcard.pkt
--- tcp/zerocopy/fastopen-client.pkt    2023-06-27 18:36:22.956369457
-0700
+++ tcp/zerocopy/fastopen-client-wscale-wildcard.pkt    2023-06-27
18:37:29.306312093 -0700
@@ -14,7 +14,7 @@
    +0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
    +0 setsockopt(3, SOL_SOCKET, SO_ZEROCOPY, [1], 4) = 0
    +0 sendto(3, ..., 500, MSG_FASTOPEN|MSG_ZEROCOPY, ..., ...) = -1
EINPROGRESS (Operation now in progress)
-   +0 > S 0:0(0) <mss 1460,sackOK,TS val 1000 ecr 0,nop,wscale
    8,FO,nop,nop>
+   +0 > S 0:0(0) <mss 1460,sackOK,TS val 1000 ecr 0,nop,wscale
    *,FO,nop,nop>
  +.01 < S. 123:123(0) ack 1 win 14600 <mss 940,TS val 2000 ecr
1000,sackOK,nop,wscale 6, FO abcd1234,nop,nop>
    +0 > . 1:1(0) ack 1 <nop,nop,TS val 1001 ecr 2000>

@@ -35,7 +35,7 @@
    +0 fcntl(5, F_SETFL, O_RDWR|O_NONBLOCK) = 0
    +0 setsockopt(5, SOL_SOCKET, SO_ZEROCOPY, [1], 4) = 0
    +0 sendto(5, ..., 500, MSG_FASTOPEN|MSG_ZEROCOPY, ..., ...) = 500
-   +0 > S 0:500(500) <mss 1460,nop,nop,sackOK,nop,wscale 8,FO
    abcd1234,nop,nop>
+   +0 > S 0:500(500) <mss 1460,nop,nop,sackOK,nop,wscale *,FO
    abcd1234,nop,nop>
  +.05 < S. 5678:5678(0) ack 501 win 14600 <mss
1460,nop,nop,sackOK,nop,wscale 6>
    +0 > . 501:501(0) ack 1
```

and confirmed the test now pass:
```
$ sudo ./packetdrill/run_all.py -S -v  -L -l
tcp/zerocopy/fastopen-client-wscale-wildcard.pkt
OK
[/data/users/chantra/google-packetdrill/gtests/net/tcp/zerocopy/fastopen-client-wscale-wildcard.pkt
(ipv4)]
stdout:
stderr:
OK
[/data/users/chantra/google-packetdrill/gtests/net/tcp/zerocopy/fastopen-client-wscale-wildcard.pkt
(ipv6)]
stdout:
stderr:
OK
[/data/users/chantra/google-packetdrill/gtests/net/tcp/zerocopy/fastopen-client-wscale-wildcard.pkt
(ipv4-mapped-v6)]
stdout:
stderr:
Ran    3 tests:    3 passing,    0 failing,    0 timed out (7.91 sec):
tcp/zerocopy/fastopen-client-wscale-wildcard.pkt
```

and also still work properly when the wscale is matching expectations:
```
$ diff -ruN tcp/zerocopy/fastopen-client.pkt tcp/zerocopy/fastopen-client-correct-wscale.pkt
--- tcp/zerocopy/fastopen-client.pkt    2023-06-27 18:36:22.956369457
-0700
+++ tcp/zerocopy/fastopen-client-correct-wscale.pkt     2023-06-27
18:39:24.630212385 -0700
@@ -14,7 +14,7 @@
    +0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
    +0 setsockopt(3, SOL_SOCKET, SO_ZEROCOPY, [1], 4) = 0
    +0 sendto(3, ..., 500, MSG_FASTOPEN|MSG_ZEROCOPY, ..., ...) = -1
EINPROGRESS (Operation now in progress)
-   +0 > S 0:0(0) <mss 1460,sackOK,TS val 1000 ecr 0,nop,wscale
    8,FO,nop,nop>
+   +0 > S 0:0(0) <mss 1460,sackOK,TS val 1000 ecr 0,nop,wscale
    9,FO,nop,nop>
  +.01 < S. 123:123(0) ack 1 win 14600 <mss 940,TS val 2000 ecr
1000,sackOK,nop,wscale 6, FO abcd1234,nop,nop>
    +0 > . 1:1(0) ack 1 <nop,nop,TS val 1001 ecr 2000>

@@ -35,7 +35,7 @@
    +0 fcntl(5, F_SETFL, O_RDWR|O_NONBLOCK) = 0
    +0 setsockopt(5, SOL_SOCKET, SO_ZEROCOPY, [1], 4) = 0
    +0 sendto(5, ..., 500, MSG_FASTOPEN|MSG_ZEROCOPY, ..., ...) = 500
-   +0 > S 0:500(500) <mss 1460,nop,nop,sackOK,nop,wscale 8,FO
    abcd1234,nop,nop>
+   +0 > S 0:500(500) <mss 1460,nop,nop,sackOK,nop,wscale 9,FO
    abcd1234,nop,nop>
  +.05 < S. 5678:5678(0) ack 501 win 14600 <mss
1460,nop,nop,sackOK,nop,wscale 6>
    +0 > . 501:501(0) ack 1
```

with
```
$ sudo ./packetdrill/run_all.py -S -v  -L -l tcp/zerocopy/fastopen-client-correct-wscale.pkt
OK
[/data/users/chantra/google-packetdrill/gtests/net/tcp/zerocopy/fastopen-client-correct-wscale.pkt
(ipv4)]
stdout:
stderr:
OK
[/data/users/chantra/google-packetdrill/gtests/net/tcp/zerocopy/fastopen-client-correct-wscale.pkt
(ipv6)]
stdout:
stderr:
OK
[/data/users/chantra/google-packetdrill/gtests/net/tcp/zerocopy/fastopen-client-correct-wscale.pkt
(ipv4-mapped-v6)]
stdout:
stderr:
Ran    3 tests:    3 passing,    0 failing,    0 timed out (8.16 sec):
tcp/zerocopy/fastopen-client-correct-wscale.pkt
```

Also comfirmed that wscale wildcard would not cause and option which has
0x80 set to pass.

For instance with:
```
$ diff -ruN tcp/fastopen/server/simple2.pkt
tcp/fastopen/server/simple2-wscale.pkt
--- tcp/fastopen/server/simple2.pkt     2023-06-27 17:28:58.547790456
-0700
+++ tcp/fastopen/server/simple2-wscale.pkt      2023-06-27
19:00:49.460036441 -0700
@@ -22,7 +22,7 @@

    +0 < S 9873242:9873242(0) win 10000 <mss 1012,FOEXP,sackOK,TS val 1
ecr 0,nop,wscale 7>
 // Test the cookie is as expected by encoding both IPs w/ key
-   +0 > S. 0:0(0) ack 9873243 <mss 1460,sackOK,TS val 10000 ecr
    1,nop,wscale 8, FOEXP 1313a2da994a0951>
+   +0 > S. 0:0(0) ack 9873243 <mss 1460,sackOK,TS val 10000 ecr
    1,nop,wscale *, FOEXP f49b0ef989d9f624>
   +.1 < . 1:1(0) ack 1 win 257 <nop,nop,TS val 2 ecr 10000>
    +0 accept(3, ..., ...) = 4
    +0 close(4) = 0
@@ -38,8 +38,8 @@
    +0 bind(3, ..., ...) = 0
    +0 listen(3, 1) = 0

- +.05 < S 19124022:19125022(1000) win 10000 <mss 1012,FOEXP
  1313a2da994a0951,sackOK,TS val 10 ecr 0,nop,wscale 7>
-   +0 > S. 0:0(0) ack 19125023 <mss 1460,sackOK,TS val 100000 ecr
    10,nop,wscale 8>
+ +.05 < S 19124022:19125022(1000) win 10000 <mss 1012,FOEXP
  f49b0ef989d9f624,sackOK,TS val 10 ecr 0,nop,wscale 7>
+   +0 > S. 0:0(0) ack 19125023 <mss 1460,sackOK,TS val 100000 ecr
    10,nop,wscale 9>
    +0 accept(3, ..., ...) = 4

 `/tmp/sysctl_restore_${PPID}.sh`
```
The test fails at handling Fast Open Experimental

```
simple2-wscale.pkt:25: error handling packet: bad value outbound TCP
option 254
script packet:  0.000163 S. 0:0(0) ack 9873243 <mss 1460,sackOK,TS val
10000 ecr 1,nop,wscale *,FOEXP f49b0ef989d9f624>
actual packet:  0.000159 S. 0:0(0) ack 9873243 win 65535 <mss
1460,sackOK,TS val 10000 ecr 1,nop,wscale 9,FOEXP 792f542eed8979b8>
OK
[/data/users/chantra/google-packetdrill/gtests/net/tcp/fastopen/server/simple2-wscale.pkt
(ipv4-mapped-v6)]
```

Signed-off-by: Manu Bretelle <[email protected]>
  • Loading branch information
chantra committed Jun 28, 2023
1 parent c2b94c5 commit 99d6954
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 2 deletions.
4 changes: 4 additions & 0 deletions gtests/net/packetdrill/parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -1282,6 +1282,10 @@ tcp_option
}
$$->data.window_scale.shift_count = $2;
}
| WSCALE '*' {
$$ = tcp_option_new(TCPOPT_WINDOW | TCPOPT_WILDCARD, TCPOLEN_WINDOW);
$$->data.window_scale.shift_count = 0;
}
| SACKOK {
$$ = tcp_option_new(TCPOPT_SACK_PERMITTED,
TCPOLEN_SACK_PERMITTED);
Expand Down
9 changes: 7 additions & 2 deletions gtests/net/packetdrill/run_packet.c
Original file line number Diff line number Diff line change
Expand Up @@ -1383,12 +1383,17 @@ static int verify_outbound_live_tcp_options(
/* TCP options are expected to be a deterministic order. */
while (a_opt != NULL || s_opt != NULL) {
if (a_opt == NULL || s_opt == NULL ||
a_opt->kind != s_opt->kind) {
(a_opt->kind != s_opt->kind &&
!(s_opt->kind == (TCPOPT_WILDCARD | TCPOPT_WINDOW) &&
a_opt->kind == TCPOPT_WINDOW))) {
asprintf(error, "bad outbound TCP options");
return STATUS_ERR;
}

if (verify_outbound_tcp_option(state, actual_packet,
/* skip byte-to-byte comparison of wildcard option */
if (s_opt->kind == (TCPOPT_WILDCARD | TCPOPT_WINDOW))
;
else if (verify_outbound_tcp_option(state, actual_packet,
script_packet, a_opt, s_opt,
error) != STATUS_OK) {
return STATUS_ERR;
Expand Down
11 changes: 11 additions & 0 deletions gtests/net/packetdrill/tcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,17 @@

#define TCP_MD5_DIGEST_LEN 16 /* bytes in RFC2385 TCP MD5 digest */

/*
* To compare subset of options between script packet and actual packet,
* we use * for "option with any value". For example, "wscale *" in the
* script packet means wscale option of any value.
*
* TCPOPT_WILDCARD is used to mark a option in the script packet as
* "any value". A script packet of kind "TCPOPT_WINDOW | TCPOPT_WILDCARD"
* means "wscale option of any value".
*/
#define TCPOPT_WILDCARD 0x80

/* A portable TCP header definition (Linux and *BSD use different names). */
struct tcp {
__be16 src_port;
Expand Down
1 change: 1 addition & 0 deletions gtests/net/packetdrill/tcp_options_iterator.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ static int get_expected_tcp_option_length(u8 kind, u8 *expected_length,
break;

case TCPOPT_WINDOW:
case TCPOPT_WINDOW | TCPOPT_WILDCARD:
*expected_length = TCPOLEN_WINDOW;
break;

Expand Down
4 changes: 4 additions & 0 deletions gtests/net/packetdrill/tcp_options_to_string.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ int tcp_options_to_string(struct packet *packet,
option->data.window_scale.shift_count);
break;

case TCPOPT_WINDOW | TCPOPT_WILDCARD:
fprintf(s, "wscale *");
break;

case TCPOPT_SACK_PERMITTED:
fputs("sackOK", s);
break;
Expand Down

0 comments on commit 99d6954

Please sign in to comment.