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_map_names() 63{ 64 COMPREPLY+=( $( compgen -W "$( bpftool -jp map 2>&1 | \ 65 command sed -n 's/.*"name": \(.*\),$/\1/p' )" -- "$cur" ) ) 66} 67 68# Takes map type and adds matching map names to the list of suggestions. 69_bpftool_get_map_names_for_type() 70{ 71 local type="$1" 72 COMPREPLY+=( $( compgen -W "$( bpftool -jp map 2>&1 | \ 73 command grep -C2 "$type" | \ 74 command sed -n 's/.*"name": \(.*\),$/\1/p' )" -- "$cur" ) ) 75} 76 77_bpftool_get_prog_ids() 78{ 79 COMPREPLY+=( $( compgen -W "$( bpftool -jp prog 2>&1 | \ 80 command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) ) 81} 82 83_bpftool_get_prog_tags() 84{ 85 COMPREPLY+=( $( compgen -W "$( bpftool -jp prog 2>&1 | \ 86 command sed -n 's/.*"tag": "\(.*\)",$/\1/p' )" -- "$cur" ) ) 87} 88 89_bpftool_get_prog_names() 90{ 91 COMPREPLY+=( $( compgen -W "$( bpftool -jp prog 2>&1 | \ 92 command sed -n 's/.*"name": "\(.*\)",$/\1/p' )" -- "$cur" ) ) 93} 94 95_bpftool_get_btf_ids() 96{ 97 COMPREPLY+=( $( compgen -W "$( bpftool -jp btf 2>&1 | \ 98 command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) ) 99} 100 101_bpftool_get_link_ids() 102{ 103 COMPREPLY+=( $( compgen -W "$( bpftool -jp link 2>&1 | \ 104 command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) ) 105} 106 107_bpftool_get_obj_map_names() 108{ 109 local obj 110 111 obj=$1 112 113 maps=$(objdump -j maps -t $obj 2>/dev/null | \ 114 command awk '/g . maps/ {print $NF}') 115 116 COMPREPLY+=( $( compgen -W "$maps" -- "$cur" ) ) 117} 118 119_bpftool_get_obj_map_idxs() 120{ 121 local obj 122 123 obj=$1 124 125 nmaps=$(objdump -j maps -t $obj 2>/dev/null | grep -c 'g . maps') 126 127 COMPREPLY+=( $( compgen -W "$(seq 0 $((nmaps - 1)))" -- "$cur" ) ) 128} 129 130_sysfs_get_netdevs() 131{ 132 COMPREPLY+=( $( compgen -W "$( ls /sys/class/net 2>/dev/null )" -- \ 133 "$cur" ) ) 134} 135 136# Retrieve type of the map that we are operating on. 137_bpftool_map_guess_map_type() 138{ 139 local keyword ref 140 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do 141 case "${words[$((idx-2))]}" in 142 lookup|update) 143 keyword=${words[$((idx-1))]} 144 ref=${words[$((idx))]} 145 ;; 146 push) 147 printf "stack" 148 return 0 149 ;; 150 enqueue) 151 printf "queue" 152 return 0 153 ;; 154 esac 155 done 156 [[ -z $ref ]] && return 0 157 158 local type 159 type=$(bpftool -jp map show $keyword $ref | \ 160 command sed -n 's/.*"type": "\(.*\)",$/\1/p') 161 [[ -n $type ]] && printf $type 162} 163 164_bpftool_map_update_get_id() 165{ 166 local command="$1" 167 168 # Is it the map to update, or a map to insert into the map to update? 169 # Search for "value" keyword. 170 local idx value 171 for (( idx=7; idx < ${#words[@]}-1; idx++ )); do 172 if [[ ${words[idx]} == "value" ]]; then 173 value=1 174 break 175 fi 176 done 177 if [[ $value -eq 0 ]]; then 178 case "$command" in 179 push) 180 _bpftool_get_map_ids_for_type stack 181 ;; 182 enqueue) 183 _bpftool_get_map_ids_for_type queue 184 ;; 185 *) 186 _bpftool_get_map_ids 187 ;; 188 esac 189 return 0 190 fi 191 192 # Id to complete is for a value. It can be either prog id or map id. This 193 # depends on the type of the map to update. 194 local type=$(_bpftool_map_guess_map_type) 195 case $type in 196 array_of_maps|hash_of_maps) 197 _bpftool_get_map_ids 198 return 0 199 ;; 200 prog_array) 201 _bpftool_get_prog_ids 202 return 0 203 ;; 204 *) 205 return 0 206 ;; 207 esac 208} 209 210_bpftool_map_update_get_name() 211{ 212 local command="$1" 213 214 # Is it the map to update, or a map to insert into the map to update? 215 # Search for "value" keyword. 216 local idx value 217 for (( idx=7; idx < ${#words[@]}-1; idx++ )); do 218 if [[ ${words[idx]} == "value" ]]; then 219 value=1 220 break 221 fi 222 done 223 if [[ $value -eq 0 ]]; then 224 case "$command" in 225 push) 226 _bpftool_get_map_names_for_type stack 227 ;; 228 enqueue) 229 _bpftool_get_map_names_for_type queue 230 ;; 231 *) 232 _bpftool_get_map_names 233 ;; 234 esac 235 return 0 236 fi 237 238 # Name to complete is for a value. It can be either prog name or map name. This 239 # depends on the type of the map to update. 240 local type=$(_bpftool_map_guess_map_type) 241 case $type in 242 array_of_maps|hash_of_maps) 243 _bpftool_get_map_names 244 return 0 245 ;; 246 prog_array) 247 _bpftool_get_prog_names 248 return 0 249 ;; 250 *) 251 return 0 252 ;; 253 esac 254} 255 256_bpftool() 257{ 258 local cur prev words objword json=0 259 _init_completion || return 260 261 # Deal with options 262 if [[ ${words[cword]} == -* ]]; then 263 local c='--version --json --pretty --bpffs --mapcompat --debug \ 264 --use-loader --base-btf' 265 COMPREPLY=( $( compgen -W "$c" -- "$cur" ) ) 266 return 0 267 fi 268 if _bpftool_search_list -j --json -p --pretty; then 269 json=1 270 fi 271 272 # Deal with simplest keywords 273 case $prev in 274 help|hex) 275 return 0 276 ;; 277 tag) 278 _bpftool_get_prog_tags 279 return 0 280 ;; 281 dev|offload_dev|xdpmeta_dev) 282 _sysfs_get_netdevs 283 return 0 284 ;; 285 file|pinned|-B|--base-btf) 286 _filedir 287 return 0 288 ;; 289 batch) 290 COMPREPLY=( $( compgen -W 'file' -- "$cur" ) ) 291 return 0 292 ;; 293 esac 294 295 # Remove all options so completions don't have to deal with them. 296 local i 297 for (( i=1; i < ${#words[@]}; )); do 298 if [[ ${words[i]::1} == - ]] && 299 [[ ${words[i]} != "-B" ]] && [[ ${words[i]} != "--base-btf" ]]; then 300 words=( "${words[@]:0:i}" "${words[@]:i+1}" ) 301 [[ $i -le $cword ]] && cword=$(( cword - 1 )) 302 else 303 i=$(( ++i )) 304 fi 305 done 306 cur=${words[cword]} 307 prev=${words[cword - 1]} 308 pprev=${words[cword - 2]} 309 310 local object=${words[1]} command=${words[2]} 311 312 if [[ -z $object || $cword -eq 1 ]]; then 313 case $cur in 314 *) 315 COMPREPLY=( $( compgen -W "$( bpftool help 2>&1 | \ 316 command sed \ 317 -e '/OBJECT := /!d' \ 318 -e 's/.*{//' \ 319 -e 's/}.*//' \ 320 -e 's/|//g' )" -- "$cur" ) ) 321 COMPREPLY+=( $( compgen -W 'batch help' -- "$cur" ) ) 322 return 0 323 ;; 324 esac 325 fi 326 327 [[ $command == help ]] && return 0 328 329 # Completion depends on object and command in use 330 case $object in 331 prog) 332 # Complete id and name, only for subcommands that use prog (but no 333 # map) ids/names. 334 case $command in 335 show|list|dump|pin) 336 case $prev in 337 id) 338 _bpftool_get_prog_ids 339 return 0 340 ;; 341 name) 342 _bpftool_get_prog_names 343 return 0 344 ;; 345 esac 346 ;; 347 esac 348 349 local PROG_TYPE='id pinned tag name' 350 local MAP_TYPE='id pinned name' 351 local METRIC_TYPE='cycles instructions l1d_loads llc_misses \ 352 itlb_misses dtlb_misses' 353 case $command in 354 show|list) 355 [[ $prev != "$command" ]] && return 0 356 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) 357 return 0 358 ;; 359 dump) 360 case $prev in 361 $command) 362 COMPREPLY+=( $( compgen -W "xlated jited" -- \ 363 "$cur" ) ) 364 return 0 365 ;; 366 xlated|jited) 367 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \ 368 "$cur" ) ) 369 return 0 370 ;; 371 *) 372 # "file" is not compatible with other keywords here 373 if _bpftool_search_list 'file'; then 374 return 0 375 fi 376 if ! _bpftool_search_list 'linum opcodes visual'; then 377 _bpftool_once_attr 'file' 378 fi 379 _bpftool_once_attr 'linum opcodes' 380 if _bpftool_search_list 'xlated' && [[ "$json" == 0 ]]; then 381 _bpftool_once_attr 'visual' 382 fi 383 return 0 384 ;; 385 esac 386 ;; 387 pin) 388 if [[ $prev == "$command" ]]; then 389 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) 390 else 391 _filedir 392 fi 393 return 0 394 ;; 395 attach|detach) 396 case $cword in 397 3) 398 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) 399 return 0 400 ;; 401 4) 402 case $prev in 403 id) 404 _bpftool_get_prog_ids 405 ;; 406 name) 407 _bpftool_get_prog_names 408 ;; 409 pinned) 410 _filedir 411 ;; 412 esac 413 return 0 414 ;; 415 5) 416 local BPFTOOL_PROG_ATTACH_TYPES='sk_msg_verdict \ 417 sk_skb_verdict sk_skb_stream_verdict sk_skb_stream_parser \ 418 flow_dissector' 419 COMPREPLY=( $( compgen -W "$BPFTOOL_PROG_ATTACH_TYPES" -- "$cur" ) ) 420 return 0 421 ;; 422 6) 423 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 424 return 0 425 ;; 426 7) 427 case $prev in 428 id) 429 _bpftool_get_map_ids 430 ;; 431 name) 432 _bpftool_get_map_names 433 ;; 434 pinned) 435 _filedir 436 ;; 437 esac 438 return 0 439 ;; 440 esac 441 ;; 442 load|loadall) 443 local obj 444 445 # Propose "load/loadall" to complete "bpftool prog load", 446 # or bash tries to complete "load" as a filename below. 447 if [[ ${#words[@]} -eq 3 ]]; then 448 COMPREPLY=( $( compgen -W "load loadall" -- "$cur" ) ) 449 return 0 450 fi 451 452 if [[ ${#words[@]} -lt 6 ]]; then 453 _filedir 454 return 0 455 fi 456 457 obj=${words[3]} 458 459 if [[ ${words[-4]} == "map" ]]; then 460 COMPREPLY=( $( compgen -W "id pinned" -- "$cur" ) ) 461 return 0 462 fi 463 if [[ ${words[-3]} == "map" ]]; then 464 if [[ ${words[-2]} == "idx" ]]; then 465 _bpftool_get_obj_map_idxs $obj 466 elif [[ ${words[-2]} == "name" ]]; then 467 _bpftool_get_obj_map_names $obj 468 fi 469 return 0 470 fi 471 if [[ ${words[-2]} == "map" ]]; then 472 COMPREPLY=( $( compgen -W "idx name" -- "$cur" ) ) 473 return 0 474 fi 475 476 case $prev in 477 type) 478 local BPFTOOL_PROG_LOAD_TYPES='socket kprobe \ 479 kretprobe classifier flow_dissector \ 480 action tracepoint raw_tracepoint \ 481 xdp perf_event cgroup/skb cgroup/sock \ 482 cgroup/dev lwt_in lwt_out lwt_xmit \ 483 lwt_seg6local sockops sk_skb sk_msg \ 484 lirc_mode2 cgroup/bind4 cgroup/bind6 \ 485 cgroup/connect4 cgroup/connect6 \ 486 cgroup/getpeername4 cgroup/getpeername6 \ 487 cgroup/getsockname4 cgroup/getsockname6 \ 488 cgroup/sendmsg4 cgroup/sendmsg6 \ 489 cgroup/recvmsg4 cgroup/recvmsg6 \ 490 cgroup/post_bind4 cgroup/post_bind6 \ 491 cgroup/sysctl cgroup/getsockopt \ 492 cgroup/setsockopt cgroup/sock_release struct_ops \ 493 fentry fexit freplace sk_lookup' 494 COMPREPLY=( $( compgen -W "$BPFTOOL_PROG_LOAD_TYPES" -- "$cur" ) ) 495 return 0 496 ;; 497 id) 498 _bpftool_get_map_ids 499 return 0 500 ;; 501 name) 502 _bpftool_get_map_names 503 return 0 504 ;; 505 pinned|pinmaps) 506 _filedir 507 return 0 508 ;; 509 *) 510 COMPREPLY=( $( compgen -W "map" -- "$cur" ) ) 511 _bpftool_once_attr 'type pinmaps autoattach' 512 _bpftool_one_of_list 'offload_dev xdpmeta_dev' 513 return 0 514 ;; 515 esac 516 ;; 517 tracelog) 518 return 0 519 ;; 520 profile) 521 case $cword in 522 3) 523 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) 524 return 0 525 ;; 526 4) 527 case $prev in 528 id) 529 _bpftool_get_prog_ids 530 ;; 531 name) 532 _bpftool_get_prog_names 533 ;; 534 pinned) 535 _filedir 536 ;; 537 esac 538 return 0 539 ;; 540 5) 541 COMPREPLY=( $( compgen -W "$METRIC_TYPE duration" -- "$cur" ) ) 542 return 0 543 ;; 544 6) 545 case $prev in 546 duration) 547 return 0 548 ;; 549 *) 550 COMPREPLY=( $( compgen -W "$METRIC_TYPE" -- "$cur" ) ) 551 return 0 552 ;; 553 esac 554 return 0 555 ;; 556 *) 557 COMPREPLY=( $( compgen -W "$METRIC_TYPE" -- "$cur" ) ) 558 return 0 559 ;; 560 esac 561 ;; 562 run) 563 if [[ ${#words[@]} -eq 4 ]]; then 564 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) 565 return 0 566 fi 567 case $prev in 568 id) 569 _bpftool_get_prog_ids 570 return 0 571 ;; 572 name) 573 _bpftool_get_prog_names 574 return 0 575 ;; 576 data_in|data_out|ctx_in|ctx_out) 577 _filedir 578 return 0 579 ;; 580 repeat|data_size_out|ctx_size_out) 581 return 0 582 ;; 583 *) 584 _bpftool_once_attr 'data_in data_out data_size_out \ 585 ctx_in ctx_out ctx_size_out repeat' 586 return 0 587 ;; 588 esac 589 ;; 590 *) 591 [[ $prev == $object ]] && \ 592 COMPREPLY=( $( compgen -W 'dump help pin attach detach \ 593 load loadall show list tracelog run profile' -- "$cur" ) ) 594 ;; 595 esac 596 ;; 597 struct_ops) 598 local STRUCT_OPS_TYPE='id name' 599 case $command in 600 show|list|dump|unregister) 601 case $prev in 602 $command) 603 COMPREPLY=( $( compgen -W "$STRUCT_OPS_TYPE" -- "$cur" ) ) 604 ;; 605 id) 606 _bpftool_get_map_ids_for_type struct_ops 607 ;; 608 name) 609 _bpftool_get_map_names_for_type struct_ops 610 ;; 611 esac 612 return 0 613 ;; 614 register) 615 _filedir 616 return 0 617 ;; 618 *) 619 [[ $prev == $object ]] && \ 620 COMPREPLY=( $( compgen -W 'register unregister show list dump help' \ 621 -- "$cur" ) ) 622 ;; 623 esac 624 ;; 625 iter) 626 case $command in 627 pin) 628 case $prev in 629 $command) 630 _filedir 631 ;; 632 id) 633 _bpftool_get_map_ids 634 ;; 635 name) 636 _bpftool_get_map_names 637 ;; 638 pinned) 639 _filedir 640 ;; 641 *) 642 _bpftool_one_of_list $MAP_TYPE 643 ;; 644 esac 645 return 0 646 ;; 647 *) 648 [[ $prev == $object ]] && \ 649 COMPREPLY=( $( compgen -W 'pin help' \ 650 -- "$cur" ) ) 651 ;; 652 esac 653 ;; 654 map) 655 local MAP_TYPE='id pinned name' 656 case $command in 657 show|list|dump|peek|pop|dequeue|freeze) 658 case $prev in 659 $command) 660 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 661 return 0 662 ;; 663 id) 664 case "$command" in 665 peek) 666 _bpftool_get_map_ids_for_type stack 667 _bpftool_get_map_ids_for_type queue 668 ;; 669 pop) 670 _bpftool_get_map_ids_for_type stack 671 ;; 672 dequeue) 673 _bpftool_get_map_ids_for_type queue 674 ;; 675 *) 676 _bpftool_get_map_ids 677 ;; 678 esac 679 return 0 680 ;; 681 name) 682 case "$command" in 683 peek) 684 _bpftool_get_map_names_for_type stack 685 _bpftool_get_map_names_for_type queue 686 ;; 687 pop) 688 _bpftool_get_map_names_for_type stack 689 ;; 690 dequeue) 691 _bpftool_get_map_names_for_type queue 692 ;; 693 *) 694 _bpftool_get_map_names 695 ;; 696 esac 697 return 0 698 ;; 699 *) 700 return 0 701 ;; 702 esac 703 ;; 704 create) 705 case $prev in 706 $command) 707 _filedir 708 return 0 709 ;; 710 type) 711 local BPFTOOL_MAP_CREATE_TYPES="$(bpftool feature list_builtins map_types 2>/dev/null | \ 712 grep -v '^unspec$')" 713 COMPREPLY=( $( compgen -W "$BPFTOOL_MAP_CREATE_TYPES" -- "$cur" ) ) 714 return 0 715 ;; 716 key|value|flags|entries) 717 return 0 718 ;; 719 inner_map) 720 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 721 return 0 722 ;; 723 id) 724 _bpftool_get_map_ids 725 ;; 726 name) 727 case $pprev in 728 inner_map) 729 _bpftool_get_map_names 730 ;; 731 *) 732 return 0 733 ;; 734 esac 735 ;; 736 *) 737 _bpftool_once_attr 'type key value entries name flags offload_dev' 738 if _bpftool_search_list 'array_of_maps' 'hash_of_maps'; then 739 _bpftool_once_attr 'inner_map' 740 fi 741 return 0 742 ;; 743 esac 744 ;; 745 lookup|getnext|delete) 746 case $prev in 747 $command) 748 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 749 return 0 750 ;; 751 id) 752 _bpftool_get_map_ids 753 return 0 754 ;; 755 name) 756 _bpftool_get_map_names 757 return 0 758 ;; 759 key) 760 COMPREPLY+=( $( compgen -W 'hex' -- "$cur" ) ) 761 ;; 762 *) 763 case $(_bpftool_map_guess_map_type) in 764 queue|stack) 765 return 0 766 ;; 767 esac 768 769 _bpftool_once_attr 'key' 770 return 0 771 ;; 772 esac 773 ;; 774 update|push|enqueue) 775 case $prev in 776 $command) 777 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 778 return 0 779 ;; 780 id) 781 _bpftool_map_update_get_id $command 782 return 0 783 ;; 784 name) 785 _bpftool_map_update_get_name $command 786 return 0 787 ;; 788 key) 789 COMPREPLY+=( $( compgen -W 'hex' -- "$cur" ) ) 790 ;; 791 value) 792 # We can have bytes, or references to a prog or a 793 # map, depending on the type of the map to update. 794 case "$(_bpftool_map_guess_map_type)" in 795 array_of_maps|hash_of_maps) 796 local MAP_TYPE='id pinned name' 797 COMPREPLY+=( $( compgen -W "$MAP_TYPE" \ 798 -- "$cur" ) ) 799 return 0 800 ;; 801 prog_array) 802 local PROG_TYPE='id pinned tag name' 803 COMPREPLY+=( $( compgen -W "$PROG_TYPE" \ 804 -- "$cur" ) ) 805 return 0 806 ;; 807 *) 808 COMPREPLY+=( $( compgen -W 'hex' \ 809 -- "$cur" ) ) 810 return 0 811 ;; 812 esac 813 return 0 814 ;; 815 *) 816 case $(_bpftool_map_guess_map_type) in 817 queue|stack) 818 _bpftool_once_attr 'value' 819 return 0; 820 ;; 821 esac 822 823 _bpftool_once_attr 'key' 824 local UPDATE_FLAGS='any exist noexist' 825 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do 826 if [[ ${words[idx]} == 'value' ]]; then 827 # 'value' is present, but is not the last 828 # word i.e. we can now have UPDATE_FLAGS. 829 _bpftool_one_of_list "$UPDATE_FLAGS" 830 return 0 831 fi 832 done 833 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do 834 if [[ ${words[idx]} == 'key' ]]; then 835 # 'key' is present, but is not the last 836 # word i.e. we can now have 'value'. 837 _bpftool_once_attr 'value' 838 return 0 839 fi 840 done 841 842 return 0 843 ;; 844 esac 845 ;; 846 pin) 847 case $prev in 848 $command) 849 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 850 ;; 851 id) 852 _bpftool_get_map_ids 853 ;; 854 name) 855 _bpftool_get_map_names 856 ;; 857 esac 858 return 0 859 ;; 860 event_pipe) 861 case $prev in 862 $command) 863 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 864 return 0 865 ;; 866 id) 867 _bpftool_get_map_ids_for_type perf_event_array 868 return 0 869 ;; 870 name) 871 _bpftool_get_map_names_for_type perf_event_array 872 return 0 873 ;; 874 cpu) 875 return 0 876 ;; 877 index) 878 return 0 879 ;; 880 *) 881 _bpftool_once_attr 'cpu index' 882 return 0 883 ;; 884 esac 885 ;; 886 *) 887 [[ $prev == $object ]] && \ 888 COMPREPLY=( $( compgen -W 'delete dump getnext help \ 889 lookup pin event_pipe show list update create \ 890 peek push enqueue pop dequeue freeze' -- \ 891 "$cur" ) ) 892 ;; 893 esac 894 ;; 895 btf) 896 local PROG_TYPE='id pinned tag name' 897 local MAP_TYPE='id pinned name' 898 case $command in 899 dump) 900 case $prev in 901 $command) 902 COMPREPLY+=( $( compgen -W "id map prog file" -- \ 903 "$cur" ) ) 904 return 0 905 ;; 906 prog) 907 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) 908 return 0 909 ;; 910 map) 911 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 912 return 0 913 ;; 914 id) 915 case $pprev in 916 prog) 917 _bpftool_get_prog_ids 918 ;; 919 map) 920 _bpftool_get_map_ids 921 ;; 922 $command) 923 _bpftool_get_btf_ids 924 ;; 925 esac 926 return 0 927 ;; 928 name) 929 case $pprev in 930 prog) 931 _bpftool_get_prog_names 932 ;; 933 map) 934 _bpftool_get_map_names 935 ;; 936 esac 937 return 0 938 ;; 939 format) 940 COMPREPLY=( $( compgen -W "c raw" -- "$cur" ) ) 941 ;; 942 *) 943 # emit extra options 944 case ${words[3]} in 945 id|file) 946 _bpftool_once_attr 'format' 947 ;; 948 map|prog) 949 if [[ ${words[3]} == "map" ]] && [[ $cword == 6 ]]; then 950 COMPREPLY+=( $( compgen -W "key value kv all" -- "$cur" ) ) 951 fi 952 _bpftool_once_attr 'format' 953 ;; 954 *) 955 ;; 956 esac 957 return 0 958 ;; 959 esac 960 ;; 961 show|list) 962 case $prev in 963 $command) 964 COMPREPLY+=( $( compgen -W "id" -- "$cur" ) ) 965 ;; 966 id) 967 _bpftool_get_btf_ids 968 ;; 969 esac 970 return 0 971 ;; 972 *) 973 [[ $prev == $object ]] && \ 974 COMPREPLY=( $( compgen -W 'dump help show list' \ 975 -- "$cur" ) ) 976 ;; 977 esac 978 ;; 979 gen) 980 case $command in 981 object) 982 _filedir 983 return 0 984 ;; 985 skeleton) 986 case $prev in 987 $command) 988 _filedir 989 return 0 990 ;; 991 *) 992 _bpftool_once_attr 'name' 993 return 0 994 ;; 995 esac 996 ;; 997 subskeleton) 998 case $prev in 999 $command) 1000 _filedir 1001 return 0 1002 ;; 1003 *) 1004 _bpftool_once_attr 'name' 1005 return 0 1006 ;; 1007 esac 1008 ;; 1009 min_core_btf) 1010 _filedir 1011 return 0 1012 ;; 1013 *) 1014 [[ $prev == $object ]] && \ 1015 COMPREPLY=( $( compgen -W 'object skeleton subskeleton help min_core_btf' -- "$cur" ) ) 1016 ;; 1017 esac 1018 ;; 1019 cgroup) 1020 case $command in 1021 show|list|tree) 1022 case $cword in 1023 3) 1024 _filedir 1025 ;; 1026 4) 1027 COMPREPLY=( $( compgen -W 'effective' -- "$cur" ) ) 1028 ;; 1029 esac 1030 return 0 1031 ;; 1032 attach|detach) 1033 local BPFTOOL_CGROUP_ATTACH_TYPES="$(bpftool feature list_builtins attach_types 2>/dev/null | \ 1034 grep '^cgroup_')" 1035 local ATTACH_FLAGS='multi override' 1036 local PROG_TYPE='id pinned tag name' 1037 # Check for $prev = $command first 1038 if [ $prev = $command ]; then 1039 _filedir 1040 return 0 1041 # Then check for attach type. This is done outside of the 1042 # "case $prev in" to avoid writing the whole list of attach 1043 # types again as pattern to match (where we cannot reuse 1044 # our variable). 1045 elif [[ $BPFTOOL_CGROUP_ATTACH_TYPES =~ $prev ]]; then 1046 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \ 1047 "$cur" ) ) 1048 return 0 1049 fi 1050 # case/esac for the other cases 1051 case $prev in 1052 id) 1053 _bpftool_get_prog_ids 1054 return 0 1055 ;; 1056 *) 1057 if ! _bpftool_search_list "$BPFTOOL_CGROUP_ATTACH_TYPES"; then 1058 COMPREPLY=( $( compgen -W \ 1059 "$BPFTOOL_CGROUP_ATTACH_TYPES" -- "$cur" ) ) 1060 elif [[ "$command" == "attach" ]]; then 1061 # We have an attach type on the command line, 1062 # but it is not the previous word, or 1063 # "id|pinned|tag|name" (we already checked for 1064 # that). This should only leave the case when 1065 # we need attach flags for "attach" commamnd. 1066 _bpftool_one_of_list "$ATTACH_FLAGS" 1067 fi 1068 return 0 1069 ;; 1070 esac 1071 ;; 1072 *) 1073 [[ $prev == $object ]] && \ 1074 COMPREPLY=( $( compgen -W 'help attach detach \ 1075 show list tree' -- "$cur" ) ) 1076 ;; 1077 esac 1078 ;; 1079 perf) 1080 case $command in 1081 *) 1082 [[ $prev == $object ]] && \ 1083 COMPREPLY=( $( compgen -W 'help \ 1084 show list' -- "$cur" ) ) 1085 ;; 1086 esac 1087 ;; 1088 net) 1089 local PROG_TYPE='id pinned tag name' 1090 local ATTACH_TYPES='xdp xdpgeneric xdpdrv xdpoffload' 1091 case $command in 1092 show|list) 1093 [[ $prev != "$command" ]] && return 0 1094 COMPREPLY=( $( compgen -W 'dev' -- "$cur" ) ) 1095 return 0 1096 ;; 1097 attach) 1098 case $cword in 1099 3) 1100 COMPREPLY=( $( compgen -W "$ATTACH_TYPES" -- "$cur" ) ) 1101 return 0 1102 ;; 1103 4) 1104 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) 1105 return 0 1106 ;; 1107 5) 1108 case $prev in 1109 id) 1110 _bpftool_get_prog_ids 1111 ;; 1112 name) 1113 _bpftool_get_prog_names 1114 ;; 1115 pinned) 1116 _filedir 1117 ;; 1118 esac 1119 return 0 1120 ;; 1121 6) 1122 COMPREPLY=( $( compgen -W 'dev' -- "$cur" ) ) 1123 return 0 1124 ;; 1125 8) 1126 _bpftool_once_attr 'overwrite' 1127 return 0 1128 ;; 1129 esac 1130 ;; 1131 detach) 1132 case $cword in 1133 3) 1134 COMPREPLY=( $( compgen -W "$ATTACH_TYPES" -- "$cur" ) ) 1135 return 0 1136 ;; 1137 4) 1138 COMPREPLY=( $( compgen -W 'dev' -- "$cur" ) ) 1139 return 0 1140 ;; 1141 esac 1142 ;; 1143 *) 1144 [[ $prev == $object ]] && \ 1145 COMPREPLY=( $( compgen -W 'help \ 1146 show list attach detach' -- "$cur" ) ) 1147 ;; 1148 esac 1149 ;; 1150 feature) 1151 case $command in 1152 probe) 1153 [[ $prev == "prefix" ]] && return 0 1154 if _bpftool_search_list 'macros'; then 1155 _bpftool_once_attr 'prefix' 1156 else 1157 COMPREPLY+=( $( compgen -W 'macros' -- "$cur" ) ) 1158 fi 1159 _bpftool_one_of_list 'kernel dev' 1160 _bpftool_once_attr 'full unprivileged' 1161 return 0 1162 ;; 1163 list_builtins) 1164 [[ $prev != "$command" ]] && return 0 1165 COMPREPLY=( $( compgen -W 'prog_types map_types \ 1166 attach_types link_types helpers' -- "$cur" ) ) 1167 ;; 1168 *) 1169 [[ $prev == $object ]] && \ 1170 COMPREPLY=( $( compgen -W 'help list_builtins probe' -- "$cur" ) ) 1171 ;; 1172 esac 1173 ;; 1174 link) 1175 case $command in 1176 show|list|pin|detach) 1177 case $prev in 1178 id) 1179 _bpftool_get_link_ids 1180 return 0 1181 ;; 1182 esac 1183 ;; 1184 esac 1185 1186 local LINK_TYPE='id pinned' 1187 case $command in 1188 show|list) 1189 [[ $prev != "$command" ]] && return 0 1190 COMPREPLY=( $( compgen -W "$LINK_TYPE" -- "$cur" ) ) 1191 return 0 1192 ;; 1193 pin|detach) 1194 if [[ $prev == "$command" ]]; then 1195 COMPREPLY=( $( compgen -W "$LINK_TYPE" -- "$cur" ) ) 1196 else 1197 _filedir 1198 fi 1199 return 0 1200 ;; 1201 *) 1202 [[ $prev == $object ]] && \ 1203 COMPREPLY=( $( compgen -W 'help pin show list' -- "$cur" ) ) 1204 ;; 1205 esac 1206 ;; 1207 esac 1208} && 1209complete -F _bpftool bpftool 1210 1211# ex: ts=4 sw=4 et filetype=sh 1212