| #!/bin/bash |
| # SPDX-License-Identifier: GPL-2.0 |
| # |
| # Test the protodown mechanism. Verify basic protodown toggling, protodown |
| # reasons, operational state when the lower device carrier changes, and correct |
| # operational state when the lower device has no carrier. |
| |
| # shellcheck disable=SC1091,SC2034,SC2154,SC2317 |
| source lib.sh |
| |
| require_command jq |
| |
| ALL_TESTS=" |
| protodown_basic_macvlan |
| protodown_basic_vxlan |
| protodown_reasons |
| protodown_lower_toggle |
| protodown_lower_down |
| " |
| |
| operstate_get() |
| { |
| local ns=$1; shift |
| local dev=$1; shift |
| |
| ip -n "$ns" -j link show dev "$dev" | jq -r '.[].operstate' |
| } |
| |
| operstate_check() |
| { |
| local ns=$1; shift |
| local dev=$1; shift |
| local expected=$1; shift |
| |
| local current |
| current=$(operstate_get "$ns" "$dev") |
| |
| [ "$current" = "$expected" ] |
| } |
| |
| setup_prepare() |
| { |
| setup_ns NS |
| defer cleanup_all_ns |
| |
| ip -n "$NS" link add name dummy0 up type dummy |
| |
| ip -n "$NS" link add name macvlan0 link dummy0 up type macvlan mode bridge |
| |
| ip -n "$NS" link add name vxlan0 up type vxlan id 10010 dstport 4789 |
| } |
| |
| protodown_basic() |
| { |
| local dev=$1; shift |
| |
| ip -n "$NS" link set dev "$dev" protodown on |
| check_err $? "Failed to set protodown on" |
| |
| busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" "$dev" DOWN |
| check_err $? "Operational state is not DOWN after setting protodown" |
| |
| ip -n "$NS" link set dev "$dev" protodown off |
| check_err $? "Failed to set protodown off" |
| |
| busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" "$dev" UP |
| check_err $? "Operational state is not UP after clearing protodown" |
| } |
| |
| protodown_basic_macvlan() |
| { |
| RET=0 |
| |
| protodown_basic macvlan0 |
| |
| log_test "Basic protodown on/off with macvlan" |
| } |
| |
| protodown_basic_vxlan() |
| { |
| RET=0 |
| |
| protodown_basic vxlan0 |
| |
| log_test "Basic protodown on/off with vxlan" |
| } |
| |
| protodown_reasons() |
| { |
| RET=0 |
| |
| ip -n "$NS" link set dev macvlan0 protodown on |
| |
| ip -n "$NS" link set dev macvlan0 protodown_reason 0 on |
| check_err $? "Failed to set protodown reason bit 0" |
| |
| # Cannot clear protodown while reasons are active. |
| ip -n "$NS" link set dev macvlan0 protodown off 2>/dev/null |
| check_fail $? "Clearing protodown succeeded with active reasons" |
| |
| ip -n "$NS" link set dev macvlan0 protodown_reason 0 off |
| check_err $? "Failed to clear protodown reason bit 0" |
| |
| # Can clear protodown when no reasons are active. |
| ip -n "$NS" link set dev macvlan0 protodown off |
| check_err $? "Failed to clear protodown with no active reasons" |
| |
| busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" macvlan0 UP |
| check_err $? "Operational state is not UP after clearing protodown" |
| |
| log_test "Protodown reasons" |
| } |
| |
| protodown_lower_toggle() |
| { |
| RET=0 |
| |
| ip -n "$NS" link set dev macvlan0 protodown on |
| |
| busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" macvlan0 DOWN |
| check_err $? "Operational state is not DOWN after setting protodown" |
| |
| # Toggle carrier on the lower device. The macvlan should stay DOWN |
| # because protodown is on. |
| ip -n "$NS" link set dev dummy0 carrier off |
| ip -n "$NS" link set dev dummy0 carrier on |
| |
| busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" dummy0 UP |
| check_err $? "Lower device is not UP after carrier on" |
| |
| busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" macvlan0 DOWN |
| check_err $? "Macvlan operational state is not DOWN despite protodown" |
| |
| # Clear protodown and verify the macvlan comes back up. |
| ip -n "$NS" link set dev macvlan0 protodown off |
| |
| busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" macvlan0 UP |
| check_err $? "Operational state is not UP after clearing protodown" |
| |
| log_test "Protodown with lower device toggled" |
| } |
| |
| protodown_lower_down() |
| { |
| RET=0 |
| |
| # Bring the lower device carrier down first. |
| ip -n "$NS" link set dev dummy0 carrier off |
| |
| busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" macvlan0 LOWERLAYERDOWN |
| check_err $? "Macvlan is not LOWERLAYERDOWN with lower carrier off" |
| |
| # Toggle protodown on and off while lower has no carrier. The macvlan |
| # should not transition to UP. |
| ip -n "$NS" link set dev macvlan0 protodown on |
| |
| busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" macvlan0 LOWERLAYERDOWN |
| check_err $? "Macvlan is not LOWERLAYERDOWN after setting protodown" |
| |
| ip -n "$NS" link set dev macvlan0 protodown off |
| |
| busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" macvlan0 LOWERLAYERDOWN |
| check_err $? "Macvlan is not LOWERLAYERDOWN after clearing protodown" |
| |
| # Bring the lower device carrier up. The macvlan should transition to |
| # UP. |
| ip -n "$NS" link set dev dummy0 carrier on |
| |
| busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" dummy0 UP |
| check_err $? "Lower device is not UP after carrier on" |
| |
| busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" macvlan0 UP |
| check_err $? "Macvlan is not UP after lower device is UP" |
| |
| log_test "Protodown with lower device down" |
| } |
| |
| trap defer_scopes_cleanup EXIT |
| setup_prepare |
| tests_run |
| |
| exit "$EXIT_STATUS" |