One of the nice things about network namespaces is that they allow one to easily create and test complex environments.
Unfortunately, these namespaces can not be used with actual switching ASICs, as their ports can not be migrated to other network namespaces (NETIF_F_NETNS_LOCAL) and most of them probably do not support the L1-separation provided by namespaces.
However, a similar kind of flexibility can be achieved by using VRFs and by looping the switch ports together. For example:
br0 + vrf-h1 | vrf-h2 + +---+----+ + | | | | 192.0.2.1/24 + + + + 192.0.2.2/24 swp1 swp2 swp3 swp4 + + + + | | | | +--------+ +--------+
The VRFs act as lightweight namespaces representing hosts connected to the switch.
This approach for testing switch ASICs has several advantages over the traditional method that requires multiple physical machines, to name a few:
1. Only the device under test (DUT) is being tested without noise from other system.
2. Ability to easily provision complex topologies. Testing bridging between 4-ports LAGs or 8-way ECMP requires many physical links that are not always available. With the VRF-based approach one merely needs to loopback more ports.
These tests are written with switch ASICs in mind, but they can be run on any Linux box using veth pairs to emulate physical loopbacks.
Feedback is is welcome. Particularly regarding the best location for these tests (e.g., current location, tools/testing/selftests/net).
Thanks.
Ido Schimmel (7): selftests: forwarding: Add initial testing framework selftests: forwarding: Add a test for FDB learning selftests: forwarding: Add a test for flooded traffic selftests: forwarding: Add a test for basic IPv4 and IPv6 routing selftests: forwarding: Create test topology for multipath routing selftests: forwarding: Test IPv4 weighted nexthops selftests: forwarding: Test IPv6 weighted nexthops
Jiri Pirko (5): selftests: forwarding: Add tc offload check helper selftests: forwarding: Add MAC get helper selftests: forwarding: Allow to get netdev interfaces names from commandline selftests: forwarding: Allow to pass commandline options selftests: forwarding: Introduce tc flower matching tests
tools/testing/selftests/Makefile | 1 + tools/testing/selftests/forwarding/.gitignore | 1 + tools/testing/selftests/forwarding/Makefile | 6 + tools/testing/selftests/forwarding/README | 56 +++ tools/testing/selftests/forwarding/bridge.sh | 117 +++++++ tools/testing/selftests/forwarding/config | 12 + .../selftests/forwarding/forwarding.config.sample | 19 + tools/testing/selftests/forwarding/lib.sh | 383 +++++++++++++++++++++ tools/testing/selftests/forwarding/router.sh | 131 +++++++ .../selftests/forwarding/router_multipath.sh | 321 +++++++++++++++++ tools/testing/selftests/forwarding/tc_flower.sh | 261 ++++++++++++++ 11 files changed, 1308 insertions(+) create mode 100644 tools/testing/selftests/forwarding/.gitignore create mode 100644 tools/testing/selftests/forwarding/Makefile create mode 100644 tools/testing/selftests/forwarding/README create mode 100755 tools/testing/selftests/forwarding/bridge.sh create mode 100644 tools/testing/selftests/forwarding/config create mode 100644 tools/testing/selftests/forwarding/forwarding.config.sample create mode 100644 tools/testing/selftests/forwarding/lib.sh create mode 100755 tools/testing/selftests/forwarding/router.sh create mode 100755 tools/testing/selftests/forwarding/router_multipath.sh create mode 100755 tools/testing/selftests/forwarding/tc_flower.sh
Add initial framework to test packet forwarding functionality. The tests can run on actual devices using loop-backed cables or using veth pairs.
Signed-off-by: Jiri Pirko jiri@mellanox.com Signed-off-by: Ido Schimmel idosch@mellanox.com --- tools/testing/selftests/Makefile | 1 + tools/testing/selftests/forwarding/.gitignore | 1 + tools/testing/selftests/forwarding/Makefile | 6 + tools/testing/selftests/forwarding/README | 56 +++++++ tools/testing/selftests/forwarding/bridge.sh | 111 +++++++++++++ tools/testing/selftests/forwarding/config | 12 ++ .../selftests/forwarding/forwarding.config.sample | 19 +++ tools/testing/selftests/forwarding/lib.sh | 175 +++++++++++++++++++++ 8 files changed, 381 insertions(+) create mode 100644 tools/testing/selftests/forwarding/.gitignore create mode 100644 tools/testing/selftests/forwarding/Makefile create mode 100644 tools/testing/selftests/forwarding/README create mode 100755 tools/testing/selftests/forwarding/bridge.sh create mode 100644 tools/testing/selftests/forwarding/config create mode 100644 tools/testing/selftests/forwarding/forwarding.config.sample create mode 100644 tools/testing/selftests/forwarding/lib.sh
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index eaf599dc2137..77b34d093a86 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile @@ -8,6 +8,7 @@ TARGETS += cpu-hotplug TARGETS += efivarfs TARGETS += exec TARGETS += firmware +TARGETS += forwarding TARGETS += ftrace TARGETS += futex TARGETS += gpio diff --git a/tools/testing/selftests/forwarding/.gitignore b/tools/testing/selftests/forwarding/.gitignore new file mode 100644 index 000000000000..a793eef5b876 --- /dev/null +++ b/tools/testing/selftests/forwarding/.gitignore @@ -0,0 +1 @@ +forwarding.config diff --git a/tools/testing/selftests/forwarding/Makefile b/tools/testing/selftests/forwarding/Makefile new file mode 100644 index 000000000000..ef9380c49123 --- /dev/null +++ b/tools/testing/selftests/forwarding/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0 +# Makefile for forwarding selftests + +TEST_PROGS := bridge.sh + +include ../lib.mk diff --git a/tools/testing/selftests/forwarding/README b/tools/testing/selftests/forwarding/README new file mode 100644 index 000000000000..4a0964c42860 --- /dev/null +++ b/tools/testing/selftests/forwarding/README @@ -0,0 +1,56 @@ +Motivation +========== + +One of the nice things about network namespaces is that they allow one +to easily create and test complex environments. + +Unfortunately, these namespaces can not be used with actual switching +ASICs, as their ports can not be migrated to other network namespaces +(NETIF_F_NETNS_LOCAL) and most of them probably do not support the +L1-separation provided by namespaces. + +However, a similar kind of flexibility can be achieved by using VRFs and +by looping the switch ports together. For example: + + br0 + + + vrf-h1 | vrf-h2 + + +---+----+ + + | | | | + 192.0.2.1/24 + + + + 192.0.2.2/24 + swp1 swp2 swp3 swp4 + + + + + + | | | | + +--------+ +--------+ + +The VRFs act as lightweight namespaces representing hosts connected to +the switch. + +This approach for testing switch ASICs has several advantages over the +traditional method that requires multiple physical machines, to name a +few: + +1. Only the device under test (DUT) is being tested without noise from +other system. + +2. Ability to easily provision complex topologies. Testing bridging +between 4-ports LAGs or 8-way ECMP requires many physical links that are +not always available. With the VRF-based approach one merely needs to +loopback more ports. + +These tests are written with switch ASICs in mind, but they can be run +on any Linux box using veth pairs to emulate physical loopbacks. + +Guidelines for Writing Tests +============================ + +o Where possible, reuse an existing topology for different tests instead + of recreating the same topology. +o Where possible, IPv6 and IPv4 addresses shall conform to RFC 3849 and + RFC 5737, respectively. +o Where possible, tests shall be written so that they can be reused by + multiple topologies and added to lib.sh. +o Checks shall be added to lib.sh for any external dependencies. +o Code shall be checked using ShellCheck [1] prior to submission. + +1. https://www.shellcheck.net/ diff --git a/tools/testing/selftests/forwarding/bridge.sh b/tools/testing/selftests/forwarding/bridge.sh new file mode 100755 index 000000000000..c53086c53b37 --- /dev/null +++ b/tools/testing/selftests/forwarding/bridge.sh @@ -0,0 +1,111 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +NUM_NETIFS=4 +source lib.sh + +h1_create() +{ + vrf_create "vrf-h1" 1 + ip link set dev $h1 master vrf-h1 + + ip link set dev vrf-h1 up + ip link set dev $h1 up + + ip address add 192.0.2.1/24 dev $h1 + ip address add 2001:db8:1::1/64 dev $h1 +} + +h1_destroy() +{ + ip address del 2001:db8:1::1/64 dev $h1 + ip address del 192.0.2.1/24 dev $h1 + + ip link set dev $h1 down + vrf_destroy "vrf-h1" 1 +} + +h2_create() +{ + vrf_create "vrf-h2" 2 + ip link set dev $h2 master vrf-h2 + + ip link set dev vrf-h2 up + ip link set dev $h2 up + + ip address add 192.0.2.2/24 dev $h2 + ip address add 2001:db8:1::2/64 dev $h2 +} + +h2_destroy() +{ + ip address del 2001:db8:1::2/64 dev $h2 + ip address del 192.0.2.2/24 dev $h2 + + ip link set dev $h2 down + vrf_destroy "vrf-h2" 2 +} + +bridge_create() +{ + ip link add dev br0 type bridge vlan_filtering 1 mcast_snooping 0 + + ip link set dev $swp1 master br0 + ip link set dev $swp2 master br0 + + ip link set dev br0 up + ip link set dev $swp1 up + ip link set dev $swp2 up +} + +bridge_destroy() +{ + ip link set dev $swp2 down + ip link set dev $swp1 down + + ip link del dev br0 +} + +setup_prepare() +{ + h1=${NETIFS[p1]} + swp1=${NETIFS[p2]} + + swp2=${NETIFS[p3]} + h2=${NETIFS[p4]} + + netifs_arr=($h1 $swp1 $swp2 $h2) + + vrf_prepare + + h1_create + h2_create + + bridge_create +} + +cleanup() +{ + bridge_destroy + + h2_destroy + h1_destroy + + vrf_cleanup +} + +trap cleanup EXIT + +setup_prepare +setup_wait + +ping_test "vrf-h1" 192.0.2.2 +ping_test "vrf-h1" 2001:db8:1::2 + +old_mtu=$(mtu_get $h1) +mtu_change 9000 "${netifs_arr[@]}" +ping_test "vrf-h1" 192.0.2.2 +ping_test "vrf-h1" 2001:db8:1::2 +mtu_change $old_mtu "${netifs_arr[@]}" + +exit $EXIT_STATUS diff --git a/tools/testing/selftests/forwarding/config b/tools/testing/selftests/forwarding/config new file mode 100644 index 000000000000..5cd2aed97958 --- /dev/null +++ b/tools/testing/selftests/forwarding/config @@ -0,0 +1,12 @@ +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_BRIDGE_VLAN_FILTERING=y +CONFIG_NET_L3_MASTER_DEV=y +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_NET_VRF=m +CONFIG_BPF_SYSCALL=y +CONFIG_CGROUP_BPF=y +CONFIG_NET_CLS_FLOWER=m +CONFIG_NET_SCH_INGRESS=m +CONFIG_NET_ACT_GACT=m +CONFIG_VETH=m diff --git a/tools/testing/selftests/forwarding/forwarding.config.sample b/tools/testing/selftests/forwarding/forwarding.config.sample new file mode 100644 index 000000000000..f2b14814e4ba --- /dev/null +++ b/tools/testing/selftests/forwarding/forwarding.config.sample @@ -0,0 +1,19 @@ +#!/bin/bash + +# Topology description. p1 looped back to p2, p3 to p4 and so on. +declare -A NETIFS + +NETIFS[p1]=veth0 +NETIFS[p2]=veth1 +NETIFS[p3]=veth2 +NETIFS[p4]=veth3 +NETIFS[p5]=veth4 +NETIFS[p6]=veth5 +NETIFS[p7]=veth6 +NETIFS[p8]=veth7 + +# Various configuration options applicable to the testing framework. +declare -A OPTIONS + +# Time to wait after interfaces participating in the test are all UP. +OPTIONS[wait_time]=5 diff --git a/tools/testing/selftests/forwarding/lib.sh b/tools/testing/selftests/forwarding/lib.sh new file mode 100644 index 000000000000..bb423371f4de --- /dev/null +++ b/tools/testing/selftests/forwarding/lib.sh @@ -0,0 +1,175 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +if [[ "$(id -u)" -ne 0 ]]; then + echo "SKIP: need root privileges" + exit 0 +fi + +if [[ ! -f forwarding.config ]]; then + echo "SKIP: could not find configuration file" + exit 0 +fi + +tc -j &> /dev/null +if [[ $? -ne 0 ]]; then + echo "SKIP: iproute2 too old, missing JSON support" + exit 0 +fi + +if [[ ! -x "$(command -v jq)" ]]; then + echo "SKIP: jq not installed" + exit 0 +fi + +if [[ ! -v NUM_NETIFS ]]; then + echo "SKIP: importer does not define "NUM_NETIFS"" + exit 0 +fi + +source forwarding.config + +for i in $(eval echo {1..$NUM_NETIFS}); do + ip link show dev ${NETIFS[p$i]} &> /dev/null + if [[ $? -ne 0 ]]; then + echo "SKIP: could not find all required interfaces" + exit 0 + fi +done + +# Exit status to return at the end. Set in case one of the tests fails. +EXIT_STATUS=0 +# Per-test return value. Clear at the beginning of each test. +RET=0 + +### Helpers ### + +check_err() +{ + local err=$1 + local msg=$2 + + if [[ $RET -eq 0 ]]; then + RET=$err + retmsg=$msg + fi +} + +check_fail() +{ + local err=$1 + local msg=$2 + + if [[ $err -eq 0 ]]; then + RET=1 + retmsg=$msg + fi +} + +print_result() +{ + local test_name=$1 + local opt_str=$2 + + if [[ $# -eq 2 ]]; then + opt_str="($opt_str)" + fi + + if [[ $RET -ne 0 ]]; then + EXIT_STATUS=1 + echo "FAIL: $test_name $opt_str" + if [[ ! -z "$retmsg" ]]; then + echo "$retmsg" + fi + return 1 + fi + + echo "PASS: $test_name $opt_str" + return 0 +} + +setup_wait() +{ + for i in $(eval echo {1..$NUM_NETIFS}); do + while true; do + ip link show dev ${NETIFS[p$i]} up \ + | grep 'state UP' &> /dev/null + if [[ $? -ne 0 ]]; then + sleep 1 + else + break + fi + done + done + + # Make sure links are ready. + sleep ${OPTIONS[wait_time]} +} + +vrf_prepare() +{ + ip -4 rule add pref 32765 table local + ip -4 rule del pref 0 + ip -6 rule add pref 32765 table local + ip -6 rule del pref 0 +} + +vrf_cleanup() +{ + ip -6 rule add pref 0 table local + ip -6 rule del pref 32765 + ip -4 rule add pref 0 table local + ip -4 rule del pref 32765 +} + +vrf_create() +{ + local vrf_name=$1 + local tb_id=$2 + + ip link add dev $vrf_name type vrf table $tb_id + ip -4 route add table $tb_id unreachable default metric 4278198272 + ip -6 route add table $tb_id unreachable default metric 4278198272 +} + +vrf_destroy() +{ + local vrf_name=$1 + local tb_id=$2 + + ip -6 route del table $tb_id unreachable default metric 4278198272 + ip -4 route del table $tb_id unreachable default metric 4278198272 + ip link del dev $vrf_name +} + +mtu_get() +{ + local if_name=$1 + + ip -j link show dev $if_name | jq '.[]["mtu"]' +} + +mtu_change() +{ + local new_mtu=$1 + local if_name + + shift + for if_name in "${@}"; do + ip link set dev $if_name mtu $new_mtu + done +} + +### Tests ### + +ping_test() +{ + local vrf_name=$1 + local dip=$2 + + RET=0 + + ip vrf exec $vrf_name ping $dip -c 10 -i 0.1 -w 2 &> /dev/null + check_err $? + print_result "ping" +}
On 1/15/18 11:18 AM, Ido Schimmel wrote:
+### Tests ###
+ping_test() +{
- local vrf_name=$1
- local dip=$2
- RET=0
- ip vrf exec $vrf_name ping $dip -c 10 -i 0.1 -w 2 &> /dev/null
- check_err $?
- print_result "ping"
+}
IPv6 addresses on debian need ping6:
root@mlx-2700-05:~/selftests# ip vrf exec vrf-h1 ping 2001:db8:2::2 -c 10 -i 0.1 -w 2 ping: unknown host 2001:db8:2::2
-- To unsubscribe from this list: send the line "unsubscribe linux-kselftest" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
IPv6 addresses on debian need ping6:
root@mlx-2700-05:~/selftests# ip vrf exec vrf-h1 ping 2001:db8:2::2 -c 10 -i 0.1 -w 2 ping: unknown host 2001:db8:2::2
Hi David
Depends on you vintage of Debian:
$ ping 2607:f8b0:4009:813::2004 PING 2607:f8b0:4009:813::2004(2607:f8b0:4009:813::2004) 56 data bytes 64 bytes from 2607:f8b0:4009:813::2004: icmp_seq=1 ttl=54 time=22.1 ms 64 bytes from 2607:f8b0:4009:813::2004: icmp_seq=2 ttl=54 time=20.7 ms ^C --- 2607:f8b0:4009:813::2004 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1001ms rtt min/avg/max/mdev = 20.714/21.426/22.139/0.727 ms
I however don't know when this generally because available, but stretch, buster and sid appear to have it.
Andrew
-- To unsubscribe from this list: send the line "unsubscribe linux-kselftest" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 1/17/18 1:18 PM, Andrew Lunn wrote:
IPv6 addresses on debian need ping6:
root@mlx-2700-05:~/selftests# ip vrf exec vrf-h1 ping 2001:db8:2::2 -c 10 -i 0.1 -w 2 ping: unknown host 2001:db8:2::2
Hi David
Depends on you vintage of Debian:
Yes, ping from iputils-ping in stretch (20161105) supports ipv6; the jessie version (20121221) does not.
$ ping 2607:f8b0:4009:813::2004 PING 2607:f8b0:4009:813::2004(2607:f8b0:4009:813::2004) 56 data bytes 64 bytes from 2607:f8b0:4009:813::2004: icmp_seq=1 ttl=54 time=22.1 ms 64 bytes from 2607:f8b0:4009:813::2004: icmp_seq=2 ttl=54 time=20.7 ms ^C --- 2607:f8b0:4009:813::2004 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1001ms rtt min/avg/max/mdev = 20.714/21.426/22.139/0.727 ms
I however don't know when this generally because available, but stretch, buster and sid appear to have it.
Andrew
-- To unsubscribe from this list: send the line "unsubscribe linux-kselftest" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Send a packet with a specific destination MAC, make sure it was learned on the ingress port and then aged-out.
Signed-off-by: Ido Schimmel idosch@mellanox.com --- tools/testing/selftests/forwarding/bridge.sh | 6 ++- tools/testing/selftests/forwarding/lib.sh | 58 ++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/forwarding/bridge.sh b/tools/testing/selftests/forwarding/bridge.sh index c53086c53b37..0bdcee478211 100755 --- a/tools/testing/selftests/forwarding/bridge.sh +++ b/tools/testing/selftests/forwarding/bridge.sh @@ -48,7 +48,9 @@ h2_destroy()
bridge_create() { - ip link add dev br0 type bridge vlan_filtering 1 mcast_snooping 0 + # 10 Seconds ageing time. + ip link add dev br0 type bridge vlan_filtering 1 ageing_time 1000 \ + mcast_snooping 0
ip link set dev $swp1 master br0 ip link set dev $swp2 master br0 @@ -108,4 +110,6 @@ ping_test "vrf-h1" 192.0.2.2 ping_test "vrf-h1" 2001:db8:1::2 mtu_change $old_mtu "${netifs_arr[@]}"
+learning_test "br0" $swp1 1 $h1 + exit $EXIT_STATUS diff --git a/tools/testing/selftests/forwarding/lib.sh b/tools/testing/selftests/forwarding/lib.sh index bb423371f4de..264bf0af4c4d 100644 --- a/tools/testing/selftests/forwarding/lib.sh +++ b/tools/testing/selftests/forwarding/lib.sh @@ -22,6 +22,11 @@ if [[ ! -x "$(command -v jq)" ]]; then exit 0 fi
+if [[ ! -x "$(command -v mausezahn)" ]]; then + echo "SKIP: mausezahn not installed" + exit 0 +fi + if [[ ! -v NUM_NETIFS ]]; then echo "SKIP: importer does not define "NUM_NETIFS"" exit 0 @@ -160,6 +165,17 @@ mtu_change() done }
+bridge_ageing_time_get() +{ + local ageing_time + local bridge=$1 + + # Need to divide by 100 to convert to seconds. + ageing_time=$(ip -j -d link show dev $bridge \ + | jq '.[]["linkinfo"]["info_data"]["ageing_time"]') + echo $((ageing_time / 100)) +} + ### Tests ###
ping_test() @@ -173,3 +189,45 @@ ping_test() check_err $? print_result "ping" } + +learning_test() +{ + local ageing_time + local host_if=$4 + local br_port=$2 + local bridge=$1 + local vid=$3 + + RET=0 + + bridge -j fdb show br $bridge brport $br_port vlan $vid \ + | jq -e '.[] | select(.mac == "de:ad:be:ef:13:37")' &> /dev/null + check_fail $? "found FDB record when should not" + + mausezahn $host_if -c 1 -p 64 -a de:ad:be:ef:13:37 -t ip -q + + bridge -j fdb show br $bridge brport $br_port vlan $vid \ + | jq -e '.[] | select(.mac == "de:ad:be:ef:13:37")' &> /dev/null + check_err $? "did not find FDB record when should" + + # Wait for 10 seconds after the ageing time to make sure FDB + # record was aged-out. + ageing_time=$(bridge_ageing_time_get $bridge) + sleep $((ageing_time + 10)) + + bridge -j fdb show br $bridge brport $br_port vlan $vid \ + | jq -e '.[] | select(.mac == "de:ad:be:ef:13:37")' &> /dev/null + check_fail $? "found FDB record when should not" + + bridge link set dev $br_port learning off + + mausezahn $host_if -c 1 -p 64 -a de:ad:be:ef:13:37 -t ip -q + + bridge -j fdb show br $bridge brport $br_port vlan $vid \ + | jq -e '.[] | select(.mac == "de:ad:be:ef:13:37")' &> /dev/null + check_fail $? "found FDB record when should not" + + bridge link set dev $br_port learning on + + print_result "learning" +}
On Mon, Jan 15, 2018 at 09:18:43PM +0200, Ido Schimmel wrote:
Send a packet with a specific destination MAC, make sure it was learned on the ingress port and then aged-out.
Hi Ido
It would be interesting to show the hardware actually uses the FDB, not just learns it. Send some packets back, and ensure they go out the intended port. Also, check they don't go out a third port, i.e. make sure the hardware is not flooding. Once it has aged-out, then test is is flooding out all ports.
Andrew -- To unsubscribe from this list: send the line "unsubscribe linux-kselftest" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi Andrew,
On Mon, Jan 15, 2018 at 08:41:46PM +0100, Andrew Lunn wrote:
On Mon, Jan 15, 2018 at 09:18:43PM +0200, Ido Schimmel wrote:
Send a packet with a specific destination MAC, make sure it was learned on the ingress port and then aged-out.
It would be interesting to show the hardware actually uses the FDB, not just learns it. Send some packets back, and ensure they go out the intended port. Also, check they don't go out a third port, i.e. make sure the hardware is not flooding. Once it has aged-out, then test is is flooding out all ports.
Good idea. We can actually do that with only two ports. Disable flooding on port A, check packets with DMAC A don't egress the port. Inject a packet with SMAC A through port A, check packets with DMAC A egress the port. -- To unsubscribe from this list: send the line "unsubscribe linux-kselftest" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Good idea. We can actually do that with only two ports. Disable flooding on port A, check packets with DMAC A don't egress the port. Inject a packet with SMAC A through port A, check packets with DMAC A egress the port.
Hi Ido
You could do it like that. But that is more testing that you can disable flooding. And how often do users do that?
What does your marketing department tell you about typical users of your switches? For DSA, we typically have 4 or 5 ports. 4 of those ports are typically in one bridge, and the remaining port is used alone. That is the sort of setup i test in DSA. Your switches typically have 40 ports? Do your users setup 20 bridges each with two ports?
I would test the use cases which people actually use. I expect people setup a bridge with multiple ports, and they send traffic without changing any defaults. So that setup is what i would test.
Andrew -- To unsubscribe from this list: send the line "unsubscribe linux-kselftest" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 1/15/18 11:18 AM, Ido Schimmel wrote:
diff --git a/tools/testing/selftests/forwarding/lib.sh b/tools/testing/selftests/forwarding/lib.sh index bb423371f4de..264bf0af4c4d 100644 --- a/tools/testing/selftests/forwarding/lib.sh +++ b/tools/testing/selftests/forwarding/lib.sh @@ -22,6 +22,11 @@ if [[ ! -x "$(command -v jq)" ]]; then exit 0 fi +if [[ ! -x "$(command -v mausezahn)" ]]; then
- echo "SKIP: mausezahn not installed"
- exit 0
+fi
The checks are good, but hitting a collision with this one: $ ./router.sh SKIP: mausezahn not installed
For debian, it is mz not mausezahn.
-- To unsubscribe from this list: send the line "unsubscribe linux-kselftest" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Wed, Jan 17, 2018 at 09:48:54PM CET, dsahern@gmail.com wrote:
On 1/15/18 11:18 AM, Ido Schimmel wrote:
diff --git a/tools/testing/selftests/forwarding/lib.sh b/tools/testing/selftests/forwarding/lib.sh index bb423371f4de..264bf0af4c4d 100644 --- a/tools/testing/selftests/forwarding/lib.sh +++ b/tools/testing/selftests/forwarding/lib.sh @@ -22,6 +22,11 @@ if [[ ! -x "$(command -v jq)" ]]; then exit 0 fi +if [[ ! -x "$(command -v mausezahn)" ]]; then
- echo "SKIP: mausezahn not installed"
- exit 0
+fi
The checks are good, but hitting a collision with this one: $ ./router.sh SKIP: mausezahn not installed
For debian, it is mz not mausezahn.
That is weird. If you look at the sources, the binary name is "mausezahn". Looks like debian is doing some renaming :/
-- To unsubscribe from this list: send the line "unsubscribe linux-kselftest" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Wed, Jan 17, 2018 at 1:01 PM, Jiri Pirko jiri@resnulli.us wrote:
Wed, Jan 17, 2018 at 09:48:54PM CET, dsahern@gmail.com wrote:
On 1/15/18 11:18 AM, Ido Schimmel wrote:
diff --git a/tools/testing/selftests/forwarding/lib.sh b/tools/testing/selftests/forwarding/lib.sh index bb423371f4de..264bf0af4c4d 100644 --- a/tools/testing/selftests/forwarding/lib.sh +++ b/tools/testing/selftests/forwarding/lib.sh @@ -22,6 +22,11 @@ if [[ ! -x "$(command -v jq)" ]]; then exit 0 fi
+if [[ ! -x "$(command -v mausezahn)" ]]; then
- echo "SKIP: mausezahn not installed"
- exit 0
+fi
The checks are good, but hitting a collision with this one: $ ./router.sh SKIP: mausezahn not installed
For debian, it is mz not mausezahn.
That is weird. If you look at the sources, the binary name is "mausezahn". Looks like debian is doing some renaming :/
I have seen/used both versions. Debian packages from some old upstream source which calls it mz. https://packages.debian.org/sid/main/mz
I have used latest mz (with ipv6 support etc) from netsniff-ng which builds it as mausezahn. -- To unsubscribe from this list: send the line "unsubscribe linux-kselftest" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Wed, Jan 17, 2018 at 2:46 PM, Roopa Prabhu roopa@cumulusnetworks.com wrote:
On Wed, Jan 17, 2018 at 1:01 PM, Jiri Pirko jiri@resnulli.us wrote:
Wed, Jan 17, 2018 at 09:48:54PM CET, dsahern@gmail.com wrote:
On 1/15/18 11:18 AM, Ido Schimmel wrote:
diff --git a/tools/testing/selftests/forwarding/lib.sh b/tools/testing/selftests/forwarding/lib.sh index bb423371f4de..264bf0af4c4d 100644 --- a/tools/testing/selftests/forwarding/lib.sh +++ b/tools/testing/selftests/forwarding/lib.sh @@ -22,6 +22,11 @@ if [[ ! -x "$(command -v jq)" ]]; then exit 0 fi
+if [[ ! -x "$(command -v mausezahn)" ]]; then
- echo "SKIP: mausezahn not installed"
- exit 0
+fi
The checks are good, but hitting a collision with this one: $ ./router.sh SKIP: mausezahn not installed
For debian, it is mz not mausezahn.
That is weird. If you look at the sources, the binary name is "mausezahn". Looks like debian is doing some renaming :/
I have seen/used both versions. Debian packages from some old upstream source which calls it mz. https://packages.debian.org/sid/main/mz
I have used latest mz (with ipv6 support etc) from netsniff-ng which builds it as mausezahn.
actually Debian also builds https://packages.debian.org/sid/netsniff-ng and installs 'mausezahn'
so you might have to check and use which exists... (mausezahn overriding mz). -- To unsubscribe from this list: send the line "unsubscribe linux-kselftest" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Wed, Jan 17, 2018 at 11:59:10PM CET, roopa@cumulusnetworks.com wrote:
On Wed, Jan 17, 2018 at 2:46 PM, Roopa Prabhu roopa@cumulusnetworks.com wrote:
On Wed, Jan 17, 2018 at 1:01 PM, Jiri Pirko jiri@resnulli.us wrote:
Wed, Jan 17, 2018 at 09:48:54PM CET, dsahern@gmail.com wrote:
On 1/15/18 11:18 AM, Ido Schimmel wrote:
diff --git a/tools/testing/selftests/forwarding/lib.sh b/tools/testing/selftests/forwarding/lib.sh index bb423371f4de..264bf0af4c4d 100644 --- a/tools/testing/selftests/forwarding/lib.sh +++ b/tools/testing/selftests/forwarding/lib.sh @@ -22,6 +22,11 @@ if [[ ! -x "$(command -v jq)" ]]; then exit 0 fi
+if [[ ! -x "$(command -v mausezahn)" ]]; then
- echo "SKIP: mausezahn not installed"
- exit 0
+fi
The checks are good, but hitting a collision with this one: $ ./router.sh SKIP: mausezahn not installed
For debian, it is mz not mausezahn.
That is weird. If you look at the sources, the binary name is "mausezahn". Looks like debian is doing some renaming :/
I have seen/used both versions. Debian packages from some old upstream source which calls it mz. https://packages.debian.org/sid/main/mz
I have used latest mz (with ipv6 support etc) from netsniff-ng which builds it as mausezahn.
actually Debian also builds https://packages.debian.org/sid/netsniff-ng and installs 'mausezahn'
so you might have to check and use which exists... (mausezahn overriding mz).
I believe we can stick with mausezahn, since it is apparently available on Debian too.
-- To unsubscribe from this list: send the line "unsubscribe linux-kselftest" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 1/17/18 3:31 PM, Jiri Pirko wrote:
Wed, Jan 17, 2018 at 11:59:10PM CET, roopa@cumulusnetworks.com wrote:
On Wed, Jan 17, 2018 at 2:46 PM, Roopa Prabhu roopa@cumulusnetworks.com wrote:
On Wed, Jan 17, 2018 at 1:01 PM, Jiri Pirko jiri@resnulli.us wrote:
Wed, Jan 17, 2018 at 09:48:54PM CET, dsahern@gmail.com wrote:
On 1/15/18 11:18 AM, Ido Schimmel wrote:
diff --git a/tools/testing/selftests/forwarding/lib.sh b/tools/testing/selftests/forwarding/lib.sh index bb423371f4de..264bf0af4c4d 100644 --- a/tools/testing/selftests/forwarding/lib.sh +++ b/tools/testing/selftests/forwarding/lib.sh @@ -22,6 +22,11 @@ if [[ ! -x "$(command -v jq)" ]]; then exit 0 fi
+if [[ ! -x "$(command -v mausezahn)" ]]; then
- echo "SKIP: mausezahn not installed"
- exit 0
+fi
The checks are good, but hitting a collision with this one: $ ./router.sh SKIP: mausezahn not installed
For debian, it is mz not mausezahn.
That is weird. If you look at the sources, the binary name is "mausezahn". Looks like debian is doing some renaming :/
I have seen/used both versions. Debian packages from some old upstream source which calls it mz. https://packages.debian.org/sid/main/mz
I have used latest mz (with ipv6 support etc) from netsniff-ng which builds it as mausezahn.
actually Debian also builds https://packages.debian.org/sid/netsniff-ng and installs 'mausezahn'
so you might have to check and use which exists... (mausezahn overriding mz).
I believe we can stick with mausezahn, since it is apparently available on Debian too.
How about the attached - make ping, ping6 and mz variables? Default to ping and mausezahn but let users update that name if necessary. Comments in the sample config to the effect need to be added to help users.
On Wed, Jan 17, 2018 at 04:15:04PM -0800, David Ahern wrote:
How about the attached - make ping, ping6 and mz variables? Default to ping and mausezahn but let users update that name if necessary. Comments in the sample config to the effect need to be added to help users.
Yes, looks good to me. Will include the change in the next version.
Thanks! -- To unsubscribe from this list: send the line "unsubscribe linux-kselftest" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Thu, Jan 18, 2018 at 08:16:54AM CET, idosch@idosch.org wrote:
On Wed, Jan 17, 2018 at 04:15:04PM -0800, David Ahern wrote:
How about the attached - make ping, ping6 and mz variables? Default to ping and mausezahn but let users update that name if necessary. Comments in the sample config to the effect need to be added to help users.
Yes, looks good to me. Will include the change in the next version.
Ido, please keep in mind that the script should run without the config file. So the defaults should be in lib.sh.
Thanks! -- To unsubscribe from this list: send the line "unsubscribe linux-kselftest" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Add test cases for unknown unicast and unregistered multicast flooding.
For each traffic type, turn off flooding on one bridged port and inject a packet of the specified type through the second bridged port. Make sure the packet was not received by the listening tcpdump session on the other end. Later, turn on flooding and make sure the packet was received.
Signed-off-by: Ido Schimmel idosch@mellanox.com --- tools/testing/selftests/forwarding/bridge.sh | 2 + tools/testing/selftests/forwarding/lib.sh | 88 ++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+)
diff --git a/tools/testing/selftests/forwarding/bridge.sh b/tools/testing/selftests/forwarding/bridge.sh index 0bdcee478211..7ae4f1639c45 100755 --- a/tools/testing/selftests/forwarding/bridge.sh +++ b/tools/testing/selftests/forwarding/bridge.sh @@ -112,4 +112,6 @@ mtu_change $old_mtu "${netifs_arr[@]}"
learning_test "br0" $swp1 1 $h1
+flood_test $swp2 $h1 $h2 + exit $EXIT_STATUS diff --git a/tools/testing/selftests/forwarding/lib.sh b/tools/testing/selftests/forwarding/lib.sh index 264bf0af4c4d..03e5253b30d8 100644 --- a/tools/testing/selftests/forwarding/lib.sh +++ b/tools/testing/selftests/forwarding/lib.sh @@ -231,3 +231,91 @@ learning_test()
print_result "learning" } + +flood_test_do() +{ + local should_flood=$1 + local host1_if=$4 + local host2_if=$5 + local mac=$2 + local ip=$3 + local err=0 + + # Add an ACL on `host2_if` which will tell us whether the packet + # was flooded to it or not. + tc qdisc add dev $host2_if ingress + tc filter add dev $host2_if ingress protocol ip pref 1 handle 101 \ + flower dst_mac $mac action drop + + mausezahn $host1_if -c 1 -p 64 -b $mac -B $ip -t ip -q + + tc -j -s filter show dev $host2_if ingress \ + | jq -e ".[] | select(.options.keys.dst_mac == "$mac") \ + | select(.options.actions[0].stats.packets == 1)" &> /dev/null + if [[ $? -ne 0 && $should_flood == "true" || \ + $? -eq 0 && $should_flood == "false" ]]; then + err=1 + fi + + tc filter del dev $host2_if ingress protocol ip pref 1 handle 101 flower + tc qdisc del dev $host2_if ingress + + return $err +} + +flood_unicast_test() +{ + local mac=de:ad:be:ef:13:37 + local ip=192.0.2.100 + local host1_if=$2 + local host2_if=$3 + local br_port=$1 + + RET=0 + + bridge link set dev $br_port flood off + + flood_test_do false $mac $ip $host1_if $host2_if + check_err $? "packet flooded when should not" + + bridge link set dev $br_port flood on + + flood_test_do true $mac $ip $host1_if $host2_if + check_err $? "packet was not flooded when should" + + print_result "unknown unicast flood" +} + +flood_multicast_test() +{ + local mac=01:00:5e:00:00:01 + local ip=239.0.0.1 + local host1_if=$2 + local host2_if=$3 + local br_port=$1 + + RET=0 + + bridge link set dev $br_port mcast_flood off + + flood_test_do false $mac $ip $host1_if $host2_if + check_err $? "packet flooded when should not" + + bridge link set dev $br_port mcast_flood on + + flood_test_do true $mac $ip $host1_if $host2_if + check_err $? "packet was not flooded when should" + + print_result "unregistered multicast flood" +} + +flood_test() +{ + # `br_port` is connected to `host2_if` + local host1_if=$2 + local host2_if=$3 + local br_port=$1 + + flood_unicast_test $br_port $host1_if $host2_if + flood_multicast_test $br_port $host1_if $host2_if +}
Configure two hosts which are directly connected to the same router and test IPv4 and IPv6 ping. Use a large MTU and check that ping is unaffected.
Signed-off-by: Ido Schimmel idosch@mellanox.com --- tools/testing/selftests/forwarding/Makefile | 2 +- tools/testing/selftests/forwarding/lib.sh | 15 +++ tools/testing/selftests/forwarding/router.sh | 131 +++++++++++++++++++++++++++ 3 files changed, 147 insertions(+), 1 deletion(-) create mode 100755 tools/testing/selftests/forwarding/router.sh
diff --git a/tools/testing/selftests/forwarding/Makefile b/tools/testing/selftests/forwarding/Makefile index ef9380c49123..4efb0c96af94 100644 --- a/tools/testing/selftests/forwarding/Makefile +++ b/tools/testing/selftests/forwarding/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 # Makefile for forwarding selftests
-TEST_PROGS := bridge.sh +TEST_PROGS := bridge.sh router.sh
include ../lib.mk diff --git a/tools/testing/selftests/forwarding/lib.sh b/tools/testing/selftests/forwarding/lib.sh index 03e5253b30d8..11b6f6101d10 100644 --- a/tools/testing/selftests/forwarding/lib.sh +++ b/tools/testing/selftests/forwarding/lib.sh @@ -176,6 +176,21 @@ bridge_ageing_time_get() echo $((ageing_time / 100)) }
+forwarding_enable() +{ + ipv4_fwd=$(sysctl -n net.ipv4.conf.all.forwarding) + ipv6_fwd=$(sysctl -n net.ipv6.conf.all.forwarding) + + sysctl -q -w net.ipv4.conf.all.forwarding=1 + sysctl -q -w net.ipv6.conf.all.forwarding=1 +} + +forwarding_restore() +{ + sysctl -q -w net.ipv6.conf.all.forwarding=$ipv6_fwd + sysctl -q -w net.ipv4.conf.all.forwarding=$ipv4_fwd +} + ### Tests ###
ping_test() diff --git a/tools/testing/selftests/forwarding/router.sh b/tools/testing/selftests/forwarding/router.sh new file mode 100755 index 000000000000..79ad6cba9118 --- /dev/null +++ b/tools/testing/selftests/forwarding/router.sh @@ -0,0 +1,131 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +NUM_NETIFS=4 +source lib.sh + +h1_create() +{ + vrf_create "vrf-h1" 1 + ip link set dev $h1 master vrf-h1 + + ip link set dev vrf-h1 up + ip link set dev $h1 up + + ip address add 192.0.2.2/24 dev $h1 + ip address add 2001:db8:1::2/64 dev $h1 + + ip route add 198.51.100.0/24 vrf vrf-h1 nexthop via 192.0.2.1 + ip route add 2001:db8:2::/64 vrf vrf-h1 nexthop via 2001:db8:1::1 +} + +h1_destroy() +{ + ip route del 2001:db8:2::/64 vrf vrf-h1 + ip route del 198.51.100.0/24 vrf vrf-h1 + + ip address del 2001:db8:1::2/64 dev $h1 + ip address del 192.0.2.2/24 dev $h1 + + ip link set dev $h1 down + vrf_destroy "vrf-h1" 1 +} + +h2_create() +{ + vrf_create "vrf-h2" 2 + ip link set dev $h2 master vrf-h2 + + ip link set dev vrf-h2 up + ip link set dev $h2 up + + ip address add 198.51.100.2/24 dev $h2 + ip address add 2001:db8:2::2/64 dev $h2 + + ip route add 192.0.2.0/24 vrf vrf-h2 nexthop via 198.51.100.1 + ip route add 2001:db8:1::/64 vrf vrf-h2 nexthop via 2001:db8:2::1 +} + +h2_destroy() +{ + ip route del 2001:db8:1::/64 vrf vrf-h2 + ip route del 192.0.2.0/24 vrf vrf-h2 + + ip address del 2001:db8:2::2/64 dev $h2 + ip address del 198.51.100.2/24 dev $h2 + + ip link set dev $h2 down + vrf_destroy "vrf-h2" 2 +} + +router_create() +{ + ip link set dev $rp1 up + ip link set dev $rp2 up + + ip address add 192.0.2.1/24 dev $rp1 + ip address add 2001:db8:1::1/64 dev $rp1 + + ip address add 198.51.100.1/24 dev $rp2 + ip address add 2001:db8:2::1/64 dev $rp2 +} + +router_destroy() +{ + ip address del 2001:db8:2::1/64 dev $rp2 + ip address del 198.51.100.1/24 dev $rp2 + + ip address del 2001:db8:1::1/64 dev $rp1 + ip address del 192.0.2.1/24 dev $rp1 + + ip link set dev $rp2 down + ip link set dev $rp1 down +} + +setup_prepare() +{ + h1=${NETIFS[p1]} + rp1=${NETIFS[p2]} + + rp2=${NETIFS[p3]} + h2=${NETIFS[p4]} + + netifs_arr=($h1 $rp1 $rp2 $h2) + + vrf_prepare + + h1_create + h2_create + + router_create + + forwarding_enable +} + +cleanup() +{ + forwarding_restore + + router_destroy + + h2_destroy + h1_destroy + + vrf_cleanup +} + +trap cleanup EXIT + +setup_prepare +setup_wait + +ping_test "vrf-h1" 198.51.100.2 +ping_test "vrf-h1" 2001:db8:2::2 + +old_mtu=$(mtu_get $h1) +mtu_change 9000 "${netifs_arr[@]}" +ping_test "vrf-h1" 198.51.100.2 +ping_test "vrf-h1" 2001:db8:2::2 +mtu_change $old_mtu "${netifs_arr[@]}" + +exit $EXIT_STATUS
Create a topology with two hosts, each directly connected to a different router. Both routers are connected using two links, enabling multipath routing.
Test IPv4 and IPv6 ping using default MTU and large MTU.
Signed-off-by: Ido Schimmel idosch@mellanox.com --- tools/testing/selftests/forwarding/Makefile | 2 +- .../selftests/forwarding/router_multipath.sh | 215 +++++++++++++++++++++ 2 files changed, 216 insertions(+), 1 deletion(-) create mode 100755 tools/testing/selftests/forwarding/router_multipath.sh
diff --git a/tools/testing/selftests/forwarding/Makefile b/tools/testing/selftests/forwarding/Makefile index 4efb0c96af94..48e5de22db05 100644 --- a/tools/testing/selftests/forwarding/Makefile +++ b/tools/testing/selftests/forwarding/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 # Makefile for forwarding selftests
-TEST_PROGS := bridge.sh router.sh +TEST_PROGS := bridge.sh router.sh router_multipath.sh
include ../lib.mk diff --git a/tools/testing/selftests/forwarding/router_multipath.sh b/tools/testing/selftests/forwarding/router_multipath.sh new file mode 100755 index 000000000000..70f9f2c3794e --- /dev/null +++ b/tools/testing/selftests/forwarding/router_multipath.sh @@ -0,0 +1,215 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +NUM_NETIFS=8 +source lib.sh + +h1_create() +{ + vrf_create "vrf-h1" 1 + ip link set dev $h1 master vrf-h1 + + ip link set dev vrf-h1 up + ip link set dev $h1 up + + ip address add 192.0.2.2/24 dev $h1 + ip address add 2001:db8:1::2/64 dev $h1 + + ip route add 198.51.100.0/24 vrf vrf-h1 nexthop via 192.0.2.1 + ip route add 2001:db8:2::/64 vrf vrf-h1 nexthop via 2001:db8:1::1 +} + +h1_destroy() +{ + ip route del 2001:db8:2::/64 vrf vrf-h1 + ip route del 198.51.100.0/24 vrf vrf-h1 + + ip address del 2001:db8:1::2/64 dev $h1 + ip address del 192.0.2.2/24 dev $h1 + + ip link set dev $h1 down + vrf_destroy "vrf-h1" 1 +} + +h2_create() +{ + vrf_create "vrf-h2" 2 + ip link set dev $h2 master vrf-h2 + + ip link set dev vrf-h2 up + ip link set dev $h2 up + + ip address add 198.51.100.2/24 dev $h2 + ip address add 2001:db8:2::2/64 dev $h2 + + ip route add 192.0.2.0/24 vrf vrf-h2 nexthop via 198.51.100.1 + ip route add 2001:db8:1::/64 vrf vrf-h2 nexthop via 2001:db8:2::1 +} + +h2_destroy() +{ + ip route del 2001:db8:1::/64 vrf vrf-h2 + ip route del 192.0.2.0/24 vrf vrf-h2 + + ip address del 2001:db8:2::2/64 dev $h2 + ip address del 198.51.100.2/24 dev $h2 + + ip link set dev $h2 down + vrf_destroy "vrf-h2" 2 +} + +router1_create() +{ + vrf_create "vrf-r1" 3 + ip link set dev $rp11 master vrf-r1 + ip link set dev $rp12 master vrf-r1 + ip link set dev $rp13 master vrf-r1 + + ip link set dev vrf-r1 up + ip link set dev $rp11 up + ip link set dev $rp12 up + ip link set dev $rp13 up + + ip address add 192.0.2.1/24 dev $rp11 + ip address add 2001:db8:1::1/64 dev $rp11 + + ip address add 169.254.2.12/24 dev $rp12 + ip address add fe80:2::12/64 dev $rp12 + + ip address add 169.254.3.13/24 dev $rp13 + ip address add fe80:3::13/64 dev $rp13 + + ip route add 198.51.100.0/24 vrf vrf-r1 \ + nexthop via 169.254.2.22 dev $rp12 \ + nexthop via 169.254.3.23 dev $rp13 + ip route add 2001:db8:2::/64 vrf vrf-r1 \ + nexthop via fe80:2::22 dev $rp12 \ + nexthop via fe80:3::23 dev $rp13 +} + +router1_destroy() +{ + ip route del 2001:db8:2::/64 vrf vrf-r1 + ip route del 198.51.100.0/24 vrf vrf-r1 + + ip address del fe80:3::13/64 dev $rp13 + ip address del 169.254.3.13/24 dev $rp13 + + ip address del fe80:2::12/64 dev $rp12 + ip address del 169.254.2.12/24 dev $rp12 + + ip address del 2001:db8:1::1/64 dev $rp11 + ip address del 192.0.2.1/24 dev $rp11 + + ip link set dev $rp13 down + ip link set dev $rp12 down + ip link set dev $rp11 down + + vrf_destroy "vrf-r1" 3 +} + +router2_create() +{ + vrf_create "vrf-r2" 4 + ip link set dev $rp21 master vrf-r2 + ip link set dev $rp22 master vrf-r2 + ip link set dev $rp23 master vrf-r2 + + ip link set dev vrf-r2 up + ip link set dev $rp21 up + ip link set dev $rp22 up + ip link set dev $rp23 up + + ip address add 198.51.100.1/24 dev $rp21 + ip address add 2001:db8:2::1/64 dev $rp21 + + ip address add 169.254.2.22/24 dev $rp22 + ip address add fe80:2::22/64 dev $rp22 + + ip address add 169.254.3.23/24 dev $rp23 + ip address add fe80:3::23/64 dev $rp23 + + ip route add 192.0.2.0/24 vrf vrf-r2 \ + nexthop via 169.254.2.12 dev $rp22 \ + nexthop via 169.254.3.13 dev $rp23 + ip route add 2001:db8:1::/64 vrf vrf-r2 \ + nexthop via fe80:2::12 dev $rp22 \ + nexthop via fe80:3::13 dev $rp23 +} + +router2_destroy() +{ + ip route del 2001:db8:1::/64 vrf vrf-r2 + ip route del 192.0.2.0/24 vrf vrf-r2 + + ip address del fe80:3::23/64 dev $rp23 + ip address del 169.254.3.23/24 dev $rp23 + + ip address del fe80:2::22/64 dev $rp22 + ip address del 169.254.2.22/24 dev $rp22 + + ip address del 2001:db8:2::1/64 dev $rp21 + ip address del 198.51.100.1/24 dev $rp21 + + ip link set dev $rp23 down + ip link set dev $rp22 down + ip link set dev $rp21 down + + vrf_destroy "vrf-r2" 4 +} + +setup_prepare() +{ + h1=${NETIFS[p1]} + rp11=${NETIFS[p2]} + + rp12=${NETIFS[p3]} + rp22=${NETIFS[p4]} + + rp13=${NETIFS[p5]} + rp23=${NETIFS[p6]} + + rp21=${NETIFS[p7]} + h2=${NETIFS[p8]} + + netifs_arr=($h1 $rp11 $rp12 $rp22 $rp13 $rp23 $rp21 $h2) + + vrf_prepare + + h1_create + h2_create + + router1_create + router2_create + + forwarding_enable +} + +cleanup() +{ + forwarding_restore + + router2_destroy + router1_destroy + + h2_destroy + h1_destroy + + vrf_cleanup +} + +trap cleanup EXIT + +setup_prepare +setup_wait + +ping_test "vrf-h1" 198.51.100.2 +ping_test "vrf-h1" 2001:db8:2::2 + +old_mtu=$(mtu_get $h1) +mtu_change 9000 "${netifs_arr[@]}" +ping_test "vrf-h1" 198.51.100.2 +ping_test "vrf-h1" 2001:db8:2::2 +mtu_change $old_mtu "${netifs_arr[@]}" + +exit $EXIT_STATUS
Use different weights for the multipath route configured on the first router and check that the different flows generated by the first host are distributed according to the provided weights.
Signed-off-by: Ido Schimmel idosch@mellanox.com --- tools/testing/selftests/forwarding/lib.sh | 7 +++ .../selftests/forwarding/router_multipath.sh | 71 ++++++++++++++++++++++ 2 files changed, 78 insertions(+)
diff --git a/tools/testing/selftests/forwarding/lib.sh b/tools/testing/selftests/forwarding/lib.sh index 11b6f6101d10..b814b5350378 100644 --- a/tools/testing/selftests/forwarding/lib.sh +++ b/tools/testing/selftests/forwarding/lib.sh @@ -165,6 +165,13 @@ mtu_change() done }
+link_stats_tx_packets_get() +{ + local if_name=$1 + + ip -j -s link show dev $if_name | jq '.[]["stats644"]["tx"]["packets"]' +} + bridge_ageing_time_get() { local ageing_time diff --git a/tools/testing/selftests/forwarding/router_multipath.sh b/tools/testing/selftests/forwarding/router_multipath.sh index 70f9f2c3794e..45c5fc0a6448 100755 --- a/tools/testing/selftests/forwarding/router_multipath.sh +++ b/tools/testing/selftests/forwarding/router_multipath.sh @@ -158,6 +158,75 @@ router2_destroy() vrf_destroy "vrf-r2" 4 }
+multipath_eval() +{ + local weight_rp12=$1 weight_rp13=$2 packets_rp12=$3 packets_rp13=$4 + local weights_ratio packets_ratio diff + + RET=0 + + if [[ "$weight_rp12" -gt "$weight_rp13" ]]; then + weights_ratio=$(echo $weight_rp12 / $weight_rp13 | bc -l) + packets_ratio=$(echo $packets_rp12 / $packets_rp13 | bc -l) + else + weights_ratio=$(echo $weight_rp13 / $weight_rp12 | bc -l) + packets_ratio=$(echo $packets_rp13 / $packets_rp12 | bc -l) + fi + + echo "Expected ratio: $weights_ratio Measured ratio: $packets_ratio" + + diff=$(echo $weights_ratio - $packets_ratio | bc -l) + diff=${diff#-} + + test "$(echo "$diff / $weights_ratio > 0.1" | bc -l)" -eq 0 + check_err $? "too large discrepancy between expected and measured ratios" + print_result "multipath" +} + +multipath4_test() +{ + local t0_rp12 t0_rp13 t1_rp12 t1_rp13 + local weight_rp12=$1 weight_rp13=$2 + local packets_rp12 packets_rp13 + local hash_policy + + # Transmit multiple flows from h1 to h2 and make sure they are + # distributed between both multipath links (rp12 and rp13) + # according to the configured weights. + hash_policy=$(sysctl -n net.ipv4.fib_multipath_hash_policy) + sysctl -w -q net.ipv4.fib_multipath_hash_policy=1 + ip route replace 198.51.100.0/24 vrf vrf-r1 \ + nexthop via 169.254.2.22 dev $rp12 weight $weight_rp12 \ + nexthop via 169.254.3.23 dev $rp13 weight $weight_rp13 + + t0_rp12=$(link_stats_tx_packets_get $rp12) + t0_rp13=$(link_stats_tx_packets_get $rp13) + + ip vrf exec vrf-h1 mausezahn -q -p 64 -A 192.0.2.2 -B 198.51.100.2 \ + -d 1msec -t udp "sp=1024,dp=0-32768" + + t1_rp12=$(link_stats_tx_packets_get $rp12) + t1_rp13=$(link_stats_tx_packets_get $rp13) + + let "packets_rp12 = $t1_rp12 - $t0_rp12" + let "packets_rp13 = $t1_rp13 - $t0_rp13" + multipath_eval $weight_rp12 $weight_rp13 $packets_rp12 $packets_rp13 + + # Restore settings. + ip route replace 198.51.100.0/24 vrf vrf-r1 \ + nexthop via 169.254.2.22 dev $rp12 \ + nexthop via 169.254.3.23 dev $rp13 + sysctl -w -q net.ipv4.fib_multipath_hash_policy=$hash_policy +} + +multipath_test() +{ + echo "Performing IPv4 multipath tests" + multipath4_test 1 1 + multipath4_test 2 1 + multipath4_test 11 45 +} + setup_prepare() { h1=${NETIFS[p1]} @@ -212,4 +281,6 @@ ping_test "vrf-h1" 198.51.100.2 ping_test "vrf-h1" 2001:db8:2::2 mtu_change $old_mtu "${netifs_arr[@]}"
+multipath_test + exit $EXIT_STATUS
Have one host generate 16K IPv6 echo requests with a random flow label and check that they are distributed between both multipath links according to the provided weights.
Signed-off-by: Ido Schimmel idosch@mellanox.com --- .../selftests/forwarding/router_multipath.sh | 35 ++++++++++++++++++++++ 1 file changed, 35 insertions(+)
diff --git a/tools/testing/selftests/forwarding/router_multipath.sh b/tools/testing/selftests/forwarding/router_multipath.sh index 45c5fc0a6448..58f6e75c627e 100755 --- a/tools/testing/selftests/forwarding/router_multipath.sh +++ b/tools/testing/selftests/forwarding/router_multipath.sh @@ -219,12 +219,47 @@ multipath4_test() sysctl -w -q net.ipv4.fib_multipath_hash_policy=$hash_policy }
+multipath6_test() +{ + local t0_rp12 t0_rp13 t1_rp12 t1_rp13 + local weight_rp12=$1 weight_rp13=$2 + local packets_rp12 packets_rp13 + + ip route replace 2001:db8:2::/64 vrf vrf-r1 \ + nexthop via fe80:2::22 dev $rp12 weight $weight_rp12 \ + nexthop via fe80:3::23 dev $rp13 weight $weight_rp13 + + t0_rp12=$(link_stats_tx_packets_get $rp12) + t0_rp13=$(link_stats_tx_packets_get $rp13) + + # Generate 16384 echo requests, each with a random flow label. + for _ in $(seq 1 16384); do + ip vrf exec vrf-h1 ping 2001:db8:2::2 -F 0 -c 1 -q &> /dev/null + done + + t1_rp12=$(link_stats_tx_packets_get $rp12) + t1_rp13=$(link_stats_tx_packets_get $rp13) + + let "packets_rp12 = $t1_rp12 - $t0_rp12" + let "packets_rp13 = $t1_rp13 - $t0_rp13" + multipath_eval $weight_rp12 $weight_rp13 $packets_rp12 $packets_rp13 + + ip route replace 2001:db8:2::/64 vrf vrf-r1 \ + nexthop via fe80:2::22 dev $rp12 \ + nexthop via fe80:3::23 dev $rp13 +} + multipath_test() { echo "Performing IPv4 multipath tests" multipath4_test 1 1 multipath4_test 2 1 multipath4_test 11 45 + + echo "Performing IPv6 multipath tests" + multipath6_test 1 1 + multipath6_test 2 1 + multipath6_test 11 45 }
setup_prepare()
From: Jiri Pirko jiri@mellanox.com
Signed-off-by: Jiri Pirko jiri@mellanox.com Signed-off-by: Ido Schimmel idosch@mellanox.com --- tools/testing/selftests/forwarding/lib.sh | 13 +++++++++++++ 1 file changed, 13 insertions(+)
diff --git a/tools/testing/selftests/forwarding/lib.sh b/tools/testing/selftests/forwarding/lib.sh index b814b5350378..346ec4283953 100644 --- a/tools/testing/selftests/forwarding/lib.sh +++ b/tools/testing/selftests/forwarding/lib.sh @@ -198,6 +198,19 @@ forwarding_restore() sysctl -q -w net.ipv4.conf.all.forwarding=$ipv4_fwd }
+tc_offload_check() +{ + for i in $(eval echo {1..$NUM_NETIFS}); do + ethtool -k ${NETIFS[p$i]} \ + | grep "hw-tc-offload: on" &> /dev/null + if [[ $? -ne 0 ]]; then + return 1 + fi + done + + return 0 +} + ### Tests ###
ping_test()
From: Jiri Pirko jiri@mellanox.com
Signed-off-by: Jiri Pirko jiri@mellanox.com Signed-off-by: Ido Schimmel idosch@mellanox.com --- tools/testing/selftests/forwarding/lib.sh | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/tools/testing/selftests/forwarding/lib.sh b/tools/testing/selftests/forwarding/lib.sh index 346ec4283953..ddc3ef77f21d 100644 --- a/tools/testing/selftests/forwarding/lib.sh +++ b/tools/testing/selftests/forwarding/lib.sh @@ -172,6 +172,13 @@ link_stats_tx_packets_get() ip -j -s link show dev $if_name | jq '.[]["stats644"]["tx"]["packets"]' }
+mac_get() +{ + local if_name=$1 + + ip -j link show dev $if_name | jq -r '.[]["address"]' +} + bridge_ageing_time_get() { local ageing_time
From: Jiri Pirko jiri@mellanox.com
Signed-off-by: Jiri Pirko jiri@mellanox.com Signed-off-by: Ido Schimmel idosch@mellanox.com --- tools/testing/selftests/forwarding/lib.sh | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
diff --git a/tools/testing/selftests/forwarding/lib.sh b/tools/testing/selftests/forwarding/lib.sh index ddc3ef77f21d..85dbbe83a243 100644 --- a/tools/testing/selftests/forwarding/lib.sh +++ b/tools/testing/selftests/forwarding/lib.sh @@ -34,6 +34,20 @@ fi
source forwarding.config
+# Load netdev names from command line + +count=0 + +while [[ $# -gt 0 ]]; do + if [[ "$count" -eq "0" ]]; then + unset NETIFS + declare -A NETIFS + fi + count=$((count + 1)) + NETIFS[p$count]="$1" + shift +done + for i in $(eval echo {1..$NUM_NETIFS}); do ip link show dev ${NETIFS[p$i]} &> /dev/null if [[ $? -ne 0 ]]; then
From: Jiri Pirko jiri@mellanox.com
Signed-off-by: Jiri Pirko jiri@mellanox.com Signed-off-by: Ido Schimmel idosch@mellanox.com --- tools/testing/selftests/forwarding/lib.sh | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/tools/testing/selftests/forwarding/lib.sh b/tools/testing/selftests/forwarding/lib.sh index 85dbbe83a243..b9b049af93cb 100644 --- a/tools/testing/selftests/forwarding/lib.sh +++ b/tools/testing/selftests/forwarding/lib.sh @@ -34,17 +34,23 @@ fi
source forwarding.config
-# Load netdev names from command line +# Load options and netdev names from command line
count=0
while [[ $# -gt 0 ]]; do - if [[ "$count" -eq "0" ]]; then - unset NETIFS - declare -A NETIFS + echo $1 | grep "=" &> /dev/null + if [[ $? -eq 0 ]]; then + splitarr=(${1//=/ }) + OPTIONS[${splitarr[0]}]=${splitarr[1]} + else + if [[ "$count" -eq "0" ]]; then + unset NETIFS + declare -A NETIFS + fi + count=$((count + 1)) + NETIFS[p$count]="$1" fi - count=$((count + 1)) - NETIFS[p$count]="$1" shift done
From: Jiri Pirko jiri@mellanox.com
Add first part of flower tests. This patch only contains dst/src ip/mac matching.
Signed-off-by: Jiri Pirko jiri@mellanox.com Signed-off-by: Ido Schimmel idosch@mellanox.com --- tools/testing/selftests/forwarding/Makefile | 2 +- tools/testing/selftests/forwarding/tc_flower.sh | 261 ++++++++++++++++++++++++ 2 files changed, 262 insertions(+), 1 deletion(-) create mode 100755 tools/testing/selftests/forwarding/tc_flower.sh
diff --git a/tools/testing/selftests/forwarding/Makefile b/tools/testing/selftests/forwarding/Makefile index 48e5de22db05..5bc8340d4711 100644 --- a/tools/testing/selftests/forwarding/Makefile +++ b/tools/testing/selftests/forwarding/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 # Makefile for forwarding selftests
-TEST_PROGS := bridge.sh router.sh router_multipath.sh +TEST_PROGS := bridge.sh router.sh router_multipath.sh tc_flower.sh
include ../lib.mk diff --git a/tools/testing/selftests/forwarding/tc_flower.sh b/tools/testing/selftests/forwarding/tc_flower.sh new file mode 100755 index 000000000000..de825ff2712c --- /dev/null +++ b/tools/testing/selftests/forwarding/tc_flower.sh @@ -0,0 +1,261 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +NUM_NETIFS=2 +source lib.sh + +tcflags="skip_hw" + +h1_create() +{ + vrf_create "vrf-h1" 1 + ip link set dev $h1 master vrf-h1 + + ip link set dev vrf-h1 up + ip link set dev $h1 up + + ip address add 192.0.2.1/24 dev $h1 + ip address add 198.51.100.1/24 dev $h1 + ip address add 2001:db8:1::1/64 dev $h1 + + tc qdisc add dev $h1 clsact +} + +h1_destroy() +{ + tc qdisc del dev $h1 clsact + + ip address del 2001:db8:1::1/64 dev $h1 + ip address del 198.51.100.1/24 dev $h1 + ip address del 192.0.2.1/24 dev $h1 + + ip link set dev $h1 down + vrf_destroy "vrf-h1" 1 +} + +h2_create() +{ + vrf_create "vrf-h2" 2 + ip link set dev $h2 master vrf-h2 + + ip link set dev vrf-h2 up + ip link set dev $h2 up + + ip address add 192.0.2.2/24 dev $h2 + ip address add 198.51.100.2/24 dev $h2 + ip address add 2001:db8:1::2/64 dev $h2 + + tc qdisc add dev $h2 clsact +} + +h2_destroy() +{ + tc qdisc del dev $h2 clsact + + ip address del 2001:db8:1::2/64 dev $h2 + ip address del 198.51.100.2/24 dev $h2 + ip address del 192.0.2.2/24 dev $h2 + + ip link set dev $h2 down + vrf_destroy "vrf-h2" 2 +} + +match_dst_mac_test() +{ + local dummy_mac=de:ad:be:ef:aa:aa + + RET=0 + + tc filter add dev $h2 ingress protocol ip pref 1 handle 101 flower \ + $tcflags dst_mac $dummy_mac action drop + tc filter add dev $h2 ingress protocol ip pref 2 handle 102 flower \ + $tcflags dst_mac $h2mac action drop + + mausezahn $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ + -t ip -q + + tc -j -s filter show dev $h2 ingress \ + | jq -e ".[] | select(.options.keys.dst_mac == "$dummy_mac") \ + | select(.options.actions[0].stats.packets == 1)" &> /dev/null + check_fail $? "matched on a wrong filter" + + tc -j -s filter show dev $h2 ingress \ + | jq -e ".[] | select(.options.keys.dst_mac == "$h2mac") \ + | select(.options.actions[0].stats.packets == 1)" &> /dev/null + check_err $? "did not match on correct filter" + + tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower + tc filter del dev $h2 ingress protocol ip pref 2 handle 102 flower + + print_result "dst_mac match" +} + +match_src_mac_test() +{ + local dummy_mac=de:ad:be:ef:aa:aa + + RET=0 + + tc filter add dev $h2 ingress protocol ip pref 1 handle 101 flower \ + $tcflags src_mac $dummy_mac action drop + tc filter add dev $h2 ingress protocol ip pref 2 handle 102 flower \ + $tcflags src_mac $h1mac action drop + + mausezahn $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ + -t ip -q + + tc -j -s filter show dev $h2 ingress \ + | jq -e ".[] | select(.options.keys.src_mac == "$dummy_mac") \ + | select(.options.actions[0].stats.packets == 1)" &> /dev/null + check_fail $? "matched on a wrong filter" + + tc -j -s filter show dev $h2 ingress \ + | jq -e ".[] | select(.options.keys.src_mac == "$h1mac") \ + | select(.options.actions[0].stats.packets == 1)" &> /dev/null + check_err $? "did not match on correct filter" + + tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower + tc filter del dev $h2 ingress protocol ip pref 2 handle 102 flower + + print_result "src_mac match" +} + +match_dst_ip_test() +{ + RET=0 + + tc filter add dev $h2 ingress protocol ip pref 1 handle 101 flower \ + $tcflags dst_ip 198.51.100.2 action drop + tc filter add dev $h2 ingress protocol ip pref 2 handle 102 flower \ + $tcflags dst_ip 192.0.2.2 action drop + tc filter add dev $h2 ingress protocol ip pref 3 handle 103 flower \ + $tcflags dst_ip 192.0.2.0/24 action drop + + mausezahn $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ + -t ip -q + + tc -j -s filter show dev $h2 ingress \ + | jq -e ".[] \ + | select(.options.keys.dst_ip == "198.51.100.2") \ + | select(.options.actions[0].stats.packets == 1)" &> /dev/null + check_fail $? "matched on a wrong filter" + + tc -j -s filter show dev $h2 ingress \ + | jq -e ".[] \ + | select(.options.keys.dst_ip == "192.0.2.2") \ + | select(.options.actions[0].stats.packets == 1)" &> /dev/null + check_err $? "did not match on correct filter" + + tc filter del dev $h2 ingress protocol ip pref 2 handle 102 flower + + mausezahn $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ + -t ip -q + + tc -j -s filter show dev $h2 ingress \ + | jq -e ".[] \ + | select(.options.keys.dst_ip == "192.0.2.0/24") \ + | select(.options.actions[0].stats.packets == 1)" &> /dev/null + check_err $? "did not match on correct filter with mask" + + tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower + tc filter del dev $h2 ingress protocol ip pref 3 handle 103 flower + + print_result "dst_ip match" +} + +match_src_ip_test() +{ + RET=0 + + tc filter add dev $h2 ingress protocol ip pref 1 handle 101 flower \ + $tcflags src_ip 198.51.100.1 action drop + tc filter add dev $h2 ingress protocol ip pref 2 handle 102 flower \ + $tcflags src_ip 192.0.2.1 action drop + tc filter add dev $h2 ingress protocol ip pref 3 handle 103 flower \ + $tcflags src_ip 192.0.2.0/24 action drop + + mausezahn $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ + -t ip -q + + tc -j -s filter show dev $h2 ingress \ + | jq -e ".[] \ + | select(.options.keys.src_ip == "198.51.100.1") \ + | select(.options.actions[0].stats.packets == 1)" &> /dev/null + check_fail $? "matched on a wrong filter" + + tc -j -s filter show dev $h2 ingress \ + | jq -e ".[] \ + | select(.options.keys.src_ip == "192.0.2.1") \ + | select(.options.actions[0].stats.packets == 1)" &> /dev/null + check_err $? "did not match on correct filter" + + tc filter del dev $h2 ingress protocol ip pref 2 handle 102 flower + + mausezahn $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ + -t ip -q + + tc -j -s filter show dev $h2 ingress \ + | jq -e ".[] \ + | select(.options.keys.src_ip == "192.0.2.0/24") \ + | select(.options.actions[0].stats.packets == 1)" &> /dev/null + check_err $? "did not match on correct filter with mask" + + tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower + tc filter del dev $h2 ingress protocol ip pref 3 handle 103 flower + + print_result "src_ip match" +} + +setup_prepare() +{ + h1=${NETIFS[p1]} + h2=${NETIFS[p2]} + h1mac=$(mac_get $h1) + h2mac=$(mac_get $h2) + + if [[ "${OPTIONS[noprepare]}" == "yes" ]]; then + echo "INFO: Not doing setup prepare" + return 0 + fi + + vrf_prepare + + h1_create + h2_create +} + +cleanup() +{ + if [[ "${OPTIONS[nocleanup]}" == "yes" ]]; then + echo "INFO: Not doing cleanup" + return 0 + fi + + h2_destroy + h1_destroy + + vrf_cleanup +} + +trap cleanup EXIT + +setup_prepare +setup_wait + +match_dst_mac_test +match_src_mac_test +match_dst_ip_test +match_src_ip_test + +tc_offload_check +if [[ $? -ne 0 ]]; then + echo "WARN: Could not test offloaded functionality" +else + tcflags="skip_sw" + match_dst_mac_test + match_src_mac_test + match_dst_ip_test + match_src_ip_test +fi + +exit $EXIT_STATUS
On 1/15/18 12:18 PM, Ido Schimmel wrote:
One of the nice things about network namespaces is that they allow one to easily create and test complex environments.
Unfortunately, these namespaces can not be used with actual switching ASICs, as their ports can not be migrated to other network namespaces (NETIF_F_NETNS_LOCAL) and most of them probably do not support the L1-separation provided by namespaces.
However, a similar kind of flexibility can be achieved by using VRFs and by looping the switch ports together. For example:
br0 + vrf-h1 | vrf-h2 + +---+----+ + | | | | 192.0.2.1/24 + + + + 192.0.2.2/24 swp1 swp2 swp3 swp4 + + + + | | | | +--------+ +--------+
The VRFs act as lightweight namespaces representing hosts connected to the switch.
This approach for testing switch ASICs has several advantages over the traditional method that requires multiple physical machines, to name a few:
- Only the device under test (DUT) is being tested without noise from
other system.
- Ability to easily provision complex topologies. Testing bridging
between 4-ports LAGs or 8-way ECMP requires many physical links that are not always available. With the VRF-based approach one merely needs to loopback more ports.
These tests are written with switch ASICs in mind, but they can be run on any Linux box using veth pairs to emulate physical loopbacks.
Feedback is is welcome. Particularly regarding the best location for these tests (e.g., current location, tools/testing/selftests/net).
Awesome. Thanks for working on this.
A couple of feature requests: 1. an option to pause on any error to allow inspection of the setup
2. an option to configure the system and leave it in that state (ie, don't trap exit and run cleanup). By extension, an option is needed to do cleanup only.
This framework will be very useful. -- To unsubscribe from this list: send the line "unsubscribe linux-kselftest" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Mon, Jan 15, 2018 at 09:14:56PM CET, dsahern@gmail.com wrote:
On 1/15/18 12:18 PM, Ido Schimmel wrote:
One of the nice things about network namespaces is that they allow one to easily create and test complex environments.
Unfortunately, these namespaces can not be used with actual switching ASICs, as their ports can not be migrated to other network namespaces (NETIF_F_NETNS_LOCAL) and most of them probably do not support the L1-separation provided by namespaces.
However, a similar kind of flexibility can be achieved by using VRFs and by looping the switch ports together. For example:
br0 + vrf-h1 | vrf-h2 + +---+----+ + | | | | 192.0.2.1/24 + + + + 192.0.2.2/24 swp1 swp2 swp3 swp4 + + + + | | | | +--------+ +--------+
The VRFs act as lightweight namespaces representing hosts connected to the switch.
This approach for testing switch ASICs has several advantages over the traditional method that requires multiple physical machines, to name a few:
- Only the device under test (DUT) is being tested without noise from
other system.
- Ability to easily provision complex topologies. Testing bridging
between 4-ports LAGs or 8-way ECMP requires many physical links that are not always available. With the VRF-based approach one merely needs to loopback more ports.
These tests are written with switch ASICs in mind, but they can be run on any Linux box using veth pairs to emulate physical loopbacks.
Feedback is is welcome. Particularly regarding the best location for these tests (e.g., current location, tools/testing/selftests/net).
Awesome. Thanks for working on this.
A couple of feature requests:
- an option to pause on any error to allow inspection of the setup
Good idea. Should be easy to add.
- an option to configure the system and leave it in that state (ie,
don't trap exit and run cleanup). By extension, an option is needed to do cleanup only.
Checkout the last patch. It has "noprepare" and "nocleanup" options. So I guess you imagine something like that, but generic?
This framework will be very useful.
-- To unsubscribe from this list: send the line "unsubscribe linux-kselftest" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 1/15/18 4:17 PM, Jiri Pirko wrote:
A couple of feature requests:
- an option to pause on any error to allow inspection of the setup
Good idea. Should be easy to add.
Here is a snippet from my vrf test script:
PAUSE_ON_FAIL=no -p option sets PAUSE_ON_FAIL=yes
log_test() { local rc=$1 local expected=$2 local msg="$3"
if [ ${rc} -eq ${expected} ]; then nsuccess=$((nsuccess+1)) printf "\n TEST: %-80s [ OK ]\n" "${msg}" else nfail=$((nfail+1)) printf "\n TEST: %-80s [FAIL]\n" "${msg}" if [ "${PAUSE_ON_FAIL}" = "yes" ]; then echo echo "hit enter to continue, 'q' to quit" read a [ "$a" = "q" ] && exit 1 fi fi }
'rc' is the return code from the command run
'expected' is the expected return code. This allows negative testing where rc can be non-0 and the test passes
'msg' is the name of the test.
The above maps close to print_result in lib.sh
(nsuccess and nfail track total number of tests run that pass/fail. I print a summary when the test set is done.)
- an option to configure the system and leave it in that state (ie,
don't trap exit and run cleanup). By extension, an option is needed to do cleanup only.
Checkout the last patch. It has "noprepare" and "nocleanup" options. So I guess you imagine something like that, but generic?
Sure that is one way.
Something else I have found useful is to not redirect stdout/stderr from the commands and to have tags that can be grep'ed to provide a summary. I run my VRF test script as:
$ run-test.sh 2>&1 | tee vrf-results.txt | grep TEST
The terminal gets a nice summary:
TEST SECTION: IPv4 ping TEST: ping out - VRF device, peer IP [ OK ] TEST: ping out - enslaved device, peer IP [ OK ] TEST: ping in - My IP [ OK ] TEST: ping in - VRF IP [FAIL] TEST: ping local - VRF device, My IP [ OK ] TEST: ping local - VRF device, VRF IP [ OK ] TEST: ping local - VRF device, loopback [ OK ] TEST: ping local - enslaved device, My IP [ OK ] TEST: ping local - enslaved device, VRF IP [ OK ] TEST: ping out - VRF device, VRF source, peer IP [ OK ] TEST: ping out - enslaved device, VRF source, peer IP [ OK ]
And when I find a test failing I can go look at the full output:
$ vi vrf-results.txt
Test setup VRF name: lisa Enslaved device veth1
Device addresses: 172.16.99.1 2001:db8:99::1 VRF local IP: 1.1.1.1 1111:1::1
Peer device: veth2 Peer addresses: 172.16.99.254 2001:db8:99::64
######################################## Configuring network namespace
Resetting config ...
###################################################################### TEST SECTION: IPv4 ping ######################################################################
#################### COMMAND: ping -c1 -w1 -I lisa 172.16.99.254
ping: Warning: source address might be selected on device other than lisa. PING 172.16.99.254 (172.16.99.254) from 172.16.99.1 lisa: 56(84) bytes of data. 64 bytes from 172.16.99.254: icmp_seq=1 ttl=64 time=0.084 ms
--- 172.16.99.254 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 0.084/0.084/0.084/0.000 ms
TEST: ping out - VRF device, peer IP [ OK ] ... -- To unsubscribe from this list: send the line "unsubscribe linux-kselftest" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Mon, Jan 15, 2018 at 04:48:25PM -0700, David Ahern wrote:
On 1/15/18 4:17 PM, Jiri Pirko wrote:
A couple of feature requests:
- an option to pause on any error to allow inspection of the setup
Good idea. Should be easy to add.
Here is a snippet from my vrf test script:
PAUSE_ON_FAIL=no -p option sets PAUSE_ON_FAIL=yes
log_test() { local rc=$1 local expected=$2 local msg="$3"
if [ ${rc} -eq ${expected} ]; then nsuccess=$((nsuccess+1)) printf "\n TEST: %-80s [ OK ]\n" "${msg}" else nfail=$((nfail+1)) printf "\n TEST: %-80s [FAIL]\n" "${msg}" if [ "${PAUSE_ON_FAIL}" = "yes" ]; then echo echo "hit enter to continue, 'q' to quit" read a [ "$a" = "q" ] && exit 1 fi fi
}
Nice. Will add.
[...]
- an option to configure the system and leave it in that state (ie,
don't trap exit and run cleanup). By extension, an option is needed to do cleanup only.
Checkout the last patch. It has "noprepare" and "nocleanup" options. So I guess you imagine something like that, but generic?
Sure that is one way.
I think we can do something similar to your 'PAUSE_ON_FAIL' option. At the end of the run the system is supposed to be configured as it was in the beginning of the test, so we can have the trap wait for user to hit 'c' for cleanup if the option is set. By default it will run cleanup.
Something else I have found useful is to not redirect stdout/stderr from the commands and to have tags that can be grep'ed to provide a summary. I run my VRF test script as:
$ run-test.sh 2>&1 | tee vrf-results.txt | grep TEST
Good idea. Will change. -- To unsubscribe from this list: send the line "unsubscribe linux-kselftest" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 01/15/2018 12:14 PM, David Ahern wrote:
On 1/15/18 12:18 PM, Ido Schimmel wrote:
One of the nice things about network namespaces is that they allow one to easily create and test complex environments.
Unfortunately, these namespaces can not be used with actual switching ASICs, as their ports can not be migrated to other network namespaces (NETIF_F_NETNS_LOCAL) and most of them probably do not support the L1-separation provided by namespaces.
However, a similar kind of flexibility can be achieved by using VRFs and by looping the switch ports together. For example:
br0 + vrf-h1 | vrf-h2 + +---+----+ + | | | | 192.0.2.1/24 + + + + 192.0.2.2/24 swp1 swp2 swp3 swp4 + + + + | | | | +--------+ +--------+
The VRFs act as lightweight namespaces representing hosts connected to the switch.
This approach for testing switch ASICs has several advantages over the traditional method that requires multiple physical machines, to name a few:
- Only the device under test (DUT) is being tested without noise from
other system.
- Ability to easily provision complex topologies. Testing bridging
between 4-ports LAGs or 8-way ECMP requires many physical links that are not always available. With the VRF-based approach one merely needs to loopback more ports.
These tests are written with switch ASICs in mind, but they can be run on any Linux box using veth pairs to emulate physical loopbacks.
Feedback is is welcome. Particularly regarding the best location for these tests (e.g., current location, tools/testing/selftests/net).
Awesome. Thanks for working on this.
Agreed this is really cool! For DSA enabled switches, we usually have a host that does the test sequencing and then execute commands remotely on the DUT, but we might be able to get such a similar framework up and running on the DUT itself without too much hassle.
However, a similar kind of flexibility can be achieved by using VRFs and by looping the switch ports together. For example:
br0 + vrf-h1 | vrf-h2 + +---+----+ + | | | | 192.0.2.1/24 + + + + 192.0.2.2/24 swp1 swp2 swp3 swp4 + + + + | | | | +--------+ +--------+
Agreed this is really cool! For DSA enabled switches, we usually have a host that does the test sequencing and then execute commands remotely on the DUT, but we might be able to get such a similar framework up and running on the DUT itself without too much hassle.
I think the problem we will have is a lack of ports. Most DSA switches have 4 or 5 ports. Given the need for two ports per bridge port, we will be limited to bridges with just two members. That really limits what sort of tests you can do.
But for top or rack switches, 16 ports, 8 loopback cables, that does give interesting setups. If i were writing tests for that class of routers, that would be the hardware setup i would define.
Andrew -- To unsubscribe from this list: send the line "unsubscribe linux-kselftest" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi Andrew, Florian
On Thu, Jan 18, 2018 at 12:11:11AM +0100, Andrew Lunn wrote:
However, a similar kind of flexibility can be achieved by using VRFs and by looping the switch ports together. For example:
br0 + vrf-h1 | vrf-h2 + +---+----+ + | | | | 192.0.2.1/24 + + + + 192.0.2.2/24 swp1 swp2 swp3 swp4 + + + + | | | | +--------+ +--------+
Agreed this is really cool! For DSA enabled switches, we usually have a host that does the test sequencing and then execute commands remotely on the DUT, but we might be able to get such a similar framework up and running on the DUT itself without too much hassle.
I think the problem we will have is a lack of ports. Most DSA switches have 4 or 5 ports. Given the need for two ports per bridge port, we will be limited to bridges with just two members. That really limits what sort of tests you can do.
I was actually interested in feedback from you guys. Looking at dsa_slave_changeupper() I see you don't forbid the enslavement to a VRF and that you set STP state to forwarding when a port leaves a bridge (good). Does that mean you're able to use some of these tests on your switches?
The reason we can use these tests for mlxsw is that we support VRF and ACL offload. At least in the above example, swp4 is able to receive packets directed at 192.0.2.2 because we program the device with the host route 192.0.2.2/32. -- To unsubscribe from this list: send the line "unsubscribe linux-kselftest" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
br0 + vrf-h1 | vrf-h2 + +---+----+ + | | | | 192.0.2.1/24 + + + + 192.0.2.2/24 swp1 swp2 swp3 swp4 + + + + | | | | +--------+ +--------+
Agreed this is really cool! For DSA enabled switches, we usually have a host that does the test sequencing and then execute commands remotely on the DUT, but we might be able to get such a similar framework up and running on the DUT itself without too much hassle.
I think the problem we will have is a lack of ports. Most DSA switches have 4 or 5 ports. Given the need for two ports per bridge port, we will be limited to bridges with just two members. That really limits what sort of tests you can do.
I was actually interested in feedback from you guys. Looking at dsa_slave_changeupper() I see you don't forbid the enslavement to a VRF and that you set STP state to forwarding when a port leaves a bridge (good). Does that mean you're able to use some of these tests on your switches?
By default, we have port separation. So you can add individual IP addresses to interfaces, and ping from them. In fact, this is the first test i always run. My test setup uses 4 ports of the switch, and connects a USB-Ethernet dongle to each port. The 4 USB cables then connect to my host running the tests. I setup four parallel subnets, and ping across each.
I've never used vrf, so i've no idea if that will just work on top.
The reason we can use these tests for mlxsw is that we support VRF and ACL offload. At least in the above example, swp4 is able to receive packets directed at 192.0.2.2 because we program the device with the host route 192.0.2.2/32.
We are all L2. So no route needed. No ACLs either.
So in theory, this could be used with DSA. But in practice, only having two test ports really restricts you from doing anything interesting. You need a minimum of 3, and all my tests use 4. Given your double requirements, that means you actually need a switch with 8 external ports. I don't know of any DSA board which has that.
Andrew
-- To unsubscribe from this list: send the line "unsubscribe linux-kselftest" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
linux-kselftest-mirror@lists.linaro.org