1# bash completion for ethtool(8) -*- shell-script -*- 2# shellcheck shell=bash disable=SC2207 3 4# Complete a word representing a set of characters. 5# @param $@ chars Characters which may be present in completed set. 6_ethtool_compgen_letterset() 7{ 8 local char 9 for char; do 10 case "$cur" in 11 *"$char"*) 12 # $cur already contains $char 13 ;; 14 *) 15 COMPREPLY+=( "$cur$char" ) 16 ;; 17 esac 18 done 19} 20 21# Generate completions for words matched case-insensitively 22# @param $@ choices Completion choices. 23_ethtool_compgen_nocase() 24{ 25 local reset 26 reset=$( shopt -p nocasematch ) 27 shopt -s nocasematch 28 29 local choice 30 for choice; do 31 case "$choice" in 32 "$cur"*) COMPREPLY+=( "$choice" ) ;; 33 esac 34 done 35 36 $reset 37} 38 39# Gets names from a section of ethtool output. 40# @param $1 section_bre POSIX BRE matching section heading (without : at end). 41# @param $@ ethtool arguments 42_ethtool_get_names_in_section() 43{ 44 local section_bre="$1" 45 shift 46 47 PATH="$PATH:/sbin:/usr/sbin:/usr/local/sbin" \ 48 ethtool "$@" 2>/dev/null | 49 command sed -n " 50# Line is section heading iff it ends with : 51# From requested section heading to next section heading 52/^$section_bre:$/,/:$/ { 53 # If line is section heading, ignore it 54 /:$/d 55 # Remove value and separator, if present 56 s/[[:space:]]*:.*// 57 # Remove leading space, if present 58 s/^[[:space:]]*// 59 # Print the line 60 p 61}" 62} 63 64# Complete an RSS Context ID 65_ethtool_context() 66{ 67 COMPREPLY=( 68 $(PATH="$PATH:/sbin:/usr/sbin:/usr/local/sbin" \ 69 ethtool --show-nfc "${words[2]}" 2>/dev/null | 70 command sed -n 's/^[[:space:]]*RSS Context ID:[[:space:]]*\([0-9]*\)$/\1/p' | 71 sort -u) ) 72} 73 74# Complete a network flow traffic type 75# Available OPTIONS: 76# --hash Complete only types suitable for rx hashing 77_ethtool_flow_type() 78{ 79 local types='ah4 ah6 esp4 esp6 ether sctp4 sctp6 tcp4 tcp6 udp4 udp6' 80 if [ "${1-}" != --hash ]; then 81 types="$types ip4 ip6" 82 fi 83 COMPREPLY=( $( compgen -W "$types" -- "$cur" ) ) 84} 85 86# Completion for ethtool --change 87_ethtool_change() 88{ 89 local -A settings=( 90 [advertise]=notseen 91 [autoneg]=notseen 92 [duplex]=notseen 93 [mdix]=notseen 94 [msglvl]=notseen 95 [port]=notseen 96 [phyad]=notseen 97 [speed]=notseen 98 [wol]=notseen 99 [xcvr]=notseen 100 ) 101 102 local -A msgtypes=( 103 [drv]=notseen 104 [hw]=notseen 105 [ifdown]=notseen 106 [ifup]=notseen 107 [intr]=notseen 108 [link]=notseen 109 [pktdata]=notseen 110 [probe]=notseen 111 [rx_err]=notseen 112 [rx_status]=notseen 113 [timer]=notseen 114 [tx_done]=notseen 115 [tx_err]=notseen 116 [tx_queued]=notseen 117 [wol]=notseen 118 ) 119 120 # Mark seen settings and msgtypes, and whether in msglvl sub-command 121 local in_msglvl= 122 local word 123 for word in "${words[@]:3:${#words[@]}-4}"; do 124 if [ "$in_msglvl" ] && [ "${msgtypes[$word]+set}" ]; then 125 msgtypes[$word]=seen 126 elif [ "${settings[$word]+set}" ]; then 127 settings[$word]=seen 128 if [ "$word" = msglvl ]; then 129 in_msglvl=1 130 else 131 in_msglvl= 132 fi 133 fi 134 done 135 136 if [ "$in_msglvl" ] && [ "${msgtypes[$prev]+set}" ]; then 137 # All msgtypes take an on/off argument 138 COMPREPLY=( $( compgen -W 'on off' -- "$cur" ) ) 139 return 140 fi 141 142 case "$prev" in 143 advertise) 144 # Hex number 145 return ;; 146 autoneg) 147 COMPREPLY=( $( compgen -W 'on off' -- "$cur" ) ) 148 return ;; 149 duplex) 150 COMPREPLY=( $( compgen -W 'half full' -- "$cur" ) ) 151 return ;; 152 mdix) 153 COMPREPLY=( $( compgen -W 'auto on off' -- "$cur" ) ) 154 return ;; 155 msglvl) 156 # Unsigned integer or msgtype 157 COMPREPLY=( $( compgen -W "${!msgtypes[*]}" -- "$cur" ) ) 158 return ;; 159 port) 160 COMPREPLY=( $( compgen -W 'aui bnc fibre mii tp' -- "$cur" ) ) 161 return ;; 162 phyad) 163 # Integer 164 return ;; 165 sopass) 166 _mac_addresses 167 return ;; 168 speed) 169 # Number 170 return ;; 171 wol) 172 # $cur is a set of wol type characters. 173 _ethtool_compgen_letterset p u m b a g s f d 174 return ;; 175 xcvr) 176 COMPREPLY=( $( compgen -W 'internal external' -- "$cur" ) ) 177 return ;; 178 esac 179 180 local -a comp_words=() 181 182 # Add settings not seen to completions 183 local setting 184 for setting in "${!settings[@]}"; do 185 if [ "${settings[$setting]}" = notseen ]; then 186 comp_words+=( "$setting" ) 187 fi 188 done 189 190 # Add settings not seen to completions 191 if [ "$in_msglvl" ]; then 192 local msgtype 193 for msgtype in "${!msgtypes[@]}"; do 194 if [ "${msgtypes[$msgtype]}" = notseen ]; then 195 comp_words+=( "$msgtype" ) 196 fi 197 done 198 fi 199 200 COMPREPLY=( $( compgen -W "${comp_words[*]}" -- "$cur" ) ) 201} 202 203# Completion for ethtool --change-eeprom 204_ethtool_change_eeprom() 205{ 206 local -A settings=( 207 [length]=1 208 [magic]=1 209 [offset]=1 210 [value]=1 211 ) 212 213 if [ "${settings[$prev]+set}" ]; then 214 # All settings take an unsigned integer argument 215 return 216 fi 217 218 # Remove settings which have been seen 219 local word 220 for word in "${words[@]:3:${#words[@]}-4}"; do 221 unset "settings[$word]" 222 done 223 224 COMPREPLY=( $( compgen -W "${!settings[*]}" -- "$cur" ) ) 225} 226 227# Completion for ethtool --coalesce 228_ethtool_coalesce() 229{ 230 local -A settings=( 231 [adaptive-rx]=1 232 [adaptive-tx]=1 233 [pkt-rate-high]=1 234 [pkt-rate-low]=1 235 [rx-frames]=1 236 [rx-frames-high]=1 237 [rx-frames-irq]=1 238 [rx-frames-low]=1 239 [rx-usecs]=1 240 [rx-usecs-high]=1 241 [rx-usecs-irq]=1 242 [rx-usecs-low]=1 243 [sample-interval]=1 244 [stats-block-usecs]=1 245 [tx-frames]=1 246 [tx-frames-high]=1 247 [tx-frames-irq]=1 248 [tx-frames-low]=1 249 [tx-usecs]=1 250 [tx-usecs-high]=1 251 [tx-usecs-irq]=1 252 [tx-usecs-low]=1 253 ) 254 255 case "$prev" in 256 adaptive-rx|\ 257 adaptive-tx) 258 COMPREPLY=( $( compgen -W 'on off' -- "$cur" ) ) 259 return ;; 260 esac 261 262 if [ "${settings[$prev]+set}" ]; then 263 # Unsigned integer 264 return 265 fi 266 267 # Remove settings which have been seen 268 local word 269 for word in "${words[@]:3:${#words[@]}-4}"; do 270 unset "settings[$word]" 271 done 272 273 COMPREPLY=( $( compgen -W "${!settings[*]}" -- "$cur" ) ) 274} 275 276# Completion for ethtool --config-nfc <devname> flow-type 277_ethtool_config_nfc_flow_type() 278{ 279 if [ "$cword" -eq 4 ]; then 280 _ethtool_flow_type --spec 281 return 282 fi 283 284 case "$prev" in 285 context) 286 _ethtool_context 287 return ;; 288 dst|\ 289 dst-mac|\ 290 src) 291 # TODO: Complete only local for dst and remote for src 292 _mac_addresses 293 return ;; 294 dst-ip) 295 # Note: RX classification, so dst is usually local 296 case "${words[4]}" in 297 *4) _ip_addresses -4 return ;; 298 *6) _ip_addresses -6 return ;; 299 esac 300 return ;; 301 src-ip) 302 # Note: RX classification, so src is usually remote 303 # TODO: Remote IP addresses (ARP cache + /etc/hosts + ?) 304 return ;; 305 m|\ 306 *-mask) 307 # MAC, IP, or integer bitmask 308 return ;; 309 esac 310 311 local -A settings=( 312 [action]=1 313 [context]=1 314 [loc]=1 315 [queue]=1 316 [vf]=1 317 ) 318 319 if [ "${settings[$prev]+set}" ]; then 320 # Integer 321 return 322 fi 323 324 case "${words[4]}" in 325 ah4|\ 326 esp4) 327 local -A fields=( 328 [dst-ip]=1 329 [dst-mac]=1 330 [spi]=1 331 [src-ip]=1 332 [tos]=1 333 [user-def]=1 334 [vlan-etype]=1 335 [vlan]=1 336 ) 337 ;; 338 ah6|\ 339 esp6) 340 local -A fields=( 341 [dst-ip]=1 342 [dst-mac]=1 343 [spi]=1 344 [src-ip]=1 345 [tclass]=1 346 [user-def]=1 347 [vlan-etype]=1 348 [vlan]=1 349 ) 350 ;; 351 ether) 352 local -A fields=( 353 [dst]=1 354 [proto]=1 355 [src]=1 356 [user-def]=1 357 [vlan-etype]=1 358 [vlan]=1 359 ) 360 ;; 361 ip4) 362 local -A fields=( 363 [dst-ip]=1 364 [dst-mac]=1 365 [dst-port]=1 366 [l4data]=1 367 [l4proto]=1 368 [spi]=1 369 [src-ip]=1 370 [src-port]=1 371 [tos]=1 372 [user-def]=1 373 [vlan-etype]=1 374 [vlan]=1 375 ) 376 ;; 377 ip6) 378 local -A fields=( 379 [dst-ip]=1 380 [dst-mac]=1 381 [dst-port]=1 382 [l4data]=1 383 [l4proto]=1 384 [spi]=1 385 [src-ip]=1 386 [src-port]=1 387 [tclass]=1 388 [user-def]=1 389 [vlan-etype]=1 390 [vlan]=1 391 ) 392 ;; 393 sctp4|\ 394 tcp4|\ 395 udp4) 396 local -A fields=( 397 [dst-ip]=1 398 [dst-mac]=1 399 [dst-port]=1 400 [src-ip]=1 401 [src-port]=1 402 [tos]=1 403 [user-def]=1 404 [vlan-etype]=1 405 [vlan]=1 406 ) 407 ;; 408 sctp6|\ 409 tcp6|\ 410 udp6) 411 local -A fields=( 412 [dst-ip]=1 413 [dst-mac]=1 414 [dst-port]=1 415 [src-ip]=1 416 [src-port]=1 417 [tclass]=1 418 [user-def]=1 419 [vlan-etype]=1 420 [vlan]=1 421 ) 422 ;; 423 *) 424 return ;; 425 esac 426 427 if [ "${fields[$prev]+set}" ]; then 428 # Integer 429 return 430 fi 431 432 # If the previous 2 words were a field+value, suggest a mask 433 local mask= 434 if [ "${fields[${words[$cword-2]}]+set}" ]; then 435 mask="m ${words[$cword-2]}-mask" 436 fi 437 438 # Remove fields and settings which have been seen 439 local word 440 for word in "${words[@]:5:${#words[@]}-6}"; do 441 unset "fields[$word]" "settings[$word]" 442 done 443 444 # Remove mutually-exclusive options 445 if ! [ "${settings[action]+set}" ]; then 446 unset 'settings[queue]' 'settings[vf]' 447 fi 448 if ! [ "${settings[queue]+set}" ]; then 449 unset 'settings[action]' 450 fi 451 if ! [ "${settings[vf]+set}" ]; then 452 unset 'settings[action]' 453 fi 454 455 COMPREPLY=( $( compgen -W "$mask ${!fields[*]} ${!settings[*]}" -- "$cur" ) ) 456} 457 458# Completion for ethtool --config-nfc 459_ethtool_config_nfc() 460{ 461 if [ "$cword" -eq 3 ]; then 462 COMPREPLY=( $( compgen -W 'delete flow-type rx-flow-hash' -- "$cur" ) ) 463 return 464 fi 465 466 case "${words[3]}" in 467 delete) 468 # Unsigned integer 469 return ;; 470 flow-type) 471 _ethtool_config_nfc_flow_type 472 return ;; 473 rx-flow-hash) 474 case "$cword" in 475 4) 476 _ethtool_flow_type --hash 477 return ;; 478 5) 479 _ethtool_compgen_letterset m v t s d f n r 480 return ;; 481 6) 482 COMPREPLY=( $( compgen -W context -- "$cur" ) ) 483 return ;; 484 7) 485 _ethtool_context 486 return ;; 487 esac 488 return ;; 489 esac 490} 491 492# Completion for ethtool --eeprom-dump 493_ethtool_eeprom_dump() 494{ 495 local -A settings=( 496 [length]=1 497 [offset]=1 498 [raw]=1 499 ) 500 501 if [ "$prev" = raw ]; then 502 COMPREPLY=( $( compgen -W 'on off' -- "$cur" ) ) 503 return 504 fi 505 506 if [ "${settings[$prev]+set}" ]; then 507 # Unsigned integer argument 508 return 509 fi 510 511 # Remove settings which have been seen 512 local word 513 for word in "${words[@]:3:${#words[@]}-4}"; do 514 unset "settings[$word]" 515 done 516 517 COMPREPLY=( $( compgen -W "${!settings[*]}" -- "$cur" ) ) 518} 519 520# Completion for ethtool --features 521_ethtool_features() 522{ 523 local -A abbreviations=( 524 [generic-receive-offload]=gro 525 [generic-segmentation-offload]=gso 526 [large-receive-offload]=lro 527 [ntuple-filters]=ntuple 528 [receive-hashing]=rxhash 529 [rx-checksumming]=rx 530 [rx-vlan-offload]=rxvlan 531 [scatter-gather]=sg 532 [tcp-segmentation-offload]=tso 533 [tx-checksumming]=tx 534 [tx-vlan-offload]=txvlan 535 [udp-fragmentation-offload]=ufo 536 ) 537 538 local -A features=() 539 local feature status fixed 540 # shellcheck disable=SC2034 541 while read -r feature status fixed; do 542 if [ -z "$feature" ]; then 543 # Ignore blank line from empty expansion in here-document 544 continue 545 fi 546 547 if [ "$feature" = Features ]; then 548 # Ignore heading 549 continue 550 fi 551 552 if [ "$fixed" = '[fixed]' ]; then 553 # Fixed features can't be changed 554 continue 555 fi 556 557 feature=${feature%:} 558 if [ "${abbreviations[$feature]+set}" ]; then 559 features[${abbreviations[$feature]}]=1 560 else 561 features[$feature]=1 562 fi 563 done <<ETHTOOL_FEATURES 564$(PATH="$PATH:/sbin:/usr/sbin:/usr/local/sbin" \ 565 ethtool --show-features "${words[2]}" 2>/dev/null) 566ETHTOOL_FEATURES 567 568 if [ "${features[$prev]+set}" ]; then 569 COMPREPLY=( $( compgen -W 'on off' -- "$cur" ) ) 570 return 571 fi 572 573 # Remove features which have been seen 574 local word 575 for word in "${words[@]:3:${#words[@]}-4}"; do 576 unset "features[$word]" 577 done 578 579 COMPREPLY=( $( compgen -W "${!features[*]}" -- "$cur" ) ) 580} 581 582# Complete the current word as a kernel firmware file (for request_firmware) 583# See https://www.kernel.org/doc/html/latest/driver-api/firmware/core.html 584_ethtool_firmware() 585{ 586 local -a firmware_paths=( 587 /lib/firmware/updates/ 588 /lib/firmware/ 589 ) 590 591 local release 592 if release=$( uname -r 2>/dev/null ); then 593 firmware_paths+=( 594 "/lib/firmware/updates/$release/" 595 "/lib/firmware/$release/" 596 ) 597 fi 598 599 local fw_path_para 600 if fw_path_para=$( cat /sys/module/firmware_class/parameters/path 2>/dev/null ) \ 601 && [ -n "$fw_path_para" ]; then 602 firmware_paths+=( "$fw_path_para" ) 603 fi 604 605 local -A firmware_files=() 606 607 local firmware_path 608 for firmware_path in "${firmware_paths[@]}"; do 609 local firmware_file 610 for firmware_file in "$firmware_path"*; do 611 if [ -f "$firmware_file" ]; then 612 firmware_files[${firmware_file##*/}]=1 613 fi 614 done 615 done 616 617 local IFS=' 618' 619 COMPREPLY=( $( compgen -W "${!firmware_files[*]}" -- "$cur" ) ) 620} 621 622# Completion for ethtool --flash 623_ethtool_flash() 624{ 625 if [ "$cword" -eq 3 ]; then 626 _ethtool_firmware 627 return 628 fi 629} 630 631# Completion for ethtool --get-dump 632_ethtool_get_dump() 633{ 634 case "$cword" in 635 3) 636 COMPREPLY=( $( compgen -W data -- "$cur" ) ) 637 return ;; 638 4) 639 # Output filename 640 local IFS=' 641' 642 COMPREPLY=( $( compgen -f -- "$cur" ) ) 643 return ;; 644 esac 645} 646 647# Completion for ethtool --get-phy-tunable 648_ethtool_get_phy_tunable() 649{ 650 if [ "$cword" -eq 3 ]; then 651 COMPREPLY=( $( compgen -W downshift -- "$cur" ) ) 652 return 653 fi 654} 655 656# Completion for ethtool --module-info 657_ethtool_module_info() 658{ 659 local -A settings=( 660 [hex]=1 661 [length]=1 662 [offset]=1 663 [raw]=1 664 ) 665 666 case "$prev" in 667 hex|\ 668 raw) 669 COMPREPLY=( $( compgen -W 'on off' -- "$cur" ) ) 670 return ;; 671 esac 672 673 if [ "${settings[$prev]+set}" ]; then 674 # Unsigned integer argument 675 return 676 fi 677 678 # Remove settings which have been seen 679 local word 680 for word in "${words[@]:3:${#words[@]}-4}"; do 681 unset "settings[$word]" 682 done 683 684 COMPREPLY=( $( compgen -W "${!settings[*]}" -- "$cur" ) ) 685} 686 687# Completion for ethtool --pause 688_ethtool_pause() 689{ 690 local -A settings=( 691 [autoneg]=1 692 [rx]=1 693 [tx]=1 694 ) 695 696 if [ "${settings[$prev]+set}" ]; then 697 COMPREPLY=( $( compgen -W 'on off' -- "$cur" ) ) 698 return 699 fi 700 701 # Remove settings which have been seen 702 local word 703 for word in "${words[@]:3:${#words[@]}-4}"; do 704 unset "settings[$word]" 705 done 706 707 COMPREPLY=( $( compgen -W "${!settings[*]}" -- "$cur" ) ) 708} 709 710# Completion for ethtool --per-queue 711_ethtool_per_queue() 712{ 713 local -a subcommands=( 714 --coalesce 715 --show-coalesce 716 ) 717 718 if [ "$cword" -eq 3 ]; then 719 COMPREPLY=( $( compgen -W "queue_mask ${subcommands[*]}" -- "$cur" ) ) 720 return 721 fi 722 723 local sc_start=3 724 if [ "${words[3]}" = queue_mask ] ; then 725 case "$cword" in 726 4) 727 # Hex number 728 return ;; 729 5) 730 COMPREPLY=( $( compgen -W "${subcommands[*]}" -- "$cur" ) ) 731 return ;; 732 esac 733 734 sc_start=5 735 fi 736 737 case "${words[$sc_start]}" in 738 --coalesce) 739 # Remove --per-queue args to match normal --coalesce invocation 740 local words=( 741 "${words[0]}" 742 --coalesce 743 "${words[2]}" 744 "${words[@]:$sc_start+1:${#words[@]}-$sc_start-1}" 745 ) 746 _ethtool_coalesce 747 return ;; 748 --show-coalesce) 749 # No args 750 return ;; 751 esac 752} 753 754# Completion for ethtool --register-dump 755_ethtool_register_dump() 756{ 757 local -A settings=( 758 [file]=1 759 [hex]=1 760 [raw]=1 761 ) 762 763 case "$prev" in 764 hex|\ 765 raw) 766 COMPREPLY=( $( compgen -W 'on off' -- "$cur" ) ) 767 return ;; 768 file) 769 local IFS=' 770' 771 COMPREPLY=( $( compgen -f -- "$cur" ) ) 772 return ;; 773 esac 774 775 # Remove settings which have been seen 776 local word 777 for word in "${words[@]:3:${#words[@]}-4}"; do 778 unset "settings[$word]" 779 done 780 781 COMPREPLY=( $( compgen -W "${!settings[*]}" -- "$cur" ) ) 782} 783 784# Completion for ethtool --reset 785_ethtool_reset() 786{ 787 if [ "$prev" = flags ]; then 788 # Unsigned integer 789 return 790 fi 791 792 local -A flag_names=( 793 [ap]=1 794 [dma]=1 795 [filter]=1 796 [irq]=1 797 [mac]=1 798 [mgmt]=1 799 [offload]=1 800 [phy]=1 801 [ram]=1 802 ) 803 804 local -A all_flag_names=() 805 local flag_name 806 for flag_name in "${!flag_names[@]}"; do 807 all_flag_names[$flag_name]=1 808 all_flag_names[$flag_name-shared]=1 809 done 810 811 # Remove all_flag_names which have been seen 812 local any_dedicated= 813 local word 814 for word in "${words[@]:3:${#words[@]}-4}"; do 815 case "$word" in 816 all) 817 # Flags are always additive. 818 # Nothing to add after "all". 819 return ;; 820 dedicated) 821 any_dedicated=1 822 # "dedicated" sets all non-shared flags 823 for flag_name in "${!flag_names[@]}"; do 824 unset "all_flag_names[$flag_name]" 825 done 826 continue ;; 827 esac 828 829 if [ "${flag_names[$word]+set}" ]; then 830 any_dedicated=1 831 fi 832 833 unset "all_flag_names[$word]" 834 done 835 836 COMPREPLY=( $( compgen -W "${!all_flag_names[*]}" -- "$cur" ) ) 837 838 # Although it is permitted to mix named and un-named flags or duplicate 839 # flags with "all" or "dedicated", it's not likely intentional. 840 # Reconsider if a real use-case (or good consistency argument) is found. 841 if [ "$cword" -eq 3 ]; then 842 COMPREPLY+=( all dedicated flags ) 843 elif [ -z "$any_dedicated" ]; then 844 COMPREPLY+=( dedicated ) 845 fi 846} 847 848# Completion for ethtool --rxfh 849_ethtool_rxfh() 850{ 851 local -A settings=( 852 [context]=1 853 [default]=1 854 [delete]=1 855 [equal]=1 856 [hfunc]=1 857 [hkey]=1 858 [weight]=1 859 ) 860 861 case "$prev" in 862 context) 863 _ethtool_context 864 # "new" to create a new context 865 COMPREPLY+=( new ) 866 return ;; 867 equal) 868 # Positive integer 869 return ;; 870 hfunc) 871 # Complete available RSS hash functions 872 COMPREPLY=( 873 $(_ethtool_get_names_in_section 'RSS hash function' \ 874 --show-rxfh "${words[2]}") 875 ) 876 return ;; 877 hkey) 878 # Pairs of hex digits separated by : 879 return ;; 880 weight) 881 # Non-negative integer 882 return ;; 883 esac 884 885 local word 886 for word in "${words[@]:3:${#words[@]}-4}"; do 887 # Remove settings which have been seen 888 unset "settings[$word]" 889 890 # Remove settings which are mutually-exclusive with seen settings 891 case "$word" in 892 context) 893 unset 'settings[default]' 894 ;; 895 default) 896 unset \ 897 'settings[context]' \ 898 'settings[delete]' \ 899 'settings[equal]' \ 900 'settings[weight]' 901 ;; 902 delete) 903 unset \ 904 'settings[default]' \ 905 'settings[equal]' \ 906 'settings[hkey]' \ 907 'settings[weight]' 908 ;; 909 equal) 910 unset \ 911 'settings[default]' \ 912 'settings[delete]' \ 913 'settings[weight]' 914 ;; 915 hkey) 916 unset 'settings[delete]' 917 ;; 918 weight) 919 unset \ 920 'settings[default]' \ 921 'settings[delete]' \ 922 'settings[equal]' 923 ;; 924 esac 925 done 926 927 928 COMPREPLY=( $( compgen -W "${!settings[*]}" -- "$cur" ) ) 929} 930 931# Completion for ethtool --set-channels 932_ethtool_set_channels() 933{ 934 local -A settings=( 935 [combined]=1 936 [other]=1 937 [rx]=1 938 [tx]=1 939 ) 940 941 if [ "${settings[$prev]+set}" ]; then 942 # Unsigned integer argument 943 return 944 fi 945 946 # Remove settings which have been seen 947 local word 948 for word in "${words[@]:3:${#words[@]}-4}"; do 949 unset "settings[$word]" 950 done 951 952 COMPREPLY=( $( compgen -W "${!settings[*]}" -- "$cur" ) ) 953} 954 955# Completion for ethtool --set-eee 956_ethtool_set_eee() 957{ 958 local -A settings=( 959 [advertise]=1 960 [eee]=1 961 [tx-lpi]=1 962 [tx-timer]=1 963 ) 964 965 case "$prev" in 966 advertise|\ 967 tx-timer) 968 # Unsigned integer 969 return ;; 970 eee|\ 971 tx-lpi) 972 COMPREPLY=( $( compgen -W 'on off' -- "$cur" ) ) 973 return ;; 974 esac 975 976 # Remove settings which have been seen 977 local word 978 for word in "${words[@]:3:${#words[@]}-4}"; do 979 unset "settings[$word]" 980 done 981 982 COMPREPLY=( $( compgen -W "${!settings[*]}" -- "$cur" ) ) 983} 984 985# Completion for ethtool --set-fec 986_ethtool_set_fec() 987{ 988 if [ "$cword" -eq 3 ]; then 989 COMPREPLY=( $( compgen -W encoding -- "$cur" ) ) 990 return 991 fi 992 993 local -A modes=( 994 [auto]=auto 995 [rs]=RS 996 [off]=off 997 [baser]=BaseR 998 ) 999 1000 # Remove modes which have been seen 1001 local word 1002 for word in "${words[@]:3:${#words[@]}-4}"; do 1003 # ethtool recognizes modes case-insensitively 1004 unset "modes[${word,,}]" 1005 done 1006 1007 _ethtool_compgen_nocase "${modes[@]}" 1008} 1009 1010# Completion for ethtool --set-phy-tunable 1011_ethtool_set_phy_tunable() 1012{ 1013 case "$cword" in 1014 3) 1015 COMPREPLY=( $( compgen -W downshift -- "$cur" ) ) 1016 return ;; 1017 4) 1018 COMPREPLY=( $( compgen -W 'on off' -- "$cur" ) ) 1019 return ;; 1020 5) 1021 COMPREPLY=( $( compgen -W count -- "$cur" ) ) 1022 return ;; 1023 esac 1024} 1025 1026# Completion for ethtool --set-priv-flags 1027_ethtool_set_priv_flags() 1028{ 1029 if [ $(( cword % 2 )) -eq 0 ]; then 1030 COMPREPLY=( $( compgen -W 'on off' -- "$cur" ) ) 1031 return 1032 fi 1033 1034 # Get available private flags 1035 local -A flags=() 1036 local flag 1037 while IFS= read -r flag; do 1038 # Ignore blank line from empty here-document 1039 if [ -n "$flag" ]; then 1040 flags[$flag]=1 1041 fi 1042 done <<ETHTOOL_PRIV_FLAGS 1043$(_ethtool_get_names_in_section \ 1044 'Private flags for [[:graph:]]*' --show-priv-flags "${words[2]}") 1045ETHTOOL_PRIV_FLAGS 1046 1047 # Remove flags which have been seen 1048 local word 1049 for word in "${words[@]:3:${#words[@]}-4}"; do 1050 unset "flags[$word]" 1051 done 1052 1053 COMPREPLY=( $( compgen -W "${!flags[*]}" -- "$cur" ) ) 1054} 1055 1056# Completion for ethtool --set-ring 1057_ethtool_set_ring() 1058{ 1059 local -A settings=( 1060 [rx-jumbo]=1 1061 [rx-mini]=1 1062 [rx]=1 1063 [tx]=1 1064 ) 1065 1066 if [ "${settings[$prev]+set}" ]; then 1067 # Unsigned integer argument 1068 return 1069 fi 1070 1071 # Remove settings which have been seen 1072 local word 1073 for word in "${words[@]:3:${#words[@]}-4}"; do 1074 unset "settings[$word]" 1075 done 1076 1077 COMPREPLY=( $( compgen -W "${!settings[*]}" -- "$cur" ) ) 1078} 1079 1080# Completion for ethtool --show-nfc 1081_ethtool_show_nfc() 1082{ 1083 if [ "$cword" -eq 3 ]; then 1084 COMPREPLY=( $( compgen -W 'rule rx-flow-hash' -- "$cur" ) ) 1085 return 1086 fi 1087 1088 case "${words[3]}" in 1089 rule) 1090 if [ "$cword" -eq 4 ]; then 1091 COMPREPLY=( 1092 $(PATH="$PATH:/sbin:/usr/sbin:/usr/local/sbin" \ 1093 ethtool --show-nfc "${words[2]}" 2>/dev/null | 1094 command sed -n 's/^Filter:[[:space:]]*\([0-9]*\)$/\1/p') 1095 ) 1096 fi 1097 return ;; 1098 rx-flow-hash) 1099 case "$cword" in 1100 4) 1101 _ethtool_flow_type --hash 1102 return ;; 1103 5) 1104 COMPREPLY=( $( compgen -W context -- "$cur" ) ) 1105 return ;; 1106 6) 1107 _ethtool_context 1108 return ;; 1109 esac 1110 ;; 1111 esac 1112} 1113 1114# Completion for ethtool --show-rxfh 1115_ethtool_show_rxfh() 1116{ 1117 case "$cword" in 1118 3) 1119 COMPREPLY=( $( compgen -W context -- "$cur" ) ) 1120 return ;; 1121 4) 1122 _ethtool_context 1123 return ;; 1124 esac 1125} 1126 1127# Completion for ethtool --test 1128_ethtool_test() 1129{ 1130 if [ "$cword" -eq 3 ]; then 1131 COMPREPLY=( $( compgen -W 'external_lb offline online' -- "$cur" ) ) 1132 return 1133 fi 1134} 1135 1136 1137# Complete any ethtool command 1138_ethtool() 1139{ 1140 local cur prev words cword 1141 _init_completion || return 1142 1143 # Per "Contributing to bash-completion", complete non-duplicate long opts 1144 local -A suggested_funcs=( 1145 [--change-eeprom]=change_eeprom 1146 [--change]=change 1147 [--coalesce]=coalesce 1148 [--config-nfc]=config_nfc 1149 [--driver]=devname 1150 [--dump-module-eeprom]=module_info 1151 [--eeprom-dump]=eeprom_dump 1152 [--features]=features 1153 [--flash]=flash 1154 [--get-dump]=get_dump 1155 [--get-phy-tunable]=get_phy_tunable 1156 [--identify]=devname 1157 [--module-info]=module_info 1158 [--negotiate]=devname 1159 [--offload]=features 1160 [--pause]=pause 1161 [--per-queue]=per_queue 1162 [--phy-statistics]=devname 1163 [--register-dump]=register_dump 1164 [--reset]=reset 1165 [--set-channels]=set_channels 1166 [--set-dump]=devname 1167 [--set-eee]=set_eee 1168 [--set-fec]=set_fec 1169 [--set-phy-tunable]=set_phy_tunable 1170 [--set-priv-flags]=set_priv_flags 1171 [--set-ring]=set_ring 1172 [--set-rxfh-indir]=rxfh 1173 [--show-channels]=devname 1174 [--show-coalesce]=devname 1175 [--show-eee]=devname 1176 [--show-features]=devname 1177 [--show-fec]=devname 1178 [--show-nfc]=show_nfc 1179 [--show-offload]=devname 1180 [--show-pause]=devname 1181 [--show-permaddr]=devname 1182 [--show-priv-flags]=devname 1183 [--show-ring]=devname 1184 [--show-rxfh]=show_rxfh 1185 [--show-time-stamping]=devname 1186 [--statistics]=devname 1187 [--test]=test 1188 ) 1189 local -A other_funcs=( 1190 [--config-ntuple]=config_nfc 1191 [--rxfh]=rxfh 1192 [--show-ntuple]=show_nfc 1193 [--show-rxfh-indir]=devname 1194 [-A]=pause 1195 [-C]=coalesce 1196 [-E]=change_eeprom 1197 [-G]=set_ring 1198 [-K]=features 1199 [-L]=set_channels 1200 [-N]=config_nfc 1201 [-P]=devname 1202 [-Q]=per_queue 1203 [-S]=devname 1204 [-T]=devname 1205 [-U]=config_nfc 1206 [-W]=devname 1207 [-X]=rxfh 1208 [-a]=devname 1209 [-c]=devname 1210 [-d]=register_dump 1211 [-e]=eeprom_dump 1212 [-f]=flash 1213 [-g]=devname 1214 [-i]=devname 1215 [-k]=devname 1216 [-l]=devname 1217 [-m]=module_info 1218 [-n]=show_nfc 1219 [-p]=devname 1220 [-r]=devname 1221 [-s]=change 1222 [-t]=test 1223 [-u]=show_nfc 1224 [-w]=get_dump 1225 [-x]=devname 1226 ) 1227 1228 if [ "$cword" -le 1 ]; then 1229 _available_interfaces 1230 COMPREPLY+=( 1231 $( compgen -W "--help --version ${!suggested_funcs[*]}" -- "$cur" ) 1232 ) 1233 return 1234 fi 1235 1236 local func=${suggested_funcs[${words[1]}]-${other_funcs[${words[1]}]-}} 1237 if [ "$func" ]; then 1238 # All sub-commands have devname as their first argument 1239 if [ "$cword" -eq 2 ]; then 1240 _available_interfaces 1241 return 1242 fi 1243 1244 if [ "$func" != devname ]; then 1245 "_ethtool_$func" 1246 fi 1247 fi 1248} && 1249complete -F _ethtool ethtool 1250 1251# ex: filetype=sh sts=8 sw=8 ts=8 noet 1252