iproute2/bash-completion/devlink
<<
>>
Prefs
   1# bash completion for devlink(8)                          -*- shell-script -*-
   2
   3# Get all the optional commands for devlink
   4_devlink_get_optional_commands()
   5{
   6    local object=$1; shift
   7
   8    local filter_options=""
   9    local options="$(devlink $object help 2>&1 \
  10        | command sed -n -e "s/^.*devlink $object //p" \
  11        | cut -d " " -f 1)"
  12
  13    # Remove duplicate options from "devlink $OBJECT help" command
  14    local opt
  15    for opt in $options; do
  16        if [[ $filter_options =~ $opt ]]; then
  17            continue
  18        else
  19            filter_options="$filter_options $opt"
  20        fi
  21    done
  22
  23    echo $filter_options
  24}
  25
  26# Complete based on given word, for when an argument or an option name has
  27# but a few possible arguments.
  28_devlink_direct_complete()
  29{
  30    local dev port region value
  31
  32    case $1 in
  33        dev)
  34            value=$(devlink dev show 2>/dev/null)
  35            ;;
  36        selftests_id)
  37            dev=${words[4]}
  38            value=$(devlink -j dev selftests show 2>/dev/null \
  39                    | jq ".selftests[\"$dev\"][]")
  40            ;;
  41        param_name)
  42            dev=${words[4]}
  43            value=$(devlink -j dev param show 2>/dev/null \
  44                    | jq ".param[\"$dev\"][].name")
  45            ;;
  46        port)
  47            value=$(devlink -j port show 2>/dev/null \
  48                    | jq '.port as $ports | $ports | keys[] as $key
  49                    | ($ports[$key].netdev // $key)')
  50            ;;
  51        lc)
  52            dev=${words[3]}
  53            value=$(devlink -j lc show 2>/dev/null \
  54                    | jq ".lc[\"$dev\"]" \
  55                    | jq '. as $lcs | $lcs | keys[] as $key |($lcs[$key].lc)' \
  56                    2>/dev/null)
  57            ;;
  58        lc_type)
  59            dev=${words[3]}
  60            lc=${words[5]}
  61            value=$(devlink lc show $dev lc $lc -j 2>/dev/null \
  62                    | jq '.[][][]["supported_types"][]')
  63            ;;
  64        region)
  65            value=$(devlink -j region show 2>/dev/null \
  66                    | jq '.regions' | jq 'keys[]')
  67            ;;
  68        snapshot)
  69            region=${words[3]}
  70            value=$(devlink -j region show 2>/dev/null \
  71                    | jq ".regions[\"$region\"].snapshot[]")
  72            ;;
  73        trap)
  74            dev=${words[3]}
  75            value=$(devlink -j trap show 2>/dev/null \
  76                    | jq ".trap[\"$dev\"][].name")
  77            ;;
  78        trap_group)
  79            dev=${words[4]}
  80            value=$(devlink -j trap group show 2>/dev/null \
  81                    | jq ".trap_group[\"$dev\"][].name")
  82            ;;
  83        trap_policer)
  84            dev=${words[4]}
  85            value=$(devlink -j trap policer show 2>/dev/null \
  86                    | jq ".trap_policer[\"$dev\"][].policer")
  87            ;;
  88        health_dev)
  89            value=$(devlink -j health show 2>/dev/null | jq '.health' \
  90                    | jq 'keys[]')
  91            ;;
  92        reporter)
  93            dev=${words[cword - 2]}
  94            value=$(devlink -j health show 2>/dev/null \
  95                    | jq ".health[\"$dev\"][].reporter")
  96            ;;
  97        pool)
  98            dev=$pprev
  99            value=$(devlink -j sb pool show 2>/dev/null \
 100                    | jq ".pool[\"$dev\"][].pool")
 101            ;;
 102        port_pool)
 103            port=${words[5]}
 104            value=$(devlink -j sb port pool show 2>/dev/null \
 105                    | jq ".port_pool[\"$port\"][].pool")
 106            ;;
 107        tc)
 108            port=$pprev
 109            value=$(devlink -j sb tc bind show 2>/dev/null \
 110                    | jq ".tc_bind[\"$port\"][].tc")
 111            ;;
 112    esac
 113
 114    COMPREPLY+=( $( compgen -W "$value" -- "$cur" ) )
 115    # Remove colon containing prefix from COMPREPLY items in order to avoid
 116    # wordbreaks with colon.
 117    __ltrim_colon_completions "$cur"
 118}
 119
 120# Completion for devlink dev eswitch set
 121_devlink_dev_eswitch_set()
 122{
 123    local -A settings=(
 124        [mode]=notseen
 125        [inline-mode]=notseen
 126        [encap-mode]=notseen
 127    )
 128
 129    if [[ $cword -eq 5 ]]; then
 130        COMPREPLY=( $( compgen -W "mode inline-mode encap-mode" -- "$cur" ) )
 131    fi
 132
 133    # Mark seen settings
 134    local word
 135    for word in "${words[@]:5:${#words[@]}-1}"; do
 136        if [[ -n $word ]]; then
 137            if [[ "${settings[$word]}" ]]; then
 138                settings[$word]=seen
 139            fi
 140        fi
 141    done
 142
 143    case $prev in
 144        mode)
 145            COMPREPLY=( $( compgen -W "legacy switchdev" -- "$cur" ) )
 146            return
 147            ;;
 148        inline-mode)
 149            COMPREPLY=( $( compgen -W "none link network transport" -- \
 150                "$cur" ) )
 151            return
 152            ;;
 153        encap-mode)
 154            COMPREPLY=( $( compgen -W "none basic" -- "$cur" ) )
 155            return
 156            ;;
 157    esac
 158
 159    local -a comp_words=()
 160
 161    # Add settings not seen to completions
 162    local setting
 163    for setting in "${!settings[@]}"; do
 164        if [ "${settings[$setting]}" = notseen ]; then
 165            comp_words+=( "$setting" )
 166        fi
 167    done
 168
 169    COMPREPLY=( $( compgen -W "${comp_words[*]}" -- "$cur" ) )
 170}
 171
 172# Completion for devlink dev eswitch
 173_devlink_dev_eswitch()
 174{
 175    case "$cword" in
 176        3)
 177            COMPREPLY=( $( compgen -W "show set" -- "$cur" ) )
 178            return
 179            ;;
 180        4)
 181            _devlink_direct_complete "dev"
 182            return
 183            ;;
 184    esac
 185
 186    case "${words[3]}" in
 187        set)
 188            _devlink_dev_eswitch_set
 189            return
 190            ;;
 191        show)
 192            return
 193            ;;
 194    esac
 195}
 196
 197# Completion for devlink dev param set
 198_devlink_dev_param_set()
 199{
 200    case $cword in
 201        7)
 202            COMPREPLY=( $( compgen -W "value" -- "$cur" ) )
 203            return
 204            ;;
 205        8)
 206            # String argument
 207            return
 208            ;;
 209        9)
 210            COMPREPLY=( $( compgen -W "cmode" -- "$cur" ) )
 211            return
 212            ;;
 213        10)
 214            COMPREPLY=( $( compgen -W "runtime driverinit permanent" -- \
 215                "$cur" ) )
 216            return
 217            ;;
 218    esac
 219}
 220
 221# Completion for devlink dev param
 222_devlink_dev_param()
 223{
 224    case "$cword" in
 225        3)
 226            COMPREPLY=( $( compgen -W "show set" -- "$cur" ) )
 227            return
 228            ;;
 229        4)
 230            _devlink_direct_complete "dev"
 231            return
 232            ;;
 233        5)
 234            COMPREPLY=( $( compgen -W "name" -- "$cur" ) )
 235            return
 236            ;;
 237        6)
 238            _devlink_direct_complete "param_name"
 239            return
 240            ;;
 241    esac
 242
 243    if [[ "${words[3]}" == "set" ]]; then
 244        _devlink_dev_param_set
 245    fi
 246}
 247
 248# Completion for devlink dev reload
 249_devlink_dev_reload()
 250{
 251    case "$cword" in
 252        4)
 253            COMPREPLY=( $( compgen -W "netns" -- "$cur" ) )
 254            return
 255            ;;
 256        5)
 257            local nslist=$( ip netns list 2>/dev/null )
 258            COMPREPLY=( $( compgen -W "$nslist" -- "$cur" ) )
 259            return
 260            ;;
 261    esac
 262}
 263
 264# Completion for devlink dev flash
 265_devlink_dev_flash()
 266{
 267    case "$cword" in
 268        4)
 269            COMPREPLY=( $( compgen -W "file" -- "$cur" ) )
 270            return
 271            ;;
 272        5)
 273            _filedir
 274            return
 275            ;;
 276        6)
 277            COMPREPLY=( $( compgen -W "component" -- "$cur" ) )
 278            return
 279            ;;
 280     esac
 281}
 282
 283# Completion for devlink dev selftests
 284_devlink_dev_selftests()
 285{
 286    if [[ $cword -gt 5 ]]; then
 287            _devlink_direct_complete "selftests_id"
 288            return
 289    fi
 290    case "$cword" in
 291        3)
 292            COMPREPLY=( $( compgen -W "show run" -- "$cur" ) )
 293            return
 294            ;;
 295        4)
 296            _devlink_direct_complete "dev"
 297            return
 298            ;;
 299        5)
 300            COMPREPLY=( $( compgen -W "id" -- "$cur" ) )
 301            return
 302            ;;
 303    esac
 304}
 305
 306# Completion for devlink dev
 307_devlink_dev()
 308{
 309    case $command in
 310        show|reload|info|flash)
 311            if [[ $cword -le 3 ]]; then
 312                _devlink_direct_complete "dev"
 313            elif [[ $command == "reload" || $command == "flash" ]];then
 314                _devlink_dev_$command
 315            fi
 316            return
 317            ;;
 318        eswitch|param|selftests)
 319            _devlink_dev_$command
 320            return
 321            ;;
 322    esac
 323}
 324
 325# Completion for devlink port set
 326_devlink_port_set()
 327{
 328    case "$cword" in
 329        3)
 330            _devlink_direct_complete "port"
 331            return
 332            ;;
 333        4)
 334            COMPREPLY=( $( compgen -W "type" -- "$cur" ) )
 335            return
 336            ;;
 337        5)
 338            COMPREPLY=( $( compgen -W "eth ib auto" -- "$cur" ) )
 339            return
 340            ;;
 341    esac
 342}
 343
 344# Completion for devlink port split
 345_devlink_port_split()
 346{
 347    case "$cword" in
 348        3)
 349            _devlink_direct_complete "port"
 350            return
 351            ;;
 352        4)
 353            COMPREPLY=( $( compgen -W "count" -- "$cur" ) )
 354            return
 355            ;;
 356        5)
 357            # Integer argument
 358            return
 359            ;;
 360    esac
 361}
 362
 363# Completion for devlink port param set
 364_devlink_port_param_set()
 365{
 366    case $cword in
 367        7)
 368            COMPREPLY=( $( compgen -W "value" -- "$cur" ) )
 369            return
 370            ;;
 371        8)
 372            # String argument
 373            return
 374            ;;
 375        9)
 376            COMPREPLY=( $( compgen -W "cmode" -- "$cur" ) )
 377            return
 378            ;;
 379        10)
 380            COMPREPLY=( $( compgen -W "runtime driverinit permanent" -- \
 381                "$cur" ) )
 382            return
 383            ;;
 384    esac
 385}
 386
 387# Completion for devlink port param
 388_devlink_port_param()
 389{
 390    case "$cword" in
 391        3)
 392            COMPREPLY=( $( compgen -W "show set" -- "$cur" ) )
 393            return
 394            ;;
 395        4)
 396            _devlink_direct_complete "port"
 397            return
 398            ;;
 399        5)
 400            COMPREPLY=( $( compgen -W "name" -- "$cur" ) )
 401            return
 402            ;;
 403        6)
 404            _devlink_direct_complete "param_name"
 405            return
 406            ;;
 407    esac
 408
 409    if [[ "${words[3]}" == "set" ]]; then
 410        _devlink_port_param_set
 411    fi
 412}
 413
 414# Completion for devlink port
 415_devlink_port()
 416{
 417    case $command in
 418        set)
 419            _devlink_port_set
 420            return
 421            ;;
 422        split)
 423            _devlink_port_split
 424            return
 425            ;;
 426        param)
 427            _devlink_port_param
 428            return
 429            ;;
 430        show|unsplit)
 431            if [[ $cword -eq 3 ]]; then
 432                _devlink_direct_complete "port"
 433            fi
 434            return
 435            ;;
 436    esac
 437}
 438
 439# Completion for devlink lc set
 440_devlink_lc_set()
 441{
 442    case "$cword" in
 443        3)
 444            _devlink_direct_complete "dev"
 445            return
 446            ;;
 447        4)
 448            COMPREPLY=( $( compgen -W "lc" -- "$cur" ) )
 449            ;;
 450        5)
 451            _devlink_direct_complete "lc"
 452            ;;
 453        6)
 454            COMPREPLY=( $( compgen -W "type notype" -- "$cur" ) )
 455            return
 456            ;;
 457        7)
 458            if [[ "$prev" == "type" ]]; then
 459                _devlink_direct_complete "lc_type"
 460            fi
 461    esac
 462}
 463
 464# Completion for devlink lc show
 465_devlink_lc_show()
 466{
 467    case $cword in
 468        3)
 469            _devlink_direct_complete "dev"
 470            ;;
 471        4)
 472            COMPREPLY=( $( compgen -W "lc" -- "$cur" ) )
 473            ;;
 474        5)
 475            _devlink_direct_complete "lc"
 476            ;;
 477    esac
 478}
 479
 480# Completion for devlink lc
 481_devlink_lc()
 482{
 483    case $command in
 484        set)
 485            _devlink_lc_set
 486            return
 487            ;;
 488        show)
 489            _devlink_lc_show
 490            return
 491            ;;
 492    esac
 493}
 494
 495# Completion for devlink dpipe
 496_devlink_dpipe()
 497{
 498    local options="$(devlink dpipe help 2>&1 \
 499                     | command sed -e '/OBJECT-LIST := /!d' \
 500                     -e 's/.*{ //' -e 's/}.*//' -e 's/|//g' )"
 501
 502    if [[ $cword -eq 2 ]]; then
 503        COMPREPLY+=( $( compgen -W "$options" -- "$cur" ) )
 504    fi
 505}
 506
 507# Completion for devlink monitor
 508_devlink_monitor()
 509{
 510    local options="$(devlink monitor help 2>&1 \
 511                     | command sed -e '/OBJECT-LIST := /!d' \
 512                     -e 's/.*{ //' -e 's/}.*//' -e 's/|//g' )"
 513
 514    if [[ $cword -eq 2 ]]; then
 515        COMPREPLY+=( $( compgen -W "all $options" -- "$cur" ) )
 516    fi
 517}
 518
 519# Completion for the rest of devlink sb $command
 520_devlink_sb_command_options()
 521{
 522    local subcmd
 523
 524    case $command in
 525        pool)
 526            subcmd=${words[3]}
 527            if [[ $cword -eq 5 ]]; then
 528                COMPREPLY=( $( compgen -W "pool" -- "$cur" ) )
 529            fi
 530            if [[ $subcmd == "set" ]]; then
 531                case $cword in
 532                    7)
 533                        COMPREPLY+=( $( compgen -W "size" -- "$cur" ) )
 534                        ;;
 535                    9)
 536                        COMPREPLY+=( $( compgen -W "thtype" -- "$cur" ) )
 537                        ;;
 538                esac
 539            fi
 540            ;;
 541        port)
 542            subcmd=${words[4]}
 543            if [[ $cword -eq 6 ]]; then
 544                COMPREPLY+=( $( compgen -W "pool" -- "$cur" ) )
 545            fi
 546            if [[ $subcmd == "set" ]]; then
 547                case $cword in
 548                    8)
 549                        COMPREPLY+=( $( compgen -W "th" -- "$cur" ) )
 550                        ;;
 551                esac
 552            fi
 553            ;;
 554        tc)
 555            subcmd=${words[4]}
 556            case $cword in
 557                6)
 558                    COMPREPLY+=( $( compgen -W "tc" -- "$cur" ) )
 559                    ;;
 560                8)
 561                    COMPREPLY+=( $( compgen -W "type" -- "$cur" ) )
 562                    ;;
 563            esac
 564            if [[ $subcmd == "set" ]]; then
 565                case $cword in
 566                    10)
 567                        COMPREPLY+=( $( compgen -W "pool" -- "$cur" ) )
 568                        ;;
 569                    12)
 570                        COMPREPLY+=( $( compgen -W "th" -- "$cur" ) )
 571                        ;;
 572                esac
 573            fi
 574            ;;
 575    esac
 576}
 577
 578# Completion for devlink sb
 579_devlink_sb()
 580{
 581    case $prev in
 582        bind)
 583            COMPREPLY=( $( compgen -W "set show" -- "$cur" ) )
 584            ;;
 585        occupancy)
 586            COMPREPLY=( $( compgen -W "show snapshot clearmax" -- "$cur" ) )
 587            ;;
 588        pool)
 589            if [[ $cword -eq 3 || $cword -eq 4 ]]; then
 590                COMPREPLY=( $( compgen -W "set show" -- "$cur" ) )
 591            elif [[ $command == "port" || $command == "tc" ]]; then
 592                _devlink_direct_complete "port_pool"
 593            else
 594                _devlink_direct_complete "pool"
 595            fi
 596            ;;
 597        port)
 598            if [[ $cword -eq 3 ]]; then
 599                COMPREPLY=( $( compgen -W "pool" -- "$cur" ) )
 600            fi
 601            ;;
 602        show|set|snapshot|clearmax)
 603            case $command in
 604                show|pool|occupancy)
 605                    _devlink_direct_complete "dev"
 606                    if [[ $command == "occupancy" && $prev == "show" ]];then
 607                        _devlink_direct_complete "port"
 608                    fi
 609                    ;;
 610                port|tc)
 611                    _devlink_direct_complete "port"
 612                    ;;
 613            esac
 614            ;;
 615        size)
 616            # Integer argument
 617            ;;
 618        thtype)
 619            COMPREPLY=( $( compgen -W "static dynamic" -- "$cur" ) )
 620            ;;
 621        th)
 622            # Integer argument
 623            ;;
 624        tc)
 625            if [[ $cword -eq 3 ]]; then
 626                COMPREPLY=( $( compgen -W "bind" -- "$cur" ) )
 627            else
 628                _devlink_direct_complete "tc"
 629            fi
 630            ;;
 631        type)
 632            COMPREPLY=( $( compgen -W "ingress egress" -- "$cur" ) )
 633            ;;
 634    esac
 635
 636    _devlink_sb_command_options
 637    return
 638}
 639
 640# Completion for devlink resource set path argument
 641_devlink_resource_path()
 642{
 643    local path parents parent all_path
 644    local dev=${words[3]}
 645    local -a path
 646
 647    local all_path=$(
 648        devlink resource show $dev \
 649            | sed -E '# Of resource lines, keep only the name itself.
 650                    s/name ([^ ]*) .*/\1/
 651                    # Drop headers.
 652                    /:$/d
 653                    # First layer is not aligned enough, align it.
 654                    s/^/  /
 655                    # Use slashes as unary code for resource depth.
 656                    s,    ,/,g
 657                    # Separate tally count from resource name.
 658                    s,/*,&\t,' \
 659            | while read d name; do
 660                    while ((${#path[@]} > ${#d})); do
 661                        unset path[$((${#path[@]} - 1))]
 662                    done
 663                    path[$((${#d} - 1))]=$name
 664                    echo ${path[@]}
 665              done \
 666            | sed '# Convert paths to slash-separated
 667                    s,^,/,;s, ,/,g;s,$,/,'
 668    )
 669    COMPREPLY=( ${COMPREPLY[@]:-} $( compgen -W "$all_path" -- "$cur" ) )
 670}
 671
 672# Completion for devlink resource set
 673_devlink_resource_set()
 674{
 675    case "$cword" in
 676        3)
 677            _devlink_direct_complete "dev"
 678            return
 679            ;;
 680        4)
 681            COMPREPLY=( $( compgen -W "path" -- "$cur" ) )
 682            return
 683            ;;
 684        5)
 685            _devlink_resource_path
 686            return
 687            ;;
 688        6)
 689            COMPREPLY=( $( compgen -W "size" -- "$cur" ) )
 690            return
 691            ;;
 692        7)
 693            # Integer argument
 694            return
 695            ;;
 696    esac
 697}
 698
 699# Completion for devlink resource
 700_devlink_resource()
 701{
 702    case $command in
 703        show)
 704            if [[ $cword -eq 3 ]]; then
 705                _devlink_direct_complete "dev"
 706            fi
 707            return
 708            ;;
 709        set)
 710            _devlink_resource_set
 711            return
 712            ;;
 713    esac
 714}
 715
 716# Completion for devlink region read
 717_devlink_region_read()
 718{
 719    case "$cword" in
 720        6)
 721            COMPREPLY=( $( compgen -W "address" -- "$cur" ) )
 722            return
 723            ;;
 724        7)
 725            # Address argument, for example: 0x10
 726            return
 727            ;;
 728        8)
 729            COMPREPLY=( $( compgen -W "length" -- "$cur" ) )
 730            return
 731            ;;
 732        9)
 733            # Integer argument
 734            return
 735            ;;
 736    esac
 737}
 738
 739# Completion for devlink region
 740_devlink_region()
 741{
 742    if [[ $cword -eq 3 && $command != "help" ]]; then
 743            _devlink_direct_complete "region"
 744    fi
 745
 746    case $command in
 747        show)
 748            return
 749            ;;
 750        del|dump|read)
 751            case "$cword" in
 752                4)
 753                    COMPREPLY=( $( compgen -W "snapshot" -- "$cur" ) )
 754                    ;;
 755                5)
 756                    _devlink_direct_complete "snapshot"
 757                    ;;
 758            esac
 759
 760            if [[ $command == "read" ]]; then
 761                _devlink_region_read
 762            fi
 763            return
 764            ;;
 765    esac
 766}
 767
 768# Completion reporter for devlink health
 769_devlink_health_reporter()
 770{
 771    local i=$1; shift
 772
 773    case $cword in
 774        $((3 + $i)))
 775            _devlink_direct_complete "health_dev"
 776            ;;
 777        $((4 + $i)))
 778            COMPREPLY=( $( compgen -W "reporter" -- "$cur" ) )
 779            ;;
 780        $((5 + $i)))
 781            _devlink_direct_complete "reporter"
 782            ;;
 783    esac
 784}
 785
 786# Completion for devlink health
 787_devlink_health()
 788{
 789    case $command in
 790        show|recover|diagnose|set|test)
 791            _devlink_health_reporter 0
 792            if [[ $command == "set" ]]; then
 793                case $cword in
 794                    6)
 795                        COMPREPLY=( $( compgen -W "grace_period auto_recover" \
 796                                   -- "$cur" ) )
 797                        ;;
 798                    7)
 799                        case $prev in
 800                            grace_period)
 801                                # Integer argument- msec
 802                                ;;
 803                            auto_recover)
 804                                COMPREPLY=( $( compgen -W "true false" -- \
 805                                    "$cur" ) )
 806                                ;;
 807                        esac
 808                esac
 809            fi
 810            return
 811            ;;
 812        dump)
 813            if [[ $cword -eq 3 ]]; then
 814                COMPREPLY=( $( compgen -W "show clear" -- "$cur" ) )
 815            fi
 816
 817            _devlink_health_reporter 1
 818            return
 819            ;;
 820    esac
 821}
 822
 823# Completion for action in devlink trap set
 824_devlink_trap_set_action()
 825{
 826    local i=$1; shift
 827
 828    case $cword in
 829        $((6 + $i)))
 830            COMPREPLY=( $( compgen -W "action" -- "$cur" ) )
 831            ;;
 832        $((7 + $i)))
 833            COMPREPLY=( $( compgen -W "trap drop mirror" -- "$cur" ) )
 834            ;;
 835    esac
 836}
 837
 838# Completion for devlink trap group set
 839_devlink_trap_group_set()
 840{
 841    local -A settings=(
 842        [action]=notseen
 843        [policer]=notseen
 844        [nopolicer]=notseen
 845    )
 846
 847    if [[ $cword -eq 7 ]]; then
 848        COMPREPLY=( $( compgen -W "action policer nopolicer" -- "$cur" ) )
 849    fi
 850
 851    # Mark seen settings
 852    local word
 853    for word in "${words[@]:7:${#words[@]}-1}"; do
 854        if [[ -n $word ]]; then
 855            if [[ "${settings[$word]}" ]]; then
 856                settings[$word]=seen
 857            fi
 858        fi
 859    done
 860
 861    case $prev in
 862        action)
 863            COMPREPLY=( $( compgen -W "trap drop mirror" -- "$cur" ) )
 864            return
 865            ;;
 866        policer)
 867            _devlink_direct_complete "trap_policer"
 868            return
 869            ;;
 870    esac
 871
 872    local -a comp_words=()
 873
 874    # Add settings not seen to completions
 875    local setting
 876    for setting in "${!settings[@]}"; do
 877        if [ "${settings[$setting]}" = notseen ]; then
 878            comp_words+=( "$setting" )
 879        fi
 880    done
 881
 882    COMPREPLY=( $( compgen -W "${comp_words[*]}" -- "$cur" ) )
 883}
 884
 885# Completion for devlink trap group
 886_devlink_trap_group()
 887{
 888    case $cword in
 889        3)
 890            COMPREPLY=( $( compgen -W "set show" -- "$cur" ) )
 891            return
 892            ;;
 893        4)
 894            _devlink_direct_complete "dev"
 895            return
 896            ;;
 897        5)
 898            COMPREPLY=( $( compgen -W "group" -- "$cur" ) )
 899            return
 900            ;;
 901        6)
 902            _devlink_direct_complete "trap_group"
 903            return
 904            ;;
 905    esac
 906
 907    if [[ ${words[3]} == "set" ]]; then
 908        _devlink_trap_group_set
 909    fi
 910}
 911
 912# Completion for devlink trap policer set
 913_devlink_trap_policer_set()
 914{
 915    local -A settings=(
 916        [rate]=notseen
 917        [burst]=notseen
 918    )
 919
 920    if [[ $cword -eq 7 ]]; then
 921        COMPREPLY=( $( compgen -W "rate burst" -- "$cur" ) )
 922    fi
 923
 924    # Mark seen settings
 925    local word
 926    for word in "${words[@]:7:${#words[@]}-1}"; do
 927        if [[ -n $word ]]; then
 928            if [[ "${settings[$word]}" ]]; then
 929                settings[$word]=seen
 930            fi
 931        fi
 932    done
 933
 934    case $prev in
 935        rate)
 936            # Integer argument
 937            return
 938            ;;
 939        burst)
 940            # Integer argument
 941            return
 942            ;;
 943    esac
 944
 945    local -a comp_words=()
 946
 947    # Add settings not seen to completions
 948    local setting
 949    for setting in "${!settings[@]}"; do
 950        if [ "${settings[$setting]}" = notseen ]; then
 951            comp_words+=( "$setting" )
 952        fi
 953    done
 954
 955    COMPREPLY=( $( compgen -W "${comp_words[*]}" -- "$cur" ) )
 956}
 957
 958# Completion for devlink trap policer
 959_devlink_trap_policer()
 960{
 961    case $cword in
 962        3)
 963            COMPREPLY=( $( compgen -W "set show" -- "$cur" ) )
 964            return
 965            ;;
 966        4)
 967            _devlink_direct_complete "dev"
 968            return
 969            ;;
 970        5)
 971            COMPREPLY=( $( compgen -W "policer" -- "$cur" ) )
 972            return
 973            ;;
 974        6)
 975            _devlink_direct_complete "trap_policer"
 976            return
 977            ;;
 978    esac
 979
 980    if [[ ${words[3]} == "set" ]]; then
 981        _devlink_trap_policer_set
 982    fi
 983}
 984
 985# Completion for devlink trap
 986_devlink_trap()
 987{
 988    case $command in
 989        show|set)
 990            case $cword in
 991                3)
 992                    _devlink_direct_complete "dev"
 993                    ;;
 994                4)
 995                    COMPREPLY=( $( compgen -W "trap" -- "$cur" ) )
 996                    ;;
 997                5)
 998                    _devlink_direct_complete "trap"
 999                    ;;
1000            esac
1001
1002            if [[ $command == "set" ]]; then
1003                _devlink_trap_set_action 0
1004            fi
1005            return
1006            ;;
1007        group)
1008            _devlink_trap_$command
1009            return
1010            ;;
1011        policer)
1012            _devlink_trap_$command
1013            return
1014            ;;
1015    esac
1016}
1017
1018# Complete any devlink command
1019_devlink()
1020{
1021    local cur prev words cword
1022    local opt='--Version --no-nice-names --json --pretty --verbose \
1023        --statistics --force --Netns --batch'
1024    local objects="$(devlink help 2>&1 | command sed -e '/OBJECT := /!d' \
1025                     -e 's/.*{//' -e 's/}.*//' -e \ 's/|//g' )"
1026
1027    _init_completion || return
1028    # Gets the word-to-complete without considering the colon as word breaks
1029    _get_comp_words_by_ref -n : cur prev words cword
1030
1031    if [[ $cword -eq 1 ]]; then
1032            case $cur in
1033                -*)
1034                        COMPREPLY=( $( compgen -W "$opt" -- "$cur" ) )
1035                        return 0
1036                        ;;
1037                *)
1038                        COMPREPLY=( $( compgen -W "$objects" -- "$cur" ) )
1039                        return 0
1040                        ;;
1041            esac
1042    fi
1043
1044    # Deal with options
1045    if [[ $prev == -* ]]; then
1046            case $prev in
1047                -V|--Version)
1048                        return 0
1049                        ;;
1050                -b|--batch)
1051                        _filedir
1052                        return 0
1053                        ;;
1054                --force)
1055                COMPREPLY=( $( compgen -W "--batch" -- "$cur" ) )
1056                        return 0
1057                        ;;
1058                -N|--Netns)
1059                        local nslist=$( ip netns list 2>/dev/null )
1060                        COMPREPLY=( $( compgen -W "$nslist" -- "$cur" ) )
1061                        return 0
1062                        ;;
1063                -j|--json)
1064                        COMPREPLY=( $( compgen -W "--pretty $objects" -- "$cur" ) )
1065                        return 0
1066                        ;;
1067            *)
1068                COMPREPLY=( $( compgen -W "$objects" -- "$cur" ) )
1069                        return 0
1070                        ;;
1071            esac
1072    fi
1073
1074    # Remove all options so completions don't have to deal with them.
1075    local i
1076    for (( i=1; i < ${#words[@]}; )); do
1077        if [[ ${words[i]::1} == - ]]; then
1078            words=( "${words[@]:0:i}" "${words[@]:i+1}" )
1079            [[ $i -le $cword ]] && cword=$(( cword - 1 ))
1080        else
1081            i=$(( ++i ))
1082        fi
1083    done
1084
1085    local object=${words[1]}
1086    local command=${words[2]}
1087    local pprev=${words[cword - 2]}
1088    local prev=${words[cword - 1]}
1089
1090    if [[ $objects =~ $object ]]; then
1091        if [[ $cword -eq 2 ]]; then
1092            COMPREPLY=( $( compgen -W "help" -- "$cur") )
1093            if [[ $object != "monitor" && $object != "dpipe" ]]; then
1094                COMPREPLY+=( $( compgen -W \
1095                    "$(_devlink_get_optional_commands $object)" -- "$cur" ) )
1096            fi
1097        fi
1098        "_devlink_$object"
1099    fi
1100
1101} &&
1102complete -F _devlink devlink
1103
1104# ex: ts=4 sw=4 et filetype=sh
1105