Commit | Line | Data |
---|---|---|
bc7cbb1e PM |
1 | #!/bin/bash |
2 | # SPDX-License-Identifier: GPL-2.0 | |
3 | ||
bc7cbb1e PM |
4 | ############################################################################## |
5 | # Defines | |
6 | ||
bc030d9c IS |
7 | if [[ ! -v DEVLINK_DEV ]]; then |
8 | DEVLINK_DEV=$(devlink port show "${NETIFS[p1]}" -j \ | |
9 | | jq -r '.port | keys[]' | cut -d/ -f-2) | |
10 | if [ -z "$DEVLINK_DEV" ]; then | |
11 | echo "SKIP: ${NETIFS[p1]} has no devlink device registered for it" | |
12 | exit 1 | |
13 | fi | |
14 | if [[ "$(echo $DEVLINK_DEV | grep -c pci)" -eq 0 ]]; then | |
15 | echo "SKIP: devlink device's bus is not PCI" | |
16 | exit 1 | |
17 | fi | |
18 | ||
19 | DEVLINK_VIDDID=$(lspci -s $(echo $DEVLINK_DEV | cut -d"/" -f2) \ | |
20 | -n | cut -d" " -f3) | |
bc7cbb1e PM |
21 | fi |
22 | ||
bc7cbb1e PM |
23 | ############################################################################## |
24 | # Sanity checks | |
25 | ||
6f64bcb6 | 26 | devlink help 2>&1 | grep resource &> /dev/null |
bc7cbb1e PM |
27 | if [ $? -ne 0 ]; then |
28 | echo "SKIP: iproute2 too old, missing devlink resource support" | |
29 | exit 1 | |
30 | fi | |
31 | ||
a054c8d9 IS |
32 | devlink help 2>&1 | grep trap &> /dev/null |
33 | if [ $? -ne 0 ]; then | |
34 | echo "SKIP: iproute2 too old, missing devlink trap support" | |
35 | exit 1 | |
36 | fi | |
37 | ||
bc7cbb1e PM |
38 | ############################################################################## |
39 | # Devlink helpers | |
40 | ||
41 | devlink_resource_names_to_path() | |
42 | { | |
43 | local resource | |
44 | local path="" | |
45 | ||
46 | for resource in "${@}"; do | |
47 | if [ "$path" == "" ]; then | |
48 | path="$resource" | |
49 | else | |
50 | path="${path}/$resource" | |
51 | fi | |
52 | done | |
53 | ||
54 | echo "$path" | |
55 | } | |
56 | ||
57 | devlink_resource_get() | |
58 | { | |
59 | local name=$1 | |
60 | local resource_name=.[][\"$DEVLINK_DEV\"] | |
61 | ||
62 | resource_name="$resource_name | .[] | select (.name == \"$name\")" | |
63 | ||
64 | shift | |
65 | for resource in "${@}"; do | |
66 | resource_name="${resource_name} | .[\"resources\"][] | \ | |
67 | select (.name == \"$resource\")" | |
68 | done | |
69 | ||
70 | devlink -j resource show "$DEVLINK_DEV" | jq "$resource_name" | |
71 | } | |
72 | ||
73 | devlink_resource_size_get() | |
74 | { | |
75 | local size=$(devlink_resource_get "$@" | jq '.["size_new"]') | |
76 | ||
77 | if [ "$size" == "null" ]; then | |
78 | devlink_resource_get "$@" | jq '.["size"]' | |
79 | else | |
80 | echo "$size" | |
81 | fi | |
82 | } | |
83 | ||
84 | devlink_resource_size_set() | |
85 | { | |
86 | local new_size=$1 | |
87 | local path | |
88 | ||
89 | shift | |
90 | path=$(devlink_resource_names_to_path "$@") | |
91 | devlink resource set "$DEVLINK_DEV" path "$path" size "$new_size" | |
92 | check_err $? "Failed setting path $path to size $size" | |
93 | } | |
94 | ||
95 | devlink_reload() | |
96 | { | |
97 | local still_pending | |
98 | ||
99 | devlink dev reload "$DEVLINK_DEV" &> /dev/null | |
100 | check_err $? "Failed reload" | |
101 | ||
102 | still_pending=$(devlink resource show "$DEVLINK_DEV" | \ | |
103 | grep -c "size_new") | |
104 | check_err $still_pending "Failed reload - There are still unset sizes" | |
105 | } | |
d04cc726 PM |
106 | |
107 | declare -A DEVLINK_ORIG | |
108 | ||
109 | devlink_port_pool_threshold() | |
110 | { | |
111 | local port=$1; shift | |
112 | local pool=$1; shift | |
113 | ||
114 | devlink sb port pool show $port pool $pool -j \ | |
115 | | jq '.port_pool."'"$port"'"[].threshold' | |
116 | } | |
117 | ||
118 | devlink_port_pool_th_set() | |
119 | { | |
120 | local port=$1; shift | |
121 | local pool=$1; shift | |
122 | local th=$1; shift | |
123 | local key="port_pool($port,$pool).threshold" | |
124 | ||
125 | DEVLINK_ORIG[$key]=$(devlink_port_pool_threshold $port $pool) | |
126 | devlink sb port pool set $port pool $pool th $th | |
127 | } | |
128 | ||
129 | devlink_port_pool_th_restore() | |
130 | { | |
131 | local port=$1; shift | |
132 | local pool=$1; shift | |
133 | local key="port_pool($port,$pool).threshold" | |
134 | ||
135 | devlink sb port pool set $port pool $pool th ${DEVLINK_ORIG[$key]} | |
136 | } | |
137 | ||
138 | devlink_pool_size_thtype() | |
139 | { | |
140 | local pool=$1; shift | |
141 | ||
142 | devlink sb pool show "$DEVLINK_DEV" pool $pool -j \ | |
143 | | jq -r '.pool[][] | (.size, .thtype)' | |
144 | } | |
145 | ||
146 | devlink_pool_size_thtype_set() | |
147 | { | |
148 | local pool=$1; shift | |
149 | local thtype=$1; shift | |
150 | local size=$1; shift | |
151 | local key="pool($pool).size_thtype" | |
152 | ||
153 | DEVLINK_ORIG[$key]=$(devlink_pool_size_thtype $pool) | |
154 | devlink sb pool set "$DEVLINK_DEV" pool $pool size $size thtype $thtype | |
155 | } | |
156 | ||
157 | devlink_pool_size_thtype_restore() | |
158 | { | |
159 | local pool=$1; shift | |
160 | local key="pool($pool).size_thtype" | |
161 | local -a orig=(${DEVLINK_ORIG[$key]}) | |
162 | ||
163 | devlink sb pool set "$DEVLINK_DEV" pool $pool \ | |
164 | size ${orig[0]} thtype ${orig[1]} | |
165 | } | |
166 | ||
167 | devlink_tc_bind_pool_th() | |
168 | { | |
169 | local port=$1; shift | |
170 | local tc=$1; shift | |
171 | local dir=$1; shift | |
172 | ||
173 | devlink sb tc bind show $port tc $tc type $dir -j \ | |
174 | | jq -r '.tc_bind[][] | (.pool, .threshold)' | |
175 | } | |
176 | ||
177 | devlink_tc_bind_pool_th_set() | |
178 | { | |
179 | local port=$1; shift | |
180 | local tc=$1; shift | |
181 | local dir=$1; shift | |
182 | local pool=$1; shift | |
183 | local th=$1; shift | |
184 | local key="tc_bind($port,$dir,$tc).pool_th" | |
185 | ||
186 | DEVLINK_ORIG[$key]=$(devlink_tc_bind_pool_th $port $tc $dir) | |
187 | devlink sb tc bind set $port tc $tc type $dir pool $pool th $th | |
188 | } | |
189 | ||
190 | devlink_tc_bind_pool_th_restore() | |
191 | { | |
192 | local port=$1; shift | |
193 | local tc=$1; shift | |
194 | local dir=$1; shift | |
195 | local key="tc_bind($port,$dir,$tc).pool_th" | |
196 | local -a orig=(${DEVLINK_ORIG[$key]}) | |
197 | ||
198 | devlink sb tc bind set $port tc $tc type $dir \ | |
199 | pool ${orig[0]} th ${orig[1]} | |
200 | } | |
a054c8d9 IS |
201 | |
202 | devlink_traps_num_get() | |
203 | { | |
204 | devlink -j trap | jq '.[]["'$DEVLINK_DEV'"] | length' | |
205 | } | |
206 | ||
207 | devlink_traps_get() | |
208 | { | |
209 | devlink -j trap | jq -r '.[]["'$DEVLINK_DEV'"][].name' | |
210 | } | |
211 | ||
212 | devlink_trap_type_get() | |
213 | { | |
214 | local trap_name=$1; shift | |
215 | ||
216 | devlink -j trap show $DEVLINK_DEV trap $trap_name \ | |
217 | | jq -r '.[][][].type' | |
218 | } | |
219 | ||
220 | devlink_trap_action_set() | |
221 | { | |
222 | local trap_name=$1; shift | |
223 | local action=$1; shift | |
224 | ||
225 | # Pipe output to /dev/null to avoid expected warnings. | |
226 | devlink trap set $DEVLINK_DEV trap $trap_name \ | |
227 | action $action &> /dev/null | |
228 | } | |
229 | ||
230 | devlink_trap_action_get() | |
231 | { | |
232 | local trap_name=$1; shift | |
233 | ||
234 | devlink -j trap show $DEVLINK_DEV trap $trap_name \ | |
235 | | jq -r '.[][][].action' | |
236 | } | |
237 | ||
238 | devlink_trap_group_get() | |
239 | { | |
240 | devlink -j trap show $DEVLINK_DEV trap $trap_name \ | |
241 | | jq -r '.[][][].group' | |
242 | } | |
243 | ||
244 | devlink_trap_metadata_test() | |
245 | { | |
246 | local trap_name=$1; shift | |
247 | local metadata=$1; shift | |
248 | ||
249 | devlink -jv trap show $DEVLINK_DEV trap $trap_name \ | |
250 | | jq -e '.[][][].metadata | contains(["'$metadata'"])' \ | |
251 | &> /dev/null | |
252 | } | |
253 | ||
254 | devlink_trap_rx_packets_get() | |
255 | { | |
256 | local trap_name=$1; shift | |
257 | ||
258 | devlink -js trap show $DEVLINK_DEV trap $trap_name \ | |
259 | | jq '.[][][]["stats"]["rx"]["packets"]' | |
260 | } | |
261 | ||
262 | devlink_trap_rx_bytes_get() | |
263 | { | |
264 | local trap_name=$1; shift | |
265 | ||
266 | devlink -js trap show $DEVLINK_DEV trap $trap_name \ | |
267 | | jq '.[][][]["stats"]["rx"]["bytes"]' | |
268 | } | |
269 | ||
270 | devlink_trap_stats_idle_test() | |
271 | { | |
272 | local trap_name=$1; shift | |
273 | local t0_packets t0_bytes | |
274 | local t1_packets t1_bytes | |
275 | ||
276 | t0_packets=$(devlink_trap_rx_packets_get $trap_name) | |
277 | t0_bytes=$(devlink_trap_rx_bytes_get $trap_name) | |
278 | ||
279 | sleep 1 | |
280 | ||
281 | t1_packets=$(devlink_trap_rx_packets_get $trap_name) | |
282 | t1_bytes=$(devlink_trap_rx_bytes_get $trap_name) | |
283 | ||
284 | if [[ $t0_packets -eq $t1_packets && $t0_bytes -eq $t1_bytes ]]; then | |
285 | return 0 | |
286 | else | |
287 | return 1 | |
288 | fi | |
289 | } | |
290 | ||
291 | devlink_traps_enable_all() | |
292 | { | |
293 | local trap_name | |
294 | ||
295 | for trap_name in $(devlink_traps_get); do | |
296 | devlink_trap_action_set $trap_name "trap" | |
297 | done | |
298 | } | |
299 | ||
300 | devlink_traps_disable_all() | |
301 | { | |
302 | for trap_name in $(devlink_traps_get); do | |
303 | devlink_trap_action_set $trap_name "drop" | |
304 | done | |
305 | } | |
306 | ||
307 | devlink_trap_groups_get() | |
308 | { | |
309 | devlink -j trap group | jq -r '.[]["'$DEVLINK_DEV'"][].name' | |
310 | } | |
311 | ||
312 | devlink_trap_group_action_set() | |
313 | { | |
314 | local group_name=$1; shift | |
315 | local action=$1; shift | |
316 | ||
317 | # Pipe output to /dev/null to avoid expected warnings. | |
318 | devlink trap group set $DEVLINK_DEV group $group_name action $action \ | |
319 | &> /dev/null | |
320 | } | |
321 | ||
322 | devlink_trap_group_rx_packets_get() | |
323 | { | |
324 | local group_name=$1; shift | |
325 | ||
326 | devlink -js trap group show $DEVLINK_DEV group $group_name \ | |
327 | | jq '.[][][]["stats"]["rx"]["packets"]' | |
328 | } | |
329 | ||
330 | devlink_trap_group_rx_bytes_get() | |
331 | { | |
332 | local group_name=$1; shift | |
333 | ||
334 | devlink -js trap group show $DEVLINK_DEV group $group_name \ | |
335 | | jq '.[][][]["stats"]["rx"]["bytes"]' | |
336 | } | |
337 | ||
338 | devlink_trap_group_stats_idle_test() | |
339 | { | |
340 | local group_name=$1; shift | |
341 | local t0_packets t0_bytes | |
342 | local t1_packets t1_bytes | |
343 | ||
344 | t0_packets=$(devlink_trap_group_rx_packets_get $group_name) | |
345 | t0_bytes=$(devlink_trap_group_rx_bytes_get $group_name) | |
346 | ||
347 | sleep 1 | |
348 | ||
349 | t1_packets=$(devlink_trap_group_rx_packets_get $group_name) | |
350 | t1_bytes=$(devlink_trap_group_rx_bytes_get $group_name) | |
351 | ||
352 | if [[ $t0_packets -eq $t1_packets && $t0_bytes -eq $t1_bytes ]]; then | |
353 | return 0 | |
354 | else | |
355 | return 1 | |
356 | fi | |
357 | } | |
6b45fe95 | 358 | |
7ce4e760 AC |
359 | devlink_trap_exception_test() |
360 | { | |
361 | local trap_name=$1; shift | |
362 | local group_name=$1; shift | |
363 | ||
364 | devlink_trap_stats_idle_test $trap_name | |
365 | check_fail $? "Trap stats idle when packets should have been trapped" | |
366 | ||
367 | devlink_trap_group_stats_idle_test $group_name | |
368 | check_fail $? "Trap group idle when packets should have been trapped" | |
369 | } | |
370 | ||
6b45fe95 AC |
371 | devlink_trap_drop_test() |
372 | { | |
373 | local trap_name=$1; shift | |
374 | local group_name=$1; shift | |
375 | local dev=$1; shift | |
376 | ||
377 | # This is the common part of all the tests. It checks that stats are | |
378 | # initially idle, then non-idle after changing the trap action and | |
379 | # finally idle again. It also makes sure the packets are dropped and | |
380 | # never forwarded. | |
381 | devlink_trap_stats_idle_test $trap_name | |
382 | check_err $? "Trap stats not idle with initial drop action" | |
383 | devlink_trap_group_stats_idle_test $group_name | |
384 | check_err $? "Trap group stats not idle with initial drop action" | |
385 | ||
386 | ||
387 | devlink_trap_action_set $trap_name "trap" | |
388 | devlink_trap_stats_idle_test $trap_name | |
389 | check_fail $? "Trap stats idle after setting action to trap" | |
390 | devlink_trap_group_stats_idle_test $group_name | |
391 | check_fail $? "Trap group stats idle after setting action to trap" | |
392 | ||
393 | devlink_trap_action_set $trap_name "drop" | |
394 | ||
395 | devlink_trap_stats_idle_test $trap_name | |
396 | check_err $? "Trap stats not idle after setting action to drop" | |
397 | devlink_trap_group_stats_idle_test $group_name | |
398 | check_err $? "Trap group stats not idle after setting action to drop" | |
399 | ||
400 | tc_check_packets "dev $dev egress" 101 0 | |
401 | check_err $? "Packets were not dropped" | |
402 | } | |
403 | ||
404 | devlink_trap_drop_cleanup() | |
405 | { | |
406 | local mz_pid=$1; shift | |
407 | local dev=$1; shift | |
ef7f6b16 | 408 | local proto=$1; shift |
6b45fe95 AC |
409 | |
410 | kill $mz_pid && wait $mz_pid &> /dev/null | |
ef7f6b16 | 411 | tc filter del dev $dev egress protocol $proto pref 1 handle 101 flower |
6b45fe95 | 412 | } |