diff --git a/cfgmgr/intfmgr.cpp b/cfgmgr/intfmgr.cpp index 3e0ed862be..47069f6b54 100644 --- a/cfgmgr/intfmgr.cpp +++ b/cfgmgr/intfmgr.cpp @@ -29,12 +29,15 @@ IntfMgr::IntfMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, c m_cfgVlanIntfTable(cfgDb, CFG_VLAN_INTF_TABLE_NAME), m_cfgLagIntfTable(cfgDb, CFG_LAG_INTF_TABLE_NAME), m_cfgLoopbackIntfTable(cfgDb, CFG_LOOPBACK_INTERFACE_TABLE_NAME), + m_cfgSubIntfTable(cfgDb, CFG_VLAN_SUB_INTF_TABLE_NAME), m_statePortTable(stateDb, STATE_PORT_TABLE_NAME), m_stateLagTable(stateDb, STATE_LAG_TABLE_NAME), m_stateVlanTable(stateDb, STATE_VLAN_TABLE_NAME), m_stateVrfTable(stateDb, STATE_VRF_TABLE_NAME), m_stateIntfTable(stateDb, STATE_INTERFACE_TABLE_NAME), - m_appIntfTableProducer(appDb, APP_INTF_TABLE_NAME) + m_appIntfTableProducer(appDb, APP_INTF_TABLE_NAME), + m_appPortTable(appDb, APP_PORT_TABLE_NAME), + m_appLagTable(appDb, APP_LAG_TABLE_NAME) { if (!WarmStart::isWarmStart()) { @@ -449,6 +452,107 @@ bool IntfMgr::isIntfStateOk(const string &alias) return false; } +bool IntfMgr::doHostSubIntfUpdateTask(const vector &keys, + const vector &fvTuples, + const string &op) +{ + SWSS_LOG_ENTER(); + + string parentAlias(keys[0]); + + if (op == SET_COMMAND) + { + if (!isIntfStateOk(parentAlias)) + { + return false; + } + + string mtu = ""; + string parentAdminStatus = ""; + for (const auto &fv : fvTuples) + { + if (fvField(fv) == "mtu") + { + mtu = fvValue(fv); + } + else if (fvField(fv) == "admin_status") + { + parentAdminStatus = fvValue(fv); + } + } + + if (!mtu.empty()) + { + for (const auto &alias : m_portSubIntfSet[parentAlias]) + { + try + { + setHostSubIntfMtu(alias, mtu); + } + catch (const std::runtime_error &e) + { + SWSS_LOG_DEBUG("Sub interface ip link set mtu %s failure. Runtime error: %s", mtu.c_str(), e.what()); + return false; + } + SWSS_LOG_INFO("Sub interface %s ip link set mtu %s succeeded", alias.c_str(), mtu.c_str()); + } + } + + if (parentAdminStatus == "up") + { + string parentAdminStatusAppDb; + if (!parentAlias.compare(0, strlen(LAG_PREFIX), LAG_PREFIX)) + { + m_appLagTable.hget(parentAlias, "admin_status", parentAdminStatusAppDb); + } + else + { + m_appPortTable.hget(parentAlias, "admin_status", parentAdminStatusAppDb); + } + if (parentAdminStatusAppDb != parentAdminStatus) + { + // Parent port admin status has not yet been synced from config db to appl db, which + // indicates that parent port admin status at kernel has not yet been updated from + // down to up by portmgrd. + return false; + } + + for (const auto &alias : m_portSubIntfSet[parentAlias]) + { + string adminStatus; + if (!m_cfgSubIntfTable.hget(alias, "admin_status", adminStatus)) + { + adminStatus = "up"; + } + + if (adminStatus == "down") + { + try + { + setHostSubIntfAdminStatus(alias, adminStatus); + } + catch (const std::runtime_error &e) + { + SWSS_LOG_DEBUG("Sub interface ip link set admin status %s failure. Runtime error: %s", adminStatus.c_str(), e.what()); + return false; + } + SWSS_LOG_INFO("Sub interface %s ip link set admin status %s succeeded", alias.c_str(), adminStatus.c_str()); + } + } + } + } + else if (op == DEL_COMMAND) + { + m_portSubIntfSet.erase(parentAlias); + } + else + { + SWSS_LOG_ERROR("Unknown operation: %s", op.c_str()); + } + + return true; +} + bool IntfMgr::doIntfGeneralTask(const vector& keys, vector data, const string& op) @@ -591,25 +695,15 @@ bool IntfMgr::doIntfGeneralTask(const vector& keys, } m_subIntfList.insert(alias); + m_portSubIntfSet[parentAlias].insert(alias); } if (!mtu.empty()) { - try - { - setHostSubIntfMtu(alias, mtu); - } - catch (const std::runtime_error &e) - { - SWSS_LOG_NOTICE("Sub interface ip link set mtu failure. Runtime error: %s", e.what()); - return false; - } - } - else - { - FieldValueTuple fvTuple("mtu", MTU_INHERITANCE); - data.push_back(fvTuple); + SWSS_LOG_NOTICE("Sub interface inherits parent port mtu. User mtu %s ignored", mtu.c_str()); } + FieldValueTuple fvTuple("mtu", MTU_INHERITANCE); + data.push_back(fvTuple); if (adminStatus.empty()) { @@ -701,6 +795,7 @@ bool IntfMgr::doIntfGeneralTask(const vector& keys, { removeHostSubIntf(alias); m_subIntfList.erase(alias); + m_portSubIntfSet[parentAlias].erase(alias); removeSubIntfState(alias); } @@ -789,7 +884,21 @@ void IntfMgr::doTask(Consumer &consumer) if (keys.size() == 1) { - if((table_name == CFG_VOQ_INBAND_INTERFACE_TABLE_NAME) && + if ((table_name == CFG_PORT_TABLE_NAME) + || (table_name == CFG_LAG_TABLE_NAME)) + { + if (!doHostSubIntfUpdateTask(keys, data, op)) + { + it++; + } + else + { + it = consumer.m_toSync.erase(it); + } + continue; + } + + if ((table_name == CFG_VOQ_INBAND_INTERFACE_TABLE_NAME) && (op == SET_COMMAND)) { //No further processing needed. Just relay to orchagent @@ -799,6 +908,7 @@ void IntfMgr::doTask(Consumer &consumer) it = consumer.m_toSync.erase(it); continue; } + if (!doIntfGeneralTask(keys, data, op)) { it++; diff --git a/cfgmgr/intfmgr.h b/cfgmgr/intfmgr.h index 655fb4deeb..b6d204d264 100644 --- a/cfgmgr/intfmgr.h +++ b/cfgmgr/intfmgr.h @@ -19,10 +19,12 @@ class IntfMgr : public Orch private: ProducerStateTable m_appIntfTableProducer; - Table m_cfgIntfTable, m_cfgVlanIntfTable, m_cfgLagIntfTable, m_cfgLoopbackIntfTable; + Table m_cfgIntfTable, m_cfgVlanIntfTable, m_cfgLagIntfTable, m_cfgLoopbackIntfTable, m_cfgSubIntfTable; Table m_statePortTable, m_stateLagTable, m_stateVlanTable, m_stateVrfTable, m_stateIntfTable; + Table m_appPortTable, m_appLagTable; - std::set m_subIntfList; + std::unordered_set m_subIntfList; + std::unordered_map> m_portSubIntfSet; std::set m_loopbackIntfList; std::set m_pendingReplayIntfList; @@ -33,6 +35,7 @@ class IntfMgr : public Orch bool doIntfGeneralTask(const std::vector& keys, std::vector data, const std::string& op); bool doIntfAddrTask(const std::vector& keys, const std::vector& data, const std::string& op); + bool doHostSubIntfUpdateTask(const std::vector& keys, const std::vector& data, const std::string& op); void doTask(Consumer &consumer); bool isIntfStateOk(const std::string &alias); diff --git a/cfgmgr/intfmgrd.cpp b/cfgmgr/intfmgrd.cpp index d6ed18526e..c3e7aacdb3 100644 --- a/cfgmgr/intfmgrd.cpp +++ b/cfgmgr/intfmgrd.cpp @@ -48,6 +48,8 @@ int main(int argc, char **argv) CFG_LOOPBACK_INTERFACE_TABLE_NAME, CFG_VLAN_SUB_INTF_TABLE_NAME, CFG_VOQ_INBAND_INTERFACE_TABLE_NAME, + CFG_PORT_TABLE_NAME, + CFG_LAG_TABLE_NAME, }; DBConnector cfgDb("CONFIG_DB", 0); diff --git a/tests/test_sub_port_intf.py b/tests/test_sub_port_intf.py index ac65a30696..ca7d82ba3d 100644 --- a/tests/test_sub_port_intf.py +++ b/tests/test_sub_port_intf.py @@ -37,6 +37,8 @@ ETHERNET_PREFIX = "Ethernet" LAG_PREFIX = "PortChannel" +VRF_PREFIX = "Vrf" +VNET_PREFIX = "Vnet" VLAN_SUB_INTERFACE_SEPARATOR = "." APPL_DB_SEPARATOR = ":" @@ -138,6 +140,9 @@ def create_phy_port_appl_db(self, dvs, port_name): self.asic_db.wait_for_n_keys(ASIC_HOSTIF_TABLE, hostif_cnt + 1) dvs.asicdb._generate_oid_to_interface_mapping() + (ec, out) = dvs.runcmd(['bash', '-c', "ip link set {} mtu {}".format(port_name, self.port_fvs[port_name]["mtu"])]) + assert ec == 0 + for key, fvs in self.buf_pg_fvs.items(): if port_name in key: self.config_db.create_entry("BUFFER_PG", key, fvs) @@ -318,6 +323,23 @@ def _access_function(): wait_for_result(_access_function) + def check_sub_port_intf_mtu_kernel(self, dvs, port_name, mtu): + (ec, out) = dvs.runcmd(['bash', '-c', "ip link show {} | grep 'mtu {}'".format(port_name, mtu)]) + assert ec == 0 + assert mtu in out + + def check_sub_port_intf_admin_status_kernel(self, dvs, port_name, admin_up): + up = "UP" + if admin_up == True: + up = "," + up + (ec, out) = dvs.runcmd(['bash', '-c', "ip link show {} | grep {}".format(port_name, up)]) + if admin_up == True: + assert ec == 0 + assert up in out + else: + assert ec == 1 + assert up not in out + 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 @@ -616,6 +638,9 @@ def _test_sub_port_intf_admin_status_change(self, dvs, sub_port_intf_name, vrf_n 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) + # Verify sub port interface admin status in linux kernel + self.check_sub_port_intf_admin_status_kernel(dvs, sub_port_intf_name, admin_up=True) + fv_dict = { ADMIN_STATUS: "up", } @@ -635,6 +660,9 @@ def _test_sub_port_intf_admin_status_change(self, dvs, sub_port_intf_name, vrf_n # Change sub port interface admin status to down self.set_sub_port_intf_admin_status(sub_port_intf_name, "down") + # Verify sub port interface admin status change in linux kernel + self.check_sub_port_intf_admin_status_kernel(dvs, sub_port_intf_name, admin_up=False) + # Verify that sub port interface admin status change is synced to APP_DB by Intfmgrd fv_dict = { ADMIN_STATUS: "down", @@ -656,6 +684,9 @@ def _test_sub_port_intf_admin_status_change(self, dvs, sub_port_intf_name, vrf_n # Change sub port interface admin status to up self.set_sub_port_intf_admin_status(sub_port_intf_name, "up") + # Verify sub port interface admin status change in linux kernel + self.check_sub_port_intf_admin_status_kernel(dvs, sub_port_intf_name, admin_up=True) + # Verify that sub port interface admin status change is synced to APP_DB by Intfmgrd fv_dict = { ADMIN_STATUS: "up", @@ -704,6 +735,189 @@ def test_sub_port_intf_admin_status_change(self, dvs): 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_parent_port_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) + + # Set parent port admin status up + self.set_parent_port_admin_status(dvs, parent_port, "up") + 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) + if vrf_name is None or not vrf_name.startswith(VNET_PREFIX): + self.add_sub_port_intf_ip_addr(sub_port_intf_name, self.IPV6_ADDR_UNDER_TEST) + + # Verify sub port interface admin status up in linux kernel + self.check_sub_port_intf_admin_status_kernel(dvs, sub_port_intf_name, admin_up=True) + # Verify sub port interface admin status up in APP_DB + fv_dict = { + ADMIN_STATUS: "up", + } + if vrf_name: + fv_dict[VRF_NAME if vrf_name.startswith(VRF_PREFIX) else VNET_NAME] = vrf_name + self.check_sub_port_intf_fvs(self.app_db, APP_INTF_TABLE_NAME, sub_port_intf_name, fv_dict) + # Verify sub port interface admin status up in ASIC_DB + 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) + + # Set parent port admin status down, with sub port interface admin status up + self.set_parent_port_admin_status(dvs, parent_port, "down") + + # Verify sub port interface admin status down in linux kernel + self.check_sub_port_intf_admin_status_kernel(dvs, sub_port_intf_name, admin_up=False) + # Verify that sub port interface admin status in APP_DB stays unchanged (admin status up) + fv_dict = { + ADMIN_STATUS: "up", + } + if vrf_name: + fv_dict[VRF_NAME if vrf_name.startswith(VRF_PREFIX) else VNET_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 stays unchanged (admin status up) + 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) + + # Set parent port admin status up, with sub port interface admin status up + self.set_parent_port_admin_status(dvs, parent_port, "up") + + # Verify sub port interface admin status up in linux kernel + self.check_sub_port_intf_admin_status_kernel(dvs, sub_port_intf_name, admin_up=True) + # Verify that sub port interface admin status in APP_DB stays unchanged (admin status up) + fv_dict = { + ADMIN_STATUS: "up", + } + if vrf_name: + fv_dict[VRF_NAME if vrf_name.startswith(VRF_PREFIX) else VNET_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 stays unchanged (admin status up) + 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) + + # Change sub port interface admin status to down, with parent port admin status up + self.set_sub_port_intf_admin_status(sub_port_intf_name, "down") + + # Verify sub port interface admin status change in linux kernel + self.check_sub_port_intf_admin_status_kernel(dvs, sub_port_intf_name, admin_up=False) + # Verify that sub port interface admin status change is synced to APP_DB by Intfmgrd + fv_dict = { + ADMIN_STATUS: "down", + } + if vrf_name: + fv_dict[VRF_NAME if vrf_name.startswith(VRF_PREFIX) else VNET_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 + fv_dict = { + "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) + + # Set parent port admin status down, with sub port interface admin status down + self.set_parent_port_admin_status(dvs, parent_port, "down") + + # Verify sub port interface admin status down in linux kernel + self.check_sub_port_intf_admin_status_kernel(dvs, sub_port_intf_name, admin_up=False) + # Verify that sub port interface admin status in APP_DB stays unchanged (admin down) + fv_dict = { + ADMIN_STATUS: "down", + } + if vrf_name: + fv_dict[VRF_NAME if vrf_name.startswith(VRF_PREFIX) else VNET_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 stays unchanged (admin down) + fv_dict = { + "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) + + # Set parent port admin status up, with sub port interface admin status down + self.set_parent_port_admin_status(dvs, parent_port, "up") + + # Verify sub port interface admin status down in linux kernel + self.check_sub_port_intf_admin_status_kernel(dvs, sub_port_intf_name, admin_up=False) + # Verify that sub port interface admin status in APP_DB stays unchanged (admin status down) + fv_dict = { + ADMIN_STATUS: "down", + } + if vrf_name: + fv_dict[VRF_NAME if vrf_name.startswith(VRF_PREFIX) else VNET_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 stays unchanged (admin status down) + fv_dict = { + "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) + + # Remove IP addresses + ip_addrs = [ + self.IPV4_ADDR_UNDER_TEST, + ] + self.remove_sub_port_intf_ip_addr(sub_port_intf_name, self.IPV4_ADDR_UNDER_TEST) + if vrf_name is None or not vrf_name.startswith(VNET_PREFIX): + ip_addrs.append(self.IPV6_ADDR_UNDER_TEST) + self.remove_sub_port_intf_ip_addr(sub_port_intf_name, self.IPV6_ADDR_UNDER_TEST) + self.check_sub_port_intf_ip_addr_removal(sub_port_intf_name, ip_addrs) + + # Remove a sub port interface + 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) + if vrf_name.startswith(VNET_PREFIX): + self.remove_vxlan_tunnel(self.TUNNEL_UNDER_TEST) + self.app_db.wait_for_n_keys(ASIC_TUNNEL_TABLE, 0) + + # 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_parent_port_admin_status_change(self, dvs): + self.connect_dbs(dvs) + + self._test_sub_port_intf_parent_port_admin_status_change(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST) + self._test_sub_port_intf_parent_port_admin_status_change(dvs, self.LAG_SUB_PORT_INTERFACE_UNDER_TEST) + + self._test_sub_port_intf_parent_port_admin_status_change(dvs, self.SUB_PORT_INTERFACE_UNDER_TEST, self.VRF_UNDER_TEST) + self._test_sub_port_intf_parent_port_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] @@ -976,10 +1190,44 @@ def _test_sub_port_intf_mtu(self, dvs, sub_port_intf_name, vrf_name=None): rif_oid = self.get_newly_created_oid(ASIC_RIF_TABLE, old_rif_oids) + # Verify sub port interface mtu in linux kernel + self.check_sub_port_intf_mtu_kernel(dvs, sub_port_intf_name, DEFAULT_MTU) + # Change parent port mtu mtu = "8888" dvs.set_mtu(parent_port, mtu) + # Verify sub port interface mtu in linux kernel + self.check_sub_port_intf_mtu_kernel(dvs, sub_port_intf_name, mtu) + + # 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) + + # Change parent port mtu + mtu = "6666" + dvs.set_mtu(parent_port, mtu) + + # Verify sub port interface mtu in linux kernel + self.check_sub_port_intf_mtu_kernel(dvs, sub_port_intf_name, mtu) + + # 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) + + # Change parent port mtu + mtu = "7777" + dvs.set_mtu(parent_port, mtu) + + # Verify sub port interface mtu in linux kernel + self.check_sub_port_intf_mtu_kernel(dvs, sub_port_intf_name, mtu) + # Verify that sub port router interface entry in ASIC_DB has the updated mtu fv_dict = { "SAI_ROUTER_INTERFACE_ATTR_MTU": mtu, @@ -990,6 +1238,9 @@ def _test_sub_port_intf_mtu(self, dvs, sub_port_intf_name, vrf_name=None): # Restore parent port mtu dvs.set_mtu(parent_port, DEFAULT_MTU) + # Verify sub port interface mtu in linux kernel + self.check_sub_port_intf_mtu_kernel(dvs, sub_port_intf_name, DEFAULT_MTU) + # Verify that sub port router interface entry in ASIC_DB has the default mtu fv_dict = { "SAI_ROUTER_INTERFACE_ATTR_MTU": DEFAULT_MTU,