projects/linux·blob master · refs

1493 lines · 45.2 KiB

1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3#
4# OVS kernel module self tests
5
6trap ovs_exit_sig EXIT TERM INT ERR
7
8# Kselftest framework requirement - SKIP code is 4.
9ksft_skip=4
10
11PAUSE_ON_FAIL=no
12VERBOSE=0
13TRACING=0
14WAIT_TIMEOUT=5
15
16if test "X$KSFT_MACHINE_SLOW" == "Xyes"; then
17 WAIT_TIMEOUT=10
18fi
19
20tests="
21 arp_ping eth-arp: Basic arp ping between two NS
22 ct_connect_v4 ip4-ct-xon: Basic ipv4 tcp connection using ct
23 connect_v4 ip4-xon: Basic ipv4 ping between two NS
24 nat_connect_v4 ip4-nat-xon: Basic ipv4 tcp connection via NAT
25 nat_related_v4 ip4-nat-related: ICMP related matches work with SNAT
26 netlink_checks ovsnl: validate netlink attrs and settings
27 upcall_interfaces ovs: test the upcall interfaces
28 tunnel_metadata ovs: test extraction of tunnel metadata
29 drop_reason drop: test drop reasons are emitted
30 pop_vlan vlan: POP_VLAN action strips tag
31 dec_ttl ttl: dec_ttl decrements IP TTL
32 flow_set flow-set: Flow modify
33 action_set set: SET action rewrites fields
34 trunc trunc: output truncation
35 icmpv6 icmpv6: ICMPv6 echo type match
36 sctp_connect_v4 sctp: SCTP flow key matching
37 psample psample: Sampling packets with psample"
38
39info() {
40 [ "${ovs_dir}" != "" ] &&
41 echo "`date +"[%m-%d %H:%M:%S]"` $*" >> ${ovs_dir}/debug.log
42 [ $VERBOSE = 0 ] || echo $*
43}
44
45ovs_wait() {
46 info "waiting $WAIT_TIMEOUT s for: $@"
47
48 if "$@" ; then
49 info "wait succeeded immediately"
50 return 0
51 fi
52
53 # A quick re-check helps speed up small races in fast systems.
54 # However, fractional sleeps might not necessarily work.
55 local start=0
56 sleep 0.1 || { sleep 1; start=1; }
57
58 for (( i=start; i<WAIT_TIMEOUT; i++ )); do
59 if "$@" ; then
60 info "wait succeeded after $i seconds"
61 return 0
62 fi
63 sleep 1
64 done
65 info "wait failed after $i seconds"
66 return 1
67}
68
69ovs_base=`pwd`
70sbxs=
71sbx_add () {
72 info "adding sandbox '$1'"
73
74 sbxs="$sbxs $1"
75
76 NO_BIN=0
77
78 # Create sandbox.
79 local d="$ovs_base"/$1
80 if [ -e $d ]; then
81 info "removing $d"
82 rm -rf "$d"
83 fi
84 mkdir "$d" || return 1
85 ovs_setenv $1
86}
87
88ovs_exit_sig() {
89 [ -e ${ovs_dir}/cleanup ] && . "$ovs_dir/cleanup"
90}
91
92on_exit() {
93 echo "$1" > ${ovs_dir}/cleanup.tmp
94 cat ${ovs_dir}/cleanup >> ${ovs_dir}/cleanup.tmp
95 mv ${ovs_dir}/cleanup.tmp ${ovs_dir}/cleanup
96}
97
98ovs_setenv() {
99 sandbox=$1
100
101 ovs_dir=$ovs_base${1:+/$1}; export ovs_dir
102
103 test -e ${ovs_dir}/cleanup || : > ${ovs_dir}/cleanup
104}
105
106ovs_sbx() {
107 if test "X$2" != X; then
108 (ovs_setenv $1; shift;
109 info "run cmd: $@"; "$@" >> ${ovs_dir}/debug.log)
110 else
111 ovs_setenv $1
112 fi
113}
114
115ovs_add_dp () {
116 info "Adding DP/Bridge IF: sbx:$1 dp:$2 {$3, $4, $5}"
117 sbxname="$1"
118 shift
119 ovs_sbx "$sbxname" python3 $ovs_base/ovs-dpctl.py add-dp $*
120 on_exit "ovs_sbx $sbxname python3 $ovs_base/ovs-dpctl.py del-dp $1;"
121}
122
123ovs_add_if () {
124 info "Adding IF to DP: br:$3 if:$4 ($2)"
125 if [ "$5" != "-u" ]; then
126 ovs_sbx "$1" python3 $ovs_base/ovs-dpctl.py add-if \
127 -t "$2" "$3" "$4" || return 1
128 else
129 python3 $ovs_base/ovs-dpctl.py add-if \
130 -u -t "$2" "$3" "$4" >$ovs_dir/$4.out 2>$ovs_dir/$4.err &
131 pid=$!
132 on_exit "ovs_sbx $1 kill -TERM $pid 2>/dev/null"
133 fi
134}
135
136ovs_del_if () {
137 info "Deleting IF from DP: br:$2 if:$3"
138 ovs_sbx "$1" python3 $ovs_base/ovs-dpctl.py del-if "$2" "$3" || return 1
139}
140
141ovs_netns_spawn_daemon() {
142 sbx=$1
143 shift
144 netns=$1
145 shift
146 if [ "$netns" == "_default" ]; then
147 $* >> $ovs_dir/stdout 2>> $ovs_dir/stderr &
148 else
149 ip netns exec $netns $* >> $ovs_dir/stdout 2>> $ovs_dir/stderr &
150 fi
151 pid=$!
152 ovs_sbx "$sbx" on_exit "kill -TERM $pid 2>/dev/null"
153}
154
155ovs_spawn_daemon() {
156 sbx=$1
157 shift
158 ovs_netns_spawn_daemon $sbx "_default" $*
159}
160
161ovs_add_netns_and_veths () {
162 info "Adding netns attached: sbx:$1 dp:$2 {$3, $4, $5}"
163 ovs_sbx "$1" ip netns add "$3" || return 1
164 on_exit "ovs_sbx $1 ip netns del $3"
165 ovs_sbx "$1" ip link add "$4" type veth peer name "$5" || return 1
166 on_exit "ovs_sbx $1 ip link del $4 >/dev/null 2>&1"
167 ovs_sbx "$1" ip link set "$4" up || return 1
168 ovs_sbx "$1" ip link set "$5" netns "$3" || return 1
169 ovs_sbx "$1" ip netns exec "$3" ip link set "$5" up || return 1
170
171 if [ "$6" != "" ]; then
172 ovs_sbx "$1" ip netns exec "$3" ip addr add "$6" dev "$5" \
173 || return 1
174 fi
175
176 if [ "$7" != "-u" ]; then
177 ovs_add_if "$1" "netdev" "$2" "$4" || return 1
178 else
179 ovs_add_if "$1" "netdev" "$2" "$4" -u || return 1
180 fi
181
182 if [ $TRACING -eq 1 ]; then
183 ovs_netns_spawn_daemon "$1" "$3" tcpdump -l -i any -s 6553
184 ovs_wait grep -q "listening on any" ${ovs_dir}/stderr
185 fi
186
187 return 0
188}
189
190ovs_add_flow () {
191 info "Adding flow to DP: sbx:$1 br:$2 flow:$3 act:$4"
192 ovs_sbx "$1" python3 $ovs_base/ovs-dpctl.py add-flow "$2" "$3" "$4"
193 if [ $? -ne 0 ]; then
194 info "Flow [ $3 : $4 ] failed"
195 return 1
196 fi
197 return 0
198}
199
200ovs_mod_flow () {
201 if [ -n "$4" ]; then
202 info "Modifying flow: sbx:$1 br:$2 flow:$3 act:$4"
203 ovs_sbx "$1" python3 $ovs_base/ovs-dpctl.py \
204 mod-flow "$2" "$3" "$4"
205 else
206 info "Modifying flow (no actions): sbx:$1 br:$2 flow:$3"
207 ovs_sbx "$1" python3 $ovs_base/ovs-dpctl.py \
208 mod-flow "$2" "$3"
209 fi
210 if [ $? -ne 0 ]; then
211 info "Flow modify [ $3 ] failed"
212 return 1
213 fi
214 return 0
215}
216
217ovs_del_flows () {
218 info "Deleting all flows from DP: sbx:$1 br:$2"
219 ovs_sbx "$1" python3 $ovs_base/ovs-dpctl.py del-flows "$2"
220 return 0
221}
222
223ovs_drop_record_and_run () {
224 local sbx=$1
225 shift
226
227 perf record -a -q -e skb:kfree_skb -o ${ovs_dir}/perf.data $* \
228 >> ${ovs_dir}/stdout 2>> ${ovs_dir}/stderr
229 return $?
230}
231
232ovs_drop_reason_count()
233{
234 local reason=$1
235
236 local perf_output=`perf script -i ${ovs_dir}/perf.data -F trace:event,trace`
237 local pattern="skb:kfree_skb:.*reason: $reason"
238
239 return `echo "$perf_output" | grep "$pattern" | wc -l`
240}
241
242ovs_test_flow_fails () {
243 ERR_MSG="Flow actions may not be safe on all matching packets"
244
245 PRE_TEST=$(dmesg | grep -c "${ERR_MSG}")
246 ovs_add_flow $@ &> /dev/null $@ && return 1
247 POST_TEST=$(dmesg | grep -c "${ERR_MSG}")
248
249 if [ "$PRE_TEST" == "$POST_TEST" ]; then
250 return 1
251 fi
252 return 0
253}
254
255usage() {
256 echo
257 echo "$0 [OPTIONS] [TEST]..."
258 echo "If no TEST argument is given, all tests will be run."
259 echo
260 echo "Options"
261 echo " -t: capture traffic via tcpdump"
262 echo " -v: verbose"
263 echo " -p: pause on failure"
264 echo
265 echo "Available tests${tests}"
266 exit 1
267}
268
269
270test_dec_ttl() {
271 sbx_add "test_dec_ttl" || return $?
272 ovs_add_dp "test_dec_ttl" decttl || return 1
273
274 info "create namespaces"
275 for ns in client server; do
276 ovs_add_netns_and_veths "test_dec_ttl" "decttl" "$ns" \
277 "${ns:0:1}0" "${ns:0:1}1" || return 1
278 done
279
280 ip netns exec client ip addr add 10.0.0.1/24 dev c1
281 ip netns exec client ip link set c1 up
282 ip netns exec server ip addr add 10.0.0.2/24 dev s1
283 ip netns exec server ip link set s1 up
284
285 # Probe: check if kernel supports dec_ttl action.
286 ovs_add_flow "test_dec_ttl" decttl \
287 'in_port(1),eth(),eth_type(0x0800),ipv4()' \
288 'dec_ttl(le_1())' &>/dev/null
289 if [ $? -ne 0 ]; then
290 info "no support for dec_ttl - skipping"
291 ovs_exit_sig
292 return $ksft_skip
293 fi
294
295 ovs_del_flows "test_dec_ttl" decttl
296
297 # ARP flows (bidirectional)
298 ovs_add_flow "test_dec_ttl" decttl \
299 'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1
300 ovs_add_flow "test_dec_ttl" decttl \
301 'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1
302
303 # IP flows with dec_ttl action
304 ovs_add_flow "test_dec_ttl" decttl \
305 'in_port(1),eth(),eth_type(0x0800),ipv4()' \
306 'dec_ttl(le_1()),2' || return 1
307 ovs_add_flow "test_dec_ttl" decttl \
308 'in_port(2),eth(),eth_type(0x0800),ipv4()' \
309 'dec_ttl(le_1()),1' || return 1
310
311 info "verify connectivity with dec_ttl"
312 ovs_sbx "test_dec_ttl" ip netns exec client ping -c 1 -W 2 \
313 10.0.0.2 || return 1
314
315 info "verify TTL=1 is dropped by dec_ttl"
316 ovs_sbx "test_dec_ttl" ip netns exec client ping -c 1 -W 2 \
317 -t 1 10.0.0.2 >/dev/null 2>&1 \
318 && { info "FAIL: ping should fail with TTL=1 and dec_ttl"
319 return 1; }
320
321 return 0
322}
323
324test_flow_set() {
325 sbx_add "test_flow_set" || return $?
326 ovs_add_dp "test_flow_set" flowset || return 1
327
328 info "create namespaces"
329 for ns in client server; do
330 ovs_add_netns_and_veths "test_flow_set" "flowset" "$ns" \
331 "${ns:0:1}0" "${ns:0:1}1" || return 1
332 done
333
334 ip netns exec client ip addr add 10.0.0.1/24 dev c1
335 ip netns exec client ip link set c1 up
336 ip netns exec server ip addr add 10.0.0.2/24 dev s1
337 ip netns exec server ip link set s1 up
338
339 ovs_add_flow "test_flow_set" flowset \
340 'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1
341 ovs_add_flow "test_flow_set" flowset \
342 'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1
343
344 local fwd_flow="ufid:00000001-0002-0003-0004-000500060007"
345 fwd_flow="$fwd_flow,in_port(1),eth(),eth_type(0x0800),ipv4()"
346
347 ovs_add_flow "test_flow_set" flowset "$fwd_flow" '2' \
348 || return 1
349 ovs_add_flow "test_flow_set" flowset \
350 'in_port(2),eth(),eth_type(0x0800),ipv4()' '1' || return 1
351
352 info "verify initial forwarding"
353 ovs_sbx "test_flow_set" ip netns exec client ping -c 1 -W 2 \
354 10.0.0.2 || return 1
355
356 info "mod-flow with new actions (change to drop)"
357 ovs_mod_flow "test_flow_set" flowset "$fwd_flow" 'drop' \
358 || return 1
359
360 info "verify traffic is now dropped"
361 ovs_sbx "test_flow_set" ip netns exec client ping -c 1 -W 2 \
362 10.0.0.2 >/dev/null 2>&1 \
363 && { info "FAIL: ping should fail after mod-flow to drop"
364 return 1; }
365
366 info "mod-flow without actions"
367 ovs_mod_flow "test_flow_set" flowset "$fwd_flow" || return 1
368
369 info "verify flow retained drop action via dump"
370 python3 "$ovs_base/ovs-dpctl.py" dump-flows flowset \
371 | grep -q "actions:drop" || \
372 { info "FAIL: flow not showing drop action"; return 1; }
373
374 info "verify drop actions unchanged"
375 ovs_sbx "test_flow_set" ip netns exec client ping -c 1 -W 2 \
376 10.0.0.2 >/dev/null 2>&1 \
377 && { info "FAIL: ping should still fail after no-actions set"
378 return 1; }
379
380 return 0
381}
382
383test_action_set() {
384 sbx_add "test_action_set" || return $?
385 ovs_add_dp "test_action_set" settest || return 1
386
387 info "create namespaces"
388 for ns in client server; do
389 ovs_add_netns_and_veths "test_action_set" "settest" "$ns" \
390 "${ns:0:1}0" "${ns:0:1}1" || return 1
391 done
392
393 ip netns exec client ip addr add 10.0.0.1/24 dev c1
394 ip netns exec client ip link set c1 up
395 ip netns exec server ip addr add 10.0.0.2/24 dev s1
396 ip netns exec server ip link set s1 up
397
398 ovs_add_flow "test_action_set" settest \
399 'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1
400 ovs_add_flow "test_action_set" settest \
401 'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1
402
403 ovs_add_flow "test_action_set" settest \
404 'in_port(1),eth(),eth_type(0x0800),ipv4()' '2' || return 1
405 ovs_add_flow "test_action_set" settest \
406 'in_port(2),eth(),eth_type(0x0800),ipv4()' '1' || return 1
407
408 info "verify connectivity without SET"
409 ovs_sbx "test_action_set" ip netns exec client ping -c 1 -W 2 \
410 10.0.0.2 || return 1
411
412 ovs_del_flows "test_action_set" settest
413 ovs_add_flow "test_action_set" settest \
414 'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1
415 ovs_add_flow "test_action_set" settest \
416 'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1
417
418 info "set ipv4 dst to unreachable address"
419 ovs_add_flow "test_action_set" settest \
420 'in_port(1),eth(),eth_type(0x0800),ipv4()' \
421 'set(ipv4(dst=10.0.0.99)),2' || return 1
422 ovs_add_flow "test_action_set" settest \
423 'in_port(2),eth(),eth_type(0x0800),ipv4()' '1' || return 1
424
425 info "verify ping fails with rewritten dst"
426 ovs_sbx "test_action_set" ip netns exec client ping -c 1 -W 2 \
427 10.0.0.2 >/dev/null 2>&1 \
428 && { info "FAIL: ping should fail with dst rewritten"
429 return 1; }
430
431 ovs_del_flows "test_action_set" settest
432 ovs_add_flow "test_action_set" settest \
433 'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1
434 ovs_add_flow "test_action_set" settest \
435 'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1
436 ovs_add_flow "test_action_set" settest \
437 'in_port(1),eth(),eth_type(0x0800),ipv4()' '2' || return 1
438 ovs_add_flow "test_action_set" settest \
439 'in_port(2),eth(),eth_type(0x0800),ipv4()' '1' || return 1
440
441 info "verify connectivity restored without SET"
442 ovs_sbx "test_action_set" ip netns exec client ping -c 1 -W 2 \
443 10.0.0.2 || return 1
444
445 return 0
446}
447
448# trunc test
449# - trunc(14): truncate to ETH_HLEN, strips IP payload, ping fails
450# - trunc(1) and trunc(13): kernel rejects below ETH_HLEN (EINVAL)
451# - restore normal forwarding and verify recovery
452test_trunc() {
453 sbx_add "test_trunc" || return $?
454 ovs_add_dp "test_trunc" trunctest || return 1
455
456 info "create namespaces"
457 for ns in client server; do
458 ovs_add_netns_and_veths "test_trunc" "trunctest" \
459 "$ns" "${ns:0:1}0" "${ns:0:1}1" || return 1
460 done
461
462 ip netns exec client ip addr add 10.0.0.1/24 dev c1
463 ip netns exec client ip link set c1 up
464 ip netns exec server ip addr add 10.0.0.2/24 dev s1
465 ip netns exec server ip link set s1 up
466
467 ovs_add_flow "test_trunc" trunctest \
468 'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1
469 ovs_add_flow "test_trunc" trunctest \
470 'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1
471 ovs_add_flow "test_trunc" trunctest \
472 'in_port(1),eth(),eth_type(0x0800),ipv4()' \
473 '2' || return 1
474 ovs_add_flow "test_trunc" trunctest \
475 'in_port(2),eth(),eth_type(0x0800),ipv4()' \
476 '1' || return 1
477
478 info "verify connectivity without truncation"
479 ovs_sbx "test_trunc" ip netns exec client \
480 ping -c 1 -W 2 10.0.0.2 || return 1
481
482 # trunc below ETH_HLEN must be rejected by the kernel
483 info "verify trunc(1) is rejected"
484 ovs_add_flow "test_trunc" trunctest \
485 'in_port(1),eth(),eth_type(0x0800),ipv4()' \
486 'trunc(1),2' &> /dev/null \
487 && { info "trunc(1) should be rejected"; return 1; }
488
489 info "verify trunc(13) is rejected"
490 ovs_add_flow "test_trunc" trunctest \
491 'in_port(1),eth(),eth_type(0x0800),ipv4()' \
492 'trunc(13),2' &> /dev/null \
493 && { info "trunc(13) should be rejected"; return 1; }
494
495 ovs_del_flows "test_trunc" trunctest
496 ovs_add_flow "test_trunc" trunctest \
497 'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1
498 ovs_add_flow "test_trunc" trunctest \
499 'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1
500
501 info "add trunc(14) forwarding flow"
502 ovs_add_flow "test_trunc" trunctest \
503 'in_port(1),eth(),eth_type(0x0800),ipv4()' \
504 'trunc(14),2' || return 1
505 ovs_add_flow "test_trunc" trunctest \
506 'in_port(2),eth(),eth_type(0x0800),ipv4()' \
507 '1' || return 1
508
509 info "verify ping fails with trunc(14)"
510 ovs_sbx "test_trunc" ip netns exec client \
511 ping -c 1 -W 2 10.0.0.2 >/dev/null 2>&1 \
512 && { info "ping should fail with trunc(14)"
513 return 1; }
514
515 ovs_del_flows "test_trunc" trunctest
516 ovs_add_flow "test_trunc" trunctest \
517 'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1
518 ovs_add_flow "test_trunc" trunctest \
519 'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1
520 ovs_add_flow "test_trunc" trunctest \
521 'in_port(1),eth(),eth_type(0x0800),ipv4()' \
522 '2' || return 1
523 ovs_add_flow "test_trunc" trunctest \
524 'in_port(2),eth(),eth_type(0x0800),ipv4()' \
525 '1' || return 1
526
527 info "verify connectivity restored"
528 ovs_sbx "test_trunc" ip netns exec client \
529 ping -c 1 -W 2 10.0.0.2 || return 1
530
531 return 0
532}
533
534# icmpv6 test
535# - static neighbours to bypass NDP (nud permanent)
536# - icmpv6(type=128) echo request, icmpv6(type=129) echo reply
537# - remove flows and verify ping fails, reinstall and recover
538test_icmpv6() {
539 local t="test_icmpv6"
540 local v6="eth_type(0x86dd),ipv6(proto=58)"
541
542 sbx_add "$t" || return $?
543 ovs_add_dp "$t" icmpv6 || return 1
544
545 info "create namespaces"
546 for ns in client server; do
547 ovs_add_netns_and_veths "$t" "icmpv6" \
548 "$ns" "${ns:0:1}0" "${ns:0:1}1" || return 1
549 done
550
551 ip netns exec client ip addr add fd00::1/64 dev c1 nodad
552 ip netns exec client ip link set c1 up
553 ip netns exec server ip addr add fd00::2/64 dev s1 nodad
554 ip netns exec server ip link set s1 up
555
556 local cl_mac sl_mac
557 cl_mac=$(ip netns exec client ip link show c1 \
558 | awk '/link\/ether/ {print $2}')
559 [ -z "$cl_mac" ] && \
560 { info "failed to get c1 hwaddr"; return 1; }
561 sl_mac=$(ip netns exec server ip link show s1 \
562 | awk '/link\/ether/ {print $2}')
563 [ -z "$sl_mac" ] && \
564 { info "failed to get s1 hwaddr"; return 1; }
565 ip netns exec client ip -6 neigh add fd00::2 \
566 lladdr "$sl_mac" nud permanent dev c1 || return 1
567 ip netns exec server ip -6 neigh add fd00::1 \
568 lladdr "$cl_mac" nud permanent dev s1 || return 1
569
570 # Probe: check if kernel supports icmpv6 flow key.
571 ovs_add_flow "$t" icmpv6 \
572 "in_port(1),eth(),$v6,icmpv6(type=128)" \
573 '2' &>/dev/null
574 if [ $? -ne 0 ]; then
575 info "no support for icmpv6 key - skipping"
576 ovs_exit_sig
577 return $ksft_skip
578 fi
579 ovs_del_flows "$t" icmpv6
580
581 ovs_add_flow "$t" icmpv6 \
582 "in_port(1),eth(),$v6,icmpv6(type=128)" \
583 '2' || return 1
584 ovs_add_flow "$t" icmpv6 \
585 "in_port(2),eth(),$v6,icmpv6(type=129)" \
586 '1' || return 1
587
588 info "verify ICMPv6 echo with type-specific flows"
589 ovs_sbx "$t" ip netns exec client \
590 ping -6 -c 1 -W 2 fd00::2 || return 1
591
592 ovs_del_flows "$t" icmpv6
593
594 info "verify ping fails without echo flows"
595 ovs_sbx "$t" ip netns exec client \
596 ping -6 -c 1 -W 2 fd00::2 >/dev/null 2>&1 \
597 && { info "ping should fail without flows"
598 return 1; }
599
600 ovs_add_flow "$t" icmpv6 \
601 "in_port(1),eth(),$v6,icmpv6(type=128)" \
602 '2' || return 1
603 ovs_add_flow "$t" icmpv6 \
604 "in_port(2),eth(),$v6,icmpv6(type=129)" \
605 '1' || return 1
606
607 info "verify connectivity restored"
608 ovs_sbx "$t" ip netns exec client \
609 ping -6 -c 1 -W 2 fd00::2 || return 1
610
611 return 0
612}
613
614# Check for an SCTP endpoint via /proc, which works without sctp_diag.
615sctp_eps_has() {
616 ip netns exec "$1" awk -v p="$2" '$6==p' /proc/net/sctp/eps | grep -q .
617}
618
619# sctp_connect_v4 test
620# - sctp(dst=4443) matches client-to-server INIT
621# - sctp(src=4443) matches server-to-client INIT-ACK
622# - remove flows and verify connection fails, reinstall and recover
623test_sctp_connect_v4() {
624 local t="test_sctp_connect_v4"
625 local srv_ip=172.31.110.20
626
627 modprobe -q sctp 2>/dev/null || return "$ksft_skip"
628 socat -V 2>&1 | grep -q "define WITH_SCTP" || return "$ksft_skip"
629
630 sbx_add "$t" || return $?
631 ovs_add_dp "$t" sctp4 || return 1
632
633 info "create namespaces"
634 for ns in client server; do
635 ovs_add_netns_and_veths "$t" "sctp4" "$ns" \
636 "${ns:0:1}0" "${ns:0:1}1" || return 1
637 done
638
639 ip netns exec client ip addr add 172.31.110.10/24 dev c1
640 ip netns exec client ip link set c1 up
641 ip netns exec server ip addr add "${srv_ip}/24" dev s1
642 ip netns exec server ip link set s1 up
643
644 # ARP forwarding
645 ovs_add_flow "$t" sctp4 \
646 'in_port(1),eth(),eth_type(0x0806),arp()' \
647 '2' || return 1
648 ovs_add_flow "$t" sctp4 \
649 'in_port(2),eth(),eth_type(0x0806),arp()' \
650 '1' || return 1
651
652 # SCTP port matching: dst for request, src for reply
653 ovs_add_flow "$t" sctp4 \
654 'in_port(1),eth(),eth_type(0x0800),ipv4(proto=132),sctp(dst=4443)' \
655 '2' || return 1
656 ovs_add_flow "$t" sctp4 \
657 'in_port(2),eth(),eth_type(0x0800),ipv4(proto=132),sctp(src=4443)' \
658 '1' || return 1
659
660 # The listener forks a child per association, so one instance serves
661 # the whole test and the flows stay the only variable. -t 1 bounds
662 # how long a child lingers after its association closes.
663 ovs_netns_spawn_daemon "$t" "server" \
664 socat -u -t 1 SCTP4-LISTEN:4443,fork STDOUT
665 ovs_wait sctp_eps_has server 4443 || return 1
666
667 info "verify SCTP association with port-keyed flows"
668 ovs_sbx "$t" ip netns exec client \
669 timeout 3 socat -u STDIN "SCTP4-CONNECT:${srv_ip}:4443" </dev/null \
670 || return 1
671
672 ovs_del_flows "$t" sctp4
673
674 info "verify connection fails without flows"
675 ovs_add_flow "$t" sctp4 \
676 'in_port(1),eth(),eth_type(0x0806),arp()' \
677 '2' || return 1
678 ovs_add_flow "$t" sctp4 \
679 'in_port(2),eth(),eth_type(0x0806),arp()' \
680 '1' || return 1
681
682 ovs_sbx "$t" ip netns exec client \
683 timeout 3 socat -u STDIN "SCTP4-CONNECT:${srv_ip}:4443" </dev/null \
684 >/dev/null 2>&1 \
685 && { info "connection should fail without flows"
686 return 1; }
687
688 info "reinstall flows and verify recovery"
689 ovs_add_flow "$t" sctp4 \
690 'in_port(1),eth(),eth_type(0x0800),ipv4(proto=132),sctp(dst=4443)' \
691 '2' || return 1
692 ovs_add_flow "$t" sctp4 \
693 'in_port(2),eth(),eth_type(0x0800),ipv4(proto=132),sctp(src=4443)' \
694 '1' || return 1
695
696 ovs_sbx "$t" ip netns exec client \
697 timeout 3 socat -u STDIN "SCTP4-CONNECT:${srv_ip}:4443" </dev/null \
698 || return 1
699
700 return 0
701}
702
703# psample test
704# - use psample to observe packets
705test_psample() {
706 sbx_add "test_psample" || return $?
707
708 # Add a datapath with per-vport dispatching.
709 ovs_add_dp "test_psample" psample -V 2:1 || return 1
710
711 info "create namespaces"
712 ovs_add_netns_and_veths "test_psample" "psample" \
713 client c0 c1 172.31.110.10/24 -u || return 1
714 ovs_add_netns_and_veths "test_psample" "psample" \
715 server s0 s1 172.31.110.20/24 -u || return 1
716
717 # Check if psample actions can be configured.
718 ovs_add_flow "test_psample" psample \
719 'in_port(1),eth(),eth_type(0x0806),arp()' 'psample(group=1)' &> /dev/null
720 if [ $? == 1 ]; then
721 info "no support for psample - skipping"
722 ovs_exit_sig
723 return $ksft_skip
724 fi
725
726 ovs_del_flows "test_psample" psample
727
728 # Test action verification.
729 OLDIFS=$IFS
730 IFS='*'
731 min_key='in_port(1),eth(),eth_type(0x0800),ipv4()'
732 for testcase in \
733 "cookie to large"*"psample(group=1,cookie=1615141312111009080706050403020100)" \
734 "no group with cookie"*"psample(cookie=abcd)" \
735 "no group"*"psample()";
736 do
737 set -- $testcase;
738 ovs_test_flow_fails "test_psample" psample $min_key $2
739 if [ $? == 1 ]; then
740 info "failed - $1"
741 return 1
742 fi
743 done
744 IFS=$OLDIFS
745
746 ovs_del_flows "test_psample" psample
747 # Allow ARP
748 ovs_add_flow "test_psample" psample \
749 'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1
750 ovs_add_flow "test_psample" psample \
751 'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1
752
753 # Sample first 14 bytes of all traffic.
754 ovs_add_flow "test_psample" psample \
755 "in_port(1),eth(),eth_type(0x0800),ipv4()" \
756 "trunc(14),psample(group=1,cookie=c0ffee),2"
757
758 # Sample all traffic. In this case, use a sample() action with both
759 # psample and an upcall emulating simultaneous local sampling and
760 # sFlow / IPFIX.
761 nlpid=$(grep -E "listening on upcall packet handler" \
762 $ovs_dir/s0.out | cut -d ":" -f 2 | tr -d ' ')
763 [ -z "$nlpid" ] && \
764 { info "failed to get upcall PID"; return 1; }
765
766 ovs_add_flow "test_psample" psample \
767 "in_port(2),eth(),eth_type(0x0800),ipv4()" \
768 "sample(sample=100%,actions(psample(group=2,cookie=eeff0c),userspace(pid=${nlpid},userdata=eeff0c))),1"
769
770 # Record psample data.
771 ovs_spawn_daemon "test_psample" python3 $ovs_base/ovs-dpctl.py psample-events
772 ovs_wait grep -q "listening for psample events" ${ovs_dir}/stdout
773
774 # Send a single ping.
775 ovs_sbx "test_psample" ip netns exec client ping -I c1 172.31.110.20 -c 1 || return 1
776
777 # We should have received one userspace action upcall and 2 psample packets.
778 ovs_wait grep -q "userspace action command" $ovs_dir/s0.out || return 1
779
780 # client -> server samples should only contain the first 14 bytes of the packet.
781 ovs_wait grep -qE "rate:4294967295,group:1,cookie:c0ffee data:[0-9a-f]{28}$" \
782 $ovs_dir/stdout || return 1
783
784 ovs_wait grep -q "rate:4294967295,group:2,cookie:eeff0c" $ovs_dir/stdout || return 1
785
786 return 0
787}
788
789# drop_reason test
790# - drop packets and verify the right drop reason is reported
791test_drop_reason() {
792 which perf >/dev/null 2>&1 || return $ksft_skip
793 which pahole >/dev/null 2>&1 || return $ksft_skip
794
795 ovs_drop_subsys=$(pahole -C skb_drop_reason_subsys |
796 awk '/OPENVSWITCH/ { print $3; }' |
797 tr -d ,)
798 if [ -z "$ovs_drop_subsys" ]; then
799 info "failed to get OVS drop subsys ID"
800 return $ksft_skip
801 fi
802
803 sbx_add "test_drop_reason" || return $?
804
805 ovs_add_dp "test_drop_reason" dropreason || return 1
806
807 info "create namespaces"
808 for ns in client server; do
809 ovs_add_netns_and_veths "test_drop_reason" "dropreason" "$ns" \
810 "${ns:0:1}0" "${ns:0:1}1" || return 1
811 done
812
813 # Setup client namespace
814 ip netns exec client ip addr add 172.31.110.10/24 dev c1
815 ip netns exec client ip link set c1 up
816
817 # Setup server namespace
818 ip netns exec server ip addr add 172.31.110.20/24 dev s1
819 ip netns exec server ip link set s1 up
820
821 # Check if drop reasons can be sent
822 ovs_add_flow "test_drop_reason" dropreason \
823 'in_port(1),eth(),eth_type(0x0806),arp()' 'drop(10)' 2>/dev/null
824 if [ $? == 1 ]; then
825 info "no support for drop reasons - skipping"
826 ovs_exit_sig
827 return $ksft_skip
828 fi
829
830 ovs_del_flows "test_drop_reason" dropreason
831
832 # Allow ARP
833 ovs_add_flow "test_drop_reason" dropreason \
834 'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1
835 ovs_add_flow "test_drop_reason" dropreason \
836 'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1
837
838 # Allow client ICMP traffic but drop return path
839 ovs_add_flow "test_drop_reason" dropreason \
840 "in_port(1),eth(),eth_type(0x0800),ipv4(src=172.31.110.10,proto=1),icmp()" '2'
841 ovs_add_flow "test_drop_reason" dropreason \
842 "in_port(2),eth(),eth_type(0x0800),ipv4(src=172.31.110.20,proto=1),icmp()" 'drop'
843
844 ovs_drop_record_and_run "test_drop_reason" ip netns exec client ping -c 2 172.31.110.20
845 ovs_drop_reason_count 0x${ovs_drop_subsys}0001 # OVS_DROP_FLOW_ACTION
846 if [[ "$?" -ne "2" ]]; then
847 info "Did not detect expected drops: $?"
848 return 1
849 fi
850
851 # Drop UDP 6000 traffic with an explicit action and an error code.
852 ovs_add_flow "test_drop_reason" dropreason \
853 "in_port(1),eth(),eth_type(0x0800),ipv4(src=172.31.110.10,proto=17),udp(dst=6000)" \
854 'drop(42)'
855 # Drop UDP 7000 traffic with an explicit action with no error code.
856 ovs_add_flow "test_drop_reason" dropreason \
857 "in_port(1),eth(),eth_type(0x0800),ipv4(src=172.31.110.10,proto=17),udp(dst=7000)" \
858 'drop(0)'
859
860 ovs_drop_record_and_run \
861 "test_drop_reason" ip netns exec client nc -i 1 -zuv 172.31.110.20 6000
862 ovs_drop_reason_count 0x${ovs_drop_subsys}0004 # OVS_DROP_EXPLICIT_ACTION_ERROR
863 if [[ "$?" -ne "1" ]]; then
864 info "Did not detect expected explicit error drops: $?"
865 return 1
866 fi
867
868 ovs_drop_record_and_run \
869 "test_drop_reason" ip netns exec client nc -i 1 -zuv 172.31.110.20 7000
870 ovs_drop_reason_count 0x${ovs_drop_subsys}0003 # OVS_DROP_EXPLICIT_ACTION
871 if [[ "$?" -ne "1" ]]; then
872 info "Did not detect expected explicit drops: $?"
873 return 1
874 fi
875
876 return 0
877}
878
879# arp_ping test
880# - client has 1500 byte MTU
881# - server has 1500 byte MTU
882# - send ARP ping between two ns
883test_arp_ping () {
884
885 which arping >/dev/null 2>&1 || return $ksft_skip
886
887 sbx_add "test_arp_ping" || return $?
888
889 ovs_add_dp "test_arp_ping" arpping || return 1
890
891 info "create namespaces"
892 for ns in client server; do
893 ovs_add_netns_and_veths "test_arp_ping" "arpping" "$ns" \
894 "${ns:0:1}0" "${ns:0:1}1" || return 1
895 done
896
897 # Setup client namespace
898 ip netns exec client ip addr add 172.31.110.10/24 dev c1
899 ip netns exec client ip link set c1 up
900 HW_CLIENT=$(ip netns exec client ip link show dev c1 \
901 | awk '/link\/ether/ {print $2}')
902 [ -z "$HW_CLIENT" ] && \
903 { info "failed to get client hwaddr"; return 1; }
904 info "Client hwaddr: $HW_CLIENT"
905
906 # Setup server namespace
907 ip netns exec server ip addr add 172.31.110.20/24 dev s1
908 ip netns exec server ip link set s1 up
909 HW_SERVER=$(ip netns exec server ip link show dev s1 \
910 | awk '/link\/ether/ {print $2}')
911 [ -z "$HW_SERVER" ] && \
912 { info "failed to get server hwaddr"; return 1; }
913 info "Server hwaddr: $HW_SERVER"
914
915 ovs_add_flow "test_arp_ping" arpping \
916 "in_port(1),eth(),eth_type(0x0806),arp(sip=172.31.110.10,tip=172.31.110.20,sha=$HW_CLIENT,tha=ff:ff:ff:ff:ff:ff)" '2' || return 1
917 ovs_add_flow "test_arp_ping" arpping \
918 "in_port(2),eth(),eth_type(0x0806),arp()" '1' || return 1
919
920 ovs_sbx "test_arp_ping" ip netns exec client arping -I c1 172.31.110.20 -c 1 || return 1
921
922 return 0
923}
924
925# ct_connect_v4 test
926# - client has 1500 byte MTU
927# - server has 1500 byte MTU
928# - use ICMP to ping in each direction
929# - only allow CT state stuff to pass through new in c -> s
930test_ct_connect_v4 () {
931
932 which nc >/dev/null 2>/dev/null || return $ksft_skip
933
934 sbx_add "test_ct_connect_v4" || return $?
935
936 ovs_add_dp "test_ct_connect_v4" ct4 || return 1
937 info "create namespaces"
938 for ns in client server; do
939 ovs_add_netns_and_veths "test_ct_connect_v4" "ct4" "$ns" \
940 "${ns:0:1}0" "${ns:0:1}1" || return 1
941 done
942
943 ip netns exec client ip addr add 172.31.110.10/24 dev c1
944 ip netns exec client ip link set c1 up
945 ip netns exec server ip addr add 172.31.110.20/24 dev s1
946 ip netns exec server ip link set s1 up
947
948 # Add forwarding for ARP and ip packets - completely wildcarded
949 ovs_add_flow "test_ct_connect_v4" ct4 \
950 'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1
951 ovs_add_flow "test_ct_connect_v4" ct4 \
952 'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1
953 ovs_add_flow "test_ct_connect_v4" ct4 \
954 'ct_state(-trk),eth(),eth_type(0x0800),ipv4()' \
955 'ct(commit),recirc(0x1)' || return 1
956 ovs_add_flow "test_ct_connect_v4" ct4 \
957 'recirc_id(0x1),ct_state(+trk+new),in_port(1),eth(),eth_type(0x0800),ipv4(src=172.31.110.10)' \
958 '2' || return 1
959 ovs_add_flow "test_ct_connect_v4" ct4 \
960 'recirc_id(0x1),ct_state(+trk+est),in_port(1),eth(),eth_type(0x0800),ipv4(src=172.31.110.10)' \
961 '2' || return 1
962 ovs_add_flow "test_ct_connect_v4" ct4 \
963 'recirc_id(0x1),ct_state(+trk+est),in_port(2),eth(),eth_type(0x0800),ipv4(dst=172.31.110.10)' \
964 '1' || return 1
965 ovs_add_flow "test_ct_connect_v4" ct4 \
966 'recirc_id(0x1),ct_state(+trk+inv),eth(),eth_type(0x0800),ipv4()' 'drop' || \
967 return 1
968
969 # do a ping
970 ovs_sbx "test_ct_connect_v4" ip netns exec client ping 172.31.110.20 -c 3 || return 1
971
972 # create an echo server in 'server'
973 echo "server" | \
974 ovs_netns_spawn_daemon "test_ct_connect_v4" "server" \
975 nc -lvnp 4443
976 ovs_sbx "test_ct_connect_v4" ip netns exec client nc -i 1 -zv 172.31.110.20 4443 || return 1
977
978 # Now test in the other direction (should fail)
979 echo "client" | \
980 ovs_netns_spawn_daemon "test_ct_connect_v4" "client" \
981 nc -lvnp 4443
982 ovs_sbx "test_ct_connect_v4" ip netns exec client nc -i 1 -zv 172.31.110.10 4443
983 if [ $? == 0 ]; then
984 info "ct connect to client was successful"
985 return 1
986 fi
987
988 info "done..."
989 return 0
990}
991
992# connect_v4 test
993# - client has 1500 byte MTU
994# - server has 1500 byte MTU
995# - use ICMP to ping in each direction
996test_connect_v4 () {
997
998 sbx_add "test_connect_v4" || return $?
999
1000 ovs_add_dp "test_connect_v4" cv4 || return 1
1001
1002 info "create namespaces"
1003 for ns in client server; do
1004 ovs_add_netns_and_veths "test_connect_v4" "cv4" "$ns" \
1005 "${ns:0:1}0" "${ns:0:1}1" || return 1
1006 done
1007
1008
1009 ip netns exec client ip addr add 172.31.110.10/24 dev c1
1010 ip netns exec client ip link set c1 up
1011 ip netns exec server ip addr add 172.31.110.20/24 dev s1
1012 ip netns exec server ip link set s1 up
1013
1014 # Add forwarding for ARP and ip packets - completely wildcarded
1015 ovs_add_flow "test_connect_v4" cv4 \
1016 'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1
1017 ovs_add_flow "test_connect_v4" cv4 \
1018 'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1
1019 ovs_add_flow "test_connect_v4" cv4 \
1020 'in_port(1),eth(),eth_type(0x0800),ipv4(src=172.31.110.10)' '2' || return 1
1021 ovs_add_flow "test_connect_v4" cv4 \
1022 'in_port(2),eth(),eth_type(0x0800),ipv4(src=172.31.110.20)' '1' || return 1
1023
1024 # do a ping
1025 ovs_sbx "test_connect_v4" ip netns exec client ping 172.31.110.20 -c 3 || return 1
1026
1027 info "done..."
1028 return 0
1029}
1030
1031# nat_connect_v4 test
1032# - client has 1500 byte MTU
1033# - server has 1500 byte MTU
1034# - use ICMP to ping in each direction
1035# - only allow CT state stuff to pass through new in c -> s
1036test_nat_connect_v4 () {
1037 which nc >/dev/null 2>/dev/null || return $ksft_skip
1038
1039 sbx_add "test_nat_connect_v4" || return $?
1040
1041 ovs_add_dp "test_nat_connect_v4" nat4 || return 1
1042 info "create namespaces"
1043 for ns in client server; do
1044 ovs_add_netns_and_veths "test_nat_connect_v4" "nat4" "$ns" \
1045 "${ns:0:1}0" "${ns:0:1}1" || return 1
1046 done
1047
1048 ip netns exec client ip addr add 172.31.110.10/24 dev c1
1049 ip netns exec client ip link set c1 up
1050 ip netns exec server ip addr add 172.31.110.20/24 dev s1
1051 ip netns exec server ip link set s1 up
1052
1053 ip netns exec client ip route add default via 172.31.110.20
1054
1055 ovs_add_flow "test_nat_connect_v4" nat4 \
1056 'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1
1057 ovs_add_flow "test_nat_connect_v4" nat4 \
1058 'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1
1059 ovs_add_flow "test_nat_connect_v4" nat4 \
1060 "ct_state(-trk),in_port(1),eth(),eth_type(0x0800),ipv4(dst=192.168.0.20)" \
1061 "ct(commit,nat(dst=172.31.110.20)),recirc(0x1)"
1062 ovs_add_flow "test_nat_connect_v4" nat4 \
1063 "ct_state(-trk),in_port(2),eth(),eth_type(0x0800),ipv4()" \
1064 "ct(commit,nat),recirc(0x2)"
1065
1066 ovs_add_flow "test_nat_connect_v4" nat4 \
1067 "recirc_id(0x1),ct_state(+trk-inv),in_port(1),eth(),eth_type(0x0800),ipv4()" "2"
1068 ovs_add_flow "test_nat_connect_v4" nat4 \
1069 "recirc_id(0x2),ct_state(+trk-inv),in_port(2),eth(),eth_type(0x0800),ipv4()" "1"
1070
1071 # do a ping
1072 ovs_sbx "test_nat_connect_v4" ip netns exec client ping 192.168.0.20 -c 3 || return 1
1073
1074 # create an echo server in 'server'
1075 echo "server" | \
1076 ovs_netns_spawn_daemon "test_nat_connect_v4" "server" \
1077 nc -lvnp 4443
1078 ovs_sbx "test_nat_connect_v4" ip netns exec client nc -i 1 -zv 192.168.0.20 4443 || return 1
1079
1080 # Now test in the other direction (should fail)
1081 echo "client" | \
1082 ovs_netns_spawn_daemon "test_nat_connect_v4" "client" \
1083 nc -lvnp 4443
1084 ovs_sbx "test_nat_connect_v4" ip netns exec client nc -i 1 -zv 172.31.110.10 4443
1085 if [ $? == 0 ]; then
1086 info "connect to client was successful"
1087 return 1
1088 fi
1089
1090 info "done..."
1091 return 0
1092}
1093
1094# nat_related_v4 test
1095# - client->server ip packets go via SNAT
1096# - client solicits ICMP destination unreachable packet from server
1097# - undo NAT for ICMP reply and test dst ip has been updated
1098test_nat_related_v4 () {
1099 which nc >/dev/null 2>/dev/null || return $ksft_skip
1100
1101 sbx_add "test_nat_related_v4" || return $?
1102
1103 ovs_add_dp "test_nat_related_v4" natrelated4 || return 1
1104 info "create namespaces"
1105 for ns in client server; do
1106 ovs_add_netns_and_veths "test_nat_related_v4" "natrelated4" "$ns" \
1107 "${ns:0:1}0" "${ns:0:1}1" || return 1
1108 done
1109
1110 ip netns exec client ip addr add 172.31.110.10/24 dev c1
1111 ip netns exec client ip link set c1 up
1112 ip netns exec server ip addr add 172.31.110.20/24 dev s1
1113 ip netns exec server ip link set s1 up
1114
1115 ip netns exec server ip route add 192.168.0.20/32 via 172.31.110.10
1116
1117 # Allow ARP
1118 ovs_add_flow "test_nat_related_v4" natrelated4 \
1119 "in_port(1),eth(),eth_type(0x0806),arp()" "2" || return 1
1120 ovs_add_flow "test_nat_related_v4" natrelated4 \
1121 "in_port(2),eth(),eth_type(0x0806),arp()" "1" || return 1
1122
1123 # Allow IP traffic from client->server, rewrite source IP with SNAT to 192.168.0.20
1124 ovs_add_flow "test_nat_related_v4" natrelated4 \
1125 "ct_state(-trk),in_port(1),eth(),eth_type(0x0800),ipv4(dst=172.31.110.20)" \
1126 "ct(commit,nat(src=192.168.0.20)),recirc(0x1)" || return 1
1127 ovs_add_flow "test_nat_related_v4" natrelated4 \
1128 "recirc_id(0x1),ct_state(+trk-inv),in_port(1),eth(),eth_type(0x0800),ipv4()" \
1129 "2" || return 1
1130
1131 # Allow related ICMP responses back from server and undo NAT to restore original IP
1132 # Drop any ICMP related packets where dst ip hasn't been restored back to original IP
1133 ovs_add_flow "test_nat_related_v4" natrelated4 \
1134 "ct_state(-trk),in_port(2),eth(),eth_type(0x0800),ipv4()" \
1135 "ct(commit,nat),recirc(0x2)" || return 1
1136 ovs_add_flow "test_nat_related_v4" natrelated4 \
1137 "recirc_id(0x2),ct_state(+rel+trk),in_port(2),eth(),eth_type(0x0800),ipv4(src=172.31.110.20,dst=172.31.110.10,proto=1),icmp()" \
1138 "1" || return 1
1139 ovs_add_flow "test_nat_related_v4" natrelated4 \
1140 "recirc_id(0x2),ct_state(+rel+trk),in_port(2),eth(),eth_type(0x0800),ipv4(dst=192.168.0.20,proto=1),icmp()" \
1141 "drop" || return 1
1142
1143 # Solicit destination unreachable response from server
1144 ovs_sbx "test_nat_related_v4" ip netns exec client \
1145 bash -c "echo a | nc -u -w 1 172.31.110.20 10000"
1146
1147 # Check to make sure no packets matched the drop rule with incorrect dst ip
1148 python3 "$ovs_base/ovs-dpctl.py" dump-flows natrelated4 \
1149 | grep "drop" | grep "packets:0" >/dev/null || return 1
1150
1151 info "done..."
1152 return 0
1153}
1154
1155# netlink_validation
1156# - Create a dp
1157# - check no warning with "old version" simulation
1158test_netlink_checks () {
1159 sbx_add "test_netlink_checks" || return 1
1160
1161 info "setting up new DP"
1162 ovs_add_dp "test_netlink_checks" nv0 || return 1
1163 # now try again
1164 PRE_TEST=$(dmesg | grep -E "RIP: [0-9a-fA-Fx]+:ovs_dp_cmd_new\+")
1165 ovs_add_dp "test_netlink_checks" nv0 -V 0 || return 1
1166 POST_TEST=$(dmesg | grep -E "RIP: [0-9a-fA-Fx]+:ovs_dp_cmd_new\+")
1167 if [ "$PRE_TEST" != "$POST_TEST" ]; then
1168 info "failed - gen warning"
1169 return 1
1170 fi
1171
1172 ovs_add_netns_and_veths "test_netlink_checks" nv0 left left0 l0 || \
1173 return 1
1174 ovs_add_netns_and_veths "test_netlink_checks" nv0 right right0 r0 || \
1175 return 1
1176 [ $(python3 $ovs_base/ovs-dpctl.py show nv0 | grep port | \
1177 wc -l) == 3 ] || \
1178 return 1
1179 ovs_del_if "test_netlink_checks" nv0 right0 || return 1
1180 [ $(python3 $ovs_base/ovs-dpctl.py show nv0 | grep port | \
1181 wc -l) == 2 ] || \
1182 return 1
1183
1184 info "Checking clone depth"
1185 ERR_MSG="Flow actions may not be safe on all matching packets"
1186 PRE_TEST=$(dmesg | grep -c "${ERR_MSG}")
1187 ovs_add_flow "test_netlink_checks" nv0 \
1188 'in_port(1),eth(),eth_type(0x800),ipv4()' \
1189 'clone(clone(clone(clone(clone(clone(clone(clone(clone(clone(clone(clone(clone(clone(clone(clone(clone(drop)))))))))))))))))' \
1190 >/dev/null 2>&1 && return 1
1191 POST_TEST=$(dmesg | grep -c "${ERR_MSG}")
1192
1193 if [ "$PRE_TEST" == "$POST_TEST" ]; then
1194 info "failed - clone depth too large"
1195 return 1
1196 fi
1197
1198 PRE_TEST=$(dmesg | grep -c "${ERR_MSG}")
1199 ovs_add_flow "test_netlink_checks" nv0 \
1200 'in_port(1),eth(),eth_type(0x0806),arp()' 'drop(0),2' \
1201 &> /dev/null && return 1
1202 POST_TEST=$(dmesg | grep -c "${ERR_MSG}")
1203 if [ "$PRE_TEST" == "$POST_TEST" ]; then
1204 info "failed - error not generated"
1205 return 1
1206 fi
1207 return 0
1208}
1209
1210test_upcall_interfaces() {
1211 sbx_add "test_upcall_interfaces" || return 1
1212
1213 info "setting up new DP"
1214 ovs_add_dp "test_upcall_interfaces" ui0 -V 2:1 || return 1
1215
1216 ovs_add_netns_and_veths "test_upcall_interfaces" ui0 upc left0 l0 \
1217 172.31.110.1/24 -u || return 1
1218
1219 ovs_wait grep -q "listening on upcall packet handler" ${ovs_dir}/left0.out
1220
1221 info "sending arping"
1222 ip netns exec upc arping -I l0 172.31.110.20 -c 1 \
1223 >$ovs_dir/arping.stdout 2>$ovs_dir/arping.stderr
1224
1225 grep -E "MISS upcall\[0/yes\]: .*arp\(sip=172.31.110.1,tip=172.31.110.20,op=1,sha=" $ovs_dir/left0.out >/dev/null 2>&1 || return 1
1226 return 0
1227}
1228
1229ovs_add_kernel_tunnel() {
1230 local sbxname=$1; shift
1231 local ns=$1; shift
1232 local tnl_type=$1; shift
1233 local name=$1; shift
1234 local addr=$1; shift
1235
1236 info "setting up kernel ${tnl_type} tunnel ${name}"
1237 ovs_sbx "${sbxname}" ip -netns ${ns} link add dev ${name} type ${tnl_type} $* || return 1
1238 on_exit "ovs_sbx ${sbxname} ip -netns ${ns} link del ${name} >/dev/null 2>&1"
1239 ovs_sbx "${sbxname}" ip -netns ${ns} addr add dev ${name} ${addr} || return 1
1240 ovs_sbx "${sbxname}" ip -netns ${ns} link set dev ${name} mtu 1450 up || return 1
1241}
1242
1243test_tunnel_metadata() {
1244 which arping >/dev/null 2>&1 || return $ksft_skip
1245
1246 sbxname="test_tunnel_metadata"
1247 sbx_add "${sbxname}" || return 1
1248
1249 info "setting up new DP"
1250 ovs_add_dp "${sbxname}" tdp0 -V 2:1 || return 1
1251
1252 ovs_add_netns_and_veths "${sbxname}" tdp0 tns left0 l0 \
1253 172.31.110.1/24 || return 1
1254
1255 info "removing veth interface from openvswitch and setting IP"
1256 ovs_del_if "${sbxname}" tdp0 left0 || return 1
1257 ovs_sbx "${sbxname}" ip addr add 172.31.110.2/24 dev left0 || return 1
1258 ovs_sbx "${sbxname}" ip link set left0 up || return 1
1259
1260 info "setting up tunnel port in openvswitch"
1261 ovs_add_if "${sbxname}" "vxlan" tdp0 ovs-vxlan0 -u || return 1
1262 on_exit "ovs_sbx ${sbxname} ip link del ovs-vxlan0"
1263 ovs_wait ip link show ovs-vxlan0 &>/dev/null || return 1
1264 ovs_sbx "${sbxname}" ip link set ovs-vxlan0 up || return 1
1265
1266 configs=$(echo '
1267 1 172.31.221.1/24 1155332 32 set udpcsum flags\(df\|csum\)
1268 2 172.31.222.1/24 1234567 45 set noudpcsum flags\(df\)
1269 3 172.31.223.1/24 1020304 23 unset udpcsum flags\(csum\)
1270 4 172.31.224.1/24 1357986 15 unset noudpcsum' | sed '/^$/d')
1271
1272 while read -r i addr id ttl df csum flags; do
1273 ovs_add_kernel_tunnel "${sbxname}" tns vxlan vxlan${i} ${addr} \
1274 remote 172.31.110.2 id ${id} dstport 4789 \
1275 ttl ${ttl} df ${df} ${csum} || return 1
1276 done <<< "${configs}"
1277
1278 ovs_wait grep -q 'listening on upcall packet handler' \
1279 ${ovs_dir}/ovs-vxlan0.out || return 1
1280
1281 info "sending arping"
1282 for i in 1 2 3 4; do
1283 ovs_sbx "${sbxname}" ip netns exec tns \
1284 arping -I vxlan${i} 172.31.22${i}.2 -c 1 \
1285 >${ovs_dir}/arping.stdout 2>${ovs_dir}/arping.stderr
1286 done
1287
1288 info "checking that received decapsulated packets carry correct metadata"
1289 while read -r i addr id ttl df csum flags; do
1290 arp_hdr="arp\\(sip=172.31.22${i}.1,tip=172.31.22${i}.2,op=1,sha="
1291 addrs="src=172.31.110.1,dst=172.31.110.2"
1292 ports="tp_src=[0-9]*,tp_dst=4789"
1293 tnl_md="tunnel\\(tun_id=${id},${addrs},ttl=${ttl},${ports},${flags}\\)"
1294
1295 ovs_sbx "${sbxname}" grep -qE "MISS upcall.*${tnl_md}.*${arp_hdr}" \
1296 ${ovs_dir}/ovs-vxlan0.out || return 1
1297 done <<< "${configs}"
1298
1299 return 0
1300}
1301
1302test_pop_vlan() {
1303 local sbx="test_pop_vlan"
1304 sbx_add "$sbx" || return $?
1305 ovs_add_dp "$sbx" vlandp || return 1
1306
1307 ovs_add_netns_and_veths "$sbx" vlandp \
1308 ns1 veth1 ns1veth 192.0.2.1/24 || return 1
1309 ovs_add_netns_and_veths "$sbx" vlandp \
1310 ns2 veth2 ns2veth 192.0.2.2/24 || return 1
1311
1312 # Baseline: untagged bidirectional forwarding
1313 ovs_add_flow "$sbx" vlandp \
1314 'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1
1315 ovs_add_flow "$sbx" vlandp \
1316 'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1
1317 ovs_add_flow "$sbx" vlandp \
1318 'in_port(1),eth(),eth_type(0x0800),ipv4()' '2' || return 1
1319 ovs_add_flow "$sbx" vlandp \
1320 'in_port(2),eth(),eth_type(0x0800),ipv4()' '1' || return 1
1321 ovs_sbx "$sbx" ip netns exec ns1 ping -c 3 -W 2 \
1322 192.0.2.2 || return 1
1323
1324 # VLAN topology: ns1 uses VLAN sub-interface, ns2 is plain
1325 ip -n ns1 link add link ns1veth name ns1veth.10 \
1326 type vlan id 10 || return 1
1327 on_exit "ip -n ns1 link del ns1veth.10 2>/dev/null"
1328 ip -n ns1 addr add 198.51.100.1/24 dev ns1veth.10 || return 1
1329 ip -n ns1 link set ns1veth.10 up || return 1
1330 ip -n ns2 addr add 198.51.100.2/24 dev ns2veth || return 1
1331
1332 ovs_del_flows "$sbx" vlandp
1333
1334 # Static ARP: avoids VLAN-tagged ARP complexity
1335 local ns1veth10mac ns2mac
1336 ns1veth10mac=$(ip -n ns1 link show ns1veth.10 \
1337 | awk '/link\/ether/ {print $2}')
1338 [ -z "$ns1veth10mac" ] && \
1339 { info "failed to get ns1veth10mac"; return 1; }
1340 ns2mac=$(ip -n ns2 link show ns2veth \
1341 | awk '/link\/ether/ {print $2}')
1342 [ -z "$ns2mac" ] && \
1343 { info "failed to get ns2mac"; return 1; }
1344 ip -n ns1 neigh replace 198.51.100.2 lladdr "$ns2mac" \
1345 dev ns1veth.10 nud permanent || return 1
1346 ip -n ns2 neigh replace 198.51.100.1 \
1347 lladdr "$ns1veth10mac" \
1348 dev ns2veth nud permanent || return 1
1349
1350 local vlan_match='in_port(1),eth(),eth_type(0x8100),'
1351 vlan_match+='vlan(vid=10),'
1352 vlan_match+='encap(eth_type(0x0800),'
1353 vlan_match+='ipv4(src=198.51.100.1,proto=1),icmp())'
1354
1355 # Negative: forward without pop_vlan -- tagged frame
1356 # is invisible to ns2 (no VLAN sub-interface), ping fails
1357 ovs_add_flow "$sbx" vlandp "$vlan_match" '2' || return 1
1358 ovs_sbx "$sbx" ip netns exec ns1 ping -I ns1veth.10 \
1359 -c 3 -W 1 198.51.100.2 >/dev/null 2>&1 \
1360 && { info "FAIL: ping should fail without pop_vlan"
1361 return 1; }
1362
1363 ovs_del_flows "$sbx" vlandp
1364
1365 # Positive: pop_vlan strips tag on forward path,
1366 # push_vlan restores tag on return path -- ping succeeds
1367 ovs_add_flow "$sbx" vlandp \
1368 "$vlan_match" 'pop_vlan,2' || return 1
1369 ovs_add_flow "$sbx" vlandp \
1370 'in_port(2),eth(),eth_type(0x0800),ipv4()' \
1371 'push_vlan(vid=10,pcp=0,tpid=0x8100),1' || return 1
1372 ovs_sbx "$sbx" ip netns exec ns1 ping -I ns1veth.10 \
1373 -c 3 -W 2 198.51.100.2 || return 1
1374
1375 return 0
1376}
1377
1378run_test() {
1379 (
1380 tname="$1"
1381 tdesc="$2"
1382
1383 if python3 ovs-dpctl.py -h 2>&1 | \
1384 grep -E "Need to (install|upgrade) the python" >/dev/null 2>&1; then
1385 stdbuf -o0 printf "TEST: %-60s [PYLIB]\n" "${tdesc}"
1386 return $ksft_skip
1387 fi
1388
1389 python3 ovs-dpctl.py show >/dev/null 2>&1 || \
1390 echo "[DPCTL] show exception."
1391
1392 if ! lsmod | grep openvswitch >/dev/null 2>&1; then
1393 stdbuf -o0 printf "TEST: %-60s [NOMOD]\n" "${tdesc}"
1394 return $ksft_skip
1395 fi
1396
1397 printf "TEST: %-60s [START]\n" "${tname}"
1398
1399 unset IFS
1400
1401 eval test_${tname}
1402 ret=$?
1403
1404 if [ $ret -eq 0 ]; then
1405 printf "TEST: %-60s [ OK ]\n" "${tdesc}"
1406 ovs_exit_sig
1407 rm -rf "$ovs_dir"
1408 elif [ $ret -eq 1 ]; then
1409 printf "TEST: %-60s [FAIL]\n" "${tdesc}"
1410 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
1411 echo
1412 echo "Pausing. Logs in $ovs_dir/. Hit enter to continue"
1413 read a
1414 fi
1415 ovs_exit_sig
1416 [ "${PAUSE_ON_FAIL}" = "yes" ] || rm -rf "$ovs_dir"
1417 exit 1
1418 elif [ $ret -eq $ksft_skip ]; then
1419 printf "TEST: %-60s [SKIP]\n" "${tdesc}"
1420 elif [ $ret -eq 2 ]; then
1421 rm -rf test_${tname}
1422 run_test "$1" "$2"
1423 fi
1424
1425 return $ret
1426 )
1427 ret=$?
1428 case $ret in
1429 0)
1430 [ $all_skipped = true ] && [ $exitcode=$ksft_skip ] && exitcode=0
1431 all_skipped=false
1432 ;;
1433 $ksft_skip)
1434 [ $all_skipped = true ] && exitcode=$ksft_skip
1435 ;;
1436 *)
1437 all_skipped=false
1438 exitcode=1
1439 ;;
1440 esac
1441
1442 return $ret
1443}
1444
1445
1446exitcode=0
1447desc=0
1448all_skipped=true
1449
1450while getopts :pvt o
1451do
1452 case $o in
1453 p) PAUSE_ON_FAIL=yes;;
1454 v) VERBOSE=1;;
1455 t) if which tcpdump > /dev/null 2>&1; then
1456 TRACING=1
1457 else
1458 echo "=== tcpdump not available, tracing disabled"
1459 fi
1460 ;;
1461 *) usage;;
1462 esac
1463done
1464shift $(($OPTIND-1))
1465
1466IFS="
1467"
1468
1469for arg do
1470 # Check first that all requested tests are available before running any
1471 command -v > /dev/null "test_${arg}" || { echo "=== Test ${arg} not found"; usage; }
1472done
1473
1474name=""
1475desc=""
1476for t in ${tests}; do
1477 [ "${name}" = "" ] && name="${t}" && continue
1478 [ "${desc}" = "" ] && desc="${t}"
1479
1480 run_this=1
1481 for arg do
1482 [ "${arg}" != "${arg#--*}" ] && continue
1483 [ "${arg}" = "${name}" ] && run_this=1 && break
1484 run_this=0
1485 done
1486 if [ $run_this -eq 1 ]; then
1487 run_test "${name}" "${desc}"
1488 fi
1489 name=""
1490 desc=""
1491done
1492
1493exit ${exitcode}