From e68cef479047e5d862957939e12d3c83fe1a27e5 Mon Sep 17 00:00:00 2001 From: Vivek Reddy Karri Date: Wed, 4 Aug 2021 21:44:12 +0000 Subject: [PATCH 1/5] Route Module files added Signed-off-by: Vivek Reddy Karri --- dump/plugins/route.py | 294 ++++++++++++++++++++ tests/dump_input/route/appl_db.json | 34 +++ tests/dump_input/route/asic_db.json | 119 ++++++++ tests/dump_input/route/config_db.json | 9 + tests/dump_tests/module_tests/route_test.py | 229 +++++++++++++++ 5 files changed, 685 insertions(+) create mode 100644 dump/plugins/route.py create mode 100644 tests/dump_input/route/appl_db.json create mode 100644 tests/dump_input/route/asic_db.json create mode 100644 tests/dump_input/route/config_db.json create mode 100644 tests/dump_tests/module_tests/route_test.py diff --git a/dump/plugins/route.py b/dump/plugins/route.py new file mode 100644 index 0000000000..32a9818aad --- /dev/null +++ b/dump/plugins/route.py @@ -0,0 +1,294 @@ +import json, re, copy +from dump.match_infra import MatchEngine, MatchRequest +from dump.helper import create_template_dict, verbose_print +from .executor import Executor + +NH = "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP" +NH_GRP = "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP" +RIF = "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE" +CPU_PORT = "ASIC_STATE:SAI_OBJECT_TYPE_PORT" + +def get_route_pattern(dest): + return "*\"dest\":\"" + dest + "\"*" + +def get_vr_oid(asic_route_entry): + matches = re.findall("\{.*\}", asic_route_entry) + key_dict = {} + if matches: + try: + key_dict = json.loads(matches[0]) + except Exception as e: + pass + return key_dict.get("vr", "") + + +class NextHopGroupMatchOptimizer(): + """ + A Stateful Wrapper which optimizes the the queries by caching the redis keys. + Will be used for these ASIC keys in particular + 1) SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER + 2) SAI_OBJECT_TYPE_NEXT_HOP + 3) SAI_OBJECT_TYPE_ROUTER_INTERFACE + Note: Caches all the kv pairs for a key + """ + def __init__(self, m_engine): + self.key_cache = dict() + self.m_engine = m_engine + + def mutate_request(self, req): + fv_requested = [] + ret_just_keys = req.just_keys + fv_requested = copy.deepcopy(req.return_fields) + if ret_just_keys: + req.just_keys = False + req.return_fields = [] + return req, fv_requested, ret_just_keys + + def mutate_response(self, ret, fv_requested, ret_just_keys): + if not ret_just_keys: + return ret + new_ret = {"error" : "", "keys" : [], "return_values" : {}} + for key_fv in ret["keys"]: + if isinstance(key_fv, dict): + keys = key_fv.keys() + new_ret["keys"].extend(keys) + for key in keys: + new_ret["return_values"][key] = {} + for field in fv_requested: + new_ret["return_values"][key][field] = key_fv[key][field] + return new_ret + + def fill_cache(self, ret): + for key_fv in ret["keys"]: + keys = key_fv.keys() + for key in keys: + self.key_cache[key] = key_fv[key] + + def fetch_from_cache(self, key, req): + verbose_print("Cache Hit for Key: {}".format(key)) + new_ret = {"error" : "", "keys" : [], "return_values" : {}} + if not req.just_keys: + new_ret["keys"].append(self.key_cache[key]) + else: + new_ret["keys"].append(key) + if req.return_fields: + new_ret["return_values"][key] = {} + for field in req.return_fields: + new_ret["return_values"][key][field] = self.key_cache[key][field] + return new_ret + + def fetch(self, req): + key = req.table + ":" + req.key_pattern + if key in self.key_cache: + return self.fetch_from_cache(key, req) + else: + req, fv_requested, ret_just_keys = self.mutate_request(req) + ret = self.m_engine.fetch(req) + if ret["error"]: + return ret + self.fill_cache(ret) + return self.mutate_response(ret, fv_requested, ret_just_keys) + +class Route(Executor): + """ + Debug Dump Plugin for Route Module + """ + ARG_NAME = "destination_network" + + def __init__(self): + self.match_engine = MatchEngine() + self.nhgrp_match_engine = NextHopGroupMatchOptimizer(self.match_engine) + self.ret_temp = {} + self.ns = '' + self.dest_net = '' + self.nh_id = '' + self.nh_type = '' + + def get_all_args(self, ns=""): + req = MatchRequest(db="APPL_DB", table="ROUTE_TABLE", key_pattern="*", ns=self.ns) + ret = self.match_engine.fetch(req) + all_routes = ret.get("keys", []) + return [key[len("ROUTE_TABLE:"):] for key in all_routes] + + def execute(self, params): + self.ret_temp = create_template_dict(dbs=["CONFIG_DB", "APPL_DB", "ASIC_DB"]) + self.dest_net = params[Route.ARG_NAME] + self.ns = params["namespace"] + # CONFIG DB + if not self.init_route_config_info(): + del self.ret_temp["CONFIG_DB"] + # APPL DB + self.init_route_appl_info() + # ASIC DB - ROUTE ENTRY + self.nh_id, vr = self.init_asic_route_entry_info() + # ASIC DB - VIRTUAL ROUTER + self.init_asic_vr_info(vr) + # ASIC DB - KEYS dependent on NEXT HOP ID + self.init_asic_nh() + return self.ret_temp + + def add_to_ret_template(self, table, db, keys, err, add_to_tables_not_found=True): + if not err and keys: + self.ret_temp[db]["keys"].extend(keys) + return keys + elif add_to_tables_not_found: + self.ret_temp[db]["tables_not_found"].extend([table]) + return [] + + def init_route_config_info(self): + req = MatchRequest(db="CONFIG_DB", table="STATIC_ROUTE", key_pattern=self.dest_net, ns=self.ns) + ret = self.match_engine.fetch(req) + return self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) + + def init_route_appl_info(self): + req = MatchRequest(db="APPL_DB", table="ROUTE_TABLE", key_pattern=self.dest_net, ns=self.ns) + ret = self.match_engine.fetch(req) + self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"], True) + + def init_asic_route_entry_info(self): + nh_id_field = "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID" + req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY", key_pattern=get_route_pattern(self.dest_net), + ns=self.ns, return_fields=[nh_id_field]) + ret = self.match_engine.fetch(req) + keys = self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"], True) + asic_route_entry = keys[0] if keys else "" + vr = get_vr_oid(asic_route_entry) + nh_id = ret["return_values"].get(asic_route_entry, {}).get(nh_id_field, "") + return nh_id, vr + + def init_asic_vr_info(self, vr): + ret = {} + if vr: + req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER", key_pattern=vr, ns=self.ns) + ret = self.nhgrp_match_engine.fetch(req) + self.add_to_ret_template("ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER", "ASIC_DB", ret.get("keys", []), ret.get("error", "")) + + def init_asic_nh(self): + self.nh_type = self.get_nh_type() + nh_ex = NHExtractor.initialize(self) + nh_ex.collect() + + def get_nh_type(self): + if not self.nh_id: + return "DROP" + ret = self.nhgrp_match_engine.fetch(MatchRequest(db="ASIC_DB", table=NH_GRP, key_pattern=self.nh_id, ns=self.ns)) + if ret["keys"]: + return NH_GRP + ret = self.nhgrp_match_engine.fetch(MatchRequest(db="ASIC_DB", table=NH, key_pattern=self.nh_id, ns=self.ns)) + if ret["keys"]: + return NH + ret = self.nhgrp_match_engine.fetch(MatchRequest(db="ASIC_DB", table=RIF, key_pattern=self.nh_id, ns=self.ns)) + if ret["keys"]: + return RIF + ret = self.nhgrp_match_engine.fetch(MatchRequest(db="ASIC_DB", table=CPU_PORT, key_pattern=self.nh_id, ns=self.ns)) + if ret["keys"]: + return CPU_PORT + return "DROP" + +class NHExtractor(object): + """ + Base Class for NH_ID Type + """ + @staticmethod + def initialize(route_obj): + if route_obj.nh_type == NH: + return SingleNextHop(route_obj) + elif route_obj.nh_type == NH_GRP: + return MultipleNextHop(route_obj) + elif route_obj.nh_type == RIF: + return DirecAttachedRt(route_obj) + elif route_obj.nh_type == CPU_PORT: + return CPUPort(route_obj) + return NHExtractor(route_obj) + + def __init__(self, route_obj): + self.rt = route_obj + + def collect(self): + pass + + def init_asic_rif_info(self, oid, add_to_tables_not_found=True): + ret = {} + if oid: + req = MatchRequest(db="ASIC_DB", table=RIF, key_pattern=oid, ns=self.rt.ns) + ret = self.rt.nhgrp_match_engine.fetch(req) + return self.rt.add_to_ret_template(RIF, "ASIC_DB", ret.get("keys", []), ret.get("error", ""), add_to_tables_not_found) + + def init_asic_next_hop_info(self, oid, add_to_tables_not_found=True): + ret = {} + if oid: + req = MatchRequest(db="ASIC_DB", table=NH, key_pattern=oid, ns=self.rt.ns, + return_fields=["SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID"]) + ret = self.rt.nhgrp_match_engine.fetch(req) + keys = self.rt.add_to_ret_template(NH, "ASIC_DB", ret.get("keys", []), ret.get("error", ""), add_to_tables_not_found) + nh_key = keys[0] if keys else "" + return ret.get("return_values", {}).get(nh_key, {}).get("SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID", "") + +class CPUPort(NHExtractor): + def collect(self): + req = MatchRequest(db="ASIC_DB", table=CPU_PORT, key_pattern=self.rt.nh_id, ns=self.rt.ns) + ret = self.rt.nhgrp_match_engine.fetch(req) + self.rt.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"], True) + +class DirecAttachedRt(NHExtractor): + def collect(self): + self.init_asic_rif_info(self.rt.nh_id) + +class SingleNextHop(NHExtractor): + def collect(self): + rif_oid = self.init_asic_next_hop_info(self.rt.nh_id) + self.init_asic_rif_info(rif_oid) + +class MultipleNextHop(NHExtractor): + def collect(self): + self.init_asic_nh_group_info(self.rt.nh_id) + nh_oids = self.init_asic_nh_group_members_info(self.rt.nh_id) + rif_oids = self.init_asic_next_hops_info(nh_oids) + self.init_asic_rifs_info(rif_oids) + + def init_asic_nh_group_info(self, oid): + ret = {} + if oid: + req = MatchRequest(db="ASIC_DB", table=NH_GRP, key_pattern=oid, ns=self.rt.ns) + ret = self.rt.nhgrp_match_engine.fetch(req) + self.rt.add_to_ret_template(NH_GRP, "ASIC_DB", ret.get("keys", []), ret.get("error", "")) + + def init_asic_nh_group_members_info(self, oid): + ret = {} + if oid: + req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER", + field="SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID", value=oid, ns=self.rt.ns, + return_fields=["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID"]) + ret = self.rt.nhgrp_match_engine.fetch(req) + keys = self.rt.add_to_ret_template("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER", "ASIC_DB", + ret.get("keys", []), ret.get("error", ""), False) + if not keys: + self.rt.ret_temp["ASIC_DB"]["tables_not_found"].append("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER") + return [ret.get("return_values", {}).get(key, {}).get("SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID", "") for key in keys] + + def init_asic_next_hops_info(self, nh_oids): + rif_oids = [] + for oid in nh_oids: + rif_oid = self.init_asic_next_hop_info(oid, False) + if rif_oid: + rif_oids.append(rif_oid) + if not rif_oids: + self.rt.ret_temp["ASIC_DB"]["tables_not_found"].append("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP") + return rif_oids + + def init_asic_rifs_info(self, rif_oids): + nothing_found = True + for oid in rif_oids: + if self.init_asic_rif_info(oid, False): + nothing_found = False + if nothing_found: + self.rt.ret_temp["ASIC_DB"]["tables_not_found"].append("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") + + + + + + + + + diff --git a/tests/dump_input/route/appl_db.json b/tests/dump_input/route/appl_db.json new file mode 100644 index 0000000000..b2fe1200c4 --- /dev/null +++ b/tests/dump_input/route/appl_db.json @@ -0,0 +1,34 @@ +{ + "ROUTE_TABLE:1.1.1.0/24":{ + "ifname":"Ethernet0", + "nexthop":"0.0.0.0" + }, + "ROUTE_TABLE:10.1.0.32":{ + "ifname":"Loopback0", + "nexthop":"0.0.0.0" + }, + "ROUTE_TABLE:10.212.0.0/16":{ + "ifname":"Ethernet0", + "nexthop":"1.1.1.2" + }, + "ROUTE_TABLE:20.0.0.0/24":{ + "ifname":"Ethernet0", + "nexthop":"1.1.1.2" + }, + "ROUTE_TABLE:fe80::/64":{ + "ifname":"Loopback0", + "nexthop":"::" + }, + "ROUTE_TABLE:20c0:e6e0:0:80::/64": { + "ifname": "PortChannel0001,PortChannel0002,PortChannel0003,PortChannel0004", + "nexthop": "fc00::72,fc00::76,fc00::7a,fc00::7e" + }, + "ROUTE_TABLE:192.168.0.4/24": { + "ifname": "PortChannel0001,PortChannel0002,PortChannel0003,PortChannel0004", + "nexthop": "fc00::72,fc00::76,fc00::7a,fc00::7e" + }, + "ROUTE_TABLE:192.168.0.10/22": { + "ifname": "PortChannel0001,PortChannel0002,PortChannel0003,PortChannel0004", + "nexthop": "fc00::72,fc00::76,fc00::7a,fc00::7e" + } +} \ No newline at end of file diff --git a/tests/dump_input/route/asic_db.json b/tests/dump_input/route/asic_db.json new file mode 100644 index 0000000000..09cd74a99f --- /dev/null +++ b/tests/dump_input/route/asic_db.json @@ -0,0 +1,119 @@ +{ + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"0.0.0.0/0\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000002\"}":{ + "SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION":"SAI_PACKET_ACTION_DROP" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"::/0\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000002\"}":{ + "SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION":"SAI_PACKET_ACTION_DROP" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"1.1.1.1/32\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000002\"}":{ + "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID":"oid:0x1000000000001", + "SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION":"SAI_PACKET_ACTION_FORWARD" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"fe80::/64\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000002\"}":{ + "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID":"oid:0x1000000000001", + "SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION":"SAI_PACKET_ACTION_FORWARD" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_PORT:oid:0x1000000000001": { + "NULL": "NULL" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"10.212.0.0/16\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000002\"}":{ + "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID":"oid:0x40000000002e7" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"20.0.0.0/24\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000002\"}":{ + "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID":"oid:0x40000000002e7" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP:oid:0x40000000002e7": { + "SAI_NEXT_HOP_ATTR_IP": "1.1.1.2", + "SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID": "oid:0x60000000002cd", + "SAI_NEXT_HOP_ATTR_TYPE": "SAI_NEXT_HOP_TYPE_IP" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"1.1.1.0/24\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000002\"}":{ + "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID":"oid:0x60000000002cd" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:oid:0x60000000002cd": { + "SAI_ROUTER_INTERFACE_ATTR_MTU": "9100", + "SAI_ROUTER_INTERFACE_ATTR_PORT_ID": "oid:0x1000000000170", + "SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS": "EC:0D:9A:60:39:00", + "SAI_ROUTER_INTERFACE_ATTR_TYPE": "SAI_ROUTER_INTERFACE_TYPE_PORT", + "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": "oid:0x3000000000002" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"20c0:e6e0:0:80::/64\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000002\"}": { + "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID": "oid:0x5000000000689" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"192.168.0.4/24\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000002\"}": { + "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID": "oid:0x5000000000689" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"192.168.0.10/22\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000002\"}": { + "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID": "oid:0x5000000000689" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP:oid:0x5000000000689": { + "SAI_NEXT_HOP_GROUP_ATTR_TYPE": "SAI_NEXT_HOP_GROUP_TYPE_DYNAMIC_UNORDERED_ECMP" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER:oid:0x2d00000000068a": { + "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID": "oid:0x5000000000689", + "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID": "oid:0x400000000067f" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER:oid:0x2d00000000068b": { + "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID": "oid:0x5000000000689", + "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID": "oid:0x400000000066f" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER:oid:0x2d00000000068c": { + "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID": "oid:0x5000000000689", + "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID": "oid:0x4000000000665" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER:oid:0x2d00000000068d": { + "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID": "oid:0x5000000000689", + "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID": "oid:0x4000000000667" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP:oid:0x400000000066f": { + "SAI_NEXT_HOP_ATTR_IP": "fc00::76", + "SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID": "oid:0x60000000005c7", + "SAI_NEXT_HOP_ATTR_TYPE": "SAI_NEXT_HOP_TYPE_IP" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP:oid:0x400000000067f": { + "SAI_NEXT_HOP_ATTR_IP": "fc00::72", + "SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID": "oid:0x60000000005c6", + "SAI_NEXT_HOP_ATTR_TYPE": "SAI_NEXT_HOP_TYPE_IP" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP:oid:0x4000000000665": { + "SAI_NEXT_HOP_ATTR_IP": "fc00::7a", + "SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID": "oid:0x60000000005c8", + "SAI_NEXT_HOP_ATTR_TYPE": "SAI_NEXT_HOP_TYPE_IP" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP:oid:0x4000000000667": { + "SAI_NEXT_HOP_ATTR_IP": "fc00::7e", + "SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID": "oid:0x60000000005c9", + "SAI_NEXT_HOP_ATTR_TYPE": "SAI_NEXT_HOP_TYPE_IP" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:oid:0x60000000005c6": { + "SAI_ROUTER_INTERFACE_ATTR_MTU": "9100", + "SAI_ROUTER_INTERFACE_ATTR_PORT_ID": "oid:0x2000000000599", + "SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS": "1C:34:DA:1D:40:00", + "SAI_ROUTER_INTERFACE_ATTR_TYPE": "SAI_ROUTER_INTERFACE_TYPE_PORT", + "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": "oid:0x3000000000002" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:oid:0x60000000005c7": { + "SAI_ROUTER_INTERFACE_ATTR_MTU": "9100", + "SAI_ROUTER_INTERFACE_ATTR_PORT_ID": "oid:0x200000000059a", + "SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS": "1C:34:DA:1D:40:00", + "SAI_ROUTER_INTERFACE_ATTR_TYPE": "SAI_ROUTER_INTERFACE_TYPE_PORT", + "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": "oid:0x3000000000002" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:oid:0x60000000005c8": { + "SAI_ROUTER_INTERFACE_ATTR_MTU": "9100", + "SAI_ROUTER_INTERFACE_ATTR_PORT_ID": "oid:0x200000000059b", + "SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS": "1C:34:DA:1D:40:00", + "SAI_ROUTER_INTERFACE_ATTR_TYPE": "SAI_ROUTER_INTERFACE_TYPE_PORT", + "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": "oid:0x3000000000002" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER:oid:0x3000000000002": { + "NULL": "NULL" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:oid:0x60000000005c9": { + "SAI_ROUTER_INTERFACE_ATTR_MTU": "9100", + "SAI_ROUTER_INTERFACE_ATTR_PORT_ID": "oid:0x200000000059c", + "SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS": "1C:34:DA:1D:40:00", + "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/route/config_db.json b/tests/dump_input/route/config_db.json new file mode 100644 index 0000000000..00e344326c --- /dev/null +++ b/tests/dump_input/route/config_db.json @@ -0,0 +1,9 @@ +{ + "STATIC_ROUTE|20.0.0.0/24": { + "blackhole": "false", + "distance": "0", + "ifname": ",", + "nexthop": "1.1.1.2", + "nexthop-vrf": "," + } +} diff --git a/tests/dump_tests/module_tests/route_test.py b/tests/dump_tests/module_tests/route_test.py new file mode 100644 index 0000000000..ef4d097583 --- /dev/null +++ b/tests/dump_tests/module_tests/route_test.py @@ -0,0 +1,229 @@ +import os +import unittest +import pytest +from deepdiff import DeepDiff +from mock import patch +from dump.helper import create_template_dict +from dump.plugins.route import Route + +from .mock_sonicv2connector import MockSonicV2Connector + +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") + +# Location for dedicated db's used for UT +Route_files_path = os.path.join(dump_test_input, "route") + +dedicated_dbs = {} +dedicated_dbs['CONFIG_DB'] = os.path.join(Route_files_path, "config_db.json") +dedicated_dbs['APPL_DB'] = os.path.join(Route_files_path, "appl_db.json") +dedicated_dbs['ASIC_DB'] = os.path.join(Route_files_path, "asic_db.json") + +def mock_connector(namespace, use_unix_socket_path=True): + return MockSonicV2Connector(dedicated_dbs, namespace=namespace, use_unix_socket_path=use_unix_socket_path) + +@pytest.fixture(scope="module", autouse=True) +def verbosity_setup(): + print("SETUP") + os.environ["VERBOSE"] = "1" + yield + print("TEARDOWN") + os.environ["VERBOSE"] = "0" + +def get_asic_route_key(dest): + return "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"" + dest + \ + "\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000002\"}" + +@patch("dump.match_infra.SonicV2Connector", mock_connector) +class TestRouteModule(unittest.TestCase): + def test_static_route(self): + """ + Scenario: Fetch the Keys related to a Static Route from CONF, APPL & ASIC DB's + 1) CONF & APPL are straightforward + 2) SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID = SAI_OBJECT_TYPE_NEXT_HOP here + For More details about SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID, check the SAI header in sairoute.h + """ + params = {Route.ARG_NAME : "20.0.0.0/24", "namespace" : ""} + m_route = Route() + returned = m_route.execute(params) + expect = create_template_dict(dbs=["CONFIG_DB", "APPL_DB", "ASIC_DB"]) + expect["CONFIG_DB"]["keys"].append("STATIC_ROUTE|20.0.0.0/24") + expect["APPL_DB"]["keys"].append("ROUTE_TABLE:20.0.0.0/24") + expect["ASIC_DB"]["keys"].append(get_asic_route_key("20.0.0.0/24")) + expect["ASIC_DB"]["keys"].append("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP:oid:0x40000000002e7") + expect["ASIC_DB"]["keys"].append("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:oid:0x60000000002cd") + expect["ASIC_DB"]["keys"].append("ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER:oid:0x3000000000002") + ddiff = DeepDiff(returned, expect, ignore_order=True) + assert not ddiff, ddiff + + def test_ip2me_route(self): + """ + Scenario: Fetch the keys related to a ip2me route from APPL & ASIC DB. + 1) CONF DB doesn't have a ip2me route entry unlike a static route. + 2) APPL is straightforward + 3) SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID = SAI_OBJECT_TYPE_PORT (CPU Port) + 4) Thus, no SAI_OBJECT_TYPE_ROUTER_INTERFACE entry for this route + For More details about SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID, check the SAI header in sairoute.h + """ + params = {Route.ARG_NAME : "fe80::/64", "namespace" : ""} + m_route = Route() + returned = m_route.execute(params) + expect = create_template_dict(dbs=["APPL_DB", "ASIC_DB"]) + expect["APPL_DB"]["keys"].append("ROUTE_TABLE:fe80::/64") + expect["ASIC_DB"]["keys"].append(get_asic_route_key("fe80::/64")) + expect["ASIC_DB"]["keys"].append("ASIC_STATE:SAI_OBJECT_TYPE_PORT:oid:0x1000000000001") + expect["ASIC_DB"]["keys"].append("ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER:oid:0x3000000000002") + ddiff = DeepDiff(returned, expect, ignore_order=True) + assert not ddiff, ddiff + + def test_directly_connected_route(self): + """ + Scenario: Fetch the keys related to a directly connected route from APPL & ASIC DB. + 1) CONF DB doesn't have this route entry + 2) APPL is straightforward + 3) SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID = SAI_OBJECT_TYPE_ROUTER_INTERFACE + For More details about SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID, check the SAI header in sairoute.h + """ + params = {Route.ARG_NAME : "1.1.1.0/24", "namespace" : ""} + m_route = Route() + returned = m_route.execute(params) + expect = create_template_dict(dbs=["APPL_DB", "ASIC_DB"]) + expect["APPL_DB"]["keys"].append("ROUTE_TABLE:1.1.1.0/24") + expect["ASIC_DB"]["keys"].append(get_asic_route_key("1.1.1.0/24")) + expect["ASIC_DB"]["keys"].append("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:oid:0x60000000002cd") + expect["ASIC_DB"]["keys"].append("ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER:oid:0x3000000000002") + ddiff = DeepDiff(returned, expect, ignore_order=True) + assert not ddiff, ddiff + + def test_route_with_next_hop(self): + """ + Scenario: Fetch the keys related to a route with next hop. + 1) CONF DB doesn't have this route entry + 2) APPL is straightforward + 3) SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID = SAI_OBJECT_TYPE_NEXT_HOP + For More details about SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID, check the SAI header in sairoute.h + """ + params = {Route.ARG_NAME : "10.212.0.0/16", "namespace" : ""} + m_route = Route() + returned = m_route.execute(params) + expect = create_template_dict(dbs=["APPL_DB", "ASIC_DB"]) + expect["APPL_DB"]["keys"].append("ROUTE_TABLE:10.212.0.0/16") + expect["ASIC_DB"]["keys"].append(get_asic_route_key("10.212.0.0/16")) + expect["ASIC_DB"]["keys"].append("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP:oid:0x40000000002e7") + expect["ASIC_DB"]["keys"].append("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:oid:0x60000000002cd") + expect["ASIC_DB"]["keys"].append("ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER:oid:0x3000000000002") + ddiff = DeepDiff(returned, expect, ignore_order=True) + assert not ddiff, ddiff + + def test_all_args(self): + """ + Scenario: Verify Whether the get_all_args method is working as expected + """ + m_route = Route() + returned = m_route.get_all_args("") + expect = ["1.1.1.0/24", "10.1.0.32", "10.212.0.0/16", "20.0.0.0/24", "192.168.0.10/22", + "fe80::/64", "20c0:e6e0:0:80::/64", "192.168.0.4/24"] + ddiff = DeepDiff(expect, returned, ignore_order=True) + assert not ddiff, ddiff + + def test_no_next_hop_id(self): + """ + Scenario: Fetch the keys related to a route with no next hop id + 1) CONF DB doesn't have this route entry + 2) APPL is straightforward + 3) SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID = EMPTY + For More details about SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID, check the SAI header in sairoute.h + """ + params = {Route.ARG_NAME : "0.0.0.0/0", "namespace" : ""} + m_route = Route() + returned = m_route.execute(params) + expect = create_template_dict(dbs=["APPL_DB", "ASIC_DB"]) + expect["APPL_DB"]["tables_not_found"].append("ROUTE_TABLE") + expect["ASIC_DB"]["keys"].append(get_asic_route_key("0.0.0.0/0")) + expect["ASIC_DB"]["keys"].append("ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER:oid:0x3000000000002") + ddiff = DeepDiff(returned, expect, ignore_order=True) + assert not ddiff, ddiff + + def get_asic_nh_group_expected(self, asic_route_key): + expect = [] + expect.append(asic_route_key) + exp_nh_group = "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP:oid:0x5000000000689" + exp_nh_group_mem = ["ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER:oid:0x2d00000000068a", + "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER:oid:0x2d00000000068b", + "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER:oid:0x2d00000000068c", + "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER:oid:0x2d00000000068d"] + exp_nh = ["ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP:oid:0x400000000066f", + "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP:oid:0x400000000067f", + "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP:oid:0x4000000000665", + "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP:oid:0x4000000000667"] + exp_rif = ["ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:oid:0x60000000005c6", + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:oid:0x60000000005c7", + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:oid:0x60000000005c8", + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:oid:0x60000000005c9"] + expect.append(exp_nh_group) + expect.extend(exp_nh_group_mem) + expect.extend(exp_nh) + expect.extend(exp_rif) + expect.append("ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER:oid:0x3000000000002") + return expect + + def test_route_with_next_hop_group(self): + """ + Scenario: Fetch the keys related to a route with multiple next hops. + 1) CONF DB doesn't have this route entry + 2) APPL is straightforward + 3) SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID = SAI_OBJECT_TYPE_NEXT_HOP_GROUP + For More details about SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID, check the SAI header in sairoute.h + """ + params = {Route.ARG_NAME : "20c0:e6e0:0:80::/64", "namespace" : ""} + m_route = Route() + returned = m_route.execute(params) + expect = create_template_dict(dbs=["APPL_DB", "ASIC_DB"]) + expect["APPL_DB"]["keys"].append("ROUTE_TABLE:20c0:e6e0:0:80::/64") + expect["ASIC_DB"]["keys"].extend(self.get_asic_nh_group_expected(get_asic_route_key("20c0:e6e0:0:80::/64"))) + ddiff = DeepDiff(returned, expect, ignore_order=True) + assert not ddiff, ddiff + + def test_caching_redis_keys(self): + """ + Scenario: Test the caching mechanism which reduces number of redis calls + """ + m_route = Route() + params = {Route.ARG_NAME : "20c0:e6e0:0:80::/64", "namespace" : ""} + returned = m_route.execute(params) + expect = create_template_dict(dbs=["APPL_DB", "ASIC_DB"]) + expect["APPL_DB"]["keys"].append("ROUTE_TABLE:20c0:e6e0:0:80::/64") + expect["ASIC_DB"]["keys"].extend(self.get_asic_nh_group_expected(get_asic_route_key("20c0:e6e0:0:80::/64"))) + ddiff = DeepDiff(returned, expect, ignore_order=True) + + params = {Route.ARG_NAME : "192.168.0.4/24", "namespace" : ""} + returned = m_route.execute(params) + expect = create_template_dict(dbs=["APPL_DB", "ASIC_DB"]) + expect["APPL_DB"]["keys"].append("ROUTE_TABLE:192.168.0.4/24") + expect["ASIC_DB"]["keys"].extend(self.get_asic_nh_group_expected(get_asic_route_key("192.168.0.4/24"))) + ddiff = DeepDiff(returned, expect, ignore_order=True) + assert not ddiff, ddiff + + params = {Route.ARG_NAME : "192.168.0.10/22", "namespace" : ""} + returned = m_route.execute(params) + expect = create_template_dict(dbs=["APPL_DB", "ASIC_DB"]) + expect["APPL_DB"]["keys"].append("ROUTE_TABLE:192.168.0.10/22") + expect["ASIC_DB"]["keys"].extend(self.get_asic_nh_group_expected(get_asic_route_key("192.168.0.10/22"))) + ddiff = DeepDiff(returned, expect, ignore_order=True) + assert not ddiff, ddiff + + def test_no_route_entry(self): + """ + Scenario: Fetch the keys related to a non-exitent route + """ + params = {Route.ARG_NAME : "192.168.19.45/28", "namespace" : ""} + m_route = Route() + returned = m_route.execute(params) + expect = create_template_dict(dbs=["APPL_DB", "ASIC_DB"]) + expect["APPL_DB"]["tables_not_found"].append("ROUTE_TABLE") + expect["ASIC_DB"]["tables_not_found"].append("ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") + expect["ASIC_DB"]["tables_not_found"].append("ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER") + ddiff = DeepDiff(returned, expect, ignore_order=True) + assert not ddiff, ddiff \ No newline at end of file From 62528c2c4dbd3ab9d5023ae1ec45e24be969b7a8 Mon Sep 17 00:00:00 2001 From: Vivek Reddy Karri Date: Sat, 21 Aug 2021 03:00:50 +0000 Subject: [PATCH 2/5] Changed the UT to use default mock Signed-off-by: Vivek Reddy Karri --- dump/plugins/route.py | 6 +- tests/dump_tests/module_tests/route_test.py | 102 +++++++++++++------- 2 files changed, 71 insertions(+), 37 deletions(-) diff --git a/dump/plugins/route.py b/dump/plugins/route.py index 32a9818aad..cc4c692b27 100644 --- a/dump/plugins/route.py +++ b/dump/plugins/route.py @@ -32,7 +32,7 @@ class NextHopGroupMatchOptimizer(): Note: Caches all the kv pairs for a key """ def __init__(self, m_engine): - self.key_cache = dict() + self.key_cache = dict() self.m_engine = m_engine def mutate_request(self, req): @@ -95,8 +95,8 @@ class Route(Executor): """ ARG_NAME = "destination_network" - def __init__(self): - self.match_engine = MatchEngine() + def __init__(self, match_engine=None): + super().__init__(match_engine) self.nhgrp_match_engine = NextHopGroupMatchOptimizer(self.match_engine) self.ret_temp = {} self.ns = '' diff --git a/tests/dump_tests/module_tests/route_test.py b/tests/dump_tests/module_tests/route_test.py index ef4d097583..093e014d0f 100644 --- a/tests/dump_tests/module_tests/route_test.py +++ b/tests/dump_tests/module_tests/route_test.py @@ -1,44 +1,78 @@ import os import unittest import pytest +import json from deepdiff import DeepDiff from mock import patch from dump.helper import create_template_dict -from dump.plugins.route import Route +from dump.plugins.route import Route +from dump.match_infra import MatchEngine, ConnectionPool +from swsscommon.swsscommon import SonicV2Connector -from .mock_sonicv2connector import MockSonicV2Connector +# 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") - -# Location for dedicated db's used for UT Route_files_path = os.path.join(dump_test_input, "route") +# Define the mock files to read from dedicated_dbs = {} dedicated_dbs['CONFIG_DB'] = os.path.join(Route_files_path, "config_db.json") dedicated_dbs['APPL_DB'] = os.path.join(Route_files_path, "appl_db.json") dedicated_dbs['ASIC_DB'] = os.path.join(Route_files_path, "asic_db.json") -def mock_connector(namespace, use_unix_socket_path=True): - return MockSonicV2Connector(dedicated_dbs, namespace=namespace, use_unix_socket_path=use_unix_socket_path) -@pytest.fixture(scope="module", autouse=True) -def verbosity_setup(): +def populate_mock(db, db_names): + for db_name in db_names: + db.connect(db_name) + # Delete any default data + db.delete_all_by_pattern(db_name, "*") + with open(dedicated_dbs[db_name]) as f: + mock_json = json.load(f) + for key in mock_json: + for field, value in mock_json[key].items(): + db.set(db_name, key, field, value) + + +@pytest.fixture(scope="class", autouse=True) +def match_engine(): + print("SETUP") os.environ["VERBOSE"] = "1" - yield + + # 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) + 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" + def get_asic_route_key(dest): return "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"" + dest + \ "\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000002\"}" -@patch("dump.match_infra.SonicV2Connector", mock_connector) -class TestRouteModule(unittest.TestCase): - def test_static_route(self): +@pytest.mark.usefixtures("match_engine") +class TestRouteModule: + def test_static_route(self, match_engine): """ Scenario: Fetch the Keys related to a Static Route from CONF, APPL & ASIC DB's 1) CONF & APPL are straightforward @@ -46,7 +80,7 @@ def test_static_route(self): For More details about SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID, check the SAI header in sairoute.h """ params = {Route.ARG_NAME : "20.0.0.0/24", "namespace" : ""} - m_route = Route() + m_route = Route(match_engine) returned = m_route.execute(params) expect = create_template_dict(dbs=["CONFIG_DB", "APPL_DB", "ASIC_DB"]) expect["CONFIG_DB"]["keys"].append("STATIC_ROUTE|20.0.0.0/24") @@ -58,7 +92,7 @@ def test_static_route(self): ddiff = DeepDiff(returned, expect, ignore_order=True) assert not ddiff, ddiff - def test_ip2me_route(self): + def test_ip2me_route(self, match_engine): """ Scenario: Fetch the keys related to a ip2me route from APPL & ASIC DB. 1) CONF DB doesn't have a ip2me route entry unlike a static route. @@ -68,7 +102,7 @@ def test_ip2me_route(self): For More details about SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID, check the SAI header in sairoute.h """ params = {Route.ARG_NAME : "fe80::/64", "namespace" : ""} - m_route = Route() + m_route = Route(match_engine) returned = m_route.execute(params) expect = create_template_dict(dbs=["APPL_DB", "ASIC_DB"]) expect["APPL_DB"]["keys"].append("ROUTE_TABLE:fe80::/64") @@ -78,7 +112,7 @@ def test_ip2me_route(self): ddiff = DeepDiff(returned, expect, ignore_order=True) assert not ddiff, ddiff - def test_directly_connected_route(self): + def test_directly_connected_route(self, match_engine): """ Scenario: Fetch the keys related to a directly connected route from APPL & ASIC DB. 1) CONF DB doesn't have this route entry @@ -87,7 +121,7 @@ def test_directly_connected_route(self): For More details about SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID, check the SAI header in sairoute.h """ params = {Route.ARG_NAME : "1.1.1.0/24", "namespace" : ""} - m_route = Route() + m_route = Route(match_engine) returned = m_route.execute(params) expect = create_template_dict(dbs=["APPL_DB", "ASIC_DB"]) expect["APPL_DB"]["keys"].append("ROUTE_TABLE:1.1.1.0/24") @@ -97,7 +131,7 @@ def test_directly_connected_route(self): ddiff = DeepDiff(returned, expect, ignore_order=True) assert not ddiff, ddiff - def test_route_with_next_hop(self): + def test_route_with_next_hop(self, match_engine): """ Scenario: Fetch the keys related to a route with next hop. 1) CONF DB doesn't have this route entry @@ -106,7 +140,7 @@ def test_route_with_next_hop(self): For More details about SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID, check the SAI header in sairoute.h """ params = {Route.ARG_NAME : "10.212.0.0/16", "namespace" : ""} - m_route = Route() + m_route = Route(match_engine) returned = m_route.execute(params) expect = create_template_dict(dbs=["APPL_DB", "ASIC_DB"]) expect["APPL_DB"]["keys"].append("ROUTE_TABLE:10.212.0.0/16") @@ -117,18 +151,18 @@ def test_route_with_next_hop(self): ddiff = DeepDiff(returned, expect, ignore_order=True) assert not ddiff, ddiff - def test_all_args(self): + def test_all_args(self, match_engine): """ Scenario: Verify Whether the get_all_args method is working as expected """ - m_route = Route() + m_route = Route(match_engine) returned = m_route.get_all_args("") expect = ["1.1.1.0/24", "10.1.0.32", "10.212.0.0/16", "20.0.0.0/24", "192.168.0.10/22", "fe80::/64", "20c0:e6e0:0:80::/64", "192.168.0.4/24"] ddiff = DeepDiff(expect, returned, ignore_order=True) assert not ddiff, ddiff - def test_no_next_hop_id(self): + def test_no_next_hop_id(self, match_engine): """ Scenario: Fetch the keys related to a route with no next hop id 1) CONF DB doesn't have this route entry @@ -137,7 +171,7 @@ def test_no_next_hop_id(self): For More details about SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID, check the SAI header in sairoute.h """ params = {Route.ARG_NAME : "0.0.0.0/0", "namespace" : ""} - m_route = Route() + m_route = Route(match_engine) returned = m_route.execute(params) expect = create_template_dict(dbs=["APPL_DB", "ASIC_DB"]) expect["APPL_DB"]["tables_not_found"].append("ROUTE_TABLE") @@ -168,8 +202,8 @@ def get_asic_nh_group_expected(self, asic_route_key): expect.extend(exp_rif) expect.append("ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER:oid:0x3000000000002") return expect - - def test_route_with_next_hop_group(self): + + def test_route_with_next_hop_group(self, match_engine): """ Scenario: Fetch the keys related to a route with multiple next hops. 1) CONF DB doesn't have this route entry @@ -178,26 +212,26 @@ def test_route_with_next_hop_group(self): For More details about SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID, check the SAI header in sairoute.h """ params = {Route.ARG_NAME : "20c0:e6e0:0:80::/64", "namespace" : ""} - m_route = Route() + m_route = Route(match_engine) returned = m_route.execute(params) expect = create_template_dict(dbs=["APPL_DB", "ASIC_DB"]) expect["APPL_DB"]["keys"].append("ROUTE_TABLE:20c0:e6e0:0:80::/64") expect["ASIC_DB"]["keys"].extend(self.get_asic_nh_group_expected(get_asic_route_key("20c0:e6e0:0:80::/64"))) ddiff = DeepDiff(returned, expect, ignore_order=True) assert not ddiff, ddiff - - def test_caching_redis_keys(self): + + def test_caching_redis_keys(self, match_engine): """ Scenario: Test the caching mechanism which reduces number of redis calls """ - m_route = Route() + m_route = Route(match_engine) params = {Route.ARG_NAME : "20c0:e6e0:0:80::/64", "namespace" : ""} returned = m_route.execute(params) expect = create_template_dict(dbs=["APPL_DB", "ASIC_DB"]) expect["APPL_DB"]["keys"].append("ROUTE_TABLE:20c0:e6e0:0:80::/64") expect["ASIC_DB"]["keys"].extend(self.get_asic_nh_group_expected(get_asic_route_key("20c0:e6e0:0:80::/64"))) ddiff = DeepDiff(returned, expect, ignore_order=True) - + params = {Route.ARG_NAME : "192.168.0.4/24", "namespace" : ""} returned = m_route.execute(params) expect = create_template_dict(dbs=["APPL_DB", "ASIC_DB"]) @@ -205,7 +239,7 @@ def test_caching_redis_keys(self): expect["ASIC_DB"]["keys"].extend(self.get_asic_nh_group_expected(get_asic_route_key("192.168.0.4/24"))) ddiff = DeepDiff(returned, expect, ignore_order=True) assert not ddiff, ddiff - + params = {Route.ARG_NAME : "192.168.0.10/22", "namespace" : ""} returned = m_route.execute(params) expect = create_template_dict(dbs=["APPL_DB", "ASIC_DB"]) @@ -213,13 +247,13 @@ def test_caching_redis_keys(self): expect["ASIC_DB"]["keys"].extend(self.get_asic_nh_group_expected(get_asic_route_key("192.168.0.10/22"))) ddiff = DeepDiff(returned, expect, ignore_order=True) assert not ddiff, ddiff - - def test_no_route_entry(self): + + def test_no_route_entry(self, match_engine): """ Scenario: Fetch the keys related to a non-exitent route """ params = {Route.ARG_NAME : "192.168.19.45/28", "namespace" : ""} - m_route = Route() + m_route = Route(match_engine) returned = m_route.execute(params) expect = create_template_dict(dbs=["APPL_DB", "ASIC_DB"]) expect["APPL_DB"]["tables_not_found"].append("ROUTE_TABLE") From 2b7dd3dfd2f1573585fc8e452bbebbe15e384ceb Mon Sep 17 00:00:00 2001 From: Vivek Reddy Karri Date: Sat, 21 Aug 2021 03:02:34 +0000 Subject: [PATCH 3/5] Ran Code beautifier Signed-off-by: Vivek Reddy Karri --- dump/plugins/route.py | 114 ++++++++++---------- tests/dump_tests/module_tests/route_test.py | 57 +++++----- 2 files changed, 87 insertions(+), 84 deletions(-) diff --git a/dump/plugins/route.py b/dump/plugins/route.py index cc4c692b27..78e4dbfef2 100644 --- a/dump/plugins/route.py +++ b/dump/plugins/route.py @@ -1,4 +1,6 @@ -import json, re, copy +import json +import re +import copy from dump.match_infra import MatchEngine, MatchRequest from dump.helper import create_template_dict, verbose_print from .executor import Executor @@ -8,11 +10,13 @@ RIF = "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE" CPU_PORT = "ASIC_STATE:SAI_OBJECT_TYPE_PORT" + def get_route_pattern(dest): return "*\"dest\":\"" + dest + "\"*" + def get_vr_oid(asic_route_entry): - matches = re.findall("\{.*\}", asic_route_entry) + matches = re.findall(r"\{.*\}", asic_route_entry) key_dict = {} if matches: try: @@ -31,10 +35,11 @@ class NextHopGroupMatchOptimizer(): 3) SAI_OBJECT_TYPE_ROUTER_INTERFACE Note: Caches all the kv pairs for a key """ + def __init__(self, m_engine): self.key_cache = dict() self.m_engine = m_engine - + def mutate_request(self, req): fv_requested = [] ret_just_keys = req.just_keys @@ -43,11 +48,11 @@ def mutate_request(self, req): req.just_keys = False req.return_fields = [] return req, fv_requested, ret_just_keys - + def mutate_response(self, ret, fv_requested, ret_just_keys): if not ret_just_keys: return ret - new_ret = {"error" : "", "keys" : [], "return_values" : {}} + new_ret = {"error": "", "keys": [], "return_values": {}} for key_fv in ret["keys"]: if isinstance(key_fv, dict): keys = key_fv.keys() @@ -56,17 +61,17 @@ def mutate_response(self, ret, fv_requested, ret_just_keys): new_ret["return_values"][key] = {} for field in fv_requested: new_ret["return_values"][key][field] = key_fv[key][field] - return new_ret - + return new_ret + def fill_cache(self, ret): for key_fv in ret["keys"]: keys = key_fv.keys() for key in keys: self.key_cache[key] = key_fv[key] - + def fetch_from_cache(self, key, req): verbose_print("Cache Hit for Key: {}".format(key)) - new_ret = {"error" : "", "keys" : [], "return_values" : {}} + new_ret = {"error": "", "keys": [], "return_values": {}} if not req.just_keys: new_ret["keys"].append(self.key_cache[key]) else: @@ -76,7 +81,7 @@ def fetch_from_cache(self, key, req): for field in req.return_fields: new_ret["return_values"][key][field] = self.key_cache[key][field] return new_ret - + def fetch(self, req): key = req.table + ":" + req.key_pattern if key in self.key_cache: @@ -88,13 +93,14 @@ def fetch(self, req): return ret self.fill_cache(ret) return self.mutate_response(ret, fv_requested, ret_just_keys) - + + class Route(Executor): """ Debug Dump Plugin for Route Module """ ARG_NAME = "destination_network" - + def __init__(self, match_engine=None): super().__init__(match_engine) self.nhgrp_match_engine = NextHopGroupMatchOptimizer(self.match_engine) @@ -103,13 +109,13 @@ def __init__(self, match_engine=None): self.dest_net = '' self.nh_id = '' self.nh_type = '' - + def get_all_args(self, ns=""): req = MatchRequest(db="APPL_DB", table="ROUTE_TABLE", key_pattern="*", ns=self.ns) ret = self.match_engine.fetch(req) all_routes = ret.get("keys", []) return [key[len("ROUTE_TABLE:"):] for key in all_routes] - + def execute(self, params): self.ret_temp = create_template_dict(dbs=["CONFIG_DB", "APPL_DB", "ASIC_DB"]) self.dest_net = params[Route.ARG_NAME] @@ -126,7 +132,7 @@ def execute(self, params): # ASIC DB - KEYS dependent on NEXT HOP ID self.init_asic_nh() return self.ret_temp - + def add_to_ret_template(self, table, db, keys, err, add_to_tables_not_found=True): if not err and keys: self.ret_temp[db]["keys"].extend(keys) @@ -134,20 +140,20 @@ def add_to_ret_template(self, table, db, keys, err, add_to_tables_not_found=True elif add_to_tables_not_found: self.ret_temp[db]["tables_not_found"].extend([table]) return [] - + def init_route_config_info(self): req = MatchRequest(db="CONFIG_DB", table="STATIC_ROUTE", key_pattern=self.dest_net, ns=self.ns) ret = self.match_engine.fetch(req) return self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) - + def init_route_appl_info(self): req = MatchRequest(db="APPL_DB", table="ROUTE_TABLE", key_pattern=self.dest_net, ns=self.ns) ret = self.match_engine.fetch(req) self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"], True) - + def init_asic_route_entry_info(self): nh_id_field = "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID" - req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY", key_pattern=get_route_pattern(self.dest_net), + req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY", key_pattern=get_route_pattern(self.dest_net), ns=self.ns, return_fields=[nh_id_field]) ret = self.match_engine.fetch(req) keys = self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"], True) @@ -162,29 +168,30 @@ def init_asic_vr_info(self, vr): req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER", key_pattern=vr, ns=self.ns) ret = self.nhgrp_match_engine.fetch(req) self.add_to_ret_template("ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER", "ASIC_DB", ret.get("keys", []), ret.get("error", "")) - + def init_asic_nh(self): self.nh_type = self.get_nh_type() nh_ex = NHExtractor.initialize(self) nh_ex.collect() - + def get_nh_type(self): - if not self.nh_id: + if not self.nh_id: return "DROP" ret = self.nhgrp_match_engine.fetch(MatchRequest(db="ASIC_DB", table=NH_GRP, key_pattern=self.nh_id, ns=self.ns)) - if ret["keys"]: + if ret["keys"]: return NH_GRP ret = self.nhgrp_match_engine.fetch(MatchRequest(db="ASIC_DB", table=NH, key_pattern=self.nh_id, ns=self.ns)) - if ret["keys"]: + if ret["keys"]: return NH ret = self.nhgrp_match_engine.fetch(MatchRequest(db="ASIC_DB", table=RIF, key_pattern=self.nh_id, ns=self.ns)) - if ret["keys"]: + if ret["keys"]: return RIF ret = self.nhgrp_match_engine.fetch(MatchRequest(db="ASIC_DB", table=CPU_PORT, key_pattern=self.nh_id, ns=self.ns)) - if ret["keys"]: + if ret["keys"]: return CPU_PORT - return "DROP" - + return "DROP" + + class NHExtractor(object): """ Base Class for NH_ID Type @@ -198,22 +205,22 @@ def initialize(route_obj): elif route_obj.nh_type == RIF: return DirecAttachedRt(route_obj) elif route_obj.nh_type == CPU_PORT: - return CPUPort(route_obj) + return CPUPort(route_obj) return NHExtractor(route_obj) - + def __init__(self, route_obj): self.rt = route_obj def collect(self): pass - + def init_asic_rif_info(self, oid, add_to_tables_not_found=True): ret = {} - if oid: + if oid: req = MatchRequest(db="ASIC_DB", table=RIF, key_pattern=oid, ns=self.rt.ns) ret = self.rt.nhgrp_match_engine.fetch(req) return self.rt.add_to_ret_template(RIF, "ASIC_DB", ret.get("keys", []), ret.get("error", ""), add_to_tables_not_found) - + def init_asic_next_hop_info(self, oid, add_to_tables_not_found=True): ret = {} if oid: @@ -222,50 +229,54 @@ def init_asic_next_hop_info(self, oid, add_to_tables_not_found=True): ret = self.rt.nhgrp_match_engine.fetch(req) keys = self.rt.add_to_ret_template(NH, "ASIC_DB", ret.get("keys", []), ret.get("error", ""), add_to_tables_not_found) nh_key = keys[0] if keys else "" - return ret.get("return_values", {}).get(nh_key, {}).get("SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID", "") - + return ret.get("return_values", {}).get(nh_key, {}).get("SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID", "") + + class CPUPort(NHExtractor): def collect(self): req = MatchRequest(db="ASIC_DB", table=CPU_PORT, key_pattern=self.rt.nh_id, ns=self.rt.ns) ret = self.rt.nhgrp_match_engine.fetch(req) self.rt.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"], True) + class DirecAttachedRt(NHExtractor): def collect(self): - self.init_asic_rif_info(self.rt.nh_id) - + self.init_asic_rif_info(self.rt.nh_id) + + class SingleNextHop(NHExtractor): def collect(self): rif_oid = self.init_asic_next_hop_info(self.rt.nh_id) - self.init_asic_rif_info(rif_oid) - + self.init_asic_rif_info(rif_oid) + + class MultipleNextHop(NHExtractor): def collect(self): self.init_asic_nh_group_info(self.rt.nh_id) nh_oids = self.init_asic_nh_group_members_info(self.rt.nh_id) rif_oids = self.init_asic_next_hops_info(nh_oids) self.init_asic_rifs_info(rif_oids) - + def init_asic_nh_group_info(self, oid): ret = {} if oid: req = MatchRequest(db="ASIC_DB", table=NH_GRP, key_pattern=oid, ns=self.rt.ns) ret = self.rt.nhgrp_match_engine.fetch(req) self.rt.add_to_ret_template(NH_GRP, "ASIC_DB", ret.get("keys", []), ret.get("error", "")) - + def init_asic_nh_group_members_info(self, oid): ret = {} if oid: - req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER", - field="SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID", value=oid, ns=self.rt.ns, + req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER", + field="SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID", value=oid, ns=self.rt.ns, return_fields=["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID"]) - ret = self.rt.nhgrp_match_engine.fetch(req) - keys = self.rt.add_to_ret_template("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER", "ASIC_DB", + ret = self.rt.nhgrp_match_engine.fetch(req) + keys = self.rt.add_to_ret_template("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER", "ASIC_DB", ret.get("keys", []), ret.get("error", ""), False) if not keys: self.rt.ret_temp["ASIC_DB"]["tables_not_found"].append("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER") return [ret.get("return_values", {}).get(key, {}).get("SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID", "") for key in keys] - + def init_asic_next_hops_info(self, nh_oids): rif_oids = [] for oid in nh_oids: @@ -275,7 +286,7 @@ def init_asic_next_hops_info(self, nh_oids): if not rif_oids: self.rt.ret_temp["ASIC_DB"]["tables_not_found"].append("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP") return rif_oids - + def init_asic_rifs_info(self, rif_oids): nothing_found = True for oid in rif_oids: @@ -283,12 +294,3 @@ def init_asic_rifs_info(self, rif_oids): nothing_found = False if nothing_found: self.rt.ret_temp["ASIC_DB"]["tables_not_found"].append("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - - - - - - - - - diff --git a/tests/dump_tests/module_tests/route_test.py b/tests/dump_tests/module_tests/route_test.py index 093e014d0f..e45f0e1afc 100644 --- a/tests/dump_tests/module_tests/route_test.py +++ b/tests/dump_tests/module_tests/route_test.py @@ -19,8 +19,8 @@ # Define the mock files to read from dedicated_dbs = {} -dedicated_dbs['CONFIG_DB'] = os.path.join(Route_files_path, "config_db.json") -dedicated_dbs['APPL_DB'] = os.path.join(Route_files_path, "appl_db.json") +dedicated_dbs['CONFIG_DB'] = os.path.join(Route_files_path, "config_db.json") +dedicated_dbs['APPL_DB'] = os.path.join(Route_files_path, "appl_db.json") dedicated_dbs['ASIC_DB'] = os.path.join(Route_files_path, "asic_db.json") @@ -57,7 +57,7 @@ def match_engine(): conn_pool = ConnectionPool() DEF_NS = '' # Default Namespace conn_pool.cache = {DEF_NS: {'conn': db, - 'connected_to': set(db_names)}} + 'connected_to': set(db_names)}} # Initialize match_engine match_engine = MatchEngine(conn_pool) @@ -68,7 +68,8 @@ def match_engine(): def get_asic_route_key(dest): return "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"" + dest + \ - "\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000002\"}" + "\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000002\"}" + @pytest.mark.usefixtures("match_engine") class TestRouteModule: @@ -79,7 +80,7 @@ def test_static_route(self, match_engine): 2) SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID = SAI_OBJECT_TYPE_NEXT_HOP here For More details about SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID, check the SAI header in sairoute.h """ - params = {Route.ARG_NAME : "20.0.0.0/24", "namespace" : ""} + params = {Route.ARG_NAME: "20.0.0.0/24", "namespace": ""} m_route = Route(match_engine) returned = m_route.execute(params) expect = create_template_dict(dbs=["CONFIG_DB", "APPL_DB", "ASIC_DB"]) @@ -91,7 +92,7 @@ def test_static_route(self, match_engine): expect["ASIC_DB"]["keys"].append("ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER:oid:0x3000000000002") ddiff = DeepDiff(returned, expect, ignore_order=True) assert not ddiff, ddiff - + def test_ip2me_route(self, match_engine): """ Scenario: Fetch the keys related to a ip2me route from APPL & ASIC DB. @@ -99,9 +100,9 @@ def test_ip2me_route(self, match_engine): 2) APPL is straightforward 3) SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID = SAI_OBJECT_TYPE_PORT (CPU Port) 4) Thus, no SAI_OBJECT_TYPE_ROUTER_INTERFACE entry for this route - For More details about SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID, check the SAI header in sairoute.h + For More details about SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID, check the SAI header in sairoute.h """ - params = {Route.ARG_NAME : "fe80::/64", "namespace" : ""} + params = {Route.ARG_NAME: "fe80::/64", "namespace": ""} m_route = Route(match_engine) returned = m_route.execute(params) expect = create_template_dict(dbs=["APPL_DB", "ASIC_DB"]) @@ -111,16 +112,16 @@ def test_ip2me_route(self, match_engine): expect["ASIC_DB"]["keys"].append("ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER:oid:0x3000000000002") ddiff = DeepDiff(returned, expect, ignore_order=True) assert not ddiff, ddiff - + def test_directly_connected_route(self, match_engine): """ Scenario: Fetch the keys related to a directly connected route from APPL & ASIC DB. 1) CONF DB doesn't have this route entry 2) APPL is straightforward 3) SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID = SAI_OBJECT_TYPE_ROUTER_INTERFACE - For More details about SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID, check the SAI header in sairoute.h + For More details about SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID, check the SAI header in sairoute.h """ - params = {Route.ARG_NAME : "1.1.1.0/24", "namespace" : ""} + params = {Route.ARG_NAME: "1.1.1.0/24", "namespace": ""} m_route = Route(match_engine) returned = m_route.execute(params) expect = create_template_dict(dbs=["APPL_DB", "ASIC_DB"]) @@ -130,16 +131,16 @@ def test_directly_connected_route(self, match_engine): expect["ASIC_DB"]["keys"].append("ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER:oid:0x3000000000002") ddiff = DeepDiff(returned, expect, ignore_order=True) assert not ddiff, ddiff - + def test_route_with_next_hop(self, match_engine): """ Scenario: Fetch the keys related to a route with next hop. 1) CONF DB doesn't have this route entry 2) APPL is straightforward 3) SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID = SAI_OBJECT_TYPE_NEXT_HOP - For More details about SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID, check the SAI header in sairoute.h + For More details about SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID, check the SAI header in sairoute.h """ - params = {Route.ARG_NAME : "10.212.0.0/16", "namespace" : ""} + params = {Route.ARG_NAME: "10.212.0.0/16", "namespace": ""} m_route = Route(match_engine) returned = m_route.execute(params) expect = create_template_dict(dbs=["APPL_DB", "ASIC_DB"]) @@ -161,25 +162,25 @@ def test_all_args(self, match_engine): "fe80::/64", "20c0:e6e0:0:80::/64", "192.168.0.4/24"] ddiff = DeepDiff(expect, returned, ignore_order=True) assert not ddiff, ddiff - + def test_no_next_hop_id(self, match_engine): """ Scenario: Fetch the keys related to a route with no next hop id 1) CONF DB doesn't have this route entry 2) APPL is straightforward 3) SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID = EMPTY - For More details about SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID, check the SAI header in sairoute.h + For More details about SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID, check the SAI header in sairoute.h """ - params = {Route.ARG_NAME : "0.0.0.0/0", "namespace" : ""} + params = {Route.ARG_NAME: "0.0.0.0/0", "namespace": ""} m_route = Route(match_engine) returned = m_route.execute(params) expect = create_template_dict(dbs=["APPL_DB", "ASIC_DB"]) expect["APPL_DB"]["tables_not_found"].append("ROUTE_TABLE") expect["ASIC_DB"]["keys"].append(get_asic_route_key("0.0.0.0/0")) expect["ASIC_DB"]["keys"].append("ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER:oid:0x3000000000002") - ddiff = DeepDiff(returned, expect, ignore_order=True) + ddiff = DeepDiff(returned, expect, ignore_order=True) assert not ddiff, ddiff - + def get_asic_nh_group_expected(self, asic_route_key): expect = [] expect.append(asic_route_key) @@ -188,7 +189,7 @@ def get_asic_nh_group_expected(self, asic_route_key): "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER:oid:0x2d00000000068b", "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER:oid:0x2d00000000068c", "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER:oid:0x2d00000000068d"] - exp_nh = ["ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP:oid:0x400000000066f", + exp_nh = ["ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP:oid:0x400000000066f", "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP:oid:0x400000000067f", "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP:oid:0x4000000000665", "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP:oid:0x4000000000667"] @@ -209,9 +210,9 @@ def test_route_with_next_hop_group(self, match_engine): 1) CONF DB doesn't have this route entry 2) APPL is straightforward 3) SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID = SAI_OBJECT_TYPE_NEXT_HOP_GROUP - For More details about SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID, check the SAI header in sairoute.h + For More details about SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID, check the SAI header in sairoute.h """ - params = {Route.ARG_NAME : "20c0:e6e0:0:80::/64", "namespace" : ""} + params = {Route.ARG_NAME: "20c0:e6e0:0:80::/64", "namespace": ""} m_route = Route(match_engine) returned = m_route.execute(params) expect = create_template_dict(dbs=["APPL_DB", "ASIC_DB"]) @@ -225,14 +226,14 @@ def test_caching_redis_keys(self, match_engine): Scenario: Test the caching mechanism which reduces number of redis calls """ m_route = Route(match_engine) - params = {Route.ARG_NAME : "20c0:e6e0:0:80::/64", "namespace" : ""} + params = {Route.ARG_NAME: "20c0:e6e0:0:80::/64", "namespace": ""} returned = m_route.execute(params) expect = create_template_dict(dbs=["APPL_DB", "ASIC_DB"]) expect["APPL_DB"]["keys"].append("ROUTE_TABLE:20c0:e6e0:0:80::/64") expect["ASIC_DB"]["keys"].extend(self.get_asic_nh_group_expected(get_asic_route_key("20c0:e6e0:0:80::/64"))) ddiff = DeepDiff(returned, expect, ignore_order=True) - params = {Route.ARG_NAME : "192.168.0.4/24", "namespace" : ""} + params = {Route.ARG_NAME: "192.168.0.4/24", "namespace": ""} returned = m_route.execute(params) expect = create_template_dict(dbs=["APPL_DB", "ASIC_DB"]) expect["APPL_DB"]["keys"].append("ROUTE_TABLE:192.168.0.4/24") @@ -240,7 +241,7 @@ def test_caching_redis_keys(self, match_engine): ddiff = DeepDiff(returned, expect, ignore_order=True) assert not ddiff, ddiff - params = {Route.ARG_NAME : "192.168.0.10/22", "namespace" : ""} + params = {Route.ARG_NAME: "192.168.0.10/22", "namespace": ""} returned = m_route.execute(params) expect = create_template_dict(dbs=["APPL_DB", "ASIC_DB"]) expect["APPL_DB"]["keys"].append("ROUTE_TABLE:192.168.0.10/22") @@ -252,12 +253,12 @@ def test_no_route_entry(self, match_engine): """ Scenario: Fetch the keys related to a non-exitent route """ - params = {Route.ARG_NAME : "192.168.19.45/28", "namespace" : ""} + params = {Route.ARG_NAME: "192.168.19.45/28", "namespace": ""} m_route = Route(match_engine) returned = m_route.execute(params) expect = create_template_dict(dbs=["APPL_DB", "ASIC_DB"]) expect["APPL_DB"]["tables_not_found"].append("ROUTE_TABLE") expect["ASIC_DB"]["tables_not_found"].append("ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") expect["ASIC_DB"]["tables_not_found"].append("ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER") - ddiff = DeepDiff(returned, expect, ignore_order=True) - assert not ddiff, ddiff \ No newline at end of file + ddiff = DeepDiff(returned, expect, ignore_order=True) + assert not ddiff, ddiff From 8219002d42fef7c583551a2f723dedb8cbec0809 Mon Sep 17 00:00:00 2001 From: Vivek Reddy Karri Date: Sat, 11 Sep 2021 08:20:22 +0000 Subject: [PATCH 4/5] comments addressed Signed-off-by: Vivek Reddy Karri --- dump/plugins/route.py | 32 +-- tests/dump_input/route/appl_db.json | 40 ++-- tests/dump_input/route/asic_db.json | 214 ++++++++++---------- tests/dump_input/route/config_db.json | 14 +- tests/dump_tests/module_tests/route_test.py | 68 +++++-- 5 files changed, 197 insertions(+), 171 deletions(-) diff --git a/dump/plugins/route.py b/dump/plugins/route.py index 78e4dbfef2..3f3e2de677 100644 --- a/dump/plugins/route.py +++ b/dump/plugins/route.py @@ -10,6 +10,13 @@ RIF = "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE" CPU_PORT = "ASIC_STATE:SAI_OBJECT_TYPE_PORT" +OID_HEADERS = { + NH: "0x40", + NH_GRP: "0x50", + RIF: "0x60", + CPU_PORT: "0x10" +} + def get_route_pattern(dest): return "*\"dest\":\"" + dest + "\"*" @@ -70,7 +77,6 @@ def fill_cache(self, ret): self.key_cache[key] = key_fv[key] def fetch_from_cache(self, key, req): - verbose_print("Cache Hit for Key: {}".format(key)) new_ret = {"error": "", "keys": [], "return_values": {}} if not req.just_keys: new_ret["keys"].append(self.key_cache[key]) @@ -85,8 +91,10 @@ def fetch_from_cache(self, key, req): def fetch(self, req): key = req.table + ":" + req.key_pattern if key in self.key_cache: + verbose_print("Cache Hit for Key: {}".format(key)) return self.fetch_from_cache(key, req) else: + verbose_print("Cache Miss for Key: {}".format(key)) req, fv_requested, ret_just_keys = self.mutate_request(req) ret = self.m_engine.fetch(req) if ret["error"]: @@ -149,14 +157,14 @@ def init_route_config_info(self): def init_route_appl_info(self): req = MatchRequest(db="APPL_DB", table="ROUTE_TABLE", key_pattern=self.dest_net, ns=self.ns) ret = self.match_engine.fetch(req) - self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"], True) + self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) def init_asic_route_entry_info(self): nh_id_field = "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID" req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY", key_pattern=get_route_pattern(self.dest_net), ns=self.ns, return_fields=[nh_id_field]) ret = self.match_engine.fetch(req) - keys = self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"], True) + keys = self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) asic_route_entry = keys[0] if keys else "" vr = get_vr_oid(asic_route_entry) nh_id = ret["return_values"].get(asic_route_entry, {}).get(nh_id_field, "") @@ -177,18 +185,10 @@ def init_asic_nh(self): def get_nh_type(self): if not self.nh_id: return "DROP" - ret = self.nhgrp_match_engine.fetch(MatchRequest(db="ASIC_DB", table=NH_GRP, key_pattern=self.nh_id, ns=self.ns)) - if ret["keys"]: - return NH_GRP - ret = self.nhgrp_match_engine.fetch(MatchRequest(db="ASIC_DB", table=NH, key_pattern=self.nh_id, ns=self.ns)) - if ret["keys"]: - return NH - ret = self.nhgrp_match_engine.fetch(MatchRequest(db="ASIC_DB", table=RIF, key_pattern=self.nh_id, ns=self.ns)) - if ret["keys"]: - return RIF - ret = self.nhgrp_match_engine.fetch(MatchRequest(db="ASIC_DB", table=CPU_PORT, key_pattern=self.nh_id, ns=self.ns)) - if ret["keys"]: - return CPU_PORT + oid = self.nh_id.split(":")[-1] + for nh_type in [NH_GRP, NH, RIF, CPU_PORT]: + if oid.startswith(OID_HEADERS.get(nh_type, "")): + return nh_type return "DROP" @@ -236,7 +236,7 @@ class CPUPort(NHExtractor): def collect(self): req = MatchRequest(db="ASIC_DB", table=CPU_PORT, key_pattern=self.rt.nh_id, ns=self.rt.ns) ret = self.rt.nhgrp_match_engine.fetch(req) - self.rt.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"], True) + self.rt.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"]) class DirecAttachedRt(NHExtractor): diff --git a/tests/dump_input/route/appl_db.json b/tests/dump_input/route/appl_db.json index b2fe1200c4..d6ad347265 100644 --- a/tests/dump_input/route/appl_db.json +++ b/tests/dump_input/route/appl_db.json @@ -1,34 +1,34 @@ { "ROUTE_TABLE:1.1.1.0/24":{ - "ifname":"Ethernet0", - "nexthop":"0.0.0.0" + "ifname":"Ethernet0", + "nexthop":"0.0.0.0" }, "ROUTE_TABLE:10.1.0.32":{ - "ifname":"Loopback0", - "nexthop":"0.0.0.0" + "ifname":"Loopback0", + "nexthop":"0.0.0.0" }, "ROUTE_TABLE:10.212.0.0/16":{ - "ifname":"Ethernet0", - "nexthop":"1.1.1.2" + "ifname":"Ethernet0", + "nexthop":"1.1.1.2" }, "ROUTE_TABLE:20.0.0.0/24":{ - "ifname":"Ethernet0", - "nexthop":"1.1.1.2" + "ifname":"Ethernet0", + "nexthop":"1.1.1.2" }, "ROUTE_TABLE:fe80::/64":{ - "ifname":"Loopback0", - "nexthop":"::" + "ifname":"Loopback0", + "nexthop":"::" }, - "ROUTE_TABLE:20c0:e6e0:0:80::/64": { - "ifname": "PortChannel0001,PortChannel0002,PortChannel0003,PortChannel0004", - "nexthop": "fc00::72,fc00::76,fc00::7a,fc00::7e" + "ROUTE_TABLE:20c0:e6e0:0:80::/64":{ + "ifname":"PortChannel0001,PortChannel0002,PortChannel0003,PortChannel0004", + "nexthop":"fc00::72,fc00::76,fc00::7a,fc00::7e" }, - "ROUTE_TABLE:192.168.0.4/24": { - "ifname": "PortChannel0001,PortChannel0002,PortChannel0003,PortChannel0004", - "nexthop": "fc00::72,fc00::76,fc00::7a,fc00::7e" + "ROUTE_TABLE:192.168.0.4/24":{ + "ifname":"PortChannel0001,PortChannel0002,PortChannel0003,PortChannel0004", + "nexthop":"fc00::72,fc00::76,fc00::7a,fc00::7e" }, - "ROUTE_TABLE:192.168.0.10/22": { - "ifname": "PortChannel0001,PortChannel0002,PortChannel0003,PortChannel0004", - "nexthop": "fc00::72,fc00::76,fc00::7a,fc00::7e" + "ROUTE_TABLE:192.168.0.10/22":{ + "ifname":"PortChannel0001,PortChannel0002,PortChannel0003,PortChannel0004", + "nexthop":"fc00::72,fc00::76,fc00::7a,fc00::7e" } -} \ No newline at end of file +} diff --git a/tests/dump_input/route/asic_db.json b/tests/dump_input/route/asic_db.json index 09cd74a99f..8c25630b43 100644 --- a/tests/dump_input/route/asic_db.json +++ b/tests/dump_input/route/asic_db.json @@ -1,119 +1,119 @@ { - "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"0.0.0.0/0\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000002\"}":{ + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"0.0.0.0/0\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000002\"}":{ "SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION":"SAI_PACKET_ACTION_DROP" - }, - "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"::/0\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000002\"}":{ + }, + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"::/0\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000002\"}":{ "SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION":"SAI_PACKET_ACTION_DROP" - }, - "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"1.1.1.1/32\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000002\"}":{ + }, + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"1.1.1.1/32\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000002\"}":{ "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID":"oid:0x1000000000001", "SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION":"SAI_PACKET_ACTION_FORWARD" - }, - "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"fe80::/64\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000002\"}":{ + }, + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"fe80::/64\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000002\"}":{ "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID":"oid:0x1000000000001", "SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION":"SAI_PACKET_ACTION_FORWARD" - }, - "ASIC_STATE:SAI_OBJECT_TYPE_PORT:oid:0x1000000000001": { - "NULL": "NULL" - }, - "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"10.212.0.0/16\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000002\"}":{ + }, + "ASIC_STATE:SAI_OBJECT_TYPE_PORT:oid:0x1000000000001":{ + "NULL":"NULL" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"10.212.0.0/16\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000002\"}":{ "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID":"oid:0x40000000002e7" - }, - "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"20.0.0.0/24\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000002\"}":{ + }, + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"20.0.0.0/24\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000002\"}":{ "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID":"oid:0x40000000002e7" - }, - "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP:oid:0x40000000002e7": { - "SAI_NEXT_HOP_ATTR_IP": "1.1.1.2", - "SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID": "oid:0x60000000002cd", - "SAI_NEXT_HOP_ATTR_TYPE": "SAI_NEXT_HOP_TYPE_IP" - }, - "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"1.1.1.0/24\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000002\"}":{ + }, + "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP:oid:0x40000000002e7":{ + "SAI_NEXT_HOP_ATTR_IP":"1.1.1.2", + "SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID":"oid:0x60000000002cd", + "SAI_NEXT_HOP_ATTR_TYPE":"SAI_NEXT_HOP_TYPE_IP" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"1.1.1.0/24\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000002\"}":{ "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID":"oid:0x60000000002cd" - }, - "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:oid:0x60000000002cd": { - "SAI_ROUTER_INTERFACE_ATTR_MTU": "9100", - "SAI_ROUTER_INTERFACE_ATTR_PORT_ID": "oid:0x1000000000170", - "SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS": "EC:0D:9A:60:39:00", - "SAI_ROUTER_INTERFACE_ATTR_TYPE": "SAI_ROUTER_INTERFACE_TYPE_PORT", - "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": "oid:0x3000000000002" - }, - "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"20c0:e6e0:0:80::/64\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000002\"}": { - "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID": "oid:0x5000000000689" - }, - "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"192.168.0.4/24\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000002\"}": { - "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID": "oid:0x5000000000689" - }, - "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"192.168.0.10/22\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000002\"}": { - "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID": "oid:0x5000000000689" - }, - "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP:oid:0x5000000000689": { - "SAI_NEXT_HOP_GROUP_ATTR_TYPE": "SAI_NEXT_HOP_GROUP_TYPE_DYNAMIC_UNORDERED_ECMP" - }, - "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER:oid:0x2d00000000068a": { - "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID": "oid:0x5000000000689", - "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID": "oid:0x400000000067f" - }, - "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER:oid:0x2d00000000068b": { - "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID": "oid:0x5000000000689", - "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID": "oid:0x400000000066f" - }, - "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER:oid:0x2d00000000068c": { - "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID": "oid:0x5000000000689", - "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID": "oid:0x4000000000665" - }, - "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER:oid:0x2d00000000068d": { - "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID": "oid:0x5000000000689", - "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID": "oid:0x4000000000667" - }, - "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP:oid:0x400000000066f": { - "SAI_NEXT_HOP_ATTR_IP": "fc00::76", - "SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID": "oid:0x60000000005c7", - "SAI_NEXT_HOP_ATTR_TYPE": "SAI_NEXT_HOP_TYPE_IP" - }, - "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP:oid:0x400000000067f": { - "SAI_NEXT_HOP_ATTR_IP": "fc00::72", - "SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID": "oid:0x60000000005c6", - "SAI_NEXT_HOP_ATTR_TYPE": "SAI_NEXT_HOP_TYPE_IP" - }, - "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP:oid:0x4000000000665": { - "SAI_NEXT_HOP_ATTR_IP": "fc00::7a", - "SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID": "oid:0x60000000005c8", - "SAI_NEXT_HOP_ATTR_TYPE": "SAI_NEXT_HOP_TYPE_IP" - }, - "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP:oid:0x4000000000667": { - "SAI_NEXT_HOP_ATTR_IP": "fc00::7e", - "SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID": "oid:0x60000000005c9", - "SAI_NEXT_HOP_ATTR_TYPE": "SAI_NEXT_HOP_TYPE_IP" - }, - "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:oid:0x60000000005c6": { - "SAI_ROUTER_INTERFACE_ATTR_MTU": "9100", - "SAI_ROUTER_INTERFACE_ATTR_PORT_ID": "oid:0x2000000000599", - "SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS": "1C:34:DA:1D:40:00", - "SAI_ROUTER_INTERFACE_ATTR_TYPE": "SAI_ROUTER_INTERFACE_TYPE_PORT", - "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": "oid:0x3000000000002" - }, - "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:oid:0x60000000005c7": { - "SAI_ROUTER_INTERFACE_ATTR_MTU": "9100", - "SAI_ROUTER_INTERFACE_ATTR_PORT_ID": "oid:0x200000000059a", - "SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS": "1C:34:DA:1D:40:00", - "SAI_ROUTER_INTERFACE_ATTR_TYPE": "SAI_ROUTER_INTERFACE_TYPE_PORT", - "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": "oid:0x3000000000002" - }, - "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:oid:0x60000000005c8": { - "SAI_ROUTER_INTERFACE_ATTR_MTU": "9100", - "SAI_ROUTER_INTERFACE_ATTR_PORT_ID": "oid:0x200000000059b", - "SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS": "1C:34:DA:1D:40:00", - "SAI_ROUTER_INTERFACE_ATTR_TYPE": "SAI_ROUTER_INTERFACE_TYPE_PORT", - "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": "oid:0x3000000000002" - }, - "ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER:oid:0x3000000000002": { - "NULL": "NULL" - }, - "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:oid:0x60000000005c9": { - "SAI_ROUTER_INTERFACE_ATTR_MTU": "9100", - "SAI_ROUTER_INTERFACE_ATTR_PORT_ID": "oid:0x200000000059c", - "SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS": "1C:34:DA:1D:40:00", - "SAI_ROUTER_INTERFACE_ATTR_TYPE": "SAI_ROUTER_INTERFACE_TYPE_PORT", - "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": "oid:0x3000000000002" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:oid:0x60000000002cd":{ + "SAI_ROUTER_INTERFACE_ATTR_MTU":"9100", + "SAI_ROUTER_INTERFACE_ATTR_PORT_ID":"oid:0x1000000000170", + "SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS":"EC:0D:9A:60:39:00", + "SAI_ROUTER_INTERFACE_ATTR_TYPE":"SAI_ROUTER_INTERFACE_TYPE_PORT", + "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID":"oid:0x3000000000002" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"20c0:e6e0:0:80::/64\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000002\"}":{ + "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID":"oid:0x5000000000689" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"192.168.0.4/24\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000002\"}":{ + "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID":"oid:0x5000000000689" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"192.168.0.10/22\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000002\"}":{ + "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID":"oid:0x5000000000689" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP:oid:0x5000000000689":{ + "SAI_NEXT_HOP_GROUP_ATTR_TYPE":"SAI_NEXT_HOP_GROUP_TYPE_DYNAMIC_UNORDERED_ECMP" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER:oid:0x2d00000000068a":{ + "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID":"oid:0x5000000000689", + "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID":"oid:0x400000000067f" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER:oid:0x2d00000000068b":{ + "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID":"oid:0x5000000000689", + "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID":"oid:0x400000000066f" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER:oid:0x2d00000000068c":{ + "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID":"oid:0x5000000000689", + "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID":"oid:0x4000000000665" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER:oid:0x2d00000000068d":{ + "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID":"oid:0x5000000000689", + "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID":"oid:0x4000000000667" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP:oid:0x400000000066f":{ + "SAI_NEXT_HOP_ATTR_IP":"fc00::76", + "SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID":"oid:0x60000000005c7", + "SAI_NEXT_HOP_ATTR_TYPE":"SAI_NEXT_HOP_TYPE_IP" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP:oid:0x400000000067f":{ + "SAI_NEXT_HOP_ATTR_IP":"fc00::72", + "SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID":"oid:0x60000000005c6", + "SAI_NEXT_HOP_ATTR_TYPE":"SAI_NEXT_HOP_TYPE_IP" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP:oid:0x4000000000665":{ + "SAI_NEXT_HOP_ATTR_IP":"fc00::7a", + "SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID":"oid:0x60000000005c8", + "SAI_NEXT_HOP_ATTR_TYPE":"SAI_NEXT_HOP_TYPE_IP" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP:oid:0x4000000000667":{ + "SAI_NEXT_HOP_ATTR_IP":"fc00::7e", + "SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID":"oid:0x60000000005c9", + "SAI_NEXT_HOP_ATTR_TYPE":"SAI_NEXT_HOP_TYPE_IP" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:oid:0x60000000005c6":{ + "SAI_ROUTER_INTERFACE_ATTR_MTU":"9100", + "SAI_ROUTER_INTERFACE_ATTR_PORT_ID":"oid:0x2000000000599", + "SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS":"1C:34:DA:1D:40:00", + "SAI_ROUTER_INTERFACE_ATTR_TYPE":"SAI_ROUTER_INTERFACE_TYPE_PORT", + "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID":"oid:0x3000000000002" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:oid:0x60000000005c7":{ + "SAI_ROUTER_INTERFACE_ATTR_MTU":"9100", + "SAI_ROUTER_INTERFACE_ATTR_PORT_ID":"oid:0x200000000059a", + "SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS":"1C:34:DA:1D:40:00", + "SAI_ROUTER_INTERFACE_ATTR_TYPE":"SAI_ROUTER_INTERFACE_TYPE_PORT", + "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID":"oid:0x3000000000002" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:oid:0x60000000005c8":{ + "SAI_ROUTER_INTERFACE_ATTR_MTU":"9100", + "SAI_ROUTER_INTERFACE_ATTR_PORT_ID":"oid:0x200000000059b", + "SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS":"1C:34:DA:1D:40:00", + "SAI_ROUTER_INTERFACE_ATTR_TYPE":"SAI_ROUTER_INTERFACE_TYPE_PORT", + "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID":"oid:0x3000000000002" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER:oid:0x3000000000002":{ + "NULL":"NULL" + }, + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:oid:0x60000000005c9":{ + "SAI_ROUTER_INTERFACE_ATTR_MTU":"9100", + "SAI_ROUTER_INTERFACE_ATTR_PORT_ID":"oid:0x200000000059c", + "SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS":"1C:34:DA:1D:40:00", + "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/route/config_db.json b/tests/dump_input/route/config_db.json index 00e344326c..0d25accd5e 100644 --- a/tests/dump_input/route/config_db.json +++ b/tests/dump_input/route/config_db.json @@ -1,9 +1,9 @@ { - "STATIC_ROUTE|20.0.0.0/24": { - "blackhole": "false", - "distance": "0", - "ifname": ",", - "nexthop": "1.1.1.2", - "nexthop-vrf": "," - } + "STATIC_ROUTE|20.0.0.0/24":{ + "blackhole":"false", + "distance":"0", + "ifname":",", + "nexthop":"1.1.1.2", + "nexthop-vrf":"," + } } diff --git a/tests/dump_tests/module_tests/route_test.py b/tests/dump_tests/module_tests/route_test.py index e45f0e1afc..2103df47c9 100644 --- a/tests/dump_tests/module_tests/route_test.py +++ b/tests/dump_tests/module_tests/route_test.py @@ -225,29 +225,55 @@ def test_caching_redis_keys(self, match_engine): """ Scenario: Test the caching mechanism which reduces number of redis calls """ - m_route = Route(match_engine) - params = {Route.ARG_NAME: "20c0:e6e0:0:80::/64", "namespace": ""} - returned = m_route.execute(params) - expect = create_template_dict(dbs=["APPL_DB", "ASIC_DB"]) - expect["APPL_DB"]["keys"].append("ROUTE_TABLE:20c0:e6e0:0:80::/64") - expect["ASIC_DB"]["keys"].extend(self.get_asic_nh_group_expected(get_asic_route_key("20c0:e6e0:0:80::/64"))) - ddiff = DeepDiff(returned, expect, ignore_order=True) + global num_hits, num_miss, msgs + num_hits, num_miss, msgs = 0, 0, [] - params = {Route.ARG_NAME: "192.168.0.4/24", "namespace": ""} - returned = m_route.execute(params) - expect = create_template_dict(dbs=["APPL_DB", "ASIC_DB"]) - expect["APPL_DB"]["keys"].append("ROUTE_TABLE:192.168.0.4/24") - expect["ASIC_DB"]["keys"].extend(self.get_asic_nh_group_expected(get_asic_route_key("192.168.0.4/24"))) - ddiff = DeepDiff(returned, expect, ignore_order=True) - assert not ddiff, ddiff + def verbose_print_mock(msg): + global num_hits, num_miss, msgs + if "Cache Hit for Key:" in msg: + num_hits = num_hits + 1 + elif "Cache Miss for Key:" in msg: + num_miss = num_miss + 1 + else: + return + msgs.append(msg) - params = {Route.ARG_NAME: "192.168.0.10/22", "namespace": ""} - returned = m_route.execute(params) - expect = create_template_dict(dbs=["APPL_DB", "ASIC_DB"]) - expect["APPL_DB"]["keys"].append("ROUTE_TABLE:192.168.0.10/22") - expect["ASIC_DB"]["keys"].extend(self.get_asic_nh_group_expected(get_asic_route_key("192.168.0.10/22"))) - ddiff = DeepDiff(returned, expect, ignore_order=True) - assert not ddiff, ddiff + with patch("dump.plugins.route.verbose_print", verbose_print_mock): + m_route = Route(match_engine) + params = {Route.ARG_NAME: "20c0:e6e0:0:80::/64", "namespace": ""} + returned = m_route.execute(params) + expect = create_template_dict(dbs=["APPL_DB", "ASIC_DB"]) + expect["APPL_DB"]["keys"].append("ROUTE_TABLE:20c0:e6e0:0:80::/64") + expect["ASIC_DB"]["keys"].extend(self.get_asic_nh_group_expected(get_asic_route_key("20c0:e6e0:0:80::/64"))) + ddiff = DeepDiff(returned, expect, ignore_order=True) + assert not ddiff, ddiff + print(msgs) + assert num_hits == 0 + assert num_miss == 11 + num_hits, num_miss, msgs = 0, 0, [] + + params = {Route.ARG_NAME: "192.168.0.4/24", "namespace": ""} + returned = m_route.execute(params) + expect = create_template_dict(dbs=["APPL_DB", "ASIC_DB"]) + expect["APPL_DB"]["keys"].append("ROUTE_TABLE:192.168.0.4/24") + expect["ASIC_DB"]["keys"].extend(self.get_asic_nh_group_expected(get_asic_route_key("192.168.0.4/24"))) + ddiff = DeepDiff(returned, expect, ignore_order=True) + assert not ddiff, ddiff + print(msgs) + assert num_hits == 10 + assert num_miss == 1 + num_hits, num_miss, msgs = 0, 0, [] + + params = {Route.ARG_NAME: "192.168.0.10/22", "namespace": ""} + returned = m_route.execute(params) + expect = create_template_dict(dbs=["APPL_DB", "ASIC_DB"]) + expect["APPL_DB"]["keys"].append("ROUTE_TABLE:192.168.0.10/22") + expect["ASIC_DB"]["keys"].extend(self.get_asic_nh_group_expected(get_asic_route_key("192.168.0.10/22"))) + ddiff = DeepDiff(returned, expect, ignore_order=True) + assert not ddiff, ddiff + print(msgs) + assert num_hits == 10 + assert num_miss == 1 def test_no_route_entry(self, match_engine): """ From 8b9228bdc14edd1adb1e8d43e8d997a35559c56d Mon Sep 17 00:00:00 2001 From: Vivek Reddy Karri Date: Mon, 11 Oct 2021 16:25:06 +0000 Subject: [PATCH 5/5] Minor Comments Handled Signed-off-by: Vivek Reddy Karri --- dump/plugins/route.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dump/plugins/route.py b/dump/plugins/route.py index 3f3e2de677..387c384427 100644 --- a/dump/plugins/route.py +++ b/dump/plugins/route.py @@ -35,7 +35,7 @@ def get_vr_oid(asic_route_entry): class NextHopGroupMatchOptimizer(): """ - A Stateful Wrapper which optimizes the the queries by caching the redis keys. + A Stateful Wrapper which optimizes the queries by caching the redis keys. Will be used for these ASIC keys in particular 1) SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER 2) SAI_OBJECT_TYPE_NEXT_HOP @@ -44,7 +44,7 @@ class NextHopGroupMatchOptimizer(): """ def __init__(self, m_engine): - self.key_cache = dict() + self.key_cache = {} self.m_engine = m_engine def mutate_request(self, req):