1 # bpftool(8) bash completion -*- shell-script -*-
3 # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
4 # Copyright (C) 2017-2018 Netronome Systems, Inc.
6 # Author: Quentin Monnet <quentin.monnet@netronome.com>
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.
15 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
16 if [[ $w == ${words[idx]} ]]; then
21 [[ $found -eq 0 ]] && \
22 COMPREPLY+=( $( compgen -W "$w" -- "$cur" ) )
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()
32 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
33 [[ $w == ${words[idx]} ]] && return 0
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()
43 _bpftool_search_list $* && return 1
44 COMPREPLY+=( $( compgen -W "$*" -- "$cur" ) )
47 _bpftool_get_map_ids()
49 COMPREPLY+=( $( compgen -W "$( bpftool -jp map 2>&1 | \
50 command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) )
53 # Takes map type and adds matching map ids to the list of suggestions.
54 _bpftool_get_map_ids_for_type()
57 COMPREPLY+=( $( compgen -W "$( bpftool -jp map 2>&1 | \
58 command grep -C2 "$type" | \
59 command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) )
62 _bpftool_get_prog_ids()
64 COMPREPLY+=( $( compgen -W "$( bpftool -jp prog 2>&1 | \
65 command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) )
68 _bpftool_get_prog_tags()
70 COMPREPLY+=( $( compgen -W "$( bpftool -jp prog 2>&1 | \
71 command sed -n 's/.*"tag": "\(.*\)",$/\1/p' )" -- "$cur" ) )
74 _bpftool_get_obj_map_names()
80 maps=$(objdump -j maps -t $obj 2>/dev/null | \
81 command awk '/g . maps/ {print $NF}')
83 COMPREPLY+=( $( compgen -W "$maps" -- "$cur" ) )
86 _bpftool_get_obj_map_idxs()
92 nmaps=$(objdump -j maps -t $obj 2>/dev/null | grep -c 'g . maps')
94 COMPREPLY+=( $( compgen -W "$(seq 0 $((nmaps - 1)))" -- "$cur" ) )
99 COMPREPLY+=( $( compgen -W "$( ls /sys/class/net 2>/dev/null )" -- \
103 # Retrieve type of the map that we are operating on.
104 _bpftool_map_guess_map_type()
107 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
108 case "${words[$((idx-2))]}" in
110 keyword=${words[$((idx-1))]}
111 ref=${words[$((idx))]}
123 [[ -z $ref ]] && return 0
126 type=$(bpftool -jp map show $keyword $ref | \
127 command sed -n 's/.*"type": "\(.*\)",$/\1/p')
128 [[ -n $type ]] && printf $type
131 _bpftool_map_update_get_id()
135 # Is it the map to update, or a map to insert into the map to update?
136 # Search for "value" keyword.
138 for (( idx=7; idx < ${#words[@]}-1; idx++ )); do
139 if [[ ${words[idx]} == "value" ]]; then
144 if [[ $value -eq 0 ]]; then
147 _bpftool_get_map_ids_for_type stack
150 _bpftool_get_map_ids_for_type queue
159 # Id to complete is for a value. It can be either prog id or map id. This
160 # depends on the type of the map to update.
161 local type=$(_bpftool_map_guess_map_type)
163 array_of_maps|hash_of_maps)
168 _bpftool_get_prog_ids
179 local cur prev words objword
180 _init_completion || return
183 if [[ ${words[cword]} == -* ]]; then
184 local c='--version --json --pretty --bpffs --mapcompat'
185 COMPREPLY=( $( compgen -W "$c" -- "$cur" ) )
189 # Deal with simplest keywords
191 help|hex|opcodes|visual|linum)
195 _bpftool_get_prog_tags
203 COMPREPLY=( $( compgen -W 'file' -- "$cur" ) )
208 # Remove all options so completions don't have to deal with them.
210 for (( i=1; i < ${#words[@]}; )); do
211 if [[ ${words[i]::1} == - ]]; then
212 words=( "${words[@]:0:i}" "${words[@]:i+1}" )
213 [[ $i -le $cword ]] && cword=$(( cword - 1 ))
219 prev=${words[cword - 1]}
221 local object=${words[1]} command=${words[2]}
223 if [[ -z $object || $cword -eq 1 ]]; then
226 COMPREPLY=( $( compgen -W "$( bpftool help 2>&1 | \
228 -e '/OBJECT := /!d' \
231 -e 's/|//g' )" -- "$cur" ) )
232 COMPREPLY+=( $( compgen -W 'batch help' -- "$cur" ) )
238 [[ $command == help ]] && return 0
240 # Completion depends on object and command in use
243 # Complete id, only for subcommands that use prog (but no map) ids
248 _bpftool_get_prog_ids
255 local PROG_TYPE='id pinned tag'
256 local MAP_TYPE='id pinned'
259 [[ $prev != "$command" ]] && return 0
260 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
266 COMPREPLY+=( $( compgen -W "xlated jited" -- \
271 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \
276 _bpftool_once_attr 'file'
277 if _bpftool_search_list 'xlated'; then
278 COMPREPLY+=( $( compgen -W 'opcodes visual linum' -- \
281 COMPREPLY+=( $( compgen -W 'opcodes linum' -- \
289 if [[ $prev == "$command" ]]; then
290 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
299 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
305 _bpftool_get_prog_ids
314 COMPREPLY=( $( compgen -W 'msg_verdict stream_verdict \
315 stream_parser flow_dissector' -- "$cur" ) )
319 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
338 if [[ ${#words[@]} -lt 6 ]]; then
345 if [[ ${words[-4]} == "map" ]]; then
346 COMPREPLY=( $( compgen -W "id pinned" -- "$cur" ) )
349 if [[ ${words[-3]} == "map" ]]; then
350 if [[ ${words[-2]} == "idx" ]]; then
351 _bpftool_get_obj_map_idxs $obj
352 elif [[ ${words[-2]} == "name" ]]; then
353 _bpftool_get_obj_map_names $obj
357 if [[ ${words[-2]} == "map" ]]; then
358 COMPREPLY=( $( compgen -W "idx name" -- "$cur" ) )
364 COMPREPLY=( $( compgen -W "socket kprobe \
365 kretprobe classifier flow_dissector \
366 action tracepoint raw_tracepoint \
367 xdp perf_event cgroup/skb cgroup/sock \
368 cgroup/dev lwt_in lwt_out lwt_xmit \
369 lwt_seg6local sockops sk_skb sk_msg \
370 lirc_mode2 cgroup/bind4 cgroup/bind6 \
371 cgroup/connect4 cgroup/connect6 \
372 cgroup/sendmsg4 cgroup/sendmsg6 \
373 cgroup/post_bind4 cgroup/post_bind6" -- \
390 COMPREPLY=( $( compgen -W "map" -- "$cur" ) )
391 _bpftool_once_attr 'type'
392 _bpftool_once_attr 'dev'
393 _bpftool_once_attr 'pinmaps'
402 [[ $prev == $object ]] && \
403 COMPREPLY=( $( compgen -W 'dump help pin attach detach load \
404 show list tracelog' -- "$cur" ) )
409 local MAP_TYPE='id pinned'
411 show|list|dump|peek|pop|dequeue)
414 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
420 _bpftool_get_map_ids_for_type stack
421 _bpftool_get_map_ids_for_type queue
424 _bpftool_get_map_ids_for_type stack
427 _bpftool_get_map_ids_for_type queue
447 COMPREPLY=( $( compgen -W 'hash array prog_array \
448 perf_event_array percpu_hash percpu_array \
449 stack_trace cgroup_array lru_hash \
450 lru_percpu_hash lpm_trie array_of_maps \
451 hash_of_maps devmap sockmap cpumap xskmap \
452 sockhash cgroup_storage reuseport_sockarray \
453 percpu_cgroup_storage queue stack' -- \
457 key|value|flags|name|entries)
465 _bpftool_once_attr 'type'
466 _bpftool_once_attr 'key'
467 _bpftool_once_attr 'value'
468 _bpftool_once_attr 'entries'
469 _bpftool_once_attr 'name'
470 _bpftool_once_attr 'flags'
471 _bpftool_once_attr 'dev'
476 lookup|getnext|delete)
479 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
487 COMPREPLY+=( $( compgen -W 'hex' -- "$cur" ) )
490 case $(_bpftool_map_guess_map_type) in
496 _bpftool_once_attr 'key'
504 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
508 _bpftool_map_update_get_id $command
512 COMPREPLY+=( $( compgen -W 'hex' -- "$cur" ) )
515 # We can have bytes, or references to a prog or a
516 # map, depending on the type of the map to update.
517 case "$(_bpftool_map_guess_map_type)" in
518 array_of_maps|hash_of_maps)
519 local MAP_TYPE='id pinned'
520 COMPREPLY+=( $( compgen -W "$MAP_TYPE" \
525 local PROG_TYPE='id pinned tag'
526 COMPREPLY+=( $( compgen -W "$PROG_TYPE" \
531 COMPREPLY+=( $( compgen -W 'hex' \
539 case $(_bpftool_map_guess_map_type) in
541 _bpftool_once_attr 'value'
546 _bpftool_once_attr 'key'
547 local UPDATE_FLAGS='any exist noexist'
548 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
549 if [[ ${words[idx]} == 'value' ]]; then
550 # 'value' is present, but is not the last
551 # word i.e. we can now have UPDATE_FLAGS.
552 _bpftool_one_of_list "$UPDATE_FLAGS"
556 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do
557 if [[ ${words[idx]} == 'key' ]]; then
558 # 'key' is present, but is not the last
559 # word i.e. we can now have 'value'.
560 _bpftool_once_attr 'value'
570 if [[ $prev == "$command" ]]; then
571 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
580 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
584 _bpftool_get_map_ids_for_type perf_event_array
594 _bpftool_once_attr 'cpu'
595 _bpftool_once_attr 'index'
601 [[ $prev == $object ]] && \
602 COMPREPLY=( $( compgen -W 'delete dump getnext help \
603 lookup pin event_pipe show list update create \
604 peek push enqueue pop dequeue' -- \
620 local ATTACH_TYPES='ingress egress sock_create sock_ops \
621 device bind4 bind6 post_bind4 post_bind6 connect4 \
622 connect6 sendmsg4 sendmsg6'
623 local ATTACH_FLAGS='multi override'
624 local PROG_TYPE='id pinned tag'
630 ingress|egress|sock_create|sock_ops|device|bind4|bind6|\
631 post_bind4|post_bind6|connect4|connect6|sendmsg4|\
633 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \
638 _bpftool_get_prog_ids
642 if ! _bpftool_search_list "$ATTACH_TYPES"; then
643 COMPREPLY=( $( compgen -W "$ATTACH_TYPES" -- \
645 elif [[ "$command" == "attach" ]]; then
646 # We have an attach type on the command line,
647 # but it is not the previous word, or
648 # "id|pinned|tag" (we already checked for
649 # that). This should only leave the case when
650 # we need attach flags for "attach" commamnd.
651 _bpftool_one_of_list "$ATTACH_FLAGS"
658 [[ $prev == $object ]] && \
659 COMPREPLY=( $( compgen -W 'help attach detach \
660 show list tree' -- "$cur" ) )
667 [[ $prev == $object ]] && \
668 COMPREPLY=( $( compgen -W 'help \
669 show list' -- "$cur" ) )
676 [[ $prev == $object ]] && \
677 COMPREPLY=( $( compgen -W 'help \
678 show list' -- "$cur" ) )
685 [[ $prev == "dev" ]] && _sysfs_get_netdevs && return 0
686 [[ $prev == "prefix" ]] && return 0
687 if _bpftool_search_list 'macros'; then
688 COMPREPLY+=( $( compgen -W 'prefix' -- "$cur" ) )
690 COMPREPLY+=( $( compgen -W 'macros' -- "$cur" ) )
692 _bpftool_one_of_list 'kernel dev'
696 [[ $prev == $object ]] && \
697 COMPREPLY=( $( compgen -W 'help probe' -- "$cur" ) )
703 complete -F _bpftool bpftool
705 # ex: ts=4 sw=4 et filetype=sh