diff options
Diffstat (limited to 'tools/testing/selftests/net/openvswitch/openvswitch.sh')
| -rwxr-xr-x | tools/testing/selftests/net/openvswitch/openvswitch.sh | 292 |
1 files changed, 290 insertions, 2 deletions
diff --git a/tools/testing/selftests/net/openvswitch/openvswitch.sh b/tools/testing/selftests/net/openvswitch/openvswitch.sh index 3cdd953f6813..2954245129a2 100755 --- a/tools/testing/selftests/net/openvswitch/openvswitch.sh +++ b/tools/testing/selftests/net/openvswitch/openvswitch.sh @@ -28,6 +28,10 @@ tests=" tunnel_metadata ovs: test extraction of tunnel metadata tunnel_refcount ovs: test tunnel vport reference cleanup drop_reason drop: test drop reasons are emitted + pop_vlan vlan: POP_VLAN action strips tag + dec_ttl ttl: dec_ttl decrements IP TTL + flow_set flow-set: Flow modify + action_set set: SET action rewrites fields psample psample: Sampling packets with psample" info() { @@ -191,6 +195,23 @@ ovs_add_flow () { return 0 } +ovs_mod_flow () { + if [ -n "$4" ]; then + info "Modifying flow: sbx:$1 br:$2 flow:$3 act:$4" + ovs_sbx "$1" python3 $ovs_base/ovs-dpctl.py \ + mod-flow "$2" "$3" "$4" + else + info "Modifying flow (no actions): sbx:$1 br:$2 flow:$3" + ovs_sbx "$1" python3 $ovs_base/ovs-dpctl.py \ + mod-flow "$2" "$3" + fi + if [ $? -ne 0 ]; then + info "Flow modify [ $3 ] failed" + return 1 + fi + return 0 +} + ovs_del_flows () { info "Deleting all flows from DP: sbx:$1 br:$2" ovs_sbx "$1" python3 $ovs_base/ovs-dpctl.py del-flows "$2" @@ -244,6 +265,184 @@ usage() { } +test_dec_ttl() { + sbx_add "test_dec_ttl" || return $? + ovs_add_dp "test_dec_ttl" decttl || return 1 + + info "create namespaces" + for ns in client server; do + ovs_add_netns_and_veths "test_dec_ttl" "decttl" "$ns" \ + "${ns:0:1}0" "${ns:0:1}1" || return 1 + done + + ip netns exec client ip addr add 10.0.0.1/24 dev c1 + ip netns exec client ip link set c1 up + ip netns exec server ip addr add 10.0.0.2/24 dev s1 + ip netns exec server ip link set s1 up + + # Probe: check if kernel supports dec_ttl action. + ovs_add_flow "test_dec_ttl" decttl \ + 'in_port(1),eth(),eth_type(0x0800),ipv4()' \ + 'dec_ttl(le_1())' &>/dev/null + if [ $? -ne 0 ]; then + info "no support for dec_ttl - skipping" + ovs_exit_sig + return $ksft_skip + fi + + ovs_del_flows "test_dec_ttl" decttl + + # ARP flows (bidirectional) + ovs_add_flow "test_dec_ttl" decttl \ + 'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1 + ovs_add_flow "test_dec_ttl" decttl \ + 'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1 + + # IP flows with dec_ttl action + ovs_add_flow "test_dec_ttl" decttl \ + 'in_port(1),eth(),eth_type(0x0800),ipv4()' \ + 'dec_ttl(le_1()),2' || return 1 + ovs_add_flow "test_dec_ttl" decttl \ + 'in_port(2),eth(),eth_type(0x0800),ipv4()' \ + 'dec_ttl(le_1()),1' || return 1 + + info "verify connectivity with dec_ttl" + ovs_sbx "test_dec_ttl" ip netns exec client ping -c 1 -W 2 \ + 10.0.0.2 || return 1 + + info "verify TTL=1 is dropped by dec_ttl" + ovs_sbx "test_dec_ttl" ip netns exec client ping -c 1 -W 2 \ + -t 1 10.0.0.2 >/dev/null 2>&1 \ + && { info "FAIL: ping should fail with TTL=1 and dec_ttl" + return 1; } + + return 0 +} + +test_flow_set() { + sbx_add "test_flow_set" || return $? + ovs_add_dp "test_flow_set" flowset || return 1 + + info "create namespaces" + for ns in client server; do + ovs_add_netns_and_veths "test_flow_set" "flowset" "$ns" \ + "${ns:0:1}0" "${ns:0:1}1" || return 1 + done + + ip netns exec client ip addr add 10.0.0.1/24 dev c1 + ip netns exec client ip link set c1 up + ip netns exec server ip addr add 10.0.0.2/24 dev s1 + ip netns exec server ip link set s1 up + + ovs_add_flow "test_flow_set" flowset \ + 'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1 + ovs_add_flow "test_flow_set" flowset \ + 'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1 + + local fwd_flow="ufid:00000001-0002-0003-0004-000500060007" + fwd_flow="$fwd_flow,in_port(1),eth(),eth_type(0x0800),ipv4()" + + ovs_add_flow "test_flow_set" flowset "$fwd_flow" '2' \ + || return 1 + ovs_add_flow "test_flow_set" flowset \ + 'in_port(2),eth(),eth_type(0x0800),ipv4()' '1' || return 1 + + info "verify initial forwarding" + ovs_sbx "test_flow_set" ip netns exec client ping -c 1 -W 2 \ + 10.0.0.2 || return 1 + + info "mod-flow with new actions (change to drop)" + ovs_mod_flow "test_flow_set" flowset "$fwd_flow" 'drop' \ + || return 1 + + info "verify traffic is now dropped" + ovs_sbx "test_flow_set" ip netns exec client ping -c 1 -W 2 \ + 10.0.0.2 >/dev/null 2>&1 \ + && { info "FAIL: ping should fail after mod-flow to drop" + return 1; } + + info "mod-flow without actions" + ovs_mod_flow "test_flow_set" flowset "$fwd_flow" || return 1 + + info "verify flow retained drop action via dump" + python3 "$ovs_base/ovs-dpctl.py" dump-flows flowset \ + | grep -q "actions:drop" || \ + { info "FAIL: flow not showing drop action"; return 1; } + + info "verify drop actions unchanged" + ovs_sbx "test_flow_set" ip netns exec client ping -c 1 -W 2 \ + 10.0.0.2 >/dev/null 2>&1 \ + && { info "FAIL: ping should still fail after no-actions set" + return 1; } + + return 0 +} + +test_action_set() { + sbx_add "test_action_set" || return $? + ovs_add_dp "test_action_set" settest || return 1 + + info "create namespaces" + for ns in client server; do + ovs_add_netns_and_veths "test_action_set" "settest" "$ns" \ + "${ns:0:1}0" "${ns:0:1}1" || return 1 + done + + ip netns exec client ip addr add 10.0.0.1/24 dev c1 + ip netns exec client ip link set c1 up + ip netns exec server ip addr add 10.0.0.2/24 dev s1 + ip netns exec server ip link set s1 up + + ovs_add_flow "test_action_set" settest \ + 'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1 + ovs_add_flow "test_action_set" settest \ + 'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1 + + ovs_add_flow "test_action_set" settest \ + 'in_port(1),eth(),eth_type(0x0800),ipv4()' '2' || return 1 + ovs_add_flow "test_action_set" settest \ + 'in_port(2),eth(),eth_type(0x0800),ipv4()' '1' || return 1 + + info "verify connectivity without SET" + ovs_sbx "test_action_set" ip netns exec client ping -c 1 -W 2 \ + 10.0.0.2 || return 1 + + ovs_del_flows "test_action_set" settest + ovs_add_flow "test_action_set" settest \ + 'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1 + ovs_add_flow "test_action_set" settest \ + 'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1 + + info "set ipv4 dst to unreachable address" + ovs_add_flow "test_action_set" settest \ + 'in_port(1),eth(),eth_type(0x0800),ipv4()' \ + 'set(ipv4(dst=10.0.0.99)),2' || return 1 + ovs_add_flow "test_action_set" settest \ + 'in_port(2),eth(),eth_type(0x0800),ipv4()' '1' || return 1 + + info "verify ping fails with rewritten dst" + ovs_sbx "test_action_set" ip netns exec client ping -c 1 -W 2 \ + 10.0.0.2 >/dev/null 2>&1 \ + && { info "FAIL: ping should fail with dst rewritten" + return 1; } + + ovs_del_flows "test_action_set" settest + ovs_add_flow "test_action_set" settest \ + 'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1 + ovs_add_flow "test_action_set" settest \ + 'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1 + ovs_add_flow "test_action_set" settest \ + 'in_port(1),eth(),eth_type(0x0800),ipv4()' '2' || return 1 + ovs_add_flow "test_action_set" settest \ + 'in_port(2),eth(),eth_type(0x0800),ipv4()' '1' || return 1 + + info "verify connectivity restored without SET" + ovs_sbx "test_action_set" ip netns exec client ping -c 1 -W 2 \ + 10.0.0.2 || return 1 + + return 0 +} + # psample test # - use psample to observe packets test_psample() { @@ -304,6 +503,8 @@ test_psample() { # sFlow / IPFIX. nlpid=$(grep -E "listening on upcall packet handler" \ $ovs_dir/s0.out | cut -d ":" -f 2 | tr -d ' ') + [ -z "$nlpid" ] && \ + { info "failed to get upcall PID"; return 1; } ovs_add_flow "test_psample" psample \ "in_port(2),eth(),eth_type(0x0800),ipv4()" \ @@ -337,6 +538,10 @@ test_drop_reason() { ovs_drop_subsys=$(pahole -C skb_drop_reason_subsys | awk '/OPENVSWITCH/ { print $3; }' | tr -d ,) + if [ -z "$ovs_drop_subsys" ]; then + info "failed to get OVS drop subsys ID" + return $ksft_skip + fi sbx_add "test_drop_reason" || return $? @@ -435,13 +640,19 @@ test_arp_ping () { # Setup client namespace ip netns exec client ip addr add 172.31.110.10/24 dev c1 ip netns exec client ip link set c1 up - HW_CLIENT=`ip netns exec client ip link show dev c1 | grep -E 'link/ether [0-9a-f:]+' | awk '{print $2;}'` + HW_CLIENT=$(ip netns exec client ip link show dev c1 \ + | awk '/link\/ether/ {print $2}') + [ -z "$HW_CLIENT" ] && \ + { info "failed to get client hwaddr"; return 1; } info "Client hwaddr: $HW_CLIENT" # Setup server namespace ip netns exec server ip addr add 172.31.110.20/24 dev s1 ip netns exec server ip link set s1 up - HW_SERVER=`ip netns exec server ip link show dev s1 | grep -E 'link/ether [0-9a-f:]+' | awk '{print $2;}'` + HW_SERVER=$(ip netns exec server ip link show dev s1 \ + | awk '/link\/ether/ {print $2}') + [ -z "$HW_SERVER" ] && \ + { info "failed to get server hwaddr"; return 1; } info "Server hwaddr: $HW_SERVER" ovs_add_flow "test_arp_ping" arpping \ @@ -864,6 +1075,83 @@ test_tunnel_refcount() { ovs_wait dev_removed dp-${tun_type} || return 1 ovs_wait dev_removed ovs-${tun_type}0 || return 1 done + + return 0 +} + +test_pop_vlan() { + local sbx="test_pop_vlan" + sbx_add "$sbx" || return $? + ovs_add_dp "$sbx" vlandp || return 1 + + ovs_add_netns_and_veths "$sbx" vlandp \ + ns1 veth1 ns1veth 192.0.2.1/24 || return 1 + ovs_add_netns_and_veths "$sbx" vlandp \ + ns2 veth2 ns2veth 192.0.2.2/24 || return 1 + + # Baseline: untagged bidirectional forwarding + ovs_add_flow "$sbx" vlandp \ + 'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1 + ovs_add_flow "$sbx" vlandp \ + 'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1 + ovs_add_flow "$sbx" vlandp \ + 'in_port(1),eth(),eth_type(0x0800),ipv4()' '2' || return 1 + ovs_add_flow "$sbx" vlandp \ + 'in_port(2),eth(),eth_type(0x0800),ipv4()' '1' || return 1 + ovs_sbx "$sbx" ip netns exec ns1 ping -c 3 -W 2 \ + 192.0.2.2 || return 1 + + # VLAN topology: ns1 uses VLAN sub-interface, ns2 is plain + ip -n ns1 link add link ns1veth name ns1veth.10 \ + type vlan id 10 || return 1 + on_exit "ip -n ns1 link del ns1veth.10 2>/dev/null" + ip -n ns1 addr add 198.51.100.1/24 dev ns1veth.10 || return 1 + ip -n ns1 link set ns1veth.10 up || return 1 + ip -n ns2 addr add 198.51.100.2/24 dev ns2veth || return 1 + + ovs_del_flows "$sbx" vlandp + + # Static ARP: avoids VLAN-tagged ARP complexity + local ns1veth10mac ns2mac + ns1veth10mac=$(ip -n ns1 link show ns1veth.10 \ + | awk '/link\/ether/ {print $2}') + [ -z "$ns1veth10mac" ] && \ + { info "failed to get ns1veth10mac"; return 1; } + ns2mac=$(ip -n ns2 link show ns2veth \ + | awk '/link\/ether/ {print $2}') + [ -z "$ns2mac" ] && \ + { info "failed to get ns2mac"; return 1; } + ip -n ns1 neigh replace 198.51.100.2 lladdr "$ns2mac" \ + dev ns1veth.10 nud permanent || return 1 + ip -n ns2 neigh replace 198.51.100.1 \ + lladdr "$ns1veth10mac" \ + dev ns2veth nud permanent || return 1 + + local vlan_match='in_port(1),eth(),eth_type(0x8100),' + vlan_match+='vlan(vid=10),' + vlan_match+='encap(eth_type(0x0800),' + vlan_match+='ipv4(src=198.51.100.1,proto=1),icmp())' + + # Negative: forward without pop_vlan -- tagged frame + # is invisible to ns2 (no VLAN sub-interface), ping fails + ovs_add_flow "$sbx" vlandp "$vlan_match" '2' || return 1 + ovs_sbx "$sbx" ip netns exec ns1 ping -I ns1veth.10 \ + -c 3 -W 1 198.51.100.2 >/dev/null 2>&1 \ + && { info "FAIL: ping should fail without pop_vlan" + return 1; } + + ovs_del_flows "$sbx" vlandp + + # Positive: pop_vlan strips tag on forward path, + # push_vlan restores tag on return path -- ping succeeds + ovs_add_flow "$sbx" vlandp \ + "$vlan_match" 'pop_vlan,2' || return 1 + ovs_add_flow "$sbx" vlandp \ + 'in_port(2),eth(),eth_type(0x0800),ipv4()' \ + 'push_vlan(vid=10,pcp=0,tpid=0x8100),1' || return 1 + ovs_sbx "$sbx" ip netns exec ns1 ping -I ns1veth.10 \ + -c 3 -W 2 198.51.100.2 || return 1 + return 0 } |
