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 259 _init_completion || return 260 261 # Deal with options 262 if [[ ${words[cword]} == -* ]]; then 263 local c='--version --json --pretty --bpffs --mapcompat --debug' 264 COMPREPLY=( $( compgen -W "$c" -- "$cur" ) ) 265 return 0 266 fi 267 268 # Deal with simplest keywords 269 case $prev in 270 help|hex|opcodes|visual|linum) 271 return 0 272 ;; 273 tag) 274 _bpftool_get_prog_tags 275 return 0 276 ;; 277 dev) 278 _sysfs_get_netdevs 279 return 0 280 ;; 281 file|pinned) 282 _filedir 283 return 0 284 ;; 285 batch) 286 COMPREPLY=( $( compgen -W 'file' -- "$cur" ) ) 287 return 0 288 ;; 289 esac 290 291 # Remove all options so completions don't have to deal with them. 292 local i 293 for (( i=1; i < ${#words[@]}; )); do 294 if [[ ${words[i]::1} == - ]]; then 295 words=( "${words[@]:0:i}" "${words[@]:i+1}" ) 296 [[ $i -le $cword ]] && cword=$(( cword - 1 )) 297 else 298 i=$(( ++i )) 299 fi 300 done 301 cur=${words[cword]} 302 prev=${words[cword - 1]} 303 pprev=${words[cword - 2]} 304 305 local object=${words[1]} command=${words[2]} 306 307 if [[ -z $object || $cword -eq 1 ]]; then 308 case $cur in 309 *) 310 COMPREPLY=( $( compgen -W "$( bpftool help 2>&1 | \ 311 command sed \ 312 -e '/OBJECT := /!d' \ 313 -e 's/.*{//' \ 314 -e 's/}.*//' \ 315 -e 's/|//g' )" -- "$cur" ) ) 316 COMPREPLY+=( $( compgen -W 'batch help' -- "$cur" ) ) 317 return 0 318 ;; 319 esac 320 fi 321 322 [[ $command == help ]] && return 0 323 324 # Completion depends on object and command in use 325 case $object in 326 prog) 327 # Complete id and name, only for subcommands that use prog (but no 328 # map) ids/names. 329 case $command in 330 show|list|dump|pin) 331 case $prev in 332 id) 333 _bpftool_get_prog_ids 334 return 0 335 ;; 336 name) 337 _bpftool_get_prog_names 338 return 0 339 ;; 340 esac 341 ;; 342 esac 343 344 local PROG_TYPE='id pinned tag name' 345 local MAP_TYPE='id pinned name' 346 local METRIC_TYPE='cycles instructions l1d_loads llc_misses' 347 case $command in 348 show|list) 349 [[ $prev != "$command" ]] && return 0 350 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) 351 return 0 352 ;; 353 dump) 354 case $prev in 355 $command) 356 COMPREPLY+=( $( compgen -W "xlated jited" -- \ 357 "$cur" ) ) 358 return 0 359 ;; 360 xlated|jited) 361 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \ 362 "$cur" ) ) 363 return 0 364 ;; 365 *) 366 _bpftool_once_attr 'file' 367 if _bpftool_search_list 'xlated'; then 368 COMPREPLY+=( $( compgen -W 'opcodes visual linum' -- \ 369 "$cur" ) ) 370 else 371 COMPREPLY+=( $( compgen -W 'opcodes linum' -- \ 372 "$cur" ) ) 373 fi 374 return 0 375 ;; 376 esac 377 ;; 378 pin) 379 if [[ $prev == "$command" ]]; then 380 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) 381 else 382 _filedir 383 fi 384 return 0 385 ;; 386 attach|detach) 387 case $cword in 388 3) 389 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) 390 return 0 391 ;; 392 4) 393 case $prev in 394 id) 395 _bpftool_get_prog_ids 396 ;; 397 name) 398 _bpftool_get_prog_names 399 ;; 400 pinned) 401 _filedir 402 ;; 403 esac 404 return 0 405 ;; 406 5) 407 COMPREPLY=( $( compgen -W 'msg_verdict stream_verdict \ 408 stream_parser flow_dissector' -- "$cur" ) ) 409 return 0 410 ;; 411 6) 412 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 413 return 0 414 ;; 415 7) 416 case $prev in 417 id) 418 _bpftool_get_map_ids 419 ;; 420 name) 421 _bpftool_get_map_names 422 ;; 423 pinned) 424 _filedir 425 ;; 426 esac 427 return 0 428 ;; 429 esac 430 ;; 431 load|loadall) 432 local obj 433 434 # Propose "load/loadall" to complete "bpftool prog load", 435 # or bash tries to complete "load" as a filename below. 436 if [[ ${#words[@]} -eq 3 ]]; then 437 COMPREPLY=( $( compgen -W "load loadall" -- "$cur" ) ) 438 return 0 439 fi 440 441 if [[ ${#words[@]} -lt 6 ]]; then 442 _filedir 443 return 0 444 fi 445 446 obj=${words[3]} 447 448 if [[ ${words[-4]} == "map" ]]; then 449 COMPREPLY=( $( compgen -W "id pinned" -- "$cur" ) ) 450 return 0 451 fi 452 if [[ ${words[-3]} == "map" ]]; then 453 if [[ ${words[-2]} == "idx" ]]; then 454 _bpftool_get_obj_map_idxs $obj 455 elif [[ ${words[-2]} == "name" ]]; then 456 _bpftool_get_obj_map_names $obj 457 fi 458 return 0 459 fi 460 if [[ ${words[-2]} == "map" ]]; then 461 COMPREPLY=( $( compgen -W "idx name" -- "$cur" ) ) 462 return 0 463 fi 464 465 case $prev in 466 type) 467 COMPREPLY=( $( compgen -W "socket kprobe \ 468 kretprobe classifier flow_dissector \ 469 action tracepoint raw_tracepoint \ 470 xdp perf_event cgroup/skb cgroup/sock \ 471 cgroup/dev lwt_in lwt_out lwt_xmit \ 472 lwt_seg6local sockops sk_skb sk_msg \ 473 lirc_mode2 cgroup/bind4 cgroup/bind6 \ 474 cgroup/connect4 cgroup/connect6 \ 475 cgroup/getpeername4 cgroup/getpeername6 \ 476 cgroup/getsockname4 cgroup/getsockname6 \ 477 cgroup/sendmsg4 cgroup/sendmsg6 \ 478 cgroup/recvmsg4 cgroup/recvmsg6 \ 479 cgroup/post_bind4 cgroup/post_bind6 \ 480 cgroup/sysctl cgroup/getsockopt \ 481 cgroup/setsockopt struct_ops \ 482 fentry fexit freplace sk_lookup" -- \ 483 "$cur" ) ) 484 return 0 485 ;; 486 id) 487 _bpftool_get_map_ids 488 return 0 489 ;; 490 name) 491 _bpftool_get_map_names 492 return 0 493 ;; 494 pinned|pinmaps) 495 _filedir 496 return 0 497 ;; 498 *) 499 COMPREPLY=( $( compgen -W "map" -- "$cur" ) ) 500 _bpftool_once_attr 'type' 501 _bpftool_once_attr 'dev' 502 _bpftool_once_attr 'pinmaps' 503 return 0 504 ;; 505 esac 506 ;; 507 tracelog) 508 return 0 509 ;; 510 profile) 511 case $cword in 512 3) 513 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) 514 return 0 515 ;; 516 4) 517 case $prev in 518 id) 519 _bpftool_get_prog_ids 520 ;; 521 name) 522 _bpftool_get_prog_names 523 ;; 524 pinned) 525 _filedir 526 ;; 527 esac 528 return 0 529 ;; 530 5) 531 COMPREPLY=( $( compgen -W "$METRIC_TYPE duration" -- "$cur" ) ) 532 return 0 533 ;; 534 6) 535 case $prev in 536 duration) 537 return 0 538 ;; 539 *) 540 COMPREPLY=( $( compgen -W "$METRIC_TYPE" -- "$cur" ) ) 541 return 0 542 ;; 543 esac 544 return 0 545 ;; 546 *) 547 COMPREPLY=( $( compgen -W "$METRIC_TYPE" -- "$cur" ) ) 548 return 0 549 ;; 550 esac 551 ;; 552 run) 553 if [[ ${#words[@]} -eq 4 ]]; then 554 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) 555 return 0 556 fi 557 case $prev in 558 id) 559 _bpftool_get_prog_ids 560 return 0 561 ;; 562 name) 563 _bpftool_get_prog_names 564 return 0 565 ;; 566 data_in|data_out|ctx_in|ctx_out) 567 _filedir 568 return 0 569 ;; 570 repeat|data_size_out|ctx_size_out) 571 return 0 572 ;; 573 *) 574 _bpftool_once_attr 'data_in data_out data_size_out \ 575 ctx_in ctx_out ctx_size_out repeat' 576 return 0 577 ;; 578 esac 579 ;; 580 *) 581 [[ $prev == $object ]] && \ 582 COMPREPLY=( $( compgen -W 'dump help pin attach detach \ 583 load loadall show list tracelog run profile' -- "$cur" ) ) 584 ;; 585 esac 586 ;; 587 struct_ops) 588 local STRUCT_OPS_TYPE='id name' 589 case $command in 590 show|list|dump|unregister) 591 case $prev in 592 $command) 593 COMPREPLY=( $( compgen -W "$STRUCT_OPS_TYPE" -- "$cur" ) ) 594 ;; 595 id) 596 _bpftool_get_map_ids_for_type struct_ops 597 ;; 598 name) 599 _bpftool_get_map_names_for_type struct_ops 600 ;; 601 esac 602 return 0 603 ;; 604 register) 605 _filedir 606 return 0 607 ;; 608 *) 609 [[ $prev == $object ]] && \ 610 COMPREPLY=( $( compgen -W 'register unregister show list dump help' \ 611 -- "$cur" ) ) 612 ;; 613 esac 614 ;; 615 iter) 616 case $command in 617 pin) 618 case $prev in 619 $command) 620 _filedir 621 ;; 622 id) 623 _bpftool_get_map_ids 624 ;; 625 name) 626 _bpftool_get_map_names 627 ;; 628 pinned) 629 _filedir 630 ;; 631 *) 632 _bpftool_one_of_list $MAP_TYPE 633 ;; 634 esac 635 return 0 636 ;; 637 *) 638 [[ $prev == $object ]] && \ 639 COMPREPLY=( $( compgen -W 'pin help' \ 640 -- "$cur" ) ) 641 ;; 642 esac 643 ;; 644 map) 645 local MAP_TYPE='id pinned name' 646 case $command in 647 show|list|dump|peek|pop|dequeue|freeze) 648 case $prev in 649 $command) 650 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 651 return 0 652 ;; 653 id) 654 case "$command" in 655 peek) 656 _bpftool_get_map_ids_for_type stack 657 _bpftool_get_map_ids_for_type queue 658 ;; 659 pop) 660 _bpftool_get_map_ids_for_type stack 661 ;; 662 dequeue) 663 _bpftool_get_map_ids_for_type queue 664 ;; 665 *) 666 _bpftool_get_map_ids 667 ;; 668 esac 669 return 0 670 ;; 671 name) 672 case "$command" in 673 peek) 674 _bpftool_get_map_names_for_type stack 675 _bpftool_get_map_names_for_type queue 676 ;; 677 pop) 678 _bpftool_get_map_names_for_type stack 679 ;; 680 dequeue) 681 _bpftool_get_map_names_for_type queue 682 ;; 683 *) 684 _bpftool_get_map_names 685 ;; 686 esac 687 return 0 688 ;; 689 *) 690 return 0 691 ;; 692 esac 693 ;; 694 create) 695 case $prev in 696 $command) 697 _filedir 698 return 0 699 ;; 700 type) 701 COMPREPLY=( $( compgen -W 'hash array prog_array \ 702 perf_event_array percpu_hash percpu_array \ 703 stack_trace cgroup_array lru_hash \ 704 lru_percpu_hash lpm_trie array_of_maps \ 705 hash_of_maps devmap devmap_hash sockmap cpumap \ 706 xskmap sockhash cgroup_storage reuseport_sockarray \ 707 percpu_cgroup_storage queue stack sk_storage \ 708 struct_ops inode_storage' -- \ 709 "$cur" ) ) 710 return 0 711 ;; 712 key|value|flags|entries) 713 return 0 714 ;; 715 inner_map) 716 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 717 return 0 718 ;; 719 id) 720 _bpftool_get_map_ids 721 ;; 722 name) 723 case $pprev in 724 inner_map) 725 _bpftool_get_map_names 726 ;; 727 *) 728 return 0 729 ;; 730 esac 731 ;; 732 *) 733 _bpftool_once_attr 'type' 734 _bpftool_once_attr 'key' 735 _bpftool_once_attr 'value' 736 _bpftool_once_attr 'entries' 737 _bpftool_once_attr 'name' 738 _bpftool_once_attr 'flags' 739 if _bpftool_search_list 'array_of_maps' 'hash_of_maps'; then 740 _bpftool_once_attr 'inner_map' 741 fi 742 _bpftool_once_attr 'dev' 743 return 0 744 ;; 745 esac 746 ;; 747 lookup|getnext|delete) 748 case $prev in 749 $command) 750 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 751 return 0 752 ;; 753 id) 754 _bpftool_get_map_ids 755 return 0 756 ;; 757 name) 758 _bpftool_get_map_names 759 return 0 760 ;; 761 key) 762 COMPREPLY+=( $( compgen -W 'hex' -- "$cur" ) ) 763 ;; 764 *) 765 case $(_bpftool_map_guess_map_type) in 766 queue|stack) 767 return 0 768 ;; 769 esac 770 771 _bpftool_once_attr 'key' 772 return 0 773 ;; 774 esac 775 ;; 776 update|push|enqueue) 777 case $prev in 778 $command) 779 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 780 return 0 781 ;; 782 id) 783 _bpftool_map_update_get_id $command 784 return 0 785 ;; 786 name) 787 _bpftool_map_update_get_name $command 788 return 0 789 ;; 790 key) 791 COMPREPLY+=( $( compgen -W 'hex' -- "$cur" ) ) 792 ;; 793 value) 794 # We can have bytes, or references to a prog or a 795 # map, depending on the type of the map to update. 796 case "$(_bpftool_map_guess_map_type)" in 797 array_of_maps|hash_of_maps) 798 local MAP_TYPE='id pinned name' 799 COMPREPLY+=( $( compgen -W "$MAP_TYPE" \ 800 -- "$cur" ) ) 801 return 0 802 ;; 803 prog_array) 804 local PROG_TYPE='id pinned tag name' 805 COMPREPLY+=( $( compgen -W "$PROG_TYPE" \ 806 -- "$cur" ) ) 807 return 0 808 ;; 809 *) 810 COMPREPLY+=( $( compgen -W 'hex' \ 811 -- "$cur" ) ) 812 return 0 813 ;; 814 esac 815 return 0 816 ;; 817 *) 818 case $(_bpftool_map_guess_map_type) in 819 queue|stack) 820 _bpftool_once_attr 'value' 821 return 0; 822 ;; 823 esac 824 825 _bpftool_once_attr 'key' 826 local UPDATE_FLAGS='any exist noexist' 827 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do 828 if [[ ${words[idx]} == 'value' ]]; then 829 # 'value' is present, but is not the last 830 # word i.e. we can now have UPDATE_FLAGS. 831 _bpftool_one_of_list "$UPDATE_FLAGS" 832 return 0 833 fi 834 done 835 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do 836 if [[ ${words[idx]} == 'key' ]]; then 837 # 'key' is present, but is not the last 838 # word i.e. we can now have 'value'. 839 _bpftool_once_attr 'value' 840 return 0 841 fi 842 done 843 844 return 0 845 ;; 846 esac 847 ;; 848 pin) 849 case $prev in 850 $command) 851 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 852 ;; 853 id) 854 _bpftool_get_map_ids 855 ;; 856 name) 857 _bpftool_get_map_names 858 ;; 859 esac 860 return 0 861 ;; 862 event_pipe) 863 case $prev in 864 $command) 865 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 866 return 0 867 ;; 868 id) 869 _bpftool_get_map_ids_for_type perf_event_array 870 return 0 871 ;; 872 name) 873 _bpftool_get_map_names_for_type perf_event_array 874 return 0 875 ;; 876 cpu) 877 return 0 878 ;; 879 index) 880 return 0 881 ;; 882 *) 883 _bpftool_once_attr 'cpu' 884 _bpftool_once_attr 'index' 885 return 0 886 ;; 887 esac 888 ;; 889 *) 890 [[ $prev == $object ]] && \ 891 COMPREPLY=( $( compgen -W 'delete dump getnext help \ 892 lookup pin event_pipe show list update create \ 893 peek push enqueue pop dequeue freeze' -- \ 894 "$cur" ) ) 895 ;; 896 esac 897 ;; 898 btf) 899 local PROG_TYPE='id pinned tag name' 900 local MAP_TYPE='id pinned name' 901 case $command in 902 dump) 903 case $prev in 904 $command) 905 COMPREPLY+=( $( compgen -W "id map prog file" -- \ 906 "$cur" ) ) 907 return 0 908 ;; 909 prog) 910 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) 911 return 0 912 ;; 913 map) 914 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 915 return 0 916 ;; 917 id) 918 case $pprev in 919 prog) 920 _bpftool_get_prog_ids 921 ;; 922 map) 923 _bpftool_get_map_ids 924 ;; 925 $command) 926 _bpftool_get_btf_ids 927 ;; 928 esac 929 return 0 930 ;; 931 name) 932 case $pprev in 933 prog) 934 _bpftool_get_prog_names 935 ;; 936 map) 937 _bpftool_get_map_names 938 ;; 939 esac 940 return 0 941 ;; 942 format) 943 COMPREPLY=( $( compgen -W "c raw" -- "$cur" ) ) 944 ;; 945 *) 946 # emit extra options 947 case ${words[3]} in 948 id|file) 949 _bpftool_once_attr 'format' 950 ;; 951 map|prog) 952 if [[ ${words[3]} == "map" ]] && [[ $cword == 6 ]]; then 953 COMPREPLY+=( $( compgen -W "key value kv all" -- "$cur" ) ) 954 fi 955 _bpftool_once_attr 'format' 956 ;; 957 *) 958 ;; 959 esac 960 return 0 961 ;; 962 esac 963 ;; 964 show|list) 965 case $prev in 966 $command) 967 COMPREPLY+=( $( compgen -W "id" -- "$cur" ) ) 968 ;; 969 id) 970 _bpftool_get_btf_ids 971 ;; 972 esac 973 return 0 974 ;; 975 *) 976 [[ $prev == $object ]] && \ 977 COMPREPLY=( $( compgen -W 'dump help show list' \ 978 -- "$cur" ) ) 979 ;; 980 esac 981 ;; 982 gen) 983 case $command in 984 skeleton) 985 _filedir 986 ;; 987 *) 988 [[ $prev == $object ]] && \ 989 COMPREPLY=( $( compgen -W 'skeleton help' -- "$cur" ) ) 990 ;; 991 esac 992 ;; 993 cgroup) 994 case $command in 995 show|list|tree) 996 case $cword in 997 3) 998 _filedir 999 ;; 1000 4) 1001 COMPREPLY=( $( compgen -W 'effective' -- "$cur" ) ) 1002 ;; 1003 esac 1004 return 0 1005 ;; 1006 attach|detach) 1007 local ATTACH_TYPES='ingress egress sock_create sock_ops \ 1008 device bind4 bind6 post_bind4 post_bind6 connect4 connect6 \ 1009 getpeername4 getpeername6 getsockname4 getsockname6 \ 1010 sendmsg4 sendmsg6 recvmsg4 recvmsg6 sysctl getsockopt \ 1011 setsockopt' 1012 local ATTACH_FLAGS='multi override' 1013 local PROG_TYPE='id pinned tag name' 1014 case $prev in 1015 $command) 1016 _filedir 1017 return 0 1018 ;; 1019 ingress|egress|sock_create|sock_ops|device|bind4|bind6|\ 1020 post_bind4|post_bind6|connect4|connect6|getpeername4|\ 1021 getpeername6|getsockname4|getsockname6|sendmsg4|sendmsg6|\ 1022 recvmsg4|recvmsg6|sysctl|getsockopt|setsockopt) 1023 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \ 1024 "$cur" ) ) 1025 return 0 1026 ;; 1027 id) 1028 _bpftool_get_prog_ids 1029 return 0 1030 ;; 1031 *) 1032 if ! _bpftool_search_list "$ATTACH_TYPES"; then 1033 COMPREPLY=( $( compgen -W "$ATTACH_TYPES" -- \ 1034 "$cur" ) ) 1035 elif [[ "$command" == "attach" ]]; then 1036 # We have an attach type on the command line, 1037 # but it is not the previous word, or 1038 # "id|pinned|tag|name" (we already checked for 1039 # that). This should only leave the case when 1040 # we need attach flags for "attach" commamnd. 1041 _bpftool_one_of_list "$ATTACH_FLAGS" 1042 fi 1043 return 0 1044 ;; 1045 esac 1046 ;; 1047 *) 1048 [[ $prev == $object ]] && \ 1049 COMPREPLY=( $( compgen -W 'help attach detach \ 1050 show list tree' -- "$cur" ) ) 1051 ;; 1052 esac 1053 ;; 1054 perf) 1055 case $command in 1056 *) 1057 [[ $prev == $object ]] && \ 1058 COMPREPLY=( $( compgen -W 'help \ 1059 show list' -- "$cur" ) ) 1060 ;; 1061 esac 1062 ;; 1063 net) 1064 local PROG_TYPE='id pinned tag name' 1065 local ATTACH_TYPES='xdp xdpgeneric xdpdrv xdpoffload' 1066 case $command in 1067 show|list) 1068 [[ $prev != "$command" ]] && return 0 1069 COMPREPLY=( $( compgen -W 'dev' -- "$cur" ) ) 1070 return 0 1071 ;; 1072 attach) 1073 case $cword in 1074 3) 1075 COMPREPLY=( $( compgen -W "$ATTACH_TYPES" -- "$cur" ) ) 1076 return 0 1077 ;; 1078 4) 1079 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) 1080 return 0 1081 ;; 1082 5) 1083 case $prev in 1084 id) 1085 _bpftool_get_prog_ids 1086 ;; 1087 name) 1088 _bpftool_get_prog_names 1089 ;; 1090 pinned) 1091 _filedir 1092 ;; 1093 esac 1094 return 0 1095 ;; 1096 6) 1097 COMPREPLY=( $( compgen -W 'dev' -- "$cur" ) ) 1098 return 0 1099 ;; 1100 8) 1101 _bpftool_once_attr 'overwrite' 1102 return 0 1103 ;; 1104 esac 1105 ;; 1106 detach) 1107 case $cword in 1108 3) 1109 COMPREPLY=( $( compgen -W "$ATTACH_TYPES" -- "$cur" ) ) 1110 return 0 1111 ;; 1112 4) 1113 COMPREPLY=( $( compgen -W 'dev' -- "$cur" ) ) 1114 return 0 1115 ;; 1116 esac 1117 ;; 1118 *) 1119 [[ $prev == $object ]] && \ 1120 COMPREPLY=( $( compgen -W 'help \ 1121 show list attach detach' -- "$cur" ) ) 1122 ;; 1123 esac 1124 ;; 1125 feature) 1126 case $command in 1127 probe) 1128 [[ $prev == "prefix" ]] && return 0 1129 if _bpftool_search_list 'macros'; then 1130 _bpftool_once_attr 'prefix' 1131 else 1132 COMPREPLY+=( $( compgen -W 'macros' -- "$cur" ) ) 1133 fi 1134 _bpftool_one_of_list 'kernel dev' 1135 _bpftool_once_attr 'full unprivileged' 1136 return 0 1137 ;; 1138 *) 1139 [[ $prev == $object ]] && \ 1140 COMPREPLY=( $( compgen -W 'help probe' -- "$cur" ) ) 1141 ;; 1142 esac 1143 ;; 1144 link) 1145 case $command in 1146 show|list|pin|detach) 1147 case $prev in 1148 id) 1149 _bpftool_get_link_ids 1150 return 0 1151 ;; 1152 esac 1153 ;; 1154 esac 1155 1156 local LINK_TYPE='id pinned' 1157 case $command in 1158 show|list) 1159 [[ $prev != "$command" ]] && return 0 1160 COMPREPLY=( $( compgen -W "$LINK_TYPE" -- "$cur" ) ) 1161 return 0 1162 ;; 1163 pin|detach) 1164 if [[ $prev == "$command" ]]; then 1165 COMPREPLY=( $( compgen -W "$LINK_TYPE" -- "$cur" ) ) 1166 else 1167 _filedir 1168 fi 1169 return 0 1170 ;; 1171 *) 1172 [[ $prev == $object ]] && \ 1173 COMPREPLY=( $( compgen -W 'help pin show list' -- "$cur" ) ) 1174 ;; 1175 esac 1176 ;; 1177 esac 1178} && 1179complete -F _bpftool bpftool 1180 1181# ex: ts=4 sw=4 et filetype=sh 1182