From 17b3c9046219bcac9efe75c2e6cb68d90645158d Mon Sep 17 00:00:00 2001 From: twtseng-tim <59221293+twtseng-tim@users.noreply.github.com> Date: Tue, 9 Apr 2024 09:51:58 +0800 Subject: [PATCH 1/3] Support pvid get --- src/sonic_ax_impl/mibs/ietf/rfc4363.py | 81 ++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/src/sonic_ax_impl/mibs/ietf/rfc4363.py b/src/sonic_ax_impl/mibs/ietf/rfc4363.py index 560e4a524..e90280de0 100644 --- a/src/sonic_ax_impl/mibs/ietf/rfc4363.py +++ b/src/sonic_ax_impl/mibs/ietf/rfc4363.py @@ -132,12 +132,93 @@ def get_next(self, sub_id): return self.vlanmac_ifindex_list[right] +class Dot1qPortUpdater(MIBUpdater): + def __init__(self): + super().__init__() + self.db_conn = Namespace.init_namespace_dbs() + + self.if_name_map = {} + self.if_alias_map = {} + self.if_id_map = {} + self.oid_name_map = {} + self.sai_lag_map = {} + self.ifindex_pvid_map = {} + self.ifindex_pvid_list = [] + + def reinit_data(self): + """ + Subclass update interface information + """ + ( + self.if_name_map, + self.if_alias_map, + self.if_id_map, + self.oid_name_map, + ) = Namespace.get_sync_d_from_all_namespace( + mibs.init_sync_d_interface_tables, self.db_conn + ) + + self.lag_name_if_name_map, \ + self.if_name_lag_name_map, \ + self.oid_lag_name_map, \ + _, self.sai_lag_map = Namespace.get_sync_d_from_all_namespace(mibs.init_sync_d_lag_tables, self.db_conn) + + + def update_data(self): + """ + Update redis (caches config) + Pulls the table references for each interface. + """ + self.ifindex_pvid_map = {} + self.ifindex_pvid_list = [] + + vlan_member_strings = Namespace.dbs_keys(self.db_conn, mibs.CONFIG_DB, "VLAN_MEMBER|*") + if not vlan_member_strings: + return + + for s in vlan_member_strings: + vlan_member = s + + try: + _, vlan_id, port_name = s.split("|", maxsplit=2) + vlan_id = int(vlan_id.split("Vlan")[1]) + port_index = (mibs.get_index_from_str(port_name),) + except ValueError as e: # includes simplejson.decoder.JSONDecodeError + mibs.logger.error("'CONFIG_DB' includes invalid Vlan member: {}.".format(s)) + continue + + ent = Namespace.dbs_get_all(self.db_conn, mibs.CONFIG_DB, s, blocking=True) + untagged = ent["tagging_mode"] == "untagged" + if untagged: + self.ifindex_pvid_map[port_index] = vlan_id + mibs.logger.info("vid = {}".format(vlan_id)) + else: + if port_index not in self.ifindex_pvid_map.keys(): + self.ifindex_pvid_map[port_index] = 0 + + self.ifindex_pvid_list.append(port_index) + self.ifindex_pvid_list.sort() + + def port_vid(self, sub_id): + return self.ifindex_pvid_map.get(sub_id, None) + + def get_next(self, sub_id): + right = bisect_right(self.ifindex_pvid_list, sub_id) + if right >= len(self.ifindex_pvid_list): + return None + + return self.ifindex_pvid_list[right] + class QBridgeMIBObjects(metaclass=MIBMeta, prefix='.1.3.6.1.2.1.17.7.1'): """ 'Forwarding Database' https://tools.ietf.org/html/rfc4363 """ fdb_updater = FdbUpdater() + dot1q_port_updater = Dot1qPortUpdater() dot1qTpFdbPort = \ SubtreeMIBEntry('2.2.1.2', fdb_updater, ValueType.INTEGER, fdb_updater.fdb_ifindex) + + dot1qPvid = \ + SubtreeMIBEntry('4.5.1.1', dot1q_port_updater, ValueType.INTEGER, dot1q_port_updater.port_vid) From c28aa4c8eec2ee10eb5e021a965ae6f1d5284b9f Mon Sep 17 00:00:00 2001 From: twtseng-tim <59221293+twtseng-tim@users.noreply.github.com> Date: Tue, 9 Apr 2024 10:35:06 +0800 Subject: [PATCH 2/3] Add mock file for testing pvid get --- tests/mock_tables/config_db.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/mock_tables/config_db.json b/tests/mock_tables/config_db.json index 2d9dd54e0..07030682d 100644 --- a/tests/mock_tables/config_db.json +++ b/tests/mock_tables/config_db.json @@ -18,5 +18,11 @@ "DEVICE_METADATA|localhost": { "chassis_serial_number": "SAMPLETESTSN", "hostname" : "test_hostname" + }, + "VLAN_MEMBER|Vlan10|Ethernet10": { + "tagging_mode": "untagged" + }, + "VLAN_MEMBER|Vlan10|PortChannel1": { + "tagging_mode": "untagged" } } From c76f22f3946cd9bb72ee3dade3fcf0f78cfedbf9 Mon Sep 17 00:00:00 2001 From: twtseng-tim <59221293+twtseng-tim@users.noreply.github.com> Date: Tue, 9 Apr 2024 10:41:34 +0800 Subject: [PATCH 3/3] Add unit test for getting pvid --- tests/namespace/test_dot1q_port.py | 127 +++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 tests/namespace/test_dot1q_port.py diff --git a/tests/namespace/test_dot1q_port.py b/tests/namespace/test_dot1q_port.py new file mode 100644 index 000000000..76b89879a --- /dev/null +++ b/tests/namespace/test_dot1q_port.py @@ -0,0 +1,127 @@ +import os +import sys + +modules_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, os.path.join(modules_path, 'src')) + +from unittest import TestCase + +# noinspection PyUnresolvedReferences +import tests.mock_tables.dbconnector + +from ax_interface.mib import MIBTable +from ax_interface.pdu import PDUHeader +from ax_interface.pdu_implementations import GetPDU, GetNextPDU +from ax_interface import ValueType +from ax_interface.encodings import ObjectIdentifier +from ax_interface.constants import PduTypes +from sonic_ax_impl.mibs.ietf import rfc4363 +from sonic_ax_impl.main import SonicMIB +from swsssdk.port_util import BaseIdx + +class TestSonicMIB(TestCase): + @classmethod + def setUpClass(cls): + cls.lut = MIBTable(SonicMIB) + for updater in cls.lut.updater_instances: + updater.update_data() + updater.reinit_data() + updater.update_data() + + def test_getpdu(self): + oid = ObjectIdentifier(20, 0, 0, 0, (1, 3, 6, 1, 2, 1, 17, 7, 1, 4, 5, 1, 1, 11)) + get_pdu = GetPDU( + header=PDUHeader(1, PduTypes.GET, 16, 0, 42, 0, 0, 0), + oids=[oid] + ) + + encoded = get_pdu.encode() + response = get_pdu.make_response(self.lut) + print(response) + + value0 = response.values[0] + self.assertEqual(value0.type_, ValueType.INTEGER) + self.assertEqual(str(value0.name), str(oid)) + self.assertEqual(value0.data, 10) + + def test_getnextpdu(self): + get_pdu = GetNextPDU( + header=PDUHeader(1, PduTypes.GET, 16, 0, 42, 0, 0, 0), + oids=( + ObjectIdentifier(20, 0, 0, 0, (1, 3, 6, 1, 2, 1, 17, 7, 1, 4, 5, 1, 1, 10)), + ) + ) + + encoded = get_pdu.encode() + response = get_pdu.make_response(self.lut) + print(response) + + n = len(response.values) + value0 = response.values[0] + self.assertEqual(value0.type_, ValueType.INTEGER) + self.assertEqual(value0.data, 10) + + def test_getnextpdu_lag(self): + get_pdu = GetNextPDU( + header=PDUHeader(1, PduTypes.GET, 16, 0, 42, 0, 0, 0), + oids=( + ObjectIdentifier(20, 0, 0, 0, (1, 3, 6, 1, 2, 1, 17, 7, 1, 4, 5, 1, 1, 1000)), + ) + ) + + response = get_pdu.make_response(self.lut) + + value0 = response.values[0] + self.assertEqual(value0.type_, ValueType.INTEGER) + self.assertEqual(value0.data, 10) + + def test_getnextpdu_exactmatch(self): + # oid.include = 1 + oid = ObjectIdentifier(20, 0, 1, 0, (1, 3, 6, 1, 2, 1, 17, 7, 1, 4, 5, 1, 1, 11)) + get_pdu = GetNextPDU( + header=PDUHeader(1, PduTypes.GET, 16, 0, 42, 0, 0, 0), + oids=[oid] + ) + + encoded = get_pdu.encode() + response = get_pdu.make_response(self.lut) + print(response) + + n = len(response.values) + value0 = response.values[0] + self.assertEqual(value0.type_, ValueType.INTEGER) + print("test_getnextpdu_exactmatch: ", str(oid)) + self.assertEqual(str(value0.name), str(oid)) + self.assertEqual(value0.data, 10) + + def test_getpdu_noinstance(self): + get_pdu = GetPDU( + header=PDUHeader(1, PduTypes.GET, 16, 0, 42, 0, 0, 0), + oids=( + ObjectIdentifier(20, 0, 0, 0, (1, 3, 6, 1, 2, 1, 17, 7, 1, 4, 5, 1, 1, 100)), + ) + ) + + encoded = get_pdu.encode() + response = get_pdu.make_response(self.lut) + print(response) + + n = len(response.values) + value0 = response.values[0] + self.assertEqual(value0.type_, ValueType.NO_SUCH_INSTANCE) + + def test_getnextpdu_empty(self): + get_pdu = GetNextPDU( + header=PDUHeader(1, PduTypes.GET, 16, 0, 42, 0, 0, 0), + oids=( + ObjectIdentifier(20, 0, 0, 0, (1, 3, 6, 1, 2, 1, 17, 7, 1, 4, 5, 1, 2)), + ) + ) + + encoded = get_pdu.encode() + response = get_pdu.make_response(self.lut) + print(response) + + n = len(response.values) + value0 = response.values[0] + self.assertEqual(value0.type_, ValueType.END_OF_MIB_VIEW)