diff --git a/fboss/agent/hw/sai/switch/SaiAclTableManager.cpp b/fboss/agent/hw/sai/switch/SaiAclTableManager.cpp index 8a573ae5154c6..676f085dd8407 100644 --- a/fboss/agent/hw/sai/switch/SaiAclTableManager.cpp +++ b/fboss/agent/hw/sai/switch/SaiAclTableManager.cpp @@ -22,6 +22,7 @@ #include "fboss/agent/hw/sai/switch/SaiPortManager.h" #include "fboss/agent/hw/sai/switch/SaiSwitch.h" #include "fboss/agent/hw/sai/switch/SaiSwitchManager.h" +#include "fboss/agent/hw/sai/switch/SaiUdfManager.h" #include "fboss/agent/hw/switch_asics/HwAsic.h" #include "fboss/agent/platforms/sai/SaiPlatform.h" @@ -562,6 +563,96 @@ SaiAclTableManager::addAclCounter( return std::make_pair(saiAclCounter, aclCounterTypeAndName); } +#if ( \ + (SAI_API_VERSION >= SAI_VERSION(1, 14, 0) || \ + (defined(BRCM_SAI_SDK_GTE_11_0) && defined(BRCM_SAI_SDK_XGS))) && \ + !defined(TAJO_SDK)) +void SaiAclTableManager::updateUdfGroupAttributes( + const std::shared_ptr& addedAclEntry, + const std::string& aclTableName, + std::optional& udfGroup0, + std::optional& udfGroup1, + std::optional& udfGroup2, + std::optional& udfGroup3, + std::optional& udfGroup4) { + auto convertSignedCharsToUnsignedChars = + [](const std::vector& vec) { + std::vector unsignedVec; + + std::transform( + vec.begin(), + vec.end(), + std::back_inserter(unsignedVec), + [](signed char c) { return static_cast(c); }); + + return unsignedVec; + }; + + /* + * UDF fields in ACL entries have to match the attribute ID offset where + * group is defined in the ACL table + * If udfGroup1 is at (SAI_ACL_TABLE_ATTR_USER_DEFINED_FIELD_GROUP_MIN + 1), + * the corresponding ACL entry fields should also use + * (SAI_ACL_ENTRY_ATTR_USER_DEFINED_FIELD_GROUP_MIN + 1) + * https://github.com/opencomputeproject/SAI/blob/master/doc/ACL/UDF-based-ACL.md#example-1 + * + * We have capability to program 5 UDF fields. The below code will try + * to match the UDF group SAI ID currently processed with the attribute used + * in the ACL table + */ + if (addedAclEntry->getUdfTable()) { + auto& aclApi = SaiApiTable::getInstance()->aclApi(); + auto aclTableHandle = getAclTableHandle(aclTableName); + auto aclTableSaiId = aclTableHandle->aclTable->adapterKey(); + // Get the udfGroup IDs, if programmed, from each of the 5 attributes + auto udfGroupId0 = aclApi.getAttribute(aclTableSaiId, AclTableUdfGroup0()); + auto udfGroupId1 = aclApi.getAttribute(aclTableSaiId, AclTableUdfGroup1()); + auto udfGroupId2 = aclApi.getAttribute(aclTableSaiId, AclTableUdfGroup2()); + auto udfGroupId3 = aclApi.getAttribute(aclTableSaiId, AclTableUdfGroup3()); + auto udfGroupId4 = aclApi.getAttribute(aclTableSaiId, AclTableUdfGroup4()); + + const auto udfTable = addedAclEntry->getUdfTable().value(); + for (const auto& udfEntry : udfTable) { + auto data = convertSignedCharsToUnsignedChars(*udfEntry.roceBytes()); + auto mask = convertSignedCharsToUnsignedChars(*udfEntry.roceMask()); + auto udfData = std::make_pair(std::move(data), std::move(mask)); + + std::vector udfGroupNames = {*udfEntry.udfGroup()}; + auto udfGroupSaiIds = + managerTable_->udfManager().getUdfGroupIds(udfGroupNames); + if (udfGroupSaiIds.size() == 0) { + throw FbossError( + "Invalid UdfGroup {} in ACL entry", *udfEntry.udfGroup()); + } + auto udfGroupSaiId = udfGroupSaiIds[0]; + + // for each udfGroup used in this ACL entry, check which attribute it + // uses in the ACL table and use the same ACL entry attribute + if (udfGroupSaiId == udfGroupId0) { + udfGroup0 = AclEntryUdfGroup0{AclEntryFieldU8List{udfData}}; + continue; + } + if (udfGroupSaiId == udfGroupId1) { + udfGroup1 = AclEntryUdfGroup1{AclEntryFieldU8List{udfData}}; + continue; + } + if (udfGroupSaiId == udfGroupId2) { + udfGroup2 = AclEntryUdfGroup2{AclEntryFieldU8List{udfData}}; + continue; + } + if (udfGroupSaiId == udfGroupId3) { + udfGroup3 = AclEntryUdfGroup3{AclEntryFieldU8List{udfData}}; + continue; + } + if (udfGroupSaiId == udfGroupId4) { + udfGroup4 = AclEntryUdfGroup4{AclEntryFieldU8List{udfData}}; + continue; + } + } + } +} +#endif + AclEntrySaiId SaiAclTableManager::addAclEntry( const std::shared_ptr& addedAclEntry, const std::string& aclTableName) { @@ -876,6 +967,26 @@ AclEntrySaiId SaiAclTableManager::addAclEntry( addedAclEntry->getLookupClassL2().value()))}; } +#if ( \ + (SAI_API_VERSION >= SAI_VERSION(1, 14, 0) || \ + (defined(BRCM_SAI_SDK_GTE_11_0) && defined(BRCM_SAI_SDK_XGS))) && \ + !defined(TAJO_SDK)) + std::optional userDefinedGroup0{std::nullopt}; + std::optional userDefinedGroup1{std::nullopt}; + std::optional userDefinedGroup2{std::nullopt}; + std::optional userDefinedGroup3{std::nullopt}; + std::optional userDefinedGroup4{std::nullopt}; + + updateUdfGroupAttributes( + addedAclEntry, + aclTableName, + userDefinedGroup0, + userDefinedGroup1, + userDefinedGroup2, + userDefinedGroup3, + userDefinedGroup4); +#endif + // TODO(skhare) Support all other ACL actions std::optional aclActionPacketAction{std::nullopt}; @@ -1136,6 +1247,14 @@ AclEntrySaiId SaiAclTableManager::addAclEntry( #endif #if !defined(TAJO_SDK) && !defined(BRCM_SAI_SDK_XGS) fieldIpv6NextHeader.has_value() || +#endif +#if ( \ + (SAI_API_VERSION >= SAI_VERSION(1, 14, 0) || \ + (defined(BRCM_SAI_SDK_GTE_11_0) && defined(BRCM_SAI_SDK_XGS))) && \ + !defined(TAJO_SDK)) + userDefinedGroup0.has_value() || userDefinedGroup1.has_value() || + userDefinedGroup2.has_value() || userDefinedGroup3.has_value() || + userDefinedGroup4.has_value() || #endif platform_->getAsic()->isSupported(HwAsic::Feature::EMPTY_ACL_MATCHER)); if (fieldSrcPort.has_value()) { @@ -1205,11 +1324,11 @@ AclEntrySaiId SaiAclTableManager::addAclEntry( (SAI_API_VERSION >= SAI_VERSION(1, 14, 0) || \ (defined(BRCM_SAI_SDK_GTE_11_0) && defined(BRCM_SAI_SDK_XGS))) && \ !defined(TAJO_SDK)) - std::nullopt, - std::nullopt, - std::nullopt, - std::nullopt, - std::nullopt, + userDefinedGroup0, + userDefinedGroup1, + userDefinedGroup2, + userDefinedGroup3, + userDefinedGroup4, #endif aclActionPacketAction, aclActionCounter, diff --git a/fboss/agent/hw/sai/switch/SaiAclTableManager.h b/fboss/agent/hw/sai/switch/SaiAclTableManager.h index 3e31f63e42ca2..02bee3e3a1b14 100644 --- a/fboss/agent/hw/sai/switch/SaiAclTableManager.h +++ b/fboss/agent/hw/sai/switch/SaiAclTableManager.h @@ -38,6 +38,33 @@ using SaiAclTable = SaiObject; using SaiAclEntry = SaiObject; using SaiAclCounter = SaiObject; +#if ( \ + (SAI_API_VERSION >= SAI_VERSION(1, 14, 0) || \ + (defined(BRCM_SAI_SDK_GTE_11_0) && defined(BRCM_SAI_SDK_XGS))) && \ + !defined(TAJO_SDK)) +using AclTableUdfGroup0 = + SaiAclTableTraits::Attributes::UserDefinedFieldGroupMin0; +using AclTableUdfGroup1 = + SaiAclTableTraits::Attributes::UserDefinedFieldGroupMin1; +using AclTableUdfGroup2 = + SaiAclTableTraits::Attributes::UserDefinedFieldGroupMin2; +using AclTableUdfGroup3 = + SaiAclTableTraits::Attributes::UserDefinedFieldGroupMin3; +using AclTableUdfGroup4 = + SaiAclTableTraits::Attributes::UserDefinedFieldGroupMin4; + +using AclEntryUdfGroup0 = + SaiAclEntryTraits::Attributes::UserDefinedFieldGroupMin0; +using AclEntryUdfGroup1 = + SaiAclEntryTraits::Attributes::UserDefinedFieldGroupMin1; +using AclEntryUdfGroup2 = + SaiAclEntryTraits::Attributes::UserDefinedFieldGroupMin2; +using AclEntryUdfGroup3 = + SaiAclEntryTraits::Attributes::UserDefinedFieldGroupMin3; +using AclEntryUdfGroup4 = + SaiAclEntryTraits::Attributes::UserDefinedFieldGroupMin4; +#endif + struct SaiAclEntryHandle { /* * In FBOSS implementation, an ACL counter is always associated with single @@ -83,6 +110,8 @@ class SaiAclTableManager { */ static auto constexpr kDscpMask = 0x3F; + static auto constexpr kMaxUdfGroups = 5; + /* * L4 Src/Dst Port Mask. * L4 Src/Dst Port is 16-bit. @@ -138,6 +167,19 @@ class SaiAclTableManager { SaiAclTableHandle* FOLLY_NULLABLE getAclTableHandle(const std::string& aclTableName); +#if ( \ + (SAI_API_VERSION >= SAI_VERSION(1, 14, 0) || \ + (defined(BRCM_SAI_SDK_GTE_11_0) && defined(BRCM_SAI_SDK_XGS))) && \ + !defined(TAJO_SDK)) + void updateUdfGroupAttributes( + const std::shared_ptr& addedAclEntry, + const std::string& aclTableName, + std::optional& udfGroup0, + std::optional& udfGroup1, + std::optional& udfGroup2, + std::optional& udfGroup3, + std::optional& udfGroup4); +#endif AclEntrySaiId addAclEntry( const std::shared_ptr& addedAclEntry, const std::string& aclTableName); diff --git a/fboss/agent/hw/sai/switch/npu/SaiAclTableManager.cpp b/fboss/agent/hw/sai/switch/npu/SaiAclTableManager.cpp index 65aea1e6d3675..61881035853e5 100644 --- a/fboss/agent/hw/sai/switch/npu/SaiAclTableManager.cpp +++ b/fboss/agent/hw/sai/switch/npu/SaiAclTableManager.cpp @@ -15,6 +15,7 @@ #include "fboss/agent/hw/sai/switch/SaiMirrorManager.h" #include "fboss/agent/hw/sai/switch/SaiPortManager.h" #include "fboss/agent/hw/sai/switch/SaiSwitchManager.h" +#include "fboss/agent/hw/sai/switch/SaiUdfManager.h" #include "fboss/agent/hw/switch_asics/HwAsic.h" #include "fboss/agent/platforms/sai/SaiPlatform.h" @@ -153,6 +154,15 @@ std:: return qualifierSet.find(qualifier) != qualifierSet.end(); }; + std::vector> udfGroupIds( + SaiAclTableManager::kMaxUdfGroups, std::nullopt); + int i = 0; + auto udfGroupSaiIds = managerTable_->udfManager().getUdfGroupIds( + addedAclTable->getUdfGroups()->toThrift()); + for (const auto udfGroupSaiId : udfGroupSaiIds) { + udfGroupIds[i++] = udfGroupSaiId; + } + SaiAclTableTraits::CreateAttributes attributes{ tableStage, bindPointList, @@ -191,11 +201,11 @@ std:: (SAI_API_VERSION >= SAI_VERSION(1, 14, 0) || \ (defined(BRCM_SAI_SDK_GTE_11_0) && defined(BRCM_SAI_SDK_XGS))) && \ !defined(TAJO_SDK)) - std::nullopt, // UserDefinedFieldGroupMin0 - std::nullopt, // UserDefinedFieldGroupMin1 - std::nullopt, // UserDefinedFieldGroupMin2 - std::nullopt, // UserDefinedFieldGroupMin3 - std::nullopt, // UserDefinedFieldGroupMin4 + udfGroupIds[0], // UserDefinedFieldGroupMin0 + udfGroupIds[1], // UserDefinedFieldGroupMin1 + udfGroupIds[2], // UserDefinedFieldGroupMin2 + udfGroupIds[3], // UserDefinedFieldGroupMin3 + udfGroupIds[4], // UserDefinedFieldGroupMin4 #endif };