Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1# bpftool(8) bash completion -*- shell-script -*-
2#
3# Copyright (C) 2017-2018 Netronome Systems, Inc.
4#
5# This software is dual licensed under the GNU General License
6# Version 2, June 1991 as shown in the file COPYING in the top-level
7# directory of this source tree or the BSD 2-Clause License provided
8# below. You have the option to license this software under the
9# complete terms of either license.
10#
11# The BSD 2-Clause License:
12#
13# Redistribution and use in source and binary forms, with or
14# without modification, are permitted provided that the following
15# conditions are met:
16#
17# 1. Redistributions of source code must retain the above
18# copyright notice, this list of conditions and the following
19# disclaimer.
20#
21# 2. Redistributions in binary form must reproduce the above
22# copyright notice, this list of conditions and the following
23# disclaimer in the documentation and/or other materials
24# provided with the distribution.
25#
26# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33# SOFTWARE.
34#
35# Author: Quentin Monnet <quentin.monnet@netronome.com>
36
37# Takes a list of words in argument; each one of them is added to COMPREPLY if
38# it is not already present on the command line. Returns no value.
39_bpftool_once_attr()
40{
41 local w idx found
42 for w in $*; do
43 found=0
44 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
45 if [[ $w == ${words[idx]} ]]; then
46 found=1
47 break
48 fi
49 done
50 [[ $found -eq 0 ]] && \
51 COMPREPLY+=( $( compgen -W "$w" -- "$cur" ) )
52 done
53}
54
55# Takes a list of words as argument; if any of those words is present on the
56# command line, return 0. Otherwise, return 1.
57_bpftool_search_list()
58{
59 local w idx
60 for w in $*; do
61 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
62 [[ $w == ${words[idx]} ]] && return 0
63 done
64 done
65 return 1
66}
67
68# Takes a list of words in argument; adds them all to COMPREPLY if none of them
69# is already present on the command line. Returns no value.
70_bpftool_one_of_list()
71{
72 _bpftool_search_list $* && return 1
73 COMPREPLY+=( $( compgen -W "$*" -- "$cur" ) )
74}
75
76_bpftool_get_map_ids()
77{
78 COMPREPLY+=( $( compgen -W "$( bpftool -jp map 2>&1 | \
79 command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) )
80}
81
82_bpftool_get_perf_map_ids()
83{
84 COMPREPLY+=( $( compgen -W "$( bpftool -jp map 2>&1 | \
85 command grep -C2 perf_event_array | \
86 command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) )
87}
88
89
90_bpftool_get_prog_ids()
91{
92 COMPREPLY+=( $( compgen -W "$( bpftool -jp prog 2>&1 | \
93 command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) )
94}
95
96_bpftool_get_prog_tags()
97{
98 COMPREPLY+=( $( compgen -W "$( bpftool -jp prog 2>&1 | \
99 command sed -n 's/.*"tag": "\(.*\)",$/\1/p' )" -- "$cur" ) )
100}
101
102_bpftool_get_obj_map_names()
103{
104 local obj
105
106 obj=$1
107
108 maps=$(objdump -j maps -t $obj 2>/dev/null | \
109 command awk '/g . maps/ {print $NF}')
110
111 COMPREPLY+=( $( compgen -W "$maps" -- "$cur" ) )
112}
113
114_bpftool_get_obj_map_idxs()
115{
116 local obj
117
118 obj=$1
119
120 nmaps=$(objdump -j maps -t $obj 2>/dev/null | grep -c 'g . maps')
121
122 COMPREPLY+=( $( compgen -W "$(seq 0 $((nmaps - 1)))" -- "$cur" ) )
123}
124
125_sysfs_get_netdevs()
126{
127 COMPREPLY+=( $( compgen -W "$( ls /sys/class/net 2>/dev/null )" -- \
128 "$cur" ) )
129}
130
131# For bpftool map update: retrieve type of the map to update.
132_bpftool_map_update_map_type()
133{
134 local keyword ref
135 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
136 if [[ ${words[$((idx-2))]} == "update" ]]; then
137 keyword=${words[$((idx-1))]}
138 ref=${words[$((idx))]}
139 fi
140 done
141 [[ -z $ref ]] && return 0
142
143 local type
144 type=$(bpftool -jp map show $keyword $ref | \
145 command sed -n 's/.*"type": "\(.*\)",$/\1/p')
146 printf $type
147}
148
149_bpftool_map_update_get_id()
150{
151 # Is it the map to update, or a map to insert into the map to update?
152 # Search for "value" keyword.
153 local idx value
154 for (( idx=7; idx < ${#words[@]}-1; idx++ )); do
155 if [[ ${words[idx]} == "value" ]]; then
156 value=1
157 break
158 fi
159 done
160 [[ $value -eq 0 ]] && _bpftool_get_map_ids && return 0
161
162 # Id to complete is for a value. It can be either prog id or map id. This
163 # depends on the type of the map to update.
164 local type=$(_bpftool_map_update_map_type)
165 case $type in
166 array_of_maps|hash_of_maps)
167 _bpftool_get_map_ids
168 return 0
169 ;;
170 prog_array)
171 _bpftool_get_prog_ids
172 return 0
173 ;;
174 *)
175 return 0
176 ;;
177 esac
178}
179
180_bpftool()
181{
182 local cur prev words objword
183 _init_completion || return
184
185 # Deal with options
186 if [[ ${words[cword]} == -* ]]; then
187 local c='--version --json --pretty --bpffs'
188 COMPREPLY=( $( compgen -W "$c" -- "$cur" ) )
189 return 0
190 fi
191
192 # Deal with simplest keywords
193 case $prev in
194 help|hex|opcodes|visual)
195 return 0
196 ;;
197 tag)
198 _bpftool_get_prog_tags
199 return 0
200 ;;
201 file|pinned)
202 _filedir
203 return 0
204 ;;
205 batch)
206 COMPREPLY=( $( compgen -W 'file' -- "$cur" ) )
207 return 0
208 ;;
209 esac
210
211 # Remove all options so completions don't have to deal with them.
212 local i
213 for (( i=1; i < ${#words[@]}; )); do
214 if [[ ${words[i]::1} == - ]]; then
215 words=( "${words[@]:0:i}" "${words[@]:i+1}" )
216 [[ $i -le $cword ]] && cword=$(( cword - 1 ))
217 else
218 i=$(( ++i ))
219 fi
220 done
221 cur=${words[cword]}
222 prev=${words[cword - 1]}
223
224 local object=${words[1]} command=${words[2]}
225
226 if [[ -z $object || $cword -eq 1 ]]; then
227 case $cur in
228 *)
229 COMPREPLY=( $( compgen -W "$( bpftool help 2>&1 | \
230 command sed \
231 -e '/OBJECT := /!d' \
232 -e 's/.*{//' \
233 -e 's/}.*//' \
234 -e 's/|//g' )" -- "$cur" ) )
235 COMPREPLY+=( $( compgen -W 'batch help' -- "$cur" ) )
236 return 0
237 ;;
238 esac
239 fi
240
241 [[ $command == help ]] && return 0
242
243 # Completion depends on object and command in use
244 case $object in
245 prog)
246 if [[ $command != "load" ]]; then
247 case $prev in
248 id)
249 _bpftool_get_prog_ids
250 return 0
251 ;;
252 esac
253 fi
254
255 local PROG_TYPE='id pinned tag'
256 case $command in
257 show|list)
258 [[ $prev != "$command" ]] && return 0
259 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
260 return 0
261 ;;
262 dump)
263 case $prev in
264 $command)
265 COMPREPLY+=( $( compgen -W "xlated jited" -- \
266 "$cur" ) )
267 return 0
268 ;;
269 xlated|jited)
270 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \
271 "$cur" ) )
272 return 0
273 ;;
274 *)
275 _bpftool_once_attr 'file'
276 if _bpftool_search_list 'xlated'; then
277 COMPREPLY+=( $( compgen -W 'opcodes visual' -- \
278 "$cur" ) )
279 else
280 COMPREPLY+=( $( compgen -W 'opcodes' -- \
281 "$cur" ) )
282 fi
283 return 0
284 ;;
285 esac
286 ;;
287 pin)
288 if [[ $prev == "$command" ]]; then
289 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
290 else
291 _filedir
292 fi
293 return 0
294 ;;
295 load)
296 local obj
297
298 if [[ ${#words[@]} -lt 6 ]]; then
299 _filedir
300 return 0
301 fi
302
303 obj=${words[3]}
304
305 if [[ ${words[-4]} == "map" ]]; then
306 COMPREPLY=( $( compgen -W "id pinned" -- "$cur" ) )
307 return 0
308 fi
309 if [[ ${words[-3]} == "map" ]]; then
310 if [[ ${words[-2]} == "idx" ]]; then
311 _bpftool_get_obj_map_idxs $obj
312 elif [[ ${words[-2]} == "name" ]]; then
313 _bpftool_get_obj_map_names $obj
314 fi
315 return 0
316 fi
317 if [[ ${words[-2]} == "map" ]]; then
318 COMPREPLY=( $( compgen -W "idx name" -- "$cur" ) )
319 return 0
320 fi
321
322 case $prev in
323 type)
324 COMPREPLY=( $( compgen -W "socket kprobe kretprobe classifier action tracepoint raw_tracepoint xdp perf_event cgroup/skb cgroup/sock cgroup/dev lwt_in lwt_out lwt_xmit lwt_seg6local sockops sk_skb sk_msg lirc_mode2 cgroup/bind4 cgroup/bind6 cgroup/connect4 cgroup/connect6 cgroup/sendmsg4 cgroup/sendmsg6 cgroup/post_bind4 cgroup/post_bind6" -- \
325 "$cur" ) )
326 return 0
327 ;;
328 id)
329 _bpftool_get_map_ids
330 return 0
331 ;;
332 pinned)
333 _filedir
334 return 0
335 ;;
336 dev)
337 _sysfs_get_netdevs
338 return 0
339 ;;
340 *)
341 COMPREPLY=( $( compgen -W "map" -- "$cur" ) )
342 _bpftool_once_attr 'type'
343 _bpftool_once_attr 'dev'
344 return 0
345 ;;
346 esac
347 ;;
348 *)
349 [[ $prev == $object ]] && \
350 COMPREPLY=( $( compgen -W 'dump help pin load \
351 show list' -- "$cur" ) )
352 ;;
353 esac
354 ;;
355 map)
356 local MAP_TYPE='id pinned'
357 case $command in
358 show|list|dump)
359 case $prev in
360 $command)
361 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
362 return 0
363 ;;
364 id)
365 _bpftool_get_map_ids
366 return 0
367 ;;
368 *)
369 return 0
370 ;;
371 esac
372 ;;
373 lookup|getnext|delete)
374 case $prev in
375 $command)
376 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
377 return 0
378 ;;
379 id)
380 _bpftool_get_map_ids
381 return 0
382 ;;
383 key)
384 COMPREPLY+=( $( compgen -W 'hex' -- "$cur" ) )
385 ;;
386 *)
387 _bpftool_once_attr 'key'
388 return 0
389 ;;
390 esac
391 ;;
392 update)
393 case $prev in
394 $command)
395 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
396 return 0
397 ;;
398 id)
399 _bpftool_map_update_get_id
400 return 0
401 ;;
402 key)
403 COMPREPLY+=( $( compgen -W 'hex' -- "$cur" ) )
404 ;;
405 value)
406 # We can have bytes, or references to a prog or a
407 # map, depending on the type of the map to update.
408 case $(_bpftool_map_update_map_type) in
409 array_of_maps|hash_of_maps)
410 local MAP_TYPE='id pinned'
411 COMPREPLY+=( $( compgen -W "$MAP_TYPE" \
412 -- "$cur" ) )
413 return 0
414 ;;
415 prog_array)
416 local PROG_TYPE='id pinned tag'
417 COMPREPLY+=( $( compgen -W "$PROG_TYPE" \
418 -- "$cur" ) )
419 return 0
420 ;;
421 *)
422 COMPREPLY+=( $( compgen -W 'hex' \
423 -- "$cur" ) )
424 return 0
425 ;;
426 esac
427 return 0
428 ;;
429 *)
430 _bpftool_once_attr 'key'
431 local UPDATE_FLAGS='any exist noexist'
432 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
433 if [[ ${words[idx]} == 'value' ]]; then
434 # 'value' is present, but is not the last
435 # word i.e. we can now have UPDATE_FLAGS.
436 _bpftool_one_of_list "$UPDATE_FLAGS"
437 return 0
438 fi
439 done
440 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
441 if [[ ${words[idx]} == 'key' ]]; then
442 # 'key' is present, but is not the last
443 # word i.e. we can now have 'value'.
444 _bpftool_once_attr 'value'
445 return 0
446 fi
447 done
448 return 0
449 ;;
450 esac
451 ;;
452 pin)
453 if [[ $prev == "$command" ]]; then
454 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
455 else
456 _filedir
457 fi
458 return 0
459 ;;
460 event_pipe)
461 case $prev in
462 $command)
463 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
464 return 0
465 ;;
466 id)
467 _bpftool_get_perf_map_ids
468 return 0
469 ;;
470 cpu)
471 return 0
472 ;;
473 index)
474 return 0
475 ;;
476 *)
477 _bpftool_once_attr 'cpu'
478 _bpftool_once_attr 'index'
479 return 0
480 ;;
481 esac
482 ;;
483 *)
484 [[ $prev == $object ]] && \
485 COMPREPLY=( $( compgen -W 'delete dump getnext help \
486 lookup pin event_pipe show list update' -- \
487 "$cur" ) )
488 ;;
489 esac
490 ;;
491 cgroup)
492 case $command in
493 show|list)
494 _filedir
495 return 0
496 ;;
497 tree)
498 _filedir
499 return 0
500 ;;
501 attach|detach)
502 local ATTACH_TYPES='ingress egress sock_create sock_ops \
503 device bind4 bind6 post_bind4 post_bind6 connect4 \
504 connect6 sendmsg4 sendmsg6'
505 local ATTACH_FLAGS='multi override'
506 local PROG_TYPE='id pinned tag'
507 case $prev in
508 $command)
509 _filedir
510 return 0
511 ;;
512 ingress|egress|sock_create|sock_ops|device|bind4|bind6|\
513 post_bind4|post_bind6|connect4|connect6|sendmsg4|\
514 sendmsg6)
515 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \
516 "$cur" ) )
517 return 0
518 ;;
519 id)
520 _bpftool_get_prog_ids
521 return 0
522 ;;
523 *)
524 if ! _bpftool_search_list "$ATTACH_TYPES"; then
525 COMPREPLY=( $( compgen -W "$ATTACH_TYPES" -- \
526 "$cur" ) )
527 elif [[ "$command" == "attach" ]]; then
528 # We have an attach type on the command line,
529 # but it is not the previous word, or
530 # "id|pinned|tag" (we already checked for
531 # that). This should only leave the case when
532 # we need attach flags for "attach" commamnd.
533 _bpftool_one_of_list "$ATTACH_FLAGS"
534 fi
535 return 0
536 ;;
537 esac
538 ;;
539 *)
540 [[ $prev == $object ]] && \
541 COMPREPLY=( $( compgen -W 'help attach detach \
542 show list tree' -- "$cur" ) )
543 ;;
544 esac
545 ;;
546 perf)
547 case $command in
548 *)
549 [[ $prev == $object ]] && \
550 COMPREPLY=( $( compgen -W 'help \
551 show list' -- "$cur" ) )
552 ;;
553 esac
554 ;;
555 esac
556} &&
557complete -F _bpftool bpftool
558
559# ex: ts=4 sw=4 et filetype=sh