diff --git a/orchagent/portsorch.cpp b/orchagent/portsorch.cpp index 395f419c63..b621906a4a 100755 --- a/orchagent/portsorch.cpp +++ b/orchagent/portsorch.cpp @@ -1032,6 +1032,38 @@ void PortsOrch::getCpuPort(Port &port) port = m_cpuPort; } +/* + * Create host_tx_ready field in PORT_TABLE of STATE-DB + * and set the field to false by default for the + * front port. + */ +void PortsOrch::initHostTxReadyState(Port &port) +{ + SWSS_LOG_ENTER(); + + vector tuples; + bool exist = m_portStateTable.get(port.m_alias, tuples); + string hostTxReady; + + if (exist) + { + for (auto i : tuples) + { + if (fvField(i) == "host_tx_ready") + { + hostTxReady = fvValue(i); + } + } + } + + if (hostTxReady.empty()) + { + m_portStateTable.hset(port.m_alias, "host_tx_ready", "false"); + SWSS_LOG_INFO("initalize hostTxReady %s with status %s", + port.m_alias.c_str(), hostTxReady.c_str()); + } +} + bool PortsOrch::setPortAdminStatus(Port &port, bool state) { SWSS_LOG_ENTER(); @@ -1040,11 +1072,20 @@ bool PortsOrch::setPortAdminStatus(Port &port, bool state) attr.id = SAI_PORT_ATTR_ADMIN_STATE; attr.value.booldata = state; + /* Update the host_tx_ready to false before setting admin_state, when admin state is false */ + if (!state) + { + m_portStateTable.hset(port.m_alias, "host_tx_ready", "false"); + SWSS_LOG_INFO("Set admin status DOWN host_tx_ready to false to port pid:%" PRIx64, + port.m_port_id); + } + sai_status_t status = sai_port_api->set_port_attribute(port.m_port_id, &attr); if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to set admin status %s to port pid:%" PRIx64, state ? "UP" : "DOWN", port.m_port_id); + m_portStateTable.hset(port.m_alias, "host_tx_ready", "false"); task_process_status handle_status = handleSaiSetStatus(SAI_API_PORT, status); if (handle_status != task_success) { @@ -1052,10 +1093,19 @@ bool PortsOrch::setPortAdminStatus(Port &port, bool state) } } - SWSS_LOG_INFO("Set admin status %s to port pid:%" PRIx64, - state ? "UP" : "DOWN", port.m_port_id); - - setGearboxPortsAttr(port, SAI_PORT_ATTR_ADMIN_STATE, &state); + bool gbstatus = setGearboxPortsAttr(port, SAI_PORT_ATTR_ADMIN_STATE, &state); + if (gbstatus != true) + { + m_portStateTable.hset(port.m_alias, "host_tx_ready", "false"); + } + + /* Update the state table for host_tx_ready*/ + if (state && (gbstatus == true) && (status == SAI_STATUS_SUCCESS) ) + { + m_portStateTable.hset(port.m_alias, "host_tx_ready", "true"); + SWSS_LOG_INFO("Set admin status UP host_tx_ready to true to port pid:%" PRIx64, + port.m_port_id); + } return true; } @@ -1940,7 +1990,7 @@ void PortsOrch::initPortSupportedSpeeds(const std::string& alias, sai_object_id_ */ bool PortsOrch::setGearboxPortsAttr(Port &port, sai_port_attr_t id, void *value) { - bool status; + bool status = false; status = setGearboxPortAttr(port, PHY_PORT_TYPE, id, value); @@ -3362,7 +3412,10 @@ void PortsOrch::doPortTask(Consumer &consumer) } } - + + /* create host_tx_ready field in state-db */ + initHostTxReadyState(p); + /* Last step set port admin status */ if (!admin_status.empty() && (p.m_admin_state_up != (admin_status == "up"))) { diff --git a/orchagent/portsorch.h b/orchagent/portsorch.h index c820d6969d..0fd3552e19 100755 --- a/orchagent/portsorch.h +++ b/orchagent/portsorch.h @@ -95,6 +95,7 @@ class PortsOrch : public Orch, public Subject bool getPortByBridgePortId(sai_object_id_t bridge_port_id, Port &port); void setPort(string alias, Port port); void getCpuPort(Port &port); + void initHostTxReadyState(Port &port); bool getInbandPort(Port &port); bool getVlanByVlanId(sai_vlan_id_t vlan_id, Port &vlan); diff --git a/tests/test_admin_status.py b/tests/test_admin_status.py index 15724a7c02..1b99bf37c7 100644 --- a/tests/test_admin_status.py +++ b/tests/test_admin_status.py @@ -9,6 +9,7 @@ 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) + self.sdb = swsscommon.DBConnector(6, dvs.redis_sock, 0) def set_admin_status(self, port, admin_status): assert admin_status == "up" or admin_status == "down" @@ -52,6 +53,16 @@ def check_admin_status(self, dvs, port, admin_status): if fv[0] == "SAI_PORT_ATTR_ADMIN_STATE": assert fv[1] == "true" if admin_status == "up" else "false" + def check_host_tx_ready_status(self, dvs, port, admin_status): + assert admin_status == "up" or admin_status == "down" + ptbl = swsscommon.Table(self.sdb, "PORT_TABLE") + (status, fvs) = ptbl.get(port) + assert status == True + assert "host_tx_ready" in [fv[0] for fv in fvs] + for fv in fvs: + if fv[0] == "host_tx_ready": + assert fv[1] == "true" if admin_status == "up" else "false" + def test_PortChannelMemberAdminStatus(self, dvs, testlog): self.setup_db(dvs) @@ -79,6 +90,24 @@ def test_PortChannelMemberAdminStatus(self, dvs, testlog): # remove port channel self.remove_port_channel(dvs, "PortChannel6") + def test_PortHostTxReadiness(self, dvs, testlog): + self.setup_db(dvs) + + # configure admin status to interface + self.set_admin_status("Ethernet0", "up") + self.set_admin_status("Ethernet4", "down") + self.set_admin_status("Ethernet8", "up") + + # check ASIC port database + self.check_admin_status(dvs, "Ethernet0", "up") + self.check_admin_status(dvs, "Ethernet4", "down") + self.check_admin_status(dvs, "Ethernet8", "up") + + # check host readiness status in PORT TABLE of STATE-DB + self.check_host_tx_ready_status(dvs, "Ethernet0", "up") + self.check_host_tx_ready_status(dvs, "Ethernet4", "down") + self.check_host_tx_ready_status(dvs, "Ethernet8", "up") + # Add Dummy always-pass test at end as workaroud # for issue when Flaky fail on final test it invokes module tear-down before retrying