@@ -356,88 +356,95 @@ def get_interface_naming_mode():
356
356
mode = "default"
357
357
return mode
358
358
359
- def _is_neighbor_ipaddress (ipaddress ):
359
+ # Get the local BGP ASN from DEVICE_METADATA
360
+ def get_local_bgp_asn (config_db ):
361
+ metadata = config_db .get_table ('DEVICE_METADATA' )
362
+ return metadata ['localhost' ]['bgp_asn' ]
363
+
364
+ def _is_neighbor_ipaddress (config_db , ipaddress ):
360
365
"""Returns True if a neighbor has the IP address <ipaddress>, False if not
361
366
"""
362
- config_db = ConfigDBConnector ()
363
- config_db .connect ()
364
367
entry = config_db .get_entry ('BGP_NEIGHBOR' , ipaddress )
365
368
return True if entry else False
366
369
367
- def _get_all_neighbor_ipaddresses ():
370
+ def _get_all_neighbor_ipaddresses (config_db , ignore_local_hosts = False ):
368
371
"""Returns list of strings containing IP addresses of all BGP neighbors
372
+ if the flag ignore_local_hosts is set to True, additional check to see if
373
+ if the BGP neighbor AS number is same as local BGP AS number, if so ignore that neigbor.
369
374
"""
370
- config_db = ConfigDBConnector ()
371
- config_db .connect ()
372
- return config_db .get_table ('BGP_NEIGHBOR' ).keys ()
375
+ addrs = []
376
+ bgp_sessions = config_db .get_table ('BGP_NEIGHBOR' )
377
+ local_as = get_local_bgp_asn (config_db )
378
+ for addr , session in bgp_sessions .iteritems ():
379
+ if not ignore_local_hosts or (ignore_local_hosts and local_as != session ['asn' ]):
380
+ addrs .append (addr )
381
+ return addrs
373
382
374
- def _get_neighbor_ipaddress_list_by_hostname (hostname ):
383
+ def _get_neighbor_ipaddress_list_by_hostname (config_db , hostname ):
375
384
"""Returns list of strings, each containing an IP address of neighbor with
376
385
hostname <hostname>. Returns empty list if <hostname> not a neighbor
377
386
"""
378
387
addrs = []
379
- config_db = ConfigDBConnector ()
380
- config_db .connect ()
381
388
bgp_sessions = config_db .get_table ('BGP_NEIGHBOR' )
382
389
for addr , session in bgp_sessions .iteritems ():
383
390
if session .has_key ('name' ) and session ['name' ] == hostname :
384
391
addrs .append (addr )
385
392
return addrs
386
393
387
- def _change_bgp_session_status_by_addr (ipaddress , status , verbose ):
394
+ def _change_bgp_session_status_by_addr (config_db , ipaddress , status , verbose ):
388
395
"""Start up or shut down BGP session by IP address
389
396
"""
390
397
verb = 'Starting' if status == 'up' else 'Shutting'
391
398
click .echo ("{} {} BGP session with neighbor {}..." .format (verb , status , ipaddress ))
392
- config_db = ConfigDBConnector ()
393
- config_db .connect ()
394
399
395
400
config_db .mod_entry ('bgp_neighbor' , ipaddress , {'admin_status' : status })
396
401
397
- def _change_bgp_session_status (ipaddr_or_hostname , status , verbose ):
402
+ def _change_bgp_session_status (config_db , ipaddr_or_hostname , status , verbose ):
398
403
"""Start up or shut down BGP session by IP address or hostname
399
404
"""
400
405
ip_addrs = []
401
406
402
407
# If we were passed an IP address, convert it to lowercase because IPv6 addresses were
403
408
# stored in ConfigDB with all lowercase alphabet characters during minigraph parsing
404
- if _is_neighbor_ipaddress (ipaddr_or_hostname .lower ()):
409
+ if _is_neighbor_ipaddress (config_db , ipaddr_or_hostname .lower ()):
405
410
ip_addrs .append (ipaddr_or_hostname .lower ())
406
411
else :
407
412
# If <ipaddr_or_hostname> is not the IP address of a neighbor, check to see if it's a hostname
408
- ip_addrs = _get_neighbor_ipaddress_list_by_hostname (ipaddr_or_hostname )
413
+ ip_addrs = _get_neighbor_ipaddress_list_by_hostname (config_db , ipaddr_or_hostname )
409
414
410
415
if not ip_addrs :
411
- click . get_current_context (). fail ( "Could not locate neighbor '{}'" . format ( ipaddr_or_hostname ))
416
+ return False
412
417
413
418
for ip_addr in ip_addrs :
414
- _change_bgp_session_status_by_addr (ip_addr , status , verbose )
419
+ _change_bgp_session_status_by_addr (config_db , ip_addr , status , verbose )
420
+
421
+ return True
415
422
416
- def _validate_bgp_neighbor (neighbor_ip_or_hostname ):
423
+ def _validate_bgp_neighbor (config_db , neighbor_ip_or_hostname ):
417
424
"""validates whether the given ip or host name is a BGP neighbor
418
425
"""
419
426
ip_addrs = []
420
- if _is_neighbor_ipaddress (neighbor_ip_or_hostname .lower ()):
427
+ if _is_neighbor_ipaddress (config_db , neighbor_ip_or_hostname .lower ()):
421
428
ip_addrs .append (neighbor_ip_or_hostname .lower ())
422
429
else :
423
- ip_addrs = _get_neighbor_ipaddress_list_by_hostname (neighbor_ip_or_hostname .upper ())
424
-
425
- if not ip_addrs :
426
- click .get_current_context ().fail ("Could not locate neighbor '{}'" .format (neighbor_ip_or_hostname ))
430
+ ip_addrs = _get_neighbor_ipaddress_list_by_hostname (config_db , neighbor_ip_or_hostname .upper ())
427
431
428
432
return ip_addrs
429
433
430
- def _remove_bgp_neighbor_config (neighbor_ip_or_hostname ):
434
+ def _remove_bgp_neighbor_config (config_db , neighbor_ip_or_hostname ):
431
435
"""Removes BGP configuration of the given neighbor
432
436
"""
433
- ip_addrs = _validate_bgp_neighbor (neighbor_ip_or_hostname )
434
- config_db = ConfigDBConnector ()
435
- config_db .connect ()
437
+ ip_addrs = _validate_bgp_neighbor (config_db , neighbor_ip_or_hostname )
438
+
439
+ if not ip_addrs :
440
+ return False
436
441
437
442
for ip_addr in ip_addrs :
438
443
config_db .mod_entry ('bgp_neighbor' , ip_addr , None )
439
444
click .echo ("Removed configuration of BGP neighbor {}" .format (ip_addr ))
440
445
446
+ return True
447
+
441
448
def _change_hostname (hostname ):
442
449
current_hostname = os .uname ()[1 ]
443
450
if current_hostname != hostname :
@@ -1664,20 +1671,53 @@ def num_dumps(kdump_num_dumps):
1664
1671
@shutdown .command ()
1665
1672
@click .option ('-v' , '--verbose' , is_flag = True , help = "Enable verbose output" )
1666
1673
def all (verbose ):
1667
- """Shut down all BGP sessions"""
1674
+ """Shut down all BGP sessions
1675
+ In the case of Multi-Asic platform, we shut only the EBGP sessions with external neighbors.
1676
+ """
1668
1677
log_info ("'bgp shutdown all' executing..." )
1669
- bgp_neighbor_ip_list = _get_all_neighbor_ipaddresses ()
1670
- for ipaddress in bgp_neighbor_ip_list :
1671
- _change_bgp_session_status_by_addr (ipaddress , 'down' , verbose )
1678
+ namespaces = [DEFAULT_NAMESPACE ]
1679
+ ignore_local_hosts = False
1680
+
1681
+ if sonic_device_util .is_multi_npu ():
1682
+ ns_list = sonic_device_util .get_all_namespaces ()
1683
+ namespaces = ns_list ['front_ns' ]
1684
+ ignore_local_hosts = True
1685
+
1686
+ # Connect to CONFIG_DB in linux host (in case of single ASIC) or CONFIG_DB in all the
1687
+ # namespaces (in case of multi ASIC) and do the sepcified "action" on the BGP neighbor(s)
1688
+ for namespace in namespaces :
1689
+ config_db = ConfigDBConnector (use_unix_socket_path = True , namespace = namespace )
1690
+ config_db .connect ()
1691
+ bgp_neighbor_ip_list = _get_all_neighbor_ipaddresses (config_db , ignore_local_hosts )
1692
+ for ipaddress in bgp_neighbor_ip_list :
1693
+ _change_bgp_session_status_by_addr (config_db , ipaddress , 'down' , verbose )
1672
1694
1673
1695
# 'neighbor' subcommand
1674
1696
@shutdown .command ()
1675
1697
@click .argument ('ipaddr_or_hostname' , metavar = '<ipaddr_or_hostname>' , required = True )
1676
1698
@click .option ('-v' , '--verbose' , is_flag = True , help = "Enable verbose output" )
1677
1699
def neighbor (ipaddr_or_hostname , verbose ):
1678
- """Shut down BGP session by neighbor IP address or hostname"""
1700
+ """Shut down BGP session by neighbor IP address or hostname.
1701
+ User can specify either internal or external BGP neighbor to shutdown
1702
+ """
1679
1703
log_info ("'bgp shutdown neighbor {}' executing..." .format (ipaddr_or_hostname ))
1680
- _change_bgp_session_status (ipaddr_or_hostname , 'down' , verbose )
1704
+ namespaces = [DEFAULT_NAMESPACE ]
1705
+ found_neighbor = False
1706
+
1707
+ if sonic_device_util .is_multi_npu ():
1708
+ ns_list = sonic_device_util .get_all_namespaces ()
1709
+ namespaces = ns_list ['front_ns' ] + ns_list ['back_ns' ]
1710
+
1711
+ # Connect to CONFIG_DB in linux host (in case of single ASIC) or CONFIG_DB in all the
1712
+ # namespaces (in case of multi ASIC) and do the sepcified "action" on the BGP neighbor(s)
1713
+ for namespace in namespaces :
1714
+ config_db = ConfigDBConnector (use_unix_socket_path = True , namespace = namespace )
1715
+ config_db .connect ()
1716
+ if _change_bgp_session_status (config_db , ipaddr_or_hostname , 'down' , verbose ):
1717
+ found_neighbor = True
1718
+
1719
+ if not found_neighbor :
1720
+ click .get_current_context ().fail ("Could not locate neighbor '{}'" .format (ipaddr_or_hostname ))
1681
1721
1682
1722
@bgp .group (cls = AbbreviationGroup )
1683
1723
def startup ():
@@ -1688,20 +1728,53 @@ def startup():
1688
1728
@startup .command ()
1689
1729
@click .option ('-v' , '--verbose' , is_flag = True , help = "Enable verbose output" )
1690
1730
def all (verbose ):
1691
- """Start up all BGP sessions"""
1731
+ """Start up all BGP sessions
1732
+ In the case of Multi-Asic platform, we startup only the EBGP sessions with external neighbors.
1733
+ """
1692
1734
log_info ("'bgp startup all' executing..." )
1693
- bgp_neighbor_ip_list = _get_all_neighbor_ipaddresses ()
1694
- for ipaddress in bgp_neighbor_ip_list :
1695
- _change_bgp_session_status (ipaddress , 'up' , verbose )
1735
+ namespaces = [DEFAULT_NAMESPACE ]
1736
+ ignore_local_hosts = False
1737
+
1738
+ if sonic_device_util .is_multi_npu ():
1739
+ ns_list = sonic_device_util .get_all_namespaces ()
1740
+ namespaces = ns_list ['front_ns' ]
1741
+ ignore_local_hosts = True
1742
+
1743
+ # Connect to CONFIG_DB in linux host (in case of single ASIC) or CONFIG_DB in all the
1744
+ # namespaces (in case of multi ASIC) and do the sepcified "action" on the BGP neighbor(s)
1745
+ for namespace in namespaces :
1746
+ config_db = ConfigDBConnector (use_unix_socket_path = True , namespace = namespace )
1747
+ config_db .connect ()
1748
+ bgp_neighbor_ip_list = _get_all_neighbor_ipaddresses (config_db , ignore_local_hosts )
1749
+ for ipaddress in bgp_neighbor_ip_list :
1750
+ _change_bgp_session_status_by_addr (config_db , ipaddress , 'up' , verbose )
1696
1751
1697
1752
# 'neighbor' subcommand
1698
1753
@startup .command ()
1699
1754
@click .argument ('ipaddr_or_hostname' , metavar = '<ipaddr_or_hostname>' , required = True )
1700
1755
@click .option ('-v' , '--verbose' , is_flag = True , help = "Enable verbose output" )
1701
1756
def neighbor (ipaddr_or_hostname , verbose ):
1702
- """Start up BGP session by neighbor IP address or hostname"""
1703
1757
log_info ("'bgp startup neighbor {}' executing..." .format (ipaddr_or_hostname ))
1704
- _change_bgp_session_status (ipaddr_or_hostname , 'up' , verbose )
1758
+ """Start up BGP session by neighbor IP address or hostname.
1759
+ User can specify either internal or external BGP neighbor to startup
1760
+ """
1761
+ namespaces = [DEFAULT_NAMESPACE ]
1762
+ found_neighbor = False
1763
+
1764
+ if sonic_device_util .is_multi_npu ():
1765
+ ns_list = sonic_device_util .get_all_namespaces ()
1766
+ namespaces = ns_list ['front_ns' ] + ns_list ['back_ns' ]
1767
+
1768
+ # Connect to CONFIG_DB in linux host (in case of single ASIC) or CONFIG_DB in all the
1769
+ # namespaces (in case of multi ASIC) and do the sepcified "action" on the BGP neighbor(s)
1770
+ for namespace in namespaces :
1771
+ config_db = ConfigDBConnector (use_unix_socket_path = True , namespace = namespace )
1772
+ config_db .connect ()
1773
+ if _change_bgp_session_status (config_db , ipaddr_or_hostname , 'up' , verbose ):
1774
+ found_neighbor = True
1775
+
1776
+ if not found_neighbor :
1777
+ click .get_current_context ().fail ("Could not locate neighbor '{}'" .format (ipaddr_or_hostname ))
1705
1778
1706
1779
#
1707
1780
# 'remove' subgroup ('config bgp remove ...')
@@ -1715,8 +1788,26 @@ def remove():
1715
1788
@remove .command ('neighbor' )
1716
1789
@click .argument ('neighbor_ip_or_hostname' , metavar = '<neighbor_ip_or_hostname>' , required = True )
1717
1790
def remove_neighbor (neighbor_ip_or_hostname ):
1718
- """Deletes BGP neighbor configuration of given hostname or ip from devices"""
1719
- _remove_bgp_neighbor_config (neighbor_ip_or_hostname )
1791
+ """Deletes BGP neighbor configuration of given hostname or ip from devices
1792
+ User can specify either internal or external BGP neighbor to remove
1793
+ """
1794
+ namespaces = [DEFAULT_NAMESPACE ]
1795
+ removed_neighbor = False
1796
+
1797
+ if sonic_device_util .is_multi_npu ():
1798
+ ns_list = sonic_device_util .get_all_namespaces ()
1799
+ namespaces = ns_list ['front_ns' ] + ns_list ['back_ns' ]
1800
+
1801
+ # Connect to CONFIG_DB in linux host (in case of single ASIC) or CONFIG_DB in all the
1802
+ # namespaces (in case of multi ASIC) and do the sepcified "action" on the BGP neighbor(s)
1803
+ for namespace in namespaces :
1804
+ config_db = ConfigDBConnector (use_unix_socket_path = True , namespace = namespace )
1805
+ config_db .connect ()
1806
+ if _remove_bgp_neighbor_config (config_db , neighbor_ip_or_hostname ):
1807
+ removed_neighbor = True
1808
+
1809
+ if not removed_neighbor :
1810
+ click .get_current_context ().fail ("Could not locate neighbor '{}'" .format (neighbor_ip_or_hostname ))
1720
1811
1721
1812
#
1722
1813
# 'interface' group ('config interface ...')
0 commit comments