1# bpftool(8) bash completion -*- shell-script -*- 2# 3# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 4# Copyright (C) 2017-2018 Netronome Systems, Inc. 5# 6# Author: Quentin Monnet <quentin.monnet@netronome.com> 7 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. 10_bpftool_once_attr() 11{ 12 local w idx found 13 for w in $*; do 14 found=0 15 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do 16 if [[ $w == ${words[idx]} ]]; then 17 found=1 18 break 19 fi 20 done 21 [[ $found -eq 0 ]] && \ 22 COMPREPLY+=( $( compgen -W "$w" -- "$cur" ) ) 23 done 24} 25 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() 29{ 30 local w idx 31 for w in $*; do 32 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do 33 [[ $w == ${words[idx]} ]] && return 0 34 done 35 done 36 return 1 37} 38 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() 42{ 43 _bpftool_search_list $* && return 1 44 COMPREPLY+=( $( compgen -W "$*" -- "$cur" ) ) 45} 46 47_bpftool_get_map_ids() 48{ 49 COMPREPLY+=( $( compgen -W "$( bpftool -jp map 2>&1 | \ 50 command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) ) 51} 52 53# Takes map type and adds matching map ids to the list of suggestions. 54_bpftool_get_map_ids_for_type() 55{ 56 local type="$1" 57 COMPREPLY+=( $( compgen -W "$( bpftool -jp map 2>&1 | \ 58 command grep -C2 "$type" | \ 59 command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) ) 60} 61 62_bpftool_get_prog_ids() 63{ 64 COMPREPLY+=( $( compgen -W "$( bpftool -jp prog 2>&1 | \ 65 command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) ) 66} 67 68_bpftool_get_prog_tags() 69{ 70 COMPREPLY+=( $( compgen -W "$( bpftool -jp prog 2>&1 | \ 71 command sed -n 's/.*"tag": "\(.*\)",$/\1/p' )" -- "$cur" ) ) 72} 73 74_bpftool_get_btf_ids() 75{ 76 COMPREPLY+=( $( compgen -W "$( bpftool -jp btf 2>&1 | \ 77 command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) ) 78} 79 80_bpftool_get_obj_map_names() 81{ 82 local obj 83 84 obj=$1 85 86 maps=$(objdump -j maps -t $obj 2>/dev/null | \ 87 command awk '/g . maps/ {print $NF}') 88 89 COMPREPLY+=( $( compgen -W "$maps" -- "$cur" ) ) 90} 91 92_bpftool_get_obj_map_idxs() 93{ 94 local obj 95 96 obj=$1 97 98 nmaps=$(objdump -j maps -t $obj 2>/dev/null | grep -c 'g . maps') 99 100 COMPREPLY+=( $( compgen -W "$(seq 0 $((nmaps - 1)))" -- "$cur" ) ) 101} 102 103_sysfs_get_netdevs() 104{ 105 COMPREPLY+=( $( compgen -W "$( ls /sys/class/net 2>/dev/null )" -- \ 106 "$cur" ) ) 107} 108 109# Retrieve type of the map that we are operating on. 110_bpftool_map_guess_map_type() 111{ 112 local keyword ref 113 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do 114 case "${words[$((idx-2))]}" in 115 lookup|update) 116 keyword=${words[$((idx-1))]} 117 ref=${words[$((idx))]} 118 ;; 119 push) 120 printf "stack" 121 return 0 122 ;; 123 enqueue) 124 printf "queue" 125 return 0 126 ;; 127 esac 128 done 129 [[ -z $ref ]] && return 0 130 131 local type 132 type=$(bpftool -jp map show $keyword $ref | \ 133 command sed -n 's/.*"type": "\(.*\)",$/\1/p') 134 [[ -n $type ]] && printf $type 135} 136 137_bpftool_map_update_get_id() 138{ 139 local command="$1" 140 141 # Is it the map to update, or a map to insert into the map to update? 142 # Search for "value" keyword. 143 local idx value 144 for (( idx=7; idx < ${#words[@]}-1; idx++ )); do 145 if [[ ${words[idx]} == "value" ]]; then 146 value=1 147 break 148 fi 149 done 150 if [[ $value -eq 0 ]]; then 151 case "$command" in 152 push) 153 _bpftool_get_map_ids_for_type stack 154 ;; 155 enqueue) 156 _bpftool_get_map_ids_for_type queue 157 ;; 158 *) 159 _bpftool_get_map_ids 160 ;; 161 esac 162 return 0 163 fi 164 165 # Id to complete is for a value. It can be either prog id or map id. This 166 # depends on the type of the map to update. 167 local type=$(_bpftool_map_guess_map_type) 168 case $type in 169 array_of_maps|hash_of_maps) 170 _bpftool_get_map_ids 171 return 0 172 ;; 173 prog_array) 174 _bpftool_get_prog_ids 175 return 0 176 ;; 177 *) 178 return 0 179 ;; 180 esac 181} 182 183_bpftool() 184{ 185 local cur prev words objword 186 _init_completion || return 187 188 # Deal with options 189 if [[ ${words[cword]} == -* ]]; then 190 local c='--version --json --pretty --bpffs --mapcompat --debug' 191 COMPREPLY=( $( compgen -W "$c" -- "$cur" ) ) 192 return 0 193 fi 194 195 # Deal with simplest keywords 196 case $prev in 197 help|hex|opcodes|visual|linum) 198 return 0 199 ;; 200 tag) 201 _bpftool_get_prog_tags 202 return 0 203 ;; 204 dev) 205 _sysfs_get_netdevs 206 return 0 207 ;; 208 file|pinned) 209 _filedir 210 return 0 211 ;; 212 batch) 213 COMPREPLY=( $( compgen -W 'file' -- "$cur" ) ) 214 return 0 215 ;; 216 esac 217 218 # Remove all options so completions don't have to deal with them. 219 local i 220 for (( i=1; i < ${#words[@]}; )); do 221 if [[ ${words[i]::1} == - ]]; then 222 words=( "${words[@]:0:i}" "${words[@]:i+1}" ) 223 [[ $i -le $cword ]] && cword=$(( cword - 1 )) 224 else 225 i=$(( ++i )) 226 fi 227 done 228 cur=${words[cword]} 229 prev=${words[cword - 1]} 230 pprev=${words[cword - 2]} 231 232 local object=${words[1]} command=${words[2]} 233 234 if [[ -z $object || $cword -eq 1 ]]; then 235 case $cur in 236 *) 237 COMPREPLY=( $( compgen -W "$( bpftool help 2>&1 | \ 238 command sed \ 239 -e '/OBJECT := /!d' \ 240 -e 's/.*{//' \ 241 -e 's/}.*//' \ 242 -e 's/|//g' )" -- "$cur" ) ) 243 COMPREPLY+=( $( compgen -W 'batch help' -- "$cur" ) ) 244 return 0 245 ;; 246 esac 247 fi 248 249 [[ $command == help ]] && return 0 250 251 # Completion depends on object and command in use 252 case $object in 253 prog) 254 # Complete id, only for subcommands that use prog (but no map) ids 255 case $command in 256 show|list|dump|pin) 257 case $prev in 258 id) 259 _bpftool_get_prog_ids 260 return 0 261 ;; 262 esac 263 ;; 264 esac 265 266 local PROG_TYPE='id pinned tag' 267 local MAP_TYPE='id pinned' 268 case $command in 269 show|list) 270 [[ $prev != "$command" ]] && return 0 271 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) 272 return 0 273 ;; 274 dump) 275 case $prev in 276 $command) 277 COMPREPLY+=( $( compgen -W "xlated jited" -- \ 278 "$cur" ) ) 279 return 0 280 ;; 281 xlated|jited) 282 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \ 283 "$cur" ) ) 284 return 0 285 ;; 286 *) 287 _bpftool_once_attr 'file' 288 if _bpftool_search_list 'xlated'; then 289 COMPREPLY+=( $( compgen -W 'opcodes visual linum' -- \ 290 "$cur" ) ) 291 else 292 COMPREPLY+=( $( compgen -W 'opcodes linum' -- \ 293 "$cur" ) ) 294 fi 295 return 0 296 ;; 297 esac 298 ;; 299 pin) 300 if [[ $prev == "$command" ]]; then 301 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) 302 else 303 _filedir 304 fi 305 return 0 306 ;; 307 attach|detach) 308 case $cword in 309 3) 310 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) 311 return 0 312 ;; 313 4) 314 case $prev in 315 id) 316 _bpftool_get_prog_ids 317 ;; 318 pinned) 319 _filedir 320 ;; 321 esac 322 return 0 323 ;; 324 5) 325 COMPREPLY=( $( compgen -W 'msg_verdict stream_verdict \ 326 stream_parser flow_dissector' -- "$cur" ) ) 327 return 0 328 ;; 329 6) 330 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 331 return 0 332 ;; 333 7) 334 case $prev in 335 id) 336 _bpftool_get_map_ids 337 ;; 338 pinned) 339 _filedir 340 ;; 341 esac 342 return 0 343 ;; 344 esac 345 ;; 346 load|loadall) 347 local obj 348 349 # Propose "load/loadall" to complete "bpftool prog load", 350 # or bash tries to complete "load" as a filename below. 351 if [[ ${#words[@]} -eq 3 ]]; then 352 COMPREPLY=( $( compgen -W "load loadall" -- "$cur" ) ) 353 return 0 354 fi 355 356 if [[ ${#words[@]} -lt 6 ]]; then 357 _filedir 358 return 0 359 fi 360 361 obj=${words[3]} 362 363 if [[ ${words[-4]} == "map" ]]; then 364 COMPREPLY=( $( compgen -W "id pinned" -- "$cur" ) ) 365 return 0 366 fi 367 if [[ ${words[-3]} == "map" ]]; then 368 if [[ ${words[-2]} == "idx" ]]; then 369 _bpftool_get_obj_map_idxs $obj 370 elif [[ ${words[-2]} == "name" ]]; then 371 _bpftool_get_obj_map_names $obj 372 fi 373 return 0 374 fi 375 if [[ ${words[-2]} == "map" ]]; then 376 COMPREPLY=( $( compgen -W "idx name" -- "$cur" ) ) 377 return 0 378 fi 379 380 case $prev in 381 type) 382 COMPREPLY=( $( compgen -W "socket kprobe \ 383 kretprobe classifier flow_dissector \ 384 action tracepoint raw_tracepoint \ 385 xdp perf_event cgroup/skb cgroup/sock \ 386 cgroup/dev lwt_in lwt_out lwt_xmit \ 387 lwt_seg6local sockops sk_skb sk_msg \ 388 lirc_mode2 cgroup/bind4 cgroup/bind6 \ 389 cgroup/connect4 cgroup/connect6 \ 390 cgroup/sendmsg4 cgroup/sendmsg6 \ 391 cgroup/recvmsg4 cgroup/recvmsg6 \ 392 cgroup/post_bind4 cgroup/post_bind6 \ 393 cgroup/sysctl cgroup/getsockopt \ 394 cgroup/setsockopt" -- \ 395 "$cur" ) ) 396 return 0 397 ;; 398 id) 399 _bpftool_get_map_ids 400 return 0 401 ;; 402 pinned|pinmaps) 403 _filedir 404 return 0 405 ;; 406 *) 407 COMPREPLY=( $( compgen -W "map" -- "$cur" ) ) 408 _bpftool_once_attr 'type' 409 _bpftool_once_attr 'dev' 410 _bpftool_once_attr 'pinmaps' 411 return 0 412 ;; 413 esac 414 ;; 415 tracelog) 416 return 0 417 ;; 418 run) 419 if [[ ${#words[@]} -lt 5 ]]; then 420 _filedir 421 return 0 422 fi 423 case $prev in 424 id) 425 _bpftool_get_prog_ids 426 return 0 427 ;; 428 data_in|data_out|ctx_in|ctx_out) 429 _filedir 430 return 0 431 ;; 432 repeat|data_size_out|ctx_size_out) 433 return 0 434 ;; 435 *) 436 _bpftool_once_attr 'data_in data_out data_size_out \ 437 ctx_in ctx_out ctx_size_out repeat' 438 return 0 439 ;; 440 esac 441 ;; 442 *) 443 [[ $prev == $object ]] && \ 444 COMPREPLY=( $( compgen -W 'dump help pin attach detach \ 445 load loadall show list tracelog run' -- "$cur" ) ) 446 ;; 447 esac 448 ;; 449 map) 450 local MAP_TYPE='id pinned' 451 case $command in 452 show|list|dump|peek|pop|dequeue|freeze) 453 case $prev in 454 $command) 455 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 456 return 0 457 ;; 458 id) 459 case "$command" in 460 peek) 461 _bpftool_get_map_ids_for_type stack 462 _bpftool_get_map_ids_for_type queue 463 ;; 464 pop) 465 _bpftool_get_map_ids_for_type stack 466 ;; 467 dequeue) 468 _bpftool_get_map_ids_for_type queue 469 ;; 470 *) 471 _bpftool_get_map_ids 472 ;; 473 esac 474 return 0 475 ;; 476 *) 477 return 0 478 ;; 479 esac 480 ;; 481 create) 482 case $prev in 483 $command) 484 _filedir 485 return 0 486 ;; 487 type) 488 COMPREPLY=( $( compgen -W 'hash array prog_array \ 489 perf_event_array percpu_hash percpu_array \ 490 stack_trace cgroup_array lru_hash \ 491 lru_percpu_hash lpm_trie array_of_maps \ 492 hash_of_maps devmap devmap_hash sockmap cpumap \ 493 xskmap sockhash cgroup_storage reuseport_sockarray \ 494 percpu_cgroup_storage queue stack' -- \ 495 "$cur" ) ) 496 return 0 497 ;; 498 key|value|flags|name|entries) 499 return 0 500 ;; 501 *) 502 _bpftool_once_attr 'type' 503 _bpftool_once_attr 'key' 504 _bpftool_once_attr 'value' 505 _bpftool_once_attr 'entries' 506 _bpftool_once_attr 'name' 507 _bpftool_once_attr 'flags' 508 _bpftool_once_attr 'dev' 509 return 0 510 ;; 511 esac 512 ;; 513 lookup|getnext|delete) 514 case $prev in 515 $command) 516 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 517 return 0 518 ;; 519 id) 520 _bpftool_get_map_ids 521 return 0 522 ;; 523 key) 524 COMPREPLY+=( $( compgen -W 'hex' -- "$cur" ) ) 525 ;; 526 *) 527 case $(_bpftool_map_guess_map_type) in 528 queue|stack) 529 return 0 530 ;; 531 esac 532 533 _bpftool_once_attr 'key' 534 return 0 535 ;; 536 esac 537 ;; 538 update|push|enqueue) 539 case $prev in 540 $command) 541 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 542 return 0 543 ;; 544 id) 545 _bpftool_map_update_get_id $command 546 return 0 547 ;; 548 key) 549 COMPREPLY+=( $( compgen -W 'hex' -- "$cur" ) ) 550 ;; 551 value) 552 # We can have bytes, or references to a prog or a 553 # map, depending on the type of the map to update. 554 case "$(_bpftool_map_guess_map_type)" in 555 array_of_maps|hash_of_maps) 556 local MAP_TYPE='id pinned' 557 COMPREPLY+=( $( compgen -W "$MAP_TYPE" \ 558 -- "$cur" ) ) 559 return 0 560 ;; 561 prog_array) 562 local PROG_TYPE='id pinned tag' 563 COMPREPLY+=( $( compgen -W "$PROG_TYPE" \ 564 -- "$cur" ) ) 565 return 0 566 ;; 567 *) 568 COMPREPLY+=( $( compgen -W 'hex' \ 569 -- "$cur" ) ) 570 return 0 571 ;; 572 esac 573 return 0 574 ;; 575 *) 576 case $(_bpftool_map_guess_map_type) in 577 queue|stack) 578 _bpftool_once_attr 'value' 579 return 0; 580 ;; 581 esac 582 583 _bpftool_once_attr 'key' 584 local UPDATE_FLAGS='any exist noexist' 585 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do 586 if [[ ${words[idx]} == 'value' ]]; then 587 # 'value' is present, but is not the last 588 # word i.e. we can now have UPDATE_FLAGS. 589 _bpftool_one_of_list "$UPDATE_FLAGS" 590 return 0 591 fi 592 done 593 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do 594 if [[ ${words[idx]} == 'key' ]]; then 595 # 'key' is present, but is not the last 596 # word i.e. we can now have 'value'. 597 _bpftool_once_attr 'value' 598 return 0 599 fi 600 done 601 602 return 0 603 ;; 604 esac 605 ;; 606 pin) 607 if [[ $prev == "$command" ]]; then 608 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) 609 else 610 _filedir 611 fi 612 return 0 613 ;; 614 event_pipe) 615 case $prev in 616 $command) 617 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 618 return 0 619 ;; 620 id) 621 _bpftool_get_map_ids_for_type perf_event_array 622 return 0 623 ;; 624 cpu) 625 return 0 626 ;; 627 index) 628 return 0 629 ;; 630 *) 631 _bpftool_once_attr 'cpu' 632 _bpftool_once_attr 'index' 633 return 0 634 ;; 635 esac 636 ;; 637 *) 638 [[ $prev == $object ]] && \ 639 COMPREPLY=( $( compgen -W 'delete dump getnext help \ 640 lookup pin event_pipe show list update create \ 641 peek push enqueue pop dequeue freeze' -- \ 642 "$cur" ) ) 643 ;; 644 esac 645 ;; 646 btf) 647 local PROG_TYPE='id pinned tag' 648 local MAP_TYPE='id pinned' 649 case $command in 650 dump) 651 case $prev in 652 $command) 653 COMPREPLY+=( $( compgen -W "id map prog file" -- \ 654 "$cur" ) ) 655 return 0 656 ;; 657 prog) 658 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) 659 return 0 660 ;; 661 map) 662 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 663 return 0 664 ;; 665 id) 666 case $pprev in 667 prog) 668 _bpftool_get_prog_ids 669 ;; 670 map) 671 _bpftool_get_map_ids 672 ;; 673 $command) 674 _bpftool_get_btf_ids 675 ;; 676 esac 677 return 0 678 ;; 679 format) 680 COMPREPLY=( $( compgen -W "c raw" -- "$cur" ) ) 681 ;; 682 *) 683 # emit extra options 684 case ${words[3]} in 685 id|file) 686 _bpftool_once_attr 'format' 687 ;; 688 map|prog) 689 if [[ ${words[3]} == "map" ]] && [[ $cword == 6 ]]; then 690 COMPREPLY+=( $( compgen -W "key value kv all" -- "$cur" ) ) 691 fi 692 _bpftool_once_attr 'format' 693 ;; 694 *) 695 ;; 696 esac 697 return 0 698 ;; 699 esac 700 ;; 701 show|list) 702 case $prev in 703 $command) 704 COMPREPLY+=( $( compgen -W "id" -- "$cur" ) ) 705 ;; 706 id) 707 _bpftool_get_btf_ids 708 ;; 709 esac 710 return 0 711 ;; 712 *) 713 [[ $prev == $object ]] && \ 714 COMPREPLY=( $( compgen -W 'dump help show list' \ 715 -- "$cur" ) ) 716 ;; 717 esac 718 ;; 719 cgroup) 720 case $command in 721 show|list|tree) 722 case $cword in 723 3) 724 _filedir 725 ;; 726 4) 727 COMPREPLY=( $( compgen -W 'effective' -- "$cur" ) ) 728 ;; 729 esac 730 return 0 731 ;; 732 attach|detach) 733 local ATTACH_TYPES='ingress egress sock_create sock_ops \ 734 device bind4 bind6 post_bind4 post_bind6 connect4 \ 735 connect6 sendmsg4 sendmsg6 recvmsg4 recvmsg6 sysctl \ 736 getsockopt setsockopt' 737 local ATTACH_FLAGS='multi override' 738 local PROG_TYPE='id pinned tag' 739 case $prev in 740 $command) 741 _filedir 742 return 0 743 ;; 744 ingress|egress|sock_create|sock_ops|device|bind4|bind6|\ 745 post_bind4|post_bind6|connect4|connect6|sendmsg4|\ 746 sendmsg6|recvmsg4|recvmsg6|sysctl|getsockopt|\ 747 setsockopt) 748 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \ 749 "$cur" ) ) 750 return 0 751 ;; 752 id) 753 _bpftool_get_prog_ids 754 return 0 755 ;; 756 *) 757 if ! _bpftool_search_list "$ATTACH_TYPES"; then 758 COMPREPLY=( $( compgen -W "$ATTACH_TYPES" -- \ 759 "$cur" ) ) 760 elif [[ "$command" == "attach" ]]; then 761 # We have an attach type on the command line, 762 # but it is not the previous word, or 763 # "id|pinned|tag" (we already checked for 764 # that). This should only leave the case when 765 # we need attach flags for "attach" commamnd. 766 _bpftool_one_of_list "$ATTACH_FLAGS" 767 fi 768 return 0 769 ;; 770 esac 771 ;; 772 *) 773 [[ $prev == $object ]] && \ 774 COMPREPLY=( $( compgen -W 'help attach detach \ 775 show list tree' -- "$cur" ) ) 776 ;; 777 esac 778 ;; 779 perf) 780 case $command in 781 *) 782 [[ $prev == $object ]] && \ 783 COMPREPLY=( $( compgen -W 'help \ 784 show list' -- "$cur" ) ) 785 ;; 786 esac 787 ;; 788 net) 789 local PROG_TYPE='id pinned tag' 790 local ATTACH_TYPES='xdp xdpgeneric xdpdrv xdpoffload' 791 case $command in 792 show|list) 793 [[ $prev != "$command" ]] && return 0 794 COMPREPLY=( $( compgen -W 'dev' -- "$cur" ) ) 795 return 0 796 ;; 797 attach) 798 case $cword in 799 3) 800 COMPREPLY=( $( compgen -W "$ATTACH_TYPES" -- "$cur" ) ) 801 return 0 802 ;; 803 4) 804 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) 805 return 0 806 ;; 807 5) 808 case $prev in 809 id) 810 _bpftool_get_prog_ids 811 ;; 812 pinned) 813 _filedir 814 ;; 815 esac 816 return 0 817 ;; 818 6) 819 COMPREPLY=( $( compgen -W 'dev' -- "$cur" ) ) 820 return 0 821 ;; 822 8) 823 _bpftool_once_attr 'overwrite' 824 return 0 825 ;; 826 esac 827 ;; 828 detach) 829 case $cword in 830 3) 831 COMPREPLY=( $( compgen -W "$ATTACH_TYPES" -- "$cur" ) ) 832 return 0 833 ;; 834 4) 835 COMPREPLY=( $( compgen -W 'dev' -- "$cur" ) ) 836 return 0 837 ;; 838 esac 839 ;; 840 *) 841 [[ $prev == $object ]] && \ 842 COMPREPLY=( $( compgen -W 'help \ 843 show list attach detach' -- "$cur" ) ) 844 ;; 845 esac 846 ;; 847 feature) 848 case $command in 849 probe) 850 [[ $prev == "prefix" ]] && return 0 851 if _bpftool_search_list 'macros'; then 852 COMPREPLY+=( $( compgen -W 'prefix' -- "$cur" ) ) 853 else 854 COMPREPLY+=( $( compgen -W 'macros' -- "$cur" ) ) 855 fi 856 _bpftool_one_of_list 'kernel dev' 857 return 0 858 ;; 859 *) 860 [[ $prev == $object ]] && \ 861 COMPREPLY=( $( compgen -W 'help probe' -- "$cur" ) ) 862 ;; 863 esac 864 ;; 865 esac 866} && 867complete -F _bpftool bpftool 868 869# ex: ts=4 sw=4 et filetype=sh 870