diff --git a/show/bgp_frr_v4.py b/show/bgp_frr_v4.py index 5b630d8981..4a3e065200 100644 --- a/show/bgp_frr_v4.py +++ b/show/bgp_frr_v4.py @@ -1,11 +1,12 @@ import click + +from sonic_py_common import multi_asic +from show.main import ip import utilities_common.bgp_util as bgp_util import utilities_common.cli as clicommon import utilities_common.constants as constants import utilities_common.multi_asic as multi_asic_util -from show.main import ip, run_command - ############################################################################### # # 'show ip bgp' cli stanza @@ -13,7 +14,6 @@ ############################################################################### - @ip.group(cls=clicommon.AliasedGroup) def bgp(): """Show IPv4 BGP (Border Gateway Protocol) information""" @@ -24,43 +24,93 @@ def bgp(): @bgp.command() @multi_asic_util.multi_asic_click_options def summary(namespace, display): - bgp_summary = bgp_util.get_bgp_summary_from_all_bgp_instances(constants.IPV4, namespace,display) + bgp_summary = bgp_util.get_bgp_summary_from_all_bgp_instances( + constants.IPV4, namespace, display) bgp_util.display_bgp_summary(bgp_summary=bgp_summary, af=constants.IPV4) - + # 'neighbors' subcommand ("show ip bgp neighbors") @bgp.command() @click.argument('ipaddress', required=False) -@click.argument('info_type', type=click.Choice(['routes', 'advertised-routes', 'received-routes']), required=False) -def neighbors(ipaddress, info_type): +@click.argument('info_type', + type=click.Choice( + ['routes', 'advertised-routes', 'received-routes']), + required=False) +@click.option('--namespace', + '-n', + 'namespace', + default=None, + type=str, + show_default=True, + help='Namespace name or all', + callback=multi_asic_util.multi_asic_namespace_validation_callback) +def neighbors(ipaddress, info_type, namespace): """Show IP (IPv4) BGP neighbors""" - command = 'sudo vtysh -c "show ip bgp neighbor' - + command = 'show ip bgp neighbor' if ipaddress is not None: - command += ' {}'.format(ipaddress) + if not bgp_util.is_ipv4_address(ipaddress): + ctx = click.get_current_context() + ctx.fail("{} is not valid ipv4 address\n".format(ipaddress)) + try: + actual_namespace = bgp_util.get_namespace_for_bgp_neighbor( + ipaddress) + if namespace is not None and namespace != actual_namespace: + click.echo( + "[WARNING]: bgp neighbor {} is present in namespace {} not in {}" + .format(ipaddress, actual_namespace, namespace)) - # info_type is only valid if ipaddress is specified - if info_type is not None: - command += ' {}'.format(info_type) + # save the namespace in which the bgp neighbor is configured + namespace = actual_namespace + + command += ' {}'.format(ipaddress) - command += '"' + # info_type is only valid if ipaddress is specified + if info_type is not None: + command += ' {}'.format(info_type) + except ValueError as err: + ctx = click.get_current_context() + ctx.fail("{}\n".format(err)) + + ns_list = multi_asic.get_namespace_list(namespace) + output = "" + for ns in ns_list: + output += bgp_util.run_bgp_command(command, ns) + + click.echo(output.rstrip('\n')) - run_command(command) # 'network' subcommand ("show ip bgp network") @bgp.command() -@click.argument('ipaddress', metavar='[|]', required=False) -@click.argument('info_type', metavar='[bestpath|json|longer-prefixes|multipath]', - type=click.Choice(['bestpath', 'json', 'longer-prefixes', 'multipath']), required=False) -def network(ipaddress, info_type): +@click.argument('ipaddress', + metavar='[|]', + required=False) +@click.argument('info_type', + metavar='[bestpath|json|longer-prefixes|multipath]', + type=click.Choice( + ['bestpath', 'json', 'longer-prefixes', 'multipath']), + required=False) +@click.option('--namespace', + '-n', + 'namespace', + type=str, + show_default=True, + required=True if multi_asic.is_multi_asic is True else False, + help='Namespace name or all', + default=None, + callback=multi_asic_util.multi_asic_namespace_validation_callback) +def network(ipaddress, info_type, namespace): """Show IP (IPv4) BGP network""" - command = 'sudo vtysh -c "show ip bgp' + if multi_asic.is_multi_asic() and namespace not in multi_asic.get_namespace_list(): + ctx = click.get_current_context() + ctx.fail('-n/--namespace option required. provide namespace from list {}'\ + .format(multi_asic.get_namespace_list())) + command = 'show ip bgp' if ipaddress is not None: if '/' in ipaddress: - # For network prefixes then this all info_type(s) are available + # For network prefixes then this all info_type(s) are available pass else: # For an ipaddress then check info_type, exit if specified option doesn't work. @@ -75,6 +125,5 @@ def network(ipaddress, info_type): if info_type is not None: command += ' {}'.format(info_type) - command += '"' - - run_command(command) + output = bgp_util.run_bgp_command(command, namespace) + click.echo(output.rstrip('\n')) diff --git a/show/bgp_frr_v6.py b/show/bgp_frr_v6.py index 39be295b18..eb1a5b641b 100644 --- a/show/bgp_frr_v6.py +++ b/show/bgp_frr_v6.py @@ -1,7 +1,8 @@ import click +from sonic_py_common import multi_asic import utilities_common.cli as clicommon -from show.main import ipv6, run_command +from show.main import ipv6 import utilities_common.multi_asic as multi_asic_util import utilities_common.bgp_util as bgp_util import utilities_common.constants as constants @@ -31,27 +32,85 @@ def summary(namespace, display): # 'neighbors' subcommand ("show ipv6 bgp neighbors") @bgp.command() @click.argument('ipaddress', required=False) -@click.argument('info_type', type=click.Choice(['routes', 'advertised-routes', 'received-routes']), required=False) -def neighbors(ipaddress, info_type): +@click.argument('info_type', + type=click.Choice( + ['routes', 'advertised-routes', 'received-routes']), + required=False) +@click.option('--namespace', + '-n', + 'namespace', + default=None, + type=str, + show_default=True, + help='Namespace name or all', + callback=multi_asic_util.multi_asic_namespace_validation_callback) +def neighbors(ipaddress, info_type, namespace): """Show IPv6 BGP neighbors""" - ipaddress = "" if ipaddress is None else ipaddress + + if ipaddress is not None: + if not bgp_util.is_ipv6_address(ipaddress): + ctx = click.get_current_context() + ctx.fail("{} is not valid ipv6 address\n".format(ipaddress)) + try: + actual_namespace = bgp_util.get_namespace_for_bgp_neighbor( + ipaddress) + if namespace is not None and namespace != actual_namespace: + click.echo( + "bgp neighbor {} is present in namespace {} not in {}" + .format(ipaddress, actual_namespace, namespace)) + + # save the namespace in which the bgp neighbor is configured + namespace = actual_namespace + except ValueError as err: + ctx = click.get_current_context() + ctx.fail("{}\n".format(err)) + else: + ipaddress = "" + info_type = "" if info_type is None else info_type - command = 'sudo vtysh -c "show bgp ipv6 neighbor {} {}"'.format(ipaddress, info_type) - run_command(command) + command = 'show bgp ipv6 neighbor {} {}'.format( + ipaddress, info_type) + + ns_list = multi_asic.get_namespace_list(namespace) + output = "" + for ns in ns_list: + output += bgp_util.run_bgp_command(command, ns) + + click.echo(output.rstrip('\n')) + # 'network' subcommand ("show ipv6 bgp network") @bgp.command() -@click.argument('ipaddress', metavar='[|]', required=False) -@click.argument('info_type', metavar='[bestpath|json|longer-prefixes|multipath]', - type=click.Choice(['bestpath', 'json', 'longer-prefixes', 'multipath']), required=False) -def network(ipaddress, info_type): +@click.argument('ipaddress', + metavar='[|]', + required=False) +@click.argument('info_type', + metavar='[bestpath|json|longer-prefixes|multipath]', + type=click.Choice( + ['bestpath', 'json', 'longer-prefixes', 'multipath']), + required=False) +@click.option('--namespace', + '-n', + 'namespace', + type=str, + show_default=True, + required=True if multi_asic.is_multi_asic is True else False, + help='Namespace name or all', + default=None, + callback=multi_asic_util.multi_asic_namespace_validation_callback) +def network(ipaddress, info_type, namespace): """Show BGP ipv6 network""" - command = 'sudo vtysh -c "show bgp ipv6' + command = 'show bgp ipv6' + + if multi_asic.is_multi_asic() and namespace not in multi_asic.get_namespace_list(): + ctx = click.get_current_context() + ctx.fail('-n/--namespace option required. provide namespace from list {}'\ + .format(multi_asic.get_namespace_list())) if ipaddress is not None: if '/' in ipaddress: - # For network prefixes then this all info_type(s) are available + # For network prefixes then this all info_type(s) are available pass else: # For an ipaddress then check info_type, exit if specified option doesn't work. @@ -66,6 +125,5 @@ def network(ipaddress, info_type): if info_type is not None: command += ' {}'.format(info_type) - command += '"' - - run_command(command) + output = bgp_util.run_bgp_command(command, namespace) + click.echo(output.rstrip('\n')) diff --git a/tests/bgp_commands_input/__init__.py b/tests/bgp_commands_input/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/bgp_commands_input/bgp_neighbor_test_vector.py b/tests/bgp_commands_input/bgp_neighbor_test_vector.py new file mode 100644 index 0000000000..a5766c2a5c --- /dev/null +++ b/tests/bgp_commands_input/bgp_neighbor_test_vector.py @@ -0,0 +1,755 @@ +bgp_v4_neighbors_output = \ +""" +BGP neighbor is 10.0.0.57, remote AS 64600, local AS 65100, external link + Description: ARISTA01T1 + Member of peer-group PEER_V4 for session parameters + BGP version 4, remote router ID 100.1.0.29, local router ID 10.1.0.32 + BGP state = Established, up for 00:00:39 + Last read 00:00:00, Last write 00:00:00 + Hold time is 10, keepalive interval is 3 seconds + Configured hold time is 10, keepalive interval is 3 seconds + Neighbor capabilities: + 4 Byte AS: advertised and received + AddPath: + IPv4 Unicast: RX advertised IPv4 Unicast and received + Route refresh: advertised and received(new) + Address Family IPv4 Unicast: advertised and received + Hostname Capability: advertised (name: vlab-01,domain name: n/a) not received + Graceful Restart Capability: advertised and received + Remote Restart timer is 300 seconds + Address families by peer: + none + Graceful restart information: + End-of-RIB send: IPv4 Unicast + End-of-RIB received: IPv4 Unicast + Local GR Mode: Restart* + Remote GR Mode: Helper + R bit: False + Timers: + Configured Restart Time(sec): 240 + Received Restart Time(sec): 300 + IPv4 Unicast: + F bit: False + End-of-RIB sent: Yes + End-of-RIB sent after update: No + End-of-RIB received: Yes + Timers: + Configured Stale Path Time(sec): 360 + Configured Selection Deferral Time(sec): 360 + Message statistics: + Inq depth is 0 + Outq depth is 0 + Sent Rcvd + Opens: 2 1 + Notifications: 2 2 + Updates: 3203 3202 + Keepalives: 14 15 + Route Refresh: 0 0 + Capability: 0 0 + Total: 3221 3220 + Minimum time between advertisement runs is 0 seconds + + For address family: IPv4 Unicast + PEER_V4 peer-group member + Update group 1, subgroup 1 + Packet Queue length 0 + Inbound soft reconfiguration allowed + Community attribute sent to this neighbor(all) + Inbound path policy configured + Outbound path policy configured + Route map for incoming advertisements is *FROM_BGP_PEER_V4 + Route map for outgoing advertisements is *TO_BGP_PEER_V4 + 6400 accepted prefixes + + Connections established 1; dropped 0 + Last reset 00:01:01, No AFI/SAFI activated for peer +Local host: 10.0.0.56, Local port: 179 +Foreign host: 10.0.0.57, Foreign port: 44731 +Nexthop: 10.0.0.56 +Nexthop global: fc00::71 +Nexthop local: fe80::5054:ff:fea9:41c2 +BGP connection: shared network +BGP Connect Retry Timer in Seconds: 10 +Estimated round trip time: 20 ms +Read thread: on Write thread: on FD used: 28 +""" + +bgp_v4_neighbor_invalid = \ +"""Error: Bgp neighbor 20.1.1.1 not configured""" + +bgp_v4_neighbor_invalid_address = \ +"""Error: invalid_address is not valid ipv4 address""" + +bgp_v4_neighbor_output_adv_routes = \ +""" +BGP table version is 6405, local router ID is 10.1.0.32, vrf id 0 +Default local pref 100, local AS 65100 +Status codes: s suppressed, d damped, h history, * valid, > best, = multipath, + i internal, r RIB-failure, S Stale, R Removed +Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self +Origin codes: i - IGP, e - EGP, ? - incomplete + + Network Next Hop Metric LocPrf Weight Path +*> 0.0.0.0/0 0.0.0.0 0 64600 65534 6666 6667 i +*> 10.1.0.32/32 0.0.0.0 0 32768 i +*> 100.1.0.29/32 0.0.0.0 0 64600 i +*> 100.1.0.30/32 0.0.0.0 0 64600 i +*> 100.1.0.31/32 0.0.0.0 0 64600 i +*> 100.1.0.32/32 0.0.0.0 0 64600 i +*> 192.168.0.0/21 0.0.0.0 0 32768 i +*> 192.168.8.0/25 0.0.0.0 0 64600 65501 i +*> 192.168.8.128/25 0.0.0.0 0 64600 65501 i +*> 192.168.16.0/25 0.0.0.0 0 64600 65502 i +*> 192.168.16.128/25 + 0.0.0.0 0 64600 65502 i +*> 192.168.24.0/25 0.0.0.0 0 64600 65503 i +*> 192.168.24.128/25 + 0.0.0.0 0 64600 65503 i +*> 192.168.32.0/25 0.0.0.0 0 64600 65504 i +*> 192.168.32.128/25 + 0.0.0.0 0 64600 65504 i +*> 192.168.40.0/25 0.0.0.0 0 64600 65505 i +*> 192.168.40.128/25 + 0.0.0.0 0 64600 65505 i +*> 192.168.48.0/25 0.0.0.0 0 64600 65506 i +*> 192.168.48.128/25 + 0.0.0.0 0 64600 65506 i +*> 192.168.56.0/25 0.0.0.0 0 64600 65507 i +*> 192.168.56.128/25 + 0.0.0.0 0 64600 65507 i +""" + +bgp_v4_neighbor_output_recv_routes = \ +""" +BGP table version is 6405, local router ID is 10.1.0.32, vrf id 0 +Default local pref 100, local AS 65100 +Status codes: s suppressed, d damped, h history, * valid, > best, = multipath, + i internal, r RIB-failure, S Stale, R Removed +Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self +Origin codes: i - IGP, e - EGP, ? - incomplete + + Network Next Hop Metric LocPrf Weight Path +*> 0.0.0.0/0 10.0.0.57 0 64600 65534 6666 6667 i +*> 100.1.0.29/32 10.0.0.57 0 64600 i +*> 192.168.8.0/25 10.0.0.57 0 64600 65501 i +*> 192.168.8.128/25 10.0.0.57 0 64600 65501 i +*> 192.168.16.0/25 10.0.0.57 0 64600 65502 i +*> 192.168.16.128/25 + 10.0.0.57 0 64600 65502 i +*> 192.168.24.0/25 10.0.0.57 0 64600 65503 i +*> 192.168.24.128/25 + 10.0.0.57 0 64600 65503 i +*> 192.168.32.0/25 10.0.0.57 0 64600 65504 i +*> 192.168.32.128/25 + 10.0.0.57 0 64600 65504 i +*> 192.168.40.0/25 10.0.0.57 0 64600 65505 i +*> 192.168.40.128/25 + 10.0.0.57 0 64600 65505 i +*> 192.168.48.0/25 10.0.0.57 0 64600 65506 i +*> 192.168.48.128/25 + 10.0.0.57 0 64600 65506 i +*> 192.168.56.0/25 10.0.0.57 0 64600 65507 i +*> 192.168.56.128/25 + 10.0.0.57 0 64600 65507 i +""" + +bgp_v6_neighbors_output = \ +""" +BGP neighbor is fc00::72, remote AS 64600, local AS 65100, external link + Description: ARISTA01T1 + Member of peer-group PEER_V6 for session parameters + BGP version 4, remote router ID 100.1.0.29, local router ID 10.1.0.32 + BGP state = Established, up for 01:06:23 + Last read 00:00:02, Last write 00:00:00 + Hold time is 10, keepalive interval is 3 seconds + Configured hold time is 10, keepalive interval is 3 seconds + Neighbor capabilities: + 4 Byte AS: advertised and received + AddPath: + IPv6 Unicast: RX advertised IPv6 Unicast and received + Route refresh: advertised and received(new) + Address Family IPv6 Unicast: advertised and received + Hostname Capability: advertised (name: vlab-01,domain name: n/a) not received + Graceful Restart Capability: advertised and received + Remote Restart timer is 300 seconds + Address families by peer: + none + Graceful restart information: + End-of-RIB send: IPv6 Unicast + End-of-RIB received: IPv6 Unicast + Local GR Mode: Restart* + Remote GR Mode: Helper + R bit: False + Timers: + Configured Restart Time(sec): 240 + Received Restart Time(sec): 300 + IPv6 Unicast: + F bit: False + End-of-RIB sent: Yes + End-of-RIB sent after update: No + End-of-RIB received: Yes + Timers: + Configured Stale Path Time(sec): 360 + Configured Selection Deferral Time(sec): 360 + Message statistics: + Inq depth is 0 + Outq depth is 0 + Sent Rcvd + Opens: 1 1 + Notifications: 0 0 + Updates: 3206 3202 + Keepalives: 1328 1329 + Route Refresh: 0 0 + Capability: 0 0 + Total: 4535 4532 + Minimum time between advertisement runs is 0 seconds + + For address family: IPv6 Unicast + PEER_V6 peer-group member + Update group 2, subgroup 2 + Packet Queue length 0 + Inbound soft reconfiguration allowed + Community attribute sent to this neighbor(all) + Inbound path policy configured + Outbound path policy configured + Route map for incoming advertisements is *FROM_BGP_PEER_V6 + Route map for outgoing advertisements is *TO_BGP_PEER_V6 + 6400 accepted prefixes + + Connections established 1; dropped 0 + Last reset 01:06:46, Waiting for peer OPEN +Local host: fc00::71, Local port: 59726 +Foreign host: fc00::72, Foreign port: 179 +Nexthop: 10.0.0.56 +Nexthop global: fc00::71 +Nexthop local: fe80::5054:ff:fea9:41c2 +BGP connection: shared network +BGP Connect Retry Timer in Seconds: 10 +Estimated round trip time: 4 ms +Read thread: on Write thread: on FD used: 30 +""" + +bgp_v6_neighbor_output_adv_routes = \ +""" +BGP table version is 6407, local router ID is 10.1.0.32, vrf id 0 +Default local pref 100, local AS 65100 +Status codes: s suppressed, d damped, h history, * valid, > best, = multipath, + i internal, r RIB-failure, S Stale, R Removed +Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self +Origin codes: i - IGP, e - EGP, ? - incomplete + + Network Next Hop Metric LocPrf Weight Path +*> ::/0 :: 0 64600 65534 6666 6667 i +*> 2064:100::1d/128 :: 0 64600 i +*> 2064:100::1e/128 :: 0 64600 i +*> 2064:100::1f/128 :: 0 64600 i +*> 2064:100::20/128 :: 0 64600 i +*> 20c0:a808::/64 :: 0 64600 65501 i +*> 20c0:a808:0:80::/64 + :: 0 64600 65501 i +*> 20c0:a810::/64 :: 0 64600 65502 i +*> 20c0:a810:0:80::/64 + :: 0 64600 65502 i +*> 20c0:a818::/64 :: 0 64600 65503 i +*> 20c0:a818:0:80::/64 + :: 0 64600 65503 i +*> 20c0:a820::/64 :: 0 64600 65504 i +*> 20c0:a820:0:80::/64 + :: 0 64600 65504 i +*> 20c0:a828::/64 :: 0 64600 65505 i +*> 20c0:a828:0:80::/64 + :: 0 64600 65505 i +*> 20c0:a830::/64 :: 0 64600 65506 i +*> 20c0:a830:0:80::/64 + :: 0 64600 65506 i +*> 20c0:a838::/64 :: 0 64600 65507 i +*> 20c0:a838:0:80::/64 + :: 0 64600 65507 i +*> 20c0:a840::/64 :: 0 64600 65508 i +*> 20c0:a840:0:80::/64 + :: 0 64600 65508 i +*> 20c0:a848::/64 :: 0 64600 65509 i +*> 20c0:a848:0:80::/64 + :: 0 64600 65509 i +*> 20c0:a850::/64 :: 0 64600 65510 i +*> 20c0:a850:0:80::/64 + :: 0 64600 65510 i +*> 20c0:a858::/64 :: 0 64600 65511 i +*> 20c0:a858:0:80::/64 + :: 0 64600 65511 i +*> 20c0:a860::/64 :: 0 64600 65512 i +*> 20c0:a860:0:80::/64 + :: 0 64600 65512 i +*> 20c0:a868::/64 :: 0 64600 65513 i +*> 20c0:a868:0:80::/64 + :: 0 64600 65513 i +""" + +bgp_v6_neighbor_output_recv_routes = \ +""" +BGP table version is 6407, local router ID is 10.1.0.32, vrf id 0 +Default local pref 100, local AS 65100 +Status codes: s suppressed, d damped, h history, * valid, > best, = multipath, + i internal, r RIB-failure, S Stale, R Removed +Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self +Origin codes: i - IGP, e - EGP, ? - incomplete + + Network Next Hop Metric LocPrf Weight Path +*> ::/0 fc00::72 0 64600 65534 6666 6667 i +*> 2064:100::1d/128 fc00::72 0 64600 i +*> 20c0:a808::/64 fc00::72 0 64600 65501 i +*> 20c0:a808:0:80::/64 + fc00::72 0 64600 65501 i +*> 20c0:a810::/64 fc00::72 0 64600 65502 i +*> 20c0:a810:0:80::/64 + fc00::72 0 64600 65502 i +*> 20c0:a818::/64 fc00::72 0 64600 65503 i +*> 20c0:a818:0:80::/64 + fc00::72 0 64600 65503 i +*> 20c0:a820::/64 fc00::72 0 64600 65504 i +*> 20c0:a820:0:80::/64 + fc00::72 0 64600 65504 i +*> 20c0:a828::/64 fc00::72 0 64600 65505 i +*> 20c0:a828:0:80::/64 + fc00::72 0 64600 65505 i +*> 20c0:a830::/64 fc00::72 0 64600 65506 i +*> 20c0:a830:0:80::/64 + fc00::72 0 64600 65506 i +*> 20c0:a838::/64 fc00::72 0 64600 65507 i +*> 20c0:a838:0:80::/64 + fc00::72 0 64600 65507 i +*> 20c0:a840::/64 fc00::72 0 64600 65508 i +*> 20c0:a840:0:80::/64 + fc00::72 0 64600 65508 i +*> 20c0:a848::/64 fc00::72 0 64600 65509 i +*> 20c0:a848:0:80::/64 + fc00::72 0 64600 65509 i +*> 20c0:a850::/64 fc00::72 0 64600 65510 i +*> 20c0:a850:0:80::/64 + fc00::72 0 64600 65510 i +*> 20c0:a858::/64 fc00::72 0 64600 65511 i +*> 20c0:a858:0:80::/64 + fc00::72 0 64600 65511 i +*> 20c0:a860::/64 fc00::72 0 64600 65512 i +*> 20c0:a860:0:80::/64 + fc00::72 0 64600 65512 i +*> 20c0:a868::/64 fc00::72 0 64600 65513 i +*> 20c0:a868:0:80::/64 + fc00::72 0 64600 65513 i +""" + +bgp_v6_neighbor_invalid = \ +"""Error: Bgp neighbor aa00::72 not configured""" + +bgp_v6_neighbor_invalid_address = \ +"""Error: 20.1.1.1 is not valid ipv6 address""" + +bgp_v4_neighbors_output_asic0 = \ +""" +BGP neighbor is 10.0.0.1, remote AS 65200, local AS 65100, external link + Description: ARISTA01T2 + Member of peer-group TIER2_V4 for session parameters + BGP version 4, remote router ID 100.1.0.1, local router ID 10.1.0.32 + BGP state = Established, up for 04:41:19 + Last read 00:00:19, Last write 00:00:19 + Hold time is 180, keepalive interval is 60 seconds + Neighbor capabilities: + 4 Byte AS: advertised and received + AddPath: + IPv4 Unicast: RX advertised IPv4 Unicast and received + Route refresh: advertised and received(new) + Address Family IPv4 Unicast: advertised and received + Hostname Capability: advertised (name: str-n3164-acs-2,domain name: n/a) not received + Graceful Restart Capabilty: advertised and received + Remote Restart timer is 300 seconds + Address families by peer: + IPv4 Unicast(not preserved) + Graceful restart information: + End-of-RIB send: IPv4 Unicast + End-of-RIB received: IPv4 Unicast + Message statistics: + Inq depth is 0 + Outq depth is 0 + Sent Rcvd + Opens: 2 1 + Notifications: 2 0 + Updates: 43 3187 + Keepalives: 282 283 + Route Refresh: 0 0 + Capability: 0 0 + Total: 329 3471 + Minimum time between advertisement runs is 0 seconds + + For address family: IPv4 Unicast + TIER2_V4 peer-group member + Update group 3, subgroup 3 + Packet Queue length 0 + Inbound soft reconfiguration allowed + Community attribute sent to this neighbor(all) + Inbound path policy configured + Outbound path policy configured + Route map for incoming advertisements is *FROM_TIER2_V4 + Route map for outgoing advertisements is *TO_TIER2_V4 + 6370 accepted prefixes + Maximum prefixes allowed 12000 (warning-only) + Threshold for warning message 90% + + Connections established 1; dropped 0 + Last reset 04:41:43, No AFI/SAFI activated for peer +Local host: 10.0.0.0, Local port: 179 +Foreign host: 10.0.0.1, Foreign port: 56376 +Nexthop: 10.0.0.0 +Nexthop global: fc00::1 +Nexthop local: fe80::2be:75ff:fe3a:ef50 +BGP connection: shared network +BGP Connect Retry Timer in Seconds: 120 +Read thread: on Write thread: on FD used: 25 +""" +bgp_v4_neighbors_output_asic1 = \ +""" +BGP neighbor is 10.1.0.1, remote AS 65100, local AS 65100, internal link + Description: ASIC0 +Hostname: sonic + Member of peer-group INTERNAL_PEER_V4 for session parameters + BGP version 4, remote router ID 10.1.0.32, local router ID 8.0.0.4 + BGP state = Established, up for 04:50:18 + Last read 00:00:03, Last write 00:00:03 + Hold time is 10, keepalive interval is 3 seconds + Configured hold time is 10, keepalive interval is 3 seconds + Neighbor capabilities: + 4 Byte AS: advertised and received + AddPath: + IPv4 Unicast: RX advertised IPv4 Unicast and received + Route refresh: advertised and received(old & new) + Address Family IPv4 Unicast: advertised and received + Hostname Capability: advertised (name: str-n3164-acs-2,domain name: n/a) received (name: str-n3164-acs-2,domain name: n/a) + Graceful Restart Capabilty: advertised and received + Remote Restart timer is 240 seconds + Address families by peer: + IPv4 Unicast(preserved) + Graceful restart information: + End-of-RIB send: IPv4 Unicast + End-of-RIB received: IPv4 Unicast + Message statistics: + Inq depth is 0 + Outq depth is 0 + Sent Rcvd + Opens: 1 1 + Notifications: 0 0 + Updates: 6390 3194 + Keepalives: 5806 5806 + Route Refresh: 0 0 + Capability: 0 0 + Total: 12197 9001 + Minimum time between advertisement runs is 0 seconds + + For address family: IPv4 Unicast + INTERNAL_PEER_V4 peer-group member + Update group 2, subgroup 2 + Packet Queue length 0 + Route-Reflector Client + Inbound soft reconfiguration allowed + NEXT_HOP is always this router + Community attribute sent to this neighbor(all) + Inbound path policy configured + Outbound path policy configured + Route map for incoming advertisements is *FROM_BGP_INTERNAL_PEER_V4 + Route map for outgoing advertisements is *TO_BGP_INTERNAL_PEER_V4 + 6377 accepted prefixes + + Connections established 1; dropped 0 + Last reset 04:50:40, Waiting for NHT +Local host: 10.1.0.0, Local port: 52802 +Foreign host: 10.1.0.1, Foreign port: 179 +Nexthop: 10.1.0.0 +Nexthop global: 2603:10e2:400:1::1 +Nexthop local: fe80::42:f0ff:fe7f:104 +BGP connection: shared network +BGP Connect Retry Timer in Seconds: 10 +Read thread: on Write thread: on FD used: 17 +""" +bgp_v4_neighbors_output_all_asics = bgp_v4_neighbors_output_asic0 + bgp_v4_neighbors_output_asic1 + +bgp_v6_neighbor_output_warning =\ +"""bgp neighbor 2603:10e2:400:1::2 is present in namespace asic1 not in asic0""" + +bgp_v6_neighbors_output_asic0 = \ +""" + BGP neighbor is fc00::2, remote AS 65200, local AS 65100, external link + Description: ARISTA01T2 + Member of peer-group TIER2_V6 for session parameters + BGP version 4, remote router ID 100.1.0.1, local router ID 10.1.0.32 + BGP state = Established, up for 13:26:44 + Last read 00:00:45, Last write 00:00:44 + Hold time is 180, keepalive interval is 60 seconds + Neighbor capabilities: + 4 Byte AS: advertised and received + AddPath: + IPv6 Unicast: RX advertised IPv6 Unicast and received + Route refresh: advertised and received(new) + Address Family IPv6 Unicast: advertised and received + Hostname Capability: advertised (name: str-n3164-acs-2,domain name: n/a) not received + Graceful Restart Capabilty: advertised and received + Remote Restart timer is 300 seconds + Address families by peer: + IPv6 Unicast(not preserved) + Graceful restart information: + End-of-RIB send: IPv6 Unicast + End-of-RIB received: IPv6 Unicast + Message statistics: + Inq depth is 0 + Outq depth is 0 + Sent Rcvd + Opens: 2 1 + Notifications: 2 0 + Updates: 5 3187 + Keepalives: 807 808 + Route Refresh: 0 0 + Capability: 0 0 + Total: 816 3996 + Minimum time between advertisement runs is 0 seconds + + For address family: IPv6 Unicast + TIER2_V6 peer-group member + Update group 2, subgroup 2 + Packet Queue length 0 + Inbound soft reconfiguration allowed + Community attribute sent to this neighbor(all) + Inbound path policy configured + Outbound path policy configured + Route map for incoming advertisements is *FROM_TIER2_V6 + Route map for outgoing advertisements is *TO_TIER2_V6 + 6370 accepted prefixes + Maximum prefixes allowed 8000 (warning-only) + Threshold for warning message 90% + + Connections established 1; dropped 0 + Last reset 13:27:08, No AFI/SAFI activated for peer +Local host: fc00::1, Local port: 179 +Foreign host: fc00::2, Foreign port: 57838 +Nexthop: 10.0.0.0 +Nexthop global: fc00::1 +Nexthop local: fe80::2be:75ff:fe3a:ef50 +BGP connection: shared network +BGP Connect Retry Timer in Seconds: 120 +Read thread: on Write thread: on FD used: 26 +""" + +bgp_v6_neighbors_output_asic1 = \ +""" + BGP neighbor is 2603:10e2:400:1::2, remote AS 65100, local AS 65100, internal link + Description: ASIC0 +Hostname: str-n3164-acs-2 + Member of peer-group INTERNAL_PEER_V6 for session parameters + BGP version 4, remote router ID 10.1.0.32, local router ID 8.0.0.4 + BGP state = Established, up for 13:28:48 + Last read 00:00:02, Last write 00:00:02 + Hold time is 10, keepalive interval is 3 seconds + Configured hold time is 10, keepalive interval is 3 seconds + Neighbor capabilities: + 4 Byte AS: advertised and received + AddPath: + IPv6 Unicast: RX advertised IPv6 Unicast and received + Route refresh: advertised and received(old & new) + Address Family IPv6 Unicast: advertised and received + Hostname Capability: advertised (name: str-n3164-acs-2,domain name: n/a) received (name: str-n3164-acs-2,domain name: n/a) + Graceful Restart Capabilty: advertised and received + Remote Restart timer is 240 seconds + Address families by peer: + IPv6 Unicast(preserved) + Graceful restart information: + End-of-RIB send: IPv6 Unicast + End-of-RIB received: IPv6 Unicast + Message statistics: + Inq depth is 0 + Outq depth is 0 + Sent Rcvd + Opens: 1 1 + Notifications: 0 0 + Updates: 6380 4746 + Keepalives: 16176 16176 + Route Refresh: 0 0 + Capability: 0 0 + Total: 22557 20923 + Minimum time between advertisement runs is 0 seconds + + For address family: IPv6 Unicast + INTERNAL_PEER_V6 peer-group member + Update group 1, subgroup 1 + Packet Queue length 0 + Route-Reflector Client + Inbound soft reconfiguration allowed + NEXT_HOP is always this router + Community attribute sent to this neighbor(all) + Inbound path policy configured + Outbound path policy configured + Route map for incoming advertisements is *FROM_BGP_INTERNAL_PEER_V6 + Route map for outgoing advertisements is *TO_BGP_INTERNAL_PEER_V6 + 6380 accepted prefixes + + Connections established 1; dropped 0 + Last reset 13:29:08, No AFI/SAFI activated for peer +Local host: 2603:10e2:400:1::1, Local port: 179 +Foreign host: 2603:10e2:400:1::2, Foreign port: 58984 +Nexthop: 10.1.0.0 +Nexthop global: 2603:10e2:400:1::1 +Nexthop local: fe80::42:f0ff:fe7f:104 +BGP connection: shared network +BGP Connect Retry Timer in Seconds: 10 +Read thread: on Write thread: on FD used: 22 +""" + +bgp_v6_neighbors_output_all_asics = bgp_v6_neighbors_output_asic0 +\ + bgp_v6_neighbors_output_asic1 + + +def mock_show_bgp_neighbor_multi_asic(param, namespace): + if param == 'bgp_v4_neighbors_output_all_asics': + if namespace == 'asic0': + return bgp_v4_neighbors_output_asic0 + if namespace == 'asic1': + return bgp_v4_neighbors_output_asic1 + if param == 'bgp_v6_neighbors_output_all_asics': + if namespace == 'asic0': + return bgp_v6_neighbors_output_asic0 + if namespace == 'asic1': + return bgp_v6_neighbors_output_asic1 + if param == 'bgp_v4_neighbors_output_asic0': + return bgp_v4_neighbors_output_asic0 + if param == 'bgp_v4_neighbors_output_asic1': + return bgp_v4_neighbors_output_asic1 + elif param == 'bgp_v6_neighbors_output_all_asics': + return bgp_v6_neighbors_output_all_asics + if param == 'bgp_v6_neighbors_output_asic0': + return bgp_v6_neighbors_output_asic0 + if param == 'bgp_v6_neighbors_output_asic1': + return bgp_v6_neighbors_output_asic1 + else: + return "" + + +def mock_show_bgp_neighbor_single_asic(request): + if request.param == 'bgp_v4_neighbors_output': + return bgp_v4_neighbors_output + elif request.param == 'bgp_v6_neighbors_output': + return bgp_v6_neighbors_output + elif request.param == 'bgp_v4_neighbor_output_adv_routes': + return bgp_v4_neighbor_output_adv_routes + elif request.param == 'bgp_v4_neighbor_output_recv_routes': + return bgp_v4_neighbor_output_recv_routes + elif request.param == 'bgp_v6_neighbor_output_adv_routes': + return bgp_v6_neighbor_output_adv_routes + elif request.param == 'bgp_v6_neighbor_output_recv_routes': + return bgp_v6_neighbor_output_recv_routes + else: + return "" + + +testData = { + 'bgp_v4_neighbors': { + 'args': [], + 'rc': 0, + 'rc_output': bgp_v4_neighbors_output + }, + 'bgp_v4_neighbor_ip_address': { + 'args': ['10.0.0.57'], + 'rc': 0, + 'rc_output': bgp_v4_neighbors_output + }, + 'bgp_v4_neighbor_invalid': { + 'args': ['20.1.1.1'], + 'rc': 2, + 'rc_err_msg': bgp_v4_neighbor_invalid + }, + 'bgp_v4_neighbor_invalid_address': { + 'args': ['invalid_address'], + 'rc': 2, + 'rc_err_msg': bgp_v4_neighbor_invalid_address + }, + 'bgp_v4_neighbor_adv_routes': { + 'args': ["10.0.0.57", "advertised-routes"], + 'rc': 0, + 'rc_output': bgp_v4_neighbor_output_adv_routes + }, + 'bgp_v4_neighbor_recv_routes': { + 'args': ["10.0.0.57", "received-routes"], + 'rc': 0, + 'rc_output': bgp_v4_neighbor_output_recv_routes + }, + 'bgp_v6_neighbors': { + 'args': [], + 'rc': 0, + 'rc_output': bgp_v6_neighbors_output + }, + 'bgp_v6_neighbor_ip_address': { + 'args': ['fc00::72'], + 'rc': 0, + 'rc_output': bgp_v6_neighbors_output + }, + 'bgp_v6_neighbor_invalid': { + 'args': ['aa00::72'], + 'rc': 2, + 'rc_err_msg': bgp_v6_neighbor_invalid + }, + 'bgp_v6_neighbor_invalid_address': { + 'args': ['20.1.1.1'], + 'rc': 2, + 'rc_err_msg': bgp_v6_neighbor_invalid_address + }, + 'bgp_v6_neighbor_adv_routes': { + 'args': ["fc00::72", "advertised-routes"], + 'rc': 0, + 'rc_output': bgp_v6_neighbor_output_adv_routes + }, + 'bgp_v6_neighbor_recv_routes': { + 'args': ["fc00::72", "received-routes"], + 'rc': 0, + 'rc_output': bgp_v6_neighbor_output_recv_routes + }, + 'bgp_v4_neighbors_multi_asic' : { + 'args': [], + 'rc': 0, + 'rc_output': bgp_v4_neighbors_output_all_asics + }, + 'bgp_v4_neighbors_asic' : { + 'args': ['-nasic1'], + 'rc': 0, + 'rc_output': bgp_v4_neighbors_output_asic1 + }, + 'bgp_v4_neighbors_external' : { + 'args': ['10.0.0.1'], + 'rc': 0, + 'rc_output': bgp_v4_neighbors_output_asic0 + }, + 'bgp_v4_neighbors_internal' : { + 'args': ['10.1.0.1'], + 'rc': 0, + 'rc_output': bgp_v4_neighbors_output_asic1 + }, + 'bgp_v6_neighbors_multi_asic' : { + 'args': [], + 'rc': 0, + 'rc_output': bgp_v6_neighbors_output_all_asics + }, + 'bgp_v6_neighbors_asic' : { + 'args': ['-nasic0'], + 'rc': 0, + 'rc_output': bgp_v6_neighbors_output_asic0 + }, + 'bgp_v6_neighbors_external' : { + 'args': ['fc00::2'], + 'rc': 0, + 'rc_output': bgp_v6_neighbors_output_asic0 + }, + 'bgp_v6_neighbors_internal' : { + 'args': ['2603:10e2:400:1::2'], + 'rc': 0, + 'rc_output': bgp_v6_neighbors_output_asic1 + }, + 'bgp_v6_neighbor_warning' : { + 'args': ['2603:10e2:400:1::2', '-nasic0'], + 'rc': 0, + 'rc_warning_msg': bgp_v6_neighbor_output_warning + }, + +} \ No newline at end of file diff --git a/tests/bgp_commands_input/bgp_network_test_vector.py b/tests/bgp_commands_input/bgp_network_test_vector.py new file mode 100644 index 0000000000..da93e8e8e8 --- /dev/null +++ b/tests/bgp_commands_input/bgp_network_test_vector.py @@ -0,0 +1,522 @@ +bgp_v4_network = \ +""" +BGP table version is 6405, local router ID is 10.1.0.32, vrf id 0 +Default local pref 100, local AS 65100 +Status codes: s suppressed, d damped, h history, * valid, > best, = multipath, + i internal, r RIB-failure, S Stale, R Removed +Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self +Origin codes: i - IGP, e - EGP, ? - incomplete + + Network Next Hop Metric LocPrf Weight Path +*= 0.0.0.0/0 10.0.0.63 0 64600 65534 6666 6667 i +*= 10.0.0.61 0 64600 65534 6666 6667 i +*= 10.0.0.59 0 64600 65534 6666 6667 i +*> 10.0.0.57 0 64600 65534 6666 6667 i +*> 10.1.0.32/32 0.0.0.0 0 32768 i +*> 100.1.0.29/32 10.0.0.57 0 64600 i +*> 100.1.0.30/32 10.0.0.59 0 64600 i +*> 100.1.0.31/32 10.0.0.61 0 64600 i +*> 100.1.0.32/32 10.0.0.63 0 64600 i +*> 192.168.0.0/21 0.0.0.0 0 32768 i +*= 192.168.8.0/25 10.0.0.63 0 64600 65501 i +*= 10.0.0.61 0 64600 65501 i +*= 10.0.0.59 0 64600 65501 i +*> 10.0.0.57 0 64600 65501 i +*= 192.168.8.128/25 10.0.0.63 0 64600 65501 i +*= 10.0.0.61 0 64600 65501 i +*= 10.0.0.59 0 64600 65501 i +*> 10.0.0.57 0 64600 65501 i +*= 192.168.16.0/25 10.0.0.63 0 64600 65502 i +*= 10.0.0.61 0 64600 65502 i +*= 10.0.0.59 0 64600 65502 i +*> 10.0.0.57 0 64600 65502 i +*= 192.168.16.128/25 + 10.0.0.63 0 64600 65502 i +*= 10.0.0.61 0 64600 65502 i +*= 10.0.0.59 0 64600 65502 i +*> 10.0.0.57 0 64600 65502 i +*= 192.168.24.0/25 10.0.0.63 0 64600 65503 i +*= 10.0.0.61 0 64600 65503 i +*= 10.0.0.59 0 64600 65503 i +*> 10.0.0.57 0 64600 65503 i +*= 192.168.24.128/25 + 10.0.0.63 0 64600 65503 i +*= 10.0.0.61 0 64600 65503 i +*= 10.0.0.59 0 64600 65503 i +*> 10.0.0.57 0 64600 65503 i +*= 192.168.32.0/25 10.0.0.63 0 64600 65504 i +*= 10.0.0.61 0 64600 65504 i +*= 10.0.0.59 0 64600 65504 i +*> 10.0.0.57 0 64600 65504 i +""" + +bgp_v4_network_ip_address = \ +""" +BGP routing table entry for 193.11.248.128/25 +Paths: (4 available, best #4, table default) + Advertised to non peer-group peers: + 10.0.0.57 10.0.0.59 10.0.0.61 10.0.0.63 + 64600 65534 64799 65515 + 10.0.0.61 from 10.0.0.61 (100.1.0.31) + Origin IGP, valid, external, multipath + Community: 5060:12345 + Last update: Tue Apr 20 05:54:41 2021 + 64600 65534 64799 65515 + 10.0.0.59 from 10.0.0.59 (100.1.0.30) + Origin IGP, valid, external, multipath + Community: 5060:12345 + Last update: Tue Apr 20 05:54:19 2021 + 64600 65534 64799 65515 + 10.0.0.63 from 10.0.0.63 (100.1.0.32) + Origin IGP, valid, external, multipath + Community: 5060:12345 + Last update: Tue Apr 20 05:54:16 2021 + 64600 65534 64799 65515 + 10.0.0.57 from 10.0.0.57 (100.1.0.29) + Origin IGP, valid, external, multipath, best (Router ID) + Community: 5060:12345 + Last update: Tue Apr 20 05:54:16 2021 +""" + +bgp_v4_network_longer_prefixes_error = \ +"""The parameter option: "longer-prefixes" only available if passing a network prefix +EX: 'show ip bgp network 10.0.0.0/24 longer-prefixes' +Aborted! +""" + +bgp_v4_network_bestpath = \ +""" +BGP routing table entry for 193.11.248.128/25 +Paths: (4 available, best #4, table default) + Advertised to non peer-group peers: + 10.0.0.57 10.0.0.59 10.0.0.61 10.0.0.63 + 64600 65534 64799 65515 + 10.0.0.57 from 10.0.0.57 (100.1.0.29) + Origin IGP, valid, external, multipath, best (Router ID) + Community: 5060:12345 + Last update: Tue Apr 20 05:54:15 2021 +""" + +bgp_v6_network = \ +""" +BGP table version is 6407, local router ID is 10.1.0.32, vrf id 0 +Default local pref 100, local AS 65100 +Status codes: s suppressed, d damped, h history, * valid, > best, = multipath, + i internal, r RIB-failure, S Stale, R Removed +Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self +Origin codes: i - IGP, e - EGP, ? - incomplete + + Network Next Hop Metric LocPrf Weight Path +*= ::/0 fc00::7e 0 64600 65534 6666 6667 i +*= fc00::7a 0 64600 65534 6666 6667 i +*= fc00::76 0 64600 65534 6666 6667 i +*> fc00::72 0 64600 65534 6666 6667 i +*> 2064:100::1d/128 fc00::72 0 64600 i +*> 2064:100::1e/128 fc00::76 0 64600 i +*> 2064:100::1f/128 fc00::7a 0 64600 i +*> 2064:100::20/128 fc00::7e 0 64600 i +*= 20c0:a808::/64 fc00::7e 0 64600 65501 i +*= fc00::7a 0 64600 65501 i +*= fc00::76 0 64600 65501 i +*> fc00::72 0 64600 65501 i +*= 20c0:a808:0:80::/64 + fc00::7e 0 64600 65501 i +*= fc00::7a 0 64600 65501 i +*= fc00::76 0 64600 65501 i +*> fc00::72 0 64600 65501 i +*= 20c0:a810::/64 fc00::7e 0 64600 65502 i +*= fc00::7a 0 64600 65502 i +*= fc00::76 0 64600 65502 i +*> fc00::72 0 64600 65502 i +*= 20c0:a810:0:80::/64 + fc00::7e 0 64600 65502 i +*= fc00::7a 0 64600 65502 i +*= fc00::76 0 64600 65502 i +*> fc00::72 0 64600 65502 i +*= 20c0:a818::/64 fc00::7e 0 64600 65503 i +*= fc00::7a 0 64600 65503 i +*= fc00::76 0 64600 65503 i +*> fc00::72 0 64600 65503 i +*= 20c0:a818:0:80::/64 + fc00::7e 0 64600 65503 i +*= fc00::7a 0 64600 65503 i +*= fc00::76 0 64600 65503 i +*> fc00::72 0 64600 65503 i +*= 20c0:a820::/64 fc00::7e 0 64600 65504 i +*= fc00::7a 0 64600 65504 i +*= fc00::76 0 64600 65504 i +*> fc00::72 0 64600 65504 i +*= 20c0:a820:0:80::/64 + fc00::7e 0 64600 65504 i +*= fc00::7a 0 64600 65504 i +*= fc00::76 0 64600 65504 i +*> fc00::72 0 64600 65504 i +""" + +bgp_v6_network_ip_address = \ +""" +BGP routing table entry for 20c0:a820:0:80::/64 +Paths: (4 available, best #4, table default) + Advertised to non peer-group peers: + fc00::72 fc00::76 fc00::7a fc00::7e + 64600 65504 + fc00::7e from fc00::7e (100.1.0.32) + (fe80::1850:e9ff:fef9:27cb) (prefer-global) + Origin IGP, valid, external, multipath + Community: 5060:12345 + Last update: Tue Apr 20 05:54:17 2021 + 64600 65504 + fc00::7a from fc00::7a (100.1.0.31) + (fe80::1810:25ff:fe01:c153) (prefer-global) + Origin IGP, valid, external, multipath + Community: 5060:12345 + Last update: Tue Apr 20 05:54:17 2021 + 64600 65504 + fc00::76 from fc00::76 (100.1.0.30) + (fe80::80a7:74ff:fee1:d66d) (prefer-global) + Origin IGP, valid, external, multipath + Community: 5060:12345 + Last update: Tue Apr 20 05:54:17 2021 + 64600 65504 + fc00::72 from fc00::72 (100.1.0.29) + (fe80::90ec:bcff:fe4b:1e3e) (prefer-global) + Origin IGP, valid, external, multipath, best (Router ID) + Community: 5060:12345 + Last update: Tue Apr 20 05:54:16 2021 +""" + +bgp_v6_network_longer_prefixes_error = \ +"""The parameter option: "longer-prefixes" only available if passing a network prefix +EX: 'show ipv6 bgp network fc00:1::/64 longer-prefixes' +Aborted! +""" + +bgp_v6_network_longer_prefixes = \ +""" +BGP table version is 6407, local router ID is 10.1.0.32, vrf id 0 +Default local pref 100, local AS 65100 +Status codes: s suppressed, d damped, h history, * valid, > best, = multipath, + i internal, r RIB-failure, S Stale, R Removed +Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self +Origin codes: i - IGP, e - EGP, ? - incomplete + + Network Next Hop Metric LocPrf Weight Path +*= 20c0:a820:0:80::/64 + fc00::7e 0 64600 65504 i +*= fc00::7a 0 64600 65504 i +*= fc00::76 0 64600 65504 i +*> fc00::72 0 64600 65504 i + +Displayed 1 routes and 25602 total paths +""" + +bgp_v6_network_bestpath = \ +""" +BGP routing table entry for 20c0:a820:0:80::/64 +Paths: (4 available, best #4, table default) + Advertised to non peer-group peers: + fc00::72 fc00::76 fc00::7a fc00::7e + 64600 65504 + fc00::72 from fc00::72 (100.1.0.29) + (fe80::90ec:bcff:fe4b:1e3e) (prefer-global) + Origin IGP, valid, external, multipath, best (Router ID) + Community: 5060:12345 + Last update: Tue Apr 20 05:54:15 2021 +""" + +multi_asic_bgp_network_err = \ +"""Error: -n/--namespace option required. provide namespace from list ['asic0', 'asic1']""" + +bgp_v4_network_asic0 = \ +""" +BGP table version is 11256, local router ID is 10.1.0.32, vrf id 0 +Default local pref 100, local AS 65100 +Status codes: s suppressed, d damped, h history, * valid, > best, = multipath, + i internal, r RIB-failure, S Stale, R Removed +Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self +Origin codes: i - IGP, e - EGP, ? - incomplete + + Network Next Hop Metric LocPrf Weight Path +* i0.0.0.0/0 10.1.0.2 100 0 65200 6666 6667 i +* i 10.1.0.0 100 0 65200 6666 6667 i +*= 10.0.0.5 0 65200 6666 6667 i +*> 10.0.0.1 0 65200 6666 6667 i +* i8.0.0.0/32 10.1.0.2 0 100 0 i +* i 10.1.0.0 0 100 0 i +* 0.0.0.0 0 32768 ? +*> 0.0.0.0 0 32768 i +*=i8.0.0.1/32 10.1.0.2 0 100 0 i +*>i 10.1.0.0 0 100 0 i +*=i8.0.0.2/32 10.1.0.2 0 100 0 i +*>i 10.1.0.0 0 100 0 i +*=i8.0.0.3/32 10.1.0.2 0 100 0 i +*>i 10.1.0.0 0 100 0 i +*>i8.0.0.4/32 10.1.0.0 0 100 0 i +*>i8.0.0.5/32 10.1.0.2 0 100 0 i +* i10.0.0.0/31 10.1.0.2 0 100 0 ? +* i 10.1.0.0 0 100 0 ? +*> 0.0.0.0 0 32768 ? +* i10.0.0.4/31 10.1.0.2 0 100 0 ? +* i 10.1.0.0 0 100 0 ? +*> 0.0.0.0 0 32768 ? +*=i10.0.0.8/31 10.1.0.2 0 100 0 ? +*>i 10.1.0.0 0 100 0 ? +*=i10.0.0.12/31 10.1.0.2 0 100 0 ? +*>i 10.1.0.0 0 100 0 ? +*=i10.0.0.32/31 10.1.0.2 0 100 0 ? +*>i 10.1.0.0 0 100 0 ? +*=i10.0.0.34/31 10.1.0.2 0 100 0 ? +*>i 10.1.0.0 0 100 0 ? +*=i10.0.0.36/31 10.1.0.2 0 100 0 ? +*>i 10.1.0.0 0 100 0 ? +*=i10.0.0.38/31 10.1.0.2 0 100 0 ? +*>i 10.1.0.0 0 100 0 ? +*=i10.0.0.40/31 10.1.0.2 0 100 0 ? +*>i 10.1.0.0 0 100 0 ? +*=i10.0.0.42/31 10.1.0.2 0 100 0 ? +*>i 10.1.0.0 0 100 0 ? +*=i10.0.0.44/31 10.1.0.2 0 100 0 ? +*>i 10.1.0.0 0 100 0 ? +""" + +bgp_v4_network_ip_address_asic0 = \ +""" + BGP routing table entry for 10.0.0.44/31 +Paths: (2 available, best #2, table default, not advertised outside local AS) + Not advertised to any peer + Local + 10.1.0.2 from 10.1.0.2 (8.0.0.5) + Origin incomplete, metric 0, localpref 100, valid, internal, multipath + Community: local-AS + Originator: 8.0.0.5, Cluster list: 8.0.0.5 + Last update: Thu Apr 22 02:13:31 2021 + + Local + 10.1.0.0 from 10.1.0.0 (8.0.0.4) + Origin incomplete, metric 0, localpref 100, valid, internal, multipath, best (Router ID) + Community: local-AS + Originator: 8.0.0.4, Cluster list: 8.0.0.4 + Last update: Thu Apr 22 02:13:31 2021 +""" +bgp_v4_network_bestpath_asic0 = \ +""" +BGP routing table entry for 10.0.0.44/31 +Paths: (2 available, best #2, table default, not advertised outside local AS) + Not advertised to any peer + Local + 10.1.0.0 from 10.1.0.0 (8.0.0.4) + Origin incomplete, metric 0, localpref 100, valid, internal, multipath, best (Router ID) + Community: local-AS + Originator: 8.0.0.4, Cluster list: 8.0.0.4 + Last update: Thu Apr 22 02:13:30 2021 +""" + +bgp_v6_network_asic0 = \ +""" +BGP table version is 12849, local router ID is 10.1.0.32, vrf id 0 +Default local pref 100, local AS 65100 +Status codes: s suppressed, d damped, h history, * valid, > best, = multipath, + i internal, r RIB-failure, S Stale, R Removed +Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self +Origin codes: i - IGP, e - EGP, ? - incomplete + + Network Next Hop Metric LocPrf Weight Path +* i::/0 2603:10e2:400:1::1 + 100 0 65200 6666 6667 i +* i 2603:10e2:400:1::5 + 100 0 65200 6666 6667 i +*= fc00::6 0 65200 6666 6667 i +*> fc00::2 0 65200 6666 6667 i +* i2064:100::1/128 2603:10e2:400:1::1 + 100 0 65200 i +* i 2603:10e2:400:1::5 + 100 0 65200 i +*> fc00::2 0 65200 i +* i2064:100::3/128 2603:10e2:400:1::1 + 100 0 65200 i +* i 2603:10e2:400:1::5 + 100 0 65200 i +*> fc00::6 0 65200 i +*=i2064:100::5/128 2603:10e2:400:1::5 + 100 0 65200 i +*>i 2603:10e2:400:1::1 + 100 0 65200 i +*>i2064:100::7/128 2603:10e2:400:1::1 + 100 0 65200 i +*=i 2603:10e2:400:1::5 + 100 0 65200 i +*>i20c0:a800::/64 2603:10e2:400:1::1 + 100 0 64004 i +*=i 2603:10e2:400:1::5 + 100 0 64004 i +*>i20c0:a800:0:80::/64 + 2603:10e2:400:1::1 + 100 0 64004 i +*=i 2603:10e2:400:1::5 + 100 0 64004 i +*>i20c0:a808::/64 2603:10e2:400:1::1 + 100 0 64004 i +*=i 2603:10e2:400:1::5 + 100 0 64004 i +""" + +bgp_v6_network_ip_address_asic0 = \ +""" +BGP routing table entry for 20c0:a808:0:80::/64 +Paths: (2 available, best #1, table default) + Advertised to non peer-group peers: + fc00::2 fc00::6 + 64004 + 2603:10e2:400:1::1 from 2603:10e2:400:1::1 (8.0.0.4) + Origin IGP, localpref 100, valid, internal, multipath, best (Router ID) + Community: 8075:8823 + Originator: 8.0.0.4, Cluster list: 8.0.0.4 + Last update: Thu Apr 22 02:13:31 2021 + + 64004 + 2603:10e2:400:1::5 from 2603:10e2:400:1::5 (8.0.0.5) + Origin IGP, localpref 100, valid, internal, multipath + Community: 8075:8823 + Originator: 8.0.0.5, Cluster list: 8.0.0.5 + Last update: Thu Apr 22 02:13:31 2021 +""" + +bgp_v6_network_ip_address_asic0_bestpath = \ +""" +BGP routing table entry for 20c0:a808:0:80::/64 +Paths: (2 available, best #1, table default) + Advertised to non peer-group peers: + fc00::2 fc00::6 + 64004 + 2603:10e2:400:1::1 from 2603:10e2:400:1::1 (8.0.0.4) + Origin IGP, localpref 100, valid, internal, multipath, best (Router ID) + Community: 8075:8823 + Originator: 8.0.0.4, Cluster list: 8.0.0.4 + Last update: Thu Apr 22 02:13:30 2021 +""" + + +def mock_show_bgp_network_single_asic(request): + param = request.param + if param == 'bgp_v4_network': + return bgp_v4_network + elif param == 'bgp_v4_network_ip_address': + return bgp_v4_network_ip_address + elif param == 'bgp_v4_network_bestpath': + return bgp_v4_network_bestpath + elif param == 'bgp_v6_network': + return bgp_v6_network + elif param == 'bgp_v6_network_ip_address': + return bgp_v6_network_ip_address + elif param == 'bgp_v6_network_longer_prefixes': + return bgp_v6_network_longer_prefixes + elif param == 'bgp_v6_network_bestpath': + return bgp_v6_network_bestpath + else: + return "" + + +def mock_show_bgp_network_multi_asic(param): + if param == "bgp_v4_network_asic0": + return bgp_v4_network_asic0 + elif param == 'bgp_v4_network_ip_address_asic0': + return bgp_v4_network_ip_address_asic0 + elif param == 'bgp_v4_network_bestpath_asic0': + return bgp_v4_network_bestpath_asic0 + if param == "bgp_v6_network_asic0": + return bgp_v4_network_asic0 + elif param == 'bgp_v6_network_ip_address_asic0': + return bgp_v6_network_ip_address_asic0 + elif param == 'bgp_v6_network_bestpath_asic0': + return bgp_v6_network_ip_address_asic0_bestpath + else: + return '' + + +testData = { + 'bgp_v4_network': { + 'args': [], + 'rc': 0, + 'rc_output': bgp_v4_network + }, + 'bgp_v4_network_ip_address': { + 'args': [' 193.11.248.128/25'], + 'rc': 0, + 'rc_output': bgp_v4_network_ip_address + }, + 'bgp_v4_network_bestpath': { + 'args': [' 193.11.248.128/25', 'bestpath'], + 'rc': 0, + 'rc_output': bgp_v4_network_bestpath + }, + 'bgp_v4_network_longer_prefixes_error': { + 'args': [' 193.11.248.128', 'longer-prefixes'], + 'rc': 1, + 'rc_output': bgp_v4_network_longer_prefixes_error + }, + 'bgp_v6_network': { + 'args': [], + 'rc': 0, + 'rc_output': bgp_v6_network + }, + 'bgp_v6_network_ip_address': { + 'args': [' 20c0:a820:0:80::/64'], + 'rc': 0, + 'rc_output': bgp_v6_network_ip_address + }, + 'bgp_v6_network_bestpath': { + 'args': [' 20c0:a820:0:80::/64', 'bestpath'], + 'rc': 0, + 'rc_output': bgp_v6_network_bestpath + }, + 'bgp_v6_network_longer_prefixes_error': { + 'args': [' 20c0:a820:0:80::', 'longer-prefixes'], + 'rc': 1, + 'rc_output': bgp_v6_network_longer_prefixes_error + }, + 'bgp_v6_network_longer_prefixes': { + 'args': [' 20c0:a820:0:80::/64', 'longer-prefixes'], + 'rc': 0, + 'rc_output': bgp_v6_network_longer_prefixes + }, + 'bgp_v4_network_multi_asic': { + 'args': [], + 'rc': 2, + 'rc_err_msg': multi_asic_bgp_network_err + }, + 'bgp_v4_network_asic0': { + 'args': ['-nasic0'], + 'rc': 0, + 'rc_output': bgp_v4_network_asic0 + }, + 'bgp_v4_network_ip_address_asic0': { + 'args': ['-nasic0', '10.0.0.44'], + 'rc': 0, + 'rc_output': bgp_v4_network_ip_address_asic0 + }, + 'bgp_v4_network_bestpath_asic0': { + 'args': ['-nasic0', '10.0.0.44', 'bestpath'], + 'rc': 0, + 'rc_output': bgp_v4_network_bestpath_asic0 + }, + 'bgp_v6_network_multi_asic': { + 'args': [], + 'rc': 2, + 'rc_err_msg': multi_asic_bgp_network_err + }, + 'bgp_v6_network_asic0': { + 'args': ['-nasic0'], + 'rc': 0, + 'rc_output': bgp_v4_network_asic0 + }, + 'bgp_v6_network_ip_address_asic0': { + 'args': ['-nasic0', '20c0:a808:0:80::/64'], + 'rc': 0, + 'rc_output': bgp_v6_network_ip_address_asic0 + }, + 'bgp_v6_network_bestpath_asic0': { + 'args': ['-nasic0', '20c0:a808:0:80::/64', 'bestpath'], + 'rc': 0, + 'rc_output': bgp_v6_network_ip_address_asic0_bestpath + } +} \ No newline at end of file diff --git a/tests/conftest.py b/tests/conftest.py index 4ff1a002bd..6ad352b224 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,14 +1,24 @@ import json import os +import re import sys from unittest import mock + import pytest from sonic_py_common import device_info from swsscommon.swsscommon import ConfigDBConnector from .mock_tables import dbconnector from . import show_ip_route_common +from .bgp_commands_input.bgp_neighbor_test_vector import( + mock_show_bgp_neighbor_single_asic, + mock_show_bgp_neighbor_multi_asic, + ) +from .bgp_commands_input.bgp_network_test_vector import ( + mock_show_bgp_network_single_asic, + mock_show_bgp_network_multi_asic + ) from . import config_int_ip_common test_path = os.path.dirname(os.path.abspath(__file__)) @@ -108,7 +118,6 @@ def setup_t1_topo(): @pytest.fixture def setup_single_bgp_instance(request): import utilities_common.bgp_util as bgp_util - if request.param == 'v4': bgp_mocked_json = os.path.join( test_path, 'mock_tables', 'ipv4_bgp_summary.json') @@ -119,7 +128,7 @@ def setup_single_bgp_instance(request): bgp_mocked_json = os.path.join( test_path, 'mock_tables', 'dummy.json') - def mock_run_bgp_command(vtysh_cmd, bgp_namespace): + def mock_show_bgp_summary(vtysh_cmd, bgp_namespace): if os.path.isfile(bgp_mocked_json): with open(bgp_mocked_json) as json_data: mock_frr_data = json_data.read() @@ -140,7 +149,7 @@ def mock_run_show_ip_route_commands(request): elif request.param == 'ip_route': return show_ip_route_common.show_ip_route_expected_output elif request.param == 'ip_specific_route': - return show_ip_route_common.show_specific_ip_route_expected_output + return show_ip_route_common.show_specific_ip_route_expected_output elif request.param == 'ip_special_route': return show_ip_route_common.show_special_ip_route_expected_output elif request.param == 'ipv6_route': @@ -150,18 +159,26 @@ def mock_run_show_ip_route_commands(request): else: return "" - + if any ([request.param == 'ipv6_route_err', request.param == 'ip_route',\ request.param == 'ip_specific_route', request.param == 'ip_special_route',\ request.param == 'ipv6_route', request.param == 'ipv6_specific_route']): bgp_util.run_bgp_command = mock.MagicMock( return_value=mock_run_show_ip_route_commands(request)) + elif request.param.startswith('bgp_v4_neighbor') or \ + request.param.startswith('bgp_v6_neighbor'): + bgp_util.run_bgp_command = mock.MagicMock( + return_value=mock_show_bgp_neighbor_single_asic(request)) + elif request.param.startswith('bgp_v4_network') or \ + request.param.startswith('bgp_v6_network'): + bgp_util.run_bgp_command = mock.MagicMock( + return_value=mock_show_bgp_network_single_asic(request)) elif request.param == 'ip_route_for_int_ip': _old_run_bgp_command = bgp_util.run_bgp_command bgp_util.run_bgp_command = mock_run_bgp_command_for_static else: bgp_util.run_bgp_command = mock.MagicMock( - return_value=mock_run_bgp_command("", "")) + return_value=mock_show_bgp_summary("", "")) yield @@ -191,6 +208,11 @@ def setup_multi_asic_bgp_instance(request): m_asic_json_file = 'ip_special_recursive_route.json' elif request.param == 'ip_route_summary': m_asic_json_file = 'ip_route_summary.txt' + elif request.param.startswith('bgp_v4_network') or \ + request.param.startswith('bgp_v6_network') or \ + request.param.startswith('bgp_v4_neighbor') or \ + request.param.startswith('bgp_v6_neighbor'): + m_asic_json_file = request.param else: m_asic_json_file = os.path.join( test_path, 'mock_tables', 'dummy.json') @@ -206,6 +228,14 @@ def mock_run_bgp_command_for_static(vtysh_cmd, bgp_namespace=""): return "" def mock_run_bgp_command(vtysh_cmd, bgp_namespace): + if m_asic_json_file.startswith('bgp_v4_network') or \ + m_asic_json_file.startswith('bgp_v6_network'): + return mock_show_bgp_network_multi_asic(m_asic_json_file) + + if m_asic_json_file.startswith('bgp_v4_neighbor') or \ + m_asic_json_file.startswith('bgp_v6_neighbor'): + return mock_show_bgp_neighbor_multi_asic(m_asic_json_file, bgp_namespace) + bgp_mocked_json = os.path.join( test_path, 'mock_tables', bgp_namespace, m_asic_json_file) if os.path.isfile(bgp_mocked_json): @@ -241,3 +271,4 @@ def setup_ip_route_commands(): import show.main as show return show + diff --git a/tests/mock_tables/asic0/config_db.json b/tests/mock_tables/asic0/config_db.json index 0643baf57f..adc620ffb1 100644 --- a/tests/mock_tables/asic0/config_db.json +++ b/tests/mock_tables/asic0/config_db.json @@ -203,5 +203,25 @@ }, "VLAN_MEMBER|Vlan1000|PortChannel1002": { "tagging_mode": "tagged" + }, + "BGP_NEIGHBOR|10.0.0.1": { + "rrclient": "0", + "name": "ARISTA01T2", + "local_addr": "10.0.0.0", + "nhopself": "0", + "admin_status": "up", + "holdtime": "10", + "asn": "65200", + "keepalive": "3" + }, + "BGP_NEIGHBOR|fc00::2": { + "rrclient": "0", + "name": "ARISTA01T2", + "local_addr": "fc00::1", + "nhopself": "0", + "admin_status": "up", + "holdtime": "10", + "asn": "65200", + "keepalive": "3" } } diff --git a/tests/mock_tables/asic1/config_db.json b/tests/mock_tables/asic1/config_db.json index 5aab92c45a..f5caae6d35 100644 --- a/tests/mock_tables/asic1/config_db.json +++ b/tests/mock_tables/asic1/config_db.json @@ -165,5 +165,25 @@ "state": "enabled", "auto_restart": "enabled", "high_mem_alert": "disabled" + }, + "BGP_INTERNAL_NEIGHBOR|10.1.0.1": { + "rrclient": "0", + "name": "ASIC0", + "local_addr": "10.1.0.0", + "nhopself": "0", + "admin_status": "up", + "holdtime": "0", + "asn": "65100", + "keepalive": "0" + }, + "BGP_INTERNAL_NEIGHBOR|2603:10e2:400:1::2": { + "rrclient": "0", + "name": "ASIC0", + "local_addr": "2603:10e2:400:1::1", + "nhopself": "0", + "admin_status": "up", + "holdtime": "0", + "asn": "65100", + "keepalive": "0" } } diff --git a/tests/mock_tables/mock_multi_asic.py b/tests/mock_tables/mock_multi_asic.py index 46f943369d..0e5589c301 100644 --- a/tests/mock_tables/mock_multi_asic.py +++ b/tests/mock_tables/mock_multi_asic.py @@ -63,6 +63,8 @@ def mock_is_multi_asic(): def mock_get_namespace_list(namespace=None): + if namespace: + return [namespace] return ['asic0', 'asic1'] diff --git a/tests/pfcstat_test.py b/tests/pfcstat_test.py index 6e0a76d364..5115ad11f1 100644 --- a/tests/pfcstat_test.py +++ b/tests/pfcstat_test.py @@ -1,3 +1,4 @@ +import importlib import os import shutil import sys @@ -247,3 +248,7 @@ def teardown_class(cls): os.environ["UTILITIES_UNIT_TESTING"] = "0" os.environ["UTILITIES_UNIT_TESTING_TOPOLOGY"] = "" del_cached_stats() + import mock_tables.mock_single_asic + importlib.reload(mock_tables.mock_single_asic) + import pfcwd.main + importlib.reload(pfcwd.main) diff --git a/tests/pfcwd_test.py b/tests/pfcwd_test.py index be04a11f25..b0af050233 100644 --- a/tests/pfcwd_test.py +++ b/tests/pfcwd_test.py @@ -497,3 +497,7 @@ def teardown_class(cls): ) os.environ["UTILITIES_UNIT_TESTING"] = "0" os.environ["UTILITIES_UNIT_TESTING_TOPOLOGY"] = "" + import mock_tables.mock_single_asic + importlib.reload(mock_tables.mock_single_asic) + import pfcwd.main + importlib.reload(pfcwd.main) \ No newline at end of file diff --git a/tests/show_bgp_neighbor_test.py b/tests/show_bgp_neighbor_test.py new file mode 100644 index 0000000000..de84223060 --- /dev/null +++ b/tests/show_bgp_neighbor_test.py @@ -0,0 +1,128 @@ +import importlib +import os + +import pytest + +from click.testing import CliRunner +from .bgp_commands_input.bgp_neighbor_test_vector import * + + +def executor(test_vector, show): + runner = CliRunner() + input = testData[test_vector] + if test_vector.startswith('bgp_v6'): + exec_cmd = show.cli.commands["ipv6"].commands["bgp"].commands["neighbors"] + else: + exec_cmd = show.cli.commands["ip"].commands["bgp"].commands["neighbors"] + + result = runner.invoke(exec_cmd, input['args']) + + print(result.exit_code) + print(result.output) + + if input['rc'] == 0: + assert result.exit_code == 0 + else: + assert result.exit_code == input['rc'] + + if 'rc_err_msg' in input: + output = result.output.strip().split("\n")[-1] + assert input['rc_err_msg'] == output + + if 'rc_output' in input: + assert result.output == input['rc_output'] + + if 'rc_warning_msg' in input: + output = result.output.strip().split("\n")[0] + assert input['rc_warning_msg'] in output + + +class TestBgpNeighbors(object): + + @classmethod + def setup_class(cls): + print("SETUP") + from .mock_tables import mock_single_asic + importlib.reload(mock_single_asic) + from .mock_tables import dbconnector + dbconnector.load_namespace_config() + + @pytest.mark.parametrize('setup_single_bgp_instance, test_vector', + [ + ('bgp_v4_neighbors_output', 'bgp_v4_neighbors'), + ('bgp_v4_neighbors_output', + 'bgp_v4_neighbor_ip_address'), + ('bgp_v4_neighbor_invalid_neigh', + 'bgp_v4_neighbor_invalid'), + ('bgp_v4_neighbor_invalid_address', + 'bgp_v4_neighbor_invalid_address'), + ('bgp_v4_neighbor_output_adv_routes', + 'bgp_v4_neighbor_adv_routes'), + ('bgp_v4_neighbor_output_recv_routes', + 'bgp_v4_neighbor_recv_routes'), + ('bgp_v6_neighbors_output', 'bgp_v6_neighbors'), + ('bgp_v6_neighbors_output', + 'bgp_v6_neighbor_ip_address'), + ('bgp_v6_neighbor_invalid', + 'bgp_v6_neighbor_invalid'), + ('bgp_v6_neighbor_invalid_address', + 'bgp_v6_neighbor_invalid_address'), + ('bgp_v6_neighbor_output_adv_routes', + 'bgp_v6_neighbor_adv_routes'), + ('bgp_v6_neighbor_output_recv_routes', + 'bgp_v6_neighbor_recv_routes'), + ], + indirect=['setup_single_bgp_instance']) + def test_bgp_neighbors(self, + setup_bgp_commands, + setup_single_bgp_instance, + test_vector): + show = setup_bgp_commands + executor(test_vector, show) + + +class TestBgpNeighborsMultiAsic(object): + @classmethod + def setup_class(cls): + print("SETUP") + from .mock_tables import mock_multi_asic + importlib.reload(mock_multi_asic) + from .mock_tables import dbconnector + dbconnector.load_namespace_config() + + @pytest.mark.parametrize('setup_multi_asic_bgp_instance, test_vector', + [ + ('bgp_v4_neighbors_output_all_asics', + 'bgp_v4_neighbors_multi_asic'), + ('bgp_v4_neighbors_output_asic1', + 'bgp_v4_neighbors_asic'), + ('bgp_v4_neighbors_output_asic1', + 'bgp_v4_neighbors_internal'), + ('bgp_v4_neighbors_output_asic0', + 'bgp_v4_neighbors_external'), + ('bgp_v6_neighbor_output_warning', + 'bgp_v6_neighbor_warning'), + ('bgp_v6_neighbors_output_all_asics', + 'bgp_v6_neighbors_multi_asic'), + ('bgp_v6_neighbors_output_asic0', + 'bgp_v6_neighbors_asic'), + ('bgp_v6_neighbors_output_asic0', + 'bgp_v6_neighbors_external'), + ('bgp_v6_neighbors_output_asic1', + 'bgp_v6_neighbors_internal') + ], + indirect=['setup_multi_asic_bgp_instance']) + def test_bgp_neighbors(self, + setup_bgp_commands, + setup_multi_asic_bgp_instance, + test_vector): + show = setup_bgp_commands + executor(test_vector, show) + + @classmethod + def teardown_class(cls): + print("TEARDOWN") + from .mock_tables import mock_single_asic + importlib.reload(mock_single_asic) + from .mock_tables import dbconnector + dbconnector.load_database_config diff --git a/tests/show_bgp_network_test.py b/tests/show_bgp_network_test.py new file mode 100644 index 0000000000..f610199538 --- /dev/null +++ b/tests/show_bgp_network_test.py @@ -0,0 +1,100 @@ +import importlib +import os + +import pytest + +from click.testing import CliRunner +from .bgp_commands_input import bgp_network_test_vector + + +def executor(test_vector, show): + runner = CliRunner() + input = bgp_network_test_vector.testData[test_vector] + if test_vector.startswith('bgp_v6'): + exec_cmd = show.cli.commands["ipv6"].commands["bgp"].commands["network"] + else: + exec_cmd = show.cli.commands["ip"].commands["bgp"].commands["network"] + + result = runner.invoke(exec_cmd, input['args']) + + print(result.exit_code) + print(result.output) + + if input['rc'] == 0: + assert result.exit_code == 0 + else: + assert result.exit_code == input['rc'] + + if 'rc_err_msg' in input: + output = result.output.strip().split("\n")[-1] + assert input['rc_err_msg'] in output + + if 'rc_output' in input: + assert result.output == input['rc_output'] + + if 'rc_warning_msg' in input: + output = result.output.strip().split("\n")[0] + assert input['rc_warning_msg'] in output + + +class TestBgpNetwork(object): + + @classmethod + def setup_class(cls): + from .mock_tables import mock_single_asic + importlib.reload(mock_single_asic) + from .mock_tables import dbconnector + dbconnector.load_database_config + + + @pytest.mark.parametrize( + 'setup_single_bgp_instance, test_vector', + [('bgp_v4_network', 'bgp_v4_network'), + ('bgp_v6_network', 'bgp_v6_network'), + ('bgp_v4_network_ip_address', 'bgp_v4_network_ip_address'), + ('bgp_v6_network_ip_address', 'bgp_v6_network_ip_address'), + ('bgp_v6_network_bestpath', 'bgp_v6_network_bestpath'), + ('bgp_v4_network_bestpath', 'bgp_v4_network_bestpath'), + ('bgp_v6_network_longer_prefixes', 'bgp_v6_network_longer_prefixes'), + ('bgp_v4_network', 'bgp_v4_network_longer_prefixes_error'), + ('bgp_v4_network', 'bgp_v6_network_longer_prefixes_error')], + indirect=['setup_single_bgp_instance']) + def test_bgp_network(self, setup_bgp_commands, test_vector, + setup_single_bgp_instance): + show = setup_bgp_commands + executor(test_vector, show) + + +class TestMultiAsicBgpNetwork(object): + + @classmethod + def setup_class(cls): + print("SETUP") + from .mock_tables import mock_multi_asic + importlib.reload(mock_multi_asic) + from .mock_tables import dbconnector + dbconnector.load_namespace_config() + + @pytest.mark.parametrize( + 'setup_multi_asic_bgp_instance, test_vector', + [('bgp_v4_network', 'bgp_v4_network_multi_asic'), + ('bgp_v6_network', 'bgp_v6_network_multi_asic'), + ('bgp_v4_network_asic0', 'bgp_v4_network_asic0'), + ('bgp_v4_network_ip_address_asic0', 'bgp_v4_network_ip_address_asic0'), + ('bgp_v4_network_bestpath_asic0', 'bgp_v4_network_bestpath_asic0'), + ('bgp_v6_network_asic0', 'bgp_v6_network_asic0'), + ('bgp_v6_network_ip_address_asic0', 'bgp_v6_network_ip_address_asic0'), + ('bgp_v6_network_bestpath_asic0', 'bgp_v6_network_bestpath_asic0')], + indirect=['setup_multi_asic_bgp_instance']) + def test_bgp_network(self, setup_bgp_commands, test_vector, + setup_multi_asic_bgp_instance): + show = setup_bgp_commands + executor(test_vector, show) + + @classmethod + def teardown_class(cls): + print("TEARDOWN") + from .mock_tables import mock_single_asic + importlib.reload(mock_single_asic) + from .mock_tables import dbconnector + dbconnector.load_database_config diff --git a/utilities_common/bgp_util.py b/utilities_common/bgp_util.py index 3d3968bd32..1d46ec5686 100644 --- a/utilities_common/bgp_util.py +++ b/utilities_common/bgp_util.py @@ -11,6 +11,32 @@ from utilities_common import constants +def get_namespace_for_bgp_neighbor(neighbor_ip): + namespace_list = multi_asic.get_namespace_list() + for namespace in namespace_list: + if is_bgp_neigh_present(neighbor_ip, namespace): + return namespace + + # neighbor IP not present in any namespace + raise ValueError( + ' Bgp neighbor {} not configured'.format(neighbor_ip)) + + +def is_bgp_neigh_present(neighbor_ip, namespace=multi_asic.DEFAULT_NAMESPACE): + config_db = multi_asic.connect_config_db_for_ns(namespace) + #check the internal + bgp_session = config_db.get_entry(multi_asic.BGP_NEIGH_CFG_DB_TABLE, + neighbor_ip) + if bgp_session: + return True + + bgp_session = config_db.get_entry( + multi_asic.BGP_INTERNAL_NEIGH_CFG_DB_TABLE, neighbor_ip) + if bgp_session: + return True + return False + + def is_ipv4_address(ip_address): """ Checks if given ip is ipv4 @@ -147,11 +173,13 @@ def get_neighbor_dict_from_table(db, table_name): return neighbor_dict -def run_bgp_command(vtysh_cmd, bgp_namespace=multi_asic.DEFAULT_NAMESPACE): +def run_bgp_command(vtysh_cmd, + bgp_namespace=multi_asic.DEFAULT_NAMESPACE): bgp_instance_id = ' ' output = None if bgp_namespace is not multi_asic.DEFAULT_NAMESPACE: - bgp_instance_id = " -n {} ".format(multi_asic.get_asic_id_from_name(bgp_namespace)) + bgp_instance_id = " -n {} ".format( + multi_asic.get_asic_id_from_name(bgp_namespace)) cmd = 'sudo vtysh {} -c "{}"'.format( bgp_instance_id, vtysh_cmd) @@ -159,11 +187,10 @@ def run_bgp_command(vtysh_cmd, bgp_namespace=multi_asic.DEFAULT_NAMESPACE): output = clicommon.run_command(cmd, return_cmd=True) except Exception: ctx = click.get_current_context() - ctx.fail("Unable to get summary from bgp".format(bgp_instance_id)) + ctx.fail("Unable to get summary from bgp {}".format(bgp_instance_id)) return output - def get_bgp_summary_from_all_bgp_instances(af, namespace, display): device = multi_asic_util.MultiAsic(display, namespace) @@ -258,7 +285,7 @@ def process_bgp_summary_json(bgp_summary, cmd_output, device): bgp_summary['peerGroupMemory'] = bgp_summary.get( 'peerGroupMemory', 0) + cmd_output['peerGroupMemory'] - #store instance level field is seperate dict + # store instance level field is seperate dict router_info = {} router_info['router_id'] = cmd_output['routerId'] router_info['vrf'] = cmd_output['vrfId'] @@ -288,7 +315,7 @@ def process_bgp_summary_json(bgp_summary, cmd_output, device): peers.append(value['pfxRcd']) else: peers.append(value['state']) - + # Get the bgp neighbour name ans store it neigh_name = get_bgp_neighbor_ip_to_name( peer_ip, static_neighbors, dynamic_neighbors) diff --git a/utilities_common/multi_asic.py b/utilities_common/multi_asic.py index d98b26b399..920b5eebe5 100644 --- a/utilities_common/multi_asic.py +++ b/utilities_common/multi_asic.py @@ -105,6 +105,11 @@ def multi_asic_display_default_option(): help='Namespace name or all'), ] +def multi_asic_namespace_validation_callback(ctx, param, value): + if not multi_asic.is_multi_asic: + click.echo("-n/--namespace is not available for single asic") + ctx.abort() + return value def multi_asic_click_options(func): for option in reversed(_multi_asic_click_options):