Merge branches 'clk-range', 'clk-uniphier', 'clk-apple' and 'clk-qcom' into clk-next
[linux-2.6-microblaze.git] / tools / testing / selftests / netfilter / nft_concat_range.sh
1 #!/bin/sh
2 # SPDX-License-Identifier: GPL-2.0
3 #
4 # nft_concat_range.sh - Tests for sets with concatenation of ranged fields
5 #
6 # Copyright (c) 2019 Red Hat GmbH
7 #
8 # Author: Stefano Brivio <sbrivio@redhat.com>
9 #
10 # shellcheck disable=SC2154,SC2034,SC2016,SC2030,SC2031
11 # ^ Configuration and templates sourced with eval, counters reused in subshells
12
13 KSELFTEST_SKIP=4
14
15 # Available test groups:
16 # - reported_issues: check for issues that were reported in the past
17 # - correctness: check that packets match given entries, and only those
18 # - concurrency: attempt races between insertion, deletion and lookup
19 # - timeout: check that packets match entries until they expire
20 # - performance: estimate matching rate, compare with rbtree and hash baselines
21 TESTS="reported_issues correctness concurrency timeout"
22 [ "${quicktest}" != "1" ] && TESTS="${TESTS} performance"
23
24 # Set types, defined by TYPE_ variables below
25 TYPES="net_port port_net net6_port port_proto net6_port_mac net6_port_mac_proto
26        net_port_net net_mac mac_net net_mac_icmp net6_mac_icmp
27        net6_port_net6_port net_port_mac_proto_net"
28
29 # Reported bugs, also described by TYPE_ variables below
30 BUGS="flush_remove_add reload"
31
32 # List of possible paths to pktgen script from kernel tree for performance tests
33 PKTGEN_SCRIPT_PATHS="
34         ../../../samples/pktgen/pktgen_bench_xmit_mode_netif_receive.sh
35         pktgen/pktgen_bench_xmit_mode_netif_receive.sh"
36
37 # Definition of set types:
38 # display       display text for test report
39 # type_spec     nftables set type specifier
40 # chain_spec    nftables type specifier for rules mapping to set
41 # dst           call sequence of format_*() functions for destination fields
42 # src           call sequence of format_*() functions for source fields
43 # start         initial integer used to generate addresses and ports
44 # count         count of entries to generate and match
45 # src_delta     number summed to destination generator for source fields
46 # tools         list of tools for correctness and timeout tests, any can be used
47 # proto         L4 protocol of test packets
48 #
49 # race_repeat   race attempts per thread, 0 disables concurrency test for type
50 # flood_tools   list of tools for concurrency tests, any can be used
51 # flood_proto   L4 protocol of test packets for concurrency tests
52 # flood_spec    nftables type specifier for concurrency tests
53 #
54 # perf_duration duration of single pktgen injection test
55 # perf_spec     nftables type specifier for performance tests
56 # perf_dst      format_*() functions for destination fields in performance test
57 # perf_src      format_*() functions for source fields in performance test
58 # perf_entries  number of set entries for performance test
59 # perf_proto    L3 protocol of test packets
60 TYPE_net_port="
61 display         net,port
62 type_spec       ipv4_addr . inet_service
63 chain_spec      ip daddr . udp dport
64 dst             addr4 port
65 src              
66 start           1
67 count           5
68 src_delta       2000
69 tools           sendip nc bash
70 proto           udp
71
72 race_repeat     3
73 flood_tools     iperf3 iperf netperf
74 flood_proto     udp
75 flood_spec      ip daddr . udp dport
76
77 perf_duration   5
78 perf_spec       ip daddr . udp dport
79 perf_dst        addr4 port
80 perf_src         
81 perf_entries    1000
82 perf_proto      ipv4
83 "
84
85 TYPE_port_net="
86 display         port,net
87 type_spec       inet_service . ipv4_addr
88 chain_spec      udp dport . ip daddr
89 dst             port addr4
90 src              
91 start           1
92 count           5
93 src_delta       2000
94 tools           sendip nc bash
95 proto           udp
96
97 race_repeat     3
98 flood_tools     iperf3 iperf netperf
99 flood_proto     udp
100 flood_spec      udp dport . ip daddr
101
102 perf_duration   5
103 perf_spec       udp dport . ip daddr
104 perf_dst        port addr4
105 perf_src         
106 perf_entries    100
107 perf_proto      ipv4
108 "
109
110 TYPE_net6_port="
111 display         net6,port
112 type_spec       ipv6_addr . inet_service
113 chain_spec      ip6 daddr . udp dport
114 dst             addr6 port
115 src              
116 start           10
117 count           5
118 src_delta       2000
119 tools           sendip nc bash
120 proto           udp6
121
122 race_repeat     3
123 flood_tools     iperf3 iperf netperf
124 flood_proto     tcp6
125 flood_spec      ip6 daddr . udp dport
126
127 perf_duration   5
128 perf_spec       ip6 daddr . udp dport
129 perf_dst        addr6 port
130 perf_src         
131 perf_entries    1000
132 perf_proto      ipv6
133 "
134
135 TYPE_port_proto="
136 display         port,proto
137 type_spec       inet_service . inet_proto
138 chain_spec      udp dport . meta l4proto
139 dst             port proto
140 src              
141 start           1
142 count           5
143 src_delta       2000
144 tools           sendip nc bash
145 proto           udp
146
147 race_repeat     0
148
149 perf_duration   5
150 perf_spec       udp dport . meta l4proto
151 perf_dst        port proto
152 perf_src         
153 perf_entries    30000
154 perf_proto      ipv4
155 "
156
157 TYPE_net6_port_mac="
158 display         net6,port,mac
159 type_spec       ipv6_addr . inet_service . ether_addr
160 chain_spec      ip6 daddr . udp dport . ether saddr
161 dst             addr6 port
162 src             mac
163 start           10
164 count           5
165 src_delta       2000
166 tools           sendip nc bash
167 proto           udp6
168
169 race_repeat     0
170
171 perf_duration   5
172 perf_spec       ip6 daddr . udp dport . ether daddr
173 perf_dst        addr6 port mac
174 perf_src         
175 perf_entries    10
176 perf_proto      ipv6
177 "
178
179 TYPE_net6_port_mac_proto="
180 display         net6,port,mac,proto
181 type_spec       ipv6_addr . inet_service . ether_addr . inet_proto
182 chain_spec      ip6 daddr . udp dport . ether saddr . meta l4proto
183 dst             addr6 port
184 src             mac proto
185 start           10
186 count           5
187 src_delta       2000
188 tools           sendip nc bash
189 proto           udp6
190
191 race_repeat     0
192
193 perf_duration   5
194 perf_spec       ip6 daddr . udp dport . ether daddr . meta l4proto
195 perf_dst        addr6 port mac proto
196 perf_src         
197 perf_entries    1000
198 perf_proto      ipv6
199 "
200
201 TYPE_net_port_net="
202 display         net,port,net
203 type_spec       ipv4_addr . inet_service . ipv4_addr
204 chain_spec      ip daddr . udp dport . ip saddr
205 dst             addr4 port
206 src             addr4
207 start           1
208 count           5
209 src_delta       2000
210 tools           sendip nc bash
211 proto           udp
212
213 race_repeat     3
214 flood_tools     iperf3 iperf netperf
215 flood_proto     tcp
216 flood_spec      ip daddr . udp dport . ip saddr
217
218 perf_duration   0
219 "
220
221 TYPE_net6_port_net6_port="
222 display         net6,port,net6,port
223 type_spec       ipv6_addr . inet_service . ipv6_addr . inet_service
224 chain_spec      ip6 daddr . udp dport . ip6 saddr . udp sport
225 dst             addr6 port
226 src             addr6 port
227 start           10
228 count           5
229 src_delta       2000
230 tools           sendip nc
231 proto           udp6
232
233 race_repeat     3
234 flood_tools     iperf3 iperf netperf
235 flood_proto     tcp6
236 flood_spec      ip6 daddr . tcp dport . ip6 saddr . tcp sport
237
238 perf_duration   0
239 "
240
241 TYPE_net_port_mac_proto_net="
242 display         net,port,mac,proto,net
243 type_spec       ipv4_addr . inet_service . ether_addr . inet_proto . ipv4_addr
244 chain_spec      ip daddr . udp dport . ether saddr . meta l4proto . ip saddr
245 dst             addr4 port
246 src             mac proto addr4
247 start           1
248 count           5
249 src_delta       2000
250 tools           sendip nc bash
251 proto           udp
252
253 race_repeat     0
254
255 perf_duration   0
256 "
257
258 TYPE_net_mac="
259 display         net,mac
260 type_spec       ipv4_addr . ether_addr
261 chain_spec      ip daddr . ether saddr
262 dst             addr4
263 src             mac
264 start           1
265 count           5
266 src_delta       2000
267 tools           sendip nc bash
268 proto           udp
269
270 race_repeat     0
271
272 perf_duration   5
273 perf_spec       ip daddr . ether daddr
274 perf_dst        addr4 mac
275 perf_src         
276 perf_entries    1000
277 perf_proto      ipv4
278 "
279
280 TYPE_mac_net="
281 display         mac,net
282 type_spec       ether_addr . ipv4_addr
283 chain_spec      ether saddr . ip saddr
284 dst              
285 src             mac addr4
286 start           1
287 count           5
288 src_delta       2000
289 tools           sendip nc bash
290 proto           udp
291
292 race_repeat     0
293
294 perf_duration   0
295 "
296
297 TYPE_net_mac_icmp="
298 display         net,mac - ICMP
299 type_spec       ipv4_addr . ether_addr
300 chain_spec      ip daddr . ether saddr
301 dst             addr4
302 src             mac
303 start           1
304 count           5
305 src_delta       2000
306 tools           ping
307 proto           icmp
308
309 race_repeat     0
310
311 perf_duration   0
312 "
313
314 TYPE_net6_mac_icmp="
315 display         net6,mac - ICMPv6
316 type_spec       ipv6_addr . ether_addr
317 chain_spec      ip6 daddr . ether saddr
318 dst             addr6
319 src             mac
320 start           10
321 count           50
322 src_delta       2000
323 tools           ping
324 proto           icmp6
325
326 race_repeat     0
327
328 perf_duration   0
329 "
330
331 TYPE_net_port_proto_net="
332 display         net,port,proto,net
333 type_spec       ipv4_addr . inet_service . inet_proto . ipv4_addr
334 chain_spec      ip daddr . udp dport . meta l4proto . ip saddr
335 dst             addr4 port proto
336 src             addr4
337 start           1
338 count           5
339 src_delta       2000
340 tools           sendip nc
341 proto           udp
342
343 race_repeat     3
344 flood_tools     iperf3 iperf netperf
345 flood_proto     tcp
346 flood_spec      ip daddr . tcp dport . meta l4proto . ip saddr
347
348 perf_duration   0
349 "
350
351 # Definition of tests for bugs reported in the past:
352 # display       display text for test report
353 TYPE_flush_remove_add="
354 display         Add two elements, flush, re-add
355 "
356
357 TYPE_reload="
358 display         net,mac with reload
359 type_spec       ipv4_addr . ether_addr
360 chain_spec      ip daddr . ether saddr
361 dst             addr4
362 src             mac
363 start           1
364 count           1
365 src_delta       2000
366 tools           sendip nc bash
367 proto           udp
368
369 race_repeat     0
370
371 perf_duration   0
372 "
373
374 # Set template for all tests, types and rules are filled in depending on test
375 set_template='
376 flush ruleset
377
378 table inet filter {
379         counter test {
380                 packets 0 bytes 0
381         }
382
383         set test {
384                 type ${type_spec}
385                 flags interval,timeout
386         }
387
388         chain input {
389                 type filter hook prerouting priority 0; policy accept;
390                 ${chain_spec} @test counter name \"test\"
391         }
392 }
393
394 table netdev perf {
395         counter test {
396                 packets 0 bytes 0
397         }
398
399         counter match {
400                 packets 0 bytes 0
401         }
402
403         set test {
404                 type ${type_spec}
405                 flags interval
406         }
407
408         set norange {
409                 type ${type_spec}
410         }
411
412         set noconcat {
413                 type ${type_spec%% *}
414                 flags interval
415         }
416
417         chain test {
418                 type filter hook ingress device veth_a priority 0;
419         }
420 }
421 '
422
423 err_buf=
424 info_buf=
425
426 # Append string to error buffer
427 err() {
428         err_buf="${err_buf}${1}
429 "
430 }
431
432 # Append string to information buffer
433 info() {
434         info_buf="${info_buf}${1}
435 "
436 }
437
438 # Flush error buffer to stdout
439 err_flush() {
440         printf "%s" "${err_buf}"
441         err_buf=
442 }
443
444 # Flush information buffer to stdout
445 info_flush() {
446         printf "%s" "${info_buf}"
447         info_buf=
448 }
449
450 # Setup veth pair: this namespace receives traffic, B generates it
451 setup_veth() {
452         ip netns add B
453         ip link add veth_a type veth peer name veth_b || return 1
454
455         ip link set veth_a up
456         ip link set veth_b netns B
457
458         ip -n B link set veth_b up
459
460         ip addr add dev veth_a 10.0.0.1
461         ip route add default dev veth_a
462
463         ip -6 addr add fe80::1/64 dev veth_a nodad
464         ip -6 addr add 2001:db8::1/64 dev veth_a nodad
465         ip -6 route add default dev veth_a
466
467         ip -n B route add default dev veth_b
468
469         ip -6 -n B addr add fe80::2/64 dev veth_b nodad
470         ip -6 -n B addr add 2001:db8::2/64 dev veth_b nodad
471         ip -6 -n B route add default dev veth_b
472
473         B() {
474                 ip netns exec B "$@" >/dev/null 2>&1
475         }
476
477         sleep 2
478 }
479
480 # Fill in set template and initialise set
481 setup_set() {
482         eval "echo \"${set_template}\"" | nft -f -
483 }
484
485 # Check that at least one of the needed tools is available
486 check_tools() {
487         [ -z "${tools}" ] && return 0
488
489         __tools=
490         for tool in ${tools}; do
491                 if [ "${tool}" = "nc" ] && [ "${proto}" = "udp6" ] && \
492                    ! nc -u -w0 1.1.1.1 1 2>/dev/null; then
493                         # Some GNU netcat builds might not support IPv6
494                         __tools="${__tools} netcat-openbsd"
495                         continue
496                 fi
497                 __tools="${__tools} ${tool}"
498
499                 command -v "${tool}" >/dev/null && return 0
500         done
501         err "need one of:${__tools}, skipping" && return 1
502 }
503
504 # Set up function to send ICMP packets
505 setup_send_icmp() {
506         send_icmp() {
507                 B ping -c1 -W1 "${dst_addr4}" >/dev/null 2>&1
508         }
509 }
510
511 # Set up function to send ICMPv6 packets
512 setup_send_icmp6() {
513         if command -v ping6 >/dev/null; then
514                 send_icmp6() {
515                         ip -6 addr add "${dst_addr6}" dev veth_a nodad \
516                                 2>/dev/null
517                         B ping6 -q -c1 -W1 "${dst_addr6}"
518                 }
519         else
520                 send_icmp6() {
521                         ip -6 addr add "${dst_addr6}" dev veth_a nodad \
522                                 2>/dev/null
523                         B ping -q -6 -c1 -W1 "${dst_addr6}"
524                 }
525         fi
526 }
527
528 # Set up function to send single UDP packets on IPv4
529 setup_send_udp() {
530         if command -v sendip >/dev/null; then
531                 send_udp() {
532                         [ -n "${src_port}" ] && src_port="-us ${src_port}"
533                         [ -n "${dst_port}" ] && dst_port="-ud ${dst_port}"
534                         [ -n "${src_addr4}" ] && src_addr4="-is ${src_addr4}"
535
536                         # shellcheck disable=SC2086 # sendip needs split options
537                         B sendip -p ipv4 -p udp ${src_addr4} ${src_port} \
538                                                 ${dst_port} "${dst_addr4}"
539
540                         src_port=
541                         dst_port=
542                         src_addr4=
543                 }
544         elif command -v nc >/dev/null; then
545                 if nc -u -w0 1.1.1.1 1 2>/dev/null; then
546                         # OpenBSD netcat
547                         nc_opt="-w0"
548                 else
549                         # GNU netcat
550                         nc_opt="-q0"
551                 fi
552
553                 send_udp() {
554                         if [ -n "${src_addr4}" ]; then
555                                 B ip addr add "${src_addr4}" dev veth_b
556                                 __src_addr4="-s ${src_addr4}"
557                         fi
558                         ip addr add "${dst_addr4}" dev veth_a 2>/dev/null
559                         [ -n "${src_port}" ] && src_port="-p ${src_port}"
560
561                         echo "" | B nc -u "${nc_opt}" "${__src_addr4}" \
562                                   "${src_port}" "${dst_addr4}" "${dst_port}"
563
564                         src_addr4=
565                         src_port=
566                 }
567         elif [ -z "$(bash -c 'type -p')" ]; then
568                 send_udp() {
569                         ip addr add "${dst_addr4}" dev veth_a 2>/dev/null
570                         if [ -n "${src_addr4}" ]; then
571                                 B ip addr add "${src_addr4}/16" dev veth_b
572                                 B ip route add default dev veth_b
573                         fi
574
575                         B bash -c "echo > /dev/udp/${dst_addr4}/${dst_port}"
576
577                         if [ -n "${src_addr4}" ]; then
578                                 B ip addr del "${src_addr4}/16" dev veth_b
579                         fi
580                         src_addr4=
581                 }
582         else
583                 return 1
584         fi
585 }
586
587 # Set up function to send single UDP packets on IPv6
588 setup_send_udp6() {
589         if command -v sendip >/dev/null; then
590                 send_udp6() {
591                         [ -n "${src_port}" ] && src_port="-us ${src_port}"
592                         [ -n "${dst_port}" ] && dst_port="-ud ${dst_port}"
593                         if [ -n "${src_addr6}" ]; then
594                                 src_addr6="-6s ${src_addr6}"
595                         else
596                                 src_addr6="-6s 2001:db8::2"
597                         fi
598                         ip -6 addr add "${dst_addr6}" dev veth_a nodad \
599                                 2>/dev/null
600
601                         # shellcheck disable=SC2086 # this needs split options
602                         B sendip -p ipv6 -p udp ${src_addr6} ${src_port} \
603                                                 ${dst_port} "${dst_addr6}"
604
605                         src_port=
606                         dst_port=
607                         src_addr6=
608                 }
609         elif command -v nc >/dev/null && nc -u -w0 1.1.1.1 1 2>/dev/null; then
610                 # GNU netcat might not work with IPv6, try next tool
611                 send_udp6() {
612                         ip -6 addr add "${dst_addr6}" dev veth_a nodad \
613                                 2>/dev/null
614                         if [ -n "${src_addr6}" ]; then
615                                 B ip addr add "${src_addr6}" dev veth_b nodad
616                         else
617                                 src_addr6="2001:db8::2"
618                         fi
619                         [ -n "${src_port}" ] && src_port="-p ${src_port}"
620
621                         # shellcheck disable=SC2086 # this needs split options
622                         echo "" | B nc -u w0 "-s${src_addr6}" ${src_port} \
623                                                ${dst_addr6} ${dst_port}
624
625                         src_addr6=
626                         src_port=
627                 }
628         elif [ -z "$(bash -c 'type -p')" ]; then
629                 send_udp6() {
630                         ip -6 addr add "${dst_addr6}" dev veth_a nodad \
631                                 2>/dev/null
632                         B ip addr add "${src_addr6}" dev veth_b nodad
633                         B bash -c "echo > /dev/udp/${dst_addr6}/${dst_port}"
634                         ip -6 addr del "${dst_addr6}" dev veth_a 2>/dev/null
635                 }
636         else
637                 return 1
638         fi
639 }
640
641 # Set up function to send TCP traffic on IPv4
642 setup_flood_tcp() {
643         if command -v iperf3 >/dev/null; then
644                 flood_tcp() {
645                         [ -n "${dst_port}" ] && dst_port="-p ${dst_port}"
646                         if [ -n "${src_addr4}" ]; then
647                                 B ip addr add "${src_addr4}/16" dev veth_b
648                                 src_addr4="-B ${src_addr4}"
649                         else
650                                 B ip addr add dev veth_b 10.0.0.2
651                                 src_addr4="-B 10.0.0.2"
652                         fi
653                         if [ -n "${src_port}" ]; then
654                                 src_port="--cport ${src_port}"
655                         fi
656                         B ip route add default dev veth_b 2>/dev/null
657                         ip addr add "${dst_addr4}" dev veth_a 2>/dev/null
658
659                         # shellcheck disable=SC2086 # this needs split options
660                         iperf3 -s -DB "${dst_addr4}" ${dst_port} >/dev/null 2>&1
661                         sleep 2
662
663                         # shellcheck disable=SC2086 # this needs split options
664                         B iperf3 -c "${dst_addr4}" ${dst_port} ${src_port} \
665                                 ${src_addr4} -l16 -t 1000
666
667                         src_addr4=
668                         src_port=
669                         dst_port=
670                 }
671         elif command -v iperf >/dev/null; then
672                 flood_tcp() {
673                         [ -n "${dst_port}" ] && dst_port="-p ${dst_port}"
674                         if [ -n "${src_addr4}" ]; then
675                                 B ip addr add "${src_addr4}/16" dev veth_b
676                                 src_addr4="-B ${src_addr4}"
677                         else
678                                 B ip addr add dev veth_b 10.0.0.2 2>/dev/null
679                                 src_addr4="-B 10.0.0.2"
680                         fi
681                         if [ -n "${src_port}" ]; then
682                                 src_addr4="${src_addr4}:${src_port}"
683                         fi
684                         B ip route add default dev veth_b
685                         ip addr add "${dst_addr4}" dev veth_a 2>/dev/null
686
687                         # shellcheck disable=SC2086 # this needs split options
688                         iperf -s -DB "${dst_addr4}" ${dst_port} >/dev/null 2>&1
689                         sleep 2
690
691                         # shellcheck disable=SC2086 # this needs split options
692                         B iperf -c "${dst_addr4}" ${dst_port} ${src_addr4} \
693                                 -l20 -t 1000
694
695                         src_addr4=
696                         src_port=
697                         dst_port=
698                 }
699         elif command -v netperf >/dev/null; then
700                 flood_tcp() {
701                         [ -n "${dst_port}" ] && dst_port="-p ${dst_port}"
702                         if [ -n "${src_addr4}" ]; then
703                                 B ip addr add "${src_addr4}/16" dev veth_b
704                         else
705                                 B ip addr add dev veth_b 10.0.0.2
706                                 src_addr4="10.0.0.2"
707                         fi
708                         if [ -n "${src_port}" ]; then
709                                 dst_port="${dst_port},${src_port}"
710                         fi
711                         B ip route add default dev veth_b
712                         ip addr add "${dst_addr4}" dev veth_a 2>/dev/null
713
714                         # shellcheck disable=SC2086 # this needs split options
715                         netserver -4 ${dst_port} -L "${dst_addr4}" \
716                                 >/dev/null 2>&1
717                         sleep 2
718
719                         # shellcheck disable=SC2086 # this needs split options
720                         B netperf -4 -H "${dst_addr4}" ${dst_port} \
721                                 -L "${src_addr4}" -l 1000 -t TCP_STREAM
722
723                         src_addr4=
724                         src_port=
725                         dst_port=
726                 }
727         else
728                 return 1
729         fi
730 }
731
732 # Set up function to send TCP traffic on IPv6
733 setup_flood_tcp6() {
734         if command -v iperf3 >/dev/null; then
735                 flood_tcp6() {
736                         [ -n "${dst_port}" ] && dst_port="-p ${dst_port}"
737                         if [ -n "${src_addr6}" ]; then
738                                 B ip addr add "${src_addr6}" dev veth_b nodad
739                                 src_addr6="-B ${src_addr6}"
740                         else
741                                 src_addr6="-B 2001:db8::2"
742                         fi
743                         if [ -n "${src_port}" ]; then
744                                 src_port="--cport ${src_port}"
745                         fi
746                         B ip route add default dev veth_b
747                         ip -6 addr add "${dst_addr6}" dev veth_a nodad \
748                                 2>/dev/null
749
750                         # shellcheck disable=SC2086 # this needs split options
751                         iperf3 -s -DB "${dst_addr6}" ${dst_port} >/dev/null 2>&1
752                         sleep 2
753
754                         # shellcheck disable=SC2086 # this needs split options
755                         B iperf3 -c "${dst_addr6}" ${dst_port} \
756                                 ${src_port} ${src_addr6} -l16 -t 1000
757
758                         src_addr6=
759                         src_port=
760                         dst_port=
761                 }
762         elif command -v iperf >/dev/null; then
763                 flood_tcp6() {
764                         [ -n "${dst_port}" ] && dst_port="-p ${dst_port}"
765                         if [ -n "${src_addr6}" ]; then
766                                 B ip addr add "${src_addr6}" dev veth_b nodad
767                                 src_addr6="-B ${src_addr6}"
768                         else
769                                 src_addr6="-B 2001:db8::2"
770                         fi
771                         if [ -n "${src_port}" ]; then
772                                 src_addr6="${src_addr6}:${src_port}"
773                         fi
774                         B ip route add default dev veth_b
775                         ip -6 addr add "${dst_addr6}" dev veth_a nodad \
776                                 2>/dev/null
777
778                         # shellcheck disable=SC2086 # this needs split options
779                         iperf -s -VDB "${dst_addr6}" ${dst_port} >/dev/null 2>&1
780                         sleep 2
781
782                         # shellcheck disable=SC2086 # this needs split options
783                         B iperf -c "${dst_addr6}" -V ${dst_port} \
784                                 ${src_addr6} -l1 -t 1000
785
786                         src_addr6=
787                         src_port=
788                         dst_port=
789                 }
790         elif command -v netperf >/dev/null; then
791                 flood_tcp6() {
792                         [ -n "${dst_port}" ] && dst_port="-p ${dst_port}"
793                         if [ -n "${src_addr6}" ]; then
794                                 B ip addr add "${src_addr6}" dev veth_b nodad
795                         else
796                                 src_addr6="2001:db8::2"
797                         fi
798                         if [ -n "${src_port}" ]; then
799                                 dst_port="${dst_port},${src_port}"
800                         fi
801                         B ip route add default dev veth_b
802                         ip -6 addr add "${dst_addr6}" dev veth_a nodad \
803                                 2>/dev/null
804
805                         # shellcheck disable=SC2086 # this needs split options
806                         netserver -6 ${dst_port} -L "${dst_addr6}" \
807                                 >/dev/null 2>&1
808                         sleep 2
809
810                         # shellcheck disable=SC2086 # this needs split options
811                         B netperf -6 -H "${dst_addr6}" ${dst_port} \
812                                 -L "${src_addr6}" -l 1000 -t TCP_STREAM
813
814                         src_addr6=
815                         src_port=
816                         dst_port=
817                 }
818         else
819                 return 1
820         fi
821 }
822
823 # Set up function to send UDP traffic on IPv4
824 setup_flood_udp() {
825         if command -v iperf3 >/dev/null; then
826                 flood_udp() {
827                         [ -n "${dst_port}" ] && dst_port="-p ${dst_port}"
828                         if [ -n "${src_addr4}" ]; then
829                                 B ip addr add "${src_addr4}/16" dev veth_b
830                                 src_addr4="-B ${src_addr4}"
831                         else
832                                 B ip addr add dev veth_b 10.0.0.2 2>/dev/null
833                                 src_addr4="-B 10.0.0.2"
834                         fi
835                         if [ -n "${src_port}" ]; then
836                                 src_port="--cport ${src_port}"
837                         fi
838                         B ip route add default dev veth_b
839                         ip addr add "${dst_addr4}" dev veth_a 2>/dev/null
840
841                         # shellcheck disable=SC2086 # this needs split options
842                         iperf3 -s -DB "${dst_addr4}" ${dst_port}
843                         sleep 2
844
845                         # shellcheck disable=SC2086 # this needs split options
846                         B iperf3 -u -c "${dst_addr4}" -Z -b 100M -l16 -t1000 \
847                                 ${dst_port} ${src_port} ${src_addr4}
848
849                         src_addr4=
850                         src_port=
851                         dst_port=
852                 }
853         elif command -v iperf >/dev/null; then
854                 flood_udp() {
855                         [ -n "${dst_port}" ] && dst_port="-p ${dst_port}"
856                         if [ -n "${src_addr4}" ]; then
857                                 B ip addr add "${src_addr4}/16" dev veth_b
858                                 src_addr4="-B ${src_addr4}"
859                         else
860                                 B ip addr add dev veth_b 10.0.0.2
861                                 src_addr4="-B 10.0.0.2"
862                         fi
863                         if [ -n "${src_port}" ]; then
864                                 src_addr4="${src_addr4}:${src_port}"
865                         fi
866                         B ip route add default dev veth_b
867                         ip addr add "${dst_addr4}" dev veth_a 2>/dev/null
868
869                         # shellcheck disable=SC2086 # this needs split options
870                         iperf -u -sDB "${dst_addr4}" ${dst_port} >/dev/null 2>&1
871                         sleep 2
872
873                         # shellcheck disable=SC2086 # this needs split options
874                         B iperf -u -c "${dst_addr4}" -b 100M -l1 -t1000 \
875                                 ${dst_port} ${src_addr4}
876
877                         src_addr4=
878                         src_port=
879                         dst_port=
880                 }
881         elif command -v netperf >/dev/null; then
882                 flood_udp() {
883                         [ -n "${dst_port}" ] && dst_port="-p ${dst_port}"
884                         if [ -n "${src_addr4}" ]; then
885                                 B ip addr add "${src_addr4}/16" dev veth_b
886                         else
887                                 B ip addr add dev veth_b 10.0.0.2
888                                 src_addr4="10.0.0.2"
889                         fi
890                         if [ -n "${src_port}" ]; then
891                                 dst_port="${dst_port},${src_port}"
892                         fi
893                         B ip route add default dev veth_b
894                         ip addr add "${dst_addr4}" dev veth_a 2>/dev/null
895
896                         # shellcheck disable=SC2086 # this needs split options
897                         netserver -4 ${dst_port} -L "${dst_addr4}" \
898                                 >/dev/null 2>&1
899                         sleep 2
900
901                         # shellcheck disable=SC2086 # this needs split options
902                         B netperf -4 -H "${dst_addr4}" ${dst_port} \
903                                 -L "${src_addr4}" -l 1000 -t UDP_STREAM
904
905                         src_addr4=
906                         src_port=
907                         dst_port=
908                 }
909         else
910                 return 1
911         fi
912 }
913
914 # Find pktgen script and set up function to start pktgen injection
915 setup_perf() {
916         for pktgen_script_path in ${PKTGEN_SCRIPT_PATHS} __notfound; do
917                 command -v "${pktgen_script_path}" >/dev/null && break
918         done
919         [ "${pktgen_script_path}" = "__notfound" ] && return 1
920
921         perf_ipv4() {
922                 ${pktgen_script_path} -s80 \
923                         -i veth_a -d "${dst_addr4}" -p "${dst_port}" \
924                         -m "${dst_mac}" \
925                         -t $(($(nproc) / 5 + 1)) -b10000 -n0 2>/dev/null &
926                 perf_pid=$!
927         }
928         perf_ipv6() {
929                 IP6=6 ${pktgen_script_path} -s100 \
930                         -i veth_a -d "${dst_addr6}" -p "${dst_port}" \
931                         -m "${dst_mac}" \
932                         -t $(($(nproc) / 5 + 1)) -b10000 -n0 2>/dev/null &
933                 perf_pid=$!
934         }
935 }
936
937 # Clean up before each test
938 cleanup() {
939         nft reset counter inet filter test      >/dev/null 2>&1
940         nft flush ruleset                       >/dev/null 2>&1
941         ip link del dummy0                      2>/dev/null
942         ip route del default                    2>/dev/null
943         ip -6 route del default                 2>/dev/null
944         ip netns del B                          2>/dev/null
945         ip link del veth_a                      2>/dev/null
946         timeout=
947         killall iperf3                          2>/dev/null
948         killall iperf                           2>/dev/null
949         killall netperf                         2>/dev/null
950         killall netserver                       2>/dev/null
951         rm -f ${tmp}
952         sleep 2
953 }
954
955 # Entry point for setup functions
956 setup() {
957         if [ "$(id -u)" -ne 0 ]; then
958                 echo "  need to run as root"
959                 exit ${KSELFTEST_SKIP}
960         fi
961
962         cleanup
963         check_tools || return 1
964         for arg do
965                 if ! eval setup_"${arg}"; then
966                         err "  ${arg} not supported"
967                         return 1
968                 fi
969         done
970 }
971
972 # Format integer into IPv4 address, summing 10.0.0.5 (arbitrary) to it
973 format_addr4() {
974         a=$((${1} + 16777216 * 10 + 5))
975         printf "%i.%i.%i.%i"                                            \
976                "$((a / 16777216))" "$((a % 16777216 / 65536))"  \
977                "$((a % 65536 / 256))" "$((a % 256))"
978 }
979
980 # Format integer into IPv6 address, summing 2001:db8:: to it
981 format_addr6() {
982         printf "2001:db8::%04x:%04x" "$((${1} / 65536))" "$((${1} % 65536))"
983 }
984
985 # Format integer into EUI-48 address, summing 00:01:00:00:00:00 to it
986 format_mac() {
987         printf "00:01:%02x:%02x:%02x:%02x" \
988                "$((${1} / 16777216))" "$((${1} % 16777216 / 65536))"    \
989                "$((${1} % 65536 / 256))" "$((${1} % 256))"
990 }
991
992 # Format integer into port, avoid 0 port
993 format_port() {
994         printf "%i" "$((${1} % 65534 + 1))"
995 }
996
997 # Drop suffixed '6' from L4 protocol, if any
998 format_proto() {
999         printf "%s" "${proto}" | tr -d 6
1000 }
1001
1002 # Format destination and source fields into nft concatenated type
1003 format() {
1004         __start=
1005         __end=
1006         __expr="{ "
1007
1008         for f in ${dst}; do
1009                 [ "${__expr}" != "{ " ] && __expr="${__expr} . "
1010
1011                 __start="$(eval format_"${f}" "${start}")"
1012                 __end="$(eval format_"${f}" "${end}")"
1013
1014                 if [ "${f}" = "proto" ]; then
1015                         __expr="${__expr}${__start}"
1016                 else
1017                         __expr="${__expr}${__start}-${__end}"
1018                 fi
1019         done
1020         for f in ${src}; do
1021                 [ "${__expr}" != "{ " ] && __expr="${__expr} . "
1022
1023                 __start="$(eval format_"${f}" "${srcstart}")"
1024                 __end="$(eval format_"${f}" "${srcend}")"
1025
1026                 if [ "${f}" = "proto" ]; then
1027                         __expr="${__expr}${__start}"
1028                 else
1029                         __expr="${__expr}${__start}-${__end}"
1030                 fi
1031         done
1032
1033         if [ -n "${timeout}" ]; then
1034                 echo "${__expr} timeout ${timeout}s }"
1035         else
1036                 echo "${__expr} }"
1037         fi
1038 }
1039
1040 # Format destination and source fields into nft type, start element only
1041 format_norange() {
1042         __expr="{ "
1043
1044         for f in ${dst}; do
1045                 [ "${__expr}" != "{ " ] && __expr="${__expr} . "
1046
1047                 __expr="${__expr}$(eval format_"${f}" "${start}")"
1048         done
1049         for f in ${src}; do
1050                 __expr="${__expr} . $(eval format_"${f}" "${start}")"
1051         done
1052
1053         echo "${__expr} }"
1054 }
1055
1056 # Format first destination field into nft type
1057 format_noconcat() {
1058         for f in ${dst}; do
1059                 __start="$(eval format_"${f}" "${start}")"
1060                 __end="$(eval format_"${f}" "${end}")"
1061
1062                 if [ "${f}" = "proto" ]; then
1063                         echo "{ ${__start} }"
1064                 else
1065                         echo "{ ${__start}-${__end} }"
1066                 fi
1067                 return
1068         done
1069 }
1070
1071 # Add single entry to 'test' set in 'inet filter' table
1072 add() {
1073         if ! nft add element inet filter test "${1}"; then
1074                 err "Failed to add ${1} given ruleset:"
1075                 err "$(nft -a list ruleset)"
1076                 return 1
1077         fi
1078 }
1079
1080 # Format and output entries for sets in 'netdev perf' table
1081 add_perf() {
1082         if [ "${1}" = "test" ]; then
1083                 echo "add element netdev perf test $(format)"
1084         elif [ "${1}" = "norange" ]; then
1085                 echo "add element netdev perf norange $(format_norange)"
1086         elif [ "${1}" = "noconcat" ]; then
1087                 echo "add element netdev perf noconcat $(format_noconcat)"
1088         fi
1089 }
1090
1091 # Add single entry to 'norange' set in 'netdev perf' table
1092 add_perf_norange() {
1093         if ! nft add element netdev perf norange "${1}"; then
1094                 err "Failed to add ${1} given ruleset:"
1095                 err "$(nft -a list ruleset)"
1096                 return 1
1097         fi
1098 }
1099
1100 # Add single entry to 'noconcat' set in 'netdev perf' table
1101 add_perf_noconcat() {
1102         if ! nft add element netdev perf noconcat "${1}"; then
1103                 err "Failed to add ${1} given ruleset:"
1104                 err "$(nft -a list ruleset)"
1105                 return 1
1106         fi
1107 }
1108
1109 # Delete single entry from set
1110 del() {
1111         if ! nft delete element inet filter test "${1}"; then
1112                 err "Failed to delete ${1} given ruleset:"
1113                 err "$(nft -a list ruleset)"
1114                 return 1
1115         fi
1116 }
1117
1118 # Return packet count from 'test' counter in 'inet filter' table
1119 count_packets() {
1120         found=0
1121         for token in $(nft list counter inet filter test); do
1122                 [ ${found} -eq 1 ] && echo "${token}" && return
1123                 [ "${token}" = "packets" ] && found=1
1124         done
1125 }
1126
1127 # Return packet count from 'test' counter in 'netdev perf' table
1128 count_perf_packets() {
1129         found=0
1130         for token in $(nft list counter netdev perf test); do
1131                 [ ${found} -eq 1 ] && echo "${token}" && return
1132                 [ "${token}" = "packets" ] && found=1
1133         done
1134 }
1135
1136 # Set MAC addresses, send traffic according to specifier
1137 flood() {
1138         ip link set veth_a address "$(format_mac "${1}")"
1139         ip -n B link set veth_b address "$(format_mac "${2}")"
1140
1141         for f in ${dst}; do
1142                 eval dst_"$f"=\$\(format_\$f "${1}"\)
1143         done
1144         for f in ${src}; do
1145                 eval src_"$f"=\$\(format_\$f "${2}"\)
1146         done
1147         eval flood_\$proto
1148 }
1149
1150 # Set MAC addresses, start pktgen injection
1151 perf() {
1152         dst_mac="$(format_mac "${1}")"
1153         ip link set veth_a address "${dst_mac}"
1154
1155         for f in ${dst}; do
1156                 eval dst_"$f"=\$\(format_\$f "${1}"\)
1157         done
1158         for f in ${src}; do
1159                 eval src_"$f"=\$\(format_\$f "${2}"\)
1160         done
1161         eval perf_\$perf_proto
1162 }
1163
1164 # Set MAC addresses, send single packet, check that it matches, reset counter
1165 send_match() {
1166         ip link set veth_a address "$(format_mac "${1}")"
1167         ip -n B link set veth_b address "$(format_mac "${2}")"
1168
1169         for f in ${dst}; do
1170                 eval dst_"$f"=\$\(format_\$f "${1}"\)
1171         done
1172         for f in ${src}; do
1173                 eval src_"$f"=\$\(format_\$f "${2}"\)
1174         done
1175         eval send_\$proto
1176         if [ "$(count_packets)" != "1" ]; then
1177                 err "${proto} packet to:"
1178                 err "  $(for f in ${dst}; do
1179                          eval format_\$f "${1}"; printf ' '; done)"
1180                 err "from:"
1181                 err "  $(for f in ${src}; do
1182                          eval format_\$f "${2}"; printf ' '; done)"
1183                 err "should have matched ruleset:"
1184                 err "$(nft -a list ruleset)"
1185                 return 1
1186         fi
1187         nft reset counter inet filter test >/dev/null
1188 }
1189
1190 # Set MAC addresses, send single packet, check that it doesn't match
1191 send_nomatch() {
1192         ip link set veth_a address "$(format_mac "${1}")"
1193         ip -n B link set veth_b address "$(format_mac "${2}")"
1194
1195         for f in ${dst}; do
1196                 eval dst_"$f"=\$\(format_\$f "${1}"\)
1197         done
1198         for f in ${src}; do
1199                 eval src_"$f"=\$\(format_\$f "${2}"\)
1200         done
1201         eval send_\$proto
1202         if [ "$(count_packets)" != "0" ]; then
1203                 err "${proto} packet to:"
1204                 err "  $(for f in ${dst}; do
1205                          eval format_\$f "${1}"; printf ' '; done)"
1206                 err "from:"
1207                 err "  $(for f in ${src}; do
1208                          eval format_\$f "${2}"; printf ' '; done)"
1209                 err "should not have matched ruleset:"
1210                 err "$(nft -a list ruleset)"
1211                 return 1
1212         fi
1213 }
1214
1215 # Correctness test template:
1216 # - add ranged element, check that packets match it
1217 # - check that packets outside range don't match it
1218 # - remove some elements, check that packets don't match anymore
1219 test_correctness() {
1220         setup veth send_"${proto}" set || return ${KSELFTEST_SKIP}
1221
1222         range_size=1
1223         for i in $(seq "${start}" $((start + count))); do
1224                 end=$((start + range_size))
1225
1226                 # Avoid negative or zero-sized port ranges
1227                 if [ $((end / 65534)) -gt $((start / 65534)) ]; then
1228                         start=${end}
1229                         end=$((end + 1))
1230                 fi
1231                 srcstart=$((start + src_delta))
1232                 srcend=$((end + src_delta))
1233
1234                 add "$(format)" || return 1
1235                 for j in $(seq ${start} $((range_size / 2 + 1)) ${end}); do
1236                         send_match "${j}" $((j + src_delta)) || return 1
1237                 done
1238                 send_nomatch $((end + 1)) $((end + 1 + src_delta)) || return 1
1239
1240                 # Delete elements now and then
1241                 if [ $((i % 3)) -eq 0 ]; then
1242                         del "$(format)" || return 1
1243                         for j in $(seq ${start} \
1244                                    $((range_size / 2 + 1)) ${end}); do
1245                                 send_nomatch "${j}" $((j + src_delta)) \
1246                                         || return 1
1247                         done
1248                 fi
1249
1250                 range_size=$((range_size + 1))
1251                 start=$((end + range_size))
1252         done
1253 }
1254
1255 # Concurrency test template:
1256 # - add all the elements
1257 # - start a thread for each physical thread that:
1258 #   - adds all the elements
1259 #   - flushes the set
1260 #   - adds all the elements
1261 #   - flushes the entire ruleset
1262 #   - adds the set back
1263 #   - adds all the elements
1264 #   - delete all the elements
1265 test_concurrency() {
1266         proto=${flood_proto}
1267         tools=${flood_tools}
1268         chain_spec=${flood_spec}
1269         setup veth flood_"${proto}" set || return ${KSELFTEST_SKIP}
1270
1271         range_size=1
1272         cstart=${start}
1273         flood_pids=
1274         for i in $(seq ${start} $((start + count))); do
1275                 end=$((start + range_size))
1276                 srcstart=$((start + src_delta))
1277                 srcend=$((end + src_delta))
1278
1279                 add "$(format)" || return 1
1280
1281                 flood "${i}" $((i + src_delta)) & flood_pids="${flood_pids} $!"
1282
1283                 range_size=$((range_size + 1))
1284                 start=$((end + range_size))
1285         done
1286
1287         sleep 10
1288
1289         pids=
1290         for c in $(seq 1 "$(nproc)"); do (
1291                 for r in $(seq 1 "${race_repeat}"); do
1292                         range_size=1
1293
1294                         # $start needs to be local to this subshell
1295                         # shellcheck disable=SC2030
1296                         start=${cstart}
1297                         for i in $(seq ${start} $((start + count))); do
1298                                 end=$((start + range_size))
1299                                 srcstart=$((start + src_delta))
1300                                 srcend=$((end + src_delta))
1301
1302                                 add "$(format)" 2>/dev/null
1303
1304                                 range_size=$((range_size + 1))
1305                                 start=$((end + range_size))
1306                         done
1307
1308                         nft flush inet filter test 2>/dev/null
1309
1310                         range_size=1
1311                         start=${cstart}
1312                         for i in $(seq ${start} $((start + count))); do
1313                                 end=$((start + range_size))
1314                                 srcstart=$((start + src_delta))
1315                                 srcend=$((end + src_delta))
1316
1317                                 add "$(format)" 2>/dev/null
1318
1319                                 range_size=$((range_size + 1))
1320                                 start=$((end + range_size))
1321                         done
1322
1323                         nft flush ruleset
1324                         setup set 2>/dev/null
1325
1326                         range_size=1
1327                         start=${cstart}
1328                         for i in $(seq ${start} $((start + count))); do
1329                                 end=$((start + range_size))
1330                                 srcstart=$((start + src_delta))
1331                                 srcend=$((end + src_delta))
1332
1333                                 add "$(format)" 2>/dev/null
1334
1335                                 range_size=$((range_size + 1))
1336                                 start=$((end + range_size))
1337                         done
1338
1339                         range_size=1
1340                         start=${cstart}
1341                         for i in $(seq ${start} $((start + count))); do
1342                                 end=$((start + range_size))
1343                                 srcstart=$((start + src_delta))
1344                                 srcend=$((end + src_delta))
1345
1346                                 del "$(format)" 2>/dev/null
1347
1348                                 range_size=$((range_size + 1))
1349                                 start=$((end + range_size))
1350                         done
1351                 done
1352         ) & pids="${pids} $!"
1353         done
1354
1355         # shellcheck disable=SC2046,SC2086 # word splitting wanted here
1356         wait $(for pid in ${pids}; do echo ${pid}; done)
1357         # shellcheck disable=SC2046,SC2086
1358         kill $(for pid in ${flood_pids}; do echo ${pid}; done) 2>/dev/null
1359         # shellcheck disable=SC2046,SC2086
1360         wait $(for pid in ${flood_pids}; do echo ${pid}; done) 2>/dev/null
1361
1362         return 0
1363 }
1364
1365 # Timeout test template:
1366 # - add all the elements with 3s timeout while checking that packets match
1367 # - wait 3s after the last insertion, check that packets don't match any entry
1368 test_timeout() {
1369         setup veth send_"${proto}" set || return ${KSELFTEST_SKIP}
1370
1371         timeout=3
1372         range_size=1
1373         for i in $(seq "${start}" $((start + count))); do
1374                 end=$((start + range_size))
1375                 srcstart=$((start + src_delta))
1376                 srcend=$((end + src_delta))
1377
1378                 add "$(format)" || return 1
1379
1380                 for j in $(seq ${start} $((range_size / 2 + 1)) ${end}); do
1381                         send_match "${j}" $((j + src_delta)) || return 1
1382                 done
1383
1384                 range_size=$((range_size + 1))
1385                 start=$((end + range_size))
1386         done
1387         sleep 3
1388         for i in $(seq ${start} $((start + count))); do
1389                 end=$((start + range_size))
1390                 srcstart=$((start + src_delta))
1391                 srcend=$((end + src_delta))
1392
1393                 for j in $(seq ${start} $((range_size / 2 + 1)) ${end}); do
1394                         send_nomatch "${j}" $((j + src_delta)) || return 1
1395                 done
1396
1397                 range_size=$((range_size + 1))
1398                 start=$((end + range_size))
1399         done
1400 }
1401
1402 # Performance test template:
1403 # - add concatenated ranged entries
1404 # - add non-ranged concatenated entries (for hash set matching rate baseline)
1405 # - add ranged entries with first field only (for rbhash baseline)
1406 # - start pktgen injection directly on device rx path of this namespace
1407 # - measure drop only rate, hash and rbtree baselines, then matching rate
1408 test_performance() {
1409         chain_spec=${perf_spec}
1410         dst="${perf_dst}"
1411         src="${perf_src}"
1412         setup veth perf set || return ${KSELFTEST_SKIP}
1413
1414         first=${start}
1415         range_size=1
1416         for set in test norange noconcat; do
1417                 start=${first}
1418                 for i in $(seq ${start} $((start + perf_entries))); do
1419                         end=$((start + range_size))
1420                         srcstart=$((start + src_delta))
1421                         srcend=$((end + src_delta))
1422
1423                         if [ $((end / 65534)) -gt $((start / 65534)) ]; then
1424                                 start=${end}
1425                                 end=$((end + 1))
1426                         elif [ ${start} -eq ${end} ]; then
1427                                 end=$((start + 1))
1428                         fi
1429
1430                         add_perf ${set}
1431
1432                         start=$((end + range_size))
1433                 done > "${tmp}"
1434                 nft -f "${tmp}"
1435         done
1436
1437         perf $((end - 1)) ${srcstart}
1438
1439         sleep 2
1440
1441         nft add rule netdev perf test counter name \"test\" drop
1442         nft reset counter netdev perf test >/dev/null 2>&1
1443         sleep "${perf_duration}"
1444         pps="$(printf %10s $(($(count_perf_packets) / perf_duration)))"
1445         info "    baseline (drop from netdev hook):            ${pps}pps"
1446         handle="$(nft -a list chain netdev perf test | grep counter)"
1447         handle="${handle##* }"
1448         nft delete rule netdev perf test handle "${handle}"
1449
1450         nft add rule "netdev perf test ${chain_spec} @norange \
1451                 counter name \"test\" drop"
1452         nft reset counter netdev perf test >/dev/null 2>&1
1453         sleep "${perf_duration}"
1454         pps="$(printf %10s $(($(count_perf_packets) / perf_duration)))"
1455         info "    baseline hash (non-ranged entries):          ${pps}pps"
1456         handle="$(nft -a list chain netdev perf test | grep counter)"
1457         handle="${handle##* }"
1458         nft delete rule netdev perf test handle "${handle}"
1459
1460         nft add rule "netdev perf test ${chain_spec%%. *} @noconcat \
1461                 counter name \"test\" drop"
1462         nft reset counter netdev perf test >/dev/null 2>&1
1463         sleep "${perf_duration}"
1464         pps="$(printf %10s $(($(count_perf_packets) / perf_duration)))"
1465         info "    baseline rbtree (match on first field only): ${pps}pps"
1466         handle="$(nft -a list chain netdev perf test | grep counter)"
1467         handle="${handle##* }"
1468         nft delete rule netdev perf test handle "${handle}"
1469
1470         nft add rule "netdev perf test ${chain_spec} @test \
1471                 counter name \"test\" drop"
1472         nft reset counter netdev perf test >/dev/null 2>&1
1473         sleep "${perf_duration}"
1474         pps="$(printf %10s $(($(count_perf_packets) / perf_duration)))"
1475         p5="$(printf %5s "${perf_entries}")"
1476         info "    set with ${p5} full, ranged entries:         ${pps}pps"
1477         kill "${perf_pid}"
1478 }
1479
1480 test_bug_flush_remove_add() {
1481         set_cmd='{ set s { type ipv4_addr . inet_service; flags interval; }; }'
1482         elem1='{ 10.0.0.1 . 22-25, 10.0.0.1 . 10-20 }'
1483         elem2='{ 10.0.0.1 . 10-20, 10.0.0.1 . 22-25 }'
1484         for i in `seq 1 100`; do
1485                 nft add table t ${set_cmd}      || return ${KSELFTEST_SKIP}
1486                 nft add element t s ${elem1}    2>/dev/null || return 1
1487                 nft flush set t s               2>/dev/null || return 1
1488                 nft add element t s ${elem2}    2>/dev/null || return 1
1489         done
1490         nft flush ruleset
1491 }
1492
1493 # - add ranged element, check that packets match it
1494 # - reload the set, check packets still match
1495 test_bug_reload() {
1496         setup veth send_"${proto}" set || return ${KSELFTEST_SKIP}
1497         rstart=${start}
1498
1499         range_size=1
1500         for i in $(seq "${start}" $((start + count))); do
1501                 end=$((start + range_size))
1502
1503                 # Avoid negative or zero-sized port ranges
1504                 if [ $((end / 65534)) -gt $((start / 65534)) ]; then
1505                         start=${end}
1506                         end=$((end + 1))
1507                 fi
1508                 srcstart=$((start + src_delta))
1509                 srcend=$((end + src_delta))
1510
1511                 add "$(format)" || return 1
1512                 range_size=$((range_size + 1))
1513                 start=$((end + range_size))
1514         done
1515
1516         # check kernel does allocate pcpu sctrach map
1517         # for reload with no elemet add/delete
1518         ( echo flush set inet filter test ;
1519           nft list set inet filter test ) | nft -f -
1520
1521         start=${rstart}
1522         range_size=1
1523
1524         for i in $(seq "${start}" $((start + count))); do
1525                 end=$((start + range_size))
1526
1527                 # Avoid negative or zero-sized port ranges
1528                 if [ $((end / 65534)) -gt $((start / 65534)) ]; then
1529                         start=${end}
1530                         end=$((end + 1))
1531                 fi
1532                 srcstart=$((start + src_delta))
1533                 srcend=$((end + src_delta))
1534
1535                 for j in $(seq ${start} $((range_size / 2 + 1)) ${end}); do
1536                         send_match "${j}" $((j + src_delta)) || return 1
1537                 done
1538
1539                 range_size=$((range_size + 1))
1540                 start=$((end + range_size))
1541         done
1542
1543         nft flush ruleset
1544 }
1545
1546 test_reported_issues() {
1547         eval test_bug_"${subtest}"
1548 }
1549
1550 # Run everything in a separate network namespace
1551 [ "${1}" != "run" ] && { unshare -n "${0}" run; exit $?; }
1552 tmp="$(mktemp)"
1553 trap cleanup EXIT
1554
1555 # Entry point for test runs
1556 passed=0
1557 for name in ${TESTS}; do
1558         printf "TEST: %s\n" "$(echo ${name} | tr '_' ' ')"
1559         if [ "${name}" = "reported_issues" ]; then
1560                 SUBTESTS="${BUGS}"
1561         else
1562                 SUBTESTS="${TYPES}"
1563         fi
1564
1565         for subtest in ${SUBTESTS}; do
1566                 eval desc=\$TYPE_"${subtest}"
1567                 IFS='
1568 '
1569                 for __line in ${desc}; do
1570                         # shellcheck disable=SC2086
1571                         eval ${__line%% *}=\"${__line##*        }\";
1572                 done
1573                 IFS='   
1574 '
1575
1576                 if [ "${name}" = "concurrency" ] && \
1577                    [ "${race_repeat}" = "0" ]; then
1578                         continue
1579                 fi
1580                 if [ "${name}" = "performance" ] && \
1581                    [ "${perf_duration}" = "0" ]; then
1582                         continue
1583                 fi
1584
1585                 printf "  %-60s  " "${display}"
1586                 eval test_"${name}"
1587                 ret=$?
1588
1589                 if [ $ret -eq 0 ]; then
1590                         printf "[ OK ]\n"
1591                         info_flush
1592                         passed=$((passed + 1))
1593                 elif [ $ret -eq 1 ]; then
1594                         printf "[FAIL]\n"
1595                         err_flush
1596                         exit 1
1597                 elif [ $ret -eq ${KSELFTEST_SKIP} ]; then
1598                         printf "[SKIP]\n"
1599                         err_flush
1600                 fi
1601         done
1602 done
1603
1604 [ ${passed} -eq 0 ] && exit ${KSELFTEST_SKIP}