Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[multi-asic] support show ip bgp neigh/network for multi asic #1574

Merged
merged 4 commits into from
Apr 27, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
smaheshm marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if it's not lot of work can you explore adding the 'json' dump option.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, this PR is just adding support for multi asic. We can explore the json option in a future PR

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:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question on the overall design to handle multi-ASIC. By looking at how this is implemented it looks like it will cycle through all the name spaces and no attempt to merge/filter but will display whatever each namespace has to the output directly?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gechiang, Yes, this command we just display neighbor from all the namespaces. No filtering done for this commands

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,
smaheshm marked this conversation as resolved.
Show resolved Hide resolved
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