| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378 |
- #!/bin/bash
- # SPDX-License-Identifier: GPL-2.0
- # shellcheck disable=SC2329
- source ../lib.sh
- ALL_TESTS="
- test_clean_hsrv0
- test_cut_link_hsrv0
- test_packet_loss_hsrv0
- test_high_packet_loss_hsrv0
- test_reordering_hsrv0
- test_clean_hsrv1
- test_cut_link_hsrv1
- test_packet_loss_hsrv1
- test_high_packet_loss_hsrv1
- test_reordering_hsrv1
- test_clean_prp
- test_cut_link_prp
- test_packet_loss_prp
- test_high_packet_loss_prp
- test_reordering_prp
- "
- # The tests are running ping for 5sec with a relatively short interval in
- # different scenarios with faulty links (cut links, packet loss, delay,
- # reordering) that should be recoverable by HSR/PRP. The ping interval (10ms)
- # is short enough that the base delay (50ms) leads to a queue in the netem
- # qdiscs which is needed for reordering.
- setup_hsr_topo()
- {
- # Three HSR nodes in a ring, every node has a LAN A interface connected
- # to the LAN B interface of the next node.
- #
- # node1 node2
- #
- # vethA -------- vethB
- # hsr1 hsr2
- # vethB vethA
- # \ /
- # vethA vethB
- # hsr3
- #
- # node3
- local ver="$1"
- setup_ns node1 node2 node3
- # veth links
- # shellcheck disable=SC2154 # variables assigned by setup_ns
- ip link add vethA netns "$node1" type veth peer name vethB netns "$node2"
- # shellcheck disable=SC2154 # variables assigned by setup_ns
- ip link add vethA netns "$node2" type veth peer name vethB netns "$node3"
- ip link add vethA netns "$node3" type veth peer name vethB netns "$node1"
- # MAC addresses (not needed for HSR operation, but helps with debugging)
- ip -net "$node1" link set address 00:11:22:00:01:01 dev vethA
- ip -net "$node1" link set address 00:11:22:00:01:02 dev vethB
- ip -net "$node2" link set address 00:11:22:00:02:01 dev vethA
- ip -net "$node2" link set address 00:11:22:00:02:02 dev vethB
- ip -net "$node3" link set address 00:11:22:00:03:01 dev vethA
- ip -net "$node3" link set address 00:11:22:00:03:02 dev vethB
- # HSR interfaces
- ip -net "$node1" link add name hsr1 type hsr proto 0 version "$ver" \
- slave1 vethA slave2 vethB supervision 45
- ip -net "$node2" link add name hsr2 type hsr proto 0 version "$ver" \
- slave1 vethA slave2 vethB supervision 45
- ip -net "$node3" link add name hsr3 type hsr proto 0 version "$ver" \
- slave1 vethA slave2 vethB supervision 45
- # IP addresses
- ip -net "$node1" addr add 100.64.0.1/24 dev hsr1
- ip -net "$node2" addr add 100.64.0.2/24 dev hsr2
- ip -net "$node3" addr add 100.64.0.3/24 dev hsr3
- # Set all links up
- ip -net "$node1" link set vethA up
- ip -net "$node1" link set vethB up
- ip -net "$node1" link set hsr1 up
- ip -net "$node2" link set vethA up
- ip -net "$node2" link set vethB up
- ip -net "$node2" link set hsr2 up
- ip -net "$node3" link set vethA up
- ip -net "$node3" link set vethB up
- ip -net "$node3" link set hsr3 up
- }
- setup_prp_topo()
- {
- # Two PRP nodes, connected by two links (treated as LAN A and LAN B).
- #
- # vethA ----- vethA
- # prp1 prp2
- # vethB ----- vethB
- #
- # node1 node2
- setup_ns node1 node2
- # veth links
- ip link add vethA netns "$node1" type veth peer name vethA netns "$node2"
- ip link add vethB netns "$node1" type veth peer name vethB netns "$node2"
- # MAC addresses will be copied from LAN A interface
- ip -net "$node1" link set address 00:11:22:00:00:01 dev vethA
- ip -net "$node2" link set address 00:11:22:00:00:02 dev vethA
- # PRP interfaces
- ip -net "$node1" link add name prp1 type hsr \
- slave1 vethA slave2 vethB supervision 45 proto 1
- ip -net "$node2" link add name prp2 type hsr \
- slave1 vethA slave2 vethB supervision 45 proto 1
- # IP addresses
- ip -net "$node1" addr add 100.64.0.1/24 dev prp1
- ip -net "$node2" addr add 100.64.0.2/24 dev prp2
- # All links up
- ip -net "$node1" link set vethA up
- ip -net "$node1" link set vethB up
- ip -net "$node1" link set prp1 up
- ip -net "$node2" link set vethA up
- ip -net "$node2" link set vethB up
- ip -net "$node2" link set prp2 up
- }
- wait_for_hsr_node_table()
- {
- log_info "Wait for node table entries to be merged."
- WAIT=5
- while [ "${WAIT}" -gt 0 ]; do
- nts=$(cat /sys/kernel/debug/hsr/hsr*/node_table)
- # We need entries in the node tables, and they need to be merged
- if (echo "$nts" | grep -qE "^([0-9a-f]{2}:){5}") && \
- ! (echo "$nts" | grep -q "00:00:00:00:00:00"); then
- return
- fi
- sleep 1
- ((WAIT--))
- done
- check_err 1 "Failed to wait for merged node table entries"
- }
- setup_topo()
- {
- local proto="$1"
- if [ "$proto" = "HSRv0" ]; then
- setup_hsr_topo 0
- wait_for_hsr_node_table
- elif [ "$proto" = "HSRv1" ]; then
- setup_hsr_topo 1
- wait_for_hsr_node_table
- elif [ "$proto" = "PRP" ]; then
- setup_prp_topo
- else
- check_err 1 "Unknown protocol (${proto})"
- fi
- }
- check_ping()
- {
- local node="$1"
- local dst="$2"
- local accepted_dups="$3"
- local ping_args="-q -i 0.01 -c 400"
- log_info "Running ping $node -> $dst"
- # shellcheck disable=SC2086
- output=$(ip netns exec "$node" ping $ping_args "$dst" | \
- grep "packets transmitted")
- log_info "$output"
- dups=0
- loss=0
- if [[ "$output" =~ \+([0-9]+)" duplicates" ]]; then
- dups="${BASH_REMATCH[1]}"
- fi
- if [[ "$output" =~ ([0-9\.]+\%)" packet loss" ]]; then
- loss="${BASH_REMATCH[1]}"
- fi
- if [ "$dups" -gt "$accepted_dups" ]; then
- check_err 1 "Unexpected duplicate packets (${dups})"
- fi
- if [ "$loss" != "0%" ]; then
- check_err 1 "Unexpected packet loss (${loss})"
- fi
- }
- test_clean()
- {
- local proto="$1"
- RET=0
- tname="${FUNCNAME[0]} - ${proto}"
- setup_topo "$proto"
- if ((RET != ksft_pass)); then
- log_test "${tname} setup"
- return
- fi
- check_ping "$node1" "100.64.0.2" 0
- log_test "${tname}"
- }
- test_clean_hsrv0()
- {
- test_clean "HSRv0"
- }
- test_clean_hsrv1()
- {
- test_clean "HSRv1"
- }
- test_clean_prp()
- {
- test_clean "PRP"
- }
- test_cut_link()
- {
- local proto="$1"
- RET=0
- tname="${FUNCNAME[0]} - ${proto}"
- setup_topo "$proto"
- if ((RET != ksft_pass)); then
- log_test "${tname} setup"
- return
- fi
- # Cutting link from subshell, so check_ping can run in the normal shell
- # with access to global variables from the test harness.
- (
- sleep 2
- log_info "Cutting link"
- ip -net "$node1" link set vethB down
- ) &
- check_ping "$node1" "100.64.0.2" 0
- wait
- log_test "${tname}"
- }
- test_cut_link_hsrv0()
- {
- test_cut_link "HSRv0"
- }
- test_cut_link_hsrv1()
- {
- test_cut_link "HSRv1"
- }
- test_cut_link_prp()
- {
- test_cut_link "PRP"
- }
- test_packet_loss()
- {
- local proto="$1"
- local loss="$2"
- RET=0
- tname="${FUNCNAME[0]} - ${proto}, ${loss}"
- setup_topo "$proto"
- if ((RET != ksft_pass)); then
- log_test "${tname} setup"
- return
- fi
- # Packet loss with lower delay makes sure the packets on the lossy link
- # arrive first.
- tc -net "$node1" qdisc add dev vethA root netem delay 50ms
- tc -net "$node1" qdisc add dev vethB root netem delay 20ms loss "$loss"
- check_ping "$node1" "100.64.0.2" 40
- log_test "${tname}"
- }
- test_packet_loss_hsrv0()
- {
- test_packet_loss "HSRv0" "20%"
- }
- test_packet_loss_hsrv1()
- {
- test_packet_loss "HSRv1" "20%"
- }
- test_packet_loss_prp()
- {
- test_packet_loss "PRP" "20%"
- }
- test_high_packet_loss_hsrv0()
- {
- test_packet_loss "HSRv0" "80%"
- }
- test_high_packet_loss_hsrv1()
- {
- test_packet_loss "HSRv1" "80%"
- }
- test_high_packet_loss_prp()
- {
- test_packet_loss "PRP" "80%"
- }
- test_reordering()
- {
- local proto="$1"
- RET=0
- tname="${FUNCNAME[0]} - ${proto}"
- setup_topo "$proto"
- if ((RET != ksft_pass)); then
- log_test "${tname} setup"
- return
- fi
- tc -net "$node1" qdisc add dev vethA root netem delay 50ms
- tc -net "$node1" qdisc add dev vethB root netem delay 50ms reorder 20%
- check_ping "$node1" "100.64.0.2" 40
- log_test "${tname}"
- }
- test_reordering_hsrv0()
- {
- test_reordering "HSRv0"
- }
- test_reordering_hsrv1()
- {
- test_reordering "HSRv1"
- }
- test_reordering_prp()
- {
- test_reordering "PRP"
- }
- cleanup()
- {
- cleanup_all_ns
- }
- trap cleanup EXIT
- tests_run
- exit $EXIT_STATUS
|