Skip to content

Commit c166f66

Browse files
authored
[multi-asic] support show ip bgp neigh/network for multi asic (sonic-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 <[email protected]>
1 parent 9dba93f commit c166f66

15 files changed

+1776
-50
lines changed

show/bgp_frr_v4.py

+73-24
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
import click
2+
3+
from sonic_py_common import multi_asic
4+
from show.main import ip
25
import utilities_common.bgp_util as bgp_util
36
import utilities_common.cli as clicommon
47
import utilities_common.constants as constants
58
import utilities_common.multi_asic as multi_asic_util
69

7-
from show.main import ip, run_command
8-
910
###############################################################################
1011
#
1112
# 'show ip bgp' cli stanza
1213
#
1314
###############################################################################
1415

1516

16-
1717
@ip.group(cls=clicommon.AliasedGroup)
1818
def bgp():
1919
"""Show IPv4 BGP (Border Gateway Protocol) information"""
@@ -24,43 +24,93 @@ def bgp():
2424
@bgp.command()
2525
@multi_asic_util.multi_asic_click_options
2626
def summary(namespace, display):
27-
bgp_summary = bgp_util.get_bgp_summary_from_all_bgp_instances(constants.IPV4, namespace,display)
27+
bgp_summary = bgp_util.get_bgp_summary_from_all_bgp_instances(
28+
constants.IPV4, namespace, display)
2829
bgp_util.display_bgp_summary(bgp_summary=bgp_summary, af=constants.IPV4)
29-
30+
3031

3132
# 'neighbors' subcommand ("show ip bgp neighbors")
3233
@bgp.command()
3334
@click.argument('ipaddress', required=False)
34-
@click.argument('info_type', type=click.Choice(['routes', 'advertised-routes', 'received-routes']), required=False)
35-
def neighbors(ipaddress, info_type):
35+
@click.argument('info_type',
36+
type=click.Choice(
37+
['routes', 'advertised-routes', 'received-routes']),
38+
required=False)
39+
@click.option('--namespace',
40+
'-n',
41+
'namespace',
42+
default=None,
43+
type=str,
44+
show_default=True,
45+
help='Namespace name or all',
46+
callback=multi_asic_util.multi_asic_namespace_validation_callback)
47+
def neighbors(ipaddress, info_type, namespace):
3648
"""Show IP (IPv4) BGP neighbors"""
3749

38-
command = 'sudo vtysh -c "show ip bgp neighbor'
39-
50+
command = 'show ip bgp neighbor'
4051
if ipaddress is not None:
41-
command += ' {}'.format(ipaddress)
52+
if not bgp_util.is_ipv4_address(ipaddress):
53+
ctx = click.get_current_context()
54+
ctx.fail("{} is not valid ipv4 address\n".format(ipaddress))
55+
try:
56+
actual_namespace = bgp_util.get_namespace_for_bgp_neighbor(
57+
ipaddress)
58+
if namespace is not None and namespace != actual_namespace:
59+
click.echo(
60+
"[WARNING]: bgp neighbor {} is present in namespace {} not in {}"
61+
.format(ipaddress, actual_namespace, namespace))
4262

43-
# info_type is only valid if ipaddress is specified
44-
if info_type is not None:
45-
command += ' {}'.format(info_type)
63+
# save the namespace in which the bgp neighbor is configured
64+
namespace = actual_namespace
65+
66+
command += ' {}'.format(ipaddress)
4667

47-
command += '"'
68+
# info_type is only valid if ipaddress is specified
69+
if info_type is not None:
70+
command += ' {}'.format(info_type)
71+
except ValueError as err:
72+
ctx = click.get_current_context()
73+
ctx.fail("{}\n".format(err))
74+
75+
ns_list = multi_asic.get_namespace_list(namespace)
76+
output = ""
77+
for ns in ns_list:
78+
output += bgp_util.run_bgp_command(command, ns)
79+
80+
click.echo(output.rstrip('\n'))
4881

49-
run_command(command)
5082

5183
# 'network' subcommand ("show ip bgp network")
5284
@bgp.command()
53-
@click.argument('ipaddress', metavar='[<ipv4-address>|<ipv4-prefix>]', required=False)
54-
@click.argument('info_type', metavar='[bestpath|json|longer-prefixes|multipath]',
55-
type=click.Choice(['bestpath', 'json', 'longer-prefixes', 'multipath']), required=False)
56-
def network(ipaddress, info_type):
85+
@click.argument('ipaddress',
86+
metavar='[<ipv4-address>|<ipv4-prefix>]',
87+
required=False)
88+
@click.argument('info_type',
89+
metavar='[bestpath|json|longer-prefixes|multipath]',
90+
type=click.Choice(
91+
['bestpath', 'json', 'longer-prefixes', 'multipath']),
92+
required=False)
93+
@click.option('--namespace',
94+
'-n',
95+
'namespace',
96+
type=str,
97+
show_default=True,
98+
required=True if multi_asic.is_multi_asic is True else False,
99+
help='Namespace name or all',
100+
default=None,
101+
callback=multi_asic_util.multi_asic_namespace_validation_callback)
102+
def network(ipaddress, info_type, namespace):
57103
"""Show IP (IPv4) BGP network"""
58104

59-
command = 'sudo vtysh -c "show ip bgp'
105+
if multi_asic.is_multi_asic() and namespace not in multi_asic.get_namespace_list():
106+
ctx = click.get_current_context()
107+
ctx.fail('-n/--namespace option required. provide namespace from list {}'\
108+
.format(multi_asic.get_namespace_list()))
60109

110+
command = 'show ip bgp'
61111
if ipaddress is not None:
62112
if '/' in ipaddress:
63-
# For network prefixes then this all info_type(s) are available
113+
# For network prefixes then this all info_type(s) are available
64114
pass
65115
else:
66116
# For an ipaddress then check info_type, exit if specified option doesn't work.
@@ -75,6 +125,5 @@ def network(ipaddress, info_type):
75125
if info_type is not None:
76126
command += ' {}'.format(info_type)
77127

78-
command += '"'
79-
80-
run_command(command)
128+
output = bgp_util.run_bgp_command(command, namespace)
129+
click.echo(output.rstrip('\n'))

show/bgp_frr_v6.py

+73-15
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import click
22

3+
from sonic_py_common import multi_asic
34
import utilities_common.cli as clicommon
4-
from show.main import ipv6, run_command
5+
from show.main import ipv6
56
import utilities_common.multi_asic as multi_asic_util
67
import utilities_common.bgp_util as bgp_util
78
import utilities_common.constants as constants
@@ -31,27 +32,85 @@ def summary(namespace, display):
3132
# 'neighbors' subcommand ("show ipv6 bgp neighbors")
3233
@bgp.command()
3334
@click.argument('ipaddress', required=False)
34-
@click.argument('info_type', type=click.Choice(['routes', 'advertised-routes', 'received-routes']), required=False)
35-
def neighbors(ipaddress, info_type):
35+
@click.argument('info_type',
36+
type=click.Choice(
37+
['routes', 'advertised-routes', 'received-routes']),
38+
required=False)
39+
@click.option('--namespace',
40+
'-n',
41+
'namespace',
42+
default=None,
43+
type=str,
44+
show_default=True,
45+
help='Namespace name or all',
46+
callback=multi_asic_util.multi_asic_namespace_validation_callback)
47+
def neighbors(ipaddress, info_type, namespace):
3648
"""Show IPv6 BGP neighbors"""
37-
ipaddress = "" if ipaddress is None else ipaddress
49+
50+
if ipaddress is not None:
51+
if not bgp_util.is_ipv6_address(ipaddress):
52+
ctx = click.get_current_context()
53+
ctx.fail("{} is not valid ipv6 address\n".format(ipaddress))
54+
try:
55+
actual_namespace = bgp_util.get_namespace_for_bgp_neighbor(
56+
ipaddress)
57+
if namespace is not None and namespace != actual_namespace:
58+
click.echo(
59+
"bgp neighbor {} is present in namespace {} not in {}"
60+
.format(ipaddress, actual_namespace, namespace))
61+
62+
# save the namespace in which the bgp neighbor is configured
63+
namespace = actual_namespace
64+
except ValueError as err:
65+
ctx = click.get_current_context()
66+
ctx.fail("{}\n".format(err))
67+
else:
68+
ipaddress = ""
69+
3870
info_type = "" if info_type is None else info_type
39-
command = 'sudo vtysh -c "show bgp ipv6 neighbor {} {}"'.format(ipaddress, info_type)
40-
run_command(command)
71+
command = 'show bgp ipv6 neighbor {} {}'.format(
72+
ipaddress, info_type)
73+
74+
ns_list = multi_asic.get_namespace_list(namespace)
75+
output = ""
76+
for ns in ns_list:
77+
output += bgp_util.run_bgp_command(command, ns)
78+
79+
click.echo(output.rstrip('\n'))
80+
4181

4282
# 'network' subcommand ("show ipv6 bgp network")
4383
@bgp.command()
44-
@click.argument('ipaddress', metavar='[<ipv6-address>|<ipv6-prefix>]', required=False)
45-
@click.argument('info_type', metavar='[bestpath|json|longer-prefixes|multipath]',
46-
type=click.Choice(['bestpath', 'json', 'longer-prefixes', 'multipath']), required=False)
47-
def network(ipaddress, info_type):
84+
@click.argument('ipaddress',
85+
metavar='[<ipv6-address>|<ipv6-prefix>]',
86+
required=False)
87+
@click.argument('info_type',
88+
metavar='[bestpath|json|longer-prefixes|multipath]',
89+
type=click.Choice(
90+
['bestpath', 'json', 'longer-prefixes', 'multipath']),
91+
required=False)
92+
@click.option('--namespace',
93+
'-n',
94+
'namespace',
95+
type=str,
96+
show_default=True,
97+
required=True if multi_asic.is_multi_asic is True else False,
98+
help='Namespace name or all',
99+
default=None,
100+
callback=multi_asic_util.multi_asic_namespace_validation_callback)
101+
def network(ipaddress, info_type, namespace):
48102
"""Show BGP ipv6 network"""
49103

50-
command = 'sudo vtysh -c "show bgp ipv6'
104+
command = 'show bgp ipv6'
105+
106+
if multi_asic.is_multi_asic() and namespace not in multi_asic.get_namespace_list():
107+
ctx = click.get_current_context()
108+
ctx.fail('-n/--namespace option required. provide namespace from list {}'\
109+
.format(multi_asic.get_namespace_list()))
51110

52111
if ipaddress is not None:
53112
if '/' in ipaddress:
54-
# For network prefixes then this all info_type(s) are available
113+
# For network prefixes then this all info_type(s) are available
55114
pass
56115
else:
57116
# For an ipaddress then check info_type, exit if specified option doesn't work.
@@ -66,6 +125,5 @@ def network(ipaddress, info_type):
66125
if info_type is not None:
67126
command += ' {}'.format(info_type)
68127

69-
command += '"'
70-
71-
run_command(command)
128+
output = bgp_util.run_bgp_command(command, namespace)
129+
click.echo(output.rstrip('\n'))

tests/bgp_commands_input/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)