1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3# 4# This tests basic flowtable functionality. 5# Creates following default topology: 6# 7# Originator (MTU 9000) <-Router1-> MTU 1500 <-Router2-> Responder (MTU 2000) 8# Router1 is the one doing flow offloading, Router2 has no special 9# purpose other than having a link that is smaller than either Originator 10# and responder, i.e. TCPMSS announced values are too large and will still 11# result in fragmentation and/or PMTU discovery. 12# 13# You can check with different Orgininator/Link/Responder MTU eg: 14# nft_flowtable.sh -o8000 -l1500 -r2000 15# 16 17source lib.sh 18 19ret=0 20SOCAT_TIMEOUT=60 21 22nsin="" 23nsin_small="" 24ns1out="" 25ns2out="" 26 27log_netns=$(sysctl -n net.netfilter.nf_log_all_netns) 28 29checktool "nft --version" "run test without nft tool" 30checktool "socat -h" "run test without socat" 31 32setup_ns ns1 ns2 nsr1 nsr2 33 34cleanup() { 35 ip netns pids "$ns1" | xargs kill 2>/dev/null 36 ip netns pids "$ns2" | xargs kill 2>/dev/null 37 38 cleanup_all_ns 39 40 rm -f "$nsin" "$nsin_small" "$ns1out" "$ns2out" 41 42 [ "$log_netns" -eq 0 ] && sysctl -q net.netfilter.nf_log_all_netns="$log_netns" 43} 44 45trap cleanup EXIT 46 47sysctl -q net.netfilter.nf_log_all_netns=1 48 49ip link add veth0 netns "$nsr1" type veth peer name eth0 netns "$ns1" 50ip link add veth1 netns "$nsr1" type veth peer name veth0 netns "$nsr2" 51 52ip link add veth1 netns "$nsr2" type veth peer name eth0 netns "$ns2" 53 54for dev in veth0 veth1; do 55 ip -net "$nsr1" link set "$dev" up 56 ip -net "$nsr2" link set "$dev" up 57done 58 59ip -net "$nsr1" addr add 10.0.1.1/24 dev veth0 60ip -net "$nsr1" addr add dead:1::1/64 dev veth0 nodad 61 62ip -net "$nsr2" addr add 10.0.2.1/24 dev veth1 63ip -net "$nsr2" addr add dead:2::1/64 dev veth1 nodad 64 65# set different MTUs so we need to push packets coming from ns1 (large MTU) 66# to ns2 (smaller MTU) to stack either to perform fragmentation (ip_no_pmtu_disc=1), 67# or to do PTMU discovery (send ICMP error back to originator). 68# ns2 is going via nsr2 with a smaller mtu, so that TCPMSS announced by both peers 69# is NOT the lowest link mtu. 70 71omtu=9000 72lmtu=1500 73rmtu=2000 74 75filesize=$((2 * 1024 * 1024)) 76filesize_small=$((filesize / 16)) 77 78usage(){ 79 echo "nft_flowtable.sh [OPTIONS]" 80 echo 81 echo "MTU options" 82 echo " -o originator" 83 echo " -l link" 84 echo " -r responder" 85 exit 1 86} 87 88while getopts "o:l:r:s:" o 89do 90 case $o in 91 o) omtu=$OPTARG;; 92 l) lmtu=$OPTARG;; 93 r) rmtu=$OPTARG;; 94 s) 95 filesize=$OPTARG 96 filesize_small=$((OPTARG / 16)) 97 ;; 98 *) usage;; 99 esac 100done 101 102if ! ip -net "$nsr1" link set veth0 mtu "$omtu"; then 103 exit 1 104fi 105 106ip -net "$ns1" link set eth0 mtu "$omtu" 107 108if ! ip -net "$nsr2" link set veth1 mtu "$rmtu"; then 109 exit 1 110fi 111 112if ! ip -net "$nsr1" link set veth1 mtu "$lmtu"; then 113 exit 1 114fi 115 116if ! ip -net "$nsr2" link set veth0 mtu "$lmtu"; then 117 exit 1 118fi 119 120ip -net "$ns2" link set eth0 mtu "$rmtu" 121 122# transfer-net between nsr1 and nsr2. 123# these addresses are not used for connections. 124ip -net "$nsr1" addr add 192.168.10.1/24 dev veth1 125ip -net "$nsr1" addr add fee1:2::1/64 dev veth1 nodad 126 127ip -net "$nsr2" addr add 192.168.10.2/24 dev veth0 128ip -net "$nsr2" addr add fee1:2::2/64 dev veth0 nodad 129 130ip netns exec "$nsr1" sysctl net.ipv6.conf.all.forwarding=1 > /dev/null 131ip netns exec "$nsr2" sysctl net.ipv6.conf.all.forwarding=1 > /dev/null 132for i in 0 1; do 133 ip netns exec "$nsr1" sysctl net.ipv4.conf.veth$i.forwarding=1 > /dev/null 134 ip netns exec "$nsr2" sysctl net.ipv4.conf.veth$i.forwarding=1 > /dev/null 135done 136 137for ns in "$ns1" "$ns2";do 138 ip -net "$ns" link set eth0 up 139 140 if ! ip netns exec "$ns" sysctl net.ipv4.tcp_no_metrics_save=1 > /dev/null; then 141 echo "ERROR: Check Originator/Responder values (problem during address addition)" 142 exit 1 143 fi 144 # don't set ip DF bit for first two tests 145 ip netns exec "$ns" sysctl net.ipv4.ip_no_pmtu_disc=1 > /dev/null 146done 147 148ip -net "$ns1" addr add 10.0.1.99/24 dev eth0 149ip -net "$ns2" addr add 10.0.2.99/24 dev eth0 150ip -net "$ns1" route add default via 10.0.1.1 151ip -net "$ns2" route add default via 10.0.2.1 152ip -net "$ns1" addr add dead:1::99/64 dev eth0 nodad 153ip -net "$ns2" addr add dead:2::99/64 dev eth0 nodad 154ip -net "$ns1" route add default via dead:1::1 155ip -net "$ns2" route add default via dead:2::1 156 157ip -net "$nsr1" route add default via 192.168.10.2 158ip -6 -net "$nsr1" route add default via fee1:2::2 159ip -net "$nsr2" route add default via 192.168.10.1 160ip -6 -net "$nsr2" route add default via fee1:2::1 161 162ip netns exec "$nsr1" nft -f - <<EOF 163table inet filter { 164 flowtable f1 { 165 hook ingress priority 0 166 devices = { veth0, veth1 } 167 } 168 169 counter routed_orig { } 170 counter routed_repl { } 171 172 chain forward { 173 type filter hook forward priority 0; policy drop; 174 175 # flow offloaded? Tag ct with mark 1, so we can detect when it fails. 176 meta oif "veth1" tcp dport 12345 ct mark set 1 flow add @f1 counter name routed_orig accept 177 178 # count packets supposedly offloaded as per direction. 179 ct mark 1 counter name ct direction map { original : routed_orig, reply : routed_repl } accept 180 181 ct state established,related accept 182 183 meta nfproto ipv4 meta l4proto icmp accept 184 meta nfproto ipv6 meta l4proto icmpv6 accept 185 } 186} 187EOF 188 189if [ $? -ne 0 ]; then 190 echo "SKIP: Could not load nft ruleset" 191 exit $ksft_skip 192fi 193 194ip netns exec "$ns2" nft -f - <<EOF 195table inet filter { 196 counter ip4dscp0 { } 197 counter ip4dscp3 { } 198 199 chain input { 200 type filter hook input priority 0; policy accept; 201 meta l4proto tcp goto { 202 ip dscp cs3 counter name ip4dscp3 accept 203 ip dscp 0 counter name ip4dscp0 accept 204 } 205 } 206} 207EOF 208 209if [ $? -ne 0 ]; then 210 echo -n "SKIP: Could not load ruleset: " 211 nft --version 212 exit $ksft_skip 213fi 214 215# test basic connectivity 216if ! ip netns exec "$ns1" ping -c 1 -q 10.0.2.99 > /dev/null; then 217 echo "ERROR: $ns1 cannot reach ns2" 1>&2 218 exit 1 219fi 220 221if ! ip netns exec "$ns2" ping -c 1 -q 10.0.1.99 > /dev/null; then 222 echo "ERROR: $ns2 cannot reach $ns1" 1>&2 223 exit 1 224fi 225 226nsin=$(mktemp) 227nsin_small=$(mktemp) 228ns1out=$(mktemp) 229ns2out=$(mktemp) 230 231make_file() 232{ 233 name="$1" 234 sz="$2" 235 236 head -c "$sz" < /dev/urandom > "$name" 237} 238 239check_counters() 240{ 241 local what=$1 242 local ok=1 243 244 local orig repl 245 orig=$(ip netns exec "$nsr1" nft reset counter inet filter routed_orig | grep packets) 246 repl=$(ip netns exec "$nsr1" nft reset counter inet filter routed_repl | grep packets) 247 248 local orig_cnt=${orig#*bytes} 249 local repl_cnt=${repl#*bytes} 250 251 local fs 252 fs=$(du -sb "$nsin") 253 local max_orig=${fs%%/*} 254 local max_repl=$((max_orig)) 255 256 # flowtable fastpath should bypass normal routing one, i.e. the counters in forward hook 257 # should always be lower than the size of the transmitted file (max_orig). 258 if [ "$orig_cnt" -gt "$max_orig" ];then 259 echo "FAIL: $what: original counter $orig_cnt exceeds expected value $max_orig, reply counter $repl_cnt" 1>&2 260 ret=1 261 ok=0 262 fi 263 264 if [ "$repl_cnt" -gt $max_repl ];then 265 echo "FAIL: $what: reply counter $repl_cnt exceeds expected value $max_repl, original counter $orig_cnt" 1>&2 266 ret=1 267 ok=0 268 fi 269 270 if [ $ok -eq 1 ]; then 271 echo "PASS: $what" 272 fi 273} 274 275check_dscp() 276{ 277 local what=$1 278 local pmtud="$2" 279 local ok=1 280 281 local counter 282 counter=$(ip netns exec "$ns2" nft reset counter inet filter ip4dscp3 | grep packets) 283 284 local pc4=${counter%*bytes*} 285 local pc4=${pc4#*packets} 286 287 counter=$(ip netns exec "$ns2" nft reset counter inet filter ip4dscp0 | grep packets) 288 local pc4z=${counter%*bytes*} 289 local pc4z=${pc4z#*packets} 290 291 local failmsg="FAIL: pmtu $pmtu: $what counters do not match, expected" 292 293 case "$what" in 294 "dscp_none") 295 if [ "$pc4" -gt 0 ] || [ "$pc4z" -eq 0 ]; then 296 echo "$failmsg dscp3 == 0, dscp0 > 0, but got $pc4,$pc4z" 1>&2 297 ret=1 298 ok=0 299 fi 300 ;; 301 "dscp_fwd") 302 if [ "$pc4" -eq 0 ] || [ "$pc4z" -eq 0 ]; then 303 echo "$failmsg dscp3 and dscp0 > 0 but got $pc4,$pc4z" 1>&2 304 ret=1 305 ok=0 306 fi 307 ;; 308 "dscp_ingress") 309 if [ "$pc4" -eq 0 ] || [ "$pc4z" -gt 0 ]; then 310 echo "$failmsg dscp3 > 0, dscp0 == 0 but got $pc4,$pc4z" 1>&2 311 ret=1 312 ok=0 313 fi 314 ;; 315 "dscp_egress") 316 if [ "$pc4" -eq 0 ] || [ "$pc4z" -gt 0 ]; then 317 echo "$failmsg dscp3 > 0, dscp0 == 0 but got $pc4,$pc4z" 1>&2 318 ret=1 319 ok=0 320 fi 321 ;; 322 *) 323 echo "$failmsg: Unknown DSCP check" 1>&2 324 ret=1 325 ok=0 326 esac 327 328 if [ "$ok" -eq 1 ] ;then 329 echo "PASS: $what: dscp packet counters match" 330 fi 331} 332 333check_transfer() 334{ 335 local in=$1 336 local out=$2 337 local what=$3 338 339 if ! cmp "$in" "$out" > /dev/null 2>&1; then 340 echo "FAIL: file mismatch for $what" 1>&2 341 ls -l "$in" 342 ls -l "$out" 343 return 1 344 fi 345 346 return 0 347} 348 349listener_ready() 350{ 351 ss -N "$nsb" -lnt -o "sport = :12345" | grep -q 12345 352} 353 354test_tcp_forwarding_ip() 355{ 356 local nsa=$1 357 local nsb=$2 358 local pmtu=$3 359 local proto=$4 360 local dstip=$5 361 local dstport=$6 362 local lret=0 363 local socatc 364 local socatl 365 local infile="$nsin" 366 367 if [ $pmtu -eq 0 ]; then 368 infile="$nsin_small" 369 fi 370 371 timeout "$SOCAT_TIMEOUT" ip netns exec "$nsb" socat -${proto} \ 372 TCP"${proto}"-LISTEN:12345,reuseaddr STDIO < "$infile" > "$ns2out" & 373 lpid=$! 374 375 busywait 1000 listener_ready 376 377 timeout "$SOCAT_TIMEOUT" ip netns exec "$nsa" socat -${proto} \ 378 TCP"${proto}":"$dstip":"$dstport" STDIO < "$infile" > "$ns1out" 379 socatc=$? 380 381 wait $lpid 382 socatl=$? 383 384 if [ $socatl -ne 0 ] || [ $socatc -ne 0 ];then 385 rc=1 386 fi 387 388 if ! check_transfer "$infile" "$ns2out" "ns1 -> ns2"; then 389 lret=1 390 ret=1 391 fi 392 393 if ! check_transfer "$infile" "$ns1out" "ns1 <- ns2"; then 394 lret=1 395 ret=1 396 fi 397 398 return $lret 399} 400 401test_tcp_forwarding() 402{ 403 local pmtu="$3" 404 local proto="$4" 405 local dstip="$5" 406 local dstport="$6" 407 408 test_tcp_forwarding_ip "$1" "$2" "$pmtu" "$proto" "$dstip" "$dstport" 409 410 return $? 411} 412 413test_tcp_forwarding_set_dscp() 414{ 415 local pmtu="$3" 416 local proto="$4" 417 local dstip="$5" 418 local dstport="$6" 419 420ip netns exec "$nsr1" nft -f - <<EOF 421table netdev dscpmangle { 422 chain setdscp0 { 423 type filter hook ingress device "veth0" priority 0; policy accept 424 ip dscp set cs3 425 } 426} 427EOF 428if [ $? -eq 0 ]; then 429 test_tcp_forwarding_ip "$1" "$2" "$pmtu" "$proto" "$dstip" "$dstport" 430 check_dscp "dscp_ingress" "$pmtu" 431 432 ip netns exec "$nsr1" nft delete table netdev dscpmangle 433else 434 echo "SKIP: Could not load netdev:ingress for veth0" 435fi 436 437ip netns exec "$nsr1" nft -f - <<EOF 438table netdev dscpmangle { 439 chain setdscp0 { 440 type filter hook egress device "veth1" priority 0; policy accept 441 ip dscp set cs3 442 } 443} 444EOF 445if [ $? -eq 0 ]; then 446 test_tcp_forwarding_ip "$1" "$2" "$pmtu" "$proto" "$dstip" "$dstport" 447 check_dscp "dscp_egress" "$pmtu" 448 449 ip netns exec "$nsr1" nft delete table netdev dscpmangle 450else 451 echo "SKIP: Could not load netdev:egress for veth1" 452fi 453 454 # partial. If flowtable really works, then both dscp-is-0 and dscp-is-cs3 455 # counters should have seen packets (before and after ft offload kicks in). 456 ip netns exec "$nsr1" nft -a insert rule inet filter forward ip dscp set cs3 457 test_tcp_forwarding_ip "$1" "$2" "$pmtu" "$proto" "$dstip" "$dstport" 458 check_dscp "dscp_fwd" "$pmtu" 459} 460 461test_tcp_forwarding_nat() 462{ 463 local nsa="$1" 464 local nsb="$2" 465 local pmtu="$3" 466 local what="$4" 467 local lret 468 469 [ "$pmtu" -eq 0 ] && what="$what (pmtu disabled)" 470 471 test_tcp_forwarding_ip "$nsa" "$nsb" "$pmtu" 4 10.0.2.99 12345 472 lret=$? 473 474 if [ "$lret" -eq 0 ] ; then 475 if [ "$pmtu" -eq 1 ] ;then 476 check_counters "flow offload for ns1/ns2 with masquerade $what" 477 else 478 echo "PASS: flow offload for ns1/ns2 with masquerade $what" 479 fi 480 481 test_tcp_forwarding_ip "$1" "$2" "$pmtu" 4 10.6.6.6 1666 482 lret=$? 483 if [ "$pmtu" -eq 1 ] ;then 484 check_counters "flow offload for ns1/ns2 with dnat $what" 485 elif [ "$lret" -eq 0 ] ; then 486 echo "PASS: flow offload for ns1/ns2 with dnat $what" 487 fi 488 else 489 echo "FAIL: flow offload for ns1/ns2 with dnat $what" 490 fi 491 492 return $lret 493} 494 495make_file "$nsin" "$filesize" 496make_file "$nsin_small" "$filesize_small" 497 498# First test: 499# No PMTU discovery, nsr1 is expected to fragment packets from ns1 to ns2 as needed. 500# Due to MTU mismatch in both directions, all packets (except small packets like pure 501# acks) have to be handled by normal forwarding path. Therefore, packet counters 502# are not checked. 503if test_tcp_forwarding "$ns1" "$ns2" 0 4 10.0.2.99 12345; then 504 echo "PASS: flow offloaded for ns1/ns2" 505else 506 echo "FAIL: flow offload for ns1/ns2:" 1>&2 507 ip netns exec "$nsr1" nft list ruleset 508 ret=1 509fi 510 511if test_tcp_forwarding "$ns1" "$ns2" 0 6 "[dead:2::99]" 12345; then 512 echo "PASS: IPv6 flow offloaded for ns1/ns2" 513else 514 echo "FAIL: IPv6 flow offload for ns1/ns2:" 1>&2 515 ip netns exec "$nsr1" nft list ruleset 516 ret=1 517fi 518 519# delete default route, i.e. ns2 won't be able to reach ns1 and 520# will depend on ns1 being masqueraded in nsr1. 521# expect ns1 has nsr1 address. 522ip -net "$ns2" route del default via 10.0.2.1 523ip -net "$ns2" route del default via dead:2::1 524ip -net "$ns2" route add 192.168.10.1 via 10.0.2.1 525 526# Second test: 527# Same, but with NAT enabled. Same as in first test: we expect normal forward path 528# to handle most packets. 529ip netns exec "$nsr1" nft -f - <<EOF 530table ip nat { 531 chain prerouting { 532 type nat hook prerouting priority 0; policy accept; 533 meta iif "veth0" ip daddr 10.6.6.6 tcp dport 1666 counter dnat ip to 10.0.2.99:12345 534 } 535 536 chain postrouting { 537 type nat hook postrouting priority 0; policy accept; 538 meta oifname "veth1" counter masquerade 539 } 540} 541EOF 542 543check_dscp "dscp_none" "0" 544if ! test_tcp_forwarding_set_dscp "$ns1" "$ns2" 0 4 10.0.2.99 12345; then 545 echo "FAIL: flow offload for ns1/ns2 with dscp update and no pmtu discovery" 1>&2 546 exit 0 547fi 548 549if ! test_tcp_forwarding_nat "$ns1" "$ns2" 0 ""; then 550 echo "FAIL: flow offload for ns1/ns2 with NAT" 1>&2 551 ip netns exec "$nsr1" nft list ruleset 552 ret=1 553fi 554 555# Third test: 556# Same as second test, but with PMTU discovery enabled. This 557# means that we expect the fastpath to handle packets as soon 558# as the endpoints adjust the packet size. 559ip netns exec "$ns1" sysctl net.ipv4.ip_no_pmtu_disc=0 > /dev/null 560ip netns exec "$ns2" sysctl net.ipv4.ip_no_pmtu_disc=0 > /dev/null 561 562# reset counters. 563# With pmtu in-place we'll also check that nft counters 564# are lower than file size and packets were forwarded via flowtable layer. 565# For earlier tests (large mtus), packets cannot be handled via flowtable 566# (except pure acks and other small packets). 567ip netns exec "$nsr1" nft reset counters table inet filter >/dev/null 568ip netns exec "$ns2" nft reset counters table inet filter >/dev/null 569 570if ! test_tcp_forwarding_set_dscp "$ns1" "$ns2" 1 4 10.0.2.99 12345; then 571 echo "FAIL: flow offload for ns1/ns2 with dscp update and pmtu discovery" 1>&2 572 exit 0 573fi 574 575ip netns exec "$nsr1" nft reset counters table inet filter >/dev/null 576 577if ! test_tcp_forwarding_nat "$ns1" "$ns2" 1 ""; then 578 echo "FAIL: flow offload for ns1/ns2 with NAT and pmtu discovery" 1>&2 579 ip netns exec "$nsr1" nft list ruleset 580fi 581 582# IPIP tunnel test: 583# Add IPIP tunnel interfaces and check flowtable acceleration. 584test_ipip() { 585if ! ip -net "$nsr1" link add name tun0 type ipip \ 586 local 192.168.10.1 remote 192.168.10.2 >/dev/null;then 587 echo "SKIP: could not add ipip tunnel" 588 [ "$ret" -eq 0 ] && ret=$ksft_skip 589 return 590fi 591ip -net "$nsr1" link set tun0 up 592ip -net "$nsr1" addr add 192.168.100.1/24 dev tun0 593ip netns exec "$nsr1" sysctl net.ipv4.conf.tun0.forwarding=1 > /dev/null 594 595ip -net "$nsr1" link add name tun6 type ip6tnl local fee1:2::1 remote fee1:2::2 encaplimit none 596ip -net "$nsr1" link set tun6 up 597ip -net "$nsr1" addr add fee1:3::1/64 dev tun6 nodad 598 599ip -net "$nsr2" link add name tun0 type ipip local 192.168.10.2 remote 192.168.10.1 600ip -net "$nsr2" link set tun0 up 601ip -net "$nsr2" addr add 192.168.100.2/24 dev tun0 602ip netns exec "$nsr2" sysctl net.ipv4.conf.tun0.forwarding=1 > /dev/null 603 604ip -net "$nsr2" link add name tun6 type ip6tnl local fee1:2::2 remote fee1:2::1 encaplimit none || ret=1 605ip -net "$nsr2" link set tun6 up 606ip -net "$nsr2" addr add fee1:3::2/64 dev tun6 nodad 607 608ip -net "$nsr1" route change default via 192.168.100.2 609ip -net "$nsr2" route change default via 192.168.100.1 610 611# do not use "route change" and delete old default so 612# socat fails to connect in case new default can't be added. 613ip -6 -net "$nsr1" route delete default 614ip -6 -net "$nsr1" route add default via fee1:3::2 615ip -6 -net "$nsr2" route delete default 616ip -6 -net "$nsr2" route add default via fee1:3::1 617ip -net "$ns2" route add default via 10.0.2.1 618ip -6 -net "$ns2" route add default via dead:2::1 619 620ip netns exec "$nsr1" nft -a insert rule inet filter forward \ 621 'meta oif tun0 tcp dport 12345 ct mark set 1 flow add @f1 counter name routed_orig accept' 622ip netns exec "$nsr1" nft -a insert rule inet filter forward 'meta oif tun0 accept' 623ip netns exec "$nsr1" nft -a insert rule inet filter forward \ 624 'meta oif tun6 tcp dport 12345 ct mark set 1 flow add @f1 counter name routed_orig accept' 625ip netns exec "$nsr1" nft -a insert rule inet filter forward 'meta oif tun6 accept' 626ip netns exec "$nsr1" nft -a insert rule inet filter forward \ 627 'meta oif "veth0" tcp sport 12345 ct mark set 1 flow add @f1 counter name routed_repl accept' 628 629if ! test_tcp_forwarding_nat "$ns1" "$ns2" 1 "IPIP tunnel"; then 630 echo "FAIL: flow offload for ns1/ns2 with IPIP tunnel" 1>&2 631 ip netns exec "$nsr1" nft list ruleset 632 ret=1 633fi 634 635if test_tcp_forwarding "$ns1" "$ns2" 1 6 "[dead:2::99]" 12345; then 636 check_counters "flow offload for ns1/ns2 IP6IP6 tunnel" 637else 638 echo "FAIL: flow offload for ns1/ns2 with IP6IP6 tunnel" 1>&2 639 ip netns exec "$nsr1" nft list ruleset 640 ret=1 641fi 642 643# Create vlan tagged devices for IPIP traffic. 644ip -net "$nsr1" link add link veth1 name veth1.10 type vlan id 10 645ip -net "$nsr1" link set veth1.10 up 646ip -net "$nsr1" addr add 192.168.20.1/24 dev veth1.10 647ip -net "$nsr1" addr add fee1:4::1/64 dev veth1.10 nodad 648ip netns exec "$nsr1" sysctl net.ipv4.conf.veth1/10.forwarding=1 > /dev/null 649ip netns exec "$nsr1" nft -a insert rule inet filter forward \ 650 'meta oif veth1.10 tcp dport 12345 ct mark set 1 flow add @f1 counter name routed_orig accept' 651ip netns exec "$nsr1" nft -a insert rule inet filter forward 'meta oif veth1.10 accept' 652 653ip -net "$nsr1" link add name tun0.10 type ipip local 192.168.20.1 remote 192.168.20.2 654ip -net "$nsr1" link set tun0.10 up 655ip -net "$nsr1" addr add 192.168.200.1/24 dev tun0.10 656ip -net "$nsr1" route change default via 192.168.200.2 657ip netns exec "$nsr1" sysctl net.ipv4.conf.tun0/10.forwarding=1 > /dev/null 658ip netns exec "$nsr1" nft -a insert rule inet filter forward \ 659 'meta oif tun0.10 tcp dport 12345 ct mark set 1 flow add @f1 counter name routed_orig accept' 660ip netns exec "$nsr1" nft -a insert rule inet filter forward 'meta oif tun0.10 accept' 661 662ip -net "$nsr1" link add name tun6.10 type ip6tnl local fee1:4::1 remote fee1:4::2 encaplimit none 663ip -net "$nsr1" link set tun6.10 up 664ip -net "$nsr1" addr add fee1:5::1/64 dev tun6.10 nodad 665ip -6 -net "$nsr1" route delete default 666ip -6 -net "$nsr1" route add default via fee1:5::2 667ip netns exec "$nsr1" nft -a insert rule inet filter forward \ 668 'meta oif tun6.10 tcp dport 12345 ct mark set 1 flow add @f1 counter name routed_orig accept' 669ip netns exec "$nsr1" nft -a insert rule inet filter forward 'meta oif tun6.10 accept' 670 671ip -net "$nsr2" link add link veth0 name veth0.10 type vlan id 10 672ip -net "$nsr2" link set veth0.10 up 673ip -net "$nsr2" addr add 192.168.20.2/24 dev veth0.10 674ip -net "$nsr2" addr add fee1:4::2/64 dev veth0.10 nodad 675ip netns exec "$nsr2" sysctl net.ipv4.conf.veth0/10.forwarding=1 > /dev/null 676 677ip -net "$nsr2" link add name tun0.10 type ipip local 192.168.20.2 remote 192.168.20.1 678ip -net "$nsr2" link set tun0.10 up 679ip -net "$nsr2" addr add 192.168.200.2/24 dev tun0.10 680ip -net "$nsr2" route change default via 192.168.200.1 681ip netns exec "$nsr2" sysctl net.ipv4.conf.tun0/10.forwarding=1 > /dev/null 682 683ip -net "$nsr2" link add name tun6.10 type ip6tnl local fee1:4::2 remote fee1:4::1 encaplimit none || ret=1 684ip -net "$nsr2" link set tun6.10 up 685ip -net "$nsr2" addr add fee1:5::2/64 dev tun6.10 nodad 686ip -6 -net "$nsr2" route delete default 687ip -6 -net "$nsr2" route add default via fee1:5::1 688 689if ! test_tcp_forwarding_nat "$ns1" "$ns2" 1 "IPIP tunnel over vlan"; then 690 echo "FAIL: flow offload for ns1/ns2 with IPIP tunnel over vlan" 1>&2 691 ip netns exec "$nsr1" nft list ruleset 692 ret=1 693fi 694 695if test_tcp_forwarding "$ns1" "$ns2" 1 6 "[dead:2::99]" 12345; then 696 check_counters "flow offload for ns1/ns2 IP6IP6 tunnel over vlan" 697else 698 echo "FAIL: flow offload for ns1/ns2 with IP6IP6 tunnel over vlan" 1>&2 699 ip netns exec "$nsr1" nft list ruleset 700 ret=1 701fi 702 703# Restore the previous configuration 704ip -net "$nsr1" route change default via 192.168.10.2 705ip -net "$nsr2" route change default via 192.168.10.1 706ip -net "$ns2" route del default via 10.0.2.1 707ip -6 -net "$ns2" route del default via dead:2::1 708} 709 710# Another test: 711# Add bridge interface br0 to Router1, with NAT enabled. 712test_bridge() { 713if ! ip -net "$nsr1" link add name br0 type bridge 2>/dev/null;then 714 echo "SKIP: could not add bridge br0" 715 [ "$ret" -eq 0 ] && ret=$ksft_skip 716 return 717fi 718ip -net "$nsr1" addr flush dev veth0 719ip -net "$nsr1" link set up dev veth0 720ip -net "$nsr1" link set veth0 master br0 721ip -net "$nsr1" addr add 10.0.1.1/24 dev br0 722ip -net "$nsr1" addr add dead:1::1/64 dev br0 nodad 723ip -net "$nsr1" link set up dev br0 724 725ip netns exec "$nsr1" sysctl net.ipv4.conf.br0.forwarding=1 > /dev/null 726 727# br0 with NAT enabled. 728ip netns exec "$nsr1" nft -f - <<EOF 729flush table ip nat 730table ip nat { 731 chain prerouting { 732 type nat hook prerouting priority 0; policy accept; 733 meta iif "br0" ip daddr 10.6.6.6 tcp dport 1666 counter dnat ip to 10.0.2.99:12345 734 } 735 736 chain postrouting { 737 type nat hook postrouting priority 0; policy accept; 738 meta oifname "veth1" counter masquerade 739 } 740} 741EOF 742 743if ! test_tcp_forwarding_nat "$ns1" "$ns2" 1 "on bridge"; then 744 echo "FAIL: flow offload for ns1/ns2 with bridge NAT" 1>&2 745 ip netns exec "$nsr1" nft list ruleset 746 ret=1 747fi 748 749if ip -net "$nsr1" link show tun0 > /dev/null 2>&1 && 750 ip -net "$nsr2" link show tun0 > /dev/null 2>&1; then 751 ip -net "$nsr1" route change default via 192.168.100.2 752 ip -net "$nsr2" route change default via 192.168.100.1 753 ip -6 -net "$nsr1" route delete default 754 ip -6 -net "$nsr1" route add default via fee1:3::2 755 ip -6 -net "$nsr2" route delete default 756 ip -6 -net "$nsr2" route add default via fee1:3::1 757 ip -net "$ns2" route add default via 10.0.2.1 758 ip -6 -net "$ns2" route add default via dead:2::1 759 760 ip netns exec "$nsr1" nft -a insert rule inet filter forward \ 761 'meta oif "tun0" tcp dport 12345 ct mark set 1 flow add @f1 counter name routed_orig accept' 762 ip netns exec "$nsr1" nft -a insert rule inet filter forward \ 763 'meta oif "tun6" tcp dport 12345 ct mark set 1 flow add @f1 counter name routed_orig accept' 764 ip netns exec "$nsr1" nft -a insert rule inet filter forward \ 765 'meta oif "veth0" tcp sport 12345 ct mark set 1 flow add @f1 counter name routed_repl accept' 766 ip netns exec "$nsr1" nft -a insert rule inet filter forward \ 767 'meta oif "br0" tcp sport 12345 ct mark set 1 flow add @f1 counter name routed_repl accept' 768 ip netns exec "$nsr1" nft -a insert rule inet filter forward \ 769 'meta oif "tun0" accept' 770 ip netns exec "$nsr1" nft -a insert rule inet filter forward \ 771 'meta oif "tun6" accept' 772 773 ip netns exec "$nsr1" nft reset counters table inet filter >/dev/null 774 775 if test_tcp_forwarding "$ns1" "$ns2" 1 4 10.0.2.99 12345; then 776 check_counters "bridge + IPIP tunnel" 777 else 778 echo "FAIL: flow offload for ns1/ns2 with bridge + IPIP tunnel" 1>&2 779 ip netns exec "$nsr1" nft list ruleset 780 ret=1 781 fi 782 783 if test_tcp_forwarding "$ns1" "$ns2" 1 6 "[dead:2::99]" 12345; then 784 check_counters "bridge + IP6IP6 tunnel" 785 else 786 echo "FAIL: flow offload for ns1/ns2 with bridge + IP6IP6 tunnel" 1>&2 787 ip netns exec "$nsr1" nft list ruleset 788 ret=1 789 fi 790 791 ip -net "$nsr1" route change default via 192.168.10.2 792 ip -net "$nsr2" route change default via 192.168.10.1 793 ip -net "$ns2" route del default via 10.0.2.1 794 ip -6 -net "$nsr1" route delete default 795 ip -6 -net "$nsr1" route add default via fee1:2::2 796 ip -6 -net "$nsr2" route delete default 797 ip -6 -net "$nsr2" route add default via fee1:2::1 798 ip -6 -net "$ns2" route del default via dead:2::1 799else 800 echo "SKIP: bridge + tunnel flowtable regression (tun0 missing)" 801 [ "$ret" -eq 0 ] && ret=$ksft_skip 802fi 803 804 805# Another test: 806# Add bridge interface br0 to Router1, with NAT and VLAN. 807ip -net "$nsr1" link set veth0 nomaster 808ip -net "$nsr1" link set down dev veth0 809ip -net "$nsr1" link add link veth0 name veth0.10 type vlan id 10 810ip -net "$nsr1" link set up dev veth0 811ip -net "$nsr1" link set up dev veth0.10 812ip -net "$nsr1" link set veth0.10 master br0 813 814ip -net "$ns1" addr flush dev eth0 815ip -net "$ns1" link add link eth0 name eth0.10 type vlan id 10 816ip -net "$ns1" link set eth0 up 817ip -net "$ns1" link set eth0.10 up 818ip -net "$ns1" addr add 10.0.1.99/24 dev eth0.10 819ip -net "$ns1" route add default via 10.0.1.1 820ip -net "$ns1" addr add dead:1::99/64 dev eth0.10 nodad 821 822if ! test_tcp_forwarding_nat "$ns1" "$ns2" 1 "bridge and VLAN"; then 823 echo "FAIL: flow offload for ns1/ns2 with bridge NAT and VLAN" 1>&2 824 ip netns exec "$nsr1" nft list ruleset 825 ret=1 826fi 827 828# restore test topology (remove bridge and VLAN) 829ip -net "$nsr1" link set veth0 nomaster 830ip -net "$nsr1" link set veth0 down 831ip -net "$nsr1" link set veth0.10 down 832ip -net "$nsr1" link delete veth0.10 type vlan 833ip -net "$nsr1" link delete br0 type bridge 834ip -net "$ns1" addr flush dev eth0.10 835ip -net "$ns1" link set eth0.10 down 836ip -net "$ns1" link set eth0 down 837ip -net "$ns1" link delete eth0.10 type vlan 838 839# restore address in ns1 and nsr1 840ip -net "$ns1" link set eth0 up 841ip -net "$ns1" addr add 10.0.1.99/24 dev eth0 842ip -net "$ns1" route add default via 10.0.1.1 843ip -net "$ns1" addr add dead:1::99/64 dev eth0 nodad 844ip -net "$ns1" route add default via dead:1::1 845ip -net "$nsr1" addr add 10.0.1.1/24 dev veth0 846ip -net "$nsr1" addr add dead:1::1/64 dev veth0 nodad 847ip -net "$nsr1" link set up dev veth0 848} 849 850test_ipip 851 852test_bridge 853 854KEY_SHA="0x"$(ps -af | sha1sum | cut -d " " -f 1) 855KEY_AES="0x"$(ps -af | md5sum | cut -d " " -f 1) 856SPI1=$RANDOM 857SPI2=$RANDOM 858 859if [ $SPI1 -eq $SPI2 ]; then 860 SPI2=$((SPI2+1)) 861fi 862 863do_esp() { 864 local ns=$1 865 local me=$2 866 local remote=$3 867 local lnet=$4 868 local rnet=$5 869 local spi_out=$6 870 local spi_in=$7 871 872 ip -net "$ns" xfrm state add src "$remote" dst "$me" proto esp spi "$spi_in" enc aes "$KEY_AES" auth sha1 "$KEY_SHA" mode tunnel sel src "$rnet" dst "$lnet" 873 ip -net "$ns" xfrm state add src "$me" dst "$remote" proto esp spi "$spi_out" enc aes "$KEY_AES" auth sha1 "$KEY_SHA" mode tunnel sel src "$lnet" dst "$rnet" 874 875 # to encrypt packets as they go out (includes forwarded packets that need encapsulation) 876 ip -net "$ns" xfrm policy add src "$lnet" dst "$rnet" dir out tmpl src "$me" dst "$remote" proto esp mode tunnel priority 1 action allow 877 # to fwd decrypted packets after esp processing: 878 ip -net "$ns" xfrm policy add src "$rnet" dst "$lnet" dir fwd tmpl src "$remote" dst "$me" proto esp mode tunnel priority 1 action allow 879} 880 881do_esp "$nsr1" 192.168.10.1 192.168.10.2 10.0.1.0/24 10.0.2.0/24 "$SPI1" "$SPI2" 882 883do_esp "$nsr2" 192.168.10.2 192.168.10.1 10.0.2.0/24 10.0.1.0/24 "$SPI2" "$SPI1" 884 885ip netns exec "$nsr1" nft delete table ip nat 886 887# restore default routes 888ip -net "$ns2" route del 192.168.10.1 via 10.0.2.1 889ip -net "$ns2" route add default via 10.0.2.1 890ip -net "$ns2" route add default via dead:2::1 891 892if test_tcp_forwarding "$ns1" "$ns2" 1 4 10.0.2.99 12345; then 893 check_counters "ipsec tunnel mode for ns1/ns2" 894else 895 echo "FAIL: ipsec tunnel mode for ns1/ns2" 896 ip netns exec "$nsr1" nft list ruleset 1>&2 897 ip netns exec "$nsr1" cat /proc/net/xfrm_stat 1>&2 898fi 899 900if test_tcp_forwarding "$ns1" "$ns2" 1 6 "[dead:2::99]" 12345; then 901 check_counters "IPv6 ipsec tunnel mode for ns1/ns2" 902else 903 echo "FAIL: IPv6 ipsec tunnel mode for ns1/ns2" 904 ip netns exec "$nsr1" nft list ruleset 1>&2 905 ip netns exec "$nsr1" cat /proc/net/xfrm_stat 1>&2 906fi 907 908if [ "$1" = "" ]; then 909 low=1280 910 mtu=$((65536 - low)) 911 o=$(((RANDOM%mtu) + low)) 912 l=$(((RANDOM%mtu) + low)) 913 r=$(((RANDOM%mtu) + low)) 914 915 MINSIZE=$((2 * 1000 * 1000)) 916 MAXSIZE=$((64 * 1000 * 1000)) 917 918 filesize=$(((RANDOM * RANDOM) % MAXSIZE)) 919 if [ "$filesize" -lt "$MINSIZE" ]; then 920 filesize=$((filesize+MINSIZE)) 921 fi 922 923 echo "re-run with random mtus and file size: -o $o -l $l -r $r -s $filesize" 924 $0 -o "$o" -l "$l" -r "$r" -s "$filesize" || ret=1 925fi 926 927exit $ret 928