From 406ab264f244f473072244fe8e9234536e5a08e3 Mon Sep 17 00:00:00 2001 From: vkarri Date: Fri, 28 Jan 2022 19:50:20 +0000 Subject: [PATCH 1/8] Refactored modules and separated out common methods Signed-off-by: vkarri --- dump/helper.py | 5 ++- dump/match_helper.py | 90 +++++++++++++++++++++++++++++++++++++ dump/plugins/port.py | 15 ++----- dump/plugins/portchannel.py | 60 +++++-------------------- dump/plugins/vlan.py | 14 ++---- 5 files changed, 110 insertions(+), 74 deletions(-) create mode 100644 dump/match_helper.py diff --git a/dump/helper.py b/dump/helper.py index 7da893a464..3a882c0771 100644 --- a/dump/helper.py +++ b/dump/helper.py @@ -1,13 +1,16 @@ import os, sys, json + def create_template_dict(dbs): """ Generate a Template which will be returned by Executor Classes """ return {db: {'keys': [], 'tables_not_found': []} for db in dbs} + def verbose_print(str): if "VERBOSE" in os.environ and os.environ["VERBOSE"] == "1": print(str) + def handle_error(err_str, excep=False): """ Handles general error conditions, if any experienced by the module, @@ -17,7 +20,7 @@ def handle_error(err_str, excep=False): raise Exception("ERROR : {}".format(err_str)) else: print("ERROR : {}".format(err_str), file = sys.stderr) - + def handle_multiple_keys_matched_error(err_str, key_to_go_with="", excep=False): if excep: diff --git a/dump/match_helper.py b/dump/match_helper.py new file mode 100644 index 0000000000..17f2888c28 --- /dev/null +++ b/dump/match_helper.py @@ -0,0 +1,90 @@ +import os, sys, json +from dump.match_infra import MatchRequest +from dump.helper import create_template_dict + +# Port Helper Methods + +def fetch_port_oid(match_engine, port_name, ns): + """ + Fetches thr relevant SAI_OBJECT_TYPE_PORT given port name + """ + req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF", key_pattern="*", field="SAI_HOSTIF_ATTR_NAME", + value=port_name, return_fields=["SAI_HOSTIF_ATTR_OBJ_ID"], ns=ns) + ret = match_engine.fetch(req) + asic_port_obj_id = "" + if not ret["error"] and len(ret["keys"]) != 0: + sai_hostif_obj_key = ret["keys"][-1] + if sai_hostif_obj_key in ret["return_values"] and "SAI_HOSTIF_ATTR_OBJ_ID" in ret["return_values"][sai_hostif_obj_key]: + asic_port_obj_id = ret["return_values"][sai_hostif_obj_key]["SAI_HOSTIF_ATTR_OBJ_ID"] + return req, asic_port_obj_id, ret + +# Vlan Helper Methods + +def fetch_vlan_oid(match_engine, vlan_name, ns): + # Convert 'Vlanxxx' to 'xxx' + if vlan_name[0:4] != "Vlan" or not vlan_name[4:].isnumeric(): + vlan_num = -1 + else: + vlan_num = int(vlan_name[4:]) + + # Find the table named "ASIC_STATE:SAI_OBJECT_TYPE_VLAN:*" in which SAI_VLAN_ATTR_VLAN_ID = vlan_num + req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_VLAN", key_pattern="*", field="SAI_VLAN_ATTR_VLAN_ID", + value=str(vlan_num), ns=ns) + ret = match_engine.fetch(req) + vlan_oid = "" + if ret["keys"]: + vlan_oid = ret["keys"][0].split(":", 2)[-1] + return req, vlan_oid, ret + +# LAG Helper Methods + +def get_lag_members_from_cfg(match_engine, lag_name, ns): + """ + Get the members associated with a LAG from Config DB + """ + lag_members = [] + req = MatchRequest(db="CONFIG_DB", table="PORTCHANNEL_MEMBER", key_pattern=lag_name + "|*", ns=ns) + ret = match_engine.fetch(req) + for key in ret["keys"]: + lag_members.append(key.split("|")[-1]) + return req, lag_members, ret + +def get_lag_and_member_obj(match_engine, port_asic_obj, ns): + """ + Given the member port oid, fetch lag_member & lag oid's + """ + req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER", key_pattern="*", field="SAI_LAG_MEMBER_ATTR_PORT_ID", + value=port_asic_obj, return_fields=["SAI_LAG_MEMBER_ATTR_LAG_ID"], ns=ns) + ret = match_engine.fetch(req) + lag_member_key = "" + lag_oid = "" + if not ret["error"] and ret["keys"]: + lag_member_key = ret["keys"][-1] + if lag_member_key in ret["return_values"] and "SAI_LAG_MEMBER_ATTR_LAG_ID" in ret["return_values"][lag_member_key]: + lag_oid = ret["return_values"][lag_member_key]["SAI_LAG_MEMBER_ATTR_LAG_ID"] + return lag_member_key, lag_oid + +def fetch_lag_oid(match_engine, lag_members, ns): + """ + Finding the relevant SAI_OBJECT_TYPE_LAG key directly from the ASIC is not possible given a LAG name + Thus, using the members to find SAI_LAG_MEMBER_ATTR_LAG_ID + """ + lag_type_oid = set() + for port_name in lag_members: + print(port_name) + _, port_asic_obj, _ = fetch_port_oid(match_engine, port_name, ns) + if port_asic_obj: + lag_member_key, lag_oid = get_lag_and_member_obj(match_engine, port_asic_obj, ns) + lag_type_oid.add(lag_oid) + return "", lag_type_oid, "" + + + + + + + + + + + diff --git a/dump/plugins/port.py b/dump/plugins/port.py index f3f74897a3..2cffda2fd7 100644 --- a/dump/plugins/port.py +++ b/dump/plugins/port.py @@ -1,5 +1,6 @@ from dump.match_infra import MatchRequest from dump.helper import create_template_dict +from dump.match_helper import fetch_port_oid from .executor import Executor @@ -45,18 +46,8 @@ def init_state_port_info(self, port_name): self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) def init_asic_hostif_info(self, port_name): - req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF", key_pattern="*", field="SAI_HOSTIF_ATTR_NAME", - value=port_name, return_fields=["SAI_HOSTIF_ATTR_OBJ_ID"], ns=self.ns) - ret = self.match_engine.fetch(req) - asic_port_obj_id = "" - - if not ret["error"] and len(ret["keys"]) != 0: - self.ret_temp[req.db]["keys"] = ret["keys"] - sai_hostif_obj_key = ret["keys"][-1] - if sai_hostif_obj_key in ret["return_values"] and "SAI_HOSTIF_ATTR_OBJ_ID" in ret["return_values"][sai_hostif_obj_key]: - asic_port_obj_id = ret["return_values"][sai_hostif_obj_key]["SAI_HOSTIF_ATTR_OBJ_ID"] - else: - self.ret_temp[req.db]["tables_not_found"] = [req.table] + req, asic_port_obj_id, ret = fetch_port_oid(self.match_engine, port_name, self.ns) + self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) return asic_port_obj_id def init_asic_port_info(self, asic_port_obj_id): diff --git a/dump/plugins/portchannel.py b/dump/plugins/portchannel.py index b71c7c4fc3..2a54b40d9c 100644 --- a/dump/plugins/portchannel.py +++ b/dump/plugins/portchannel.py @@ -1,5 +1,6 @@ from dump.match_infra import MatchRequest -from dump.helper import create_template_dict +from dump.helper import create_template_dict, verbose_print +from dump.match_helper import fetch_lag_oid, get_lag_members_from_cfg from .executor import Executor @@ -25,16 +26,13 @@ def execute(self, params_dict): self.lag_name = params_dict[Portchannel.ARG_NAME] self.ns = params_dict["namespace"] # CONFIG_DB - lag_found = self.init_lag_config_info() - if lag_found: - self.init_lag_member_config_info() + self.init_lag_config_info() # APPL_DB self.init_lag_appl_info() # STATE_DB self.init_lag_state_info() # ASIC_DB - lag_type_objs_asic = self.init_lag_member_type_obj_asic_info() - self.init_lag_asic_info(lag_type_objs_asic) + self.init_lag_asic_info() return self.ret_temp def init_lag_config_info(self): @@ -42,12 +40,6 @@ def init_lag_config_info(self): ret = self.match_engine.fetch(req) return self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) - def init_lag_member_config_info(self): - req = MatchRequest(db="CONFIG_DB", table="PORTCHANNEL_MEMBER", key_pattern=self.lag_name + "|*", ns=self.ns) - ret = self.match_engine.fetch(req) - for key in ret["keys"]: - self.lag_members.add(key.split("|")[-1]) - def init_lag_appl_info(self): req = MatchRequest(db="APPL_DB", table="LAG_TABLE", key_pattern=self.lag_name, ns=self.ns) ret = self.match_engine.fetch(req) @@ -58,47 +50,15 @@ def init_lag_state_info(self): ret = self.match_engine.fetch(req) return self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) - def init_lag_asic_info(self, lag_type_objs_asic): + def init_lag_asic_info(self): + # Fetch Lag Members from CFG DB + _, lag_members, _ = get_lag_members_from_cfg(self.match_engine, self.lag_name, self.ns) + # Fetch Lag Type Asic Obj from Members info + _, lag_type_objs_asic, _ = fetch_lag_oid(self.match_engine, lag_members, self.ns) if len(lag_type_objs_asic) == 0: self.ret_temp["ASIC_DB"]["tables_not_found"].extend(["ASIC_STATE:SAI_OBJECT_TYPE_LAG"]) return for lag_asic_obj in lag_type_objs_asic: req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_LAG", key_pattern=lag_asic_obj, ns=self.ns) ret = self.match_engine.fetch(req) - self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) - - def init_lag_member_type_obj_asic_info(self): - """ - Finding the relevant SAI_OBJECT_TYPE_LAG key directly from the ASIC is not possible given a LAG name - Thus, using the members to find SAI_LAG_MEMBER_ATTR_LAG_ID - """ - lag_type_objs_asic = set() - for port_name in self.lag_members: - port_asic_obj = self.get_port_asic_obj(port_name) - if port_asic_obj: - lag_member_key, lag_oid = self.get_lag_and_member_obj(port_asic_obj) - lag_type_objs_asic.add(lag_oid) - return lag_type_objs_asic - - def get_port_asic_obj(self, port_name): - req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF", key_pattern="*", field="SAI_HOSTIF_ATTR_NAME", - value=port_name, return_fields=["SAI_HOSTIF_ATTR_OBJ_ID"], ns=self.ns) - ret = self.match_engine.fetch(req) - asic_port_obj_id = "" - if not ret["error"] and ret["keys"]: - sai_hostif_obj_key = ret["keys"][-1] - if sai_hostif_obj_key in ret["return_values"] and "SAI_HOSTIF_ATTR_OBJ_ID" in ret["return_values"][sai_hostif_obj_key]: - asic_port_obj_id = ret["return_values"][sai_hostif_obj_key]["SAI_HOSTIF_ATTR_OBJ_ID"] - return asic_port_obj_id - - def get_lag_and_member_obj(self, port_asic_obj): - req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER", key_pattern="*", field="SAI_LAG_MEMBER_ATTR_PORT_ID", - value=port_asic_obj, return_fields=["SAI_LAG_MEMBER_ATTR_LAG_ID"], ns=self.ns) - ret = self.match_engine.fetch(req) - lag_member_key = "" - lag_oid = "" - if not ret["error"] and ret["keys"]: - lag_member_key = ret["keys"][-1] - if lag_member_key in ret["return_values"] and "SAI_LAG_MEMBER_ATTR_LAG_ID" in ret["return_values"][lag_member_key]: - lag_oid = ret["return_values"][lag_member_key]["SAI_LAG_MEMBER_ATTR_LAG_ID"] - return lag_member_key, lag_oid + self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) \ No newline at end of file diff --git a/dump/plugins/vlan.py b/dump/plugins/vlan.py index 6f5c9b90a9..9175102acf 100644 --- a/dump/plugins/vlan.py +++ b/dump/plugins/vlan.py @@ -1,6 +1,7 @@ from .executor import Executor from dump.match_infra import MatchRequest from dump.helper import create_template_dict +from dump.match_helper import fetch_vlan_oid class Vlan(Executor): @@ -43,14 +44,5 @@ def init_state_vlan_info(self, vlan_name): self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) def init_asic_vlan_info(self, vlan_name): - # Convert 'Vlanxxx' to 'xxx' - if vlan_name[0:4] != "Vlan" or not vlan_name[4:].isnumeric(): - self.ret_temp["ASIC_DB"]["tables_not_found"] =["ASIC_STATE:SAI_OBJECT_TYPE_VLAN"] - return {}, {} - vlan_num = int(vlan_name[4:]) - - # Find the table named "ASIC_STATE:SAI_OBJECT_TYPE_VLAN:*" in which SAI_VLAN_ATTR_VLAN_ID = vlan_num - req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_VLAN", key_pattern="*", field="SAI_VLAN_ATTR_VLAN_ID", - value=str(vlan_num), ns=self.ns) - ret = self.match_engine.fetch(req) - self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) + req, _, ret = fetch_vlan_oid(self.match_engine, vlan_name, self.ns) + self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) \ No newline at end of file From 16e2b7ad002940eaa597b5a4d0075c5b1d4733a6 Mon Sep 17 00:00:00 2001 From: vkarri Date: Sat, 29 Jan 2022 04:25:59 +0000 Subject: [PATCH 2/8] Dump input files added Signed-off-by: vkarri --- tests/dump_input/interface/appl_db.json | 44 ++++++++++++++ tests/dump_input/interface/asic_db.json | 74 +++++++++++++++++++++++ tests/dump_input/interface/config_db.json | 39 ++++++++++++ tests/dump_input/interface/state_db.json | 32 ++++++++++ 4 files changed, 189 insertions(+) create mode 100644 tests/dump_input/interface/appl_db.json create mode 100644 tests/dump_input/interface/asic_db.json create mode 100644 tests/dump_input/interface/config_db.json create mode 100644 tests/dump_input/interface/state_db.json diff --git a/tests/dump_input/interface/appl_db.json b/tests/dump_input/interface/appl_db.json new file mode 100644 index 0000000000..d0fce42e2e --- /dev/null +++ b/tests/dump_input/interface/appl_db.json @@ -0,0 +1,44 @@ +{ + "INTF_TABLE:Ethernet16":{ + "NULL": "NULL", + "mac_addr": "00:00:00:00:00:00" + }, + "INTF_TABLE:Ethernet16:3.3.3.1/24": { + "family": "IPv4", + "scope": "global" + }, + "INTF_TABLE:PortChannel1111": { + "NULL": "NULL", + "mac_addr": "00:00:00:00:00:00" + }, + "INTF_TABLE:PortChannel1111:1.1.1.1/24": { + "family": "IPv4", + "scope": "global" + }, + "INTF_TABLE:Vlan10": { + "NULL": "NULL", + "mac_addr": "00:00:00:00:00:00" + }, + "INTF_TABLE:Vlan10:2.2.2.1/24": { + "family": "IPv4", + "scope": "global" + }, + "INTF_TABLE:Eth0.1": { + "admin_status": "up", + "mac_addr": "00:00:00:00:00:00", + "mtu": "9100", + "vlan": "10" + }, + "INTF_TABLE:Eth0.1:9.9.9.9/24": { + "family": "IPv4", + "scope": "global" + }, + "INTF_TABLE:PortChannel1234": { + "NULL": "NULL", + "mac_addr": "00:00:00:00:00:00" + }, + "INTF_TABLE:PortChannel1234:7.7.7.1/24": { + "family": "IPv4", + "scope": "global" + } +} \ No newline at end of file diff --git a/tests/dump_input/interface/asic_db.json b/tests/dump_input/interface/asic_db.json new file mode 100644 index 0000000000..8d84017ffd --- /dev/null +++ b/tests/dump_input/interface/asic_db.json @@ -0,0 +1,74 @@ +{ + "ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF:oid:0xd000000000a26": { + "SAI_HOSTIF_ATTR_NAME": "Ethernet16", + "SAI_HOSTIF_ATTR_OBJ_ID": "oid:0x1000000000937", + "SAI_HOSTIF_ATTR_OPER_STATUS": "true", + "SAI_HOSTIF_ATTR_TYPE": "SAI_HOSTIF_TYPE_NETDEV" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:oid:0x6000000000c7c": { + "SAI_ROUTER_INTERFACE_ATTR_MTU": "9100", + "SAI_ROUTER_INTERFACE_ATTR_PORT_ID": "oid:0x1000000000937", + "SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS": "1C:34:DA:1C:9F:00", + "SAI_ROUTER_INTERFACE_ATTR_TYPE": "SAI_ROUTER_INTERFACE_TYPE_PORT", + "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": "oid:0x3000000000010" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_VLAN:oid:0x26000000000c78": { + "SAI_VLAN_ATTR_VLAN_ID": "10" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:oid:0x6000000000c7b": { + "SAI_ROUTER_INTERFACE_ATTR_MTU": "9100", + "SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS": "1C:34:DA:1C:9F:00", + "SAI_ROUTER_INTERFACE_ATTR_TYPE": "SAI_ROUTER_INTERFACE_TYPE_VLAN", + "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": "oid:0x3000000000010", + "SAI_ROUTER_INTERFACE_ATTR_VLAN_ID": "oid:0x26000000000c78" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_LAG:oid:0x2000000000c73": { + "NULL": "NULL" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:oid:0x6000000000c77": { + "SAI_ROUTER_INTERFACE_ATTR_MTU": "9100", + "SAI_ROUTER_INTERFACE_ATTR_PORT_ID": "oid:0x2000000000c73", + "SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS": "1C:34:DA:1C:9F:00", + "SAI_ROUTER_INTERFACE_ATTR_TYPE": "SAI_ROUTER_INTERFACE_TYPE_PORT", + "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": "oid:0x3000000000010" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF:oid:0xd00000000056e": { + "SAI_HOSTIF_ATTR_NAME": "Ethernet0", + "SAI_HOSTIF_ATTR_OBJ_ID": "oid:0x1000000000528", + "SAI_HOSTIF_ATTR_OPER_STATUS": "true", + "SAI_HOSTIF_ATTR_TYPE": "SAI_HOSTIF_TYPE_NETDEV", + "SAI_HOSTIF_ATTR_VLAN_TAG": "SAI_HOSTIF_VLAN_TAG_KEEP" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:oid:0x60000000005e9": { + "SAI_ROUTER_INTERFACE_ATTR_ADMIN_V4_STATE": "true", + "SAI_ROUTER_INTERFACE_ATTR_ADMIN_V6_STATE": "true", + "SAI_ROUTER_INTERFACE_ATTR_MTU": "9100", + "SAI_ROUTER_INTERFACE_ATTR_OUTER_VLAN_ID": "10", + "SAI_ROUTER_INTERFACE_ATTR_PORT_ID": "oid:0x1000000000528", + "SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS": "7C:FE:90:F5:36:40", + "SAI_ROUTER_INTERFACE_ATTR_TYPE": "SAI_ROUTER_INTERFACE_TYPE_SUB_PORT", + "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": "oid:0x3000000000002" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF:oid:0xd00000000058c": { + "SAI_HOSTIF_ATTR_NAME": "Ethernet120", + "SAI_HOSTIF_ATTR_OBJ_ID": "oid:0x1000000000318", + "SAI_HOSTIF_ATTR_OPER_STATUS": "false", + "SAI_HOSTIF_ATTR_TYPE": "SAI_HOSTIF_TYPE_NETDEV" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER:oid:0x1b0000000005eb": { + "SAI_LAG_MEMBER_ATTR_EGRESS_DISABLE": "true", + "SAI_LAG_MEMBER_ATTR_INGRESS_DISABLE": "true", + "SAI_LAG_MEMBER_ATTR_LAG_ID": "oid:0x200000000058e", + "SAI_LAG_MEMBER_ATTR_PORT_ID": "oid:0x1000000000318" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_LAG:oid:0x200000000058e": { + "NULL": "NULL" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:oid:0x60000000005ec": { + "SAI_ROUTER_INTERFACE_ATTR_MTU": "9100", + "SAI_ROUTER_INTERFACE_ATTR_PORT_ID": "oid:0x200000000058e", + "SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS": "7C:FE:90:F5:36:40", + "SAI_ROUTER_INTERFACE_ATTR_TYPE": "SAI_ROUTER_INTERFACE_TYPE_PORT", + "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": "oid:0x3000000000002" + } +} diff --git a/tests/dump_input/interface/config_db.json b/tests/dump_input/interface/config_db.json new file mode 100644 index 0000000000..e6b251e300 --- /dev/null +++ b/tests/dump_input/interface/config_db.json @@ -0,0 +1,39 @@ +{ + "INTERFACE|Ethernet16": { + "NULL" : "NULL" + }, + "INTERFACE|Ethernet16|3.3.3.1/24": { + "NULL" : "NULL" + }, + "VLAN_INTERFACE|Vlan10": { + "NULL" : "NULL" + }, + "VLAN_INTERFACE|Vlan10|2.2.2.1/24": { + "NULL" : "NULL" + }, + "PORTCHANNEL_INTERFACE|PortChannel1111": { + "NULL": "NULL" + }, + "PORTCHANNEL_INTERFACE|PortChannel1111|1.1.1.1/24": { + "NULL": "NULL" + }, + "PORTCHANNEL_INTERFACE|PortChannel1234": { + "NULL": "NULL" + }, + "PORTCHANNEL_INTERFACE|PortChannel1234|7.7.7.1/24": { + "NULL": "NULL" + }, + "PORTCHANNEL_MEMBER|PortChannel1234|Ethernet120": { + "NULL": "NULL" + }, + "PORTCHANNEL_MEMBER|PortChannel1234|Ethernet124": { + "NULL": "NULL" + }, + "VLAN_SUB_INTERFACE|Eth0.1": { + "admin_status": "up", + "vlan": "10" + }, + "VLAN_SUB_INTERFACE|Eth0.1|9.9.9.9/24": { + "NULL": "NULL" + } +} diff --git a/tests/dump_input/interface/state_db.json b/tests/dump_input/interface/state_db.json new file mode 100644 index 0000000000..d1a744c3b6 --- /dev/null +++ b/tests/dump_input/interface/state_db.json @@ -0,0 +1,32 @@ +{ + "INTERFACE_TABLE|Ethernet16": { + "vrf": "" + }, + "INTERFACE_TABLE|Ethernet16|3.3.3.1/24": { + "state": "ok" + }, + "INTERFACE_TABLE|PortChannel1111": { + "vrf": "" + }, + "INTERFACE_TABLE|PortChannel1111|1.1.1.1/24": { + "state": "ok" + }, + "INTERFACE_TABLE|Vlan10": { + "vrf": "" + }, + "INTERFACE_TABLE|Vlan10|2.2.2.1/24": { + "state": "ok" + }, + "INTERFACE_TABLE|Eth0.1": { + "vrf": "" + }, + "INTERFACE_TABLE|Eth0.1|9.9.9.9/24": { + "state": "ok" + }, + "INTERFACE_TABLE|PortChannel1234": { + "vrf": "" + }, + "INTERFACE_TABLE|PortChannel1234|7.7.7.1/24": { + "state": "ok" + } +} From ae712cd5a8ae0c91d00a93194e827421ca0613ca Mon Sep 17 00:00:00 2001 From: vkarri Date: Sat, 29 Jan 2022 09:17:33 +0000 Subject: [PATCH 3/8] Added inteface module and tests Signed-off-by: vkarri --- dump/match_helper.py | 7 +- dump/plugins/interface.py | 265 ++++++++++++++++++ dump/plugins/portchannel.py | 12 +- .../dump_tests/module_tests/interface_test.py | 144 ++++++++++ 4 files changed, 418 insertions(+), 10 deletions(-) create mode 100644 dump/plugins/interface.py create mode 100644 tests/dump_tests/module_tests/interface_test.py diff --git a/dump/match_helper.py b/dump/match_helper.py index 17f2888c28..b1aa8844ef 100644 --- a/dump/match_helper.py +++ b/dump/match_helper.py @@ -69,13 +69,16 @@ def fetch_lag_oid(match_engine, lag_members, ns): Finding the relevant SAI_OBJECT_TYPE_LAG key directly from the ASIC is not possible given a LAG name Thus, using the members to find SAI_LAG_MEMBER_ATTR_LAG_ID """ - lag_type_oid = set() + lag_type_oids = set() for port_name in lag_members: print(port_name) _, port_asic_obj, _ = fetch_port_oid(match_engine, port_name, ns) if port_asic_obj: lag_member_key, lag_oid = get_lag_and_member_obj(match_engine, port_asic_obj, ns) - lag_type_oid.add(lag_oid) + lag_type_oids.add(lag_oid) + lag_type_oid, lag_type_oids = "", list(lag_type_oids) + if lag_type_oids: + lag_type_oid = lag_type_oids[-1] return "", lag_type_oid, "" diff --git a/dump/plugins/interface.py b/dump/plugins/interface.py new file mode 100644 index 0000000000..a6fe419255 --- /dev/null +++ b/dump/plugins/interface.py @@ -0,0 +1,265 @@ +import json +import re +from sonic_py_common.interface import get_interface_table_name, get_intf_longname, VLAN_SUB_INTERFACE_SEPARATOR +from dump.match_infra import MatchRequest, RedisSource +from dump.helper import create_template_dict, handle_error +from dump.match_helper import fetch_port_oid, fetch_vlan_oid, fetch_lag_oid, get_lag_members_from_cfg +from .executor import Executor + + +class Interface(Executor): + """ + Debug Dump Plugin for Interface Module. + Interface can be of Ethernet, PortChannel, Loopback, Vlan or SubInterface type + Human readable intf string names are supported + """ + ARG_NAME = "intf_name" + + def __init__(self, match_engine=None): + super().__init__(match_engine) + self.ns = '' + self.intf_type = "" + self.ret_temp = dict() + self.valid_cfg_tables = set(["INTERFACE", + "PORTCHANNEL_INTERFACE", + "VLAN_INTERFACE", + "LOOPBACK_INTERFACE", + "VLAN_SUB_INTERFACE"]) + + def get_all_args(self, ns=""): + """ + Fetch all the interfaces from the valid cfg tables + """ + req = MatchRequest(db="CONFIG_DB", table="*INTERFACE", key_pattern="*", ns=ns) + ret = self.match_engine.fetch(req) + all_intfs = ret["keys"] + filtered_keys = [] + for key in all_intfs: + num_sep = key.count("|") + if num_sep == 1: + filtered_keys.append(key.split("|")[-1]) + return filtered_keys + + def execute(self, params): + self.ret_temp = create_template_dict(dbs=["CONFIG_DB", "APPL_DB", "STATE_DB", "ASIC_DB"]) + self.intf_name = params[Interface.ARG_NAME] + self.ns = params["namespace"] + # CONFIG_DB + self.intf_type = self.init_intf_config_info() + # APPL_DB + self.init_intf_appl_info() + # STATE_DB + self.init_intf_state_info() + # ASIC_DB + self.init_intf_asic_info() + return self.ret_temp + + def init_intf_config_info(self): + intf_type = get_interface_table_name(self.intf_name) + if not intf_type: + self.ret_temp["CONFIG_DB"]["tables_not_found"].extend(list(self.valid_cfg_tables)) + else: + req = MatchRequest(db="CONFIG_DB", table=intf_type, key_pattern=self.intf_name+"*", ns=self.ns) + ret = self.match_engine.fetch(req) + self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) + return intf_type + + def init_intf_appl_info(self): + req = MatchRequest(db="APPL_DB", table="INTF_TABLE", key_pattern=self.intf_name+"*", ns=self.ns) + ret = self.match_engine.fetch(req) + self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) + + def init_intf_state_info(self): + req = MatchRequest(db="STATE_DB", table="INTERFACE_TABLE", key_pattern=self.intf_name+"*", ns=self.ns) + ret = self.match_engine.fetch(req) + self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) + + def init_intf_asic_info(self): + """ + Fetch SAI_OBJECT_TYPE_ROUTER_INTERFACE ASIC Object for the corresponding interface + To find the relevant ASIC RIF object, this method would need the following: + 1) INTERFACE - SAI_OBJECT_TYPE_PORT oid + 2) PORTCHANNEL - SAI_OBJECT_TYPE_LAG oid + 3) VLAN - SAI_OBJECT_TYPE_VLAN + 4) SUB_INTERFACE - SAI_OBJECT_TYPE_PORT/SAI_OBJECT_TYPE_LAG & SAI_ROUTER_INTERFACE_ATTR_OUTER_VLAN_ID + """ + rif_obj = RIF.initialize(self) + rif_obj.collect() + return + +class RIF(object): + """ + Base Class for RIF type + """ + @staticmethod + def initialize(intf_obj): + if intf_obj.intf_type == "INTERFACE": + return PortRIF(intf_obj) + elif intf_obj.intf_type == "PORTCHANNEL_INTERFACE": + return LagRIF(intf_obj) + elif intf_obj.intf_type == "VLAN_INTERFACE": + return VlanRIF(intf_obj) + elif intf_obj.intf_type == "LOOPBACK_INTERFACE": + return LpbRIF(intf_obj) + elif intf_obj.intf_type == "VLAN_SUB_INTERFACE": + return SubIntfRif(intf_obj) + return RIF(intf_obj) + + def __init__(self, intf_obj): + self.intf = intf_obj + + def fetch_rif_keys_using_port_oid(self, port_oid, rfs=["SAI_ROUTER_INTERFACE_ATTR_TYPE"]): + if not port_oid: + port_oid = "INVALID" + req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE", key_pattern="*", field="SAI_ROUTER_INTERFACE_ATTR_PORT_ID", + value=port_oid, return_fields=rfs, ns=self.intf.ns) + ret = self.intf.match_engine.fetch(req) + return req, ret + + def fetch_rif_keys_using_vlan_oid(self, vlan_oid): + if not vlan_oid: + vlan_oid = "INVALID" + req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE", key_pattern="*", field="SAI_ROUTER_INTERFACE_ATTR_VLAN_ID", + value=vlan_oid, return_fields=["SAI_ROUTER_INTERFACE_ATTR_TYPE"], ns=self.intf.ns) + ret = self.intf.match_engine.fetch(req) + return req, ret + + def verify_valid_rif_type(self, ret, exp_rif_type=""): + if not ret or not exp_rif_type: + return True, "" + + rif_type = "" + if not ret["error"] and ret["keys"]: + rif_key = ret["keys"][-1] + rif_type = ret.get("return_values", {}).get(rif_key, {}).get("SAI_ROUTER_INTERFACE_ATTR_TYPE", "") + + if rif_type == exp_rif_type: + return True, rif_type + else: + return False, rif_type + + def sanity_check_rif_type(self, rif_oid, exp_type, recv_type, str_name): + #Sanity check to see if the TYPE is SAI_ROUTER_INTERFACE_TYPE_PORT + if exp_type != recv_type: + err_str = "TYPE Mismatch on SAI_OBJECT_TYPE_ROUTER_INTERFACE, {} oid:{}, expected type:{}, recieved type:{}" + handle_error(err_str.format(str_name, rif_oid, exp_type, recv_type), True) + return + + def collect(self): + self.intf.ret_temp["ASIC_DB"]["tables_not_found"].extend(["ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE"]) + return + + +class LpbRIF(RIF): + """ + Handler for Loopback Interface + """ + def collect(self): + # When an ip is added to Loopback interface, + # no ROUTER_INTERFACE asic obj is created, so skipping it + # and not adding to tables not found + return + + +class PortRIF(RIF): + """ + Handler for Port type Obj + """ + def collect(self): + # Get port oid from port name + _, port_oid, _ = fetch_port_oid(self.intf.match_engine, self.intf.intf_name, self.intf.ns) + # Use Port oid to get the RIF + req, ret = self.fetch_rif_keys_using_port_oid(port_oid) + rif_oids = self.intf.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) + if rif_oids: + # Sanity check to see if the TYPE is SAI_ROUTER_INTERFACE_TYPE_PORT + exp_type = "SAI_ROUTER_INTERFACE_TYPE_PORT" + result, recv_rif_type = self.verify_valid_rif_type(ret, exp_type) + self.sanity_check_rif_type(rif_oids[-1], exp_type, recv_rif_type, "PORT") + + +class VlanRIF(RIF): + """ + Handler for Vlan type Obj + """ + def collect(self): + # Get vlan oid from vlan name + _, vlan_oid, _ = fetch_vlan_oid(self.intf.match_engine, self.intf.intf_name, self.intf.ns) + # Use vlan oid to get the RIF + req, ret = self.fetch_rif_keys_using_vlan_oid(vlan_oid) + rif_oids = self.intf.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) + if rif_oids: + # Sanity check to see if the TYPE is SAI_ROUTER_INTERFACE_TYPE_VLAN + exp_type = "SAI_ROUTER_INTERFACE_TYPE_VLAN" + result, recv_rif_type = self.verify_valid_rif_type(ret, exp_type) + self.sanity_check_rif_type(rif_oids[-1], exp_type, recv_rif_type, "VLAN") + + +class LagRIF(RIF): + """ + Handler for PortChannel/LAG type Obj + """ + def collect(self): + # Fetch Lag Members from CFG DB + _, lag_members, _ = get_lag_members_from_cfg(self.intf.match_engine, self.intf.intf_name, self.intf.ns) + # Get lag oid from lag_members + _, lag_oid, _ = fetch_lag_oid(self.intf.match_engine, lag_members, self.intf.ns) + # Use vlan oid to get the RIF + req, ret = self.fetch_rif_keys_using_port_oid(lag_oid) + rif_oids = self.intf.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) + if rif_oids: + # Sanity check to see if the TYPE is SAI_ROUTER_INTERFACE_TYPE_PORT + exp_type = "SAI_ROUTER_INTERFACE_TYPE_PORT" + result, recv_rif_type = self.verify_valid_rif_type(ret, exp_type) + self.sanity_check_rif_type(rif_oids[-1], exp_type, recv_rif_type, "LAG") + + +class SubIntfRif(RIF): + """ + Handler for PortChannel/LAG type Obj + """ + def fetch_vlan_id_subintf(self, sub_intf): + req = MatchRequest(db="CONFIG_DB", table="VLAN_SUB_INTERFACE", key_pattern=sub_intf, return_fields=["vlan"], ns=self.intf.ns) + ret = self.intf.match_engine.fetch(req) + vlan_id = "" + if not ret["error"] and ret["keys"]: + key = ret["keys"][-1] + vlan_id = ret["return_values"].get(key, {}).get("vlan", "") + return vlan_id + + def collect(self): + """ + To match the RIF object, two checks have to be performed, + 1) SAI_ROUTER_INTERFACE_ATTR_PORT_ID + - This can either be SAI_OBJECT_TYPE_PORT or SAI_OBJECT_TYPE_LAG + 2) SAI_ROUTER_INTERFACE_ATTR_OUTER_VLAN_ID + - This will be Vlan Number (uint16) + """ + intf_oid = "" + parent_port, _ = self.intf.intf_name.split(VLAN_SUB_INTERFACE_SEPARATOR) + parent_port = get_intf_longname(parent_port) + vlan_id = self.fetch_vlan_id_subintf(self.intf.intf_name) + if parent_port.startswith("Eth"): + _, intf_oid, _ = fetch_port_oid(self.intf.match_engine, parent_port, self.intf.ns) + else: + _, intf_oid, _ = fetch_lag_oid(self.intf.match_engine, parent_port, self.intf.ns) + + # Use vlan oid to get the RIF + return_fields = ["SAI_ROUTER_INTERFACE_ATTR_OUTER_VLAN_ID", "SAI_ROUTER_INTERFACE_ATTR_TYPE"] + req, ret = self.fetch_rif_keys_using_port_oid(intf_oid, rfs=return_fields) + + # Search for keys who has SAI_ROUTER_INTERFACE_ATTR_OUTER_VLAN_ID field + filtered_keys = [] + if not ret["error"] and len(ret['keys']) > 0: + for key in ret["keys"]: + rcv_vlan_id = ret.get("return_values", {}).get(key, {}).get("SAI_ROUTER_INTERFACE_ATTR_OUTER_VLAN_ID", "") + if rcv_vlan_id == vlan_id: + filtered_keys.append(key) + break + + rif_oids = self.intf.add_to_ret_template(req.table, req.db, filtered_keys, ret["error"]) + if rif_oids: + # Sanity check to see if the TYPE is SAI_ROUTER_INTERFACE_TYPE_PORT + exp_type = "SAI_ROUTER_INTERFACE_TYPE_SUB_PORT" + result, recv_rif_type = self.verify_valid_rif_type(ret, exp_type) + self.sanity_check_rif_type(rif_oids[-1], exp_type, recv_rif_type, "LAG") diff --git a/dump/plugins/portchannel.py b/dump/plugins/portchannel.py index 2a54b40d9c..950e205986 100644 --- a/dump/plugins/portchannel.py +++ b/dump/plugins/portchannel.py @@ -54,11 +54,7 @@ def init_lag_asic_info(self): # Fetch Lag Members from CFG DB _, lag_members, _ = get_lag_members_from_cfg(self.match_engine, self.lag_name, self.ns) # Fetch Lag Type Asic Obj from Members info - _, lag_type_objs_asic, _ = fetch_lag_oid(self.match_engine, lag_members, self.ns) - if len(lag_type_objs_asic) == 0: - self.ret_temp["ASIC_DB"]["tables_not_found"].extend(["ASIC_STATE:SAI_OBJECT_TYPE_LAG"]) - return - for lag_asic_obj in lag_type_objs_asic: - req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_LAG", key_pattern=lag_asic_obj, ns=self.ns) - ret = self.match_engine.fetch(req) - self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) \ No newline at end of file + _, lag_asic_obj, _ = fetch_lag_oid(self.match_engine, lag_members, self.ns) + req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_LAG", key_pattern=lag_asic_obj, ns=self.ns) + ret = self.match_engine.fetch(req) + self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) \ No newline at end of file diff --git a/tests/dump_tests/module_tests/interface_test.py b/tests/dump_tests/module_tests/interface_test.py new file mode 100644 index 0000000000..d26abf6a95 --- /dev/null +++ b/tests/dump_tests/module_tests/interface_test.py @@ -0,0 +1,144 @@ +import json +import os +import sys +import jsonpatch +import unittest +import pytest +from deepdiff import DeepDiff +from mock import patch +from dump.helper import create_template_dict, sort_lists, populate_mock +from dump.plugins.interface import Interface +from dump.match_infra import MatchEngine, ConnectionPool +from swsscommon.swsscommon import SonicV2Connector + +# Location for dedicated db's used for UT +module_tests_path = os.path.dirname(__file__) +dump_tests_path = os.path.join(module_tests_path, "../") +tests_path = os.path.join(dump_tests_path, "../") +dump_test_input = os.path.join(tests_path, "dump_input") +port_files_path = os.path.join(dump_test_input, "interface") + +# Define the mock files to read from +dedicated_dbs = {} +dedicated_dbs['CONFIG_DB'] = os.path.join(port_files_path, "config_db.json") +dedicated_dbs['APPL_DB'] = os.path.join(port_files_path, "appl_db.json") +dedicated_dbs['ASIC_DB'] = os.path.join(port_files_path, "asic_db.json") +dedicated_dbs['STATE_DB'] = os.path.join(port_files_path, "state_db.json") + + +@pytest.fixture(scope="class", autouse=True) +def match_engine(): + + print("SETUP") + os.environ["VERBOSE"] = "1" + + # Monkey Patch the SonicV2Connector Object + from ...mock_tables import dbconnector + db = SonicV2Connector() + + # popualate the db with mock data + db_names = list(dedicated_dbs.keys()) + try: + populate_mock(db, db_names, dedicated_dbs) + except Exception as e: + assert False, "Mock initialization failed: " + str(e) + + # Initialize connection pool + conn_pool = ConnectionPool() + DEF_NS = '' # Default Namespace + conn_pool.cache = {DEF_NS: {'conn': db, + 'connected_to': set(db_names)}} + + # Initialize match_engine + match_engine = MatchEngine(conn_pool) + yield match_engine + print("TEARDOWN") + os.environ["VERBOSE"] = "0" + +@pytest.mark.usefixtures("match_engine") +class TestInterfaceModule: + def test_port_type_interface(self, match_engine): + """ + Scenario: Test the flow fetching objs related to PORT_TYPE interfac + """ + params = {Interface.ARG_NAME: "Ethernet16", "namespace": ""} + m_intf = Interface(match_engine) + returned = m_intf.execute(params) + expect = create_template_dict(dbs=["CONFIG_DB", "APPL_DB", "ASIC_DB", "STATE_DB"]) + expect["CONFIG_DB"]["keys"].extend(["INTERFACE|Ethernet16", "INTERFACE|Ethernet16|3.3.3.1/24"]) + expect["APPL_DB"]["keys"].extend(["INTF_TABLE:Ethernet16", "INTF_TABLE:Ethernet16:3.3.3.1/24"]) + expect["STATE_DB"]["keys"].extend(["INTERFACE_TABLE|Ethernet16", "INTERFACE_TABLE|Ethernet16|3.3.3.1/24"]) + expect["ASIC_DB"]["keys"].append("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:oid:0x6000000000c7c") + ddiff = DeepDiff(sort_lists(returned), sort_lists(expect), ignore_order=True) + assert not ddiff, ddiff + + def test_vlan_type_interface(self, match_engine): + """ + Scenario: Test the flow fetching objs related to VLAN_TYPE interfac + """ + params = {Interface.ARG_NAME: "Vlan10", "namespace": ""} + m_intf = Interface(match_engine) + returned = m_intf.execute(params) + expect = create_template_dict(dbs=["CONFIG_DB", "APPL_DB", "ASIC_DB", "STATE_DB"]) + expect["CONFIG_DB"]["keys"].extend(["VLAN_INTERFACE|Vlan10", "VLAN_INTERFACE|Vlan10|2.2.2.1/24"]) + expect["APPL_DB"]["keys"].extend(["INTF_TABLE:Vlan10", "INTF_TABLE:Vlan10:2.2.2.1/24"]) + expect["STATE_DB"]["keys"].extend(["INTERFACE_TABLE|Vlan10", "INTERFACE_TABLE|Vlan10|2.2.2.1/24"]) + expect["ASIC_DB"]["keys"].append("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:oid:0x6000000000c7b") + ddiff = DeepDiff(sort_lists(returned), sort_lists(expect), ignore_order=True) + assert not ddiff, ddiff + + def test_lag_type_interface_no_members(self, match_engine): + """ + Scenario: Test the flow fetching objs related to LAG_TYPE iface without members + """ + params = {Interface.ARG_NAME: "PortChannel1111", "namespace": ""} + m_intf = Interface(match_engine) + returned = m_intf.execute(params) + expect = create_template_dict(dbs=["CONFIG_DB", "APPL_DB", "ASIC_DB", "STATE_DB"]) + expect["CONFIG_DB"]["keys"].extend(["PORTCHANNEL_INTERFACE|PortChannel1111", "PORTCHANNEL_INTERFACE|PortChannel1111|1.1.1.1/24"]) + expect["APPL_DB"]["keys"].extend(["INTF_TABLE:PortChannel1111", "INTF_TABLE:PortChannel1111:1.1.1.1/24"]) + expect["STATE_DB"]["keys"].extend(["INTERFACE_TABLE|PortChannel1111", "INTERFACE_TABLE|PortChannel1111|1.1.1.1/24"]) + expect["ASIC_DB"]["tables_not_found"].append("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") + ddiff = DeepDiff(sort_lists(returned), sort_lists(expect), ignore_order=True) + assert not ddiff, ddiff + + def test_lag_type_interface(self, match_engine): + """ + Scenario: Test the flow fetching objs related to LAG_TYPE iface + """ + params = {Interface.ARG_NAME: "PortChannel1234", "namespace": ""} + m_intf = Interface(match_engine) + returned = m_intf.execute(params) + expect = create_template_dict(dbs=["CONFIG_DB", "APPL_DB", "ASIC_DB", "STATE_DB"]) + expect["CONFIG_DB"]["keys"].extend(["PORTCHANNEL_INTERFACE|PortChannel1234", "PORTCHANNEL_INTERFACE|PortChannel1234|7.7.7.1/24"]) + expect["APPL_DB"]["keys"].extend(["INTF_TABLE:PortChannel1234", "INTF_TABLE:PortChannel1234:7.7.7.1/24"]) + expect["STATE_DB"]["keys"].extend(["INTERFACE_TABLE|PortChannel1234", "INTERFACE_TABLE|PortChannel1234|7.7.7.1/24"]) + expect["ASIC_DB"]["keys"].append("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:oid:0x60000000005ec") + ddiff = DeepDiff(sort_lists(returned), sort_lists(expect), ignore_order=True) + assert not ddiff, ddiff + + def test_subintf_type_interface(self, match_engine): + """ + Scenario: Test the flow fetching objs related to Sub-Interface iface + """ + params = {Interface.ARG_NAME: "Eth0.1", "namespace": ""} + m_intf = Interface(match_engine) + returned = m_intf.execute(params) + expect = create_template_dict(dbs=["CONFIG_DB", "APPL_DB", "ASIC_DB", "STATE_DB"]) + expect["CONFIG_DB"]["keys"].extend(["VLAN_SUB_INTERFACE|Eth0.1", "VLAN_SUB_INTERFACE|Eth0.1|9.9.9.9/24"]) + expect["APPL_DB"]["keys"].extend(["INTF_TABLE:Eth0.1", "INTF_TABLE:Eth0.1:9.9.9.9/24"]) + expect["STATE_DB"]["keys"].extend(["INTERFACE_TABLE|Eth0.1", "INTERFACE_TABLE|Eth0.1|9.9.9.9/24"]) + expect["ASIC_DB"]["keys"].append("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:oid:0x60000000005e9") + ddiff = DeepDiff(sort_lists(returned), sort_lists(expect), ignore_order=True) + assert not ddiff, ddiff + + def test_all_args(self, match_engine): + """ + Scenario: Verify Whether the get_all_args method is working as expected + """ + params = {} + m_port = Interface(match_engine) + returned = m_port.get_all_args("") + expect = ["Ethernet16", "Vlan10", "PortChannel1111", "PortChannel1234", "Eth0.1"] + ddiff = DeepDiff(expect, returned, ignore_order=True) + assert not ddiff, ddiff From 76444855790ab4b7a38add1d623d8e3f61d33fd7 Mon Sep 17 00:00:00 2001 From: vkarri Date: Sun, 30 Jan 2022 09:08:58 +0000 Subject: [PATCH 4/8] New tests added Signed-off-by: vkarri --- dump/plugins/interface.py | 27 ++++++---- tests/dump_input/interface/appl_db.json | 8 +++ tests/dump_input/interface/config_db.json | 6 +++ tests/dump_input/interface/state_db.json | 6 +++ .../dump_tests/module_tests/interface_test.py | 50 ++++++++++++++++++- 5 files changed, 87 insertions(+), 10 deletions(-) diff --git a/dump/plugins/interface.py b/dump/plugins/interface.py index a6fe419255..9babbda3d7 100644 --- a/dump/plugins/interface.py +++ b/dump/plugins/interface.py @@ -4,6 +4,7 @@ from dump.match_infra import MatchRequest, RedisSource from dump.helper import create_template_dict, handle_error from dump.match_helper import fetch_port_oid, fetch_vlan_oid, fetch_lag_oid, get_lag_members_from_cfg +from swsscommon.swsscommon import SonicDBConfig from .executor import Executor @@ -54,25 +55,32 @@ def execute(self, params): self.init_intf_asic_info() return self.ret_temp + def get_sep(self, db): + return SonicDBConfig.getSeparator(db) + + def add_intf_keys(self, db_name, table_name): + # Fetch Interface Keys + req = MatchRequest(db=db_name, table=table_name, key_pattern=self.intf_name, ns=self.ns) + ret = self.match_engine.fetch(req) + self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) + # Fetch IP & Interface Related keys + req = MatchRequest(db=db_name, table=table_name, key_pattern=self.intf_name+self.get_sep(db_name)+"*", ns=self.ns) + ret = self.match_engine.fetch(req) + self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) + def init_intf_config_info(self): intf_type = get_interface_table_name(self.intf_name) if not intf_type: self.ret_temp["CONFIG_DB"]["tables_not_found"].extend(list(self.valid_cfg_tables)) else: - req = MatchRequest(db="CONFIG_DB", table=intf_type, key_pattern=self.intf_name+"*", ns=self.ns) - ret = self.match_engine.fetch(req) - self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) + self.add_intf_keys("CONFIG_DB", intf_type) return intf_type def init_intf_appl_info(self): - req = MatchRequest(db="APPL_DB", table="INTF_TABLE", key_pattern=self.intf_name+"*", ns=self.ns) - ret = self.match_engine.fetch(req) - self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) + self.add_intf_keys("APPL_DB", "INTF_TABLE") def init_intf_state_info(self): - req = MatchRequest(db="STATE_DB", table="INTERFACE_TABLE", key_pattern=self.intf_name+"*", ns=self.ns) - ret = self.match_engine.fetch(req) - self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) + self.add_intf_keys("STATE_DB", "INTERFACE_TABLE") def init_intf_asic_info(self): """ @@ -100,6 +108,7 @@ def initialize(intf_obj): elif intf_obj.intf_type == "VLAN_INTERFACE": return VlanRIF(intf_obj) elif intf_obj.intf_type == "LOOPBACK_INTERFACE": + print("REACHED_HERE") return LpbRIF(intf_obj) elif intf_obj.intf_type == "VLAN_SUB_INTERFACE": return SubIntfRif(intf_obj) diff --git a/tests/dump_input/interface/appl_db.json b/tests/dump_input/interface/appl_db.json index d0fce42e2e..deaf3117ee 100644 --- a/tests/dump_input/interface/appl_db.json +++ b/tests/dump_input/interface/appl_db.json @@ -40,5 +40,13 @@ "INTF_TABLE:PortChannel1234:7.7.7.1/24": { "family": "IPv4", "scope": "global" + }, + "INTF_TABLE:Loopback0": { + "NULL": "NULL", + "mac_addr": "00:00:00:00:00:00" + }, + "INTF_TABLE:Loopback0:10.1.0.1/32": { + "family": "IPv4", + "scope": "global" } } \ No newline at end of file diff --git a/tests/dump_input/interface/config_db.json b/tests/dump_input/interface/config_db.json index e6b251e300..8765e0e62a 100644 --- a/tests/dump_input/interface/config_db.json +++ b/tests/dump_input/interface/config_db.json @@ -35,5 +35,11 @@ }, "VLAN_SUB_INTERFACE|Eth0.1|9.9.9.9/24": { "NULL": "NULL" + }, + "LOOPBACK_INTERFACE|Loopback0": { + "NULL": "NULL" + }, + "LOOPBACK_INTERFACE|Loopback0|10.1.0.1/32": { + "NULL": "NULL" } } diff --git a/tests/dump_input/interface/state_db.json b/tests/dump_input/interface/state_db.json index d1a744c3b6..4d7d9e5d1f 100644 --- a/tests/dump_input/interface/state_db.json +++ b/tests/dump_input/interface/state_db.json @@ -28,5 +28,11 @@ }, "INTERFACE_TABLE|PortChannel1234|7.7.7.1/24": { "state": "ok" + }, + "INTERFACE_TABLE|Loopback0": { + "vrf": "" + }, + "INTERFACE_TABLE|Loopback0|10.1.0.1/32": { + "state": "ok" } } diff --git a/tests/dump_tests/module_tests/interface_test.py b/tests/dump_tests/module_tests/interface_test.py index d26abf6a95..1a0dbb014e 100644 --- a/tests/dump_tests/module_tests/interface_test.py +++ b/tests/dump_tests/module_tests/interface_test.py @@ -132,6 +132,54 @@ def test_subintf_type_interface(self, match_engine): ddiff = DeepDiff(sort_lists(returned), sort_lists(expect), ignore_order=True) assert not ddiff, ddiff + def test_no_interface(self, match_engine): + """ + Scenario: Test the flow fetching objs related to an interface which is not present + """ + params = {Interface.ARG_NAME: "Ethernet160", "namespace": ""} + m_intf = Interface(match_engine) + returned = m_intf.execute(params) + expect = create_template_dict(dbs=["CONFIG_DB", "APPL_DB", "ASIC_DB", "STATE_DB"]) + expect["CONFIG_DB"]["tables_not_found"].extend(["INTERFACE"]) + expect["APPL_DB"]["tables_not_found"].extend(["INTF_TABLE"]) + expect["STATE_DB"]["tables_not_found"].extend(["INTERFACE_TABLE"]) + expect["ASIC_DB"]["tables_not_found"].append("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") + ddiff = DeepDiff(sort_lists(returned), sort_lists(expect), ignore_order=True) + assert not ddiff, ddiff + + def test_invalid_interface(self, match_engine): + """ + Scenario: Test the flow fetching objs related to an interface which is invalid + """ + params = {Interface.ARG_NAME: "Whatever", "namespace": ""} + m_intf = Interface(match_engine) + returned = m_intf.execute(params) + expect = create_template_dict(dbs=["CONFIG_DB", "APPL_DB", "ASIC_DB", "STATE_DB"]) + expect["CONFIG_DB"]["tables_not_found"].extend(["INTERFACE", + "PORTCHANNEL_INTERFACE", + "VLAN_INTERFACE", + "VLAN_SUB_INTERFACE", + "LOOPBACK_INTERFACE"]) + expect["APPL_DB"]["tables_not_found"].extend(["INTF_TABLE"]) + expect["STATE_DB"]["tables_not_found"].extend(["INTERFACE_TABLE"]) + expect["ASIC_DB"]["tables_not_found"].append("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") + ddiff = DeepDiff(sort_lists(returned), sort_lists(expect), ignore_order=True) + assert not ddiff, ddiff + + def test_loopback_interface(self, match_engine): + """ + Scenario: Test the flow fetching objs related to loopback iface + """ + params = {Interface.ARG_NAME: "Loopback0", "namespace": ""} + m_intf = Interface(match_engine) + returned = m_intf.execute(params) + expect = create_template_dict(dbs=["CONFIG_DB", "APPL_DB", "ASIC_DB", "STATE_DB"]) + expect["CONFIG_DB"]["keys"].extend(["LOOPBACK_INTERFACE|Loopback0", "LOOPBACK_INTERFACE|Loopback0|10.1.0.1/32"]) + expect["APPL_DB"]["keys"].extend(["INTF_TABLE:Loopback0", "INTF_TABLE:Loopback0:10.1.0.1/32"]) + expect["STATE_DB"]["keys"].extend(["INTERFACE_TABLE|Loopback0", "INTERFACE_TABLE|Loopback0|10.1.0.1/32"]) + ddiff = DeepDiff(sort_lists(returned), sort_lists(expect), ignore_order=True) + assert not ddiff, ddiff + def test_all_args(self, match_engine): """ Scenario: Verify Whether the get_all_args method is working as expected @@ -139,6 +187,6 @@ def test_all_args(self, match_engine): params = {} m_port = Interface(match_engine) returned = m_port.get_all_args("") - expect = ["Ethernet16", "Vlan10", "PortChannel1111", "PortChannel1234", "Eth0.1"] + expect = ["Ethernet16", "Vlan10", "PortChannel1111", "PortChannel1234", "Eth0.1", "Loopback0"] ddiff = DeepDiff(expect, returned, ignore_order=True) assert not ddiff, ddiff From 5d562d11fed4e7167def8379791e727fb1f308b8 Mon Sep 17 00:00:00 2001 From: vkarri Date: Sun, 30 Jan 2022 09:36:28 +0000 Subject: [PATCH 5/8] Minor Changes handled Signed-off-by: vkarri --- dump/match_helper.py | 12 ------------ dump/plugins/interface.py | 3 +-- dump/plugins/portchannel.py | 2 +- dump/plugins/vlan.py | 2 +- 4 files changed, 3 insertions(+), 16 deletions(-) diff --git a/dump/match_helper.py b/dump/match_helper.py index b1aa8844ef..167fbf8660 100644 --- a/dump/match_helper.py +++ b/dump/match_helper.py @@ -71,7 +71,6 @@ def fetch_lag_oid(match_engine, lag_members, ns): """ lag_type_oids = set() for port_name in lag_members: - print(port_name) _, port_asic_obj, _ = fetch_port_oid(match_engine, port_name, ns) if port_asic_obj: lag_member_key, lag_oid = get_lag_and_member_obj(match_engine, port_asic_obj, ns) @@ -80,14 +79,3 @@ def fetch_lag_oid(match_engine, lag_members, ns): if lag_type_oids: lag_type_oid = lag_type_oids[-1] return "", lag_type_oid, "" - - - - - - - - - - - diff --git a/dump/plugins/interface.py b/dump/plugins/interface.py index 9babbda3d7..dca1e57854 100644 --- a/dump/plugins/interface.py +++ b/dump/plugins/interface.py @@ -108,7 +108,6 @@ def initialize(intf_obj): elif intf_obj.intf_type == "VLAN_INTERFACE": return VlanRIF(intf_obj) elif intf_obj.intf_type == "LOOPBACK_INTERFACE": - print("REACHED_HERE") return LpbRIF(intf_obj) elif intf_obj.intf_type == "VLAN_SUB_INTERFACE": return SubIntfRif(intf_obj) @@ -151,7 +150,7 @@ def sanity_check_rif_type(self, rif_oid, exp_type, recv_type, str_name): #Sanity check to see if the TYPE is SAI_ROUTER_INTERFACE_TYPE_PORT if exp_type != recv_type: err_str = "TYPE Mismatch on SAI_OBJECT_TYPE_ROUTER_INTERFACE, {} oid:{}, expected type:{}, recieved type:{}" - handle_error(err_str.format(str_name, rif_oid, exp_type, recv_type), True) + handle_error(err_str.format(str_name, rif_oid, exp_type, recv_type), False) return def collect(self): diff --git a/dump/plugins/portchannel.py b/dump/plugins/portchannel.py index 950e205986..91d1c44142 100644 --- a/dump/plugins/portchannel.py +++ b/dump/plugins/portchannel.py @@ -57,4 +57,4 @@ def init_lag_asic_info(self): _, lag_asic_obj, _ = fetch_lag_oid(self.match_engine, lag_members, self.ns) req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_LAG", key_pattern=lag_asic_obj, ns=self.ns) ret = self.match_engine.fetch(req) - self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) \ No newline at end of file + self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) diff --git a/dump/plugins/vlan.py b/dump/plugins/vlan.py index 9175102acf..f3a99f4250 100644 --- a/dump/plugins/vlan.py +++ b/dump/plugins/vlan.py @@ -45,4 +45,4 @@ def init_state_vlan_info(self, vlan_name): def init_asic_vlan_info(self, vlan_name): req, _, ret = fetch_vlan_oid(self.match_engine, vlan_name, self.ns) - self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) \ No newline at end of file + self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) From 6fc025e20d162857eaab7f6044199043135b8f07 Mon Sep 17 00:00:00 2001 From: Vivek Reddy Karri Date: Fri, 11 Feb 2022 22:54:24 +0000 Subject: [PATCH 6/8] Abstracted the lag_oid extraction method Signed-off-by: Vivek Reddy Karri --- dump/match_helper.py | 3 ++- dump/plugins/interface.py | 8 +++----- dump/plugins/portchannel.py | 8 +++----- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/dump/match_helper.py b/dump/match_helper.py index 167fbf8660..2b9d4da539 100644 --- a/dump/match_helper.py +++ b/dump/match_helper.py @@ -64,11 +64,12 @@ def get_lag_and_member_obj(match_engine, port_asic_obj, ns): lag_oid = ret["return_values"][lag_member_key]["SAI_LAG_MEMBER_ATTR_LAG_ID"] return lag_member_key, lag_oid -def fetch_lag_oid(match_engine, lag_members, ns): +def fetch_lag_oid(match_engine, lag_name, ns): """ Finding the relevant SAI_OBJECT_TYPE_LAG key directly from the ASIC is not possible given a LAG name Thus, using the members to find SAI_LAG_MEMBER_ATTR_LAG_ID """ + _, lag_members, _ = get_lag_members_from_cfg(match_engine, lag_name, ns) lag_type_oids = set() for port_name in lag_members: _, port_asic_obj, _ = fetch_port_oid(match_engine, port_name, ns) diff --git a/dump/plugins/interface.py b/dump/plugins/interface.py index dca1e57854..cc126773c2 100644 --- a/dump/plugins/interface.py +++ b/dump/plugins/interface.py @@ -3,7 +3,7 @@ from sonic_py_common.interface import get_interface_table_name, get_intf_longname, VLAN_SUB_INTERFACE_SEPARATOR from dump.match_infra import MatchRequest, RedisSource from dump.helper import create_template_dict, handle_error -from dump.match_helper import fetch_port_oid, fetch_vlan_oid, fetch_lag_oid, get_lag_members_from_cfg +from dump.match_helper import fetch_port_oid, fetch_vlan_oid, fetch_lag_oid from swsscommon.swsscommon import SonicDBConfig from .executor import Executor @@ -208,10 +208,8 @@ class LagRIF(RIF): Handler for PortChannel/LAG type Obj """ def collect(self): - # Fetch Lag Members from CFG DB - _, lag_members, _ = get_lag_members_from_cfg(self.intf.match_engine, self.intf.intf_name, self.intf.ns) - # Get lag oid from lag_members - _, lag_oid, _ = fetch_lag_oid(self.intf.match_engine, lag_members, self.intf.ns) + # Get lag oid from lag name + _, lag_oid, _ = fetch_lag_oid(self.intf.match_engine, self.intf.intf_name, self.intf.ns) # Use vlan oid to get the RIF req, ret = self.fetch_rif_keys_using_port_oid(lag_oid) rif_oids = self.intf.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) diff --git a/dump/plugins/portchannel.py b/dump/plugins/portchannel.py index 91d1c44142..370e26cfcb 100644 --- a/dump/plugins/portchannel.py +++ b/dump/plugins/portchannel.py @@ -1,6 +1,6 @@ from dump.match_infra import MatchRequest from dump.helper import create_template_dict, verbose_print -from dump.match_helper import fetch_lag_oid, get_lag_members_from_cfg +from dump.match_helper import fetch_lag_oid from .executor import Executor @@ -51,10 +51,8 @@ def init_lag_state_info(self): return self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) def init_lag_asic_info(self): - # Fetch Lag Members from CFG DB - _, lag_members, _ = get_lag_members_from_cfg(self.match_engine, self.lag_name, self.ns) - # Fetch Lag Type Asic Obj from Members info - _, lag_asic_obj, _ = fetch_lag_oid(self.match_engine, lag_members, self.ns) + # Fetch Lag Type Asic Obj from CFG DB given lag name + _, lag_asic_obj, _ = fetch_lag_oid(self.match_engine, self.lag_name, self.ns) req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_LAG", key_pattern=lag_asic_obj, ns=self.ns) ret = self.match_engine.fetch(req) self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) From e96c8f1710a7bad626b94a738a05792131c79e83 Mon Sep 17 00:00:00 2001 From: Vivek Reddy Karri Date: Fri, 11 Feb 2022 23:00:21 +0000 Subject: [PATCH 7/8] Minor Comments handled Signed-off-by: Vivek Reddy Karri --- dump/plugins/interface.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/dump/plugins/interface.py b/dump/plugins/interface.py index cc126773c2..8d5c35b4db 100644 --- a/dump/plugins/interface.py +++ b/dump/plugins/interface.py @@ -69,19 +69,19 @@ def add_intf_keys(self, db_name, table_name): self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) def init_intf_config_info(self): - intf_type = get_interface_table_name(self.intf_name) - if not intf_type: + intf_table_name = get_interface_table_name(self.intf_name) + if not intf_table_name: self.ret_temp["CONFIG_DB"]["tables_not_found"].extend(list(self.valid_cfg_tables)) else: - self.add_intf_keys("CONFIG_DB", intf_type) - return intf_type - + self.add_intf_keys("CONFIG_DB", intf_table_name) + return intf_table_name + def init_intf_appl_info(self): self.add_intf_keys("APPL_DB", "INTF_TABLE") - + def init_intf_state_info(self): self.add_intf_keys("STATE_DB", "INTERFACE_TABLE") - + def init_intf_asic_info(self): """ Fetch SAI_OBJECT_TYPE_ROUTER_INTERFACE ASIC Object for the corresponding interface @@ -124,14 +124,6 @@ def fetch_rif_keys_using_port_oid(self, port_oid, rfs=["SAI_ROUTER_INTERFACE_ATT ret = self.intf.match_engine.fetch(req) return req, ret - def fetch_rif_keys_using_vlan_oid(self, vlan_oid): - if not vlan_oid: - vlan_oid = "INVALID" - req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE", key_pattern="*", field="SAI_ROUTER_INTERFACE_ATTR_VLAN_ID", - value=vlan_oid, return_fields=["SAI_ROUTER_INTERFACE_ATTR_TYPE"], ns=self.intf.ns) - ret = self.intf.match_engine.fetch(req) - return req, ret - def verify_valid_rif_type(self, ret, exp_rif_type=""): if not ret or not exp_rif_type: return True, "" @@ -190,6 +182,14 @@ class VlanRIF(RIF): """ Handler for Vlan type Obj """ + def fetch_rif_keys_using_vlan_oid(self, vlan_oid): + if not vlan_oid: + vlan_oid = "INVALID" + req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE", key_pattern="*", field="SAI_ROUTER_INTERFACE_ATTR_VLAN_ID", + value=vlan_oid, return_fields=["SAI_ROUTER_INTERFACE_ATTR_TYPE"], ns=self.intf.ns) + ret = self.intf.match_engine.fetch(req) + return req, ret + def collect(self): # Get vlan oid from vlan name _, vlan_oid, _ = fetch_vlan_oid(self.intf.match_engine, self.intf.intf_name, self.intf.ns) From 91a6fab604e1d1d3533585b18e9736fa22b81769 Mon Sep 17 00:00:00 2001 From: Vivek Reddy Karri Date: Sat, 12 Feb 2022 01:21:40 +0000 Subject: [PATCH 8/8] Handled Comments Signed-off-by: Vivek Reddy Karri --- dump/plugins/interface.py | 22 ++--- tests/dump_input/interface/appl_db.json | 6 ++ tests/dump_input/interface/asic_db.json | 6 ++ tests/dump_input/interface/config_db.json | 90 ++++++++++--------- .../dump_tests/module_tests/interface_test.py | 17 +++- 5 files changed, 84 insertions(+), 57 deletions(-) diff --git a/dump/plugins/interface.py b/dump/plugins/interface.py index 8d5c35b4db..8d62831143 100644 --- a/dump/plugins/interface.py +++ b/dump/plugins/interface.py @@ -66,7 +66,7 @@ def add_intf_keys(self, db_name, table_name): # Fetch IP & Interface Related keys req = MatchRequest(db=db_name, table=table_name, key_pattern=self.intf_name+self.get_sep(db_name)+"*", ns=self.ns) ret = self.match_engine.fetch(req) - self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) + self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"], False) def init_intf_config_info(self): intf_table_name = get_interface_table_name(self.intf_name) @@ -138,9 +138,10 @@ def verify_valid_rif_type(self, ret, exp_rif_type=""): else: return False, rif_type - def sanity_check_rif_type(self, rif_oid, exp_type, recv_type, str_name): - #Sanity check to see if the TYPE is SAI_ROUTER_INTERFACE_TYPE_PORT - if exp_type != recv_type: + def sanity_check_rif_type(self, ret, rif_oid, exp_type, str_name): + # Sanity check to see if the TYPE is SAI_ROUTER_INTERFACE_TYPE_PORT + _, recv_type = self.verify_valid_rif_type(ret, exp_type) + if exp_type != recv_type: err_str = "TYPE Mismatch on SAI_OBJECT_TYPE_ROUTER_INTERFACE, {} oid:{}, expected type:{}, recieved type:{}" handle_error(err_str.format(str_name, rif_oid, exp_type, recv_type), False) return @@ -174,8 +175,7 @@ def collect(self): if rif_oids: # Sanity check to see if the TYPE is SAI_ROUTER_INTERFACE_TYPE_PORT exp_type = "SAI_ROUTER_INTERFACE_TYPE_PORT" - result, recv_rif_type = self.verify_valid_rif_type(ret, exp_type) - self.sanity_check_rif_type(rif_oids[-1], exp_type, recv_rif_type, "PORT") + self.sanity_check_rif_type(ret, rif_oids[-1], exp_type, "PORT") class VlanRIF(RIF): @@ -199,8 +199,7 @@ def collect(self): if rif_oids: # Sanity check to see if the TYPE is SAI_ROUTER_INTERFACE_TYPE_VLAN exp_type = "SAI_ROUTER_INTERFACE_TYPE_VLAN" - result, recv_rif_type = self.verify_valid_rif_type(ret, exp_type) - self.sanity_check_rif_type(rif_oids[-1], exp_type, recv_rif_type, "VLAN") + self.sanity_check_rif_type(ret, rif_oids[-1], exp_type, "VLAN") class LagRIF(RIF): @@ -216,8 +215,7 @@ def collect(self): if rif_oids: # Sanity check to see if the TYPE is SAI_ROUTER_INTERFACE_TYPE_PORT exp_type = "SAI_ROUTER_INTERFACE_TYPE_PORT" - result, recv_rif_type = self.verify_valid_rif_type(ret, exp_type) - self.sanity_check_rif_type(rif_oids[-1], exp_type, recv_rif_type, "LAG") + self.sanity_check_rif_type(ret, rif_oids[-1], exp_type, "LAG") class SubIntfRif(RIF): @@ -265,7 +263,5 @@ def collect(self): rif_oids = self.intf.add_to_ret_template(req.table, req.db, filtered_keys, ret["error"]) if rif_oids: - # Sanity check to see if the TYPE is SAI_ROUTER_INTERFACE_TYPE_PORT exp_type = "SAI_ROUTER_INTERFACE_TYPE_SUB_PORT" - result, recv_rif_type = self.verify_valid_rif_type(ret, exp_type) - self.sanity_check_rif_type(rif_oids[-1], exp_type, recv_rif_type, "LAG") + self.sanity_check_rif_type(ret, rif_oids[-1], exp_type, "SUB_INTERFACE") diff --git a/tests/dump_input/interface/appl_db.json b/tests/dump_input/interface/appl_db.json index deaf3117ee..772cc32332 100644 --- a/tests/dump_input/interface/appl_db.json +++ b/tests/dump_input/interface/appl_db.json @@ -48,5 +48,11 @@ "INTF_TABLE:Loopback0:10.1.0.1/32": { "family": "IPv4", "scope": "global" + }, + "INTF_TABLE:Eth4.1": { + "admin_status": "up", + "mac_addr": "00:00:00:00:00:00", + "mtu": "9100", + "vlan": "100" } } \ No newline at end of file diff --git a/tests/dump_input/interface/asic_db.json b/tests/dump_input/interface/asic_db.json index 8d84017ffd..bbad0c9cd9 100644 --- a/tests/dump_input/interface/asic_db.json +++ b/tests/dump_input/interface/asic_db.json @@ -70,5 +70,11 @@ "SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS": "7C:FE:90:F5:36:40", "SAI_ROUTER_INTERFACE_ATTR_TYPE": "SAI_ROUTER_INTERFACE_TYPE_PORT", "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": "oid:0x3000000000002" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF:oid:0xd00000000056f": { + "SAI_HOSTIF_ATTR_NAME": "Ethernet4", + "SAI_HOSTIF_ATTR_OBJ_ID": "oid:0x1000000000529", + "SAI_HOSTIF_ATTR_OPER_STATUS": "true", + "SAI_HOSTIF_ATTR_TYPE": "SAI_HOSTIF_TYPE_NETDEV" } } diff --git a/tests/dump_input/interface/config_db.json b/tests/dump_input/interface/config_db.json index 8765e0e62a..afeaccad9f 100644 --- a/tests/dump_input/interface/config_db.json +++ b/tests/dump_input/interface/config_db.json @@ -1,45 +1,49 @@ { - "INTERFACE|Ethernet16": { - "NULL" : "NULL" - }, - "INTERFACE|Ethernet16|3.3.3.1/24": { - "NULL" : "NULL" - }, - "VLAN_INTERFACE|Vlan10": { - "NULL" : "NULL" - }, - "VLAN_INTERFACE|Vlan10|2.2.2.1/24": { - "NULL" : "NULL" - }, - "PORTCHANNEL_INTERFACE|PortChannel1111": { - "NULL": "NULL" - }, - "PORTCHANNEL_INTERFACE|PortChannel1111|1.1.1.1/24": { - "NULL": "NULL" - }, - "PORTCHANNEL_INTERFACE|PortChannel1234": { - "NULL": "NULL" - }, - "PORTCHANNEL_INTERFACE|PortChannel1234|7.7.7.1/24": { - "NULL": "NULL" - }, - "PORTCHANNEL_MEMBER|PortChannel1234|Ethernet120": { - "NULL": "NULL" - }, - "PORTCHANNEL_MEMBER|PortChannel1234|Ethernet124": { - "NULL": "NULL" - }, - "VLAN_SUB_INTERFACE|Eth0.1": { - "admin_status": "up", - "vlan": "10" - }, - "VLAN_SUB_INTERFACE|Eth0.1|9.9.9.9/24": { - "NULL": "NULL" - }, - "LOOPBACK_INTERFACE|Loopback0": { - "NULL": "NULL" - }, - "LOOPBACK_INTERFACE|Loopback0|10.1.0.1/32": { - "NULL": "NULL" - } + "INTERFACE|Ethernet16": { + "NULL" : "NULL" + }, + "INTERFACE|Ethernet16|3.3.3.1/24": { + "NULL" : "NULL" + }, + "VLAN_INTERFACE|Vlan10": { + "NULL" : "NULL" + }, + "VLAN_INTERFACE|Vlan10|2.2.2.1/24": { + "NULL" : "NULL" + }, + "PORTCHANNEL_INTERFACE|PortChannel1111": { + "NULL": "NULL" + }, + "PORTCHANNEL_INTERFACE|PortChannel1111|1.1.1.1/24": { + "NULL": "NULL" + }, + "PORTCHANNEL_INTERFACE|PortChannel1234": { + "NULL": "NULL" + }, + "PORTCHANNEL_INTERFACE|PortChannel1234|7.7.7.1/24": { + "NULL": "NULL" + }, + "PORTCHANNEL_MEMBER|PortChannel1234|Ethernet120": { + "NULL": "NULL" + }, + "PORTCHANNEL_MEMBER|PortChannel1234|Ethernet124": { + "NULL": "NULL" + }, + "VLAN_SUB_INTERFACE|Eth0.1": { + "admin_status": "up", + "vlan": "10" + }, + "VLAN_SUB_INTERFACE|Eth0.1|9.9.9.9/24": { + "NULL": "NULL" + }, + "LOOPBACK_INTERFACE|Loopback0": { + "NULL": "NULL" + }, + "LOOPBACK_INTERFACE|Loopback0|10.1.0.1/32": { + "NULL": "NULL" + }, + "VLAN_SUB_INTERFACE|Eth4.1": { + "admin_status": "up", + "vlan": "100" + } } diff --git a/tests/dump_tests/module_tests/interface_test.py b/tests/dump_tests/module_tests/interface_test.py index 1a0dbb014e..969272b069 100644 --- a/tests/dump_tests/module_tests/interface_test.py +++ b/tests/dump_tests/module_tests/interface_test.py @@ -180,6 +180,21 @@ def test_loopback_interface(self, match_engine): ddiff = DeepDiff(sort_lists(returned), sort_lists(expect), ignore_order=True) assert not ddiff, ddiff + def test_subintf_with_invalid_vlan(self, match_engine): + """ + Scenario: Test the flow fetching objs related to a subintf with invalid vlan + """ + params = {Interface.ARG_NAME: "Eth4.1", "namespace": ""} + m_intf = Interface(match_engine) + returned = m_intf.execute(params) + expect = create_template_dict(dbs=["CONFIG_DB", "APPL_DB", "ASIC_DB", "STATE_DB"]) + expect["CONFIG_DB"]["keys"].extend(["VLAN_SUB_INTERFACE|Eth4.1"]) + expect["APPL_DB"]["keys"].extend(["INTF_TABLE:Eth4.1"]) + expect["STATE_DB"]["tables_not_found"].extend(["INTERFACE_TABLE"]) + expect["ASIC_DB"]["tables_not_found"].extend(["ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE"]) + ddiff = DeepDiff(sort_lists(returned), sort_lists(expect), ignore_order=True) + assert not ddiff, ddiff + def test_all_args(self, match_engine): """ Scenario: Verify Whether the get_all_args method is working as expected @@ -187,6 +202,6 @@ def test_all_args(self, match_engine): params = {} m_port = Interface(match_engine) returned = m_port.get_all_args("") - expect = ["Ethernet16", "Vlan10", "PortChannel1111", "PortChannel1234", "Eth0.1", "Loopback0"] + expect = ["Ethernet16", "Vlan10", "PortChannel1111", "PortChannel1234", "Eth0.1", "Loopback0", "Eth4.1"] ddiff = DeepDiff(expect, returned, ignore_order=True) assert not ddiff, ddiff