at v4.16-rc2 414 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) 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 COMPREPLY+=( $( compgen -W 'opcodes' -- \ 228 "$cur" ) ) 229 return 0 230 ;; 231 esac 232 ;; 233 pin) 234 if [[ $prev == "$command" ]]; then 235 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) 236 else 237 _filedir 238 fi 239 return 0 240 ;; 241 load) 242 _filedir 243 return 0 244 ;; 245 *) 246 [[ $prev == $object ]] && \ 247 COMPREPLY=( $( compgen -W 'dump help pin load \ 248 show list' -- "$cur" ) ) 249 ;; 250 esac 251 ;; 252 map) 253 local MAP_TYPE='id pinned' 254 case $command in 255 show|list|dump) 256 case $prev in 257 $command) 258 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 259 return 0 260 ;; 261 id) 262 _bpftool_get_map_ids 263 return 0 264 ;; 265 *) 266 return 0 267 ;; 268 esac 269 ;; 270 lookup|getnext|delete) 271 case $prev in 272 $command) 273 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 274 return 0 275 ;; 276 id) 277 _bpftool_get_map_ids 278 return 0 279 ;; 280 key) 281 return 0 282 ;; 283 *) 284 _bpftool_once_attr 'key' 285 return 0 286 ;; 287 esac 288 ;; 289 update) 290 case $prev in 291 $command) 292 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 293 return 0 294 ;; 295 id) 296 _bpftool_map_update_get_id 297 return 0 298 ;; 299 key) 300 return 0 301 ;; 302 value) 303 # We can have bytes, or references to a prog or a 304 # map, depending on the type of the map to update. 305 case $(_bpftool_map_update_map_type) in 306 array_of_maps|hash_of_maps) 307 local MAP_TYPE='id pinned' 308 COMPREPLY+=( $( compgen -W "$MAP_TYPE" \ 309 -- "$cur" ) ) 310 return 0 311 ;; 312 prog_array) 313 local PROG_TYPE='id pinned tag' 314 COMPREPLY+=( $( compgen -W "$PROG_TYPE" \ 315 -- "$cur" ) ) 316 return 0 317 ;; 318 *) 319 return 0 320 ;; 321 esac 322 return 0 323 ;; 324 *) 325 _bpftool_once_attr 'key' 326 local UPDATE_FLAGS='any exist noexist' 327 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do 328 if [[ ${words[idx]} == 'value' ]]; then 329 # 'value' is present, but is not the last 330 # word i.e. we can now have UPDATE_FLAGS. 331 _bpftool_one_of_list "$UPDATE_FLAGS" 332 return 0 333 fi 334 done 335 for (( idx=3; idx < ${#words[@]}-1; idx++ )); do 336 if [[ ${words[idx]} == 'key' ]]; then 337 # 'key' is present, but is not the last 338 # word i.e. we can now have 'value'. 339 _bpftool_once_attr 'value' 340 return 0 341 fi 342 done 343 return 0 344 ;; 345 esac 346 ;; 347 pin) 348 if [[ $prev == "$command" ]]; then 349 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) 350 else 351 _filedir 352 fi 353 return 0 354 ;; 355 *) 356 [[ $prev == $object ]] && \ 357 COMPREPLY=( $( compgen -W 'delete dump getnext help \ 358 lookup pin show list update' -- "$cur" ) ) 359 ;; 360 esac 361 ;; 362 cgroup) 363 case $command in 364 show|list) 365 _filedir 366 return 0 367 ;; 368 attach|detach) 369 local ATTACH_TYPES='ingress egress sock_create sock_ops \ 370 device' 371 local ATTACH_FLAGS='multi override' 372 local PROG_TYPE='id pinned tag' 373 case $prev in 374 $command) 375 _filedir 376 return 0 377 ;; 378 ingress|egress|sock_create|sock_ops|device) 379 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \ 380 "$cur" ) ) 381 return 0 382 ;; 383 id) 384 _bpftool_get_prog_ids 385 return 0 386 ;; 387 *) 388 if ! _bpftool_search_list "$ATTACH_TYPES"; then 389 COMPREPLY=( $( compgen -W "$ATTACH_TYPES" -- \ 390 "$cur" ) ) 391 elif [[ "$command" == "attach" ]]; then 392 # We have an attach type on the command line, 393 # but it is not the previous word, or 394 # "id|pinned|tag" (we already checked for 395 # that). This should only leave the case when 396 # we need attach flags for "attach" commamnd. 397 _bpftool_one_of_list "$ATTACH_FLAGS" 398 fi 399 return 0 400 ;; 401 esac 402 ;; 403 *) 404 [[ $prev == $object ]] && \ 405 COMPREPLY=( $( compgen -W 'help attach detach \ 406 show list' -- "$cur" ) ) 407 ;; 408 esac 409 ;; 410 esac 411} && 412complete -F _bpftool bpftool 413 414# ex: ts=4 sw=4 et filetype=sh