mirror of
https://git.kernel.org/pub/scm/network/iproute2/iproute2.git
synced 2026-01-26 22:22:18 +00:00
Add a new devlink health set option to configure the health reporter’s burst period. The burst period defines a time window during which recovery attempts for reported errors are allowed. Once this period expires, the configured grace period begins. This feature addresses cases where multiple errors occur simultaneously due to a common root cause. Without a burst period, the grace period starts immediately after the first error recovery attempt finishes. This means that only the first error might be recovered, while subsequent errors are blocked during the grace period. With the burst period, the reporter initiates a recovery attempt for every error reported within this time window before the grace period starts. Example: $ devlink health set pci/0000:00:09.0 reporter tx burst_period 500 Signed-off-by: Shahar Shitrit <shshitrit@nvidia.com> Reviewed-by: Carolina Jubran <cjubran@nvidia.com> Reviewed-by: Jiri Pirko <jiri@nvidia.com> Signed-off-by: Tariq Toukan <tariqt@nvidia.com> Signed-off-by: David Ahern <dsahern@kernel.org>
1105 lines
27 KiB
Bash
1105 lines
27 KiB
Bash
# bash completion for devlink(8) -*- shell-script -*-
|
|
|
|
# Get all the optional commands for devlink
|
|
_devlink_get_optional_commands()
|
|
{
|
|
local object=$1; shift
|
|
|
|
local filter_options=""
|
|
local options="$(devlink $object help 2>&1 \
|
|
| command sed -n -e "s/^.*devlink $object //p" \
|
|
| cut -d " " -f 1)"
|
|
|
|
# Remove duplicate options from "devlink $OBJECT help" command
|
|
local opt
|
|
for opt in $options; do
|
|
if [[ $filter_options =~ $opt ]]; then
|
|
continue
|
|
else
|
|
filter_options="$filter_options $opt"
|
|
fi
|
|
done
|
|
|
|
echo $filter_options
|
|
}
|
|
|
|
# Complete based on given word, for when an argument or an option name has
|
|
# but a few possible arguments.
|
|
_devlink_direct_complete()
|
|
{
|
|
local dev port region value
|
|
|
|
case $1 in
|
|
dev)
|
|
value=$(devlink dev show 2>/dev/null)
|
|
;;
|
|
selftests_id)
|
|
dev=${words[4]}
|
|
value=$(devlink -j dev selftests show 2>/dev/null \
|
|
| jq ".selftests[\"$dev\"][]")
|
|
;;
|
|
param_name)
|
|
dev=${words[4]}
|
|
value=$(devlink -j dev param show 2>/dev/null \
|
|
| jq ".param[\"$dev\"][].name")
|
|
;;
|
|
port)
|
|
value=$(devlink -j port show 2>/dev/null \
|
|
| jq '.port as $ports | $ports | keys[] as $key
|
|
| ($ports[$key].netdev // $key)')
|
|
;;
|
|
lc)
|
|
dev=${words[3]}
|
|
value=$(devlink -j lc show 2>/dev/null \
|
|
| jq ".lc[\"$dev\"]" \
|
|
| jq '. as $lcs | $lcs | keys[] as $key |($lcs[$key].lc)' \
|
|
2>/dev/null)
|
|
;;
|
|
lc_type)
|
|
dev=${words[3]}
|
|
lc=${words[5]}
|
|
value=$(devlink lc show $dev lc $lc -j 2>/dev/null \
|
|
| jq '.[][][]["supported_types"][]')
|
|
;;
|
|
region)
|
|
value=$(devlink -j region show 2>/dev/null \
|
|
| jq '.regions' | jq 'keys[]')
|
|
;;
|
|
snapshot)
|
|
region=${words[3]}
|
|
value=$(devlink -j region show 2>/dev/null \
|
|
| jq ".regions[\"$region\"].snapshot[]")
|
|
;;
|
|
trap)
|
|
dev=${words[3]}
|
|
value=$(devlink -j trap show 2>/dev/null \
|
|
| jq ".trap[\"$dev\"][].name")
|
|
;;
|
|
trap_group)
|
|
dev=${words[4]}
|
|
value=$(devlink -j trap group show 2>/dev/null \
|
|
| jq ".trap_group[\"$dev\"][].name")
|
|
;;
|
|
trap_policer)
|
|
dev=${words[4]}
|
|
value=$(devlink -j trap policer show 2>/dev/null \
|
|
| jq ".trap_policer[\"$dev\"][].policer")
|
|
;;
|
|
health_dev)
|
|
value=$(devlink -j health show 2>/dev/null | jq '.health' \
|
|
| jq 'keys[]')
|
|
;;
|
|
reporter)
|
|
dev=${words[cword - 2]}
|
|
value=$(devlink -j health show 2>/dev/null \
|
|
| jq ".health[\"$dev\"][].reporter")
|
|
;;
|
|
pool)
|
|
dev=$pprev
|
|
value=$(devlink -j sb pool show 2>/dev/null \
|
|
| jq ".pool[\"$dev\"][].pool")
|
|
;;
|
|
port_pool)
|
|
port=${words[5]}
|
|
value=$(devlink -j sb port pool show 2>/dev/null \
|
|
| jq ".port_pool[\"$port\"][].pool")
|
|
;;
|
|
tc)
|
|
port=$pprev
|
|
value=$(devlink -j sb tc bind show 2>/dev/null \
|
|
| jq ".tc_bind[\"$port\"][].tc")
|
|
;;
|
|
esac
|
|
|
|
COMPREPLY+=( $( compgen -W "$value" -- "$cur" ) )
|
|
# Remove colon containing prefix from COMPREPLY items in order to avoid
|
|
# wordbreaks with colon.
|
|
__ltrim_colon_completions "$cur"
|
|
}
|
|
|
|
# Completion for devlink dev eswitch set
|
|
_devlink_dev_eswitch_set()
|
|
{
|
|
local -A settings=(
|
|
[mode]=notseen
|
|
[inline-mode]=notseen
|
|
[encap-mode]=notseen
|
|
)
|
|
|
|
if [[ $cword -eq 5 ]]; then
|
|
COMPREPLY=( $( compgen -W "mode inline-mode encap-mode" -- "$cur" ) )
|
|
fi
|
|
|
|
# Mark seen settings
|
|
local word
|
|
for word in "${words[@]:5:${#words[@]}-1}"; do
|
|
if [[ -n $word ]]; then
|
|
if [[ "${settings[$word]}" ]]; then
|
|
settings[$word]=seen
|
|
fi
|
|
fi
|
|
done
|
|
|
|
case $prev in
|
|
mode)
|
|
COMPREPLY=( $( compgen -W "legacy switchdev" -- "$cur" ) )
|
|
return
|
|
;;
|
|
inline-mode)
|
|
COMPREPLY=( $( compgen -W "none link network transport" -- \
|
|
"$cur" ) )
|
|
return
|
|
;;
|
|
encap-mode)
|
|
COMPREPLY=( $( compgen -W "none basic" -- "$cur" ) )
|
|
return
|
|
;;
|
|
esac
|
|
|
|
local -a comp_words=()
|
|
|
|
# Add settings not seen to completions
|
|
local setting
|
|
for setting in "${!settings[@]}"; do
|
|
if [ "${settings[$setting]}" = notseen ]; then
|
|
comp_words+=( "$setting" )
|
|
fi
|
|
done
|
|
|
|
COMPREPLY=( $( compgen -W "${comp_words[*]}" -- "$cur" ) )
|
|
}
|
|
|
|
# Completion for devlink dev eswitch
|
|
_devlink_dev_eswitch()
|
|
{
|
|
case "$cword" in
|
|
3)
|
|
COMPREPLY=( $( compgen -W "show set" -- "$cur" ) )
|
|
return
|
|
;;
|
|
4)
|
|
_devlink_direct_complete "dev"
|
|
return
|
|
;;
|
|
esac
|
|
|
|
case "${words[3]}" in
|
|
set)
|
|
_devlink_dev_eswitch_set
|
|
return
|
|
;;
|
|
show)
|
|
return
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Completion for devlink dev param set
|
|
_devlink_dev_param_set()
|
|
{
|
|
case $cword in
|
|
7)
|
|
COMPREPLY=( $( compgen -W "value" -- "$cur" ) )
|
|
return
|
|
;;
|
|
8)
|
|
# String argument
|
|
return
|
|
;;
|
|
9)
|
|
COMPREPLY=( $( compgen -W "cmode" -- "$cur" ) )
|
|
return
|
|
;;
|
|
10)
|
|
COMPREPLY=( $( compgen -W "runtime driverinit permanent" -- \
|
|
"$cur" ) )
|
|
return
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Completion for devlink dev param
|
|
_devlink_dev_param()
|
|
{
|
|
case "$cword" in
|
|
3)
|
|
COMPREPLY=( $( compgen -W "show set" -- "$cur" ) )
|
|
return
|
|
;;
|
|
4)
|
|
_devlink_direct_complete "dev"
|
|
return
|
|
;;
|
|
5)
|
|
COMPREPLY=( $( compgen -W "name" -- "$cur" ) )
|
|
return
|
|
;;
|
|
6)
|
|
_devlink_direct_complete "param_name"
|
|
return
|
|
;;
|
|
esac
|
|
|
|
if [[ "${words[3]}" == "set" ]]; then
|
|
_devlink_dev_param_set
|
|
fi
|
|
}
|
|
|
|
# Completion for devlink dev reload
|
|
_devlink_dev_reload()
|
|
{
|
|
case "$cword" in
|
|
4)
|
|
COMPREPLY=( $( compgen -W "netns" -- "$cur" ) )
|
|
return
|
|
;;
|
|
5)
|
|
local nslist=$( ip netns list 2>/dev/null )
|
|
COMPREPLY=( $( compgen -W "$nslist" -- "$cur" ) )
|
|
return
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Completion for devlink dev flash
|
|
_devlink_dev_flash()
|
|
{
|
|
case "$cword" in
|
|
4)
|
|
COMPREPLY=( $( compgen -W "file" -- "$cur" ) )
|
|
return
|
|
;;
|
|
5)
|
|
_filedir
|
|
return
|
|
;;
|
|
6)
|
|
COMPREPLY=( $( compgen -W "component" -- "$cur" ) )
|
|
return
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Completion for devlink dev selftests
|
|
_devlink_dev_selftests()
|
|
{
|
|
if [[ $cword -gt 5 ]]; then
|
|
_devlink_direct_complete "selftests_id"
|
|
return
|
|
fi
|
|
case "$cword" in
|
|
3)
|
|
COMPREPLY=( $( compgen -W "show run" -- "$cur" ) )
|
|
return
|
|
;;
|
|
4)
|
|
_devlink_direct_complete "dev"
|
|
return
|
|
;;
|
|
5)
|
|
COMPREPLY=( $( compgen -W "id" -- "$cur" ) )
|
|
return
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Completion for devlink dev
|
|
_devlink_dev()
|
|
{
|
|
case $command in
|
|
show|reload|info|flash)
|
|
if [[ $cword -le 3 ]]; then
|
|
_devlink_direct_complete "dev"
|
|
elif [[ $command == "reload" || $command == "flash" ]];then
|
|
_devlink_dev_$command
|
|
fi
|
|
return
|
|
;;
|
|
eswitch|param|selftests)
|
|
_devlink_dev_$command
|
|
return
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Completion for devlink port set
|
|
_devlink_port_set()
|
|
{
|
|
case "$cword" in
|
|
3)
|
|
_devlink_direct_complete "port"
|
|
return
|
|
;;
|
|
4)
|
|
COMPREPLY=( $( compgen -W "type" -- "$cur" ) )
|
|
return
|
|
;;
|
|
5)
|
|
COMPREPLY=( $( compgen -W "eth ib auto" -- "$cur" ) )
|
|
return
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Completion for devlink port split
|
|
_devlink_port_split()
|
|
{
|
|
case "$cword" in
|
|
3)
|
|
_devlink_direct_complete "port"
|
|
return
|
|
;;
|
|
4)
|
|
COMPREPLY=( $( compgen -W "count" -- "$cur" ) )
|
|
return
|
|
;;
|
|
5)
|
|
# Integer argument
|
|
return
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Completion for devlink port param set
|
|
_devlink_port_param_set()
|
|
{
|
|
case $cword in
|
|
7)
|
|
COMPREPLY=( $( compgen -W "value" -- "$cur" ) )
|
|
return
|
|
;;
|
|
8)
|
|
# String argument
|
|
return
|
|
;;
|
|
9)
|
|
COMPREPLY=( $( compgen -W "cmode" -- "$cur" ) )
|
|
return
|
|
;;
|
|
10)
|
|
COMPREPLY=( $( compgen -W "runtime driverinit permanent" -- \
|
|
"$cur" ) )
|
|
return
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Completion for devlink port param
|
|
_devlink_port_param()
|
|
{
|
|
case "$cword" in
|
|
3)
|
|
COMPREPLY=( $( compgen -W "show set" -- "$cur" ) )
|
|
return
|
|
;;
|
|
4)
|
|
_devlink_direct_complete "port"
|
|
return
|
|
;;
|
|
5)
|
|
COMPREPLY=( $( compgen -W "name" -- "$cur" ) )
|
|
return
|
|
;;
|
|
6)
|
|
_devlink_direct_complete "param_name"
|
|
return
|
|
;;
|
|
esac
|
|
|
|
if [[ "${words[3]}" == "set" ]]; then
|
|
_devlink_port_param_set
|
|
fi
|
|
}
|
|
|
|
# Completion for devlink port
|
|
_devlink_port()
|
|
{
|
|
case $command in
|
|
set)
|
|
_devlink_port_set
|
|
return
|
|
;;
|
|
split)
|
|
_devlink_port_split
|
|
return
|
|
;;
|
|
param)
|
|
_devlink_port_param
|
|
return
|
|
;;
|
|
show|unsplit)
|
|
if [[ $cword -eq 3 ]]; then
|
|
_devlink_direct_complete "port"
|
|
fi
|
|
return
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Completion for devlink lc set
|
|
_devlink_lc_set()
|
|
{
|
|
case "$cword" in
|
|
3)
|
|
_devlink_direct_complete "dev"
|
|
return
|
|
;;
|
|
4)
|
|
COMPREPLY=( $( compgen -W "lc" -- "$cur" ) )
|
|
;;
|
|
5)
|
|
_devlink_direct_complete "lc"
|
|
;;
|
|
6)
|
|
COMPREPLY=( $( compgen -W "type notype" -- "$cur" ) )
|
|
return
|
|
;;
|
|
7)
|
|
if [[ "$prev" == "type" ]]; then
|
|
_devlink_direct_complete "lc_type"
|
|
fi
|
|
esac
|
|
}
|
|
|
|
# Completion for devlink lc show
|
|
_devlink_lc_show()
|
|
{
|
|
case $cword in
|
|
3)
|
|
_devlink_direct_complete "dev"
|
|
;;
|
|
4)
|
|
COMPREPLY=( $( compgen -W "lc" -- "$cur" ) )
|
|
;;
|
|
5)
|
|
_devlink_direct_complete "lc"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Completion for devlink lc
|
|
_devlink_lc()
|
|
{
|
|
case $command in
|
|
set)
|
|
_devlink_lc_set
|
|
return
|
|
;;
|
|
show)
|
|
_devlink_lc_show
|
|
return
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Completion for devlink dpipe
|
|
_devlink_dpipe()
|
|
{
|
|
local options="$(devlink dpipe help 2>&1 \
|
|
| command sed -e '/OBJECT-LIST := /!d' \
|
|
-e 's/.*{ //' -e 's/}.*//' -e 's/|//g' )"
|
|
|
|
if [[ $cword -eq 2 ]]; then
|
|
COMPREPLY+=( $( compgen -W "$options" -- "$cur" ) )
|
|
fi
|
|
}
|
|
|
|
# Completion for devlink monitor
|
|
_devlink_monitor()
|
|
{
|
|
local options="$(devlink monitor help 2>&1 \
|
|
| command sed -e '/OBJECT-LIST := /!d' \
|
|
-e 's/.*{ //' -e 's/}.*//' -e 's/|//g' )"
|
|
|
|
if [[ $cword -eq 2 ]]; then
|
|
COMPREPLY+=( $( compgen -W "all $options" -- "$cur" ) )
|
|
fi
|
|
}
|
|
|
|
# Completion for the rest of devlink sb $command
|
|
_devlink_sb_command_options()
|
|
{
|
|
local subcmd
|
|
|
|
case $command in
|
|
pool)
|
|
subcmd=${words[3]}
|
|
if [[ $cword -eq 5 ]]; then
|
|
COMPREPLY=( $( compgen -W "pool" -- "$cur" ) )
|
|
fi
|
|
if [[ $subcmd == "set" ]]; then
|
|
case $cword in
|
|
7)
|
|
COMPREPLY+=( $( compgen -W "size" -- "$cur" ) )
|
|
;;
|
|
9)
|
|
COMPREPLY+=( $( compgen -W "thtype" -- "$cur" ) )
|
|
;;
|
|
esac
|
|
fi
|
|
;;
|
|
port)
|
|
subcmd=${words[4]}
|
|
if [[ $cword -eq 6 ]]; then
|
|
COMPREPLY+=( $( compgen -W "pool" -- "$cur" ) )
|
|
fi
|
|
if [[ $subcmd == "set" ]]; then
|
|
case $cword in
|
|
8)
|
|
COMPREPLY+=( $( compgen -W "th" -- "$cur" ) )
|
|
;;
|
|
esac
|
|
fi
|
|
;;
|
|
tc)
|
|
subcmd=${words[4]}
|
|
case $cword in
|
|
6)
|
|
COMPREPLY+=( $( compgen -W "tc" -- "$cur" ) )
|
|
;;
|
|
8)
|
|
COMPREPLY+=( $( compgen -W "type" -- "$cur" ) )
|
|
;;
|
|
esac
|
|
if [[ $subcmd == "set" ]]; then
|
|
case $cword in
|
|
10)
|
|
COMPREPLY+=( $( compgen -W "pool" -- "$cur" ) )
|
|
;;
|
|
12)
|
|
COMPREPLY+=( $( compgen -W "th" -- "$cur" ) )
|
|
;;
|
|
esac
|
|
fi
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Completion for devlink sb
|
|
_devlink_sb()
|
|
{
|
|
case $prev in
|
|
bind)
|
|
COMPREPLY=( $( compgen -W "set show" -- "$cur" ) )
|
|
;;
|
|
occupancy)
|
|
COMPREPLY=( $( compgen -W "show snapshot clearmax" -- "$cur" ) )
|
|
;;
|
|
pool)
|
|
if [[ $cword -eq 3 || $cword -eq 4 ]]; then
|
|
COMPREPLY=( $( compgen -W "set show" -- "$cur" ) )
|
|
elif [[ $command == "port" || $command == "tc" ]]; then
|
|
_devlink_direct_complete "port_pool"
|
|
else
|
|
_devlink_direct_complete "pool"
|
|
fi
|
|
;;
|
|
port)
|
|
if [[ $cword -eq 3 ]]; then
|
|
COMPREPLY=( $( compgen -W "pool" -- "$cur" ) )
|
|
fi
|
|
;;
|
|
show|set|snapshot|clearmax)
|
|
case $command in
|
|
show|pool|occupancy)
|
|
_devlink_direct_complete "dev"
|
|
if [[ $command == "occupancy" && $prev == "show" ]];then
|
|
_devlink_direct_complete "port"
|
|
fi
|
|
;;
|
|
port|tc)
|
|
_devlink_direct_complete "port"
|
|
;;
|
|
esac
|
|
;;
|
|
size)
|
|
# Integer argument
|
|
;;
|
|
thtype)
|
|
COMPREPLY=( $( compgen -W "static dynamic" -- "$cur" ) )
|
|
;;
|
|
th)
|
|
# Integer argument
|
|
;;
|
|
tc)
|
|
if [[ $cword -eq 3 ]]; then
|
|
COMPREPLY=( $( compgen -W "bind" -- "$cur" ) )
|
|
else
|
|
_devlink_direct_complete "tc"
|
|
fi
|
|
;;
|
|
type)
|
|
COMPREPLY=( $( compgen -W "ingress egress" -- "$cur" ) )
|
|
;;
|
|
esac
|
|
|
|
_devlink_sb_command_options
|
|
return
|
|
}
|
|
|
|
# Completion for devlink resource set path argument
|
|
_devlink_resource_path()
|
|
{
|
|
local path parents parent all_path
|
|
local dev=${words[3]}
|
|
local -a path
|
|
|
|
local all_path=$(
|
|
devlink resource show $dev \
|
|
| sed -E '# Of resource lines, keep only the name itself.
|
|
s/name ([^ ]*) .*/\1/
|
|
# Drop headers.
|
|
/:$/d
|
|
# First layer is not aligned enough, align it.
|
|
s/^/ /
|
|
# Use slashes as unary code for resource depth.
|
|
s, ,/,g
|
|
# Separate tally count from resource name.
|
|
s,/*,&\t,' \
|
|
| while read d name; do
|
|
while ((${#path[@]} > ${#d})); do
|
|
unset path[$((${#path[@]} - 1))]
|
|
done
|
|
path[$((${#d} - 1))]=$name
|
|
echo ${path[@]}
|
|
done \
|
|
| sed '# Convert paths to slash-separated
|
|
s,^,/,;s, ,/,g;s,$,/,'
|
|
)
|
|
COMPREPLY=( ${COMPREPLY[@]:-} $( compgen -W "$all_path" -- "$cur" ) )
|
|
}
|
|
|
|
# Completion for devlink resource set
|
|
_devlink_resource_set()
|
|
{
|
|
case "$cword" in
|
|
3)
|
|
_devlink_direct_complete "dev"
|
|
return
|
|
;;
|
|
4)
|
|
COMPREPLY=( $( compgen -W "path" -- "$cur" ) )
|
|
return
|
|
;;
|
|
5)
|
|
_devlink_resource_path
|
|
return
|
|
;;
|
|
6)
|
|
COMPREPLY=( $( compgen -W "size" -- "$cur" ) )
|
|
return
|
|
;;
|
|
7)
|
|
# Integer argument
|
|
return
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Completion for devlink resource
|
|
_devlink_resource()
|
|
{
|
|
case $command in
|
|
show)
|
|
if [[ $cword -eq 3 ]]; then
|
|
_devlink_direct_complete "dev"
|
|
fi
|
|
return
|
|
;;
|
|
set)
|
|
_devlink_resource_set
|
|
return
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Completion for devlink region read
|
|
_devlink_region_read()
|
|
{
|
|
case "$cword" in
|
|
6)
|
|
COMPREPLY=( $( compgen -W "address" -- "$cur" ) )
|
|
return
|
|
;;
|
|
7)
|
|
# Address argument, for example: 0x10
|
|
return
|
|
;;
|
|
8)
|
|
COMPREPLY=( $( compgen -W "length" -- "$cur" ) )
|
|
return
|
|
;;
|
|
9)
|
|
# Integer argument
|
|
return
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Completion for devlink region
|
|
_devlink_region()
|
|
{
|
|
if [[ $cword -eq 3 && $command != "help" ]]; then
|
|
_devlink_direct_complete "region"
|
|
fi
|
|
|
|
case $command in
|
|
show)
|
|
return
|
|
;;
|
|
del|dump|read)
|
|
case "$cword" in
|
|
4)
|
|
COMPREPLY=( $( compgen -W "snapshot" -- "$cur" ) )
|
|
;;
|
|
5)
|
|
_devlink_direct_complete "snapshot"
|
|
;;
|
|
esac
|
|
|
|
if [[ $command == "read" ]]; then
|
|
_devlink_region_read
|
|
fi
|
|
return
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Completion reporter for devlink health
|
|
_devlink_health_reporter()
|
|
{
|
|
local i=$1; shift
|
|
|
|
case $cword in
|
|
$((3 + $i)))
|
|
_devlink_direct_complete "health_dev"
|
|
;;
|
|
$((4 + $i)))
|
|
COMPREPLY=( $( compgen -W "reporter" -- "$cur" ) )
|
|
;;
|
|
$((5 + $i)))
|
|
_devlink_direct_complete "reporter"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Completion for devlink health
|
|
_devlink_health()
|
|
{
|
|
case $command in
|
|
show|recover|diagnose|set|test)
|
|
_devlink_health_reporter 0
|
|
if [[ $command == "set" ]]; then
|
|
case $cword in
|
|
6)
|
|
COMPREPLY=( $( compgen -W "grace_period burst_period auto_recover" \
|
|
-- "$cur" ) )
|
|
;;
|
|
7)
|
|
case $prev in
|
|
grace_period|burst_period)
|
|
# Integer argument- msec
|
|
;;
|
|
auto_recover)
|
|
COMPREPLY=( $( compgen -W "true false" -- \
|
|
"$cur" ) )
|
|
;;
|
|
esac
|
|
esac
|
|
fi
|
|
return
|
|
;;
|
|
dump)
|
|
if [[ $cword -eq 3 ]]; then
|
|
COMPREPLY=( $( compgen -W "show clear" -- "$cur" ) )
|
|
fi
|
|
|
|
_devlink_health_reporter 1
|
|
return
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Completion for action in devlink trap set
|
|
_devlink_trap_set_action()
|
|
{
|
|
local i=$1; shift
|
|
|
|
case $cword in
|
|
$((6 + $i)))
|
|
COMPREPLY=( $( compgen -W "action" -- "$cur" ) )
|
|
;;
|
|
$((7 + $i)))
|
|
COMPREPLY=( $( compgen -W "trap drop mirror" -- "$cur" ) )
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Completion for devlink trap group set
|
|
_devlink_trap_group_set()
|
|
{
|
|
local -A settings=(
|
|
[action]=notseen
|
|
[policer]=notseen
|
|
[nopolicer]=notseen
|
|
)
|
|
|
|
if [[ $cword -eq 7 ]]; then
|
|
COMPREPLY=( $( compgen -W "action policer nopolicer" -- "$cur" ) )
|
|
fi
|
|
|
|
# Mark seen settings
|
|
local word
|
|
for word in "${words[@]:7:${#words[@]}-1}"; do
|
|
if [[ -n $word ]]; then
|
|
if [[ "${settings[$word]}" ]]; then
|
|
settings[$word]=seen
|
|
fi
|
|
fi
|
|
done
|
|
|
|
case $prev in
|
|
action)
|
|
COMPREPLY=( $( compgen -W "trap drop mirror" -- "$cur" ) )
|
|
return
|
|
;;
|
|
policer)
|
|
_devlink_direct_complete "trap_policer"
|
|
return
|
|
;;
|
|
esac
|
|
|
|
local -a comp_words=()
|
|
|
|
# Add settings not seen to completions
|
|
local setting
|
|
for setting in "${!settings[@]}"; do
|
|
if [ "${settings[$setting]}" = notseen ]; then
|
|
comp_words+=( "$setting" )
|
|
fi
|
|
done
|
|
|
|
COMPREPLY=( $( compgen -W "${comp_words[*]}" -- "$cur" ) )
|
|
}
|
|
|
|
# Completion for devlink trap group
|
|
_devlink_trap_group()
|
|
{
|
|
case $cword in
|
|
3)
|
|
COMPREPLY=( $( compgen -W "set show" -- "$cur" ) )
|
|
return
|
|
;;
|
|
4)
|
|
_devlink_direct_complete "dev"
|
|
return
|
|
;;
|
|
5)
|
|
COMPREPLY=( $( compgen -W "group" -- "$cur" ) )
|
|
return
|
|
;;
|
|
6)
|
|
_devlink_direct_complete "trap_group"
|
|
return
|
|
;;
|
|
esac
|
|
|
|
if [[ ${words[3]} == "set" ]]; then
|
|
_devlink_trap_group_set
|
|
fi
|
|
}
|
|
|
|
# Completion for devlink trap policer set
|
|
_devlink_trap_policer_set()
|
|
{
|
|
local -A settings=(
|
|
[rate]=notseen
|
|
[burst]=notseen
|
|
)
|
|
|
|
if [[ $cword -eq 7 ]]; then
|
|
COMPREPLY=( $( compgen -W "rate burst" -- "$cur" ) )
|
|
fi
|
|
|
|
# Mark seen settings
|
|
local word
|
|
for word in "${words[@]:7:${#words[@]}-1}"; do
|
|
if [[ -n $word ]]; then
|
|
if [[ "${settings[$word]}" ]]; then
|
|
settings[$word]=seen
|
|
fi
|
|
fi
|
|
done
|
|
|
|
case $prev in
|
|
rate)
|
|
# Integer argument
|
|
return
|
|
;;
|
|
burst)
|
|
# Integer argument
|
|
return
|
|
;;
|
|
esac
|
|
|
|
local -a comp_words=()
|
|
|
|
# Add settings not seen to completions
|
|
local setting
|
|
for setting in "${!settings[@]}"; do
|
|
if [ "${settings[$setting]}" = notseen ]; then
|
|
comp_words+=( "$setting" )
|
|
fi
|
|
done
|
|
|
|
COMPREPLY=( $( compgen -W "${comp_words[*]}" -- "$cur" ) )
|
|
}
|
|
|
|
# Completion for devlink trap policer
|
|
_devlink_trap_policer()
|
|
{
|
|
case $cword in
|
|
3)
|
|
COMPREPLY=( $( compgen -W "set show" -- "$cur" ) )
|
|
return
|
|
;;
|
|
4)
|
|
_devlink_direct_complete "dev"
|
|
return
|
|
;;
|
|
5)
|
|
COMPREPLY=( $( compgen -W "policer" -- "$cur" ) )
|
|
return
|
|
;;
|
|
6)
|
|
_devlink_direct_complete "trap_policer"
|
|
return
|
|
;;
|
|
esac
|
|
|
|
if [[ ${words[3]} == "set" ]]; then
|
|
_devlink_trap_policer_set
|
|
fi
|
|
}
|
|
|
|
# Completion for devlink trap
|
|
_devlink_trap()
|
|
{
|
|
case $command in
|
|
show|set)
|
|
case $cword in
|
|
3)
|
|
_devlink_direct_complete "dev"
|
|
;;
|
|
4)
|
|
COMPREPLY=( $( compgen -W "trap" -- "$cur" ) )
|
|
;;
|
|
5)
|
|
_devlink_direct_complete "trap"
|
|
;;
|
|
esac
|
|
|
|
if [[ $command == "set" ]]; then
|
|
_devlink_trap_set_action 0
|
|
fi
|
|
return
|
|
;;
|
|
group)
|
|
_devlink_trap_$command
|
|
return
|
|
;;
|
|
policer)
|
|
_devlink_trap_$command
|
|
return
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Complete any devlink command
|
|
_devlink()
|
|
{
|
|
local cur prev words cword
|
|
local opt='--Version --no-nice-names --json --pretty --verbose \
|
|
--statistics --force --Netns --batch'
|
|
local objects="$(devlink help 2>&1 | command sed -e '/OBJECT := /!d' \
|
|
-e 's/.*{//' -e 's/}.*//' -e \ 's/|//g' )"
|
|
|
|
_init_completion || return
|
|
# Gets the word-to-complete without considering the colon as word breaks
|
|
_get_comp_words_by_ref -n : cur prev words cword
|
|
|
|
if [[ $cword -eq 1 ]]; then
|
|
case $cur in
|
|
-*)
|
|
COMPREPLY=( $( compgen -W "$opt" -- "$cur" ) )
|
|
return 0
|
|
;;
|
|
*)
|
|
COMPREPLY=( $( compgen -W "$objects" -- "$cur" ) )
|
|
return 0
|
|
;;
|
|
esac
|
|
fi
|
|
|
|
# Deal with options
|
|
if [[ $prev == -* ]]; then
|
|
case $prev in
|
|
-V|--Version)
|
|
return 0
|
|
;;
|
|
-b|--batch)
|
|
_filedir
|
|
return 0
|
|
;;
|
|
--force)
|
|
COMPREPLY=( $( compgen -W "--batch" -- "$cur" ) )
|
|
return 0
|
|
;;
|
|
-N|--Netns)
|
|
local nslist=$( ip netns list 2>/dev/null )
|
|
COMPREPLY=( $( compgen -W "$nslist" -- "$cur" ) )
|
|
return 0
|
|
;;
|
|
-j|--json)
|
|
COMPREPLY=( $( compgen -W "--pretty $objects" -- "$cur" ) )
|
|
return 0
|
|
;;
|
|
*)
|
|
COMPREPLY=( $( compgen -W "$objects" -- "$cur" ) )
|
|
return 0
|
|
;;
|
|
esac
|
|
fi
|
|
|
|
# Remove all options so completions don't have to deal with them.
|
|
local i
|
|
for (( i=1; i < ${#words[@]}; )); do
|
|
if [[ ${words[i]::1} == - ]]; then
|
|
words=( "${words[@]:0:i}" "${words[@]:i+1}" )
|
|
[[ $i -le $cword ]] && cword=$(( cword - 1 ))
|
|
else
|
|
i=$(( ++i ))
|
|
fi
|
|
done
|
|
|
|
local object=${words[1]}
|
|
local command=${words[2]}
|
|
local pprev=${words[cword - 2]}
|
|
local prev=${words[cword - 1]}
|
|
|
|
if [[ $objects =~ $object ]]; then
|
|
if [[ $cword -eq 2 ]]; then
|
|
COMPREPLY=( $( compgen -W "help" -- "$cur") )
|
|
if [[ $object != "monitor" && $object != "dpipe" ]]; then
|
|
COMPREPLY+=( $( compgen -W \
|
|
"$(_devlink_get_optional_commands $object)" -- "$cur" ) )
|
|
fi
|
|
fi
|
|
"_devlink_$object"
|
|
fi
|
|
|
|
} &&
|
|
complete -F _devlink devlink
|
|
|
|
# ex: ts=4 sw=4 et filetype=sh
|