]> git.proxmox.com Git - mirror_iproute2.git/blame - bash-completion/tc
tc: man: matchall: Update examples to include sample
[mirror_iproute2.git] / bash-completion / tc
CommitLineData
27d44f3a
QM
1# tc(8) completion -*- shell-script -*-
2# Copyright 2016 6WIND S.A.
3# Copyright 2016 Quentin Monnet <quentin.monnet@6wind.com>
4
5# Takes a list of words in argument; each one of them is added to COMPREPLY if
6# it is not already present on the command line. Returns no value.
7_tc_once_attr()
8{
9 local w subcword found
10 for w in $*; do
11 found=0
12 for (( subcword=3; subcword < ${#words[@]}-1; subcword++ )); do
13 if [[ $w == ${words[subcword]} ]]; then
14 found=1
15 break
16 fi
17 done
18 [[ $found -eq 0 ]] && \
19 COMPREPLY+=( $( compgen -W "$w" -- "$cur" ) )
20 done
21}
22
23# Takes a list of words in argument; adds them all to COMPREPLY if none of them
24# is already present on the command line. Returns no value.
25_tc_one_of_list()
26{
27 local w subcword
28 for w in $*; do
29 for (( subcword=3; subcword < ${#words[@]}-1; subcword++ )); do
30 [[ $w == ${words[subcword]} ]] && return 1
31 done
32 done
33 COMPREPLY+=( $( compgen -W "$*" -- "$cur" ) )
34}
35
36# Returns "$cur ${cur}arg1 ${cur}arg2 ..."
37_tc_expand_units()
38{
39 [[ $cur =~ ^[0-9]+ ]] || return 1
40 local value=${cur%%[^0-9]*}
41 [[ $cur == $value ]] && echo $cur
42 echo ${@/#/$value}
43}
44
45# Complete based on given word, usually $prev (or possibly the word before),
46# for when an argument or an option name has but a few possible arguments (so
47# tc does not take particular commands into account here).
48# Returns 0 is completion should stop after running this function, 1 otherwise.
49_tc_direct_complete()
50{
51 case $1 in
52 # Command options
53 dev)
54 _available_interfaces
55 return 0
56 ;;
57 classid)
58 return 0
59 ;;
60 estimator)
61 local list=$( _tc_expand_units 'secs' 'msecs' 'usecs' )
62 COMPREPLY+=( $( compgen -W "$list" -- "$cur" ) )
63 return 0
64 ;;
65 handle)
66 return 0
67 ;;
68 parent|flowid)
69 local i iface ids cmd
70 for (( i=3; i < ${#words[@]}-2; i++ )); do
71 [[ ${words[i]} == dev ]] && iface=${words[i+1]}
72 break
73 done
74 for cmd in qdisc class; do
75 if [[ -n $iface ]]; then
76 ids+=$( tc $cmd show dev $iface 2>/dev/null | \
77 cut -d\ -f 3 )" "
78 else
79 ids+=$( tc $cmd show 2>/dev/null | cut -d\ -f 3 )
80 fi
81 done
82 [[ $ids != " " ]] && \
83 COMPREPLY+=( $( compgen -W "$ids" -- "$cur" ) )
84 return 0
85 ;;
86 protocol) # list comes from lib/ll_proto.c
87 COMPREPLY+=( $( compgen -W ' 802.1Q 802.1ad 802_2 802_3 LLDP aarp \
88 all aoe arp atalk atmfate atmmpoa ax25 bpq can control cust \
89 ddcmp dec diag dna_dl dna_rc dna_rt econet ieeepup ieeepupat \
90 ip ipv4 ipv6 ipx irda lat localtalk loop mobitex ppp_disc \
91 ppp_mp ppp_ses ppptalk pup pupat rarp sca snap tipc tr_802_2 \
92 wan_ppp x25' -- "$cur" ) )
93 return 0
94 ;;
95 prio)
96 return 0
97 ;;
98 stab)
99 COMPREPLY+=( $( compgen -W 'mtu tsize mpu overhead
100 linklayer' -- "$cur" ) )
101 ;;
102
103 # Qdiscs and classes options
104 alpha|bands|beta|buckets|corrupt|debug|decrement|default|\
105 default_index|depth|direct_qlen|divisor|duplicate|ewma|flow_limit|\
106 flows|hh_limit|increment|indices|linklayer|non_hh_weight|num_tc|\
107 penalty_burst|penalty_rate|prio|priomap|probability|queues|r2q|\
108 reorder|vq|vqs)
109 return 0
110 ;;
111 setup)
112 COMPREPLY+=( $( compgen -W 'vqs' -- "$cur" ) )
113 return 0
114 ;;
115 hw)
116 COMPREPLY+=( $( compgen -W '1 0' -- "$cur" ) )
117 return 0
118 ;;
119 distribution)
120 COMPREPLY+=( $( compgen -W 'uniform normal pareto
121 paretonormal' -- "$cur" ) )
122 return 0
123 ;;
124 loss)
125 COMPREPLY+=( $( compgen -W 'random state gmodel' -- "$cur" ) )
126 return 0
127 ;;
128
129 # Qdiscs and classes options options
130 gap|gmodel|state)
131 return 0
132 ;;
133
134 # Filters options
135 map)
136 COMPREPLY+=( $( compgen -W 'key' -- "$cur" ) )
137 return 0
138 ;;
139 hash)
140 COMPREPLY+=( $( compgen -W 'keys' -- "$cur" ) )
141 return 0
142 ;;
143 indev)
144 _available_interfaces
145 return 0
146 ;;
147 eth_type)
148 COMPREPLY+=( $( compgen -W 'ipv4 ipv6' -- "$cur" ) )
149 return 0
150 ;;
151 ip_proto)
152 COMPREPLY+=( $( compgen -W 'tcp udp' -- "$cur" ) )
153 return 0
154 ;;
155
156 # Filters options options
157 key|keys)
158 [[ ${words[@]} =~ graft ]] && return 1
159 COMPREPLY+=( $( compgen -W 'src dst proto proto-src proto-dst iif \
160 priority mark nfct nfct-src nfct-dst nfct-proto-src \
161 nfct-proto-dst rt-classid sk-uid sk-gid vlan-tag rxhash' -- \
162 "$cur" ) )
163 return 0
164 ;;
165
166 # BPF options - used for filters, actions, and exec
167 export|bytecode|bytecode-file|object-file)
168 _filedir
169 return 0
170 ;;
171 object-pinned|graft) # Pinned object is probably under /sys/fs/bpf/
172 [[ -n "$cur" ]] && _filedir && return 0
173 COMPREPLY=( $( compgen -G "/sys/fs/bpf/*" -- "$cur" ) ) || _filedir
174 compopt -o nospace
175 return 0
176 ;;
177 section)
178 if (type objdump > /dev/null 2>&1) ; then
179 local fword objfile section_list
180 for (( fword=3; fword < ${#words[@]}-3; fword++ )); do
181 if [[ ${words[fword]} == object-file ]]; then
182 objfile=${words[fword+1]}
183 break
184 fi
185 done
186 section_list=$( objdump -h $objfile 2>/dev/null | \
187 sed -n 's/^ *[0-9]\+ \([^ ]*\) *.*/\1/p' )
188 COMPREPLY+=( $( compgen -W "$section_list" -- "$cur" ) )
189 fi
190 return 0
191 ;;
192 import|run)
193 _filedir
194 return 0
195 ;;
196 type)
197 COMPREPLY+=( $( compgen -W 'cls act' -- "$cur" ) )
198 return 0
199 ;;
200
201 # Actions options
202 random)
203 _tc_one_of_list 'netrand determ'
204 return 0
205 ;;
206
207 # Units for option arguments
208 bandwidth|maxrate|peakrate|rate)
209 local list=$( _tc_expand_units 'bit' \
210 'kbit' 'kibit' 'kbps' 'kibps' \
211 'mbit' 'mibit' 'mbps' 'mibps' \
212 'gbit' 'gibit' 'gbps' 'gibps' \
213 'tbit' 'tibit' 'tbps' 'tibps' )
214 COMPREPLY+=( $( compgen -W "$list" -- "$cur" ) )
215 ;;
216 admit_bytes|avpkt|burst|cell|initial_quantum|limit|max|min|mtu|mpu|\
217 overhead|quantum|redflowlist)
218 local list=$( _tc_expand_units \
219 'b' 'kbit' 'k' 'mbit' 'm' 'gbit' 'g' )
220 COMPREPLY+=( $( compgen -W "$list" -- "$cur" ) )
221 ;;
222 db|delay|evict_timeout|interval|latency|perturb|rehash|reset_timeout|\
223 target|tupdate)
224 local list=$( _tc_expand_units 'secs' 'msecs' 'usecs' )
225 COMPREPLY+=( $( compgen -W "$list" -- "$cur" ) )
226 ;;
227 esac
228 return 1
229}
230
231# Complete with options names for qdiscs. Each qdisc has its own set of options
232# and it seems we cannot really parse it from anywhere, so we add it manually
233# in this function.
234# Returns 0 is completion should stop after running this function, 1 otherwise.
235_tc_qdisc_options()
236{
237 case $1 in
238 choke)
239 _tc_once_attr 'limit bandwidth ecn min max burst'
240 return 0
241 ;;
242 codel)
243 _tc_once_attr 'limit target interval'
244 _tc_one_of_list 'ecn noecn'
245 return 0
246 ;;
247 bfifo|pfifo|pfifo_head_drop)
248 _tc_once_attr 'limit'
249 return 0
250 ;;
251 fq)
252 _tc_once_attr 'limit flow_limit quantum initial_quantum maxrate \
253 buckets'
254 _tc_one_of_list 'pacing nopacing'
255 return 0
256 ;;
257 fq_codel)
258 _tc_once_attr 'limit flows target interval quantum'
259 _tc_one_of_list 'ecn noecn'
260 return 0
261 ;;
262 gred)
263 _tc_once_attr 'setup vqs default grio vq prio limit min max avpkt \
264 burst probability bandwidth'
265 return 0
266 ;;
267 hhf)
268 _tc_once_attr 'limit quantum hh_limit reset_timeout admit_bytes \
269 evict_timeout non_hh_weight'
270 return 0
271 ;;
272 mqprio)
273 _tc_once_attr 'num_tc map queues hw'
274 return 0
275 ;;
276 netem)
277 _tc_once_attr 'delay distribution corrupt duplicate loss ecn \
278 reorder rate'
279 return 0
280 ;;
281 pie)
282 _tc_once_attr 'limit target tupdate alpha beta'
283 _tc_one_of_list 'bytemode nobytemode'
284 _tc_one_of_list 'ecn noecn'
285 return 0
286 ;;
287 red)
288 _tc_once_attr 'limit min max avpkt burst adaptive probability \
289 bandwidth ecn harddrop'
290 return 0
291 ;;
292 rr|prio)
293 _tc_once_attr 'bands priomap multiqueue'
294 return 0
295 ;;
296 sfb)
297 _tc_once_attr 'rehash db limit max target increment decrement \
298 penalty_rate penalty_burst'
299 return 0
300 ;;
301 sfq)
302 _tc_once_attr 'limit perturb quantum divisor flows depth headdrop \
303 redflowlimit min max avpkt burst probability ecn harddrop'
304 return 0
305 ;;
306 tbf)
307 _tc_once_attr 'limit burst rate mtu peakrate latency overhead \
308 linklayer'
309 return 0
310 ;;
311 cbq)
312 _tc_once_attr 'bandwidth avpkt mpu cell ewma'
313 return 0
314 ;;
315 dsmark)
316 _tc_once_attr 'indices default_index set_tc_index'
317 return 0
318 ;;
319 hfsc)
320 _tc_once_attr 'default'
321 return 0
322 ;;
323 htb)
324 _tc_once_attr 'default r2q direct_qlen debug'
325 return 0
326 ;;
327 multiq|pfifo_fast|atm|drr|qfq)
328 return 0
329 ;;
330 esac
331 return 1
332}
333
334# Complete with options names for BPF filters or actions.
335# Returns 0 is completion should stop after running this function, 1 otherwise.
336_tc_bpf_options()
337{
338 [[ ${words[${#words[@]}-3]} == object-file ]] && \
339 _tc_once_attr 'section export'
340 [[ ${words[${#words[@]}-5]} == object-file ]] && \
341 [[ ${words[${#words[@]}-3]} =~ (section|export) ]] && \
342 _tc_once_attr 'section export'
343 _tc_one_of_list 'bytecode bytecode-file object-file object-pinned'
344 _tc_once_attr 'verbose index direct-action action classid'
345 return 0
346}
347
348# Complete with options names for filters.
349# Returns 0 is completion should stop after running this function, 1 otherwise.
350_tc_filter_options()
351{
352 case $1 in
353 basic)
354 _tc_once_attr 'match action classid'
355 return 0
356 ;;
357 bpf)
358 _tc_bpf_options
359 return 0
360 ;;
361 cgroup)
362 _tc_once_attr 'match action'
363 return 0
364 ;;
365 flow)
366 local i
367 for (( i=5; i < ${#words[@]}-1; i++ )); do
368 if [[ ${words[i]} =~ ^keys?$ ]]; then
369 _tc_direct_complete 'key'
370 COMPREPLY+=( $( compgen -W 'or and xor rshift addend' -- \
371 "$cur" ) )
372 break
373 fi
374 done
375 _tc_once_attr 'map hash divisor baseclass match action'
376 return 0
377 ;;
378 flower)
379 _tc_once_attr 'action classid indev dst_mac src_mac eth_type \
380 ip_proto dst_ip src_ip dst_port src_port'
381 return 0
382 ;;
383 fw)
384 _tc_once_attr 'action classid'
385 return 0
386 ;;
387 route)
388 _tc_one_of_list 'from fromif'
389 _tc_once_attr 'to classid action'
390 return 0
391 ;;
392 rsvp)
393 _tc_once_attr 'ipproto session sender classid action tunnelid \
394 tunnel flowlabel spi/ah spi/esp u8 u16 u32'
395 [[ ${words[${#words[@]}-3]} == tunnel ]] && \
396 COMPREPLY+=( $( compgen -W 'skip' -- "$cur" ) )
397 [[ ${words[${#words[@]}-3]} =~ u(8|16|32) ]] && \
398 COMPREPLY+=( $( compgen -W 'mask' -- "$cur" ) )
399 [[ ${words[${#words[@]}-3]} == mask ]] && \
400 COMPREPLY+=( $( compgen -W 'at' -- "$cur" ) )
401 return 0
402 ;;
403 tcindex)
404 _tc_once_attr 'hash mask shift classid action'
405 _tc_one_of_list 'pass_on fall_through'
406 return 0
407 ;;
408 u32)
409 _tc_once_attr 'match link classid action offset ht hashkey sample'
410 COMPREPLY+=( $( compgen -W 'ip ip6 udp tcp icmp u8 u16 u32 mark \
411 divisor' -- "$cur" ) )
412 return 0
413 ;;
414 esac
415 return 1
416}
417
418# Complete with options names for actions.
419# Returns 0 is completion should stop after running this function, 1 otherwise.
420_tc_action_options()
421{
422 case $1 in
423 bpf)
424 _tc_bpf_options
425 return 0
426 ;;
427 mirred)
428 _tc_one_of_list 'ingress egress'
429 _tc_one_of_list 'mirror redirect'
430 _tc_once_attr 'index dev'
431 return 0
432 ;;
0b1abd84
YG
433 sample)
434 _tc_once_attr 'rate'
435 _tc_once_attr 'trunc'
436 _tc_once_attr 'group'
437 return 0
438 ;;
27d44f3a
QM
439 gact)
440 _tc_one_of_list 'reclassify drop continue pass'
441 _tc_once_attr 'random'
442 return 0
443 ;;
444 esac
445 return 1
446}
447
448# Complete with options names for exec.
449# Returns 0 is completion should stop after running this function, 1 otherwise.
450_tc_exec_options()
451{
452 case $1 in
453 import)
454 [[ ${words[${#words[@]}-3]} == import ]] && \
455 _tc_once_attr 'run'
456 return 0
457 ;;
458 graft)
459 COMPREPLY+=( $( compgen -W 'key type' -- "$cur" ) )
460 [[ ${words[${#words[@]}-3]} == object-file ]] && \
461 _tc_once_attr 'type'
462 _tc_bpf_options
463 return 0
464 ;;
465 esac
466 return 1
467}
468
469# Main completion function
470# Logic is as follows:
471# 1. Check if previous word is a global option; if so, propose arguments.
472# 2. Check if current word is a global option; if so, propose completion.
473# 3. Check for the presence of a main command (qdisc|class|filter|...). If
474# there is one, first call _tc_direct_complete to see if previous word is
475# waiting for a particular completion. If so, propose completion and exit.
476# 4. Extract main command and -- if available -- its subcommand
477# (add|delete|show|...).
478# 5. Propose completion based on main and sub- command in use. Additional
479# functions may be called for qdiscs, classes or filter options.
480_tc()
481{
482 local cur prev words cword
483 _init_completion || return
484
485 case $prev in
486 -V|-Version)
487 return 0
488 ;;
489 -b|-batch|-cf|-conf)
490 _filedir
491 return 0
492 ;;
493 -force)
494 COMPREPLY=( $( compgen -W '-batch' -- "$cur" ) )
495 return 0
496 ;;
497 -nm|name)
498 [[ -r /etc/iproute2/tc_cls ]] || \
499 COMPREPLY=( $( compgen -W '-conf' -- "$cur" ) )
500 return 0
501 ;;
502 -n|-net|-netns)
503 local nslist=$( ip netns list 2>/dev/null )
504 COMPREPLY+=( $( compgen -W "$nslist" -- "$cur" ) )
505 return 0
506 ;;
507 -tshort)
508 _tc_once_attr '-statistics'
509 COMPREPLY+=( $( compgen -W 'monitor' -- "$cur" ) )
510 return 0
511 ;;
512 -timestamp)
513 _tc_once_attr '-statistics -tshort'
514 COMPREPLY+=( $( compgen -W 'monitor' -- "$cur" ) )
515 return 0
516 ;;
517 esac
518
519 # Search for main commands
520 local subcword cmd subcmd
521 for (( subcword=1; subcword < ${#words[@]}-1; subcword++ )); do
522 [[ ${words[subcword]} == -b?(atch) ]] && return 0
523 [[ -n $cmd ]] && subcmd=${words[subcword]} && break
524 [[ ${words[subcword]} != -* && \
525 ${words[subcword-1]} != -@(n?(et?(ns))|c?(on)f) ]] && \
526 cmd=${words[subcword]}
527 done
528
529 if [[ -z $cmd ]]; then
530 case $cur in
531 -*)
532 local c='-Version -statistics -details -raw -pretty \
533 -iec -graphe -batch -name -netns -timestamp'
534 [[ $cword -eq 1 ]] && c+=' -force'
535 COMPREPLY=( $( compgen -W "$c" -- "$cur" ) )
536 return 0
537 ;;
538 *)
539 COMPREPLY=( $( compgen -W "help $( tc help 2>&1 | \
540 command sed \
541 -e '/OBJECT := /!d' \
542 -e 's/.*{//' \
543 -e 's/}.*//' \
544 -e \ 's/|//g' )" -- "$cur" ) )
545 return 0
546 ;;
547 esac
548 fi
549
550 [[ $subcmd == help ]] && return 0
551
552 # For this set of commands we may create COMPREPLY just by analysing the
553 # previous word, if it expects for a specific list of options or values.
554 if [[ $cmd =~ (qdisc|class|filter|action|exec) ]]; then
555 _tc_direct_complete $prev && return 0
556 if [[ ${words[${#words[@]}-3]} == estimator ]]; then
557 local list=$( _tc_expand_units 'secs' 'msecs' 'usecs' )
558 COMPREPLY+=( $( compgen -W "$list" -- "$cur" ) ) && return 0
559 fi
560 fi
561
562 # Completion depends on main command and subcommand in use.
563 case $cmd in
564 qdisc)
565 case $subcmd in
566 add|change|replace|link|del|delete)
567 if [[ $(($cword-$subcword)) -eq 1 ]]; then
568 COMPREPLY=( $( compgen -W 'dev' -- "$cur" ) )
569 return 0
570 fi
571 local qdisc qdwd QDISC_KIND=' choke codel bfifo pfifo \
572 pfifo_head_drop fq fq_codel gred hhf mqprio multiq \
573 netem pfifo_fast pie red rr sfb sfq tbf atm cbq drr \
574 dsmark hfsc htb prio qfq '
575 for ((qdwd=$subcword; qdwd < ${#words[@]}-1; qdwd++)); do
576 if [[ $QDISC_KIND =~ ' '${words[qdwd]}' ' ]]; then
577 qdisc=${words[qdwd]}
578 _tc_qdisc_options $qdisc && return 0
579 fi
580 done
581 _tc_one_of_list $QDISC_KIND
582 _tc_one_of_list 'root ingress parent clsact'
583 _tc_once_attr 'handle estimator stab'
584 ;;
585 show)
586 _tc_once_attr 'dev'
587 _tc_one_of_list 'ingress clsact'
588 _tc_once_attr '-statistics -details -raw -pretty -iec \
589 -graph -name'
590 ;;
591 help)
592 return 0
593 ;;
594 *)
595 [[ $cword -eq $subcword ]] && \
596 COMPREPLY=( $( compgen -W 'help add delete change \
597 replace link show' -- "$cur" ) )
598 ;;
599 esac
600 ;;
601
602 class)
603 case $subcmd in
604 add|change|replace|del|delete)
605 if [[ $(($cword-$subcword)) -eq 1 ]]; then
606 COMPREPLY=( $( compgen -W 'dev' -- "$cur" ) )
607 return 0
608 fi
609 local qdisc qdwd QDISC_KIND=' choke codel bfifo pfifo \
610 pfifo_head_drop fq fq_codel gred hhf mqprio multiq \
611 netem pfifo_fast pie red rr sfb sfq tbf atm cbq drr \
612 dsmark hfsc htb prio qfq '
613 for ((qdwd=$subcword; qdwd < ${#words[@]}-1; qdwd++)); do
614 if [[ $QDISC_KIND =~ ' '${words[qdwd]}' ' ]]; then
615 qdisc=${words[qdwd]}
616 _tc_qdisc_options $qdisc && return 0
617 fi
618 done
619 _tc_one_of_list $QDISC_KIND
620 _tc_one_of_list 'root parent'
621 _tc_once_attr 'classid'
622 ;;
623 show)
624 _tc_once_attr 'dev'
625 _tc_one_of_list 'root parent'
626 _tc_once_attr '-statistics -details -raw -pretty -iec \
627 -graph -name'
628 ;;
629 help)
630 return 0
631 ;;
632 *)
633 [[ $cword -eq $subcword ]] && \
634 COMPREPLY=( $( compgen -W 'help add delete change \
635 replace show' -- "$cur" ) )
636 ;;
637 esac
638 ;;
639
640 filter)
641 case $subcmd in
642 add|change|replace|del|delete)
643 if [[ $(($cword-$subcword)) -eq 1 ]]; then
644 COMPREPLY=( $( compgen -W 'dev' -- "$cur" ) )
645 return 0
646 fi
647 local filter fltwd FILTER_KIND=' basic bpf cgroup flow \
648 flower fw route rsvp tcindex u32 '
649 for ((fltwd=$subcword; fltwd < ${#words[@]}-1; fltwd++));
650 do
651 if [[ $FILTER_KIND =~ ' '${words[fltwd]}' ' ]]; then
652 filter=${words[fltwd]}
653 _tc_filter_options $filter && return 0
654 fi
655 done
656 _tc_one_of_list $FILTER_KIND
657 _tc_one_of_list 'root ingress egress parent'
658 _tc_once_attr 'handle estimator pref protocol'
659 ;;
660 show)
661 _tc_once_attr 'dev'
662 _tc_one_of_list 'root ingress egress parent'
663 _tc_once_attr '-statistics -details -raw -pretty -iec \
664 -graph -name'
665 ;;
666 help)
667 return 0
668 ;;
669 *)
670 [[ $cword -eq $subcword ]] && \
671 COMPREPLY=( $( compgen -W 'help add delete change \
672 replace show' -- "$cur" ) )
673 ;;
674 esac
675 ;;
676
677 action)
678 case $subcmd in
679 add|change|replace)
0b1abd84 680 local action acwd ACTION_KIND=' gact mirred bpf sample '
27d44f3a
QM
681 for ((acwd=$subcword; acwd < ${#words[@]}-1; acwd++)); do
682 if [[ $ACTION_KIND =~ ' '${words[acwd]}' ' ]]; then
683 action=${words[acwd]}
684 _tc_action_options $action && return 0
685 fi
686 done
687 _tc_one_of_list $ACTION_KIND
688 ;;
689 get|del|delete)
690 _tc_once_attr 'index'
691 ;;
692 lst|list|flush|show)
693 _tc_one_of_list $ACTION_KIND
694 ;;
695 *)
696 [[ $cword -eq $subcword ]] && \
697 COMPREPLY=( $( compgen -W 'help add delete change \
698 replace show list flush action' -- "$cur" ) )
699 ;;
700 esac
701 ;;
702
703 monitor)
704 COMPREPLY=( $( compgen -W 'help' -- "$cur" ) )
705 ;;
706
707 exec)
708 case $subcmd in
709 bpf)
710 local excmd exwd EXEC_KIND=' import debug graft '
711 for ((exwd=$subcword; exwd < ${#words[@]}-1; exwd++)); do
712 if [[ $EXEC_KIND =~ ' '${words[exwd]}' ' ]]; then
713 excmd=${words[exwd]}
714 _tc_exec_options $excmd && return 0
715 fi
716 done
717 _tc_one_of_list $EXEC_KIND
718 ;;
719 *)
720 [[ $cword -eq $subcword ]] && \
721 COMPREPLY=( $( compgen -W 'bpf' -- "$cur" ) )
722 ;;
723 esac
724 ;;
725 esac
726} &&
727complete -F _tc tc
728
729# ex: ts=4 sw=4 et filetype=sh