Loading...
Note: File does not exist in v3.15.
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
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
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 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 objword
259 _init_completion || return
260
261 # Deal with options
262 if [[ ${words[cword]} == -* ]]; then
263 local c='--version --json --pretty --bpffs --mapcompat --debug'
264 COMPREPLY=( $( compgen -W "$c" -- "$cur" ) )
265 return 0
266 fi
267
268 # Deal with simplest keywords
269 case $prev in
270 help|hex|opcodes|visual|linum)
271 return 0
272 ;;
273 tag)
274 _bpftool_get_prog_tags
275 return 0
276 ;;
277 dev)
278 _sysfs_get_netdevs
279 return 0
280 ;;
281 file|pinned)
282 _filedir
283 return 0
284 ;;
285 batch)
286 COMPREPLY=( $( compgen -W 'file' -- "$cur" ) )
287 return 0
288 ;;
289 esac
290
291 # Remove all options so completions don't have to deal with them.
292 local i
293 for (( i=1; i < ${#words[@]}; )); do
294 if [[ ${words[i]::1} == - ]]; then
295 words=( "${words[@]:0:i}" "${words[@]:i+1}" )
296 [[ $i -le $cword ]] && cword=$(( cword - 1 ))
297 else
298 i=$(( ++i ))
299 fi
300 done
301 cur=${words[cword]}
302 prev=${words[cword - 1]}
303 pprev=${words[cword - 2]}
304
305 local object=${words[1]} command=${words[2]}
306
307 if [[ -z $object || $cword -eq 1 ]]; then
308 case $cur in
309 *)
310 COMPREPLY=( $( compgen -W "$( bpftool help 2>&1 | \
311 command sed \
312 -e '/OBJECT := /!d' \
313 -e 's/.*{//' \
314 -e 's/}.*//' \
315 -e 's/|//g' )" -- "$cur" ) )
316 COMPREPLY+=( $( compgen -W 'batch help' -- "$cur" ) )
317 return 0
318 ;;
319 esac
320 fi
321
322 [[ $command == help ]] && return 0
323
324 # Completion depends on object and command in use
325 case $object in
326 prog)
327 # Complete id and name, only for subcommands that use prog (but no
328 # map) ids/names.
329 case $command in
330 show|list|dump|pin)
331 case $prev in
332 id)
333 _bpftool_get_prog_ids
334 return 0
335 ;;
336 name)
337 _bpftool_get_prog_names
338 return 0
339 ;;
340 esac
341 ;;
342 esac
343
344 local PROG_TYPE='id pinned tag name'
345 local MAP_TYPE='id pinned name'
346 local METRIC_TYPE='cycles instructions l1d_loads llc_misses'
347 case $command in
348 show|list)
349 [[ $prev != "$command" ]] && return 0
350 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
351 return 0
352 ;;
353 dump)
354 case $prev in
355 $command)
356 COMPREPLY+=( $( compgen -W "xlated jited" -- \
357 "$cur" ) )
358 return 0
359 ;;
360 xlated|jited)
361 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \
362 "$cur" ) )
363 return 0
364 ;;
365 *)
366 _bpftool_once_attr 'file'
367 if _bpftool_search_list 'xlated'; then
368 COMPREPLY+=( $( compgen -W 'opcodes visual linum' -- \
369 "$cur" ) )
370 else
371 COMPREPLY+=( $( compgen -W 'opcodes linum' -- \
372 "$cur" ) )
373 fi
374 return 0
375 ;;
376 esac
377 ;;
378 pin)
379 if [[ $prev == "$command" ]]; then
380 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
381 else
382 _filedir
383 fi
384 return 0
385 ;;
386 attach|detach)
387 case $cword in
388 3)
389 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
390 return 0
391 ;;
392 4)
393 case $prev in
394 id)
395 _bpftool_get_prog_ids
396 ;;
397 name)
398 _bpftool_get_prog_names
399 ;;
400 pinned)
401 _filedir
402 ;;
403 esac
404 return 0
405 ;;
406 5)
407 COMPREPLY=( $( compgen -W 'msg_verdict stream_verdict \
408 stream_parser flow_dissector' -- "$cur" ) )
409 return 0
410 ;;
411 6)
412 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
413 return 0
414 ;;
415 7)
416 case $prev in
417 id)
418 _bpftool_get_map_ids
419 ;;
420 name)
421 _bpftool_get_map_names
422 ;;
423 pinned)
424 _filedir
425 ;;
426 esac
427 return 0
428 ;;
429 esac
430 ;;
431 load|loadall)
432 local obj
433
434 # Propose "load/loadall" to complete "bpftool prog load",
435 # or bash tries to complete "load" as a filename below.
436 if [[ ${#words[@]} -eq 3 ]]; then
437 COMPREPLY=( $( compgen -W "load loadall" -- "$cur" ) )
438 return 0
439 fi
440
441 if [[ ${#words[@]} -lt 6 ]]; then
442 _filedir
443 return 0
444 fi
445
446 obj=${words[3]}
447
448 if [[ ${words[-4]} == "map" ]]; then
449 COMPREPLY=( $( compgen -W "id pinned" -- "$cur" ) )
450 return 0
451 fi
452 if [[ ${words[-3]} == "map" ]]; then
453 if [[ ${words[-2]} == "idx" ]]; then
454 _bpftool_get_obj_map_idxs $obj
455 elif [[ ${words[-2]} == "name" ]]; then
456 _bpftool_get_obj_map_names $obj
457 fi
458 return 0
459 fi
460 if [[ ${words[-2]} == "map" ]]; then
461 COMPREPLY=( $( compgen -W "idx name" -- "$cur" ) )
462 return 0
463 fi
464
465 case $prev in
466 type)
467 COMPREPLY=( $( compgen -W "socket kprobe \
468 kretprobe classifier flow_dissector \
469 action tracepoint raw_tracepoint \
470 xdp perf_event cgroup/skb cgroup/sock \
471 cgroup/dev lwt_in lwt_out lwt_xmit \
472 lwt_seg6local sockops sk_skb sk_msg \
473 lirc_mode2 cgroup/bind4 cgroup/bind6 \
474 cgroup/connect4 cgroup/connect6 \
475 cgroup/getpeername4 cgroup/getpeername6 \
476 cgroup/getsockname4 cgroup/getsockname6 \
477 cgroup/sendmsg4 cgroup/sendmsg6 \
478 cgroup/recvmsg4 cgroup/recvmsg6 \
479 cgroup/post_bind4 cgroup/post_bind6 \
480 cgroup/sysctl cgroup/getsockopt \
481 cgroup/setsockopt struct_ops \
482 fentry fexit freplace sk_lookup" -- \
483 "$cur" ) )
484 return 0
485 ;;
486 id)
487 _bpftool_get_map_ids
488 return 0
489 ;;
490 name)
491 _bpftool_get_map_names
492 return 0
493 ;;
494 pinned|pinmaps)
495 _filedir
496 return 0
497 ;;
498 *)
499 COMPREPLY=( $( compgen -W "map" -- "$cur" ) )
500 _bpftool_once_attr 'type'
501 _bpftool_once_attr 'dev'
502 _bpftool_once_attr 'pinmaps'
503 return 0
504 ;;
505 esac
506 ;;
507 tracelog)
508 return 0
509 ;;
510 profile)
511 case $cword in
512 3)
513 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
514 return 0
515 ;;
516 4)
517 case $prev in
518 id)
519 _bpftool_get_prog_ids
520 ;;
521 name)
522 _bpftool_get_prog_names
523 ;;
524 pinned)
525 _filedir
526 ;;
527 esac
528 return 0
529 ;;
530 5)
531 COMPREPLY=( $( compgen -W "$METRIC_TYPE duration" -- "$cur" ) )
532 return 0
533 ;;
534 6)
535 case $prev in
536 duration)
537 return 0
538 ;;
539 *)
540 COMPREPLY=( $( compgen -W "$METRIC_TYPE" -- "$cur" ) )
541 return 0
542 ;;
543 esac
544 return 0
545 ;;
546 *)
547 COMPREPLY=( $( compgen -W "$METRIC_TYPE" -- "$cur" ) )
548 return 0
549 ;;
550 esac
551 ;;
552 run)
553 if [[ ${#words[@]} -eq 4 ]]; then
554 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
555 return 0
556 fi
557 case $prev in
558 id)
559 _bpftool_get_prog_ids
560 return 0
561 ;;
562 name)
563 _bpftool_get_prog_names
564 return 0
565 ;;
566 data_in|data_out|ctx_in|ctx_out)
567 _filedir
568 return 0
569 ;;
570 repeat|data_size_out|ctx_size_out)
571 return 0
572 ;;
573 *)
574 _bpftool_once_attr 'data_in data_out data_size_out \
575 ctx_in ctx_out ctx_size_out repeat'
576 return 0
577 ;;
578 esac
579 ;;
580 *)
581 [[ $prev == $object ]] && \
582 COMPREPLY=( $( compgen -W 'dump help pin attach detach \
583 load loadall show list tracelog run profile' -- "$cur" ) )
584 ;;
585 esac
586 ;;
587 struct_ops)
588 local STRUCT_OPS_TYPE='id name'
589 case $command in
590 show|list|dump|unregister)
591 case $prev in
592 $command)
593 COMPREPLY=( $( compgen -W "$STRUCT_OPS_TYPE" -- "$cur" ) )
594 ;;
595 id)
596 _bpftool_get_map_ids_for_type struct_ops
597 ;;
598 name)
599 _bpftool_get_map_names_for_type struct_ops
600 ;;
601 esac
602 return 0
603 ;;
604 register)
605 _filedir
606 return 0
607 ;;
608 *)
609 [[ $prev == $object ]] && \
610 COMPREPLY=( $( compgen -W 'register unregister show list dump help' \
611 -- "$cur" ) )
612 ;;
613 esac
614 ;;
615 iter)
616 case $command in
617 pin)
618 case $prev in
619 $command)
620 _filedir
621 ;;
622 id)
623 _bpftool_get_map_ids
624 ;;
625 name)
626 _bpftool_get_map_names
627 ;;
628 pinned)
629 _filedir
630 ;;
631 *)
632 _bpftool_one_of_list $MAP_TYPE
633 ;;
634 esac
635 return 0
636 ;;
637 *)
638 [[ $prev == $object ]] && \
639 COMPREPLY=( $( compgen -W 'pin help' \
640 -- "$cur" ) )
641 ;;
642 esac
643 ;;
644 map)
645 local MAP_TYPE='id pinned name'
646 case $command in
647 show|list|dump|peek|pop|dequeue|freeze)
648 case $prev in
649 $command)
650 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
651 return 0
652 ;;
653 id)
654 case "$command" in
655 peek)
656 _bpftool_get_map_ids_for_type stack
657 _bpftool_get_map_ids_for_type queue
658 ;;
659 pop)
660 _bpftool_get_map_ids_for_type stack
661 ;;
662 dequeue)
663 _bpftool_get_map_ids_for_type queue
664 ;;
665 *)
666 _bpftool_get_map_ids
667 ;;
668 esac
669 return 0
670 ;;
671 name)
672 case "$command" in
673 peek)
674 _bpftool_get_map_names_for_type stack
675 _bpftool_get_map_names_for_type queue
676 ;;
677 pop)
678 _bpftool_get_map_names_for_type stack
679 ;;
680 dequeue)
681 _bpftool_get_map_names_for_type queue
682 ;;
683 *)
684 _bpftool_get_map_names
685 ;;
686 esac
687 return 0
688 ;;
689 *)
690 return 0
691 ;;
692 esac
693 ;;
694 create)
695 case $prev in
696 $command)
697 _filedir
698 return 0
699 ;;
700 type)
701 COMPREPLY=( $( compgen -W 'hash array prog_array \
702 perf_event_array percpu_hash percpu_array \
703 stack_trace cgroup_array lru_hash \
704 lru_percpu_hash lpm_trie array_of_maps \
705 hash_of_maps devmap devmap_hash sockmap cpumap \
706 xskmap sockhash cgroup_storage reuseport_sockarray \
707 percpu_cgroup_storage queue stack' -- \
708 "$cur" ) )
709 return 0
710 ;;
711 key|value|flags|name|entries)
712 return 0
713 ;;
714 *)
715 _bpftool_once_attr 'type'
716 _bpftool_once_attr 'key'
717 _bpftool_once_attr 'value'
718 _bpftool_once_attr 'entries'
719 _bpftool_once_attr 'name'
720 _bpftool_once_attr 'flags'
721 _bpftool_once_attr 'dev'
722 return 0
723 ;;
724 esac
725 ;;
726 lookup|getnext|delete)
727 case $prev in
728 $command)
729 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
730 return 0
731 ;;
732 id)
733 _bpftool_get_map_ids
734 return 0
735 ;;
736 name)
737 _bpftool_get_map_names
738 return 0
739 ;;
740 key)
741 COMPREPLY+=( $( compgen -W 'hex' -- "$cur" ) )
742 ;;
743 *)
744 case $(_bpftool_map_guess_map_type) in
745 queue|stack)
746 return 0
747 ;;
748 esac
749
750 _bpftool_once_attr 'key'
751 return 0
752 ;;
753 esac
754 ;;
755 update|push|enqueue)
756 case $prev in
757 $command)
758 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
759 return 0
760 ;;
761 id)
762 _bpftool_map_update_get_id $command
763 return 0
764 ;;
765 name)
766 _bpftool_map_update_get_name $command
767 return 0
768 ;;
769 key)
770 COMPREPLY+=( $( compgen -W 'hex' -- "$cur" ) )
771 ;;
772 value)
773 # We can have bytes, or references to a prog or a
774 # map, depending on the type of the map to update.
775 case "$(_bpftool_map_guess_map_type)" in
776 array_of_maps|hash_of_maps)
777 local MAP_TYPE='id pinned name'
778 COMPREPLY+=( $( compgen -W "$MAP_TYPE" \
779 -- "$cur" ) )
780 return 0
781 ;;
782 prog_array)
783 local PROG_TYPE='id pinned tag name'
784 COMPREPLY+=( $( compgen -W "$PROG_TYPE" \
785 -- "$cur" ) )
786 return 0
787 ;;
788 *)
789 COMPREPLY+=( $( compgen -W 'hex' \
790 -- "$cur" ) )
791 return 0
792 ;;
793 esac
794 return 0
795 ;;
796 *)
797 case $(_bpftool_map_guess_map_type) in
798 queue|stack)
799 _bpftool_once_attr 'value'
800 return 0;
801 ;;
802 esac
803
804 _bpftool_once_attr 'key'
805 local UPDATE_FLAGS='any exist noexist'
806 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
807 if [[ ${words[idx]} == 'value' ]]; then
808 # 'value' is present, but is not the last
809 # word i.e. we can now have UPDATE_FLAGS.
810 _bpftool_one_of_list "$UPDATE_FLAGS"
811 return 0
812 fi
813 done
814 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
815 if [[ ${words[idx]} == 'key' ]]; then
816 # 'key' is present, but is not the last
817 # word i.e. we can now have 'value'.
818 _bpftool_once_attr 'value'
819 return 0
820 fi
821 done
822
823 return 0
824 ;;
825 esac
826 ;;
827 pin)
828 case $prev in
829 $command)
830 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
831 ;;
832 id)
833 _bpftool_get_map_ids
834 ;;
835 name)
836 _bpftool_get_map_names
837 ;;
838 esac
839 return 0
840 ;;
841 event_pipe)
842 case $prev in
843 $command)
844 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
845 return 0
846 ;;
847 id)
848 _bpftool_get_map_ids_for_type perf_event_array
849 return 0
850 ;;
851 name)
852 _bpftool_get_map_names_for_type perf_event_array
853 return 0
854 ;;
855 cpu)
856 return 0
857 ;;
858 index)
859 return 0
860 ;;
861 *)
862 _bpftool_once_attr 'cpu'
863 _bpftool_once_attr 'index'
864 return 0
865 ;;
866 esac
867 ;;
868 *)
869 [[ $prev == $object ]] && \
870 COMPREPLY=( $( compgen -W 'delete dump getnext help \
871 lookup pin event_pipe show list update create \
872 peek push enqueue pop dequeue freeze' -- \
873 "$cur" ) )
874 ;;
875 esac
876 ;;
877 btf)
878 local PROG_TYPE='id pinned tag name'
879 local MAP_TYPE='id pinned name'
880 case $command in
881 dump)
882 case $prev in
883 $command)
884 COMPREPLY+=( $( compgen -W "id map prog file" -- \
885 "$cur" ) )
886 return 0
887 ;;
888 prog)
889 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
890 return 0
891 ;;
892 map)
893 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
894 return 0
895 ;;
896 id)
897 case $pprev in
898 prog)
899 _bpftool_get_prog_ids
900 ;;
901 map)
902 _bpftool_get_map_ids
903 ;;
904 $command)
905 _bpftool_get_btf_ids
906 ;;
907 esac
908 return 0
909 ;;
910 name)
911 case $pprev in
912 prog)
913 _bpftool_get_prog_names
914 ;;
915 map)
916 _bpftool_get_map_names
917 ;;
918 esac
919 return 0
920 ;;
921 format)
922 COMPREPLY=( $( compgen -W "c raw" -- "$cur" ) )
923 ;;
924 *)
925 # emit extra options
926 case ${words[3]} in
927 id|file)
928 _bpftool_once_attr 'format'
929 ;;
930 map|prog)
931 if [[ ${words[3]} == "map" ]] && [[ $cword == 6 ]]; then
932 COMPREPLY+=( $( compgen -W "key value kv all" -- "$cur" ) )
933 fi
934 _bpftool_once_attr 'format'
935 ;;
936 *)
937 ;;
938 esac
939 return 0
940 ;;
941 esac
942 ;;
943 show|list)
944 case $prev in
945 $command)
946 COMPREPLY+=( $( compgen -W "id" -- "$cur" ) )
947 ;;
948 id)
949 _bpftool_get_btf_ids
950 ;;
951 esac
952 return 0
953 ;;
954 *)
955 [[ $prev == $object ]] && \
956 COMPREPLY=( $( compgen -W 'dump help show list' \
957 -- "$cur" ) )
958 ;;
959 esac
960 ;;
961 gen)
962 case $command in
963 skeleton)
964 _filedir
965 ;;
966 *)
967 [[ $prev == $object ]] && \
968 COMPREPLY=( $( compgen -W 'skeleton help' -- "$cur" ) )
969 ;;
970 esac
971 ;;
972 cgroup)
973 case $command in
974 show|list|tree)
975 case $cword in
976 3)
977 _filedir
978 ;;
979 4)
980 COMPREPLY=( $( compgen -W 'effective' -- "$cur" ) )
981 ;;
982 esac
983 return 0
984 ;;
985 attach|detach)
986 local ATTACH_TYPES='ingress egress sock_create sock_ops \
987 device bind4 bind6 post_bind4 post_bind6 connect4 connect6 \
988 getpeername4 getpeername6 getsockname4 getsockname6 \
989 sendmsg4 sendmsg6 recvmsg4 recvmsg6 sysctl getsockopt \
990 setsockopt'
991 local ATTACH_FLAGS='multi override'
992 local PROG_TYPE='id pinned tag name'
993 case $prev in
994 $command)
995 _filedir
996 return 0
997 ;;
998 ingress|egress|sock_create|sock_ops|device|bind4|bind6|\
999 post_bind4|post_bind6|connect4|connect6|getpeername4|\
1000 getpeername6|getsockname4|getsockname6|sendmsg4|sendmsg6|\
1001 recvmsg4|recvmsg6|sysctl|getsockopt|setsockopt)
1002 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \
1003 "$cur" ) )
1004 return 0
1005 ;;
1006 id)
1007 _bpftool_get_prog_ids
1008 return 0
1009 ;;
1010 *)
1011 if ! _bpftool_search_list "$ATTACH_TYPES"; then
1012 COMPREPLY=( $( compgen -W "$ATTACH_TYPES" -- \
1013 "$cur" ) )
1014 elif [[ "$command" == "attach" ]]; then
1015 # We have an attach type on the command line,
1016 # but it is not the previous word, or
1017 # "id|pinned|tag|name" (we already checked for
1018 # that). This should only leave the case when
1019 # we need attach flags for "attach" commamnd.
1020 _bpftool_one_of_list "$ATTACH_FLAGS"
1021 fi
1022 return 0
1023 ;;
1024 esac
1025 ;;
1026 *)
1027 [[ $prev == $object ]] && \
1028 COMPREPLY=( $( compgen -W 'help attach detach \
1029 show list tree' -- "$cur" ) )
1030 ;;
1031 esac
1032 ;;
1033 perf)
1034 case $command in
1035 *)
1036 [[ $prev == $object ]] && \
1037 COMPREPLY=( $( compgen -W 'help \
1038 show list' -- "$cur" ) )
1039 ;;
1040 esac
1041 ;;
1042 net)
1043 local PROG_TYPE='id pinned tag name'
1044 local ATTACH_TYPES='xdp xdpgeneric xdpdrv xdpoffload'
1045 case $command in
1046 show|list)
1047 [[ $prev != "$command" ]] && return 0
1048 COMPREPLY=( $( compgen -W 'dev' -- "$cur" ) )
1049 return 0
1050 ;;
1051 attach)
1052 case $cword in
1053 3)
1054 COMPREPLY=( $( compgen -W "$ATTACH_TYPES" -- "$cur" ) )
1055 return 0
1056 ;;
1057 4)
1058 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
1059 return 0
1060 ;;
1061 5)
1062 case $prev in
1063 id)
1064 _bpftool_get_prog_ids
1065 ;;
1066 name)
1067 _bpftool_get_prog_names
1068 ;;
1069 pinned)
1070 _filedir
1071 ;;
1072 esac
1073 return 0
1074 ;;
1075 6)
1076 COMPREPLY=( $( compgen -W 'dev' -- "$cur" ) )
1077 return 0
1078 ;;
1079 8)
1080 _bpftool_once_attr 'overwrite'
1081 return 0
1082 ;;
1083 esac
1084 ;;
1085 detach)
1086 case $cword in
1087 3)
1088 COMPREPLY=( $( compgen -W "$ATTACH_TYPES" -- "$cur" ) )
1089 return 0
1090 ;;
1091 4)
1092 COMPREPLY=( $( compgen -W 'dev' -- "$cur" ) )
1093 return 0
1094 ;;
1095 esac
1096 ;;
1097 *)
1098 [[ $prev == $object ]] && \
1099 COMPREPLY=( $( compgen -W 'help \
1100 show list attach detach' -- "$cur" ) )
1101 ;;
1102 esac
1103 ;;
1104 feature)
1105 case $command in
1106 probe)
1107 [[ $prev == "prefix" ]] && return 0
1108 if _bpftool_search_list 'macros'; then
1109 _bpftool_once_attr 'prefix'
1110 else
1111 COMPREPLY+=( $( compgen -W 'macros' -- "$cur" ) )
1112 fi
1113 _bpftool_one_of_list 'kernel dev'
1114 _bpftool_once_attr 'full unprivileged'
1115 return 0
1116 ;;
1117 *)
1118 [[ $prev == $object ]] && \
1119 COMPREPLY=( $( compgen -W 'help probe' -- "$cur" ) )
1120 ;;
1121 esac
1122 ;;
1123 link)
1124 case $command in
1125 show|list|pin|detach)
1126 case $prev in
1127 id)
1128 _bpftool_get_link_ids
1129 return 0
1130 ;;
1131 esac
1132 ;;
1133 esac
1134
1135 local LINK_TYPE='id pinned'
1136 case $command in
1137 show|list)
1138 [[ $prev != "$command" ]] && return 0
1139 COMPREPLY=( $( compgen -W "$LINK_TYPE" -- "$cur" ) )
1140 return 0
1141 ;;
1142 pin|detach)
1143 if [[ $prev == "$command" ]]; then
1144 COMPREPLY=( $( compgen -W "$LINK_TYPE" -- "$cur" ) )
1145 else
1146 _filedir
1147 fi
1148 return 0
1149 ;;
1150 *)
1151 [[ $prev == $object ]] && \
1152 COMPREPLY=( $( compgen -W 'help pin show list' -- "$cur" ) )
1153 ;;
1154 esac
1155 ;;
1156 esac
1157} &&
1158complete -F _bpftool bpftool
1159
1160# ex: ts=4 sw=4 et filetype=sh