Skip to content

Commit

Permalink
[multi-asic] support show ip bgp neigh/network for multi asic (#1574)
Browse files Browse the repository at this point in the history
This change is to add support for the commands "show ip bgp neighbor "and "show ip bgp network" for multi asic platforms
Add unit tests for these commands

Signed-off-by: Arvindsrinivasan Lakshmi Narasimhan <arlakshm@microsoft.com>
  • Loading branch information
arlakshm authored Apr 27, 2021
1 parent 9dba93f commit c166f66
Show file tree
Hide file tree
Showing 15 changed files with 1,776 additions and 50 deletions.
97 changes: 73 additions & 24 deletions show/bgp_frr_v4.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
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
#
###############################################################################



@ip.group(cls=clicommon.AliasedGroup)
def bgp():
"""Show IPv4 BGP (Border Gateway Protocol) information"""
Expand All @@ -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='[<ipv4-address>|<ipv4-prefix>]', 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='[<ipv4-address>|<ipv4-prefix>]',
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.
Expand All @@ -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'))
88 changes: 73 additions & 15 deletions show/bgp_frr_v6.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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='[<ipv6-address>|<ipv6-prefix>]', 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='[<ipv6-address>|<ipv6-prefix>]',
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.
Expand All @@ -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'))
Empty file.
Loading

0 comments on commit c166f66

Please sign in to comment.