Skip to main content

Best way to start writing a Parser - Part 2

  • 27 August 2024
  • 0 replies
  • 24 views

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. 

Be the first to reply!

Reply