summaryrefslogtreecommitdiff
path: root/tools/testing/selftests/net/msg_zerocopy.sh
blob: 28178a38a4e7b50b14480c91dd08adc25542d570 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#!/bin/bash
#
# Send data between two processes across namespaces
# Run twice: once without and once with zerocopy

set -e

readonly DEV="veth0"
readonly DUMMY_DEV="dummy0"
readonly DEV_MTU=65535
readonly BIN="./msg_zerocopy"

readonly RAND="$(mktemp -u XXXXXX)"
readonly NSPREFIX="ns-${RAND}"
readonly NS1="${NSPREFIX}1"
readonly NS2="${NSPREFIX}2"

readonly LPREFIX4='192.168.1'
readonly RPREFIX4='192.168.2'
readonly LPREFIX6='fd'
readonly RPREFIX6='fc'


readonly path_sysctl_mem="net.core.optmem_max"

# No arguments: automated test
if [[ "$#" -eq "0" ]]; then
	ret=0

	$0 4 tcp -t 1 || ret=1
	$0 6 tcp -t 1 || ret=1
	$0 4 udp -t 1 || ret=1
	$0 6 udp -t 1 || ret=1

	[[ "$ret" == "0" ]] && echo "OK. All tests passed"
	exit $ret
fi

# Argument parsing
if [[ "$#" -lt "2" ]]; then
	echo "Usage: $0 [4|6] [tcp|udp|raw|raw_hdrincl|packet|packet_dgram] <args>"
	exit 1
fi

readonly IP="$1"
shift
readonly TXMODE="$1"
shift
readonly EXTRA_ARGS="$@"

# Argument parsing: configure addresses
if [[ "${IP}" == "4" ]]; then
	readonly SADDR="${LPREFIX4}.1"
	readonly DADDR="${LPREFIX4}.2"
	readonly DUMMY_ADDR="${RPREFIX4}.1"
	readonly DADDR_TXONLY="${RPREFIX4}.2"
	readonly MASK="24"
elif [[ "${IP}" == "6" ]]; then
	readonly SADDR="${LPREFIX6}::1"
	readonly DADDR="${LPREFIX6}::2"
	readonly DUMMY_ADDR="${RPREFIX6}::1"
	readonly DADDR_TXONLY="${RPREFIX6}::2"
	readonly MASK="64"
	readonly NODAD="nodad"
else
	echo "Invalid IP version ${IP}"
	exit 1
fi

# Argument parsing: select receive mode
#
# This differs from send mode for
# - packet:	use raw recv, because packet receives skb clones
# - raw_hdrinc: use raw recv, because hdrincl is a tx-only option
case "${TXMODE}" in
'packet' | 'packet_dgram' | 'raw_hdrincl')
	RXMODE='raw'
	;;
*)
	RXMODE="${TXMODE}"
	;;
esac

# Start of state changes: install cleanup handler

cleanup() {
	ip netns del "${NS2}"
	ip netns del "${NS1}"
}

trap cleanup EXIT

# Create virtual ethernet pair between network namespaces
ip netns add "${NS1}"
ip netns add "${NS2}"

# Configure system settings
ip netns exec "${NS1}" sysctl -w -q "${path_sysctl_mem}=1000000"
ip netns exec "${NS2}" sysctl -w -q "${path_sysctl_mem}=1000000"

ip link add "${DEV}" mtu "${DEV_MTU}" netns "${NS1}" type veth \
  peer name "${DEV}" mtu "${DEV_MTU}" netns "${NS2}"

ip link add "${DUMMY_DEV}" mtu "${DEV_MTU}" netns "${NS2}" type dummy

# Bring the devices up
ip -netns "${NS1}" link set "${DEV}" up
ip -netns "${NS2}" link set "${DEV}" up
ip -netns "${NS2}" link set "${DUMMY_DEV}" up

# Set fixed MAC addresses on the devices
ip -netns "${NS1}" link set dev "${DEV}" address 02:02:02:02:02:02
ip -netns "${NS2}" link set dev "${DEV}" address 06:06:06:06:06:06

# Add fixed IP addresses to the devices
ip -netns "${NS1}" addr add "${SADDR}/${MASK}" dev "${DEV}" ${NODAD}
ip -netns "${NS2}" addr add "${DADDR}/${MASK}" dev "${DEV}" ${NODAD}
ip -netns "${NS2}" addr add "${DUMMY_ADDR}/${MASK}" dev "${DUMMY_DEV}" ${NODAD}

ip -netns "${NS1}" route add default via "${DADDR}" dev "${DEV}"
ip -netns "${NS2}" route add default via "${DADDR_TXONLY}" dev "${DUMMY_DEV}"

ip netns exec "${NS2}" sysctl -wq net.ipv4.ip_forward=1
ip netns exec "${NS2}" sysctl -wq net.ipv6.conf.all.forwarding=1

# Optionally disable sg or csum offload to test edge cases
# ip netns exec "${NS1}" ethtool -K "${DEV}" sg off

ret=0

do_test() {
	local readonly ARGS="$1"

	# tx-rx test
	# packets queued to a local socket are copied,
	# sender notification has SO_EE_CODE_ZEROCOPY_COPIED.

	echo -e "\nipv${IP} ${TXMODE} ${ARGS} tx-rx\n"
	ip netns exec "${NS2}" "${BIN}" "-${IP}" -i "${DEV}" -t 2 -C 2 \
		-S "${SADDR}" -D "${DADDR}" ${ARGS} -r "${RXMODE}" &
	sleep 0.2
	ip netns exec "${NS1}" "${BIN}" "-${IP}" -i "${DEV}" -t 1 -C 3 \
		-S "${SADDR}" -D "${DADDR}" ${ARGS} "${TXMODE}" -Z 0 || ret=1
	wait

	# next test is unconnected tx to dummy0, cannot exercise with tcp
	[[ "${TXMODE}" == "tcp" ]] && return

	# tx-only test: send out dummy0
	# packets leaving the host are not copied,
	# sender notification does not have SO_EE_CODE_ZEROCOPY_COPIED.

	echo -e "\nipv${IP} ${TXMODE} ${ARGS} tx-only\n"
	ip netns exec "${NS1}" "${BIN}" "-${IP}" -i "${DEV}" -t 1 -C 3 \
		-S "${SADDR}" -D "${DADDR_TXONLY}" ${ARGS} "${TXMODE}" -Z 1 || ret=1
}

do_test "${EXTRA_ARGS}"
do_test "-z ${EXTRA_ARGS}"

[[ "$ret" == "0" ]] && echo "OK"