]>
Commit | Line | Data |
---|---|---|
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 | } && | |
727 | complete -F _tc tc | |
728 | ||
729 | # ex: ts=4 sw=4 et filetype=sh |