Last active
April 9, 2020 20:23
-
-
Save clouetb/0719ed518cb3484eeb9696a56c6ad560 to your computer and use it in GitHub Desktop.
A utility for flattening CISCO 'show system internal l2fm l2dbg macdb' command output
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import regex as re | |
from sys import argv, exit | |
macdb_regexpr = r""" | |
# Some examples matched by this regexp : | |
# VLAN: 2324 MAC: d867.d972.0fc3 | |
# Time If/swid Db Op Src Slot FE Count | |
# Mon Apr 6 20:37:34 2020 0x160003e6 0 INSERT 3 5 7 | |
# Mon Apr 6 20:37:59 2020 0x160003e6 0 NON_PI_MOD 3 2 15 6 | |
# Mon Apr 6 21:33:03 2020 0x160003e6 0 FLUSH 2 0 15 | |
# | |
# VLAN: 1982 MAC: d4d2.52ca.931a FE ID: 4 | |
# Time If/swid Db Op Src Slot FE Count | |
# Tue Apr 7 12:54:21 2020 0x16000024 0 AGE 3 5 4 | |
# Tue Apr 7 16:38:00 2020 0x16000024 0 AGE 3 6 4 | |
# | |
# VLAN: 197 MAC: 0000.0c9f.f0c5 | |
# Time If Db Op Src Slot FE Local Remote | |
# Tue Apr 7 22:20:01 2020 0x090300c5 1 MAC_SMLIST 2 0 15 0 0 | |
# Tue Apr 7 22:20:01 2020 0x090300c5 1 GWMAC_SKIP_NO_CHG 2 0 15 0 0 | |
# Test this regexp here https://regex101.com/r/dA9sQ5/8 | |
(?(DEFINE) | |
(?P<vlan_descriptor> # A VLAN descriptor is an header with either a local or a remote descriptor | |
(?&vlan_header) | |
(?&local_or_remote_vlan) | |
) | |
(?P<local_or_remote_vlan> # A VLAN can be either local or remote | |
(?&local_vlan) | |
| | |
(?&remote_vlan) | |
) | |
(?P<local_vlan> # Local VLAN has local column header "Time If/swid Db Op Src Slot FE Count" and local columns | |
(?&local_vlan_column_header) | |
(?&local_vlan_event)+ # and several local style events | |
) | |
(?P<local_vlan_column_header>\s*Time\s*If\/swid\s*Db\s*Op\s*Src\s*Slot\s*FE\s*Count) | |
(?P<local_vlan_event>\s*(?&full_date)\s*(?&ifswid)\s*(?&db)\s*(?&op)\s*(?&src)\s*(?&slot)\s*(?&fe)\s*(?&count)?) | |
(?P<remote_vlan> # Remote VLAN has remote column header "Time If Db Op Src Slot FE Local Remote" and local columns | |
(?&remote_vlan_column_header) | |
(?&remote_vlan_event)+ # and several remote style events | |
) | |
(?P<remote_vlan_column_header>\s*Time\s*If\s*Db\s*Op\s*Src\s*Slot\s*FE\s*Local\s*Remote) | |
(?P<remote_vlan_event>\s*(?&full_date)\s*(?&ifswid)\s*(?&db)\s*(?&op)\s*(?&src)\s*(?&slot)\s*(?&fe)\s*(?&local)\s*(?&remote)) | |
# VLAN header has VLAN id and MAC address and possibly an FE ID | |
(?P<vlan_header>\s*VLAN:\s*(?&vlan_id)\s*MAC:\s*(?&mac_address)\s*(FE\ ID:\s*(?&feid))?) | |
(?P<vlan_id>[0-9]+) | |
(?P<mac_address>[0-9a-f]{4}.[0-9a-f]{4}.[0-9a-f]{4}) | |
(?P<feid>[0-9]+) | |
(?P<full_date>(?&day)\s*(?&month)\s*(?&day_in_month)\s*(?&time)\s*(?&year)) | |
(?P<day>Mon|Tue|Wed|Thu|Fri|Sat|Sun) | |
(?P<day_in_month>[0-9]+) | |
(?P<month>Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) | |
(?P<year>[0-9]{4}) | |
(?P<time>([0-1][0-9]|[2][0-3]):([0-5][0-9]):([0-5][0-9])) | |
(?P<ifswid>0x[0-9a-f]{8}) | |
(?P<op>[A-Z]([A-Z_]*)) | |
(?P<db>[0-9]+) | |
(?P<src>[0-9]+) | |
(?P<slot>[0-9]+) | |
(?P<fe>[0-9]+) | |
(?P<count>([0-9]+)) | |
(?P<local>([0-9]+)) | |
(?P<remote>([0-9]+)) | |
) | |
# Match all kind of VLAN descriptors (see above) | |
(?&vlan_descriptor) | |
""" | |
if len(argv) < 2: | |
print(f"""Usage :\n\t{__file__} [macdb file]""") | |
exit(1) | |
# Open parameter on command line | |
buffer = open(argv[1]).read() | |
expression = re.compile(macdb_regexpr, re.MULTILINE | re.VERBOSE) | |
# Extract all the matches in the specified file | |
matches = expression.finditer(buffer) | |
for match in matches: | |
# Returns a dict where each column contents is in a list | |
match_dict = match.capturesdict() | |
# VLAN type Local or Remote (don't know if useful) | |
local_or_remote = "L" if match_dict["local_vlan"] else "R" | |
for counter, event in enumerate(match_dict["full_date"], start=0): | |
# Output format is VLAN_ID;MAC_ADDR;L or R;Date and time;If/Swid;Op | |
print( | |
f"{match_dict['vlan_id'][0]};{match_dict['mac_address'][0]};" | |
f"{local_or_remote};{match_dict['full_date'][counter]};{match_dict['ifswid'][counter]};" | |
f"{match_dict['op'][counter]}" | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment