Loading...
1# bpftool(8) bash completion -*- shell-script -*-
2#
3# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
4# Copyright (C) 2017-2018 Netronome Systems, Inc.
5#
6# Author: Quentin Monnet <quentin.monnet@netronome.com>
7
8# Takes a list of words in argument; each one of them is added to COMPREPLY if
9# it is not already present on the command line. Returns no value.
10_bpftool_once_attr()
11{
12 local w idx found
13 for w in $*; do
14 found=0
15 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
16 if [[ $w == ${words[idx]} ]]; then
17 found=1
18 break
19 fi
20 done
21 [[ $found -eq 0 ]] && \
22 COMPREPLY+=( $( compgen -W "$w" -- "$cur" ) )
23 done
24}
25
26# Takes a list of words as argument; if any of those words is present on the
27# command line, return 0. Otherwise, return 1.
28_bpftool_search_list()
29{
30 local w idx
31 for w in $*; do
32 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
33 [[ $w == ${words[idx]} ]] && return 0
34 done
35 done
36 return 1
37}
38
39# Takes a list of words in argument; adds them all to COMPREPLY if none of them
40# is already present on the command line. Returns no value.
41_bpftool_one_of_list()
42{
43 _bpftool_search_list $* && return 1
44 COMPREPLY+=( $( compgen -W "$*" -- "$cur" ) )
45}
46
47_bpftool_get_map_ids()
48{
49 COMPREPLY+=( $( compgen -W "$( bpftool -jp map 2>&1 | \
50 command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) )
51}
52
53# Takes map type and adds matching map ids to the list of suggestions.
54_bpftool_get_map_ids_for_type()
55{
56 local type="$1"
57 COMPREPLY+=( $( compgen -W "$( bpftool -jp map 2>&1 | \
58 command grep -C2 "$type" | \
59 command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) )
60}
61
62_bpftool_get_map_names()
63{
64 COMPREPLY+=( $( compgen -W "$( bpftool -jp map 2>&1 | \
65 command sed -n 's/.*"name": \(.*\),$/\1/p' )" -- "$cur" ) )
66}
67
68# Takes map type and adds matching map names to the list of suggestions.
69_bpftool_get_map_names_for_type()
70{
71 local type="$1"
72 COMPREPLY+=( $( compgen -W "$( bpftool -jp map 2>&1 | \
73 command grep -C2 "$type" | \
74 command sed -n 's/.*"name": \(.*\),$/\1/p' )" -- "$cur" ) )
75}
76
77_bpftool_get_prog_ids()
78{
79 COMPREPLY+=( $( compgen -W "$( bpftool -jp prog 2>&1 | \
80 command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) )
81}
82
83_bpftool_get_prog_tags()
84{
85 COMPREPLY+=( $( compgen -W "$( bpftool -jp prog 2>&1 | \
86 command sed -n 's/.*"tag": "\(.*\)",$/\1/p' )" -- "$cur" ) )
87}
88
89_bpftool_get_prog_names()
90{
91 COMPREPLY+=( $( compgen -W "$( bpftool -jp prog 2>&1 | \
92 command sed -n 's/.*"name": "\(.*\)",$/\1/p' )" -- "$cur" ) )
93}
94
95_bpftool_get_btf_ids()
96{
97 COMPREPLY+=( $( compgen -W "$( bpftool -jp btf 2>&1 | \
98 command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) )
99}
100
101_bpftool_get_link_ids()
102{
103 COMPREPLY+=( $( compgen -W "$( bpftool -jp link 2>&1 | \
104 command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) )
105}
106
107_bpftool_get_obj_map_names()
108{
109 local obj maps
110
111 obj=$1
112
113 maps=$(objdump -j .maps -t $obj 2>/dev/null | \
114 command awk '/g . .maps/ {print $NF}')
115
116 COMPREPLY+=( $( compgen -W "$maps" -- "$cur" ) )
117}
118
119_bpftool_get_obj_map_idxs()
120{
121 local obj nmaps
122
123 obj=$1
124
125 nmaps=$(objdump -j maps -t $obj 2>/dev/null | grep -c 'g . maps')
126
127 COMPREPLY+=( $( compgen -W "$(seq 0 $((nmaps - 1)))" -- "$cur" ) )
128}
129
130_sysfs_get_netdevs()
131{
132 COMPREPLY+=( $( compgen -W "$( ls /sys/class/net 2>/dev/null )" -- \
133 "$cur" ) )
134}
135
136# Retrieve type of the map that we are operating on.
137_bpftool_map_guess_map_type()
138{
139 local keyword idx ref=""
140 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
141 case "${words[$((idx-2))]}" in
142 lookup|update)
143 keyword=${words[$((idx-1))]}
144 ref=${words[$((idx))]}
145 ;;
146 push)
147 printf "stack"
148 return 0
149 ;;
150 enqueue)
151 printf "queue"
152 return 0
153 ;;
154 esac
155 done
156 [[ -z $ref ]] && return 0
157
158 local type
159 type=$(bpftool -jp map show $keyword $ref | \
160 command sed -n 's/.*"type": "\(.*\)",$/\1/p')
161 [[ -n $type ]] && printf $type
162}
163
164_bpftool_map_update_get_id()
165{
166 local command="$1"
167
168 # Is it the map to update, or a map to insert into the map to update?
169 # Search for "value" keyword.
170 local idx value
171 for (( idx=7; idx < ${#words[@]}-1; idx++ )); do
172 if [[ ${words[idx]} == "value" ]]; then
173 value=1
174 break
175 fi
176 done
177 if [[ $value -eq 0 ]]; then
178 case "$command" in
179 push)
180 _bpftool_get_map_ids_for_type stack
181 ;;
182 enqueue)
183 _bpftool_get_map_ids_for_type queue
184 ;;
185 *)
186 _bpftool_get_map_ids
187 ;;
188 esac
189 return 0
190 fi
191
192 # Id to complete is for a value. It can be either prog id or map id. This
193 # depends on the type of the map to update.
194 local type=$(_bpftool_map_guess_map_type)
195 case $type in
196 array_of_maps|hash_of_maps)
197 _bpftool_get_map_ids
198 return 0
199 ;;
200 prog_array)
201 _bpftool_get_prog_ids
202 return 0
203 ;;
204 *)
205 return 0
206 ;;
207 esac
208}
209
210_bpftool_map_update_get_name()
211{
212 local command="$1"
213
214 # Is it the map to update, or a map to insert into the map to update?
215 # Search for "value" keyword.
216 local idx value
217 for (( idx=7; idx < ${#words[@]}-1; idx++ )); do
218 if [[ ${words[idx]} == "value" ]]; then
219 value=1
220 break
221 fi
222 done
223 if [[ $value -eq 0 ]]; then
224 case "$command" in
225 push)
226 _bpftool_get_map_names_for_type stack
227 ;;
228 enqueue)
229 _bpftool_get_map_names_for_type queue
230 ;;
231 *)
232 _bpftool_get_map_names
233 ;;
234 esac
235 return 0
236 fi
237
238 # Name to complete is for a value. It can be either prog name or map name. This
239 # depends on the type of the map to update.
240 local type=$(_bpftool_map_guess_map_type)
241 case $type in
242 array_of_maps|hash_of_maps)
243 _bpftool_get_map_names
244 return 0
245 ;;
246 prog_array)
247 _bpftool_get_prog_names
248 return 0
249 ;;
250 *)
251 return 0
252 ;;
253 esac
254}
255
256_bpftool()
257{
258 local cur prev words cword comp_args
259 local json=0
260 _init_completion -- "$@" || return
261
262 # Deal with options
263 if [[ ${words[cword]} == -* ]]; then
264 local c='--version --json --pretty --bpffs --mapcompat --debug \
265 --use-loader --base-btf'
266 COMPREPLY=( $( compgen -W "$c" -- "$cur" ) )
267 return 0
268 fi
269 if _bpftool_search_list -j --json -p --pretty; then
270 json=1
271 fi
272
273 # Deal with simplest keywords
274 case $prev in
275 help|hex)
276 return 0
277 ;;
278 tag)
279 _bpftool_get_prog_tags
280 return 0
281 ;;
282 dev|offload_dev|xdpmeta_dev)
283 _sysfs_get_netdevs
284 return 0
285 ;;
286 file|pinned|-B|--base-btf)
287 _filedir
288 return 0
289 ;;
290 batch)
291 COMPREPLY=( $( compgen -W 'file' -- "$cur" ) )
292 return 0
293 ;;
294 esac
295
296 # Remove all options so completions don't have to deal with them.
297 local i pprev
298 for (( i=1; i < ${#words[@]}; )); do
299 if [[ ${words[i]::1} == - ]] &&
300 [[ ${words[i]} != "-B" ]] && [[ ${words[i]} != "--base-btf" ]]; then
301 words=( "${words[@]:0:i}" "${words[@]:i+1}" )
302 [[ $i -le $cword ]] && cword=$(( cword - 1 ))
303 else
304 i=$(( ++i ))
305 fi
306 done
307 cur=${words[cword]}
308 prev=${words[cword - 1]}
309 pprev=${words[cword - 2]}
310
311 local object=${words[1]}
312
313 if [[ -z $object || $cword -eq 1 ]]; then
314 case $cur in
315 *)
316 COMPREPLY=( $( compgen -W "$( bpftool help 2>&1 | \
317 command sed \
318 -e '/OBJECT := /!d' \
319 -e 's/.*{//' \
320 -e 's/}.*//' \
321 -e 's/|//g' )" -- "$cur" ) )
322 COMPREPLY+=( $( compgen -W 'batch help' -- "$cur" ) )
323 return 0
324 ;;
325 esac
326 fi
327
328 local command=${words[2]}
329 [[ $command == help ]] && return 0
330
331 local MAP_TYPE='id pinned name'
332 local PROG_TYPE='id pinned tag name'
333
334 # Completion depends on object and command in use
335 case $object in
336 prog)
337 # Complete id and name, only for subcommands that use prog (but no
338 # map) ids/names.
339 case $command in
340 show|list|dump|pin)
341 case $prev in
342 id)
343 _bpftool_get_prog_ids
344 return 0
345 ;;
346 name)
347 _bpftool_get_prog_names
348 return 0
349 ;;
350 esac
351 ;;
352 esac
353
354 local METRIC_TYPE='cycles instructions l1d_loads llc_misses \
355 itlb_misses dtlb_misses'
356 case $command in
357 show|list)
358 [[ $prev != "$command" ]] && return 0
359 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
360 return 0
361 ;;
362 dump)
363 case $prev in
364 $command)
365 COMPREPLY+=( $( compgen -W "xlated jited" -- \
366 "$cur" ) )
367 return 0
368 ;;
369 xlated|jited)
370 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \
371 "$cur" ) )
372 return 0
373 ;;
374 *)
375 # "file" is not compatible with other keywords here
376 if _bpftool_search_list 'file'; then
377 return 0
378 fi
379 if ! _bpftool_search_list 'linum opcodes visual'; then
380 _bpftool_once_attr 'file'
381 fi
382 _bpftool_once_attr 'linum opcodes'
383 if _bpftool_search_list 'xlated' && [[ "$json" == 0 ]]; then
384 _bpftool_once_attr 'visual'
385 fi
386 return 0
387 ;;
388 esac
389 ;;
390 pin)
391 if [[ $prev == "$command" ]]; then
392 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
393 else
394 _filedir
395 fi
396 return 0
397 ;;
398 attach|detach)
399 case $cword in
400 3)
401 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
402 return 0
403 ;;
404 4)
405 case $prev in
406 id)
407 _bpftool_get_prog_ids
408 ;;
409 name)
410 _bpftool_get_prog_names
411 ;;
412 pinned)
413 _filedir
414 ;;
415 esac
416 return 0
417 ;;
418 5)
419 local BPFTOOL_PROG_ATTACH_TYPES='sk_msg_verdict \
420 sk_skb_verdict sk_skb_stream_verdict sk_skb_stream_parser \
421 flow_dissector'
422 COMPREPLY=( $( compgen -W "$BPFTOOL_PROG_ATTACH_TYPES" -- "$cur" ) )
423 return 0
424 ;;
425 6)
426 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
427 return 0
428 ;;
429 7)
430 case $prev in
431 id)
432 _bpftool_get_map_ids
433 ;;
434 name)
435 _bpftool_get_map_names
436 ;;
437 pinned)
438 _filedir
439 ;;
440 esac
441 return 0
442 ;;
443 esac
444 ;;
445 load|loadall)
446 local obj
447
448 # Propose "load/loadall" to complete "bpftool prog load",
449 # or bash tries to complete "load" as a filename below.
450 if [[ ${#words[@]} -eq 3 ]]; then
451 COMPREPLY=( $( compgen -W "load loadall" -- "$cur" ) )
452 return 0
453 fi
454
455 if [[ ${#words[@]} -lt 6 ]]; then
456 _filedir
457 return 0
458 fi
459
460 obj=${words[3]}
461
462 if [[ ${words[-4]} == "map" ]]; then
463 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
464 return 0
465 fi
466 if [[ ${words[-3]} == "map" ]]; then
467 if [[ ${words[-2]} == "idx" ]]; then
468 _bpftool_get_obj_map_idxs $obj
469 elif [[ ${words[-2]} == "name" ]]; then
470 _bpftool_get_obj_map_names $obj
471 fi
472 return 0
473 fi
474 if [[ ${words[-2]} == "map" ]]; then
475 COMPREPLY=( $( compgen -W "idx name" -- "$cur" ) )
476 return 0
477 fi
478
479 case $prev in
480 type)
481 local BPFTOOL_PROG_LOAD_TYPES='socket kprobe \
482 kretprobe classifier flow_dissector \
483 action tracepoint raw_tracepoint \
484 xdp perf_event cgroup/skb cgroup/sock \
485 cgroup/dev lwt_in lwt_out lwt_xmit \
486 lwt_seg6local sockops sk_skb sk_msg lirc_mode2 \
487 cgroup/bind4 cgroup/bind6 \
488 cgroup/connect4 cgroup/connect6 cgroup/connect_unix \
489 cgroup/getpeername4 cgroup/getpeername6 cgroup/getpeername_unix \
490 cgroup/getsockname4 cgroup/getsockname6 cgroup/getsockname_unix \
491 cgroup/sendmsg4 cgroup/sendmsg6 cgroup/sendmsg_unix \
492 cgroup/recvmsg4 cgroup/recvmsg6 cgroup/recvmsg_unix \
493 cgroup/post_bind4 cgroup/post_bind6 \
494 cgroup/sysctl cgroup/getsockopt \
495 cgroup/setsockopt cgroup/sock_release struct_ops \
496 fentry fexit freplace sk_lookup'
497 COMPREPLY=( $( compgen -W "$BPFTOOL_PROG_LOAD_TYPES" -- "$cur" ) )
498 return 0
499 ;;
500 id)
501 _bpftool_get_map_ids
502 return 0
503 ;;
504 name)
505 _bpftool_get_map_names
506 return 0
507 ;;
508 pinned|pinmaps)
509 _filedir
510 return 0
511 ;;
512 *)
513 COMPREPLY=( $( compgen -W "map" -- "$cur" ) )
514 _bpftool_once_attr 'type pinmaps autoattach'
515 _bpftool_one_of_list 'offload_dev xdpmeta_dev'
516 return 0
517 ;;
518 esac
519 ;;
520 tracelog)
521 return 0
522 ;;
523 profile)
524 case $cword in
525 3)
526 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
527 return 0
528 ;;
529 4)
530 case $prev in
531 id)
532 _bpftool_get_prog_ids
533 ;;
534 name)
535 _bpftool_get_prog_names
536 ;;
537 pinned)
538 _filedir
539 ;;
540 esac
541 return 0
542 ;;
543 5)
544 COMPREPLY=( $( compgen -W "$METRIC_TYPE duration" -- "$cur" ) )
545 return 0
546 ;;
547 *)
548 [[ $prev == duration ]] && return 0
549 _bpftool_once_attr "$METRIC_TYPE"
550 return 0
551 ;;
552 esac
553 ;;
554 run)
555 if [[ ${#words[@]} -eq 4 ]]; then
556 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
557 return 0
558 fi
559 case $prev in
560 id)
561 _bpftool_get_prog_ids
562 return 0
563 ;;
564 name)
565 _bpftool_get_prog_names
566 return 0
567 ;;
568 data_in|data_out|ctx_in|ctx_out)
569 _filedir
570 return 0
571 ;;
572 repeat|data_size_out|ctx_size_out)
573 return 0
574 ;;
575 *)
576 _bpftool_once_attr 'data_in data_out data_size_out \
577 ctx_in ctx_out ctx_size_out repeat'
578 return 0
579 ;;
580 esac
581 ;;
582 *)
583 [[ $prev == $object ]] && \
584 COMPREPLY=( $( compgen -W 'dump help pin attach detach \
585 load loadall show list tracelog run profile' -- "$cur" ) )
586 ;;
587 esac
588 ;;
589 struct_ops)
590 local STRUCT_OPS_TYPE='id name'
591 case $command in
592 show|list|dump|unregister)
593 case $prev in
594 $command)
595 COMPREPLY=( $( compgen -W "$STRUCT_OPS_TYPE" -- "$cur" ) )
596 ;;
597 id)
598 _bpftool_get_map_ids_for_type struct_ops
599 ;;
600 name)
601 _bpftool_get_map_names_for_type struct_ops
602 ;;
603 esac
604 return 0
605 ;;
606 register)
607 [[ $prev == $command ]] && _filedir
608 return 0
609 ;;
610 *)
611 [[ $prev == $object ]] && \
612 COMPREPLY=( $( compgen -W 'register unregister show list dump help' \
613 -- "$cur" ) )
614 ;;
615 esac
616 ;;
617 iter)
618 case $command in
619 pin)
620 case $prev in
621 $command)
622 _filedir
623 ;;
624 id)
625 _bpftool_get_map_ids
626 ;;
627 name)
628 _bpftool_get_map_names
629 ;;
630 pinned)
631 _filedir
632 ;;
633 map)
634 _bpftool_one_of_list $MAP_TYPE
635 ;;
636 *)
637 _bpftool_once_attr 'map'
638 ;;
639 esac
640 return 0
641 ;;
642 *)
643 [[ $prev == $object ]] && \
644 COMPREPLY=( $( compgen -W 'pin help' \
645 -- "$cur" ) )
646 ;;
647 esac
648 ;;
649 map)
650 case $command in
651 show|list|dump|peek|pop|dequeue|freeze)
652 case $prev in
653 $command)
654 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
655 return 0
656 ;;
657 id)
658 case "$command" in
659 peek)
660 _bpftool_get_map_ids_for_type stack
661 _bpftool_get_map_ids_for_type queue
662 ;;
663 pop)
664 _bpftool_get_map_ids_for_type stack
665 ;;
666 dequeue)
667 _bpftool_get_map_ids_for_type queue
668 ;;
669 *)
670 _bpftool_get_map_ids
671 ;;
672 esac
673 return 0
674 ;;
675 name)
676 case "$command" in
677 peek)
678 _bpftool_get_map_names_for_type stack
679 _bpftool_get_map_names_for_type queue
680 ;;
681 pop)
682 _bpftool_get_map_names_for_type stack
683 ;;
684 dequeue)
685 _bpftool_get_map_names_for_type queue
686 ;;
687 *)
688 _bpftool_get_map_names
689 ;;
690 esac
691 return 0
692 ;;
693 *)
694 return 0
695 ;;
696 esac
697 ;;
698 create)
699 case $prev in
700 $command)
701 _filedir
702 return 0
703 ;;
704 type)
705 local BPFTOOL_MAP_CREATE_TYPES="$(bpftool feature list_builtins map_types 2>/dev/null | \
706 grep -v '^unspec$')"
707 COMPREPLY=( $( compgen -W "$BPFTOOL_MAP_CREATE_TYPES" -- "$cur" ) )
708 return 0
709 ;;
710 key|value|flags|entries)
711 return 0
712 ;;
713 inner_map)
714 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
715 return 0
716 ;;
717 id)
718 _bpftool_get_map_ids
719 ;;
720 name)
721 case $pprev in
722 inner_map)
723 _bpftool_get_map_names
724 ;;
725 *)
726 return 0
727 ;;
728 esac
729 ;;
730 *)
731 _bpftool_once_attr 'type key value entries name flags offload_dev'
732 if _bpftool_search_list 'array_of_maps' 'hash_of_maps'; then
733 _bpftool_once_attr 'inner_map'
734 fi
735 return 0
736 ;;
737 esac
738 ;;
739 lookup|getnext|delete)
740 case $prev in
741 $command)
742 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
743 return 0
744 ;;
745 id)
746 _bpftool_get_map_ids
747 return 0
748 ;;
749 name)
750 _bpftool_get_map_names
751 return 0
752 ;;
753 key)
754 COMPREPLY+=( $( compgen -W 'hex' -- "$cur" ) )
755 ;;
756 *)
757 case $(_bpftool_map_guess_map_type) in
758 queue|stack)
759 return 0
760 ;;
761 esac
762
763 _bpftool_once_attr 'key'
764 return 0
765 ;;
766 esac
767 ;;
768 update|push|enqueue)
769 case $prev in
770 $command)
771 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
772 return 0
773 ;;
774 id)
775 _bpftool_map_update_get_id $command
776 return 0
777 ;;
778 name)
779 _bpftool_map_update_get_name $command
780 return 0
781 ;;
782 key)
783 COMPREPLY+=( $( compgen -W 'hex' -- "$cur" ) )
784 ;;
785 value)
786 # We can have bytes, or references to a prog or a
787 # map, depending on the type of the map to update.
788 case "$(_bpftool_map_guess_map_type)" in
789 array_of_maps|hash_of_maps)
790 COMPREPLY+=( $( compgen -W "$MAP_TYPE" \
791 -- "$cur" ) )
792 return 0
793 ;;
794 prog_array)
795 COMPREPLY+=( $( compgen -W "$PROG_TYPE" \
796 -- "$cur" ) )
797 return 0
798 ;;
799 *)
800 COMPREPLY+=( $( compgen -W 'hex' \
801 -- "$cur" ) )
802 return 0
803 ;;
804 esac
805 return 0
806 ;;
807 *)
808 case $(_bpftool_map_guess_map_type) in
809 queue|stack)
810 _bpftool_once_attr 'value'
811 return 0;
812 ;;
813 esac
814
815 _bpftool_once_attr 'key'
816 local UPDATE_FLAGS='any exist noexist' idx
817 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
818 if [[ ${words[idx]} == 'value' ]]; then
819 # 'value' is present, but is not the last
820 # word i.e. we can now have UPDATE_FLAGS.
821 _bpftool_one_of_list "$UPDATE_FLAGS"
822 return 0
823 fi
824 done
825 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
826 if [[ ${words[idx]} == 'key' ]]; then
827 # 'key' is present, but is not the last
828 # word i.e. we can now have 'value'.
829 _bpftool_once_attr 'value'
830 return 0
831 fi
832 done
833
834 return 0
835 ;;
836 esac
837 ;;
838 pin)
839 case $prev in
840 $command)
841 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
842 ;;
843 id)
844 _bpftool_get_map_ids
845 ;;
846 name)
847 _bpftool_get_map_names
848 ;;
849 esac
850 return 0
851 ;;
852 event_pipe)
853 case $prev in
854 $command)
855 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
856 return 0
857 ;;
858 id)
859 _bpftool_get_map_ids_for_type perf_event_array
860 return 0
861 ;;
862 name)
863 _bpftool_get_map_names_for_type perf_event_array
864 return 0
865 ;;
866 cpu)
867 return 0
868 ;;
869 index)
870 return 0
871 ;;
872 *)
873 _bpftool_once_attr 'cpu index'
874 return 0
875 ;;
876 esac
877 ;;
878 *)
879 [[ $prev == $object ]] && \
880 COMPREPLY=( $( compgen -W 'delete dump getnext help \
881 lookup pin event_pipe show list update create \
882 peek push enqueue pop dequeue freeze' -- \
883 "$cur" ) )
884 ;;
885 esac
886 ;;
887 btf)
888 local MAP_TYPE='id pinned name'
889 case $command in
890 dump)
891 case $prev in
892 $command)
893 COMPREPLY+=( $( compgen -W "id map prog file" -- \
894 "$cur" ) )
895 return 0
896 ;;
897 prog)
898 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
899 return 0
900 ;;
901 map)
902 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
903 return 0
904 ;;
905 id)
906 case $pprev in
907 prog)
908 _bpftool_get_prog_ids
909 ;;
910 map)
911 _bpftool_get_map_ids
912 ;;
913 $command)
914 _bpftool_get_btf_ids
915 ;;
916 esac
917 return 0
918 ;;
919 name)
920 case $pprev in
921 prog)
922 _bpftool_get_prog_names
923 ;;
924 map)
925 _bpftool_get_map_names
926 ;;
927 esac
928 return 0
929 ;;
930 format)
931 COMPREPLY=( $( compgen -W "c raw" -- "$cur" ) )
932 ;;
933 c)
934 COMPREPLY=( $( compgen -W "unsorted" -- "$cur" ) )
935 ;;
936 *)
937 # emit extra options
938 case ${words[3]} in
939 id|file)
940 _bpftool_once_attr 'format'
941 ;;
942 map|prog)
943 if [[ ${words[3]} == "map" ]] && [[ $cword == 6 ]]; then
944 COMPREPLY+=( $( compgen -W "key value kv all" -- "$cur" ) )
945 fi
946 _bpftool_once_attr 'format'
947 ;;
948 *)
949 ;;
950 esac
951 return 0
952 ;;
953 esac
954 ;;
955 show|list)
956 case $prev in
957 $command)
958 COMPREPLY+=( $( compgen -W "id" -- "$cur" ) )
959 ;;
960 id)
961 _bpftool_get_btf_ids
962 ;;
963 esac
964 return 0
965 ;;
966 *)
967 [[ $prev == $object ]] && \
968 COMPREPLY=( $( compgen -W 'dump help show list' \
969 -- "$cur" ) )
970 ;;
971 esac
972 ;;
973 gen)
974 case $command in
975 object)
976 _filedir
977 return 0
978 ;;
979 skeleton)
980 case $prev in
981 $command)
982 _filedir
983 return 0
984 ;;
985 *)
986 _bpftool_once_attr 'name'
987 return 0
988 ;;
989 esac
990 ;;
991 subskeleton)
992 case $prev in
993 $command)
994 _filedir
995 return 0
996 ;;
997 *)
998 _bpftool_once_attr 'name'
999 return 0
1000 ;;
1001 esac
1002 ;;
1003 min_core_btf)
1004 _filedir
1005 return 0
1006 ;;
1007 *)
1008 [[ $prev == $object ]] && \
1009 COMPREPLY=( $( compgen -W 'object skeleton subskeleton help min_core_btf' -- "$cur" ) )
1010 ;;
1011 esac
1012 ;;
1013 cgroup)
1014 case $command in
1015 show|list|tree)
1016 case $cword in
1017 3)
1018 _filedir
1019 ;;
1020 4)
1021 COMPREPLY=( $( compgen -W 'effective' -- "$cur" ) )
1022 ;;
1023 esac
1024 return 0
1025 ;;
1026 attach|detach)
1027 local BPFTOOL_CGROUP_ATTACH_TYPES="$(bpftool feature list_builtins attach_types 2>/dev/null | \
1028 grep '^cgroup_')"
1029 local ATTACH_FLAGS='multi override'
1030 # Check for $prev = $command first
1031 if [ $prev = $command ]; then
1032 _filedir
1033 return 0
1034 # Then check for attach type. This is done outside of the
1035 # "case $prev in" to avoid writing the whole list of attach
1036 # types again as pattern to match (where we cannot reuse
1037 # our variable).
1038 elif [[ $BPFTOOL_CGROUP_ATTACH_TYPES =~ $prev ]]; then
1039 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \
1040 "$cur" ) )
1041 return 0
1042 fi
1043 # case/esac for the other cases
1044 case $prev in
1045 id)
1046 _bpftool_get_prog_ids
1047 return 0
1048 ;;
1049 *)
1050 if ! _bpftool_search_list "$BPFTOOL_CGROUP_ATTACH_TYPES"; then
1051 COMPREPLY=( $( compgen -W \
1052 "$BPFTOOL_CGROUP_ATTACH_TYPES" -- "$cur" ) )
1053 elif [[ "$command" == "attach" ]]; then
1054 # We have an attach type on the command line,
1055 # but it is not the previous word, or
1056 # "id|pinned|tag|name" (we already checked for
1057 # that). This should only leave the case when
1058 # we need attach flags for "attach" commamnd.
1059 _bpftool_one_of_list "$ATTACH_FLAGS"
1060 fi
1061 return 0
1062 ;;
1063 esac
1064 ;;
1065 *)
1066 [[ $prev == $object ]] && \
1067 COMPREPLY=( $( compgen -W 'help attach detach \
1068 show list tree' -- "$cur" ) )
1069 ;;
1070 esac
1071 ;;
1072 perf)
1073 case $command in
1074 *)
1075 [[ $prev == $object ]] && \
1076 COMPREPLY=( $( compgen -W 'help \
1077 show list' -- "$cur" ) )
1078 ;;
1079 esac
1080 ;;
1081 net)
1082 local ATTACH_TYPES='xdp xdpgeneric xdpdrv xdpoffload tcx_ingress tcx_egress'
1083 case $command in
1084 show|list)
1085 [[ $prev != "$command" ]] && return 0
1086 COMPREPLY=( $( compgen -W 'dev' -- "$cur" ) )
1087 return 0
1088 ;;
1089 attach)
1090 case $cword in
1091 3)
1092 COMPREPLY=( $( compgen -W "$ATTACH_TYPES" -- "$cur" ) )
1093 return 0
1094 ;;
1095 4)
1096 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
1097 return 0
1098 ;;
1099 5)
1100 case $prev in
1101 id)
1102 _bpftool_get_prog_ids
1103 ;;
1104 name)
1105 _bpftool_get_prog_names
1106 ;;
1107 pinned)
1108 _filedir
1109 ;;
1110 esac
1111 return 0
1112 ;;
1113 6)
1114 COMPREPLY=( $( compgen -W 'dev' -- "$cur" ) )
1115 return 0
1116 ;;
1117 8)
1118 _bpftool_once_attr 'overwrite'
1119 return 0
1120 ;;
1121 esac
1122 ;;
1123 detach)
1124 case $cword in
1125 3)
1126 COMPREPLY=( $( compgen -W "$ATTACH_TYPES" -- "$cur" ) )
1127 return 0
1128 ;;
1129 4)
1130 COMPREPLY=( $( compgen -W 'dev' -- "$cur" ) )
1131 return 0
1132 ;;
1133 esac
1134 ;;
1135 *)
1136 [[ $prev == $object ]] && \
1137 COMPREPLY=( $( compgen -W 'help \
1138 show list attach detach' -- "$cur" ) )
1139 ;;
1140 esac
1141 ;;
1142 feature)
1143 case $command in
1144 probe)
1145 [[ $prev == "prefix" ]] && return 0
1146 if _bpftool_search_list 'macros'; then
1147 _bpftool_once_attr 'prefix'
1148 else
1149 COMPREPLY+=( $( compgen -W 'macros' -- "$cur" ) )
1150 fi
1151 _bpftool_one_of_list 'kernel dev'
1152 _bpftool_once_attr 'full unprivileged'
1153 return 0
1154 ;;
1155 list_builtins)
1156 [[ $prev != "$command" ]] && return 0
1157 COMPREPLY=( $( compgen -W 'prog_types map_types \
1158 attach_types link_types helpers' -- "$cur" ) )
1159 ;;
1160 *)
1161 [[ $prev == $object ]] && \
1162 COMPREPLY=( $( compgen -W 'help list_builtins probe' -- "$cur" ) )
1163 ;;
1164 esac
1165 ;;
1166 link)
1167 case $command in
1168 show|list|pin|detach)
1169 case $prev in
1170 id)
1171 _bpftool_get_link_ids
1172 return 0
1173 ;;
1174 esac
1175 ;;
1176 esac
1177
1178 local LINK_TYPE='id pinned'
1179 case $command in
1180 show|list)
1181 [[ $prev != "$command" ]] && return 0
1182 COMPREPLY=( $( compgen -W "$LINK_TYPE" -- "$cur" ) )
1183 return 0
1184 ;;
1185 pin|detach)
1186 if [[ $prev == "$command" ]]; then
1187 COMPREPLY=( $( compgen -W "$LINK_TYPE" -- "$cur" ) )
1188 elif [[ $pprev == "$command" ]]; then
1189 _filedir
1190 fi
1191 return 0
1192 ;;
1193 *)
1194 [[ $prev == $object ]] && \
1195 COMPREPLY=( $( compgen -W 'help pin detach show list' -- "$cur" ) )
1196 ;;
1197 esac
1198 ;;
1199 esac
1200} &&
1201complete -F _bpftool bpftool
1202
1203# ex: ts=4 sw=4 et filetype=sh
1# bpftool(8) bash completion -*- shell-script -*-
2#
3# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
4# Copyright (C) 2017-2018 Netronome Systems, Inc.
5#
6# Author: Quentin Monnet <quentin.monnet@netronome.com>
7
8# Takes a list of words in argument; each one of them is added to COMPREPLY if
9# it is not already present on the command line. Returns no value.
10_bpftool_once_attr()
11{
12 local w idx found
13 for w in $*; do
14 found=0
15 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
16 if [[ $w == ${words[idx]} ]]; then
17 found=1
18 break
19 fi
20 done
21 [[ $found -eq 0 ]] && \
22 COMPREPLY+=( $( compgen -W "$w" -- "$cur" ) )
23 done
24}
25
26# Takes a list of words as argument; if any of those words is present on the
27# command line, return 0. Otherwise, return 1.
28_bpftool_search_list()
29{
30 local w idx
31 for w in $*; do
32 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
33 [[ $w == ${words[idx]} ]] && return 0
34 done
35 done
36 return 1
37}
38
39# Takes a list of words in argument; adds them all to COMPREPLY if none of them
40# is already present on the command line. Returns no value.
41_bpftool_one_of_list()
42{
43 _bpftool_search_list $* && return 1
44 COMPREPLY+=( $( compgen -W "$*" -- "$cur" ) )
45}
46
47_bpftool_get_map_ids()
48{
49 COMPREPLY+=( $( compgen -W "$( bpftool -jp map 2>&1 | \
50 command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) )
51}
52
53# Takes map type and adds matching map ids to the list of suggestions.
54_bpftool_get_map_ids_for_type()
55{
56 local type="$1"
57 COMPREPLY+=( $( compgen -W "$( bpftool -jp map 2>&1 | \
58 command grep -C2 "$type" | \
59 command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) )
60}
61
62_bpftool_get_prog_ids()
63{
64 COMPREPLY+=( $( compgen -W "$( bpftool -jp prog 2>&1 | \
65 command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) )
66}
67
68_bpftool_get_prog_tags()
69{
70 COMPREPLY+=( $( compgen -W "$( bpftool -jp prog 2>&1 | \
71 command sed -n 's/.*"tag": "\(.*\)",$/\1/p' )" -- "$cur" ) )
72}
73
74_bpftool_get_btf_ids()
75{
76 COMPREPLY+=( $( compgen -W "$( bpftool -jp btf 2>&1 | \
77 command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) )
78}
79
80_bpftool_get_obj_map_names()
81{
82 local obj
83
84 obj=$1
85
86 maps=$(objdump -j maps -t $obj 2>/dev/null | \
87 command awk '/g . maps/ {print $NF}')
88
89 COMPREPLY+=( $( compgen -W "$maps" -- "$cur" ) )
90}
91
92_bpftool_get_obj_map_idxs()
93{
94 local obj
95
96 obj=$1
97
98 nmaps=$(objdump -j maps -t $obj 2>/dev/null | grep -c 'g . maps')
99
100 COMPREPLY+=( $( compgen -W "$(seq 0 $((nmaps - 1)))" -- "$cur" ) )
101}
102
103_sysfs_get_netdevs()
104{
105 COMPREPLY+=( $( compgen -W "$( ls /sys/class/net 2>/dev/null )" -- \
106 "$cur" ) )
107}
108
109# Retrieve type of the map that we are operating on.
110_bpftool_map_guess_map_type()
111{
112 local keyword ref
113 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
114 case "${words[$((idx-2))]}" in
115 lookup|update)
116 keyword=${words[$((idx-1))]}
117 ref=${words[$((idx))]}
118 ;;
119 push)
120 printf "stack"
121 return 0
122 ;;
123 enqueue)
124 printf "queue"
125 return 0
126 ;;
127 esac
128 done
129 [[ -z $ref ]] && return 0
130
131 local type
132 type=$(bpftool -jp map show $keyword $ref | \
133 command sed -n 's/.*"type": "\(.*\)",$/\1/p')
134 [[ -n $type ]] && printf $type
135}
136
137_bpftool_map_update_get_id()
138{
139 local command="$1"
140
141 # Is it the map to update, or a map to insert into the map to update?
142 # Search for "value" keyword.
143 local idx value
144 for (( idx=7; idx < ${#words[@]}-1; idx++ )); do
145 if [[ ${words[idx]} == "value" ]]; then
146 value=1
147 break
148 fi
149 done
150 if [[ $value -eq 0 ]]; then
151 case "$command" in
152 push)
153 _bpftool_get_map_ids_for_type stack
154 ;;
155 enqueue)
156 _bpftool_get_map_ids_for_type queue
157 ;;
158 *)
159 _bpftool_get_map_ids
160 ;;
161 esac
162 return 0
163 fi
164
165 # Id to complete is for a value. It can be either prog id or map id. This
166 # depends on the type of the map to update.
167 local type=$(_bpftool_map_guess_map_type)
168 case $type in
169 array_of_maps|hash_of_maps)
170 _bpftool_get_map_ids
171 return 0
172 ;;
173 prog_array)
174 _bpftool_get_prog_ids
175 return 0
176 ;;
177 *)
178 return 0
179 ;;
180 esac
181}
182
183_bpftool()
184{
185 local cur prev words objword
186 _init_completion || return
187
188 # Deal with options
189 if [[ ${words[cword]} == -* ]]; then
190 local c='--version --json --pretty --bpffs --mapcompat --debug'
191 COMPREPLY=( $( compgen -W "$c" -- "$cur" ) )
192 return 0
193 fi
194
195 # Deal with simplest keywords
196 case $prev in
197 help|hex|opcodes|visual|linum)
198 return 0
199 ;;
200 tag)
201 _bpftool_get_prog_tags
202 return 0
203 ;;
204 dev)
205 _sysfs_get_netdevs
206 return 0
207 ;;
208 file|pinned)
209 _filedir
210 return 0
211 ;;
212 batch)
213 COMPREPLY=( $( compgen -W 'file' -- "$cur" ) )
214 return 0
215 ;;
216 esac
217
218 # Remove all options so completions don't have to deal with them.
219 local i
220 for (( i=1; i < ${#words[@]}; )); do
221 if [[ ${words[i]::1} == - ]]; then
222 words=( "${words[@]:0:i}" "${words[@]:i+1}" )
223 [[ $i -le $cword ]] && cword=$(( cword - 1 ))
224 else
225 i=$(( ++i ))
226 fi
227 done
228 cur=${words[cword]}
229 prev=${words[cword - 1]}
230 pprev=${words[cword - 2]}
231
232 local object=${words[1]} command=${words[2]}
233
234 if [[ -z $object || $cword -eq 1 ]]; then
235 case $cur in
236 *)
237 COMPREPLY=( $( compgen -W "$( bpftool help 2>&1 | \
238 command sed \
239 -e '/OBJECT := /!d' \
240 -e 's/.*{//' \
241 -e 's/}.*//' \
242 -e 's/|//g' )" -- "$cur" ) )
243 COMPREPLY+=( $( compgen -W 'batch help' -- "$cur" ) )
244 return 0
245 ;;
246 esac
247 fi
248
249 [[ $command == help ]] && return 0
250
251 # Completion depends on object and command in use
252 case $object in
253 prog)
254 # Complete id, only for subcommands that use prog (but no map) ids
255 case $command in
256 show|list|dump|pin)
257 case $prev in
258 id)
259 _bpftool_get_prog_ids
260 return 0
261 ;;
262 esac
263 ;;
264 esac
265
266 local PROG_TYPE='id pinned tag'
267 local MAP_TYPE='id pinned'
268 case $command in
269 show|list)
270 [[ $prev != "$command" ]] && return 0
271 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
272 return 0
273 ;;
274 dump)
275 case $prev in
276 $command)
277 COMPREPLY+=( $( compgen -W "xlated jited" -- \
278 "$cur" ) )
279 return 0
280 ;;
281 xlated|jited)
282 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \
283 "$cur" ) )
284 return 0
285 ;;
286 *)
287 _bpftool_once_attr 'file'
288 if _bpftool_search_list 'xlated'; then
289 COMPREPLY+=( $( compgen -W 'opcodes visual linum' -- \
290 "$cur" ) )
291 else
292 COMPREPLY+=( $( compgen -W 'opcodes linum' -- \
293 "$cur" ) )
294 fi
295 return 0
296 ;;
297 esac
298 ;;
299 pin)
300 if [[ $prev == "$command" ]]; then
301 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
302 else
303 _filedir
304 fi
305 return 0
306 ;;
307 attach|detach)
308 case $cword in
309 3)
310 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
311 return 0
312 ;;
313 4)
314 case $prev in
315 id)
316 _bpftool_get_prog_ids
317 ;;
318 pinned)
319 _filedir
320 ;;
321 esac
322 return 0
323 ;;
324 5)
325 COMPREPLY=( $( compgen -W 'msg_verdict stream_verdict \
326 stream_parser flow_dissector' -- "$cur" ) )
327 return 0
328 ;;
329 6)
330 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
331 return 0
332 ;;
333 7)
334 case $prev in
335 id)
336 _bpftool_get_map_ids
337 ;;
338 pinned)
339 _filedir
340 ;;
341 esac
342 return 0
343 ;;
344 esac
345 ;;
346 load|loadall)
347 local obj
348
349 # Propose "load/loadall" to complete "bpftool prog load",
350 # or bash tries to complete "load" as a filename below.
351 if [[ ${#words[@]} -eq 3 ]]; then
352 COMPREPLY=( $( compgen -W "load loadall" -- "$cur" ) )
353 return 0
354 fi
355
356 if [[ ${#words[@]} -lt 6 ]]; then
357 _filedir
358 return 0
359 fi
360
361 obj=${words[3]}
362
363 if [[ ${words[-4]} == "map" ]]; then
364 COMPREPLY=( $( compgen -W "id pinned" -- "$cur" ) )
365 return 0
366 fi
367 if [[ ${words[-3]} == "map" ]]; then
368 if [[ ${words[-2]} == "idx" ]]; then
369 _bpftool_get_obj_map_idxs $obj
370 elif [[ ${words[-2]} == "name" ]]; then
371 _bpftool_get_obj_map_names $obj
372 fi
373 return 0
374 fi
375 if [[ ${words[-2]} == "map" ]]; then
376 COMPREPLY=( $( compgen -W "idx name" -- "$cur" ) )
377 return 0
378 fi
379
380 case $prev in
381 type)
382 COMPREPLY=( $( compgen -W "socket kprobe \
383 kretprobe classifier flow_dissector \
384 action tracepoint raw_tracepoint \
385 xdp perf_event cgroup/skb cgroup/sock \
386 cgroup/dev lwt_in lwt_out lwt_xmit \
387 lwt_seg6local sockops sk_skb sk_msg \
388 lirc_mode2 cgroup/bind4 cgroup/bind6 \
389 cgroup/connect4 cgroup/connect6 \
390 cgroup/sendmsg4 cgroup/sendmsg6 \
391 cgroup/recvmsg4 cgroup/recvmsg6 \
392 cgroup/post_bind4 cgroup/post_bind6 \
393 cgroup/sysctl cgroup/getsockopt \
394 cgroup/setsockopt" -- \
395 "$cur" ) )
396 return 0
397 ;;
398 id)
399 _bpftool_get_map_ids
400 return 0
401 ;;
402 pinned|pinmaps)
403 _filedir
404 return 0
405 ;;
406 *)
407 COMPREPLY=( $( compgen -W "map" -- "$cur" ) )
408 _bpftool_once_attr 'type'
409 _bpftool_once_attr 'dev'
410 _bpftool_once_attr 'pinmaps'
411 return 0
412 ;;
413 esac
414 ;;
415 tracelog)
416 return 0
417 ;;
418 run)
419 if [[ ${#words[@]} -lt 5 ]]; then
420 _filedir
421 return 0
422 fi
423 case $prev in
424 id)
425 _bpftool_get_prog_ids
426 return 0
427 ;;
428 data_in|data_out|ctx_in|ctx_out)
429 _filedir
430 return 0
431 ;;
432 repeat|data_size_out|ctx_size_out)
433 return 0
434 ;;
435 *)
436 _bpftool_once_attr 'data_in data_out data_size_out \
437 ctx_in ctx_out ctx_size_out repeat'
438 return 0
439 ;;
440 esac
441 ;;
442 *)
443 [[ $prev == $object ]] && \
444 COMPREPLY=( $( compgen -W 'dump help pin attach detach \
445 load loadall show list tracelog run' -- "$cur" ) )
446 ;;
447 esac
448 ;;
449 map)
450 local MAP_TYPE='id pinned'
451 case $command in
452 show|list|dump|peek|pop|dequeue|freeze)
453 case $prev in
454 $command)
455 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
456 return 0
457 ;;
458 id)
459 case "$command" in
460 peek)
461 _bpftool_get_map_ids_for_type stack
462 _bpftool_get_map_ids_for_type queue
463 ;;
464 pop)
465 _bpftool_get_map_ids_for_type stack
466 ;;
467 dequeue)
468 _bpftool_get_map_ids_for_type queue
469 ;;
470 *)
471 _bpftool_get_map_ids
472 ;;
473 esac
474 return 0
475 ;;
476 *)
477 return 0
478 ;;
479 esac
480 ;;
481 create)
482 case $prev in
483 $command)
484 _filedir
485 return 0
486 ;;
487 type)
488 COMPREPLY=( $( compgen -W 'hash array prog_array \
489 perf_event_array percpu_hash percpu_array \
490 stack_trace cgroup_array lru_hash \
491 lru_percpu_hash lpm_trie array_of_maps \
492 hash_of_maps devmap devmap_hash sockmap cpumap \
493 xskmap sockhash cgroup_storage reuseport_sockarray \
494 percpu_cgroup_storage queue stack' -- \
495 "$cur" ) )
496 return 0
497 ;;
498 key|value|flags|name|entries)
499 return 0
500 ;;
501 *)
502 _bpftool_once_attr 'type'
503 _bpftool_once_attr 'key'
504 _bpftool_once_attr 'value'
505 _bpftool_once_attr 'entries'
506 _bpftool_once_attr 'name'
507 _bpftool_once_attr 'flags'
508 _bpftool_once_attr 'dev'
509 return 0
510 ;;
511 esac
512 ;;
513 lookup|getnext|delete)
514 case $prev in
515 $command)
516 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
517 return 0
518 ;;
519 id)
520 _bpftool_get_map_ids
521 return 0
522 ;;
523 key)
524 COMPREPLY+=( $( compgen -W 'hex' -- "$cur" ) )
525 ;;
526 *)
527 case $(_bpftool_map_guess_map_type) in
528 queue|stack)
529 return 0
530 ;;
531 esac
532
533 _bpftool_once_attr 'key'
534 return 0
535 ;;
536 esac
537 ;;
538 update|push|enqueue)
539 case $prev in
540 $command)
541 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
542 return 0
543 ;;
544 id)
545 _bpftool_map_update_get_id $command
546 return 0
547 ;;
548 key)
549 COMPREPLY+=( $( compgen -W 'hex' -- "$cur" ) )
550 ;;
551 value)
552 # We can have bytes, or references to a prog or a
553 # map, depending on the type of the map to update.
554 case "$(_bpftool_map_guess_map_type)" in
555 array_of_maps|hash_of_maps)
556 local MAP_TYPE='id pinned'
557 COMPREPLY+=( $( compgen -W "$MAP_TYPE" \
558 -- "$cur" ) )
559 return 0
560 ;;
561 prog_array)
562 local PROG_TYPE='id pinned tag'
563 COMPREPLY+=( $( compgen -W "$PROG_TYPE" \
564 -- "$cur" ) )
565 return 0
566 ;;
567 *)
568 COMPREPLY+=( $( compgen -W 'hex' \
569 -- "$cur" ) )
570 return 0
571 ;;
572 esac
573 return 0
574 ;;
575 *)
576 case $(_bpftool_map_guess_map_type) in
577 queue|stack)
578 _bpftool_once_attr 'value'
579 return 0;
580 ;;
581 esac
582
583 _bpftool_once_attr 'key'
584 local UPDATE_FLAGS='any exist noexist'
585 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
586 if [[ ${words[idx]} == 'value' ]]; then
587 # 'value' is present, but is not the last
588 # word i.e. we can now have UPDATE_FLAGS.
589 _bpftool_one_of_list "$UPDATE_FLAGS"
590 return 0
591 fi
592 done
593 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
594 if [[ ${words[idx]} == 'key' ]]; then
595 # 'key' is present, but is not the last
596 # word i.e. we can now have 'value'.
597 _bpftool_once_attr 'value'
598 return 0
599 fi
600 done
601
602 return 0
603 ;;
604 esac
605 ;;
606 pin)
607 if [[ $prev == "$command" ]]; then
608 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
609 else
610 _filedir
611 fi
612 return 0
613 ;;
614 event_pipe)
615 case $prev in
616 $command)
617 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
618 return 0
619 ;;
620 id)
621 _bpftool_get_map_ids_for_type perf_event_array
622 return 0
623 ;;
624 cpu)
625 return 0
626 ;;
627 index)
628 return 0
629 ;;
630 *)
631 _bpftool_once_attr 'cpu'
632 _bpftool_once_attr 'index'
633 return 0
634 ;;
635 esac
636 ;;
637 *)
638 [[ $prev == $object ]] && \
639 COMPREPLY=( $( compgen -W 'delete dump getnext help \
640 lookup pin event_pipe show list update create \
641 peek push enqueue pop dequeue freeze' -- \
642 "$cur" ) )
643 ;;
644 esac
645 ;;
646 btf)
647 local PROG_TYPE='id pinned tag'
648 local MAP_TYPE='id pinned'
649 case $command in
650 dump)
651 case $prev in
652 $command)
653 COMPREPLY+=( $( compgen -W "id map prog file" -- \
654 "$cur" ) )
655 return 0
656 ;;
657 prog)
658 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
659 return 0
660 ;;
661 map)
662 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
663 return 0
664 ;;
665 id)
666 case $pprev in
667 prog)
668 _bpftool_get_prog_ids
669 ;;
670 map)
671 _bpftool_get_map_ids
672 ;;
673 $command)
674 _bpftool_get_btf_ids
675 ;;
676 esac
677 return 0
678 ;;
679 format)
680 COMPREPLY=( $( compgen -W "c raw" -- "$cur" ) )
681 ;;
682 *)
683 # emit extra options
684 case ${words[3]} in
685 id|file)
686 _bpftool_once_attr 'format'
687 ;;
688 map|prog)
689 if [[ ${words[3]} == "map" ]] && [[ $cword == 6 ]]; then
690 COMPREPLY+=( $( compgen -W "key value kv all" -- "$cur" ) )
691 fi
692 _bpftool_once_attr 'format'
693 ;;
694 *)
695 ;;
696 esac
697 return 0
698 ;;
699 esac
700 ;;
701 show|list)
702 case $prev in
703 $command)
704 COMPREPLY+=( $( compgen -W "id" -- "$cur" ) )
705 ;;
706 id)
707 _bpftool_get_btf_ids
708 ;;
709 esac
710 return 0
711 ;;
712 *)
713 [[ $prev == $object ]] && \
714 COMPREPLY=( $( compgen -W 'dump help show list' \
715 -- "$cur" ) )
716 ;;
717 esac
718 ;;
719 cgroup)
720 case $command in
721 show|list|tree)
722 case $cword in
723 3)
724 _filedir
725 ;;
726 4)
727 COMPREPLY=( $( compgen -W 'effective' -- "$cur" ) )
728 ;;
729 esac
730 return 0
731 ;;
732 attach|detach)
733 local ATTACH_TYPES='ingress egress sock_create sock_ops \
734 device bind4 bind6 post_bind4 post_bind6 connect4 \
735 connect6 sendmsg4 sendmsg6 recvmsg4 recvmsg6 sysctl \
736 getsockopt setsockopt'
737 local ATTACH_FLAGS='multi override'
738 local PROG_TYPE='id pinned tag'
739 case $prev in
740 $command)
741 _filedir
742 return 0
743 ;;
744 ingress|egress|sock_create|sock_ops|device|bind4|bind6|\
745 post_bind4|post_bind6|connect4|connect6|sendmsg4|\
746 sendmsg6|recvmsg4|recvmsg6|sysctl|getsockopt|\
747 setsockopt)
748 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \
749 "$cur" ) )
750 return 0
751 ;;
752 id)
753 _bpftool_get_prog_ids
754 return 0
755 ;;
756 *)
757 if ! _bpftool_search_list "$ATTACH_TYPES"; then
758 COMPREPLY=( $( compgen -W "$ATTACH_TYPES" -- \
759 "$cur" ) )
760 elif [[ "$command" == "attach" ]]; then
761 # We have an attach type on the command line,
762 # but it is not the previous word, or
763 # "id|pinned|tag" (we already checked for
764 # that). This should only leave the case when
765 # we need attach flags for "attach" commamnd.
766 _bpftool_one_of_list "$ATTACH_FLAGS"
767 fi
768 return 0
769 ;;
770 esac
771 ;;
772 *)
773 [[ $prev == $object ]] && \
774 COMPREPLY=( $( compgen -W 'help attach detach \
775 show list tree' -- "$cur" ) )
776 ;;
777 esac
778 ;;
779 perf)
780 case $command in
781 *)
782 [[ $prev == $object ]] && \
783 COMPREPLY=( $( compgen -W 'help \
784 show list' -- "$cur" ) )
785 ;;
786 esac
787 ;;
788 net)
789 local PROG_TYPE='id pinned tag'
790 local ATTACH_TYPES='xdp xdpgeneric xdpdrv xdpoffload'
791 case $command in
792 show|list)
793 [[ $prev != "$command" ]] && return 0
794 COMPREPLY=( $( compgen -W 'dev' -- "$cur" ) )
795 return 0
796 ;;
797 attach)
798 case $cword in
799 3)
800 COMPREPLY=( $( compgen -W "$ATTACH_TYPES" -- "$cur" ) )
801 return 0
802 ;;
803 4)
804 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
805 return 0
806 ;;
807 5)
808 case $prev in
809 id)
810 _bpftool_get_prog_ids
811 ;;
812 pinned)
813 _filedir
814 ;;
815 esac
816 return 0
817 ;;
818 6)
819 COMPREPLY=( $( compgen -W 'dev' -- "$cur" ) )
820 return 0
821 ;;
822 8)
823 _bpftool_once_attr 'overwrite'
824 return 0
825 ;;
826 esac
827 ;;
828 detach)
829 case $cword in
830 3)
831 COMPREPLY=( $( compgen -W "$ATTACH_TYPES" -- "$cur" ) )
832 return 0
833 ;;
834 4)
835 COMPREPLY=( $( compgen -W 'dev' -- "$cur" ) )
836 return 0
837 ;;
838 esac
839 ;;
840 *)
841 [[ $prev == $object ]] && \
842 COMPREPLY=( $( compgen -W 'help \
843 show list attach detach' -- "$cur" ) )
844 ;;
845 esac
846 ;;
847 feature)
848 case $command in
849 probe)
850 [[ $prev == "prefix" ]] && return 0
851 if _bpftool_search_list 'macros'; then
852 COMPREPLY+=( $( compgen -W 'prefix' -- "$cur" ) )
853 else
854 COMPREPLY+=( $( compgen -W 'macros' -- "$cur" ) )
855 fi
856 _bpftool_one_of_list 'kernel dev'
857 return 0
858 ;;
859 *)
860 [[ $prev == $object ]] && \
861 COMPREPLY=( $( compgen -W 'help probe' -- "$cur" ) )
862 ;;
863 esac
864 ;;
865 esac
866} &&
867complete -F _bpftool bpftool
868
869# ex: ts=4 sw=4 et filetype=sh