By Glenn McCallum

TextFSM parse Cisco output

I recently got a file with all the show cdp neighbour detail from 200 routers in a network and was required to produce a report to show all the devices and their direct connections.

I have cut the output to 3 routers for this example and simplified the output to Router1 to Router3

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Router1
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
terminal length 0
Router1#show cdp neighbors detail
-------------------------
Device ID: Switch1
Entry address(es): 
  IP address: 1.1.1.1
Platform: cisco WS-C2960-48PST-L,  Capabilities: Switch IGMP 
Interface: GigabitEthernet0/1/0,  Port ID (outgoing port): FastEthernet0/48
Holdtime : 139 sec

Version :
Cisco IOS Software, C2960 Software (C2960-LANBASEK9-M), Version 12.2(55)SE5, RELEASE SOFTWARE (fc1)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 1986-2012 by Cisco Systems, Inc.
Compiled Thu 09-Feb-12 19:11 by prod_rel_team

advertisement version: 2
Protocol Hello:  OUI=0x00000C, Protocol ID=0x0112; payload len=27, value=00000000FFFFFFFF010221FF00000000000034A84E680E80FF0000
VTP Management Domain: 'toxfree'
Native VLAN: 1
Duplex: full
Management address(es): 
  IP address: 1.1.1.1


Total cdp entries displayed : 1
Router1#

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Router2
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
terminal length 0
Router2#show cdp neighbors detail
-------------------------
Device ID: Switch2
Entry address(es): 
  IP address: 1.1.1.2
Platform: Cisco C867VAE-K9,  Capabilities: Router Trans-Bridge Source-Route-Bridge Switch IGMP 
Interface: GigabitEthernet0/0/0,  Port ID (outgoing port): GigabitEthernet1
Holdtime : 175 sec

Version :
Cisco IOS Software, C860 Software (C860VAE2-ADVSECK9-M), Version 15.6(3)M3a, RELEASE SOFTWARE (fc2)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 1986-2017 by Cisco Systems, Inc.
Compiled Tue 19-Sep-17 00:39 by prod_rel_team

advertisement version: 2
VTP Management Domain: ''
Native VLAN: 5
Duplex: full
Management address(es): 
  IP address: 1.1.1.2

-------------------------
Device ID: Switch3
Entry address(es): 
  IP address: 1.1.1.3
Platform: cisco WS-C2960X-24PS-L,  Capabilities: Switch IGMP 
Interface: GigabitEthernet0/1/0,  Port ID (outgoing port): GigabitEthernet1/0/24
Holdtime : 167 sec

Version :
Cisco IOS Software, C2960X Software (C2960X-UNIVERSALK9-M), Version 15.2(2)E4, RELEASE SOFTWARE (fc2)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 1986-2016 by Cisco Systems, Inc.
Compiled Fri 12-Feb-16 22:57 by prod_rel_team

advertisement version: 2
Protocol Hello:  OUI=0x00000C, Protocol ID=0x0112; payload len=27, value=00000000FFFFFFFF010221FF0000000000005006ABCB6980FF0000
VTP Management Domain: ''
Native VLAN: 1
Duplex: full
Management address(es): 
  IP address: 1.1.1.3


Total cdp entries displayed : 2
Router2#

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Router3
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
terminal length 0
Router3#show cdp neighbors detail
-------------------------
Device ID: Switch4
Entry address(es): 
  IP address: 1.1.1.4
Platform: cisco WS-C3560CG-8PC-S,  Capabilities: Switch IGMP 
Interface: GigabitEthernet0/1/0,  Port ID (outgoing port): GigabitEthernet0/9
Holdtime : 143 sec

Version :
Cisco IOS Software, C3560C Software (C3560c405ex-UNIVERSALK9-M), Version 15.2(2)E4, RELEASE SOFTWARE (fc2)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 1986-2016 by Cisco Systems, Inc.
Compiled Sat 13-Feb-16 02:28 by prod_rel_team

advertisement version: 2
Protocol Hello:  OUI=0x00000C, Protocol ID=0x0112; payload len=27, value=00000000FFFFFFFF010221FF0000000000009C57AD04C500FF0000
VTP Management Domain: ''
Native VLAN: 1
Duplex: full
Management address(es): 
  IP address: 1.1.1.4


Total cdp entries displayed : 1
Router3#

Create a folder named textfsm and save the above output as show_cdp.txt

I am using Sublime Text, python 3.8 and TextFSM to complete this so you can follow along

I am going to assume you already have Python installed so lets install TextFSM, im using Ubuntu so

sudo apt install python3-textfsm

You can download all the textfsm templates from https://github.com/networktocode/ntc-templates but we are only going to use the template named cisco_ios_show_cdp_neighbors_detail.textfsm also shown below

Value Required DESTINATION_HOST (\S+)
Value MANAGEMENT_IP (\d+\.\d+\.\d+\.\d+|\w+\.\w+\.\w+)
Value PLATFORM (.*)
Value REMOTE_PORT (.*)
Value LOCAL_PORT (.*)
Value SOFTWARE_VERSION (.*$)
Value CAPABILITIES (.+?)

Start
  ^Device ID: ${DESTINATION_HOST}
  ^Entry address\(es\)\s*:\s* -> ParseIP
  ^Platform\s*:\s*${PLATFORM}\s*,\s*Capabilities\s*:\s*${CAPABILITIES}\s+$$
  ^Platform\s*:\s*${PLATFORM}\s*,\s*Capabilities\s*:\s*${CAPABILITIES}$$
  ^Interface: ${LOCAL_PORT},  Port ID \(outgoing port\): ${REMOTE_PORT}
  ^Version : -> GetVersion
  # Capture time-stamp if vty line has command time-stamping turned on
  ^Load\s+for\s+
  ^Time\s+source\s+is

ParseIP
  ^.*IP address: ${MANAGEMENT_IP} -> Start
  ^Platform\s*:\s*${PLATFORM}\s*,\s*Capabilities\s*:\s*${CAPABILITIES}\s+$$ -> Start
  ^Platform\s*:\s*${PLATFORM}\s*,\s*Capabilities\s*:\s*${CAPABILITIES}$$ -> Start
  ^.* -> Start

GetVersion
  ^${SOFTWARE_VERSION} -> Record Start

Create a folder named “templates” inside textfsm folder and save the above to a file named cisco_ios_show_cdp_neighbors_detail.textfsm

Below is how I started the script to test TextFSM parsing was working

import textfsm
import json
from pprint import pprint
import re

# Load cisco output into file_data
input_file = open("show_cdp.txt", encoding='utf-8')
file_data = input_file.read()
input_file.close()

# Use textfsm show cdp neighbour detail template
template = open("templates/cisco_ios_show_cdp_neighbors_detail.textfsm")
re_table = textfsm.TextFSM(template)
parsed_output = re_table.ParseText(file_data)

# Parsed output into Dict and print using pretty print
results = [dict(zip(re_table.header, textfsm)) for textfsm in parsed_output]
pprint(results)

Save the above as textfsm_parse_cdp_neighbour_detail.py

With Sublime text you can run the script within sublime by going to Tools->Build System -> Python and then you can just press Control+b to run the script and output will be generated below

You can see that the output in bottom section of window is showing the outputs using Pretty Print but i noticed it did not capture the actual Hosts (ie Router 1, Router2, Router3)

So I made an edit in bold to the TextFSM template below to capture the Hosts to put into the report. I am only using a simple regex to capture the string before the # in each line in show_cdp.txt like

Router1#show cdp neighbors detail 

Add the below in bold to your TextFSM template

Value HOST (.*)
Value Required DESTINATION_HOST (\S+)
Value MANAGEMENT_IP (\d+\.\d+\.\d+\.\d+|\w+\.\w+\.\w+)
Value PLATFORM (.*)
Value REMOTE_PORT (.*)
Value LOCAL_PORT (.*)
Value SOFTWARE_VERSION (.*$)
Value CAPABILITIES (.+?)


Start
  ^${HOST}#show\scdp\sneighbors\sdetail
  ^Device ID: ${DESTINATION_HOST}
  ^Entry address\(es\)\s*:\s* -> ParseIP
  ^Platform\s*:\s*${PLATFORM}\s*,\s*Capabilities\s*:\s*${CAPABILITIES}\s+$$
  ^Platform\s*:\s*${PLATFORM}\s*,\s*Capabilities\s*:\s*${CAPABILITIES}$$
  ^Interface: ${LOCAL_PORT},  Port ID \(outgoing port\): ${REMOTE_PORT}
  ^Version : -> GetVersion
  # Capture time-stamp if vty line has command time-stamping turned on
  ^Load\s+for\s+
  ^Time\s+source\s+is

ParseIP
  ^.*IP address: ${MANAGEMENT_IP} -> Start
  ^Platform\s*:\s*${PLATFORM}\s*,\s*Capabilities\s*:\s*${CAPABILITIES}\s+$$ -> Start
  ^Platform\s*:\s*${PLATFORM}\s*,\s*Capabilities\s*:\s*${CAPABILITIES}$$ -> Start
  ^.* -> Start

GetVersion
  ^${SOFTWARE_VERSION} -> Record Start

Run your script file again and you will now see HOST output

Now we want to output this to a CSV file so add the below at the bottom of your script

# open csv file for output
output = open("cdp_report.csv", "w+")
cdp_report = output

# Write the csv headers on first row
print(re_table.header)
for s in re_table.header:
    cdp_report.write("%s;" % s)
cdp_report.write("\n")

# Write each result to a new row in cdp report
counter = 0
for row in parsed_output:
    print(row)
    for s in row:
        cdp_report.write("%s;" % s)
    cdp_report.write("\n")
    counter += 1

# Print to screen how many rows printed
print("\nWrote %d devices" % counter)

Run your script again in Sublime with Control+b and this should now generate a csv file named cdp_report.csv and output should look like below but there is a small issue. Can you see it?

It is missing Router2 in Cell A4. Router2 has two cdp neighbours where Router1 and Router 3 has only one cdp neighbour each. To fix this we can use a feature on TextFSM called Filldown

Filldown - value that previously matched with a regex, remembered until the next processing line (if has not been explicitly cleared or matched again). This means that the last column value that matches regex is stored and used in the following strings if this column is not present.

So go back and edit your template file and add Filldown to the first line we added in

Value Filldown HOST (.*)

Rerun your script and reopen your csv file and this should be fixed

I hope this demonstrates the power of TextFSM in a practical way to process Cisco output.

I have the full code details on my github https://github.com/glennmccallum/textfsm-parse-cisco-output

Please leave any comments below or any questions

Share this:
Cisco, Network Automation, Python, Scripting 0

Leave a Reply

Your email address will not be published. Required fields are marked *