]> git.proxmox.com Git - mirror_iproute2.git/blob - bash-completion/tc
tc: m_action: Improve conversion to C99 style initializers
[mirror_iproute2.git] / bash-completion / tc
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 ;;
433 gact)
434 _tc_one_of_list 'reclassify drop continue pass'
435 _tc_once_attr 'random'
436 return 0
437 ;;
438 esac
439 return 1
440 }
441
442 # Complete with options names for exec.
443 # Returns 0 is completion should stop after running this function, 1 otherwise.
444 _tc_exec_options()
445 {
446 case $1 in
447 import)
448 [[ ${words[${#words[@]}-3]} == import ]] && \
449 _tc_once_attr 'run'
450 return 0
451 ;;
452 graft)
453 COMPREPLY+=( $( compgen -W 'key type' -- "$cur" ) )
454 [[ ${words[${#words[@]}-3]} == object-file ]] && \
455 _tc_once_attr 'type'
456 _tc_bpf_options
457 return 0
458 ;;
459 esac
460 return 1
461 }
462
463 # Main completion function
464 # Logic is as follows:
465 # 1. Check if previous word is a global option; if so, propose arguments.
466 # 2. Check if current word is a global option; if so, propose completion.
467 # 3. Check for the presence of a main command (qdisc|class|filter|...). If
468 # there is one, first call _tc_direct_complete to see if previous word is
469 # waiting for a particular completion. If so, propose completion and exit.
470 # 4. Extract main command and -- if available -- its subcommand
471 # (add|delete|show|...).
472 # 5. Propose completion based on main and sub- command in use. Additional
473 # functions may be called for qdiscs, classes or filter options.
474 _tc()
475 {
476 local cur prev words cword
477 _init_completion || return
478
479 case $prev in
480 -V|-Version)
481 return 0
482 ;;
483 -b|-batch|-cf|-conf)
484 _filedir
485 return 0
486 ;;
487 -force)
488 COMPREPLY=( $( compgen -W '-batch' -- "$cur" ) )
489 return 0
490 ;;
491 -nm|name)
492 [[ -r /etc/iproute2/tc_cls ]] || \
493 COMPREPLY=( $( compgen -W '-conf' -- "$cur" ) )
494 return 0
495 ;;
496 -n|-net|-netns)
497 local nslist=$( ip netns list 2>/dev/null )
498 COMPREPLY+=( $( compgen -W "$nslist" -- "$cur" ) )
499 return 0
500 ;;
501 -tshort)
502 _tc_once_attr '-statistics'
503 COMPREPLY+=( $( compgen -W 'monitor' -- "$cur" ) )
504 return 0
505 ;;
506 -timestamp)
507 _tc_once_attr '-statistics -tshort'
508 COMPREPLY+=( $( compgen -W 'monitor' -- "$cur" ) )
509 return 0
510 ;;
511 esac
512
513 # Search for main commands
514 local subcword cmd subcmd
515 for (( subcword=1; subcword < ${#words[@]}-1; subcword++ )); do
516 [[ ${words[subcword]} == -b?(atch) ]] && return 0
517 [[ -n $cmd ]] && subcmd=${words[subcword]} && break
518 [[ ${words[subcword]} != -* && \
519 ${words[subcword-1]} != -@(n?(et?(ns))|c?(on)f) ]] && \
520 cmd=${words[subcword]}
521 done
522
523 if [[ -z $cmd ]]; then
524 case $cur in
525 -*)
526 local c='-Version -statistics -details -raw -pretty \
527 -iec -graphe -batch -name -netns -timestamp'
528 [[ $cword -eq 1 ]] && c+=' -force'
529 COMPREPLY=( $( compgen -W "$c" -- "$cur" ) )
530 return 0
531 ;;
532 *)
533 COMPREPLY=( $( compgen -W "help $( tc help 2>&1 | \
534 command sed \
535 -e '/OBJECT := /!d' \
536 -e 's/.*{//' \
537 -e 's/}.*//' \
538 -e \ 's/|//g' )" -- "$cur" ) )
539 return 0
540 ;;
541 esac
542 fi
543
544 [[ $subcmd == help ]] && return 0
545
546 # For this set of commands we may create COMPREPLY just by analysing the
547 # previous word, if it expects for a specific list of options or values.
548 if [[ $cmd =~ (qdisc|class|filter|action|exec) ]]; then
549 _tc_direct_complete $prev && return 0
550 if [[ ${words[${#words[@]}-3]} == estimator ]]; then
551 local list=$( _tc_expand_units 'secs' 'msecs' 'usecs' )
552 COMPREPLY+=( $( compgen -W "$list" -- "$cur" ) ) && return 0
553 fi
554 fi
555
556 # Completion depends on main command and subcommand in use.
557 case $cmd in
558 qdisc)
559 case $subcmd in
560 add|change|replace|link|del|delete)
561 if [[ $(($cword-$subcword)) -eq 1 ]]; then
562 COMPREPLY=( $( compgen -W 'dev' -- "$cur" ) )
563 return 0
564 fi
565 local qdisc qdwd QDISC_KIND=' choke codel bfifo pfifo \
566 pfifo_head_drop fq fq_codel gred hhf mqprio multiq \
567 netem pfifo_fast pie red rr sfb sfq tbf atm cbq drr \
568 dsmark hfsc htb prio qfq '
569 for ((qdwd=$subcword; qdwd < ${#words[@]}-1; qdwd++)); do
570 if [[ $QDISC_KIND =~ ' '${words[qdwd]}' ' ]]; then
571 qdisc=${words[qdwd]}
572 _tc_qdisc_options $qdisc && return 0
573 fi
574 done
575 _tc_one_of_list $QDISC_KIND
576 _tc_one_of_list 'root ingress parent clsact'
577 _tc_once_attr 'handle estimator stab'
578 ;;
579 show)
580 _tc_once_attr 'dev'
581 _tc_one_of_list 'ingress clsact'
582 _tc_once_attr '-statistics -details -raw -pretty -iec \
583 -graph -name'
584 ;;
585 help)
586 return 0
587 ;;
588 *)
589 [[ $cword -eq $subcword ]] && \
590 COMPREPLY=( $( compgen -W 'help add delete change \
591 replace link show' -- "$cur" ) )
592 ;;
593 esac
594 ;;
595
596 class)
597 case $subcmd in
598 add|change|replace|del|delete)
599 if [[ $(($cword-$subcword)) -eq 1 ]]; then
600 COMPREPLY=( $( compgen -W 'dev' -- "$cur" ) )
601 return 0
602 fi
603 local qdisc qdwd QDISC_KIND=' choke codel bfifo pfifo \
604 pfifo_head_drop fq fq_codel gred hhf mqprio multiq \
605 netem pfifo_fast pie red rr sfb sfq tbf atm cbq drr \
606 dsmark hfsc htb prio qfq '
607 for ((qdwd=$subcword; qdwd < ${#words[@]}-1; qdwd++)); do
608 if [[ $QDISC_KIND =~ ' '${words[qdwd]}' ' ]]; then
609 qdisc=${words[qdwd]}
610 _tc_qdisc_options $qdisc && return 0
611 fi
612 done
613 _tc_one_of_list $QDISC_KIND
614 _tc_one_of_list 'root parent'
615 _tc_once_attr 'classid'
616 ;;
617 show)
618 _tc_once_attr 'dev'
619 _tc_one_of_list 'root parent'
620 _tc_once_attr '-statistics -details -raw -pretty -iec \
621 -graph -name'
622 ;;
623 help)
624 return 0
625 ;;
626 *)
627 [[ $cword -eq $subcword ]] && \
628 COMPREPLY=( $( compgen -W 'help add delete change \
629 replace show' -- "$cur" ) )
630 ;;
631 esac
632 ;;
633
634 filter)
635 case $subcmd in
636 add|change|replace|del|delete)
637 if [[ $(($cword-$subcword)) -eq 1 ]]; then
638 COMPREPLY=( $( compgen -W 'dev' -- "$cur" ) )
639 return 0
640 fi
641 local filter fltwd FILTER_KIND=' basic bpf cgroup flow \
642 flower fw route rsvp tcindex u32 '
643 for ((fltwd=$subcword; fltwd < ${#words[@]}-1; fltwd++));
644 do
645 if [[ $FILTER_KIND =~ ' '${words[fltwd]}' ' ]]; then
646 filter=${words[fltwd]}
647 _tc_filter_options $filter && return 0
648 fi
649 done
650 _tc_one_of_list $FILTER_KIND
651 _tc_one_of_list 'root ingress egress parent'
652 _tc_once_attr 'handle estimator pref protocol'
653 ;;
654 show)
655 _tc_once_attr 'dev'
656 _tc_one_of_list 'root ingress egress parent'
657 _tc_once_attr '-statistics -details -raw -pretty -iec \
658 -graph -name'
659 ;;
660 help)
661 return 0
662 ;;
663 *)
664 [[ $cword -eq $subcword ]] && \
665 COMPREPLY=( $( compgen -W 'help add delete change \
666 replace show' -- "$cur" ) )
667 ;;
668 esac
669 ;;
670
671 action)
672 case $subcmd in
673 add|change|replace)
674 local action acwd ACTION_KIND=' gact mirred bpf '
675 for ((acwd=$subcword; acwd < ${#words[@]}-1; acwd++)); do
676 if [[ $ACTION_KIND =~ ' '${words[acwd]}' ' ]]; then
677 action=${words[acwd]}
678 _tc_action_options $action && return 0
679 fi
680 done
681 _tc_one_of_list $ACTION_KIND
682 ;;
683 get|del|delete)
684 _tc_once_attr 'index'
685 ;;
686 lst|list|flush|show)
687 _tc_one_of_list $ACTION_KIND
688 ;;
689 *)
690 [[ $cword -eq $subcword ]] && \
691 COMPREPLY=( $( compgen -W 'help add delete change \
692 replace show list flush action' -- "$cur" ) )
693 ;;
694 esac
695 ;;
696
697 monitor)
698 COMPREPLY=( $( compgen -W 'help' -- "$cur" ) )
699 ;;
700
701 exec)
702 case $subcmd in
703 bpf)
704 local excmd exwd EXEC_KIND=' import debug graft '
705 for ((exwd=$subcword; exwd < ${#words[@]}-1; exwd++)); do
706 if [[ $EXEC_KIND =~ ' '${words[exwd]}' ' ]]; then
707 excmd=${words[exwd]}
708 _tc_exec_options $excmd && return 0
709 fi
710 done
711 _tc_one_of_list $EXEC_KIND
712 ;;
713 *)
714 [[ $cword -eq $subcword ]] && \
715 COMPREPLY=( $( compgen -W 'bpf' -- "$cur" ) )
716 ;;
717 esac
718 ;;
719 esac
720 } &&
721 complete -F _tc tc
722
723 # ex: ts=4 sw=4 et filetype=sh