genieparser icon indicating copy to clipboard operation
genieparser copied to clipboard

IOS-XR Static route parser contains a bug on routes with multiple next hops

Open naveci opened this issue 2 years ago • 12 comments

Hi all,

I just found a bug when trying to test for some different situations and it seems to come from the regex interpretation in src/genie/libs/parser/iosxr/show_static_routing.py

In short, it cannot handle routes that have multiple next hop interfaces. Example router CLI output from show static vrf all topology detail

10.252.252.31/32    None                     1.1.1.1             None                             None                [0/0/5/0/1]       No label  
  Path is configured at Mar 15 16:20:37.770
  Path version: 0, Path status: 0x0

10.255.255.224/32   None                     1.3.2.1             None                             None                [0/2048/10/0/1]   No label  
  Path is installed into RIB at Mar 20 15:40:34.674 
  Path version: 1, Path status: 0x21
  Path has best tag: 0

10.255.255.253/32   Bundle-Ether5.507        None                None                             None                [0/4096/1/0/1]    No label  
  Path is configured at Mar 15 16:20:37.770
  Path version: 0, Path status: 0x0
                    Bundle-Ether5.506        None                None                             None                [0/4096/1/0/1]    No label  
  Path is configured at Mar 15 16:20:37.770
  Path version: 0, Path status: 0x0

10.255.255.240/28   Bundle-Ether5.507        None                None                             None                [0/4096/1/0/1]    No label  
  Path is configured at Mar 15 16:20:37.770
  Path version: 0, Path status: 0x0
                    Bundle-Ether5.506        None                None                             None                [0/4096/1/0/1]    No label  
  Path is configured at Mar 15 16:20:37.770
  Path version: 0, Path status: 0x0

The results are as follows (pyats returned JSON dict at the bottom):

  • The first bogus route isn't installed in RIB and is returned just fine as expected from this output.
  • Bogus route 2 is installed in RIB and successfully returned in the dict
  • Bogus route 3:
    • Nexthop interface 5.507 is returned in the dict just fine
    • Nexthop interface 5.506 returns with a first bug. The route is identified as B and the Next-hop interface is in the dict set to Undle-Ether5.506
  • Bogus route 4:
    • Nexthop interface 5.507 is returned in the dict just fine
    • Nexthop interface 5.506 is nowehere in the returned dict as if pyats doesn't know about it.

Config to replicate:

router static address-family ipv4 unicast 10.252.252.31/32 1.1.1.1 5
router static address-family ipv4 unicast 10.255.255.224/32 1.3.2.1 10 permanent
router static address-family ipv4 unicast 10.255.255.240/28 Bundle-Ether5.506 description Purposefully_misconfgd_route
router static address-family ipv4 unicast 10.255.255.240/28 Bundle-Ether5.507 description Purposefully_misconfgd_route
router static address-family ipv4 unicast 10.255.255.253/32 Bundle-Ether5.506 description Purposefully_misconfgd_route
router static address-family ipv4 unicast 10.255.255.253/32 Bundle-Ether5.507 description Purposefully_misconfgd_route

Version:

You are currently running pyATS version: 23.2
Python: 3.9.6 [64bit]

Checking for outdated packages...

  Package                      Version Latest
  ---------------------------- ------- ------
  genie                        23.2
  genie.libs.clean             23.2
  genie.libs.conf              23.2
  genie.libs.filetransferutils 23.2
  genie.libs.health            23.2
  genie.libs.ops               23.2
  genie.libs.parser            23.2
  genie.libs.robot             23.2
  genie.libs.sdk               23.2
  genie.telemetry              23.2
  genie.trafficgen             23.2
  pyats                        23.2
  pyats.aereport               23.2
  pyats.aetest                 23.2
  pyats.async                  23.2
  pyats.connections            23.2
  pyats.contrib                23.2
  pyats.datastructures         23.2
  pyats.easypy                 23.2
  pyats.kleenex                23.2
  pyats.log                    23.2
  pyats.reporter               23.2
  pyats.results                23.2
  pyats.robot                  23.2
  pyats.tcl                    23.2
  pyats.topology               23.2
  pyats.utils                  23.2
  unicon                       23.2
  unicon.plugins               23.2
  yang.connector               23.2

All your packages are up to date!

Pyats returned dict:

{
    "safi": "unicast",
    "table_id": "0xe0000000",
    "routes": {
        "10.252.252.31/32": {
            "route": "10.252.252.31/32",
            "next_hop": {
                "next_hop_list": {
                    "1": {
                        "index": 1,
                        "next_hop": "1.1.1.1",
                        "metrics": 1,
                        "preference": 5,
                        "local_label": "No label",
                        "active": false,
                        "path_event": "Path is configured at Mar 15 16:20:37.770",
                        "path_version": 0,
                        "path_status": "0x0"
                    }
                }
            }
        },
        "10.255.255.224/32": {
            "route": "10.255.255.224/32",
            "next_hop": {
                "next_hop_list": {
                    "1": {
                        "index": 1,
                        "next_hop": "1.3.2.1",
                        "metrics": 1,
                        "preference": 10,
                        "local_label": "No label",
                        "active": true,
                        "path_event": "Path is installed into RIB at Mar 20 15:40:34.674",
                        "path_version": 1,
                        "path_status": "0x21",
                        "tag": 0
                    }
                }
            }
        },
        "10.255.255.253/32": {
            "route": "10.255.255.253/32",
            "next_hop": {
                "outgoing_interface": {
                    "Bundle-Ether5.507": {
                        "outgoing_interface": "Bundle-Ether5.507",
                        "metrics": 1,
                        "preference": 1,
                        "local_label": "No label",
                        "active": false,
                        "path_event": "Path is configured at Mar 15 16:20:37.770",
                        "path_version": 0,
                        "path_status": "0x0"
                    }
                }
            }
        },
        "B": {
            "route": "B",
            "next_hop": {
                "outgoing_interface": {
                    "Undle-Ether5.506": {
                        "outgoing_interface": "Undle-Ether5.506",
                        "metrics": 1,
                        "preference": 1,
                        "local_label": "No label",
                        "active": false,
                        "path_event": "Path is configured at Mar 15 16:20:37.770",
                        "path_version": 0,
                        "path_status": "0x0"
                    }
                }
            }
        },
        "10.255.255.240/28": {
            "route": "10.255.255.240/28",
            "next_hop": {
                "outgoing_interface": {
                    "Bundle-Ether5.507": {
                        "outgoing_interface": "Bundle-Ether5.507",
                        "metrics": 1,
                        "preference": 1,
                        "local_label": "No label",
                        "active": false,
                        "path_event": "Path is configured at Mar 15 16:20:37.770",
                        "path_version": 0,
                        "path_status": "0x0"
                    }
                }
            }
        },
        "0.0.0.0/0": {
            "route": "0.0.0.0/0",
            "next_hop": {
                "next_hop_list": {
                    "1": {
                        "index": 1,
                        "next_hop": "10.215.132.1",
                        "metrics": 1,
                        "preference": 1,
                        "local_label": "No label",
                        "active": true,
                        "path_event": "Path is installed into RIB at Mar 15 16:23:29.895",
                        "path_version": 1,
                        "path_status": "0x21",
                        "tag": 0
                    }
                }
            }
        }
    }
}

naveci avatar Mar 21 '23 15:03 naveci

Hi , I am looking at your ticket and reviewing it, Please let me know are you facing the issue still or not ?

iamsatyanarayan avatar Apr 07 '23 08:04 iamsatyanarayan

Hi , I am looking at your ticket and reviewing it, Please let me know are you facing the issue still or not ?

iamsatyanarayan avatar Apr 12 '23 08:04 iamsatyanarayan

hi @iamsatyanarayan,

This is still an issue as it seems to be problem in the library with the parsing of the output with regex. The reason is that the CLI outputs multiple exit interfaces under the same route and your regex code doesn't handle the lack of route prefix there.

Thanks

naveci avatar Apr 13 '23 13:04 naveci

Hi naveci, Could you please share with me the regex. pattern. I will check and let you know.

iamsatyanarayan avatar Apr 19 '23 11:04 iamsatyanarayan

Hi @iamsatyanarayan,

I was referring to this file: https://github.com/CiscoTestAutomation/genieparser/blob/master/src/genie/libs/parser/iosxr/show_static_routing.py

Somewhere in that regex is the problem that misinterprets the outgoing interfaces if there are multiple configured for the same prefix.

I've updated to Pyats 23.3 in the meanwhile, but that hasn't fixed it.

naveci avatar Apr 24 '23 10:04 naveci

Hi naveci, I'm finding some discrepancy in the cli and parser output shared above as I'm getting error while trying to execute the parser command. The cli output starts with routes definition but whereas parser output has "safi" and "table_id" which I don't see them in the cli output shared. Could you please share the actual cli output(show static vrf all topology detail) for the issue you are facing. So that we can help you in fixing the issue.

ghost avatar May 04 '23 13:05 ghost

Hi,

Yes, I did trim the output a bit to not share unnecessary output. Here's the output with the headers included.

VRF: default Table Id: 0xe0000000 AFI: IPv4 SAFI: Unicast
  Last path event occured at May  1 22:11:04.487
Prefix/Len          Interface                Nexthop             Object                           Explicit-path       Metrics       Local-Label   
10.248.4.16/32      Bundle-Ether100          None                None                             None                [0/4096/1/0/1]    No label  
  Path is installed into RIB at May  1 22:10:34.079 
  Path version: 1, Path status: 0x21
  Path has best tag: 0

10.248.4.18/32      Bundle-Ether200          None                None                             None                [0/4096/1/0/1]    No label  
  Path is installed into RIB at May  1 22:11:04.487 
  Path version: 1, Path status: 0x21
  Path has best tag: 0

10.252.252.31/32    None                     1.1.1.1             None                             None                [0/0/5/0/1]       No label  
  Path is configured at May  1 22:04:12.804
  Path version: 0, Path status: 0x0

10.255.255.224/32   None                     1.3.2.1             None                             None                [0/2048/10/0/1]   No label  
  Path is installed into RIB at May  1 22:06:22.240 
  Path version: 1, Path status: 0x21
  Path has best tag: 0

10.255.255.253/32   Bundle-Ether5.507        None                None                             None                [0/4096/1/0/1]    No label  
  Path is configured at May  1 22:04:12.804
  Path version: 0, Path status: 0x0
                    Bundle-Ether5.506        None                None                             None                [0/4096/1/0/1]    No label  
  Path is configured at May  1 22:04:12.804
  Path version: 0, Path status: 0x0

10.255.255.240/28   Bundle-Ether5.507        None                None                             None                [0/4096/1/0/1]    No label  
  Path is configured at May  1 22:04:12.804
  Path version: 0, Path status: 0x0
                    Bundle-Ether5.506        None                None                             None                [0/4096/1/0/1]    No label  
  Path is configured at May  1 22:04:12.804
  Path version: 0, Path status: 0x0

naveci avatar May 04 '23 14:05 naveci

Hi naveci, I did some changes in regx. and i am getting expected output now.

p2 = re.compile(r'^(?P([\s]+)?|([a-fA-F\d/.:]+)?) ' r'(?P[a-zA-Z][\w/.-]+) ' r'+(?P[\w/.:]+) +(?P[\w]+) ' r'+(?P<explicit_path>[\w]+) +(?P[\w/[]]+)' r'(\s+(?P<local_label>[\w\s]+?))?' r'(\s+(?P<path_event>(Path|Last).))?$')

Could you please try with the above pattern and let me know. i hope it will work for you.

ghost avatar May 15 '23 05:05 ghost

Hi naveci, I hope you have seen my previous comment. have you tried that regex. pattern in your script ?

iamsatyanarayan avatar May 16 '23 06:05 iamsatyanarayan

Hi naveci, I hope you have seen my previous comment. have you tried that regex. pattern in your script ?

iamsatyanarayan avatar May 16 '23 06:05 iamsatyanarayan

It already breaks on the first line:

RP/0/RSP0/CPU0:test-pe#
Issue with the parser show static vrf all topology detail


Traceback (most recent call last):
  File "src/genie/cli/commands/parser.py", line 339, in genie.cli.commands.parser.ParserCommand.parse
  File "src/genie/conf/base/device.py", line 531, in genie.conf.base.device.Device.parse
  File "src/genie/conf/base/device.py", line 570, in genie.conf.base.device.Device._get_parser_output
  File "src/genie/conf/base/device.py", line 568, in genie.conf.base.device.Device._get_parser_output
  File "src/genie/metaparser/_metaparser.py", line 308, in genie.metaparser._metaparser.MetaParser.parse
  File "/Users/naveci/coding/pyats/.venv/lib/python3.9/site-packages/genie/libs/parser/iosxr/show_static_routing.py", line 146, in cli
    p2 = re.compile(
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/re.py", line 252, in compile
    return _compile(pattern, flags)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/re.py", line 304, in _compile
    p = sre_compile.compile(pattern, flags)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/sre_compile.py", line 764, in compile
    p = sre_parse.parse(p, flags)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/sre_parse.py", line 948, in parse
    p = _parse_sub(source, state, flags & SRE_FLAG_VERBOSE, 0)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/sre_parse.py", line 443, in _parse_sub
    itemsappend(_parse(source, state, verbose, nested + 1,
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/sre_parse.py", line 725, in _parse
    raise source.error("unknown extension ?P" + char,
re.error: unknown extension ?P( at position 2
100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:01<00:00,  1.75s/it]

My code editor colors the top three lines differently from the bottom three. This has to do with the <> following the ?P.

naveci avatar May 16 '23 09:05 naveci

Hi naveci, Issue is fixed and PR merged. The parser will be release in next version.

iamsatyanarayan avatar Jun 20 '23 06:06 iamsatyanarayan