App Dev · · 4 min read
NetLay: Teaching it to read a running-config
Building a switch importer before the real exports arrived, parsing Cisco output without a library, and why nothing gets written until you have seen the plan.
Waiting for the network team#
Everything in NetLay so far has been typed in by hand. That is fine for the cabinet in your own office and entirely unreasonable for a site with fifteen switches, so the obvious next step is to let the switches tell the app what they know.
The obvious problem with that step was this note to myself.
"We will be doing the switch imports but I am waiting to get the information from the central network team."
Waiting for other people is a good way to lose a month. Cisco's output formats are stable and documented though, so I built against synthetic captures written from the documentation and my own memory of staring at them, on the understanding that everything would need checking against reality later.
Six pieces of output.#
You paste what you have and the app uses whichever parts turned up. The running configuration is the only one it insists on, because that is what gives it the shape of the switch, the interfaces, the VLANs and the descriptions.
After that, CDP neighbours tell it which ports lead to other switches, phones or access points. The MAC address table says which devices are on which port. The ARP table turns those MAC addresses into IP addresses. The inventory and version output supply serial numbers and the software release.
None of them individually produce a map. Together they produce a very good first draft of one.
Parsing without a library.#
There is no neat library for this, and writing one properly is a career, so the job is to handle what actually appears in the wild.
Interface names arrive in at least four shapes, the full GigabitEthernet1/0/24, the short Gi1/0/24, the spaced Gig 1/0/1, and the 2960's Gi0/1 with no stack member at all, which gets read as member one. The modules on a switch are worked out from what is configured on it, by taking the highest port number seen for each member and slot. Ten gig ports in slot one become an SFP network module, and stackable models get their stack ports added.
VLAN lists come as 100,200 and as ranges like 10-20, and the management address is the first switched virtual interface that has an address and is not shut down.
The MAC table has its own quirks. Rows for All and the CPU get dropped. Ports with several MAC addresses on them, which is almost always a phone with a PC plugged into the back of it, are skipped by default rather than guessed at.
The plan is the product.#
This is the design decision I feel strongest about in the whole application.
The importer never writes anything when you press import. It shows you a plan. Every switch it would create, every port VLAN it would set, every device it would add, every uplink it would draw, each one a row with a tick box. Nothing touches the database until you press apply, and you can untick anything you disagree with.
That matters because this tool exists to be trusted. A tool that rewrites your documentation from a paste is a tool you will stop using the first time it gets something wrong, and it will get something wrong, because somebody's switch will have a description on it that says "DO NOT USE - ask Dave".
Re-importing works the same way. Switches are matched by name and stack member, port VLANs that have not changed come up unticked, and devices already sitting on a port are left alone. Uplinks pointing at a switch that is not on the map yet are listed as pending, so you import that one and run it again.
Then the real exports arrived.#
They were worse than my synthetic ones, as everybody who has ever done this could have told me.
Real captures are full of --More-- prompts where somebody paged through the output, backspace characters, stray carriage returns and the occasional escape sequence from a terminal that was trying to be helpful. All of that is now stripped before anything is parsed.
The Nexus cores in the middle were a different dialect again, with their own MAC table format and Ethernet interface names. LLDP output is merged with CDP where both exist, with CDP winning on any port they both describe, and there is a rule that anything LLDP calls a bridge never becomes an uplink, because LLDP describes phones and access points that way and I would rather not draw an uplink to a desk phone.
There is also a path for when the network team will not hand over a running configuration at all, which happens. Interface status output on its own is enough to get the ports and descriptions, and the switch name comes from the prompt in the capture, from the version output, or from a box you fill in.
The honest state at the end of this post is that it reads everything I have been given correctly, and it has still never been run against a site I did not already have the answers for.
Next time, pointing the same parser at a map I built by hand, and asking it where I got it wrong.