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