at v4.17-rc6 419 lines 15 kB view raw
1# bpftool(8) bash completion -*- shell-script -*- 2# 3# Copyright (C) 2017 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_prog_ids() 83{ 84 COMPREPLY+=( $( compgen -W "$( bpftool -jp prog 2>&1 | \ 85 command sed -n 's/.*"id": \(.*\),$/\1/p' )" -- "$cur" ) ) 86} 87 88_bpftool_get_prog_tags() 89{ 90 COMPREPLY+=( $( compgen -W "$( bpftool -jp prog 2>&1 | \ 91 command sed -n 's/.*"tag": "\(.*\)",$/\1/p' )" -- "$cur" ) ) 92} 93 94# For bpftool map update: retrieve type of the map to update. 95_bpftool_map_update_map_type() 96{ 97 local keyword ref 98 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do 99 if [[ ${words[$((idx-2))]} == "update" ]]; then 100 keyword=${words[$((idx-1))]} 101 ref=${words[$((idx))]} 102 fi 103 done 104 [[ -z $ref ]] && return 0 105 106 local type 107 type=$(bpftool -jp map show $keyword $ref | \ 108 command sed -n 's/.*"type": "\(.*\)",$/\1/p') 109 printf $type 110} 111 112_bpftool_map_update_get_id() 113{ 114 # Is it the map to update, or a map to insert into the map to update? 115 # Search for "value" keyword. 116 local idx value 117 for (( idx=7; idx < ${#words[@]}-1; idx++ )); do 118 if [[ ${words[idx]} == "value" ]]; then 119 value=1 120 break 121 fi 122 done 123 [[ $value -eq 0 ]] && _bpftool_get_map_ids && return 0 124 125 # Id to complete is for a value. It can be either prog id or map id. This 126 # depends on the type of the map to update. 127 local type=$(_bpftool_map_update_map_type) 128 case $type in 129 array_of_maps|hash_of_maps) 130 _bpftool_get_map_ids 131 return 0 132 ;; 133 prog_array) 134 _bpftool_get_prog_ids 135 return 0 136 ;; 137 *) 138 return 0 139 ;; 140 esac 141} 142 143_bpftool() 144{ 145 local cur prev words objword 146 _init_completion || return 147 148 # Deal with simplest keywords 149 case $prev in 150 help|key|opcodes|visual) 151 return 0 152 ;; 153 tag) 154 _bpftool_get_prog_tags 155 return 0 156 ;; 157 file|pinned) 158 _filedir 159 return 0 160 ;; 161 batch) 162 COMPREPLY=( $( compgen -W 'file' -- "$cur" ) ) 163 return 0 164 ;; 165 esac 166 167 # Search for object and command 168 local object command cmdword 169 for (( cmdword=1; cmdword < ${#words[@]}-1; cmdword++ )); do 170 [[ -n $object ]] && command=${words[cmdword]} && break 171 [[ ${words[cmdword]} != -* ]] && object=${words[cmdword]} 172 done 173 174 if [[ -z $object ]]; then 175 case $cur in 176 -*) 177 local c='--version --json --pretty' 178 COMPREPLY=( $( compgen -W "$c" -- "$cur" ) ) 179 return 0 180 ;; 181 *) 182 COMPREPLY=( $( compgen -W "$( bpftool help 2>&1 | \ 183 command sed \ 184 -e '/OBJECT := /!d' \ 185 -e 's/.*{//' \ 186 -e 's/}.*//' \ 187 -e 's/|//g' )" -- "$cur" ) ) 188 COMPREPLY+=( $( compgen -W 'batch help' -- "$cur" ) ) 189 return 0 190 ;; 191 esac 192 fi 193 194 [[ $command == help ]] && return 0 195 196 # Completion depends on object and command in use 197 case $object in 198 prog) 199 case $prev in 200 id) 201 _bpftool_get_prog_ids 202 return 0 203 ;; 204 esac 205 206 local PROG_TYPE='id pinned tag' 207 case $command in 208 show|list) 209 [[ $prev != "$command" ]] && return 0 210 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) 211 return 0 212 ;; 213 dump) 214 case $prev in 215 $command) 216 COMPREPLY+=( $( compgen -W "xlated jited" -- \ 217 "$cur" ) ) 218 return 0 219 ;; 220 xlated|jited) 221 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \ 222 "$cur" ) ) 223 return 0 224 ;; 225 *) 226 _bpftool_once_attr 'file' 227 if _bpftool_search_list 'xlated'; then 228 COMPREPLY+=( $( compgen -W 'opcodes visual' -- \ 229 "$cur" ) ) 230 else 231 COMPREPLY+=( $( compgen -W 'opcodes' -- \ 232 "$cur" ) ) 233 fi 234 return 0 235 ;; 236 esac 237 ;; 238 pin) 239 if [[ $prev == "$command" ]]; then 240 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) 241 else 242 _filedir 243 fi 244 return 0 245 ;; 246 load) 247 _filedir 248 return 0 249 ;; 250 *) 251 [[ $prev == $object ]] && \ 252 COMPREPLY=( $( compgen -W 'dump help pin load \ 253 show list' -- "$cur" ) ) 254 ;; 255 esac 256 ;; 257 map) 258 local MAP_TYPE='id pinned' 259 case $command in 260 show|list|dump) 261 case $prev in 262 $command) 263 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 264 return 0 265 ;; 266 id) 267 _bpftool_get_map_ids 268 return 0 269 ;; 270 *) 271 return 0 272 ;; 273 esac 274 ;; 275 lookup|getnext|delete) 276 case $prev in 277 $command) 278 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 279 return 0 280 ;; 281 id) 282 _bpftool_get_map_ids 283 return 0 284 ;; 285 key) 286 return 0 287 ;; 288 *) 289 _bpftool_once_attr 'key' 290 return 0 291 ;; 292 esac 293 ;; 294 update) 295 case $prev in 296 $command) 297 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 298 return 0 299 ;; 300 id) 301 _bpftool_map_update_get_id 302 return 0 303 ;; 304 key) 305 return 0 306 ;; 307 value) 308 # We can have bytes, or references to a prog or a 309 # map, depending on the type of the map to update. 310 case $(_bpftool_map_update_map_type) in 311 array_of_maps|hash_of_maps) 312 local MAP_TYPE='id pinned' 313 COMPREPLY+=( $( compgen -W "$MAP_TYPE" \ 314 -- "$cur" ) ) 315 return 0 316 ;; 317 prog_array) 318 local PROG_TYPE='id pinned tag' 319 COMPREPLY+=( $( compgen -W "$PROG_TYPE" \ 320 -- "$cur" ) ) 321 return 0 322 ;; 323 *) 324 return 0 325 ;; 326 esac 327 return 0 328 ;; 329 *) 330 _bpftool_once_attr 'key' 331 local UPDATE_FLAGS='any exist noexist' 332 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do 333 if [[ ${words[idx]} == 'value' ]]; then 334 # 'value' is present, but is not the last 335 # word i.e. we can now have UPDATE_FLAGS. 336 _bpftool_one_of_list "$UPDATE_FLAGS" 337 return 0 338 fi 339 done 340 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do 341 if [[ ${words[idx]} == 'key' ]]; then 342 # 'key' is present, but is not the last 343 # word i.e. we can now have 'value'. 344 _bpftool_once_attr 'value' 345 return 0 346 fi 347 done 348 return 0 349 ;; 350 esac 351 ;; 352 pin) 353 if [[ $prev == "$command" ]]; then 354 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) 355 else 356 _filedir 357 fi 358 return 0 359 ;; 360 *) 361 [[ $prev == $object ]] && \ 362 COMPREPLY=( $( compgen -W 'delete dump getnext help \ 363 lookup pin show list update' -- "$cur" ) ) 364 ;; 365 esac 366 ;; 367 cgroup) 368 case $command in 369 show|list) 370 _filedir 371 return 0 372 ;; 373 attach|detach) 374 local ATTACH_TYPES='ingress egress sock_create sock_ops \ 375 device' 376 local ATTACH_FLAGS='multi override' 377 local PROG_TYPE='id pinned tag' 378 case $prev in 379 $command) 380 _filedir 381 return 0 382 ;; 383 ingress|egress|sock_create|sock_ops|device) 384 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \ 385 "$cur" ) ) 386 return 0 387 ;; 388 id) 389 _bpftool_get_prog_ids 390 return 0 391 ;; 392 *) 393 if ! _bpftool_search_list "$ATTACH_TYPES"; then 394 COMPREPLY=( $( compgen -W "$ATTACH_TYPES" -- \ 395 "$cur" ) ) 396 elif [[ "$command" == "attach" ]]; then 397 # We have an attach type on the command line, 398 # but it is not the previous word, or 399 # "id|pinned|tag" (we already checked for 400 # that). This should only leave the case when 401 # we need attach flags for "attach" commamnd. 402 _bpftool_one_of_list "$ATTACH_FLAGS" 403 fi 404 return 0 405 ;; 406 esac 407 ;; 408 *) 409 [[ $prev == $object ]] && \ 410 COMPREPLY=( $( compgen -W 'help attach detach \ 411 show list' -- "$cur" ) ) 412 ;; 413 esac 414 ;; 415 esac 416} && 417complete -F _bpftool bpftool 418 419# ex: ts=4 sw=4 et filetype=sh