| # bpftool(8) bash completion -*- shell-script -*- | |
| # | |
| # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | |
| # Copyright (C) 2017-2018 Netronome Systems, Inc. | |
| # | |
| # Author: Quentin Monnet <quentin.monnet@netronome.com> | |
| # Takes a list of words in argument; each one of them is added to COMPREPLY if | |
| # it is not already present on the command line. Returns no value. | |
| _bpftool_once_attr() | |
| { | |
| local w idx found | |
| for w in $*; do | |
| found=0 | |
| for (( idx=3; idx < ${#words[@]}-1; idx++ )); do | |
| if [[ $w == ${words[idx]} ]]; then | |
| found=1 | |
| break | |
| fi | |
| done | |
| [[ $found -eq 0 ]] && \ | |
| COMPREPLY+=( $( compgen -W "$w" -- "$cur" ) ) | |
| done | |
| } | |
| # Takes a list of words as argument; if any of those words is present on the | |
| # command line, return 0. Otherwise, return 1. | |
| _bpftool_search_list() | |
| { | |
| local w idx | |
| for w in $*; do | |
| for (( idx=3; idx < ${#words[@]}-1; idx++ )); do | |
| [[ $w == ${words[idx]} ]] && return 0 | |
| done | |
| done | |
| return 1 | |
| } | |
| # Takes a list of words in argument; adds them all to COMPREPLY if none of them | |
| # is already present on the command line. Returns no value. | |
| _bpftool_one_of_list() | |
| { | |
| _bpftool_search_list $* && return 1 | |
| COMPREPLY+=( $( compgen -W "$*" -- "$cur" ) ) | |
| } | |
| _bpftool_get_map_ids() | |
| { | |
| COMPREPLY+=( $( compgen -W "$( bpftool -jp map 2>&1 | \ | |
| command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) ) | |
| } | |
| # Takes map type and adds matching map ids to the list of suggestions. | |
| _bpftool_get_map_ids_for_type() | |
| { | |
| local type="$1" | |
| COMPREPLY+=( $( compgen -W "$( bpftool -jp map 2>&1 | \ | |
| command grep -C2 "$type" | \ | |
| command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) ) | |
| } | |
| _bpftool_get_prog_ids() | |
| { | |
| COMPREPLY+=( $( compgen -W "$( bpftool -jp prog 2>&1 | \ | |
| command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) ) | |
| } | |
| _bpftool_get_prog_tags() | |
| { | |
| COMPREPLY+=( $( compgen -W "$( bpftool -jp prog 2>&1 | \ | |
| command sed -n 's/.*"tag": "\(.*\)",$/\1/p' )" -- "$cur" ) ) | |
| } | |
| _bpftool_get_btf_ids() | |
| { | |
| COMPREPLY+=( $( compgen -W "$( bpftool -jp btf 2>&1 | \ | |
| command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) ) | |
| } | |
| _bpftool_get_obj_map_names() | |
| { | |
| local obj | |
| obj=$1 | |
| maps=$(objdump -j maps -t $obj 2>/dev/null | \ | |
| command awk '/g . maps/ {print $NF}') | |
| COMPREPLY+=( $( compgen -W "$maps" -- "$cur" ) ) | |
| } | |
| _bpftool_get_obj_map_idxs() | |
| { | |
| local obj | |
| obj=$1 | |
| nmaps=$(objdump -j maps -t $obj 2>/dev/null | grep -c 'g . maps') | |
| COMPREPLY+=( $( compgen -W "$(seq 0 $((nmaps - 1)))" -- "$cur" ) ) | |
| } | |
| _sysfs_get_netdevs() | |
| { | |
| COMPREPLY+=( $( compgen -W "$( ls /sys/class/net 2>/dev/null )" -- \ | |
| "$cur" ) ) | |
| } | |
| # Retrieve type of the map that we are operating on. | |
| _bpftool_map_guess_map_type() | |
| { | |
| local keyword ref | |
| for (( idx=3; idx < ${#words[@]}-1; idx++ )); do | |
| case "${words[$((idx-2))]}" in | |
| lookup|update) | |
| keyword=${words[$((idx-1))]} | |
| ref=${words[$((idx))]} | |
| ;; | |
| push) | |
| printf "stack" | |
| return 0 | |
| ;; | |
| enqueue) | |
| printf "queue" | |
| return 0 | |
| ;; | |
| esac | |
| done | |
| [[ -z $ref ]] && return 0 | |
| local type | |
| type=$(bpftool -jp map show $keyword $ref | \ | |
| command sed -n 's/.*"type": "\(.*\)",$/\1/p') | |
| [[ -n $type ]] && printf $type | |
| } | |
| _bpftool_map_update_get_id() | |
| { | |
| local command="$1" | |
| # Is it the map to update, or a map to insert into the map to update? | |
| # Search for "value" keyword. | |
| local idx value | |
| for (( idx=7; idx < ${#words[@]}-1; idx++ )); do | |
| if [[ ${words[idx]} == "value" ]]; then | |
| value=1 | |
| break | |
| fi | |
| done | |
| if [[ $value -eq 0 ]]; then | |
| case "$command" in | |
| push) | |
| _bpftool_get_map_ids_for_type stack | |
| ;; | |
| enqueue) | |
| _bpftool_get_map_ids_for_type queue | |
| ;; | |
| *) | |
| _bpftool_get_map_ids | |
| ;; | |
| esac | |
| return 0 | |
| fi | |
| # Id to complete is for a value. It can be either prog id or map id. This | |
| # depends on the type of the map to update. | |
| local type=$(_bpftool_map_guess_map_type) | |
| case $type in | |
| array_of_maps|hash_of_maps) | |
| _bpftool_get_map_ids | |
| return 0 | |
| ;; | |
| prog_array) | |
| _bpftool_get_prog_ids | |
| return 0 | |
| ;; | |
| *) | |
| return 0 | |
| ;; | |
| esac | |
| } | |
| _bpftool() | |
| { | |
| local cur prev words objword | |
| _init_completion || return | |
| # Deal with options | |
| if [[ ${words[cword]} == -* ]]; then | |
| local c='--version --json --pretty --bpffs --mapcompat --debug' | |
| COMPREPLY=( $( compgen -W "$c" -- "$cur" ) ) | |
| return 0 | |
| fi | |
| # Deal with simplest keywords | |
| case $prev in | |
| help|hex|opcodes|visual|linum) | |
| return 0 | |
| ;; | |
| tag) | |
| _bpftool_get_prog_tags | |
| return 0 | |
| ;; | |
| dev) | |
| _sysfs_get_netdevs | |
| return 0 | |
| ;; | |
| file|pinned) | |
| _filedir | |
| return 0 | |
| ;; | |
| batch) | |
| COMPREPLY=( $( compgen -W 'file' -- "$cur" ) ) | |
| return 0 | |
| ;; | |
| esac | |
| # Remove all options so completions don't have to deal with them. | |
| local i | |
| for (( i=1; i < ${#words[@]}; )); do | |
| if [[ ${words[i]::1} == - ]]; then | |
| words=( "${words[@]:0:i}" "${words[@]:i+1}" ) | |
| [[ $i -le $cword ]] && cword=$(( cword - 1 )) | |
| else | |
| i=$(( ++i )) | |
| fi | |
| done | |
| cur=${words[cword]} | |
| prev=${words[cword - 1]} | |
| pprev=${words[cword - 2]} | |
| local object=${words[1]} command=${words[2]} | |
| if [[ -z $object || $cword -eq 1 ]]; then | |
| case $cur in | |
| *) | |
| COMPREPLY=( $( compgen -W "$( bpftool help 2>&1 | \ | |
| command sed \ | |
| -e '/OBJECT := /!d' \ | |
| -e 's/.*{//' \ | |
| -e 's/}.*//' \ | |
| -e 's/|//g' )" -- "$cur" ) ) | |
| COMPREPLY+=( $( compgen -W 'batch help' -- "$cur" ) ) | |
| return 0 | |
| ;; | |
| esac | |
| fi | |
| [[ $command == help ]] && return 0 | |
| # Completion depends on object and command in use | |
| case $object in | |
| prog) | |
| # Complete id, only for subcommands that use prog (but no map) ids | |
| case $command in | |
| show|list|dump|pin) | |
| case $prev in | |
| id) | |
| _bpftool_get_prog_ids | |
| return 0 | |
| ;; | |
| esac | |
| ;; | |
| esac | |
| local PROG_TYPE='id pinned tag' | |
| local MAP_TYPE='id pinned' | |
| case $command in | |
| show|list) | |
| [[ $prev != "$command" ]] && return 0 | |
| COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) | |
| return 0 | |
| ;; | |
| dump) | |
| case $prev in | |
| $command) | |
| COMPREPLY+=( $( compgen -W "xlated jited" -- \ | |
| "$cur" ) ) | |
| return 0 | |
| ;; | |
| xlated|jited) | |
| COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \ | |
| "$cur" ) ) | |
| return 0 | |
| ;; | |
| *) | |
| _bpftool_once_attr 'file' | |
| if _bpftool_search_list 'xlated'; then | |
| COMPREPLY+=( $( compgen -W 'opcodes visual linum' -- \ | |
| "$cur" ) ) | |
| else | |
| COMPREPLY+=( $( compgen -W 'opcodes linum' -- \ | |
| "$cur" ) ) | |
| fi | |
| return 0 | |
| ;; | |
| esac | |
| ;; | |
| pin) | |
| if [[ $prev == "$command" ]]; then | |
| COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) | |
| else | |
| _filedir | |
| fi | |
| return 0 | |
| ;; | |
| attach|detach) | |
| case $cword in | |
| 3) | |
| COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) | |
| return 0 | |
| ;; | |
| 4) | |
| case $prev in | |
| id) | |
| _bpftool_get_prog_ids | |
| ;; | |
| pinned) | |
| _filedir | |
| ;; | |
| esac | |
| return 0 | |
| ;; | |
| 5) | |
| COMPREPLY=( $( compgen -W 'msg_verdict stream_verdict \ | |
| stream_parser flow_dissector' -- "$cur" ) ) | |
| return 0 | |
| ;; | |
| 6) | |
| COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) | |
| return 0 | |
| ;; | |
| 7) | |
| case $prev in | |
| id) | |
| _bpftool_get_map_ids | |
| ;; | |
| pinned) | |
| _filedir | |
| ;; | |
| esac | |
| return 0 | |
| ;; | |
| esac | |
| ;; | |
| load|loadall) | |
| local obj | |
| # Propose "load/loadall" to complete "bpftool prog load", | |
| # or bash tries to complete "load" as a filename below. | |
| if [[ ${#words[@]} -eq 3 ]]; then | |
| COMPREPLY=( $( compgen -W "load loadall" -- "$cur" ) ) | |
| return 0 | |
| fi | |
| if [[ ${#words[@]} -lt 6 ]]; then | |
| _filedir | |
| return 0 | |
| fi | |
| obj=${words[3]} | |
| if [[ ${words[-4]} == "map" ]]; then | |
| COMPREPLY=( $( compgen -W "id pinned" -- "$cur" ) ) | |
| return 0 | |
| fi | |
| if [[ ${words[-3]} == "map" ]]; then | |
| if [[ ${words[-2]} == "idx" ]]; then | |
| _bpftool_get_obj_map_idxs $obj | |
| elif [[ ${words[-2]} == "name" ]]; then | |
| _bpftool_get_obj_map_names $obj | |
| fi | |
| return 0 | |
| fi | |
| if [[ ${words[-2]} == "map" ]]; then | |
| COMPREPLY=( $( compgen -W "idx name" -- "$cur" ) ) | |
| return 0 | |
| fi | |
| case $prev in | |
| type) | |
| COMPREPLY=( $( compgen -W "socket kprobe \ | |
| kretprobe classifier flow_dissector \ | |
| 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/recvmsg4 cgroup/recvmsg6 \ | |
| cgroup/post_bind4 cgroup/post_bind6 \ | |
| cgroup/sysctl cgroup/getsockopt \ | |
| cgroup/setsockopt" -- \ | |
| "$cur" ) ) | |
| return 0 | |
| ;; | |
| id) | |
| _bpftool_get_map_ids | |
| return 0 | |
| ;; | |
| pinned|pinmaps) | |
| _filedir | |
| return 0 | |
| ;; | |
| *) | |
| COMPREPLY=( $( compgen -W "map" -- "$cur" ) ) | |
| _bpftool_once_attr 'type' | |
| _bpftool_once_attr 'dev' | |
| _bpftool_once_attr 'pinmaps' | |
| return 0 | |
| ;; | |
| esac | |
| ;; | |
| tracelog) | |
| return 0 | |
| ;; | |
| run) | |
| if [[ ${#words[@]} -lt 5 ]]; then | |
| _filedir | |
| return 0 | |
| fi | |
| case $prev in | |
| id) | |
| _bpftool_get_prog_ids | |
| return 0 | |
| ;; | |
| data_in|data_out|ctx_in|ctx_out) | |
| _filedir | |
| return 0 | |
| ;; | |
| repeat|data_size_out|ctx_size_out) | |
| return 0 | |
| ;; | |
| *) | |
| _bpftool_once_attr 'data_in data_out data_size_out \ | |
| ctx_in ctx_out ctx_size_out repeat' | |
| return 0 | |
| ;; | |
| esac | |
| ;; | |
| *) | |
| [[ $prev == $object ]] && \ | |
| COMPREPLY=( $( compgen -W 'dump help pin attach detach \ | |
| load loadall show list tracelog run' -- "$cur" ) ) | |
| ;; | |
| esac | |
| ;; | |
| map) | |
| local MAP_TYPE='id pinned' | |
| case $command in | |
| show|list|dump|peek|pop|dequeue|freeze) | |
| case $prev in | |
| $command) | |
| COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) | |
| return 0 | |
| ;; | |
| id) | |
| case "$command" in | |
| peek) | |
| _bpftool_get_map_ids_for_type stack | |
| _bpftool_get_map_ids_for_type queue | |
| ;; | |
| pop) | |
| _bpftool_get_map_ids_for_type stack | |
| ;; | |
| dequeue) | |
| _bpftool_get_map_ids_for_type queue | |
| ;; | |
| *) | |
| _bpftool_get_map_ids | |
| ;; | |
| esac | |
| return 0 | |
| ;; | |
| *) | |
| return 0 | |
| ;; | |
| esac | |
| ;; | |
| create) | |
| case $prev in | |
| $command) | |
| _filedir | |
| return 0 | |
| ;; | |
| type) | |
| COMPREPLY=( $( compgen -W 'hash array prog_array \ | |
| perf_event_array percpu_hash percpu_array \ | |
| stack_trace cgroup_array lru_hash \ | |
| lru_percpu_hash lpm_trie array_of_maps \ | |
| hash_of_maps devmap devmap_hash sockmap cpumap \ | |
| xskmap sockhash cgroup_storage reuseport_sockarray \ | |
| percpu_cgroup_storage queue stack' -- \ | |
| "$cur" ) ) | |
| return 0 | |
| ;; | |
| key|value|flags|name|entries) | |
| return 0 | |
| ;; | |
| *) | |
| _bpftool_once_attr 'type' | |
| _bpftool_once_attr 'key' | |
| _bpftool_once_attr 'value' | |
| _bpftool_once_attr 'entries' | |
| _bpftool_once_attr 'name' | |
| _bpftool_once_attr 'flags' | |
| _bpftool_once_attr 'dev' | |
| return 0 | |
| ;; | |
| esac | |
| ;; | |
| lookup|getnext|delete) | |
| case $prev in | |
| $command) | |
| COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) | |
| return 0 | |
| ;; | |
| id) | |
| _bpftool_get_map_ids | |
| return 0 | |
| ;; | |
| key) | |
| COMPREPLY+=( $( compgen -W 'hex' -- "$cur" ) ) | |
| ;; | |
| *) | |
| case $(_bpftool_map_guess_map_type) in | |
| queue|stack) | |
| return 0 | |
| ;; | |
| esac | |
| _bpftool_once_attr 'key' | |
| return 0 | |
| ;; | |
| esac | |
| ;; | |
| update|push|enqueue) | |
| case $prev in | |
| $command) | |
| COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) | |
| return 0 | |
| ;; | |
| id) | |
| _bpftool_map_update_get_id $command | |
| return 0 | |
| ;; | |
| key) | |
| COMPREPLY+=( $( compgen -W 'hex' -- "$cur" ) ) | |
| ;; | |
| value) | |
| # We can have bytes, or references to a prog or a | |
| # map, depending on the type of the map to update. | |
| case "$(_bpftool_map_guess_map_type)" in | |
| array_of_maps|hash_of_maps) | |
| local MAP_TYPE='id pinned' | |
| COMPREPLY+=( $( compgen -W "$MAP_TYPE" \ | |
| -- "$cur" ) ) | |
| return 0 | |
| ;; | |
| prog_array) | |
| local PROG_TYPE='id pinned tag' | |
| COMPREPLY+=( $( compgen -W "$PROG_TYPE" \ | |
| -- "$cur" ) ) | |
| return 0 | |
| ;; | |
| *) | |
| COMPREPLY+=( $( compgen -W 'hex' \ | |
| -- "$cur" ) ) | |
| return 0 | |
| ;; | |
| esac | |
| return 0 | |
| ;; | |
| *) | |
| case $(_bpftool_map_guess_map_type) in | |
| queue|stack) | |
| _bpftool_once_attr 'value' | |
| return 0; | |
| ;; | |
| esac | |
| _bpftool_once_attr 'key' | |
| local UPDATE_FLAGS='any exist noexist' | |
| for (( idx=3; idx < ${#words[@]}-1; idx++ )); do | |
| if [[ ${words[idx]} == 'value' ]]; then | |
| # 'value' is present, but is not the last | |
| # word i.e. we can now have UPDATE_FLAGS. | |
| _bpftool_one_of_list "$UPDATE_FLAGS" | |
| return 0 | |
| fi | |
| done | |
| for (( idx=3; idx < ${#words[@]}-1; idx++ )); do | |
| if [[ ${words[idx]} == 'key' ]]; then | |
| # 'key' is present, but is not the last | |
| # word i.e. we can now have 'value'. | |
| _bpftool_once_attr 'value' | |
| return 0 | |
| fi | |
| done | |
| return 0 | |
| ;; | |
| esac | |
| ;; | |
| pin) | |
| if [[ $prev == "$command" ]]; then | |
| COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) | |
| else | |
| _filedir | |
| fi | |
| return 0 | |
| ;; | |
| event_pipe) | |
| case $prev in | |
| $command) | |
| COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) | |
| return 0 | |
| ;; | |
| id) | |
| _bpftool_get_map_ids_for_type perf_event_array | |
| return 0 | |
| ;; | |
| cpu) | |
| return 0 | |
| ;; | |
| index) | |
| return 0 | |
| ;; | |
| *) | |
| _bpftool_once_attr 'cpu' | |
| _bpftool_once_attr 'index' | |
| return 0 | |
| ;; | |
| esac | |
| ;; | |
| *) | |
| [[ $prev == $object ]] && \ | |
| COMPREPLY=( $( compgen -W 'delete dump getnext help \ | |
| lookup pin event_pipe show list update create \ | |
| peek push enqueue pop dequeue freeze' -- \ | |
| "$cur" ) ) | |
| ;; | |
| esac | |
| ;; | |
| btf) | |
| local PROG_TYPE='id pinned tag' | |
| local MAP_TYPE='id pinned' | |
| case $command in | |
| dump) | |
| case $prev in | |
| $command) | |
| COMPREPLY+=( $( compgen -W "id map prog file" -- \ | |
| "$cur" ) ) | |
| return 0 | |
| ;; | |
| prog) | |
| COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) | |
| return 0 | |
| ;; | |
| map) | |
| COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) | |
| return 0 | |
| ;; | |
| id) | |
| case $pprev in | |
| prog) | |
| _bpftool_get_prog_ids | |
| ;; | |
| map) | |
| _bpftool_get_map_ids | |
| ;; | |
| $command) | |
| _bpftool_get_btf_ids | |
| ;; | |
| esac | |
| return 0 | |
| ;; | |
| format) | |
| COMPREPLY=( $( compgen -W "c raw" -- "$cur" ) ) | |
| ;; | |
| *) | |
| # emit extra options | |
| case ${words[3]} in | |
| id|file) | |
| _bpftool_once_attr 'format' | |
| ;; | |
| map|prog) | |
| if [[ ${words[3]} == "map" ]] && [[ $cword == 6 ]]; then | |
| COMPREPLY+=( $( compgen -W "key value kv all" -- "$cur" ) ) | |
| fi | |
| _bpftool_once_attr 'format' | |
| ;; | |
| *) | |
| ;; | |
| esac | |
| return 0 | |
| ;; | |
| esac | |
| ;; | |
| show|list) | |
| case $prev in | |
| $command) | |
| COMPREPLY+=( $( compgen -W "id" -- "$cur" ) ) | |
| ;; | |
| id) | |
| _bpftool_get_btf_ids | |
| ;; | |
| esac | |
| return 0 | |
| ;; | |
| *) | |
| [[ $prev == $object ]] && \ | |
| COMPREPLY=( $( compgen -W 'dump help show list' \ | |
| -- "$cur" ) ) | |
| ;; | |
| esac | |
| ;; | |
| cgroup) | |
| case $command in | |
| show|list|tree) | |
| case $cword in | |
| 3) | |
| _filedir | |
| ;; | |
| 4) | |
| COMPREPLY=( $( compgen -W 'effective' -- "$cur" ) ) | |
| ;; | |
| esac | |
| return 0 | |
| ;; | |
| attach|detach) | |
| local ATTACH_TYPES='ingress egress sock_create sock_ops \ | |
| device bind4 bind6 post_bind4 post_bind6 connect4 \ | |
| connect6 sendmsg4 sendmsg6 recvmsg4 recvmsg6 sysctl \ | |
| getsockopt setsockopt' | |
| local ATTACH_FLAGS='multi override' | |
| local PROG_TYPE='id pinned tag' | |
| case $prev in | |
| $command) | |
| _filedir | |
| return 0 | |
| ;; | |
| ingress|egress|sock_create|sock_ops|device|bind4|bind6|\ | |
| post_bind4|post_bind6|connect4|connect6|sendmsg4|\ | |
| sendmsg6|recvmsg4|recvmsg6|sysctl|getsockopt|\ | |
| setsockopt) | |
| COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \ | |
| "$cur" ) ) | |
| return 0 | |
| ;; | |
| id) | |
| _bpftool_get_prog_ids | |
| return 0 | |
| ;; | |
| *) | |
| if ! _bpftool_search_list "$ATTACH_TYPES"; then | |
| COMPREPLY=( $( compgen -W "$ATTACH_TYPES" -- \ | |
| "$cur" ) ) | |
| elif [[ "$command" == "attach" ]]; then | |
| # We have an attach type on the command line, | |
| # but it is not the previous word, or | |
| # "id|pinned|tag" (we already checked for | |
| # that). This should only leave the case when | |
| # we need attach flags for "attach" commamnd. | |
| _bpftool_one_of_list "$ATTACH_FLAGS" | |
| fi | |
| return 0 | |
| ;; | |
| esac | |
| ;; | |
| *) | |
| [[ $prev == $object ]] && \ | |
| COMPREPLY=( $( compgen -W 'help attach detach \ | |
| show list tree' -- "$cur" ) ) | |
| ;; | |
| esac | |
| ;; | |
| perf) | |
| case $command in | |
| *) | |
| [[ $prev == $object ]] && \ | |
| COMPREPLY=( $( compgen -W 'help \ | |
| show list' -- "$cur" ) ) | |
| ;; | |
| esac | |
| ;; | |
| net) | |
| local PROG_TYPE='id pinned tag' | |
| local ATTACH_TYPES='xdp xdpgeneric xdpdrv xdpoffload' | |
| case $command in | |
| show|list) | |
| [[ $prev != "$command" ]] && return 0 | |
| COMPREPLY=( $( compgen -W 'dev' -- "$cur" ) ) | |
| return 0 | |
| ;; | |
| attach) | |
| case $cword in | |
| 3) | |
| COMPREPLY=( $( compgen -W "$ATTACH_TYPES" -- "$cur" ) ) | |
| return 0 | |
| ;; | |
| 4) | |
| COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) | |
| return 0 | |
| ;; | |
| 5) | |
| case $prev in | |
| id) | |
| _bpftool_get_prog_ids | |
| ;; | |
| pinned) | |
| _filedir | |
| ;; | |
| esac | |
| return 0 | |
| ;; | |
| 6) | |
| COMPREPLY=( $( compgen -W 'dev' -- "$cur" ) ) | |
| return 0 | |
| ;; | |
| 8) | |
| _bpftool_once_attr 'overwrite' | |
| return 0 | |
| ;; | |
| esac | |
| ;; | |
| detach) | |
| case $cword in | |
| 3) | |
| COMPREPLY=( $( compgen -W "$ATTACH_TYPES" -- "$cur" ) ) | |
| return 0 | |
| ;; | |
| 4) | |
| COMPREPLY=( $( compgen -W 'dev' -- "$cur" ) ) | |
| return 0 | |
| ;; | |
| esac | |
| ;; | |
| *) | |
| [[ $prev == $object ]] && \ | |
| COMPREPLY=( $( compgen -W 'help \ | |
| show list attach detach' -- "$cur" ) ) | |
| ;; | |
| esac | |
| ;; | |
| feature) | |
| case $command in | |
| probe) | |
| [[ $prev == "prefix" ]] && return 0 | |
| if _bpftool_search_list 'macros'; then | |
| COMPREPLY+=( $( compgen -W 'prefix' -- "$cur" ) ) | |
| else | |
| COMPREPLY+=( $( compgen -W 'macros' -- "$cur" ) ) | |
| fi | |
| _bpftool_one_of_list 'kernel dev' | |
| return 0 | |
| ;; | |
| *) | |
| [[ $prev == $object ]] && \ | |
| COMPREPLY=( $( compgen -W 'help probe' -- "$cur" ) ) | |
| ;; | |
| esac | |
| ;; | |
| esac | |
| } && | |
| complete -F _bpftool bpftool | |
| # ex: ts=4 sw=4 et filetype=sh |