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