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) 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 dev pinmaps autoattach' 512 return 0 513 ;; 514 esac 515 ;; 516 tracelog) 517 return 0 518 ;; 519 profile) 520 case $cword in 521 3) 522 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) 523 return 0 524 ;; 525 4) 526 case $prev in 527 id) 528 _bpftool_get_prog_ids 529 ;; 530 name) 531 _bpftool_get_prog_names 532 ;; 533 pinned) 534 _filedir 535 ;; 536 esac 537 return 0 538 ;; 539 5) 540 COMPREPLY=( $( compgen -W "$METRIC_TYPE duration" -- "$cur" ) ) 541 return 0 542 ;; 543 6) 544 case $prev in 545 duration) 546 return 0 547 ;; 548 *) 549 COMPREPLY=( $( compgen -W "$METRIC_TYPE" -- "$cur" ) ) 550 return 0 551 ;; 552 esac 553 return 0 554 ;; 555 *) 556 COMPREPLY=( $( compgen -W "$METRIC_TYPE" -- "$cur" ) ) 557 return 0 558 ;; 559 esac 560 ;; 561 run) 562 if [[ ${#words[@]} -eq 4 ]]; then 563 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) 564 return 0 565 fi 566 case $prev in 567 id) 568 _bpftool_get_prog_ids 569 return 0 570 ;; 571 name) 572 _bpftool_get_prog_names 573 return 0 574 ;; 575 data_in|data_out|ctx_in|ctx_out) 576 _filedir 577 return 0 578 ;; 579 repeat|data_size_out|ctx_size_out) 580 return 0 581 ;; 582 *) 583 _bpftool_once_attr 'data_in data_out data_size_out \ 584 ctx_in ctx_out ctx_size_out repeat' 585 return 0 586 ;; 587 esac 588 ;; 589 *) 590 [[ $prev == $object ]] && \ 591 COMPREPLY=( $( compgen -W 'dump help pin attach detach \ 592 load loadall show list tracelog run profile' -- "$cur" ) ) 593 ;; 594 esac 595 ;; 596 struct_ops) 597 local STRUCT_OPS_TYPE='id name' 598 case $command in 599 show|list|dump|unregister) 600 case $prev in 601 $command) 602 COMPREPLY=( $( compgen -W "$STRUCT_OPS_TYPE" -- "$cur" ) ) 603 ;; 604 id) 605 _bpftool_get_map_ids_for_type struct_ops 606 ;; 607 name) 608 _bpftool_get_map_names_for_type struct_ops 609 ;; 610 esac 611 return 0 612 ;; 613 register) 614 _filedir 615 return 0 616 ;; 617 *) 618 [[ $prev == $object ]] && \ 619 COMPREPLY=( $( compgen -W 'register unregister show list dump help' \ 620 -- "$cur" ) ) 621 ;; 622 esac 623 ;; 624 iter) 625 case $command in 626 pin) 627 case $prev in 628 $command) 629 _filedir 630 ;; 631 id) 632 _bpftool_get_map_ids 633 ;; 634 name) 635 _bpftool_get_map_names 636 ;; 637 pinned) 638 _filedir 639 ;; 640 *) 641 _bpftool_one_of_list $MAP_TYPE 642 ;; 643 esac 644 return 0 645 ;; 646 *) 647 [[ $prev == $object ]] && \ 648 COMPREPLY=( $( compgen -W 'pin help' \ 649 -- "$cur" ) ) 650 ;; 651 esac 652 ;; 653 map) 654 local MAP_TYPE='id pinned name' 655 case $command in 656 show|list|dump|peek|pop|dequeue|freeze) 657 case $prev in 658 $command) 659 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 660 return 0 661 ;; 662 id) 663 case "$command" in 664 peek) 665 _bpftool_get_map_ids_for_type stack 666 _bpftool_get_map_ids_for_type queue 667 ;; 668 pop) 669 _bpftool_get_map_ids_for_type stack 670 ;; 671 dequeue) 672 _bpftool_get_map_ids_for_type queue 673 ;; 674 *) 675 _bpftool_get_map_ids 676 ;; 677 esac 678 return 0 679 ;; 680 name) 681 case "$command" in 682 peek) 683 _bpftool_get_map_names_for_type stack 684 _bpftool_get_map_names_for_type queue 685 ;; 686 pop) 687 _bpftool_get_map_names_for_type stack 688 ;; 689 dequeue) 690 _bpftool_get_map_names_for_type queue 691 ;; 692 *) 693 _bpftool_get_map_names 694 ;; 695 esac 696 return 0 697 ;; 698 *) 699 return 0 700 ;; 701 esac 702 ;; 703 create) 704 case $prev in 705 $command) 706 _filedir 707 return 0 708 ;; 709 type) 710 local BPFTOOL_MAP_CREATE_TYPES="$(bpftool feature list_builtins map_types 2>/dev/null | \ 711 grep -v '^unspec$')" 712 COMPREPLY=( $( compgen -W "$BPFTOOL_MAP_CREATE_TYPES" -- "$cur" ) ) 713 return 0 714 ;; 715 key|value|flags|entries) 716 return 0 717 ;; 718 inner_map) 719 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 720 return 0 721 ;; 722 id) 723 _bpftool_get_map_ids 724 ;; 725 name) 726 case $pprev in 727 inner_map) 728 _bpftool_get_map_names 729 ;; 730 *) 731 return 0 732 ;; 733 esac 734 ;; 735 *) 736 _bpftool_once_attr 'type key value entries name flags dev' 737 if _bpftool_search_list 'array_of_maps' 'hash_of_maps'; then 738 _bpftool_once_attr 'inner_map' 739 fi 740 return 0 741 ;; 742 esac 743 ;; 744 lookup|getnext|delete) 745 case $prev in 746 $command) 747 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 748 return 0 749 ;; 750 id) 751 _bpftool_get_map_ids 752 return 0 753 ;; 754 name) 755 _bpftool_get_map_names 756 return 0 757 ;; 758 key) 759 COMPREPLY+=( $( compgen -W 'hex' -- "$cur" ) ) 760 ;; 761 *) 762 case $(_bpftool_map_guess_map_type) in 763 queue|stack) 764 return 0 765 ;; 766 esac 767 768 _bpftool_once_attr 'key' 769 return 0 770 ;; 771 esac 772 ;; 773 update|push|enqueue) 774 case $prev in 775 $command) 776 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 777 return 0 778 ;; 779 id) 780 _bpftool_map_update_get_id $command 781 return 0 782 ;; 783 name) 784 _bpftool_map_update_get_name $command 785 return 0 786 ;; 787 key) 788 COMPREPLY+=( $( compgen -W 'hex' -- "$cur" ) ) 789 ;; 790 value) 791 # We can have bytes, or references to a prog or a 792 # map, depending on the type of the map to update. 793 case "$(_bpftool_map_guess_map_type)" in 794 array_of_maps|hash_of_maps) 795 local MAP_TYPE='id pinned name' 796 COMPREPLY+=( $( compgen -W "$MAP_TYPE" \ 797 -- "$cur" ) ) 798 return 0 799 ;; 800 prog_array) 801 local PROG_TYPE='id pinned tag name' 802 COMPREPLY+=( $( compgen -W "$PROG_TYPE" \ 803 -- "$cur" ) ) 804 return 0 805 ;; 806 *) 807 COMPREPLY+=( $( compgen -W 'hex' \ 808 -- "$cur" ) ) 809 return 0 810 ;; 811 esac 812 return 0 813 ;; 814 *) 815 case $(_bpftool_map_guess_map_type) in 816 queue|stack) 817 _bpftool_once_attr 'value' 818 return 0; 819 ;; 820 esac 821 822 _bpftool_once_attr 'key' 823 local UPDATE_FLAGS='any exist noexist' 824 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do 825 if [[ ${words[idx]} == 'value' ]]; then 826 # 'value' is present, but is not the last 827 # word i.e. we can now have UPDATE_FLAGS. 828 _bpftool_one_of_list "$UPDATE_FLAGS" 829 return 0 830 fi 831 done 832 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do 833 if [[ ${words[idx]} == 'key' ]]; then 834 # 'key' is present, but is not the last 835 # word i.e. we can now have 'value'. 836 _bpftool_once_attr 'value' 837 return 0 838 fi 839 done 840 841 return 0 842 ;; 843 esac 844 ;; 845 pin) 846 case $prev in 847 $command) 848 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 849 ;; 850 id) 851 _bpftool_get_map_ids 852 ;; 853 name) 854 _bpftool_get_map_names 855 ;; 856 esac 857 return 0 858 ;; 859 event_pipe) 860 case $prev in 861 $command) 862 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 863 return 0 864 ;; 865 id) 866 _bpftool_get_map_ids_for_type perf_event_array 867 return 0 868 ;; 869 name) 870 _bpftool_get_map_names_for_type perf_event_array 871 return 0 872 ;; 873 cpu) 874 return 0 875 ;; 876 index) 877 return 0 878 ;; 879 *) 880 _bpftool_once_attr 'cpu index' 881 return 0 882 ;; 883 esac 884 ;; 885 *) 886 [[ $prev == $object ]] && \ 887 COMPREPLY=( $( compgen -W 'delete dump getnext help \ 888 lookup pin event_pipe show list update create \ 889 peek push enqueue pop dequeue freeze' -- \ 890 "$cur" ) ) 891 ;; 892 esac 893 ;; 894 btf) 895 local PROG_TYPE='id pinned tag name' 896 local MAP_TYPE='id pinned name' 897 case $command in 898 dump) 899 case $prev in 900 $command) 901 COMPREPLY+=( $( compgen -W "id map prog file" -- \ 902 "$cur" ) ) 903 return 0 904 ;; 905 prog) 906 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) 907 return 0 908 ;; 909 map) 910 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 911 return 0 912 ;; 913 id) 914 case $pprev in 915 prog) 916 _bpftool_get_prog_ids 917 ;; 918 map) 919 _bpftool_get_map_ids 920 ;; 921 $command) 922 _bpftool_get_btf_ids 923 ;; 924 esac 925 return 0 926 ;; 927 name) 928 case $pprev in 929 prog) 930 _bpftool_get_prog_names 931 ;; 932 map) 933 _bpftool_get_map_names 934 ;; 935 esac 936 return 0 937 ;; 938 format) 939 COMPREPLY=( $( compgen -W "c raw" -- "$cur" ) ) 940 ;; 941 *) 942 # emit extra options 943 case ${words[3]} in 944 id|file) 945 _bpftool_once_attr 'format' 946 ;; 947 map|prog) 948 if [[ ${words[3]} == "map" ]] && [[ $cword == 6 ]]; then 949 COMPREPLY+=( $( compgen -W "key value kv all" -- "$cur" ) ) 950 fi 951 _bpftool_once_attr 'format' 952 ;; 953 *) 954 ;; 955 esac 956 return 0 957 ;; 958 esac 959 ;; 960 show|list) 961 case $prev in 962 $command) 963 COMPREPLY+=( $( compgen -W "id" -- "$cur" ) ) 964 ;; 965 id) 966 _bpftool_get_btf_ids 967 ;; 968 esac 969 return 0 970 ;; 971 *) 972 [[ $prev == $object ]] && \ 973 COMPREPLY=( $( compgen -W 'dump help show list' \ 974 -- "$cur" ) ) 975 ;; 976 esac 977 ;; 978 gen) 979 case $command in 980 object) 981 _filedir 982 return 0 983 ;; 984 skeleton) 985 case $prev in 986 $command) 987 _filedir 988 return 0 989 ;; 990 *) 991 _bpftool_once_attr 'name' 992 return 0 993 ;; 994 esac 995 ;; 996 subskeleton) 997 case $prev in 998 $command) 999 _filedir 1000 return 0 1001 ;; 1002 *) 1003 _bpftool_once_attr 'name' 1004 return 0 1005 ;; 1006 esac 1007 ;; 1008 min_core_btf) 1009 _filedir 1010 return 0 1011 ;; 1012 *) 1013 [[ $prev == $object ]] && \ 1014 COMPREPLY=( $( compgen -W 'object skeleton subskeleton help min_core_btf' -- "$cur" ) ) 1015 ;; 1016 esac 1017 ;; 1018 cgroup) 1019 case $command in 1020 show|list|tree) 1021 case $cword in 1022 3) 1023 _filedir 1024 ;; 1025 4) 1026 COMPREPLY=( $( compgen -W 'effective' -- "$cur" ) ) 1027 ;; 1028 esac 1029 return 0 1030 ;; 1031 attach|detach) 1032 local BPFTOOL_CGROUP_ATTACH_TYPES="$(bpftool feature list_builtins attach_types 2>/dev/null | \ 1033 grep '^cgroup_')" 1034 local ATTACH_FLAGS='multi override' 1035 local PROG_TYPE='id pinned tag name' 1036 # Check for $prev = $command first 1037 if [ $prev = $command ]; then 1038 _filedir 1039 return 0 1040 # Then check for attach type. This is done outside of the 1041 # "case $prev in" to avoid writing the whole list of attach 1042 # types again as pattern to match (where we cannot reuse 1043 # our variable). 1044 elif [[ $BPFTOOL_CGROUP_ATTACH_TYPES =~ $prev ]]; then 1045 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \ 1046 "$cur" ) ) 1047 return 0 1048 fi 1049 # case/esac for the other cases 1050 case $prev in 1051 id) 1052 _bpftool_get_prog_ids 1053 return 0 1054 ;; 1055 *) 1056 if ! _bpftool_search_list "$BPFTOOL_CGROUP_ATTACH_TYPES"; then 1057 COMPREPLY=( $( compgen -W \ 1058 "$BPFTOOL_CGROUP_ATTACH_TYPES" -- "$cur" ) ) 1059 elif [[ "$command" == "attach" ]]; then 1060 # We have an attach type on the command line, 1061 # but it is not the previous word, or 1062 # "id|pinned|tag|name" (we already checked for 1063 # that). This should only leave the case when 1064 # we need attach flags for "attach" commamnd. 1065 _bpftool_one_of_list "$ATTACH_FLAGS" 1066 fi 1067 return 0 1068 ;; 1069 esac 1070 ;; 1071 *) 1072 [[ $prev == $object ]] && \ 1073 COMPREPLY=( $( compgen -W 'help attach detach \ 1074 show list tree' -- "$cur" ) ) 1075 ;; 1076 esac 1077 ;; 1078 perf) 1079 case $command in 1080 *) 1081 [[ $prev == $object ]] && \ 1082 COMPREPLY=( $( compgen -W 'help \ 1083 show list' -- "$cur" ) ) 1084 ;; 1085 esac 1086 ;; 1087 net) 1088 local PROG_TYPE='id pinned tag name' 1089 local ATTACH_TYPES='xdp xdpgeneric xdpdrv xdpoffload' 1090 case $command in 1091 show|list) 1092 [[ $prev != "$command" ]] && return 0 1093 COMPREPLY=( $( compgen -W 'dev' -- "$cur" ) ) 1094 return 0 1095 ;; 1096 attach) 1097 case $cword in 1098 3) 1099 COMPREPLY=( $( compgen -W "$ATTACH_TYPES" -- "$cur" ) ) 1100 return 0 1101 ;; 1102 4) 1103 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) 1104 return 0 1105 ;; 1106 5) 1107 case $prev in 1108 id) 1109 _bpftool_get_prog_ids 1110 ;; 1111 name) 1112 _bpftool_get_prog_names 1113 ;; 1114 pinned) 1115 _filedir 1116 ;; 1117 esac 1118 return 0 1119 ;; 1120 6) 1121 COMPREPLY=( $( compgen -W 'dev' -- "$cur" ) ) 1122 return 0 1123 ;; 1124 8) 1125 _bpftool_once_attr 'overwrite' 1126 return 0 1127 ;; 1128 esac 1129 ;; 1130 detach) 1131 case $cword in 1132 3) 1133 COMPREPLY=( $( compgen -W "$ATTACH_TYPES" -- "$cur" ) ) 1134 return 0 1135 ;; 1136 4) 1137 COMPREPLY=( $( compgen -W 'dev' -- "$cur" ) ) 1138 return 0 1139 ;; 1140 esac 1141 ;; 1142 *) 1143 [[ $prev == $object ]] && \ 1144 COMPREPLY=( $( compgen -W 'help \ 1145 show list attach detach' -- "$cur" ) ) 1146 ;; 1147 esac 1148 ;; 1149 feature) 1150 case $command in 1151 probe) 1152 [[ $prev == "prefix" ]] && return 0 1153 if _bpftool_search_list 'macros'; then 1154 _bpftool_once_attr 'prefix' 1155 else 1156 COMPREPLY+=( $( compgen -W 'macros' -- "$cur" ) ) 1157 fi 1158 _bpftool_one_of_list 'kernel dev' 1159 _bpftool_once_attr 'full unprivileged' 1160 return 0 1161 ;; 1162 list_builtins) 1163 [[ $prev != "$command" ]] && return 0 1164 COMPREPLY=( $( compgen -W 'prog_types map_types \ 1165 attach_types link_types helpers' -- "$cur" ) ) 1166 ;; 1167 *) 1168 [[ $prev == $object ]] && \ 1169 COMPREPLY=( $( compgen -W 'help list_builtins probe' -- "$cur" ) ) 1170 ;; 1171 esac 1172 ;; 1173 link) 1174 case $command in 1175 show|list|pin|detach) 1176 case $prev in 1177 id) 1178 _bpftool_get_link_ids 1179 return 0 1180 ;; 1181 esac 1182 ;; 1183 esac 1184 1185 local LINK_TYPE='id pinned' 1186 case $command in 1187 show|list) 1188 [[ $prev != "$command" ]] && return 0 1189 COMPREPLY=( $( compgen -W "$LINK_TYPE" -- "$cur" ) ) 1190 return 0 1191 ;; 1192 pin|detach) 1193 if [[ $prev == "$command" ]]; then 1194 COMPREPLY=( $( compgen -W "$LINK_TYPE" -- "$cur" ) ) 1195 else 1196 _filedir 1197 fi 1198 return 0 1199 ;; 1200 *) 1201 [[ $prev == $object ]] && \ 1202 COMPREPLY=( $( compgen -W 'help pin show list' -- "$cur" ) ) 1203 ;; 1204 esac 1205 ;; 1206 esac 1207} && 1208complete -F _bpftool bpftool 1209 1210# ex: ts=4 sw=4 et filetype=sh 1211