Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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