# bpftool(8) bash completion                               -*- shell-script -*- 
 | 
# 
 | 
# Copyright (C) 2017-2018 Netronome Systems, Inc. 
 | 
# 
 | 
# This software is dual licensed under the GNU General License 
 | 
# Version 2, June 1991 as shown in the file COPYING in the top-level 
 | 
# directory of this source tree or the BSD 2-Clause License provided 
 | 
# below.  You have the option to license this software under the 
 | 
# complete terms of either license. 
 | 
# 
 | 
# The BSD 2-Clause License: 
 | 
# 
 | 
#     Redistribution and use in source and binary forms, with or 
 | 
#     without modification, are permitted provided that the following 
 | 
#     conditions are met: 
 | 
# 
 | 
#      1. Redistributions of source code must retain the above 
 | 
#         copyright notice, this list of conditions and the following 
 | 
#         disclaimer. 
 | 
# 
 | 
#      2. Redistributions in binary form must reproduce the above 
 | 
#         copyright notice, this list of conditions and the following 
 | 
#         disclaimer in the documentation and/or other materials 
 | 
#         provided with the distribution. 
 | 
# 
 | 
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
 | 
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
 | 
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
 | 
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 
 | 
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
 | 
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
 | 
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
 | 
# SOFTWARE. 
 | 
# 
 | 
# 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" ) ) 
 | 
} 
 | 
  
 | 
_bpftool_get_perf_map_ids() 
 | 
{ 
 | 
    COMPREPLY+=( $( compgen -W "$( bpftool -jp map  2>&1 | \ 
 | 
        command grep -C2 perf_event_array | \ 
 | 
        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_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" ) ) 
 | 
} 
 | 
  
 | 
# For bpftool map update: retrieve type of the map to update. 
 | 
_bpftool_map_update_map_type() 
 | 
{ 
 | 
    local keyword ref 
 | 
    for (( idx=3; idx < ${#words[@]}-1; idx++ )); do 
 | 
        if [[ ${words[$((idx-2))]} == "update" ]]; then 
 | 
            keyword=${words[$((idx-1))]} 
 | 
            ref=${words[$((idx))]} 
 | 
        fi 
 | 
    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() 
 | 
{ 
 | 
    # 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 
 | 
    [[ $value -eq 0 ]] && _bpftool_get_map_ids && return 0 
 | 
  
 | 
    # 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_update_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' 
 | 
        COMPREPLY=( $( compgen -W "$c" -- "$cur" ) ) 
 | 
        return 0 
 | 
    fi 
 | 
  
 | 
    # Deal with simplest keywords 
 | 
    case $prev in 
 | 
        help|hex|opcodes|visual) 
 | 
            return 0 
 | 
            ;; 
 | 
        tag) 
 | 
            _bpftool_get_prog_tags 
 | 
            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]} 
 | 
  
 | 
    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) 
 | 
            if [[ $command != "load" ]]; then 
 | 
                case $prev in 
 | 
                    id) 
 | 
                        _bpftool_get_prog_ids 
 | 
                        return 0 
 | 
                        ;; 
 | 
                esac 
 | 
            fi 
 | 
  
 | 
            local PROG_TYPE='id pinned tag' 
 | 
            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' -- \ 
 | 
                                "$cur" ) ) 
 | 
                        else 
 | 
                            COMPREPLY+=( $( compgen -W 'opcodes' -- \ 
 | 
                                "$cur" ) ) 
 | 
                        fi 
 | 
                        return 0 
 | 
                        ;; 
 | 
                    esac 
 | 
                    ;; 
 | 
                pin) 
 | 
                    if [[ $prev == "$command" ]]; then 
 | 
                        COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) 
 | 
                    else 
 | 
                        _filedir 
 | 
                    fi 
 | 
                    return 0 
 | 
                    ;; 
 | 
                load) 
 | 
                    local obj 
 | 
  
 | 
                    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 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" -- \ 
 | 
                                                   "$cur" ) ) 
 | 
                            return 0 
 | 
                            ;; 
 | 
                        id) 
 | 
                            _bpftool_get_map_ids 
 | 
                            return 0 
 | 
                            ;; 
 | 
                        pinned) 
 | 
                            _filedir 
 | 
                            return 0 
 | 
                            ;; 
 | 
                        dev) 
 | 
                            _sysfs_get_netdevs 
 | 
                            return 0 
 | 
                            ;; 
 | 
                        *) 
 | 
                            COMPREPLY=( $( compgen -W "map" -- "$cur" ) ) 
 | 
                            _bpftool_once_attr 'type' 
 | 
                            _bpftool_once_attr 'dev' 
 | 
                            return 0 
 | 
                            ;; 
 | 
                    esac 
 | 
                    ;; 
 | 
                *) 
 | 
                    [[ $prev == $object ]] && \ 
 | 
                        COMPREPLY=( $( compgen -W 'dump help pin load \ 
 | 
                            show list' -- "$cur" ) ) 
 | 
                    ;; 
 | 
            esac 
 | 
            ;; 
 | 
        map) 
 | 
            local MAP_TYPE='id pinned' 
 | 
            case $command in 
 | 
                show|list|dump) 
 | 
                    case $prev in 
 | 
                        $command) 
 | 
                            COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 
 | 
                            return 0 
 | 
                            ;; 
 | 
                        id) 
 | 
                            _bpftool_get_map_ids 
 | 
                            return 0 
 | 
                            ;; 
 | 
                        *) 
 | 
                            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" ) ) 
 | 
                            ;; 
 | 
                        *) 
 | 
                            _bpftool_once_attr 'key' 
 | 
                            return 0 
 | 
                            ;; 
 | 
                    esac 
 | 
                    ;; 
 | 
                update) 
 | 
                    case $prev in 
 | 
                        $command) 
 | 
                            COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 
 | 
                            return 0 
 | 
                            ;; 
 | 
                        id) 
 | 
                            _bpftool_map_update_get_id 
 | 
                            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_update_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 
 | 
                            ;; 
 | 
                        *) 
 | 
                            _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_perf_map_ids 
 | 
                            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' -- \ 
 | 
                            "$cur" ) ) 
 | 
                    ;; 
 | 
            esac 
 | 
            ;; 
 | 
        cgroup) 
 | 
            case $command in 
 | 
                show|list) 
 | 
                    _filedir 
 | 
                    return 0 
 | 
                    ;; 
 | 
        tree) 
 | 
            _filedir 
 | 
            return 0 
 | 
            ;; 
 | 
                attach|detach) 
 | 
                    local ATTACH_TYPES='ingress egress sock_create sock_ops \ 
 | 
                        device bind4 bind6 post_bind4 post_bind6 connect4 \ 
 | 
                        connect6 sendmsg4 sendmsg6' 
 | 
                    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) 
 | 
                            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 
 | 
            ;; 
 | 
    esac 
 | 
} && 
 | 
complete -F _bpftool bpftool 
 | 
  
 | 
# ex: ts=4 sw=4 et filetype=sh 
 |