]> asedeno.scripts.mit.edu Git - linux.git/blob - tools/bpf/bpftool/bash-completion/bpftool
fffd76f4998b5e9e5e0e1825e17ac3ccb4c74c66
[linux.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 # For bpftool map update: retrieve type of the map to update.
103 _bpftool_map_update_map_type()
104 {
105     local keyword ref
106     for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
107         if [[ ${words[$((idx-2))]} == "update" ]]; then
108             keyword=${words[$((idx-1))]}
109             ref=${words[$((idx))]}
110         fi
111     done
112     [[ -z $ref ]] && return 0
113
114     local type
115     type=$(bpftool -jp map show $keyword $ref | \
116         command sed -n 's/.*"type": "\(.*\)",$/\1/p')
117     printf $type
118 }
119
120 _bpftool_map_update_get_id()
121 {
122     # Is it the map to update, or a map to insert into the map to update?
123     # Search for "value" keyword.
124     local idx value
125     for (( idx=7; idx < ${#words[@]}-1; idx++ )); do
126         if [[ ${words[idx]} == "value" ]]; then
127             value=1
128             break
129         fi
130     done
131     [[ $value -eq 0 ]] && _bpftool_get_map_ids && return 0
132
133     # Id to complete is for a value. It can be either prog id or map id. This
134     # depends on the type of the map to update.
135     local type=$(_bpftool_map_update_map_type)
136     case $type in
137         array_of_maps|hash_of_maps)
138             _bpftool_get_map_ids
139             return 0
140             ;;
141         prog_array)
142             _bpftool_get_prog_ids
143             return 0
144             ;;
145         *)
146             return 0
147             ;;
148     esac
149 }
150
151 _bpftool()
152 {
153     local cur prev words objword
154     _init_completion || return
155
156     # Deal with options
157     if [[ ${words[cword]} == -* ]]; then
158         local c='--version --json --pretty --bpffs'
159         COMPREPLY=( $( compgen -W "$c" -- "$cur" ) )
160         return 0
161     fi
162
163     # Deal with simplest keywords
164     case $prev in
165         help|hex|opcodes|visual)
166             return 0
167             ;;
168         tag)
169             _bpftool_get_prog_tags
170             return 0
171             ;;
172         file|pinned)
173             _filedir
174             return 0
175             ;;
176         batch)
177             COMPREPLY=( $( compgen -W 'file' -- "$cur" ) )
178             return 0
179             ;;
180     esac
181
182     # Remove all options so completions don't have to deal with them.
183     local i
184     for (( i=1; i < ${#words[@]}; )); do
185         if [[ ${words[i]::1} == - ]]; then
186             words=( "${words[@]:0:i}" "${words[@]:i+1}" )
187             [[ $i -le $cword ]] && cword=$(( cword - 1 ))
188         else
189             i=$(( ++i ))
190         fi
191     done
192     cur=${words[cword]}
193     prev=${words[cword - 1]}
194
195     local object=${words[1]} command=${words[2]}
196
197     if [[ -z $object || $cword -eq 1 ]]; then
198         case $cur in
199             *)
200                 COMPREPLY=( $( compgen -W "$( bpftool help 2>&1 | \
201                     command sed \
202                     -e '/OBJECT := /!d' \
203                     -e 's/.*{//' \
204                     -e 's/}.*//' \
205                     -e 's/|//g' )" -- "$cur" ) )
206                 COMPREPLY+=( $( compgen -W 'batch help' -- "$cur" ) )
207                 return 0
208                 ;;
209         esac
210     fi
211
212     [[ $command == help ]] && return 0
213
214     # Completion depends on object and command in use
215     case $object in
216         prog)
217             case $prev in
218                 id)
219                     _bpftool_get_prog_ids
220                     return 0
221                     ;;
222             esac
223
224             local PROG_TYPE='id pinned tag'
225             case $command in
226                 show|list)
227                     [[ $prev != "$command" ]] && return 0
228                     COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
229                     return 0
230                     ;;
231                 dump)
232                     case $prev in
233                         $command)
234                             COMPREPLY+=( $( compgen -W "xlated jited" -- \
235                                 "$cur" ) )
236                             return 0
237                             ;;
238                         xlated|jited)
239                             COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \
240                                 "$cur" ) )
241                             return 0
242                             ;;
243                     *)
244                         _bpftool_once_attr 'file'
245                         if _bpftool_search_list 'xlated'; then
246                             COMPREPLY+=( $( compgen -W 'opcodes visual' -- \
247                                 "$cur" ) )
248                         else
249                             COMPREPLY+=( $( compgen -W 'opcodes' -- \
250                                 "$cur" ) )
251                         fi
252                         return 0
253                         ;;
254                     esac
255                     ;;
256                 pin)
257                     if [[ $prev == "$command" ]]; then
258                         COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
259                     else
260                         _filedir
261                     fi
262                     return 0
263                     ;;
264                 load)
265                     _filedir
266                     return 0
267                     ;;
268                 *)
269                     [[ $prev == $object ]] && \
270                         COMPREPLY=( $( compgen -W 'dump help pin load \
271                             show list' -- "$cur" ) )
272                     ;;
273             esac
274             ;;
275         map)
276             local MAP_TYPE='id pinned'
277             case $command in
278                 show|list|dump)
279                     case $prev in
280                         $command)
281                             COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
282                             return 0
283                             ;;
284                         id)
285                             _bpftool_get_map_ids
286                             return 0
287                             ;;
288                         *)
289                             return 0
290                             ;;
291                     esac
292                     ;;
293                 lookup|getnext|delete)
294                     case $prev in
295                         $command)
296                             COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
297                             return 0
298                             ;;
299                         id)
300                             _bpftool_get_map_ids
301                             return 0
302                             ;;
303                         key)
304                             COMPREPLY+=( $( compgen -W 'hex' -- "$cur" ) )
305                             ;;
306                         *)
307                             _bpftool_once_attr 'key'
308                             return 0
309                             ;;
310                     esac
311                     ;;
312                 update)
313                     case $prev in
314                         $command)
315                             COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
316                             return 0
317                             ;;
318                         id)
319                             _bpftool_map_update_get_id
320                             return 0
321                             ;;
322                         key)
323                             COMPREPLY+=( $( compgen -W 'hex' -- "$cur" ) )
324                             ;;
325                         value)
326                             # We can have bytes, or references to a prog or a
327                             # map, depending on the type of the map to update.
328                             case $(_bpftool_map_update_map_type) in
329                                 array_of_maps|hash_of_maps)
330                                     local MAP_TYPE='id pinned'
331                                     COMPREPLY+=( $( compgen -W "$MAP_TYPE" \
332                                         -- "$cur" ) )
333                                     return 0
334                                     ;;
335                                 prog_array)
336                                     local PROG_TYPE='id pinned tag'
337                                     COMPREPLY+=( $( compgen -W "$PROG_TYPE" \
338                                         -- "$cur" ) )
339                                     return 0
340                                     ;;
341                                 *)
342                                     COMPREPLY+=( $( compgen -W 'hex' \
343                                         -- "$cur" ) )
344                                     return 0
345                                     ;;
346                             esac
347                             return 0
348                             ;;
349                         *)
350                             _bpftool_once_attr 'key'
351                             local UPDATE_FLAGS='any exist noexist'
352                             for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
353                                 if [[ ${words[idx]} == 'value' ]]; then
354                                     # 'value' is present, but is not the last
355                                     # word i.e. we can now have UPDATE_FLAGS.
356                                     _bpftool_one_of_list "$UPDATE_FLAGS"
357                                     return 0
358                                 fi
359                             done
360                             for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
361                                 if [[ ${words[idx]} == 'key' ]]; then
362                                     # 'key' is present, but is not the last
363                                     # word i.e. we can now have 'value'.
364                                     _bpftool_once_attr 'value'
365                                     return 0
366                                 fi
367                             done
368                             return 0
369                             ;;
370                     esac
371                     ;;
372                 pin)
373                     if [[ $prev == "$command" ]]; then
374                         COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
375                     else
376                         _filedir
377                     fi
378                     return 0
379                     ;;
380                 event_pipe)
381                     case $prev in
382                         $command)
383                             COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
384                             return 0
385                             ;;
386                         id)
387                             _bpftool_get_perf_map_ids
388                             return 0
389                             ;;
390                         cpu)
391                             return 0
392                             ;;
393                         index)
394                             return 0
395                             ;;
396                         *)
397                             _bpftool_once_attr 'cpu'
398                             _bpftool_once_attr 'index'
399                             return 0
400                             ;;
401                     esac
402                     ;;
403                 *)
404                     [[ $prev == $object ]] && \
405                         COMPREPLY=( $( compgen -W 'delete dump getnext help \
406                             lookup pin event_pipe show list update' -- \
407                             "$cur" ) )
408                     ;;
409             esac
410             ;;
411         cgroup)
412             case $command in
413                 show|list)
414                     _filedir
415                     return 0
416                     ;;
417                 attach|detach)
418                     local ATTACH_TYPES='ingress egress sock_create sock_ops \
419                         device bind4 bind6 post_bind4 post_bind6 connect4 \
420                         connect6 sendmsg4 sendmsg6'
421                     local ATTACH_FLAGS='multi override'
422                     local PROG_TYPE='id pinned tag'
423                     case $prev in
424                         $command)
425                             _filedir
426                             return 0
427                             ;;
428                         ingress|egress|sock_create|sock_ops|device|bind4|bind6|\
429                         post_bind4|post_bind6|connect4|connect6|sendmsg4|\
430                         sendmsg6)
431                             COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \
432                                 "$cur" ) )
433                             return 0
434                             ;;
435                         id)
436                             _bpftool_get_prog_ids
437                             return 0
438                             ;;
439                         *)
440                             if ! _bpftool_search_list "$ATTACH_TYPES"; then
441                                 COMPREPLY=( $( compgen -W "$ATTACH_TYPES" -- \
442                                     "$cur" ) )
443                             elif [[ "$command" == "attach" ]]; then
444                                 # We have an attach type on the command line,
445                                 # but it is not the previous word, or
446                                 # "id|pinned|tag" (we already checked for
447                                 # that). This should only leave the case when
448                                 # we need attach flags for "attach" commamnd.
449                                 _bpftool_one_of_list "$ATTACH_FLAGS"
450                             fi
451                             return 0
452                             ;;
453                     esac
454                     ;;
455                 *)
456                     [[ $prev == $object ]] && \
457                         COMPREPLY=( $( compgen -W 'help attach detach \
458                             show list' -- "$cur" ) )
459                     ;;
460             esac
461             ;;
462         perf)
463             case $command in
464                 *)
465                     [[ $prev == $object ]] && \
466                         COMPREPLY=( $( compgen -W 'help \
467                             show list' -- "$cur" ) )
468                     ;;
469             esac
470             ;;
471     esac
472 } &&
473 complete -F _bpftool bpftool
474
475 # ex: ts=4 sw=4 et filetype=sh