Skip to content

Commit

Permalink
[Multi-asic]: Namespace support for LLDP and Sensor tables (#131)
Browse files Browse the repository at this point in the history
* Changes in below MIB tables implementation to support multi-asic platform:
LLDPRemManAddrTable
PhysicalTableMIB
PhysicalSensorTableMIB
QBridgeMIBObjects
* Fix LGTM errors.
* Fix merge conflicts and fix function names as per review comment.
  • Loading branch information
SuvarnaMeenakshi authored May 29, 2020
1 parent fcb8955 commit 89b7b2c
Show file tree
Hide file tree
Showing 9 changed files with 635 additions and 66 deletions.
19 changes: 19 additions & 0 deletions src/sonic_ax_impl/mibs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -571,3 +571,22 @@ def init_namespace_sync_d_queue_tables(dbs):
port_queue_list_map.update(port_queue_list_map_ns)

return port_queues_map, queue_stat_map, port_queue_list_map

@staticmethod
def dbs_get_bridge_port_map(dbs, db_name):
"""
get_bridge_port_map from all namespace DBs
"""
if_br_oid_map = {}
for db_conn in Namespace.get_non_host_dbs(dbs):
if_br_oid_map_ns = port_util.get_bridge_port_map(db_conn)
if_br_oid_map.update(if_br_oid_map_ns)
return if_br_oid_map

@staticmethod
def dbs_get_vlan_id_from_bvid(dbs, bvid):
for db_conn in Namespace.get_non_host_dbs(dbs):
db_conn.connect('ASIC_DB')
vlan_obj = db.keys('ASIC_DB', "ASIC_STATE:SAI_OBJECT_TYPE_VLAN:" + bvid)
if vlan_obj is not None:
return port_util.get_vlan_id_from_bvid(db_conn, bvid)
81 changes: 45 additions & 36 deletions src/sonic_ax_impl/mibs/ieee802_1ab.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

from swsssdk import port_util
from sonic_ax_impl import mibs, logger
from sonic_ax_impl.mibs import Namespace
from ax_interface import MIBMeta, SubtreeMIBEntry, MIBEntry, MIBUpdater, ValueType


Expand Down Expand Up @@ -102,16 +103,16 @@ class LLDPLocalSystemDataUpdater(MIBUpdater):
def __init__(self):
super().__init__()

self.db_conn = mibs.init_db()
self.db_conn = Namespace.init_namespace_dbs()
self.loc_chassis_data = {}

def reinit_data(self):
"""
Subclass update data routine.
"""
# establish connection to application database.
self.db_conn.connect(mibs.APPL_DB)
self.loc_chassis_data = self.db_conn.get_all(mibs.APPL_DB, mibs.LOC_CHASSIS_TABLE)
Namespace.connect_all_dbs(self.db_conn, mibs.APPL_DB)
self.loc_chassis_data = Namespace.dbs_get_all(self.db_conn, mibs.APPL_DB, mibs.LOC_CHASSIS_TABLE)
self.loc_chassis_data[b'lldp_loc_sys_cap_supported'] = parse_sys_capability(self.loc_chassis_data[b'lldp_loc_sys_cap_supported'])
self.loc_chassis_data[b'lldp_loc_sys_cap_enabled'] = parse_sys_capability(self.loc_chassis_data[b'lldp_loc_sys_cap_enabled'])
def update_data(self):
Expand Down Expand Up @@ -139,9 +140,9 @@ class LocPortUpdater(MIBUpdater):
def __init__(self):
super().__init__()

self.db_conn = mibs.init_db()
self.db_conn = Namespace.init_namespace_dbs()
# establish connection to application database.
self.db_conn.connect(mibs.APPL_DB)
Namespace.connect_all_dbs(self.db_conn, mibs.APPL_DB)
self.if_name_map = {}
self.if_alias_map = {}
self.if_id_map = {}
Expand All @@ -156,7 +157,7 @@ def __init__(self):
# cache of port data
# { if_name -> { 'key': 'value' } }
self.loc_port_data = {}
self.pubsub = None
self.pubsub = [None] * len(self.db_conn)

def reinit_data(self):
"""
Expand All @@ -166,10 +167,10 @@ def reinit_data(self):
self.if_alias_map, \
self.if_id_map, \
self.oid_sai_map, \
self.oid_name_map = mibs.init_sync_d_interface_tables(self.db_conn)
self.oid_name_map = Namespace.init_namespace_sync_d_interface_tables(self.db_conn)

self.mgmt_oid_name_map, \
self.mgmt_alias_map = mibs.init_mgmt_interface_tables(self.db_conn)
self.mgmt_alias_map = mibs.init_mgmt_interface_tables(self.db_conn[0])

# merge dataplane and mgmt ports
self.oid_name_map.update(self.mgmt_oid_name_map)
Expand Down Expand Up @@ -199,7 +200,7 @@ def _get_if_entry(self, if_name):
else:
return None

return self.db_conn.get_all(db, if_table, blocking=True)
return Namespace.dbs_get_all(self.db_conn, db, if_table, blocking=True)

def update_interface_data(self, if_name):
"""
Expand All @@ -221,25 +222,29 @@ def get_next(self, sub_id):
return None
return self.if_range[right]

def update_data(self):
def _update_per_namespace_data(self, db_conn, pubsub):
"""
Listen to updates in APP DB, update local cache
"""
if not self.pubsub:
redis_client = self.db_conn.get_redis_client(self.db_conn.APPL_DB)
db = self.db_conn.get_dbid(self.db_conn.APPL_DB)
self.pubsub = redis_client.pubsub()
self.pubsub.psubscribe("__keyspace@{}__:{}".format(db, mibs.lldp_entry_table(b'*')))
if not pubsub:
redis_client = db_conn.get_redis_client(db_conn.APPL_DB)
db = db_conn.get_dbid(db_conn.APPL_DB)
pubsub = redis_client.pubsub()
pubsub.psubscribe("__keyspace@{}__:{}".format(db, mibs.lldp_entry_table(b'*')))

while True:
data, interface, if_id = poll_lldp_entry_updates(self.pubsub)
data, interface, if_id = poll_lldp_entry_updates(pubsub)

if not data:
break

if b"set" in data:
self.update_interface_data(interface.encode())

def update_data(self):
for i in range(len(self.db_conn)):
self._update_per_namespace_data(self.db_conn[i], self.pubsub[i])

def local_port_num(self, sub_id):
if len(sub_id) == 0:
return None
Expand Down Expand Up @@ -302,7 +307,7 @@ def reinit_data(self):
self.mgmt_ip_str = None

# establish connection to application database.
self.db_conn.connect(mibs.APPL_DB)
self.db_conn.connect(mibs.APPL_DB)
mgmt_ip_bytes = self.db_conn.get(mibs.APPL_DB, mibs.LOC_CHASSIS_TABLE, b'lldp_loc_man_addr')

if not mgmt_ip_bytes:
Expand Down Expand Up @@ -377,7 +382,7 @@ class LLDPRemTableUpdater(MIBUpdater):
def __init__(self):
super().__init__()

self.db_conn = mibs.init_db()
self.db_conn = Namespace.init_namespace_dbs()
self.if_name_map = {}
self.if_alias_map = {}
self.if_id_map = {}
Expand All @@ -400,9 +405,9 @@ def reinit_data(self):
self.if_alias_map, \
self.if_id_map, \
self.oid_sai_map, \
self.oid_name_map = mibs.init_sync_d_interface_tables(self.db_conn)
self.oid_name_map = Namespace.init_namespace_sync_d_interface_tables(self.db_conn)

self.mgmt_oid_name_map, _ = mibs.init_mgmt_interface_tables(self.db_conn)
self.mgmt_oid_name_map, _ = mibs.init_mgmt_interface_tables(self.db_conn[0])

self.oid_name_map.update(self.mgmt_oid_name_map)

Expand All @@ -421,12 +426,11 @@ def update_data(self):
Subclass update data routine. Updates available LLDP counters.
"""
# establish connection to application database.
self.db_conn.connect(mibs.APPL_DB)

self.if_range = []
self.lldp_counters = {}
for if_oid, if_name in self.oid_name_map.items():
lldp_kvs = self.db_conn.get_all(mibs.APPL_DB, mibs.lldp_entry_table(if_name))
lldp_kvs = Namespace.dbs_get_all(self.db_conn, mibs.APPL_DB, mibs.lldp_entry_table(if_name))
if not lldp_kvs:
continue
try:
Expand Down Expand Up @@ -484,18 +488,18 @@ class LLDPRemManAddrUpdater(MIBUpdater):
def __init__(self):
super().__init__()

self.db_conn = mibs.init_db()
self.db_conn = Namespace.init_namespace_dbs()
# establish connection to application database.
self.db_conn.connect(self.db_conn.APPL_DB)
Namespace.connect_all_dbs(self.db_conn, mibs.APPL_DB)
self.if_range = []
self.mgmt_ips = {}
self.oid_name_map = {}
self.mgmt_oid_name_map = {}
self.mgmt_ip_str = None
self.pubsub = None
self.pubsub = [None] * len(self.db_conn)

def update_rem_if_mgmt(self, if_oid, if_name):
lldp_kvs = self.db_conn.get_all(mibs.APPL_DB, mibs.lldp_entry_table(if_name))
lldp_kvs = Namespace.dbs_get_all(self.db_conn, mibs.APPL_DB, mibs.lldp_entry_table(if_name))
if not lldp_kvs or b'lldp_rem_man_addr' not in lldp_kvs:
# this interfaces doesn't have remote lldp data, or the peer doesn't advertise his mgmt address
return
Expand Down Expand Up @@ -532,18 +536,18 @@ def update_rem_if_mgmt(self, if_oid, if_name):
return
self.if_range.sort()

def update_data(self):
def _update_per_namespace_data(self, db_conn, pubsub):
"""
Listen to updates in APP DB, update local cache
"""
if not self.pubsub:
redis_client = self.db_conn.get_redis_client(self.db_conn.APPL_DB)
db = self.db_conn.get_dbid(self.db_conn.APPL_DB)
self.pubsub = redis_client.pubsub()
self.pubsub.psubscribe("__keyspace@{}__:{}".format(db, mibs.lldp_entry_table(b'*')))
if not pubsub:
redis_client = db_conn.get_redis_client(db_conn.APPL_DB)
db = db_conn.get_dbid(db_conn.APPL_DB)
pubsub = redis_client.pubsub()
pubsub.psubscribe("__keyspace@{}__:{}".format(db, mibs.lldp_entry_table(b'*')))

while True:
data, interface, if_index = poll_lldp_entry_updates(self.pubsub)
data, interface, if_index = poll_lldp_entry_updates(pubsub)

if not data:
break
Expand All @@ -555,18 +559,23 @@ def update_data(self):
self.if_range = [sub_oid for sub_oid in self.if_range if sub_oid[0] != if_index]
self.update_rem_if_mgmt(if_index, interface.encode())

def update_data(self):
for i in range(len(self.db_conn)):
self._update_per_namespace_data(self.db_conn[i], self.pubsub[i])


def reinit_data(self):
"""
Subclass reinit data routine.
"""
_, _, _, _, self.oid_name_map = mibs.init_sync_d_interface_tables(self.db_conn)
_, _, _, _, self.oid_name_map = Namespace.init_namespace_sync_d_interface_tables(self.db_conn)

self.mgmt_oid_name_map, _ = mibs.init_mgmt_interface_tables(self.db_conn)
self.mgmt_oid_name_map, _ = mibs.init_mgmt_interface_tables(self.db_conn[0])

self.oid_name_map.update(self.mgmt_oid_name_map)

# establish connection to application database.
self.db_conn.connect(mibs.APPL_DB)
Namespace.connect_all_dbs(self.db_conn, mibs.APPL_DB)

self.if_range = []
self.mgmt_ips = {}
Expand Down
38 changes: 21 additions & 17 deletions src/sonic_ax_impl/mibs/ietf/rfc2737.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
from enum import Enum, unique
from bisect import bisect_right, insort_right

from swsssdk import SonicV2Connector, port_util
from swsssdk import port_util
from ax_interface import MIBMeta, MIBUpdater, ValueType, SubtreeMIBEntry

from sonic_ax_impl import mibs

from sonic_ax_impl.mibs import Namespace

@unique
class PhysicalClass(int, Enum):
Expand Down Expand Up @@ -120,8 +120,8 @@ class PhysicalTableMIBUpdater(MIBUpdater):
def __init__(self):
super().__init__()

self.statedb = SonicV2Connector()
self.statedb.connect(self.statedb.STATE_DB)
self.statedb = Namespace.init_namespace_dbs()
Namespace.connect_all_dbs(self.statedb, mibs.STATE_DB)

self.if_alias_map = {}

Expand All @@ -136,7 +136,7 @@ def __init__(self):
self.physical_mfg_name_map = {}
self.physical_model_name_map = {}

self.pubsub = None
self.pubsub = [None] * len(self.statedb)

def reinit_data(self):
"""
Expand All @@ -153,9 +153,9 @@ def reinit_data(self):

# update interface maps
_, self.if_alias_map, _, _, _ = \
mibs.init_sync_d_interface_tables(SonicV2Connector())
Namespace.init_namespace_sync_d_interface_tables(Namespace.init_namespace_dbs())

device_metadata = mibs.get_device_metadata(self.statedb)
device_metadata = mibs.get_device_metadata(self.statedb[0])
chassis_sub_id = (self.CHASSIS_ID, )
self.physical_entities = [chassis_sub_id]

Expand All @@ -168,7 +168,7 @@ def reinit_data(self):
self.physical_serial_number_map[chassis_sub_id] = chassis_serial_number

# retrieve the initial list of transceivers that are present in the system
transceiver_info = self.statedb.keys(self.statedb.STATE_DB, self.TRANSCEIVER_KEY_PATTERN)
transceiver_info = Namespace.dbs_keys(self.statedb, mibs.STATE_DB, self.TRANSCEIVER_KEY_PATTERN)
if transceiver_info:
self.transceiver_entries = [entry.decode() \
for entry in transceiver_info]
Expand All @@ -181,7 +181,7 @@ def reinit_data(self):
interface = transceiver_entry.split(mibs.TABLE_NAME_SEPARATOR_VBAR)[-1]
self._update_transceiver_cache(interface)

def update_data(self):
def _update_per_namespace_data(self, statedb, pubsub):
"""
Update cache.
Here we listen to changes in STATE_DB TRANSCEIVER_INFO table
Expand All @@ -190,14 +190,14 @@ def update_data(self):

# This code is not executed in unit test, since mockredis
# does not support pubsub
if not self.pubsub:
redis_client = self.statedb.get_redis_client(self.statedb.STATE_DB)
db = self.statedb.get_dbid(self.statedb.STATE_DB)
self.pubsub = redis_client.pubsub()
self.pubsub.psubscribe("__keyspace@{}__:{}".format(db, self.TRANSCEIVER_KEY_PATTERN))
if not pubsub:
redis_client = statedb.get_redis_client(statedb.STATE_DB)
db = statedb.get_dbid(statedb.STATE_DB)
pubsub = redis_client.pubsub()
pubsub.psubscribe("__keyspace@{}__:{}".format(db, self.TRANSCEIVER_KEY_PATTERN))

while True:
msg = self.pubsub.get_message()
msg = pubsub.get_message()

if not msg:
break
Expand Down Expand Up @@ -232,6 +232,10 @@ def update_data(self):
if sub_id and sub_id in self.physical_entities:
self.physical_entities.remove(sub_id)

def update_data(self):
for i in range(len(self.statedb)):
self._update_per_namespace_data(self.statedb[i], self.pubsub[i])

def _update_transceiver_cache(self, interface):
"""
Update data for single transceiver
Expand All @@ -249,7 +253,7 @@ def _update_transceiver_cache(self, interface):
insort_right(self.physical_entities, sub_id)

# get transceiver information from transceiver info entry in STATE DB
transceiver_info = self.statedb.get_all(self.statedb.STATE_DB,
transceiver_info = Namespace.dbs_get_all(self.statedb, mibs.STATE_DB,
mibs.transceiver_info_table(interface))

if not transceiver_info:
Expand Down Expand Up @@ -283,7 +287,7 @@ def _update_transceiver_sensor_cache(self, interface):
ifindex = port_util.get_index_from_str(interface)

# get transceiver sensors from transceiver dom entry in STATE DB
transceiver_dom_entry = self.statedb.get_all(self.statedb.STATE_DB,
transceiver_dom_entry = Namespace.dbs_get_all(self.statedb, mibs.STATE_DB,
mibs.transceiver_dom_table(interface))

if not transceiver_dom_entry:
Expand Down
Loading

0 comments on commit 89b7b2c

Please sign in to comment.