162306a36Sopenharmony_ci#!/bin/bash
262306a36Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0
362306a36Sopenharmony_ci
462306a36Sopenharmony_ciret=0
562306a36Sopenharmony_ciksft_skip=4
662306a36Sopenharmony_ciipv6=true
762306a36Sopenharmony_ci
862306a36Sopenharmony_cioptstring="h4"
962306a36Sopenharmony_ciusage() {
1062306a36Sopenharmony_ci	echo "Usage: $0 [OPTION]"
1162306a36Sopenharmony_ci	echo -e "\t-4: IPv4 only: disable IPv6 tests (default: test both IPv4 and IPv6)"
1262306a36Sopenharmony_ci}
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ciwhile getopts "$optstring" option;do
1562306a36Sopenharmony_ci	case "$option" in
1662306a36Sopenharmony_ci	"h")
1762306a36Sopenharmony_ci		usage $0
1862306a36Sopenharmony_ci		exit 0
1962306a36Sopenharmony_ci		;;
2062306a36Sopenharmony_ci	"4")
2162306a36Sopenharmony_ci		ipv6=false
2262306a36Sopenharmony_ci		;;
2362306a36Sopenharmony_ci	"?")
2462306a36Sopenharmony_ci		usage $0
2562306a36Sopenharmony_ci		exit 1
2662306a36Sopenharmony_ci		;;
2762306a36Sopenharmony_ciesac
2862306a36Sopenharmony_cidone
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_cisec=$(date +%s)
3162306a36Sopenharmony_cirndh=$(printf %x $sec)-$(mktemp -u XXXXXX)
3262306a36Sopenharmony_cins1="ns1-$rndh"
3362306a36Sopenharmony_cins2="ns2-$rndh"
3462306a36Sopenharmony_cins3="ns3-$rndh"
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_cicleanup()
3762306a36Sopenharmony_ci{
3862306a36Sopenharmony_ci	local netns
3962306a36Sopenharmony_ci	for netns in "$ns1" "$ns2" "$ns3" ;do
4062306a36Sopenharmony_ci		ip netns del $netns
4162306a36Sopenharmony_ci	done
4262306a36Sopenharmony_ci}
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci# $1: IP address
4562306a36Sopenharmony_ciis_v6()
4662306a36Sopenharmony_ci{
4762306a36Sopenharmony_ci	[ -z "${1##*:*}" ]
4862306a36Sopenharmony_ci}
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_cido_ping()
5162306a36Sopenharmony_ci{
5262306a36Sopenharmony_ci	local netns="$1"
5362306a36Sopenharmony_ci	local connect_addr="$2"
5462306a36Sopenharmony_ci	local ping_args="-q -c 2"
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	if is_v6 "${connect_addr}"; then
5762306a36Sopenharmony_ci		$ipv6 || return 0
5862306a36Sopenharmony_ci		ping_args="${ping_args} -6"
5962306a36Sopenharmony_ci	fi
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	ip netns exec ${netns} ping ${ping_args} $connect_addr >/dev/null
6262306a36Sopenharmony_ci	if [ $? -ne 0 ] ; then
6362306a36Sopenharmony_ci		echo "$netns -> $connect_addr connectivity [ FAIL ]" 1>&2
6462306a36Sopenharmony_ci		ret=1
6562306a36Sopenharmony_ci		return 1
6662306a36Sopenharmony_ci	fi
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	return 0
6962306a36Sopenharmony_ci}
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_cido_ping_long()
7262306a36Sopenharmony_ci{
7362306a36Sopenharmony_ci	local netns="$1"
7462306a36Sopenharmony_ci	local connect_addr="$2"
7562306a36Sopenharmony_ci	local ping_args="-q -c 10"
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	if is_v6 "${connect_addr}"; then
7862306a36Sopenharmony_ci		$ipv6 || return 0
7962306a36Sopenharmony_ci		ping_args="${ping_args} -6"
8062306a36Sopenharmony_ci	fi
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	OUT="$(LANG=C ip netns exec ${netns} ping ${ping_args} $connect_addr | grep received)"
8362306a36Sopenharmony_ci	if [ $? -ne 0 ] ; then
8462306a36Sopenharmony_ci		echo "$netns -> $connect_addr ping [ FAIL ]" 1>&2
8562306a36Sopenharmony_ci		ret=1
8662306a36Sopenharmony_ci		return 1
8762306a36Sopenharmony_ci	fi
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	VAL="$(echo $OUT | cut -d' ' -f1-8)"
9062306a36Sopenharmony_ci	if [ "$VAL" != "10 packets transmitted, 10 received, 0% packet loss," ]
9162306a36Sopenharmony_ci	then
9262306a36Sopenharmony_ci		echo "$netns -> $connect_addr ping TEST [ FAIL ]"
9362306a36Sopenharmony_ci		echo "Expect to send and receive 10 packets and no duplicates."
9462306a36Sopenharmony_ci		echo "Full message: ${OUT}."
9562306a36Sopenharmony_ci		ret=1
9662306a36Sopenharmony_ci		return 1
9762306a36Sopenharmony_ci	fi
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	return 0
10062306a36Sopenharmony_ci}
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_cistop_if_error()
10362306a36Sopenharmony_ci{
10462306a36Sopenharmony_ci	local msg="$1"
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	if [ ${ret} -ne 0 ]; then
10762306a36Sopenharmony_ci		echo "FAIL: ${msg}" 1>&2
10862306a36Sopenharmony_ci		exit ${ret}
10962306a36Sopenharmony_ci	fi
11062306a36Sopenharmony_ci}
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_cido_complete_ping_test()
11362306a36Sopenharmony_ci{
11462306a36Sopenharmony_ci	echo "INFO: Initial validation ping."
11562306a36Sopenharmony_ci	# Each node has to be able each one.
11662306a36Sopenharmony_ci	do_ping "$ns1" 100.64.0.2
11762306a36Sopenharmony_ci	do_ping "$ns2" 100.64.0.1
11862306a36Sopenharmony_ci	do_ping "$ns3" 100.64.0.1
11962306a36Sopenharmony_ci	stop_if_error "Initial validation failed."
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci	do_ping "$ns1" 100.64.0.3
12262306a36Sopenharmony_ci	do_ping "$ns2" 100.64.0.3
12362306a36Sopenharmony_ci	do_ping "$ns3" 100.64.0.2
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	do_ping "$ns1" dead:beef:1::2
12662306a36Sopenharmony_ci	do_ping "$ns1" dead:beef:1::3
12762306a36Sopenharmony_ci	do_ping "$ns2" dead:beef:1::1
12862306a36Sopenharmony_ci	do_ping "$ns2" dead:beef:1::2
12962306a36Sopenharmony_ci	do_ping "$ns3" dead:beef:1::1
13062306a36Sopenharmony_ci	do_ping "$ns3" dead:beef:1::2
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci	stop_if_error "Initial validation failed."
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci# Wait until supervisor all supervision frames have been processed and the node
13562306a36Sopenharmony_ci# entries have been merged. Otherwise duplicate frames will be observed which is
13662306a36Sopenharmony_ci# valid at this stage.
13762306a36Sopenharmony_ci	WAIT=5
13862306a36Sopenharmony_ci	while [ ${WAIT} -gt 0 ]
13962306a36Sopenharmony_ci	do
14062306a36Sopenharmony_ci		grep 00:00:00:00:00:00 /sys/kernel/debug/hsr/hsr*/node_table
14162306a36Sopenharmony_ci		if [ $? -ne 0 ]
14262306a36Sopenharmony_ci		then
14362306a36Sopenharmony_ci			break
14462306a36Sopenharmony_ci		fi
14562306a36Sopenharmony_ci		sleep 1
14662306a36Sopenharmony_ci		let "WAIT = WAIT - 1"
14762306a36Sopenharmony_ci	done
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci# Just a safety delay in case the above check didn't handle it.
15062306a36Sopenharmony_ci	sleep 1
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	echo "INFO: Longer ping test."
15362306a36Sopenharmony_ci	do_ping_long "$ns1" 100.64.0.2
15462306a36Sopenharmony_ci	do_ping_long "$ns1" dead:beef:1::2
15562306a36Sopenharmony_ci	do_ping_long "$ns1" 100.64.0.3
15662306a36Sopenharmony_ci	do_ping_long "$ns1" dead:beef:1::3
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci	stop_if_error "Longer ping test failed."
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci	do_ping_long "$ns2" 100.64.0.1
16162306a36Sopenharmony_ci	do_ping_long "$ns2" dead:beef:1::1
16262306a36Sopenharmony_ci	do_ping_long "$ns2" 100.64.0.3
16362306a36Sopenharmony_ci	do_ping_long "$ns2" dead:beef:1::2
16462306a36Sopenharmony_ci	stop_if_error "Longer ping test failed."
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci	do_ping_long "$ns3" 100.64.0.1
16762306a36Sopenharmony_ci	do_ping_long "$ns3" dead:beef:1::1
16862306a36Sopenharmony_ci	do_ping_long "$ns3" 100.64.0.2
16962306a36Sopenharmony_ci	do_ping_long "$ns3" dead:beef:1::2
17062306a36Sopenharmony_ci	stop_if_error "Longer ping test failed."
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci	echo "INFO: Cutting one link."
17362306a36Sopenharmony_ci	do_ping_long "$ns1" 100.64.0.3 &
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci	sleep 3
17662306a36Sopenharmony_ci	ip -net "$ns3" link set ns3eth1 down
17762306a36Sopenharmony_ci	wait
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci	ip -net "$ns3" link set ns3eth1 up
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci	stop_if_error "Failed with one link down."
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci	echo "INFO: Delay the link and drop a few packages."
18462306a36Sopenharmony_ci	tc -net "$ns3" qdisc add dev ns3eth1 root netem delay 50ms
18562306a36Sopenharmony_ci	tc -net "$ns2" qdisc add dev ns2eth1 root netem delay 5ms loss 25%
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	do_ping_long "$ns1" 100.64.0.2
18862306a36Sopenharmony_ci	do_ping_long "$ns1" 100.64.0.3
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci	stop_if_error "Failed with delay and packetloss."
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci	do_ping_long "$ns2" 100.64.0.1
19362306a36Sopenharmony_ci	do_ping_long "$ns2" 100.64.0.3
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci	stop_if_error "Failed with delay and packetloss."
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci	do_ping_long "$ns3" 100.64.0.1
19862306a36Sopenharmony_ci	do_ping_long "$ns3" 100.64.0.2
19962306a36Sopenharmony_ci	stop_if_error "Failed with delay and packetloss."
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci	echo "INFO: All good."
20262306a36Sopenharmony_ci}
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_cisetup_hsr_interfaces()
20562306a36Sopenharmony_ci{
20662306a36Sopenharmony_ci	local HSRv="$1"
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci	echo "INFO: preparing interfaces for HSRv${HSRv}."
20962306a36Sopenharmony_ci# Three HSR nodes. Each node has one link to each of its neighbour, two links in total.
21062306a36Sopenharmony_ci#
21162306a36Sopenharmony_ci#    ns1eth1 ----- ns2eth1
21262306a36Sopenharmony_ci#      hsr1         hsr2
21362306a36Sopenharmony_ci#    ns1eth2       ns2eth2
21462306a36Sopenharmony_ci#       |            |
21562306a36Sopenharmony_ci#    ns3eth1      ns3eth2
21662306a36Sopenharmony_ci#           \    /
21762306a36Sopenharmony_ci#            hsr3
21862306a36Sopenharmony_ci#
21962306a36Sopenharmony_ci	# Interfaces
22062306a36Sopenharmony_ci	ip link add ns1eth1 netns "$ns1" type veth peer name ns2eth1 netns "$ns2"
22162306a36Sopenharmony_ci	ip link add ns1eth2 netns "$ns1" type veth peer name ns3eth1 netns "$ns3"
22262306a36Sopenharmony_ci	ip link add ns3eth2 netns "$ns3" type veth peer name ns2eth2 netns "$ns2"
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	# HSRv0/1
22562306a36Sopenharmony_ci	ip -net "$ns1" link add name hsr1 type hsr slave1 ns1eth1 slave2 ns1eth2 supervision 45 version $HSRv proto 0
22662306a36Sopenharmony_ci	ip -net "$ns2" link add name hsr2 type hsr slave1 ns2eth1 slave2 ns2eth2 supervision 45 version $HSRv proto 0
22762306a36Sopenharmony_ci	ip -net "$ns3" link add name hsr3 type hsr slave1 ns3eth1 slave2 ns3eth2 supervision 45 version $HSRv proto 0
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci	# IP for HSR
23062306a36Sopenharmony_ci	ip -net "$ns1" addr add 100.64.0.1/24 dev hsr1
23162306a36Sopenharmony_ci	ip -net "$ns1" addr add dead:beef:1::1/64 dev hsr1 nodad
23262306a36Sopenharmony_ci	ip -net "$ns2" addr add 100.64.0.2/24 dev hsr2
23362306a36Sopenharmony_ci	ip -net "$ns2" addr add dead:beef:1::2/64 dev hsr2 nodad
23462306a36Sopenharmony_ci	ip -net "$ns3" addr add 100.64.0.3/24 dev hsr3
23562306a36Sopenharmony_ci	ip -net "$ns3" addr add dead:beef:1::3/64 dev hsr3 nodad
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	# All Links up
23862306a36Sopenharmony_ci	ip -net "$ns1" link set ns1eth1 up
23962306a36Sopenharmony_ci	ip -net "$ns1" link set ns1eth2 up
24062306a36Sopenharmony_ci	ip -net "$ns1" link set hsr1 up
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci	ip -net "$ns2" link set ns2eth1 up
24362306a36Sopenharmony_ci	ip -net "$ns2" link set ns2eth2 up
24462306a36Sopenharmony_ci	ip -net "$ns2" link set hsr2 up
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	ip -net "$ns3" link set ns3eth1 up
24762306a36Sopenharmony_ci	ip -net "$ns3" link set ns3eth2 up
24862306a36Sopenharmony_ci	ip -net "$ns3" link set hsr3 up
24962306a36Sopenharmony_ci}
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ciip -Version > /dev/null 2>&1
25262306a36Sopenharmony_ciif [ $? -ne 0 ];then
25362306a36Sopenharmony_ci	echo "SKIP: Could not run test without ip tool"
25462306a36Sopenharmony_ci	exit $ksft_skip
25562306a36Sopenharmony_cifi
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_citrap cleanup EXIT
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_cifor i in "$ns1" "$ns2" "$ns3" ;do
26062306a36Sopenharmony_ci	ip netns add $i || exit $ksft_skip
26162306a36Sopenharmony_ci	ip -net $i link set lo up
26262306a36Sopenharmony_cidone
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_cisetup_hsr_interfaces 0
26562306a36Sopenharmony_cido_complete_ping_test
26662306a36Sopenharmony_cicleanup
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_cifor i in "$ns1" "$ns2" "$ns3" ;do
26962306a36Sopenharmony_ci	ip netns add $i || exit $ksft_skip
27062306a36Sopenharmony_ci	ip -net $i link set lo up
27162306a36Sopenharmony_cidone
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_cisetup_hsr_interfaces 1
27462306a36Sopenharmony_cido_complete_ping_test
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ciexit $ret
277