In Part 1 of Best way to start writing a Parser I described how you can start writing a parser without running it against a snapshot, which can save a lot of time.
I ended it with parsing the interface out of a device output blob.
This Article will extend the same NQE, but I will extend the content of the information that we will be parsing for.
As a reminder, here the final NQE from Part 1:
test_string =
"""
GigabitEthernet0/0 is up, line protocol is up (connected)
MTU 1500 bytes, BW 1000000 Kbit, DLY 10 usec,
reliability 255/255, txload 1/255, rxload 1/255
Encapsulation ARPA, loopback not set
Keepalive set (10 sec)
Full-duplex, 1000Mb/s, media type is RJ45
output flow-control is XON, input flow-control is XON
ARP type: ARPA, ARP Timeout 04:00:00
Last input 00:00:00, output 00:00:00, output hang never
Last clearing of "show interface" counters 25w3d
Input queue: 0/75/0/0 (size/max/drops/flushes); Total output drops: 0
Queueing strategy: Class-based queueing
Output queue: 0/1000/64/0 (size/max total/threshold/drops)
Conversations 0/2/256 (active/max active/max total)
Reserved Conversations 4/4 (allocated/max allocated)
Available Bandwidth 0 kilobits/sec
5 minute input rate 4000 bits/sec, 6 packets/sec
5 minute output rate 3000 bits/sec, 4 packets/sec
35659777 packets input, 3682764911 bytes, 0 no buffer
Received 0 broadcasts, 0 runts, 0 giants, 0 throttles
0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored
0 watchdog, 33245532 multicast, 0 pause input
0 input packets with dribble condition detected
19564830 packets output, 2596316333 bytes, 0 underruns
0 output errors, 0 collisions, 0 interface resets
0 babbles, 0 late collision, 0 deferred
0 lost carrier, 0 no carrier, 0 pause output
0 output buffer failures, 0 output buffers swapped out
GigabitEthernet0/1 is up, line protocol is up (connected)
MTU 1501 bytes, BW 1000000 Kbit, DLY 10 usec,
reliability 255/255, txload 1/255, rxload 1/255
Encapsulation ARPA, loopback not set
Keepalive set (10 sec)
Full-duplex, 1000Mb/s, media type is RJ45
output flow-control is XON, input flow-control is XON
ARP type: ARPA, ARP Timeout 04:00:00
Last input 00:00:00, output 00:00:00, output hang never
Last clearing of "show interface" counters 25w3d
Input queue: 0/75/0/0 (size/max/drops/flushes); Total output drops: 0
Queueing strategy: Class-based queueing
Output queue: 0/1000/64/0 (size/max total/threshold/drops)
Conversations 0/2/256 (active/max active/max total)
Reserved Conversations 4/4 (allocated/max allocated)
Available Bandwidth 0 kilobits/sec
5 minute input rate 4000 bits/sec, 6 packets/sec
5 minute output rate 3000 bits/sec, 4 packets/sec
35659777 packets input, 3682764911 bytes, 0 no buffer
Received 0 broadcasts, 0 runts, 0 giants, 0 throttles
0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored
0 watchdog, 33245532 multicast, 0 pause input
0 input packets with dribble condition detected
19564830 packets output, 2596316333 bytes, 0 underruns
0 output errors, 0 collisions, 0 interface resets
0 babbles, 0 late collision, 0 deferred
0 lost carrier, 0 no carrier, 0 pause output
0 output buffer failures, 0 output buffers swapped out
""";
interface_parser =
```
{int:string} is
```;
foreach x in [1]
let lines = parseConfigBlocks(OS.UNKNOWN, test_string)
foreach line in blockMatches(lines, interface_parser)
select {
Interface: line.data.int
}
It parses the test_string variable and extracts the interface name.
Now we want to extract the MTU length for each interface.
The output of "show interfaces" provides following information:
GigabitEthernet0/0 is up, line protocol is up (connected)
MTU 1500 bytes, BW 1000000 Kbit, DLY 10 usec,
look at the second line. Do you see the indentation?
NQE recognizes this indentation as a parent-child object.
To parse for the interface and the MTU speed, we can use this parser:
interface_parser =
```
{int:string} is
MTU {mtu:number} bytes,
```;
here is the new NQE without the test_string content:
test_string =
"""
<snip content>
""";
interface_parser =
```
{int:string} is
MTU {mtu:number} bytes,
```;
foreach x in 1]
let lines = parseConfigBlocks(OS.UNKNOWN, test_string)
foreach line in blockMatches(lines, interface_parser)
select {
Interface: line.data.int,
MTU: line.data.mtu
}
Great. Last step.
Let's add to the list the CRC errors on each interface.
Look at the “show interfaces” output and identify where the information is in:
GigabitEthernet0/0 is up, line protocol is up (connected)
MTU 1500 bytes, BW 1000000 Kbit, DLY 10 usec,
reliability 255/255, txload 1/255, rxload 1/255
Encapsulation ARPA, loopback not set
Keepalive set (10 sec)
Full-duplex, 1000Mb/s, media type is RJ45
output flow-control is XON, input flow-control is XON
ARP type: ARPA, ARP Timeout 04:00:00
Last input 00:00:00, output 00:00:00, output hang never
Last clearing of "show interface" counters 25w3d
Input queue: 0/75/0/0 (size/max/drops/flushes); Total output drops: 0
Queueing strategy: Class-based queueing
Output queue: 0/1000/64/0 (size/max total/threshold/drops)
Conversations 0/2/256 (active/max active/max total)
Reserved Conversations 4/4 (allocated/max allocated)
Available Bandwidth 0 kilobits/sec
5 minute input rate 4000 bits/sec, 6 packets/sec
5 minute output rate 3000 bits/sec, 4 packets/sec
35659777 packets input, 3682764911 bytes, 0 no buffer
Received 0 broadcasts, 0 runts, 0 giants, 0 throttles
0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored
we see that the CRC information is a child object of the line:
5 minute output rate 3000 bits/sec, 4 packets/sec
To help us with the creation of the pattern, we can delete any line that contains information but is not needed:
GigabitEthernet0/0 is up, line protocol is up (connected)
MTU 1500 bytes, BW 1000000 Kbit, DLY 10 usec,
5 minute output rate 3000 bits/sec, 4 packets/sec
0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored
Now lets create the parser. Lets reuse the code for interface and MTU first:
{int:string} is
MTU {mtu:number} bytes,
5 minute output rate 3000 bits/sec, 4 packets/sec
0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored
Now the line:
5 minute output rate 3000 bits/sec, 4 packets/sec
is required, but has counters that can change. We can mask those counters with {string} and this way ignore them.
{string} minute output rate {string} bits/sec, {string} packets/sec
Next is the line with the CRC counters.
0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored
becomes
{string} input errors, {crc:number} CRC, {string} frame, {string} overrun, {string} ignored
Here the final parser:
interface_parser =
```
{int:string} is
MTU {mtu:number} bytes,
{string} minute output rate {string} bits/sec, {string} packets/sec
{string} input errors, {crc:number} CRC, {string} frame, {string} overrun, {string} ignored
```;
Here the final NQE without test_string content:
test_string =
"""
<snip content>
""";
interface_parser =
```
{int:string} is
MTU {mtu:number} bytes,
{string} minute output rate {string} bits/sec, {string} packets/sec
{string} input errors, {crc:number} CRC, {string} frame, {string} overrun, {string} ignored
```;
foreach x in r1]
let lines = parseConfigBlocks(OS.UNKNOWN, test_string)
foreach line in blockMatches(lines, interface_parser)
select {
Interface: line.data.int,
MTU: line.data.mtu,
CRC: line.data.crc
}
I hope this helps on you journey with NQE.