1 # bpftool(8) bash completion -*- shell-script -*-
3 # Copyright (C) 2017-2018 Netronome Systems, Inc.
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.
11 # The BSD 2-Clause License:
13 # Redistribution and use in source and binary forms, with or
14 # without modification, are permitted provided that the following
17 # 1. Redistributions of source code must retain the above
18 # copyright notice, this list of conditions and the following
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.
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
35 # Author: Quentin Monnet <quentin.monnet@netronome.com>
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.
44 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
45 if [[ $w == ${words[idx]} ]]; then
50 [[ $found -eq 0 ]] && \
51 COMPREPLY+=( $( compgen -W "$w" -- "$cur" ) )
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()
61 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
62 [[ $w == ${words[idx]} ]] && return 0
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()
72 _bpftool_search_list $* && return 1
73 COMPREPLY+=( $( compgen -W "$*" -- "$cur" ) )
76 _bpftool_get_map_ids()
78 COMPREPLY+=( $( compgen -W "$( bpftool -jp map 2>&1 | \
79 command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) )
82 _bpftool_get_perf_map_ids()
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" ) )
90 _bpftool_get_prog_ids()
92 COMPREPLY+=( $( compgen -W "$( bpftool -jp prog 2>&1 | \
93 command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) )
96 _bpftool_get_prog_tags()
98 COMPREPLY+=( $( compgen -W "$( bpftool -jp prog 2>&1 | \
99 command sed -n 's/.*"tag": "\(.*\)",$/\1/p' )" -- "$cur" ) )
102 _bpftool_get_obj_map_names()
108 maps=$(objdump -j maps -t $obj 2>/dev/null | \
109 command awk '/g . maps/ {print $NF}')
111 COMPREPLY+=( $( compgen -W "$maps" -- "$cur" ) )
114 _bpftool_get_obj_map_idxs()
120 nmaps=$(objdump -j maps -t $obj 2>/dev/null | grep -c 'g . maps')
122 COMPREPLY+=( $( compgen -W "$(seq 0 $((nmaps - 1)))" -- "$cur" ) )
127 COMPREPLY+=( $( compgen -W "$( ls /sys/class/net 2>/dev/null )" -- \
131 # For bpftool map update: retrieve type of the map to update.
132 _bpftool_map_update_map_type()
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))]}
141 [[ -z $ref ]] && return 0
144 type=$(bpftool -jp map show $keyword $ref | \
145 command sed -n 's/.*"type": "\(.*\)",$/\1/p')
146 [[ -n $type ]] && printf $type
149 _bpftool_map_update_get_id()
151 # Is it the map to update, or a map to insert into the map to update?
152 # Search for "value" keyword.
154 for (( idx=7; idx < ${#words[@]}-1; idx++ )); do
155 if [[ ${words[idx]} == "value" ]]; then
160 [[ $value -eq 0 ]] && _bpftool_get_map_ids && return 0
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)
166 array_of_maps|hash_of_maps)
171 _bpftool_get_prog_ids
182 local cur prev words objword
183 _init_completion || return
186 if [[ ${words[cword]} == -* ]]; then
187 local c='--version --json --pretty --bpffs'
188 COMPREPLY=( $( compgen -W "$c" -- "$cur" ) )
192 # Deal with simplest keywords
194 help|hex|opcodes|visual)
198 _bpftool_get_prog_tags
206 COMPREPLY=( $( compgen -W 'file' -- "$cur" ) )
211 # Remove all options so completions don't have to deal with them.
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 ))
222 prev=${words[cword - 1]}
224 local object=${words[1]} command=${words[2]}
226 if [[ -z $object || $cword -eq 1 ]]; then
229 COMPREPLY=( $( compgen -W "$( bpftool help 2>&1 | \
231 -e '/OBJECT := /!d' \
234 -e 's/|//g' )" -- "$cur" ) )
235 COMPREPLY+=( $( compgen -W 'batch help' -- "$cur" ) )
241 [[ $command == help ]] && return 0
243 # Completion depends on object and command in use
246 if [[ $command != "load" ]]; then
249 _bpftool_get_prog_ids
255 local PROG_TYPE='id pinned tag'
258 [[ $prev != "$command" ]] && return 0
259 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
265 COMPREPLY+=( $( compgen -W "xlated jited" -- \
270 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \
275 _bpftool_once_attr 'file'
276 if _bpftool_search_list 'xlated'; then
277 COMPREPLY+=( $( compgen -W 'opcodes visual' -- \
280 COMPREPLY+=( $( compgen -W 'opcodes' -- \
288 if [[ $prev == "$command" ]]; then
289 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
298 if [[ ${#words[@]} -lt 6 ]]; then
305 if [[ ${words[-4]} == "map" ]]; then
306 COMPREPLY=( $( compgen -W "id pinned" -- "$cur" ) )
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
317 if [[ ${words[-2]} == "map" ]]; then
318 COMPREPLY=( $( compgen -W "idx name" -- "$cur" ) )
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" -- \
341 COMPREPLY=( $( compgen -W "map" -- "$cur" ) )
342 _bpftool_once_attr 'type'
343 _bpftool_once_attr 'dev'
349 [[ $prev == $object ]] && \
350 COMPREPLY=( $( compgen -W 'dump help pin load \
351 show list' -- "$cur" ) )
356 local MAP_TYPE='id pinned'
361 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
373 lookup|getnext|delete)
376 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
384 COMPREPLY+=( $( compgen -W 'hex' -- "$cur" ) )
387 _bpftool_once_attr 'key'
395 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
399 _bpftool_map_update_get_id
403 COMPREPLY+=( $( compgen -W 'hex' -- "$cur" ) )
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" \
416 local PROG_TYPE='id pinned tag'
417 COMPREPLY+=( $( compgen -W "$PROG_TYPE" \
422 COMPREPLY+=( $( compgen -W 'hex' \
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"
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'
453 if [[ $prev == "$command" ]]; then
454 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
463 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
467 _bpftool_get_perf_map_ids
477 _bpftool_once_attr 'cpu'
478 _bpftool_once_attr 'index'
484 [[ $prev == $object ]] && \
485 COMPREPLY=( $( compgen -W 'delete dump getnext help \
486 lookup pin event_pipe show list update' -- \
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'
512 ingress|egress|sock_create|sock_ops|device|bind4|bind6|\
513 post_bind4|post_bind6|connect4|connect6|sendmsg4|\
515 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \
520 _bpftool_get_prog_ids
524 if ! _bpftool_search_list "$ATTACH_TYPES"; then
525 COMPREPLY=( $( compgen -W "$ATTACH_TYPES" -- \
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"
540 [[ $prev == $object ]] && \
541 COMPREPLY=( $( compgen -W 'help attach detach \
542 show list tree' -- "$cur" ) )
549 [[ $prev == $object ]] && \
550 COMPREPLY=( $( compgen -W 'help \
551 show list' -- "$cur" ) )
557 complete -F _bpftool bpftool
559 # ex: ts=4 sw=4 et filetype=sh