diff --git a/orchagent/port.h b/orchagent/port.h index 62b087cf71..1e612c9b87 100644 --- a/orchagent/port.h +++ b/orchagent/port.h @@ -103,6 +103,7 @@ class Port std::set m_child_ports; std::vector m_queue_ids; std::vector m_priority_group_ids; + sai_port_flow_control_mode_t m_flowctl_mode = SAI_PORT_FLOW_CONTROL_MODE_DISABLE; sai_port_priority_flow_control_mode_t m_pfc_asym = SAI_PORT_PRIORITY_FLOW_CONTROL_MODE_COMBINED; uint8_t m_pfc_bitmask = 0; uint32_t m_nat_zone_id = 0; diff --git a/orchagent/portsorch.cpp b/orchagent/portsorch.cpp index 25a64b553b..73c6c53417 100755 --- a/orchagent/portsorch.cpp +++ b/orchagent/portsorch.cpp @@ -65,6 +65,14 @@ static map fec_mode_map = { "fc", SAI_PORT_FEC_MODE_FC } }; +static map flowctl_mode_map = +{ + { "off", SAI_PORT_FLOW_CONTROL_MODE_DISABLE }, + { "tx_only", SAI_PORT_FLOW_CONTROL_MODE_TX_ONLY }, + { "rx_only", SAI_PORT_FLOW_CONTROL_MODE_RX_ONLY }, + { "on", SAI_PORT_FLOW_CONTROL_MODE_BOTH_ENABLE } +}; + static map pfc_asym_map = { { "on", SAI_PORT_PRIORITY_FLOW_CONTROL_MODE_SEPARATE }, @@ -863,6 +871,26 @@ bool PortsOrch::setPortFec(Port &port, sai_port_fec_mode_t mode) return true; } +bool PortsOrch::setPortFlowControl(sai_object_id_t id, sai_port_flow_control_mode_t mode) +{ + SWSS_LOG_ENTER(); + + sai_attribute_t attr; + attr.id = SAI_PORT_ATTR_GLOBAL_FLOW_CONTROL_MODE; + attr.value.s32 = mode; + + sai_status_t status = sai_port_api->set_port_attribute(id, &attr); + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Failed to set flow control mode %d to port pid:%" PRIx64, + mode, id); + return false; + } + SWSS_LOG_INFO("Set flow control mode %d to port pid:%" PRIx64, + mode, id); + return true; +} + bool PortsOrch::getPortPfc(sai_object_id_t portId, uint8_t *pfc_bitmask) { SWSS_LOG_ENTER(); @@ -2091,6 +2119,7 @@ void PortsOrch::doPortTask(Consumer &consumer) string admin_status; string fec_mode; string pfc_asym; + string flowctl_mode; uint32_t mtu = 0; uint32_t speed = 0; string learn_mode; @@ -2143,6 +2172,12 @@ void PortsOrch::doPortTask(Consumer &consumer) fec_mode = fvValue(i); } + /* Set port flow control */ + if (fvField(i) == "flow_control") + { + flowctl_mode = fvValue(i); + } + /* Get port fdb learn mode*/ if (fvField(i) == "learn_mode") { @@ -2455,6 +2490,33 @@ void PortsOrch::doPortTask(Consumer &consumer) } } + if (!flowctl_mode.empty()) + { + if (flowctl_mode_map.find(flowctl_mode) != flowctl_mode_map.end()) + { + /* reset flowctl mode upon mode change */ + if (p.m_flowctl_mode != flowctl_mode_map[flowctl_mode]) + { + p.m_flowctl_mode = flowctl_mode_map[flowctl_mode]; + if (setPortFlowControl(p.m_port_id, p.m_flowctl_mode)) + { + m_portList[alias] = p; + SWSS_LOG_NOTICE("Set port %s flowctl to %s", alias.c_str(), flowctl_mode.c_str()); + } + else + { + SWSS_LOG_ERROR("Failed to set port %s flowctl to %s", alias.c_str(), flowctl_mode.c_str()); + it++; + continue; + } + } + } + else + { + SWSS_LOG_ERROR("Unknown flowctl mode %s", flowctl_mode.c_str()); + } + } + if (!learn_mode.empty() && (p.m_learn_mode != learn_mode)) { if (p.m_bridge_port_id != SAI_NULL_OBJECT_ID) diff --git a/orchagent/portsorch.h b/orchagent/portsorch.h index 35e3af2627..83d125a6ab 100755 --- a/orchagent/portsorch.h +++ b/orchagent/portsorch.h @@ -248,6 +248,7 @@ class PortsOrch : public Orch, public Subject bool setPortPvid (Port &port, sai_uint32_t pvid); bool getPortPvid(Port &port, sai_uint32_t &pvid); bool setPortFec(Port &port, sai_port_fec_mode_t mode); + bool setPortFlowControl(sai_object_id_t id, sai_port_flow_control_mode_t mode); bool setPortPfcAsym(Port &port, string pfc_asym); bool getDestPortId(sai_object_id_t src_port_id, dest_port_type_t port_type, sai_object_id_t &des_port_id);