Common functions for Multi ASIC (#4973)
Signed-off-by: Arvindsrinivasan Lakshmi Narasimhan arlakshm@microsoft.com The following common APIs are added for multi ASIC - an API to check if a given port is a internal or external port - an API to check if a given port-channel is internal or external - an API to check if a bgp-session is internal or external - an API to connect to the config and other dbs in the a given namespace - added common APIs to the sonic_py_common library. - update the sample port-config.ini with role column and add corresponding test to verify the ports configuration is - generated properly.
This commit is contained in:
parent
bf3c901c6c
commit
6c895513ac
@ -14,7 +14,7 @@ from lxml import etree as ET
|
|||||||
from lxml.etree import QName
|
from lxml.etree import QName
|
||||||
|
|
||||||
from portconfig import get_port_config
|
from portconfig import get_port_config
|
||||||
from sonic_py_common.device_info import get_npu_id_from_name
|
from sonic_py_common.multi_asic import get_asic_id_from_name
|
||||||
|
|
||||||
"""minigraph.py
|
"""minigraph.py
|
||||||
version_added: "1.9"
|
version_added: "1.9"
|
||||||
@ -840,7 +840,7 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw
|
|||||||
|
|
||||||
# hostname is the asic_name, get the asic_id from the asic_name
|
# hostname is the asic_name, get the asic_id from the asic_name
|
||||||
if asic_name is not None:
|
if asic_name is not None:
|
||||||
asic_id = get_npu_id_from_name(asic_name)
|
asic_id = get_asic_id_from_name(asic_name)
|
||||||
else:
|
else:
|
||||||
asic_id = None
|
asic_id = None
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ from minigraph import parse_device_desc_xml
|
|||||||
from minigraph import parse_asic_sub_role
|
from minigraph import parse_asic_sub_role
|
||||||
from portconfig import get_port_config, get_port_config_file_name, get_breakout_mode
|
from portconfig import get_port_config, get_port_config_file_name, get_breakout_mode
|
||||||
from sonic_py_common.device_info import get_platform, get_system_mac
|
from sonic_py_common.device_info import get_platform, get_system_mac
|
||||||
from sonic_py_common.device_info import get_npu_id_from_name, is_multi_npu
|
from sonic_py_common.multi_asic import get_asic_id_from_name, is_multi_asic
|
||||||
from config_samples import generate_sample_config
|
from config_samples import generate_sample_config
|
||||||
from config_samples import get_available_config
|
from config_samples import get_available_config
|
||||||
from swsssdk import SonicV2Connector, ConfigDBConnector, SonicDBConfig
|
from swsssdk import SonicV2Connector, ConfigDBConnector, SonicDBConfig
|
||||||
@ -240,8 +240,8 @@ def _get_jinja2_env(paths):
|
|||||||
env.filters['ip_network'] = ip_network
|
env.filters['ip_network'] = ip_network
|
||||||
for attr in ['ip', 'network', 'prefixlen', 'netmask', 'broadcast']:
|
for attr in ['ip', 'network', 'prefixlen', 'netmask', 'broadcast']:
|
||||||
env.filters[attr] = partial(prefix_attr, attr)
|
env.filters[attr] = partial(prefix_attr, attr)
|
||||||
# Pass the is_multi_npu function as global
|
# Pass the is_multi_asic function as global
|
||||||
env.globals['multi_asic'] = is_multi_npu
|
env.globals['multi_asic'] = is_multi_asic
|
||||||
|
|
||||||
return env
|
return env
|
||||||
|
|
||||||
@ -284,7 +284,7 @@ def main():
|
|||||||
asic_name = args.namespace
|
asic_name = args.namespace
|
||||||
asic_id = None
|
asic_id = None
|
||||||
if asic_name is not None:
|
if asic_name is not None:
|
||||||
asic_id = get_npu_id_from_name(asic_name)
|
asic_id = get_asic_id_from_name(asic_name)
|
||||||
|
|
||||||
|
|
||||||
# Load the database config for the namespace from global database json
|
# Load the database config for the namespace from global database json
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
# name lanes alias asic_port_name
|
# name lanes alias index asic_port_name role
|
||||||
Ethernet0 33,34,35,36 Ethernet1/1 Eth0-ASIC0
|
Ethernet0 33,34,35,36 Ethernet1/1 0 Eth0-ASIC0 Ext
|
||||||
Ethernet4 29,30,31,32 Ethernet1/2 Eth1-ASIC0
|
Ethernet4 29,30,31,32 Ethernet1/2 1 Eth1-ASIC0 Ext
|
||||||
Ethernet8 41,42,43,44 Ethernet1/3 Eth2-ASIC0
|
Ethernet8 41,42,43,44 Ethernet1/3 2 Eth2-ASIC0 Ext
|
||||||
Ethernet12 37,38,39,40 Ethernet1/4 Eth3-ASIC0
|
Ethernet12 37,38,39,40 Ethernet1/4 3 Eth3-ASIC0 Ext
|
||||||
Ethernet-BP0 13,14,15,16 Ethernet-BP0 Eth4-ASIC0
|
Ethernet-BP0 13,14,15,16 Ethernet-BP0 0 Eth4-ASIC0 Int
|
||||||
Ethernet-BP4 17,18,19,20 Ethernet-BP4 Eth5-ASIC0
|
Ethernet-BP4 17,18,19,20 Ethernet-BP4 1 Eth5-ASIC0 Int
|
||||||
Ethernet-BP8 21,22,23,24 Ethernet-BP8 Eth6-ASIC0
|
Ethernet-BP8 21,22,23,24 Ethernet-BP8 2 Eth6-ASIC0 Int
|
||||||
Ethernet-BP12 25,26,27,28 Ethernet-BP12 Eth7-ASIC0
|
Ethernet-BP12 25,26,27,28 Ethernet-BP12 3 Eth7-ASIC0 Int
|
@ -1,9 +1,9 @@
|
|||||||
# name lanes alias asic_port_name
|
# name lanes alias index asic_port_name role
|
||||||
Ethernet16 33,34,35,36 Ethernet1/5 Eth0-ASIC1
|
Ethernet16 33,34,35,36 Ethernet1/5 4 Eth0-ASIC1 Ext
|
||||||
Ethernet20 29,30,31,32 Ethernet1/6 Eth1-ASIC1
|
Ethernet20 29,30,31,32 Ethernet1/6 5 Eth1-ASIC1 Ext
|
||||||
Ethernet24 41,42,43,44 Ethernet1/7 Eth2-ASIC1
|
Ethernet24 41,42,43,44 Ethernet1/7 6 Eth2-ASIC1 Ext
|
||||||
Ethernet28 37,38,39,40 Ethernet1/8 Eth3-ASIC1
|
Ethernet28 37,38,39,40 Ethernet1/8 7 Eth3-ASIC1 Ext
|
||||||
Ethernet-BP16 13,14,15,16 Ethernet-BP16 Eth4-ASIC1
|
Ethernet-BP16 13,14,15,16 Ethernet-BP16 4 Eth4-ASIC1 Int
|
||||||
Ethernet-BP20 17,18,19,20 Ethernet-BP20 Eth5-ASIC1
|
Ethernet-BP20 17,18,19,20 Ethernet-BP20 5 Eth5-ASIC1 Int
|
||||||
Ethernet-BP24 21,22,23,24 Ethernet-BP24 Eth6-ASIC1
|
Ethernet-BP24 21,22,23,24 Ethernet-BP24 6 Eth6-ASIC1 Int
|
||||||
Ethernet-BP28 25,26,27,28 Ethernet-BP28 Eth7-ASIC1
|
Ethernet-BP28 25,26,27,28 Ethernet-BP28 7 Eth7-ASIC1 Int
|
@ -1,9 +1,9 @@
|
|||||||
# name lanes alias asic_port_name
|
# name lanes alias index asic_port_name role
|
||||||
Ethernet-BP256 61,62,63,64 Ethernet-BP256 Eth0-ASIC2
|
Ethernet-BP256 61,62,63,64 Ethernet-BP256 8 Eth0-ASIC2 Int
|
||||||
Ethernet-BP260 57,58,59,60 Ethernet-BP260 Eth1-ASIC2
|
Ethernet-BP260 57,58,59,60 Ethernet-BP260 9 Eth1-ASIC2 Int
|
||||||
Ethernet-BP264 53,54,55,56 Ethernet-BP264 Eth2-ASIC2
|
Ethernet-BP264 53,54,55,56 Ethernet-BP264 10 Eth2-ASIC2 Int
|
||||||
Ethernet-BP268 49,50,51,52 Ethernet-BP268 Eth3-ASIC2
|
Ethernet-BP268 49,50,51,52 Ethernet-BP268 11 Eth3-ASIC2 Int
|
||||||
Ethernet-BP272 45,46,47,48 Ethernet-BP272 Eth4-ASIC2
|
Ethernet-BP272 45,46,47,48 Ethernet-BP272 12 Eth4-ASIC2 Int
|
||||||
Ethernet-BP276 41,42,43,44 Ethernet-BP276 Eth5-ASIC2
|
Ethernet-BP276 41,42,43,44 Ethernet-BP276 13 Eth5-ASIC2 Int
|
||||||
Ethernet-BP280 37,38,39,40 Ethernet-BP280 Eth6-ASIC2
|
Ethernet-BP280 37,38,39,40 Ethernet-BP280 14 Eth6-ASIC2 Int
|
||||||
Ethernet-BP284 33,34,35,36 Ethernet-BP284 Eth7-ASIC2
|
Ethernet-BP284 33,34,35,36 Ethernet-BP284 15 Eth7-ASIC2 Int
|
@ -1,9 +1,9 @@
|
|||||||
# name lanes alias asic_port_name
|
# name lanes alias index asic_port_name role
|
||||||
Ethernet-BP384 29,30,31,32 Ethernet-BP384 Eth0-ASIC3
|
Ethernet-BP384 29,30,31,32 Ethernet-BP384 16 Eth0-ASIC3 Int
|
||||||
Ethernet-BP388 25,26,27,28 Ethernet-BP388 Eth1-ASIC3
|
Ethernet-BP388 25,26,27,28 Ethernet-BP388 17 Eth1-ASIC3 Int
|
||||||
Ethernet-BP392 21,22,23,24 Ethernet-BP392 Eth2-ASIC3
|
Ethernet-BP392 21,22,23,24 Ethernet-BP392 18 Eth2-ASIC3 Int
|
||||||
Ethernet-BP396 17,18,19,20 Ethernet-BP396 Eth3-ASIC3
|
Ethernet-BP396 17,18,19,20 Ethernet-BP396 19 Eth3-ASIC3 Int
|
||||||
Ethernet-BP400 13,14,15,16 Ethernet-BP400 Eth4-ASIC3
|
Ethernet-BP400 13,14,15,16 Ethernet-BP400 20 Eth4-ASIC3 Int
|
||||||
Ethernet-BP404 9,10,11,12 Ethernet-BP404 Eth5-ASIC3
|
Ethernet-BP404 9,10,11,12 Ethernet-BP404 21 Eth5-ASIC3 Int
|
||||||
Ethernet-BP408 5,6,7,8 Ethernet-BP408 Eth6-ASIC3
|
Ethernet-BP408 5,6,7,8 Ethernet-BP408 22 Eth6-ASIC3 Int
|
||||||
Ethernet-BP412 1,2,3,4 Ethernet-BP412 Eth7-ASIC3
|
Ethernet-BP412 1,2,3,4 Ethernet-BP412 23 Eth7-ASIC3 Int
|
@ -158,6 +158,19 @@ class TestMultiNpuCfgGen(TestCase):
|
|||||||
self.assertListEqual(output.keys(), \
|
self.assertListEqual(output.keys(), \
|
||||||
['PortChannel4013', 'PortChannel4013|10.1.0.2/31', 'PortChannel4014', 'PortChannel4014|10.1.0.6/31'])
|
['PortChannel4013', 'PortChannel4013|10.1.0.2/31', 'PortChannel4014', 'PortChannel4014|10.1.0.6/31'])
|
||||||
|
|
||||||
|
def test_frontend_asic_ports(self):
|
||||||
|
argument = "-m {} -p {} -n asic0 --var-json \"PORT\"".format(self.sample_graph, self.port_config[0])
|
||||||
|
output = json.loads(self.run_script(argument))
|
||||||
|
self.assertDictEqual(output, \
|
||||||
|
{"Ethernet0": { "admin_status": "up", "alias": "Ethernet1/1", "asic_port_name": "Eth0-ASIC0", "description": "01T2:Ethernet1", "index": "0", "lanes": "33,34,35,36", "mtu": "9100", "pfc_asym": "off", "role": "Ext", "speed": "40000" },
|
||||||
|
"Ethernet4": { "admin_status": "up", "alias": "Ethernet1/2", "asic_port_name": "Eth1-ASIC0", "description": "01T2:Ethernet2", "index": "1", "lanes": "29,30,31,32", "mtu": "9100", "pfc_asym": "off", "role": "Ext", "speed": "40000" },
|
||||||
|
"Ethernet8": { "alias": "Ethernet1/3", "asic_port_name": "Eth2-ASIC0", "description": "Ethernet1/3", "index": "2", "lanes": "41,42,43,44", "mtu": "9100", "pfc_asym": "off", "role": "Ext", "speed": "40000" },
|
||||||
|
"Ethernet12": { "alias": "Ethernet1/4", "asic_port_name": "Eth3-ASIC0", "description": "Ethernet1/4", "index": "3", "lanes": "37,38,39,40", "mtu": "9100", "pfc_asym": "off", "role": "Ext", "speed": "40000" },
|
||||||
|
"Ethernet-BP0": { "admin_status": "up", "alias": "Ethernet-BP0", "asic_port_name": "Eth4-ASIC0", "description": "ASIC2:Eth0-ASIC2", "index": "0", "lanes": "13,14,15,16", "mtu": "9100", "pfc_asym": "off", "role": "Int", "speed": "40000" },
|
||||||
|
"Ethernet-BP4": { "admin_status": "up", "alias": "Ethernet-BP4", "asic_port_name": "Eth5-ASIC0", "description": "ASIC2:Eth1-ASIC2", "index": "1", "lanes": "17,18,19,20", "mtu": "9100", "pfc_asym": "off", "role": "Int", "speed": "40000" },
|
||||||
|
"Ethernet-BP8": { "admin_status": "up", "alias": "Ethernet-BP8", "asic_port_name": "Eth6-ASIC0", "description": "ASIC3:Eth0-ASIC3", "index": "2", "lanes": "21,22,23,24", "mtu": "9100", "pfc_asym": "off", "role": "Int", "speed": "40000" },
|
||||||
|
"Ethernet-BP12": { "admin_status": "up", "alias": "Ethernet-BP12", "asic_port_name": "Eth7-ASIC0", "description": "ASIC3:Eth1-ASIC3", "index": "3", "lanes": "25,26,27,28", "mtu": "9100", "pfc_asym": "off", "role": "Int", "speed": "40000" }})
|
||||||
|
|
||||||
def test_frontend_asic_device_neigh(self):
|
def test_frontend_asic_device_neigh(self):
|
||||||
argument = "-m {} -p {} -n asic0 --var-json \"DEVICE_NEIGHBOR\"".format(self.sample_graph, self.port_config[0])
|
argument = "-m {} -p {} -n asic0 --var-json \"DEVICE_NEIGHBOR\"".format(self.sample_graph, self.port_config[0])
|
||||||
output = json.loads(self.run_script(argument))
|
output = json.loads(self.run_script(argument))
|
||||||
|
300
src/sonic-py-common/sonic_py_common/multi_asic.py
Normal file
300
src/sonic-py-common/sonic_py_common/multi_asic.py
Normal file
@ -0,0 +1,300 @@
|
|||||||
|
import glob
|
||||||
|
import os
|
||||||
|
|
||||||
|
from natsort import natsorted
|
||||||
|
from swsssdk import ConfigDBConnector
|
||||||
|
from swsssdk import SonicDBConfig
|
||||||
|
from swsssdk import SonicV2Connector
|
||||||
|
|
||||||
|
from .device_info import CONTAINER_PLATFORM_PATH
|
||||||
|
from .device_info import HOST_DEVICE_PATH
|
||||||
|
from .device_info import get_platform
|
||||||
|
|
||||||
|
ASIC_NAME_PREFIX = 'asic'
|
||||||
|
NAMESPACE_PATH_GLOB = '/run/netns/*'
|
||||||
|
ASIC_CONF_FILENAME = 'asic.conf'
|
||||||
|
FRONTEND_ASIC_SUB_ROLE = 'FrontEnd'
|
||||||
|
BACKEND_ASIC_SUB_ROLE = 'BackEnd'
|
||||||
|
EXTERNAL_PORT = 'Ext'
|
||||||
|
INTERNAL_PORT = 'Int'
|
||||||
|
PORT_CHANNEL_CFG_DB_TABLE = 'PORTCHANNEL'
|
||||||
|
PORT_CFG_DB_TABLE = 'PORT'
|
||||||
|
BGP_NEIGH_CFG_DB_TABLE = 'BGP_NEIGHBOR'
|
||||||
|
NEIGH_DEVICE_METADATA_CFG_DB_TABLE = 'DEVICE_NEIGHBOR_METADATA'
|
||||||
|
DEFAULT_NAMESPACE = ''
|
||||||
|
PORT_ROLE = 'role'
|
||||||
|
|
||||||
|
|
||||||
|
def connect_config_db_for_ns(namespace=DEFAULT_NAMESPACE):
|
||||||
|
"""
|
||||||
|
The function connects to the config DB for a given namespace and
|
||||||
|
returns the handle
|
||||||
|
If no namespace is provided, it will connect to the db in the
|
||||||
|
default namespace.
|
||||||
|
In case of multi ASIC, the default namespace is the database
|
||||||
|
instance running the on the host
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
handle to the config_db for a namespace
|
||||||
|
"""
|
||||||
|
SonicDBConfig.load_sonic_global_db_config()
|
||||||
|
config_db = ConfigDBConnector(namespace=namespace)
|
||||||
|
config_db.connect()
|
||||||
|
return config_db
|
||||||
|
|
||||||
|
|
||||||
|
def connect_to_all_dbs_for_ns(namespace=DEFAULT_NAMESPACE):
|
||||||
|
"""
|
||||||
|
The function connects to the DBs for a given namespace and
|
||||||
|
returns the handle
|
||||||
|
If no namespace is provided, it will connect to the db in the
|
||||||
|
default namespace.
|
||||||
|
In case of multi ASIC, the default namespace is the
|
||||||
|
database instance running the on the host
|
||||||
|
In case of single ASIC, the namespace has to be DEFAULT_NAMESPACE
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
handle to all the dbs for a namespaces
|
||||||
|
"""
|
||||||
|
SonicDBConfig.load_sonic_global_db_config()
|
||||||
|
db = SonicV2Connector(namespace=namespace)
|
||||||
|
for db_id in db.get_db_list():
|
||||||
|
db.connect(db_id)
|
||||||
|
return db
|
||||||
|
|
||||||
|
|
||||||
|
def get_asic_conf_file_path():
|
||||||
|
"""
|
||||||
|
Retrieves the path to the ASIC conguration file on the device
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A string containing the path to the ASIC conguration file on success,
|
||||||
|
None on failure
|
||||||
|
"""
|
||||||
|
asic_conf_path_candidates = []
|
||||||
|
|
||||||
|
asic_conf_path_candidates.append(os.path.join(CONTAINER_PLATFORM_PATH,
|
||||||
|
ASIC_CONF_FILENAME))
|
||||||
|
|
||||||
|
platform = get_platform()
|
||||||
|
if platform:
|
||||||
|
asic_conf_path_candidates.append(os.path.join(
|
||||||
|
HOST_DEVICE_PATH, platform, ASIC_CONF_FILENAME))
|
||||||
|
|
||||||
|
for asic_conf_file_path in asic_conf_path_candidates:
|
||||||
|
if os.path.isfile(asic_conf_file_path):
|
||||||
|
return asic_conf_file_path
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def get_num_asics():
|
||||||
|
"""
|
||||||
|
Retrieves the num of asics present in the multi ASIC platform
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Num of asics
|
||||||
|
"""
|
||||||
|
asic_conf_file_path = get_asic_conf_file_path()
|
||||||
|
|
||||||
|
if asic_conf_file_path is None:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
with open(asic_conf_file_path) as asic_conf_file:
|
||||||
|
for line in asic_conf_file:
|
||||||
|
tokens = line.split('=')
|
||||||
|
if len(tokens) < 2:
|
||||||
|
continue
|
||||||
|
if tokens[0].lower() == 'num_asic':
|
||||||
|
num_asics = tokens[1].strip()
|
||||||
|
return int(num_asics)
|
||||||
|
|
||||||
|
|
||||||
|
def is_multi_asic():
|
||||||
|
"""
|
||||||
|
Checks if the device is multi asic or not
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
True: if the num of asic is more than 1
|
||||||
|
"""
|
||||||
|
num_asics = get_num_asics()
|
||||||
|
|
||||||
|
return (num_asics > 1)
|
||||||
|
|
||||||
|
|
||||||
|
def get_asic_id_from_name(asic_name):
|
||||||
|
|
||||||
|
if asic_name.startswith(ASIC_NAME_PREFIX):
|
||||||
|
return asic_name[len(ASIC_NAME_PREFIX):]
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def get_namespaces_from_linux():
|
||||||
|
"""
|
||||||
|
In a multi asic platform, each ASIC is in a Linux Namespace.
|
||||||
|
This method returns list of all the Namespace present on the device
|
||||||
|
|
||||||
|
Note: It is preferable to use this function can be used only
|
||||||
|
when the config_db is not available.
|
||||||
|
When configdb is available use get_all_namespaces()
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
List of the namespaces present in the system
|
||||||
|
"""
|
||||||
|
ns_list = []
|
||||||
|
for path in glob.glob(NAMESPACE_PATH_GLOB):
|
||||||
|
ns = os.path.basename(path)
|
||||||
|
ns_list.append(ns)
|
||||||
|
return natsorted(ns_list)
|
||||||
|
|
||||||
|
|
||||||
|
def get_all_namespaces():
|
||||||
|
"""
|
||||||
|
In case of Multi-Asic platform, Each ASIC will have a linux network namespace created.
|
||||||
|
So we loop through the databases in different namespaces and depending on the sub_role
|
||||||
|
decide whether this is a front end ASIC/namespace or a back end one.
|
||||||
|
"""
|
||||||
|
front_ns = []
|
||||||
|
back_ns = []
|
||||||
|
num_asics = get_num_asics()
|
||||||
|
|
||||||
|
if is_multi_asic():
|
||||||
|
for asic in range(num_asics):
|
||||||
|
namespace = "{}{}".format(ASIC_NAME_PREFIX, asic)
|
||||||
|
config_db = connect_config_db_for_ns(namespace)
|
||||||
|
|
||||||
|
metadata = config_db.get_table('DEVICE_METADATA')
|
||||||
|
if metadata['localhost']['sub_role'] == FRONTEND_ASIC_SUB_ROLE:
|
||||||
|
front_ns.append(namespace)
|
||||||
|
elif metadata['localhost']['sub_role'] == BACKEND_ASIC_SUB_ROLE:
|
||||||
|
back_ns.append(namespace)
|
||||||
|
|
||||||
|
return {'front_ns': front_ns, 'back_ns': back_ns}
|
||||||
|
|
||||||
|
|
||||||
|
def get_namespace_list(namespace=None):
|
||||||
|
if not is_multi_asic():
|
||||||
|
ns_list = [DEFAULT_NAMESPACE]
|
||||||
|
return ns_list
|
||||||
|
|
||||||
|
if namespace is None:
|
||||||
|
# there are few commands that needs to work even if the
|
||||||
|
# config db is not present. So get the namespaces
|
||||||
|
# list from linux
|
||||||
|
ns_list = get_namespaces_from_linux()
|
||||||
|
else:
|
||||||
|
ns_list = [namespace]
|
||||||
|
|
||||||
|
return ns_list
|
||||||
|
|
||||||
|
|
||||||
|
def get_port_table(namespace=None):
|
||||||
|
"""
|
||||||
|
Retrieves the ports from all the asic present on the devices
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
a dict of all the ports
|
||||||
|
"""
|
||||||
|
all_ports = {}
|
||||||
|
ns_list = get_namespace_list(namespace)
|
||||||
|
|
||||||
|
for ns in ns_list:
|
||||||
|
ports = get_port_table_for_asic(ns)
|
||||||
|
all_ports.update(ports)
|
||||||
|
|
||||||
|
return all_ports
|
||||||
|
|
||||||
|
|
||||||
|
def get_port_table_for_asic(namespace):
|
||||||
|
|
||||||
|
config_db = connect_config_db_for_ns(namespace)
|
||||||
|
ports = config_db.get_table(PORT_CFG_DB_TABLE)
|
||||||
|
return ports
|
||||||
|
|
||||||
|
|
||||||
|
def get_namespace_for_port(port_name):
|
||||||
|
|
||||||
|
ns_list = get_namespace_list()
|
||||||
|
port_namespace = None
|
||||||
|
|
||||||
|
for ns in ns_list:
|
||||||
|
ports = get_port_table_for_asic(ns)
|
||||||
|
if port_name in ports:
|
||||||
|
port_namespace = ns
|
||||||
|
break
|
||||||
|
|
||||||
|
if port_namespace is None:
|
||||||
|
raise ValueError('Unknown port name {}'.format(port_name))
|
||||||
|
|
||||||
|
return port_namespace
|
||||||
|
|
||||||
|
|
||||||
|
def get_port_role(port_name, namespace=None):
|
||||||
|
|
||||||
|
ports_config = get_port_table(namespace)
|
||||||
|
if port_name not in ports_config:
|
||||||
|
raise ValueError('Unknown port name {}'.format(port_name))
|
||||||
|
|
||||||
|
if PORT_ROLE not in ports_config[port_name]:
|
||||||
|
return EXTERNAL_PORT
|
||||||
|
|
||||||
|
role = ports_config[port_name][PORT_ROLE]
|
||||||
|
return role
|
||||||
|
|
||||||
|
|
||||||
|
def is_port_internal(port_name, namespace=None):
|
||||||
|
|
||||||
|
role = get_port_role(port_name, namespace)
|
||||||
|
|
||||||
|
if role == INTERNAL_PORT:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def is_port_channel_internal(port_channel, namespace=None):
|
||||||
|
|
||||||
|
if not is_multi_asic():
|
||||||
|
return False
|
||||||
|
|
||||||
|
ns_list = get_namespace_list(namespace)
|
||||||
|
|
||||||
|
for ns in ns_list:
|
||||||
|
config_db = connect_config_db_for_ns(ns)
|
||||||
|
port_channels = config_db.get_table(PORT_CHANNEL_CFG_DB_TABLE)
|
||||||
|
|
||||||
|
if port_channel in port_channels:
|
||||||
|
if 'members' in port_channel:
|
||||||
|
members = port_channels[port_channel]['members']
|
||||||
|
if is_port_internal(members[0], namespace):
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def is_bgp_session_internal(bgp_neigh_ip, namespace=None):
|
||||||
|
|
||||||
|
if not is_multi_asic():
|
||||||
|
return False
|
||||||
|
|
||||||
|
ns_list = get_namespace_list(namespace)
|
||||||
|
|
||||||
|
for ns in ns_list:
|
||||||
|
|
||||||
|
config_db = connect_config_db_for_ns(ns)
|
||||||
|
bgp_sessions = config_db.get_table(BGP_NEIGH_CFG_DB_TABLE)
|
||||||
|
if bgp_neigh_ip not in bgp_sessions:
|
||||||
|
continue
|
||||||
|
|
||||||
|
bgp_neigh_name = bgp_sessions[bgp_neigh_ip]['name']
|
||||||
|
neighbor_metadata = config_db.get_table(
|
||||||
|
NEIGH_DEVICE_METADATA_CFG_DB_TABLE)
|
||||||
|
|
||||||
|
if ((neighbor_metadata) and
|
||||||
|
(neighbor_metadata[bgp_neigh_name]['type'].lower() ==
|
||||||
|
ASIC_NAME_PREFIX)):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
return False
|
Loading…
Reference in New Issue
Block a user