clk: uniphier: Fix fixed-rate initialization
[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"
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 # Set template for all tests, types and rules are filled in depending on test
358 set_template='
359 flush ruleset
360
361 table inet filter {
362         counter test {
363                 packets 0 bytes 0
364         }
365
366         set test {
367                 type ${type_spec}
368                 flags interval,timeout
369         }
370
371         chain input {
372                 type filter hook prerouting priority 0; policy accept;
373                 ${chain_spec} @test counter name \"test\"
374         }
375 }
376
377 table netdev perf {
378         counter test {
379                 packets 0 bytes 0
380         }
381
382         counter match {
383                 packets 0 bytes 0
384         }
385
386         set test {
387                 type ${type_spec}
388                 flags interval
389         }
390
391         set norange {
392                 type ${type_spec}
393         }
394
395         set noconcat {
396                 type ${type_spec%% *}
397                 flags interval
398         }
399
400         chain test {
401                 type filter hook ingress device veth_a priority 0;
402         }
403 }
404 '
405
406 err_buf=
407 info_buf=
408
409 # Append string to error buffer
410 err() {
411         err_buf="${err_buf}${1}
412 "
413 }
414
415 # Append string to information buffer
416 info() {
417         info_buf="${info_buf}${1}
418 "
419 }
420
421 # Flush error buffer to stdout
422 err_flush() {
423         printf "%s" "${err_buf}"
424         err_buf=
425 }
426
427 # Flush information buffer to stdout
428 info_flush() {
429         printf "%s" "${info_buf}"
430         info_buf=
431 }
432
433 # Setup veth pair: this namespace receives traffic, B generates it
434 setup_veth() {
435         ip netns add B
436         ip link add veth_a type veth peer name veth_b || return 1
437
438         ip link set veth_a up
439         ip link set veth_b netns B
440
441         ip -n B link set veth_b up
442
443         ip addr add dev veth_a 10.0.0.1
444         ip route add default dev veth_a
445
446         ip -6 addr add fe80::1/64 dev veth_a nodad
447         ip -6 addr add 2001:db8::1/64 dev veth_a nodad
448         ip -6 route add default dev veth_a
449
450         ip -n B route add default dev veth_b
451
452         ip -6 -n B addr add fe80::2/64 dev veth_b nodad
453         ip -6 -n B addr add 2001:db8::2/64 dev veth_b nodad
454         ip -6 -n B route add default dev veth_b
455
456         B() {
457                 ip netns exec B "$@" >/dev/null 2>&1
458         }
459
460         sleep 2
461 }
462
463 # Fill in set template and initialise set
464 setup_set() {
465         eval "echo \"${set_template}\"" | nft -f -
466 }
467
468 # Check that at least one of the needed tools is available
469 check_tools() {
470         [ -z "${tools}" ] && return 0
471
472         __tools=
473         for tool in ${tools}; do
474                 if [ "${tool}" = "nc" ] && [ "${proto}" = "udp6" ] && \
475                    ! nc -u -w0 1.1.1.1 1 2>/dev/null; then
476                         # Some GNU netcat builds might not support IPv6
477                         __tools="${__tools} netcat-openbsd"
478                         continue
479                 fi
480                 __tools="${__tools} ${tool}"
481
482                 command -v "${tool}" >/dev/null && return 0
483         done
484         err "need one of:${__tools}, skipping" && return 1
485 }
486
487 # Set up function to send ICMP packets
488 setup_send_icmp() {
489         send_icmp() {
490                 B ping -c1 -W1 "${dst_addr4}" >/dev/null 2>&1
491         }
492 }
493
494 # Set up function to send ICMPv6 packets
495 setup_send_icmp6() {
496         if command -v ping6 >/dev/null; then
497                 send_icmp6() {
498                         ip -6 addr add "${dst_addr6}" dev veth_a nodad \
499                                 2>/dev/null
500                         B ping6 -q -c1 -W1 "${dst_addr6}"
501                 }
502         else
503                 send_icmp6() {
504                         ip -6 addr add "${dst_addr6}" dev veth_a nodad \
505                                 2>/dev/null
506                         B ping -q -6 -c1 -W1 "${dst_addr6}"
507                 }
508         fi
509 }
510
511 # Set up function to send single UDP packets on IPv4
512 setup_send_udp() {
513         if command -v sendip >/dev/null; then
514                 send_udp() {
515                         [ -n "${src_port}" ] && src_port="-us ${src_port}"
516                         [ -n "${dst_port}" ] && dst_port="-ud ${dst_port}"
517                         [ -n "${src_addr4}" ] && src_addr4="-is ${src_addr4}"
518
519                         # shellcheck disable=SC2086 # sendip needs split options
520                         B sendip -p ipv4 -p udp ${src_addr4} ${src_port} \
521                                                 ${dst_port} "${dst_addr4}"
522
523                         src_port=
524                         dst_port=
525                         src_addr4=
526                 }
527         elif command -v nc >/dev/null; then
528                 if nc -u -w0 1.1.1.1 1 2>/dev/null; then
529                         # OpenBSD netcat
530                         nc_opt="-w0"
531                 else
532                         # GNU netcat
533                         nc_opt="-q0"
534                 fi
535
536                 send_udp() {
537                         if [ -n "${src_addr4}" ]; then
538                                 B ip addr add "${src_addr4}" dev veth_b
539                                 __src_addr4="-s ${src_addr4}"
540                         fi
541                         ip addr add "${dst_addr4}" dev veth_a 2>/dev/null
542                         [ -n "${src_port}" ] && src_port="-p ${src_port}"
543
544                         echo "" | B nc -u "${nc_opt}" "${__src_addr4}" \
545                                   "${src_port}" "${dst_addr4}" "${dst_port}"
546
547                         src_addr4=
548                         src_port=
549                 }
550         elif [ -z "$(bash -c 'type -p')" ]; then
551                 send_udp() {
552                         ip addr add "${dst_addr4}" dev veth_a 2>/dev/null
553                         if [ -n "${src_addr4}" ]; then
554                                 B ip addr add "${src_addr4}/16" dev veth_b
555                                 B ip route add default dev veth_b
556                         fi
557
558                         B bash -c "echo > /dev/udp/${dst_addr4}/${dst_port}"
559
560                         if [ -n "${src_addr4}" ]; then
561                                 B ip addr del "${src_addr4}/16" dev veth_b
562                         fi
563                         src_addr4=
564                 }
565         else
566                 return 1
567         fi
568 }
569
570 # Set up function to send single UDP packets on IPv6
571 setup_send_udp6() {
572         if command -v sendip >/dev/null; then
573                 send_udp6() {
574                         [ -n "${src_port}" ] && src_port="-us ${src_port}"
575                         [ -n "${dst_port}" ] && dst_port="-ud ${dst_port}"
576                         if [ -n "${src_addr6}" ]; then
577                                 src_addr6="-6s ${src_addr6}"
578                         else
579                                 src_addr6="-6s 2001:db8::2"
580                         fi
581                         ip -6 addr add "${dst_addr6}" dev veth_a nodad \
582                                 2>/dev/null
583
584                         # shellcheck disable=SC2086 # this needs split options
585                         B sendip -p ipv6 -p udp ${src_addr6} ${src_port} \
586                                                 ${dst_port} "${dst_addr6}"
587
588                         src_port=
589                         dst_port=
590                         src_addr6=
591                 }
592         elif command -v nc >/dev/null && nc -u -w0 1.1.1.1 1 2>/dev/null; then
593                 # GNU netcat might not work with IPv6, try next tool
594                 send_udp6() {
595                         ip -6 addr add "${dst_addr6}" dev veth_a nodad \
596                                 2>/dev/null
597                         if [ -n "${src_addr6}" ]; then
598                                 B ip addr add "${src_addr6}" dev veth_b nodad
599                         else
600                                 src_addr6="2001:db8::2"
601                         fi
602                         [ -n "${src_port}" ] && src_port="-p ${src_port}"
603
604                         # shellcheck disable=SC2086 # this needs split options
605                         echo "" | B nc -u w0 "-s${src_addr6}" ${src_port} \
606                                                ${dst_addr6} ${dst_port}
607
608                         src_addr6=
609                         src_port=
610                 }
611         elif [ -z "$(bash -c 'type -p')" ]; then
612                 send_udp6() {
613                         ip -6 addr add "${dst_addr6}" dev veth_a nodad \
614                                 2>/dev/null
615                         B ip addr add "${src_addr6}" dev veth_b nodad
616                         B bash -c "echo > /dev/udp/${dst_addr6}/${dst_port}"
617                         ip -6 addr del "${dst_addr6}" dev veth_a 2>/dev/null
618                 }
619         else
620                 return 1
621         fi
622 }
623
624 # Set up function to send TCP traffic on IPv4
625 setup_flood_tcp() {
626         if command -v iperf3 >/dev/null; then
627                 flood_tcp() {
628                         [ -n "${dst_port}" ] && dst_port="-p ${dst_port}"
629                         if [ -n "${src_addr4}" ]; then
630                                 B ip addr add "${src_addr4}/16" dev veth_b
631                                 src_addr4="-B ${src_addr4}"
632                         else
633                                 B ip addr add dev veth_b 10.0.0.2
634                                 src_addr4="-B 10.0.0.2"
635                         fi
636                         if [ -n "${src_port}" ]; then
637                                 src_port="--cport ${src_port}"
638                         fi
639                         B ip route add default dev veth_b 2>/dev/null
640                         ip addr add "${dst_addr4}" dev veth_a 2>/dev/null
641
642                         # shellcheck disable=SC2086 # this needs split options
643                         iperf3 -s -DB "${dst_addr4}" ${dst_port} >/dev/null 2>&1
644                         sleep 2
645
646                         # shellcheck disable=SC2086 # this needs split options
647                         B iperf3 -c "${dst_addr4}" ${dst_port} ${src_port} \
648                                 ${src_addr4} -l16 -t 1000
649
650                         src_addr4=
651                         src_port=
652                         dst_port=
653                 }
654         elif command -v iperf >/dev/null; then
655                 flood_tcp() {
656                         [ -n "${dst_port}" ] && dst_port="-p ${dst_port}"
657                         if [ -n "${src_addr4}" ]; then
658                                 B ip addr add "${src_addr4}/16" dev veth_b
659                                 src_addr4="-B ${src_addr4}"
660                         else
661                                 B ip addr add dev veth_b 10.0.0.2 2>/dev/null
662                                 src_addr4="-B 10.0.0.2"
663                         fi
664                         if [ -n "${src_port}" ]; then
665                                 src_addr4="${src_addr4}:${src_port}"
666                         fi
667                         B ip route add default dev veth_b
668                         ip addr add "${dst_addr4}" dev veth_a 2>/dev/null
669
670                         # shellcheck disable=SC2086 # this needs split options
671                         iperf -s -DB "${dst_addr4}" ${dst_port} >/dev/null 2>&1
672                         sleep 2
673
674                         # shellcheck disable=SC2086 # this needs split options
675                         B iperf -c "${dst_addr4}" ${dst_port} ${src_addr4} \
676                                 -l20 -t 1000
677
678                         src_addr4=
679                         src_port=
680                         dst_port=
681                 }
682         elif command -v netperf >/dev/null; then
683                 flood_tcp() {
684                         [ -n "${dst_port}" ] && dst_port="-p ${dst_port}"
685                         if [ -n "${src_addr4}" ]; then
686                                 B ip addr add "${src_addr4}/16" dev veth_b
687                         else
688                                 B ip addr add dev veth_b 10.0.0.2
689                                 src_addr4="10.0.0.2"
690                         fi
691                         if [ -n "${src_port}" ]; then
692                                 dst_port="${dst_port},${src_port}"
693                         fi
694                         B ip route add default dev veth_b
695                         ip addr add "${dst_addr4}" dev veth_a 2>/dev/null
696
697                         # shellcheck disable=SC2086 # this needs split options
698                         netserver -4 ${dst_port} -L "${dst_addr4}" \
699                                 >/dev/null 2>&1
700                         sleep 2
701
702                         # shellcheck disable=SC2086 # this needs split options
703                         B netperf -4 -H "${dst_addr4}" ${dst_port} \
704                                 -L "${src_addr4}" -l 1000 -t TCP_STREAM
705
706                         src_addr4=
707                         src_port=
708                         dst_port=
709                 }
710         else
711                 return 1
712         fi
713 }
714
715 # Set up function to send TCP traffic on IPv6
716 setup_flood_tcp6() {
717         if command -v iperf3 >/dev/null; then
718                 flood_tcp6() {
719                         [ -n "${dst_port}" ] && dst_port="-p ${dst_port}"
720                         if [ -n "${src_addr6}" ]; then
721                                 B ip addr add "${src_addr6}" dev veth_b nodad
722                                 src_addr6="-B ${src_addr6}"
723                         else
724                                 src_addr6="-B 2001:db8::2"
725                         fi
726                         if [ -n "${src_port}" ]; then
727                                 src_port="--cport ${src_port}"
728                         fi
729                         B ip route add default dev veth_b
730                         ip -6 addr add "${dst_addr6}" dev veth_a nodad \
731                                 2>/dev/null
732
733                         # shellcheck disable=SC2086 # this needs split options
734                         iperf3 -s -DB "${dst_addr6}" ${dst_port} >/dev/null 2>&1
735                         sleep 2
736
737                         # shellcheck disable=SC2086 # this needs split options
738                         B iperf3 -c "${dst_addr6}" ${dst_port} \
739                                 ${src_port} ${src_addr6} -l16 -t 1000
740
741                         src_addr6=
742                         src_port=
743                         dst_port=
744                 }
745         elif command -v iperf >/dev/null; then
746                 flood_tcp6() {
747                         [ -n "${dst_port}" ] && dst_port="-p ${dst_port}"
748                         if [ -n "${src_addr6}" ]; then
749                                 B ip addr add "${src_addr6}" dev veth_b nodad
750                                 src_addr6="-B ${src_addr6}"
751                         else
752                                 src_addr6="-B 2001:db8::2"
753                         fi
754                         if [ -n "${src_port}" ]; then
755                                 src_addr6="${src_addr6}:${src_port}"
756                         fi
757                         B ip route add default dev veth_b
758                         ip -6 addr add "${dst_addr6}" dev veth_a nodad \
759                                 2>/dev/null
760
761                         # shellcheck disable=SC2086 # this needs split options
762                         iperf -s -VDB "${dst_addr6}" ${dst_port} >/dev/null 2>&1
763                         sleep 2
764
765                         # shellcheck disable=SC2086 # this needs split options
766                         B iperf -c "${dst_addr6}" -V ${dst_port} \
767                                 ${src_addr6} -l1 -t 1000
768
769                         src_addr6=
770                         src_port=
771                         dst_port=
772                 }
773         elif command -v netperf >/dev/null; then
774                 flood_tcp6() {
775                         [ -n "${dst_port}" ] && dst_port="-p ${dst_port}"
776                         if [ -n "${src_addr6}" ]; then
777                                 B ip addr add "${src_addr6}" dev veth_b nodad
778                         else
779                                 src_addr6="2001:db8::2"
780                         fi
781                         if [ -n "${src_port}" ]; then
782                                 dst_port="${dst_port},${src_port}"
783                         fi
784                         B ip route add default dev veth_b
785                         ip -6 addr add "${dst_addr6}" dev veth_a nodad \
786                                 2>/dev/null
787
788                         # shellcheck disable=SC2086 # this needs split options
789                         netserver -6 ${dst_port} -L "${dst_addr6}" \
790                                 >/dev/null 2>&1
791                         sleep 2
792
793                         # shellcheck disable=SC2086 # this needs split options
794                         B netperf -6 -H "${dst_addr6}" ${dst_port} \
795                                 -L "${src_addr6}" -l 1000 -t TCP_STREAM
796
797                         src_addr6=
798                         src_port=
799                         dst_port=
800                 }
801         else
802                 return 1
803         fi
804 }
805
806 # Set up function to send UDP traffic on IPv4
807 setup_flood_udp() {
808         if command -v iperf3 >/dev/null; then
809                 flood_udp() {
810                         [ -n "${dst_port}" ] && dst_port="-p ${dst_port}"
811                         if [ -n "${src_addr4}" ]; then
812                                 B ip addr add "${src_addr4}/16" dev veth_b
813                                 src_addr4="-B ${src_addr4}"
814                         else
815                                 B ip addr add dev veth_b 10.0.0.2 2>/dev/null
816                                 src_addr4="-B 10.0.0.2"
817                         fi
818                         if [ -n "${src_port}" ]; then
819                                 src_port="--cport ${src_port}"
820                         fi
821                         B ip route add default dev veth_b
822                         ip addr add "${dst_addr4}" dev veth_a 2>/dev/null
823
824                         # shellcheck disable=SC2086 # this needs split options
825                         iperf3 -s -DB "${dst_addr4}" ${dst_port}
826                         sleep 2
827
828                         # shellcheck disable=SC2086 # this needs split options
829                         B iperf3 -u -c "${dst_addr4}" -Z -b 100M -l16 -t1000 \
830                                 ${dst_port} ${src_port} ${src_addr4}
831
832                         src_addr4=
833                         src_port=
834                         dst_port=
835                 }
836         elif command -v iperf >/dev/null; then
837                 flood_udp() {
838                         [ -n "${dst_port}" ] && dst_port="-p ${dst_port}"
839                         if [ -n "${src_addr4}" ]; then
840                                 B ip addr add "${src_addr4}/16" dev veth_b
841                                 src_addr4="-B ${src_addr4}"
842                         else
843                                 B ip addr add dev veth_b 10.0.0.2
844                                 src_addr4="-B 10.0.0.2"
845                         fi
846                         if [ -n "${src_port}" ]; then
847                                 src_addr4="${src_addr4}:${src_port}"
848                         fi
849                         B ip route add default dev veth_b
850                         ip addr add "${dst_addr4}" dev veth_a 2>/dev/null
851
852                         # shellcheck disable=SC2086 # this needs split options
853                         iperf -u -sDB "${dst_addr4}" ${dst_port} >/dev/null 2>&1
854                         sleep 2
855
856                         # shellcheck disable=SC2086 # this needs split options
857                         B iperf -u -c "${dst_addr4}" -b 100M -l1 -t1000 \
858                                 ${dst_port} ${src_addr4}
859
860                         src_addr4=
861                         src_port=
862                         dst_port=
863                 }
864         elif command -v netperf >/dev/null; then
865                 flood_udp() {
866                         [ -n "${dst_port}" ] && dst_port="-p ${dst_port}"
867                         if [ -n "${src_addr4}" ]; then
868                                 B ip addr add "${src_addr4}/16" dev veth_b
869                         else
870                                 B ip addr add dev veth_b 10.0.0.2
871                                 src_addr4="10.0.0.2"
872                         fi
873                         if [ -n "${src_port}" ]; then
874                                 dst_port="${dst_port},${src_port}"
875                         fi
876                         B ip route add default dev veth_b
877                         ip addr add "${dst_addr4}" dev veth_a 2>/dev/null
878
879                         # shellcheck disable=SC2086 # this needs split options
880                         netserver -4 ${dst_port} -L "${dst_addr4}" \
881                                 >/dev/null 2>&1
882                         sleep 2
883
884                         # shellcheck disable=SC2086 # this needs split options
885                         B netperf -4 -H "${dst_addr4}" ${dst_port} \
886                                 -L "${src_addr4}" -l 1000 -t UDP_STREAM
887
888                         src_addr4=
889                         src_port=
890                         dst_port=
891                 }
892         else
893                 return 1
894         fi
895 }
896
897 # Find pktgen script and set up function to start pktgen injection
898 setup_perf() {
899         for pktgen_script_path in ${PKTGEN_SCRIPT_PATHS} __notfound; do
900                 command -v "${pktgen_script_path}" >/dev/null && break
901         done
902         [ "${pktgen_script_path}" = "__notfound" ] && return 1
903
904         perf_ipv4() {
905                 ${pktgen_script_path} -s80 \
906                         -i veth_a -d "${dst_addr4}" -p "${dst_port}" \
907                         -m "${dst_mac}" \
908                         -t $(($(nproc) / 5 + 1)) -b10000 -n0 2>/dev/null &
909                 perf_pid=$!
910         }
911         perf_ipv6() {
912                 IP6=6 ${pktgen_script_path} -s100 \
913                         -i veth_a -d "${dst_addr6}" -p "${dst_port}" \
914                         -m "${dst_mac}" \
915                         -t $(($(nproc) / 5 + 1)) -b10000 -n0 2>/dev/null &
916                 perf_pid=$!
917         }
918 }
919
920 # Clean up before each test
921 cleanup() {
922         nft reset counter inet filter test      >/dev/null 2>&1
923         nft flush ruleset                       >/dev/null 2>&1
924         ip link del dummy0                      2>/dev/null
925         ip route del default                    2>/dev/null
926         ip -6 route del default                 2>/dev/null
927         ip netns del B                          2>/dev/null
928         ip link del veth_a                      2>/dev/null
929         timeout=
930         killall iperf3                          2>/dev/null
931         killall iperf                           2>/dev/null
932         killall netperf                         2>/dev/null
933         killall netserver                       2>/dev/null
934         rm -f ${tmp}
935         sleep 2
936 }
937
938 # Entry point for setup functions
939 setup() {
940         if [ "$(id -u)" -ne 0 ]; then
941                 echo "  need to run as root"
942                 exit ${KSELFTEST_SKIP}
943         fi
944
945         cleanup
946         check_tools || return 1
947         for arg do
948                 if ! eval setup_"${arg}"; then
949                         err "  ${arg} not supported"
950                         return 1
951                 fi
952         done
953 }
954
955 # Format integer into IPv4 address, summing 10.0.0.5 (arbitrary) to it
956 format_addr4() {
957         a=$((${1} + 16777216 * 10 + 5))
958         printf "%i.%i.%i.%i"                                            \
959                "$((a / 16777216))" "$((a % 16777216 / 65536))"  \
960                "$((a % 65536 / 256))" "$((a % 256))"
961 }
962
963 # Format integer into IPv6 address, summing 2001:db8:: to it
964 format_addr6() {
965         printf "2001:db8::%04x:%04x" "$((${1} / 65536))" "$((${1} % 65536))"
966 }
967
968 # Format integer into EUI-48 address, summing 00:01:00:00:00:00 to it
969 format_mac() {
970         printf "00:01:%02x:%02x:%02x:%02x" \
971                "$((${1} / 16777216))" "$((${1} % 16777216 / 65536))"    \
972                "$((${1} % 65536 / 256))" "$((${1} % 256))"
973 }
974
975 # Format integer into port, avoid 0 port
976 format_port() {
977         printf "%i" "$((${1} % 65534 + 1))"
978 }
979
980 # Drop suffixed '6' from L4 protocol, if any
981 format_proto() {
982         printf "%s" "${proto}" | tr -d 6
983 }
984
985 # Format destination and source fields into nft concatenated type
986 format() {
987         __start=
988         __end=
989         __expr="{ "
990
991         for f in ${dst}; do
992                 [ "${__expr}" != "{ " ] && __expr="${__expr} . "
993
994                 __start="$(eval format_"${f}" "${start}")"
995                 __end="$(eval format_"${f}" "${end}")"
996
997                 if [ "${f}" = "proto" ]; then
998                         __expr="${__expr}${__start}"
999                 else
1000                         __expr="${__expr}${__start}-${__end}"
1001                 fi
1002         done
1003         for f in ${src}; do
1004                 [ "${__expr}" != "{ " ] && __expr="${__expr} . "
1005
1006                 __start="$(eval format_"${f}" "${srcstart}")"
1007                 __end="$(eval format_"${f}" "${srcend}")"
1008
1009                 if [ "${f}" = "proto" ]; then
1010                         __expr="${__expr}${__start}"
1011                 else
1012                         __expr="${__expr}${__start}-${__end}"
1013                 fi
1014         done
1015
1016         if [ -n "${timeout}" ]; then
1017                 echo "${__expr} timeout ${timeout}s }"
1018         else
1019                 echo "${__expr} }"
1020         fi
1021 }
1022
1023 # Format destination and source fields into nft type, start element only
1024 format_norange() {
1025         __expr="{ "
1026
1027         for f in ${dst}; do
1028                 [ "${__expr}" != "{ " ] && __expr="${__expr} . "
1029
1030                 __expr="${__expr}$(eval format_"${f}" "${start}")"
1031         done
1032         for f in ${src}; do
1033                 __expr="${__expr} . $(eval format_"${f}" "${start}")"
1034         done
1035
1036         echo "${__expr} }"
1037 }
1038
1039 # Format first destination field into nft type
1040 format_noconcat() {
1041         for f in ${dst}; do
1042                 __start="$(eval format_"${f}" "${start}")"
1043                 __end="$(eval format_"${f}" "${end}")"
1044
1045                 if [ "${f}" = "proto" ]; then
1046                         echo "{ ${__start} }"
1047                 else
1048                         echo "{ ${__start}-${__end} }"
1049                 fi
1050                 return
1051         done
1052 }
1053
1054 # Add single entry to 'test' set in 'inet filter' table
1055 add() {
1056         if ! nft add element inet filter test "${1}"; then
1057                 err "Failed to add ${1} given ruleset:"
1058                 err "$(nft -a list ruleset)"
1059                 return 1
1060         fi
1061 }
1062
1063 # Format and output entries for sets in 'netdev perf' table
1064 add_perf() {
1065         if [ "${1}" = "test" ]; then
1066                 echo "add element netdev perf test $(format)"
1067         elif [ "${1}" = "norange" ]; then
1068                 echo "add element netdev perf norange $(format_norange)"
1069         elif [ "${1}" = "noconcat" ]; then
1070                 echo "add element netdev perf noconcat $(format_noconcat)"
1071         fi
1072 }
1073
1074 # Add single entry to 'norange' set in 'netdev perf' table
1075 add_perf_norange() {
1076         if ! nft add element netdev perf norange "${1}"; then
1077                 err "Failed to add ${1} given ruleset:"
1078                 err "$(nft -a list ruleset)"
1079                 return 1
1080         fi
1081 }
1082
1083 # Add single entry to 'noconcat' set in 'netdev perf' table
1084 add_perf_noconcat() {
1085         if ! nft add element netdev perf noconcat "${1}"; then
1086                 err "Failed to add ${1} given ruleset:"
1087                 err "$(nft -a list ruleset)"
1088                 return 1
1089         fi
1090 }
1091
1092 # Delete single entry from set
1093 del() {
1094         if ! nft delete element inet filter test "${1}"; then
1095                 err "Failed to delete ${1} given ruleset:"
1096                 err "$(nft -a list ruleset)"
1097                 return 1
1098         fi
1099 }
1100
1101 # Return packet count from 'test' counter in 'inet filter' table
1102 count_packets() {
1103         found=0
1104         for token in $(nft list counter inet filter test); do
1105                 [ ${found} -eq 1 ] && echo "${token}" && return
1106                 [ "${token}" = "packets" ] && found=1
1107         done
1108 }
1109
1110 # Return packet count from 'test' counter in 'netdev perf' table
1111 count_perf_packets() {
1112         found=0
1113         for token in $(nft list counter netdev perf test); do
1114                 [ ${found} -eq 1 ] && echo "${token}" && return
1115                 [ "${token}" = "packets" ] && found=1
1116         done
1117 }
1118
1119 # Set MAC addresses, send traffic according to specifier
1120 flood() {
1121         ip link set veth_a address "$(format_mac "${1}")"
1122         ip -n B link set veth_b address "$(format_mac "${2}")"
1123
1124         for f in ${dst}; do
1125                 eval dst_"$f"=\$\(format_\$f "${1}"\)
1126         done
1127         for f in ${src}; do
1128                 eval src_"$f"=\$\(format_\$f "${2}"\)
1129         done
1130         eval flood_\$proto
1131 }
1132
1133 # Set MAC addresses, start pktgen injection
1134 perf() {
1135         dst_mac="$(format_mac "${1}")"
1136         ip link set veth_a address "${dst_mac}"
1137
1138         for f in ${dst}; do
1139                 eval dst_"$f"=\$\(format_\$f "${1}"\)
1140         done
1141         for f in ${src}; do
1142                 eval src_"$f"=\$\(format_\$f "${2}"\)
1143         done
1144         eval perf_\$perf_proto
1145 }
1146
1147 # Set MAC addresses, send single packet, check that it matches, reset counter
1148 send_match() {
1149         ip link set veth_a address "$(format_mac "${1}")"
1150         ip -n B link set veth_b address "$(format_mac "${2}")"
1151
1152         for f in ${dst}; do
1153                 eval dst_"$f"=\$\(format_\$f "${1}"\)
1154         done
1155         for f in ${src}; do
1156                 eval src_"$f"=\$\(format_\$f "${2}"\)
1157         done
1158         eval send_\$proto
1159         if [ "$(count_packets)" != "1" ]; then
1160                 err "${proto} packet to:"
1161                 err "  $(for f in ${dst}; do
1162                          eval format_\$f "${1}"; printf ' '; done)"
1163                 err "from:"
1164                 err "  $(for f in ${src}; do
1165                          eval format_\$f "${2}"; printf ' '; done)"
1166                 err "should have matched ruleset:"
1167                 err "$(nft -a list ruleset)"
1168                 return 1
1169         fi
1170         nft reset counter inet filter test >/dev/null
1171 }
1172
1173 # Set MAC addresses, send single packet, check that it doesn't match
1174 send_nomatch() {
1175         ip link set veth_a address "$(format_mac "${1}")"
1176         ip -n B link set veth_b address "$(format_mac "${2}")"
1177
1178         for f in ${dst}; do
1179                 eval dst_"$f"=\$\(format_\$f "${1}"\)
1180         done
1181         for f in ${src}; do
1182                 eval src_"$f"=\$\(format_\$f "${2}"\)
1183         done
1184         eval send_\$proto
1185         if [ "$(count_packets)" != "0" ]; then
1186                 err "${proto} packet to:"
1187                 err "  $(for f in ${dst}; do
1188                          eval format_\$f "${1}"; printf ' '; done)"
1189                 err "from:"
1190                 err "  $(for f in ${src}; do
1191                          eval format_\$f "${2}"; printf ' '; done)"
1192                 err "should not have matched ruleset:"
1193                 err "$(nft -a list ruleset)"
1194                 return 1
1195         fi
1196 }
1197
1198 # Correctness test template:
1199 # - add ranged element, check that packets match it
1200 # - check that packets outside range don't match it
1201 # - remove some elements, check that packets don't match anymore
1202 test_correctness() {
1203         setup veth send_"${proto}" set || return ${KSELFTEST_SKIP}
1204
1205         range_size=1
1206         for i in $(seq "${start}" $((start + count))); do
1207                 end=$((start + range_size))
1208
1209                 # Avoid negative or zero-sized port ranges
1210                 if [ $((end / 65534)) -gt $((start / 65534)) ]; then
1211                         start=${end}
1212                         end=$((end + 1))
1213                 fi
1214                 srcstart=$((start + src_delta))
1215                 srcend=$((end + src_delta))
1216
1217                 add "$(format)" || return 1
1218                 for j in $(seq ${start} $((range_size / 2 + 1)) ${end}); do
1219                         send_match "${j}" $((j + src_delta)) || return 1
1220                 done
1221                 send_nomatch $((end + 1)) $((end + 1 + src_delta)) || return 1
1222
1223                 # Delete elements now and then
1224                 if [ $((i % 3)) -eq 0 ]; then
1225                         del "$(format)" || return 1
1226                         for j in $(seq ${start} \
1227                                    $((range_size / 2 + 1)) ${end}); do
1228                                 send_nomatch "${j}" $((j + src_delta)) \
1229                                         || return 1
1230                         done
1231                 fi
1232
1233                 range_size=$((range_size + 1))
1234                 start=$((end + range_size))
1235         done
1236 }
1237
1238 # Concurrency test template:
1239 # - add all the elements
1240 # - start a thread for each physical thread that:
1241 #   - adds all the elements
1242 #   - flushes the set
1243 #   - adds all the elements
1244 #   - flushes the entire ruleset
1245 #   - adds the set back
1246 #   - adds all the elements
1247 #   - delete all the elements
1248 test_concurrency() {
1249         proto=${flood_proto}
1250         tools=${flood_tools}
1251         chain_spec=${flood_spec}
1252         setup veth flood_"${proto}" set || return ${KSELFTEST_SKIP}
1253
1254         range_size=1
1255         cstart=${start}
1256         flood_pids=
1257         for i in $(seq ${start} $((start + count))); do
1258                 end=$((start + range_size))
1259                 srcstart=$((start + src_delta))
1260                 srcend=$((end + src_delta))
1261
1262                 add "$(format)" || return 1
1263
1264                 flood "${i}" $((i + src_delta)) & flood_pids="${flood_pids} $!"
1265
1266                 range_size=$((range_size + 1))
1267                 start=$((end + range_size))
1268         done
1269
1270         sleep 10
1271
1272         pids=
1273         for c in $(seq 1 "$(nproc)"); do (
1274                 for r in $(seq 1 "${race_repeat}"); do
1275                         range_size=1
1276
1277                         # $start needs to be local to this subshell
1278                         # shellcheck disable=SC2030
1279                         start=${cstart}
1280                         for i in $(seq ${start} $((start + count))); do
1281                                 end=$((start + range_size))
1282                                 srcstart=$((start + src_delta))
1283                                 srcend=$((end + src_delta))
1284
1285                                 add "$(format)" 2>/dev/null
1286
1287                                 range_size=$((range_size + 1))
1288                                 start=$((end + range_size))
1289                         done
1290
1291                         nft flush inet filter test 2>/dev/null
1292
1293                         range_size=1
1294                         start=${cstart}
1295                         for i in $(seq ${start} $((start + count))); do
1296                                 end=$((start + range_size))
1297                                 srcstart=$((start + src_delta))
1298                                 srcend=$((end + src_delta))
1299
1300                                 add "$(format)" 2>/dev/null
1301
1302                                 range_size=$((range_size + 1))
1303                                 start=$((end + range_size))
1304                         done
1305
1306                         nft flush ruleset
1307                         setup set 2>/dev/null
1308
1309                         range_size=1
1310                         start=${cstart}
1311                         for i in $(seq ${start} $((start + count))); do
1312                                 end=$((start + range_size))
1313                                 srcstart=$((start + src_delta))
1314                                 srcend=$((end + src_delta))
1315
1316                                 add "$(format)" 2>/dev/null
1317
1318                                 range_size=$((range_size + 1))
1319                                 start=$((end + range_size))
1320                         done
1321
1322                         range_size=1
1323                         start=${cstart}
1324                         for i in $(seq ${start} $((start + count))); do
1325                                 end=$((start + range_size))
1326                                 srcstart=$((start + src_delta))
1327                                 srcend=$((end + src_delta))
1328
1329                                 del "$(format)" 2>/dev/null
1330
1331                                 range_size=$((range_size + 1))
1332                                 start=$((end + range_size))
1333                         done
1334                 done
1335         ) & pids="${pids} $!"
1336         done
1337
1338         # shellcheck disable=SC2046,SC2086 # word splitting wanted here
1339         wait $(for pid in ${pids}; do echo ${pid}; done)
1340         # shellcheck disable=SC2046,SC2086
1341         kill $(for pid in ${flood_pids}; do echo ${pid}; done) 2>/dev/null
1342         # shellcheck disable=SC2046,SC2086
1343         wait $(for pid in ${flood_pids}; do echo ${pid}; done) 2>/dev/null
1344
1345         return 0
1346 }
1347
1348 # Timeout test template:
1349 # - add all the elements with 3s timeout while checking that packets match
1350 # - wait 3s after the last insertion, check that packets don't match any entry
1351 test_timeout() {
1352         setup veth send_"${proto}" set || return ${KSELFTEST_SKIP}
1353
1354         timeout=3
1355         range_size=1
1356         for i in $(seq "${start}" $((start + count))); do
1357                 end=$((start + range_size))
1358                 srcstart=$((start + src_delta))
1359                 srcend=$((end + src_delta))
1360
1361                 add "$(format)" || return 1
1362
1363                 for j in $(seq ${start} $((range_size / 2 + 1)) ${end}); do
1364                         send_match "${j}" $((j + src_delta)) || return 1
1365                 done
1366
1367                 range_size=$((range_size + 1))
1368                 start=$((end + range_size))
1369         done
1370         sleep 3
1371         for i in $(seq ${start} $((start + count))); do
1372                 end=$((start + range_size))
1373                 srcstart=$((start + src_delta))
1374                 srcend=$((end + src_delta))
1375
1376                 for j in $(seq ${start} $((range_size / 2 + 1)) ${end}); do
1377                         send_nomatch "${j}" $((j + src_delta)) || return 1
1378                 done
1379
1380                 range_size=$((range_size + 1))
1381                 start=$((end + range_size))
1382         done
1383 }
1384
1385 # Performance test template:
1386 # - add concatenated ranged entries
1387 # - add non-ranged concatenated entries (for hash set matching rate baseline)
1388 # - add ranged entries with first field only (for rbhash baseline)
1389 # - start pktgen injection directly on device rx path of this namespace
1390 # - measure drop only rate, hash and rbtree baselines, then matching rate
1391 test_performance() {
1392         chain_spec=${perf_spec}
1393         dst="${perf_dst}"
1394         src="${perf_src}"
1395         setup veth perf set || return ${KSELFTEST_SKIP}
1396
1397         first=${start}
1398         range_size=1
1399         for set in test norange noconcat; do
1400                 start=${first}
1401                 for i in $(seq ${start} $((start + perf_entries))); do
1402                         end=$((start + range_size))
1403                         srcstart=$((start + src_delta))
1404                         srcend=$((end + src_delta))
1405
1406                         if [ $((end / 65534)) -gt $((start / 65534)) ]; then
1407                                 start=${end}
1408                                 end=$((end + 1))
1409                         elif [ ${start} -eq ${end} ]; then
1410                                 end=$((start + 1))
1411                         fi
1412
1413                         add_perf ${set}
1414
1415                         start=$((end + range_size))
1416                 done > "${tmp}"
1417                 nft -f "${tmp}"
1418         done
1419
1420         perf $((end - 1)) ${srcstart}
1421
1422         sleep 2
1423
1424         nft add rule netdev perf test counter name \"test\" drop
1425         nft reset counter netdev perf test >/dev/null 2>&1
1426         sleep "${perf_duration}"
1427         pps="$(printf %10s $(($(count_perf_packets) / perf_duration)))"
1428         info "    baseline (drop from netdev hook):            ${pps}pps"
1429         handle="$(nft -a list chain netdev perf test | grep counter)"
1430         handle="${handle##* }"
1431         nft delete rule netdev perf test handle "${handle}"
1432
1433         nft add rule "netdev perf test ${chain_spec} @norange \
1434                 counter name \"test\" drop"
1435         nft reset counter netdev perf test >/dev/null 2>&1
1436         sleep "${perf_duration}"
1437         pps="$(printf %10s $(($(count_perf_packets) / perf_duration)))"
1438         info "    baseline hash (non-ranged entries):          ${pps}pps"
1439         handle="$(nft -a list chain netdev perf test | grep counter)"
1440         handle="${handle##* }"
1441         nft delete rule netdev perf test handle "${handle}"
1442
1443         nft add rule "netdev perf test ${chain_spec%%. *} @noconcat \
1444                 counter name \"test\" drop"
1445         nft reset counter netdev perf test >/dev/null 2>&1
1446         sleep "${perf_duration}"
1447         pps="$(printf %10s $(($(count_perf_packets) / perf_duration)))"
1448         info "    baseline rbtree (match on first field only): ${pps}pps"
1449         handle="$(nft -a list chain netdev perf test | grep counter)"
1450         handle="${handle##* }"
1451         nft delete rule netdev perf test handle "${handle}"
1452
1453         nft add rule "netdev perf test ${chain_spec} @test \
1454                 counter name \"test\" drop"
1455         nft reset counter netdev perf test >/dev/null 2>&1
1456         sleep "${perf_duration}"
1457         pps="$(printf %10s $(($(count_perf_packets) / perf_duration)))"
1458         p5="$(printf %5s "${perf_entries}")"
1459         info "    set with ${p5} full, ranged entries:         ${pps}pps"
1460         kill "${perf_pid}"
1461 }
1462
1463 test_bug_flush_remove_add() {
1464         set_cmd='{ set s { type ipv4_addr . inet_service; flags interval; }; }'
1465         elem1='{ 10.0.0.1 . 22-25, 10.0.0.1 . 10-20 }'
1466         elem2='{ 10.0.0.1 . 10-20, 10.0.0.1 . 22-25 }'
1467         for i in `seq 1 100`; do
1468                 nft add table t ${set_cmd}      || return ${KSELFTEST_SKIP}
1469                 nft add element t s ${elem1}    2>/dev/null || return 1
1470                 nft flush set t s               2>/dev/null || return 1
1471                 nft add element t s ${elem2}    2>/dev/null || return 1
1472         done
1473         nft flush ruleset
1474 }
1475
1476 test_reported_issues() {
1477         eval test_bug_"${subtest}"
1478 }
1479
1480 # Run everything in a separate network namespace
1481 [ "${1}" != "run" ] && { unshare -n "${0}" run; exit $?; }
1482 tmp="$(mktemp)"
1483 trap cleanup EXIT
1484
1485 # Entry point for test runs
1486 passed=0
1487 for name in ${TESTS}; do
1488         printf "TEST: %s\n" "$(echo ${name} | tr '_' ' ')"
1489         if [ "${name}" = "reported_issues" ]; then
1490                 SUBTESTS="${BUGS}"
1491         else
1492                 SUBTESTS="${TYPES}"
1493         fi
1494
1495         for subtest in ${SUBTESTS}; do
1496                 eval desc=\$TYPE_"${subtest}"
1497                 IFS='
1498 '
1499                 for __line in ${desc}; do
1500                         # shellcheck disable=SC2086
1501                         eval ${__line%% *}=\"${__line##*        }\";
1502                 done
1503                 IFS='   
1504 '
1505
1506                 if [ "${name}" = "concurrency" ] && \
1507                    [ "${race_repeat}" = "0" ]; then
1508                         continue
1509                 fi
1510                 if [ "${name}" = "performance" ] && \
1511                    [ "${perf_duration}" = "0" ]; then
1512                         continue
1513                 fi
1514
1515                 printf "  %-60s  " "${display}"
1516                 eval test_"${name}"
1517                 ret=$?
1518
1519                 if [ $ret -eq 0 ]; then
1520                         printf "[ OK ]\n"
1521                         info_flush
1522                         passed=$((passed + 1))
1523                 elif [ $ret -eq 1 ]; then
1524                         printf "[FAIL]\n"
1525                         err_flush
1526                         exit 1
1527                 elif [ $ret -eq ${KSELFTEST_SKIP} ]; then
1528                         printf "[SKIP]\n"
1529                         err_flush
1530                 fi
1531         done
1532 done
1533
1534 [ ${passed} -eq 0 ] && exit ${KSELFTEST_SKIP}