atlantic: Fix driver resume flow.
[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         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 cgroup/sock_release 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 sk_storage \
708                                 struct_ops inode_storage task_storage' -- \
709                                                    "$cur" ) )
710                             return 0
711                             ;;
712                         key|value|flags|entries)
713                             return 0
714                             ;;
715                         inner_map)
716                             COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
717                             return 0
718                             ;;
719                         id)
720                             _bpftool_get_map_ids
721                             ;;
722                         name)
723                             case $pprev in
724                                 inner_map)
725                                     _bpftool_get_map_names
726                                     ;;
727                                 *)
728                                     return 0
729                                     ;;
730                             esac
731                             ;;
732                         *)
733                             _bpftool_once_attr 'type'
734                             _bpftool_once_attr 'key'
735                             _bpftool_once_attr 'value'
736                             _bpftool_once_attr 'entries'
737                             _bpftool_once_attr 'name'
738                             _bpftool_once_attr 'flags'
739                             if _bpftool_search_list 'array_of_maps' 'hash_of_maps'; then
740                                 _bpftool_once_attr 'inner_map'
741                             fi
742                             _bpftool_once_attr 'dev'
743                             return 0
744                             ;;
745                     esac
746                     ;;
747                 lookup|getnext|delete)
748                     case $prev in
749                         $command)
750                             COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
751                             return 0
752                             ;;
753                         id)
754                             _bpftool_get_map_ids
755                             return 0
756                             ;;
757                         name)
758                             _bpftool_get_map_names
759                             return 0
760                             ;;
761                         key)
762                             COMPREPLY+=( $( compgen -W 'hex' -- "$cur" ) )
763                             ;;
764                         *)
765                             case $(_bpftool_map_guess_map_type) in
766                                 queue|stack)
767                                     return 0
768                                     ;;
769                             esac
770
771                             _bpftool_once_attr 'key'
772                             return 0
773                             ;;
774                     esac
775                     ;;
776                 update|push|enqueue)
777                     case $prev in
778                         $command)
779                             COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
780                             return 0
781                             ;;
782                         id)
783                             _bpftool_map_update_get_id $command
784                             return 0
785                             ;;
786                         name)
787                             _bpftool_map_update_get_name $command
788                             return 0
789                             ;;
790                         key)
791                             COMPREPLY+=( $( compgen -W 'hex' -- "$cur" ) )
792                             ;;
793                         value)
794                             # We can have bytes, or references to a prog or a
795                             # map, depending on the type of the map to update.
796                             case "$(_bpftool_map_guess_map_type)" in
797                                 array_of_maps|hash_of_maps)
798                                     local MAP_TYPE='id pinned name'
799                                     COMPREPLY+=( $( compgen -W "$MAP_TYPE" \
800                                         -- "$cur" ) )
801                                     return 0
802                                     ;;
803                                 prog_array)
804                                     local PROG_TYPE='id pinned tag name'
805                                     COMPREPLY+=( $( compgen -W "$PROG_TYPE" \
806                                         -- "$cur" ) )
807                                     return 0
808                                     ;;
809                                 *)
810                                     COMPREPLY+=( $( compgen -W 'hex' \
811                                         -- "$cur" ) )
812                                     return 0
813                                     ;;
814                             esac
815                             return 0
816                             ;;
817                         *)
818                             case $(_bpftool_map_guess_map_type) in
819                                 queue|stack)
820                                     _bpftool_once_attr 'value'
821                                     return 0;
822                                     ;;
823                             esac
824
825                             _bpftool_once_attr 'key'
826                             local UPDATE_FLAGS='any exist noexist'
827                             for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
828                                 if [[ ${words[idx]} == 'value' ]]; then
829                                     # 'value' is present, but is not the last
830                                     # word i.e. we can now have UPDATE_FLAGS.
831                                     _bpftool_one_of_list "$UPDATE_FLAGS"
832                                     return 0
833                                 fi
834                             done
835                             for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
836                                 if [[ ${words[idx]} == 'key' ]]; then
837                                     # 'key' is present, but is not the last
838                                     # word i.e. we can now have 'value'.
839                                     _bpftool_once_attr 'value'
840                                     return 0
841                                 fi
842                             done
843
844                             return 0
845                             ;;
846                     esac
847                     ;;
848                 pin)
849                     case $prev in
850                         $command)
851                             COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
852                             ;;
853                         id)
854                             _bpftool_get_map_ids
855                             ;;
856                         name)
857                             _bpftool_get_map_names
858                             ;;
859                     esac
860                     return 0
861                     ;;
862                 event_pipe)
863                     case $prev in
864                         $command)
865                             COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
866                             return 0
867                             ;;
868                         id)
869                             _bpftool_get_map_ids_for_type perf_event_array
870                             return 0
871                             ;;
872                         name)
873                             _bpftool_get_map_names_for_type perf_event_array
874                             return 0
875                             ;;
876                         cpu)
877                             return 0
878                             ;;
879                         index)
880                             return 0
881                             ;;
882                         *)
883                             _bpftool_once_attr 'cpu'
884                             _bpftool_once_attr 'index'
885                             return 0
886                             ;;
887                     esac
888                     ;;
889                 *)
890                     [[ $prev == $object ]] && \
891                         COMPREPLY=( $( compgen -W 'delete dump getnext help \
892                             lookup pin event_pipe show list update create \
893                             peek push enqueue pop dequeue freeze' -- \
894                             "$cur" ) )
895                     ;;
896             esac
897             ;;
898         btf)
899             local PROG_TYPE='id pinned tag name'
900             local MAP_TYPE='id pinned name'
901             case $command in
902                 dump)
903                     case $prev in
904                         $command)
905                             COMPREPLY+=( $( compgen -W "id map prog file" -- \
906                                 "$cur" ) )
907                             return 0
908                             ;;
909                         prog)
910                             COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
911                             return 0
912                             ;;
913                         map)
914                             COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
915                             return 0
916                             ;;
917                         id)
918                             case $pprev in
919                                 prog)
920                                     _bpftool_get_prog_ids
921                                     ;;
922                                 map)
923                                     _bpftool_get_map_ids
924                                     ;;
925                                 $command)
926                                     _bpftool_get_btf_ids
927                                     ;;
928                             esac
929                             return 0
930                             ;;
931                         name)
932                             case $pprev in
933                                 prog)
934                                     _bpftool_get_prog_names
935                                     ;;
936                                 map)
937                                     _bpftool_get_map_names
938                                     ;;
939                             esac
940                             return 0
941                             ;;
942                         format)
943                             COMPREPLY=( $( compgen -W "c raw" -- "$cur" ) )
944                             ;;
945                         *)
946                             # emit extra options
947                             case ${words[3]} in
948                                 id|file)
949                                     _bpftool_once_attr 'format'
950                                     ;;
951                                 map|prog)
952                                     if [[ ${words[3]} == "map" ]] && [[ $cword == 6 ]]; then
953                                         COMPREPLY+=( $( compgen -W "key value kv all" -- "$cur" ) )
954                                     fi
955                                     _bpftool_once_attr 'format'
956                                     ;;
957                                 *)
958                                     ;;
959                             esac
960                             return 0
961                             ;;
962                     esac
963                     ;;
964                 show|list)
965                     case $prev in
966                         $command)
967                             COMPREPLY+=( $( compgen -W "id" -- "$cur" ) )
968                             ;;
969                         id)
970                             _bpftool_get_btf_ids
971                             ;;
972                     esac
973                     return 0
974                     ;;
975                 *)
976                     [[ $prev == $object ]] && \
977                         COMPREPLY=( $( compgen -W 'dump help show list' \
978                             -- "$cur" ) )
979                     ;;
980             esac
981             ;;
982         gen)
983             case $command in
984                 object)
985                     _filedir
986                     return 0
987                     ;;
988                 skeleton)
989                     case $prev in
990                         $command)
991                             _filedir
992                             return 0
993                             ;;
994                         *)
995                             _bpftool_once_attr 'name'
996                             return 0
997                             ;;
998                     esac
999                     ;;
1000                 *)
1001                     [[ $prev == $object ]] && \
1002                         COMPREPLY=( $( compgen -W 'object skeleton help' -- "$cur" ) )
1003                     ;;
1004             esac
1005             ;;
1006         cgroup)
1007             case $command in
1008                 show|list|tree)
1009                     case $cword in
1010                         3)
1011                             _filedir
1012                             ;;
1013                         4)
1014                             COMPREPLY=( $( compgen -W 'effective' -- "$cur" ) )
1015                             ;;
1016                     esac
1017                     return 0
1018                     ;;
1019                 attach|detach)
1020                     local ATTACH_TYPES='ingress egress sock_create sock_ops \
1021                         device bind4 bind6 post_bind4 post_bind6 connect4 connect6 \
1022                         getpeername4 getpeername6 getsockname4 getsockname6 \
1023                         sendmsg4 sendmsg6 recvmsg4 recvmsg6 sysctl getsockopt \
1024                         setsockopt sock_release'
1025                     local ATTACH_FLAGS='multi override'
1026                     local PROG_TYPE='id pinned tag name'
1027                     case $prev in
1028                         $command)
1029                             _filedir
1030                             return 0
1031                             ;;
1032                         ingress|egress|sock_create|sock_ops|device|bind4|bind6|\
1033                         post_bind4|post_bind6|connect4|connect6|getpeername4|\
1034                         getpeername6|getsockname4|getsockname6|sendmsg4|sendmsg6|\
1035                         recvmsg4|recvmsg6|sysctl|getsockopt|setsockopt|sock_release)
1036                             COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \
1037                                 "$cur" ) )
1038                             return 0
1039                             ;;
1040                         id)
1041                             _bpftool_get_prog_ids
1042                             return 0
1043                             ;;
1044                         *)
1045                             if ! _bpftool_search_list "$ATTACH_TYPES"; then
1046                                 COMPREPLY=( $( compgen -W "$ATTACH_TYPES" -- \
1047                                     "$cur" ) )
1048                             elif [[ "$command" == "attach" ]]; then
1049                                 # We have an attach type on the command line,
1050                                 # but it is not the previous word, or
1051                                 # "id|pinned|tag|name" (we already checked for
1052                                 # that). This should only leave the case when
1053                                 # we need attach flags for "attach" commamnd.
1054                                 _bpftool_one_of_list "$ATTACH_FLAGS"
1055                             fi
1056                             return 0
1057                             ;;
1058                     esac
1059                     ;;
1060                 *)
1061                     [[ $prev == $object ]] && \
1062                         COMPREPLY=( $( compgen -W 'help attach detach \
1063                             show list tree' -- "$cur" ) )
1064                     ;;
1065             esac
1066             ;;
1067         perf)
1068             case $command in
1069                 *)
1070                     [[ $prev == $object ]] && \
1071                         COMPREPLY=( $( compgen -W 'help \
1072                             show list' -- "$cur" ) )
1073                     ;;
1074             esac
1075             ;;
1076         net)
1077             local PROG_TYPE='id pinned tag name'
1078             local ATTACH_TYPES='xdp xdpgeneric xdpdrv xdpoffload'
1079             case $command in
1080                 show|list)
1081                     [[ $prev != "$command" ]] && return 0
1082                     COMPREPLY=( $( compgen -W 'dev' -- "$cur" ) )
1083                     return 0
1084                     ;;
1085                 attach)
1086                     case $cword in
1087                         3)
1088                             COMPREPLY=( $( compgen -W "$ATTACH_TYPES" -- "$cur" ) )
1089                             return 0
1090                             ;;
1091                         4)
1092                             COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
1093                             return 0
1094                             ;;
1095                         5)
1096                             case $prev in
1097                                 id)
1098                                     _bpftool_get_prog_ids
1099                                     ;;
1100                                 name)
1101                                     _bpftool_get_prog_names
1102                                     ;;
1103                                 pinned)
1104                                     _filedir
1105                                     ;;
1106                             esac
1107                             return 0
1108                             ;;
1109                         6)
1110                             COMPREPLY=( $( compgen -W 'dev' -- "$cur" ) )
1111                             return 0
1112                             ;;
1113                         8)
1114                             _bpftool_once_attr 'overwrite'
1115                             return 0
1116                             ;;
1117                     esac
1118                     ;;
1119                 detach)
1120                     case $cword in
1121                         3)
1122                             COMPREPLY=( $( compgen -W "$ATTACH_TYPES" -- "$cur" ) )
1123                             return 0
1124                             ;;
1125                         4)
1126                             COMPREPLY=( $( compgen -W 'dev' -- "$cur" ) )
1127                             return 0
1128                             ;;
1129                     esac
1130                     ;;
1131                 *)
1132                     [[ $prev == $object ]] && \
1133                         COMPREPLY=( $( compgen -W 'help \
1134                             show list attach detach' -- "$cur" ) )
1135                     ;;
1136             esac
1137             ;;
1138         feature)
1139             case $command in
1140                 probe)
1141                     [[ $prev == "prefix" ]] && return 0
1142                     if _bpftool_search_list 'macros'; then
1143                         _bpftool_once_attr 'prefix'
1144                     else
1145                         COMPREPLY+=( $( compgen -W 'macros' -- "$cur" ) )
1146                     fi
1147                     _bpftool_one_of_list 'kernel dev'
1148                     _bpftool_once_attr 'full unprivileged'
1149                     return 0
1150                     ;;
1151                 *)
1152                     [[ $prev == $object ]] && \
1153                         COMPREPLY=( $( compgen -W 'help probe' -- "$cur" ) )
1154                     ;;
1155             esac
1156             ;;
1157         link)
1158             case $command in
1159                 show|list|pin|detach)
1160                     case $prev in
1161                         id)
1162                             _bpftool_get_link_ids
1163                             return 0
1164                             ;;
1165                     esac
1166                     ;;
1167             esac
1168
1169             local LINK_TYPE='id pinned'
1170             case $command in
1171                 show|list)
1172                     [[ $prev != "$command" ]] && return 0
1173                     COMPREPLY=( $( compgen -W "$LINK_TYPE" -- "$cur" ) )
1174                     return 0
1175                     ;;
1176                 pin|detach)
1177                     if [[ $prev == "$command" ]]; then
1178                         COMPREPLY=( $( compgen -W "$LINK_TYPE" -- "$cur" ) )
1179                     else
1180                         _filedir
1181                     fi
1182                     return 0
1183                     ;;
1184                 *)
1185                     [[ $prev == $object ]] && \
1186                         COMPREPLY=( $( compgen -W 'help pin show list' -- "$cur" ) )
1187                     ;;
1188             esac
1189             ;;
1190     esac
1191 } &&
1192 complete -F _bpftool bpftool
1193
1194 # ex: ts=4 sw=4 et filetype=sh