Add regression test for multipath routing.
authorbluhm <bluhm@openbsd.org>
Tue, 20 Feb 2024 20:04:51 +0000 (20:04 +0000)
committerbluhm <bluhm@openbsd.org>
Tue, 20 Feb 2024 20:04:51 +0000 (20:04 +0000)
Test that routes set with the -mpath flag distribute the traffic.
Each route has a different gateway and the UDP packets have different
source addresses.  The destination address is identical for all
routes and packets.  Analyze the use counter in netstat -r output
to check that multiple routes have been used.  Currently this works
only for IPv4.  sysctl net.inet.ip.multipath and net.inet6.ip6.multipath
are enabled before testing and reset afterwards.  All routes and
interface addresses are created on loopback in a separate routing
domain.

regress/sys/net/mpath/Makefile [new file with mode: 0644]

diff --git a/regress/sys/net/mpath/Makefile b/regress/sys/net/mpath/Makefile
new file mode 100644 (file)
index 0000000..1f7ae80
--- /dev/null
@@ -0,0 +1,166 @@
+#      $OpenBSD: Makefile,v 1.1 2024/02/20 20:04:51 bluhm Exp $
+
+# Copyright (c) 2024 Alexander Bluhm <bluhm@openbsd.org>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+# Regression test for multipath routing.
+
+# Test that routes set with the -mpath flag distribute the traffic.
+# Each route has a different gateway and the UDP packets have different
+# source addresses.  The destination address is identical for all
+# routes and packets.  Analyze the use counter in netstat -r output
+# to check that multiple routes have been used.  Currently this works
+# only for IPv4.  sysctl net.inet.ip.multipath and net.inet6.ip6.multipath
+# are enabled before testing and reset afterwards.  All routes and
+# interface addresses are created on loopback in a separate routing
+# domain.
+
+# Set up loopback interface in a different routing domain.
+# Create multipath routes on this loopback.
+# Send a bunch of packets with multiple source IP to same destination.
+# Count in netstart -r that most routes have been used.
+
+# This test uses routing domain and interface number 11.
+# Adjust it here, if you want to use something else.
+N1 =           11
+NUMS =         ${N1}
+
+# Traffic distribution has not been implemented for IPv6.
+REGRESS_EXPECTED_FAILURES +=   run-netstat6
+
+.include <bsd.own.mk>
+
+.PHONY: busy-rdomains ifconfig unconfig pfctl
+
+REGRESS_SETUP_ONCE +=  busy-rdomains
+busy-rdomains:
+       # Check if rdomains are busy.
+.for n in ${NUMS}
+       @if /sbin/ifconfig | grep -v '^lo$n:' | grep ' rdomain $n '; then\
+           echo routing domain $n is already used >&2; exit 1; fi
+.endfor
+
+REGRESS_SETUP_ONCE +=  multipath
+multipath:
+       ${SUDO} /sbin/sysctl net.inet.ip.multipath=1
+       ${SUDO} /sbin/sysctl net.inet6.ip6.multipath=1
+
+REGRESS_CLEANUP +=     singlepath
+singlepath:
+       ${SUDO} /sbin/sysctl net.inet.ip.multipath=0
+       ${SUDO} /sbin/sysctl net.inet6.ip6.multipath=0
+
+REGRESS_SETUP_ONCE +=  ifconfig
+ifconfig: unconfig
+       # Create and configure loopback interfaces.
+.for n in ${NUMS}
+       ${SUDO} /sbin/ifconfig lo$n rdomain $n
+       ${SUDO} /sbin/ifconfig lo$n inet 10.0.0.1/8
+       ${SUDO} /sbin/ifconfig lo$n inet 10.0.0.$n alias
+.for i in 0 1 2 3 4 5 6 7 8 9
+       ${SUDO} /sbin/ifconfig lo$n inet 10.0.$n.$i alias
+       ${SUDO} /sbin/route -n -T $n add -inet -blackhole -mpath -host \
+           10.$n.0.0 10.0.$n.$i
+.endfor
+       ${SUDO} /sbin/ifconfig lo$n inet6 fc00::$n alias
+.for i in 0 1 2 3 4 5 6 7 8 9
+       ${SUDO} /sbin/ifconfig lo$n inet6 fc00::$n:$i alias
+       ${SUDO} /sbin/route -n -T $n add -inet6 -blackhole -mpath -host \
+           fc00::$n:0:0 fc00::$n:$i
+.endfor
+       # Wait until IPv6 addresses are no longer tentative.
+       for i in `jot 50`; do\
+           if ! /sbin/ifconfig lo$n | fgrep -q tentative; then\
+                   break;\
+           fi;\
+           sleep .1;\
+       done
+       ! /sbin/ifconfig lo${N1} | fgrep tentative
+.endfor
+
+REGRESS_CLEANUP +=     unconfig
+unconfig:
+       # Destroy interfaces.
+.for n in ${NUMS}
+       -${SUDO} /sbin/ifconfig lo$n rdomain $n
+.for i in 0 1 2 3 4 5 6 7 8 9
+       -${SUDO} /sbin/route -n -T $n delete -inet6 -host \
+           fc00::$n:0:0 fc00::$n:$i
+       -${SUDO} /sbin/route -n -T $n delete -inet -host \
+           10.$n.0.0 10.0.$n.$i
+.endfor
+       -${SUDO} /sbin/ifconfig lo$n -inet -inet6
+       -${SUDO} /sbin/ifconfig lo$n destroy
+.endfor
+       rm -f stamp-ifconfig
+
+REGRESS_TARGETS +=     run-netcat
+run-netcat netstat.log:
+       # count UDP IPv6 packets used with multipath routes
+       rm -f netstat.log
+.for i in 0 1 2 3 4 5 6 7 8 9
+       /usr/bin/nc -4 -V${N1} -u -z -s10.0.${N1}.$i 10.${N1}.0.0 discard
+.endfor
+       /usr/bin/netstat -T${N1} -f inet -rn >netstat.log
+
+REGRESS_TARGETS +=     run-netstat
+run-netstat: netstat.log
+       # check route distribution of IPv4 packets
+       awk 'BEGIN{ mpath = uses = used = maxuse = 0; }\
+           /^10.${N1}.0.0 /{\
+               if ($$3 == "UGHSBP") mpath++;\
+               if ($$5 > 0) used++;\
+               if ($$5 > max) max = $$5;\
+               uses += $$5;\
+           }\
+           END{\
+               print "mpath "mpath", uses "uses", max "max", used "used;\
+               if (mpath != 10) { print "not 10 mpath: " mpath; exit 1; }\
+               if (uses != 10) { print "not 10 uses: " uses; exit 1; }\
+               if (max > 5) { print "max more than 5: " max; exit 1; }\
+               if (used < 5) { print "used less than 5: " used; exit 1; }\
+           }' \
+           netstat.log
+
+REGRESS_TARGETS +=     run-netcat6
+run-netcat6 netstat6.log:
+       # count UDP IPv6 packets used with multipath routes
+       rm -f netstat6.log
+.for i in 0 1 2 3 4 5 6 7 8 9
+       /usr/bin/nc -6 -V${N1} -u -z -sfc00::${N1}:$i fc00::${N1}:0:0 discard
+.endfor
+       /usr/bin/netstat -T${N1} -f inet6 -rn >netstat6.log
+
+REGRESS_TARGETS +=     run-netstat6
+run-netstat6: netstat6.log
+       # check route distribution of IPv6 packets
+       awk 'BEGIN{ mpath = used = uses = max = 0; }\
+           /^fc00::${N1}:0:0 /{\
+               if ($$3 == "UGHSBP") mpath++;\
+               if ($$5 > 0) used++;\
+               if ($$5 > max) max = $$5;\
+               uses += $$5;\
+           }\
+           END{\
+               print "mpath "mpath", uses "uses", max "max", used "used;\
+               if (mpath != 10) { print "not 10 mpath: " mpath; exit 1; }\
+               if (uses != 10) { print "not 10 uses: " uses; exit 1; }\
+               if (max > 5) { print "max more than 5: " max; exit 1; }\
+               if (used < 5) { print "used less than 5: " used; exit 1; }\
+           }' \
+           netstat6.log
+
+CLEANFILES +=  *.log stamp-*
+
+.include <bsd.regress.mk>