From 9f645e5a7e30d6165274c27d7fa3bc27520803f9 Mon Sep 17 00:00:00 2001 From: Shuotian Cheng Date: Tue, 21 Aug 2018 11:21:41 -0700 Subject: [PATCH] [portsorch]: Support LAG MTU configuration (#581) - LAG MTU configuration is now on stage - By default, the MTU of port channel based router interface is 9100. - If a new MTU is applied to the port channel via configuration database, this new MTU will be used 1) to the netdev in the kernel via ip command; 2) to all the member netdevs in the kernel via teamd; 3) to the port channel based router interface MTU; 4) to all the member port MTU. - Remove the libnl MTU from teamsyncd - Refactor test_interface.py tests. Each one test is independent from the other test. The switch will be cleaned up at the end of the test. Signed-off-by: Shu0T1an ChenG --- cfgmgr/portmgr.cpp | 55 ++++++++- cfgmgr/portmgr.h | 4 +- orchagent/intfsorch.cpp | 5 +- orchagent/portsorch.cpp | 58 +++++++-- teamsyncd/teamsync.cpp | 11 +- teamsyncd/teamsync.h | 2 +- tests/test_interface.py | 267 ++++++++++++++++++++++++++++++---------- 7 files changed, 309 insertions(+), 93 deletions(-) diff --git a/cfgmgr/portmgr.cpp b/cfgmgr/portmgr.cpp index 1dc74b9367c1..14073a488ada 100644 --- a/cfgmgr/portmgr.cpp +++ b/cfgmgr/portmgr.cpp @@ -1,4 +1,5 @@ #include + #include "logger.h" #include "dbconnector.h" #include "producerstatetable.h" @@ -16,17 +17,57 @@ PortMgr::PortMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, c m_cfgPortTable(cfgDb, CFG_PORT_TABLE_NAME), m_cfgLagTable(cfgDb, CFG_LAG_TABLE_NAME), m_statePortTable(stateDb, STATE_PORT_TABLE_NAME), - m_stateLagTable(stateDb, STATE_LAG_TABLE_NAME) + m_stateLagTable(stateDb, STATE_LAG_TABLE_NAME), + m_appPortTable(appDb, APP_PORT_TABLE_NAME), + m_appLagTable(appDb, APP_LAG_TABLE_NAME) { } -bool PortMgr::setPortMtu(const string &alias, const string &mtu) +bool PortMgr::setPortMtu(const string &table, const string &alias, const string &mtu) { stringstream cmd; string res; cmd << IP_CMD << " link set dev " << alias << " mtu " << mtu; - return exec(cmd.str(), res) == 0; + EXEC_WITH_ERROR_THROW(cmd.str(), res); + + if (table == CFG_PORT_TABLE_NAME) + { + // Set the port MTU in application database to update both + // the port MTU and possibly the port based router interface MTU + vector fvs; + FieldValueTuple fv("mtu", mtu); + fvs.push_back(fv); + m_appPortTable.set(alias, fvs); + } + else if (table == CFG_LAG_TABLE_NAME) + { + // Set the port channel MTU in application database to update + // the LAG based router interface MTU in orchagent + vector fvs; + FieldValueTuple fv("mtu", mtu); + fvs.push_back(fv); + m_appLagTable.set(alias, fvs); + + m_cfgLagTable.get(alias, fvs); + for (auto fv: fvs) + { + // Set the port channel members MTU in application database + // to update the port MTU in orchagent + if (fvField(fv) == "members") + { + for (auto member : tokenize(fvValue(fv), ',')) + { + vector member_fvs; + FieldValueTuple member_fv("mtu", mtu); + member_fvs.push_back(member_fv); + m_appPortTable.set(member, member_fvs); + } + } + } + } + + return true; } bool PortMgr::setPortAdminStatus(const string &alias, const bool up) @@ -35,7 +76,9 @@ bool PortMgr::setPortAdminStatus(const string &alias, const bool up) string res; cmd << IP_CMD << " link set dev " << alias << (up ? " up" : " down"); - return exec(cmd.str(), res) == 0; + EXEC_WITH_ERROR_THROW(cmd.str(), res); + + return true; } bool PortMgr::isPortStateOk(const string &table, const string &alias) @@ -80,7 +123,7 @@ void PortMgr::doTask(Consumer &consumer) { if (!isPortStateOk(table, alias)) { - SWSS_LOG_INFO("Port %s is not ready, pending", alias.c_str()); + SWSS_LOG_INFO("Port %s is not ready, pending...", alias.c_str()); it++; continue; } @@ -90,7 +133,7 @@ void PortMgr::doTask(Consumer &consumer) if (fvField(i) == "mtu") { auto mtu = fvValue(i); - setPortMtu(alias, mtu); + setPortMtu(table, alias, mtu); SWSS_LOG_NOTICE("Configure %s MTU to %s", alias.c_str(), mtu.c_str()); } diff --git a/cfgmgr/portmgr.h b/cfgmgr/portmgr.h index 341f95c58829..b378652ce2b4 100644 --- a/cfgmgr/portmgr.h +++ b/cfgmgr/portmgr.h @@ -21,9 +21,11 @@ class PortMgr : public Orch Table m_cfgLagTable; Table m_statePortTable; Table m_stateLagTable; + ProducerStateTable m_appPortTable; + ProducerStateTable m_appLagTable; void doTask(Consumer &consumer); - bool setPortMtu(const string &alias, const string &mtu); + bool setPortMtu(const string &table, const string &alias, const string &mtu); bool setPortAdminStatus(const string &alias, const bool up); bool isPortStateOk(const string &table, const string &alias); }; diff --git a/orchagent/intfsorch.cpp b/orchagent/intfsorch.cpp index 3d67767c6d87..c740deb23c78 100644 --- a/orchagent/intfsorch.cpp +++ b/orchagent/intfsorch.cpp @@ -310,13 +310,14 @@ bool IntfsOrch::addRouterIntfs(Port &port) sai_status_t status = sai_router_intfs_api->create_router_interface(&port.m_rif_id, gSwitchId, (uint32_t)attrs.size(), attrs.data()); if (status != SAI_STATUS_SUCCESS) { - SWSS_LOG_ERROR("Failed to create router interface for port %s, rv:%d", port.m_alias.c_str(), status); + SWSS_LOG_ERROR("Failed to create router interface %s, rv:%d", + port.m_alias.c_str(), status); throw runtime_error("Failed to create router interface."); } gPortsOrch->setPort(port.m_alias, port); - SWSS_LOG_NOTICE("Create router interface for port %s mtu %u", port.m_alias.c_str(), port.m_mtu); + SWSS_LOG_NOTICE("Create router interface %s MTU %u", port.m_alias.c_str(), port.m_mtu); return true; } diff --git a/orchagent/portsorch.cpp b/orchagent/portsorch.cpp index 0074798aa47b..866dcb34e55d 100644 --- a/orchagent/portsorch.cpp +++ b/orchagent/portsorch.cpp @@ -487,7 +487,8 @@ bool PortsOrch::setPortMtu(sai_object_id_t id, sai_uint32_t mtu) sai_status_t status = sai_port_api->set_port_attribute(id, &attr); if (status != SAI_STATUS_SUCCESS) { - SWSS_LOG_ERROR("Failed to set MTU %u to port pid:%lx", attr.value.u32, id); + SWSS_LOG_ERROR("Failed to set MTU %u to port pid:%lx, rv:%d", + attr.value.u32, id, status); return false; } SWSS_LOG_INFO("Set MTU %u to port pid:%lx", attr.value.u32, id); @@ -1276,7 +1277,7 @@ void PortsOrch::doPortTask(Consumer &consumer) return; } - if (op == "SET") + if (op == SET_COMMAND) { set lane_set; string admin_status; @@ -1303,11 +1304,15 @@ void PortsOrch::doPortTask(Consumer &consumer) /* Set port admin status */ if (fvField(i) == "admin_status") + { admin_status = fvValue(i); + } /* Set port MTU */ if (fvField(i) == "mtu") + { mtu = (uint32_t)stoul(fvValue(i)); + } /* Set port speed */ if (fvField(i) == "speed") @@ -1317,7 +1322,9 @@ void PortsOrch::doPortTask(Consumer &consumer) /* Set port fec */ if (fvField(i) == "fec") + { fec_mode = fvValue(i); + } /* Set autoneg and ignore the port speed setting */ if (fvField(i) == "autoneg") @@ -1786,28 +1793,57 @@ void PortsOrch::doLagTask(Consumer &consumer) { auto &t = it->second; - string lag_alias = kfvKey(t); + string alias = kfvKey(t); string op = kfvOp(t); if (op == SET_COMMAND) { - /* Duplicate entry */ - if (m_portList.find(lag_alias) != m_portList.end()) + // Retrieve attributes + uint32_t mtu = 0; + for (auto i : kfvFieldsValues(t)) { - it = consumer.m_toSync.erase(it); - continue; + if (fvField(i) == "mtu") + { + mtu = (uint32_t)stoul(fvValue(i)); + } } - if (addLag(lag_alias)) - it = consumer.m_toSync.erase(it); + // Create a new LAG when the new alias comes + if (m_portList.find(alias) == m_portList.end()) + { + if (!addLag(alias)) + { + it++; + continue; + } + } + + // Process attributes + Port l; + if (!getPort(alias, l)) + { + SWSS_LOG_ERROR("Failed to get LAG %s", alias.c_str()); + } else - it++; + { + if (mtu != 0 && l.m_rif_id) + { + l.m_mtu = mtu; + m_portList[alias] = l; + if (l.m_rif_id) + { + gIntfsOrch->setRouterIntfsMtu(l); + } + } + } + + it = consumer.m_toSync.erase(it); } else if (op == DEL_COMMAND) { Port lag; /* Cannot locate LAG */ - if (!getPort(lag_alias, lag)) + if (!getPort(alias, lag)) { it = consumer.m_toSync.erase(it); continue; diff --git a/teamsyncd/teamsync.cpp b/teamsyncd/teamsync.cpp index 88ed67602d12..6e49971d5dab 100644 --- a/teamsyncd/teamsync.cpp +++ b/teamsyncd/teamsync.cpp @@ -45,25 +45,22 @@ void TeamSync::onMsg(int nlmsg_type, struct nl_object *obj) addLag(lagName, rtnl_link_get_ifindex(link), rtnl_link_get_flags(link) & IFF_UP, - rtnl_link_get_flags(link) & IFF_LOWER_UP, - rtnl_link_get_mtu(link)); + rtnl_link_get_flags(link) & IFF_LOWER_UP); } void TeamSync::addLag(const string &lagName, int ifindex, bool admin_state, - bool oper_state, unsigned int mtu) + bool oper_state) { /* Set the LAG */ std::vector fvVector; FieldValueTuple a("admin_status", admin_state ? "up" : "down"); FieldValueTuple o("oper_status", oper_state ? "up" : "down"); - FieldValueTuple m("mtu", to_string(mtu)); fvVector.push_back(a); fvVector.push_back(o); - fvVector.push_back(m); m_lagTable.set(lagName, fvVector); - SWSS_LOG_INFO("Add %s admin_status:%s oper_status:%s mtu:%d", - lagName.c_str(), admin_state ? "up" : "down", oper_state ? "up" : "down", mtu); + SWSS_LOG_INFO("Add %s admin_status:%s oper_status:%s", + lagName.c_str(), admin_state ? "up" : "down", oper_state ? "up" : "down"); /* Return when the team instance has already been tracked */ if (m_teamPorts.find(lagName) != m_teamPorts.end()) diff --git a/teamsyncd/teamsync.h b/teamsyncd/teamsync.h index 79ca1e1e570a..c53ad224e80a 100644 --- a/teamsyncd/teamsync.h +++ b/teamsyncd/teamsync.h @@ -50,7 +50,7 @@ class TeamSync : public NetMsg protected: void addLag(const std::string &lagName, int ifindex, bool admin_state, - bool oper_state, unsigned int mtu); + bool oper_state); void removeLag(const std::string &lagName); private: diff --git a/tests/test_interface.py b/tests/test_interface.py index 701ad0cc7c63..a2232015adad 100644 --- a/tests/test_interface.py +++ b/tests/test_interface.py @@ -3,20 +3,37 @@ import time import json -class TestInterfaceIpv4Addresses(object): - def test_InterfaceAddIpv4Address(self, dvs): - pdb = swsscommon.DBConnector(0, dvs.redis_sock, 0) - adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) - - # assign IP to interface - tbl = swsscommon.Table(cdb, "INTERFACE") +class TestRouterInterfaceIpv4(object): + def setup_db(self, dvs): + self.pdb = swsscommon.DBConnector(0, dvs.redis_sock, 0) + self.adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) + self.cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) + + def add_ip_address(self, interface, ip): + tbl = swsscommon.Table(self.cdb, "INTERFACE") fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) - tbl.set("Ethernet8|10.0.0.4/31", fvs) + tbl.set(interface + "|" + ip, fvs) + time.sleep(1) + + def remove_ip_address(self, interface, ip): + tbl = swsscommon.Table(self.cdb, "INTERFACE") + tbl._del(interface + "|" + ip); time.sleep(1) + def set_mtu(self, interface, mtu): + tbl = swsscommon.Table(self.cdb, "PORT") + fvs = swsscommon.FieldValuePairs([("mtu", mtu)]) + tbl.set(interface, fvs) + time.sleep(1) + + def test_InterfaceAddRemoveIpv4Address(self, dvs): + self.setup_db(dvs) + + # assign IP to interface + self.add_ip_address("Ethernet8", "10.0.0.4/31") + # check application database - tbl = swsscommon.Table(pdb, "INTF_TABLE:Ethernet8") + tbl = swsscommon.Table(self.pdb, "INTF_TABLE:Ethernet8") intf_entries = tbl.getKeys() assert len(intf_entries) == 1 assert intf_entries[0] == "10.0.0.4/31" @@ -33,7 +50,7 @@ def test_InterfaceAddIpv4Address(self, dvs): assert False # check ASIC router interface database - tbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") intf_entries = tbl.getKeys() # one loopback router interface one port based router interface assert len(intf_entries) == 2 @@ -46,11 +63,12 @@ def test_InterfaceAddIpv4Address(self, dvs): for fv in fvs: if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_TYPE": assert fv[1] == "SAI_ROUTER_INTERFACE_TYPE_PORT" + # the default MTU without any configuration is 9100 if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_MTU": assert fv[1] == "9100" # check ASIC route database - tbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") for key in tbl.getKeys(): route = json.loads(key) if route["dest"] == "10.0.0.4/31": @@ -60,19 +78,34 @@ def test_InterfaceAddIpv4Address(self, dvs): assert subnet_found and ip2me_found - def test_InterfaceChangeMtu(self, dvs): - pdb = swsscommon.DBConnector(0, dvs.redis_sock, 0) - adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) + # remove IP from interface + self.remove_ip_address("Ethernet8", "10.0.0.4/31") - tbl = swsscommon.ProducerStateTable(pdb, "PORT_TABLE") - fvs = swsscommon.FieldValuePairs([("mtu", "8888")]) - tbl.set("Ethernet8", fvs) + # check application database + tbl = swsscommon.Table(self.pdb, "INTF_TABLE:Ethernet8") + intf_entries = tbl.getKeys() + assert len(intf_entries) == 0 - time.sleep(1) + # check ASIC database + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") + for key in tbl.getKeys(): + route = json.loads(key) + if route["dest"] == "10.0.0.4/31": + assert False + if route["dest"] == "10.0.0.4/32": + assert False + + def test_InterfaceSetMtu(self, dvs): + self.setup_db(dvs) + + # assign IP to interface + self.add_ip_address("Ethernet16", "20.0.0.8/29") + + # configure MTU to interface + self.set_mtu("Ethernet16", "8888") # check ASIC router interface database - tbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") intf_entries = tbl.getKeys() # one loopback router interface one port based router interface assert len(intf_entries) == 2 @@ -85,77 +118,181 @@ def test_InterfaceChangeMtu(self, dvs): for fv in fvs: if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_TYPE": assert fv[1] == "SAI_ROUTER_INTERFACE_TYPE_PORT" + # assert the new value set to the router interface if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_MTU": assert fv[1] == "8888" - def test_InterfaceRemoveIpv4Address(self, dvs): - pdb = swsscommon.DBConnector(0, dvs.redis_sock, 0) - adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) - # remove IP from interface - tbl = swsscommon.Table(cdb, "INTERFACE") - tbl._del("Ethernet8|10.0.0.4/31") + self.remove_ip_address("Ethernet16", "20.0.0.8/29") + +class TestLagRouterInterfaceIpv4(object): + def setup_db(self, dvs): + self.pdb = swsscommon.DBConnector(0, dvs.redis_sock, 0) + self.adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) + self.cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) + + # TODO: below three functions will be replaced with configuration + # database updates after the future changes of the lagmgrd + def create_port_channel(self, dvs, interface): + dvs.runcmd("teamd -d -t" + interface) + time.sleep(1) + + def remove_port_channel(self, dvs, interface): + dvs.runcmd("teamd -k -t" + interface) + time.sleep(1) + + def add_port_channel_members(self, dvs, interface, members): + for member in members: + dvs.runcmd("ip link set dev " + interface + " up") + dvs.runcmd("ip link set dev " + interface + " down") + dvs.runcmd("teamdctl " + interface + " port add " + member) + tbl = swsscommon.Table(self.cdb, "PORTCHANNEL") + fvs = swsscommon.FieldValuePairs([("members@", ",".join(members))]) + tbl.set(interface, fvs) + time.sleep(1) + + def add_ip_address(self, interface, ip): + tbl = swsscommon.Table(self.cdb, "PORTCHANNEL_INTERFACE") + fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) + tbl.set(interface + "|" + ip, fvs) + time.sleep(1) + + def remove_ip_address(self, interface, ip): + tbl = swsscommon.Table(self.cdb, "PORTCHANNEL_INTERFACE") + tbl._del(interface + "|" + ip); + time.sleep(1) + + def set_mtu(self, interface, mtu): + tbl = swsscommon.Table(self.cdb, "PORTCHANNEL") + fvs = swsscommon.FieldValuePairs([("mtu", mtu)]) + tbl.set(interface, fvs) time.sleep(1) + def test_InterfaceAddRemoveIpv4Address(self, dvs): + self.setup_db(dvs) + + # create port channel + self.create_port_channel(dvs, "PortChannel001") + + # assign IP to interface + self.add_ip_address("PortChannel001", "30.0.0.4/31") + # check application database - tbl = swsscommon.Table(pdb, "INTF_TABLE:Ethernet8") + tbl = swsscommon.Table(self.pdb, "INTF_TABLE:PortChannel001") intf_entries = tbl.getKeys() - assert len(intf_entries) == 0 + assert len(intf_entries) == 1 + assert intf_entries[0] == "30.0.0.4/31" - # check ASIC database - tbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") - for key in tbl.getKeys(): - route = json.loads(key) - if route["dest"] == "10.0.0.4/31": - assert False - if route["dest"] == "10.0.0.4/32": + (status, fvs) = tbl.get(tbl.getKeys()[0]) + assert status == True + assert len(fvs) == 2 + for fv in fvs: + if fv[0] == "scope": + assert fv[1] == "global" + elif fv[0] == "family": + assert fv[1] == "IPv4" + else: assert False + # check ASIC router interface database + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") + intf_entries = tbl.getKeys() + # one loopback router interface one port based router interface + assert len(intf_entries) == 2 -def test_InterfaceIpChange(dvs): - - dvs.runcmd("ifconfig Ethernet0 10.0.0.0/31 up") + for key in intf_entries: + (status, fvs) = tbl.get(key) + assert status == True + # a port based router interface has five field/value tuples + if len(fvs) == 5: + for fv in fvs: + if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_TYPE": + assert fv[1] == "SAI_ROUTER_INTERFACE_TYPE_PORT" + # the default MTU without any configuration is 9100 + if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_MTU": + assert fv[1] == "9100" - time.sleep(1) + # check ASIC route database + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") + for key in tbl.getKeys(): + route = json.loads(key) + if route["dest"] == "30.0.0.4/31": + subnet_found = True + if route["dest"] == "30.0.0.4/32": + ip2me_found = True - # check if route was propagated to ASIC DB + assert subnet_found and ip2me_found - db = swsscommon.DBConnector(1, dvs.redis_sock, 0) + # remove IP from interface + self.remove_ip_address("PortChannel001", "30.0.0.4/31") - tbl = swsscommon.Table(db, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") + # check application database + tbl = swsscommon.Table(self.pdb, "INTF_TABLE:PortChannel001") + intf_entries = tbl.getKeys() + assert len(intf_entries) == 0 - keys = tbl.getKeys() + # check ASIC database + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") + for key in tbl.getKeys(): + route = json.loads(key) + if route["dest"] == "30.0.0.4/31": + assert False + if route["dest"] == "30.0.0.4/32": + assert False - for k in keys: - rt_key = json.loads(k) + # remove port channel + self.remove_port_channel(dvs, "PortChannel001") - if rt_key['dest'] == "10.0.0.0/31": - subnet_found = True - if rt_key['dest'] == "10.0.0.0/32": - ip2me_found = True + def test_InterfaceSetMtu(self, dvs): + self.setup_db(dvs) - assert subnet_found == True and ip2me_found == True + # create port channel + self.create_port_channel(dvs, "PortChannel002") - subnet_found = False - ip2me_found = False + # add port channel members + self.add_port_channel_members(dvs, "PortChannel002", ["Ethernet0", "Ethernet4"]) - dvs.runcmd("ifconfig Ethernet0 10.0.0.0/24 up") + # assign IP to interface + self.add_ip_address("PortChannel002", "40.0.0.8/29") - time.sleep(1) + # configure MTU to interface + self.set_mtu("PortChannel002", "8888") - # check if route was propagated to ASIC DB + # check ASIC router interface database + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") + intf_entries = tbl.getKeys() + # one loopback router interface one port based router interface + assert len(intf_entries) == 2 - keys = tbl.getKeys() + for key in intf_entries: + (status, fvs) = tbl.get(key) + assert status == True + # a port based router interface has five field/value tuples + if len(fvs) == 5: + for fv in fvs: + if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_TYPE": + assert fv[1] == "SAI_ROUTER_INTERFACE_TYPE_PORT" + # assert the new value set to the router interface + if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_MTU": + assert fv[1] == "8888" - for k in keys: - rt_key = json.loads(k) + # check ASIC port database + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_PORT") + port_entries = tbl.getKeys() - if rt_key['dest'] == "10.0.0.0/24": - subnet_found = True + for key in port_entries: + (status, fvs) = tbl.get(key) + assert status == True + # a member port configured with MTU will have six field/value tuples + if len(fvs) == 6: + for fv in fvs: + # asser the new value 8888 + 22 = 8910 set to the port + if fv[0] == "SAI_PORT_ATTR_MTU": + assert fv[1] == "8910" - if rt_key['dest'] == "10.0.0.0/32": - ip2me_found = True + # remove IP from interface + self.remove_ip_address("Ethernet16", "40.0.0.8/29") - assert subnet_found == True and ip2me_found == True + # remove port channel + self.remove_port_channel(dvs, "PortChannel002")