Skip to content

Commit

Permalink
[multi-asic] support show ip bgp neigh/network for multi asic (sonic-…
Browse files Browse the repository at this point in the history
…net#1574)

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 committed 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
@@ -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
@@ -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.

0 comments on commit c166f66

Please sign in to comment.