GNU Linux-libre 4.19.286-gnu1
[releases.git] / tools / bpf / bpftool / bash-completion / bpftool
1 # bpftool(8) bash completion                               -*- shell-script -*-
2 #
3 # Copyright (C) 2017-2018 Netronome Systems, Inc.
4 #
5 # This software is dual licensed under the GNU General License
6 # Version 2, June 1991 as shown in the file COPYING in the top-level
7 # directory of this source tree or the BSD 2-Clause License provided
8 # below.  You have the option to license this software under the
9 # complete terms of either license.
10 #
11 # The BSD 2-Clause License:
12 #
13 #     Redistribution and use in source and binary forms, with or
14 #     without modification, are permitted provided that the following
15 #     conditions are met:
16 #
17 #      1. Redistributions of source code must retain the above
18 #         copyright notice, this list of conditions and the following
19 #         disclaimer.
20 #
21 #      2. Redistributions in binary form must reproduce the above
22 #         copyright notice, this list of conditions and the following
23 #         disclaimer in the documentation and/or other materials
24 #         provided with the distribution.
25 #
26 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30 # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31 # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32 # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33 # SOFTWARE.
34 #
35 # Author: Quentin Monnet <quentin.monnet@netronome.com>
36
37 # Takes a list of words in argument; each one of them is added to COMPREPLY if
38 # it is not already present on the command line. Returns no value.
39 _bpftool_once_attr()
40 {
41     local w idx found
42     for w in $*; do
43         found=0
44         for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
45             if [[ $w == ${words[idx]} ]]; then
46                 found=1
47                 break
48             fi
49         done
50         [[ $found -eq 0 ]] && \
51             COMPREPLY+=( $( compgen -W "$w" -- "$cur" ) )
52     done
53 }
54
55 # Takes a list of words as argument; if any of those words is present on the
56 # command line, return 0. Otherwise, return 1.
57 _bpftool_search_list()
58 {
59     local w idx
60     for w in $*; do
61         for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
62             [[ $w == ${words[idx]} ]] && return 0
63         done
64     done
65     return 1
66 }
67
68 # Takes a list of words in argument; adds them all to COMPREPLY if none of them
69 # is already present on the command line. Returns no value.
70 _bpftool_one_of_list()
71 {
72     _bpftool_search_list $* && return 1
73     COMPREPLY+=( $( compgen -W "$*" -- "$cur" ) )
74 }
75
76 _bpftool_get_map_ids()
77 {
78     COMPREPLY+=( $( compgen -W "$( bpftool -jp map  2>&1 | \
79         command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) )
80 }
81
82 _bpftool_get_perf_map_ids()
83 {
84     COMPREPLY+=( $( compgen -W "$( bpftool -jp map  2>&1 | \
85         command grep -C2 perf_event_array | \
86         command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) )
87 }
88
89
90 _bpftool_get_prog_ids()
91 {
92     COMPREPLY+=( $( compgen -W "$( bpftool -jp prog 2>&1 | \
93         command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) )
94 }
95
96 _bpftool_get_prog_tags()
97 {
98     COMPREPLY+=( $( compgen -W "$( bpftool -jp prog 2>&1 | \
99         command sed -n 's/.*"tag": "\(.*\)",$/\1/p' )" -- "$cur" ) )
100 }
101
102 _bpftool_get_obj_map_names()
103 {
104     local obj
105
106     obj=$1
107
108     maps=$(objdump -j maps -t $obj 2>/dev/null | \
109         command awk '/g     . maps/ {print $NF}')
110
111     COMPREPLY+=( $( compgen -W "$maps" -- "$cur" ) )
112 }
113
114 _bpftool_get_obj_map_idxs()
115 {
116     local obj
117
118     obj=$1
119
120     nmaps=$(objdump -j maps -t $obj 2>/dev/null | grep -c 'g     . maps')
121
122     COMPREPLY+=( $( compgen -W "$(seq 0 $((nmaps - 1)))" -- "$cur" ) )
123 }
124
125 _sysfs_get_netdevs()
126 {
127     COMPREPLY+=( $( compgen -W "$( ls /sys/class/net 2>/dev/null )" -- \
128         "$cur" ) )
129 }
130
131 # For bpftool map update: retrieve type of the map to update.
132 _bpftool_map_update_map_type()
133 {
134     local keyword ref
135     for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
136         if [[ ${words[$((idx-2))]} == "update" ]]; then
137             keyword=${words[$((idx-1))]}
138             ref=${words[$((idx))]}
139         fi
140     done
141     [[ -z $ref ]] && return 0
142
143     local type
144     type=$(bpftool -jp map show $keyword $ref | \
145         command sed -n 's/.*"type": "\(.*\)",$/\1/p')
146     [[ -n $type ]] && printf $type
147 }
148
149 _bpftool_map_update_get_id()
150 {
151     # Is it the map to update, or a map to insert into the map to update?
152     # Search for "value" keyword.
153     local idx value
154     for (( idx=7; idx < ${#words[@]}-1; idx++ )); do
155         if [[ ${words[idx]} == "value" ]]; then
156             value=1
157             break
158         fi
159     done
160     [[ $value -eq 0 ]] && _bpftool_get_map_ids && return 0
161
162     # Id to complete is for a value. It can be either prog id or map id. This
163     # depends on the type of the map to update.
164     local type=$(_bpftool_map_update_map_type)
165     case $type in
166         array_of_maps|hash_of_maps)
167             _bpftool_get_map_ids
168             return 0
169             ;;
170         prog_array)
171             _bpftool_get_prog_ids
172             return 0
173             ;;
174         *)
175             return 0
176             ;;
177     esac
178 }
179
180 _bpftool()
181 {
182     local cur prev words objword
183     _init_completion || return
184
185     # Deal with options
186     if [[ ${words[cword]} == -* ]]; then
187         local c='--version --json --pretty --bpffs'
188         COMPREPLY=( $( compgen -W "$c" -- "$cur" ) )
189         return 0
190     fi
191
192     # Deal with simplest keywords
193     case $prev in
194         help|hex|opcodes|visual)
195             return 0
196             ;;
197         tag)
198             _bpftool_get_prog_tags
199             return 0
200             ;;
201         file|pinned)
202             _filedir
203             return 0
204             ;;
205         batch)
206             COMPREPLY=( $( compgen -W 'file' -- "$cur" ) )
207             return 0
208             ;;
209     esac
210
211     # Remove all options so completions don't have to deal with them.
212     local i
213     for (( i=1; i < ${#words[@]}; )); do
214         if [[ ${words[i]::1} == - ]]; then
215             words=( "${words[@]:0:i}" "${words[@]:i+1}" )
216             [[ $i -le $cword ]] && cword=$(( cword - 1 ))
217         else
218             i=$(( ++i ))
219         fi
220     done
221     cur=${words[cword]}
222     prev=${words[cword - 1]}
223
224     local object=${words[1]} command=${words[2]}
225
226     if [[ -z $object || $cword -eq 1 ]]; then
227         case $cur in
228             *)
229                 COMPREPLY=( $( compgen -W "$( bpftool help 2>&1 | \
230                     command sed \
231                     -e '/OBJECT := /!d' \
232                     -e 's/.*{//' \
233                     -e 's/}.*//' \
234                     -e 's/|//g' )" -- "$cur" ) )
235                 COMPREPLY+=( $( compgen -W 'batch help' -- "$cur" ) )
236                 return 0
237                 ;;
238         esac
239     fi
240
241     [[ $command == help ]] && return 0
242
243     # Completion depends on object and command in use
244     case $object in
245         prog)
246             if [[ $command != "load" ]]; then
247                 case $prev in
248                     id)
249                         _bpftool_get_prog_ids
250                         return 0
251                         ;;
252                 esac
253             fi
254
255             local PROG_TYPE='id pinned tag'
256             case $command in
257                 show|list)
258                     [[ $prev != "$command" ]] && return 0
259                     COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
260                     return 0
261                     ;;
262                 dump)
263                     case $prev in
264                         $command)
265                             COMPREPLY+=( $( compgen -W "xlated jited" -- \
266                                 "$cur" ) )
267                             return 0
268                             ;;
269                         xlated|jited)
270                             COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \
271                                 "$cur" ) )
272                             return 0
273                             ;;
274                     *)
275                         _bpftool_once_attr 'file'
276                         if _bpftool_search_list 'xlated'; then
277                             COMPREPLY+=( $( compgen -W 'opcodes visual' -- \
278                                 "$cur" ) )
279                         else
280                             COMPREPLY+=( $( compgen -W 'opcodes' -- \
281                                 "$cur" ) )
282                         fi
283                         return 0
284                         ;;
285                     esac
286                     ;;
287                 pin)
288                     if [[ $prev == "$command" ]]; then
289                         COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
290                     else
291                         _filedir
292                     fi
293                     return 0
294                     ;;
295                 load)
296                     local obj
297
298                     if [[ ${#words[@]} -lt 6 ]]; then
299                         _filedir
300                         return 0
301                     fi
302
303                     obj=${words[3]}
304
305                     if [[ ${words[-4]} == "map" ]]; then
306                         COMPREPLY=( $( compgen -W "id pinned" -- "$cur" ) )
307                         return 0
308                     fi
309                     if [[ ${words[-3]} == "map" ]]; then
310                         if [[ ${words[-2]} == "idx" ]]; then
311                             _bpftool_get_obj_map_idxs $obj
312                         elif [[ ${words[-2]} == "name" ]]; then
313                             _bpftool_get_obj_map_names $obj
314                         fi
315                         return 0
316                     fi
317                     if [[ ${words[-2]} == "map" ]]; then
318                         COMPREPLY=( $( compgen -W "idx name" -- "$cur" ) )
319                         return 0
320                     fi
321
322                     case $prev in
323                         type)
324                             COMPREPLY=( $( compgen -W "socket kprobe kretprobe classifier action tracepoint raw_tracepoint xdp perf_event cgroup/skb cgroup/sock cgroup/dev lwt_in lwt_out lwt_xmit lwt_seg6local sockops sk_skb sk_msg lirc_mode2 cgroup/bind4 cgroup/bind6 cgroup/connect4 cgroup/connect6 cgroup/sendmsg4 cgroup/sendmsg6 cgroup/post_bind4 cgroup/post_bind6" -- \
325                                                    "$cur" ) )
326                             return 0
327                             ;;
328                         id)
329                             _bpftool_get_map_ids
330                             return 0
331                             ;;
332                         pinned)
333                             _filedir
334                             return 0
335                             ;;
336                         dev)
337                             _sysfs_get_netdevs
338                             return 0
339                             ;;
340                         *)
341                             COMPREPLY=( $( compgen -W "map" -- "$cur" ) )
342                             _bpftool_once_attr 'type'
343                             _bpftool_once_attr 'dev'
344                             return 0
345                             ;;
346                     esac
347                     ;;
348                 *)
349                     [[ $prev == $object ]] && \
350                         COMPREPLY=( $( compgen -W 'dump help pin load \
351                             show list' -- "$cur" ) )
352                     ;;
353             esac
354             ;;
355         map)
356             local MAP_TYPE='id pinned'
357             case $command in
358                 show|list|dump)
359                     case $prev in
360                         $command)
361                             COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
362                             return 0
363                             ;;
364                         id)
365                             _bpftool_get_map_ids
366                             return 0
367                             ;;
368                         *)
369                             return 0
370                             ;;
371                     esac
372                     ;;
373                 lookup|getnext|delete)
374                     case $prev in
375                         $command)
376                             COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
377                             return 0
378                             ;;
379                         id)
380                             _bpftool_get_map_ids
381                             return 0
382                             ;;
383                         key)
384                             COMPREPLY+=( $( compgen -W 'hex' -- "$cur" ) )
385                             ;;
386                         *)
387                             _bpftool_once_attr 'key'
388                             return 0
389                             ;;
390                     esac
391                     ;;
392                 update)
393                     case $prev in
394                         $command)
395                             COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
396                             return 0
397                             ;;
398                         id)
399                             _bpftool_map_update_get_id
400                             return 0
401                             ;;
402                         key)
403                             COMPREPLY+=( $( compgen -W 'hex' -- "$cur" ) )
404                             ;;
405                         value)
406                             # We can have bytes, or references to a prog or a
407                             # map, depending on the type of the map to update.
408                             case $(_bpftool_map_update_map_type) in
409                                 array_of_maps|hash_of_maps)
410                                     local MAP_TYPE='id pinned'
411                                     COMPREPLY+=( $( compgen -W "$MAP_TYPE" \
412                                         -- "$cur" ) )
413                                     return 0
414                                     ;;
415                                 prog_array)
416                                     local PROG_TYPE='id pinned tag'
417                                     COMPREPLY+=( $( compgen -W "$PROG_TYPE" \
418                                         -- "$cur" ) )
419                                     return 0
420                                     ;;
421                                 *)
422                                     COMPREPLY+=( $( compgen -W 'hex' \
423                                         -- "$cur" ) )
424                                     return 0
425                                     ;;
426                             esac
427                             return 0
428                             ;;
429                         *)
430                             _bpftool_once_attr 'key'
431                             local UPDATE_FLAGS='any exist noexist'
432                             for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
433                                 if [[ ${words[idx]} == 'value' ]]; then
434                                     # 'value' is present, but is not the last
435                                     # word i.e. we can now have UPDATE_FLAGS.
436                                     _bpftool_one_of_list "$UPDATE_FLAGS"
437                                     return 0
438                                 fi
439                             done
440                             for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
441                                 if [[ ${words[idx]} == 'key' ]]; then
442                                     # 'key' is present, but is not the last
443                                     # word i.e. we can now have 'value'.
444                                     _bpftool_once_attr 'value'
445                                     return 0
446                                 fi
447                             done
448                             return 0
449                             ;;
450                     esac
451                     ;;
452                 pin)
453                     if [[ $prev == "$command" ]]; then
454                         COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
455                     else
456                         _filedir
457                     fi
458                     return 0
459                     ;;
460                 event_pipe)
461                     case $prev in
462                         $command)
463                             COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
464                             return 0
465                             ;;
466                         id)
467                             _bpftool_get_perf_map_ids
468                             return 0
469                             ;;
470                         cpu)
471                             return 0
472                             ;;
473                         index)
474                             return 0
475                             ;;
476                         *)
477                             _bpftool_once_attr 'cpu'
478                             _bpftool_once_attr 'index'
479                             return 0
480                             ;;
481                     esac
482                     ;;
483                 *)
484                     [[ $prev == $object ]] && \
485                         COMPREPLY=( $( compgen -W 'delete dump getnext help \
486                             lookup pin event_pipe show list update' -- \
487                             "$cur" ) )
488                     ;;
489             esac
490             ;;
491         cgroup)
492             case $command in
493                 show|list)
494                     _filedir
495                     return 0
496                     ;;
497                 tree)
498                     _filedir
499                     return 0
500                     ;;
501                 attach|detach)
502                     local ATTACH_TYPES='ingress egress sock_create sock_ops \
503                         device bind4 bind6 post_bind4 post_bind6 connect4 \
504                         connect6 sendmsg4 sendmsg6'
505                     local ATTACH_FLAGS='multi override'
506                     local PROG_TYPE='id pinned tag'
507                     case $prev in
508                         $command)
509                             _filedir
510                             return 0
511                             ;;
512                         ingress|egress|sock_create|sock_ops|device|bind4|bind6|\
513                         post_bind4|post_bind6|connect4|connect6|sendmsg4|\
514                         sendmsg6)
515                             COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \
516                                 "$cur" ) )
517                             return 0
518                             ;;
519                         id)
520                             _bpftool_get_prog_ids
521                             return 0
522                             ;;
523                         *)
524                             if ! _bpftool_search_list "$ATTACH_TYPES"; then
525                                 COMPREPLY=( $( compgen -W "$ATTACH_TYPES" -- \
526                                     "$cur" ) )
527                             elif [[ "$command" == "attach" ]]; then
528                                 # We have an attach type on the command line,
529                                 # but it is not the previous word, or
530                                 # "id|pinned|tag" (we already checked for
531                                 # that). This should only leave the case when
532                                 # we need attach flags for "attach" commamnd.
533                                 _bpftool_one_of_list "$ATTACH_FLAGS"
534                             fi
535                             return 0
536                             ;;
537                     esac
538                     ;;
539                 *)
540                     [[ $prev == $object ]] && \
541                         COMPREPLY=( $( compgen -W 'help attach detach \
542                             show list tree' -- "$cur" ) )
543                     ;;
544             esac
545             ;;
546         perf)
547             case $command in
548                 *)
549                     [[ $prev == $object ]] && \
550                         COMPREPLY=( $( compgen -W 'help \
551                             show list' -- "$cur" ) )
552                     ;;
553             esac
554             ;;
555     esac
556 } &&
557 complete -F _bpftool bpftool
558
559 # ex: ts=4 sw=4 et filetype=sh