diff --git a/cfgmgr/intfmgr.cpp b/cfgmgr/intfmgr.cpp index a5bc092df9ba..836f8acf9218 100644 --- a/cfgmgr/intfmgr.cpp +++ b/cfgmgr/intfmgr.cpp @@ -428,16 +428,15 @@ bool IntfMgr::doIntfGeneralTask(const vector& keys, string alias(keys[0]); string vlanId; - string subIntfAlias; + string parentAlias; size_t found = alias.find(VLAN_SUB_INTERFACE_SEPARATOR); if (found != string::npos) { // This is a sub interface - // subIntfAlias holds the complete sub interface name - // while alias becomes the parent interface - subIntfAlias = alias; + // alias holds the complete sub interface name + // while parentAlias holds the parent port name vlanId = alias.substr(found + 1); - alias = alias.substr(0, found); + parentAlias = alias.substr(0, found); } bool is_lo = !alias.compare(0, strlen(LOOPBACK_PREFIX), LOOPBACK_PREFIX); string mac = ""; @@ -482,7 +481,7 @@ bool IntfMgr::doIntfGeneralTask(const vector& keys, if (op == SET_COMMAND) { - if (!isIntfStateOk(alias)) + if (!isIntfStateOk(parentAlias.empty() ? alias : parentAlias)) { SWSS_LOG_DEBUG("Interface is not ready, skipping %s", alias.c_str()); return false; @@ -520,59 +519,13 @@ bool IntfMgr::doIntfGeneralTask(const vector& keys, } } - if (!vrf_name.empty()) - { - setIntfVrf(alias, vrf_name); - } - - /*Set the mac of interface*/ - if (!mac.empty()) - { - setIntfMac(alias, mac); - } - else - { - FieldValueTuple fvTuple("mac_addr", MacAddress().to_string()); - data.push_back(fvTuple); - } - - if (!proxy_arp.empty()) + if (!parentAlias.empty()) { - if (!setIntfProxyArp(alias, proxy_arp)) - { - SWSS_LOG_ERROR("Failed to set proxy ARP to \"%s\" state for the \"%s\" interface", proxy_arp.c_str(), alias.c_str()); - return false; - } - - if (!alias.compare(0, strlen(VLAN_PREFIX), VLAN_PREFIX)) - { - FieldValueTuple fvTuple("proxy_arp", proxy_arp); - data.push_back(fvTuple); - } - } - - if (!grat_arp.empty()) - { - if (!setIntfGratArp(alias, grat_arp)) - { - SWSS_LOG_ERROR("Failed to set ARP accept to \"%s\" state for the \"%s\" interface", grat_arp.c_str(), alias.c_str()); - return false; - } - - if (!alias.compare(0, strlen(VLAN_PREFIX), VLAN_PREFIX)) - { - FieldValueTuple fvTuple("grat_arp", grat_arp); - data.push_back(fvTuple); - } - } - - if (!subIntfAlias.empty()) - { - if (m_subIntfList.find(subIntfAlias) == m_subIntfList.end()) + if (m_subIntfList.find(alias) == m_subIntfList.end()) { try { - addHostSubIntf(alias, subIntfAlias, vlanId); + addHostSubIntf(parentAlias, alias, vlanId); } catch (const std::runtime_error &e) { @@ -580,14 +533,14 @@ bool IntfMgr::doIntfGeneralTask(const vector& keys, return false; } - m_subIntfList.insert(subIntfAlias); + m_subIntfList.insert(alias); } if (!mtu.empty()) { try { - setHostSubIntfMtu(subIntfAlias, mtu); + setHostSubIntfMtu(alias, mtu); } catch (const std::runtime_error &e) { @@ -609,7 +562,7 @@ bool IntfMgr::doIntfGeneralTask(const vector& keys, } try { - setHostSubIntfAdminStatus(subIntfAlias, adminStatus); + setHostSubIntfAdminStatus(alias, adminStatus); } catch (const std::runtime_error &e) { @@ -618,10 +571,57 @@ bool IntfMgr::doIntfGeneralTask(const vector& keys, } // set STATE_DB port state - setSubIntfStateOk(subIntfAlias); + setSubIntfStateOk(alias); } - m_appIntfTableProducer.set(subIntfAlias.empty() ? alias : subIntfAlias, data); - m_stateIntfTable.hset(subIntfAlias.empty() ? alias : subIntfAlias, "vrf", vrf_name); + + if (!vrf_name.empty()) + { + setIntfVrf(alias, vrf_name); + } + + /*Set the mac of interface*/ + if (!mac.empty()) + { + setIntfMac(alias, mac); + } + else + { + FieldValueTuple fvTuple("mac_addr", MacAddress().to_string()); + data.push_back(fvTuple); + } + + if (!proxy_arp.empty()) + { + if (!setIntfProxyArp(alias, proxy_arp)) + { + SWSS_LOG_ERROR("Failed to set proxy ARP to \"%s\" state for the \"%s\" interface", proxy_arp.c_str(), alias.c_str()); + return false; + } + + if (!alias.compare(0, strlen(VLAN_PREFIX), VLAN_PREFIX)) + { + FieldValueTuple fvTuple("proxy_arp", proxy_arp); + data.push_back(fvTuple); + } + } + + if (!grat_arp.empty()) + { + if (!setIntfGratArp(alias, grat_arp)) + { + SWSS_LOG_ERROR("Failed to set ARP accept to \"%s\" state for the \"%s\" interface", grat_arp.c_str(), alias.c_str()); + return false; + } + + if (!alias.compare(0, strlen(VLAN_PREFIX), VLAN_PREFIX)) + { + FieldValueTuple fvTuple("grat_arp", grat_arp); + data.push_back(fvTuple); + } + } + + m_appIntfTableProducer.set(alias, data); + m_stateIntfTable.hset(alias, "vrf", vrf_name); } else if (op == DEL_COMMAND) { @@ -640,16 +640,16 @@ bool IntfMgr::doIntfGeneralTask(const vector& keys, m_loopbackIntfList.erase(alias); } - if (!subIntfAlias.empty()) + if (!parentAlias.empty()) { - removeHostSubIntf(subIntfAlias); - m_subIntfList.erase(subIntfAlias); + removeHostSubIntf(alias); + m_subIntfList.erase(alias); - removeSubIntfState(subIntfAlias); + removeSubIntfState(alias); } - m_appIntfTableProducer.del(subIntfAlias.empty() ? alias : subIntfAlias); - m_stateIntfTable.del(subIntfAlias.empty() ? alias : subIntfAlias); + m_appIntfTableProducer.del(alias); + m_stateIntfTable.del(alias); } else { diff --git a/orchagent/intfsorch.cpp b/orchagent/intfsorch.cpp index ffae3decacda..f3fab3cc61e1 100644 --- a/orchagent/intfsorch.cpp +++ b/orchagent/intfsorch.cpp @@ -731,6 +731,7 @@ void IntfsOrch::doTask(Consumer &consumer) { IntfsEntry intfs_entry; intfs_entry.ref_count = 0; + intfs_entry.proxy_arp = false; intfs_entry.vrf_id = vrf_id; m_syncdIntfses[alias] = intfs_entry; m_vrfOrch->increaseVrfRefCount(vrf_id); diff --git a/tests/conftest.py b/tests/conftest.py index d707a3d08ab8..a303c5f17e1a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1003,8 +1003,8 @@ def set_interface_status(self, interface, admin_status): tbl.set(interface, fvs) time.sleep(1) - # deps: acl, fdb_update, fdb, mirror_port_erspan, vlan - def add_ip_address(self, interface, ip): + # deps: acl, fdb_update, fdb, mirror_port_erspan, vlan, sub port intf + def add_ip_address(self, interface, ip, vrf_name=None): if interface.startswith("PortChannel"): tbl_name = "PORTCHANNEL_INTERFACE" elif interface.startswith("Vlan"): @@ -1012,7 +1012,10 @@ def add_ip_address(self, interface, ip): else: tbl_name = "INTERFACE" tbl = swsscommon.Table(self.cdb, tbl_name) - fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) + pairs = [("NULL", "NULL")] + if vrf_name: + pairs = [("vrf_name", vrf_name)] + fvs = swsscommon.FieldValuePairs(pairs) tbl.set(interface, fvs) tbl.set(interface + "|" + ip, fvs) time.sleep(1) diff --git a/tests/test_sub_port_intf.py b/tests/test_sub_port_intf.py index 50745995451d..56efb320b74f 100644 --- a/tests/test_sub_port_intf.py +++ b/tests/test_sub_port_intf.py @@ -10,6 +10,7 @@ CFG_PORT_TABLE_NAME = "PORT" CFG_LAG_TABLE_NAME = "PORTCHANNEL" CFG_LAG_MEMBER_TABLE_NAME = "PORTCHANNEL_MEMBER" +CFG_VRF_TABLE_NAME = "VRF" STATE_PORT_TABLE_NAME = "PORT_TABLE" STATE_LAG_TABLE_NAME = "LAG_TABLE" @@ -27,8 +28,11 @@ ASIC_NEXT_HOP_GROUP_MEMBER_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER" ASIC_LAG_MEMBER_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER" ASIC_HOSTIF_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF" +ASIC_VIRTUAL_ROUTER_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_VIRTUAL_ROUTER" +ASIC_LAG_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_LAG" ADMIN_STATUS = "admin_status" +VRF_NAME = "vrf_name" ETHERNET_PREFIX = "Ethernet" LAG_PREFIX = "PortChannel" @@ -50,6 +54,8 @@ class TestSubPortIntf(object): IPV6_TOME_UNDER_TEST = "fc00::41/128" IPV6_SUBNET_UNDER_TEST = "fc00::40/126" + VRF_UNDER_TEST = "Vrf0" + def connect_dbs(self, dvs): self.app_db = dvs.get_app_db() self.asic_db = dvs.get_asic_db() @@ -57,6 +63,8 @@ def connect_dbs(self, dvs): self.state_db = dvs.get_state_db() dvs.setup_db() + self.default_vrf_oid = self.get_default_vrf_oid() + def get_parent_port_index(self, port_name): if port_name.startswith(ETHERNET_PREFIX): idx = int(port_name[len(ETHERNET_PREFIX):]) @@ -71,8 +79,8 @@ def set_parent_port_oper_status(self, dvs, port_name, status): dvs.servers[srv_idx].runcmd("ip link set dev eth0 " + status) else: assert port_name.startswith(LAG_PREFIX) - dvs.runcmd("bash -c 'echo " + ("1" if status == "up" else "0") + \ - " > /sys/class/net/" + port_name + "/carrier'") + dvs.runcmd("bash -c 'echo " + ("1" if status == "up" else "0") + + " > /sys/class/net/" + port_name + "/carrier'") time.sleep(1) def set_parent_port_admin_status(self, dvs, port_name, status): @@ -84,6 +92,7 @@ def set_parent_port_admin_status(self, dvs, port_name, status): assert port_name.startswith(LAG_PREFIX) tbl_name = CFG_LAG_TABLE_NAME self.config_db.create_entry(tbl_name, port_name, fvs) + time.sleep(1) if port_name.startswith(ETHERNET_PREFIX): self.set_parent_port_oper_status(dvs, port_name, "down") @@ -91,8 +100,13 @@ def set_parent_port_admin_status(self, dvs, port_name, status): else: self.set_parent_port_oper_status(dvs, port_name, "up") - def create_sub_port_intf_profile(self, sub_port_intf_name): + def create_vrf(self, vrf_name): + self.config_db.create_entry(CFG_VRF_TABLE_NAME, vrf_name, {"NULL": "NULL"}) + + def create_sub_port_intf_profile(self, sub_port_intf_name, vrf_name=None): fvs = {ADMIN_STATUS: "up"} + if vrf_name: + fvs[VRF_NAME] = vrf_name self.config_db.create_entry(CFG_VLAN_SUB_INTF_TABLE_NAME, sub_port_intf_name, fvs) @@ -103,11 +117,13 @@ def add_lag_members(self, lag, members): key = "{}|{}".format(lag, member) self.config_db.create_entry(CFG_LAG_MEMBER_TABLE_NAME, key, fvs) - def create_sub_port_intf_profile_appl_db(self, sub_port_intf_name, admin_status): + def create_sub_port_intf_profile_appl_db(self, sub_port_intf_name, admin_status, vrf_name=None): pairs = [ (ADMIN_STATUS, admin_status), ("mtu", "0"), ] + if vrf_name: + pairs.append((VRF_NAME, vrf_name)) fvs = swsscommon.FieldValuePairs(pairs) tbl = swsscommon.ProducerStateTable(self.app_db.db_connection, APP_INTF_TABLE_NAME) @@ -129,11 +145,29 @@ def add_sub_port_intf_ip_addr_appl_db(self, sub_port_intf_name, ip_addr): tbl = swsscommon.ProducerStateTable(self.app_db.db_connection, APP_INTF_TABLE_NAME) tbl.set(sub_port_intf_name + APPL_DB_SEPARATOR + ip_addr, fvs) + def add_route_appl_db(self, ip_prefix, nhop_ips, ifnames, vrf_name=None): + fvs = swsscommon.FieldValuePairs([("nexthop", ",".join(nhop_ips)), ("ifname", ",".join(ifnames))]) + + tbl = swsscommon.ProducerStateTable(self.app_db.db_connection, APP_ROUTE_TABLE_NAME) + tbl.set(vrf_name + APPL_DB_SEPARATOR + ip_prefix if vrf_name else ip_prefix, fvs) + def set_sub_port_intf_admin_status(self, sub_port_intf_name, status): fvs = {ADMIN_STATUS: status} self.config_db.create_entry(CFG_VLAN_SUB_INTF_TABLE_NAME, sub_port_intf_name, fvs) + def remove_vrf(self, vrf_name): + self.config_db.delete_entry(CFG_VRF_TABLE_NAME, vrf_name) + + def check_vrf_removal(self, vrf_oid): + self.asic_db.wait_for_deleted_keys(ASIC_VIRTUAL_ROUTER_TABLE, [vrf_oid]) + + def remove_lag(self, lag): + self.config_db.delete_entry(CFG_LAG_TABLE_NAME, lag) + + def check_lag_removal(self, lag_oid): + self.asic_db.wait_for_deleted_keys(ASIC_LAG_TABLE, [lag_oid]) + def remove_lag_members(self, lag, members): for member in members: key = "{}|{}".format(lag, member) @@ -161,6 +195,10 @@ def remove_sub_port_intf_ip_addr_appl_db(self, sub_port_intf_name, ip_addr): tbl = swsscommon.ProducerStateTable(self.app_db.db_connection, APP_INTF_TABLE_NAME) tbl._del(sub_port_intf_name + APPL_DB_SEPARATOR + ip_addr) + def remove_route_appl_db(self, ip_prefix, vrf_name=None): + tbl = swsscommon.ProducerStateTable(self.app_db.db_connection, APP_ROUTE_TABLE_NAME) + tbl._del(vrf_name + APPL_DB_SEPARATOR + ip_prefix if vrf_name else ip_prefix) + def get_oids(self, table): return self.asic_db.get_keys(table) @@ -169,7 +207,15 @@ def get_newly_created_oid(self, table, old_oids): oid = [ids for ids in new_oids if ids not in old_oids] return oid[0] - def get_ip_prefix_nhg_oid(self, ip_prefix): + def get_default_vrf_oid(self): + oids = self.get_oids(ASIC_VIRTUAL_ROUTER_TABLE) + assert len(oids) == 1, "Wrong # of default vrfs: %d, expected #: 1." % (len(oids)) + return oids[0] + + def get_ip_prefix_nhg_oid(self, ip_prefix, vrf_oid=None): + if vrf_oid is None: + vrf_oid = self.default_vrf_oid + def _access_function(): route_entry_found = False @@ -178,6 +224,7 @@ def _access_function(): route_entry_key = json.loads(raw_route_entry_key) if route_entry_key["dest"] == ip_prefix: route_entry_found = True + assert route_entry_key["vr"] == vrf_oid break return (route_entry_found, raw_route_entry_key) @@ -186,7 +233,7 @@ def _access_function(): fvs = self.asic_db.get_entry(ASIC_ROUTE_ENTRY_TABLE, raw_route_entry_key) - nhg_oid = fvs.get( "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID", "") + nhg_oid = fvs.get("SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID", "") assert nhg_oid != "" assert nhg_oid != "oid:0x0" @@ -198,20 +245,47 @@ def check_sub_port_intf_key_existence(self, db, table_name, key): def check_sub_port_intf_fvs(self, db, table_name, key, fv_dict): db.wait_for_field_match(table_name, key, fv_dict) - def check_sub_port_intf_route_entries(self): - expected_destinations = [self.IPV4_TOME_UNDER_TEST, - self.IPV4_SUBNET_UNDER_TEST, - self.IPV6_TOME_UNDER_TEST, - self.IPV6_SUBNET_UNDER_TEST] + def check_sub_port_intf_route_entries(self, vrf_oid=None): + expected_dests = [self.IPV4_TOME_UNDER_TEST, + self.IPV4_SUBNET_UNDER_TEST, + self.IPV6_TOME_UNDER_TEST, + self.IPV6_SUBNET_UNDER_TEST] + if vrf_oid is None: + vrf_oid = self.default_vrf_oid + expected_vrf_oids = [vrf_oid, + vrf_oid, + vrf_oid, + vrf_oid] def _access_function(): raw_route_entries = self.asic_db.get_keys(ASIC_ROUTE_ENTRY_TABLE) - route_destinations = [str(json.loads(raw_route_entry)["dest"]) - for raw_route_entry in raw_route_entries] - return (all(dest in route_destinations for dest in expected_destinations), None) + route_dest_vrf_oids = [(json.loads(raw_route_entry)["dest"], json.loads(raw_route_entry)["vr"]) + for raw_route_entry in raw_route_entries] + return (all((dest, vrf_oid) in route_dest_vrf_oids for dest, vrf_oid in zip(expected_dests, expected_vrf_oids)), None) wait_for_result(_access_function) + def check_sub_port_intf_vrf_bind_kernel(self, dvs, port_name, vrf_name): + (ec, out) = dvs.runcmd(['bash', '-c', "ip link show {} | grep {}".format(port_name, vrf_name)]) + assert ec == 0 + assert vrf_name in out + + def check_sub_port_intf_vrf_nobind_kernel(self, dvs, port_name, vrf_name=None): + if vrf_name is not None: + (ec, out) = dvs.runcmd(['bash', '-c', "ip link show {} | grep {}".format(port_name, vrf_name)]) + assert ec == 1 + assert vrf_name not in out + + (ec, out) = dvs.runcmd(['bash', '-c', "ip link show {} | grep master".format(port_name)]) + assert ec == 1 + assert "master" not in out + + def check_sub_port_intf_removal_kernel(self, dvs, port_name): + (ec, out) = dvs.runcmd(['bash', '-c', "ip link show {}".format(port_name)]) + assert ec == 1 + assert port_name in out + assert "does not exist" in out + def check_sub_port_intf_key_removal(self, db, table_name, key): db.wait_for_deleted_keys(table_name, [key]) @@ -225,26 +299,33 @@ def _access_function(): wait_for_result(_access_function) - def _test_sub_port_intf_creation(self, dvs, sub_port_intf_name): + def _test_sub_port_intf_creation(self, dvs, sub_port_intf_name, vrf_name=None): substrs = sub_port_intf_name.split(VLAN_SUB_INTERFACE_SEPARATOR) parent_port = substrs[0] vlan_id = substrs[1] if parent_port.startswith(ETHERNET_PREFIX): state_tbl_name = STATE_PORT_TABLE_NAME phy_ports = [parent_port] + parent_port_oid = dvs.asicdb.portnamemap[parent_port] else: assert parent_port.startswith(LAG_PREFIX) state_tbl_name = STATE_LAG_TABLE_NAME phy_ports = self.LAG_MEMBERS_UNDER_TEST + old_lag_oids = self.get_oids(ASIC_LAG_TABLE) + vrf_oid = self.default_vrf_oid old_rif_oids = self.get_oids(ASIC_RIF_TABLE) self.set_parent_port_admin_status(dvs, parent_port, "up") - # Add lag members to test physical port host interface vlan tag attribute if parent_port.startswith(LAG_PREFIX): + parent_port_oid = self.get_newly_created_oid(ASIC_LAG_TABLE, old_lag_oids) + # Add lag members to test physical port host interface vlan tag attribute self.add_lag_members(parent_port, self.LAG_MEMBERS_UNDER_TEST) self.asic_db.wait_for_n_keys(ASIC_LAG_MEMBER_TABLE, len(self.LAG_MEMBERS_UNDER_TEST)) - self.create_sub_port_intf_profile(sub_port_intf_name) + if vrf_name: + self.create_vrf(vrf_name) + vrf_oid = self.get_newly_created_oid(ASIC_VIRTUAL_ROUTER_TABLE, [vrf_oid]) + self.create_sub_port_intf_profile(sub_port_intf_name, vrf_name) # Verify that sub port interface state ok is pushed to STATE_DB by Intfmgrd fv_dict = { @@ -252,10 +333,24 @@ def _test_sub_port_intf_creation(self, dvs, sub_port_intf_name): } self.check_sub_port_intf_fvs(self.state_db, state_tbl_name, sub_port_intf_name, fv_dict) + # Verify vrf name sub port interface bound to in STATE_DB INTERFACE_TABLE + fv_dict = { + "vrf": vrf_name if vrf_name else "", + } + self.check_sub_port_intf_fvs(self.state_db, STATE_INTERFACE_TABLE_NAME, sub_port_intf_name, fv_dict) + + # If bound to non-default vrf, verify sub port interface vrf binding in linux kernel, + # and parent port not bound to vrf + if vrf_name: + self.check_sub_port_intf_vrf_bind_kernel(dvs, sub_port_intf_name, vrf_name) + self.check_sub_port_intf_vrf_nobind_kernel(dvs, parent_port, vrf_name) + # Verify that sub port interface configuration is synced to APPL_DB INTF_TABLE by Intfmgrd fv_dict = { ADMIN_STATUS: "up", } + if vrf_name: + fv_dict[VRF_NAME] = vrf_name self.check_sub_port_intf_fvs(self.app_db, APP_INTF_TABLE_NAME, sub_port_intf_name, fv_dict) # Verify that a sub port router interface entry is created in ASIC_DB @@ -265,6 +360,8 @@ def _test_sub_port_intf_creation(self, dvs, sub_port_intf_name): "SAI_ROUTER_INTERFACE_ATTR_ADMIN_V4_STATE": "true", "SAI_ROUTER_INTERFACE_ATTR_ADMIN_V6_STATE": "true", "SAI_ROUTER_INTERFACE_ATTR_MTU": DEFAULT_MTU, + "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": vrf_oid, + "SAI_ROUTER_INTERFACE_ATTR_PORT_ID": parent_port_oid, } rif_oid = self.get_newly_created_oid(ASIC_RIF_TABLE, old_rif_oids) self.check_sub_port_intf_fvs(self.asic_db, ASIC_RIF_TABLE, rif_oid, fv_dict) @@ -281,25 +378,41 @@ def _test_sub_port_intf_creation(self, dvs, sub_port_intf_name): self.remove_sub_port_intf_profile(sub_port_intf_name) self.check_sub_port_intf_profile_removal(rif_oid) - # Remove lag members from lag parent port + # Remove vrf if created + if vrf_name: + self.remove_vrf(vrf_name) + self.check_vrf_removal(vrf_oid) + if parent_port.startswith(LAG_PREFIX): + # Remove lag members from lag parent port self.remove_lag_members(parent_port, self.LAG_MEMBERS_UNDER_TEST) self.asic_db.wait_for_n_keys(ASIC_LAG_MEMBER_TABLE, 0) + # Remove lag + self.remove_lag(parent_port) + self.check_lag_removal(parent_port_oid) + def test_sub_port_intf_creation(self, dvs): self.connect_dbs(dvs) self._test_sub_port_intf_creation(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST) self._test_sub_port_intf_creation(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST) - def _test_sub_port_intf_add_ip_addrs(self, dvs, sub_port_intf_name): + self._test_sub_port_intf_creation(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, self.VRF_UNDER_TEST) + self._test_sub_port_intf_creation(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, self.VRF_UNDER_TEST) + + def _test_sub_port_intf_add_ip_addrs(self, dvs, sub_port_intf_name, vrf_name=None): substrs = sub_port_intf_name.split(VLAN_SUB_INTERFACE_SEPARATOR) parent_port = substrs[0] + vrf_oid = self.default_vrf_oid old_rif_oids = self.get_oids(ASIC_RIF_TABLE) self.set_parent_port_admin_status(dvs, parent_port, "up") - self.create_sub_port_intf_profile(sub_port_intf_name) + if vrf_name: + self.create_vrf(vrf_name) + vrf_oid = self.get_newly_created_oid(ASIC_VIRTUAL_ROUTER_TABLE, [vrf_oid]) + self.create_sub_port_intf_profile(sub_port_intf_name, vrf_name) self.add_sub_port_intf_ip_addr(sub_port_intf_name, self.IPV4_ADDR_UNDER_TEST) self.add_sub_port_intf_ip_addr(sub_port_intf_name, self.IPV6_ADDR_UNDER_TEST) @@ -310,27 +423,27 @@ def _test_sub_port_intf_add_ip_addrs(self, dvs, sub_port_intf_name): fv_dict = { "state": "ok", } - self.check_sub_port_intf_fvs(self.state_db, STATE_INTERFACE_TABLE_NAME, \ - sub_port_intf_name + "|" + self.IPV4_ADDR_UNDER_TEST, fv_dict) - self.check_sub_port_intf_fvs(self.state_db, STATE_INTERFACE_TABLE_NAME, \ - sub_port_intf_name + "|" + self.IPV6_ADDR_UNDER_TEST, fv_dict) + self.check_sub_port_intf_fvs(self.state_db, STATE_INTERFACE_TABLE_NAME, + sub_port_intf_name + "|" + self.IPV4_ADDR_UNDER_TEST, fv_dict) + self.check_sub_port_intf_fvs(self.state_db, STATE_INTERFACE_TABLE_NAME, + sub_port_intf_name + "|" + self.IPV6_ADDR_UNDER_TEST, fv_dict) # Verify that ip address configuration is synced to APPL_DB INTF_TABLE by Intfmgrd fv_dict = { "scope": "global", "family": "IPv4", } - self.check_sub_port_intf_fvs(self.app_db, APP_INTF_TABLE_NAME, \ - sub_port_intf_name + ":" + self.IPV4_ADDR_UNDER_TEST, fv_dict) + self.check_sub_port_intf_fvs(self.app_db, APP_INTF_TABLE_NAME, + sub_port_intf_name + ":" + self.IPV4_ADDR_UNDER_TEST, fv_dict) fv_dict["family"] = "IPv6" - self.check_sub_port_intf_fvs(self.app_db, APP_INTF_TABLE_NAME, \ - sub_port_intf_name + ":" + self.IPV6_ADDR_UNDER_TEST, fv_dict) + self.check_sub_port_intf_fvs(self.app_db, APP_INTF_TABLE_NAME, + sub_port_intf_name + ":" + self.IPV6_ADDR_UNDER_TEST, fv_dict) # Verify that an IPv4 ip2me route entry is created in ASIC_DB # Verify that an IPv4 subnet route entry is created in ASIC_DB # Verify that an IPv6 ip2me route entry is created in ASIC_DB # Verify that an IPv6 subnet route entry is created in ASIC_DB - self.check_sub_port_intf_route_entries() + self.check_sub_port_intf_route_entries(vrf_oid) # Remove IP addresses self.remove_sub_port_intf_ip_addr(sub_port_intf_name, self.IPV4_ADDR_UNDER_TEST) @@ -343,20 +456,43 @@ def _test_sub_port_intf_add_ip_addrs(self, dvs, sub_port_intf_name): self.remove_sub_port_intf_profile(sub_port_intf_name) self.check_sub_port_intf_profile_removal(rif_oid) + # Remove vrf if created + if vrf_name: + self.remove_vrf(vrf_name) + self.check_vrf_removal(vrf_oid) + + # Remove lag + if parent_port.startswith(LAG_PREFIX): + self.remove_lag(parent_port) + self.asic_db.wait_for_n_keys(ASIC_LAG_TABLE, 0) + def test_sub_port_intf_add_ip_addrs(self, dvs): self.connect_dbs(dvs) self._test_sub_port_intf_add_ip_addrs(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST) self._test_sub_port_intf_add_ip_addrs(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST) - def _test_sub_port_intf_appl_db_proc_seq(self, dvs, sub_port_intf_name, admin_up): + self._test_sub_port_intf_add_ip_addrs(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, self.VRF_UNDER_TEST) + self._test_sub_port_intf_add_ip_addrs(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, self.VRF_UNDER_TEST) + + def _test_sub_port_intf_appl_db_proc_seq(self, dvs, sub_port_intf_name, admin_up, vrf_name=None): substrs = sub_port_intf_name.split(VLAN_SUB_INTERFACE_SEPARATOR) parent_port = substrs[0] vlan_id = substrs[1] + vrf_oid = self.default_vrf_oid old_rif_oids = self.get_oids(ASIC_RIF_TABLE) + old_lag_oids = self.get_oids(ASIC_LAG_TABLE) self.set_parent_port_admin_status(dvs, parent_port, "up") + if parent_port.startswith(ETHERNET_PREFIX): + parent_port_oid = dvs.asicdb.portnamemap[parent_port] + else: + assert parent_port.startswith(LAG_PREFIX) + parent_port_oid = self.get_newly_created_oid(ASIC_LAG_TABLE, old_lag_oids) + if vrf_name: + self.create_vrf(vrf_name) + vrf_oid = self.get_newly_created_oid(ASIC_VIRTUAL_ROUTER_TABLE, [vrf_oid]) # Create ip address configuration in APPL_DB before creating configuration for sub port interface itself self.add_sub_port_intf_ip_addr_appl_db(sub_port_intf_name, self.IPV4_ADDR_UNDER_TEST) @@ -364,7 +500,7 @@ def _test_sub_port_intf_appl_db_proc_seq(self, dvs, sub_port_intf_name, admin_up time.sleep(2) # Create sub port interface configuration in APPL_DB - self.create_sub_port_intf_profile_appl_db(sub_port_intf_name, "up" if admin_up == True else "down") + self.create_sub_port_intf_profile_appl_db(sub_port_intf_name, "up" if admin_up == True else "down", vrf_name) # Verify that a sub port router interface entry is created in ASIC_DB fv_dict = { @@ -373,6 +509,8 @@ def _test_sub_port_intf_appl_db_proc_seq(self, dvs, sub_port_intf_name, admin_up "SAI_ROUTER_INTERFACE_ATTR_ADMIN_V4_STATE": "true" if admin_up == True else "false", "SAI_ROUTER_INTERFACE_ATTR_ADMIN_V6_STATE": "true" if admin_up == True else "false", "SAI_ROUTER_INTERFACE_ATTR_MTU": DEFAULT_MTU, + "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": vrf_oid, + "SAI_ROUTER_INTERFACE_ATTR_PORT_ID": parent_port_oid, } rif_oid = self.get_newly_created_oid(ASIC_RIF_TABLE, old_rif_oids) self.check_sub_port_intf_fvs(self.asic_db, ASIC_RIF_TABLE, rif_oid, fv_dict) @@ -384,6 +522,16 @@ def _test_sub_port_intf_appl_db_proc_seq(self, dvs, sub_port_intf_name, admin_up self.remove_sub_port_intf_profile_appl_db(sub_port_intf_name) self.check_sub_port_intf_profile_removal(rif_oid) + # Remove vrf if created + if vrf_name: + self.remove_vrf(vrf_name) + self.check_vrf_removal(vrf_oid) + + # Remove lag + if parent_port.startswith(LAG_PREFIX): + self.remove_lag(parent_port) + self.check_lag_removal(parent_port_oid) + def test_sub_port_intf_appl_db_proc_seq(self, dvs): self.connect_dbs(dvs) @@ -393,14 +541,24 @@ def test_sub_port_intf_appl_db_proc_seq(self, dvs): self._test_sub_port_intf_appl_db_proc_seq(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, admin_up=True) self._test_sub_port_intf_appl_db_proc_seq(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, admin_up=False) - def _test_sub_port_intf_admin_status_change(self, dvs, sub_port_intf_name): + self._test_sub_port_intf_appl_db_proc_seq(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, admin_up=True, vrf_name=self.VRF_UNDER_TEST) + self._test_sub_port_intf_appl_db_proc_seq(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, admin_up=False, vrf_name=self.VRF_UNDER_TEST) + + self._test_sub_port_intf_appl_db_proc_seq(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, admin_up=True, vrf_name=self.VRF_UNDER_TEST) + self._test_sub_port_intf_appl_db_proc_seq(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, admin_up=False, vrf_name=self.VRF_UNDER_TEST) + + def _test_sub_port_intf_admin_status_change(self, dvs, sub_port_intf_name, vrf_name=None): substrs = sub_port_intf_name.split(VLAN_SUB_INTERFACE_SEPARATOR) parent_port = substrs[0] + vrf_oid = self.default_vrf_oid old_rif_oids = self.get_oids(ASIC_RIF_TABLE) self.set_parent_port_admin_status(dvs, parent_port, "up") - self.create_sub_port_intf_profile(sub_port_intf_name) + if vrf_name: + self.create_vrf(vrf_name) + vrf_oid = self.get_newly_created_oid(ASIC_VIRTUAL_ROUTER_TABLE, [vrf_oid]) + self.create_sub_port_intf_profile(sub_port_intf_name, vrf_name) self.add_sub_port_intf_ip_addr(sub_port_intf_name, self.IPV4_ADDR_UNDER_TEST) self.add_sub_port_intf_ip_addr(sub_port_intf_name, self.IPV6_ADDR_UNDER_TEST) @@ -408,12 +566,15 @@ def _test_sub_port_intf_admin_status_change(self, dvs, sub_port_intf_name): fv_dict = { ADMIN_STATUS: "up", } + if vrf_name: + fv_dict[VRF_NAME] = vrf_name self.check_sub_port_intf_fvs(self.app_db, APP_INTF_TABLE_NAME, sub_port_intf_name, fv_dict) fv_dict = { "SAI_ROUTER_INTERFACE_ATTR_ADMIN_V4_STATE": "true", "SAI_ROUTER_INTERFACE_ATTR_ADMIN_V6_STATE": "true", "SAI_ROUTER_INTERFACE_ATTR_MTU": DEFAULT_MTU, + "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": vrf_oid, } rif_oid = self.get_newly_created_oid(ASIC_RIF_TABLE, old_rif_oids) self.check_sub_port_intf_fvs(self.asic_db, ASIC_RIF_TABLE, rif_oid, fv_dict) @@ -425,6 +586,8 @@ def _test_sub_port_intf_admin_status_change(self, dvs, sub_port_intf_name): fv_dict = { ADMIN_STATUS: "down", } + if vrf_name: + fv_dict[VRF_NAME] = vrf_name self.check_sub_port_intf_fvs(self.app_db, APP_INTF_TABLE_NAME, sub_port_intf_name, fv_dict) # Verify that sub port router interface entry in ASIC_DB has the updated admin status @@ -432,6 +595,7 @@ def _test_sub_port_intf_admin_status_change(self, dvs, sub_port_intf_name): "SAI_ROUTER_INTERFACE_ATTR_ADMIN_V4_STATE": "false", "SAI_ROUTER_INTERFACE_ATTR_ADMIN_V6_STATE": "false", "SAI_ROUTER_INTERFACE_ATTR_MTU": DEFAULT_MTU, + "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": vrf_oid, } rif_oid = self.get_newly_created_oid(ASIC_RIF_TABLE, old_rif_oids) self.check_sub_port_intf_fvs(self.asic_db, ASIC_RIF_TABLE, rif_oid, fv_dict) @@ -443,6 +607,8 @@ def _test_sub_port_intf_admin_status_change(self, dvs, sub_port_intf_name): fv_dict = { ADMIN_STATUS: "up", } + if vrf_name: + fv_dict[VRF_NAME] = vrf_name self.check_sub_port_intf_fvs(self.app_db, APP_INTF_TABLE_NAME, sub_port_intf_name, fv_dict) # Verify that sub port router interface entry in ASIC_DB has the updated admin status @@ -450,6 +616,7 @@ def _test_sub_port_intf_admin_status_change(self, dvs, sub_port_intf_name): "SAI_ROUTER_INTERFACE_ATTR_ADMIN_V4_STATE": "true", "SAI_ROUTER_INTERFACE_ATTR_ADMIN_V6_STATE": "true", "SAI_ROUTER_INTERFACE_ATTR_MTU": DEFAULT_MTU, + "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": vrf_oid, } rif_oid = self.get_newly_created_oid(ASIC_RIF_TABLE, old_rif_oids) self.check_sub_port_intf_fvs(self.asic_db, ASIC_RIF_TABLE, rif_oid, fv_dict) @@ -465,20 +632,36 @@ def _test_sub_port_intf_admin_status_change(self, dvs, sub_port_intf_name): self.remove_sub_port_intf_profile(sub_port_intf_name) self.check_sub_port_intf_profile_removal(rif_oid) + # Remove vrf if created + if vrf_name: + self.remove_vrf(vrf_name) + self.check_vrf_removal(vrf_oid) + + # Remove lag + if parent_port.startswith(LAG_PREFIX): + self.remove_lag(parent_port) + self.asic_db.wait_for_n_keys(ASIC_LAG_TABLE, 0) + def test_sub_port_intf_admin_status_change(self, dvs): self.connect_dbs(dvs) self._test_sub_port_intf_admin_status_change(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST) self._test_sub_port_intf_admin_status_change(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST) - def _test_sub_port_intf_remove_ip_addrs(self, dvs, sub_port_intf_name): + self._test_sub_port_intf_admin_status_change(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, self.VRF_UNDER_TEST) + self._test_sub_port_intf_admin_status_change(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, self.VRF_UNDER_TEST) + + def _test_sub_port_intf_remove_ip_addrs(self, dvs, sub_port_intf_name, vrf_name=None): substrs = sub_port_intf_name.split(VLAN_SUB_INTERFACE_SEPARATOR) parent_port = substrs[0] old_rif_oids = self.get_oids(ASIC_RIF_TABLE) self.set_parent_port_admin_status(dvs, parent_port, "up") - self.create_sub_port_intf_profile(sub_port_intf_name) + if vrf_name: + self.create_vrf(vrf_name) + self.asic_db.wait_for_n_keys(ASIC_VIRTUAL_ROUTER_TABLE, 2) + self.create_sub_port_intf_profile(sub_port_intf_name, vrf_name) self.add_sub_port_intf_ip_addr(sub_port_intf_name, self.IPV4_ADDR_UNDER_TEST) self.add_sub_port_intf_ip_addr(sub_port_intf_name, self.IPV6_ADDR_UNDER_TEST) @@ -489,12 +672,12 @@ def _test_sub_port_intf_remove_ip_addrs(self, dvs, sub_port_intf_name): self.remove_sub_port_intf_ip_addr(sub_port_intf_name, self.IPV4_ADDR_UNDER_TEST) # Verify that IPv4 address state ok is removed from STATE_DB INTERFACE_TABLE by Intfmgrd - self.check_sub_port_intf_key_removal(self.state_db, STATE_INTERFACE_TABLE_NAME, \ - sub_port_intf_name + "|" + self.IPV4_ADDR_UNDER_TEST) + self.check_sub_port_intf_key_removal(self.state_db, STATE_INTERFACE_TABLE_NAME, + sub_port_intf_name + "|" + self.IPV4_ADDR_UNDER_TEST) # Verify that IPv4 address configuration is removed from APPL_DB INTF_TABLE by Intfmgrd - self.check_sub_port_intf_key_removal(self.app_db, APP_INTF_TABLE_NAME, \ - sub_port_intf_name + ":" + self.IPV4_ADDR_UNDER_TEST) + self.check_sub_port_intf_key_removal(self.app_db, APP_INTF_TABLE_NAME, + sub_port_intf_name + ":" + self.IPV4_ADDR_UNDER_TEST) # Verify that IPv4 subnet route entry is removed from ASIC_DB # Verify that IPv4 ip2me route entry is removed from ASIC_DB @@ -505,12 +688,12 @@ def _test_sub_port_intf_remove_ip_addrs(self, dvs, sub_port_intf_name): self.remove_sub_port_intf_ip_addr(sub_port_intf_name, self.IPV6_ADDR_UNDER_TEST) # Verify that IPv6 address state ok is removed from STATE_DB INTERFACE_TABLE by Intfmgrd - self.check_sub_port_intf_key_removal(self.state_db, STATE_INTERFACE_TABLE_NAME, \ - sub_port_intf_name + "|" + self.IPV6_ADDR_UNDER_TEST) + self.check_sub_port_intf_key_removal(self.state_db, STATE_INTERFACE_TABLE_NAME, + sub_port_intf_name + "|" + self.IPV6_ADDR_UNDER_TEST) # Verify that IPv6 address configuration is removed from APPL_DB INTF_TABLE by Intfmgrd - self.check_sub_port_intf_key_removal(self.app_db, APP_INTF_TABLE_NAME, \ - sub_port_intf_name + ":" + self.IPV6_ADDR_UNDER_TEST) + self.check_sub_port_intf_key_removal(self.app_db, APP_INTF_TABLE_NAME, + sub_port_intf_name + ":" + self.IPV6_ADDR_UNDER_TEST) # Verify that IPv6 subnet route entry is removed from ASIC_DB # Verify that IPv6 ip2me route entry is removed from ASIC_DB @@ -524,47 +707,120 @@ def _test_sub_port_intf_remove_ip_addrs(self, dvs, sub_port_intf_name): self.remove_sub_port_intf_profile(sub_port_intf_name) self.check_sub_port_intf_profile_removal(rif_oid) + # Remove vrf if created + if vrf_name: + self.remove_vrf(vrf_name) + self.asic_db.wait_for_n_keys(ASIC_VIRTUAL_ROUTER_TABLE, 1) + + # Remove lag + if parent_port.startswith(LAG_PREFIX): + self.remove_lag(parent_port) + self.asic_db.wait_for_n_keys(ASIC_LAG_TABLE, 0) + def test_sub_port_intf_remove_ip_addrs(self, dvs): self.connect_dbs(dvs) self._test_sub_port_intf_remove_ip_addrs(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST) self._test_sub_port_intf_remove_ip_addrs(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST) - def _test_sub_port_intf_removal(self, dvs, sub_port_intf_name): + self._test_sub_port_intf_remove_ip_addrs(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, self.VRF_UNDER_TEST) + self._test_sub_port_intf_remove_ip_addrs(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, self.VRF_UNDER_TEST) + + def _test_sub_port_intf_removal(self, dvs, sub_port_intf_name, removal_seq_test=False, vrf_name=None): substrs = sub_port_intf_name.split(VLAN_SUB_INTERFACE_SEPARATOR) parent_port = substrs[0] + vlan_id = substrs[1] if parent_port.startswith(ETHERNET_PREFIX): state_tbl_name = STATE_PORT_TABLE_NAME phy_ports = [parent_port] + parent_port_oid = dvs.asicdb.portnamemap[parent_port] else: assert parent_port.startswith(LAG_PREFIX) state_tbl_name = STATE_LAG_TABLE_NAME phy_ports = self.LAG_MEMBERS_UNDER_TEST + old_lag_oids = self.get_oids(ASIC_LAG_TABLE) + vrf_oid = self.default_vrf_oid old_rif_oids = self.get_oids(ASIC_RIF_TABLE) self.set_parent_port_admin_status(dvs, parent_port, "up") - # Add lag members to test physical port host interface vlan tag attribute if parent_port.startswith(LAG_PREFIX): + parent_port_oid = self.get_newly_created_oid(ASIC_LAG_TABLE, old_lag_oids) + # Add lag members to test physical port host interface vlan tag attribute self.add_lag_members(parent_port, self.LAG_MEMBERS_UNDER_TEST) self.asic_db.wait_for_n_keys(ASIC_LAG_MEMBER_TABLE, len(self.LAG_MEMBERS_UNDER_TEST)) - self.create_sub_port_intf_profile(sub_port_intf_name) + if vrf_name: + self.create_vrf(vrf_name) + vrf_oid = self.get_newly_created_oid(ASIC_VIRTUAL_ROUTER_TABLE, [vrf_oid]) + self.create_sub_port_intf_profile(sub_port_intf_name, vrf_name) self.add_sub_port_intf_ip_addr(sub_port_intf_name, self.IPV4_ADDR_UNDER_TEST) self.add_sub_port_intf_ip_addr(sub_port_intf_name, self.IPV6_ADDR_UNDER_TEST) - rif_oid = self.get_newly_created_oid(ASIC_RIF_TABLE, old_rif_oids) - fv_dict = { "state": "ok", } self.check_sub_port_intf_fvs(self.state_db, state_tbl_name, sub_port_intf_name, fv_dict) + fv_dict = { + "vrf": vrf_name if vrf_name else "", + } + self.check_sub_port_intf_fvs(self.state_db, STATE_INTERFACE_TABLE_NAME, sub_port_intf_name, fv_dict) + + if vrf_name: + self.check_sub_port_intf_vrf_bind_kernel(dvs, sub_port_intf_name, vrf_name) + self.check_sub_port_intf_vrf_nobind_kernel(dvs, parent_port, vrf_name) + fv_dict = { ADMIN_STATUS: "up", } + if vrf_name: + fv_dict[VRF_NAME] = vrf_name self.check_sub_port_intf_fvs(self.app_db, APP_INTF_TABLE_NAME, sub_port_intf_name, fv_dict) + if removal_seq_test == True: + # Remove a sub port interface before removing sub port interface IP addresses + self.remove_sub_port_intf_profile(sub_port_intf_name) + time.sleep(2) + + # Verify that sub port interface state ok persists in STATE_DB + fv_dict = { + "state": "ok", + } + self.check_sub_port_intf_fvs(self.state_db, state_tbl_name, sub_port_intf_name, fv_dict) + # Verify vrf name sub port interface bound to persists in STATE_DB INTERFACE_TABLE + fv_dict = { + "vrf": vrf_name if vrf_name else "", + } + self.check_sub_port_intf_fvs(self.state_db, STATE_INTERFACE_TABLE_NAME, sub_port_intf_name, fv_dict) + # If bound to non-default vrf, verify sub port interface vrf binding in linux kernel, + # and parent port not bound to vrf + if vrf_name: + self.check_sub_port_intf_vrf_bind_kernel(dvs, sub_port_intf_name, vrf_name) + self.check_sub_port_intf_vrf_nobind_kernel(dvs, parent_port, vrf_name) + # Verify that sub port interface configuration persists in APPL_DB INTF_TABLE + fv_dict = { + ADMIN_STATUS: "up", + } + if vrf_name: + fv_dict[VRF_NAME] = vrf_name + self.check_sub_port_intf_fvs(self.app_db, APP_INTF_TABLE_NAME, sub_port_intf_name, fv_dict) + + # Verify that a sub port router interface entry persists in ASIC_DB + fv_dict = { + "SAI_ROUTER_INTERFACE_ATTR_TYPE": "SAI_ROUTER_INTERFACE_TYPE_SUB_PORT", + "SAI_ROUTER_INTERFACE_ATTR_OUTER_VLAN_ID": "{}".format(vlan_id), + "SAI_ROUTER_INTERFACE_ATTR_ADMIN_V4_STATE": "true", + "SAI_ROUTER_INTERFACE_ATTR_ADMIN_V6_STATE": "true", + "SAI_ROUTER_INTERFACE_ATTR_MTU": DEFAULT_MTU, + "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": vrf_oid, + "SAI_ROUTER_INTERFACE_ATTR_PORT_ID": parent_port_oid, + } + rif_oid = self.get_newly_created_oid(ASIC_RIF_TABLE, old_rif_oids) + self.check_sub_port_intf_fvs(self.asic_db, ASIC_RIF_TABLE, rif_oid, fv_dict) + else: + rif_oid = self.get_newly_created_oid(ASIC_RIF_TABLE, old_rif_oids) + # Remove IP addresses self.remove_sub_port_intf_ip_addr(sub_port_intf_name, self.IPV4_ADDR_UNDER_TEST) self.remove_sub_port_intf_ip_addr(sub_port_intf_name, self.IPV6_ADDR_UNDER_TEST) @@ -572,13 +828,23 @@ def _test_sub_port_intf_removal(self, dvs, sub_port_intf_name): [self.IPV4_ADDR_UNDER_TEST, self.IPV6_ADDR_UNDER_TEST]) - # Remove a sub port interface - self.remove_sub_port_intf_profile(sub_port_intf_name) + if removal_seq_test == False: + # Remove a sub port interface + self.remove_sub_port_intf_profile(sub_port_intf_name) self.check_sub_port_intf_profile_removal(rif_oid) # Verify that sub port interface state ok is removed from STATE_DB by Intfmgrd self.check_sub_port_intf_key_removal(self.state_db, state_tbl_name, sub_port_intf_name) + # Verify sub port interface not exist in linux kernel + self.check_sub_port_intf_removal_kernel(dvs, sub_port_intf_name) + # If bound to non-default vrf, verify parent port not bound to vrf + if vrf_name: + self.check_sub_port_intf_vrf_nobind_kernel(dvs, parent_port, vrf_name) + + # Verify vrf name sub port interface bound to is removed from STATE_DB INTERFACE_TABLE + self.check_sub_port_intf_key_removal(self.state_db, STATE_INTERFACE_TABLE_NAME, sub_port_intf_name) + # Verify that sub port interface configuration is removed from APP_DB by Intfmgrd self.check_sub_port_intf_key_removal(self.app_db, APP_INTF_TABLE_NAME, sub_port_intf_name) @@ -593,25 +859,47 @@ def _test_sub_port_intf_removal(self, dvs, sub_port_intf_name): hostif_oid = dvs.asicdb.hostifnamemap[phy_port] self.check_sub_port_intf_fvs(self.asic_db, ASIC_HOSTIF_TABLE, hostif_oid, fv_dict) - # Remove lag members from lag parent port + # Remove vrf if created + if vrf_name: + self.remove_vrf(vrf_name) + self.asic_db.wait_for_n_keys(ASIC_VIRTUAL_ROUTER_TABLE, 1) + if parent_port.startswith(LAG_PREFIX): + # Remove lag members from lag parent port self.remove_lag_members(parent_port, self.LAG_MEMBERS_UNDER_TEST) self.asic_db.wait_for_n_keys(ASIC_LAG_MEMBER_TABLE, 0) + # Remove lag + self.remove_lag(parent_port) + self.check_lag_removal(parent_port_oid) + def test_sub_port_intf_removal(self, dvs): self.connect_dbs(dvs) self._test_sub_port_intf_removal(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST) self._test_sub_port_intf_removal(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST) - def _test_sub_port_intf_mtu(self, dvs, sub_port_intf_name): + self._test_sub_port_intf_removal(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, vrf_name=self.VRF_UNDER_TEST) + self._test_sub_port_intf_removal(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, vrf_name=self.VRF_UNDER_TEST) + + self._test_sub_port_intf_removal(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, removal_seq_test=True) + self._test_sub_port_intf_removal(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, removal_seq_test=True) + + self._test_sub_port_intf_removal(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, removal_seq_test=True, vrf_name=self.VRF_UNDER_TEST) + self._test_sub_port_intf_removal(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, removal_seq_test=True, vrf_name=self.VRF_UNDER_TEST) + + def _test_sub_port_intf_mtu(self, dvs, sub_port_intf_name, vrf_name=None): substrs = sub_port_intf_name.split(VLAN_SUB_INTERFACE_SEPARATOR) parent_port = substrs[0] + vrf_oid = self.default_vrf_oid old_rif_oids = self.get_oids(ASIC_RIF_TABLE) self.set_parent_port_admin_status(dvs, parent_port, "up") - self.create_sub_port_intf_profile(sub_port_intf_name) + if vrf_name: + self.create_vrf(vrf_name) + vrf_oid = self.get_newly_created_oid(ASIC_VIRTUAL_ROUTER_TABLE, [vrf_oid]) + self.create_sub_port_intf_profile(sub_port_intf_name, vrf_name) rif_oid = self.get_newly_created_oid(ASIC_RIF_TABLE, old_rif_oids) @@ -622,6 +910,7 @@ def _test_sub_port_intf_mtu(self, dvs, sub_port_intf_name): # Verify that sub port router interface entry in ASIC_DB has the updated mtu fv_dict = { "SAI_ROUTER_INTERFACE_ATTR_MTU": mtu, + "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": vrf_oid, } self.check_sub_port_intf_fvs(self.asic_db, ASIC_RIF_TABLE, rif_oid, fv_dict) @@ -631,6 +920,7 @@ def _test_sub_port_intf_mtu(self, dvs, sub_port_intf_name): # Verify that sub port router interface entry in ASIC_DB has the default mtu fv_dict = { "SAI_ROUTER_INTERFACE_ATTR_MTU": DEFAULT_MTU, + "SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID": vrf_oid, } self.check_sub_port_intf_fvs(self.asic_db, ASIC_RIF_TABLE, rif_oid, fv_dict) @@ -638,13 +928,26 @@ def _test_sub_port_intf_mtu(self, dvs, sub_port_intf_name): self.remove_sub_port_intf_profile(sub_port_intf_name) self.check_sub_port_intf_profile_removal(rif_oid) + # Remove vrf if created + if vrf_name: + self.remove_vrf(vrf_name) + self.check_vrf_removal(vrf_oid) + + # Remove lag + if parent_port.startswith(LAG_PREFIX): + self.remove_lag(parent_port) + self.asic_db.wait_for_n_keys(ASIC_LAG_TABLE, 0) + def test_sub_port_intf_mtu(self, dvs): self.connect_dbs(dvs) self._test_sub_port_intf_mtu(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST) self._test_sub_port_intf_mtu(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST) - def create_nhg_router_intfs(self, dvs, parent_port_prefix, parent_port_idx_base, vlan_id, nhop_num): + self._test_sub_port_intf_mtu(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, self.VRF_UNDER_TEST) + self._test_sub_port_intf_mtu(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, self.VRF_UNDER_TEST) + + def create_nhg_router_intfs(self, dvs, parent_port_prefix, parent_port_idx_base, vlan_id, nhop_num, vrf_name=None): ifnames = [] parent_port_idx = parent_port_idx_base for i in range(0, nhop_num): @@ -654,10 +957,10 @@ def create_nhg_router_intfs(self, dvs, parent_port_prefix, parent_port_idx_base, port_name = "{}{}".format(parent_port_prefix, parent_port_idx) ip_addr = "10.{}.{}.0/31".format(parent_port_idx, vlan_id) if vlan_id != 0: - self.create_sub_port_intf_profile(port_name) + self.create_sub_port_intf_profile(port_name, vrf_name) self.add_sub_port_intf_ip_addr(port_name, ip_addr) else: - dvs.add_ip_address(port_name, ip_addr) + dvs.add_ip_address(port_name, ip_addr, vrf_name) ifnames.append(port_name) @@ -668,9 +971,13 @@ def create_nhg_next_hop_objs(self, dvs, parent_port_prefix, parent_port_idx_base nhop_ips = [] parent_port_idx = parent_port_idx_base for i in range(0, nhop_num): + if vlan_id != 0: + port_name = "{}{}.{}".format(parent_port_prefix, parent_port_idx, vlan_id) + else: + port_name = "{}{}".format(parent_port_prefix, parent_port_idx) nhop_ip = "10.{}.{}.1".format(parent_port_idx, vlan_id) nhop_mac = "00:00:00:{:02d}:{}:01".format(parent_port_idx, vlan_id) - dvs.runcmd("arp -s " + nhop_ip + " " + nhop_mac) + dvs.runcmd("ip neigh add " + nhop_ip + " lladdr " + nhop_mac + " dev " + port_name) nhop_ips.append(nhop_ip) @@ -698,12 +1005,16 @@ def remove_nhg_router_intfs(self, dvs, parent_port_prefix, parent_port_idx_base, def remove_nhg_next_hop_objs(self, dvs, parent_port_prefix, parent_port_idx_base, vlan_id, nhop_num): parent_port_idx = parent_port_idx_base for i in range(0, nhop_num): + if vlan_id != 0: + port_name = "{}{}.{}".format(parent_port_prefix, parent_port_idx, vlan_id) + else: + port_name = "{}{}".format(parent_port_prefix, parent_port_idx) nhop_ip = "10.{}.{}.1".format(parent_port_idx, vlan_id) - dvs.runcmd("arp -d " + nhop_ip) + dvs.runcmd("ip neigh del " + nhop_ip + " dev " + port_name) parent_port_idx += (4 if parent_port_prefix == ETHERNET_PREFIX else 1) - def check_nhg_members_on_parent_port_oper_status_change(self, dvs, parent_port_prefix, parent_port_idx_base, status, \ + def check_nhg_members_on_parent_port_oper_status_change(self, dvs, parent_port_prefix, parent_port_idx_base, status, nhg_oid, nhop_num, create_intf_on_parent_port): parent_port_idx = parent_port_idx_base for i in range(0, nhop_num): @@ -721,12 +1032,12 @@ def check_nhg_members_on_parent_port_oper_status_change(self, dvs, parent_port_p # Verify next hop group member # in ASIC_DB if status == "up": - nhg_member_oids = self.asic_db.wait_for_n_keys(ASIC_NEXT_HOP_GROUP_MEMBER_TABLE, \ + nhg_member_oids = self.asic_db.wait_for_n_keys(ASIC_NEXT_HOP_GROUP_MEMBER_TABLE, 1 + i if create_intf_on_parent_port == False else (1 + i) * 2) else: assert status == "down" - nhg_member_oids = self.asic_db.wait_for_n_keys(ASIC_NEXT_HOP_GROUP_MEMBER_TABLE, \ - (nhop_num - 1) - i if create_intf_on_parent_port == False else \ + nhg_member_oids = self.asic_db.wait_for_n_keys(ASIC_NEXT_HOP_GROUP_MEMBER_TABLE, + (nhop_num - 1) - i if create_intf_on_parent_port == False else ((nhop_num - 1) - i) * 2) # Verify that next hop group members in ASIC_DB all @@ -739,7 +1050,7 @@ def check_nhg_members_on_parent_port_oper_status_change(self, dvs, parent_port_p parent_port_idx += (4 if parent_port_prefix == ETHERNET_PREFIX else 1) - def _test_sub_port_intf_nhg_accel(self, dvs, sub_port_intf_name, nhop_num=3, create_intf_on_parent_port=False): + def _test_sub_port_intf_nhg_accel(self, dvs, sub_port_intf_name, nhop_num=3, create_intf_on_parent_port=False, vrf_name=None): substrs = sub_port_intf_name.split(VLAN_SUB_INTERFACE_SEPARATOR) parent_port = substrs[0] vlan_id = substrs[1] @@ -752,6 +1063,8 @@ def _test_sub_port_intf_nhg_accel(self, dvs, sub_port_intf_name, nhop_num=3, cre parent_port_prefix = LAG_PREFIX parent_port_idx_base = self.get_parent_port_index(parent_port) + vrf_oid = self.default_vrf_oid + # Set parent ports admin status up parent_port_idx = parent_port_idx_base for i in range(0, nhop_num): @@ -760,13 +1073,20 @@ def _test_sub_port_intf_nhg_accel(self, dvs, sub_port_intf_name, nhop_num=3, cre parent_port_idx += (4 if parent_port_prefix == ETHERNET_PREFIX else 1) + if vrf_name: + self.create_vrf(vrf_name) + vrf_oid = self.get_newly_created_oid(ASIC_VIRTUAL_ROUTER_TABLE, [vrf_oid]) + ifnames = [] + rif_cnt = len(self.asic_db.get_keys(ASIC_RIF_TABLE)) # Create sub port interfaces - ifnames.extend(self.create_nhg_router_intfs(dvs, parent_port_prefix, parent_port_idx_base, int(vlan_id), nhop_num)) + ifnames.extend(self.create_nhg_router_intfs(dvs, parent_port_prefix, parent_port_idx_base, int(vlan_id), nhop_num, vrf_name)) # Create router interfaces on parent ports if create_intf_on_parent_port == True: - ifnames.extend(self.create_nhg_router_intfs(dvs, parent_port_prefix, parent_port_idx_base, 0, nhop_num)) + ifnames.extend(self.create_nhg_router_intfs(dvs, parent_port_prefix, parent_port_idx_base, 0, nhop_num, vrf_name)) + + self.asic_db.wait_for_n_keys(ASIC_RIF_TABLE, rif_cnt + nhop_num if create_intf_on_parent_port == False else rif_cnt + nhop_num * 2) nhop_ips = [] nhop_cnt = len(self.asic_db.get_keys(ASIC_NEXT_HOP_TABLE)) @@ -780,19 +1100,17 @@ def _test_sub_port_intf_nhg_accel(self, dvs, sub_port_intf_name, nhop_num=3, cre self.asic_db.wait_for_n_keys(ASIC_NEXT_HOP_TABLE, nhop_cnt + nhop_num if create_intf_on_parent_port == False else nhop_cnt + nhop_num * 2) # Create multi-next-hop route entry - rt_tbl = swsscommon.ProducerStateTable(self.app_db.db_connection, APP_ROUTE_TABLE_NAME) - fvs = swsscommon.FieldValuePairs([("nexthop", ",".join(nhop_ips)), ("ifname", ",".join(ifnames))]) ip_prefix = "2.2.2.0/24" - rt_tbl.set(ip_prefix, fvs) + self.add_route_appl_db(ip_prefix, nhop_ips, ifnames, vrf_name) # Verify route entry created in ASIC_DB and get next hop group oid - nhg_oid = self.get_ip_prefix_nhg_oid(ip_prefix) + nhg_oid = self.get_ip_prefix_nhg_oid(ip_prefix, vrf_oid) # Verify next hop group of the specified oid created in ASIC_DB self.check_sub_port_intf_key_existence(self.asic_db, ASIC_NEXT_HOP_GROUP_TABLE, nhg_oid) # Verify next hop group members created in ASIC_DB - nhg_member_oids = self.asic_db.wait_for_n_keys(ASIC_NEXT_HOP_GROUP_MEMBER_TABLE, \ + nhg_member_oids = self.asic_db.wait_for_n_keys(ASIC_NEXT_HOP_GROUP_MEMBER_TABLE, nhop_num if create_intf_on_parent_port == False else nhop_num * 2) # Verify that next hop group members all belong to the next hop group of the specified oid @@ -803,16 +1121,19 @@ def _test_sub_port_intf_nhg_accel(self, dvs, sub_port_intf_name, nhop_num=3, cre self.check_sub_port_intf_fvs(self.asic_db, ASIC_NEXT_HOP_GROUP_MEMBER_TABLE, nhg_member_oid, fv_dict) # Bring parent ports oper status down one at a time, and verify next hop group members - self.check_nhg_members_on_parent_port_oper_status_change(dvs, parent_port_prefix, parent_port_idx_base, "down", \ + self.check_nhg_members_on_parent_port_oper_status_change(dvs, parent_port_prefix, parent_port_idx_base, "down", nhg_oid, nhop_num, create_intf_on_parent_port) # Bring parent ports oper status up one at a time, and verify next hop group members - self.check_nhg_members_on_parent_port_oper_status_change(dvs, parent_port_prefix, parent_port_idx_base, "up", \ + self.check_nhg_members_on_parent_port_oper_status_change(dvs, parent_port_prefix, parent_port_idx_base, "up", nhg_oid, nhop_num, create_intf_on_parent_port) # Clean up rif_cnt = len(self.asic_db.get_keys(ASIC_RIF_TABLE)) + # Remove ecmp route entry + self.remove_route_appl_db(ip_prefix, vrf_name) + # Remove sub port interfaces self.remove_nhg_router_intfs(dvs, parent_port_prefix, parent_port_idx_base, int(vlan_id), nhop_num) @@ -820,17 +1141,24 @@ def _test_sub_port_intf_nhg_accel(self, dvs, sub_port_intf_name, nhop_num=3, cre if create_intf_on_parent_port == True: self.remove_nhg_router_intfs(dvs, parent_port_prefix, parent_port_idx_base, 0, nhop_num) - # Remove ecmp route entry - rt_tbl._del(ip_prefix) - # Removal of router interfaces indicates the proper removal of nhg, nhg members, next hop objects, and neighbor entries self.asic_db.wait_for_n_keys(ASIC_RIF_TABLE, rif_cnt - nhop_num if create_intf_on_parent_port == False else rif_cnt - nhop_num * 2) - # Make sure parent port is oper status up + # Remove vrf if created + if vrf_name: + self.remove_vrf(vrf_name) + self.check_vrf_removal(vrf_oid) + parent_port_idx = parent_port_idx_base for i in range(0, nhop_num): port_name = "{}{}".format(parent_port_prefix, parent_port_idx) - self.set_parent_port_oper_status(dvs, port_name, "up") + if parent_port.startswith(ETHERNET_PREFIX): + # Make sure physical port is oper status up + self.set_parent_port_oper_status(dvs, port_name, "up") + else: + # Remove lag + self.remove_lag(port_name) + self.asic_db.wait_for_n_keys(ASIC_LAG_TABLE, nhop_num - 1 - i) parent_port_idx += (4 if parent_port_prefix == ETHERNET_PREFIX else 1) @@ -842,7 +1170,15 @@ def test_sub_port_intf_nhg_accel(self, dvs): self._test_sub_port_intf_nhg_accel(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST) self._test_sub_port_intf_nhg_accel(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, create_intf_on_parent_port=True) - def _test_sub_port_intf_oper_down_with_pending_neigh_route_tasks(self, dvs, sub_port_intf_name, nhop_num=3, create_intf_on_parent_port=False): + self._test_sub_port_intf_nhg_accel(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, vrf_name=self.VRF_UNDER_TEST) + self._test_sub_port_intf_nhg_accel(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, + create_intf_on_parent_port=True, vrf_name=self.VRF_UNDER_TEST) + self._test_sub_port_intf_nhg_accel(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, vrf_name=self.VRF_UNDER_TEST) + self._test_sub_port_intf_nhg_accel(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, + create_intf_on_parent_port=True, vrf_name=self.VRF_UNDER_TEST) + + def _test_sub_port_intf_oper_down_with_pending_neigh_route_tasks(self, dvs, sub_port_intf_name, nhop_num=3, + create_intf_on_parent_port=False, vrf_name=None): substrs = sub_port_intf_name.split(VLAN_SUB_INTERFACE_SEPARATOR) parent_port = substrs[0] vlan_id = substrs[1] @@ -855,6 +1191,8 @@ def _test_sub_port_intf_oper_down_with_pending_neigh_route_tasks(self, dvs, sub_ parent_port_prefix = LAG_PREFIX parent_port_idx_base = self.get_parent_port_index(parent_port) + vrf_oid = self.default_vrf_oid + # Set parent ports admin status up parent_port_idx = parent_port_idx_base for i in range(0, nhop_num): @@ -863,12 +1201,18 @@ def _test_sub_port_intf_oper_down_with_pending_neigh_route_tasks(self, dvs, sub_ parent_port_idx += (4 if parent_port_prefix == ETHERNET_PREFIX else 1) + if vrf_name: + self.create_vrf(vrf_name) + vrf_oid = self.get_newly_created_oid(ASIC_VIRTUAL_ROUTER_TABLE, [vrf_oid]) + ifnames = [] + rif_cnt = len(self.asic_db.get_keys(ASIC_RIF_TABLE)) # Create sub port interfaces - ifnames.extend(self.create_nhg_router_intfs(dvs, parent_port_prefix, parent_port_idx_base, int(vlan_id), nhop_num)) + ifnames.extend(self.create_nhg_router_intfs(dvs, parent_port_prefix, parent_port_idx_base, int(vlan_id), nhop_num, vrf_name)) # Create router interfaces on parent ports if create_intf_on_parent_port == True: - ifnames.extend(self.create_nhg_router_intfs(dvs, parent_port_prefix, parent_port_idx_base, 0, nhop_num)) + ifnames.extend(self.create_nhg_router_intfs(dvs, parent_port_prefix, parent_port_idx_base, 0, nhop_num, vrf_name)) + self.asic_db.wait_for_n_keys(ASIC_RIF_TABLE, rif_cnt + nhop_num if create_intf_on_parent_port == False else rif_cnt + nhop_num * 2) # Bring parent port oper status down one at a time # Verify next hop group members created after processing pending tasks @@ -897,19 +1241,17 @@ def _test_sub_port_intf_oper_down_with_pending_neigh_route_tasks(self, dvs, sub_ self.asic_db.wait_for_n_keys(ASIC_NEXT_HOP_TABLE, nhop_cnt + nhop_num if create_intf_on_parent_port == False else nhop_cnt + nhop_num * 2) # Mimic pending multi-next-hop route entry task - rt_tbl = swsscommon.ProducerStateTable(self.app_db.db_connection, APP_ROUTE_TABLE_NAME) - fvs = swsscommon.FieldValuePairs([("nexthop", ",".join(nhop_ips)), ("ifname", ",".join(ifnames))]) ip_prefix = "2.2.2.0/24" - rt_tbl.set(ip_prefix, fvs) + self.add_route_appl_db(ip_prefix, nhop_ips, ifnames, vrf_name) # Verify route entry created in ASIC_DB and get next hop group oid - nhg_oid = self.get_ip_prefix_nhg_oid(ip_prefix) + nhg_oid = self.get_ip_prefix_nhg_oid(ip_prefix, vrf_oid) # Verify next hop group of the specified oid created in ASIC_DB self.check_sub_port_intf_key_existence(self.asic_db, ASIC_NEXT_HOP_GROUP_TABLE, nhg_oid) # Verify next hop group member # created in ASIC_DB - nhg_member_oids = self.asic_db.wait_for_n_keys(ASIC_NEXT_HOP_GROUP_MEMBER_TABLE, \ + nhg_member_oids = self.asic_db.wait_for_n_keys(ASIC_NEXT_HOP_GROUP_MEMBER_TABLE, (nhop_num - 1) - i if create_intf_on_parent_port == False else ((nhop_num - 1) - i) * 2) # Verify that next hop group members all belong to the next hop group of the specified oid @@ -926,7 +1268,7 @@ def _test_sub_port_intf_oper_down_with_pending_neigh_route_tasks(self, dvs, sub_ if create_intf_on_parent_port == True: self.remove_nhg_next_hop_objs(dvs, parent_port_prefix, parent_port_idx_base, 0, nhop_num) # Remove ecmp route entry - rt_tbl._del(ip_prefix) + self.remove_route_appl_db(ip_prefix, vrf_name) # Removal of next hop objects indicates the proper removal of route entry, nhg, and nhg members self.asic_db.wait_for_n_keys(ASIC_NEXT_HOP_TABLE, nhop_cnt - nhop_num if create_intf_on_parent_port == False else nhop_cnt - nhop_num * 2) @@ -941,11 +1283,21 @@ def _test_sub_port_intf_oper_down_with_pending_neigh_route_tasks(self, dvs, sub_ self.remove_nhg_router_intfs(dvs, parent_port_prefix, parent_port_idx_base, 0, nhop_num) self.asic_db.wait_for_n_keys(ASIC_RIF_TABLE, rif_cnt - nhop_num if create_intf_on_parent_port == False else rif_cnt - nhop_num * 2) - # Make sure parent port oper status is up + # Remove vrf if created + if vrf_name: + self.remove_vrf(vrf_name) + self.check_vrf_removal(vrf_oid) + parent_port_idx = parent_port_idx_base for i in range(0, nhop_num): port_name = "{}{}".format(parent_port_prefix, parent_port_idx) - self.set_parent_port_oper_status(dvs, port_name, "up") + if parent_port.startswith(ETHERNET_PREFIX): + # Make sure physical port oper status is up + self.set_parent_port_oper_status(dvs, port_name, "up") + else: + # Remove lag + self.remove_lag(port_name) + self.asic_db.wait_for_n_keys(ASIC_LAG_TABLE, nhop_num - 1 - i) parent_port_idx += (4 if parent_port_prefix == ETHERNET_PREFIX else 1) @@ -957,6 +1309,13 @@ def test_sub_port_intf_oper_down_with_pending_neigh_route_tasks(self, dvs): self._test_sub_port_intf_oper_down_with_pending_neigh_route_tasks(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST) self._test_sub_port_intf_oper_down_with_pending_neigh_route_tasks(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, create_intf_on_parent_port=True) + self._test_sub_port_intf_oper_down_with_pending_neigh_route_tasks(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, vrf_name=self.VRF_UNDER_TEST) + self._test_sub_port_intf_oper_down_with_pending_neigh_route_tasks(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, + create_intf_on_parent_port=True, vrf_name=self.VRF_UNDER_TEST) + self._test_sub_port_intf_oper_down_with_pending_neigh_route_tasks(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, vrf_name=self.VRF_UNDER_TEST) + self._test_sub_port_intf_oper_down_with_pending_neigh_route_tasks(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST, + create_intf_on_parent_port=True, vrf_name=self.VRF_UNDER_TEST) + # Add Dummy always-pass test at end as workaroud # for issue when Flaky fail on final test it invokes module tear-down before retrying