xref: /linux/tools/testing/selftests/net/protodown.sh (revision 8d72997dab65b1e9e3220302e26eaecd9b99c02f)
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3#
4# Test the protodown mechanism. Verify basic protodown toggling, protodown
5# reasons, operational state when the lower device carrier changes, and correct
6# operational state when the lower device has no carrier.
7
8# shellcheck disable=SC1091,SC2034,SC2154,SC2317
9source lib.sh
10
11require_command jq
12
13ALL_TESTS="
14	protodown_basic_macvlan
15	protodown_basic_vxlan
16	protodown_reasons
17	protodown_lower_toggle
18	protodown_lower_down
19"
20
21operstate_get()
22{
23	local ns=$1; shift
24	local dev=$1; shift
25
26	ip -n "$ns" -j link show dev "$dev" | jq -r '.[].operstate'
27}
28
29operstate_check()
30{
31	local ns=$1; shift
32	local dev=$1; shift
33	local expected=$1; shift
34
35	local current
36	current=$(operstate_get "$ns" "$dev")
37
38	[ "$current" = "$expected" ]
39}
40
41setup_prepare()
42{
43	setup_ns NS
44	defer cleanup_all_ns
45
46	ip -n "$NS" link add name dummy0 up type dummy
47
48	ip -n "$NS" link add name macvlan0 link dummy0 up type macvlan mode bridge
49
50	ip -n "$NS" link add name vxlan0 up type vxlan id 10010 dstport 4789
51}
52
53protodown_basic()
54{
55	local dev=$1; shift
56
57	ip -n "$NS" link set dev "$dev" protodown on
58	check_err $? "Failed to set protodown on"
59
60	busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" "$dev" DOWN
61	check_err $? "Operational state is not DOWN after setting protodown"
62
63	ip -n "$NS" link set dev "$dev" protodown off
64	check_err $? "Failed to set protodown off"
65
66	busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" "$dev" UP
67	check_err $? "Operational state is not UP after clearing protodown"
68}
69
70protodown_basic_macvlan()
71{
72	RET=0
73
74	protodown_basic macvlan0
75
76	log_test "Basic protodown on/off with macvlan"
77}
78
79protodown_basic_vxlan()
80{
81	RET=0
82
83	protodown_basic vxlan0
84
85	log_test "Basic protodown on/off with vxlan"
86}
87
88protodown_reasons()
89{
90	RET=0
91
92	ip -n "$NS" link set dev macvlan0 protodown on
93
94	ip -n "$NS" link set dev macvlan0 protodown_reason 0 on
95	check_err $? "Failed to set protodown reason bit 0"
96
97	# Cannot clear protodown while reasons are active.
98	ip -n "$NS" link set dev macvlan0 protodown off 2>/dev/null
99	check_fail $? "Clearing protodown succeeded with active reasons"
100
101	ip -n "$NS" link set dev macvlan0 protodown_reason 0 off
102	check_err $? "Failed to clear protodown reason bit 0"
103
104	# Can clear protodown when no reasons are active.
105	ip -n "$NS" link set dev macvlan0 protodown off
106	check_err $? "Failed to clear protodown with no active reasons"
107
108	busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" macvlan0 UP
109	check_err $? "Operational state is not UP after clearing protodown"
110
111	log_test "Protodown reasons"
112}
113
114protodown_lower_toggle()
115{
116	RET=0
117
118	ip -n "$NS" link set dev macvlan0 protodown on
119
120	busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" macvlan0 DOWN
121	check_err $? "Operational state is not DOWN after setting protodown"
122
123	# Toggle carrier on the lower device. The macvlan should stay DOWN
124	# because protodown is on.
125	ip -n "$NS" link set dev dummy0 carrier off
126	ip -n "$NS" link set dev dummy0 carrier on
127
128	busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" dummy0 UP
129	check_err $? "Lower device is not UP after carrier on"
130
131	busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" macvlan0 DOWN
132	check_err $? "Macvlan operational state is not DOWN despite protodown"
133
134	# Clear protodown and verify the macvlan comes back up.
135	ip -n "$NS" link set dev macvlan0 protodown off
136
137	busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" macvlan0 UP
138	check_err $? "Operational state is not UP after clearing protodown"
139
140	log_test "Protodown with lower device toggled"
141}
142
143protodown_lower_down()
144{
145	RET=0
146
147	# Bring the lower device carrier down first.
148	ip -n "$NS" link set dev dummy0 carrier off
149
150	busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" macvlan0 LOWERLAYERDOWN
151	check_err $? "Macvlan is not LOWERLAYERDOWN with lower carrier off"
152
153	# Toggle protodown on and off while lower has no carrier. The macvlan
154	# should not transition to UP.
155	ip -n "$NS" link set dev macvlan0 protodown on
156
157	busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" macvlan0 LOWERLAYERDOWN
158	check_err $? "Macvlan is not LOWERLAYERDOWN after setting protodown"
159
160	ip -n "$NS" link set dev macvlan0 protodown off
161
162	busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" macvlan0 LOWERLAYERDOWN
163	check_err $? "Macvlan is not LOWERLAYERDOWN after clearing protodown"
164
165	# Bring the lower device carrier up. The macvlan should transition to
166	# UP.
167	ip -n "$NS" link set dev dummy0 carrier on
168
169	busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" dummy0 UP
170	check_err $? "Lower device is not UP after carrier on"
171
172	busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" macvlan0 UP
173	check_err $? "Macvlan is not UP after lower device is UP"
174
175	log_test "Protodown with lower device down"
176}
177
178trap defer_scopes_cleanup EXIT
179setup_prepare
180tests_run
181
182exit "$EXIT_STATUS"
183