From 3ae826319954a4eab1b3cb94d7c0a85b75a16c42 Mon Sep 17 00:00:00 2001 From: marif-nexthop Date: Fri, 30 Oct 2026 18:54:24 +0000 Subject: [PATCH 1/2] create ports the way the Qumran4D SAI requires --- fboss/agent/hw/sai/api/PortApi.h | 41 +++++++++++++------ .../hw/sai/switch/npu/SaiPortManager.cpp | 31 ++++++++++---- fboss/agent/hw/switch_asics/ChenabAsic.cpp | 1 + fboss/agent/hw/switch_asics/EbroAsic.cpp | 1 + fboss/agent/hw/switch_asics/G202xAsic.cpp | 1 + fboss/agent/hw/switch_asics/HwAsic.h | 3 ++ fboss/agent/hw/switch_asics/Jericho2Asic.cpp | 1 + fboss/agent/hw/switch_asics/Jericho3Asic.cpp | 1 + fboss/agent/hw/switch_asics/Jericho4Asic.cpp | 1 + fboss/agent/hw/switch_asics/P200Asic.cpp | 1 + fboss/agent/hw/switch_asics/Qumran4DAsic.cpp | 1 + fboss/agent/hw/switch_asics/Tomahawk3Asic.cpp | 1 + fboss/agent/hw/switch_asics/Tomahawk4Asic.cpp | 1 + fboss/agent/hw/switch_asics/Tomahawk5Asic.cpp | 1 + fboss/agent/hw/switch_asics/Tomahawk6Asic.cpp | 1 + fboss/agent/hw/switch_asics/TomahawkAsic.cpp | 1 + .../hw/switch_asics/TomahawkUltra1Asic.cpp | 1 + fboss/agent/hw/switch_asics/YubaAsic.cpp | 1 + 18 files changed, 69 insertions(+), 21 deletions(-) diff --git a/fboss/agent/hw/sai/api/PortApi.h b/fboss/agent/hw/sai/api/PortApi.h index e16f315dcb016..02161594facd0 100644 --- a/fboss/agent/hw/sai/api/PortApi.h +++ b/fboss/agent/hw/sai/api/PortApi.h @@ -15,11 +15,12 @@ #include "fboss/agent/hw/sai/api/SaiVersion.h" #include "fboss/agent/hw/sai/api/Types.h" -#include - +#include +#include #include #include #include +#include extern "C" { #include @@ -790,15 +791,14 @@ struct SaiPortTraits { * - Enhancing AdapterHostKey as well as CreateAttribute means that the * AdatperHostKey remains computable from AdaterKey, CreateAttributes: a * requirement for our design. - * - However, this also means that attempt to create port will pass Type (a - * Read Only attribute today) and that call will fail. - * - This is not a problem at the moment since passing Type is a - * requirement only on DNX and ports are always pre-created on this - * platform and loaded by SaiStore during init and never created. - * - In future, if we support breakout ports on DNX, we would need to call - * create port which would fail: but as mentioned above, we plan to - * enhance the SAI spec and work with SAI vendors to support passing port - * type during creation. + * - It also means create_port would receive Type, a read-only attribute, + * and some adapters reject it only after creating the port, leaving a + * half-created port behind. Ports created at runtime (breakout) hit + * this, so PortApi::_create leaves a LOGICAL Type out of the attribute + * list it passes to create_port; the other types (fabric, recycle, + * eventor, management, hyper) are still passed, and Type still keys the + * SaiStore. + * - Long term the fix is a SAI spec change allowing Type on create. */ using AdapterHostKey = std::tuple< @@ -1910,7 +1910,24 @@ class PortApi : public SaiApi { sai_object_id_t switch_id, size_t count, sai_attribute_t* attr_list) const { - return api_->create_port(rawSaiId(id), switch_id, count, attr_list); + // SAI_PORT_ATTR_TYPE is read-only in the SAI spec. It is part of the DNX + // CreateAttributes so that SaiStore can key port types apart; the logical + // (front-panel) type is not sent to the adapter. An adapter that rejects it + // only after creating the port (the Broadcom DNX SAI) would otherwise leave + // a half-created port behind that no retry can replace. Other types + // (fabric, recycle, eventor, management, hyper port) are still passed. + std::vector attrs; + attrs.reserve(count); + std::copy_if( + attr_list, + attr_list + count, + std::back_inserter(attrs), + [](const sai_attribute_t& attr) { + return attr.id != SAI_PORT_ATTR_TYPE || + attr.value.s32 != SAI_PORT_TYPE_LOGICAL; + }); + return api_->create_port( + rawSaiId(id), switch_id, attrs.size(), attrs.data()); } sai_status_t _remove(PortSaiId key) const { return api_->remove_port(key); diff --git a/fboss/agent/hw/sai/switch/npu/SaiPortManager.cpp b/fboss/agent/hw/sai/switch/npu/SaiPortManager.cpp index 6d5d1e544ef23..49a87f56aaabd 100644 --- a/fboss/agent/hw/sai/switch/npu/SaiPortManager.cpp +++ b/fboss/agent/hw/sai/switch/npu/SaiPortManager.cpp @@ -1634,17 +1634,30 @@ void SaiPortManager::programSerdes( * Serdes objects are no longer created beforehand. Therefore, agent only * needs to create a new serdes object without knowing the serdes Id or * reloading the object to sai store. + * + * On the Broadcom DNX SAI that holds only where the ASIC does not claim + * PORT_SERDES_CREATED_WITH_PORT: the Qumran4D SAI attaches a default + * serdes object to every port it creates and answers a second + * create_port_serdes with SAI_STATUS_ITEM_ALREADY_EXISTS, so a port + * created at runtime (breakout) must adopt it, as on the other SAIs. */ -#if !defined(BRCM_SAI_SDK_XGS_AND_DNX) - // serdes is not yet programmed or reloaded from adapter - std::optional serdesAttr{}; - auto serdesId = SaiApiTable::getInstance()->portApi().getAttribute( - saiPort->adapterKey(), serdesAttr); - if (serdesId.has_value() && serdesId.value() != SAI_NULL_OBJECT_ID) { - // but default serdes exists in the adapter. - serdes = - store.reloadObject(static_cast(serdesId.value())); +#if !defined(BRCM_SAI_SDK_XGS_AND_DNX) || defined(BRCM_SAI_SDK_DNX) +#if defined(BRCM_SAI_SDK_DNX) + if (platform_->getAsic()->isSupported( + HwAsic::Feature::PORT_SERDES_CREATED_WITH_PORT)) { +#endif + // serdes is not yet programmed or reloaded from adapter + std::optional serdesAttr{}; + auto serdesId = SaiApiTable::getInstance()->portApi().getAttribute( + saiPort->adapterKey(), serdesAttr); + if (serdesId.has_value() && serdesId.value() != SAI_NULL_OBJECT_ID) { + // but default serdes exists in the adapter. + serdes = + store.reloadObject(static_cast(serdesId.value())); + } +#if defined(BRCM_SAI_SDK_DNX) } +#endif #endif } else { // ensure warm boot handles are reclaimed removed diff --git a/fboss/agent/hw/switch_asics/ChenabAsic.cpp b/fboss/agent/hw/switch_asics/ChenabAsic.cpp index 827cc31ae30f4..644a3b01b3b2b 100644 --- a/fboss/agent/hw/switch_asics/ChenabAsic.cpp +++ b/fboss/agent/hw/switch_asics/ChenabAsic.cpp @@ -272,6 +272,7 @@ bool ChenabAsic::isSupportedNonFabric(Feature feature) const { case HwAsic::Feature::PBR_ACL_BYTE_COUNTER: case HwAsic::Feature::LAG_TTL_DECREMENT_DISABLE: case HwAsic::Feature::PORT_LATCH_STATUS: + case HwAsic::Feature::PORT_SERDES_CREATED_WITH_PORT: return false; } return false; diff --git a/fboss/agent/hw/switch_asics/EbroAsic.cpp b/fboss/agent/hw/switch_asics/EbroAsic.cpp index ad7befea1f181..c23490daf2b93 100644 --- a/fboss/agent/hw/switch_asics/EbroAsic.cpp +++ b/fboss/agent/hw/switch_asics/EbroAsic.cpp @@ -283,6 +283,7 @@ bool EbroAsic::isSupportedNonFabric(Feature feature) const { case HwAsic::Feature::MY_MAC: case HwAsic::Feature::ISOLATION_GROUP: case HwAsic::Feature::CSIG: + case HwAsic::Feature::PORT_SERDES_CREATED_WITH_PORT: case HwAsic::Feature::SAI_ACL_MPLS_LABEL0_TTL: case HwAsic::Feature::SAI_MPLS_NEXTHOP_OUTSEG_TYPE: case HwAsic::Feature::ACL_ENTRY_OUT_PORT_QUALIFIER: diff --git a/fboss/agent/hw/switch_asics/G202xAsic.cpp b/fboss/agent/hw/switch_asics/G202xAsic.cpp index 5b73cb19ebaa4..6452f9c7db3e3 100644 --- a/fboss/agent/hw/switch_asics/G202xAsic.cpp +++ b/fboss/agent/hw/switch_asics/G202xAsic.cpp @@ -262,6 +262,7 @@ bool G202xAsic::isSupportedNonFabric(Feature feature) const { case HwAsic::Feature::MY_MAC: case HwAsic::Feature::ISOLATION_GROUP: case HwAsic::Feature::CSIG: + case HwAsic::Feature::PORT_SERDES_CREATED_WITH_PORT: case HwAsic::Feature::SWITCH_WIDE_LINK_UP_DEBOUNCE: case HwAsic::Feature::ACL_ENTRY_OUT_PORT_QUALIFIER: case HwAsic::Feature::XPHY_SERDES_TX_FIR_POST3: diff --git a/fboss/agent/hw/switch_asics/HwAsic.h b/fboss/agent/hw/switch_asics/HwAsic.h index 354f9475495e4..2737d74ff63a0 100644 --- a/fboss/agent/hw/switch_asics/HwAsic.h +++ b/fboss/agent/hw/switch_asics/HwAsic.h @@ -649,6 +649,9 @@ class HwAsic { CSIG, // TTL control on the aggregate's shared forwarding service. LAG_TTL_DECREMENT_DISABLE, + // The adapter attaches a default serdes object to every port it creates + // and rejects a second create_port_serdes; the agent adopts that object + PORT_SERDES_CREATED_WITH_PORT, }; enum class AsicMode { diff --git a/fboss/agent/hw/switch_asics/Jericho2Asic.cpp b/fboss/agent/hw/switch_asics/Jericho2Asic.cpp index 196a49f0b902e..05f07589f53ea 100644 --- a/fboss/agent/hw/switch_asics/Jericho2Asic.cpp +++ b/fboss/agent/hw/switch_asics/Jericho2Asic.cpp @@ -271,6 +271,7 @@ bool Jericho2Asic::isSupported(Feature feature) const { case HwAsic::Feature::XPHY_SERDES_TX_FIR_POST3: case HwAsic::Feature::LAG_TTL_DECREMENT_DISABLE: case HwAsic::Feature::PORT_LATCH_STATUS: + case HwAsic::Feature::PORT_SERDES_CREATED_WITH_PORT: return false; } return false; diff --git a/fboss/agent/hw/switch_asics/Jericho3Asic.cpp b/fboss/agent/hw/switch_asics/Jericho3Asic.cpp index 2ec940940f721..fe12c8bae8e84 100644 --- a/fboss/agent/hw/switch_asics/Jericho3Asic.cpp +++ b/fboss/agent/hw/switch_asics/Jericho3Asic.cpp @@ -307,6 +307,7 @@ bool Jericho3Asic::isSupported(Feature feature) const { case HwAsic::Feature::XPHY_SERDES_TX_FIR_POST3: case HwAsic::Feature::LAG_TTL_DECREMENT_DISABLE: case HwAsic::Feature::PORT_LATCH_STATUS: + case HwAsic::Feature::PORT_SERDES_CREATED_WITH_PORT: return false; } return false; diff --git a/fboss/agent/hw/switch_asics/Jericho4Asic.cpp b/fboss/agent/hw/switch_asics/Jericho4Asic.cpp index e2644b2ea7a3f..723408b9556a8 100644 --- a/fboss/agent/hw/switch_asics/Jericho4Asic.cpp +++ b/fboss/agent/hw/switch_asics/Jericho4Asic.cpp @@ -307,6 +307,7 @@ bool Jericho4Asic::isSupported(Feature feature) const { case HwAsic::Feature::XPHY_SERDES_TX_FIR_POST3: case HwAsic::Feature::LAG_TTL_DECREMENT_DISABLE: case HwAsic::Feature::PORT_LATCH_STATUS: + case HwAsic::Feature::PORT_SERDES_CREATED_WITH_PORT: return false; } return false; diff --git a/fboss/agent/hw/switch_asics/P200Asic.cpp b/fboss/agent/hw/switch_asics/P200Asic.cpp index 8ff2987cde1d4..087c38bf676e0 100644 --- a/fboss/agent/hw/switch_asics/P200Asic.cpp +++ b/fboss/agent/hw/switch_asics/P200Asic.cpp @@ -284,6 +284,7 @@ bool P200Asic::isSupportedNonFabric(Feature feature) const { case HwAsic::Feature::XPHY_SERDES_TX_FIR_POST3: case HwAsic::Feature::LAG_TTL_DECREMENT_DISABLE: case HwAsic::Feature::PORT_LATCH_STATUS: + case HwAsic::Feature::PORT_SERDES_CREATED_WITH_PORT: return false; case HwAsic::Feature::SAI_ACL_MPLS_LABEL0_TTL: // Leaba does not implement the MPLS label0 TTL ACL qualifier yet. diff --git a/fboss/agent/hw/switch_asics/Qumran4DAsic.cpp b/fboss/agent/hw/switch_asics/Qumran4DAsic.cpp index 95e11be53a854..449311ded2b5b 100644 --- a/fboss/agent/hw/switch_asics/Qumran4DAsic.cpp +++ b/fboss/agent/hw/switch_asics/Qumran4DAsic.cpp @@ -80,6 +80,7 @@ bool Qumran4DAsic::isSupported(Feature feature) const { case HwAsic::Feature::ACL_METADATA_QUALIFER: case HwAsic::Feature::EVENTOR_PORT_FOR_SFLOW: case HwAsic::Feature::SFLOWv6: + case HwAsic::Feature::PORT_SERDES_CREATED_WITH_PORT: case HwAsic::Feature::ZERO_SDK_WRITE_WARMBOOT: case HwAsic::Feature::SWITCH_REACHABILITY_CHANGE_NOTIFY: case HwAsic::Feature::ACL_ENTRY_ETHER_TYPE: diff --git a/fboss/agent/hw/switch_asics/Tomahawk3Asic.cpp b/fboss/agent/hw/switch_asics/Tomahawk3Asic.cpp index 84bffba1f590c..1114e8a251b23 100644 --- a/fboss/agent/hw/switch_asics/Tomahawk3Asic.cpp +++ b/fboss/agent/hw/switch_asics/Tomahawk3Asic.cpp @@ -111,6 +111,7 @@ bool Tomahawk3Asic::isSupported(Feature feature) const { return true; case HwAsic::Feature::ISOLATION_GROUP: case HwAsic::Feature::CSIG: + case HwAsic::Feature::PORT_SERDES_CREATED_WITH_PORT: case HwAsic::Feature::QCM: case HwAsic::Feature::SMAC_EQUALS_DMAC_CHECK_ENABLED: case HwAsic::Feature::PORT_TTL_DECREMENT_DISABLE: diff --git a/fboss/agent/hw/switch_asics/Tomahawk4Asic.cpp b/fboss/agent/hw/switch_asics/Tomahawk4Asic.cpp index 32b9999460f75..5e7152d4bd3bc 100644 --- a/fboss/agent/hw/switch_asics/Tomahawk4Asic.cpp +++ b/fboss/agent/hw/switch_asics/Tomahawk4Asic.cpp @@ -280,6 +280,7 @@ bool Tomahawk4Asic::isSupported(Feature feature) const { case HwAsic::Feature::CSIG: case HwAsic::Feature::LAG_TTL_DECREMENT_DISABLE: case HwAsic::Feature::PORT_LATCH_STATUS: + case HwAsic::Feature::PORT_SERDES_CREATED_WITH_PORT: return false; } return false; diff --git a/fboss/agent/hw/switch_asics/Tomahawk5Asic.cpp b/fboss/agent/hw/switch_asics/Tomahawk5Asic.cpp index 1ca339685914c..d1a6b66f2a754 100644 --- a/fboss/agent/hw/switch_asics/Tomahawk5Asic.cpp +++ b/fboss/agent/hw/switch_asics/Tomahawk5Asic.cpp @@ -263,6 +263,7 @@ bool Tomahawk5Asic::isSupported(Feature feature) const { case HwAsic::Feature::CSIG: case HwAsic::Feature::LAG_TTL_DECREMENT_DISABLE: case HwAsic::Feature::PORT_LATCH_STATUS: + case HwAsic::Feature::PORT_SERDES_CREATED_WITH_PORT: return false; } return false; diff --git a/fboss/agent/hw/switch_asics/Tomahawk6Asic.cpp b/fboss/agent/hw/switch_asics/Tomahawk6Asic.cpp index e0224edc72500..57ffc5990129a 100644 --- a/fboss/agent/hw/switch_asics/Tomahawk6Asic.cpp +++ b/fboss/agent/hw/switch_asics/Tomahawk6Asic.cpp @@ -270,6 +270,7 @@ bool Tomahawk6Asic::isSupported(Feature feature) const { case HwAsic::Feature::XPHY_SERDES_TX_FIR_POST3: case HwAsic::Feature::LAG_TTL_DECREMENT_DISABLE: case HwAsic::Feature::PORT_LATCH_STATUS: + case HwAsic::Feature::PORT_SERDES_CREATED_WITH_PORT: return false; } return false; diff --git a/fboss/agent/hw/switch_asics/TomahawkAsic.cpp b/fboss/agent/hw/switch_asics/TomahawkAsic.cpp index b2c4e9bcc2f5d..403f4b23e4297 100644 --- a/fboss/agent/hw/switch_asics/TomahawkAsic.cpp +++ b/fboss/agent/hw/switch_asics/TomahawkAsic.cpp @@ -261,6 +261,7 @@ bool TomahawkAsic::isSupported(Feature feature) const { case HwAsic::Feature::CSIG: case HwAsic::Feature::LAG_TTL_DECREMENT_DISABLE: case HwAsic::Feature::PORT_LATCH_STATUS: + case HwAsic::Feature::PORT_SERDES_CREATED_WITH_PORT: return false; } return false; diff --git a/fboss/agent/hw/switch_asics/TomahawkUltra1Asic.cpp b/fboss/agent/hw/switch_asics/TomahawkUltra1Asic.cpp index bfbc1af05b14e..36e42b749acff 100644 --- a/fboss/agent/hw/switch_asics/TomahawkUltra1Asic.cpp +++ b/fboss/agent/hw/switch_asics/TomahawkUltra1Asic.cpp @@ -266,6 +266,7 @@ bool TomahawkUltra1Asic::isSupported(Feature feature) const { case HwAsic::Feature::XPHY_SERDES_TX_FIR_POST3: case HwAsic::Feature::LAG_TTL_DECREMENT_DISABLE: case HwAsic::Feature::PORT_LATCH_STATUS: + case HwAsic::Feature::PORT_SERDES_CREATED_WITH_PORT: return false; } return false; diff --git a/fboss/agent/hw/switch_asics/YubaAsic.cpp b/fboss/agent/hw/switch_asics/YubaAsic.cpp index 788a6dbad8997..39efbdd03fe18 100644 --- a/fboss/agent/hw/switch_asics/YubaAsic.cpp +++ b/fboss/agent/hw/switch_asics/YubaAsic.cpp @@ -276,6 +276,7 @@ bool YubaAsic::isSupportedNonFabric(Feature feature) const { case HwAsic::Feature::RX_PACKET_TYPE: case HwAsic::Feature::MY_MAC: case HwAsic::Feature::ISOLATION_GROUP: + case HwAsic::Feature::PORT_SERDES_CREATED_WITH_PORT: case HwAsic::Feature::SWITCH_WIDE_LINK_UP_DEBOUNCE: case HwAsic::Feature::ACL_ENTRY_OUT_PORT_QUALIFIER: case HwAsic::Feature::XPHY_SERDES_TX_FIR_POST3: From 46bc4e8e7873ccf426ca04cc02dec5954bf55857 Mon Sep 17 00:00:00 2001 From: marif-nexthop Date: Fri, 30 Oct 2026 18:54:41 +0000 Subject: [PATCH 2/2] build VOQ system ports from the TM slot the Qumran4D SAI assigned --- fboss/agent/hw/sai/api/PortApi.h | 12 ++++ fboss/agent/hw/sai/api/bcm/PortApi.cpp | 16 +++++ fboss/agent/hw/sai/api/chenab/PortApi.cpp | 8 +++ .../hw/sai/api/fake/FakeSaiExtensions.cpp | 8 +++ fboss/agent/hw/sai/api/tajo/PortApi.cpp | 8 +++ .../hw/sai/switch/SaiSystemPortManager.cpp | 65 +++++++++++++++++-- .../hw/sai/switch/SaiSystemPortManager.h | 2 + fboss/agent/hw/switch_asics/ChenabAsic.cpp | 1 + fboss/agent/hw/switch_asics/EbroAsic.cpp | 1 + fboss/agent/hw/switch_asics/G202xAsic.cpp | 1 + fboss/agent/hw/switch_asics/HwAsic.h | 4 ++ fboss/agent/hw/switch_asics/Jericho2Asic.cpp | 1 + fboss/agent/hw/switch_asics/Jericho3Asic.cpp | 1 + fboss/agent/hw/switch_asics/Jericho4Asic.cpp | 1 + fboss/agent/hw/switch_asics/P200Asic.cpp | 1 + fboss/agent/hw/switch_asics/Qumran4DAsic.cpp | 1 + fboss/agent/hw/switch_asics/Tomahawk3Asic.cpp | 1 + fboss/agent/hw/switch_asics/Tomahawk4Asic.cpp | 1 + fboss/agent/hw/switch_asics/Tomahawk5Asic.cpp | 1 + fboss/agent/hw/switch_asics/Tomahawk6Asic.cpp | 1 + fboss/agent/hw/switch_asics/TomahawkAsic.cpp | 1 + .../hw/switch_asics/TomahawkUltra1Asic.cpp | 1 + fboss/agent/hw/switch_asics/YubaAsic.cpp | 1 + 23 files changed, 134 insertions(+), 4 deletions(-) diff --git a/fboss/agent/hw/sai/api/PortApi.h b/fboss/agent/hw/sai/api/PortApi.h index 02161594facd0..376fbdd2d22bc 100644 --- a/fboss/agent/hw/sai/api/PortApi.h +++ b/fboss/agent/hw/sai/api/PortApi.h @@ -288,6 +288,16 @@ struct SaiPortTraits { }; using SystemPortId = SaiExtensionAttribute; + struct AttributeAttachedCoreIndex { + std::optional operator()(); + }; + using AttachedCoreIndex = + SaiExtensionAttribute; + struct AttributeAttachedCorePortIndex { + std::optional operator()(); + }; + using AttachedCorePortIndex = + SaiExtensionAttribute; using PtpMode = SaiAttribute< EnumType, SAI_PORT_ATTR_PTP_MODE, @@ -1094,6 +1104,8 @@ SAI_ATTRIBUTE_NAME(Port, IsolationGroup) SAI_ATTRIBUTE_NAME(Port, IngressMacSecAcl) SAI_ATTRIBUTE_NAME(Port, EgressMacSecAcl) SAI_ATTRIBUTE_NAME(Port, SystemPortId) +SAI_ATTRIBUTE_NAME(Port, AttachedCoreIndex) +SAI_ATTRIBUTE_NAME(Port, AttachedCorePortIndex) SAI_ATTRIBUTE_NAME(Port, PtpMode) SAI_ATTRIBUTE_NAME(Port, PortEyeValues) SAI_ATTRIBUTE_NAME(Port, PriorityFlowControlMode) diff --git a/fboss/agent/hw/sai/api/bcm/PortApi.cpp b/fboss/agent/hw/sai/api/bcm/PortApi.cpp index dec0703720814..e38ac756ab3c8 100644 --- a/fboss/agent/hw/sai/api/bcm/PortApi.cpp +++ b/fboss/agent/hw/sai/api/bcm/PortApi.cpp @@ -268,6 +268,22 @@ std::optional SaiPortTraits::Attributes::AttributeSystemPortId::operator()() { return std::nullopt; } +std::optional +SaiPortTraits::Attributes::AttributeAttachedCoreIndex::operator()() { +#if defined(BRCM_SAI_SDK_DNX) + return SAI_PORT_ATTR_ATTACHED_CORE_INDEX; +#else + return std::nullopt; +#endif +} +std::optional +SaiPortTraits::Attributes::AttributeAttachedCorePortIndex::operator()() { +#if defined(BRCM_SAI_SDK_DNX) + return SAI_PORT_ATTR_ATTACHED_CORE_PORT_INDEX; +#else + return std::nullopt; +#endif +} std::optional SaiPortSerdesTraits::Attributes:: AttributeRxAfeAdaptiveEnableWrapper::operator()() { return std::nullopt; diff --git a/fboss/agent/hw/sai/api/chenab/PortApi.cpp b/fboss/agent/hw/sai/api/chenab/PortApi.cpp index a06b3933ef620..223d1da067cc1 100644 --- a/fboss/agent/hw/sai/api/chenab/PortApi.cpp +++ b/fboss/agent/hw/sai/api/chenab/PortApi.cpp @@ -29,6 +29,14 @@ std::optional SaiPortTraits::Attributes::AttributeSystemPortId::operator()() { return std::nullopt; } +std::optional +SaiPortTraits::Attributes::AttributeAttachedCoreIndex::operator()() { + return std::nullopt; +} +std::optional +SaiPortTraits::Attributes::AttributeAttachedCorePortIndex::operator()() { + return std::nullopt; +} std::optional SaiPortSerdesTraits::Attributes:: AttributeRxAfeAdaptiveEnableWrapper::operator()() { return std::nullopt; diff --git a/fboss/agent/hw/sai/api/fake/FakeSaiExtensions.cpp b/fboss/agent/hw/sai/api/fake/FakeSaiExtensions.cpp index aa014dd6ec5e3..dbe55db57a0be 100644 --- a/fboss/agent/hw/sai/api/fake/FakeSaiExtensions.cpp +++ b/fboss/agent/hw/sai/api/fake/FakeSaiExtensions.cpp @@ -130,6 +130,14 @@ SaiPortTraits::Attributes::AttributeSystemPortId::operator()() { return SAI_PORT_ATTR_EXT_FAKE_SYSTEM_PORT_ID; } std::optional +SaiPortTraits::Attributes::AttributeAttachedCoreIndex::operator()() { + return std::nullopt; +} +std::optional +SaiPortTraits::Attributes::AttributeAttachedCorePortIndex::operator()() { + return std::nullopt; +} +std::optional SaiPortTraits::Attributes::AttributeArsLinkState::operator()() { return std::nullopt; } diff --git a/fboss/agent/hw/sai/api/tajo/PortApi.cpp b/fboss/agent/hw/sai/api/tajo/PortApi.cpp index 8b568bc985ce1..f843fc015f792 100644 --- a/fboss/agent/hw/sai/api/tajo/PortApi.cpp +++ b/fboss/agent/hw/sai/api/tajo/PortApi.cpp @@ -44,6 +44,14 @@ std::optional SaiPortTraits::Attributes::AttributeSystemPortId::operator()() { return SAI_PORT_ATTR_EXT_SYSTEM_PORT_ID; } +std::optional +SaiPortTraits::Attributes::AttributeAttachedCoreIndex::operator()() { + return std::nullopt; +} +std::optional +SaiPortTraits::Attributes::AttributeAttachedCorePortIndex::operator()() { + return std::nullopt; +} std::optional SaiPortSerdesTraits::Attributes:: AttributeRxAfeAdaptiveEnableWrapper::operator()() { return SAI_PORT_SERDES_ATTR_EXT_RX_AFE_ADAPTIVE_ENABLE; diff --git a/fboss/agent/hw/sai/switch/SaiSystemPortManager.cpp b/fboss/agent/hw/sai/switch/SaiSystemPortManager.cpp index ab505208ea041..cfbf245f83f28 100644 --- a/fboss/agent/hw/sai/switch/SaiSystemPortManager.cpp +++ b/fboss/agent/hw/sai/switch/SaiSystemPortManager.cpp @@ -18,6 +18,7 @@ #include "fboss/agent/VoqUtils.h" #include "fboss/agent/hw/HwSysPortFb303Stats.h" #include "fboss/agent/hw/gen-cpp2/hardware_stats_constants.h" +#include "fboss/agent/hw/sai/api/SaiApiTable.h" #include "fboss/agent/hw/sai/store/SaiStore.h" #include "fboss/agent/hw/sai/switch/ConcurrentIndices.h" #include "fboss/agent/hw/sai/switch/SaiManagerTable.h" @@ -78,16 +79,72 @@ SaiSystemPortManager::SaiSystemPortManager( SaiSystemPortManager::~SaiSystemPortManager() {} +std::optional> +SaiSystemPortManager::coreAndPortIndexFromPort( + const std::shared_ptr& swSystemPort) const { + const auto* asic = platform_->getAsic(); + if (!asic->isSupported(HwAsic::Feature::SYSTEM_PORT_CORE_INDEX_FROM_PORT) || + swSystemPort->getPortType() != cfg::PortType::INTERFACE_PORT || + swSystemPort->getRemoteSystemPortType().has_value() || + !asic->getSwitchId().has_value() || + static_cast(swSystemPort->getSwitchId()) != + *asic->getSwitchId()) { + return std::nullopt; + } + // Inverse of getSystemPortID(): a local interface port's system port id is + // the port id plus the switch's local or global system port offset, minus + // the start of the switch's port id range. + auto offset = swSystemPort->getScope() == cfg::Scope::GLOBAL + ? asic->getGlobalSystemPortOffset() + : asic->getLocalSystemPortOffset(); + const auto& switchIdToSwitchInfo = *platform_->getConfig() + ->thrift.sw() + ->switchSettings() + ->switchIdToSwitchInfo(); + auto switchInfo = switchIdToSwitchInfo.find(*asic->getSwitchId()); + if (!offset.has_value() || switchInfo == switchIdToSwitchInfo.end()) { + return std::nullopt; + } + PortID portId( + static_cast( + static_cast(swSystemPort->getID()) - *offset + + *switchInfo->second.portIdRange()->minimum())); + const auto* portHandle = managerTable_->portManager().getPortHandle(portId); + if (!portHandle) { + XLOG(DBG2) << "System port " << swSystemPort->getID() << ": port " << portId + << " not created yet, using the platform mapping"; + return std::nullopt; + } + auto& portApi = SaiApiTable::getInstance()->portApi(); + auto saiPortId = portHandle->port->adapterKey(); + auto coreIndex = portApi.getAttribute( + saiPortId, SaiPortTraits::Attributes::AttachedCoreIndex{}); + auto corePortIndex = portApi.getAttribute( + saiPortId, SaiPortTraits::Attributes::AttachedCorePortIndex{}); + if (coreIndex != swSystemPort->getCoreIndex() || + corePortIndex != swSystemPort->getCorePortIndex()) { + XLOG(DBG2) << "System port " << swSystemPort->getID() << ": port " << portId + << " is on core " << coreIndex << " port index " << corePortIndex + << ", platform mapping says core " + << swSystemPort->getCoreIndex() << " port index " + << swSystemPort->getCorePortIndex(); + } + return std::make_pair(coreIndex, corePortIndex); +} + SaiSystemPortTraits::CreateAttributes SaiSystemPortManager::attributesFromSwSystemPort( const std::shared_ptr& swSystemPort) const { + auto coreIndex = static_cast(swSystemPort->getCoreIndex()); + auto corePortIndex = static_cast(swSystemPort->getCorePortIndex()); + if (auto fromPort = coreAndPortIndexFromPort(swSystemPort)) { + std::tie(coreIndex, corePortIndex) = *fromPort; + } sai_system_port_config_t config{ .port_id = static_cast(swSystemPort->getID()), .attached_switch_id = static_cast(swSystemPort->getSwitchId()), - .attached_core_index = - static_cast(swSystemPort->getCoreIndex()), - .attached_core_port_index = - static_cast(swSystemPort->getCorePortIndex()), + .attached_core_index = coreIndex, + .attached_core_port_index = corePortIndex, .speed = static_cast(swSystemPort->getSpeedMbps()), .num_voq = static_cast(swSystemPort->getNumVoqs()), }; diff --git a/fboss/agent/hw/sai/switch/SaiSystemPortManager.h b/fboss/agent/hw/sai/switch/SaiSystemPortManager.h index 6d894f3565cc4..80769b5c721fb 100644 --- a/fboss/agent/hw/sai/switch/SaiSystemPortManager.h +++ b/fboss/agent/hw/sai/switch/SaiSystemPortManager.h @@ -123,6 +123,8 @@ class SaiSystemPortManager { void loadQueues( SaiSystemPortHandle& sysPortHandle, const std::shared_ptr& swSystemPort); + std::optional> coreAndPortIndexFromPort( + const std::shared_ptr& swSystemPort) const; SaiSystemPortTraits::CreateAttributes attributesFromSwSystemPort( const std::shared_ptr& swSystemPort) const; SaiQueueHandle* FOLLY_NULLABLE diff --git a/fboss/agent/hw/switch_asics/ChenabAsic.cpp b/fboss/agent/hw/switch_asics/ChenabAsic.cpp index 644a3b01b3b2b..0dc7c373139f8 100644 --- a/fboss/agent/hw/switch_asics/ChenabAsic.cpp +++ b/fboss/agent/hw/switch_asics/ChenabAsic.cpp @@ -273,6 +273,7 @@ bool ChenabAsic::isSupportedNonFabric(Feature feature) const { case HwAsic::Feature::LAG_TTL_DECREMENT_DISABLE: case HwAsic::Feature::PORT_LATCH_STATUS: case HwAsic::Feature::PORT_SERDES_CREATED_WITH_PORT: + case HwAsic::Feature::SYSTEM_PORT_CORE_INDEX_FROM_PORT: return false; } return false; diff --git a/fboss/agent/hw/switch_asics/EbroAsic.cpp b/fboss/agent/hw/switch_asics/EbroAsic.cpp index c23490daf2b93..c1e72c2d07f09 100644 --- a/fboss/agent/hw/switch_asics/EbroAsic.cpp +++ b/fboss/agent/hw/switch_asics/EbroAsic.cpp @@ -284,6 +284,7 @@ bool EbroAsic::isSupportedNonFabric(Feature feature) const { case HwAsic::Feature::ISOLATION_GROUP: case HwAsic::Feature::CSIG: case HwAsic::Feature::PORT_SERDES_CREATED_WITH_PORT: + case HwAsic::Feature::SYSTEM_PORT_CORE_INDEX_FROM_PORT: case HwAsic::Feature::SAI_ACL_MPLS_LABEL0_TTL: case HwAsic::Feature::SAI_MPLS_NEXTHOP_OUTSEG_TYPE: case HwAsic::Feature::ACL_ENTRY_OUT_PORT_QUALIFIER: diff --git a/fboss/agent/hw/switch_asics/G202xAsic.cpp b/fboss/agent/hw/switch_asics/G202xAsic.cpp index 6452f9c7db3e3..455117a793a1e 100644 --- a/fboss/agent/hw/switch_asics/G202xAsic.cpp +++ b/fboss/agent/hw/switch_asics/G202xAsic.cpp @@ -263,6 +263,7 @@ bool G202xAsic::isSupportedNonFabric(Feature feature) const { case HwAsic::Feature::ISOLATION_GROUP: case HwAsic::Feature::CSIG: case HwAsic::Feature::PORT_SERDES_CREATED_WITH_PORT: + case HwAsic::Feature::SYSTEM_PORT_CORE_INDEX_FROM_PORT: case HwAsic::Feature::SWITCH_WIDE_LINK_UP_DEBOUNCE: case HwAsic::Feature::ACL_ENTRY_OUT_PORT_QUALIFIER: case HwAsic::Feature::XPHY_SERDES_TX_FIR_POST3: diff --git a/fboss/agent/hw/switch_asics/HwAsic.h b/fboss/agent/hw/switch_asics/HwAsic.h index 2737d74ff63a0..d21f0fcde9e2f 100644 --- a/fboss/agent/hw/switch_asics/HwAsic.h +++ b/fboss/agent/hw/switch_asics/HwAsic.h @@ -652,6 +652,10 @@ class HwAsic { // The adapter attaches a default serdes object to every port it creates // and rejects a second create_port_serdes; the agent adopts that object PORT_SERDES_CREATED_WITH_PORT, + // The adapter picks a runtime-created port's TM slot itself, so a system + // port names the core and core port index read back from the port, not + // the platform mapping's prediction + SYSTEM_PORT_CORE_INDEX_FROM_PORT, }; enum class AsicMode { diff --git a/fboss/agent/hw/switch_asics/Jericho2Asic.cpp b/fboss/agent/hw/switch_asics/Jericho2Asic.cpp index 05f07589f53ea..f108abb5523eb 100644 --- a/fboss/agent/hw/switch_asics/Jericho2Asic.cpp +++ b/fboss/agent/hw/switch_asics/Jericho2Asic.cpp @@ -272,6 +272,7 @@ bool Jericho2Asic::isSupported(Feature feature) const { case HwAsic::Feature::LAG_TTL_DECREMENT_DISABLE: case HwAsic::Feature::PORT_LATCH_STATUS: case HwAsic::Feature::PORT_SERDES_CREATED_WITH_PORT: + case HwAsic::Feature::SYSTEM_PORT_CORE_INDEX_FROM_PORT: return false; } return false; diff --git a/fboss/agent/hw/switch_asics/Jericho3Asic.cpp b/fboss/agent/hw/switch_asics/Jericho3Asic.cpp index fe12c8bae8e84..d333e1eed6f48 100644 --- a/fboss/agent/hw/switch_asics/Jericho3Asic.cpp +++ b/fboss/agent/hw/switch_asics/Jericho3Asic.cpp @@ -308,6 +308,7 @@ bool Jericho3Asic::isSupported(Feature feature) const { case HwAsic::Feature::LAG_TTL_DECREMENT_DISABLE: case HwAsic::Feature::PORT_LATCH_STATUS: case HwAsic::Feature::PORT_SERDES_CREATED_WITH_PORT: + case HwAsic::Feature::SYSTEM_PORT_CORE_INDEX_FROM_PORT: return false; } return false; diff --git a/fboss/agent/hw/switch_asics/Jericho4Asic.cpp b/fboss/agent/hw/switch_asics/Jericho4Asic.cpp index 723408b9556a8..04b73d5309c14 100644 --- a/fboss/agent/hw/switch_asics/Jericho4Asic.cpp +++ b/fboss/agent/hw/switch_asics/Jericho4Asic.cpp @@ -308,6 +308,7 @@ bool Jericho4Asic::isSupported(Feature feature) const { case HwAsic::Feature::LAG_TTL_DECREMENT_DISABLE: case HwAsic::Feature::PORT_LATCH_STATUS: case HwAsic::Feature::PORT_SERDES_CREATED_WITH_PORT: + case HwAsic::Feature::SYSTEM_PORT_CORE_INDEX_FROM_PORT: return false; } return false; diff --git a/fboss/agent/hw/switch_asics/P200Asic.cpp b/fboss/agent/hw/switch_asics/P200Asic.cpp index 087c38bf676e0..b414cc72fb776 100644 --- a/fboss/agent/hw/switch_asics/P200Asic.cpp +++ b/fboss/agent/hw/switch_asics/P200Asic.cpp @@ -285,6 +285,7 @@ bool P200Asic::isSupportedNonFabric(Feature feature) const { case HwAsic::Feature::LAG_TTL_DECREMENT_DISABLE: case HwAsic::Feature::PORT_LATCH_STATUS: case HwAsic::Feature::PORT_SERDES_CREATED_WITH_PORT: + case HwAsic::Feature::SYSTEM_PORT_CORE_INDEX_FROM_PORT: return false; case HwAsic::Feature::SAI_ACL_MPLS_LABEL0_TTL: // Leaba does not implement the MPLS label0 TTL ACL qualifier yet. diff --git a/fboss/agent/hw/switch_asics/Qumran4DAsic.cpp b/fboss/agent/hw/switch_asics/Qumran4DAsic.cpp index 449311ded2b5b..a67cb468c6756 100644 --- a/fboss/agent/hw/switch_asics/Qumran4DAsic.cpp +++ b/fboss/agent/hw/switch_asics/Qumran4DAsic.cpp @@ -81,6 +81,7 @@ bool Qumran4DAsic::isSupported(Feature feature) const { case HwAsic::Feature::EVENTOR_PORT_FOR_SFLOW: case HwAsic::Feature::SFLOWv6: case HwAsic::Feature::PORT_SERDES_CREATED_WITH_PORT: + case HwAsic::Feature::SYSTEM_PORT_CORE_INDEX_FROM_PORT: case HwAsic::Feature::ZERO_SDK_WRITE_WARMBOOT: case HwAsic::Feature::SWITCH_REACHABILITY_CHANGE_NOTIFY: case HwAsic::Feature::ACL_ENTRY_ETHER_TYPE: diff --git a/fboss/agent/hw/switch_asics/Tomahawk3Asic.cpp b/fboss/agent/hw/switch_asics/Tomahawk3Asic.cpp index 1114e8a251b23..62a9c002141cf 100644 --- a/fboss/agent/hw/switch_asics/Tomahawk3Asic.cpp +++ b/fboss/agent/hw/switch_asics/Tomahawk3Asic.cpp @@ -112,6 +112,7 @@ bool Tomahawk3Asic::isSupported(Feature feature) const { case HwAsic::Feature::ISOLATION_GROUP: case HwAsic::Feature::CSIG: case HwAsic::Feature::PORT_SERDES_CREATED_WITH_PORT: + case HwAsic::Feature::SYSTEM_PORT_CORE_INDEX_FROM_PORT: case HwAsic::Feature::QCM: case HwAsic::Feature::SMAC_EQUALS_DMAC_CHECK_ENABLED: case HwAsic::Feature::PORT_TTL_DECREMENT_DISABLE: diff --git a/fboss/agent/hw/switch_asics/Tomahawk4Asic.cpp b/fboss/agent/hw/switch_asics/Tomahawk4Asic.cpp index 5e7152d4bd3bc..b005c96c885f9 100644 --- a/fboss/agent/hw/switch_asics/Tomahawk4Asic.cpp +++ b/fboss/agent/hw/switch_asics/Tomahawk4Asic.cpp @@ -281,6 +281,7 @@ bool Tomahawk4Asic::isSupported(Feature feature) const { case HwAsic::Feature::LAG_TTL_DECREMENT_DISABLE: case HwAsic::Feature::PORT_LATCH_STATUS: case HwAsic::Feature::PORT_SERDES_CREATED_WITH_PORT: + case HwAsic::Feature::SYSTEM_PORT_CORE_INDEX_FROM_PORT: return false; } return false; diff --git a/fboss/agent/hw/switch_asics/Tomahawk5Asic.cpp b/fboss/agent/hw/switch_asics/Tomahawk5Asic.cpp index d1a6b66f2a754..11bb76d6851c9 100644 --- a/fboss/agent/hw/switch_asics/Tomahawk5Asic.cpp +++ b/fboss/agent/hw/switch_asics/Tomahawk5Asic.cpp @@ -264,6 +264,7 @@ bool Tomahawk5Asic::isSupported(Feature feature) const { case HwAsic::Feature::LAG_TTL_DECREMENT_DISABLE: case HwAsic::Feature::PORT_LATCH_STATUS: case HwAsic::Feature::PORT_SERDES_CREATED_WITH_PORT: + case HwAsic::Feature::SYSTEM_PORT_CORE_INDEX_FROM_PORT: return false; } return false; diff --git a/fboss/agent/hw/switch_asics/Tomahawk6Asic.cpp b/fboss/agent/hw/switch_asics/Tomahawk6Asic.cpp index 57ffc5990129a..01108728ae374 100644 --- a/fboss/agent/hw/switch_asics/Tomahawk6Asic.cpp +++ b/fboss/agent/hw/switch_asics/Tomahawk6Asic.cpp @@ -271,6 +271,7 @@ bool Tomahawk6Asic::isSupported(Feature feature) const { case HwAsic::Feature::LAG_TTL_DECREMENT_DISABLE: case HwAsic::Feature::PORT_LATCH_STATUS: case HwAsic::Feature::PORT_SERDES_CREATED_WITH_PORT: + case HwAsic::Feature::SYSTEM_PORT_CORE_INDEX_FROM_PORT: return false; } return false; diff --git a/fboss/agent/hw/switch_asics/TomahawkAsic.cpp b/fboss/agent/hw/switch_asics/TomahawkAsic.cpp index 403f4b23e4297..a39a57920d013 100644 --- a/fboss/agent/hw/switch_asics/TomahawkAsic.cpp +++ b/fboss/agent/hw/switch_asics/TomahawkAsic.cpp @@ -262,6 +262,7 @@ bool TomahawkAsic::isSupported(Feature feature) const { case HwAsic::Feature::LAG_TTL_DECREMENT_DISABLE: case HwAsic::Feature::PORT_LATCH_STATUS: case HwAsic::Feature::PORT_SERDES_CREATED_WITH_PORT: + case HwAsic::Feature::SYSTEM_PORT_CORE_INDEX_FROM_PORT: return false; } return false; diff --git a/fboss/agent/hw/switch_asics/TomahawkUltra1Asic.cpp b/fboss/agent/hw/switch_asics/TomahawkUltra1Asic.cpp index 36e42b749acff..344ffc35df856 100644 --- a/fboss/agent/hw/switch_asics/TomahawkUltra1Asic.cpp +++ b/fboss/agent/hw/switch_asics/TomahawkUltra1Asic.cpp @@ -267,6 +267,7 @@ bool TomahawkUltra1Asic::isSupported(Feature feature) const { case HwAsic::Feature::LAG_TTL_DECREMENT_DISABLE: case HwAsic::Feature::PORT_LATCH_STATUS: case HwAsic::Feature::PORT_SERDES_CREATED_WITH_PORT: + case HwAsic::Feature::SYSTEM_PORT_CORE_INDEX_FROM_PORT: return false; } return false; diff --git a/fboss/agent/hw/switch_asics/YubaAsic.cpp b/fboss/agent/hw/switch_asics/YubaAsic.cpp index 39efbdd03fe18..175aaffb9716b 100644 --- a/fboss/agent/hw/switch_asics/YubaAsic.cpp +++ b/fboss/agent/hw/switch_asics/YubaAsic.cpp @@ -277,6 +277,7 @@ bool YubaAsic::isSupportedNonFabric(Feature feature) const { case HwAsic::Feature::MY_MAC: case HwAsic::Feature::ISOLATION_GROUP: case HwAsic::Feature::PORT_SERDES_CREATED_WITH_PORT: + case HwAsic::Feature::SYSTEM_PORT_CORE_INDEX_FROM_PORT: case HwAsic::Feature::SWITCH_WIDE_LINK_UP_DEBOUNCE: case HwAsic::Feature::ACL_ENTRY_OUT_PORT_QUALIFIER: case HwAsic::Feature::XPHY_SERDES_TX_FIR_POST3: