Skip to content

Conversation

@anders-nexthop
Copy link
Contributor

@anders-nexthop anders-nexthop commented Nov 10, 2025

What I did

Add a new VtyshCommand class that can be used to extend click cli commands with vtysh help text. The class calls down into vtysh to get subcommand information and then generates help text following the existing format used by the top-level SONiC CLI.

Additionally, add bash completions for the vtysh subcommands.

Closes: #24036

How I did it

Call down into vtysh to extract subcommands and descriptions, and use that information to populate help text and completions. Create a VtyshCommand wrapper class that handles everything, so that other commands can be easily extended to use the functionality. Add a completion hook so that bash completions can detect subcommands correctly.

An important consideration with this proposed fix is whether it's acceptable to call down into vtysh to retrieve this information. That adds a lot of complexity for what should really be a simple operation, and it involves overriding a lot of click internals to get the result to match the format of other SONiC cli commands. The underlying issue is that the 'show ip route' command tree is not actually implemented in SONiC itself, but in FRR. The current CLI is a thin shim between FRR and the main SONiC terminal that allows operators to skip having to use vtysh directly. The question is, how much support do we want to provide for this top-level CLI? And whats the right way to interface with the underlying vtysh functionality?

The approach presented here is a general solution to this issue, which could easily be used for any show command that passes through directly to vtysh (several of these exist beyond "show ip route"). Any changes to the vtysh CLI is supported automatically, so new vtysh commands will just work.

The alternative would be to actually implement the command tree. This is considerably more work, but would have the benefit of allowing for better help strings, and modifiable behavior at any level of the tree. However, this becomes a significant effort for every command, and is subject to breakage if the underlying vtysh CLI changes.

I thought that since the existing commands have already gone the quick and general route of just passing command strings wholesale into vtysh, it isn't a much greater sin to do the same work for generating help strings. Even as an intermediary step, this change would get command help online immediately. If or when proper subcommands get implemented, this workaround could be phased out accordingly.

Note: This PR does not attempt to retrieve description strings for user-defined arguments (stuff like IPADDRESS or vrf NAME, or range values). This could be done by defining a set of known patterns which could be stated as regexes and then compared against command lists, and returning description strings for a command if a match is found. However, these instances would have to be tracked down and added manually; they could also conflict with each other (for instance trying to match A.B.C.D and A.B.C.D/E, you have to make sure the regex are applied in the correct order if you want to get the most correct match). Given the concerns there, and given the scope of the current PR, I decided to leave that handling off for now. It can be added in a later patch.

How to verify it

Manually verified that subcommand help works, that existing help works, that tab completions work, and that the existing commands and subcommands still function properly.

Added unit tests for the new functionality:

tests/vtysh_help_test.py::TestVtyshHelpCommands::test_vtysh_help_basic_functionality PASSED [ 81%]
tests/vtysh_help_test.py::TestVtyshHelpCommands::test_vtysh_help_with_subcommands PASSED [ 81%]
tests/vtysh_help_test.py::TestVtyshHelpCommands::test_vtysh_help_without_subcommands PASSED [ 81%]
tests/vtysh_help_test.py::TestVtyshHelpCommands::test_nested_command_help PASSED [ 81%]
tests/vtysh_help_test.py::TestVtyshHelpCommands::test_basic_invalid_command_error_handling PASSED [ 81%]
tests/vtysh_help_test.py::TestVtyshHelpCommands::test_nested_invalid_command_error_handling PASSED [ 81%]
tests/vtysh_help_test.py::TestVtyshHelpCommands::test_vtysh_caching_functionality PASSED [ 81%]
tests/vtysh_help_test.py::TestVtyshCompletionCommands::test_basic_completion_functionality PASSED [ 81%]
tests/vtysh_help_test.py::TestVtyshCompletionCommands::test_nested_completion_functionality PASSED [ 81%]
tests/vtysh_help_test.py::TestVtyshCompletionCommands::test_completion_with_no_results PASSED [ 81%]
tests/vtysh_help_test.py::TestVtyshCompletionCommands::test_completion_with_vtysh_error PASSED [ 81%]
tests/vtysh_help_test.py::TestVtyshCompletionCommands::test_completion_with_whitespace_handling PASSED [ 81%]
tests/vtysh_help_test.py::TestVtyshCompletionCommands::test_nested_command_help_with_completion PASSED [ 81%]
tests/vtysh_help_test.py::TestVtyshCompletionCommands::test_nested_command_help_with_inline_completion PASSED [ 81%]

Performance: the performance cost is negligable:

admin@dvc:~$ time show ip route -h
Usage: show ip route [OPTIONS] [IPADDRESS] [vrf <vrf_name>] [...]

  Show IP (IPv4) routing table

Options:
  -d, --display TEXT    all|frontend
  -n, --namespace TEXT  Namespace name or all
  --verbose             Enable verbose output
  -h, -?, --help        Show this message and exit.

real    0m0.421s
user    0m0.290s
sys     0m0.088s
admin@dvc:~$ time show ip route -h
Usage: show ip route [OPTIONS] COMMAND [ARGS]...

Show IP (IPv4) routing table

Options:
  -d, --display TEXT    all|frontend
  -n, --namespace TEXT  Namespace name or all
  --verbose             Enable verbose output
  -?, -h, --help        Show this message and exit.

Commands:
  A.B.C.D         Network in the IP routing table to display
  A.B.C.D/M       IP prefix <network>/<length>, e.g., 35.0.0.0/8
  babel           Babel routing protocol (Babel)
  bgp             Border Gateway Protocol (BGP)
  connected       Connected routes (directly attached subnet or host)
  eigrp           Enhanced Interior Gateway Routing Protocol (EIGRP)
  isis            Intermediate System to Intermediate System (IS-IS)
  json            JavaScript Object Notation
  kernel          Kernel routes (not installed via the zebra RIB)
  local           Local routes (directly attached host route)
  mrib            Multicast SAFI table
  nexthop-group   Nexthop Group Information
  nhrp            Next Hop Resolution Protocol (NHRP)
  openfabric      OpenFabric Routing Protocol
  ospf            Open Shortest Path First (OSPFv2)
  rip             Routing Information Protocol (RIP)
  sharp           Super Happy Advanced Routing Protocol (sharpd)
  static          Statically configured routes
  summary         Summary of all routes
  supernets-only  Show supernet entries only
  table           Table to display
  table-direct    Non-main Kernel Routing Table - Direct
  tag             Show only routes with tag
  vnc             Virtual Network Control (VNC)
  vrf             Specify the VRF

real    0m0.465s
user    0m0.262s
sys     0m0.118s

Previous command output (if the output of a command-line utility has changed)

All commands under the "show ip route" subtree ("show ip route", "show ip route summary", "show ip route json", etc) have the same help output:

admin@gold101-dut:~$ show ip route -h
Usage: show ip route [OPTIONS] [IPADDRESS] [vrf <vrf_name>] [...]

  Show IP (IPv4) routing table

Options:
  -d, --display TEXT    all|frontend
  -n, --namespace TEXT  Namespace name or all
  --verbose             Enable verbose output
  -h, -?, --help        Show this message and exit.
admin@gold101-dut:~$ show ip route summary -h
Usage: show ip route [OPTIONS] [IPADDRESS] [vrf <vrf_name>] [...]

  Show IP (IPv4) routing table

Options:
  -d, --display TEXT    all|frontend
  -n, --namespace TEXT  Namespace name or all
  --verbose             Enable verbose output
  -h, -?, --help        Show this message and exit.

New command output (if the output of a command-line utility has changed)

There is now actual help output for a whole bunch of commands/subcommands. Also, note that usage string for "show ip route" itself has changed to match the regular click usage style found with other (non-vtysh) commands. The arguments (IPADDRESS and vrf) are listed as regular subcommands.

admin@vlab-01:~$ show ip route -h
Usage: show ip route [OPTIONS] COMMAND [ARGS]...

Show IP (IPv4) routing table

Options:
  -d, --display TEXT    all|frontend
  -n, --namespace TEXT  Namespace name or all
  --verbose             Enable verbose output
  -?, -h, --help        Show this message and exit.

Commands:
  A.B.C.D         Network in the IP routing table to display
  A.B.C.D/M       IP prefix <network>/<length>, e.g., 35.0.0.0/8
  babel           Babel routing protocol (Babel)
  bgp             Border Gateway Protocol (BGP)
  connected       Connected routes (directly attached subnet or host)
  eigrp           Enhanced Interior Gateway Routing Protocol (EIGRP)
  isis            Intermediate System to Intermediate System (IS-IS)
  json            JavaScript Object Notation
  kernel          Kernel routes (not installed via the zebra RIB)
  local           Local routes (directly attached host route)
  mrib            Multicast SAFI table
  nexthop-group   Nexthop Group Information
  nhrp            Next Hop Resolution Protocol (NHRP)
  openfabric      OpenFabric Routing Protocol
  ospf            Open Shortest Path First (OSPFv2)
  rip             Routing Information Protocol (RIP)
  sharp           Super Happy Advanced Routing Protocol (sharpd)
  static          Statically configured routes
  summary         Summary of all routes
  supernets-only  Show supernet entries only
  table           Table to display
  table-direct    Non-main Kernel Routing Table - Direct
  tag             Show only routes with tag
  vnc             Virtual Network Control (VNC)
  vrf             Specify the VRF

There are many possible valid combinations of subcommands under this tree, and they will all have slightly different help text. The description is pulled from the short description tag given for the command in the command list of its parent command. Here are a few examples:

admin@vlab-01:~$ show ip route summary -h
Usage: show ip route summary [OPTIONS] COMMAND [ARGS]...

Summary of all routes

Options:
  -d, --display TEXT    all|frontend
  -n, --namespace TEXT  Namespace name or all
  --verbose             Enable verbose output
  -h, -?, --help        Show this message and exit.

Commands:
  json    JavaScript Object Notation
  prefix  Prefix routes
  table   Table to display summary for
admin@vlab-01:~$ show ip route vrf -h
Usage: show ip route vrf [OPTIONS] COMMAND [ARGS]...

Specify the VRF

Options:
  -d, --display TEXT    all|frontend
  -n, --namespace TEXT  Namespace name or all
  --verbose             Enable verbose output
  -h, -?, --help        Show this message and exit.

Commands:
  NAME     The VRF name
  default
  all      All VRFs
admin@vlab-01:~$ show ip route vrf all -h
Usage: show ip route vrf all [OPTIONS] COMMAND [ARGS]...

All VRFs

Options:
  -d, --display TEXT    all|frontend
  -n, --namespace TEXT  Namespace name or all
  --verbose             Enable verbose output
  -h, -?, --help        Show this message and exit.

Commands:
  A.B.C.D         Network in the IP routing table to display
  A.B.C.D/M       IP prefix <network>/<length>, e.g., 35.0.0.0/8
  babel           Babel routing protocol (Babel)
  bgp             Border Gateway Protocol (BGP)
  connected       Connected routes (directly attached subnet or host)
  eigrp           Enhanced Interior Gateway Routing Protocol (EIGRP)
  isis            Intermediate System to Intermediate System (IS-IS)
  json            JavaScript Object Notation
  kernel          Kernel routes (not installed via the zebra RIB)
  local           Local routes (directly attached host route)
  mrib            Multicast SAFI table
  nexthop-group   Nexthop Group Information
  nhrp            Next Hop Resolution Protocol (NHRP)
  openfabric      OpenFabric Routing Protocol
  ospf            Open Shortest Path First (OSPFv2)
  rip             Routing Information Protocol (RIP)
  sharp           Super Happy Advanced Routing Protocol (sharpd)
  static          Statically configured routes
  summary         Summary of all routes
  supernets-only  Show supernet entries only
  table           Table to display
  table-direct    Non-main Kernel Routing Table - Direct
  tag             Show only routes with tag
  vnc             Virtual Network Control (VNC)

Leaf entries have the correct usage arg (they do not prompt for more commands):

admin@vlab-01:~$ show ip route json -h
Usage: show ip route json [OPTIONS]

JavaScript Object Notation

Options:
  -d, --display TEXT    all|frontend
  -n, --namespace TEXT  Namespace name or all
  --verbose             Enable verbose output
  -?, -h, --help        Show this message and exit.

Error handling matches what the click library does for regular commands:

admin@vlab-01:~$ show ip not_real -h
Usage: show ip [OPTIONS] COMMAND [ARGS]...
Try "show ip -h" for help.

Error: No such command "not_real".
admin@vlab-01:~$ show ip ? route
Usage: show ip [OPTIONS] COMMAND [ARGS]...

  Show IP (IPv4) commands

Options:
  -h, -?, --help  Show this message and exit.

Commands:
  bgp          Show IPv4 BGP (Border Gateway Protocol) information
  fib          Show IP FIB table
  interfaces
  prefix-list  show ip prefix-list
  protocol     Show IPv4 protocol information
  route        Show IP (IPv4) routing table
admin@vlab-01:~$ show ip --not_real_arg --help
Usage: show ip [OPTIONS] COMMAND [ARGS]...
Try "show ip -h" for help.

Error: no such option: --not_real_arg
admin@vlab-01:~$ show not_real ip -?
Usage: show [OPTIONS] COMMAND [ARGS]...
Try "show -h" for help.

Error: No such command "not_real".
admin@vlab-01:~$ show ip --help --not_real_arg
Usage: show ip [OPTIONS] COMMAND [ARGS]...
Try "show ip -h" for help.

Error: no such option: --not_real_arg

compare to:

admin@vlab-01:~$ show ip route not_real -h
Usage: show ip route [OPTIONS] COMMAND [ARGS]...
Try "show ip route -h" for help.

Error: No such command "not_real".
admin@vlab-01:~$ show ip route ? vrf
Usage: show ip route [OPTIONS] COMMAND [ARGS]...

Show IP (IPv4) routing table

Options:
  -d, --display TEXT    all|frontend
  -n, --namespace TEXT  Namespace name or all
  --verbose             Enable verbose output
  -h, -?, --help        Show this message and exit.

Commands:
  A.B.C.D         Network in the IP routing table to display
  A.B.C.D/M       IP prefix <network>/<length>, e.g., 35.0.0.0/8
  babel           Babel routing protocol (Babel)
  bgp             Border Gateway Protocol (BGP)
  connected       Connected routes (directly attached subnet or host)
  eigrp           Enhanced Interior Gateway Routing Protocol (EIGRP)
  isis            Intermediate System to Intermediate System (IS-IS)
  json            JavaScript Object Notation
  kernel          Kernel routes (not installed via the zebra RIB)
  local           Local routes (directly attached host route)
  mrib            Multicast SAFI table
  nexthop-group   Nexthop Group Information
  nhrp            Next Hop Resolution Protocol (NHRP)
  openfabric      OpenFabric Routing Protocol
  ospf            Open Shortest Path First (OSPFv2)
  rip             Routing Information Protocol (RIP)
  sharp           Super Happy Advanced Routing Protocol (sharpd)
  static          Statically configured routes
  summary         Summary of all routes
  supernets-only  Show supernet entries only
  table           Table to display
  table-direct    Non-main Kernel Routing Table - Direct
  tag             Show only routes with tag
  vnc             Virtual Network Control (VNC)
  vrf             Specify the VRF
admin@vlab-01:~$ show ip route --not_real_arg --help
Usage: show ip route [OPTIONS] [ARGS]...
Try "show ip route -h" for help.

Error: no such option: --not_real_arg
admin@vlab-01:~$ show ip route not_real vrf -?
Usage: show ip route [OPTIONS] COMMAND [ARGS]...
Try "show ip route -h" for help.

Error: No such command "not_real".
admin@vlab-01:~$ show ip route summary not_real prefix -?
Usage: show ip route summary [OPTIONS] COMMAND [ARGS]...
Try "show ip route summary -h" for help.

Error: No such command "not_real".

Finally, all "show ip route" commands now have completions for subcommands (note that for commands with no completion available, the completion falls back to trying to find file names in the current directory, which is the default click behavior):

admin@vlab-01:~$ show ip route
babel           connected       isis            kernel          mrib            nhrp            ospf            sharp           summary         table           tag             vrf
bgp             eigrp           json            local           nexthop-group   openfabric      rip             static          supernets-only  table-direct    vnc
admin@vlab-01:~$ show ip route ta
table         table-direct  tag
admin@vlab-01:~$ show ip route json
.ansible/                  .bashrc                    .sudo_as_admin_successful
.bash_history              main.py                    .viminfo
.bash_logout               .profile                   vtysh_helper.py

@mssonicbld
Copy link
Collaborator

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

Add a new `VtyshCommand` class that can be used to extend click cli
commands with `vtysh` help text. The class calls down into `vtysh` to
get subcommand information and then generates help text following the
existing format used by the top-level SONiC CLI.

Add bash completions for the `vtysh` subcommands.

Fixes:
[24036](sonic-net/sonic-buildimage#24036)
@anders-nexthop anders-nexthop force-pushed the anders.24036.add-vtysh-help branch from 11f956f to 3a44baf Compare November 10, 2025 23:41
@mssonicbld
Copy link
Collaborator

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@anders-nexthop anders-nexthop marked this pull request as ready for review November 11, 2025 16:27
@anders-nexthop
Copy link
Contributor Author

@qiluo-msft @liamkearney-msft please take a look

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enhancement: Show options for show ip route

2 participants