Skip to content

Commit 1e42f73

Browse files
wdebruijkuba-moo
authored andcommitted
selftests/net: packetdrill: import tcp/zerocopy
Same as initial tests, import verbatim from github.com/google/packetdrill, aside from: - update `source ./defaults.sh` path to adjust for flat dir - add SPDX headers - remove author statements if any - drop blank lines at EOF (new) Also import set_sysctls.py, which many scripts depend on to set sysctls and then restore them later. This is no longer strictly needed for namespacified sysctl. But not all sysctls are namespacified, and doesn't hurt if they are. Signed-off-by: Willem de Bruijn <[email protected]> Acked-by: Matthieu Baerts (NGI0) <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent cded7e0 commit 1e42f73

13 files changed

+674
-0
lines changed

tools/testing/selftests/net/packetdrill/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
TEST_INCLUDES := ksft_runner.sh \
44
defaults.sh \
5+
set_sysctls.py \
56
../../kselftest/ktap_helpers.sh
67

78
TEST_PROGS := $(wildcard *.pkt)
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#!/usr/bin/env python3
2+
# SPDX-License-Identifier: GPL-2.0
3+
4+
"""Sets sysctl values and writes a file that restores them.
5+
6+
The arguments are of the form "<proc-file>=<val>" separated by spaces.
7+
The program first reads the current value of the proc-file and creates
8+
a shell script named "/tmp/sysctl_restore_${PACKETDRILL_PID}.sh" which
9+
restores the values when executed. It then sets the new values.
10+
11+
PACKETDRILL_PID is set by packetdrill to the pid of itself, so a .pkt
12+
file could restore sysctls by running `/tmp/sysctl_restore_${PPID}.sh`
13+
at the end.
14+
"""
15+
16+
import os
17+
import subprocess
18+
import sys
19+
20+
filename = '/tmp/sysctl_restore_%s.sh' % os.environ['PACKETDRILL_PID']
21+
22+
# Open file for restoring sysctl values
23+
restore_file = open(filename, 'w')
24+
print('#!/bin/bash', file=restore_file)
25+
26+
for a in sys.argv[1:]:
27+
sysctl = a.split('=')
28+
# sysctl[0] contains the proc-file name, sysctl[1] the new value
29+
30+
# read current value and add restore command to file
31+
cur_val = subprocess.check_output(['cat', sysctl[0]], universal_newlines=True)
32+
print('echo "%s" > %s' % (cur_val.strip(), sysctl[0]), file=restore_file)
33+
34+
# set new value
35+
cmd = 'echo "%s" > %s' % (sysctl[1], sysctl[0])
36+
os.system(cmd)
37+
38+
os.system('chmod u+x %s' % filename)
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
// basic zerocopy test:
3+
//
4+
// send a packet with MSG_ZEROCOPY and receive the notification ID
5+
// repeat and verify IDs are consecutive
6+
7+
`./defaults.sh`
8+
9+
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
10+
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
11+
+0 setsockopt(3, SOL_SOCKET, SO_ZEROCOPY, [1], 4) = 0
12+
+0 bind(3, ..., ...) = 0
13+
+0 listen(3, 1) = 0
14+
15+
+0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 7>
16+
+0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
17+
+0 < . 1:1(0) ack 1 win 257
18+
19+
+0 accept(3, ..., ...) = 4
20+
21+
+0 send(4, ..., 4000, MSG_ZEROCOPY) = 4000
22+
+0 > P. 1:4001(4000) ack 1
23+
+0 < . 1:1(0) ack 4001 win 257
24+
25+
+0 recvmsg(4, {msg_name(...)=...,
26+
msg_iov(1)=[{...,0}],
27+
msg_flags=MSG_ERRQUEUE,
28+
msg_control=[
29+
{cmsg_level=CMSG_LEVEL_IP,
30+
cmsg_type=CMSG_TYPE_RECVERR,
31+
cmsg_data={ee_errno=0,
32+
ee_origin=SO_EE_ORIGIN_ZEROCOPY,
33+
ee_type=0,
34+
ee_code=SO_EE_CODE_ZEROCOPY_COPIED,
35+
ee_info=0,
36+
ee_data=0}}
37+
]}, MSG_ERRQUEUE) = 0
38+
39+
+0 send(4, ..., 4000, MSG_ZEROCOPY) = 4000
40+
+0 > P. 4001:8001(4000) ack 1
41+
+0 < . 1:1(0) ack 8001 win 257
42+
43+
+0 recvmsg(4, {msg_name(...)=...,
44+
msg_iov(1)=[{...,0}],
45+
msg_flags=MSG_ERRQUEUE,
46+
msg_control=[
47+
{cmsg_level=CMSG_LEVEL_IP,
48+
cmsg_type=CMSG_TYPE_RECVERR,
49+
cmsg_data={ee_errno=0,
50+
ee_origin=SO_EE_ORIGIN_ZEROCOPY,
51+
ee_type=0,
52+
ee_code=SO_EE_CODE_ZEROCOPY_COPIED,
53+
ee_info=1,
54+
ee_data=1}}
55+
]}, MSG_ERRQUEUE) = 0
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
// batch zerocopy test:
3+
//
4+
// send multiple packets, then read one range of all notifications.
5+
6+
`./defaults.sh`
7+
8+
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
9+
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
10+
+0 setsockopt(3, SOL_SOCKET, SO_ZEROCOPY, [1], 4) = 0
11+
+0 bind(3, ..., ...) = 0
12+
+0 listen(3, 1) = 0
13+
14+
+0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 7>
15+
+0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
16+
+0 < . 1:1(0) ack 1 win 257
17+
18+
+0 accept(3, ..., ...) = 4
19+
+0 setsockopt(4, SOL_SOCKET, SO_MARK, [666], 4) = 0
20+
21+
+0 send(4, ..., 4000, MSG_ZEROCOPY) = 4000
22+
+0 > P. 1:4001(4000) ack 1
23+
+0 < . 1:1(0) ack 4001 win 257
24+
25+
+0 send(4, ..., 4000, MSG_ZEROCOPY) = 4000
26+
+0 > P. 4001:8001(4000) ack 1
27+
+0 < . 1:1(0) ack 8001 win 257
28+
29+
+0 recvmsg(4, {msg_name(...)=...,
30+
msg_iov(1)=[{...,0}],
31+
msg_flags=MSG_ERRQUEUE,
32+
msg_control=[
33+
{cmsg_level=CMSG_LEVEL_IP,
34+
cmsg_type=CMSG_TYPE_RECVERR,
35+
cmsg_data={ee_errno=0,
36+
ee_origin=SO_EE_ORIGIN_ZEROCOPY,
37+
ee_type=0,
38+
ee_code=SO_EE_CODE_ZEROCOPY_COPIED,
39+
ee_info=0,
40+
ee_data=1}}
41+
]}, MSG_ERRQUEUE) = 0
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
// Minimal client-side zerocopy test
3+
4+
`./defaults.sh`
5+
6+
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 4
7+
+0 setsockopt(4, SOL_SOCKET, SO_ZEROCOPY, [1], 4) = 0
8+
+0...0 connect(4, ..., ...) = 0
9+
10+
+0 > S 0:0(0) <mss 1460,sackOK,TS val 0 ecr 0,nop,wscale 8>
11+
+0 < S. 0:0(0) ack 1 win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 7>
12+
+0 > . 1:1(0) ack 1
13+
14+
+0 send(4, ..., 4000, MSG_ZEROCOPY) = 4000
15+
+0 > P. 1:4001(4000) ack 1
16+
+0 < . 1:1(0) ack 4001 win 257
17+
18+
+0 recvmsg(4, {msg_name(...)=...,
19+
msg_iov(1)=[{...,0}],
20+
msg_flags=MSG_ERRQUEUE,
21+
msg_control=[
22+
{cmsg_level=CMSG_LEVEL_IP,
23+
cmsg_type=CMSG_TYPE_RECVERR,
24+
cmsg_data={ee_errno=0,
25+
ee_origin=SO_EE_ORIGIN_ZEROCOPY,
26+
ee_type=0,
27+
ee_code=SO_EE_CODE_ZEROCOPY_COPIED,
28+
ee_info=0,
29+
ee_data=0}}
30+
]}, MSG_ERRQUEUE) = 0
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
// send with MSG_ZEROCOPY on a non-established socket
3+
//
4+
// verify that a send in state TCP_CLOSE correctly aborts the zerocopy
5+
// operation, specifically it does not increment the zerocopy counter.
6+
//
7+
// First send on a closed socket and wait for (absent) notification.
8+
// Then connect and send and verify that notification nr. is zero.
9+
10+
`./defaults.sh`
11+
12+
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 4
13+
+0 setsockopt(4, SOL_SOCKET, SO_ZEROCOPY, [1], 4) = 0
14+
15+
+0 send(4, ..., 4000, MSG_ZEROCOPY) = -1 EPIPE (Broken pipe)
16+
17+
+0.1 recvmsg(4, {msg_name(...)=...,
18+
msg_iov(1)=[{...,0}],
19+
msg_flags=MSG_ERRQUEUE,
20+
msg_control=[]}, MSG_ERRQUEUE) = -1 EAGAIN (Resource temporarily unavailable)
21+
22+
+0...0 connect(4, ..., ...) = 0
23+
24+
+0 > S 0:0(0) <mss 1460,sackOK,TS val 0 ecr 0,nop,wscale 8>
25+
+0 < S. 0:0(0) ack 1 win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 7>
26+
+0 > . 1:1(0) ack 1
27+
28+
+0 send(4, ..., 4000, MSG_ZEROCOPY) = 4000
29+
+0 > P. 1:4001(4000) ack 1
30+
+0 < . 1:1(0) ack 4001 win 257
31+
32+
+0 recvmsg(4, {msg_name(...)=...,
33+
msg_iov(1)=[{...,0}],
34+
msg_flags=MSG_ERRQUEUE,
35+
msg_control=[
36+
{cmsg_level=CMSG_LEVEL_IP,
37+
cmsg_type=CMSG_TYPE_RECVERR,
38+
cmsg_data={ee_errno=0,
39+
ee_origin=SO_EE_ORIGIN_ZEROCOPY,
40+
ee_type=0,
41+
ee_code=SO_EE_CODE_ZEROCOPY_COPIED,
42+
ee_info=0,
43+
ee_data=0}}
44+
]}, MSG_ERRQUEUE) = 0
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
// epoll zerocopy test:
3+
//
4+
// EPOLLERR is known to be not edge-triggered unlike EPOLLIN and EPOLLOUT but
5+
// it is not level-triggered either.
6+
//
7+
// fire two sends with MSG_ZEROCOPY and receive the acks. confirm that EPOLLERR
8+
// is correctly fired only once, when EPOLLET is set. send another packet with
9+
// MSG_ZEROCOPY. confirm that EPOLLERR is correctly fired again only once.
10+
`./defaults.sh`
11+
12+
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
13+
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
14+
+0 setsockopt(3, SOL_SOCKET, SO_ZEROCOPY, [1], 4) = 0
15+
+0 bind(3, ..., ...) = 0
16+
+0 listen(3, 1) = 0
17+
18+
+0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 7>
19+
+0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
20+
+0 < . 1:1(0) ack 1 win 257
21+
22+
+0 accept(3, ..., ...) = 4
23+
24+
+0 fcntl(4, F_SETFL, O_RDWR|O_NONBLOCK) = 0
25+
+0 epoll_create(1) = 5
26+
+0 epoll_ctl(5, EPOLL_CTL_ADD, 4, {events=EPOLLOUT|EPOLLET, fd=4}) = 0
27+
+0 epoll_wait(5, {events=EPOLLOUT, fd=4}, 1, 0) = 1
28+
29+
+0 send(4, ..., 4000, MSG_ZEROCOPY) = 4000
30+
+0 > P. 1:4001(4000) ack 1
31+
+0 < . 1:1(0) ack 4001 win 257
32+
33+
+0 send(4, ..., 4000, MSG_ZEROCOPY) = 4000
34+
+0 > P. 4001:8001(4000) ack 1
35+
+0 < . 1:1(0) ack 8001 win 257
36+
37+
// receive only one EPOLLERR for the two sends above.
38+
+0 epoll_wait(5, {events=EPOLLERR|EPOLLOUT, fd=4}, 1, 0) = 1
39+
+0 epoll_wait(5, {events=0, ptr=0}, 1, 0) = 0
40+
41+
+0 send(4, ..., 4000, MSG_ZEROCOPY) = 4000
42+
+0 > P. 8001:12001(4000) ack 1
43+
+0 < . 1:1(0) ack 12001 win 257
44+
45+
// receive only one EPOLLERR for the third send above.
46+
+0 epoll_wait(5, {events=EPOLLERR|EPOLLOUT, fd=4}, 1, 0) = 1
47+
+0 epoll_wait(5, {events=0, ptr=0}, 1, 0) = 0
48+
49+
+0 recvmsg(4, {msg_name(...)=...,
50+
msg_iov(1)=[{...,0}],
51+
msg_flags=MSG_ERRQUEUE,
52+
msg_control=[
53+
{cmsg_level=CMSG_LEVEL_IP,
54+
cmsg_type=CMSG_TYPE_RECVERR,
55+
cmsg_data={ee_errno=0,
56+
ee_origin=SO_EE_ORIGIN_ZEROCOPY,
57+
ee_type=0,
58+
ee_code=SO_EE_CODE_ZEROCOPY_COPIED,
59+
ee_info=0,
60+
ee_data=2}}
61+
]}, MSG_ERRQUEUE) = 0
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
// epoll zerocopy test:
3+
//
4+
// EPOLLERR is known to be not edge-triggered unlike EPOLLIN and EPOLLOUT but
5+
// it is not level-triggered either. this tests verify that the same behavior is
6+
// maintained when we have EPOLLEXCLUSIVE.
7+
//
8+
// fire two sends with MSG_ZEROCOPY and receive the acks. confirm that EPOLLERR
9+
// is correctly fired only once, when EPOLLET is set. send another packet with
10+
// MSG_ZEROCOPY. confirm that EPOLLERR is correctly fired again only once.
11+
`./defaults.sh`
12+
13+
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
14+
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
15+
+0 setsockopt(3, SOL_SOCKET, SO_ZEROCOPY, [1], 4) = 0
16+
+0 bind(3, ..., ...) = 0
17+
+0 listen(3, 1) = 0
18+
19+
+0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 7>
20+
+0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
21+
+0 < . 1:1(0) ack 1 win 257
22+
23+
+0 accept(3, ..., ...) = 4
24+
25+
+0 fcntl(4, F_SETFL, O_RDWR|O_NONBLOCK) = 0
26+
+0 epoll_create(1) = 5
27+
+0 epoll_ctl(5, EPOLL_CTL_ADD, 4,
28+
{events=EPOLLOUT|EPOLLET|EPOLLEXCLUSIVE, fd=4}) = 0
29+
+0 epoll_wait(5, {events=EPOLLOUT, fd=4}, 1, 0) = 1
30+
31+
+0 send(4, ..., 4000, MSG_ZEROCOPY) = 4000
32+
+0 > P. 1:4001(4000) ack 1
33+
+0 < . 1:1(0) ack 4001 win 257
34+
35+
+0 send(4, ..., 4000, MSG_ZEROCOPY) = 4000
36+
+0 > P. 4001:8001(4000) ack 1
37+
+0 < . 1:1(0) ack 8001 win 257
38+
39+
// receive only one EPOLLERR for the two sends above.
40+
+0 epoll_wait(5, {events=EPOLLERR|EPOLLOUT, fd=4}, 1, 0) = 1
41+
+0 epoll_wait(5, {events=0, ptr=0}, 1, 0) = 0
42+
43+
+0 send(4, ..., 4000, MSG_ZEROCOPY) = 4000
44+
+0 > P. 8001:12001(4000) ack 1
45+
+0 < . 1:1(0) ack 12001 win 257
46+
47+
// receive only one EPOLLERR for the third send above.
48+
+0 epoll_wait(5, {events=EPOLLERR|EPOLLOUT, fd=4}, 1, 0) = 1
49+
+0 epoll_wait(5, {events=0, ptr=0}, 1, 0) = 0
50+
51+
+0 recvmsg(4, {msg_name(...)=...,
52+
msg_iov(1)=[{...,0}],
53+
msg_flags=MSG_ERRQUEUE,
54+
msg_control=[
55+
{cmsg_level=CMSG_LEVEL_IP,
56+
cmsg_type=CMSG_TYPE_RECVERR,
57+
cmsg_data={ee_errno=0,
58+
ee_origin=SO_EE_ORIGIN_ZEROCOPY,
59+
ee_type=0,
60+
ee_code=SO_EE_CODE_ZEROCOPY_COPIED,
61+
ee_info=0,
62+
ee_data=2}}
63+
]}, MSG_ERRQUEUE) = 0

0 commit comments

Comments
 (0)