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