at v4.18 465 lines 17 kB view raw
1# bpftool(8) bash completion -*- shell-script -*- 2# 3# Copyright (C) 2017-2018 Netronome Systems, Inc. 4# 5# This software is dual licensed under the GNU General License 6# Version 2, June 1991 as shown in the file COPYING in the top-level 7# directory of this source tree or the BSD 2-Clause License provided 8# below. You have the option to license this software under the 9# complete terms of either license. 10# 11# The BSD 2-Clause License: 12# 13# Redistribution and use in source and binary forms, with or 14# without modification, are permitted provided that the following 15# conditions are met: 16# 17# 1. Redistributions of source code must retain the above 18# copyright notice, this list of conditions and the following 19# disclaimer. 20# 21# 2. Redistributions in binary form must reproduce the above 22# copyright notice, this list of conditions and the following 23# disclaimer in the documentation and/or other materials 24# provided with the distribution. 25# 26# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 27# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 28# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 29# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 30# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 31# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 32# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 33# SOFTWARE. 34# 35# Author: Quentin Monnet <quentin.monnet@netronome.com> 36 37# Takes a list of words in argument; each one of them is added to COMPREPLY if 38# it is not already present on the command line. Returns no value. 39_bpftool_once_attr() 40{ 41 local w idx found 42 for w in $*; do 43 found=0 44 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do 45 if [[ $w == ${words[idx]} ]]; then 46 found=1 47 break 48 fi 49 done 50 [[ $found -eq 0 ]] && \ 51 COMPREPLY+=( $( compgen -W "$w" -- "$cur" ) ) 52 done 53} 54 55# Takes a list of words as argument; if any of those words is present on the 56# command line, return 0. Otherwise, return 1. 57_bpftool_search_list() 58{ 59 local w idx 60 for w in $*; do 61 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do 62 [[ $w == ${words[idx]} ]] && return 0 63 done 64 done 65 return 1 66} 67 68# Takes a list of words in argument; adds them all to COMPREPLY if none of them 69# is already present on the command line. Returns no value. 70_bpftool_one_of_list() 71{ 72 _bpftool_search_list $* && return 1 73 COMPREPLY+=( $( compgen -W "$*" -- "$cur" ) ) 74} 75 76_bpftool_get_map_ids() 77{ 78 COMPREPLY+=( $( compgen -W "$( bpftool -jp map 2>&1 | \ 79 command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) ) 80} 81 82_bpftool_get_perf_map_ids() 83{ 84 COMPREPLY+=( $( compgen -W "$( bpftool -jp map 2>&1 | \ 85 command grep -C2 perf_event_array | \ 86 command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) ) 87} 88 89 90_bpftool_get_prog_ids() 91{ 92 COMPREPLY+=( $( compgen -W "$( bpftool -jp prog 2>&1 | \ 93 command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) ) 94} 95 96_bpftool_get_prog_tags() 97{ 98 COMPREPLY+=( $( compgen -W "$( bpftool -jp prog 2>&1 | \ 99 command sed -n 's/.*"tag": "\(.*\)",$/\1/p' )" -- "$cur" ) ) 100} 101 102# For bpftool map update: retrieve type of the map to update. 103_bpftool_map_update_map_type() 104{ 105 local keyword ref 106 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do 107 if [[ ${words[$((idx-2))]} == "update" ]]; then 108 keyword=${words[$((idx-1))]} 109 ref=${words[$((idx))]} 110 fi 111 done 112 [[ -z $ref ]] && return 0 113 114 local type 115 type=$(bpftool -jp map show $keyword $ref | \ 116 command sed -n 's/.*"type": "\(.*\)",$/\1/p') 117 printf $type 118} 119 120_bpftool_map_update_get_id() 121{ 122 # Is it the map to update, or a map to insert into the map to update? 123 # Search for "value" keyword. 124 local idx value 125 for (( idx=7; idx < ${#words[@]}-1; idx++ )); do 126 if [[ ${words[idx]} == "value" ]]; then 127 value=1 128 break 129 fi 130 done 131 [[ $value -eq 0 ]] && _bpftool_get_map_ids && return 0 132 133 # Id to complete is for a value. It can be either prog id or map id. This 134 # depends on the type of the map to update. 135 local type=$(_bpftool_map_update_map_type) 136 case $type in 137 array_of_maps|hash_of_maps) 138 _bpftool_get_map_ids 139 return 0 140 ;; 141 prog_array) 142 _bpftool_get_prog_ids 143 return 0 144 ;; 145 *) 146 return 0 147 ;; 148 esac 149} 150 151_bpftool() 152{ 153 local cur prev words objword 154 _init_completion || return 155 156 # Deal with simplest keywords 157 case $prev in 158 help|hex|opcodes|visual) 159 return 0 160 ;; 161 tag) 162 _bpftool_get_prog_tags 163 return 0 164 ;; 165 file|pinned) 166 _filedir 167 return 0 168 ;; 169 batch) 170 COMPREPLY=( $( compgen -W 'file' -- "$cur" ) ) 171 return 0 172 ;; 173 esac 174 175 # Search for object and command 176 local object command cmdword 177 for (( cmdword=1; cmdword < ${#words[@]}-1; cmdword++ )); do 178 [[ -n $object ]] && command=${words[cmdword]} && break 179 [[ ${words[cmdword]} != -* ]] && object=${words[cmdword]} 180 done 181 182 if [[ -z $object ]]; then 183 case $cur in 184 -*) 185 local c='--version --json --pretty' 186 COMPREPLY=( $( compgen -W "$c" -- "$cur" ) ) 187 return 0 188 ;; 189 *) 190 COMPREPLY=( $( compgen -W "$( bpftool help 2>&1 | \ 191 command sed \ 192 -e '/OBJECT := /!d' \ 193 -e 's/.*{//' \ 194 -e 's/}.*//' \ 195 -e 's/|//g' )" -- "$cur" ) ) 196 COMPREPLY+=( $( compgen -W 'batch help' -- "$cur" ) ) 197 return 0 198 ;; 199 esac 200 fi 201 202 [[ $command == help ]] && return 0 203 204 # Completion depends on object and command in use 205 case $object in 206 prog) 207 case $prev in 208 id) 209 _bpftool_get_prog_ids 210 return 0 211 ;; 212 esac 213 214 local PROG_TYPE='id pinned tag' 215 case $command in 216 show|list) 217 [[ $prev != "$command" ]] && return 0 218 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) 219 return 0 220 ;; 221 dump) 222 case $prev in 223 $command) 224 COMPREPLY+=( $( compgen -W "xlated jited" -- \ 225 "$cur" ) ) 226 return 0 227 ;; 228 xlated|jited) 229 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \ 230 "$cur" ) ) 231 return 0 232 ;; 233 *) 234 _bpftool_once_attr 'file' 235 if _bpftool_search_list 'xlated'; then 236 COMPREPLY+=( $( compgen -W 'opcodes visual' -- \ 237 "$cur" ) ) 238 else 239 COMPREPLY+=( $( compgen -W 'opcodes' -- \ 240 "$cur" ) ) 241 fi 242 return 0 243 ;; 244 esac 245 ;; 246 pin) 247 if [[ $prev == "$command" ]]; then 248 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) 249 else 250 _filedir 251 fi 252 return 0 253 ;; 254 load) 255 _filedir 256 return 0 257 ;; 258 *) 259 [[ $prev == $object ]] && \ 260 COMPREPLY=( $( compgen -W 'dump help pin load \ 261 show list' -- "$cur" ) ) 262 ;; 263 esac 264 ;; 265 map) 266 local MAP_TYPE='id pinned' 267 case $command in 268 show|list|dump) 269 case $prev in 270 $command) 271 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 272 return 0 273 ;; 274 id) 275 _bpftool_get_map_ids 276 return 0 277 ;; 278 *) 279 return 0 280 ;; 281 esac 282 ;; 283 lookup|getnext|delete) 284 case $prev in 285 $command) 286 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 287 return 0 288 ;; 289 id) 290 _bpftool_get_map_ids 291 return 0 292 ;; 293 key) 294 COMPREPLY+=( $( compgen -W 'hex' -- "$cur" ) ) 295 ;; 296 *) 297 _bpftool_once_attr 'key' 298 return 0 299 ;; 300 esac 301 ;; 302 update) 303 case $prev in 304 $command) 305 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 306 return 0 307 ;; 308 id) 309 _bpftool_map_update_get_id 310 return 0 311 ;; 312 key) 313 COMPREPLY+=( $( compgen -W 'hex' -- "$cur" ) ) 314 ;; 315 value) 316 # We can have bytes, or references to a prog or a 317 # map, depending on the type of the map to update. 318 case $(_bpftool_map_update_map_type) in 319 array_of_maps|hash_of_maps) 320 local MAP_TYPE='id pinned' 321 COMPREPLY+=( $( compgen -W "$MAP_TYPE" \ 322 -- "$cur" ) ) 323 return 0 324 ;; 325 prog_array) 326 local PROG_TYPE='id pinned tag' 327 COMPREPLY+=( $( compgen -W "$PROG_TYPE" \ 328 -- "$cur" ) ) 329 return 0 330 ;; 331 *) 332 COMPREPLY+=( $( compgen -W 'hex' \ 333 -- "$cur" ) ) 334 return 0 335 ;; 336 esac 337 return 0 338 ;; 339 *) 340 _bpftool_once_attr 'key' 341 local UPDATE_FLAGS='any exist noexist' 342 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do 343 if [[ ${words[idx]} == 'value' ]]; then 344 # 'value' is present, but is not the last 345 # word i.e. we can now have UPDATE_FLAGS. 346 _bpftool_one_of_list "$UPDATE_FLAGS" 347 return 0 348 fi 349 done 350 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do 351 if [[ ${words[idx]} == 'key' ]]; then 352 # 'key' is present, but is not the last 353 # word i.e. we can now have 'value'. 354 _bpftool_once_attr 'value' 355 return 0 356 fi 357 done 358 return 0 359 ;; 360 esac 361 ;; 362 pin) 363 if [[ $prev == "$command" ]]; then 364 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) 365 else 366 _filedir 367 fi 368 return 0 369 ;; 370 event_pipe) 371 case $prev in 372 $command) 373 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 374 return 0 375 ;; 376 id) 377 _bpftool_get_perf_map_ids 378 return 0 379 ;; 380 cpu) 381 return 0 382 ;; 383 index) 384 return 0 385 ;; 386 *) 387 _bpftool_once_attr 'cpu' 388 _bpftool_once_attr 'index' 389 return 0 390 ;; 391 esac 392 ;; 393 *) 394 [[ $prev == $object ]] && \ 395 COMPREPLY=( $( compgen -W 'delete dump getnext help \ 396 lookup pin event_pipe show list update' -- \ 397 "$cur" ) ) 398 ;; 399 esac 400 ;; 401 cgroup) 402 case $command in 403 show|list) 404 _filedir 405 return 0 406 ;; 407 attach|detach) 408 local ATTACH_TYPES='ingress egress sock_create sock_ops \ 409 device bind4 bind6 post_bind4 post_bind6 connect4 \ 410 connect6 sendmsg4 sendmsg6' 411 local ATTACH_FLAGS='multi override' 412 local PROG_TYPE='id pinned tag' 413 case $prev in 414 $command) 415 _filedir 416 return 0 417 ;; 418 ingress|egress|sock_create|sock_ops|device|bind4|bind6|\ 419 post_bind4|post_bind6|connect4|connect6|sendmsg4|\ 420 sendmsg6) 421 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \ 422 "$cur" ) ) 423 return 0 424 ;; 425 id) 426 _bpftool_get_prog_ids 427 return 0 428 ;; 429 *) 430 if ! _bpftool_search_list "$ATTACH_TYPES"; then 431 COMPREPLY=( $( compgen -W "$ATTACH_TYPES" -- \ 432 "$cur" ) ) 433 elif [[ "$command" == "attach" ]]; then 434 # We have an attach type on the command line, 435 # but it is not the previous word, or 436 # "id|pinned|tag" (we already checked for 437 # that). This should only leave the case when 438 # we need attach flags for "attach" commamnd. 439 _bpftool_one_of_list "$ATTACH_FLAGS" 440 fi 441 return 0 442 ;; 443 esac 444 ;; 445 *) 446 [[ $prev == $object ]] && \ 447 COMPREPLY=( $( compgen -W 'help attach detach \ 448 show list' -- "$cur" ) ) 449 ;; 450 esac 451 ;; 452 perf) 453 case $command in 454 *) 455 [[ $prev == $object ]] && \ 456 COMPREPLY=( $( compgen -W 'help \ 457 show list' -- "$cur" ) ) 458 ;; 459 esac 460 ;; 461 esac 462} && 463complete -F _bpftool bpftool 464 465# ex: ts=4 sw=4 et filetype=sh