diff --git a/changelog/2023/july.rst b/changelog/2023/july.rst index 3cb1074416..e4a3244baa 100644 --- a/changelog/2023/july.rst +++ b/changelog/2023/july.rst @@ -2,6 +2,14 @@ New -------------------------------------------------------------------------------- + +* asa + * Added ShowBgpSummary + * show bgp summary + * show bgp {address_family} unicat summary + * Added ShowRouteBgp + * show route bgp + * iosxe * Added ShowWirelessMeshApBackhaul * show wireless mesh ap backhaul @@ -224,5 +232,3 @@ * show lisp {lisp_id} instance-id {instance_id} ethernet server subscription * show lisp locator-table {locator_table} instance-id {instance_id} ethernet server subscription * show lisp eid-table vlan {eid_table} ethernet server subscription - - diff --git a/sdk_generator/outputs/github_parser.json b/sdk_generator/outputs/github_parser.json index 9d6c61a31d..ff05745871 100644 --- a/sdk_generator/outputs/github_parser.json +++ b/sdk_generator/outputs/github_parser.json @@ -11469,6 +11469,15 @@ } }, "show bgp summary": { + "asa": { + "class": "ShowBgpSummary", + "doc": " Parser for:\n * 'show bgp summary'\n * 'show bgp {address_family} summary'\n ", + "module_name": "show_bgp", + "package": "genie.libs.parser", + "schema": null, + "uid": "show_bgp_summary", + "url": "https://github.com/CiscoTestAutomation/genieparser/tree/master/src/genie/libs/parser/asa/show_bgp.py#L494" + }, "ios": { "class": "ShowBgpSummary", "doc": "Parser for show bgp summary", @@ -12203,6 +12212,15 @@ } }, "show bgp {address_family} summary": { + "asa": { + "class": "ShowBgpSummary", + "doc": " Parser for:\n * 'show bgp summary'\n * 'show bgp {address_family} summary'\n ", + "module_name": "show_bgp", + "package": "genie.libs.parser", + "schema": null, + "uid": "show_bgp_address_family_summary", + "url": "https://github.com/CiscoTestAutomation/genieparser/tree/master/src/genie/libs/parser/asa/show_bgp.py#L494" + }, "ios": { "class": "ShowBgpSummary", "doc": "Parser for show bgp summary", @@ -53034,6 +53052,17 @@ "url": "https://github.com/CiscoTestAutomation/genieparser/tree/master/src/genie/libs/parser/iosxr/show_routing.py#L1542" } }, + "show route bgp": { + "asa": { + "class": "ShowRouteBgp", + "doc": "Parser for\n * show route bgp\n ", + "module_name": "show_route", + "package": "genie.libs.parser", + "schema": "{\n'vrf': {\n 'default': {\n 'address_family': {\n 'ipv4': {\n Optional (Or) Or ('routes', 'tunneled_routes'): {\n Any (str) *: {\n 'candidate_default': ,\n Optional (str) subnet: ,\n 'route': ,\n Optional (str) active: ,\n Optional (str) date: ,\n Optional (str) route_preference: ,\n Optional (str) metric: ,\n Optional (str) source_protocol: ,\n Optional (str) source_protocol_codes: ,\n Optional (str) next_hop: {\n Optional (str) outgoing_interface_name: {\n Any (str) *: {\n Optional (str) outgoing_interface_name: ,\n },\n },\n Optional (str) next_hop_list: {\n Any (str) *: {\n Optional (str) index: ,\n Optional (str) next_hop: ,\n Optional (str) outgoing_interface_name: ,\n },\n },\n },\n },\n },\n },\n },\n },\n },\n}", + "uid": "show_route_bgp", + "url": "https://github.com/CiscoTestAutomation/genieparser/tree/master/src/genie/libs/parser/asa/show_route.py#L334" + } + }, "show route extensive": { "junos": { "class": "ShowRouteProtocolExtensive", diff --git a/src/genie/libs/parser/asa/show_bgp.py b/src/genie/libs/parser/asa/show_bgp.py new file mode 100755 index 0000000000..9d886bd894 --- /dev/null +++ b/src/genie/libs/parser/asa/show_bgp.py @@ -0,0 +1,523 @@ +''' show_bgp.py + +ASA BGP parsers for the following show commands: + * show bgp summary + * show bgp {address_family} unicast summary +''' +#Python +import re + +# Metaparser +from genie.metaparser import MetaParser +from genie.metaparser.util.schemaengine import Schema, Any, Optional + +# ===================================================== +# Schema for: +# * 'show bgp summary' +# * 'show bgp {address_family} unicast summary' +# ===================================================== +class ShowBgpSummarySchema(MetaParser): + + ''' Schema for + * 'show bgp summary' + * 'show bgp ipv4 unicast summary' + ''' + + +schema = { + "type": "object", + "properties": { + "bgp_id": { "type": "integer" }, + "neighbor": { + "type": "object", + "patternProperties": { + "^.+$": { + "type": "object", + "properties": { + "address_family": { + "type": "object", + "patternProperties": { + "^.+$": { + "type": "object", + "properties": { + "version": { "type": "integer" }, + "as": { "type": "integer" }, + "msg_rcvd": { "type": "integer" }, + "msg_sent": { "type": "integer" }, + "tbl_ver": { "type": "integer" }, + "input_queue": { "type": "integer" }, + "output_queue": { "type": "integer" }, + "up_down": { "type": "string" }, + "state_pfxrcd": { "type": "string" }, + "route_identifier": { "type": "string" }, + "local_as": { "type": "integer" }, + "bgp_table_version": { "type": "integer" }, + "routing_table_version": { "type": "integer" }, + "attribute_entries": { "type": "string" }, + "prefixes": { + "type": "object", + "properties": { + "total_entries": { "type": "integer" }, + "memory_usage": { "type": "integer" } + }, + "required": ["total_entries", "memory_usage"] + }, + "path": { + "type": "object", + "properties": { + "total_entries": { "type": "integer" }, + "memory_usage": { "type": "integer" } + }, + "required": ["total_entries", "memory_usage"] + }, + "total_memory": { "type": "integer" }, + "activity_prefixes": { "type": "string" }, + "activity_paths": { "type": "string" }, + "scan_interval": { "type": "integer" }, + "cache_entries": { + "type": "object", + "patternProperties": { + "^.+$": { + "type": "object", + "properties": { + "total_entries": { "type": "integer" }, + "memory_usage": { "type": "integer" } + }, + "required": ["total_entries", "memory_usage"] + } + } + }, + "filter-list": { + "type": "object", + "patternProperties": { + "^.+$": { + "type": "object", + "properties": { + "total_entries": { "type": "integer" }, + "memory_usage": { "type": "integer" } + }, + "required": ["total_entries", "memory_usage"] + } + } + }, + "entries": { + "type": "object", + "patternProperties": { + "^.+$": { + "type": "object", + "properties": { + "total_entries": { "type": "integer" }, + "memory_usage": { "type": "integer" } + }, + "required": ["total_entries", "memory_usage"] + } + } + } + }, + "required": ["version", "as", "msg_rcvd", "msg_sent", "tbl_ver", "input_queue", "output_queue", "up_down", "state_pfxrcd"] + } + } + } + }, + "required": ["address_family"] + } + } + } + }, + "required": ["bgp_id", "neighbor"] + } + +# ================================================== +# Super Parser for: +# * 'show bgp summary' +# * 'show bgp {address_family} summary' +# ================================================== +class ShowBgpSummarySuperParser(ShowBgpSummarySchema): + + ''' Parser for: + * 'show bgp summary' + * 'show bgp {address_family} summary' + ''' + + def cli(self, address_family='', cmd='', output=None): + + # Init vars + sum_dict = {} + cache_dict = {} + entries_dict = {} + bgp_config_dict = {} + + # For address family: IPv4 Unicast + p1 = re.compile(r'^For address family: +(?P[a-zA-Z0-9\s\-\_]+)$') + + # BGP router identifier 192.168.111.1, local AS number 100 + # BGP router identifier 30.1.107.78, local AS number 304.304 + p2 = re.compile(r'^BGP +router +identifier' + ' +(?P[0-9\.\:]+), +local +AS' + ' +number +(?P[0-9\.]+)$') + + # BGP table version is 28, main routing table version 28 + p3 = re.compile(r'^BGP +table +version +is' + ' +(?P[0-9]+),' + ' +main +routing +table +version' + ' +(?P[0-9]+)$') + + # 27 network entries using 6696 bytes of memory + p4 = re.compile(r'^(?P[0-9]+) +network +entries +using' + ' +(?P[0-9]+) +bytes +of +memory$') + + # 27 path entries using 3672 bytes of memory + p5 = re.compile(r'^(?P[0-9]+) +path +entries +using' + ' +(?P[0-9]+) +bytes +of +memory$') + + # 2 BGP rrinfo entries using 48 bytes of memory + # 201 BGP AS-PATH entries using 4824 bytes of memory + p5_1 = re.compile(r'^(?P([0-9]+)) +BGP' + ' +(?P(\S+)) +entries +using' + ' +(?P[0-9]+) +bytes +of +memory$') + + # 4 BGP extended community entries using 96 bytes of memory + p5_2 = re.compile(r'^(?P[0-9]+) +BGP +extended' + ' +community +entries +using' + ' +(?P[0-9]+) +bytes +of +memory$') + + # 1/1 BGP path/bestpath attribute entries using 280 bytes of memory + p6 = re.compile(r'^(?P(\S+)) +BGP' + ' +(?P(\S+)) +attribute +entries' + ' +using +(?P[0-9]+) +bytes +of +memory$') + + # 0 BGP route-map cache entries using 0 bytes of memory + # 0 BGP filter-list cache entries using 0 bytes of memory + p6_1 = re.compile(r'^(?P([0-9]+)) +BGP' + ' +(?P(\S+)) +cache +entries +using' + ' +(?P[0-9]+) +bytes +of +memory$') + + # BGP using 10648 total bytes of memory + p7 = re.compile(r'^BGP +using +(?P[0-9]+) +total +bytes' + ' +of +memory$') + + # BGP activity 47/20 prefixes, 66/39 paths, scan interval 60 secs + p8 = re.compile(r'^BGP +activity +(?P(\S+))' + ' +prefixes, +(?P(\S+)) +paths, +scan' + ' +interval +(?P[0-9]+) +secs$') + + # Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd + # 192.168.111.1 4 100 0 0 1 0 0 01:07:38 Idle + # 192.168.4.1 4 100 0 0 1 0 0 never Idle + # 192.168.51.1 4 100 0 0 1 0 0 01:07:38 Idle + p9 = re.compile(r'^ *(?P\*)?(?P[a-zA-Z0-9\.\:]+) +(?P[0-9]+)' + ' +(?P[0-9]+(\.\d+)?) +(?P[0-9]+)' + ' +(?P[0-9]+) +(?P[0-9]+)' + ' +(?P[0-9]+) +(?P[0-9]+)' + ' +(?P[a-zA-Z0-9\:]+)' + ' +(?P[a-zA-Z0-9\(\)\s]+)$') + + # Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd + # 2001:DB8:20:4:6::6 + # 4 400 67 73 66 0 0 01:03:11 5 + # *2001::100:1:2:1 + # 4 65001 7 7 198 0 0 00:00:02 1 + p10 = re.compile(r'^(?P\*)?(?P[a-zA-Z0-9\.\:]+)$') + + p11 = re.compile(r'^(?P[0-9]+)' + ' +(?P[0-9]+(\.\d+)?) +(?P[0-9]+)' + ' +(?P[0-9]+) +(?P[0-9]+)' + ' +(?P[0-9]+) +(?P[0-9]+)' + ' +(?P[a-zA-Z0-9\:]+)' + ' +(?P[a-zA-Z0-9\(\)\s]+)$') + + for line in output.splitlines(): + + line = line.strip() + + # For address family: IPv4 Unicast + m = p1.match(line) + if m: + # Save variables for use later + address_family = m.groupdict()['address_family'].lower() + attribute_entries = "" + num_prefix_entries = "" + path_total_entries = "" + total_memory = "" + activity_paths = "" + activity_prefixes = "" + scan_interval = "" + cache_dict = {} + entries_dict = {} + num_community_entries = "" + continue + + # BGP router identifier 192.168.111.1, local AS number 100 + # BGP router identifier 30.1.107.78, local AS number 304.304 + m = p2.match(line) + if m: + route_identifier = m.groupdict()['route_identifier'] + try: + local_as = int(m.groupdict()['local_as']) + except: + local_as = m.groupdict()['local_as'] + + sum_dict['bgp_id'] = local_as + continue + + # BGP table version is 28, main routing table version 28 + m = p3.match(line) + if m: + bgp_table_version = int(m.groupdict()['bgp_table_version']) + routing_table_version = int(m.groupdict()['routing_table_version']) + continue + + # 27 network entries using 6696 bytes of memory + m = p4.match(line) + if m: + num_prefix_entries = int(m.groupdict()['networks']) + num_memory_usage = int(m.groupdict()['bytes']) + continue + + # 27 path entries using 3672 bytes of memory + m = p5.match(line) + if m: + path_total_entries = int(m.groupdict()['path']) + path_memory_usage = int(m.groupdict()['memory_usage']) + continue + + # 2 BGP rrinfo entries using 48 bytes of memory + m = p5_1.match(line) + if m: + num_entries = int(m.groupdict()['num_entries']) + entries_type = str(m.groupdict()['entries_type']) + entries_byte = int(m.groupdict()['entries_byte']) + entries_dict[entries_type] = {} + entries_dict[entries_type]['total_entries'] = num_entries + entries_dict[entries_type]['memory_usage'] = entries_byte + continue + + # 4 BGP extended community entries using 96 bytes of memory + m = p5_2.match(line) + if m: + num_community_entries = int(m.groupdict()['num_community_entries']) + community_memory_usage = int(m.groupdict()['memory_usage']) + continue + + # 1/1 BGP path/bestpath attribute entries using 280 bytes of memory + m = p6.match(line) + if m: + attribute_entries = str(m.groupdict()['attribute_entries']) + attribute_type = str(m.groupdict()['attribute_type']) + attribute_memory_usage = int(m.groupdict()['bytes']) + continue + + # 0 BGP route-map cache entries using 0 bytes of memory + m = p6_1.match(line) + if m: + num_cache_entries = int(m.groupdict()['num_cache_entries']) + cache_type = str(m.groupdict()['cache_type']) + cache_byte = int(m.groupdict()['cache_byte']) + + cache_dict[cache_type] = {} + cache_dict[cache_type]['total_entries'] = num_cache_entries + cache_dict[cache_type]['memory_usage'] = cache_byte + continue + + # BGP using 10648 total bytes of memory + m = p7.match(line) + if m: + total_memory = int(m.groupdict()['total_memory']) + continue + + # BGP activity 47/20 prefixes, 66/39 paths, scan interval 60 secs + m = p8.match(line) + if m: + activity_prefixes = str(m.groupdict()['activity_prefixes']) + activity_paths = str(m.groupdict()['activity_paths']) + scan_interval = str(m.groupdict()['scan_interval']) + continue + + # Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd + # 192.168.111.1 4 100 0 0 1 0 0 01:07:38 Idle + # 192.168.4.1 4 100 0 0 1 0 0 never Idle + # 192.168.51.1 4 100 0 0 1 0 0 01:07:38 Idle + # 30.1.10.1 4 304.304 6953 38119 136088 0 0 00:50:14 2540 + # 30.2.10.1 4 304.304 6347 38120 136088 0 0 00:50:13 2580 + # 30.3.10.1 4 301.301 7722 38113 136088 0 0 00:50:14 4439 + m = p9.match(line) + if m: + # Add neighbor to dictionary + neighbor = str(m.groupdict()['neighbor']) + try: + neighbor_as = int(m.groupdict()['as']) + except: + neighbor_as = m.groupdict()['as'] + nbr_dict = sum_dict.setdefault('neighbor', {}).setdefault(neighbor, {}) + + nbr_af_dict = nbr_dict.setdefault('address_family', {})\ + .setdefault(address_family, {}) + + # Add keys for this address_family + nbr_af_dict['version'] = int(m.groupdict()['version']) + nbr_af_dict['as'] = neighbor_as + nbr_af_dict['msg_rcvd'] = int(m.groupdict()['msg_rcvd']) + nbr_af_dict['msg_sent'] = int(m.groupdict()['msg_sent']) + nbr_af_dict['tbl_ver'] = int(m.groupdict()['tbl_ver']) + nbr_af_dict['input_queue'] = int(m.groupdict()['inq']) + nbr_af_dict['output_queue'] = int(m.groupdict()['outq']) + nbr_af_dict['up_down'] = str(m.groupdict()['up_down']) + nbr_af_dict['state_pfxrcd'] = str(m.groupdict()['state']) + nbr_af_dict['route_identifier'] = route_identifier + nbr_af_dict['local_as'] = local_as + nbr_af_dict['bgp_table_version'] = bgp_table_version + nbr_af_dict['routing_table_version'] = routing_table_version + + try: + # Assign variables + if attribute_entries: + nbr_af_dict['attribute_entries'] = attribute_entries + if num_prefix_entries: + nbr_af_dict['prefixes'] = {} + nbr_af_dict['prefixes']['total_entries'] = num_prefix_entries + nbr_af_dict['prefixes']['memory_usage'] = num_memory_usage + + if path_total_entries: + nbr_af_dict['path'] = {} + nbr_af_dict['path']['total_entries'] = path_total_entries + nbr_af_dict['path']['memory_usage'] = path_memory_usage + + if total_memory: + nbr_af_dict['total_memory'] = total_memory + + if activity_prefixes: + nbr_af_dict['activity_prefixes'] = activity_prefixes + + if activity_paths: + nbr_af_dict['activity_paths'] = activity_paths + + if scan_interval: + nbr_af_dict['scan_interval'] = int(scan_interval) + + if len(cache_dict): + nbr_af_dict['cache_entries'] = cache_dict + + if len(entries_dict): + nbr_af_dict['entries'] = entries_dict + + if num_community_entries: + nbr_af_dict['community_entries'] = {} + nbr_af_dict['community_entries']['total_entries'] = num_community_entries + nbr_af_dict['community_entries']['memory_usage'] = community_memory_usage + except Exception: + pass + else: + # when neighbor info break down to 2 lines. + # Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd + # 2001:DB8:20:4:6::6 + # 4 400 67 73 66 0 0 01:03:11 5 + m = p10.match(line) + if m : + # Add neighbor to dictionary + neighbor = str(m.groupdict()['neighbor']) + + # Add address family to this neighbor + if 'address_family' not in nbr_dict: + nbr_dict['address_family'] = {} + if address_family not in nbr_dict['address_family']: + nbr_dict['address_family'][address_family] = {} + nbr_af_dict = nbr_dict['address_family'][address_family] + + m = p11.match(line) + if m: + # Add keys for this address_family + nbr_af_dict['version'] = int(m.groupdict()['version']) + try: + nbr_af_dict['as'] = int(m.groupdict()['as']) + except: + nbr_af_dict['as'] = m.groupdict()['as'] + nbr_af_dict['msg_rcvd'] = int(m.groupdict()['msg_rcvd']) + nbr_af_dict['msg_sent'] = int(m.groupdict()['msg_sent']) + nbr_af_dict['tbl_ver'] = int(m.groupdict()['tbl_ver']) + nbr_af_dict['input_queue'] = int(m.groupdict()['inq']) + nbr_af_dict['output_queue'] = int(m.groupdict()['outq']) + nbr_af_dict['up_down'] = str(m.groupdict()['up_down']) + nbr_af_dict['state_pfxrcd'] = str(m.groupdict()['state']) + nbr_af_dict['route_identifier'] = route_identifier + nbr_af_dict['local_as'] = local_as + nbr_af_dict['bgp_table_version'] = bgp_table_version + nbr_af_dict['routing_table_version'] = routing_table_version + + try: + # Assign variables + if attribute_entries: + nbr_af_dict['attribute_entries'] = attribute_entries + if num_prefix_entries: + nbr_af_dict['prefixes'] = {} + nbr_af_dict['prefixes']['total_entries'] = num_prefix_entries + nbr_af_dict['prefixes']['memory_usage'] = num_memory_usage + + if path_total_entries: + nbr_af_dict['path'] = {} + nbr_af_dict['path']['total_entries'] = path_total_entries + nbr_af_dict['path']['memory_usage'] = path_memory_usage + + if total_memory: + nbr_af_dict['total_memory'] = total_memory + + if activity_prefixes: + nbr_af_dict['activity_prefixes'] = activity_prefixes + + if activity_paths: + nbr_af_dict['activity_paths'] = activity_paths + + if scan_interval: + nbr_af_dict['scan_interval'] = int(scan_interval) + + if len(cache_dict): + nbr_af_dict['cache_entries'] = cache_dict + + if len(entries_dict): + nbr_af_dict['entries'] = entries_dict + + if num_community_entries: + nbr_af_dict['community_entries'] = {} + nbr_af_dict['community_entries']['total_entries'] = num_community_entries + nbr_af_dict['community_entries']['memory_usage'] = community_memory_usage + except Exception: + pass + continue + + return sum_dict + + +# ===================================================== +# Parser for: +# * 'show bgp summary' +# * 'show bgp {address_family} unicast summary' +# ===================================================== +class ShowBgpSummary(ShowBgpSummarySuperParser, ShowBgpSummarySchema): + + ''' Parser for: + * 'show bgp summary' + * 'show bgp {address_family} summary' + ''' + + cli_command = ['show bgp {address_family} summary', + 'show bgp summary' + ] + exclude = ['msg_rcvd', 'msg_sent'] + + def cli(self, address_family='', output=None): + + cmd = '' + if output is None: + # Build command + if address_family: + cmd = self.cli_command[0].format(address_family=address_family) + + else: + cmd = self.cli_command[1] + # Execute command + show_output = self.device.execute(cmd) + else: + show_output = output + + # Call super + return super().cli(output=show_output, + address_family=address_family, cmd=cmd) diff --git a/src/genie/libs/parser/asa/show_route.py b/src/genie/libs/parser/asa/show_route.py index bbdb9778c6..6d35db01df 100644 --- a/src/genie/libs/parser/asa/show_route.py +++ b/src/genie/libs/parser/asa/show_route.py @@ -326,3 +326,156 @@ def cli(self, output=None): index += 1 return ret_dict + + +# ============================================= +# Parser for 'show route bgp' +# ============================================= +class ShowRouteBgp(ShowRouteSchema): + """Parser for + * show route bgp + """ + + cli_command = 'show route bgp' + + def cli(self, output=None): + if output is None: + out = self.device.execute(self.cli_command) + else: + out = output + + ret_dict = {} + # strip this patter from the original text + # Codes: L - Local, C - connected, S - static, I - IGRP, R - RIP, M - mobile, B - BGP + # D - EIGRP, E - EGP, EX - EIGRP external, O - OSPF, I - IGRP, IA - OSPF inter area + # N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2 + # E1 - OSPF external type 1, E2 - OSPF external type 2, E - EGP + # i - IS-IS, L1 - IS-IS level-1, L2 - IS-IS level-2, ia - IS-IS inter area + # * - candidate default, su - IS-IS summary, U - per-user static route, o - ODR + # P - periodic downloaded static route, + - replicated route + # SI - Static InterVRF + p1 = re.sub(r'(?ms)(Codes:.+?)replicated\sroute(\s*SI\s-\sStatic\sInterVRF)?', '', out) + + lines = [x.strip() for x in p1.splitlines()] + entries = dict() + last_entry = str() + clean_lines = list() + + for line in lines: + if re.match(r'(^[A-Z]{1,2})', line): + entries[line] = list() + last_entry = line + else: + if last_entry == '': + continue + + entries[last_entry].append(line) + + for k, v in entries.items(): + clean_lines.append(' '.join(k.split()) + " " + " ".join(v)) + + # clean_lines now holds a list of entries in a single line (easier for parsing) + # Gateway of last resort is X.Y.Z.44 to network 0.0.0.0 + # B X.Y.Z.137 255.255.255.255 [20/0] via X.Y.Z.15, 1w0d + # B X.Y.Z.138 255.255.255.255 [20/0] via X.Y.Z.15, 1w0d + # B X.Y.Z.140 255.255.255.255 [20/0] via X.Y.Z.45, 1w0d + # B X.Y.Z.141 255.255.255.255 [20/0] via X.Y.Z.45, 1w0d + # B X.Y.Z.160 255.255.255.255 [20/5] via X.Y.Z.21, 1w0d + # B X.Y.Z.161 255.255.255.255 [20/5] via X.Y.Z.21, 1w0d + # B X.Y.Z.164 255.255.255.255 [20/5] via X.Y.Z.21, 1w0d + # B X.Y.Z.165 255.255.255.255 [20/5] via X.Y.Z.21, 1w0d + # B X.Y.Z.166 255.255.255.255 [20/0] via X.Y.Z.33, 2d17h + # B X.Y.Z.252 255.255.255.255 [20/0] via X.Y.Z.17, 1w0d + # B X.Y.Z.253 255.255.255.255 [20/0] via X.Y.Z.17, 1w0d + + # [110/11] via 10.20.192.3, 1w1d, wan3 [110/11] via 10.20.192.4, 1w1d, wan4 + + # B X.Y.Z.253 255.255.255.255 [20/0] via X.Y.X.17, 1w0d + p2 = re.compile(r'(?P\S+)\s(?P\S+)\s(?P\S+)\s\[(?P[\d\/]+)\]') + # [20/0] via 172.25.141.2, 7w0d + p3 = re.compile(r'\[(?P[\d\/]+)\]\svia\s+(?P\S+),\s(?P\S+)') + + + + if not clean_lines: + return + + dict_ipv4 = ret_dict.setdefault('vrf', {}).setdefault('default', {}). \ + setdefault('address_family', {}).setdefault('ipv4', {}) + dict_routes = dict_ipv4.setdefault('routes', {}) + + for line in clean_lines: + index = 1 + groups = dict() + next_hops = list() + + target_dict = dict_routes + + if line.startswith('B'): + """ BGP """ + + m = p2.match(line) + if m: + groups = m.groupdict() + + groups['code'] = line[0] + groups['network'], groups['subnet'] = line.split()[1], line.split()[2] + next_hops = [m.groupdict() for m in p3.finditer(line)] + + else: + continue + + prefix_length = str(IPAddress(groups['subnet']).netmask_bits()) + combined_ip = groups['network'] + '/' + prefix_length + dict_route = target_dict.setdefault(combined_ip, {}) + + if '*' in groups['code']: + dict_route.update({'candidate_default': True}) + groups['code'] = groups['code'].strip('*') + else: + dict_route.update({'candidate_default': False}) + + dict_route.update({'active': True}) + + if 'date' not in groups.keys() and next_hops: + date = next_hops[0].get('date') + else: + date = groups.get('date') + if date: + dict_route.update({'date': date}) + + dict_route.update({'route': combined_ip}) + + dict_route.update({'source_protocol_codes': groups['code']}) + dict_route.update({'source_protocol': self.source_protocol_dict[groups['code']].lower()}) + + if 'route_preference' not in groups.keys() and next_hops: + route_preference = next_hops[0]['route_preference'] + + else: + route_preference = groups.get('route_preference') + + if route_preference: + if '/' in route_preference: + route_preference, metric = map(int, route_preference.split('/')) + dict_route.update({'metric': metric}) + else: + route_preference = int(route_preference) + dict_route.update({'route_preference': route_preference}) + + if not next_hops and groups.get('context_name'): + dict_next_hop = dict_route.setdefault('next_hop', {}) + dict_next_hop.update({'outgoing_interface_name': { + groups['context_name']: {'outgoing_interface_name': groups['context_name']} + }}) + + for nh in next_hops: + dict_next_hop = dict_route.setdefault('next_hop', {}).setdefault('next_hop_list', {}).setdefault(index, + {}) + dict_next_hop.update({'index': index}) + dict_next_hop.update({'next_hop': nh.get('next_hop')}) + if nh.get('context_name'): + dict_next_hop.update({'outgoing_interface_name': nh.get('context_name')}) + index += 1 + + return ret_dict diff --git a/src/genie/libs/parser/ios/show_bgp.py b/src/genie/libs/parser/ios/show_bgp.py index 6e513542fd..d4d847f4cd 100755 --- a/src/genie/libs/parser/ios/show_bgp.py +++ b/src/genie/libs/parser/ios/show_bgp.py @@ -23,7 +23,7 @@ * show ip bgp regexp ''' -import re +import re from genie.metaparser import MetaParser from genie.metaparser.util.schemaengine import Schema, Any, Optional @@ -129,4 +129,4 @@ class ShowBgpSummary(ShowBgpSummary_iosxe): class ShowIpBgpRegexp(ShowIpBgpRegexp_iosxe): """Parser for show ip bgp regexp """ - pass \ No newline at end of file + pass