Mastering the TNSR® Command Line Interface (CLI)

Introduction

In the age of automation and orchestration, a Command Line Interface, or CLI, is still required and super handy to test commands or for quick troubleshooting. When a network engineer gets familiar with a new device, usually first impressions come from the CLI. The TNSR software router offers an industry-standard CLI; this means that engineers who are already familiar with the industry-standard CLI should be comfortable configuring, managing, and troubleshooting TNSR right out of the box. It shouldn’t take much time to get used to TNSR CLI syntax, and run commands fluently. Of course, like other network products, TNSR software has some CLI specifics, and that is what this post will help you master.

Let’s talk a little bit about the inner workings of TNSR and how the CLI works. As a VPP-based software router, TNSR runs on multiple open-source projects. The management plane, which includes CLI and RESTCONF, is provided by Clixon. To learn more about RESTCONF and how to manage TNSR via Postman, check out Setting Up Postman for TNSR Management via API. Clixon provides CLI and RESTCONF configuration interfaces based on YANG data modeling. For the details of Clixon, visit the Clixon project website. TNSR YANG models can be found here.

 

Basic Navigation and Commands

TNSR CLI Modes

TNSR has two CLI modes: regular (master) and global configuration mode. In regular mode, you can run show commands, and troubleshooting commands like ping and traceroute. Configuration mode allows you to configure TNSR. 

Command Prompt

The TNSR CLI command prompt has several components:

<hostname> tnsr<(mode)># <user input>

In the next brief example, router is the hostname, and the mode section of the prompt is shown changing when a command enters or exits a mode.

router tnsr# configure
router tnsr(config)# interface GigabitEthernet3/0/0
router tnsr(config-interface)# description <<LAN interface>>
router tnsr(config-interface)# exit
router tnsr(config)# exit
router tnsr#

Command History

The TNSR CLI stores the last 300 commands across sessions. This command history is kept in ~/.tnsr_history.

You can access the command history by pressing Ctrl-P (to see the previous command), Ctrl-N (to see the next command), or by using the up and down arrow keys.

Command Completion

The TNSR CLI supports case-sensitive tab expansion and prediction for input to speed up interactive work. For example, you can type the first few letters of a command or entity (depending on the context), and then press the tab key to complete a portion or all of the remaining input where possible. You can also shorten commands or entities provided the input is not ambiguous.

Type ? to show possible completions of the current command when in the middle of a word, or type it between words to show the next available parameter.

In the following example, the user starts typing a command wr and types ? to see all possible combinations of commands available. The user then presses tab, and the TNSR CLI autocompletes the command:

router tnsr(config)# wr
write-running-config Copy the running configuration to startup
router tnsr(config)# wr
router tnsr(config)# write-running-config
router tnsr(config)#

Keyboard Shortcuts

The TNSR CLI supports several CLI navigation and editing key combinations, including:

Command Keys
Previous History Command Ctrl-P or up arrow
Next History Command Ctrl-N or down arrow
Erase Character Ctrl-H or backspace
Erase Word Ctrl-W
Cursor to Start of Line Ctrl-A
Cursor to End of Line Ctrl-E
Clear and Redraw Screen Ctrl-L
Exit the CLI Ctrl-D
Context-Sensitive Help ?

 

Searching and Filtering Output

TNSR show commands allow additional modifiers using ‘|’ (pipe character).

router tnsr# show interface | 
 count                  exclude                match                  tail 

Use count to display the number of lines in the show command output.

router tnsr# show logging | count
10001

Use exclude to exclude unwanted lines.

router tnsr# show logging recent-lines 20 | exclude charon
Jul 26 20:23:35 router vpp_prometheus_export[5404]: Client address is [::]:0
Jul 26 20:23:50 router vpp_prometheus_export[5404]: Client address is [::]:0
Jul 26 20:24:05 router vpp_prometheus_export[5404]: Client address is [::]:0

Use match to filter the output, displaying only lines matching the pattern(s) you specify. Use regex for specific patterns.

router tnsr# show interface | match Interface|rate
Interface: wan1
      Five minute input rate 0 bits/sec, 0 packets/sec
      Five minute output rate 0 bits/sec, 0 packets/sec
      0 drops, 0 punts, 0 rx miss, 0 rx no buffer
Interface: wan2
      Five minute input rate 0 bits/sec, 0 packets/sec
      Five minute output rate 0 bits/sec, 0 packets/sec
      0 drops, 0 punts, 0 rx miss, 0 rx no buffer
Interface: wan3
      Five minute input rate 221 bits/sec, 0 packets/sec
      Five minute output rate 0 bits/sec, 0 packets/sec
      19894 drops, 0 punts, 0 rx miss, 0 rx no buffer
Interface: wan4
      Five minute input rate 13477 bits/sec, 8 packets/sec
      Five minute output rate 12776 bits/sec, 8 packets/sec
      259812 drops, 0 punts, 0 rx miss, 0 rx no buffer
Interface: wan4.128
      Five minute input rate 13256 bits/sec, 8 packets/sec
      Five minute output rate 12776 bits/sec, 8 packets/sec
      239933 drops, 0 punts, 0 rx miss, 0 rx no buffer

Use tail to display the last lines of the show command output. The following example displays the last eight lines of the output (last line happens to be empty).

router tnsr# show interface wan4.128 | tail 8
    counters:
      Five minute input rate 13678 bits/sec, 8 packets/sec
      Five minute output rate 12143 bits/sec, 8 packets/sec
      received: 109643672 bytes, 563159 packets, 0 errors
      transmitted: 111011451 bytes, 545131 packets, 0 errors
      protocols: 246655 IPv4, 35249 IPv6
      240785 drops, 0 punts, 0 rx miss, 0 rx no buffer

Configuration and Management

Configuration Database

TNSR software maintains three separate configuration databases: startup, candidate, and running. These files are stored as XML in /var/tnsr/

  • Startup configuration is loaded when the host boots up.
  • Candidate configuration is the in-process potential configuration that exists while the TNSR configuration is being actively edited. When committed, TNSR will accept this configuration as the running configuration if it is free of errors.
  • Running configuration is the active running configuration, which reflects the current TNSR state.

Saving Configuration

For changes to persist between reboots of the TNSR host, the running configuration must be copied to the startup configuration, as shown in this example:

router tnsr# configure
router tnsr(config)# configuration copy running startup

There is a shortcut command for copying running to startup, which may be familiar to Cisco IOS users:

router tnsr(config)# write

Viewing Configuration

To view the configuration databases in CLI format, use the show configuration command followed by the database name. For example:

tnsr# show configuration running

Or use the shortcut to specify the running configuration:

tnsr# show run

In addition to the CLI format, TNSR can display JSON or XML format as well. Simply add json or xml at the end of your command as shown in the following example:

router tnsr# show run json
Jul 26 14:28:07.917555: populate_self_parent: 204: No YANG spec for namespace, anydata used
{
  "netgate-acl:acl-config": {
      "acl-table": {
        "acl-list": [
            {
              "acl-name": "test",
              "acl-rules": {
                  "acl-rule": [
                    {
                        "sequence": 10,
                        "action": "deny",
                        "ip-version": "ipv4"
                    }
                  ]
              }
            }
        ]
      }
  }
...
router tnsr# show run xml
<acl-config xmlns="urn:netgate:xml:yang:netgate-acl">
   <acl-table>
      <acl-list>
        <acl-name>test</acl-name>
        <acl-rules>
            <acl-rule>
              <sequence>10</sequence>
              <action>deny</action>
              <ip-version>ipv4</ip-version>
            </acl-rule>
        </acl-rules>
      </acl-list>
  </acl-table>
</acl-config>
...

TNSR CLI can display specific portions of the configuration. This feature is based on the Clixon YANG model. If you start typing the show run command and press tab you will see the list of YANG modules, sometimes called containers:

router tnsr# show run
abf                           access_list                acl                      
as_path                    bfd                           bgp                      
bond                        bridge                     cfgfile                  
community_list        conf_history             crypto                   
gre                           host_acl                   host_if                  
host_route               intf                          ip                       
ipfix                         ipip                          ipsec_if                 
json                          kea                          ldap                     
lldp                          logging                    loopback                 
macip                       memif                     nacm                     
nat                           nat_glob_opts         neighbor                 
npf                           ntp                          ospf                     
ospf6                       prefix_list                 prometheus               
radius                      restconf                   rip                      
route                       route_map               route_tbl                
rpki                          snmp                       span                     
ssh_server               subif                         sysctl                   
system                     system_kernel         tap                      
teib                          trace                        unbound                  
vhost_user               vrrp                          vxlan                    
wireguard                XML                         zebra                    
|       

Running configuration can be displayed for each of these specific modules. As an example let’s show the running configuration for the nacm module in CLI/JSON/XML formats:

router tnsr# show run nacm
nacm disable
nacm read-default deny
nacm write-default deny
nacm exec-default deny
nacm group admin

    member root
    member tnsr
exit
nacm rule-list admin-rules
    group admin
    rule permit-all
        module *
        access-operations *
        action permit
    exit
exit
nacm enable
router tnsr# show run nacm json
{
  "ietf-netconf-acm:nacm": {
      "enable-nacm": true,
      "read-default": "deny",
      "write-default": "deny",
      "exec-default": "deny",
      "groups": {
        "group": [
            {
              "name": "admin",
              "user-name": [
                  "root",
                  "tnsr"
                  ]
            }
        ]
      },
      "rule-list": [
        {
            "name": "admin-rules",
            "group": [
              "admin"
              ],
            "rule": [
              {
                  "name": "permit-all",
                  "module-name": "*",
                  "access-operations": "*",
                  "action": "permit"
              }
            ]
        }
      ]
  }
}
router tnsr# show run nacm xml
<nacm xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-acm">
  <enable-nacm>true</enable-nacm>
  <read-default>deny</read-default>
  <write-default>deny</write-default>
  <exec-default>deny</exec-default>
  <groups>
      <group>
        <name>admin</name>
        <user-name>root</user-name>
        <user-name>tnsr</user-name>
      </group>
  </groups>
  <rule-list>
      <name>admin-rules</name>
      <group>admin</group>
      <rule>
        <name>permit-all</name>
        <module-name>*</module-name>
        <access-operations>*</access-operations>
        <action>permit</action>
      </rule>
  </rule-list>
</nacm>

Some of the show commands have brief or verbose versions.

router tnsr# show ipsec tun brief
  Client     Remote Address     Status P1/P2             Uptime P1/P2 (secs)    Virtual IPv4       Virtual IPv6
  ------     --------------     ------------             -------------------    ------------       ------------
IPsec Tunnel Mobile Clients:  10
  user-94    172.25.128.104    ESTABLISHED/INSTALLED        3220 /      618    172.25.192.103    fc00:0:25:192::6d
  user-31    172.25.128.41      ESTABLISHED/INSTALLED        3119 /      464    172.25.192.40      fc00:0:25:192::2e
  user-12    172.25.128.22      ESTABLISHED/INSTALLED        3081 /      312    172.25.192.21      fc00:0:25:192::1b
  user-51    172.25.128.61      ESTABLISHED/INSTALLED        3044 /      377    172.25.192.60      fc00:0:25:192::42
  user-46    172.25.128.56      ESTABLISHED/INSTALLED        3007 /      413    172.25.192.55      fc00:0:25:192::3d
  user-23    172.25.128.33      ESTABLISHED/INSTALLED        3003 /      342    172.25.192.32      fc00:0:25:192::26
  user-75    172.25.128.85      ESTABLISHED/INSTALLED        2994 /      400    172.25.192.84      fc00:0:25:192::5a
  user-52    172.25.128.62      ESTABLISHED/INSTALLED        2991 /      330    172.25.192.61      fc00:0:25:192::43
router tnsr# show ipsec tun verbose
IPsec Tunnel: 10
    IKE SA: ipip10    ID: 17440    Version: IKEv2
        Local: 172.25.128.5[4500]    Remote: 172.25.128.104[4500]
        Virtual: 172.25.192.103, fc00:0:25:192::6d
        Status: ESTABLISHED    Up: 3284s    Rekey: 21387s
        Local ID: 172.25.128.5    Remote ID: user-94
        Cipher: AES_GCM_16 256
        PRF: PRF_HMAC_SHA2_256    DH: MODP_2048
        SPI Init: 9512334119557307410    Resp: 7172180167503279378
        Initiator: no
        Child SA: child0    ID: 69934
            Status: INSTALLED    Up: 682s    Rekey: 502s    Expire: 758s
            Received: 0 bytes, 0 packets
            Transmitted: 0 bytes, 0 packets
            Cipher: AES_GCM_16 256    PFS: MODP_2048
            SPI in: 1506368287    out: 3435554280
    IKE SA: ipip10    ID: 17441    Version: IKEv2
        Local: 172.25.128.5[4500]    Remote: 172.25.128.41[4500]
        Virtual: 172.25.192.40, fc00:0:25:192::2e
        Status: ESTABLISHED    Up: 3183s    Rekey: 21842s
        Local ID: 172.25.128.5    Remote ID: user-31
        Cipher: AES_GCM_16 256
        PRF: PRF_HMAC_SHA2_256    DH: MODP_2048
        SPI Init: 5218707067714609809    Resp: 15127439742586380164
        Initiator: no
        Child SA: child0    ID: 69953
            Status: INSTALLED    Up: 528s    Rekey: 624s    Expire: 912s
            Received: 0 bytes, 0 packets
            Transmitted: 0 bytes, 0 packets
            Cipher: AES_GCM_16 256    PFS: MODP_2048
            SPI in: 3942101993    out: 3297140859

Configuration History

TNSR can track configuration history using Git. Depending on user preference, this history can be used in either a manual or automated manner. Stored versions can be manually loaded to roll back to earlier configurations as needed.

Let’s look at a real-world scenario to demonstrate this feature. In the following example, we’ll save the current configuration, make a change to it, save the new configuration, and finally, revert back to the original configuration:

Step1 Take a snapshot of the current configuration state. Initially the state of the lan2 interface is Admin disabled:

router tnsr(config)# sh run int                        
...
interface lan2
    disable
exit
...

To take the snapshot:

router tnsr(config)# configuration history version save lan2-disabled

Step 2 Enable the lan2 interface and take a new snapshot:

router tnsr(config)# interface lan2
router tnsr(config-interface)# enable
router tnsr(config-interface)# exit
router tnsr(config)# configuration history version save lan2-enabled

We can see the two snapshots, before and after our change:

router tnsr(config)# show configuration history versions            
lan2-disabled
lan2-enabled

Step 3 Execute a diff check of our snapshots.

For those of you who are familiar with the Git diff output, this output will be easy to read. Regardless, the output is quite self-explanatory. “-” and “+” signs indicate what lines were removed and added from the running configuration database file (running_db). In the case of our example, enable false was replaced with enable true:

router tnsr(config)# show configuration history version-diff lan2-disabled lan2-enabled
diff --git a/running_db b/running_db
index 04eba3e..b3a6805 100644
--- a/running_db
+++ b/running_db
@@ -117,7 +117,7 @@
      </interface>
      <interface>
          <name>lan2</name>
-         <enabled>false</enabled>
+         <enabled>true</enabled>
      </interface>
      <interface>
          <name>wan1</name>

Step 4 Restore to the initial configuration state.

Finally, let’s restore Initial configuration state and make sure that interface lan2 is Admin disabled:

router tnsr(config)# configuration history version load lan2-disabled
TNSR services or dataplane restart could be required!
router tnsr(config)# sh run int                                     
...
interface lan2
    disable
exit

...

This feature provides robust running configuration management and allows network engineers to back up, manage, and roll back their configuration changes. Backup and configuration history may be helpful during planned changes as post-change steps to quickly revert changes if something goes wrong. For more information on this feature, please visit our documentation page.

Conclusion

The TNSR CLI was designed to provide a user-friendly and industry-standard interface familiar to almost all network engineers. It has robust functionality to manage and show current device states. It’s easy to navigate the TNSR CLI and filter a specific configuration and show command outputs, allowing network engineers to troubleshoot quickly and effectively. We hope you find the TNSR CLI tips and commands in this article useful as you navigate and manage your TNSR router. Netgate will keep improving the CLI to give you a better user experience.