Subject: Re: [ovs-dev] [PATCH net-next 6/7] selftests: net: Use the provided dpctl rather than the vswitchd for tests.

From: Aaron Conole <[email-masked]>
Date: Tue, 18 Jun 2024 12:02:59 -0400

Aaron Conole <[email-masked]> writes:

> The current pmtu test infrastucture requires an installed copy of the
> ovs-vswitchd userspace.  This means that any automated or constrained
> environments may not have the requisite tools to run the tests.  However,
> the pmtu tests don't require any special classifier processing.  Indeed
> they are only using the vswitchd in the most basic mode - as a NORMAL
> switch.
>
> However, the ovs-dpctl kernel utility can now program all the needed basic
> flows to allow traffic to traverse the tunnels and provide support for at
> least testing some basic pmtu scenarios.  More complicated flow pipelines
> can be added to the internal ovs test infrastructure, but that is work for
> the future.  For now, enable the most common cases - wide mega flows with
> no other prerequisites.
>
> Enhance the pmtu testing to try testing using the internal utility, first.
> As a fallback, if the internal utility isn't running, then try with the
> ovs-vswitchd userspace tools.
>
> Signed-off-by: Aaron Conole <[email-masked]>
> ---
>  tools/testing/selftests/net/pmtu.sh | 145 +++++++++++++++++++++++-----
>  1 file changed, 123 insertions(+), 22 deletions(-)
>
> diff --git a/tools/testing/selftests/net/pmtu.sh b/tools/testing/selftests/net/pmtu.sh
> index cfc84958025a..51ccb9bed069 100755
> --- a/tools/testing/selftests/net/pmtu.sh
> +++ b/tools/testing/selftests/net/pmtu.sh
> @@ -842,25 +842,97 @@ setup_bridge() {
>  	run_cmd ${ns_a} ip link set veth_A-C master br0
>  }
>  
> +setup_ovs_via_internal_utility() {
> +	type="${1}"
> +	a_addr="${2}"
> +	b_addr="${3}"
> +	dport="${4}"
> +
> +	run_cmd python3 ./openvswitch/ovs-dpctl.py add-if ovs_br0 ${type}_a -t ${type} || return 1
> +
> +	ports=$(python3 ./openvswitch/ovs-dpctl.py show)
> +	br0_port=$(echo "$ports" | grep -E "\sovs_br0" | sed -e 's@port @@' | cut -d: -f1 | xargs)
> +	type_a_port=$(echo "$ports" | grep ${type}_a | sed -e 's@port @@' | cut -d: -f1 | xargs)
> +	veth_a_port=$(echo "$ports" | grep veth_A | sed -e 's@port @@' | cut -d: -f1 | xargs)
> +
> +	v4_a_tun="${prefix4}.${a_r1}.1"
> +	v4_b_tun="${prefix4}.${b_r1}.1"
> +
> +	v6_a_tun="${prefix6}:${a_r1}::1"
> +	v6_b_tun="${prefix6}:${b_r1}::1"
> +
> +	if [ "${v4_a_tun}" = "${a_addr}" ]; then
> +		run_cmd python3 ./openvswitch/ovs-dpctl.py add-flow ovs_br0 \
> +		    "recirc_id(0),in_port(${veth_a_port}),eth(),eth_type(0x0800),ipv4()" \
> +		    "set(tunnel(tun_id=1,dst=${v4_b_tun},ttl=64,tp_dst=${dport},flags(df|csum))),${type_a_port}"
> +		run_cmd python3 ./openvswitch/ovs-dpctl.py add-flow ovs_br0 \
> +		    "recirc_id(0),in_port(${veth_a_port}),eth(),eth_type(0x86dd),ipv6()" \
> +		    "set(tunnel(tun_id=1,dst=${v4_b_tun},ttl=64,tp_dst=${dport},flags(df|csum))),${type_a_port}"
> +		run_cmd python3 ./openvswitch/ovs-dpctl.py add-flow ovs_br0 \
> +		    "recirc_id(0),tunnel(tun_id=1,src=${v4_b_tun},dst=${v4_a_tun}),in_port(${type_a_port}),eth(),eth_type(0x0800),ipv4()" \
> +		    "${veth_a_port}"
> +		run_cmd python3 ./openvswitch/ovs-dpctl.py add-flow ovs_br0 \
> +		    "recirc_id(0),tunnel(tun_id=1,src=${v4_b_tun},dst=${v4_a_tun}),in_port(${type_a_port}),eth(),eth_type(0x86dd),ipv6()" \
> +		    "${veth_a_port}"
> +		run_cmd python3 ./openvswitch/ovs-dpctl.py add-flow ovs_br0 \
> +		    "recirc_id(0),tunnel(tun_id=1,src=${v4_b_tun},dst=${v4_a_tun}),in_port(${type_a_port}),eth(),eth_type(0x0806),arp()" \
> +		    "${veth_a_port}"
> +		run_cmd python3 ./openvswitch/ovs-dpctl.py add-flow ovs_br0 \
> +		    "recirc_id(0),in_port(${veth_a_port}),eth(),eth_type(0x0806),arp(sip=${veth4_c_addr},tip=${tunnel4_b_addr})" \
> +		    "set(tunnel(tun_id=1,dst=${v4_b_tun},ttl=64,tp_dst=${dport},flags(df|csum))),${type_a_port}"
> +	else
> +		run_cmd python3 ./openvswitch/ovs-dpctl.py add-flow ovs_br0 \
> +		    "recirc_id(0),in_port(${veth_a_port}),eth(),eth_type(0x0800),ipv4()" \
> +		    "set(tunnel(tun_id=1,ipv6_dst=${v6_b_tun},ttl=64,tp_dst=${dport},flags(df|csum))),${type_a_port}"
> +		run_cmd python3 ./openvswitch/ovs-dpctl.py add-flow ovs_br0 \
> +		    "recirc_id(0),in_port(${veth_a_port}),eth(),eth_type(0x86dd),ipv6()" \
> +		    "set(tunnel(tun_id=1,ipv6_dst=${v6_b_tun},ttl=64,tp_dst=${dport},flags(df|csum))),${type_a_port}"
> +		run_cmd python3 ./openvswitch/ovs-dpctl.py add-flow ovs_br0 \
> +		    "recirc_id(0),tunnel(tun_id=1,ipv6_src=${v6_b_tun},ipv6_dst=${v6_a_tun}),in_port(${type_a_port}),eth(),eth_type(0x0800),ipv4()" \
> +		    "${veth_a_port}"
> +		run_cmd python3 ./openvswitch/ovs-dpctl.py add-flow ovs_br0 \
> +		    "recirc_id(0),tunnel(tun_id=1,ipv6_src=${v6_b_tun},ipv6_dst=${v6_a_tun}),in_port(${type_a_port}),eth(),eth_type(0x86dd),ipv6()" \
> +		    "${veth_a_port}"
> +		run_cmd python3 ./openvswitch/ovs-dpctl.py add-flow ovs_br0 \
> +		    "recirc_id(0),tunnel(tun_id=1,ipv6_src=${v6_b_tun},ipv6_dst=${v6_a_tun}),in_port(${type_a_port}),eth(),eth_type(0x0806),arp()" \
> +		    "${veth_a_port}"
> +		run_cmd python3 ./openvswitch/ovs-dpctl.py add-flow ovs_br0 \
> +		    "recirc_id(0),in_port(${veth_a_port}),eth(),eth_type(0x0806),arp(sip=${veth4_c_addr},tip=${tunnel4_b_addr})" \
> +		    "set(tunnel(tun_id=1,ipv6_dst=${v6_b_tun},ttl=64,tp_dst=${dport},flags(df|csum))),${type_a_port}"
> +	fi
> +}
> +
> +setup_ovs_via_vswitchd() {
> +	type="${1}"
> +	b_addr="${2}"
> +
> +	run_cmd ovs-vsctl add-port ovs_br0 ${type}_a -- \
> +		set interface ${type}_a type=${type} \
> +		options:remote_ip=${b_addr} options:key=1 options:csum=true || return 1
> +}
> +
>  setup_ovs_vxlan_or_geneve() {
>  	type="${1}"
>  	a_addr="${2}"
>  	b_addr="${3}"
> +	dport="6081"
>  
>  	if [ "${type}" = "vxlan" ]; then
> +		dport="4789"
>  		opts="${opts} ttl 64 dstport 4789"
>  		opts_b="local ${b_addr}"
>  	fi
>  
> -	run_cmd ovs-vsctl add-port ovs_br0 ${type}_a -- \
> -		set interface ${type}_a type=${type} \
> -		options:remote_ip=${b_addr} options:key=1 options:csum=true || return 1
> +	setup_ovs_via_internal_utility "${type}" "${a_addr}" "${b_addr}" \
> +				       "${dport}" || \
> +	    setup_ovs_via_vswitchd "${type}" "${b_addr}" || return 1
>  
>  	run_cmd ${ns_b} ip link add ${type}_b type ${type} id 1 ${opts_b} remote ${a_addr} ${opts} || return 1
>  
>  	run_cmd ${ns_b} ip addr add ${tunnel4_b_addr}/${tunnel4_mask} dev ${type}_b
>  	run_cmd ${ns_b} ip addr add ${tunnel6_b_addr}/${tunnel6_mask} dev ${type}_b
>  
> +	run_cmd ip link set ${type}_a up
>  	run_cmd ${ns_b} ip link set ${type}_b up
>  }
>  
> @@ -880,8 +952,24 @@ setup_ovs_vxlan6() {
>  	setup_ovs_vxlan_or_geneve vxlan  ${prefix6}:${a_r1}::1 ${prefix6}:${b_r1}::1
>  }
>  
> +setup_ovs_br_internal() {
> +	run_cmd python3 ./openvswitch/ovs-dpctl.py add-dp ovs_br0 || \
> +		return 1
> +}
> +
> +setup_ovs_br_vswitchd() {
> +	run_cmd ovs-vsctl add-br ovs_br0 || return 1
> +}
> +
> +setup_ovs_add_if() {
> +	ifname="${1}"
> +	run_cmd python3 ./openvswitch/ovs-dpctl.py add-if ovs_br0 \
> +		"${ifname}" || \
> +		run_cmd ovs-vsctl add-port ovs_br0 "${ifname}"
> +}
> +
>  setup_ovs_bridge() {
> -	run_cmd ovs-vsctl add-br ovs_br0 || return $ksft_skip
> +	setup_ovs_br_internal || setup_ovs_br_vswitchd || return $ksft_skip
>  	run_cmd ip link set ovs_br0 up
>  
>  	run_cmd ${ns_c} ip link add veth_C-A type veth peer name veth_A-C
> @@ -891,7 +979,7 @@ setup_ovs_bridge() {
>  	run_cmd ${ns_c} ip link set veth_C-A up
>  	run_cmd ${ns_c} ip addr add ${veth4_c_addr}/${veth4_mask} dev veth_C-A
>  	run_cmd ${ns_c} ip addr add ${veth6_c_addr}/${veth6_mask} dev veth_C-A
> -	run_cmd ovs-vsctl add-port ovs_br0 veth_A-C
> +        setup_ovs_add_if veth_A-C

NIT: This should have been tab instead of space.  I will correct with v2.

>  	# Move veth_A-R1 to init
>  	run_cmd ${ns_a} ip link set veth_A-R1 netns 1
> @@ -922,6 +1010,18 @@ trace() {
>  	sleep 1
>  }
>  
> +cleanup_del_ovs_internal() {
> +	# squelch the output of the del-if commands since it can be wordy
> +	python3 ./openvswitch/ovs-dpctl.py del-if ovs_br0 -d true vxlan_a	>/dev/null	2>&1
> +	python3 ./openvswitch/ovs-dpctl.py del-if ovs_br0 -d true geneve_a	>/dev/null	2>&1
> +	python3 ./openvswitch/ovs-dpctl.py del-dp ovs_br0			>/dev/null	2>&1
> +}
> +
> +cleanup_del_ovs_vswitchd() {
> +	ovs-vsctl --if-exists del-port vxlan_a	2>/dev/null
> +	ovs-vsctl --if-exists del-br ovs_br0	2>/dev/null
> +}
> +
>  cleanup() {
>  	for pid in ${tcpdump_pids}; do
>  		kill ${pid}
> @@ -940,10 +1040,10 @@ cleanup() {
>  
>  	cleanup_all_ns
>  
> -	ip link del veth_A-C			2>/dev/null
> -	ip link del veth_A-R1			2>/dev/null
> -	ovs-vsctl --if-exists del-port vxlan_a	2>/dev/null
> -	ovs-vsctl --if-exists del-br ovs_br0	2>/dev/null
> +	ip link del veth_A-C		2>/dev/null
> +	ip link del veth_A-R1		2>/dev/null
> +	cleanup_del_ovs_internal
> +	cleanup_del_ovs_vswitchd
>  	rm -f "$tmpoutfile"
>  }
>  
> @@ -1397,6 +1497,12 @@ test_pmtu_ipvX_over_ovs_vxlanY_or_geneveY_exception() {
>  	outer_family=${3}
>  	ll_mtu=4000
>  
> +	if [ "${type}" = "vxlan" ]; then
> +		tun_a="vxlan_sys_4789"
> +	elif [ "${type}" = "geneve" ]; then
> +		tun_a="genev_sys_6081"
> +	fi
> +
>  	if [ ${outer_family} -eq 4 ]; then
>  		setup namespaces routing ovs_bridge ovs_${type}4 || return $ksft_skip
>  		#                      IPv4 header   UDP header   VXLAN/GENEVE header   Ethernet header
> @@ -1407,17 +1513,11 @@ test_pmtu_ipvX_over_ovs_vxlanY_or_geneveY_exception() {
>  		exp_mtu=$((${ll_mtu} - 40          - 8          - 8                   - 14))
>  	fi
>  
> -	if [ "${type}" = "vxlan" ]; then
> -		tun_a="vxlan_sys_4789"
> -	elif [ "${type}" = "geneve" ]; then
> -		tun_a="genev_sys_6081"
> -	fi
> -
> -	trace ""        "${tun_a}"  "${ns_b}"  ${type}_b \
> -	      ""        veth_A-R1   "${ns_r1}" veth_R1-A \
> -	      "${ns_b}" veth_B-R1   "${ns_r1}" veth_R1-B \
> -	      ""        ovs_br0     ""         veth-A-C  \
> -	      "${ns_c}" veth_C-A
> +	trace ""        ${type}_a    "${ns_b}"  ${type}_b \
> +	      ""        veth_A-R1    "${ns_r1}" veth_R1-A \
> +	      "${ns_b}" veth_B-R1    "${ns_r1}" veth_R1-B \
> +	      ""        ovs_br0      ""         veth-A_C  \
> +	      "${ns_c}" veth_C-A     ""         "${tun_a}"
>  
>  	if [ ${family} -eq 4 ]; then
>  		ping=ping
> @@ -1436,8 +1536,9 @@ test_pmtu_ipvX_over_ovs_vxlanY_or_geneveY_exception() {
>  	mtu "${ns_b}"  veth_B-R1 ${ll_mtu}
>  	mtu "${ns_r1}" veth_R1-B ${ll_mtu}
>  
> -	mtu ""        ${tun_a}  $((${ll_mtu} + 1000))
> -	mtu "${ns_b}" ${type}_b $((${ll_mtu} + 1000))
> +	mtu ""        ${tun_a}  $((${ll_mtu} + 1000)) 2>/dev/null || \
> +		mtu ""        ${type}_a  $((${ll_mtu} + 1000)) 2>/dev/null
> +	mtu "${ns_b}" ${type}_b  $((${ll_mtu} + 1000))
>  
>  	run_cmd ${ns_c} ${ping} -q -M want -i 0.1 -c 20 -s $((${ll_mtu} + 500)) ${dst} || return 1