diff --git a/.github/workflows/clang-format.yml b/.github/workflows/clang-format.yml new file mode 100644 index 0000000000000..6502ac7f34d22 --- /dev/null +++ b/.github/workflows/clang-format.yml @@ -0,0 +1,43 @@ +name: ClangFormat Lint + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + clang-format-check: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Install clang-format + run: sudo apt-get install -y clang-format + + - name: Get changed files + id: changed-files + run: | + if [ ${{ github.event_name }} == 'pull_request' ]; then + # For pull requests, compare against the base branch + echo "FILES=$(git diff --name-only --diff-filter=ACMRT ${{ github.event.pull_request.base.sha }} ${{ github.sha }} | grep -E '\.(cpp|h)$' | xargs)" >> $GITHUB_OUTPUT + else + # For pushes, compare against the parent commit + echo "FILES=$(git diff --name-only --diff-filter=ACMRT ${{ github.event.before }} ${{ github.sha }} | grep -E '\.(cpp|h)$' | xargs)" >> $GITHUB_OUTPUT + fi + + - name: Run clang-format + run: | + for file in ${{ steps.changed-files.outputs.FILES }}; do + clang-format -style=file -i "$file" + done + git diff --exit-code + + - name: Suggest changes if formatting is incorrect + if: failure() + run: | + echo "::error::Formatting issues found. Please run clang-format on your changes and commit the results." + git diff diff --git a/buck2 b/buck2 index 6232f04c10ea6..3c1af57c6d087 100755 --- a/buck2 +++ b/buck2 @@ -4,62 +4,62 @@ "name": "buck2", "platforms": { "macos-aarch64": { - "size": 23837292, + "size": 23905563, "hash": "blake3", - "digest": "45d97541497dab8c939f1650ea7282f88ce031dcb98a4412809600b36bf9d2ac", + "digest": "2716aabc7e2b68a0eba8d68908f604321dbe19673b9ed2c6f659cda2d263fa3a", "format": "zst", "path": "buck2-aarch64-apple-darwin", "providers": [ { - "url": "https://github.com/facebook/buck2/releases/download/2024-09-02/buck2-aarch64-apple-darwin.zst" + "url": "https://github.com/facebook/buck2/releases/download/2024-09-16/buck2-aarch64-apple-darwin.zst" } ] }, "linux-aarch64": { - "size": 26010757, + "size": 26041556, "hash": "blake3", - "digest": "05901b2db0e2fcaf4e5ff3b1cd2a7ce57aeeaf18e5c8b8c13f4743246cc51cfd", + "digest": "296ca8153596f29c73243a792bb235ed84bfd77a2d26c2f62eeecb1d272e3a90", "format": "zst", "path": "buck2-aarch64-unknown-linux-musl", "providers": [ { - "url": "https://github.com/facebook/buck2/releases/download/2024-09-02/buck2-aarch64-unknown-linux-musl.zst" + "url": "https://github.com/facebook/buck2/releases/download/2024-09-16/buck2-aarch64-unknown-linux-musl.zst" } ] }, "macos-x86_64": { - "size": 25454662, + "size": 25480555, "hash": "blake3", - "digest": "1a734c77fa6ee124b9e872e44d48917eb0e8388373930b3c8f5a53059c04c157", + "digest": "cf529f35b88a4a05e3a727aac7fad0e1549fac154d0b7effdaa481f942b6087e", "format": "zst", "path": "buck2-x86_64-apple-darwin", "providers": [ { - "url": "https://github.com/facebook/buck2/releases/download/2024-09-02/buck2-x86_64-apple-darwin.zst" + "url": "https://github.com/facebook/buck2/releases/download/2024-09-16/buck2-x86_64-apple-darwin.zst" } ] }, "windows-x86_64": { - "size": 20924720, + "size": 20968937, "hash": "blake3", - "digest": "903c00ce0095f5c423f141b9d1570f91edf2e6f045d41415409b5e4d5f973f05", + "digest": "7eab847191add144fdf9b979437a1d16bcf23659e7e70acbbf43ba02a901fa2e", "format": "zst", "path": "buck2-x86_64-pc-windows-msvc.exe", "providers": [ { - "url": "https://github.com/facebook/buck2/releases/download/2024-09-02/buck2-x86_64-pc-windows-msvc.exe.zst" + "url": "https://github.com/facebook/buck2/releases/download/2024-09-16/buck2-x86_64-pc-windows-msvc.exe.zst" } ] }, "linux-x86_64": { - "size": 26842328, + "size": 26879584, "hash": "blake3", - "digest": "b11fbc26e598874b0bdfde263c1c34d18ac547cd1a4fcb1f9693807cf9ba86e3", + "digest": "c50374aa898839e93a89a881bd92687cd431bb8961c24a18c0b40c30705327b2", "format": "zst", "path": "buck2-x86_64-unknown-linux-musl", "providers": [ { - "url": "https://github.com/facebook/buck2/releases/download/2024-09-02/buck2-x86_64-unknown-linux-musl.zst" + "url": "https://github.com/facebook/buck2/releases/download/2024-09-16/buck2-x86_64-unknown-linux-musl.zst" } ] } diff --git a/build/deps/github_hashes/facebook/fb303-rev.txt b/build/deps/github_hashes/facebook/fb303-rev.txt index 260bbfb8e55fa..71f656e30106f 100644 --- a/build/deps/github_hashes/facebook/fb303-rev.txt +++ b/build/deps/github_hashes/facebook/fb303-rev.txt @@ -1 +1 @@ -Subproject commit 495d843337a520d8ce089bba980d094e2794db6f +Subproject commit 456b5f6aead5a7b962dd03cac8e6a57e83157b01 diff --git a/build/deps/github_hashes/facebook/fbthrift-rev.txt b/build/deps/github_hashes/facebook/fbthrift-rev.txt index ddee273bdde91..347db4637d5e2 100644 --- a/build/deps/github_hashes/facebook/fbthrift-rev.txt +++ b/build/deps/github_hashes/facebook/fbthrift-rev.txt @@ -1 +1 @@ -Subproject commit 0cb4447fca20691ee0c6fed8c75badb94c6cb0fc +Subproject commit f6a4c13e9f0b7f533bfbe3b406195b709495d677 diff --git a/build/deps/github_hashes/facebook/folly-rev.txt b/build/deps/github_hashes/facebook/folly-rev.txt index fec2142f50bfb..0f71562de2a46 100644 --- a/build/deps/github_hashes/facebook/folly-rev.txt +++ b/build/deps/github_hashes/facebook/folly-rev.txt @@ -1 +1 @@ -Subproject commit 19254c4dd4e47c94364ebf78b12bcf69fdf28f16 +Subproject commit 5bf165e94f530215b27b87a755dc4d27e5e2ce12 diff --git a/build/deps/github_hashes/facebook/wangle-rev.txt b/build/deps/github_hashes/facebook/wangle-rev.txt index dff6d97aa3f17..baf9194e5a961 100644 --- a/build/deps/github_hashes/facebook/wangle-rev.txt +++ b/build/deps/github_hashes/facebook/wangle-rev.txt @@ -1 +1 @@ -Subproject commit fbc1ef163736bd5cf47e68472e17b1ca8b8b4ee1 +Subproject commit 9c04131911b53b3c336a13ca63eacd0548636f32 diff --git a/build/deps/github_hashes/facebookincubator/fizz-rev.txt b/build/deps/github_hashes/facebookincubator/fizz-rev.txt index 6f35de1ea4a4d..ff542a61765a4 100644 --- a/build/deps/github_hashes/facebookincubator/fizz-rev.txt +++ b/build/deps/github_hashes/facebookincubator/fizz-rev.txt @@ -1 +1 @@ -Subproject commit 9c60caec3bb99282affdebab2dfc0b4a89ea049f +Subproject commit 7215f1d7215ef80b298a0ac58cb421790a22c817 diff --git a/build/fbcode_builder/manifests/fizz b/build/fbcode_builder/manifests/fizz index 15e14ec608b3c..3709ff9d6c0da 100644 --- a/build/fbcode_builder/manifests/fizz +++ b/build/fbcode_builder/manifests/fizz @@ -25,6 +25,7 @@ BUILD_TESTS = OFF [dependencies] folly +liboqs libsodium zlib zstd diff --git a/build/fbcode_builder/manifests/libcurl b/build/fbcode_builder/manifests/libcurl index 8c94e4679d98d..cc2ac39927334 100644 --- a/build/fbcode_builder/manifests/libcurl +++ b/build/fbcode_builder/manifests/libcurl @@ -3,7 +3,7 @@ name = libcurl [rpms] libcurl-devel -libcurl +libcurl-minimal [debs] libcurl4-openssl-dev diff --git a/build/fbcode_builder/manifests/liboqs b/build/fbcode_builder/manifests/liboqs new file mode 100644 index 0000000000000..e1aaeea1c3837 --- /dev/null +++ b/build/fbcode_builder/manifests/liboqs @@ -0,0 +1,13 @@ +[manifest] +name = liboqs + +[download] +url = https://github.com/open-quantum-safe/liboqs/archive/refs/tags/0.10.1.tar.gz +sha256 = 00ca8aba65cd8c8eac00ddf978f4cac9dd23bb039f357448b60b7e3eed8f02da + +[build] +builder = cmake +subdir = liboqs-0.10.1 + +[dependencies] +openssl diff --git a/cmake/Agent.cmake b/cmake/Agent.cmake index ab86ef6592bcb..ec654092b1eb1 100644 --- a/cmake/Agent.cmake +++ b/cmake/Agent.cmake @@ -102,6 +102,14 @@ target_link_libraries(address_utils Folly::folly ) +add_library(asic_utils + fboss/agent/AsicUtils.cpp +) + +target_link_libraries(asic_utils + switch_asics +) + add_library(utils fboss/agent/AlpmUtils.cpp fboss/agent/LabelFibUtils.cpp @@ -110,18 +118,18 @@ add_library(utils ) target_link_libraries(utils + asic_utils error ctrl_cpp2 state + switchid_scope_resolver Folly::folly -) - -add_library(asic_utils - fboss/agent/AsicUtils.cpp -) - -target_link_libraries(asic_utils - switch_asics + meru400biu_platform_mapping + meru400bia_platform_mapping + meru400bfu_platform_mapping + meru800bia_platform_mapping + meru800bfa_platform_mapping + janga800bic_platform_mapping ) add_library(stats @@ -294,6 +302,7 @@ set(core_libs agent_fsdb_sync_manager fboss_event_base phy_snapshot_manager + build_info_wrapper ) target_link_libraries(core ${core_libs}) @@ -354,6 +363,11 @@ target_link_libraries(fboss_error Folly::folly ) +add_library(build_info_wrapper + fboss/agent/BuildInfoWrapper.h + fboss/agent/oss/BuildInfoWrapper.cpp +) + add_library(platform_base fboss/agent/Platform.cpp fboss/agent/PlatformPort.cpp diff --git a/cmake/AgentHwBenchmarks.cmake b/cmake/AgentHwBenchmarks.cmake index 57749c3bee8a2..618c3cfd6c4dc 100644 --- a/cmake/AgentHwBenchmarks.cmake +++ b/cmake/AgentHwBenchmarks.cmake @@ -412,3 +412,15 @@ target_link_libraries(hw_voq_scale_route_del_speed Folly::folly Folly::follybenchmark ) + +add_library(hw_switch_reachability_change_speed + fboss/agent/hw/benchmarks/HwSwitchReachabilityChangeBenchmark.cpp +) + +target_link_libraries(hw_switch_reachability_change_speed + mono_agent_ensemble + mono_agent_benchmarks + config_factory + Folly::folly + Folly::follybenchmark +) diff --git a/cmake/AgentHwSaiBenchmarks.cmake b/cmake/AgentHwSaiBenchmarks.cmake index 4a0ba0daf6545..083613688a753 100644 --- a/cmake/AgentHwSaiBenchmarks.cmake +++ b/cmake/AgentHwSaiBenchmarks.cmake @@ -470,6 +470,23 @@ function(BUILD_SAI_BENCHMARKS SAI_IMPL_NAME SAI_IMPL_ARG) -DSAI_VER_RELEASE=${SAI_VER_RELEASE}" ) + add_executable(sai_switch_reachability_change_speed-${SAI_IMPL_NAME} /dev/null) + + target_link_libraries(sai_switch_reachability_change_speed-${SAI_IMPL_NAME} + -Wl,--whole-archive + hw_switch_reachability_change_speed + mono_sai_agent_benchmarks_main + ${SAI_IMPL_ARG} + -Wl,--no-whole-archive + ) + + set_target_properties(sai_switch_reachability_change_speed-${SAI_IMPL_NAME} + PROPERTIES COMPILE_FLAGS + "-DSAI_VER_MAJOR=${SAI_VER_MAJOR} \ + -DSAI_VER_MINOR=${SAI_VER_MINOR} \ + -DSAI_VER_RELEASE=${SAI_VER_RELEASE}" + ) + endfunction() if(BUILD_SAI_FAKE AND BUILD_SAI_FAKE_BENCHMARKS) @@ -546,4 +563,7 @@ if(SAI_IMPL AND BENCHMARK_INSTALL) install( TARGETS sai_rib_resolution_speed-sai_impl) + install( + TARGETS + sai_switch_reachability_change_speed-sai_impl) endif() diff --git a/cmake/AgentHwSaiHwTest.cmake b/cmake/AgentHwSaiHwTest.cmake index a91f9c61d68cb..19a4d2a06f91f 100644 --- a/cmake/AgentHwSaiHwTest.cmake +++ b/cmake/AgentHwSaiHwTest.cmake @@ -164,6 +164,7 @@ add_library(agent_hw_test_thrift_handler fboss/agent/hw/sai/hw_test/HwTestNeighborUtilsThriftHandler.cpp fboss/agent/hw/sai/hw_test/HwTestEcmpUtilsThriftHandler.cpp fboss/agent/hw/sai/hw_test/HwTestPortUtilsThriftHandler.cpp + fboss/agent/hw/sai/hw_test/HwTestVoqSwitchUtilsThriftHandler.cpp ) target_link_libraries(agent_hw_test_thrift_handler diff --git a/cmake/AgentTestAgentHwTests.cmake b/cmake/AgentTestAgentHwTests.cmake index 9b398a4e2bc34..f687e33c72b63 100644 --- a/cmake/AgentTestAgentHwTests.cmake +++ b/cmake/AgentTestAgentHwTests.cmake @@ -48,6 +48,7 @@ add_library(agent_hw_test_src fboss/agent/test/agent_hw_tests/AgentRxReasonTests.cpp fboss/agent/test/agent_hw_tests/AgentRouteScaleTests.cpp fboss/agent/test/agent_hw_tests/MultiNodeAgentVoqSwitchTests.cpp + fboss/agent/test/agent_hw_tests/AgentHwAclMatchActionsTest.cpp ) target_link_libraries(agent_hw_test_src @@ -95,6 +96,7 @@ target_link_libraries(agent_hw_test_src pktutil mirror_test_utils voq_test_utils + fib_updater ) add_executable(multi_switch_agent_hw_test diff --git a/cmake/CliFboss2.cmake b/cmake/CliFboss2.cmake index c14f6d952e414..88bdc8b0eb685 100644 --- a/cmake/CliFboss2.cmake +++ b/cmake/CliFboss2.cmake @@ -141,6 +141,8 @@ add_fbthrift_cpp_library( fboss/cli/fboss2/commands/show/transceiver/model.thrift OPTIONS json + DEPENDS + transceiver_cpp2 ) add_fbthrift_cpp_library( diff --git a/cmake/PlatformFanService.cmake b/cmake/PlatformFanService.cmake index 859b3125f6972..9b7db3618b773 100644 --- a/cmake/PlatformFanService.cmake +++ b/cmake/PlatformFanService.cmake @@ -38,8 +38,10 @@ target_link_libraries(fan_service_lib product_info common_file_utils platform_config_lib + platform_name_lib platform_utils fan_service_config_types_cpp2 + gpiod_line sensor_service_cpp2 fan_service_cpp2 Folly::folly @@ -71,6 +73,8 @@ add_executable(fan_service_sw_test target_link_libraries(fan_service_sw_test fan_service_lib Folly::folly + ${LIBGPIOD} + gpiod_line ${GTEST} ${LIBGMOCK_LIBRARIES} ) diff --git a/cmake/PlatformFwUtil.cmake b/cmake/PlatformFwUtil.cmake index 185ad397e8f27..39911f3a39889 100644 --- a/cmake/PlatformFwUtil.cmake +++ b/cmake/PlatformFwUtil.cmake @@ -20,6 +20,7 @@ add_executable(fw_util target_link_libraries(fw_util Folly::folly platform_config_lib + platform_name_lib platform_utils FBThrift::thriftcpp2 fw_util_config-cpp2-types diff --git a/cmake/PlatformHelpers.cmake b/cmake/PlatformHelpers.cmake index f572789ca8568..e1aee0517f2a2 100644 --- a/cmake/PlatformHelpers.cmake +++ b/cmake/PlatformHelpers.cmake @@ -23,6 +23,7 @@ target_link_libraries(platform_fs_utils ) target_link_libraries(platform_name_lib + platform_fs_utils platform_utils Folly::folly fb303::fb303 diff --git a/cmake/PlatformSensorService.cmake b/cmake/PlatformSensorService.cmake index 79cbe51eeeb8d..36f768cacc987 100644 --- a/cmake/PlatformSensorService.cmake +++ b/cmake/PlatformSensorService.cmake @@ -50,6 +50,7 @@ add_library(sensor_service_lib target_link_libraries(sensor_service_lib log_thrift_call platform_config_lib + platform_name_lib platform_utils sensor_service_utils sensor_service_cpp2 diff --git a/cmake/PlatformWeutil.cmake b/cmake/PlatformWeutil.cmake index ddfdbd757e8fe..d41a1dc6ec21a 100644 --- a/cmake/PlatformWeutil.cmake +++ b/cmake/PlatformWeutil.cmake @@ -49,6 +49,7 @@ target_link_libraries(weutil_lib weutil_config_cpp2 weutil_fboss_eeprom_parser platform_config_lib + platform_name_lib ioctl_smbus_eeprom_reader ) diff --git a/fboss/.clang-format b/fboss/.clang-format new file mode 100644 index 0000000000000..d23d76b750372 --- /dev/null +++ b/fboss/.clang-format @@ -0,0 +1,114 @@ +# The primary clang-format config file. +# TODO(afuller): Set these settings when they aren't broken: +# - AllowShortBlocksOnASingleLine: Empty +--- +AccessModifierOffset: -1 +AlignAfterOpenBracket: AlwaysBreak +AlignConsecutiveMacros: false +AlignConsecutiveAssignments: false +AlignConsecutiveBitFields: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Left +AlignOperands: DontAlign +AlignTrailingComments: false +AllowAllArgumentsOnNextLine: true +AllowAllConstructorInitializersOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortEnumsOnASingleLine: true +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Empty +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: false +BinPackParameters: false +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Attach +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: false +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DeriveLineEnding: true +DerivePointerAlignment: false +DisableFormat: false +FixNamespaceComments: true +ForEachMacros: + - FOR_EACH + - FOR_EACH_R + - FOR_EACH_RANGE +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^<.*\.h(pp)?>' + Priority: 1 + - Regex: '^<.*' + Priority: 2 + - Regex: '.*' + Priority: 3 +IndentCaseLabels: true +IndentCaseBlocks: false +IndentGotoLabels: true +IndentPPDirectives: None +IndentExternBlock: AfterExternBlock +IndentWidth: 2 +IndentWrappedFunctionNames: false +InsertTrailingCommas: None +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: false +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerAlignment: Left +ReflowComments: true +SortIncludes: true +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +Standard: Latest +TabWidth: 8 +UseCRLF: false +UseTab: Never +... diff --git a/fboss/agent/ApplyThriftConfig.cpp b/fboss/agent/ApplyThriftConfig.cpp index 58697e0638daa..f249f7e084283 100644 --- a/fboss/agent/ApplyThriftConfig.cpp +++ b/fboss/agent/ApplyThriftConfig.cpp @@ -20,6 +20,7 @@ #include "fboss/agent/AclNexthopHandler.h" +#include "fboss/agent/AsicUtils.h" #include "fboss/agent/FbossError.h" #include "fboss/agent/HwAsicTable.h" #include "fboss/agent/LacpTypes.h" @@ -144,6 +145,7 @@ std::shared_ptr toMultiSwitchMap( } return multiMap; } + } // anonymous namespace namespace facebook::fboss { @@ -469,6 +471,8 @@ class ThriftConfigApplier { std::shared_ptr updateIpInIpTunnels(); std::shared_ptr updateDsfNodes(); void processUpdatedDsfNodes(); + void processReachabilityGroup( + const std::vector& localFabricSwitchIds); void validateUdfConfig(const UdfConfig& newUdfConfig); std::shared_ptr updateUdfConfig(bool* changed); @@ -493,7 +497,7 @@ class ThriftConfigApplier { SwitchID getSwitchId(const cfg::Interface& intfConfig) const; void addRemoteIntfRoute(); std::optional getAnyVoqSwitchId(); - std::vector getFabricSwitchIds() const; + std::vector getLocalFabricSwitchIds() const; std::optional getDefaultVoqConfigIfChanged( std::shared_ptr switchSettings); QueueConfig getVoqConfig(PortID portId); @@ -795,6 +799,14 @@ shared_ptr ThriftConfigApplier::run() { } } + { + // Update reachability group setting for input balanced + auto localFabricSwitchIds = getLocalFabricSwitchIds(); + if (!localFabricSwitchIds.empty()) { + processReachabilityGroup(localFabricSwitchIds); + } + } + if (!changed) { return nullptr; } @@ -814,16 +826,16 @@ std::optional ThriftConfigApplier::getAnyVoqSwitchId() { return switchId; } -std::vector ThriftConfigApplier::getFabricSwitchIds() const { - std::vector fabricSwitchIds; +std::vector ThriftConfigApplier::getLocalFabricSwitchIds() const { + std::vector localFabricSwitchIds; for (const auto& switchIdAndSwitchInfo : *cfg_->switchSettings()->switchIdToSwitchInfo()) { if (switchIdAndSwitchInfo.second.switchType() == cfg::SwitchType::FABRIC) { - fabricSwitchIds.push_back( + localFabricSwitchIds.push_back( static_cast(switchIdAndSwitchInfo.first)); } } - return fabricSwitchIds; + return localFabricSwitchIds; } // Return the new defaultVoqConfig if it is different from the @@ -1117,6 +1129,108 @@ void ThriftConfigApplier::processUpdatedDsfNodes() { [&](auto oldNode) { rmDsfNode(oldNode); }); } +void ThriftConfigApplier::processReachabilityGroup( + const std::vector& localFabricSwitchIds) { + std::unordered_map> switchNameToSwitchIds; + + // TODO(zecheng): Update to look at DsfNode layer config once available. + + // To determine if Dsf cluster is single stage: + // If there's more than one clusterIds in dsfNode map, it's in multi-stage. + std::unordered_set clusterIds; + for (const auto& [_, dsfNodeMap] : std::as_const(*new_->getDsfNodes())) { + for (const auto& [_, dsfNode] : std::as_const(*dsfNodeMap)) { + std::string nodeName = dsfNode->getName(); + auto iter = switchNameToSwitchIds.find(nodeName); + if (iter != switchNameToSwitchIds.end()) { + iter->second.push_back(dsfNode->getID()); + } else { + switchNameToSwitchIds[nodeName] = {dsfNode->getID()}; + } + if (auto clusterId = dsfNode->getClusterId()) { + clusterIds.insert(*clusterId); + } + } + } + bool isSingleStageCluster = clusterIds.size() <= 1; + + auto updateReachabilityGroupListSize = + [&](const auto fabricSwitchId, const auto reachabilityGroupListSize) { + auto matcher = HwSwitchMatcher(std::unordered_set( + {static_cast(fabricSwitchId)})); + if (new_->getSwitchSettings() + ->getNodeIf(matcher.matcherString()) + ->getReachabilityGroupListSize() != reachabilityGroupListSize) { + auto newMultiSwitchSettings = new_->getSwitchSettings()->clone(); + auto newSwitchSettings = + newMultiSwitchSettings->getNodeIf(matcher.matcherString()) + ->clone(); + newSwitchSettings->setReachabilityGroupListSize( + reachabilityGroupListSize); + newMultiSwitchSettings->updateNode( + matcher.matcherString(), newSwitchSettings); + new_->resetSwitchSettings(newMultiSwitchSettings); + } + }; + + bool parallelVoqLinks = haveParallelLinksToInterfaceNodes( + cfg_, localFabricSwitchIds, switchNameToSwitchIds, scopeResolver_); + + if (!isSingleStageCluster || parallelVoqLinks) { + auto newPortMap = new_->getPorts()->modify(&new_); + for (const auto& fabricSwitchId : localFabricSwitchIds) { + std::unordered_map destinationId2ReachabilityGroup; + for (const auto& portCfg : *cfg_->ports()) { + if (scopeResolver_.scope(portCfg).has(SwitchID(fabricSwitchId)) && + portCfg.expectedNeighborReachability()->size() > 0) { + auto neighborRemoteSwitchId = + getRemoteSwitchID(cfg_, portCfg, switchNameToSwitchIds); + const auto& neighborDsfNode = + new_->getDsfNodes()->getNode(neighborRemoteSwitchId); + + int destinationId; + // For parallel VOQ links, assign links reaching the same VOQ + // switch. + if (parallelVoqLinks && + neighborDsfNode->getType() == cfg::DsfNodeType::INTERFACE_NODE) { + destinationId = neighborRemoteSwitchId; + } else if (neighborDsfNode->getClusterId() == std::nullopt) { + // Assign links based on cluster ID. Note that in dual stage, + // FE2 has no cluster ID: use -1 for grouping purpose. + CHECK_EQ( + static_cast(cfg::DsfNodeType::FABRIC_NODE), + static_cast(neighborDsfNode->getType())); + destinationId = -1; + } else { + destinationId = neighborDsfNode->getClusterId().value(); + } + + auto [it, inserted] = destinationId2ReachabilityGroup.insert( + {destinationId, destinationId2ReachabilityGroup.size() + 1}); + auto reachabilityGroupId = it->second; + if (inserted) { + XLOG(DBG2) << "Create new reachability group " + << reachabilityGroupId << " towards node " + << neighborDsfNode->getName() << " with switchId " + << neighborRemoteSwitchId; + } else { + XLOG(DBG2) << "Add node " << neighborDsfNode->getName() + << " with switchId " << neighborRemoteSwitchId + << " to existing reachability group " + << reachabilityGroupId; + } + + auto newPort = + newPortMap->getNode(PortID(*portCfg.logicalID()))->modify(&new_); + newPort->setReachabilityGroupId(reachabilityGroupId); + } + } + updateReachabilityGroupListSize( + fabricSwitchId, destinationId2ReachabilityGroup.size()); + } + } +} + void ThriftConfigApplier::validateUdfConfig(const UdfConfig& newUdfConfig) { auto udfGroupMap = newUdfConfig.getUdfGroupMap(); if (udfGroupMap == nullptr) { @@ -4680,7 +4794,6 @@ std::shared_ptr ThriftConfigApplier::updateMirrors() { bool changed = false; size_t numExistingProcessed = 0; - int sflowMirrorCount = 0; for (const auto& mirrorCfg : *cfg_->mirrors()) { auto origMirror = origMirrors->getNodeIf(*mirrorCfg.name()); std::shared_ptr newMirror; @@ -4690,14 +4803,6 @@ std::shared_ptr ThriftConfigApplier::updateMirrors() { } else { newMirror = createMirror(&mirrorCfg); } - if (newMirror) { - sflowMirrorCount += newMirror->type() == Mirror::Type::SFLOW ? 1 : 0; - } else { - sflowMirrorCount += origMirror->type() == Mirror::Type::SFLOW ? 1 : 0; - } - if (sflowMirrorCount > 1) { - throw FbossError("More than one sflow mirrors configured"); - } changed |= updateThriftMapNode(newMirrors.get(), origMirror, newMirror); } @@ -4707,6 +4812,7 @@ std::shared_ptr ThriftConfigApplier::updateMirrors() { changed = true; } + std::set ingressMirrors; for (auto& portMap : std::as_const(*(new_->getPorts()))) { for (auto& port : std::as_const(*portMap.second)) { auto portInMirror = port.second->getIngressMirror(); @@ -4728,6 +4834,9 @@ std::shared_ptr ThriftConfigApplier::updateMirrors() { port.second->getID(), " not sflow"); } + if (inMirrorMapEntry->second->type() == Mirror::Type::SFLOW) { + ingressMirrors.insert(portInMirror.value()); + } } if (portEgMirror.has_value() && newMirrors->find(portEgMirror.value()) == newMirrors->end()) { @@ -4736,6 +4845,10 @@ std::shared_ptr ThriftConfigApplier::updateMirrors() { } } } + if (ingressMirrors.size() > 1) { + throw FbossError( + "Only one sflow mirror can be configured across all ports"); + } if (!changed) { return nullptr; diff --git a/fboss/agent/ArpHandler.cpp b/fboss/agent/ArpHandler.cpp index ae985249c3ee0..2ab1c3b83759e 100644 --- a/fboss/agent/ArpHandler.cpp +++ b/fboss/agent/ArpHandler.cpp @@ -147,6 +147,16 @@ void ArpHandler::handlePacket( << targetIP; return; } + if (op == ARP_OP_REPLY && + !AggregatePort::isIngressValid(sw_->getState(), pkt, true)) { + // drop ARP reply packets when LAG port is not up yet, + // otherwise, ARP entry would be created for this down port, + // and confuse later neighbor/next hop resolution logics + XLOG(DBG2) << "Dropping invalid ARP reply ingressing on port " + << pkt->getSrcPort() << " on vlan " << vlanIDStr << " for " + << targetIP; + return; + } // This ARP packet is destined to us. // Update the sender IP --> sender MAC entry in the ARP table. diff --git a/fboss/agent/BUCK b/fboss/agent/BUCK index 0e4c514db8f75..11f0a6a1151d5 100644 --- a/fboss/agent/BUCK +++ b/fboss/agent/BUCK @@ -469,27 +469,34 @@ cpp_library( "facebook/Utils.cpp", ], exported_deps = [ - ":fboss-error", - ":fboss-types", - ":fsdb_helper", - ":hwswitch_matcher", - ":switch_config-cpp2-types", - ":switch_state-cpp2-types", - ":switchid_scope_resolver", - "//common/network:util", - "//fboss/agent/if:ctrl-cpp2-types", - "//fboss/agent/state:state", - "//fboss/fsdb/if:fsdb_oper-cpp2-types", - "//folly:file_util", - "//folly:network_address", - "//folly:range", - "//folly:subprocess", - "//folly/json:dynamic", - "//folly/lang:bits", - "//folly/logging:logging", - "//folly/system:thread_name", - "//thrift/lib/cpp/util:enum_utils", - "//thrift/lib/cpp2/protocol:protocol", + "fbcode//common/network:util", + "fbcode//fboss/agent:asic_utils", + "fbcode//fboss/agent:fboss-error", + "fbcode//fboss/agent:fboss-types", + "fbcode//fboss/agent:fsdb_helper", + "fbcode//fboss/agent:hwswitch_matcher", + "fbcode//fboss/agent:switch_config-cpp2-types", + "fbcode//fboss/agent:switch_state-cpp2-types", + "fbcode//fboss/agent:switchid_scope_resolver", + "fbcode//fboss/agent/if:ctrl-cpp2-types", + "fbcode//fboss/agent/platforms/common/janga800bic:janga800bic_platform_mapping", + "fbcode//fboss/agent/platforms/common/meru400bfu:meru400bfu_platform_mapping", + "fbcode//fboss/agent/platforms/common/meru400bia:meru400bia_platform_mapping", + "fbcode//fboss/agent/platforms/common/meru400biu:meru400biu_platform_mapping", + "fbcode//fboss/agent/platforms/common/meru800bfa:meru800bfa_platform_mapping", + "fbcode//fboss/agent/platforms/common/meru800bia:meru800bia_platform_mapping", + "fbcode//fboss/agent/state:state", + "fbcode//fboss/fsdb/if:fsdb_oper-cpp2-types", + "fbcode//folly:file_util", + "fbcode//folly:network_address", + "fbcode//folly:range", + "fbcode//folly:subprocess", + "fbcode//folly/json:dynamic", + "fbcode//folly/lang:bits", + "fbcode//folly/logging:logging", + "fbcode//folly/system:thread_name", + "fbcode//thrift/lib/cpp/util:enum_utils", + "fbcode//thrift/lib/cpp2/protocol:protocol", ], exported_external_deps = [ "boost", @@ -564,30 +571,31 @@ cpp_library( name = "apply_thrift_config", srcs = ["ApplyThriftConfig.cpp"], exported_deps = [ - ":core", - ":fboss-error", - ":hw_asic_table", - ":lacp_types", - ":loadbalancer_utils", - ":route_update_wrapper", - ":switch_config-cpp2-types", - ":switchid_scope_resolver", - ":switchinfo_utils", - ":utils", - "//fboss/agent/hw/switch_asics:switch_asics", - "//fboss/agent/if:mpls-cpp2-types", - "//fboss/agent/platforms/common:platform_mapping", - "//fboss/agent/rib:fib_updater", - "//fboss/agent/rib:network_to_route_map", - "//fboss/agent/rib:standalone_rib", - "//fboss/agent/state:state", - "//fboss/agent/state:state_utils", - "//fboss/lib/config:fboss_config_utils", - "//fboss/thrift_cow/nodes:nodes", - "//folly:file_util", - "//folly:range", - "//folly/gen:base", - "//thrift/lib/cpp2/protocol:protocol", + "fbcode//fboss/agent:asic_utils", + "fbcode//fboss/agent:core", + "fbcode//fboss/agent:fboss-error", + "fbcode//fboss/agent:hw_asic_table", + "fbcode//fboss/agent:lacp_types", + "fbcode//fboss/agent:loadbalancer_utils", + "fbcode//fboss/agent:route_update_wrapper", + "fbcode//fboss/agent:switch_config-cpp2-types", + "fbcode//fboss/agent:switchid_scope_resolver", + "fbcode//fboss/agent:switchinfo_utils", + "fbcode//fboss/agent:utils", + "fbcode//fboss/agent/hw/switch_asics:switch_asics", + "fbcode//fboss/agent/if:mpls-cpp2-types", + "fbcode//fboss/agent/platforms/common:platform_mapping", + "fbcode//fboss/agent/rib:fib_updater", + "fbcode//fboss/agent/rib:network_to_route_map", + "fbcode//fboss/agent/rib:standalone_rib", + "fbcode//fboss/agent/state:state", + "fbcode//fboss/agent/state:state_utils", + "fbcode//fboss/lib/config:fboss_config_utils", + "fbcode//fboss/thrift_cow/nodes:nodes", + "fbcode//folly:file_util", + "fbcode//folly:range", + "fbcode//folly/gen:base", + "fbcode//thrift/lib/cpp2/protocol:protocol", ], exported_external_deps = [ ("boost", None, "boost_container"), @@ -794,6 +802,7 @@ cpp_library( "//fboss/thrift_cow/nodes:nodes", "//fboss/thrift_cow/nodes:serializer", "//fboss/thrift_cow/storage:cow_storage", + "//fboss/util:logging", "//folly:conv", "//folly:demangle", "//folly:exception_string", @@ -816,6 +825,7 @@ cpp_library( "//folly/container:f14_hash", "//folly/executors:io_thread_pool_executor", "//folly/executors/thread_factory:named_thread_factory", + "//folly/experimental/coro:bounded_queue", "//folly/futures:core", "//folly/gen:base", "//folly/io:iobuf", @@ -903,6 +913,19 @@ cpp_library( ], ) +cpp_library( + name = "build_info_wrapper", + srcs = [ + "facebook/BuildInfoWrapper.cpp", + ], + headers = [ + "BuildInfoWrapper.h", + ], + exported_deps = [ + "//common/base:build_info", + ], +) + cpp_library( name = "fboss-types", srcs = [ @@ -1412,10 +1435,10 @@ cpp_library( "//folly:cancellation_token", "//folly:network_address", "//folly:synchronized", - "//folly/experimental/coro:async_scope", - "//folly/experimental/coro:blocking_wait", - "//folly/experimental/coro:bounded_queue", - "//folly/experimental/coro:unbounded_queue", + "//folly/coro:async_scope", + "//folly/coro:blocking_wait", + "//folly/coro:bounded_queue", + "//folly/coro:unbounded_queue", "//folly/io/async:async_base", "//folly/io/async:scoped_event_base_thread", "//thrift/lib/cpp2/async:pooled_request_channel", diff --git a/fboss/agent/BuildInfoWrapper.h b/fboss/agent/BuildInfoWrapper.h new file mode 100644 index 0000000000000..5f10f122265bf --- /dev/null +++ b/fboss/agent/BuildInfoWrapper.h @@ -0,0 +1,11 @@ +// (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary. + +#pragma once + +#include + +namespace facebook::fboss { + +std::string getBuildPackageVersion(); + +} // namespace facebook::fboss diff --git a/fboss/agent/DsfSubscription.cpp b/fboss/agent/DsfSubscription.cpp index 49cd1cb2eb412..0d6dcd0cfc3ab 100644 --- a/fboss/agent/DsfSubscription.cpp +++ b/fboss/agent/DsfSubscription.cpp @@ -9,6 +9,7 @@ #include "fboss/fsdb/if/FsdbModel.h" #include "fboss/fsdb/if/gen-cpp2/fsdb_common_types.h" #include "fboss/thrift_cow/nodes/Serializer.h" +#include "fboss/util/Logging.h" using namespace facebook::fboss; namespace { @@ -53,7 +54,6 @@ std::vector> getAllSubscribePaths( DsfSubscription::makeRemoteEndpoint(localNodeName, localIP)) .tokens()}; } -auto constexpr kDsfCtrlLogPrefix = "DSF_CTRL_EVENT: "; } // namespace namespace facebook::fboss { @@ -133,7 +133,8 @@ void DsfSubscription::setupSubscription() { subMgr_->subscribe( [this, remoteEndpoint, sysPortPathKey, inftMapKey, dsfSubscriptionsKey]( auto update) { - auto agentState = update.data->template ref(); + auto agentState = + update.data->template safe_cref(); bool portsOrIntfsChanged = false; for (const auto& key : update.updatedKeys) { if (key == sysPortPathKey || key == inftMapKey) { @@ -149,7 +150,7 @@ void DsfSubscription::setupSubscription() { } if (portsOrIntfsChanged) { auto switchState = - agentState->template ref(); + agentState->template safe_cref(); queueRemoteStateChanged( *switchState->getSystemPorts(), *switchState->getInterfaces()); } @@ -262,7 +263,8 @@ void DsfSubscription::handleFsdbUpdate(fsdb::OperSubPathUnit&& operStateUnit) { } else if (getDsfSubscriptionsPath( makeRemoteEndpoint(localNodeName_, localIp_)) .matchesPath(*change.path()->path())) { - XLOG(DBG2) << "Got dsf sub update from : " << remoteNodeName_; + XLOG(DBG2) << kDsfCtrlLogPrefix + << "Got dsf sub update from : " << remoteNodeName_; using targetType = fsdb::FsdbSubscriptionState; using targetTypeClass = apache::thrift::type_class::enumeration; diff --git a/fboss/agent/HwAgentMain.cpp b/fboss/agent/HwAgentMain.cpp index 4513fd7aeaa9c..919bb87f70291 100644 --- a/fboss/agent/HwAgentMain.cpp +++ b/fboss/agent/HwAgentMain.cpp @@ -225,11 +225,15 @@ int hwAgentMain( [&thriftSyncer, &fs, &server]() { XLOG(DBG2) << "[Exit] Stopping Thrift Syncer"; thriftSyncer->stop(); + XLOG(DBG2) << "[Exit] Stop listening on thrift server"; + server->stopListening(); XLOG(DBG2) << "[Exit] Stopping Thrift Server"; auto stopController = server->getStopController(); if (auto lockedPtr = stopController.lock()) { lockedPtr->stop(); XLOG(DBG2) << "[Exit] Stopped Thrift Server"; + clearThriftModules(); + XLOG(DBG2) << "[Exit] Cleared thrift modules"; } else { LOG(WARNING) << "Unable to stop Thrift Server"; } diff --git a/fboss/agent/IPv6Handler.cpp b/fboss/agent/IPv6Handler.cpp index bcde82c96ce3e..07c3bd5305a5f 100644 --- a/fboss/agent/IPv6Handler.cpp +++ b/fboss/agent/IPv6Handler.cpp @@ -606,6 +606,21 @@ void IPv6Handler::handleNeighborAdvertisement( return; } + if (!AggregatePort::isIngressValid(sw_->getState(), pkt, true)) { + // drop NDP advertisement packets when LAG port is not up, + // otherwise, NDP entry would be created for this down port, + // and confuse later neighbor/next hop resolution logics + auto vlanID = getVlanIDFromVlanOrIntf(vlanOrIntf); + auto vlanIDStr = vlanID.has_value() + ? folly::to(static_cast(vlanID.value())) + : "None"; + XLOG(DBG2) << "Dropping invalid neighbor advertisement ingressing on port " + << pkt->getSrcPort() << " on vlan " << vlanIDStr << " for " + << targetIP; + sw_->portStats(pkt)->pktDropped(); + return; + } + XLOG(DBG4) << "got neighbor advertisement for " << targetIP << " (" << targetMac << ")"; diff --git a/fboss/agent/LacpTypes.cpp b/fboss/agent/LacpTypes.cpp index 33f02d9a7793d..3e2e93517350b 100644 --- a/fboss/agent/LacpTypes.cpp +++ b/fboss/agent/LacpTypes.cpp @@ -87,7 +87,7 @@ folly::dynamic ParticipantInfo::toFollyDynamic() const { folly::dynamic info = folly::dynamic::object; info[kId] = static_cast(key); info[kPortID] = static_cast(port); - info[kSystemID] = folly::dynamic(systemID.begin(), systemID.end()); + info[kSystemID] = folly::dynamic::array_range(systemID); info[kSystemPriority] = static_cast(systemPriority); info[kPriority] = static_cast(portPriority); info[kState] = static_cast(state); diff --git a/fboss/agent/MultiSwitchThriftHandler.cpp b/fboss/agent/MultiSwitchThriftHandler.cpp index cfb20f2ef1807..9bb9c7d1ed999 100644 --- a/fboss/agent/MultiSwitchThriftHandler.cpp +++ b/fboss/agent/MultiSwitchThriftHandler.cpp @@ -262,9 +262,21 @@ MultiSwitchThriftHandler::co_notifyRxPacket(int64_t switchId) { if (item->aggPort()) { pkt->setSrcAggregatePort(AggregatePortID(*item->aggPort())); } + if (item->cosQueue()) { + pkt->setCosQueue(static_cast(*item->cosQueue())); + } // Agent pkt handling code assumes single buffer, so coalesce pkt->buf()->coalesce(); - sw_->packetReceived(std::move(pkt)); + if (*item->length() != pkt->buf()->length()) { + XLOG(ERR) << "Rx packet length mismatch for switch " << switchId; + sw_->stats()->hwAgentRxBadPktReceived(switchIndex); + continue; + } + if (FLAGS_rx_sw_priority) { + sw_->rxPacketReceived(std::move(pkt)); + } else { + sw_->packetReceived(std::move(pkt)); + } } } catch (const std::exception& e) { XLOG(DBG2) << "Rx packet event sink cancelled for switch " << switchId diff --git a/fboss/agent/NeighborCacheImpl-defs.h b/fboss/agent/NeighborCacheImpl-defs.h index 0de10e1e38963..0c3688ceaac15 100644 --- a/fboss/agent/NeighborCacheImpl-defs.h +++ b/fboss/agent/NeighborCacheImpl-defs.h @@ -158,7 +158,7 @@ NeighborCacheImpl::getUpdateFnToProgramEntryForVlan(Entry* entry) { table->updateEntry(fields); XLOG(DBG2) << "Converting pending entry for " << fields.ip << " --> " << fields.mac << " on interface " << fields.interfaceID - << " for vlan " << vlanID; + << " port " << fields.port << " for vlan " << vlanID; } return newState; }; diff --git a/fboss/agent/RxPacket.h b/fboss/agent/RxPacket.h index 52c769be697b4..419d4a7115376 100644 --- a/fboss/agent/RxPacket.h +++ b/fboss/agent/RxPacket.h @@ -82,12 +82,9 @@ class RxPacket : public Packet { virtual std::string describeDetails() const { return ""; } - /* - * Derived classes to override and provide CoS queue - * info (if available) - */ - virtual int cosQueue() const { - return -1; + + std::optional cosQueue() const { + return cosQueue_; } /* @@ -115,6 +112,7 @@ class RxPacket : public Packet { // Once all those callsites are fixed, default to std::nullopt. std::optional srcVlan_{0}; uint32_t len_{0}; + std::optional cosQueue_; }; } // namespace facebook::fboss diff --git a/fboss/agent/SetupThrift.h b/fboss/agent/SetupThrift.h index 237ca9f9241d2..e33dc0002a497 100644 --- a/fboss/agent/SetupThrift.h +++ b/fboss/agent/SetupThrift.h @@ -28,6 +28,7 @@ namespace facebook::fboss { void serverSSLSetup(apache::thrift::ThriftServer& server); void setupThriftModules(); +void clearThriftModules(); std::unique_ptr setupThriftServer( folly::EventBase& eventBase, diff --git a/fboss/agent/SwAgentInitializer.cpp b/fboss/agent/SwAgentInitializer.cpp index 7d222a283ebf5..bdabd386e962e 100644 --- a/fboss/agent/SwAgentInitializer.cpp +++ b/fboss/agent/SwAgentInitializer.cpp @@ -153,13 +153,22 @@ void SwAgentSignalHandler::signalReceived(int /*signum*/) noexcept { } void SwAgentInitializer::stopServer() { + // Server init happens asynchronously, so if AgentEnsemble somehow exited + // before server_ is set (e.g. due to an error), the code below will crash. + if (!serverStarted_) { + return; + } // stop Thrift server: stop all worker threads and // stop accepting new connections + XLOG(DBG2) << "Stop listening on thrift server"; + server_->stopListening(); XLOG(DBG2) << "Stopping thrift server"; auto stopController = server_->getStopController(); if (auto lockedPtr = stopController.lock()) { lockedPtr->stop(); XLOG(DBG2) << "Stopped thrift server"; + clearThriftModules(); + XLOG(DBG2) << "Cleared thrift modules"; } else { LOG(WARNING) << "Unable to stop Thrift Server"; } diff --git a/fboss/agent/SwRxPacket.h b/fboss/agent/SwRxPacket.h index 07246e4a5af68..0a4a8573aec62 100644 --- a/fboss/agent/SwRxPacket.h +++ b/fboss/agent/SwRxPacket.h @@ -15,11 +15,25 @@ namespace facebook::fboss { class SwRxPacket : public RxPacket { public: - explicit SwRxPacket(std::unique_ptr buf) { + explicit SwRxPacket(std::unique_ptr buf) noexcept { buf_ = std::move(buf); len_ = buf_->computeChainDataLength(); } + // Noexcept move constructor + SwRxPacket(SwRxPacket&& other) noexcept { + buf_ = std::move(other.buf_); + len_ = other.len_; + setSrcPort(other.getSrcPort()); + setSrcVlan(other.getSrcVlan()); + if (other.cosQueue()) { + setCosQueue(*other.cosQueue()); + } + if (other.isFromAggregatePort()) { + setSrcAggregatePort(other.getSrcAggregatePort()); + } + } + void setSrcPort(PortID id) { srcPort_ = id; } @@ -30,6 +44,9 @@ class SwRxPacket : public RxPacket { isFromAggregatePort_ = true; srcAggregatePort_ = srcAggregatePort; } + void setCosQueue(uint8_t cosQueue) { + cosQueue_ = cosQueue; + } private: // Forbidden copy constructor and assignment operator diff --git a/fboss/agent/SwSwitch.cpp b/fboss/agent/SwSwitch.cpp index 88d10ac803e97..1c19a231b4a6f 100644 --- a/fboss/agent/SwSwitch.cpp +++ b/fboss/agent/SwSwitch.cpp @@ -159,7 +159,7 @@ DEFINE_int32( DEFINE_int32( fsdbStatsStreamIntervalSeconds, - 60, + 5, "Interval at which stats subscriptions are served"); DECLARE_bool(intf_nbr_tables); @@ -174,6 +174,10 @@ DEFINE_bool( false, "Flag to turn on GR behavior for DSF publisher"); +DEFINE_bool(rx_sw_priority, false, "Enable rx packet prioritization"); + +DEFINE_int32(rx_pkt_thread_timeout, 100, "Rx packet thread timeout (ms)"); + namespace { /** @@ -277,6 +281,11 @@ void accumulateFb303GlobalStats( dramBlockedTime += toAdd.dram_blocked_time_ns().value(); accumulated.dram_blocked_time_ns() = dramBlockedTime; } + if (toAdd.vsq_resource_exhaustion_drops().has_value()) { + int64_t drops = accumulated.vsq_resource_exhaustion_drops().value_or(0); + drops += toAdd.vsq_resource_exhaustion_drops().value(); + accumulated.vsq_resource_exhaustion_drops() = drops; + } *accumulated.fabric_reachability_missing() += toAdd.fabric_reachability_missing().value(); *accumulated.fabric_reachability_mismatch() += @@ -1084,7 +1093,8 @@ std::shared_ptr SwSwitch::preInit(SwitchFlags flags) { flags_ = flags; bootType_ = swSwitchWarmbootHelper_->canWarmBoot() ? BootType::WARM_BOOT : BootType::COLD_BOOT; - XLOG(INFO) << "Boot Type: " << apache::thrift::util::enumNameSafe(bootType_); + XLOG(INFO) << kNetworkEventLogPrefix + << " Boot Type: " << apache::thrift::util::enumNameSafe(bootType_); multiHwSwitchHandler_->start(); std::optional wbState{}; @@ -2119,8 +2129,9 @@ void SwSwitch::linkActiveStateChanged( state->getSwitchSettings()->getNodeIf(matcher.matcherString()); auto newActualSwitchDrainState = computeActualSwitchDrainState(switchSettings, numActiveFabricPorts); - if (newActualSwitchDrainState != - switchSettings->getActualSwitchDrainState()) { + auto currentActualDrainState = switchSettings->getActualSwitchDrainState(); + + if (newActualSwitchDrainState != currentActualDrainState) { auto newSwitchSettings = switchSettings->modify(&newState); newSwitchSettings->setActualSwitchDrainState(newActualSwitchDrainState); } @@ -2173,6 +2184,47 @@ void SwSwitch::switchReachabilityChanged( stats()->switchReachabilityChangeProcessed(); } +void SwSwitch::packetRxThread() { + packetRxRunning_.store(true); + while (packetRxRunning_.load()) { + { + std::unique_lock lk(rxPktMutex_); + rxPktThreadCV_.wait_for( + lk, std::chrono::milliseconds(FLAGS_rx_pkt_thread_timeout), [this] { + return ( + rxPacketHandlerQueues_.hasPacketsToProcess() || + !packetRxRunning_.load()); + }); + } + if (!packetRxRunning_.load()) { + return; + } +#if FOLLY_HAS_COROUTINES + while (rxPacketHandlerQueues_.hasPacketsToProcess()) { + if (!packetRxRunning_.load()) { + return; + } + auto hiPriPkt = rxPacketHandlerQueues_.getHiPriRxPktQueue().try_dequeue(); + if (hiPriPkt) { + this->packetReceived(std::move(*hiPriPkt)); + continue; + } + auto midPriPkt = + rxPacketHandlerQueues_.getMidPriRxPktQueue().try_dequeue(); + if (midPriPkt) { + this->packetReceived(std::move(*midPriPkt)); + continue; + } + auto loPriPkt = rxPacketHandlerQueues_.getLoPriRxPktQueue().try_dequeue(); + if (loPriPkt) { + this->packetReceived(std::move(*loPriPkt)); + continue; + } + } +#endif + } +} + void SwSwitch::startThreads() { backgroundThread_.reset(new std::thread( [this] { this->threadLoop("fbossBgThread", &backgroundEventBase_); })); @@ -2190,6 +2242,11 @@ void SwSwitch::startThreads() { // start LACP thread, start before creating LinkAggregationManager lacpThread_.reset(new std::thread( [this] { this->threadLoop("fbossLacpThread", &lacpEventBase_); })); + if (FLAGS_rx_sw_priority) { + packetRxThread_.reset(new std::thread( + [this] { this->threadLoop("fbossPktRxThread", &packetRxEventBase_); })); + packetRxEventBase_.runInEventBaseThread([this] { this->packetRxThread(); }); + } } void SwSwitch::postInit() { @@ -2295,6 +2352,11 @@ void SwSwitch::stopThreads() { packetTxEventBase_.runInFbossEventBaseThread( [this] { packetTxEventBase_.terminateLoopSoon(); }); } + if (packetRxThread_) { + packetRxRunning_.store(false); + packetRxEventBase_.runInEventBaseThread( + [this] { packetRxEventBase_.terminateLoopSoon(); }); + } if (pcapDistributionThread_) { pcapDistributionEventBase_.runInFbossEventBaseThread( [this] { pcapDistributionEventBase_.terminateLoopSoon(); }); @@ -2316,6 +2378,9 @@ void SwSwitch::stopThreads() { if (packetTxThread_) { packetTxThread_->join(); } + if (packetRxThread_) { + packetRxThread_->join(); + } if (pcapDistributionThread_) { pcapDistributionThread_->join(); } @@ -2493,6 +2558,7 @@ void SwSwitch::sendPacketOutViaThriftStream( if (queue) { txPacket.queue() = queue.value(); } + txPacket.length() = pkt->buf()->computeChainDataLength(); txPacket.data() = Packet::extractIOBuf(std::move(pkt)); auto switchIndex = getSwitchInfoTable().getSwitchIndexFromSwitchId(SwitchID(switchId)); @@ -2513,7 +2579,7 @@ void SwSwitch::sendPacketSwitchedAsync(std::unique_ptr pkt) noexcept { // send failures--even on successful return from sendPacketSwitchedAsync() // the send may ultimately fail since it occurs asynchronously in the // background. - XLOG(ERR) << "failed to send L2 switched packet"; + XLOG(ERR) << "failed to send switched packet"; } } @@ -2861,17 +2927,21 @@ bool SwSwitch::isValidStateUpdate(const StateDelta& delta) const { [&](const shared_ptr& /* delport */) {}); // Ensure only one sflow mirror session is configured - int sflowMirrorCount = 0; - for (auto mniter : std::as_const(*(delta.newState()->getMirrors()))) { + std::set ingressMirrors; + for (auto mniter : std::as_const(*(delta.newState()->getPorts()))) { for (auto iter : std::as_const(*mniter.second)) { - auto mirror = iter.second; - if (mirror->type() == Mirror::Type::SFLOW) { - sflowMirrorCount++; + auto port = iter.second; + if (port && port->getIngressMirror().has_value()) { + auto ingressMirror = delta.newState()->getMirrors()->getNodeIf( + port->getIngressMirror().value()); + if (ingressMirror && ingressMirror->type() == Mirror::Type::SFLOW) { + ingressMirrors.insert(port->getIngressMirror().value()); + } } } } - if (sflowMirrorCount > 1) { - XLOG(ERR) << "More than one sflow mirrors configured"; + if (ingressMirrors.size() > 1) { + XLOG(ERR) << "Only one sflow mirror can be configured across all ports"; isValid = false; } @@ -3384,4 +3454,10 @@ void SwSwitch::updateAddrToLocalIntf(const StateDelta& delta) { }); } +void SwSwitch::rxPacketReceived(std::unique_ptr pkt) { + folly::coro::blockingWait( + rxPacketHandlerQueues_.enqueue(std::move(pkt), stats())); + rxPktThreadCV_.notify_one(); +} + } // namespace facebook::fboss diff --git a/fboss/agent/SwSwitch.h b/fboss/agent/SwSwitch.h index 11a6aebf591fa..268a3a4c573b3 100644 --- a/fboss/agent/SwSwitch.h +++ b/fboss/agent/SwSwitch.h @@ -16,8 +16,10 @@ #include "fboss/agent/MultiSwitchFb303Stats.h" #include "fboss/agent/PacketObserver.h" #include "fboss/agent/RestartTimeTracker.h" +#include "fboss/agent/SwRxPacket.h" #include "fboss/agent/SwSwitchRouteUpdateWrapper.h" #include "fboss/agent/SwitchInfoTable.h" +#include "fboss/agent/SwitchStats.h" #include "fboss/agent/Utils.h" #include "fboss/agent/gen-cpp2/agent_stats_types.h" #include "fboss/agent/gen-cpp2/switch_config_types.h" @@ -39,6 +41,10 @@ #include #include +#if FOLLY_HAS_COROUTINES +#include +#endif + #include #include #include @@ -46,6 +52,8 @@ #include #include +DECLARE_bool(rx_sw_priority); + namespace facebook::fboss { struct AgentConfig; @@ -99,6 +107,10 @@ class AgentDirectoryUtil; class HwSwitchThriftClientTable; class ResourceAccountant; +inline static const int kHiPriorityBufferSize{1000}; +inline static const int kMidPriorityBufferSize{1000}; +inline static const int kLowPriorityBufferSize{1000}; + namespace fsdb { enum class FsdbSubscriptionState; } @@ -966,6 +978,7 @@ class SwSwitch : public HwSwitchCallback { getSwitchReachability() const { return *hwSwitchReachability_.rlock(); } + void rxPacketReceived(std::unique_ptr pkt); private: std::optional getSourceMac( @@ -1085,11 +1098,56 @@ class SwSwitch : public HwSwitchCallback { void stopHwSwitchHandler(); + void packetRxThread(); + // TODO: To be removed once switchWatermarkStats is available in prod HwBufferPoolStats getBufferPoolStatsFromSwitchWatermarkStats(); void updateAddrToLocalIntf(const StateDelta& delta); +#if FOLLY_HAS_COROUTINES + using BoundedRxPktQueue = folly::coro::BoundedQueue< + std::unique_ptr, + false /*SingleProducer*/, + true /* SingleConsumer*/>; + class RxPacketHandlerQueues { + public: + folly::coro::Task enqueue( + std::unique_ptr pkt, + SwitchStats* stats) { + auto cosQueue = pkt->cosQueue(); + if (!cosQueue || CpuCosQueueId(*cosQueue) == CpuCosQueueId::HIPRI) { + co_await hiPriQueue_.enqueue(std::move(pkt)); + stats->hiPriPktsReceived(); + } else if (CpuCosQueueId(*cosQueue) == CpuCosQueueId::MIDPRI) { + midPriQueue_.try_enqueue(std::move(pkt)) ? stats->midPriPktsReceived() + : stats->midPriPktsDropped(); + } else { + loPriQueue_.try_enqueue(std::move(pkt)) ? stats->loPriPktsReceived() + : stats->loPriPktsDropped(); + } + co_return; + } + bool hasPacketsToProcess() { + return hiPriQueue_.size() || midPriQueue_.size() || loPriQueue_.size(); + } + BoundedRxPktQueue& getHiPriRxPktQueue() { + return hiPriQueue_; + } + BoundedRxPktQueue& getMidPriRxPktQueue() { + return midPriQueue_; + } + BoundedRxPktQueue& getLoPriRxPktQueue() { + return loPriQueue_; + } + + private: + BoundedRxPktQueue hiPriQueue_{kHiPriorityBufferSize}; + BoundedRxPktQueue midPriQueue_{kMidPriorityBufferSize}; + BoundedRxPktQueue loPriQueue_{kLowPriorityBufferSize}; + }; +#endif + std::optional sdkVersion_; std::unique_ptr multiHwSwitchHandler_; const AgentDirectoryUtil* agentDirUtil_; @@ -1170,6 +1228,13 @@ class SwSwitch : public HwSwitchCallback { FbossEventBase neighborCacheEventBase_; std::shared_ptr neighborCacheThreadHeartbeat_; + /* + * A thread for processing rx packets from thrift stream + */ + std::unique_ptr packetRxThread_; + folly::EventBase packetRxEventBase_; + std::shared_ptr packetRxThreadHeartbeat_; + /* * A thread dedicated to monitor above thread heartbeats */ @@ -1253,5 +1318,11 @@ class SwSwitch : public HwSwitchCallback { folly::Synchronized< std::map> hwSwitchReachability_; +#if FOLLY_HAS_COROUTINES + RxPacketHandlerQueues rxPacketHandlerQueues_; +#endif + std::atomic packetRxRunning_{false}; + std::condition_variable rxPktThreadCV_; + std::mutex rxPktMutex_; }; } // namespace facebook::fboss diff --git a/fboss/agent/SwitchStats.cpp b/fboss/agent/SwitchStats.cpp index 72c7692f1b051..01666e189f9e8 100644 --- a/fboss/agent/SwitchStats.cpp +++ b/fboss/agent/SwitchStats.cpp @@ -296,6 +296,27 @@ SwitchStats::SwitchStats(ThreadLocalStatsMap* map, int numSwitches) RATE), dsfGrExpired_(map, kCounterPrefix + "dsfsession_gr_expired", SUM, RATE), dsfUpdateFailed_(map, kCounterPrefix + "dsf_update_failed", SUM, RATE), + hiPriPktsReceived_( + map, + kCounterPrefix + "hi_pri_pkts_received", + SUM, + RATE), + midPriPktsReceived_( + map, + kCounterPrefix + "mid_pri_pkts_received", + SUM, + RATE), + loPriPktsReceived_( + map, + kCounterPrefix + "lo_pri_pkts_received", + SUM, + RATE), + midPriPktsDropped_( + map, + kCounterPrefix + "mid_pri_pkts_dropped", + SUM, + RATE), + loPriPktsDropped_(map, kCounterPrefix + "lo_pri_pkts_dropped", SUM, RATE), multiSwitchStatus_(map, kCounterPrefix + "multi_switch", SUM, RATE) { @@ -590,6 +611,16 @@ SwitchStats::HwAgentStreamConnectionStatus::HwAgentStreamConnectionStatus( ".", "switch_reachability_change_event_received"), SUM, + RATE)), + rxBadPktReceived_(TLTimeseries( + map, + folly::to( + kCounterPrefix, + "switch.", + switchIndex, + ".", + "rx_bad_pkt_received"), + SUM, RATE)) {} void SwitchStats::setFabricOverdrainPct( diff --git a/fboss/agent/SwitchStats.h b/fboss/agent/SwitchStats.h index 3826d25c29297..76e02133865b4 100644 --- a/fboss/agent/SwitchStats.h +++ b/fboss/agent/SwitchStats.h @@ -436,6 +436,26 @@ class SwitchStats : public boost::noncopyable { multiSwitchStatus_.addValue(enabled ? 1 : 0); } + void hiPriPktsReceived() { + hiPriPktsReceived_.addValue(1); + } + + void midPriPktsReceived() { + midPriPktsReceived_.addValue(1); + } + + void loPriPktsReceived() { + loPriPktsReceived_.addValue(1); + } + + void midPriPktsDropped() { + midPriPktsDropped_.addValue(1); + } + + void loPriPktsDropped() { + loPriPktsDropped_.addValue(1); + } + void switchConfiguredMs(uint64_t ms) { switchConfiguredMs_.addValue(ms); } @@ -529,6 +549,10 @@ class SwitchStats : public boost::noncopyable { thriftStreamConnectionStatus_[switchIndex].txPktEventSent(); } + void hwAgentRxBadPktReceived(int switchIndex) { + thriftStreamConnectionStatus_[switchIndex].rxBadPktReceived(); + } + void dsfSessionGrExpired() { dsfGrExpired_.addValue(1); } @@ -641,6 +665,9 @@ class SwitchStats : public boost::noncopyable { void switchReachabilityChangeEventReceived() { switchReachabilityChangeEventsReceived_.addValue(1); } + void rxBadPktReceived() { + rxBadPktReceived_.addValue(1); + } int64_t getStatsEventSinkDisconnectCount() const { return getCumulativeValue(statsEventSinkDisconnects_); } @@ -671,6 +698,9 @@ class SwitchStats : public boost::noncopyable { int64_t getRxPktEventReceivedCount() const { return getCumulativeValue(rxPktEventsReceived_); } + int64_t getrxBadPktReceivedCount() const { + return getCumulativeValue(rxBadPktReceived_); + } int64_t getTxPktEventSentCount() const { return getCumulativeValue(txPktEventsSent_); } @@ -699,6 +729,7 @@ class SwitchStats : public boost::noncopyable { TLTimeseries rxPktEventsReceived_; TLTimeseries txPktEventsSent_; TLTimeseries switchReachabilityChangeEventsReceived_; + TLTimeseries rxBadPktReceived_; }; const int numSwitches_; @@ -952,6 +983,11 @@ class SwitchStats : public boost::noncopyable { TLTimeseries switchConfiguredMs_; TLTimeseries dsfGrExpired_; TLTimeseries dsfUpdateFailed_; + TLTimeseries hiPriPktsReceived_; + TLTimeseries midPriPktsReceived_; + TLTimeseries loPriPktsReceived_; + TLTimeseries midPriPktsDropped_; + TLTimeseries loPriPktsDropped_; // TODO: delete this once multi_switch becomes default TLTimeseries multiSwitchStatus_; diff --git a/fboss/agent/ThriftHandler.cpp b/fboss/agent/ThriftHandler.cpp index 96ffbb20d9df6..274b82a4380e1 100644 --- a/fboss/agent/ThriftHandler.cpp +++ b/fboss/agent/ThriftHandler.cpp @@ -112,11 +112,6 @@ DEFINE_bool( false, // false => Prevents such mutations in prod "Allow mutations of running switch state by external thrift calls"); -DEFINE_bool( - skip_drain_check_for_prbs, - false, - "Skips drain check for local PRBS testing"); - DECLARE_bool(intf_nbr_tables); DECLARE_bool(enable_acl_table_group); @@ -380,6 +375,17 @@ void getPortInfoHelper( auto fec = hw.profileConfig()->iphy()->fec().value(); portInfo.fecEnabled() = fec != phy::FecMode::NONE; portInfo.fecMode() = apache::thrift::util::enumName(fec); + + // Fill expected LLDP info + auto lldpmap = port->getLLDPValidations(); + auto peerName = lldpmap.find(cfg::LLDPTag::SYSTEM_NAME); + if (peerName != lldpmap.end()) { + portInfo.expectedLLDPeerName() = peerName->second; + } + auto peerPort = lldpmap.find(cfg::LLDPTag::PORT); + if (peerPort != lldpmap.end()) { + portInfo.expectedLLDPPeerPort() = peerPort->second; + } } auto pause = port->getPause(); @@ -1587,18 +1593,6 @@ void ThriftHandler::setPortPrbs( throw FbossError("Polynomial not supported"); } auto switchId = sw_->getScopeResolver()->scope(portId).switchId(); - auto switchType = sw_->getHwAsicTable()->getHwAsic(switchId)->getSwitchType(); - // If ASIC is DNX and --skip-drain-check-for-prbs is disabled, check if - // interface or device is drained before setting interface PRBS. - if (switchType == cfg::SwitchType::VOQ || - switchType == cfg::SwitchType::FABRIC) { - auto isDrained = - (port->getPortDrainState() == cfg::PortDrainState::DRAINED) || - isSwitchDrained(); - if (!FLAGS_skip_drain_check_for_prbs && !isDrained) { - throw FbossError("Cannot set PRBS on undrained interface"); - } - } phy::PortPrbsState newPrbsState; *newPrbsState.enabled() = enable; *newPrbsState.polynominal() = polynominal; diff --git a/fboss/agent/Utils.cpp b/fboss/agent/Utils.cpp index 53f7532a35bc4..7776e2b33c2dc 100644 --- a/fboss/agent/Utils.cpp +++ b/fboss/agent/Utils.cpp @@ -12,8 +12,10 @@ #include #include +#include "fboss/agent/AsicUtils.h" #include "fboss/agent/FbossError.h" #include "fboss/agent/FsdbHelper.h" +#include "fboss/agent/SwitchIdScopeResolver.h" #include "fboss/agent/SysError.h" #include "fboss/agent/state/ArpEntry.h" #include "fboss/agent/state/ArpTable.h" @@ -26,6 +28,14 @@ #include "fboss/agent/gen-cpp2/switch_config_types.h" +#include "fboss/agent/platforms/common/janga800bic/Janga800bicPlatformMapping.h" +#include "fboss/agent/platforms/common/meru400bfu/Meru400bfuPlatformMapping.h" +#include "fboss/agent/platforms/common/meru400bia/Meru400biaPlatformMapping.h" +#include "fboss/agent/platforms/common/meru400biu/Meru400biuPlatformMapping.h" +#include "fboss/agent/platforms/common/meru800bfa/Meru800bfaP1PlatformMapping.h" +#include "fboss/agent/platforms/common/meru800bfa/Meru800bfaPlatformMapping.h" +#include "fboss/agent/platforms/common/meru800bia/Meru800biaPlatformMapping.h" + #include #include #include @@ -89,6 +99,46 @@ AddrT getIPAddress(InterfaceID intfID, const Interface::AddressesType addrs) { throw FbossError("Cannot find IP address for interface ", intfID); } +static const facebook::fboss::PlatformMapping* FOLLY_NULLABLE +getPlatformMappingForDsfNode(const facebook::fboss::PlatformType platformType) { + switch (platformType) { + case facebook::fboss::PlatformType::PLATFORM_MERU400BIU: { + static facebook::fboss::Meru400biuPlatformMapping meru400biu; + return &meru400biu; + } + case facebook::fboss::PlatformType::PLATFORM_MERU400BIA: { + static facebook::fboss::Meru400biaPlatformMapping meru400bia; + return &meru400bia; + } + case facebook::fboss::PlatformType::PLATFORM_MERU400BFU: { + static facebook::fboss::Meru400bfuPlatformMapping meru400bfu; + return &meru400bfu; + } + case facebook::fboss::PlatformType::PLATFORM_MERU800BFA: { + static facebook::fboss::Meru800bfaPlatformMapping meru800bfa{ + true /*multiNpuPlatformMapping*/}; + return &meru800bfa; + } + case facebook::fboss::PlatformType::PLATFORM_MERU800BFA_P1: { + static facebook::fboss::Meru800bfaP1PlatformMapping meru800bfa{ + true /*multiNpuPlatformMapping*/}; + return &meru800bfa; + } + case facebook::fboss::PlatformType::PLATFORM_MERU800BIA: { + static facebook::fboss::Meru800biaPlatformMapping meru800bia; + return &meru800bia; + } + case facebook::fboss::PlatformType::PLATFORM_JANGA800BIC: { + static facebook::fboss::Janga800bicPlatformMapping janga800bic{ + true /*multiNpuPlatformMapping*/}; + return &janga800bic; + } + default: + break; + } + return nullptr; +} + } // namespace void utilCreateDir(folly::StringPiece path) { try { @@ -879,4 +929,103 @@ InterfaceID getRecyclePortIntfID( return recyclePortId; } +std::pair getExpectedNeighborAndPortName( + const cfg::Port& port) { + CHECK_EQ(port.expectedNeighborReachability()->size(), 1); + const auto& expectedNeighbor = port.expectedNeighborReachability()->cbegin(); + std::string neighborName = *expectedNeighbor->remoteSystem(); + std::string neighborPortName = *expectedNeighbor->remotePort(); + return std::make_pair(neighborName, neighborPortName); +}; + +int getRemoteSwitchID( + const cfg::SwitchConfig* cfg, + const cfg::Port& port, + const std::unordered_map>& + switchNameToSwitchIds) { + auto [neighborName, neighborPortName] = getExpectedNeighborAndPortName(port); + CHECK(!switchNameToSwitchIds.at(neighborName).empty()); + auto baseSwitchId = *std::min_element( + switchNameToSwitchIds.at(neighborName).cbegin(), + switchNameToSwitchIds.at(neighborName).cend()); + auto dsfNodeItr = cfg->dsfNodes()->find(baseSwitchId); + CHECK(dsfNodeItr != cfg->dsfNodes()->end()); + + const auto platformMapping = + getPlatformMappingForDsfNode(*dsfNodeItr->second.platformType()); + + if (!platformMapping) { + throw FbossError( + "Unable to find platform mapping for port: ", + *port.logicalID(), + " expected neighbor"); + } + auto virtualDeviceId = platformMapping->getVirtualDeviceID(neighborPortName); + if (!virtualDeviceId.has_value()) { + throw FbossError( + "Unable to find virtual device id for port: ", + *port.logicalID(), + " expected neighbor"); + } + + const auto& hwAsic = getHwAsicForAsicType(*dsfNodeItr->second.asicType()); + auto numVirtualDevices = hwAsic.getVirtualDevices(); + auto remoteSwitchId = baseSwitchId + + (virtualDeviceId.value() / numVirtualDevices) * numVirtualDevices; + + return remoteSwitchId; +}; + +bool haveParallelLinksToInterfaceNodes( + const cfg::SwitchConfig* cfg, + const std::vector& localFabricSwitchIds, + const std::unordered_map>& + switchNameToSwitchIds, + SwitchIdScopeResolver& scopeResolver) { + for (const auto& fabricSwitchId : localFabricSwitchIds) { + // TODO(zecheng): Update to look at DsfNode layer config once available. + // Can be optimized to only look at FDSW layer + std::unordered_set voqNeighbors; + for (const auto& port : *cfg->ports()) { + // Only process ports belonging to the passed switchId + if (scopeResolver.scope(port).has(SwitchID(fabricSwitchId)) && + port.expectedNeighborReachability()->size() > 0) { + auto neighborRemoteSwitchId = + getRemoteSwitchID(cfg, port, switchNameToSwitchIds); + const auto& neighborDsfNodeIter = + cfg->dsfNodes()->find(neighborRemoteSwitchId); + CHECK(neighborDsfNodeIter != cfg->dsfNodes()->end()); + if (*neighborDsfNodeIter->second.type() == + cfg::DsfNodeType::INTERFACE_NODE) { + const auto& [neighborName, _] = getExpectedNeighborAndPortName(port); + if (voqNeighbors.find(neighborName) != voqNeighbors.end()) { + return true; + } + voqNeighbors.insert(neighborName); + } + } + } + } + return false; +}; + +CpuCosQueueId hwQueueIdToCpuCosQueueId(uint8_t hwQueueId) { + switch (hwQueueId) { + case 0: + return CpuCosQueueId::LOPRI; + case 1: + return CpuCosQueueId::DEFAULT; + case 2: + return CpuCosQueueId::MIDPRI; + /* On asics with 8 queues, cosQueue 7 is high priority + * bcm has 10 mcast cpu queues and use queue 9 as high priority queue + */ + case 7: + case 9: + return CpuCosQueueId::HIPRI; + default: + XLOG(FATAL) << "Got Invalid hwQueueId " << hwQueueId; + break; + } +} } // namespace facebook::fboss diff --git a/fboss/agent/Utils.h b/fboss/agent/Utils.h index d23429df4bf44..5e2ba3759469c 100644 --- a/fboss/agent/Utils.h +++ b/fboss/agent/Utils.h @@ -85,6 +85,7 @@ inline const int kUdfAclRethDmaLenFieldSizeInBytes(2); class SwitchState; class Interface; class SwitchSettings; +class SwitchIdScopeResolver; constexpr auto kRecyclePortIdOffset = 1; @@ -422,4 +423,21 @@ InterfaceID getRecyclePortIntfID( const std::shared_ptr& state, const SwitchID& switchId); +std::pair getExpectedNeighborAndPortName( + const cfg::Port& port); + +int getRemoteSwitchID( + const cfg::SwitchConfig* cfg, + const cfg::Port& port, + const std::unordered_map>& + switchNameToSwitchIds); + +bool haveParallelLinksToInterfaceNodes( + const cfg::SwitchConfig* cfg, + const std::vector& localFabricSwitchIds, + const std::unordered_map>& + switchNameToSwitchIds, + SwitchIdScopeResolver& scopeResolver); + +CpuCosQueueId hwQueueIdToCpuCosQueueId(uint8_t hwQueueId); } // namespace facebook::fboss diff --git a/fboss/agent/capture/PktCapture.h b/fboss/agent/capture/PktCapture.h index eec5949c5df67..72f1bb84ffce5 100644 --- a/fboss/agent/capture/PktCapture.h +++ b/fboss/agent/capture/PktCapture.h @@ -27,10 +27,11 @@ class RxPacketFilter { rxCaptureFilter.get_cosQueues().begin(), rxCaptureFilter.get_cosQueues().end()) {} bool passes(const RxPacket* pkt) const { + auto cosQueue = pkt->cosQueue() + ? static_cast(*pkt->cosQueue()) + : CpuCosQueueId::HIPRI; return ( - cosQueues_.empty() || - cosQueues_.find(static_cast(pkt->cosQueue())) != - cosQueues_.end()); + cosQueues_.empty() || cosQueues_.find(cosQueue) != cosQueues_.end()); } private: diff --git a/fboss/agent/hw/HwBasePortFb303Stats.h b/fboss/agent/hw/HwBasePortFb303Stats.h index d620b7062471a..ea39c4bee603f 100644 --- a/fboss/agent/hw/HwBasePortFb303Stats.h +++ b/fboss/agent/hw/HwBasePortFb303Stats.h @@ -121,6 +121,9 @@ class HwBasePortFb303Stats { void updateQueueWatermarkStats( const std::map& queueWatermarkBytes) const; + void updateEgressGvoqWatermarkStats( + const std::map& gvoqWatermarks) const; + bool macsecStatsInited() const { return macsecStatsInited_; } diff --git a/fboss/agent/hw/HwPortFb303Stats.cpp b/fboss/agent/hw/HwPortFb303Stats.cpp index 075672fc6486d..32ebcac1d65cc 100644 --- a/fboss/agent/hw/HwPortFb303Stats.cpp +++ b/fboss/agent/hw/HwPortFb303Stats.cpp @@ -46,6 +46,7 @@ HwPortFb303Stats::kPortMonotonicCounterStatKeys() const { kFecUncorrectable(), kLeakyBucketFlapCnt(), kInLabelMissDiscards(), + kInCongestionDiscards(), kInAclDiscards(), kInTrapDiscards(), kOutForwardingDiscards(), @@ -180,6 +181,10 @@ void HwPortFb303Stats::updateStats( timeRetrieved_, kInLabelMissDiscards(), *curPortStats.inLabelMissDiscards_()); + updateStat( + timeRetrieved_, + kInCongestionDiscards(), + *curPortStats.inCongestionDiscards_()); if (curPortStats.inAclDiscards_().has_value()) { updateStat( timeRetrieved_, kInAclDiscards(), *curPortStats.inAclDiscards_()); @@ -267,6 +272,9 @@ void HwPortFb303Stats::updateStats( } else if (curPortStats.queueWatermarkLevel_()->size()) { updateQueueWatermarkStats(*curPortStats.queueWatermarkLevel_()); } + if (curPortStats.egressGvoqWatermarkBytes_()->size()) { + updateEgressGvoqWatermarkStats(*curPortStats.egressGvoqWatermarkBytes_()); + } // Macsec stats if (curPortStats.macsecStats()) { if (!macsecStatsInited()) { diff --git a/fboss/agent/hw/HwSwitchFb303Stats.cpp b/fboss/agent/hw/HwSwitchFb303Stats.cpp index 5ae8d61a61bdb..eb25336642b71 100644 --- a/fboss/agent/hw/HwSwitchFb303Stats.cpp +++ b/fboss/agent/hw/HwSwitchFb303Stats.cpp @@ -499,6 +499,8 @@ HwSwitchFb303GlobalStats HwSwitchFb303Stats::getAllFb303Stats() const { hwFb303Stats.fdr_cell_drops() = *currentDropStats_.fdrCellDrops(); } hwFb303Stats.deleted_credit_bytes() = getDeletedCreditBytes(); + hwFb303Stats.vsq_resource_exhaustion_drops() = + getVsqResourcesExhautionDrops(); return hwFb303Stats; } @@ -521,6 +523,11 @@ void HwSwitchFb303Stats::updateStats(HwSwitchFb303GlobalStats& globalStats) { if (globalStats.dram_blocked_time_ns().has_value()) { updateValue(dramBlockedTimeNsec_, *globalStats.dram_blocked_time_ns()); } + if (globalStats.vsq_resource_exhaustion_drops().has_value()) { + updateValue( + vsqResourceExhaustionDrops_, + *globalStats.vsq_resource_exhaustion_drops()); + } updateValue( switchReachabilityChangeCount_, *globalStats.switch_reachability_change()); diff --git a/fboss/agent/hw/bcm/BcmEgress.cpp b/fboss/agent/hw/bcm/BcmEgress.cpp index 14a044fb1d1c7..6f89b560f938f 100644 --- a/fboss/agent/hw/bcm/BcmEgress.cpp +++ b/fboss/agent/hw/bcm/BcmEgress.cpp @@ -452,7 +452,8 @@ bool BcmEcmpEgress::isFlowletConfigUpdateNeeded() { const auto configDynamicMode = utility::getFlowletDynamicMode(bcmEcmpFlowletConfig.switchingMode); // if required and current modes match, no updated needed - if (obj.dynamic_mode != configDynamicMode) { + if (obj.dynamic_mode != configDynamicMode || + obj.dynamic_size != bcmEcmpFlowletConfig.flowletTableSize) { const auto neededDynamicSize = utility::getFlowletSizeWithScalingFactor( static_cast(hw_), bcmEcmpFlowletConfig.flowletTableSize, diff --git a/fboss/agent/hw/bcm/BcmFieldProcessorFBConvertors.cpp b/fboss/agent/hw/bcm/BcmFieldProcessorFBConvertors.cpp index 1acc07fca5890..b8903a558302b 100644 --- a/fboss/agent/hw/bcm/BcmFieldProcessorFBConvertors.cpp +++ b/fboss/agent/hw/bcm/BcmFieldProcessorFBConvertors.cpp @@ -141,6 +141,9 @@ bcm_field_IpType_t cfgIpTypeToBcmIpType(cfg::IpType cfgIpType) { return bcmFieldIpTypeIpv4Any; case cfg::IpType::IP6: return bcmFieldIpTypeIpv6; + case cfg::IpType::ARP_REQUEST: + case cfg::IpType::ARP_REPLY: + break; } // should return in one of the cases throw FbossError("Unsupported IP Type option"); diff --git a/fboss/agent/hw/bcm/BcmRxPacket.cpp b/fboss/agent/hw/bcm/BcmRxPacket.cpp index 20027bd78fddd..80556f28294f0 100644 --- a/fboss/agent/hw/bcm/BcmRxPacket.cpp +++ b/fboss/agent/hw/bcm/BcmRxPacket.cpp @@ -132,7 +132,7 @@ FbBcmRxPacket::FbBcmRxPacket( _reasons.usePktIO = usePktIO; if (!usePktIO) { bcm_pkt_t* pkt = bcmPacket.ptrUnion.pkt; - _cosQueue = pkt->cos; + cosQueue_ = pkt->cos; if (pkt->flags & BCM_PKT_F_TRUNK) { isFromAggregatePort_ = true; @@ -152,7 +152,7 @@ FbBcmRxPacket::FbBcmRxPacket( auto rv = bcm_pktio_pmd_field_get( unit_, pkt, bcmPktioPmdTypeRx, BCMPKT_RXPMD_CPU_COS, &val); bcmCheckError(rv, "failed to get pktio CPU_COS"); - _cosQueue = val; + cosQueue_ = val; if (auto optRet = bcmSwitch->getTrunkTable()->portToAggPortGet( PortID(getSrcPort()))) { @@ -176,7 +176,7 @@ FbBcmRxPacket::FbBcmRxPacket( std::string FbBcmRxPacket::describeDetails() const { return folly::sformat( "cos={} priority={} reasons={}", - _cosQueue, + cosQueue_ ? std::to_string(*cosQueue_) : "none", _priority, RxUtils::describeReasons(_reasons)); } diff --git a/fboss/agent/hw/bcm/BcmRxPacket.h b/fboss/agent/hw/bcm/BcmRxPacket.h index 13ce4a7b9318d..5e2bbde022ac4 100644 --- a/fboss/agent/hw/bcm/BcmRxPacket.h +++ b/fboss/agent/hw/bcm/BcmRxPacket.h @@ -61,9 +61,6 @@ class FbBcmRxPacket : public BcmRxPacket { const BcmSwitch* bcmSwitch); std::string describeDetails() const override; - int cosQueue() const override { - return _cosQueue; - } std::vector getReasons() override; private: @@ -71,7 +68,6 @@ class FbBcmRxPacket : public BcmRxPacket { FbBcmRxPacket(FbBcmRxPacket const&) = delete; FbBcmRxPacket& operator=(FbBcmRxPacket const&) = delete; - uint8_t _cosQueue{0}; uint8_t _priority{0}; BcmRxReasonsT _reasons; }; diff --git a/fboss/agent/hw/bcm/tests/BUCK b/fboss/agent/hw/bcm/tests/BUCK index 4f1a9a261a511..651141fe098d2 100644 --- a/fboss/agent/hw/bcm/tests/BUCK +++ b/fboss/agent/hw/bcm/tests/BUCK @@ -612,17 +612,18 @@ cpp_library( "HwTestNeighborUtilsThriftHandler.cpp", "HwTestPortUtilsThriftHandler.cpp", "HwTestThriftHandler.cpp", + "HwTestVoqSwitchUtilsThriftHandler.cpp", ], headers = [ ], exported_deps = [ - "//fboss/agent:hw_switch", - "//fboss/agent/hw/bcm:bcm", - "//fboss/agent/hw/bcm:bcmaddress_fb_convertors", - "//fboss/agent/hw/bcm/tests:bcm_ecmp_utils", - "//fboss/agent/hw/switch_asics:switch_asics", - "//fboss/agent/hw/test:hw_test_ecmp_utils", - "//fboss/agent/hw/test:hw_test_thrift_handler_h", - "//fboss/agent/test/utils:acl_test_utils", + "fbcode//fboss/agent:hw_switch", + "fbcode//fboss/agent/hw/bcm:bcm", + "fbcode//fboss/agent/hw/bcm:bcmaddress_fb_convertors", + "fbcode//fboss/agent/hw/bcm/tests:bcm_ecmp_utils", + "fbcode//fboss/agent/hw/switch_asics:switch_asics", + "fbcode//fboss/agent/hw/test:hw_test_ecmp_utils", + "fbcode//fboss/agent/hw/test:hw_test_thrift_handler_h", + "fbcode//fboss/agent/test/utils:acl_test_utils", ], ) diff --git a/fboss/agent/hw/bcm/tests/BcmFieldProcessorFBConvertorsTests.cpp b/fboss/agent/hw/bcm/tests/BcmFieldProcessorFBConvertorsTests.cpp index 32b0209f7e9a8..c06db66aa9776 100644 --- a/fboss/agent/hw/bcm/tests/BcmFieldProcessorFBConvertorsTests.cpp +++ b/fboss/agent/hw/bcm/tests/BcmFieldProcessorFBConvertorsTests.cpp @@ -45,7 +45,11 @@ TEST(FPBcmConvertors, cfgIpFragToFromBcm) { } TEST(FPBcmConvertors, ipTypeToFromBcm) { - for (auto cfgIpType : apache::thrift::TEnumTraits::values) { + for (auto cfgIpType : + {cfg::IpType::ANY, + cfg::IpType::IP, + cfg::IpType::IP4, + cfg::IpType::IP6}) { auto bcmIpType = cfgIpTypeToBcmIpType(cfgIpType); EXPECT_EQ(cfgIpType, bcmIpTypeToCfgIpType(bcmIpType)); } diff --git a/fboss/agent/hw/bcm/tests/HwTestVoqSwitchUtilsThriftHandler.cpp b/fboss/agent/hw/bcm/tests/HwTestVoqSwitchUtilsThriftHandler.cpp new file mode 100644 index 0000000000000..11383cdb7a328 --- /dev/null +++ b/fboss/agent/hw/bcm/tests/HwTestVoqSwitchUtilsThriftHandler.cpp @@ -0,0 +1,14 @@ +// (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary. + +#include "fboss/agent/hw/bcm/BcmSwitch.h" +#include "fboss/agent/hw/test/HwTestThriftHandler.h" + +namespace facebook { +namespace fboss { +namespace utility { +void HwTestThriftHandler::injectSwitchReachabilityChangeNotification() { + throw FbossError("Switch reachability change notification is not supported!"); +} +} // namespace utility +} // namespace fboss +} // namespace facebook diff --git a/fboss/agent/hw/benchmarks/BUCK b/fboss/agent/hw/benchmarks/BUCK index 6392c08b70f93..5694f6c71aef5 100644 --- a/fboss/agent/hw/benchmarks/BUCK +++ b/fboss/agent/hw/benchmarks/BUCK @@ -369,3 +369,12 @@ agent_benchmark_lib( "//fboss/agent/test:route_scale_gen", ], ) + +agent_benchmark_lib( + name = "hw_switch_reachability_change_speed", + srcs = ["HwSwitchReachabilityChangeBenchmark.cpp"], + extra_deps = [ + "//fboss/agent/hw/test:hw_switch_ensemble_factory", + "//fboss/agent/hw/test:hw_test_thrift_handler_h", + ], +) diff --git a/fboss/agent/hw/benchmarks/HwInitAndExitBenchmarkHelper.cpp b/fboss/agent/hw/benchmarks/HwInitAndExitBenchmarkHelper.cpp index 9496e16312880..fe78470f4c52a 100644 --- a/fboss/agent/hw/benchmarks/HwInitAndExitBenchmarkHelper.cpp +++ b/fboss/agent/hw/benchmarks/HwInitAndExitBenchmarkHelper.cpp @@ -12,6 +12,7 @@ #include #include #include "fboss/agent/ApplyThriftConfig.h" +#include "fboss/agent/DsfStateUpdaterUtil.h" #include "fboss/agent/Utils.h" #include "fboss/agent/hw/switch_asics/HwAsic.h" #include "fboss/agent/hw/test/ConfigFactory.h" @@ -255,16 +256,32 @@ void initandExitBenchmarkHelper( ensemble = createAgentEnsemble( voqInitialConfig, false /*disableLinkStateToggler*/); if (ensemble->getSw()->getBootType() == BootType::COLD_BOOT) { - ensemble->applyNewState([&](const std::shared_ptr& in) { - return utility::setupRemoteIntfAndSysPorts( - in, - ensemble->scopeResolver(), - ensemble->getSw()->getConfig(), - ensemble->getSw() - ->getHwAsicTable() - ->isFeatureSupportedOnAllAsic( - HwAsic::Feature::RESERVED_ENCAP_INDEX_RANGE)); - }); + auto updateDsfStateFn = + [&ensemble](const std::shared_ptr& in) { + std::map> + switchId2SystemPorts; + std::map> switchId2Rifs; + utility::populateRemoteIntfAndSysPorts( + switchId2SystemPorts, + switchId2Rifs, + ensemble->getSw()->getConfig(), + ensemble->getSw() + ->getHwAsicTable() + ->isFeatureSupportedOnAllAsic( + HwAsic::Feature::RESERVED_ENCAP_INDEX_RANGE)); + return DsfStateUpdaterUtil::getUpdatedState( + in, + ensemble->getSw()->getScopeResolver(), + ensemble->getSw()->getRib(), + switchId2SystemPorts, + switchId2Rifs); + }; + ensemble->getSw()->getRib()->updateStateInRibThread( + [&ensemble, updateDsfStateFn]() { + ensemble->getSw()->updateStateWithHwFailureProtection( + folly::sformat("Update state for node: {}", 0), + updateDsfStateFn); + }); } break; case cfg::SwitchType::NPU: diff --git a/fboss/agent/hw/benchmarks/HwRouteScaleBenchmarkHelpers.h b/fboss/agent/hw/benchmarks/HwRouteScaleBenchmarkHelpers.h index e073ef08f1fb2..e64d7a0d9bf08 100644 --- a/fboss/agent/hw/benchmarks/HwRouteScaleBenchmarkHelpers.h +++ b/fboss/agent/hw/benchmarks/HwRouteScaleBenchmarkHelpers.h @@ -9,6 +9,7 @@ */ #include "fboss/agent/AgentFeatures.h" +#include "fboss/agent/DsfStateUpdaterUtil.h" #include "fboss/agent/HwSwitch.h" #include "fboss/agent/benchmarks/AgentBenchmarks.h" #include "fboss/agent/hw/test/ConfigFactory.h" @@ -200,14 +201,27 @@ inline void voqRouteBenchmark(bool add) { createAgentEnsemble(voqInitialConfig, false /*disableLinkStateToggler*/); ScopedCallTimer timeIt; - ensemble->applyNewState([&](const std::shared_ptr& in) { - return utility::setupRemoteIntfAndSysPorts( - in, - ensemble->scopeResolver(), + auto updateDsfStateFn = [&ensemble](const std::shared_ptr& in) { + std::map> switchId2SystemPorts; + std::map> switchId2Rifs; + utility::populateRemoteIntfAndSysPorts( + switchId2SystemPorts, + switchId2Rifs, ensemble->getSw()->getConfig(), ensemble->getSw()->getHwAsicTable()->isFeatureSupportedOnAllAsic( HwAsic::Feature::RESERVED_ENCAP_INDEX_RANGE)); - }); + return DsfStateUpdaterUtil::getUpdatedState( + in, + ensemble->getSw()->getScopeResolver(), + ensemble->getSw()->getRib(), + switchId2SystemPorts, + switchId2Rifs); + }; + ensemble->getSw()->getRib()->updateStateInRibThread( + [&ensemble, updateDsfStateFn]() { + ensemble->getSw()->updateStateWithHwFailureProtection( + folly::sformat("Update state for node: {}", 0), updateDsfStateFn); + }); // Trigger config apply to add remote interface routes as directly connected // in RIB. This is to resolve ECMP members pointing to remote nexthops. diff --git a/fboss/agent/hw/benchmarks/HwStatsCollectionBenchmark.cpp b/fboss/agent/hw/benchmarks/HwStatsCollectionBenchmark.cpp index 057ef7eaf196a..52d58fc028dd8 100644 --- a/fboss/agent/hw/benchmarks/HwStatsCollectionBenchmark.cpp +++ b/fboss/agent/hw/benchmarks/HwStatsCollectionBenchmark.cpp @@ -11,6 +11,7 @@ #include "fboss/agent/AgentFeatures.h" #include "fboss/agent/HwSwitch.h" +#include "fboss/agent/DsfStateUpdaterUtil.h" #include "fboss/agent/SwAgentInitializer.h" #include "fboss/agent/hw/test/ConfigFactory.h" #include "fboss/agent/hw/test/HwSwitchEnsemble.h" @@ -104,14 +105,28 @@ BENCHMARK(HwStatsCollection) { // Setup Remote Intf and System Ports if (ensemble->getSw()->getSwitchInfoTable().haveVoqSwitches()) { - ensemble->applyNewState([&](const std::shared_ptr& in) { - return utility::setupRemoteIntfAndSysPorts( - in, - ensemble->scopeResolver(), + auto updateDsfStateFn = [&ensemble]( + const std::shared_ptr& in) { + std::map> switchId2SystemPorts; + std::map> switchId2Rifs; + utility::populateRemoteIntfAndSysPorts( + switchId2SystemPorts, + switchId2Rifs, ensemble->getSw()->getConfig(), ensemble->getSw()->getHwAsicTable()->isFeatureSupportedOnAllAsic( HwAsic::Feature::RESERVED_ENCAP_INDEX_RANGE)); - }); + return DsfStateUpdaterUtil::getUpdatedState( + in, + ensemble->getSw()->getScopeResolver(), + ensemble->getSw()->getRib(), + switchId2SystemPorts, + switchId2Rifs); + }; + ensemble->getSw()->getRib()->updateStateInRibThread( + [&ensemble, updateDsfStateFn]() { + ensemble->getSw()->updateStateWithHwFailureProtection( + folly::sformat("Update state for node: {}", 0), updateDsfStateFn); + }); // For VOQ switches we have 2K - 4K remote system ports (each with 4-8 // VOQs). This is >10x of local ports on NPU platforms. Therefore, only run // 100 iterations. diff --git a/fboss/agent/hw/benchmarks/HwSwitchReachabilityChangeBenchmark.cpp b/fboss/agent/hw/benchmarks/HwSwitchReachabilityChangeBenchmark.cpp new file mode 100644 index 0000000000000..b4b9ef899fa43 --- /dev/null +++ b/fboss/agent/hw/benchmarks/HwSwitchReachabilityChangeBenchmark.cpp @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2004-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + */ + +#include +#include +#include "fboss/agent/AgentFeatures.h" +#include "fboss/agent/DsfStateUpdaterUtil.h" +#include "fboss/agent/Platform.h" +#include "fboss/agent/SwitchStats.h" +#include "fboss/agent/benchmarks/AgentBenchmarks.h" +#include "fboss/agent/hw/test/ConfigFactory.h" +#include "fboss/agent/hw/test/HwSwitchEnsemble.h" +#include "fboss/agent/hw/test/HwTestThriftHandler.h" +#include "fboss/agent/test/utils/FabricTestUtils.h" +#include "fboss/agent/test/utils/VoqTestUtils.h" +#include "fboss/lib/CommonUtils.h" + +DECLARE_int32(max_unprocessed_switch_reachability_changes); + +namespace facebook::fboss { +BENCHMARK(HwSwitchReachabilityChange) { + folly::BenchmarkSuspender suspender; + constexpr int kNumberOfSwitchReachabilityChangeEvents{1000}; + AgentEnsembleSwitchConfigFn initialConfig = + [](const AgentEnsemble& ensemble) { + // Disable DSF subscription on single-box test + FLAGS_dsf_subscribe = false; + // Enable fabric ports + FLAGS_hide_fabric_ports = false; + // Don't disable looped fabric ports + FLAGS_disable_looped_fabric_ports = false; + // Allow more than 1 events to be enqueued + FLAGS_max_unprocessed_switch_reachability_changes = + kNumberOfSwitchReachabilityChangeEvents; + + auto config = utility::onePortPerInterfaceConfig( + ensemble.getSw(), + ensemble.masterLogicalPortIds(), + true, /*interfaceHasSubnet*/ + true, /*setInterfaceMac*/ + utility::kBaseVlanId, + true /*enable fabric ports*/); + utility::populatePortExpectedNeighbors( + ensemble.masterLogicalPortIds(), config); + config.dsfNodes() = *utility::addRemoteDsfNodeCfg(*config.dsfNodes()); + return config; + }; + auto ensemble = + createAgentEnsemble(initialConfig, false /*disableLinkStateToggler*/); + auto updateDsfStateFn = [&ensemble](const std::shared_ptr& in) { + std::map> switchId2SystemPorts; + std::map> switchId2Rifs; + utility::populateRemoteIntfAndSysPorts( + switchId2SystemPorts, + switchId2Rifs, + ensemble->getSw()->getConfig(), + ensemble->getSw()->getHwAsicTable()->isFeatureSupportedOnAllAsic( + HwAsic::Feature::RESERVED_ENCAP_INDEX_RANGE)); + return DsfStateUpdaterUtil::getUpdatedState( + in, + ensemble->getSw()->getScopeResolver(), + ensemble->getSw()->getRib(), + switchId2SystemPorts, + switchId2Rifs); + }; + ensemble->getSw()->getRib()->updateStateInRibThread( + [&ensemble, updateDsfStateFn]() { + ensemble->getSw()->updateStateWithHwFailureProtection( + folly::sformat("Update state for node: {}", 0), updateDsfStateFn); + }); + + XLOG(DBG0) << "Wait for all fabric ports to be ACTIVE"; + // Wait for all fabric ports to be ACTIVE + WITH_RETRIES_N_TIMED(240, std::chrono::milliseconds(1000), { + for (const PortID& portId : ensemble->masterLogicalFabricPortIds()) { + auto fabricPort = + ensemble->getProgrammedState()->getPorts()->getNodeIf(portId); + EXPECT_EVENTUALLY_TRUE(fabricPort->isActive().has_value()); + EXPECT_EVENTUALLY_TRUE(*fabricPort->isActive()); + } + }); + + XLOG(DBG0) << "Inject and wait for " + << kNumberOfSwitchReachabilityChangeEvents + << " switch reachability events to be processed!"; + auto reachabilityProcessedCountAtStart = + ensemble->getSw()->stats()->getSwitchReachabilityChangeProcessed(); + int eventsInjected{0}; + suspender.dismiss(); + auto client = ensemble->getHwAgentTestClient(SwitchID(0)); + while (eventsInjected++ < kNumberOfSwitchReachabilityChangeEvents) { + // Inject switch reachability change event + client->sync_injectSwitchReachabilityChangeNotification(); + } + while (ensemble->getSw()->stats()->getSwitchReachabilityChangeProcessed() != + (reachabilityProcessedCountAtStart + + kNumberOfSwitchReachabilityChangeEvents)) { + // NOOP + } + suspender.rehire(); +} +} // namespace facebook::fboss diff --git a/fboss/agent/hw/hardware_stats.thrift b/fboss/agent/hw/hardware_stats.thrift index 168bcdbb13ba2..6631b4c895160 100644 --- a/fboss/agent/hw/hardware_stats.thrift +++ b/fboss/agent/hw/hardware_stats.thrift @@ -347,6 +347,7 @@ struct HwSwitchFb303GlobalStats { 26: optional i64 inter_port_group_cable_skew_meters; 27: optional i64 dram_blocked_time_ns; 28: optional i64 deleted_credit_bytes; + 29: optional i64 vsq_resource_exhaustion_drops; } struct HwFlowletStats { diff --git a/fboss/agent/hw/oss/HwBasePortFb303Stats.cpp b/fboss/agent/hw/oss/HwBasePortFb303Stats.cpp index 1e7847ab2e6d7..a7d613f929d2f 100644 --- a/fboss/agent/hw/oss/HwBasePortFb303Stats.cpp +++ b/fboss/agent/hw/oss/HwBasePortFb303Stats.cpp @@ -15,4 +15,6 @@ namespace facebook::fboss { void HwBasePortFb303Stats::updateQueueWatermarkStats( const std::map& /*queueWatermarks*/) const {} +void HwBasePortFb303Stats::updateEgressGvoqWatermarkStats( + const std::map& /*gvoqWatermarks*/) const {} } // namespace facebook::fboss diff --git a/fboss/agent/hw/sai/api/bcm/QueueApi.cpp b/fboss/agent/hw/sai/api/bcm/QueueApi.cpp index 8b927b8cb41a7..e12e172a022e4 100644 --- a/fboss/agent/hw/sai/api/bcm/QueueApi.cpp +++ b/fboss/agent/hw/sai/api/bcm/QueueApi.cpp @@ -4,9 +4,14 @@ #if defined(BRCM_SAI_SDK_DNX) && defined(BRCM_SAI_SDK_GTE_11_0) extern "C" { -#include -#include + +#ifndef IS_OSS_BRCM_SAI +#include +#else +#include +#endif } + #endif namespace facebook::fboss { @@ -14,7 +19,7 @@ namespace facebook::fboss { const std::vector& SaiQueueTraits::egressGvoqWatermarkBytes() { #if defined(BRCM_SAI_SDK_DNX) && defined(BRCM_SAI_SDK_GTE_11_0) static const std::vector stats{ - SAI_QUEUE_STAT_EGRESS_GVOQ_THRESHOLD_WM}; + SAI_QUEUE_STAT_EGRESS_GVOQ_THRESHOLD_WM_BYTES}; #else static const std::vector stats; #endif diff --git a/fboss/agent/hw/sai/benchmarks/BUCK b/fboss/agent/hw/sai/benchmarks/BUCK index 1e12397c5a23f..499c863a7a7ec 100644 --- a/fboss/agent/hw/sai/benchmarks/BUCK +++ b/fboss/agent/hw/sai/benchmarks/BUCK @@ -31,6 +31,7 @@ sai_mono_agent_benchmark( "//fboss/agent/hw/benchmarks:hw_rib_sync_fib_speed", "//fboss/agent/hw/benchmarks:hw_rx_slow_path_rate", "//fboss/agent/hw/benchmarks:hw_stats_collection_speed", + "//fboss/agent/hw/benchmarks:hw_switch_reachability_change_speed", "//fboss/agent/hw/benchmarks:hw_th_alpm_scale_route_add_speed", "//fboss/agent/hw/benchmarks:hw_th_alpm_scale_route_del_speed", "//fboss/agent/hw/benchmarks:hw_tx_slow_path_rate", diff --git a/fboss/agent/hw/sai/hw_test/HwTestMirrorUtilsThriftHandler.cpp b/fboss/agent/hw/sai/hw_test/HwTestMirrorUtilsThriftHandler.cpp index 1e1f610cf76c5..77d7c8f33ddbc 100644 --- a/fboss/agent/hw/sai/hw_test/HwTestMirrorUtilsThriftHandler.cpp +++ b/fboss/agent/hw/sai/hw_test/HwTestMirrorUtilsThriftHandler.cpp @@ -194,28 +194,37 @@ bool HwTestThriftHandler::isPortMirrored( auto saiSwitch = static_cast(hwSwitch_); auto portHandle = saiSwitch->managerTable()->portManager().getPortHandle(PortID(port)); - std::vector mirrorSaiOidList; + std::optional ingressMirror; + std::optional egressMirror; + std::optional mirrorSaiOid{}; if (ingress) { - mirrorSaiOidList = SaiApiTable::getInstance()->portApi().getAttribute( - portHandle->port->adapterKey(), - SaiPortTraits::Attributes::IngressSampleMirrorSession()); + ingressMirror = SaiApiTable::getInstance()->portApi().getAttribute( + portHandle->port->adapterKey(), ingressMirror); } else { - mirrorSaiOidList = SaiApiTable::getInstance()->portApi().getAttribute( - portHandle->port->adapterKey(), - SaiPortTraits::Attributes::EgressSampleMirrorSession()); + egressMirror = SaiApiTable::getInstance()->portApi().getAttribute( + portHandle->port->adapterKey(), egressMirror); } - if (mirrorSaiOidList.size() == 0) { + if (!ingressMirror && !egressMirror) { + XLOG(DBG2) << "Port " << port << " is not mirrored"; + return false; + } else if (ingressMirror) { + mirrorSaiOid = ingressMirror.value().value()[0]; + } else if (egressMirror) { + mirrorSaiOid = egressMirror.value().value()[0]; + } + if (!mirrorSaiOid) { return false; } auto mirrorHandle = saiSwitch->managerTable()->mirrorManager().getMirrorHandle(*mirror); if (!mirrorHandle) { + XLOG(DBG2) << "Mirror " << *mirror << " not found"; return false; } - return mirrorHandle->adapterKey() == mirrorSaiOidList[0]; + return mirrorHandle->adapterKey() == mirrorSaiOid.value(); } bool HwTestThriftHandler::isPortSampled( diff --git a/fboss/agent/hw/sai/hw_test/HwTestVoqSwitchUtilsThriftHandler.cpp b/fboss/agent/hw/sai/hw_test/HwTestVoqSwitchUtilsThriftHandler.cpp new file mode 100644 index 0000000000000..978ce3e9a64e4 --- /dev/null +++ b/fboss/agent/hw/sai/hw_test/HwTestVoqSwitchUtilsThriftHandler.cpp @@ -0,0 +1,15 @@ +// (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary. + +#include "fboss/agent/hw/sai/switch/SaiSwitch.h" +#include "fboss/agent/hw/test/HwTestThriftHandler.h" + +namespace facebook { +namespace fboss { +namespace utility { +void HwTestThriftHandler::injectSwitchReachabilityChangeNotification() { + auto saiSwitch = static_cast(hwSwitch_); + saiSwitch->injectSwitchReachabilityChangeNotification(); +} +} // namespace utility +} // namespace fboss +} // namespace facebook diff --git a/fboss/agent/hw/sai/hw_test/SaiRollbackTest.h b/fboss/agent/hw/sai/hw_test/SaiRollbackTest.h index 62a3a58ecd9bd..1c92357a4f2d9 100644 --- a/fboss/agent/hw/sai/hw_test/SaiRollbackTest.h +++ b/fboss/agent/hw/sai/hw_test/SaiRollbackTest.h @@ -28,6 +28,10 @@ class SaiRollbackTest : public HwLinkStateDependentTest { } void rollback(const StateDelta& delta); + bool hideFabricPorts() const override { + return false; + } + private: std::unique_ptr prodInvariants_; }; diff --git a/fboss/agent/hw/sai/hw_test/hw_test.bzl b/fboss/agent/hw/sai/hw_test/hw_test.bzl index 21949a6afc914..4e4751e2e65d5 100644 --- a/fboss/agent/hw/sai/hw_test/hw_test.bzl +++ b/fboss/agent/hw/sai/hw_test/hw_test.bzl @@ -437,6 +437,7 @@ def _test_thrift_handler(sai_impl, is_npu): "HwTestNeighborUtilsThriftHandler.cpp", "HwTestEcmpUtilsThriftHandler.cpp", "HwTestPortUtilsThriftHandler.cpp", + "HwTestVoqSwitchUtilsThriftHandler.cpp", "HwTestThriftHandler.cpp", ], auto_headers = AutoHeaders.SOURCES, diff --git a/fboss/agent/hw/sai/store/SaiStore.h b/fboss/agent/hw/sai/store/SaiStore.h index 4cf181c5ffe84..7e43c5b49bd2a 100644 --- a/fboss/agent/hw/sai/store/SaiStore.h +++ b/fboss/agent/hw/sai/store/SaiStore.h @@ -365,22 +365,18 @@ class SaiObjectStore { return objects_.end(); } - size_t warmBootHandlesCount() const { - // ignore handles owned by adapter - return std::count_if( - std::begin(warmBootHandles_), - std::end(warmBootHandles_), - [](const auto& handle) { return !handle.second->isOwnedByAdapter(); }); - } - - bool hasUnexpectedUnclaimedWarmbootHandles() const { - bool unclaimedHandles = warmBootHandlesCount() > 0 && - !IsSaiObjectOwnedByAdapter::value; + bool hasUnexpectedUnclaimedWarmbootHandles( + bool includeAdapterOwned = false) const { + auto handlesCount = warmBootHandlesCount(includeAdapterOwned); + bool unclaimedHandles = handlesCount > 0 && + (includeAdapterOwned || + !IsSaiObjectOwnedByAdapter::value); XLOGF( DBG1, - "unexpected warmboot handles {} entries: {}", + "unexpected warmboot handles {} entries: {}, includeAdapterOwned: {}", objectTypeName(), - unclaimedHandles); + unclaimedHandles, + includeAdapterOwned); return unclaimedHandles; } @@ -394,8 +390,9 @@ class SaiObjectStore { } void removeUnclaimedWarmbootHandlesIf( - std::function&)> condition) { - if (!hasUnexpectedUnclaimedWarmbootHandles()) { + std::function&)> condition, + bool includeAdapterOwned = false) { + if (!hasUnexpectedUnclaimedWarmbootHandles(includeAdapterOwned)) { return; } auto iter = std::begin(warmBootHandles_); @@ -408,12 +405,23 @@ class SaiObjectStore { } } - void removeUnexpectedUnclaimedWarmbootHandles() { + void removeUnexpectedUnclaimedWarmbootHandles( + bool includeAdapterOwned = false) { // delete all unclaimed handles - removeUnclaimedWarmbootHandlesIf([](const auto&) { return true; }); + removeUnclaimedWarmbootHandlesIf( + [](const auto&) { return true; }, includeAdapterOwned); } private: + size_t warmBootHandlesCount(bool includeAdapterOwned = false) const { + return std::count_if( + std::begin(warmBootHandles_), + std::end(warmBootHandles_), + [includeAdapterOwned](const auto& handle) { + return includeAdapterOwned || !handle.second->isOwnedByAdapter(); + }); + } + ObjectType getObject( typename ObjectTraits::AdapterKey key, const folly::dynamic* adapterKey2AdapterHostKey) { diff --git a/fboss/agent/hw/sai/switch/SaiAclTableManager.cpp b/fboss/agent/hw/sai/switch/SaiAclTableManager.cpp index 4990a5b4c8d09..124c63fc9aa95 100644 --- a/fboss/agent/hw/sai/switch/SaiAclTableManager.cpp +++ b/fboss/agent/hw/sai/switch/SaiAclTableManager.cpp @@ -275,6 +275,10 @@ sai_acl_ip_type_t SaiAclTableManager::cfgIpTypeToSaiIpType( return SAI_ACL_IP_TYPE_IPV4ANY; case cfg::IpType::IP6: return SAI_ACL_IP_TYPE_IPV6ANY; + case cfg::IpType::ARP_REQUEST: + return SAI_ACL_IP_TYPE_ARP_REQUEST; + case cfg::IpType::ARP_REPLY: + return SAI_ACL_IP_TYPE_ARP_REPLY; } // should return in one of the cases throw FbossError("Unsupported IP Type option"); @@ -289,6 +293,7 @@ uint16_t SaiAclTableManager::cfgEtherTypeToSaiEtherType( case cfg::EtherType::EAPOL: case cfg::EtherType::MACSEC: case cfg::EtherType::LLDP: + case cfg::EtherType::ARP: return static_cast(cfgEtherType); } // should return in one of the cases diff --git a/fboss/agent/hw/sai/switch/SaiBridgeManager.cpp b/fboss/agent/hw/sai/switch/SaiBridgeManager.cpp index 262d6b61efec3..07c98985df08b 100644 --- a/fboss/agent/hw/sai/switch/SaiBridgeManager.cpp +++ b/fboss/agent/hw/sai/switch/SaiBridgeManager.cpp @@ -24,6 +24,16 @@ std::shared_ptr SaiBridgeManager::addBridgePort( SaiPortDescriptor portDescriptor, PortDescriptorSaiId saiId) { // Lazily re-load or create the default bridge if it is missing + createBridgeHandle(); + auto& store = saiStore_->get(); + auto saiObjectId = saiId.intID(); + SaiBridgePortTraits::AdapterHostKey k{saiObjectId}; + SaiBridgePortTraits::CreateAttributes attributes{ + SAI_BRIDGE_PORT_TYPE_PORT, saiObjectId, true, fdbLearningMode_}; + return store.setObject(k, attributes, portDescriptor); +} + +void SaiBridgeManager::createBridgeHandle() { if (UNLIKELY(!bridgeHandle_)) { auto& store = saiStore_->get(); bridgeHandle_ = std::make_unique(); @@ -35,14 +45,7 @@ std::shared_ptr SaiBridgeManager::addBridgePort( SaiBridgeTraits::AdapterKey{default1QBridgeId}); CHECK(bridgeHandle_->bridge); } - auto& store = saiStore_->get(); - auto saiObjectId = saiId.intID(); - SaiBridgePortTraits::AdapterHostKey k{saiObjectId}; - SaiBridgePortTraits::CreateAttributes attributes{ - SAI_BRIDGE_PORT_TYPE_PORT, saiObjectId, true, fdbLearningMode_}; - return store.setObject(k, attributes, portDescriptor); } - SaiBridgeManager::SaiBridgeManager( SaiStore* saiStore, SaiManagerTable* managerTable, diff --git a/fboss/agent/hw/sai/switch/SaiBridgeManager.h b/fboss/agent/hw/sai/switch/SaiBridgeManager.h index a431cf47ac518..b2a64c0fc2fe7 100644 --- a/fboss/agent/hw/sai/switch/SaiBridgeManager.h +++ b/fboss/agent/hw/sai/switch/SaiBridgeManager.h @@ -46,6 +46,7 @@ class SaiBridgeManager { void setL2LearningMode(std::optional l2LearningMode); cfg::L2LearningMode getL2LearningMode() const; + void createBridgeHandle(); private: SaiStore* saiStore_; diff --git a/fboss/agent/hw/sai/switch/SaiFdbManager.cpp b/fboss/agent/hw/sai/switch/SaiFdbManager.cpp index 84b29ce6dc55c..1b972d276c286 100644 --- a/fboss/agent/hw/sai/switch/SaiFdbManager.cpp +++ b/fboss/agent/hw/sai/switch/SaiFdbManager.cpp @@ -111,7 +111,7 @@ SaiFdbTraits::FdbEntry ManagedFdbEntry::makeFdbEntry( } void ManagedFdbEntry::handleLinkDown() { - XLOG(DBG2) << "fdb entry (" << getInterfaceID() << ", " << getMac().toString() + XLOG(DBG2) << "fdb entry (" << toString() << ") notifying link down to subscribed neighbors"; SaiObjectEventPublisher::getInstance()->get().notifyLinkDown( intfIDAndMac_); diff --git a/fboss/agent/hw/sai/switch/SaiPortManager.cpp b/fboss/agent/hw/sai/switch/SaiPortManager.cpp index ea7fe469f92df..e112eb8d467f4 100644 --- a/fboss/agent/hw/sai/switch/SaiPortManager.cpp +++ b/fboss/agent/hw/sai/switch/SaiPortManager.cpp @@ -1006,7 +1006,12 @@ PortSaiId SaiPortManager::addPort(const std::shared_ptr& swPort) { // In future, if we need to support multiple global recycle ports, we would // need to invent some way to determiine which of the recycle ports // corresponds to the CPU port. - CHECK(!managerTable_->switchManager().getCpuRecyclePort().has_value()); + // Assert that the recycle port we are setting is either the same or unset + // from before. During rollback, we do set recycle port again, but it should + // have the same value + CHECK_EQ( + managerTable_->switchManager().getCpuRecyclePort().value_or(portSaiId), + portSaiId); managerTable_->switchManager().setCpuRecyclePort(portSaiId); } diff --git a/fboss/agent/hw/sai/switch/SaiRxPacket.cpp b/fboss/agent/hw/sai/switch/SaiRxPacket.cpp index ba3cd62693738..2a0cbb20e9005 100644 --- a/fboss/agent/hw/sai/switch/SaiRxPacket.cpp +++ b/fboss/agent/hw/sai/switch/SaiRxPacket.cpp @@ -34,7 +34,7 @@ SaiRxPacket::SaiRxPacket( srcPort_ = portId; srcVlan_ = vlanId; rxReason_ = rxReason; - _cosQueue = queueId; + cosQueue_ = queueId; } SaiRxPacket::SaiRxPacket( @@ -51,7 +51,7 @@ SaiRxPacket::SaiRxPacket( srcVlan_ = vlanId; isFromAggregatePort_ = true; rxReason_ = rxReason; - _cosQueue = queueId; + cosQueue_ = queueId; } std::string SaiRxPacket::describeDetails() const { diff --git a/fboss/agent/hw/sai/switch/SaiRxPacket.h b/fboss/agent/hw/sai/switch/SaiRxPacket.h index 37f88780137d4..a85a71e944202 100644 --- a/fboss/agent/hw/sai/switch/SaiRxPacket.h +++ b/fboss/agent/hw/sai/switch/SaiRxPacket.h @@ -54,14 +54,9 @@ class SaiRxPacket : public RxPacket { srcAggregatePort_ = srcAggregatePort; } - int cosQueue() const override { - return _cosQueue; - } - std::string describeDetails() const override; private: cfg::PacketRxReason rxReason_; - uint8_t _cosQueue{0}; }; } // namespace facebook::fboss diff --git a/fboss/agent/hw/sai/switch/SaiSwitch.cpp b/fboss/agent/hw/sai/switch/SaiSwitch.cpp index 2f7a90524e6ec..6fae3fd223f85 100644 --- a/fboss/agent/hw/sai/switch/SaiSwitch.cpp +++ b/fboss/agent/hw/sai/switch/SaiSwitch.cpp @@ -1279,10 +1279,10 @@ void SaiSwitch::processSwitchSettingsChangedEntryLocked( } { - const auto oldVal = oldSwitchSettings->getReachabilityGroupSize(); - const auto newVal = newSwitchSettings->getReachabilityGroupSize(); + const auto oldVal = oldSwitchSettings->getReachabilityGroupListSize(); + const auto newVal = newSwitchSettings->getReachabilityGroupListSize(); if (oldVal != newVal) { - managerTable_->switchManager().setReachabilityGroupSize( + managerTable_->switchManager().setReachabilityGroupList( newVal.has_value() ? newVal.value() : 0); } } @@ -2456,12 +2456,7 @@ void SaiSwitch::initStoreAndManagersLocked( // init and not need to be removed during warm boot. Change ownership for // them explicitly to adapter to remove it from unclaimed object if (getSwitchType() == cfg::SwitchType::VOQ) { - auto& systemPortStore = saiStore_->get(); - for (auto& sysPort : platform_->getInternalSystemPortConfig()) { - SaiSystemPortTraits::Attributes::ConfigInfo confInfo{sysPort}; - const auto& obj = systemPortStore.get(confInfo); - systemPortStore.loadObjectOwnedByAdapter(obj->adapterKey(), true); - } + managerTable_->bridgeManager().createBridgeHandle(); } } } // namespace facebook::fboss diff --git a/fboss/agent/hw/sai/switch/SaiSwitchManager.cpp b/fboss/agent/hw/sai/switch/SaiSwitchManager.cpp index c495639ce5f9a..30721221137a7 100644 --- a/fboss/agent/hw/sai/switch/SaiSwitchManager.cpp +++ b/fboss/agent/hw/sai/switch/SaiSwitchManager.cpp @@ -995,11 +995,11 @@ void SaiSwitchManager::setLocalCapsuleSwitchIds( SaiSwitchTraits::Attributes::MultiStageLocalSwitchIds{values}); } -void SaiSwitchManager::setReachabilityGroupSize(int reachabilityGroupSize) { +void SaiSwitchManager::setReachabilityGroupList(int reachabilityGroupListSize) { #if defined(BRCM_SAI_SDK_DNX_GTE_12_0) - if (reachabilityGroupSize > 0) { + if (reachabilityGroupListSize > 0) { std::vector list; - for (int i = 0; i < reachabilityGroupSize; i++) { + for (int i = 0; i < reachabilityGroupListSize; i++) { list.push_back(i + 1); } switch_->setOptionalAttribute( diff --git a/fboss/agent/hw/sai/switch/SaiSwitchManager.h b/fboss/agent/hw/sai/switch/SaiSwitchManager.h index 7b513248b2a9e..c77dfe668422b 100644 --- a/fboss/agent/hw/sai/switch/SaiSwitchManager.h +++ b/fboss/agent/hw/sai/switch/SaiSwitchManager.h @@ -102,7 +102,7 @@ class SaiSwitchManager { } void setLocalCapsuleSwitchIds( const std::map& switchIdToNumCores); - void setReachabilityGroupSize(int reachabilityGroupSize); + void setReachabilityGroupList(int reachabilityGroupListSize); private: void programEcmpLoadBalancerParams( diff --git a/fboss/agent/hw/sai/switch/SaiSystemPortManager.cpp b/fboss/agent/hw/sai/switch/SaiSystemPortManager.cpp index 11275739971fe..f34908fad0b09 100644 --- a/fboss/agent/hw/sai/switch/SaiSystemPortManager.cpp +++ b/fboss/agent/hw/sai/switch/SaiSystemPortManager.cpp @@ -55,7 +55,22 @@ SaiSystemPortManager::SaiSystemPortManager( tcToQueueMapAllowedOnSystemPort_( platform_->getAsic()->getSwitchType() == cfg::SwitchType::VOQ && platform_->getAsic()->isSupported( - HwAsic::Feature::TC_TO_QUEUE_QOS_MAP_ON_SYSTEM_PORT)) {} + HwAsic::Feature::TC_TO_QUEUE_QOS_MAP_ON_SYSTEM_PORT)) { + // Extract platform created system ports + if (platform_->getAsic()->getSwitchType() == cfg::SwitchType::VOQ) { + auto& systemPortStore = saiStore_->get(); + for (auto& sysPort : platform_->getInternalSystemPortConfig()) { + SaiSystemPortTraits::Attributes::ConfigInfo confInfo{sysPort}; + const auto& obj = systemPortStore.get(confInfo); + auto sysPortObj = + systemPortStore.loadObjectOwnedByAdapter(obj->adapterKey()); + auto handle = std::make_unique(); + handle->systemPort = std::move(sysPortObj); + handles_.insert( + {SystemPortID(confInfo.value().port_id), std::move(handle)}); + } + } +} SaiSystemPortManager::~SaiSystemPortManager() {} diff --git a/fboss/agent/hw/sai/switch/npu/SaiPortManager.cpp b/fboss/agent/hw/sai/switch/npu/SaiPortManager.cpp index 3c9fe7ea9b249..ea292616dfe7e 100644 --- a/fboss/agent/hw/sai/switch/npu/SaiPortManager.cpp +++ b/fboss/agent/hw/sai/switch/npu/SaiPortManager.cpp @@ -269,6 +269,8 @@ PortSaiId SaiPortManager::addPortImpl(const std::shared_ptr& swPort) { // set the lower 32-bit of SaiId as Hardware logical port ID auto portSaiId = saiPort->adapterKey(); uint32_t hwLogicalPortId = static_cast(portSaiId); + XLOG(DBG2) << "swPort ID: " << swPort->getID() + << " hwLogicalPort ID: " << hwLogicalPortId; platformPort->setHwLogicalPortId(hwLogicalPortId); auto asicPrbs = swPort->getAsicPrbs(); if (asicPrbs.enabled().value()) { diff --git a/fboss/agent/hw/sai/switch/npu/bcm/SaiQueueManager.cpp b/fboss/agent/hw/sai/switch/npu/bcm/SaiQueueManager.cpp index 0a067bb26f4ca..0515152cfbaa5 100644 --- a/fboss/agent/hw/sai/switch/npu/bcm/SaiQueueManager.cpp +++ b/fboss/agent/hw/sai/switch/npu/bcm/SaiQueueManager.cpp @@ -4,7 +4,12 @@ #if defined(BRCM_SAI_SDK_DNX) && defined(BRCM_SAI_SDK_GTE_11_0) extern "C" { -#include + +#ifndef IS_OSS_BRCM_SAI +#include +#else +#include +#endif } #endif @@ -18,7 +23,7 @@ bool fillQueueExtensionStats( HwPortStats& hwPortStats) { bool counterHandled = true; switch (counterId) { - case SAI_QUEUE_STAT_EGRESS_GVOQ_THRESHOLD_WM: + case SAI_QUEUE_STAT_EGRESS_GVOQ_THRESHOLD_WM_BYTES: // There are a few limitations w.r.t. GVOQ watermarks // 1. Granularity of this counter is 8K bytes as of now // 2. Max VoQ watermark that can be reported per VoQ is 16M diff --git a/fboss/agent/hw/switch_asics/Jericho3Asic.cpp b/fboss/agent/hw/switch_asics/Jericho3Asic.cpp index fcde42c8a107a..c156a3785d43a 100644 --- a/fboss/agent/hw/switch_asics/Jericho3Asic.cpp +++ b/fboss/agent/hw/switch_asics/Jericho3Asic.cpp @@ -279,7 +279,7 @@ HwAsic::RecyclePortInfo Jericho3Asic::getRecyclePortInfo() const { return { .coreId = 2, .corePortIndex = 2, - .speedMbps = 10000 // 10G + .speedMbps = 100000 // 100G }; } diff --git a/fboss/agent/hw/switch_asics/Ramon3Asic.cpp b/fboss/agent/hw/switch_asics/Ramon3Asic.cpp index 2ba5ace0f8a10..35bcb2834668e 100644 --- a/fboss/agent/hw/switch_asics/Ramon3Asic.cpp +++ b/fboss/agent/hw/switch_asics/Ramon3Asic.cpp @@ -118,7 +118,7 @@ uint32_t Ramon3Asic::getMaxEcmpSize() const { } uint32_t Ramon3Asic::getNumCores() const { - throw FbossError("Num cores API not supported by Ramon3Asic"); + return 2; } bool Ramon3Asic::scalingFactorBasedDynamicThresholdSupported() const { diff --git a/fboss/agent/hw/switch_asics/YubaAsic.h b/fboss/agent/hw/switch_asics/YubaAsic.h index 83a450fab9715..06b60bd6d1dd4 100644 --- a/fboss/agent/hw/switch_asics/YubaAsic.h +++ b/fboss/agent/hw/switch_asics/YubaAsic.h @@ -91,7 +91,7 @@ class YubaAsic : public TajoAsic { return 512; } int getSystemPortIDOffset() const override { - return 500; + return 0; } uint32_t getSflowShimHeaderSize() const override { return 9; diff --git a/fboss/agent/hw/test/HwAclMatchActionsTests.cpp b/fboss/agent/hw/test/HwAclMatchActionsTests.cpp index 8dfd3a9051389..8ef60fd1c5af8 100644 --- a/fboss/agent/hw/test/HwAclMatchActionsTests.cpp +++ b/fboss/agent/hw/test/HwAclMatchActionsTests.cpp @@ -53,22 +53,9 @@ void addSetDscpAction( namespace facebook::fboss { -template -struct EnableMultiAclTableT { - static constexpr auto multiAclTableEnabled = enableMultiAclTable; -}; - -using TestTypes = - ::testing::Types, EnableMultiAclTableT>; - -template class HwAclMatchActionsTest : public HwTest { - static auto constexpr isMultiAclEnabled = - EnableMultiAclTableT::multiAclTableEnabled; - protected: void SetUp() override { - FLAGS_enable_acl_table_group = isMultiAclEnabled; HwTest::SetUp(); /* * Native SDK does not support multi acl feature. @@ -76,7 +63,7 @@ class HwAclMatchActionsTest : public HwTest { */ if ((this->getPlatform()->getAsic()->getAsicType() == cfg::AsicType::ASIC_TYPE_FAKE) && - (isMultiAclEnabled)) { + (FLAGS_enable_acl_table_group)) { GTEST_SKIP(); } } @@ -86,7 +73,7 @@ class HwAclMatchActionsTest : public HwTest { getHwSwitch(), masterLogicalPortIds(), getAsic()->desiredLoopbackModes()); - if (isMultiAclEnabled) { + if (FLAGS_enable_acl_table_group) { utility::addAclTableGroup( &cfg, cfg::AclStage::INGRESS, utility::getAclTableGroupName()); utility::addDefaultAclTable(cfg); @@ -95,78 +82,7 @@ class HwAclMatchActionsTest : public HwTest { } }; -TYPED_TEST_SUITE(HwAclMatchActionsTest, TestTypes); - -TYPED_TEST(HwAclMatchActionsTest, AddTrafficPolicy) { - constexpr uint32_t kDscp = 0x24; - constexpr int kQueueId = 4; - - auto setup = [this]() { - auto newCfg = this->initialConfig(); - auto asic = this->getPlatform()->getAsic(); - utility::addDscpAclToCfg(asic, &newCfg, "acl1", kDscp); - utility::addQueueMatcher( - &newCfg, "acl1", kQueueId, this->getHwSwitchEnsemble()->isSai()); - this->applyNewConfig(newCfg); - }; - auto verify = [this]() { - EXPECT_EQ(utility::getAclTableNumAclEntries(this->getHwSwitch()), 1); - utility::checkSwHwAclMatch( - this->getHwSwitch(), this->getProgrammedState(), "acl1"); - utility::checkSwAclSendToQueue( - this->getProgrammedState(), "acl1", false, kQueueId); - }; - this->verifyAcrossWarmBoots(setup, verify); -} - -TYPED_TEST(HwAclMatchActionsTest, SetDscpMatchAction) { - constexpr uint32_t kDscp = 0x24; - constexpr uint32_t kDscp2 = 0x8; - - auto setup = [this]() { - auto newCfg = this->initialConfig(); - auto asic = this->getPlatform()->getAsic(); - utility::addDscpAclToCfg(asic, &newCfg, "acl1", kDscp); - addSetDscpAction(&newCfg, "acl1", kDscp2); - this->applyNewConfig(newCfg); - }; - auto verify = [this]() { - EXPECT_EQ(utility::getAclTableNumAclEntries(this->getHwSwitch()), 1); - utility::checkSwHwAclMatch( - this->getHwSwitch(), this->getProgrammedState(), "acl1"); - checkSwActionDscpValue(this->getProgrammedState(), "acl1", kDscp2); - }; - this->verifyAcrossWarmBoots(setup, verify); -} - -TYPED_TEST(HwAclMatchActionsTest, AddSameMatcherTwice) { - auto setup = [this]() { - auto newCfg = this->initialConfig(); - auto asic = this->getPlatform()->getAsic(); - utility::addDscpAclToCfg(asic, &newCfg, "acl1", 0); - utility::addQueueMatcher( - &newCfg, "acl1", 0, this->getHwSwitchEnsemble()->isSai()); - utility::addQueueMatcher( - &newCfg, "acl1", 0, this->getHwSwitchEnsemble()->isSai()); - utility::addDscpAclToCfg(asic, &newCfg, "acl2", 0); - addSetDscpAction(&newCfg, "acl2", 8); - addSetDscpAction(&newCfg, "acl2", 8); - this->applyNewConfig(newCfg); - }; - auto verify = [this]() { - EXPECT_EQ(utility::getAclTableNumAclEntries(this->getHwSwitch()), 2); - utility::checkSwHwAclMatch( - this->getHwSwitch(), this->getProgrammedState(), "acl1"); - utility::checkSwAclSendToQueue( - this->getProgrammedState(), "acl1", false, 0); - utility::checkSwHwAclMatch( - this->getHwSwitch(), this->getProgrammedState(), "acl2"); - checkSwActionDscpValue(this->getProgrammedState(), "acl2", 8); - }; - this->verifyAcrossWarmBoots(setup, verify); -} - -TYPED_TEST(HwAclMatchActionsTest, AddMultipleActions) { +TEST_F(HwAclMatchActionsTest, AddMultipleActions) { auto setup = [this]() { auto newCfg = this->initialConfig(); auto asic = this->getPlatform()->getAsic(); @@ -195,7 +111,7 @@ TYPED_TEST(HwAclMatchActionsTest, AddMultipleActions) { this->verifyAcrossWarmBoots(setup, verify); } -TYPED_TEST(HwAclMatchActionsTest, AddRemoveActions) { +TEST_F(HwAclMatchActionsTest, AddRemoveActions) { auto setup = [this]() { auto newCfg = this->initialConfig(); auto asic = this->getPlatform()->getAsic(); @@ -221,7 +137,7 @@ TYPED_TEST(HwAclMatchActionsTest, AddRemoveActions) { this->verifyAcrossWarmBoots(setup, verify); } -TYPED_TEST(HwAclMatchActionsTest, AddTrafficPolicyMultipleRemoveOne) { +TEST_F(HwAclMatchActionsTest, AddTrafficPolicyMultipleRemoveOne) { auto setup = [this]() { auto newCfg = this->initialConfig(); auto asic = this->getPlatform()->getAsic(); diff --git a/fboss/agent/hw/test/HwAclQualifierTests.cpp b/fboss/agent/hw/test/HwAclQualifierTests.cpp index 0f3b1230778d0..709ebac283c18 100644 --- a/fboss/agent/hw/test/HwAclQualifierTests.cpp +++ b/fboss/agent/hw/test/HwAclQualifierTests.cpp @@ -115,21 +115,9 @@ void configureAllIcmpQualifiers( namespace facebook::fboss { -template -struct EnableMultiAclTableT { - static constexpr auto multiAclTableEnabled = enableMultiAclTable; -}; - -using TestTypes = - ::testing::Types, EnableMultiAclTableT>; - -template class HwAclQualifierTest : public HwTest { public: - static auto constexpr isMultiAclEnabled = - EnableMultiAclTableT::multiAclTableEnabled; bool addQualifiers = false; - void configureAllHwQualifiers(cfg::AclEntry* acl, bool enable) { configureQualifier( acl->srcPort(), enable, masterLogicalInterfacePortIds()[0]); @@ -256,12 +244,11 @@ class HwAclQualifierTest : public HwTest { protected: void SetUp() override { - FLAGS_enable_acl_table_group = isMultiAclEnabled; HwTest::SetUp(); // Skip multi acl tests for fake sdk if ((this->getPlatform()->getAsic()->getAsicType() == cfg::AsicType::ASIC_TYPE_FAKE) && - (isMultiAclEnabled)) { + (FLAGS_enable_acl_table_group)) { GTEST_SKIP(); } } @@ -271,7 +258,7 @@ class HwAclQualifierTest : public HwTest { getHwSwitch(), masterLogicalPortIds(), getAsic()->desiredLoopbackModes()); - if (isMultiAclEnabled) { + if (FLAGS_enable_acl_table_group) { utility::addAclTableGroup( &cfg, cfg::AclStage::INGRESS, utility::getAclTableGroupName()); std::vector actions = {}; @@ -289,9 +276,7 @@ class HwAclQualifierTest : public HwTest { } }; -TYPED_TEST_SUITE(HwAclQualifierTest, TestTypes); - -TYPED_TEST(HwAclQualifierTest, AclIp4TcpQualifiers) { +TEST_F(HwAclQualifierTest, AclIp4TcpQualifiers) { auto setup = [=, this]() { auto newCfg = this->initialConfig(); auto* acl1 = utility::addAcl(&newCfg, "ip4_tcp", cfg::AclActionType::DENY); @@ -312,7 +297,7 @@ TYPED_TEST(HwAclQualifierTest, AclIp4TcpQualifiers) { this->verifyAcrossWarmBoots(setup, verify); } -TYPED_TEST(HwAclQualifierTest, AclIp6TcpQualifiers) { +TEST_F(HwAclQualifierTest, AclIp6TcpQualifiers) { auto setup = [=, this]() { auto newCfg = this->initialConfig(); auto* acl1 = utility::addAcl(&newCfg, "ip6_tcp", cfg::AclActionType::DENY); @@ -333,7 +318,7 @@ TYPED_TEST(HwAclQualifierTest, AclIp6TcpQualifiers) { this->verifyAcrossWarmBoots(setup, verify); } -TYPED_TEST(HwAclQualifierTest, AclIcmp4Qualifiers) { +TEST_F(HwAclQualifierTest, AclIcmp4Qualifiers) { auto setup = [=, this]() { auto newCfg = this->initialConfig(); auto* acl1 = utility::addAcl(&newCfg, "icmp4", cfg::AclActionType::DENY); @@ -354,7 +339,7 @@ TYPED_TEST(HwAclQualifierTest, AclIcmp4Qualifiers) { this->verifyAcrossWarmBoots(setup, verify); } -TYPED_TEST(HwAclQualifierTest, AclIcmp6Qualifiers) { +TEST_F(HwAclQualifierTest, AclIcmp6Qualifiers) { auto setup = [=, this]() { auto newCfg = this->initialConfig(); auto* acl1 = utility::addAcl(&newCfg, "icmp6", cfg::AclActionType::DENY); @@ -375,7 +360,7 @@ TYPED_TEST(HwAclQualifierTest, AclIcmp6Qualifiers) { this->verifyAcrossWarmBoots(setup, verify); } -TYPED_TEST(HwAclQualifierTest, AclRemove) { +TEST_F(HwAclQualifierTest, AclRemove) { auto setup = [=, this]() { auto newCfg = this->initialConfig(); auto* acl0 = utility::addAcl(&newCfg, "acl0", cfg::AclActionType::DENY); @@ -398,7 +383,7 @@ TYPED_TEST(HwAclQualifierTest, AclRemove) { this->verifyAcrossWarmBoots(setup, verify); } -TYPED_TEST(HwAclQualifierTest, AclModifyQualifier) { +TEST_F(HwAclQualifierTest, AclModifyQualifier) { auto setup = [=, this]() { auto newCfg = this->initialConfig(); auto* acl = utility::addAcl(&newCfg, "acl0", cfg::AclActionType::DENY); @@ -432,7 +417,7 @@ TYPED_TEST(HwAclQualifierTest, AclModifyQualifier) { this->verifyAcrossWarmBoots(setup, verify); } -TYPED_TEST(HwAclQualifierTest, AclEmptyCodeIcmp) { +TEST_F(HwAclQualifierTest, AclEmptyCodeIcmp) { auto setup = [=, this]() { auto newCfg = this->initialConfig(); auto* acl = utility::addAcl(&newCfg, "acl0", cfg::AclActionType::DENY); @@ -458,7 +443,7 @@ TYPED_TEST(HwAclQualifierTest, AclEmptyCodeIcmp) { this->verifyAcrossWarmBoots(setup, verify); } -TYPED_TEST(HwAclQualifierTest, AclVlanIDQualifier) { +TEST_F(HwAclQualifierTest, AclVlanIDQualifier) { auto setup = [=, this]() { auto newCfg = this->initialConfig(); if (this->getPlatform()->getAsic()->getAsicType() == @@ -487,7 +472,7 @@ TYPED_TEST(HwAclQualifierTest, AclVlanIDQualifier) { this->verifyAcrossWarmBoots(setup, verify); } -TYPED_TEST(HwAclQualifierTest, AclIp4Qualifiers) { +TEST_F(HwAclQualifierTest, AclIp4Qualifiers) { auto setup = [=, this]() { auto newCfg = this->initialConfig(); auto* acl = utility::addAcl(&newCfg, "ip4", cfg::AclActionType::DENY); @@ -505,7 +490,7 @@ TYPED_TEST(HwAclQualifierTest, AclIp4Qualifiers) { this->verifyAcrossWarmBoots(setup, verify); } -TYPED_TEST(HwAclQualifierTest, AclIp6Qualifiers) { +TEST_F(HwAclQualifierTest, AclIp6Qualifiers) { auto setup = [=, this]() { auto newCfg = this->initialConfig(); auto* acl = utility::addAcl(&newCfg, "ip6", cfg::AclActionType::DENY); @@ -523,7 +508,7 @@ TYPED_TEST(HwAclQualifierTest, AclIp6Qualifiers) { this->verifyAcrossWarmBoots(setup, verify); } -TYPED_TEST(HwAclQualifierTest, AclIp4LookupClassL2) { +TEST_F(HwAclQualifierTest, AclIp4LookupClassL2) { auto setup = [=, this]() { this->aclSetupHelper(true /* isIpV4 */, QualifierType::LOOKUPCLASS_L2); }; @@ -533,7 +518,7 @@ TYPED_TEST(HwAclQualifierTest, AclIp4LookupClassL2) { this->verifyAcrossWarmBoots(setup, verify); } -TYPED_TEST(HwAclQualifierTest, AclIp4LookupClassNeighbor) { +TEST_F(HwAclQualifierTest, AclIp4LookupClassNeighbor) { auto setup = [=, this]() { this->aclSetupHelper( true /* isIpV4 */, QualifierType::LOOKUPCLASS_NEIGHBOR); @@ -544,7 +529,7 @@ TYPED_TEST(HwAclQualifierTest, AclIp4LookupClassNeighbor) { this->verifyAcrossWarmBoots(setup, verify); } -TYPED_TEST(HwAclQualifierTest, AclIp4LookupClassRoute) { +TEST_F(HwAclQualifierTest, AclIp4LookupClassRoute) { auto setup = [=, this]() { this->aclSetupHelper(true /* isIpV4 */, QualifierType::LOOKUPCLASS_ROUTE); }; @@ -554,7 +539,7 @@ TYPED_TEST(HwAclQualifierTest, AclIp4LookupClassRoute) { this->verifyAcrossWarmBoots(setup, verify); } -TYPED_TEST(HwAclQualifierTest, AclIp6LookupClassL2) { +TEST_F(HwAclQualifierTest, AclIp6LookupClassL2) { auto setup = [=, this]() { this->aclSetupHelper(false /* isIpV6 */, QualifierType::LOOKUPCLASS_L2); }; @@ -564,7 +549,7 @@ TYPED_TEST(HwAclQualifierTest, AclIp6LookupClassL2) { this->verifyAcrossWarmBoots(setup, verify); } -TYPED_TEST(HwAclQualifierTest, AclIp6LookupClassNeighbor) { +TEST_F(HwAclQualifierTest, AclIp6LookupClassNeighbor) { auto setup = [=, this]() { this->aclSetupHelper( false /* isIpV6 */, QualifierType::LOOKUPCLASS_NEIGHBOR); @@ -575,7 +560,7 @@ TYPED_TEST(HwAclQualifierTest, AclIp6LookupClassNeighbor) { this->verifyAcrossWarmBoots(setup, verify); } -TYPED_TEST(HwAclQualifierTest, AclIp6LookupClassRoute) { +TEST_F(HwAclQualifierTest, AclIp6LookupClassRoute) { auto setup = [=, this]() { this->aclSetupHelper(false /* isIpV6 */, QualifierType::LOOKUPCLASS_ROUTE); }; @@ -586,11 +571,7 @@ TYPED_TEST(HwAclQualifierTest, AclIp6LookupClassRoute) { } // canary on for qualifiers from default to coop -TYPED_TEST(HwAclQualifierTest, AclQualifiersCanaryOn) { - if (!this->isMultiAclEnabled) { - return; - } - +TEST_F(HwAclQualifierTest, AclQualifiersCanaryOn) { auto setup = [=, this]() { this->aclSetupHelper(true, QualifierType::LOOKUPCLASS_IGNORE, false); }; @@ -605,11 +586,7 @@ TYPED_TEST(HwAclQualifierTest, AclQualifiersCanaryOn) { } // canary off for qualifiers from coop to default -TYPED_TEST(HwAclQualifierTest, AclQualifiersCanaryOff) { - if (!this->isMultiAclEnabled) { - return; - } - +TEST_F(HwAclQualifierTest, AclQualifiersCanaryOff) { auto setup = [=, this]() { this->aclSetupHelper(true, QualifierType::LOOKUPCLASS_IGNORE, true); }; diff --git a/fboss/agent/hw/test/HwAclStatTests.cpp b/fboss/agent/hw/test/HwAclStatTests.cpp index 6eae83ef8530f..c7e3e2288c014 100644 --- a/fboss/agent/hw/test/HwAclStatTests.cpp +++ b/fboss/agent/hw/test/HwAclStatTests.cpp @@ -26,22 +26,9 @@ namespace facebook::fboss { -template -struct EnableMultiAclTableT { - static constexpr auto multiAclTableEnabled = enableMultiAclTable; -}; - -using TestTypes = - ::testing::Types, EnableMultiAclTableT>; - -template class HwAclStatTest : public HwTest { - static auto constexpr isMultiAclEnabled = - EnableMultiAclTableT::multiAclTableEnabled; - protected: void SetUp() override { - FLAGS_enable_acl_table_group = isMultiAclEnabled; HwTest::SetUp(); /* * Native SDK does not support multi acl feature. @@ -49,7 +36,7 @@ class HwAclStatTest : public HwTest { */ if ((this->getPlatform()->getAsic()->getAsicType() == cfg::AsicType::ASIC_TYPE_FAKE) && - (isMultiAclEnabled)) { + (FLAGS_enable_acl_table_group)) { GTEST_SKIP(); } } @@ -59,7 +46,7 @@ class HwAclStatTest : public HwTest { getHwSwitch(), masterLogicalPortIds(), getAsic()->desiredLoopbackModes()); - if (isMultiAclEnabled) { + if (FLAGS_enable_acl_table_group) { utility::addAclTableGroup( &cfg, cfg::AclStage::INGRESS, utility::getAclTableGroupName()); utility::addDefaultAclTable(cfg); @@ -79,9 +66,7 @@ class HwAclStatTest : public HwTest { } }; -TYPED_TEST_SUITE(HwAclStatTest, TestTypes); - -TYPED_TEST(HwAclStatTest, AclStatCreate) { +TEST_F(HwAclStatTest, AclStatCreate) { auto setup = [=, this]() { auto newCfg = this->initialConfig(); this->addDscpAcl(&newCfg, "acl0"); @@ -112,7 +97,7 @@ TYPED_TEST(HwAclStatTest, AclStatCreate) { this->verifyAcrossWarmBoots(setup, verify); } -TYPED_TEST(HwAclStatTest, AclStatCreateDeleteCreate) { +TEST_F(HwAclStatTest, AclStatCreateDeleteCreate) { auto setup = [=, this]() { auto newCfg = this->initialConfig(); this->addDscpAcl(&newCfg, "acl0"); @@ -148,7 +133,7 @@ TYPED_TEST(HwAclStatTest, AclStatCreateDeleteCreate) { this->verifyAcrossWarmBoots(setup, verify); } -TYPED_TEST(HwAclStatTest, AclStatMultipleCounters) { +TEST_F(HwAclStatTest, AclStatMultipleCounters) { auto setup = [=, this]() { auto newCfg = this->initialConfig(); this->addDscpAcl(&newCfg, "acl0"); @@ -174,7 +159,7 @@ TYPED_TEST(HwAclStatTest, AclStatMultipleCounters) { this->verifyAcrossWarmBoots(setup, verify); } -TYPED_TEST(HwAclStatTest, AclStatChangeCounterType) { +TEST_F(HwAclStatTest, AclStatChangeCounterType) { auto setup = [=, this]() { auto newCfg = this->initialConfig(); this->addDscpAcl(&newCfg, "acl0"); @@ -214,7 +199,7 @@ TYPED_TEST(HwAclStatTest, AclStatChangeCounterType) { this->verifyAcrossWarmBoots(setup, verify, setupPostWB, verifyPostWB); } -TYPED_TEST(HwAclStatTest, AclStatCreateShared) { +TEST_F(HwAclStatTest, AclStatCreateShared) { auto setup = [=, this]() { auto newCfg = this->initialConfig(); this->addDscpAcl(&newCfg, "acl0"); @@ -251,7 +236,7 @@ TYPED_TEST(HwAclStatTest, AclStatCreateShared) { this->verifyAcrossWarmBoots(setup, verify); } -TYPED_TEST(HwAclStatTest, AclStatCreateMultiple) { +TEST_F(HwAclStatTest, AclStatCreateMultiple) { auto setup = [=, this]() { auto newCfg = this->initialConfig(); this->addDscpAcl(&newCfg, "acl0"); @@ -295,7 +280,7 @@ TYPED_TEST(HwAclStatTest, AclStatCreateMultiple) { this->verifyAcrossWarmBoots(setup, verify); } -TYPED_TEST(HwAclStatTest, AclStatMultipleActions) { +TEST_F(HwAclStatTest, AclStatMultipleActions) { auto setup = [=, this]() { auto newCfg = this->initialConfig(); this->addDscpAcl(&newCfg, "acl0"); @@ -333,7 +318,7 @@ TYPED_TEST(HwAclStatTest, AclStatMultipleActions) { this->verifyAcrossWarmBoots(setup, verify); } -TYPED_TEST(HwAclStatTest, AclStatDelete) { +TEST_F(HwAclStatTest, AclStatDelete) { auto setup = [=, this]() { auto newCfg = this->initialConfig(); this->addDscpAcl(&newCfg, "acl0"); @@ -375,7 +360,7 @@ TYPED_TEST(HwAclStatTest, AclStatDelete) { this->verifyAcrossWarmBoots(setup, verify, setupPostWB, verifyPostWB); } -TYPED_TEST(HwAclStatTest, AclStatCreatePostWarmBoot) { +TEST_F(HwAclStatTest, AclStatCreatePostWarmBoot) { auto setup = [=, this]() { auto newCfg = this->initialConfig(); this->applyNewConfig(newCfg); @@ -413,7 +398,7 @@ TYPED_TEST(HwAclStatTest, AclStatCreatePostWarmBoot) { this->verifyAcrossWarmBoots(setup, verify, setupPostWB, verifyPostWB); } -TYPED_TEST(HwAclStatTest, AclStatDeleteSharedPostWarmBoot) { +TEST_F(HwAclStatTest, AclStatDeleteSharedPostWarmBoot) { auto setup = [=, this]() { auto newCfg = this->initialConfig(); this->addDscpAcl(&newCfg, "acl0"); @@ -461,7 +446,7 @@ TYPED_TEST(HwAclStatTest, AclStatDeleteSharedPostWarmBoot) { this->verifyAcrossWarmBoots(setup, verify, setupPostWB, verifyPostWB); } -TYPED_TEST(HwAclStatTest, AclStatCreateSharedPostWarmBoot) { +TEST_F(HwAclStatTest, AclStatCreateSharedPostWarmBoot) { auto setup = [=, this]() { auto newCfg = this->initialConfig(); this->applyNewConfig(newCfg); @@ -505,7 +490,7 @@ TYPED_TEST(HwAclStatTest, AclStatCreateSharedPostWarmBoot) { this->verifyAcrossWarmBoots(setup, verify, setupPostWB, verifyPostWB); } -TYPED_TEST(HwAclStatTest, AclStatDeleteShared) { +TEST_F(HwAclStatTest, AclStatDeleteShared) { auto setup = [=, this]() { auto newCfg = this->initialConfig(); this->addDscpAcl(&newCfg, "acl0"); @@ -569,7 +554,7 @@ TYPED_TEST(HwAclStatTest, AclStatDeleteShared) { this->verifyAcrossWarmBoots(setup, verify, setupPostWB, verifyPostWB); } -TYPED_TEST(HwAclStatTest, AclStatRename) { +TEST_F(HwAclStatTest, AclStatRename) { auto setup = [=, this]() { auto newCfg = this->initialConfig(); this->addDscpAcl(&newCfg, "acl0"); @@ -628,7 +613,7 @@ TYPED_TEST(HwAclStatTest, AclStatRename) { this->verifyAcrossWarmBoots(setup, verify, setupPostWB, verifyPostWB); } -TYPED_TEST(HwAclStatTest, AclStatRenameShared) { +TEST_F(HwAclStatTest, AclStatRenameShared) { auto setup = [=, this]() { auto newCfg = this->initialConfig(); this->addDscpAcl(&newCfg, "acl0"); @@ -705,7 +690,7 @@ TYPED_TEST(HwAclStatTest, AclStatRenameShared) { this->verifyAcrossWarmBoots(setup, verify, setupPostWB, verifyPostWB); } -TYPED_TEST(HwAclStatTest, AclStatCreateSameTwice) { +TEST_F(HwAclStatTest, AclStatCreateSameTwice) { auto state = this->getProgrammedState(); auto newCfg = this->initialConfig(); this->addDscpAcl(&newCfg, "acl0"); @@ -721,7 +706,7 @@ TYPED_TEST(HwAclStatTest, AclStatCreateSameTwice) { EXPECT_NO_THROW(this->getHwSwitch()->stateChanged(delta)); } -TYPED_TEST(HwAclStatTest, AclStatDeleteNonExistent) { +TEST_F(HwAclStatTest, AclStatDeleteNonExistent) { auto newCfg = this->initialConfig(); this->addDscpAcl(&newCfg, "acl0"); utility::addAclStat( @@ -741,7 +726,7 @@ TYPED_TEST(HwAclStatTest, AclStatDeleteNonExistent) { // EXPECT_THROW(getHwSwitch()->stateChanged(delta), FbossError); } -TYPED_TEST(HwAclStatTest, AclStatModify) { +TEST_F(HwAclStatTest, AclStatModify) { auto setup = [=, this]() { auto newCfg = this->initialConfig(); this->addDscpAcl(&newCfg, "acl0"); @@ -784,7 +769,7 @@ TYPED_TEST(HwAclStatTest, AclStatModify) { this->verifyAcrossWarmBoots(setup, verify, setupPostWB, verify); } -TYPED_TEST(HwAclStatTest, AclStatShuffle) { +TEST_F(HwAclStatTest, AclStatShuffle) { auto setup = [=, this]() { auto newCfg = this->initialConfig(); this->addDscpAcl(&newCfg, "acl0"); @@ -845,7 +830,7 @@ TYPED_TEST(HwAclStatTest, AclStatShuffle) { this->verifyAcrossWarmBoots(setup, verify, setupPostWB, verify); } -TYPED_TEST(HwAclStatTest, StatNumberOfCounters) { +TEST_F(HwAclStatTest, StatNumberOfCounters) { auto setup = [=, this]() { auto newCfg = this->initialConfig(); this->addDscpAcl(&newCfg, "acl0"); @@ -882,7 +867,7 @@ TYPED_TEST(HwAclStatTest, StatNumberOfCounters) { this->verifyAcrossWarmBoots(setup, verify, setupPostWB, verifyPostWB); } -TYPED_TEST(HwAclStatTest, EmptyAclCheck) { +TEST_F(HwAclStatTest, EmptyAclCheck) { // TODO(joseph5wu) Current this test failed on TH4 because of CS00011697882 auto setup = [this]() { auto newCfg = this->initialConfig(); diff --git a/fboss/agent/hw/test/HwFlowletSwitchingTests.cpp b/fboss/agent/hw/test/HwFlowletSwitchingTests.cpp index 8e487bf79336f..32af216e7504f 100644 --- a/fboss/agent/hw/test/HwFlowletSwitchingTests.cpp +++ b/fboss/agent/hw/test/HwFlowletSwitchingTests.cpp @@ -40,6 +40,7 @@ const int kInactivityIntervalUsecs1 = 128; const int kInactivityIntervalUsecs2 = 256; const int kFlowletTableSize1 = 1024; const int kFlowletTableSize2 = 2048; +const int kMinFlowletTableSize = 256; static int kUdpProto(17); static int kUdpDstPort(4791); constexpr auto kAclName = "flowlet"; @@ -87,6 +88,48 @@ class HwFlowletSwitchingTest : public HwLinkStateDependentTest { this->addRoute(addr, 64, portDescriptorIds); } + void setupEcmpGroups(int numEcmp) { + for (int i = 1; i <= numEcmp; i++) { + std::vector portIds; + portIds.push_back(masterLogicalPortIds()[i % 64]); + portIds.push_back(masterLogicalPortIds()[(i + 1) % 64]); + resolveNextHopsAddRoute( + std::move(portIds), + folly::IPAddressV6(folly::sformat("{}:{:x}::", kAddr3, i))); + std::vector portIds2; + portIds2.push_back(masterLogicalPortIds()[i % 64]); + portIds2.push_back(masterLogicalPortIds()[(i + 2) % 64]); + resolveNextHopsAddRoute( + std::move(portIds2), + folly::IPAddressV6(folly::sformat("{}:{:x}::", kAddr4, i))); + } + } + + void verifyEcmpGroups(const cfg::SwitchConfig& cfg, int numEcmp) { + auto portFlowletConfig = + getPortFlowletConfig(kScalingFactor1, kLoadWeight1, kQueueWeight1); + for (int i = 1; i < numEcmp; i++) { + auto currentIp1 = + folly::IPAddress(folly::sformat("{}:{:x}::", kAddr3, i)); + folly::CIDRNetwork currentPrefix1{currentIp1, 64}; + EXPECT_TRUE(utility::verifyEcmpForFlowletSwitching( + getHwSwitch(), + currentPrefix1, + *cfg.flowletSwitchingConfig(), + portFlowletConfig, + true /* flowletEnable */)); + auto currentIp2 = + folly::IPAddress(folly::sformat("{}:{:x}::", kAddr4, i)); + folly::CIDRNetwork currentPrefix2{currentIp2, 64}; + EXPECT_TRUE(utility::verifyEcmpForFlowletSwitching( + getHwSwitch(), + currentPrefix2, + *cfg.flowletSwitchingConfig(), + portFlowletConfig, + true /* flowletEnable */)); + } + } + void addFlowletAcl(cfg::SwitchConfig& cfg) const { auto* acl = utility::addAcl(&cfg, kAclName); acl->proto() = kUdpProto; @@ -194,7 +237,7 @@ class HwFlowletSwitchingTest : public HwLinkStateDependentTest { auto flowletCfg = getFlowletSwitchingConfig( cfg::SwitchingMode::PER_PACKET_QUALITY, kInactivityIntervalUsecs2, - kFlowletTableSize2); + kMinFlowletTableSize); cfg.flowletSwitchingConfig() = flowletCfg; } @@ -297,7 +340,7 @@ class HwFlowletSwitchingTest : public HwLinkStateDependentTest { auto flowletCfg = getFlowletSwitchingConfig( cfg::SwitchingMode::PER_PACKET_QUALITY, kInactivityIntervalUsecs2, - kFlowletTableSize2); + kMinFlowletTableSize); EXPECT_TRUE( utility::validateFlowletSwitchingEnabled(getHwSwitch(), flowletCfg)); @@ -382,6 +425,46 @@ class HwEcmpFlowletSwitchingTest : public HwFlowletSwitchingTest { auto cfg = getDefaultConfig(); return cfg; } + + void flowletSwitchingWBHelper( + cfg::SwitchingMode preMode, + int preMaxFlows, + int preEcmpScale, + cfg::SwitchingMode postMode, + int postMaxFlows, + int postEcmpScale) { + auto setup = [this, preMode, preMaxFlows, preEcmpScale]() { + auto cfg = initialConfig(); + updateFlowletConfigs(cfg, preMode, preMaxFlows); + updatePortFlowletConfigName(cfg); + applyNewConfig(cfg); + setupEcmpGroups(preEcmpScale); + }; + + auto verify = [this, preMode, preMaxFlows, preEcmpScale]() { + auto cfg = initialConfig(); + updateFlowletConfigs(cfg, preMode, preMaxFlows); + updatePortFlowletConfigName(cfg); + verifyEcmpGroups(cfg, preEcmpScale); + }; + + auto setupPostWarmboot = [this, postMode, postMaxFlows, postEcmpScale]() { + auto cfg = initialConfig(); + updateFlowletConfigs(cfg, postMode, postMaxFlows); + updatePortFlowletConfigName(cfg); + applyNewConfig(cfg); + setupEcmpGroups(postEcmpScale); + }; + + auto verifyPostWarmboot = [this, postMode, postMaxFlows, postEcmpScale]() { + auto cfg = initialConfig(); + updateFlowletConfigs(cfg, postMode, postMaxFlows); + updatePortFlowletConfigName(cfg); + verifyEcmpGroups(cfg, postEcmpScale); + }; + + verifyAcrossWarmBoots(setup, verify, setupPostWarmboot, verifyPostWarmboot); + } }; class HwFlowletSwitchingFlowsetTests : public HwFlowletSwitchingTest { @@ -844,13 +927,23 @@ TEST_F(HwEcmpFlowletSwitchingTest, VerifyEcmpFlowletSwitchingEnable) { applyNewConfig(cfg); // verify the flowlet config verifyConfig(cfg); + // modify switchingMode to per_packet cfg = getDefaultConfig(); - updateFlowletConfigs(cfg, cfg::SwitchingMode::PER_PACKET_QUALITY); + updateFlowletConfigs( + cfg, cfg::SwitchingMode::PER_PACKET_QUALITY, kFlowletTableSize1); + updatePortFlowletConfigName(cfg); + applyNewConfig(cfg); + + // modify max_flows and keep mode the same + cfg = getDefaultConfig(); + updateFlowletConfigs( + cfg, cfg::SwitchingMode::PER_PACKET_QUALITY, kMinFlowletTableSize); updatePortFlowletConfigName(cfg); applyNewConfig(cfg); // verify the flowlet config verifyConfig(cfg); + // Remove the flowlet configs cfg = getDefaultConfig(); applyNewConfig(cfg); @@ -1000,4 +1093,102 @@ TEST_F(HwEcmpFlowletSwitchingTest, VerifySkipEcmpFlowletSwitchingEnable) { verifyAcrossWarmBoots(setup, verify); } +// Verify ability to create upto 128 ECMP DLB groups in spray mode +TEST_F(HwEcmpFlowletSwitchingTest, VerifyEcmpSprayModeScale) { + if (this->skipTest()) { +#if defined(GTEST_SKIP) + GTEST_SKIP(); +#endif + return; + } + int numEcmp = 63; + // CS00012344837 + if (getPlatform()->getAsic()->getAsicType() == + cfg::AsicType::ASIC_TYPE_TOMAHAWK3) { + numEcmp = 30; + } + + auto setup = [this, numEcmp]() { + auto cfg = initialConfig(); + updateFlowletConfigs( + cfg, cfg::SwitchingMode::PER_PACKET_QUALITY, kMinFlowletTableSize); + updatePortFlowletConfigName(cfg); + applyNewConfig(cfg); + setupEcmpGroups(numEcmp); + }; + + auto verify = [this, numEcmp]() { + auto cfg = initialConfig(); + updateFlowletConfigs( + cfg, cfg::SwitchingMode::PER_PACKET_QUALITY, kMinFlowletTableSize); + updatePortFlowletConfigName(cfg); + verifyEcmpGroups(cfg, numEcmp); + }; + + verifyAcrossWarmBoots(setup, verify); +} + +// Verify warmboot from 16 ECMP (flowlet) to 96 ECMP (per-packet) +TEST_F(HwEcmpFlowletSwitchingTest, VerifyModeFlowletToSpray) { + if (this->skipTest()) { +#if defined(GTEST_SKIP) + GTEST_SKIP(); +#endif + return; + } + int numEcmp = 48; + // CS00012344837 + if (getPlatform()->getAsic()->getAsicType() == + cfg::AsicType::ASIC_TYPE_TOMAHAWK3) { + numEcmp = 30; + } + flowletSwitchingWBHelper( + cfg::SwitchingMode::FLOWLET_QUALITY, + kFlowletTableSize2, + 8, + cfg::SwitchingMode::PER_PACKET_QUALITY, + kMinFlowletTableSize, + numEcmp); +} + +// Verify warmboot from 16 ECMP (per-packet) to 16 ECMP (flowlet) +// +// Ideally we want to test 96 per-packet ECMP to 16 flowlet ECMP +// It becomes really hard to verify post conversion because there +// will be 16 flowlet ECMPs and 80 disabled ECMPs post-warmboot. +TEST_F(HwEcmpFlowletSwitchingTest, VerifyModeSprayToFlowlet) { + if (this->skipTest()) { +#if defined(GTEST_SKIP) + GTEST_SKIP(); +#endif + return; + } + + flowletSwitchingWBHelper( + cfg::SwitchingMode::PER_PACKET_QUALITY, + kMinFlowletTableSize, + 8, + cfg::SwitchingMode::FLOWLET_QUALITY, + kFlowletTableSize2, + 8); +} + +TEST_F(HwEcmpFlowletSwitchingTest, VerifyModeSprayFlowletSizeChange) { + if (this->skipTest()) { +#if defined(GTEST_SKIP) + GTEST_SKIP(); +#endif + return; + } + + // Update max_flows size from 2048 -> 256 + flowletSwitchingWBHelper( + cfg::SwitchingMode::PER_PACKET_QUALITY, + kFlowletTableSize2, + 8, + cfg::SwitchingMode::PER_PACKET_QUALITY, + kMinFlowletTableSize, + 8); +} + } // namespace facebook::fboss diff --git a/fboss/agent/hw/test/HwPortFb303StatsTests.cpp b/fboss/agent/hw/test/HwPortFb303StatsTests.cpp index 2c4d813a9351c..721033f7ad874 100644 --- a/fboss/agent/hw/test/HwPortFb303StatsTests.cpp +++ b/fboss/agent/hw/test/HwPortFb303StatsTests.cpp @@ -142,10 +142,10 @@ HwPortStats getInitedStats() { macsecStats, 24, // inLabelMissDiscards_ {}, // queueWatermarkLevel - 0, // inCongestionDiscards - unused - 26, // inAclDiscards - 27, // inTrapDiscards - 28, // outForwardingDiscards + 25, // inCongestionDiscards_ + 27, // inAclDiscards + 28, // inTrapDiscards + 29, // outForwardingDiscards 0, // fabricConnectivityMismatch 1, // logicalPortId 2, // leakyBucketFlapCount_ diff --git a/fboss/agent/hw/test/HwResourceStatsTests.cpp b/fboss/agent/hw/test/HwResourceStatsTests.cpp index 9dae7a33ac22f..efb4c9fba70bf 100644 --- a/fboss/agent/hw/test/HwResourceStatsTests.cpp +++ b/fboss/agent/hw/test/HwResourceStatsTests.cpp @@ -29,29 +29,16 @@ using namespace facebook::fb303; namespace facebook::fboss { -template -struct EnableMultiAclTableT { - static constexpr auto multiAclTableEnabled = enableMultiAclTable; -}; - -using TestTypes = - ::testing::Types, EnableMultiAclTableT>; - -template class HwResourceStatsTest : public HwLinkStateDependentTest { - static auto constexpr isMultiAclEnabled = - EnableMultiAclTableT::multiAclTableEnabled; - protected: void SetUp() override { - FLAGS_enable_acl_table_group = isMultiAclEnabled; HwTest::SetUp(); } cfg::SwitchConfig initialConfig() const override { auto cfg = utility::onePortPerInterfaceConfig( getHwSwitch(), masterLogicalPortIds()); - if (isMultiAclEnabled) { + if (FLAGS_enable_acl_table_group) { utility::addAclTableGroup( &cfg, cfg::AclStage::INGRESS, utility::getAclTableGroupName()); utility::addDefaultAclTable(cfg); @@ -68,9 +55,7 @@ class HwResourceStatsTest : public HwLinkStateDependentTest { } }; -TYPED_TEST_SUITE(HwResourceStatsTest, TestTypes); - -TYPED_TEST(HwResourceStatsTest, l3Stats) { +TEST_F(HwResourceStatsTest, l3Stats) { if (!this->isSupported(HwAsic::Feature::RESOURCE_USAGE_STATS)) { #if defined(GTEST_SKIP) GTEST_SKIP(); @@ -148,7 +133,7 @@ TYPED_TEST(HwResourceStatsTest, l3Stats) { this->verifyAcrossWarmBoots(setup, verify); }; -TYPED_TEST(HwResourceStatsTest, aclStats) { +TEST_F(HwResourceStatsTest, aclStats) { if (!this->isSupported(HwAsic::Feature::RESOURCE_USAGE_STATS)) { #if defined(GTEST_SKIP) GTEST_SKIP(); diff --git a/fboss/agent/hw/test/HwSplitAgentTest.cpp b/fboss/agent/hw/test/HwSplitAgentTest.cpp index 739679869184e..807d1d038fc48 100644 --- a/fboss/agent/hw/test/HwSplitAgentTest.cpp +++ b/fboss/agent/hw/test/HwSplitAgentTest.cpp @@ -112,6 +112,7 @@ TEST_F(HwSplitAgentCallbackTest, txPacket) { folly::IPAddressV4("1.0.0.1"), folly::IPAddressV4("1.0.0.2")); multiswitch::TxPacket txPacket; + txPacket.length() = pkt->buf()->computeChainDataLength(); txPacket.data() = Packet::extractIOBuf(std::move(pkt)); auto statBefore = diff --git a/fboss/agent/hw/test/HwTestThriftHandler.h b/fboss/agent/hw/test/HwTestThriftHandler.h index daa66bc4db7d1..81a304eaff86f 100644 --- a/fboss/agent/hw/test/HwTestThriftHandler.h +++ b/fboss/agent/hw/test/HwTestThriftHandler.h @@ -81,6 +81,8 @@ class HwTestThriftHandler : public AgentHwTestCtrlSvIf { std::unique_ptr> hwPorts, bool injectCorrectable) override; + void injectSwitchReachabilityChangeNotification() override; + private: HwSwitch* hwSwitch_; }; diff --git a/fboss/agent/hw/test/ProdConfigFactory.cpp b/fboss/agent/hw/test/ProdConfigFactory.cpp index cde5fec49baf2..286309aa6fa73 100644 --- a/fboss/agent/hw/test/ProdConfigFactory.cpp +++ b/fboss/agent/hw/test/ProdConfigFactory.cpp @@ -101,6 +101,7 @@ uint16_t uplinksCountFromSwitch(PlatformType mode) { case PM::PLATFORM_WEDGE400C: case PM::PLATFORM_WEDGE400: case PM::PLATFORM_YAMP: + case PM::PLATFORM_MORGAN800CC: case PM::PLATFORM_MINIPACK: case PM::PLATFORM_ELBERT: case PM::PLATFORM_FUJI: diff --git a/fboss/agent/hw/test/dataplane_tests/HwTrafficPfcTests.cpp b/fboss/agent/hw/test/dataplane_tests/HwTrafficPfcTests.cpp index adc020fa74923..d8ae92f72a95a 100644 --- a/fboss/agent/hw/test/dataplane_tests/HwTrafficPfcTests.cpp +++ b/fboss/agent/hw/test/dataplane_tests/HwTrafficPfcTests.cpp @@ -226,34 +226,15 @@ class HwTrafficPfcTest : public HwLinkStateDependentTest { return cfg; } - folly::IPAddressV6 kDestIp1() const { - return folly::IPAddressV6("2620:0:1cfe:face:b00c::4"); - } - folly::IPAddressV6 kDestIp2() const { - return folly::IPAddressV6("2620:0:1cfe:face:b00c::5"); - } - PortDescriptor portDesc1() const { - return PortDescriptor(masterLogicalInterfacePortIds()[0]); - } - PortDescriptor portDesc2() const { - return PortDescriptor(masterLogicalInterfacePortIds()[1]); + std::vector portIdsForTest() { + return { + masterLogicalInterfacePortIds()[0], masterLogicalInterfacePortIds()[1]}; } - void setupECMPForwarding( - const utility::EcmpSetupTargetedPorts6& ecmpHelper, - PortDescriptor port, - const folly::CIDRNetwork& prefix) { - RoutePrefixV6 route{prefix.first.asV6(), prefix.second}; - applyNewState(ecmpHelper.resolveNextHops(getProgrammedState(), {port})); - ecmpHelper.programRoutes(getRouteUpdater(), {port}, {route}); - } - template - void disableTTLDecrements(const ECMP_HELPER& ecmpHelper) { - for (const auto& nextHop : - {ecmpHelper.nhop(portDesc1()), ecmpHelper.nhop(portDesc2())}) { - utility::ttlDecrementHandlingForLoopbackTraffic( - getHwSwitchEnsemble(), ecmpHelper.getRouterId(), nextHop); - } + std::vector kDestIps() const { + return { + folly::IPAddressV6("2620:0:1cfe:face:b00c::4"), + folly::IPAddressV6("2620:0:1cfe:face:b00c::5")}; } folly::MacAddress getIntfMac() const { @@ -488,8 +469,9 @@ class HwTrafficPfcTest : public HwLinkStateDependentTest { std::function& portIds)> validateCounterFn = + const std::vector& portIdsToValidate)> validateCounterFn = validatePfcCounters) { + std::vector portIds = portIdsForTest(); auto setup = [&]() { if ((getAsic()->getAsicType() == cfg::AsicType::ASIC_TYPE_JERICHO2) || (getAsic()->getAsicType() == cfg::AsicType::ASIC_TYPE_JERICHO3)) { @@ -498,31 +480,20 @@ class HwTrafficPfcTest : public HwLinkStateDependentTest { testParams.buffer.scalingFactor = cfg::MMUScalingFactor::ONE_32768TH; } setupBuffers(testParams.buffer, testParams.scale); - setupEcmpTraffic(); + setupEcmpTraffic(portIds); // ensure counter is 0 before we start traffic - validateInitPfcCounters( - {masterLogicalInterfacePortIds()[0], - masterLogicalInterfacePortIds()[1]}, - pfcPriority); + validateInitPfcCounters(portIds, pfcPriority); }; auto verifyCommon = [&](bool postWb) { pumpTraffic(trafficClass); // check counters are as expected - validateCounterFn( - getHwSwitchEnsemble(), - pfcPriority, - {masterLogicalInterfacePortIds()[0], - masterLogicalInterfacePortIds()[1]}); + validateCounterFn(getHwSwitchEnsemble(), pfcPriority, portIds); if (testParams.expectDrop) { - validateIngressDropCounters( - {masterLogicalInterfacePortIds()[0], - masterLogicalInterfacePortIds()[1]}); + validateIngressDropCounters(portIds); } if (!FLAGS_skip_stop_pfc_test_traffic && postWb) { // stop traffic so that unconfiguration can happen without issues - stopTraffic( - {masterLogicalInterfacePortIds()[0], - masterLogicalInterfacePortIds()[1]}); + stopTraffic(portIds); } }; auto verify = [&]() { verifyCommon(false /* postWb */); }; @@ -530,23 +501,26 @@ class HwTrafficPfcTest : public HwLinkStateDependentTest { verifyAcrossWarmBoots(setup, verify, []() {}, verifyPostWb); } - void setupEcmpTraffic() { - utility::EcmpSetupTargetedPorts6 ecmpHelper6{ + void setupEcmpTraffic(const std::vector& portIds) { + utility::EcmpSetupTargetedPorts6 ecmpHelper{ getProgrammedState(), getIntfMac()}; - setupECMPForwarding( - ecmpHelper6, - PortDescriptor(masterLogicalInterfacePortIds()[0]), - {kDestIp1(), 128}); - setupECMPForwarding( - ecmpHelper6, - PortDescriptor(masterLogicalInterfacePortIds()[1]), - {kDestIp2(), 128}); - disableTTLDecrements(ecmpHelper6); + + CHECK_EQ(portIds.size(), kDestIps().size()); + for (int i = 0; i < portIds.size(); ++i) { + const PortDescriptor port(portIds[i]); + RoutePrefixV6 route{kDestIps()[i], 128}; + applyNewState(ecmpHelper.resolveNextHops(getProgrammedState(), {port})); + ecmpHelper.programRoutes(getRouteUpdater(), {port}, {route}); + utility::ttlDecrementHandlingForLoopbackTraffic( + getHwSwitchEnsemble(), + ecmpHelper.getRouterId(), + ecmpHelper.nhop(port)); + } } void setupConfigAndEcmpTraffic() { setupBuffers(); - setupEcmpTraffic(); + setupEcmpTraffic(portIdsForTest()); } public: @@ -560,7 +534,7 @@ class HwTrafficPfcTest : public HwLinkStateDependentTest { int numPacketsPerFlow = getHwSwitchEnsemble()->getMinPktsForLineRate( masterLogicalInterfacePortIds()[0]); for (int i = 0; i < numPacketsPerFlow; i++) { - for (const auto& dstIp : {kDestIp1(), kDestIp2()}) { + for (const auto& dstIp : kDestIps()) { auto txPacket = utility::makeUDPTxPacket( getHwSwitch(), vlanId, @@ -610,9 +584,7 @@ class HwTrafficPfcTest : public HwLinkStateDependentTest { } } - for (const auto& portID : - {masterLogicalInterfacePortIds()[0], - masterLogicalInterfacePortIds()[1]}) { + for (const auto& portID : portIdsForTest()) { auto portCfg = utility::findCfgPort(cfg_, portID); if (portCfg->pfc().has_value()) { if (enable) { diff --git a/fboss/agent/if/agent_hw_test_ctrl.thrift b/fboss/agent/if/agent_hw_test_ctrl.thrift index 28dd33a106f99..d4f10cc19832c 100644 --- a/fboss/agent/if/agent_hw_test_ctrl.thrift +++ b/fboss/agent/if/agent_hw_test_ctrl.thrift @@ -66,4 +66,6 @@ service AgentHwTestCtrl { i32 getHwEcmpSize(1: CIDRNetwork prefix, 2: i32 routerID, 3: i32 sizeInSw); void injectFecError(1: list hwPorts, 2: bool injectCorrectable); + + void injectSwitchReachabilityChangeNotification(); } diff --git a/fboss/agent/if/ctrl.thrift b/fboss/agent/if/ctrl.thrift index 53df4d3b4c7ab..b596dc5faa5c6 100644 --- a/fboss/agent/if/ctrl.thrift +++ b/fboss/agent/if/ctrl.thrift @@ -371,6 +371,8 @@ struct PortInfoThrift { 24: bool isDrained; 25: optional PortActiveState activeState; 26: list activeErrors; + 27: optional string expectedLLDPeerName; + 28: optional string expectedLLDPPeerPort; } // Port queueing configuration diff --git a/fboss/agent/if/multiswitch_ctrl.thrift b/fboss/agent/if/multiswitch_ctrl.thrift index f788c91c5ecaa..f0e79bc4b84d2 100644 --- a/fboss/agent/if/multiswitch_ctrl.thrift +++ b/fboss/agent/if/multiswitch_ctrl.thrift @@ -54,6 +54,7 @@ struct TxPacket { 1: fbbinary data; 2: optional i32 port; 3: optional i32 queue; + 4: i32 length; } struct RxPacket { @@ -61,6 +62,8 @@ struct RxPacket { 2: i32 port; 3: optional i32 aggPort; 4: optional i16 vlan; + 5: i32 length; + 6: optional ctrl.CpuCosQueueId cosQueue; } struct StateOperDelta { diff --git a/fboss/agent/mnpu/FdbEventSyncer.cpp b/fboss/agent/mnpu/FdbEventSyncer.cpp index c9101702496e2..7990a056fbd2c 100644 --- a/fboss/agent/mnpu/FdbEventSyncer.cpp +++ b/fboss/agent/mnpu/FdbEventSyncer.cpp @@ -9,7 +9,7 @@ */ #include "fboss/agent/mnpu/FdbEventSyncer.h" #if FOLLY_HAS_COROUTINES -#include +#include #endif namespace facebook::fboss { diff --git a/fboss/agent/mnpu/HwSwitchStatsSinkClient.cpp b/fboss/agent/mnpu/HwSwitchStatsSinkClient.cpp index 985e007356611..99e5bb6f10abd 100644 --- a/fboss/agent/mnpu/HwSwitchStatsSinkClient.cpp +++ b/fboss/agent/mnpu/HwSwitchStatsSinkClient.cpp @@ -9,7 +9,7 @@ */ #include "fboss/agent/mnpu/HwSwitchStatsSinkClient.h" #if FOLLY_HAS_COROUTINES -#include +#include #endif namespace facebook::fboss { diff --git a/fboss/agent/mnpu/LinkChangeEventSyncer.cpp b/fboss/agent/mnpu/LinkChangeEventSyncer.cpp index b5d4577aeffef..728e864c1156b 100644 --- a/fboss/agent/mnpu/LinkChangeEventSyncer.cpp +++ b/fboss/agent/mnpu/LinkChangeEventSyncer.cpp @@ -10,7 +10,7 @@ #include "fboss/agent/mnpu/LinkChangeEventSyncer.h" #include "fboss/agent/HwSwitch.h" #if FOLLY_HAS_COROUTINES -#include +#include #endif namespace facebook::fboss { diff --git a/fboss/agent/mnpu/RxPktEventSyncer.cpp b/fboss/agent/mnpu/RxPktEventSyncer.cpp index d5b4952cb3bcc..99f3c97671cf2 100644 --- a/fboss/agent/mnpu/RxPktEventSyncer.cpp +++ b/fboss/agent/mnpu/RxPktEventSyncer.cpp @@ -9,7 +9,7 @@ */ #include "fboss/agent/mnpu/RxPktEventSyncer.h" #if FOLLY_HAS_COROUTINES -#include +#include #endif namespace facebook::fboss { diff --git a/fboss/agent/mnpu/SplitAgentThriftSyncer.cpp b/fboss/agent/mnpu/SplitAgentThriftSyncer.cpp index afa5c411fc89a..ad0327f64928c 100644 --- a/fboss/agent/mnpu/SplitAgentThriftSyncer.cpp +++ b/fboss/agent/mnpu/SplitAgentThriftSyncer.cpp @@ -76,9 +76,13 @@ void SplitAgentThriftSyncer::packetReceived( if (pkt->getSrcAggregatePort()) { rxPkt.aggPort() = pkt->getSrcAggregatePort(); } + if (pkt->cosQueue()) { + rxPkt.cosQueue() = hwQueueIdToCpuCosQueueId(*pkt->cosQueue()); + } // coalesce the IOBuf before copy pkt->buf()->coalesce(); rxPkt.data() = IOBuf::copyBuffer(pkt->buf()->data(), pkt->buf()->length()); + rxPkt.length() = pkt->buf()->computeChainDataLength(); rxPktEventSinkClient_->enqueue(std::move(rxPkt)); } diff --git a/fboss/agent/mnpu/SplitAgentThriftSyncerClient.h b/fboss/agent/mnpu/SplitAgentThriftSyncerClient.h index 46cc05c0bf682..9758ea41e1258 100644 --- a/fboss/agent/mnpu/SplitAgentThriftSyncerClient.h +++ b/fboss/agent/mnpu/SplitAgentThriftSyncerClient.h @@ -18,10 +18,10 @@ #include #if FOLLY_HAS_COROUTINES -#include -#include -#include -#include +#include +#include +#include +#include #endif #include "fboss/agent/MultiSwitchThriftHandler.h" diff --git a/fboss/agent/mnpu/SwitchReachabilityChangeEventSyncer.cpp b/fboss/agent/mnpu/SwitchReachabilityChangeEventSyncer.cpp index ffc0645098ecb..4136537a7e4a5 100644 --- a/fboss/agent/mnpu/SwitchReachabilityChangeEventSyncer.cpp +++ b/fboss/agent/mnpu/SwitchReachabilityChangeEventSyncer.cpp @@ -10,7 +10,7 @@ #include "fboss/agent/mnpu/SwitchReachabilityChangeEventSyncer.h" #include "fboss/agent/HwSwitch.h" #if FOLLY_HAS_COROUTINES -#include +#include #endif namespace facebook::fboss { diff --git a/fboss/agent/mnpu/TxPktEventSyncer.cpp b/fboss/agent/mnpu/TxPktEventSyncer.cpp index 6023981059880..16d513944f69e 100644 --- a/fboss/agent/mnpu/TxPktEventSyncer.cpp +++ b/fboss/agent/mnpu/TxPktEventSyncer.cpp @@ -12,7 +12,7 @@ #include "fboss/agent/TxPacket.h" #if FOLLY_HAS_COROUTINES -#include +#include #endif DEFINE_int32(tx_pkt_stream_buffer_size, 1000, "TxPktEventStream buffer size"); @@ -57,6 +57,12 @@ TxPktEventSyncer::initTxPktEventStream( } #endif +fb303::TimeseriesWrapper& TxPktEventSyncer::getBadPacketCounter() { + static fb303::TimeseriesWrapper txBadPktReceived{ + "tx_bad_pkt_received", fb303::SUM, fb303::RATE}; + return txBadPktReceived; +} + void TxPktEventSyncer::TxPacketEventHandler( multiswitch::TxPacket& txPkt, HwSwitch* hw) { @@ -69,6 +75,13 @@ void TxPktEventSyncer::TxPacketEventHandler( folly::io::Cursor inCursor(txPkt.data()->get()); folly::io::RWPrivateCursor outCursor(pkt->buf()); outCursor.pushAtMost(inCursor, len); + + if (*txPkt.length() != len) { + XLOG(ERR) << "Tx packet length mismatch for switch " << *hw->getSwitchId(); + getBadPacketCounter().add(1); + return; + } + if (txPkt.port().has_value()) { PortID portId(*txPkt.port()); hw->sendPacketOutOfPortAsync( diff --git a/fboss/agent/mnpu/TxPktEventSyncer.h b/fboss/agent/mnpu/TxPktEventSyncer.h index fca9818e38de3..af3e8a086eb52 100644 --- a/fboss/agent/mnpu/TxPktEventSyncer.h +++ b/fboss/agent/mnpu/TxPktEventSyncer.h @@ -35,7 +35,7 @@ class TxPktEventSyncer : public ThriftStreamClient { SwitchID switchId, apache::thrift::Client* client); #endif - + static fb303::TimeseriesWrapper& getBadPacketCounter(); static void TxPacketEventHandler(multiswitch::TxPacket&, HwSwitch*); private: diff --git a/fboss/agent/oss/BuildInfoWrapper.cpp b/fboss/agent/oss/BuildInfoWrapper.cpp new file mode 100644 index 0000000000000..df4a25edceae3 --- /dev/null +++ b/fboss/agent/oss/BuildInfoWrapper.cpp @@ -0,0 +1,13 @@ +// (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary. + +#include "fboss/agent/BuildInfoWrapper.h" + +#include + +namespace facebook::fboss { + +std::string getBuildPackageVersion() { + return std::string("buildPackageVersion"); +} + +} // namespace facebook::fboss diff --git a/fboss/agent/oss/SetupThrift.cpp b/fboss/agent/oss/SetupThrift.cpp index 2d5aa90dcbc3b..120ef955e0aee 100644 --- a/fboss/agent/oss/SetupThrift.cpp +++ b/fboss/agent/oss/SetupThrift.cpp @@ -14,5 +14,6 @@ namespace facebook::fboss { void serverSSLSetup(apache::thrift::ThriftServer& /*server*/) {} void setupThriftModules() {} +void clearThriftModules() {} } // namespace facebook::fboss diff --git a/fboss/agent/packet/EthFrame.cpp b/fboss/agent/packet/EthFrame.cpp index 661954de8b48c..a7af87a49fd67 100644 --- a/fboss/agent/packet/EthFrame.cpp +++ b/fboss/agent/packet/EthFrame.cpp @@ -7,13 +7,19 @@ #include "fboss/agent/FbossError.h" #include "fboss/agent/TxPacket.h" +#include "fboss/agent/packet/PktUtil.h" #include namespace facebook::fboss::utility { namespace { static auto kDefaultPayload = std::vector(256, 0xff); -} + +// See IEEE 802.3-2022 31.4.1 and 4.4.2. TL;DR this should be +// 64 (minFrameSize) - 12 (src/dest mac) - 2 (ethertype) +// - 4 (FCS) = 46 bytes. +static size_t kMacControlPayloadSize = 46; +} // namespace EthFrame::EthFrame(folly::io::Cursor& cursor) { hdr_ = EthHdr(cursor); @@ -30,6 +36,12 @@ EthFrame::EthFrame(folly::io::Cursor& cursor) { case static_cast(ETHERTYPE::ETHERTYPE_ARP): arpHdr_ = ArpHdr(cursor); break; + case static_cast(ETHERTYPE::ETHERTYPE_EPON): { + CHECK(cursor.canAdvance(kMacControlPayloadSize)); + macControlPayload_ = std::vector(kMacControlPayloadSize); + cursor.pull(macControlPayload_->data(), kMacControlPayloadSize); + break; + } case static_cast(ETHERTYPE::ETHERTYPE_LLDP): case static_cast(ETHERTYPE::ETHERTYPE_SLOW_PROTOCOLS): case static_cast(ETHERTYPE::ETHERTYPE_EAPOL): @@ -74,6 +86,10 @@ std::unique_ptr EthFrame::getTxPacket( rwCursor.push(cursor, mplsPayLoad_->length()); } else if (arpHdr_) { arpHdr_->serialize(&rwCursor); + } else if (macControlPayload_) { + rwCursor.template writeBE( + static_cast(ETHERTYPE::ETHERTYPE_EPON)); + rwCursor.push(macControlPayload_->data(), macControlPayload_->size()); } return txPacket; } @@ -107,6 +123,10 @@ void EthFrame::serialize(folly::io::RWPrivateCursor& cursor) const { cursor.template writeBE( static_cast(ETHERTYPE::ETHERTYPE_ARP)); arpHdr_->serialize(&cursor); + } else if (macControlPayload_) { + cursor.template writeBE( + static_cast(ETHERTYPE::ETHERTYPE_EPON)); + cursor.push(macControlPayload_->data(), macControlPayload_->size()); } } @@ -196,7 +216,13 @@ std::string utility::EthFrame::toString() const { << " arp: " << (arpHdr_.has_value() ? arpHdr_->toString() : "") << " mpls: " << (mplsPayLoad_.has_value() ? mplsPayLoad_->toString() : "") << " v6 : " << (v6PayLoad_.has_value() ? v6PayLoad_->toString() : "") - << " v4 : " << (v4PayLoad_.has_value() ? v4PayLoad_->toString() : ""); + << " v4 : " << (v4PayLoad_.has_value() ? v4PayLoad_->toString() : "") + << " mac control: " + << (macControlPayload_ ? PktUtil::hexDump(folly::IOBuf( + folly::IOBuf::CopyBufferOp::COPY_BUFFER, + macControlPayload_->data(), + macControlPayload_->size())) + : ""); return ss.str(); } diff --git a/fboss/agent/packet/EthFrame.h b/fboss/agent/packet/EthFrame.h index 620779504091a..5401873065c4c 100644 --- a/fboss/agent/packet/EthFrame.h +++ b/fboss/agent/packet/EthFrame.h @@ -56,6 +56,8 @@ class EthFrame { len += mplsPayLoad_->length(); } else if (arpHdr_) { len += arpHdr_->size(); + } else if (macControlPayload_) { + len += macControlPayload_->size(); } len += hdr_.size(); return len; @@ -76,20 +78,32 @@ class EthFrame { std::optional mplsPayLoad() const { return mplsPayLoad_; } + std::optional arpHdr() const { return arpHdr_; } + std::optional> macControlPayload() const { + return macControlPayload_; + } + void serialize(folly::io::RWPrivateCursor& cursor) const; bool operator==(const EthFrame& that) const { - return std::tie(hdr_, v4PayLoad_, v6PayLoad_, mplsPayLoad_, arpHdr_) == + return std::tie( + hdr_, + v4PayLoad_, + v6PayLoad_, + mplsPayLoad_, + arpHdr_, + macControlPayload_) == std::tie( that.hdr_, that.v4PayLoad_, that.v6PayLoad_, that.mplsPayLoad_, - arpHdr_); + that.arpHdr_, + that.macControlPayload_); } bool operator!=(const EthFrame& that) const { return !(*this == that); @@ -118,6 +132,7 @@ class EthFrame { std::optional> v6PayLoad_; std::optional mplsPayLoad_; std::optional arpHdr_; + std::optional> macControlPayload_; }; inline std::ostream& operator<<(std::ostream& os, const EthFrame& ethFrame) { diff --git a/fboss/agent/packet/PktUtil.cpp b/fboss/agent/packet/PktUtil.cpp index 829d62c6191fc..73ffb5ed6b949 100644 --- a/fboss/agent/packet/PktUtil.cpp +++ b/fboss/agent/packet/PktUtil.cpp @@ -130,6 +130,10 @@ string PktUtil::hexDump(Cursor start, Cursor end) { } string PktUtil::hexDump(Cursor cursor, uint32_t length) { + if (UNLIKELY(length == 0)) { + return ""; + } + // Go ahead and reserve the required space size_t numLines = (length + 15) / 16; size_t expectedLength = (length * 3) + // 3 bytes for each character diff --git a/fboss/agent/packet/test/BUCK b/fboss/agent/packet/test/BUCK index bbd44359c72f2..2eaba2eab460d 100644 --- a/fboss/agent/packet/test/BUCK +++ b/fboss/agent/packet/test/BUCK @@ -7,6 +7,7 @@ cpp_unittest( srcs = [ "ArpHdrTest.cpp", "DHCPv4PacketTest.cpp", + "EthFrameTest.cpp", "EthHdrTest.cpp", "ICMPHdrTest.cpp", "ICMPPacketTest.cpp", @@ -22,23 +23,24 @@ cpp_unittest( "UDPHdrTest.cpp", ], deps = [ - "//fboss/agent:core", - "//fboss/agent:dhcpv4_options_of_interest", - "//fboss/agent:fboss-error", - "//fboss/agent:stats", - "//fboss/agent/hw/mock:mock", - "//fboss/agent/hw/mock:pkt", - "//fboss/agent/packet:ether_type", - "//fboss/agent/packet:packet", - "//fboss/agent/packet:pktutil", - "//fboss/agent/state:state", - "//fboss/agent/test:utils", - "//folly:conv", - "//folly:memory", - "//folly:network_address", - "//folly:random", - "//folly/io:iobuf", - "//folly/logging:logging", + "fbcode//fboss/agent:core", + "fbcode//fboss/agent:dhcpv4_options_of_interest", + "fbcode//fboss/agent:fboss-error", + "fbcode//fboss/agent:stats", + "fbcode//fboss/agent/hw/mock:mock", + "fbcode//fboss/agent/hw/mock:pkt", + "fbcode//fboss/agent/packet:ether_type", + "fbcode//fboss/agent/packet:packet", + "fbcode//fboss/agent/packet:packet_factory", + "fbcode//fboss/agent/packet:pktutil", + "fbcode//fboss/agent/state:state", + "fbcode//fboss/agent/test:utils", + "fbcode//folly:conv", + "fbcode//folly:memory", + "fbcode//folly:network_address", + "fbcode//folly:random", + "fbcode//folly/io:iobuf", + "fbcode//folly/logging:logging", ], ) diff --git a/fboss/agent/packet/test/EthFrameTest.cpp b/fboss/agent/packet/test/EthFrameTest.cpp new file mode 100644 index 0000000000000..c69a9a3d1466a --- /dev/null +++ b/fboss/agent/packet/test/EthFrameTest.cpp @@ -0,0 +1,86 @@ +// (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary. + +#include "fboss/agent/packet/EthFrame.h" + +#include + +#include +#include +#include "fboss/agent/packet/PktUtil.h" + +using namespace ::testing; +using namespace facebook::fboss; +using namespace facebook::fboss::utility; + +TEST(EthFrameTest, ParseIpv6Frame) { + // Deserialize + auto buf = PktUtil::parseHexData( + // Dest mac, source mac + "00 02 00 00 00 01 02 00 02 01 02 03" + // 802.1q, VLAN 1 + "81 00 00 01" + // IPv6 + "86 dd" + // IPv6 version, traffic class, flow label + "6f ff ff ff" + // Payload Length + "00 00" + // Next Header: No Next Header + "3B" + // Hop Limit: 1 + "01" + // IPv6 Source Address + "26 20 00 00 1c fe fa ce" + "b0 0c 00 00 00 00 00 03" + // IPv6 Destination Address + "26 20 00 00 1c fe fa ce" + "b0 0c 00 00 00 00 00 04"); + folly::io::Cursor cursor(&buf); + EthFrame ethFrame(cursor); + EXPECT_EQ(ethFrame.length(), buf.length()); + EXPECT_TRUE(ethFrame.v6PayLoad().has_value()); + EXPECT_EQ(ethFrame.v6PayLoad()->length(), 40); + + // Serialize + auto buf2 = ethFrame.toIOBuf(); + EXPECT_TRUE(folly::IOBufEqualTo()(*buf2, buf)); + + // Parse again and check equality via == operator + folly::io::Cursor cursor2(buf2.get()); + EthFrame ethFrame2(cursor2); + EXPECT_EQ(ethFrame2, ethFrame); +} + +TEST(EthFrameTest, ParseMacControlFrame) { + // Deserialize + auto buf = PktUtil::parseHexData( + // Dest mac, source mac + "00 02 00 00 00 01 02 00 02 01 02 03" + // EPON (Mac Control) + "88 08" + // PFC opcode + "01 01" + // Always 00 + "00" + // Class Vector + "ff" + // Quanta for each class + "00 f0 00 f0 00 f0 00 f0 00 f0 00 f0 00 f0 00 f0" + // 26-byte padding + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00" + "00 00 00 00 00 00 00 00 00 00"); + folly::io::Cursor cursor(&buf); + EthFrame ethFrame(cursor); + EXPECT_EQ(ethFrame.length(), buf.length()); + EXPECT_TRUE(ethFrame.macControlPayload().has_value()); + EXPECT_EQ(ethFrame.macControlPayload()->size(), 46); + + // Serialize + auto buf2 = ethFrame.toIOBuf(); + EXPECT_TRUE(folly::IOBufEqualTo()(*buf2, buf)); + + // Parse again and check equality via == operator + folly::io::Cursor cursor2(buf2.get()); + EthFrame ethFrame2(cursor2); + EXPECT_EQ(ethFrame2, ethFrame); +} diff --git a/fboss/agent/packet/test/PktUtilTest.cpp b/fboss/agent/packet/test/PktUtilTest.cpp index 45065ecb51fe0..1c758b7cb0e0d 100644 --- a/fboss/agent/packet/test/PktUtilTest.cpp +++ b/fboss/agent/packet/test/PktUtilTest.cpp @@ -123,6 +123,11 @@ TEST(PktUtilTest, ReadIPv6) { EXPECT_THROW(PktUtil::readIPv6(&c), std::out_of_range); } +TEST(PktUtilTest, HexDumpEmptyBuffer) { + IOBuf buf(IOBuf::CREATE, 0); + EXPECT_EQ("", PktUtil::hexDump(buf)); +} + TEST(PktUtilTest, HexDump) { size_t length = 64; IOBuf buf(IOBuf::CREATE, length); diff --git a/fboss/agent/platforms/common/meru800bia/Meru800biaPlatformMapping.cpp b/fboss/agent/platforms/common/meru800bia/Meru800biaPlatformMapping.cpp index 3f4149d6787b2..329ef29f6285c 100644 --- a/fboss/agent/platforms/common/meru800bia/Meru800biaPlatformMapping.cpp +++ b/fboss/agent/platforms/common/meru800bia/Meru800biaPlatformMapping.cpp @@ -36,7 +36,7 @@ constexpr auto kJsonPlatformMappingStr = R"( "scope": 1 }, "supportedProfiles": { - "11": { + "49": { "pins": { "iphy": [ { @@ -70,7 +70,7 @@ constexpr auto kJsonPlatformMappingStr = R"( "scope": 0 }, "supportedProfiles": { - "11": { + "49": { "pins": { "iphy": [ { @@ -104,7 +104,7 @@ constexpr auto kJsonPlatformMappingStr = R"( "scope": 0 }, "supportedProfiles": { - "11": { + "49": { "pins": { "iphy": [ { @@ -138,7 +138,7 @@ constexpr auto kJsonPlatformMappingStr = R"( "scope": 0 }, "supportedProfiles": { - "11": { + "49": { "pins": { "iphy": [ { @@ -172,7 +172,7 @@ constexpr auto kJsonPlatformMappingStr = R"( "scope": 0 }, "supportedProfiles": { - "11": { + "49": { "pins": { "iphy": [ { @@ -206,7 +206,7 @@ constexpr auto kJsonPlatformMappingStr = R"( "scope": 0 }, "supportedProfiles": { - "11": { + "49": { "pins": { "iphy": [ { @@ -43099,31 +43099,31 @@ constexpr auto kJsonPlatformMappingStr = R"( }, { "factor": { - "profileID": 11 + "profileID": 45 }, "profile": { - "speed": 10000, + "speed": 400000, "iphy": { - "numLanes": 1, - "modulation": 1, - "fec": 1, + "numLanes": 4, + "modulation": 2, + "fec": 11, "medium": 1, - "interfaceType": 10 + "interfaceType": 12 } } }, { "factor": { - "profileID": 45 + "profileID": 49 }, "profile": { - "speed": 400000, + "speed": 100000, "iphy": { - "numLanes": 4, - "modulation": 2, - "fec": 11, + "numLanes": 1, + "modulation": 1, + "fec": 1, "medium": 1, - "interfaceType": 12 + "interfaceType": 10 } } }, @@ -43199,7 +43199,7 @@ constexpr auto kJsonDsfJ3ScaleTestPlatformMappingStr = R"( "scope": 1 }, "supportedProfiles": { - "11": { + "49": { "pins": { "iphy": [ { @@ -43233,7 +43233,7 @@ constexpr auto kJsonDsfJ3ScaleTestPlatformMappingStr = R"( "scope": 0 }, "supportedProfiles": { - "11": { + "49": { "pins": { "iphy": [ { @@ -43267,7 +43267,7 @@ constexpr auto kJsonDsfJ3ScaleTestPlatformMappingStr = R"( "scope": 0 }, "supportedProfiles": { - "11": { + "49": { "pins": { "iphy": [ { @@ -43301,7 +43301,7 @@ constexpr auto kJsonDsfJ3ScaleTestPlatformMappingStr = R"( "scope": 0 }, "supportedProfiles": { - "11": { + "49": { "pins": { "iphy": [ { @@ -43335,7 +43335,7 @@ constexpr auto kJsonDsfJ3ScaleTestPlatformMappingStr = R"( "scope": 0 }, "supportedProfiles": { - "11": { + "49": { "pins": { "iphy": [ { @@ -43369,7 +43369,7 @@ constexpr auto kJsonDsfJ3ScaleTestPlatformMappingStr = R"( "scope": 0 }, "supportedProfiles": { - "11": { + "49": { "pins": { "iphy": [ { @@ -71724,31 +71724,31 @@ constexpr auto kJsonDsfJ3ScaleTestPlatformMappingStr = R"( }, { "factor": { - "profileID": 11 + "profileID": 47 }, "profile": { - "speed": 10000, + "speed": 100000, "iphy": { "numLanes": 1, - "modulation": 1, - "fec": 1, - "medium": 1, - "interfaceType": 10 + "modulation": 2, + "fec": 11, + "medium": 2, + "interfaceType": 41 } } }, { "factor": { - "profileID": 47 + "profileID": 49 }, "profile": { "speed": 100000, "iphy": { "numLanes": 1, - "modulation": 2, - "fec": 11, - "medium": 2, - "interfaceType": 41 + "modulation": 1, + "fec": 1, + "medium": 1, + "interfaceType": 10 } } }, @@ -71809,7 +71809,7 @@ constexpr auto kJsonEdswPlatformMappingStr = R"( "scope": 1 }, "supportedProfiles": { - "11": { + "49": { "pins": { "iphy": [ { @@ -71843,7 +71843,7 @@ constexpr auto kJsonEdswPlatformMappingStr = R"( "scope": 0 }, "supportedProfiles": { - "11": { + "49": { "pins": { "iphy": [ { @@ -71877,7 +71877,7 @@ constexpr auto kJsonEdswPlatformMappingStr = R"( "scope": 0 }, "supportedProfiles": { - "11": { + "49": { "pins": { "iphy": [ { @@ -71911,7 +71911,7 @@ constexpr auto kJsonEdswPlatformMappingStr = R"( "scope": 0 }, "supportedProfiles": { - "11": { + "49": { "pins": { "iphy": [ { @@ -71945,7 +71945,7 @@ constexpr auto kJsonEdswPlatformMappingStr = R"( "scope": 0 }, "supportedProfiles": { - "11": { + "49": { "pins": { "iphy": [ { @@ -71979,7 +71979,7 @@ constexpr auto kJsonEdswPlatformMappingStr = R"( "scope": 0 }, "supportedProfiles": { - "11": { + "49": { "pins": { "iphy": [ { @@ -97454,13 +97454,13 @@ constexpr auto kJsonEdswPlatformMappingStr = R"( }, { "factor": { - "profileID": 11 + "profileID": 49 }, "profile": { - "speed": 10000, + "speed": 100000, "iphy": { "numLanes": 1, - "modulation": 1, + "modulation": 2, "fec": 1, "medium": 1, "interfaceType": 10 diff --git a/fboss/agent/state/AggregatePort.cpp b/fboss/agent/state/AggregatePort.cpp index 51d2b1e0510f8..150ad4dbdc72c 100644 --- a/fboss/agent/state/AggregatePort.cpp +++ b/fboss/agent/state/AggregatePort.cpp @@ -136,7 +136,8 @@ AggregatePort* AggregatePort::modify(std::shared_ptr* state) { // case C: is not CONFIGURED as a member of any AggregatePort bool AggregatePort::isIngressValid( const std::shared_ptr& state, - const std::unique_ptr& packet) { + const std::unique_ptr& packet, + const bool needAggPortUp) { auto physicalIngressPort = packet->getSrcPort(); auto owningAggregatePort = state->getAggregatePorts()->getAggregatePortForPort(physicalIngressPort); @@ -147,6 +148,9 @@ bool AggregatePort::isIngressValid( } CHECK(owningAggregatePort); + if (needAggPortUp) { + return owningAggregatePort->isUp(); + } auto physicalIngressForwardingState = owningAggregatePort->getForwardingState(physicalIngressPort); diff --git a/fboss/agent/state/AggregatePort.h b/fboss/agent/state/AggregatePort.h index 6d61e6e6fdac3..c86a764f63d90 100644 --- a/fboss/agent/state/AggregatePort.h +++ b/fboss/agent/state/AggregatePort.h @@ -336,7 +336,8 @@ class AggregatePort static bool isIngressValid( const std::shared_ptr& state, - const std::unique_ptr& packet); + const std::unique_ptr& packet, + const bool needAggPortUp = false); bool isUp() const; diff --git a/fboss/agent/state/SwitchSettings.h b/fboss/agent/state/SwitchSettings.h index b2652adf520f4..1a833ea10c832 100644 --- a/fboss/agent/state/SwitchSettings.h +++ b/fboss/agent/state/SwitchSettings.h @@ -557,19 +557,21 @@ class SwitchSettings } } - std::optional getReachabilityGroupSize() const { - if (auto reachabilityGroupSize = - cref()) { - return reachabilityGroupSize->toThrift(); + std::optional getReachabilityGroupListSize() const { + if (auto reachabilityGroupListSize = + cref()) { + return reachabilityGroupListSize->toThrift(); } return std::nullopt; } - void setReachabilityGroupSize(std::optional reachabilityGroupSize) { - if (!reachabilityGroupSize) { - ref().reset(); + void setReachabilityGroupListSize( + std::optional reachabilityGroupListSize) { + if (!reachabilityGroupListSize) { + ref().reset(); } else { - set(*reachabilityGroupSize); + set( + *reachabilityGroupListSize); } } diff --git a/fboss/agent/state/SwitchState.cpp b/fboss/agent/state/SwitchState.cpp index 194e295d6b4ea..4a3bf5db2c8b2 100644 --- a/fboss/agent/state/SwitchState.cpp +++ b/fboss/agent/state/SwitchState.cpp @@ -203,6 +203,12 @@ SwitchState::getRemoteSystemPorts() const { } std::shared_ptr SwitchState::getAcl(const std::string& name) const { + if (FLAGS_enable_acl_table_group) { + getAclTableGroups() + ->getNode(cfg::AclStage::INGRESS) + ->getAclTableMap() + ->getNodeIf(name); + } return getAcls()->getNodeIf(name); } diff --git a/fboss/agent/state/tests/MirrorTests.cpp b/fboss/agent/state/tests/MirrorTests.cpp index 83d7d9c36ca89..5d06bef0194b8 100644 --- a/fboss/agent/state/tests/MirrorTests.cpp +++ b/fboss/agent/state/tests/MirrorTests.cpp @@ -372,6 +372,31 @@ TEST_F(MirrorTest, PortWrongMirror) { publishWithFbossError(); } +TEST_F(MirrorTest, PortManyMirrors) { + config_.mirrors()->push_back(utility::getSFlowMirror( + "mirror1", + 8998, + 9889, + MirrorTest::tunnelDestination, + folly::IPAddress("10.0.0.1"), + MirrorTest::dscp, + true)); + config_.mirrors()->push_back(utility::getSFlowMirror( + "mirror2", + 8998, + 9889, + MirrorTest::tunnelDestination, + folly::IPAddress("10.0.0.2"), + MirrorTest::dscp, + true)); + publishWithStateUpdate(); + configurePortMirror("mirror1", PortID(1)); + configurePortMirror("mirror1", PortID(2)); + publishWithStateUpdate(); + configurePortMirror("mirror2", PortID(3)); + publishWithFbossError(); +} + TEST_F(MirrorTest, MirrorWrongPort) { config_.mirrors()->push_back(utility::getGREMirrorWithPort( "mirror0", "port129", MirrorTest::tunnelDestination)); diff --git a/fboss/agent/switch_config.thrift b/fboss/agent/switch_config.thrift index b0fdf0191f310..b5bbe9e98d83b 100644 --- a/fboss/agent/switch_config.thrift +++ b/fboss/agent/switch_config.thrift @@ -223,6 +223,8 @@ enum IpType { IP = 1, IP4 = 2, IP6 = 3, + ARP_REQUEST = 4, + ARP_REPLY = 5, } enum EtherType { @@ -232,6 +234,7 @@ enum EtherType { EAPOL = 0x888E, MACSEC = 0x88E5, LLDP = 0x88CC, + ARP = 0x0806, } struct Ttl { diff --git a/fboss/agent/switch_state.thrift b/fboss/agent/switch_state.thrift index 13680b3aeb984..539e12e747a12 100644 --- a/fboss/agent/switch_state.thrift +++ b/fboss/agent/switch_state.thrift @@ -388,7 +388,7 @@ struct SwitchSettingsFields { // When there's no IPv4 addresses configured, what address to use to source IPv4 ICMP packets from. 42: Address.BinaryAddress icmpV4UnavailableSrcAddress; // Switch property of reachability group size, for the use of input balanced mode. - 43: optional i32 reachabilityGroupSize; + 43: optional i32 reachabilityGroupListSize; } struct RoutePrefix { diff --git a/fboss/agent/test/AgentEnsembleTest.cpp b/fboss/agent/test/AgentEnsembleTest.cpp index 0ab9e42494d06..a760b860f0fb6 100644 --- a/fboss/agent/test/AgentEnsembleTest.cpp +++ b/fboss/agent/test/AgentEnsembleTest.cpp @@ -283,6 +283,25 @@ void AgentEnsembleTest::waitForLinkStatus( throw FbossError(msg); } +void AgentEnsembleTest::getAllHwPortStats( + std::map& hwPortStats) const { + checkWithRetry( + [&hwPortStats, this]() { + hwPortStats.clear(); + getSw()->getAllHwPortStats(hwPortStats); + for (const auto& [port, portStats] : hwPortStats) { + if (*portStats.timestamp__ref() == + hardware_stats_constants::STAT_UNINITIALIZED()) { + return false; + } + } + return !hwPortStats.empty(); + }, + 120, + std::chrono::milliseconds(1000), + " fetch all port stats"); +} + // Provided the timestamp of the last port stats collection, get another unique // set of valid port stats std::map AgentEnsembleTest::getNextUpdatedHwPortStats( @@ -291,6 +310,8 @@ std::map AgentEnsembleTest::getNextUpdatedHwPortStats( // TODO(Elangovan) do we need 120 retries? checkWithRetry( [&portStats, timestamp, this]() { + // clear the port stats between each retry + portStats.clear(); getSw()->getAllHwPortStats(portStats); // Since each port can have a unique timestamp, compare with the first // port diff --git a/fboss/agent/test/AgentEnsembleTest.h b/fboss/agent/test/AgentEnsembleTest.h index 0ccd343ad92d5..3feaef983a464 100644 --- a/fboss/agent/test/AgentEnsembleTest.h +++ b/fboss/agent/test/AgentEnsembleTest.h @@ -54,6 +54,8 @@ class AgentEnsembleTest : public ::testing::Test { void assertNoInDiscards(int maxNumDiscards = 0); void assertNoInErrors(int maxNumDiscards = 0); + void getAllHwPortStats(std::map& hwPortStats) const; + void reloadPlatformConfig(); std::map getFabricConnectivity( SwitchID switchId) const; diff --git a/fboss/agent/test/AgentHwTest.cpp b/fboss/agent/test/AgentHwTest.cpp index 67183e067fecb..e79d18e5d229b 100644 --- a/fboss/agent/test/AgentHwTest.cpp +++ b/fboss/agent/test/AgentHwTest.cpp @@ -6,6 +6,7 @@ #include "fboss/agent/hw/gen-cpp2/hardware_stats_constants.h" #include "fboss/agent/hw/test/ConfigFactory.h" #include "fboss/agent/hw/test/HwTestCoppUtils.h" +#include "fboss/agent/test/utils/AclTestUtils.h" #include "fboss/agent/test/utils/StatsTestUtils.h" #include "fboss/lib/CommonUtils.h" @@ -157,6 +158,12 @@ std::vector AgentHwTest::masterLogicalPortIds( return getAgentEnsemble()->masterLogicalPortIds(portTypes); } +std::vector AgentHwTest::masterLogicalPortIds( + const std::set& portTypes, + SwitchID switchId) const { + return getAgentEnsemble()->masterLogicalPortIds(portTypes, switchId); +} + void AgentHwTest::setSwitchDrainState( const cfg::SwitchConfig& curConfig, cfg::SwitchDrainState drainState) { @@ -179,10 +186,17 @@ void AgentHwTest::applySwitchDrainState(cfg::SwitchDrainState drainState) { cfg::SwitchConfig AgentHwTest::initialConfig( const AgentEnsemble& ensemble) const { - return utility::onePortPerInterfaceConfig( + auto config = utility::onePortPerInterfaceConfig( ensemble.getSw(), ensemble.masterLogicalPortIds(), true /*interfaceHasSubnet*/); + + if (FLAGS_enable_acl_table_group) { + utility::addAclTableGroup( + &config, cfg::AclStage::INGRESS, utility::getAclTableGroupName()); + utility::addDefaultAclTable(config); + } + return config; } void AgentHwTest::printProductionFeatures() const { diff --git a/fboss/agent/test/AgentHwTest.h b/fboss/agent/test/AgentHwTest.h index 8392029f7ae47..a58a0c80eea53 100644 --- a/fboss/agent/test/AgentHwTest.h +++ b/fboss/agent/test/AgentHwTest.h @@ -120,12 +120,18 @@ class AgentHwTest : public ::testing::Test { std::vector masterLogicalPortIds() const; std::vector masterLogicalPortIds( const std::set& portTypes) const; + std::vector masterLogicalPortIds( + const std::set& portTypes, + SwitchID switchId) const; std::vector masterLogicalInterfacePortIds() const { return masterLogicalPortIds({cfg::PortType::INTERFACE_PORT}); } std::vector masterLogicalFabricPortIds() const { return masterLogicalPortIds({cfg::PortType::FABRIC_PORT}); } + std::vector masterLogicalFabricPortIds(SwitchID switchId) const { + return masterLogicalPortIds({cfg::PortType::FABRIC_PORT}, switchId); + } void setSwitchDrainState( const cfg::SwitchConfig& curConfig, cfg::SwitchDrainState drainState); diff --git a/fboss/agent/test/BUCK b/fboss/agent/test/BUCK index 5d61f67ad3c6b..e21b702a406f0 100644 --- a/fboss/agent/test/BUCK +++ b/fboss/agent/test/BUCK @@ -118,11 +118,11 @@ cpp_unittest( "//folly:move_wrapper", "//folly:network_address", "//folly:string", + "//folly/coro:gtest_helpers", + "//folly/coro:timeout", + "//folly/coro:unbounded_queue", "//folly/executors:io_thread_pool_executor", "//folly/executors/thread_factory:named_thread_factory", - "//folly/experimental/coro:gtest_helpers", - "//folly/experimental/coro:timeout", - "//folly/experimental/coro:unbounded_queue", "//folly/io:iobuf", "//folly/logging:logging", "//folly/portability:gtest", diff --git a/fboss/agent/test/DsfSubscriberTests.cpp b/fboss/agent/test/DsfSubscriberTests.cpp index 8831dc14e4135..5c6d26021ee3a 100644 --- a/fboss/agent/test/DsfSubscriberTests.cpp +++ b/fboss/agent/test/DsfSubscriberTests.cpp @@ -25,6 +25,10 @@ using namespace facebook::fboss; +namespace { +constexpr auto kIntfNodeStart = 100; +} + namespace facebook::fboss { class DsfSubscriberTest : public ::testing::Test { public: @@ -107,45 +111,44 @@ TEST_F(DsfSubscriberTest, addSubscription) { EXPECT_EQ(sw_->getDsfSubscriber()->getSubscriptionInfo().size(), 0); // Insert 2 IN nodes - auto node5DsfConfig = makeDsfNodeCfg(5); + auto intfNodeCfg0 = makeDsfNodeCfg(kIntfNodeStart); sw_->updateStateBlocking( "Add IN node", [&](const std::shared_ptr& state) { auto newState = state->clone(); updateDsfInNode( newState->getDsfNodes()->modify(&newState), - node5DsfConfig, + intfNodeCfg0, /* add */ true); return newState; }); EXPECT_EQ( sw_->getDsfSubscriber()->getSubscriptionInfo().size(), - node5DsfConfig.loopbackIps()->size()); + intfNodeCfg0.loopbackIps()->size()); EXPECT_TRUE(verifySubscriptionState( - node5DsfConfig, sw_->getDsfSubscriber()->getSubscriptionInfo())); + intfNodeCfg0, sw_->getDsfSubscriber()->getSubscriptionInfo())); EXPECT_TRUE(verifyDsfSessionState( - node5DsfConfig, sw_->getDsfSubscriber()->getDsfSessionsThrift())); + intfNodeCfg0, sw_->getDsfSubscriber()->getDsfSessionsThrift())); - auto node6DsfConfig = makeDsfNodeCfg(6); + auto intfNodeCfg1 = makeDsfNodeCfg(kIntfNodeStart + 1); sw_->updateStateBlocking( "Add IN node", [&](const std::shared_ptr& state) { auto newState = state->clone(); updateDsfInNode( newState->getDsfNodes()->modify(&newState), - node6DsfConfig, + intfNodeCfg1, /* add */ true); return newState; }); EXPECT_EQ( sw_->getDsfSubscriber()->getSubscriptionInfo().size(), - node5DsfConfig.loopbackIps()->size() + - node6DsfConfig.loopbackIps()->size()); + intfNodeCfg0.loopbackIps()->size() + intfNodeCfg1.loopbackIps()->size()); EXPECT_TRUE(verifySubscriptionState( - node6DsfConfig, sw_->getDsfSubscriber()->getSubscriptionInfo())); + intfNodeCfg1, sw_->getDsfSubscriber()->getSubscriptionInfo())); EXPECT_TRUE(verifyDsfSessionState( - node6DsfConfig, sw_->getDsfSubscriber()->getDsfSessionsThrift())); + intfNodeCfg1, sw_->getDsfSubscriber()->getDsfSessionsThrift())); // Remove 2 IN nodes sw_->updateStateBlocking( @@ -153,11 +156,11 @@ TEST_F(DsfSubscriberTest, addSubscription) { auto newState = state->clone(); updateDsfInNode( newState->getDsfNodes()->modify(&newState), - node5DsfConfig, + intfNodeCfg0, /* add */ false); updateDsfInNode( newState->getDsfNodes()->modify(&newState), - node6DsfConfig, + intfNodeCfg1, /* add */ false); return newState; }); @@ -171,13 +174,13 @@ TEST_F(DsfSubscriberTest, failedDsfCounter) { CounterCache counters(sw_); auto failedDsfCounter = SwitchStats::kCounterPrefix + "failedDsfSubscription"; - auto node5DsfConfig = makeDsfNodeCfg(5); + auto intfNodeCfg0 = makeDsfNodeCfg(kIntfNodeStart); sw_->updateStateBlocking( "Add IN node", [&](const std::shared_ptr& state) { auto newState = state->clone(); updateDsfInNode( newState->getDsfNodes()->modify(&newState), - node5DsfConfig, + intfNodeCfg0, /* add */ true); return newState; }); @@ -185,15 +188,15 @@ TEST_F(DsfSubscriberTest, failedDsfCounter) { EXPECT_TRUE(counters.checkExist(failedDsfCounter)); EXPECT_EQ( - counters.value(failedDsfCounter), node5DsfConfig.loopbackIps()->size()); + counters.value(failedDsfCounter), intfNodeCfg0.loopbackIps()->size()); - auto node6DsfConfig = makeDsfNodeCfg(6); + auto intfNodeCfg1 = makeDsfNodeCfg(kIntfNodeStart + 1); sw_->updateStateBlocking( "Add IN node", [&](const std::shared_ptr& state) { auto newState = state->clone(); updateDsfInNode( newState->getDsfNodes()->modify(&newState), - node6DsfConfig, + intfNodeCfg1, /* add */ true); return newState; }); @@ -201,8 +204,7 @@ TEST_F(DsfSubscriberTest, failedDsfCounter) { EXPECT_EQ( counters.value(failedDsfCounter), - node5DsfConfig.loopbackIps()->size() + - node6DsfConfig.loopbackIps()->size()); + intfNodeCfg0.loopbackIps()->size() + intfNodeCfg1.loopbackIps()->size()); // Remove 2 IN nodes sw_->updateStateBlocking( @@ -210,11 +212,11 @@ TEST_F(DsfSubscriberTest, failedDsfCounter) { auto newState = state->clone(); updateDsfInNode( newState->getDsfNodes()->modify(&newState), - node5DsfConfig, + intfNodeCfg0, /* add */ false); updateDsfInNode( newState->getDsfNodes()->modify(&newState), - node6DsfConfig, + intfNodeCfg1, /* add */ false); return newState; }); diff --git a/fboss/agent/test/DsfSubscriptionTests.cpp b/fboss/agent/test/DsfSubscriptionTests.cpp index c811046f91eed..b48a092e21897 100644 --- a/fboss/agent/test/DsfSubscriptionTests.cpp +++ b/fboss/agent/test/DsfSubscriptionTests.cpp @@ -21,8 +21,10 @@ using ::testing::Return; namespace facebook::fboss { namespace { constexpr auto kRemoteSwitchIdBegin = 4; +constexpr auto kSwitchIdGap = 4; constexpr auto kSysPortBlockSize = 50; -constexpr auto kSysPortRangeMin = kRemoteSwitchIdBegin * kSysPortBlockSize; +constexpr auto kSysPortRangeMin = + (kRemoteSwitchIdBegin / kSwitchIdGap) * kSysPortBlockSize; constexpr auto intfV4AddrPrefix = "42.42.42."; constexpr auto intfV6AddrPrefix = "42::"; std::shared_ptr makeSysPortsForSwitchIds( @@ -30,7 +32,7 @@ std::shared_ptr makeSysPortsForSwitchIds( int numSysPorts = 1) { auto sysPorts = std::make_shared(); for (auto switchId : remoteSwitchIds) { - auto sysPortBegin = switchId * kSysPortBlockSize + 1; + auto sysPortBegin = (switchId / kSwitchIdGap) * kSysPortBlockSize + 1; for (auto sysPortId = sysPortBegin; sysPortId < sysPortBegin + numSysPorts; ++sysPortId) { sysPorts->addNode(makeSysPort(std::nullopt, sysPortId, switchId)); @@ -135,7 +137,7 @@ class DsfSubscriptionTest : public ::testing::Test { std::set remoteSwitchIds() const { std::set remoteSwitchIds; for (auto i = 0; i < kNumRemoteSwitchAsics; ++i) { - remoteSwitchIds.insert(SwitchID(kRemoteSwitchIdBegin + i)); + remoteSwitchIds.insert(SwitchID(kRemoteSwitchIdBegin + i * kSwitchIdGap)); } return remoteSwitchIds; } diff --git a/fboss/agent/test/SwSwitchTest.cpp b/fboss/agent/test/SwSwitchTest.cpp index cda82942efb82..1c9807daf6b09 100644 --- a/fboss/agent/test/SwSwitchTest.cpp +++ b/fboss/agent/test/SwSwitchTest.cpp @@ -234,6 +234,7 @@ TEST_F(SwSwitchTest, multiSwitchFb303Stats) { globalStats.global_drops() = val; globalStats.global_reachability_drops() = val; globalStats.packet_integrity_drops() = val; + globalStats.vsq_resource_exhaustion_drops() = val; globalStats.dram_enqueued_bytes() = val; globalStats.dram_dequeued_bytes() = val; globalStats.dram_blocked_time_ns() = val; @@ -263,6 +264,7 @@ TEST_F(SwSwitchTest, multiSwitchFb303Stats) { EXPECT_EQ(counters.value("global_drops.sum"), expectedVal); EXPECT_EQ(counters.value("global_reachability_drops.sum"), expectedVal); EXPECT_EQ(counters.value("packet_integrity_drops.sum"), expectedVal); + EXPECT_EQ(counters.value("vsq_resource_exhaustion_drops.sum"), expectedVal); EXPECT_EQ(counters.value("dram_enqueued_bytes.sum"), expectedVal); EXPECT_EQ(counters.value("dram_dequeued_bytes.sum"), expectedVal); EXPECT_EQ(counters.value("dram_blocked_time_ns.sum"), expectedVal); diff --git a/fboss/agent/test/TestEnsembleIf.cpp b/fboss/agent/test/TestEnsembleIf.cpp index aecc03767854c..e4c2971f3cfa9 100644 --- a/fboss/agent/test/TestEnsembleIf.cpp +++ b/fboss/agent/test/TestEnsembleIf.cpp @@ -55,6 +55,10 @@ std::vector TestEnsembleIf::getL3Asics() const { return l3Asics; } +int TestEnsembleIf::getNumL3Asics() const { + return getHwAsicTable()->getL3Asics().size(); +} + std::vector TestEnsembleIf::masterLogicalSysPortIds() const { std::vector sysPorts; for (const auto& asic : getHwAsicTable()->getL3Asics()) { diff --git a/fboss/agent/test/TestEnsembleIf.h b/fboss/agent/test/TestEnsembleIf.h index b080f51be1b2a..f8cd96920ce76 100644 --- a/fboss/agent/test/TestEnsembleIf.h +++ b/fboss/agent/test/TestEnsembleIf.h @@ -112,6 +112,7 @@ class TestEnsembleIf : public HwSwitchCallback { virtual const PlatformMapping* getPlatformMapping() const = 0; virtual cfg::SwitchConfig getCurrentConfig() const = 0; std::vector getL3Asics() const; + int getNumL3Asics() const; std::vector masterLogicalSysPortIds() const; private: diff --git a/fboss/agent/test/TestUtils.cpp b/fboss/agent/test/TestUtils.cpp index 58e60d29afce8..c0afd17b7991d 100644 --- a/fboss/agent/test/TestUtils.cpp +++ b/fboss/agent/test/TestUtils.cpp @@ -152,10 +152,15 @@ shared_ptr setAllPortState( } std::vector getLoopbackIps(int64_t switchIdVal) { - CHECK_LT(switchIdVal, 10) << " Switch Id >= 10, not supported"; - - auto v6 = folly::sformat("20{}::1/64", switchIdVal); - auto v4 = folly::sformat("20{}.0.0.1/24", switchIdVal); + // Starts loopback IP with 200:: + static constexpr auto firstOctetLimit = 56; + static constexpr auto switchIdLimit = firstOctetLimit * 255; + CHECK_LE(switchIdVal, switchIdLimit) + << "SwitchId > " << switchIdLimit << " not supported"; + auto firstOctet = 200 + switchIdVal % firstOctetLimit; + auto secondOctet = switchIdVal / firstOctetLimit; + auto v6 = folly::to(firstOctet, ":", secondOctet, "::1/64"); + auto v4 = folly::to(firstOctet, ".", secondOctet, ".0.1/24"); return {v6, v4}; } @@ -178,41 +183,6 @@ void addRecyclePortRif(const cfg::DsfNode& myNode, cfg::SwitchConfig& cfg) { cfg.interfaces()->push_back(recyclePortRif); } -cfg::SwitchConfig testConfigFabricSwitch() { - static constexpr auto kPortCount = 20; - cfg::SwitchConfig cfg; - cfg.ports()->resize(kPortCount); - cfg.switchSettings()->switchIdToSwitchInfo() = {std::make_pair( - kFabricSwitchIdBegin, - createSwitchInfo( - cfg::SwitchType::FABRIC, - cfg::AsicType::ASIC_TYPE_MOCK, - 0, /* port id range min */ - 1023, /* port id range max */ - 0, /* switchIndex */ - std::nullopt, /* systemPort min */ - std::nullopt, /* systemPort max */ - std::nullopt, /* switchMac */ - "68:00" /* connection handle */))}; - - for (int p = 0; p < kPortCount; ++p) { - cfg.ports()[p].logicalID() = p + 1; - cfg.ports()[p].name() = folly::to("port", p + 1); - cfg.ports()[p].state() = cfg::PortState::ENABLED; - cfg.ports()[p].speed() = cfg::PortSpeed::HUNDREDG; - cfg.ports()[p].speed() = cfg::PortSpeed::TWENTYFIVEG; - cfg.ports()[p].profileID() = - cfg::PortProfileID::PROFILE_25G_1_NRZ_CL74_COPPER; - cfg.ports()[p].portType() = cfg::PortType::FABRIC_PORT; - } - auto myNode = - makeDsfNodeCfg(kFabricSwitchIdBegin, cfg::DsfNodeType::FABRIC_NODE); - cfg.dsfNodes()->insert({*myNode.switchId(), myNode}); - cfg::DsfNode inNode = makeDsfNodeCfg(0); - cfg.dsfNodes()->insert({*inNode.switchId(), inNode}); - return cfg; -} - cfg::SwitchConfig testConfigAImpl(bool isMhnic, cfg::SwitchType switchType) { if (switchType == cfg::SwitchType::FABRIC) { return testConfigFabricSwitch(); @@ -453,7 +423,8 @@ cfg::SwitchConfig testConfigBImpl() { // Add a fabric node to DSF node as well. In prod DsfNode map will have // both IN and FN nodes - auto fnNode = makeDsfNodeCfg(20, cfg::DsfNodeType::FABRIC_NODE); + auto fnNode = + makeDsfNodeCfg(kFabricSwitchIdBegin, cfg::DsfNodeType::FABRIC_NODE); cfg.dsfNodes()->insert({*fnNode.switchId(), fnNode}); return cfg; @@ -506,7 +477,12 @@ std::tuple makeNbrs() { return std::make_pair(ndpTable, arpTable); } -cfg::DsfNode makeDsfNodeCfg(int64_t switchId, cfg::DsfNodeType type) { +cfg::DsfNode makeDsfNodeCfg( + int64_t switchId, + cfg::DsfNodeType type, + std::optional clusterId, + cfg::AsicType asicType, + std::optional fabricLevel) { cfg::DsfNode dsfNodeCfg; dsfNodeCfg.switchId() = switchId; dsfNodeCfg.name() = folly::sformat("dsfNodeCfg{}", switchId); @@ -520,7 +496,19 @@ cfg::DsfNode makeDsfNodeCfg(int64_t switchId, cfg::DsfNodeType type) { dsfNodeCfg.loopbackIps() = getLoopbackIps(switchId); dsfNodeCfg.nodeMac() = "02:00:00:00:0F:0B"; } - dsfNodeCfg.asicType() = cfg::AsicType::ASIC_TYPE_MOCK; + dsfNodeCfg.asicType() = asicType; + dsfNodeCfg.platformType() = type == cfg::DsfNodeType::INTERFACE_NODE + ? PlatformType::PLATFORM_MERU800BIA + : PlatformType::PLATFORM_MERU800BFA; + if (clusterId.has_value()) { + dsfNodeCfg.clusterId() = clusterId.value(); + } + if (fabricLevel.has_value()) { + CHECK_EQ( + static_cast(type), + static_cast(cfg::DsfNodeType::FABRIC_NODE)); + dsfNodeCfg.fabricLevel() = fabricLevel.value(); + } return dsfNodeCfg; } @@ -528,6 +516,125 @@ cfg::SwitchConfig testConfigA(cfg::SwitchType switchType) { return testConfigAImpl(false, switchType); } +cfg::SwitchConfig testConfigFabricSwitch( + bool dualStage, + int fabricLevel, + int parallLinkPerNode, + std::optional dualStageNeighborLevel2FabricNodes) { + static constexpr auto kPortCount = 20; + static constexpr auto switchIdGap = 4; + + // FabricLevel: FDSW - 1, SDSW - 2. Also ensure config is dual stage if + // fabricLevel is 2. + CHECK(fabricLevel == 1 || (fabricLevel == 2 && dualStage)); + // If dual stage and fabricLevel == 1, dualStageLevel2NeighborFabricNodes is + // needed, and no larger than the total number of neighbor nodes. + if (dualStage && fabricLevel == 1) { + CHECK(dualStageNeighborLevel2FabricNodes.has_value()); + CHECK_LE( + dualStageNeighborLevel2FabricNodes.value(), + kPortCount / parallLinkPerNode); + } + + cfg::SwitchConfig cfg; + cfg.ports()->resize(kPortCount); + cfg.switchSettings()->switchIdToSwitchInfo() = {std::make_pair( + kFabricSwitchIdBegin, + createSwitchInfo( + cfg::SwitchType::FABRIC, + cfg::AsicType::ASIC_TYPE_MOCK, + 0, /* port id range min */ + 1023, /* port id range max */ + 0, /* switchIndex */ + std::nullopt, /* systemPort min */ + std::nullopt, /* systemPort max */ + std::nullopt, /* switchMac */ + "68:00" /* connection handle */))}; + + for (int p = 0; p < kPortCount; ++p) { + cfg.ports()[p].logicalID() = p + 1; + cfg.ports()[p].name() = folly::to("port", p + 1); + cfg.ports()[p].state() = cfg::PortState::ENABLED; + cfg.ports()[p].speed() = cfg::PortSpeed::TWENTYFIVEG; + cfg.ports()[p].profileID() = + cfg::PortProfileID::PROFILE_25G_1_NRZ_CL74_COPPER; + cfg.ports()[p].portType() = cfg::PortType::FABRIC_PORT; + } + auto myNode = + makeDsfNodeCfg(kFabricSwitchIdBegin, cfg::DsfNodeType::FABRIC_NODE); + cfg.dsfNodes()->insert({*myNode.switchId(), myNode}); + + auto nextFabricSwitchId = kFabricSwitchIdBegin + switchIdGap; + auto nextVoqSwitchId = kVoqSwitchIdBegin; + + for (int i = 0; i < kPortCount / parallLinkPerNode; i++) { + // Single Stage - All nodes are interface node with no clusterId + // Dual Stage FDSW - dualStageNeighborLevel2FabricNodes fabric node and rest + // are interface node with same cluterId. Dual Stage SDSW = all farbic node + // with different clusterId + std::optional clusterId; + std::optional remoteFabricLevel; + if (dualStage) { + if (fabricLevel == 2) { + clusterId = i + 1; + remoteFabricLevel = 1; + } else if (i >= dualStageNeighborLevel2FabricNodes.value()) { + clusterId = 1; + remoteFabricLevel = 2; + } + } + + cfg::DsfNodeType remoteDsfNodeType; + if (!dualStage) { + remoteDsfNodeType = cfg::DsfNodeType::INTERFACE_NODE; + } else if (fabricLevel == 1) { + remoteDsfNodeType = i < dualStageNeighborLevel2FabricNodes.value() + ? cfg::DsfNodeType::FABRIC_NODE + : cfg::DsfNodeType::INTERFACE_NODE; + } else { + remoteDsfNodeType = cfg::DsfNodeType::FABRIC_NODE; + } + + auto asicType = remoteDsfNodeType == cfg::DsfNodeType::FABRIC_NODE + ? cfg::AsicType::ASIC_TYPE_RAMON3 + : cfg::AsicType::ASIC_TYPE_JERICHO3; + cfg::DsfNode remoteNode = makeDsfNodeCfg( + remoteDsfNodeType == cfg::DsfNodeType::FABRIC_NODE ? nextFabricSwitchId + : nextVoqSwitchId, + remoteDsfNodeType, + clusterId, + asicType, + remoteDsfNodeType == cfg::DsfNodeType::FABRIC_NODE ? remoteFabricLevel + : std::nullopt); + cfg.dsfNodes()->insert({*remoteNode.switchId(), remoteNode}); + + if (remoteDsfNodeType == cfg::DsfNodeType::FABRIC_NODE) { + nextFabricSwitchId += switchIdGap; + } else { + nextVoqSwitchId += switchIdGap; + } + + for (int j = 0; j < parallLinkPerNode; j++) { + cfg::PortNeighbor portNeighbor; + portNeighbor.remoteSystem() = *remoteNode.name(); + portNeighbor.remotePort() = folly::to("fab1/", j + 1, "/2"); + auto portIdx = i * parallLinkPerNode + j; + cfg.ports()[portIdx].expectedNeighborReachability() = {portNeighbor}; + } + } + + // Insert one more node in different cluster, such that reachability group + // will be processed as dual stage. + if (dualStage && parallLinkPerNode == 1) { + cfg::DsfNode cluster2Node = makeDsfNodeCfg( + nextVoqSwitchId, cfg::DsfNodeType::INTERFACE_NODE, 2 /* clusterId */); + cfg.dsfNodes()->insert({*cluster2Node.switchId(), cluster2Node}); + + nextVoqSwitchId += switchIdGap; + } + return cfg; +} + cfg::SwitchConfig testConfigB() { return testConfigBImpl(); } diff --git a/fboss/agent/test/TestUtils.h b/fboss/agent/test/TestUtils.h index 1f03a496b2532..dfb6f0b73c6b2 100644 --- a/fboss/agent/test/TestUtils.h +++ b/fboss/agent/test/TestUtils.h @@ -160,7 +160,10 @@ std::unique_ptr setupMockSwitchWithHW( SwitchFlags flags); cfg::DsfNode makeDsfNodeCfg( int64_t switchId = 0, - cfg::DsfNodeType type = cfg::DsfNodeType::INTERFACE_NODE); + cfg::DsfNodeType type = cfg::DsfNodeType::INTERFACE_NODE, + std::optional clusterId = std::nullopt, + cfg::AsicType asicType = cfg::AsicType::ASIC_TYPE_MOCK, + std::optional fabricLevel = std::nullopt); std::shared_ptr makeSysPort( const std::optional& qosPolicy, @@ -290,7 +293,11 @@ std::shared_ptr bringAllPortsDown( /* * Fabric switch test config */ -cfg::SwitchConfig testConfigFabricSwitch(); +cfg::SwitchConfig testConfigFabricSwitch( + bool dualStage = false, + int fabricLevel = 1, + int parallLinkPerNode = 4, + std::optional dualStageLevel2FabricNodes = std::nullopt); /* * The returned configuration object, if applied to a SwitchState with ports * 1-20, will yield the same SwitchState as that returned by testStateA(). diff --git a/fboss/agent/test/ThriftServerTest.cpp b/fboss/agent/test/ThriftServerTest.cpp index 9cf0a9570424a..65746c6c02aa2 100644 --- a/fboss/agent/test/ThriftServerTest.cpp +++ b/fboss/agent/test/ThriftServerTest.cpp @@ -28,9 +28,9 @@ #include #include "fboss/agent/test/MultiSwitchTestServer.h" -#include -#include -#include +#include +#include +#include #include #include @@ -439,11 +439,16 @@ CO_TEST_F(ThriftServerTest, receivePktHandler) { MockPlatform::getMockLocalMac())); rxPkt.port() = 1; rxPkt.vlan() = 1; + rxPkt.length() = (*rxPkt.data())->computeChainDataLength(); co_yield std::move(rxPkt); }()); EXPECT_TRUE(ret); - counters.update(); - counters.checkDelta(SwitchStats::kCounterPrefix + "ipv4.mine.sum", 1); + WITH_RETRIES({ + counters.update(); + EXPECT_EVENTUALLY_EQ( + counters.value(SwitchStats::kCounterPrefix + "ipv4.mine.sum"), + counters.prevValue(SwitchStats::kCounterPrefix + "ipv4.mine.sum") + 1); + }); } CO_TEST_F(ThriftServerTest, transmitPktHandler) { diff --git a/fboss/agent/test/ThriftTest.cpp b/fboss/agent/test/ThriftTest.cpp index 610498965029f..2e78b4ab6ad40 100644 --- a/fboss/agent/test/ThriftTest.cpp +++ b/fboss/agent/test/ThriftTest.cpp @@ -536,7 +536,8 @@ TYPED_TEST(ThriftTestAllSwitchTypes, getDsfNodes) { EXPECT_THROW(handler.getDsfNodes(dsfNodes), FbossError); } else { handler.getDsfNodes(dsfNodes); - EXPECT_EQ(dsfNodes.size(), 2); + EXPECT_EQ( + dsfNodes.size(), this->sw_->getState()->getDsfNodes()->numNodes()); } } diff --git a/fboss/agent/test/agent_hw_tests/AgentAclCounterTests.cpp b/fboss/agent/test/agent_hw_tests/AgentAclCounterTests.cpp index a5d72b9c6955f..cafd78d58d1a3 100644 --- a/fboss/agent/test/agent_hw_tests/AgentAclCounterTests.cpp +++ b/fboss/agent/test/agent_hw_tests/AgentAclCounterTests.cpp @@ -39,28 +39,14 @@ enum AclType { namespace facebook::fboss { -template -struct EnableMultiAclTable { - static constexpr auto multiAclTableEnabled = enableMultiAclTable; -}; - -using TestTypes = - ::testing::Types, EnableMultiAclTable>; - -template class AgentAclCounterTest : public AgentHwTest { - static auto constexpr isMultiAclEnabled = - EnableMultiAclTableT::multiAclTableEnabled; - public: cfg::AclActionType aclActionType_ = cfg::AclActionType::PERMIT; uint8_t roceReservedByte_ = utility::kRoceReserved; std::vector getProductionFeaturesVerified() const override { - if constexpr (std::is_same_v< - EnableMultiAclTableT, - EnableMultiAclTable>) { + if (!FLAGS_enable_acl_table_group) { return { production_features::ProductionFeature::ACL_COUNTER, production_features::ProductionFeature::SINGLE_ACL_TABLE}; @@ -73,7 +59,6 @@ class AgentAclCounterTest : public AgentHwTest { protected: void SetUp() override { - FLAGS_enable_acl_table_group = isMultiAclEnabled; AgentHwTest::SetUp(); if (IsSkipped()) { return; @@ -87,7 +72,7 @@ class AgentAclCounterTest : public AgentHwTest { ensemble.getSw(), ensemble.masterLogicalPortIds(), true /*interfaceHasSubnet*/); - if (isMultiAclEnabled) { + if (FLAGS_enable_acl_table_group) { utility::addAclTableGroup( &cfg, cfg::AclStage::INGRESS, utility::getAclTableGroupName()); utility::addDefaultAclTable(cfg); @@ -398,7 +383,7 @@ class AgentAclCounterTest : public AgentHwTest { verifyAcrossWarmBoots(setup, verify); } - auto verifyAclType(bool bumpOnHit, bool frontPanel, AclType aclType) { + void verifyAclType(bool bumpOnHit, bool frontPanel, AclType aclType) { auto egressPort = helper_->ecmpPortDescriptorAt(0).phyPortID(); auto pktsBefore = *getNextUpdatedPortStats(egressPort).outUnicastPkts__ref(); @@ -512,46 +497,44 @@ class AgentAclCounterTest : public AgentHwTest { std::unique_ptr helper_; }; -TYPED_TEST_SUITE(AgentAclCounterTest, TestTypes); - // Verify that traffic arrive on a front panel port increments ACL counter. -TYPED_TEST(AgentAclCounterTest, VerifyCounterBumpOnTtlHitFrontPanel) { +TEST_F(AgentAclCounterTest, VerifyCounterBumpOnTtlHitFrontPanel) { this->counterBumpOnHitHelper( true /* bump on hit */, true /* front panel port */, {AclType::TCP_TTLD, AclType::UDP_TTLD}); } -TYPED_TEST(AgentAclCounterTest, VerifyCounterBumpOnSportHitFrontPanel) { +TEST_F(AgentAclCounterTest, VerifyCounterBumpOnSportHitFrontPanel) { this->counterBumpOnHitHelper( true /* bump on hit */, true /* front panel port */, {AclType::SRC_PORT}); } -TYPED_TEST(AgentAclCounterTest, VerifyCounterBumpOnL4DstportHitFrontPanel) { +TEST_F(AgentAclCounterTest, VerifyCounterBumpOnL4DstportHitFrontPanel) { this->counterBumpOnHitHelper( true /* bump on hit */, true /* front panel port */, {AclType::L4_DST_PORT}); } -TYPED_TEST(AgentAclCounterTest, VerifyCounterBumpOnSportHitFrontPanelWithDrop) { +TEST_F(AgentAclCounterTest, VerifyCounterBumpOnSportHitFrontPanelWithDrop) { this->aclActionType_ = cfg::AclActionType::DENY; this->counterBumpOnHitHelper( true /* bump on hit */, true /* front panel port */, {AclType::SRC_PORT}); } // Verify that traffic originating on the CPU increments ACL counter. -TYPED_TEST(AgentAclCounterTest, VerifyCounterBumpOnTtlHitCpu) { +TEST_F(AgentAclCounterTest, VerifyCounterBumpOnTtlHitCpu) { this->counterBumpOnHitHelper( true /* bump on hit */, false /* cpu port */, {AclType::TCP_TTLD, AclType::UDP_TTLD}); } -TYPED_TEST(AgentAclCounterTest, VerifyCounterBumpOnSportHitCpu) { +TEST_F(AgentAclCounterTest, VerifyCounterBumpOnSportHitCpu) { this->counterBumpOnHitHelper( true /* bump on hit */, false /* cpu port */, {AclType::SRC_PORT}); } // Verify that traffic arrive on a front panel port increments ACL counter. -TYPED_TEST(AgentAclCounterTest, VerifyCounterNoTtlHitNoBumpFrontPanel) { +TEST_F(AgentAclCounterTest, VerifyCounterNoTtlHitNoBumpFrontPanel) { this->counterBumpOnHitHelper( false /* no hit, no bump */, true /* front panel port */, @@ -559,18 +542,18 @@ TYPED_TEST(AgentAclCounterTest, VerifyCounterNoTtlHitNoBumpFrontPanel) { } // Verify that traffic originating on the CPU increments ACL counter. -TYPED_TEST(AgentAclCounterTest, VerifyCounterNoHitNoBumpCpu) { +TEST_F(AgentAclCounterTest, VerifyCounterNoHitNoBumpCpu) { this->counterBumpOnHitHelper( false /* no hit, no bump */, false /* cpu port */, {AclType::TCP_TTLD, AclType::UDP_TTLD}); } -TYPED_TEST(AgentAclCounterTest, VerifyAclPrioritySportHitFrontPanel) { +TEST_F(AgentAclCounterTest, VerifyAclPrioritySportHitFrontPanel) { this->aclPriorityTestHelper(); } -TYPED_TEST(AgentAclCounterTest, VerifyAclPriorityL4DstportHitFrontPanel) { +TEST_F(AgentAclCounterTest, VerifyAclPriorityL4DstportHitFrontPanel) { this->aclPriorityTestHelper2(); } @@ -578,8 +561,7 @@ TYPED_TEST(AgentAclCounterTest, VerifyAclPriorityL4DstportHitFrontPanel) { * UDF Acls are not supported on SAI and multi ACL. So we only test with * multi acl disabled for now. */ -class AgentUdfAclCounterTest - : public AgentAclCounterTest> { +class AgentUdfAclCounterTest : public AgentAclCounterTest { protected: cfg::SwitchConfig initialConfig( const AgentEnsemble& ensemble) const override { @@ -721,8 +703,7 @@ TEST_F(AgentUdfAclCounterTest, VerifyUdfMinusUdfHash) { verifyAcrossWarmBoots(setup, verify, setupPostWarmboot, verify); } -class AgentBthOpcodeAclCounterTest - : public AgentAclCounterTest> { +class AgentBthOpcodeAclCounterTest : public AgentAclCounterTest { public: std::vector getProductionFeaturesVerified() const override { @@ -745,8 +726,7 @@ TEST_F( * Flowlet Acls are not supported on SAI and multi ACL. So we only test with * multi acl disabled for now. */ -class AgentFlowletAclCounterTest - : public AgentAclCounterTest> { +class AgentFlowletAclCounterTest : public AgentAclCounterTest { public: std::vector getProductionFeaturesVerified() const override { diff --git a/fboss/agent/test/agent_hw_tests/AgentAclPriorityTests.cpp b/fboss/agent/test/agent_hw_tests/AgentAclPriorityTests.cpp index 5e90ae7cac2da..01a6d01579e11 100644 --- a/fboss/agent/test/agent_hw_tests/AgentAclPriorityTests.cpp +++ b/fboss/agent/test/agent_hw_tests/AgentAclPriorityTests.cpp @@ -39,30 +39,15 @@ void addAclEntry(cfg::SwitchConfig& cfg, cfg::AclEntry* acl) { namespace facebook::fboss { -template -struct EnableMultiAclTable { - static constexpr auto multiAclTableEnabled = enableMultiAclTable; -}; - -using TestTypes = - ::testing::Types, EnableMultiAclTable>; - -template class AgentAclPriorityTest : public AgentHwTest { - static auto constexpr isMultiAclEnabled = - EnableMultiAclTableT::multiAclTableEnabled; - void setCmdLineFlagOverrides() const override { - FLAGS_enable_acl_table_group = isMultiAclEnabled; AgentHwTest::setCmdLineFlagOverrides(); } public: std::vector getProductionFeaturesVerified() const override { - if constexpr (std::is_same_v< - EnableMultiAclTableT, - EnableMultiAclTable>) { + if (FLAGS_enable_acl_table_group) { return {production_features::ProductionFeature::SINGLE_ACL_TABLE}; } else { return {production_features::ProductionFeature::MULTI_ACL_TABLE}; @@ -76,7 +61,7 @@ class AgentAclPriorityTest : public AgentHwTest { ensemble.getSw(), ensemble.masterLogicalPortIds(), true /*interfaceHasSubnet*/); - if (isMultiAclEnabled) { + if (FLAGS_enable_acl_table_group) { utility::addAclTableGroup( &cfg, cfg::AclStage::INGRESS, utility::getAclTableGroupName()); utility::addDefaultAclTable(cfg); @@ -111,11 +96,9 @@ class AgentAclPriorityTest : public AgentHwTest { } }; -TYPED_TEST_SUITE(AgentAclPriorityTest, TestTypes); - // This test verifies that trafficPolicy configuration have no influence on // ACL entry priority -TYPED_TEST(AgentAclPriorityTest, CheckAclPriorityOrder) { +TEST_F(AgentAclPriorityTest, CheckAclPriorityOrder) { const folly::IPAddress kIp("2400::1"); auto setup = [this, kIp]() { auto newCfg = this->getSw()->getConfig(); @@ -154,7 +137,7 @@ TYPED_TEST(AgentAclPriorityTest, CheckAclPriorityOrder) { this->verifyAcrossWarmBoots(setup, verify); } -TYPED_TEST(AgentAclPriorityTest, CheckAclPriortyOrderInsertMiddle) { +TEST_F(AgentAclPriorityTest, CheckAclPriortyOrderInsertMiddle) { auto setup = [this]() { auto newCfg = this->getSw()->getConfig(); this->addDenyPortAcl(newCfg, "A"); @@ -184,7 +167,7 @@ TYPED_TEST(AgentAclPriorityTest, CheckAclPriortyOrderInsertMiddle) { * This unit test case is to test we won't crash cause we're using aclName as * key of the aclMap in S/W while using priority as key of aclTable in H/W */ -TYPED_TEST(AgentAclPriorityTest, AclNameChange) { +TEST_F(AgentAclPriorityTest, AclNameChange) { auto setup = [this]() { auto newCfg = this->getSw()->getConfig(); this->addDenyPortAcl(newCfg, "A"); @@ -212,7 +195,7 @@ TYPED_TEST(AgentAclPriorityTest, AclNameChange) { this->verifyAcrossWarmBoots(setup, verify); } -TYPED_TEST(AgentAclPriorityTest, AclsChanged) { +TEST_F(AgentAclPriorityTest, AclsChanged) { const folly::IPAddress kIp("2400::1"); auto setup = [this, kIp]() { auto config = this->getSw()->getConfig(); @@ -236,7 +219,7 @@ TYPED_TEST(AgentAclPriorityTest, AclsChanged) { this->verifyAcrossWarmBoots(setup, []() {}, setupPostWb, []() {}); } -TYPED_TEST(AgentAclPriorityTest, Reprioritize) { +TEST_F(AgentAclPriorityTest, Reprioritize) { auto setup = [=, this]() { auto config = this->getSw()->getConfig(); this->addPermitIpAcl(config, "B", folly::IPAddress("1::2")); diff --git a/fboss/agent/test/agent_hw_tests/AgentFlowletSwitchingTests.cpp b/fboss/agent/test/agent_hw_tests/AgentFlowletSwitchingTests.cpp index 72f905aa62b63..3b7d8e104975f 100644 --- a/fboss/agent/test/agent_hw_tests/AgentFlowletSwitchingTests.cpp +++ b/fboss/agent/test/agent_hw_tests/AgentFlowletSwitchingTests.cpp @@ -526,6 +526,17 @@ class AgentFlowletSwitchingTest : public AgentAclCounterTestBase { } }; +class AgentFlowletAclPriorityTest : public AgentFlowletSwitchingTest { + public: + std::vector + getProductionFeaturesVerified() const override { + return { + production_features::ProductionFeature::DLB, + production_features::ProductionFeature::UDF_WR_IMMEDIATE_ACL, + production_features::ProductionFeature::SINGLE_ACL_TABLE}; + } +}; + // empty to UDF A TEST_F(AgentFlowletSwitchingTest, VerifyFlowletToUdfFlowlet) { flowletSwitchingAclHitHelper(AclType::FLOWLET, AclType::UDF_FLOWLET); @@ -606,6 +617,67 @@ TEST_F(AgentFlowletSwitchingTest, VerifyUdfAckWithNakToUdfNak) { flowletSwitchingAclHitHelper(AclType::UDF_ACK_WITH_NAK, AclType::UDF_NAK); } +// Skip this and next test due to lack of TCAM in ACL table on TH3 +TEST_F(AgentFlowletAclPriorityTest, VerifyUdfAclPriority) { + auto setup = [this]() { + this->setup(); + auto newCfg{initialConfig(*getAgentEnsemble())}; + // production priorities + addAclAndStat(&newCfg, AclType::UDF_NAK); + addAclAndStat(&newCfg, AclType::UDF_ACK); + addAclAndStat(&newCfg, AclType::UDF_WR_IMM_ZERO); + addAclAndStat(&newCfg, AclType::UDF_FLOWLET); + // Keep this at the end since each of the above calls update udfConfig + // differently + newCfg.udfConfig() = utility::addUdfAclConfig( + utility::kUdfOffsetBthOpcode | utility::kUdfOffsetBthReserved | + utility::kUdfOffsetAethSyndrome | utility::kUdfOffsetRethDmaLength); + applyNewConfig(newCfg); + }; + + auto verify = [this]() { + verifyAcl(AclType::UDF_NAK); + verifyAcl(AclType::UDF_ACK); + verifyAcl(AclType::UDF_WR_IMM_ZERO); + verifyAcl(AclType::UDF_FLOWLET); + }; + + verifyAcrossWarmBoots(setup, verify); +} + +TEST_F(AgentFlowletAclPriorityTest, VerifyUdfAclPriorityWB) { + auto setup = [this]() { + this->setup(); + auto newCfg{initialConfig(*getAgentEnsemble())}; + applyNewConfig(newCfg); + }; + + auto setupPostWarmboot = [this]() { + this->setup(); + auto newCfg{initialConfig(*getAgentEnsemble())}; + // production priorities + addAclAndStat(&newCfg, AclType::UDF_NAK); + addAclAndStat(&newCfg, AclType::UDF_ACK); + addAclAndStat(&newCfg, AclType::UDF_WR_IMM_ZERO); + addAclAndStat(&newCfg, AclType::UDF_FLOWLET); + // Keep this at the end since each of the above calls update udfConfig + // differently + newCfg.udfConfig() = utility::addUdfAclConfig( + utility::kUdfOffsetBthOpcode | utility::kUdfOffsetBthReserved | + utility::kUdfOffsetAethSyndrome | utility::kUdfOffsetRethDmaLength); + applyNewConfig(newCfg); + }; + + auto verifyPostWarmboot = [this]() { + verifyAcl(AclType::UDF_NAK); + verifyAcl(AclType::UDF_ACK); + verifyAcl(AclType::UDF_WR_IMM_ZERO); + verifyAcl(AclType::UDF_FLOWLET); + }; + + verifyAcrossWarmBoots(setup, []() {}, setupPostWarmboot, verifyPostWarmboot); +} + class AgentFlowletResourceTest : public AgentHwTest { public: std::vector diff --git a/fboss/agent/test/agent_hw_tests/AgentHwAclMatchActionsTest.cpp b/fboss/agent/test/agent_hw_tests/AgentHwAclMatchActionsTest.cpp new file mode 100644 index 0000000000000..655bc31040e85 --- /dev/null +++ b/fboss/agent/test/agent_hw_tests/AgentHwAclMatchActionsTest.cpp @@ -0,0 +1,126 @@ +// (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary. + +#include "fboss/agent/test/AgentHwTest.h" + +#include "fboss/agent/test/utils/AclTestUtils.h" +#include "fboss/agent/test/utils/AsicUtils.h" +#include "fboss/agent/test/utils/ConfigUtils.h" +#include "fboss/agent/test/utils/TrafficPolicyTestUtils.h" + +namespace facebook::fboss { + +class AgentHwAclMatchActionsTest : public AgentHwTest { + public: + std::vector + getProductionFeaturesVerified() const override { + if (!FLAGS_enable_acl_table_group) { + return {production_features::ProductionFeature::SINGLE_ACL_TABLE}; + } + return {production_features::ProductionFeature::MULTI_ACL_TABLE}; + } + + void addSetDscpAction( + cfg::SwitchConfig* config, + const std::string& matcherName, + int32_t dscpValue) { + cfg::SetDscpMatchAction setDscpMatchAction; + *setDscpMatchAction.dscpValue() = dscpValue; + cfg::MatchAction matchAction = cfg::MatchAction(); + matchAction.setDscp() = setDscpMatchAction; + utility::addMatcher(config, matcherName, matchAction); + } + + std::shared_ptr getAclEntry(const std::string& name) { + if (FLAGS_enable_acl_table_group) { + return getSw() + ->getState() + ->getAclsForTable(cfg::AclStage::INGRESS, utility::kDefaultAclTable()) + ->getNodeIf(name); + } + return getSw()->getState()->getAcl(name); + } +}; + +TEST_F(AgentHwAclMatchActionsTest, AddTrafficPolicy) { + constexpr uint32_t kDscp = 0x24; + constexpr int kQueueId = 4; + + auto setup = [=, this]() { + const auto& ensemble = *getAgentEnsemble(); + auto newCfg = initialConfig(ensemble); + auto l3Asics = ensemble.getSw()->getHwAsicTable()->getL3Asics(); + auto asic = utility::checkSameAndGetAsic(l3Asics); + + utility::addDscpAclToCfg(asic, &newCfg, "acl1", kDscp); + utility::addQueueMatcher(&newCfg, "acl1", kQueueId, ensemble.isSai()); + applyNewConfig(newCfg); + }; + auto verify = [=, this]() { + auto client = getAgentEnsemble()->getHwAgentTestClient(SwitchID(0)); + auto acl1 = getAclEntry("acl1")->toThrift(); + EXPECT_EQ( + client->sync_getAclTableNumAclEntries(utility::kDefaultAclTable()), 1); + EXPECT_TRUE(client->sync_isAclEntrySame(acl1, utility::kDefaultAclTable())); + }; + verifyAcrossWarmBoots(setup, verify); +} + +TEST_F(AgentHwAclMatchActionsTest, SetDscpMatchAction) { + constexpr uint32_t kDscp = 0x24; + constexpr uint32_t kDscp2 = 0x8; + + auto setup = [=, this]() { + const auto& ensemble = *getAgentEnsemble(); + auto newCfg = initialConfig(ensemble); + auto l3Asics = ensemble.getSw()->getHwAsicTable()->getL3Asics(); + auto asic = utility::checkSameAndGetAsic(l3Asics); + + utility::addDscpAclToCfg(asic, &newCfg, "acl1", kDscp); + addSetDscpAction(&newCfg, "acl1", kDscp2); + applyNewConfig(newCfg); + }; + auto verify = [=, this]() { + auto client = getAgentEnsemble()->getHwAgentTestClient(SwitchID(0)); + auto acl1 = getAclEntry("acl1")->toThrift(); + + EXPECT_EQ( + client->sync_getAclTableNumAclEntries(utility::kDefaultAclTable()), 1); + EXPECT_TRUE(client->sync_isAclEntrySame(acl1, utility::kDefaultAclTable())); + }; + verifyAcrossWarmBoots(setup, verify); +} + +TEST_F(AgentHwAclMatchActionsTest, AddSameMatcherTwice) { + constexpr uint32_t kDscp = 0x24; + constexpr uint32_t kDscp2 = 0x8; + + auto setup = [=, this]() { + const auto& ensemble = *getAgentEnsemble(); + auto newCfg = initialConfig(ensemble); + auto l3Asics = ensemble.getSw()->getHwAsicTable()->getL3Asics(); + auto asic = utility::checkSameAndGetAsic(l3Asics); + + utility::addDscpAclToCfg(asic, &newCfg, "acl1", kDscp); + + utility::addQueueMatcher(&newCfg, "acl1", 0, ensemble.isSai()); + utility::addQueueMatcher(&newCfg, "acl1", 0, ensemble.isSai()); + + utility::addDscpAclToCfg(asic, &newCfg, "acl2", 0); + addSetDscpAction(&newCfg, "acl2", kDscp2); + addSetDscpAction(&newCfg, "acl2", kDscp2); + + applyNewConfig(newCfg); + }; + auto verify = [=, this]() { + auto client = getAgentEnsemble()->getHwAgentTestClient(SwitchID(0)); + auto acl1 = getAclEntry("acl1")->toThrift(); + auto acl2 = getAclEntry("acl2")->toThrift(); + + EXPECT_EQ( + client->sync_getAclTableNumAclEntries(utility::kDefaultAclTable()), 2); + EXPECT_TRUE(client->sync_isAclEntrySame(acl1, utility::kDefaultAclTable())); + EXPECT_TRUE(client->sync_isAclEntrySame(acl2, utility::kDefaultAclTable())); + }; + verifyAcrossWarmBoots(setup, verify); +} +} // namespace facebook::fboss diff --git a/fboss/agent/test/agent_hw_tests/AgentMirroringTests.cpp b/fboss/agent/test/agent_hw_tests/AgentMirroringTests.cpp index bd3066b00edb5..39dd67e411713 100644 --- a/fboss/agent/test/agent_hw_tests/AgentMirroringTests.cpp +++ b/fboss/agent/test/agent_hw_tests/AgentMirroringTests.cpp @@ -6,6 +6,7 @@ #include "fboss/agent/test/EcmpSetupHelper.h" #include "fboss/agent/test/utils/AclTestUtils.h" #include "fboss/agent/test/utils/ConfigUtils.h" +#include "fboss/agent/test/utils/MirrorTestUtils.h" #include "fboss/lib/CommonUtils.h" #include @@ -17,52 +18,13 @@ #include namespace { -template -struct TestParams { - AddrT senderIp; - AddrT receiverIp; - AddrT mirrorDestinationIp; - - TestParams( - const AddrT& _senderIp, - const AddrT& _receiverIp, - const AddrT& _mirrorDestinationIp) - : senderIp(_senderIp), - receiverIp(_receiverIp), - mirrorDestinationIp(_mirrorDestinationIp) {} -}; - -template -TestParams getTestParams(); - -template <> -TestParams getTestParams() { - return TestParams( - folly::IPAddressV4("101.0.0.10"), // sender - folly::IPAddressV4("201.0.0.10"), // receiver - folly::IPAddressV4("101.0.0.11")); // erspan destination -} - -template <> -TestParams getTestParams() { - return TestParams( - folly::IPAddressV6("101::10"), // sender - folly::IPAddressV6("201::10"), // receiver - folly::IPAddressV6("101::11")); // erspan destination -} - using TestTypes = ::testing::Types; const std::string kIngressSpan = "ingress_span"; const std::string kIngressErspan = "ingress_erspan"; const std::string kEgressSpan = "egress_span"; const std::string kEgressErspan = "egress_erspan"; -// Port 0 is used for traffic and port 1 is used for mirroring. -const uint8_t kTrafficPortIndex = 0; -const uint8_t kMirrorToPortIndex = 1; - -constexpr auto kDscpDefault = facebook::fboss::cfg::switch_config_constants:: - DEFAULT_MIRROR_DSCP_; // default dscp value +const std::string kMirrorAcl = "mirror_acl"; } // namespace @@ -80,47 +42,28 @@ class AgentMirroringTest : public AgentHwTest { return config; } - /* - * This configures a local/erspan mirror session. - * Adds a tunnel config if the mirrorname is erspan. - */ - void addMirrorConfig( - cfg::SwitchConfig* cfg, - const AgentEnsemble& ensemble, - const std::string& mirrorName, - bool truncate, - uint8_t dscp = kDscpDefault) const { - auto mirrorToPort = ensemble.masterLogicalPortIds( - {cfg::PortType::INTERFACE_PORT})[kMirrorToPortIndex]; - auto params = getTestParams(); - cfg::MirrorDestination destination; - destination.egressPort() = cfg::MirrorEgressPort(); - destination.egressPort()->logicalID_ref() = mirrorToPort; - if (mirrorName == kIngressErspan || mirrorName == kEgressErspan) { - cfg::MirrorTunnel tunnel; - cfg::GreTunnel greTunnel; - greTunnel.ip() = params.mirrorDestinationIp.str(); - tunnel.greTunnel() = greTunnel; - destination.tunnel() = tunnel; - } - cfg::Mirror mirrorConfig; - mirrorConfig.name() = mirrorName; - mirrorConfig.destination() = destination; - mirrorConfig.truncate() = truncate; - mirrorConfig.dscp() = dscp; - cfg->mirrors()->push_back(mirrorConfig); + PortID getMirrorToPort(const AgentEnsemble& ensemble) const { + return ensemble.masterLogicalPortIds( + {cfg::PortType::INTERFACE_PORT})[utility::kMirrorToPortIndex]; + } + + PortID getTrafficPort(const AgentEnsemble& ensemble) const { + return ensemble.masterLogicalPortIds( + {cfg::PortType::INTERFACE_PORT})[utility::kTrafficPortIndex]; } void addPortMirrorConfig( cfg::SwitchConfig* cfg, const AgentEnsemble& ensemble, const std::string& mirrorName) const { - auto trafficPort = ensemble.masterLogicalPortIds( - {cfg::PortType::INTERFACE_PORT})[kTrafficPortIndex]; + auto trafficPort = getTrafficPort(ensemble); auto portConfig = utility::findCfgPort(*cfg, trafficPort); - if (mirrorName == kIngressSpan || mirrorName == kIngressErspan) { + if (mirrorName == utility::kIngressSpan || + mirrorName == utility::kIngressErspan) { portConfig->ingressMirror() = mirrorName; - } else if (mirrorName == kEgressSpan || mirrorName == kEgressErspan) { + } else if ( + mirrorName == utility::kEgressSpan || + mirrorName == utility::kEgressErspan) { portConfig->egressMirror() = mirrorName; } else { throw FbossError("Invalid mirror name ", mirrorName); @@ -128,12 +71,11 @@ class AgentMirroringTest : public AgentHwTest { } void sendPackets(int count, size_t payloadSize = 1) { - auto params = getTestParams(); + auto params = utility::getMirrorTestParams(); auto vlanId = utility::firstVlanID(getProgrammedState()); auto intfMac = utility::getFirstInterfaceMac(getProgrammedState()); std::vector payload(payloadSize, 0xff); - auto trafficPort = getAgentEnsemble()->masterLogicalPortIds( - {cfg::PortType::INTERFACE_PORT})[kTrafficPortIndex]; + auto trafficPort = getTrafficPort(*getAgentEnsemble()); auto oldPacketStats = getLatestPortStats(trafficPort); auto oldOutPkts = *oldPacketStats.outUnicastPkts_(); auto i = 0; @@ -175,10 +117,8 @@ class AgentMirroringTest : public AgentHwTest { template void resolveMirror(const std::string& mirrorName) { utility::EcmpSetupAnyNPorts ecmpHelper(getProgrammedState()); - auto trafficPort = getAgentEnsemble()->masterLogicalPortIds( - {cfg::PortType::INTERFACE_PORT})[kTrafficPortIndex]; - auto mirrorToPort = getAgentEnsemble()->masterLogicalPortIds( - {cfg::PortType::INTERFACE_PORT})[kMirrorToPortIndex]; + auto trafficPort = getTrafficPort(*getAgentEnsemble()); + auto mirrorToPort = getMirrorToPort(*getAgentEnsemble()); EXPECT_EQ(trafficPort, ecmpHelper.nhop(0).portDesc.phyPortID()); EXPECT_EQ(mirrorToPort, ecmpHelper.nhop(1).portDesc.phyPortID()); resolveNeigborAndProgramRoutes(ecmpHelper, 1); @@ -204,9 +144,8 @@ class AgentMirroringTest : public AgentHwTest { cfg::SwitchConfig* cfg, const AgentEnsemble& ensemble, const std::string& mirrorName) const { - auto trafficPort = ensemble.masterLogicalPortIds( - {cfg::PortType::INTERFACE_PORT})[kTrafficPortIndex]; - auto aclEntryName = "mirror_acl"; + auto trafficPort = getTrafficPort(ensemble); + std::string aclEntryName = kMirrorAcl; utility::addAclTableGroup( cfg, cfg::AclStage::INGRESS, utility::getAclTableGroupName()); utility::addDefaultAclTable(*cfg); @@ -253,10 +192,11 @@ class AgentMirroringTest : public AgentHwTest { ttl.value() = 255; ttl.mask() = 0xFF; aclEntry.ttl() = ttl; - cfg->acls()->push_back(aclEntry); + utility::addAclEntry(cfg, aclEntry, utility::kDefaultAclTable()); cfg::MatchAction matchAction = cfg::MatchAction(); - if (mirrorName == kIngressErspan || mirrorName == kEgressErspan) { + if (mirrorName == utility::kIngressErspan || + mirrorName == utility::kEgressErspan) { matchAction.ingressMirror() = mirrorName; } else { matchAction.egressMirror() = mirrorName; @@ -271,6 +211,7 @@ class AgentMirroringTest : public AgentHwTest { void verifyMirrorProgrammed(const std::string& mirrorName) { WITH_RETRIES({ auto mirror = getProgrammedState()->getMirrors()->getNodeIf(mirrorName); + EXPECT_EVENTUALLY_NE(mirror, nullptr); EXPECT_EVENTUALLY_TRUE(mirror->isResolved()); auto fields = mirror->toThrift(); auto scope = getAgentEnsemble()->scopeResolver().scope(mirror); @@ -283,10 +224,8 @@ class AgentMirroringTest : public AgentHwTest { void verify(const std::string& mirrorName, int payloadSize = 500) { verifyMirrorProgrammed(mirrorName); - auto trafficPort = getAgentEnsemble()->masterLogicalPortIds( - {cfg::PortType::INTERFACE_PORT})[kTrafficPortIndex]; - auto mirrorToPort = getAgentEnsemble()->masterLogicalPortIds( - {cfg::PortType::INTERFACE_PORT})[kMirrorToPortIndex]; + auto trafficPort = getTrafficPort(*getAgentEnsemble()); + auto mirrorToPort = getMirrorToPort(*getAgentEnsemble()); WITH_RETRIES({ auto ingressMirror = this->getProgrammedState()->getMirrors()->getNodeIf(mirrorName); @@ -332,8 +271,7 @@ class AgentMirroringTest : public AgentHwTest { void testPortMirrorWithLargePacket(const std::string& mirrorName) { auto setup = [=, this]() { this->resolveMirror(mirrorName); }; auto verify = [=, this]() { - auto mirrorToPort = getAgentEnsemble()->masterLogicalPortIds( - {cfg::PortType::INTERFACE_PORT})[kMirrorToPortIndex]; + auto mirrorToPort = getMirrorToPort(*getAgentEnsemble()); auto statsBefore = getLatestPortStats(mirrorToPort); this->verify(mirrorName, 8000); WITH_RETRIES({ @@ -356,6 +294,7 @@ class AgentMirroringTest : public AgentHwTest { !isSupportedOnAllAsics(HwAsic::Feature::ERSPANv6); } + virtual bool isIngress() const = 0; const RouterID kRid{0}; const uint16_t srcL4Port_{1234}; const uint16_t dstL4Port_{4321}; @@ -363,7 +302,6 @@ class AgentMirroringTest : public AgentHwTest { template class AgentIngressPortSpanMirroringTest : public AgentMirroringTest { - public: public: std::vector getProductionFeaturesVerified() const override { @@ -373,10 +311,15 @@ class AgentIngressPortSpanMirroringTest : public AgentMirroringTest { cfg::SwitchConfig initialConfig( const AgentEnsemble& ensemble) const override { auto cfg = AgentMirroringTest::initialConfig(ensemble); - this->addMirrorConfig(&cfg, ensemble, kIngressSpan, false /* truncate */); - this->addPortMirrorConfig(&cfg, ensemble, kIngressSpan); + utility::addMirrorConfig( + &cfg, ensemble, utility::kIngressSpan, false /* truncate */); + this->addPortMirrorConfig(&cfg, ensemble, utility::kIngressSpan); return cfg; } + + bool isIngress() const override { + return true; + } }; template @@ -390,10 +333,15 @@ class AgentIngressPortErspanMirroringTest : public AgentMirroringTest { cfg::SwitchConfig initialConfig( const AgentEnsemble& ensemble) const override { auto cfg = AgentMirroringTest::initialConfig(ensemble); - this->addMirrorConfig(&cfg, ensemble, kIngressErspan, false /* truncate */); - this->addPortMirrorConfig(&cfg, ensemble, kIngressErspan); + utility::addMirrorConfig( + &cfg, ensemble, utility::kIngressErspan, false /* truncate */); + this->addPortMirrorConfig(&cfg, ensemble, utility::kIngressErspan); return cfg; } + + bool isIngress() const override { + return true; + } }; template @@ -410,10 +358,15 @@ class AgentIngressPortErspanMirroringTruncateTest cfg::SwitchConfig initialConfig( const AgentEnsemble& ensemble) const override { auto cfg = AgentMirroringTest::initialConfig(ensemble); - this->addMirrorConfig(&cfg, ensemble, kIngressErspan, true /* truncate */); - this->addPortMirrorConfig(&cfg, ensemble, kIngressErspan); + utility::addMirrorConfig( + &cfg, ensemble, utility::kIngressErspan, true /* truncate */); + this->addPortMirrorConfig(&cfg, ensemble, utility::kIngressErspan); return cfg; } + + bool isIngress() const override { + return true; + } }; template @@ -427,10 +380,15 @@ class AgentIngressAclSpanMirroringTest : public AgentMirroringTest { cfg::SwitchConfig initialConfig( const AgentEnsemble& ensemble) const override { auto cfg = AgentMirroringTest::initialConfig(ensemble); - this->addMirrorConfig(&cfg, ensemble, kIngressSpan, false /* truncate */); - this->addAclMirrorConfig(&cfg, ensemble, kIngressSpan); + utility::addMirrorConfig( + &cfg, ensemble, utility::kIngressSpan, false /* truncate */); + this->addAclMirrorConfig(&cfg, ensemble, utility::kIngressSpan); return cfg; } + + bool isIngress() const override { + return true; + } }; template @@ -444,10 +402,15 @@ class AgentIngressAclErspanMirroringTest : public AgentMirroringTest { cfg::SwitchConfig initialConfig( const AgentEnsemble& ensemble) const override { auto cfg = AgentMirroringTest::initialConfig(ensemble); - this->addMirrorConfig(&cfg, ensemble, kIngressErspan, false /* truncate */); - this->addAclMirrorConfig(&cfg, ensemble, kIngressErspan); + utility::addMirrorConfig( + &cfg, ensemble, utility::kIngressErspan, false /* truncate */); + this->addAclMirrorConfig(&cfg, ensemble, utility::kIngressErspan); return cfg; } + + bool isIngress() const override { + return true; + } }; template @@ -462,10 +425,15 @@ class AgentEgressPortSpanMirroringTest : public AgentMirroringTest { cfg::SwitchConfig initialConfig( const AgentEnsemble& ensemble) const override { auto cfg = AgentMirroringTest::initialConfig(ensemble); - this->addMirrorConfig(&cfg, ensemble, kEgressSpan, false /* truncate */); - this->addPortMirrorConfig(&cfg, ensemble, kEgressSpan); + utility::addMirrorConfig( + &cfg, ensemble, utility::kEgressSpan, false /* truncate */); + this->addPortMirrorConfig(&cfg, ensemble, utility::kEgressSpan); return cfg; } + + bool isIngress() const override { + return false; + } }; template @@ -479,10 +447,15 @@ class AgentEgressPortErspanMirroringTest : public AgentMirroringTest { cfg::SwitchConfig initialConfig( const AgentEnsemble& ensemble) const override { auto cfg = AgentMirroringTest::initialConfig(ensemble); - this->addMirrorConfig(&cfg, ensemble, kEgressErspan, false /* truncate */); - this->addPortMirrorConfig(&cfg, ensemble, kEgressErspan); + utility::addMirrorConfig( + &cfg, ensemble, utility::kEgressErspan, false /* truncate */); + this->addPortMirrorConfig(&cfg, ensemble, utility::kEgressErspan); return cfg; } + + bool isIngress() const override { + return false; + } }; template @@ -499,10 +472,15 @@ class AgentEgressPortErspanMirroringTruncateTest cfg::SwitchConfig initialConfig( const AgentEnsemble& ensemble) const override { auto cfg = AgentMirroringTest::initialConfig(ensemble); - this->addMirrorConfig(&cfg, ensemble, kEgressErspan, true /* truncate */); - this->addPortMirrorConfig(&cfg, ensemble, kEgressErspan); + utility::addMirrorConfig( + &cfg, ensemble, utility::kEgressErspan, true /* truncate */); + this->addPortMirrorConfig(&cfg, ensemble, utility::kEgressErspan); return cfg; } + + bool isIngress() const override { + return false; + } }; template @@ -516,10 +494,15 @@ class AgentEgressAclSpanMirroringTest : public AgentMirroringTest { cfg::SwitchConfig initialConfig( const AgentEnsemble& ensemble) const override { auto cfg = AgentMirroringTest::initialConfig(ensemble); - this->addMirrorConfig(&cfg, ensemble, kEgressSpan, false /* truncate */); - this->addAclMirrorConfig(&cfg, ensemble, kEgressSpan); + utility::addMirrorConfig( + &cfg, ensemble, utility::kEgressSpan, false /* truncate */); + this->addAclMirrorConfig(&cfg, ensemble, utility::kEgressSpan); return cfg; } + + bool isIngress() const override { + return false; + } }; template @@ -533,10 +516,15 @@ class AgentEgressAclErspanMirroringTest : public AgentMirroringTest { cfg::SwitchConfig initialConfig( const AgentEnsemble& ensemble) const override { auto cfg = AgentMirroringTest::initialConfig(ensemble); - this->addMirrorConfig(&cfg, ensemble, kEgressErspan, false /* truncate */); - this->addAclMirrorConfig(&cfg, ensemble, kEgressErspan); + utility::addMirrorConfig( + &cfg, ensemble, utility::kEgressErspan, false /* truncate */); + this->addAclMirrorConfig(&cfg, ensemble, utility::kEgressErspan); return cfg; } + + bool isIngress() const override { + return false; + } }; TYPED_TEST_SUITE(AgentIngressPortSpanMirroringTest, TestTypes); @@ -551,46 +539,46 @@ TYPED_TEST_SUITE(AgentEgressAclSpanMirroringTest, TestTypes); TYPED_TEST_SUITE(AgentEgressAclErspanMirroringTest, TestTypes); TYPED_TEST(AgentIngressPortSpanMirroringTest, SpanPortMirror) { - this->testPortMirror(kIngressSpan); + this->testPortMirror(utility::kIngressSpan); } TYPED_TEST(AgentIngressPortErspanMirroringTest, ErspanPortMirror) { - this->testPortMirror(kIngressErspan); + this->testPortMirror(utility::kIngressErspan); } TYPED_TEST(AgentIngressAclSpanMirroringTest, SpanAclMirror) { - this->testAclMirror(kIngressSpan); + this->testAclMirror(utility::kIngressSpan); } TYPED_TEST(AgentIngressAclErspanMirroringTest, ErspanAclMirror) { - this->testAclMirror(kIngressErspan); + this->testAclMirror(utility::kIngressErspan); } TYPED_TEST( AgentIngressPortErspanMirroringTruncateTest, TrucatePortErspanMirror) { - this->testPortMirrorWithLargePacket(kIngressErspan); + this->testPortMirrorWithLargePacket(utility::kIngressErspan); } TYPED_TEST(AgentEgressPortSpanMirroringTest, SpanPortMirror) { - this->testPortMirror(kEgressSpan); + this->testPortMirror(utility::kEgressSpan); } TYPED_TEST(AgentEgressPortErspanMirroringTest, ErspanPortMirror) { - this->testPortMirror(kEgressErspan); + this->testPortMirror(utility::kEgressErspan); } TYPED_TEST(AgentEgressAclSpanMirroringTest, SpanAclMirror) { - this->testAclMirror(kEgressSpan); + this->testAclMirror(utility::kEgressSpan); } TYPED_TEST(AgentEgressAclErspanMirroringTest, ErspanAclMirror) { - this->testAclMirror(kEgressErspan); + this->testAclMirror(utility::kEgressErspan); } TYPED_TEST( AgentEgressPortErspanMirroringTruncateTest, TrucatePortErspanMirror) { - this->testPortMirrorWithLargePacket(kEgressErspan); + this->testPortMirrorWithLargePacket(utility::kEgressErspan); } } // namespace facebook::fboss diff --git a/fboss/agent/test/agent_hw_tests/AgentPacketSendTests.cpp b/fboss/agent/test/agent_hw_tests/AgentPacketSendTests.cpp index 7a4eadb522fa5..c6e1f3486edb5 100644 --- a/fboss/agent/test/agent_hw_tests/AgentPacketSendTests.cpp +++ b/fboss/agent/test/agent_hw_tests/AgentPacketSendTests.cpp @@ -361,7 +361,7 @@ TEST_F(AgentPacketSendReceiveTest, LldpPacketReceiveSrcPort) { auto payLoadSize = 256; auto expectedNumPktsReceived = 1; for (const auto& port : - {masterLogicalPortIds()[0], masterLogicalPortIds().back()}) { + {masterLogicalPortIds()[0], masterLogicalPortIds()[1]}) { auto txPacket = utility::makeEthTxPacket( getSw(), vlanId, diff --git a/fboss/agent/test/agent_hw_tests/AgentPfcTests.cpp b/fboss/agent/test/agent_hw_tests/AgentPfcTests.cpp new file mode 100644 index 0000000000000..3610fb3f6ef69 --- /dev/null +++ b/fboss/agent/test/agent_hw_tests/AgentPfcTests.cpp @@ -0,0 +1,92 @@ +// (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary. + +#include "fboss/agent/TxPacket.h" +#include "fboss/agent/packet/PktFactory.h" +#include "fboss/agent/test/AgentHwTest.h" +#include "fboss/agent/test/utils/ConfigUtils.h" +#include "fboss/agent/test/utils/PfcTestUtils.h" +#include "fboss/lib/CommonUtils.h" + +namespace facebook::fboss { + +class AgentPfcTest : public AgentHwTest { + public: + cfg::SwitchConfig initialConfig( + const AgentEnsemble& ensemble) const override { + auto config = utility::onePortPerInterfaceConfig( + ensemble.getSw(), + ensemble.masterLogicalPortIds(), + true /*interfaceHasSubnet*/); + return config; + } + + std::vector + getProductionFeaturesVerified() const override { + return {production_features::ProductionFeature::PFC}; + } + + protected: + void sendPfcFrame(const std::vector& portIds, uint8_t classVector) { + for (auto portId : portIds) { + // Construct PFC payload with fixed quanta 0x00F0. + // See https://github.com/archjeb/pfctest for frame structure. + std::vector payload{ + 0x01, 0x01, 0x00, classVector, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0xF0, + 0x00, 0xF0, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0xF0, + }; + std::vector padding(28, 0); + payload.insert(payload.end(), padding.begin(), padding.end()); + + // Send it out + auto vlanId = utility::firstVlanID(getProgrammedState()); + auto intfMac = utility::getFirstInterfaceMac(getProgrammedState()); + auto srcMac = utility::MacAddressGenerator().get(intfMac.u64NBO() + 1); + auto pkt = utility::makeEthTxPacket( + getSw(), + vlanId, + srcMac, + folly::MacAddress("01:80:C2:00:00:01"), // MAC control address + ETHERTYPE::ETHERTYPE_EPON, // Ethertype for PFC frames + std::move(payload)); + getSw()->sendPacketOutOfPortAsync(std::move(pkt), portId); + } + } +}; + +TEST_F(AgentPfcTest, verifyPfcCounters) { + std::vector portIds = { + masterLogicalInterfacePortIds()[0], masterLogicalInterfacePortIds()[1]}; + std::vector losslessPgIds = {2}; + + auto setup = [&]() { + auto cfg = getAgentEnsemble()->getCurrentConfig(); + utility::setupPfcBuffers(cfg, portIds, losslessPgIds); + applyNewConfig(cfg); + + for (auto portId : portIds) { + auto inPfc = getLatestPortStats(portId).get_inPfc_(); + for (auto [qos, value] : inPfc) { + EXPECT_EQ(value, 0); + } + } + }; + + auto verify = [&]() { + sendPfcFrame(portIds, 0xFF); + + WITH_RETRIES({ + for (auto portId : portIds) { + // We map pgIds to PFC priorities 1:1, so check for the same IDs. + auto inPfc = getLatestPortStats(portId).get_inPfc_(); + ASSERT_EVENTUALLY_GE(inPfc.size(), losslessPgIds.size()); + for (int pgId : losslessPgIds) { + EXPECT_EVENTUALLY_EQ(inPfc[pgId], 1); + } + } + }); + }; + + verifyAcrossWarmBoots(setup, verify); +} + +} // namespace facebook::fboss diff --git a/fboss/agent/test/agent_hw_tests/AgentSflowMirrorTest.cpp b/fboss/agent/test/agent_hw_tests/AgentSflowMirrorTest.cpp index c3312d8196936..a7ab057e4b6fd 100644 --- a/fboss/agent/test/agent_hw_tests/AgentSflowMirrorTest.cpp +++ b/fboss/agent/test/agent_hw_tests/AgentSflowMirrorTest.cpp @@ -16,6 +16,7 @@ #include "fboss/agent/test/utils/AsicUtils.h" #include "fboss/agent/test/utils/ConfigUtils.h" #include "fboss/agent/test/utils/MirrorTestUtils.h" +#include "fboss/agent/test/utils/OlympicTestUtils.h" #include "fboss/agent/test/utils/PacketSnooper.h" #include "fboss/lib/CommonUtils.h" @@ -52,6 +53,9 @@ class AgentSflowMirrorTest : public AgentHwTest { auto asic = ensemble.getSw()->getHwAsicTable()->getHwAsic(port0Switch); auto ports = getPortsForSampling(ensemble.masterLogicalPortIds(), asic); this->configureMirror(cfg); + if (asic->isSupported(HwAsic::Feature::EVENTOR_PORT_FOR_SFLOW)) { + utility::addEventorVoqConfig(&cfg, cfg::StreamType::UNICAST); + } return cfg; } @@ -127,6 +131,11 @@ class AgentSflowMirrorTest : public AgentHwTest { } std::optional getHwLogicalPortId(PortID port) const { + auto asic = checkSameAndGetAsic(); + if (asic->getAsicType() == cfg::AsicType::ASIC_TYPE_EBRO || + asic->getAsicType() == cfg::AsicType::ASIC_TYPE_YUBA) { + return std::nullopt; + } return getSw()->getHwLogicalPortId(port); } diff --git a/fboss/agent/test/agent_hw_tests/AgentVoqSwitchTests.cpp b/fboss/agent/test/agent_hw_tests/AgentVoqSwitchTests.cpp index 5dd9f33325661..f765704433ad2 100644 --- a/fboss/agent/test/agent_hw_tests/AgentVoqSwitchTests.cpp +++ b/fboss/agent/test/agent_hw_tests/AgentVoqSwitchTests.cpp @@ -1,10 +1,12 @@ // (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary. +#include "fboss/agent/DsfStateUpdaterUtil.h" #include "fboss/agent/TxPacket.h" #include "fboss/agent/hw/HwResourceStatsPublisher.h" #include "fboss/agent/hw/test/ConfigFactory.h" #include "fboss/agent/packet/EthFrame.h" #include "fboss/agent/packet/PktFactory.h" +#include "fboss/agent/rib/ForwardingInformationBaseUpdater.h" #include "fboss/agent/test/AgentHwTest.h" #include "fboss/agent/test/EcmpSetupHelper.h" #include "fboss/agent/test/utils/AclTestUtils.h" @@ -24,7 +26,7 @@ DECLARE_int32(ecmp_resource_percentage); namespace { constexpr uint8_t kDefaultQueue = 0; -} +} // namespace using namespace facebook::fb303; namespace facebook::fboss { @@ -877,7 +879,10 @@ TEST_F(AgentVoqSwitchWithFabricPortsTest, checkFabricPortSprayWithIsolate) { << " After pkts: " << afterPkts; EXPECT_EVENTUALLY_GE(afterPkts, beforePkts + 10000); auto nifBytes = getLatestPortStats(kPort.phyPortID()).get_outBytes_(); - auto fabricPortStats = getLatestPortStats(masterLogicalFabricPortIds()); + auto switchId = + getSw()->getScopeResolver()->scope(kPort.phyPortID()).switchId(); + auto fabricPortStats = + getLatestPortStats(masterLogicalFabricPortIds(switchId)); auto fabricBytes = 0; for (const auto& idAndStats : fabricPortStats) { fabricBytes += idAndStats.second.get_outBytes_(); @@ -923,7 +928,10 @@ TEST_F(AgentVoqSwitchWithFabricPortsTest, checkFabricPortSpray) { << " After pkts: " << afterPkts; EXPECT_EVENTUALLY_GE(afterPkts, beforePkts + 10000); auto nifBytes = getLatestPortStats(kPort.phyPortID()).get_outBytes_(); - auto fabricPortStats = getLatestPortStats(masterLogicalFabricPortIds()); + auto switchId = + getSw()->getScopeResolver()->scope(kPort.phyPortID()).switchId(); + auto fabricPortStats = + getLatestPortStats(masterLogicalFabricPortIds(switchId)); auto fabricBytes = 0; for (const auto& idAndStats : fabricPortStats) { fabricBytes += idAndStats.second.get_outBytes_(); @@ -1584,7 +1592,8 @@ TEST_F(AgentVoqSwitchWithMultipleDsfNodesTest, addRemoveRemoteNeighbor) { in, scopeResolver(), kRemoteSysPortId, - static_cast(numCores)); + static_cast( + numCores * getAgentEnsemble()->getNumL3Asics())); }); const InterfaceID kIntfId(remotePortId); applyNewState([&](const std::shared_ptr& in) { @@ -1646,7 +1655,8 @@ TEST_F(AgentVoqSwitchWithMultipleDsfNodesTest, voqDelete) { in, scopeResolver(), kRemoteSysPortId, - static_cast(numCores)); + static_cast( + numCores * getAgentEnsemble()->getNumL3Asics())); }); const InterfaceID kIntfId(remotePortId); applyNewState([&](const std::shared_ptr& in) { @@ -1732,7 +1742,8 @@ TEST_F(AgentVoqSwitchWithMultipleDsfNodesTest, stressAddRemoveObjects) { in, scopeResolver(), kRemoteSysPortId, - static_cast(numCores)); + static_cast( + numCores * getAgentEnsemble()->getNumL3Asics())); }); const InterfaceID kIntfId(remotePortId); applyNewState([&](const std::shared_ptr& in) { @@ -1829,7 +1840,8 @@ TEST_F(AgentVoqSwitchWithMultipleDsfNodesTest, voqTailDropCounter) { in, scopeResolver(), kRemoteSysPortId, - static_cast(numCores)); + static_cast( + numCores * getAgentEnsemble()->getNumL3Asics())); }); const InterfaceID kIntfId(remotePortId); applyNewState([&](const std::shared_ptr& in) { @@ -1877,7 +1889,8 @@ TEST_F(AgentVoqSwitchWithMultipleDsfNodesTest, verifyDscpToVoqMapping) { in, scopeResolver(), kRemoteSysPortId, - static_cast(numCores)); + static_cast( + numCores * getAgentEnsemble()->getNumL3Asics())); }); const InterfaceID kIntfId(remotePortId); applyNewState([&](const std::shared_ptr& in) { @@ -1968,6 +1981,55 @@ class AgentVoqSwitchFullScaleDsfNodesTest : public AgentVoqSwitchTest { // Resolve and return list of local nhops (only NIF ports) std::vector resolveLocalNhops( utility::EcmpSetupTargetedPorts6& ecmpHelper) { + std::vector portDescs = getLocalSysPortDesc(); + + applyNewState([&](const std::shared_ptr& in) { + auto out = in->clone(); + for (const auto& portDesc : portDescs) { + out = ecmpHelper.resolveNextHops(out, {portDesc}); + } + return out; + }); + return portDescs; + } + + void setupRemoteIntfAndSysPorts() { + auto updateDsfStateFn = [this](const std::shared_ptr& in) { + std::map> switchId2SystemPorts; + std::map> switchId2Rifs; + utility::populateRemoteIntfAndSysPorts( + switchId2SystemPorts, + switchId2Rifs, + getSw()->getConfig(), + isSupportedOnAllAsics(HwAsic::Feature::RESERVED_ENCAP_INDEX_RANGE)); + return DsfStateUpdaterUtil::getUpdatedState( + in, + getSw()->getScopeResolver(), + getSw()->getRib(), + switchId2SystemPorts, + switchId2Rifs); + }; + getSw()->getRib()->updateStateInRibThread([this, updateDsfStateFn]() { + getSw()->updateStateWithHwFailureProtection( + folly::sformat("Update state for node: {}", 0), updateDsfStateFn); + }); + } + + boost::container::flat_set getRemoteSysPortDesc() { + auto remoteSysPorts = + getProgrammedState()->getRemoteSystemPorts()->getAllNodes(); + boost::container::flat_set sysPortDescs; + std::for_each( + remoteSysPorts->begin(), + remoteSysPorts->end(), + [&sysPortDescs](const auto& idAndPort) { + sysPortDescs.insert( + PortDescriptor(static_cast(idAndPort.first))); + }); + return sysPortDescs; + } + + std::vector getLocalSysPortDesc() { auto ports = getProgrammedState()->getPorts()->getAllNodes(); std::vector portDescs; std::for_each( @@ -1980,14 +2042,6 @@ class AgentVoqSwitchFullScaleDsfNodesTest : public AgentVoqSwitchTest { PortDescriptor(getSystemPortID(PortDescriptor(port->getID())))); } }); - - applyNewState([&](const std::shared_ptr& in) { - auto out = in->clone(); - for (const auto& portDesc : portDescs) { - out = ecmpHelper.resolveNextHops(out, {portDesc}); - } - return out; - }); return portDescs; } @@ -1998,42 +2052,25 @@ class AgentVoqSwitchFullScaleDsfNodesTest : public AgentVoqSwitchTest { FLAGS_enable_stats_update_thread = false; // Allow 100% ECMP resource usage FLAGS_ecmp_resource_percentage = 100; + FLAGS_ecmp_width = 512; } }; TEST_F(AgentVoqSwitchFullScaleDsfNodesTest, systemPortScaleTest) { - auto setup = [this]() { - applyNewState([&](const std::shared_ptr& in) { - return utility::setupRemoteIntfAndSysPorts( - in, - scopeResolver(), - getSw()->getConfig(), - isSupportedOnAllAsics(HwAsic::Feature::RESERVED_ENCAP_INDEX_RANGE)); - }); - }; + auto setup = [this]() { setupRemoteIntfAndSysPorts(); }; verifyAcrossWarmBoots(setup, [] {}); } TEST_F(AgentVoqSwitchFullScaleDsfNodesTest, remoteNeighborWithEcmpGroup) { const auto kEcmpWidth = getMaxEcmpWidth(); const auto kMaxDeviation = 25; - FLAGS_ecmp_width = kEcmpWidth; - boost::container::flat_set sysPortDescs; auto setup = [&]() { - applyNewState([&](const std::shared_ptr& in) { - return utility::setupRemoteIntfAndSysPorts( - in, - scopeResolver(), - getSw()->getConfig(), - isSupportedOnAllAsics(HwAsic::Feature::RESERVED_ENCAP_INDEX_RANGE)); - }); + setupRemoteIntfAndSysPorts(); utility::EcmpSetupTargetedPorts6 ecmpHelper(getProgrammedState()); - // Trigger config apply to add remote interface routes as directly connected - // in RIB. This is to resolve ECMP members pointing to remote nexthops. - applyNewConfig(getSw()->getConfig()); // Resolve remote nhops and get a list of remote sysPort descriptors - sysPortDescs = utility::resolveRemoteNhops(getAgentEnsemble(), ecmpHelper); + boost::container::flat_set sysPortDescs = + utility::resolveRemoteNhops(getAgentEnsemble(), ecmpHelper); for (int i = 0; i < getMaxEcmpGroup(); i++) { auto prefix = RoutePrefixV6{ @@ -2049,6 +2086,7 @@ TEST_F(AgentVoqSwitchFullScaleDsfNodesTest, remoteNeighborWithEcmpGroup) { } }; auto verify = [&]() { + auto sysPortDescs = getRemoteSysPortDesc(); // Send and verify packets across voq drops. auto defaultRouteSysPorts = std::vector( sysPortDescs.begin(), sysPortDescs.begin() + kEcmpWidth); @@ -2093,26 +2131,15 @@ TEST_F(AgentVoqSwitchFullScaleDsfNodesTest, remoteNeighborWithEcmpGroup) { TEST_F(AgentVoqSwitchFullScaleDsfNodesTest, remoteAndLocalLoadBalance) { const auto kEcmpWidth = 16; const auto kMaxDeviation = 25; - FLAGS_ecmp_width = kEcmpWidth; - std::vector sysPortDescs; auto setup = [&]() { - applyNewState([&](const std::shared_ptr& in) { - return utility::setupRemoteIntfAndSysPorts( - in, - scopeResolver(), - getSw()->getConfig(), - isSupportedOnAllAsics(HwAsic::Feature::RESERVED_ENCAP_INDEX_RANGE)); - }); + setupRemoteIntfAndSysPorts(); utility::EcmpSetupTargetedPorts6 ecmpHelper(getProgrammedState()); - // Trigger config apply to add remote interface routes as directly connected - // in RIB. This is to resolve ECMP members pointing to remote nexthops. - applyNewConfig(getSw()->getConfig()); // Resolve remote and local nhops and get a list of sysPort descriptors auto remoteSysPortDescs = utility::resolveRemoteNhops(getAgentEnsemble(), ecmpHelper); auto localSysPortDescs = resolveLocalNhops(ecmpHelper); - + std::vector sysPortDescs; sysPortDescs.insert( sysPortDescs.end(), remoteSysPortDescs.begin(), @@ -2132,6 +2159,19 @@ TEST_F(AgentVoqSwitchFullScaleDsfNodesTest, remoteAndLocalLoadBalance) { {prefix}); }; auto verify = [&]() { + std::vector sysPortDescs; + auto remoteSysPortDescs = getRemoteSysPortDesc(); + auto localSysPortDescs = getLocalSysPortDesc(); + + sysPortDescs.insert( + sysPortDescs.end(), + remoteSysPortDescs.begin(), + remoteSysPortDescs.begin() + kEcmpWidth / 2); + sysPortDescs.insert( + sysPortDescs.end(), + localSysPortDescs.begin(), + localSysPortDescs.begin() + kEcmpWidth / 2); + // Send and verify packets across voq drops. std::function( const std::vector&)> @@ -2169,23 +2209,13 @@ TEST_F(AgentVoqSwitchFullScaleDsfNodesTest, remoteAndLocalLoadBalance) { TEST_F(AgentVoqSwitchFullScaleDsfNodesTest, stressProgramEcmpRoutes) { auto kEcmpWidth = getMaxEcmpWidth(); - FLAGS_ecmp_width = kEcmpWidth; // Stress add/delete 40 iterations of 5 routes with ECMP width. // 40 iterations take ~17 mins on j3. const auto routeScale = 5; const auto numIterations = 40; auto setup = [&]() { - applyNewState([&](const std::shared_ptr& in) { - return utility::setupRemoteIntfAndSysPorts( - in, - scopeResolver(), - getSw()->getConfig(), - isSupportedOnAllAsics(HwAsic::Feature::RESERVED_ENCAP_INDEX_RANGE)); - }); + setupRemoteIntfAndSysPorts(); utility::EcmpSetupTargetedPorts6 ecmpHelper(getProgrammedState()); - // Trigger config apply to add remote interface routes as directly connected - // in RIB. This is to resolve ECMP members pointing to remote nexthops. - applyNewConfig(getSw()->getConfig()); // Resolve remote nhops and get a list of remote sysPort descriptors auto sysPortDescs = diff --git a/fboss/agent/test/agent_hw_tests/BUCK b/fboss/agent/test/agent_hw_tests/BUCK index 6cba285de9581..0aae23e8e028e 100644 --- a/fboss/agent/test/agent_hw_tests/BUCK +++ b/fboss/agent/test/agent_hw_tests/BUCK @@ -25,6 +25,7 @@ cpp_library( "AgentEmptyTests.cpp", "AgentFabricSwitchTests.cpp", "AgentFlowletSwitchingTests.cpp", + "AgentHwAclMatchActionsTest.cpp", "AgentInNullRouteDiscardsTest.cpp", "AgentInTrapDiscardsTest.cpp", "AgentJumboFramesTests.cpp", @@ -41,6 +42,7 @@ cpp_library( "AgentOlympicQosTests.cpp", "AgentOverflowTestBase.cpp", "AgentPacketSendTests.cpp", + "AgentPfcTests.cpp", "AgentPortBandWidthTests.cpp", "AgentPrbsTests.cpp", "AgentQueuePerHostL2Tests.cpp", @@ -90,6 +92,7 @@ cpp_library( "//fboss/agent/packet:packet", "//fboss/agent/packet:packet_factory", "//fboss/agent/packet:pktutil", + "//fboss/agent/rib:fib_updater", "//fboss/agent/state:label_forwarding_action", "//fboss/agent/state:state", "//fboss/agent/state:state_utils", @@ -116,6 +119,7 @@ cpp_library( "//fboss/agent/test/utils:mirror_test_utils", "//fboss/agent/test/utils:olympic_qos_utils", "//fboss/agent/test/utils:packet_snooper", + "//fboss/agent/test/utils:pfc_test_utils", "//fboss/agent/test/utils:pkt_test_utils", "//fboss/agent/test/utils:port_stats_test_utils", "//fboss/agent/test/utils:port_test_utils", diff --git a/fboss/agent/test/link_tests/AgentEnsembleLinkTest.cpp b/fboss/agent/test/link_tests/AgentEnsembleLinkTest.cpp index 102667ba1bcbc..58962d5521cf4 100644 --- a/fboss/agent/test/link_tests/AgentEnsembleLinkTest.cpp +++ b/fboss/agent/test/link_tests/AgentEnsembleLinkTest.cpp @@ -52,7 +52,6 @@ void AgentEnsembleLinkTest::TearDown() { void AgentEnsembleLinkTest::setCmdLineFlagOverrides() const { FLAGS_enable_macsec = true; - FLAGS_skip_drain_check_for_prbs = true; AgentEnsembleTest::setCmdLineFlagOverrides(); } diff --git a/fboss/agent/test/link_tests/AgentEnsembleLinkTest.h b/fboss/agent/test/link_tests/AgentEnsembleLinkTest.h index a16cccfa99853..3c839ca6195f6 100644 --- a/fboss/agent/test/link_tests/AgentEnsembleLinkTest.h +++ b/fboss/agent/test/link_tests/AgentEnsembleLinkTest.h @@ -11,7 +11,6 @@ #include DECLARE_string(config); -DECLARE_bool(skip_drain_check_for_prbs); DECLARE_bool(link_stress_test); DECLARE_bool(disable_neighbor_updates); diff --git a/fboss/agent/test/link_tests/BUCK b/fboss/agent/test/link_tests/BUCK index e009412423c5c..0dc9ed02110e8 100644 --- a/fboss/agent/test/link_tests/BUCK +++ b/fboss/agent/test/link_tests/BUCK @@ -195,6 +195,11 @@ cpp_library( "AgentEnsemblePtpTests.cpp", "LinkTestUtils.cpp", "facebook/AgentEnsembleFsdbTests.cpp", + "facebook/AgentEnsembleMacsecFsdbTests.cpp", + "facebook/AgentEnsembleMacsecSanityTests.cpp", + "facebook/AgentEnsembleMacsecSessionTests.cpp", + "facebook/AgentEnsembleMacsecStatTests.cpp", + "facebook/AgentEnsembleMacsecTest.cpp", "facebook/AgentEnsembleQsfpFsdbTests.cpp", ], link_whole = True, @@ -219,6 +224,7 @@ cpp_library( "//fboss/agent/state:state_utils", "//fboss/agent/test:agent_ensemble_test", "//fboss/agent/test:ecmp_helper", + "//fboss/agent/test:resourcelibutil", "//fboss/agent/test:trunk_utils", "//fboss/agent/test:utils", "//fboss/agent/test/utils:copp_test_utils", @@ -227,6 +233,8 @@ cpp_library( "//fboss/agent/test/utils:pkt_test_utils", "//fboss/agent/test/utils:qos_test_utils", "//fboss/agent/test/utils:trap_packet_utils", + "//fboss/facebook/mka_service/fsdb/tests:MKAFsdbTestUtils", + "//fboss/facebook/mka_service/mka_module:mka_structs", "//fboss/fsdb/client:fsdb_pub_sub", "//fboss/fsdb/common:flags", "//fboss/fsdb/if:fsdb_model", @@ -237,13 +245,19 @@ cpp_library( "//fboss/lib/phy:phy-cpp2-types", "//fboss/lib/phy:prbs-cpp2-types", "//fboss/lib/thrift_service_client:thrift-service-client", + "//fboss/mka_service/if/facebook:mka_config-cpp2-types", + "//fboss/mka_service/if/facebook:mka_service_thrift-cpp2-services", "//fboss/qsfp_service/fsdb/facebook/test:fsdb-test-utils", "//fboss/qsfp_service/if:transceiver-cpp2-types", + "//fboss/qsfp_service/lib:qsfp-service-client", "//folly:network_address", "//folly:string", "//folly:subprocess", "//folly/debugging/exception_tracer:exception_tracer", + "//folly/io/async:scoped_event_base_thread", + "//folly/json:dynamic", "//folly/logging:logging", + "//thrift/lib/cpp2/async:rocket_client_channel", "//thrift/lib/cpp2/protocol:protocol", ], exported_external_deps = [ diff --git a/fboss/agent/test/link_tests/LinkTest.cpp b/fboss/agent/test/link_tests/LinkTest.cpp index 5257d1fc38fe4..2ae1b4102b8ae 100644 --- a/fboss/agent/test/link_tests/LinkTest.cpp +++ b/fboss/agent/test/link_tests/LinkTest.cpp @@ -59,7 +59,6 @@ void LinkTest::TearDown() { void LinkTest::setCmdLineFlagOverrides() const { FLAGS_enable_macsec = true; - FLAGS_skip_drain_check_for_prbs = true; AgentTest::setCmdLineFlagOverrides(); } diff --git a/fboss/agent/test/link_tests/LinkTest.h b/fboss/agent/test/link_tests/LinkTest.h index c9e5b22f1fb02..9588548aa880e 100644 --- a/fboss/agent/test/link_tests/LinkTest.h +++ b/fboss/agent/test/link_tests/LinkTest.h @@ -19,7 +19,6 @@ DECLARE_bool(disable_neighbor_updates); DECLARE_bool(link_stress_test); DECLARE_bool(enable_macsec); -DECLARE_bool(skip_drain_check_for_prbs); namespace facebook::fboss { using namespace std::chrono_literals; diff --git a/fboss/agent/test/link_tests/PhyInfoTest.cpp b/fboss/agent/test/link_tests/PhyInfoTest.cpp index 4b26359dcc47f..23b60651d418d 100644 --- a/fboss/agent/test/link_tests/PhyInfoTest.cpp +++ b/fboss/agent/test/link_tests/PhyInfoTest.cpp @@ -64,6 +64,7 @@ void validateInterfaceAndMedium( }}, {TransmitterTechnology::BACKPLANE, { + phy::InterfaceType::CR4, phy::InterfaceType::KR, phy::InterfaceType::KR2, phy::InterfaceType::KR4, diff --git a/fboss/agent/test/production_features.thrift b/fboss/agent/test/production_features.thrift index 2a366bdcec225..19df050545982 100644 --- a/fboss/agent/test/production_features.thrift +++ b/fboss/agent/test/production_features.thrift @@ -33,12 +33,12 @@ enum ProductionFeature { ECN = 20, WRED = 21, QUEUE_PER_HOST = 22, - JUMBO_FRAMES = 23, + JUMBO_FRAMES = 23, // Misc TRAP_DISCARDS_COUNTER = 24, MAC_LEARNING = 25, SCHEDULER_PPS = 26, ROUTE_COUNTERS = 27, - PORT_TX_DISABLE = 28, + PORT_TX_DISABLE = 28, // Misc SFLOWv4_SAMPLING = 29, SFLOWv6_SAMPLING = 30, MIRROR_PACKET_TRUNCATION = 31, @@ -46,12 +46,14 @@ enum ProductionFeature { INTERFACE_NEIGHBOR_TABLE = 33, INGRESS_MIRRORING = 34, EGRESS_MIRRORING = 35, - RSW_ROUTE_SCALE = 36, - FSW_ROUTE_SCALE = 37, - HGRID_DU_ROUTE_SCALE = 38, - HGRID_UU_ROUTE_SCALE = 39, - HUNDRED_THOUSAND_ROUTE_SCALE = 40, + RSW_ROUTE_SCALE = 36, // Misc + FSW_ROUTE_SCALE = 37, // Misc + HGRID_DU_ROUTE_SCALE = 38, // Misc + HGRID_UU_ROUTE_SCALE = 39, // Misc + HUNDRED_THOUSAND_ROUTE_SCALE = 40, // Misc TH_ALPM_ROUTE_SCALE = 41, + PFC = 42, + UDF_WR_IMMEDIATE_ACL = 43, # production feature which is present on all platforms, keep it at the end HW_SWITCH = 65536, } diff --git a/fboss/agent/test/utils/BUCK b/fboss/agent/test/utils/BUCK index 9de51bd887246..74e92015fe26d 100644 --- a/fboss/agent/test/utils/BUCK +++ b/fboss/agent/test/utils/BUCK @@ -106,11 +106,12 @@ cpp_library( ], headers = ["OlympicTestUtils.h"], exported_deps = [ - ":asic_test_utils", - ":traffic_policy_utils", - "//fboss/agent:fboss-error", - "//fboss/agent:switch_config-cpp2-types", - "//fboss/agent/hw/switch_asics:switch_asics", + "fbcode//fboss/agent:fboss-error", + "fbcode//fboss/agent:switch_config-cpp2-types", + "fbcode//fboss/agent:utils", + "fbcode//fboss/agent/hw/switch_asics:switch_asics", + "fbcode//fboss/agent/test/utils:asic_test_utils", + "fbcode//fboss/agent/test/utils:traffic_policy_utils", ], ) @@ -433,10 +434,27 @@ cpp_library( ":trap_packet_utils", "//fboss/agent:fboss-types", "//fboss/agent:switch_config-cpp2-types", + "//fboss/agent/test:agent_ensemble", "//folly:network_address", ], ) +cpp_library( + name = "pfc_test_utils", + srcs = [ + "PfcTestUtils.cpp", + ], + headers = [ + "PfcTestUtils.h", + ], + exported_deps = [ + "fbsource//third-party/googletest:gtest", + "//fboss/agent:fboss-types", + "//fboss/agent:switch_config-cpp2-types", + "//fboss/agent:utils", + ], +) + cpp_library( name = "queue_test_utils", srcs = [ diff --git a/fboss/agent/test/utils/ConfigUtils.cpp b/fboss/agent/test/utils/ConfigUtils.cpp index 82bdb4bcc4826..13d28f0821033 100644 --- a/fboss/agent/test/utils/ConfigUtils.cpp +++ b/fboss/agent/test/utils/ConfigUtils.cpp @@ -376,14 +376,16 @@ cfg::DsfNode dsfNodeConfig( auto fromAsicSystemPortRange = fromAsic.getSystemPortRange(); if (fromAsicSystemPortRange.has_value()) { cfg::Range64 range; - auto blockSize = *fromAsicSystemPortRange->maximum() - - *fromAsicSystemPortRange->minimum(); + int numCores = fromAsic.getNumCores(); + auto blockSize = (*fromAsicSystemPortRange->maximum() - + *fromAsicSystemPortRange->minimum() + 1) / + numCores; range.minimum() = systemPortMin.has_value() ? kSysPortOffset + systemPortMin.value() : kSysPortOffset + switchId * blockSize; range.maximum() = systemPortMax.has_value() ? kSysPortOffset + systemPortMax.value() - : *range.minimum() + blockSize; + : *range.minimum() + numCores * blockSize - 1; systemPortRange = range; } auto localMac = utility::kLocalCpuMac(); diff --git a/fboss/agent/test/utils/CoppTestUtils.cpp b/fboss/agent/test/utils/CoppTestUtils.cpp index a2cb32267077a..4dac92a39cebf 100644 --- a/fboss/agent/test/utils/CoppTestUtils.cpp +++ b/fboss/agent/test/utils/CoppTestUtils.cpp @@ -11,6 +11,7 @@ #include "fboss/agent/FbossError.h" #include "fboss/agent/HwSwitch.h" +#include "fboss/agent/LldpManager.h" #include "fboss/agent/SwSwitch.h" #include "fboss/agent/TxPacket.h" #include "fboss/agent/hw/switch_asics/HwAsic.h" @@ -474,6 +475,37 @@ void addHighPriAclForBgp( {cfg::EtherType::IPv4, cfg::EtherType::IPv6}); } +void addHighPriAclForArp( + cfg::ToCpuAction toCpuAction, + int highPriQueueId, + std::vector>& acls, + bool isSai) { + cfg::AclEntry acl1; + acl1.etherType() = cfg::EtherType::ARP; + acl1.ipType() = cfg::IpType::ARP_REQUEST; + acl1.name() = folly::to("cpuPolicing-high-arp-request-acl"); + auto action = createQueueMatchAction(highPriQueueId, isSai, toCpuAction); + acls.push_back(std::make_pair(acl1, action)); + cfg::AclEntry acl2; + acl2.etherType() = cfg::EtherType::ARP; + acl2.ipType() = cfg::IpType::ARP_REPLY; + acl2.name() = folly::to("cpuPolicing-high-arp-reply-acl"); + acls.push_back(std::make_pair(acl2, action)); +} + +void addMidPriAclForLldp( + cfg::ToCpuAction toCpuAction, + int midPriQueueId, + std::vector>& acls, + bool isSai) { + cfg::AclEntry acl; + acl.etherType() = cfg::EtherType::LLDP; + acl.dstMac() = LldpManager::LLDP_DEST_MAC.toString(); + acl.name() = folly::to("cpuPolicing-mid-lldp-acl"); + auto action = createQueueMatchAction(midPriQueueId, isSai, toCpuAction); + acls.push_back(std::make_pair(acl, action)); +} + void addMidPriAclForIp2Me( const HwAsic* hwAsic, cfg::ToCpuAction toCpuAction, @@ -699,6 +731,9 @@ std::vector> defaultCpuAclsForSai( hwAsic, cfg::ToCpuAction::TRAP, acls, true /*isSai*/); if (hwAsic->isSupported(HwAsic::Feature::NO_RX_REASON_TRAP)) { + addHighPriAclForArp( + + cfg::ToCpuAction::TRAP, getCoppHighPriQueueId(hwAsic), acls, true); addHighPriAclForBgp( hwAsic, cfg::ToCpuAction::TRAP, @@ -711,6 +746,8 @@ std::vector> defaultCpuAclsForSai( getCoppMidPriQueueId({hwAsic}), acls, true); + addMidPriAclForLldp( + cfg::ToCpuAction::TRAP, getCoppMidPriQueueId({hwAsic}), acls, true); } } @@ -949,18 +986,12 @@ std::vector getCoppRxReasonToQueuesForSai( if (hwAsic->isSupported(HwAsic::Feature::NO_RX_REASON_TRAP)) { // TODO(daiweix): remove these rx reason traps and replace them by ACLs rxReasonToQueues = { - ControlPlane::makeRxReasonToQueueEntry( - cfg::PacketRxReason::ARP, coppHighPriQueueId), - ControlPlane::makeRxReasonToQueueEntry( - cfg::PacketRxReason::ARP_RESPONSE, coppHighPriQueueId), ControlPlane::makeRxReasonToQueueEntry( cfg::PacketRxReason::NDP, coppHighPriQueueId), ControlPlane::makeRxReasonToQueueEntry( cfg::PacketRxReason::LACP, coppHighPriQueueId), ControlPlane::makeRxReasonToQueueEntry( cfg::PacketRxReason::TTL_1, kCoppLowPriQueueId), - ControlPlane::makeRxReasonToQueueEntry( - cfg::PacketRxReason::LLDP, coppMidPriQueueId), ControlPlane::makeRxReasonToQueueEntry( cfg::PacketRxReason::DHCP, coppMidPriQueueId), ControlPlane::makeRxReasonToQueueEntry( diff --git a/fboss/agent/test/utils/MirrorTestUtils.cpp b/fboss/agent/test/utils/MirrorTestUtils.cpp index 2166b35847de3..7391c9d880453 100644 --- a/fboss/agent/test/utils/MirrorTestUtils.cpp +++ b/fboss/agent/test/utils/MirrorTestUtils.cpp @@ -7,11 +7,72 @@ namespace facebook::fboss::utility { +template <> +MirrorTestParams getMirrorTestParams() { + return MirrorTestParams( + folly::IPAddressV4("101.0.0.10"), // sender + folly::IPAddressV4("201.0.0.10"), // receiver + folly::IPAddressV4("101.0.0.11")); // erspan destination +} + +template <> +MirrorTestParams getMirrorTestParams() { + return MirrorTestParams( + folly::IPAddressV6("101::10"), // sender + folly::IPAddressV6("201::10"), // receiver + folly::IPAddressV6("101::11")); // erspan destination +} + folly::IPAddress getSflowMirrorDestination(bool isV4) { return isV4 ? folly::IPAddress("101.101.101.101") : folly::IPAddress("2401:101:101::101"); } +/* + * This configures a local/erspan mirror session. + * Adds a tunnel config if the mirrorname is erspan. + */ +template +void addMirrorConfig( + cfg::SwitchConfig* cfg, + const AgentEnsemble& ensemble, + const std::string& mirrorName, + bool truncate, + uint8_t dscp) { + auto mirrorToPort = ensemble.masterLogicalPortIds( + {cfg::PortType::INTERFACE_PORT})[kMirrorToPortIndex]; + auto params = getMirrorTestParams(); + cfg::MirrorDestination destination; + destination.egressPort() = cfg::MirrorEgressPort(); + destination.egressPort()->logicalID_ref() = mirrorToPort; + if (mirrorName == kIngressErspan || mirrorName == kEgressErspan) { + cfg::MirrorTunnel tunnel; + cfg::GreTunnel greTunnel; + greTunnel.ip() = params.mirrorDestinationIp.str(); + tunnel.greTunnel() = greTunnel; + destination.tunnel() = tunnel; + } + cfg::Mirror mirrorConfig; + mirrorConfig.name() = mirrorName; + mirrorConfig.destination() = destination; + mirrorConfig.truncate() = truncate; + mirrorConfig.dscp() = dscp; + cfg->mirrors()->push_back(mirrorConfig); +} + +template void addMirrorConfig( + cfg::SwitchConfig* cfg, + const AgentEnsemble& ensemble, + const std::string& mirrorName, + bool truncate, + uint8_t dscp); +template void addMirrorConfig( + cfg::SwitchConfig* cfg, + const AgentEnsemble& ensemble, + const std::string& mirrorName, + bool truncate, + uint8_t dscp); + void configureSflowMirror( cfg::SwitchConfig& config, const std::string& mirrorName, diff --git a/fboss/agent/test/utils/MirrorTestUtils.h b/fboss/agent/test/utils/MirrorTestUtils.h index 75032bd241386..9c5e1af498e24 100644 --- a/fboss/agent/test/utils/MirrorTestUtils.h +++ b/fboss/agent/test/utils/MirrorTestUtils.h @@ -4,12 +4,51 @@ #include "fboss/agent/gen-cpp2/switch_config_types.h" +#include "fboss/agent/test/AgentEnsemble.h" #include "fboss/agent/types.h" #include namespace facebook::fboss::utility { +template +struct MirrorTestParams { + AddrT senderIp; + AddrT receiverIp; + AddrT mirrorDestinationIp; + + MirrorTestParams( + const AddrT& _senderIp, + const AddrT& _receiverIp, + const AddrT& _mirrorDestinationIp) + : senderIp(_senderIp), + receiverIp(_receiverIp), + mirrorDestinationIp(_mirrorDestinationIp) {} +}; + +template +MirrorTestParams getMirrorTestParams(); + +inline const std::string kIngressSpan("ingress_span"); +inline const std::string kIngressErspan("ingress_erspan"); +inline const std::string kEgressSpan("egress_span"); +inline const std::string kEgressErspan("egress_erspan"); + +// Port 0 is used for traffic and port 1 is used for mirroring. +inline const uint8_t kTrafficPortIndex = 0; +inline const uint8_t kMirrorToPortIndex = 1; + +constexpr auto kDscpDefault = facebook::fboss::cfg::switch_config_constants:: + DEFAULT_MIRROR_DSCP_; // default dscp value + +template +void addMirrorConfig( + cfg::SwitchConfig* cfg, + const AgentEnsemble& ensemble, + const std::string& mirrorName, + bool truncate, + uint8_t dscp = kDscpDefault); + folly::IPAddress getSflowMirrorDestination(bool isV4); void configureSflowMirror( diff --git a/fboss/agent/test/utils/OlympicTestUtils.cpp b/fboss/agent/test/utils/OlympicTestUtils.cpp index 2e7cba8d19c01..c7b10009e4e12 100644 --- a/fboss/agent/test/utils/OlympicTestUtils.cpp +++ b/fboss/agent/test/utils/OlympicTestUtils.cpp @@ -168,6 +168,26 @@ void addOlympicQueueConfigWithSchedulingHelper( } } // namespace +void addEventorVoqConfig( + cfg::SwitchConfig* config, + cfg::StreamType streamType) { + // Eventor port queue config + cfg::PortQueue queue; + *queue.id() = 0; + queue.streamType() = streamType; + queue.name() = "default"; + *queue.scheduling() = cfg::QueueScheduling::INTERNAL; + queue.maxDynamicSharedBytes() = 20 * 1024 * 1024; + std::vector eventorVoqConfig{std::move(queue)}; + const std::string kEventorQueueConfigName{"eventor_queue_config"}; + config->portQueueConfigs()[kEventorQueueConfigName] = eventorVoqConfig; + for (auto& port : *config->ports()) { + if (*port.portType() == cfg::PortType::EVENTOR_PORT) { + port.portVoqConfigName() = kEventorQueueConfigName; + } + } +} + int getOlympicQueueId(OlympicQueueType queueType) { switch (queueType) { case OlympicQueueType::SILVER: diff --git a/fboss/agent/test/utils/OlympicTestUtils.h b/fboss/agent/test/utils/OlympicTestUtils.h index 8faf96f97505f..c4d39dd8ae63f 100644 --- a/fboss/agent/test/utils/OlympicTestUtils.h +++ b/fboss/agent/test/utils/OlympicTestUtils.h @@ -209,6 +209,7 @@ void addQueueBurstSizeConfig( const int queueId, const uint32_t minKbits, const uint32_t maxKbits); +void addEventorVoqConfig(cfg::SwitchConfig* config, cfg::StreamType streamType); int getOlympicQueueId(OlympicQueueType queueType); diff --git a/fboss/agent/test/utils/PfcTestUtils.cpp b/fboss/agent/test/utils/PfcTestUtils.cpp new file mode 100644 index 0000000000000..32ab1d9f356cb --- /dev/null +++ b/fboss/agent/test/utils/PfcTestUtils.cpp @@ -0,0 +1,174 @@ +// (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary. + +#include "fboss/agent/test/utils/PfcTestUtils.h" +#include "fboss/agent/Utils.h" +#include "fboss/agent/gen-cpp2/switch_config_types.h" + +#include + +namespace facebook::fboss::utility { + +namespace { + +static const std::vector kLossyPgIds{0}; + +void setupQosMapForPfc( + cfg::QosMap& qosMap, + const std::map& tc2PgOverride = {}, + const std::map& pfcPri2PgIdOverride = {}) { + // update pfc maps + std::map tc2PgId; + std::map tc2QueueId; + std::map pfcPri2PgId; + std::map pfcPri2QueueId; + // program defaults + for (auto i = 0; i < 8; i++) { + tc2PgId.emplace(i, i); + // Jericho3 cpu/recycle port only has 2 egress queues. Tomahawk has more + // queues, but we stick to the lowest common denominator here. + // See https://fburl.com/gdoc/nyyg1cve and https://fburl.com/code/mhdeuiky + tc2QueueId.emplace(i, i < 7 ? 0 : 1); + pfcPri2PgId.emplace(i, i); + pfcPri2QueueId.emplace(i, i); + } + + for (auto& tc2Pg : tc2PgOverride) { + tc2PgId[tc2Pg.first] = tc2Pg.second; + } + for (auto& tmp : pfcPri2PgIdOverride) { + pfcPri2PgId[tmp.first] = tmp.second; + } + + qosMap.dscpMaps()->resize(8); + for (auto i = 0; i < 8; i++) { + qosMap.dscpMaps()[i].internalTrafficClass() = i; + for (auto j = 0; j < 8; j++) { + qosMap.dscpMaps()[i].fromDscpToTrafficClass()->push_back(8 * i + j); + } + } + qosMap.trafficClassToPgId() = std::move(tc2PgId); + qosMap.trafficClassToQueueId() = std::move(tc2QueueId); + qosMap.pfcPriorityToPgId() = std::move(pfcPri2PgId); + qosMap.pfcPriorityToQueueId() = std::move(pfcPri2QueueId); +} + +void setupPfc(cfg::SwitchConfig& cfg, const std::vector& ports) { + cfg::PortPfc pfc; + pfc.tx() = true; + pfc.rx() = true; + pfc.portPgConfigName() = "foo"; + + cfg::QosMap qosMap; + // setup qos map with pfc structs + setupQosMapForPfc(qosMap); + + // setup qosPolicy + cfg.qosPolicies()->resize(1); + cfg.qosPolicies()[0].name() = "qp"; + cfg.qosPolicies()[0].qosMap() = std::move(qosMap); + cfg::TrafficPolicyConfig dataPlaneTrafficPolicy; + dataPlaneTrafficPolicy.defaultQosPolicy() = "qp"; + cfg.dataPlaneTrafficPolicy() = std::move(dataPlaneTrafficPolicy); + + for (const auto& portID : ports) { + auto portCfg = std::find_if( + cfg.ports()->begin(), cfg.ports()->end(), [&portID](auto& port) { + return PortID(*port.logicalID()) == portID; + }); + portCfg->pfc() = pfc; + } +} + +void setupBufferPoolConfig( + std::map& bufferPoolCfgMap, + int globalSharedBytes, + int globalHeadroomBytes) { + cfg::BufferPoolConfig poolConfig; + // provide small shared buffer size + // idea is to hit the limit and trigger XOFF (PFC) + poolConfig.sharedBytes() = globalSharedBytes; + poolConfig.headroomBytes() = globalHeadroomBytes; + bufferPoolCfgMap.insert(std::make_pair("bufferNew", poolConfig)); +} + +void setupPortPgConfig( + std::map>& portPgConfigMap, + const std::vector& losslessPgIds, + int pgLimit, + int pgHeadroom, + std::optional scalingFactor, + int resumeOffset) { + std::vector portPgConfigs; + // create 2 pgs + for (auto pgId : losslessPgIds) { + cfg::PortPgConfig pgConfig; + pgConfig.id() = pgId; + pgConfig.bufferPoolName() = "bufferNew"; + // provide atleast 1 cell worth of minLimit + pgConfig.minLimitBytes() = pgLimit; + // set large enough headroom to avoid drop + pgConfig.headroomLimitBytes() = pgHeadroom; + // resume offset + pgConfig.resumeOffsetBytes() = resumeOffset; + // set scaling factor + if (scalingFactor) { + pgConfig.scalingFactor() = *scalingFactor; + } + portPgConfigs.emplace_back(pgConfig); + } + + // create lossy pgs + if (!FLAGS_allow_zero_headroom_for_lossless_pg) { + // If the flag is set, we already have lossless PGs being created + // with headroom as 0 and there is no way to differentiate lossy + // and lossless PGs now that headroom is set to zero for lossless. + // So, avoid creating lossy PGs as this will result in PFC being + // enabled for 3 priorities, which is not supported for TAJO. + for (auto pgId : kLossyPgIds) { + cfg::PortPgConfig pgConfig; + pgConfig.id() = pgId; + pgConfig.bufferPoolName() = "bufferNew"; + // provide atleast 1 cell worth of minLimit + pgConfig.minLimitBytes() = pgLimit; + // headroom set 0 identifies lossy pgs + pgConfig.headroomLimitBytes() = 0; + // resume offset + pgConfig.resumeOffsetBytes() = resumeOffset; + // set scaling factor + if (scalingFactor) { + pgConfig.scalingFactor() = *scalingFactor; + } + portPgConfigs.emplace_back(pgConfig); + } + } + + portPgConfigMap["foo"] = std::move(portPgConfigs); +} + +} // namespace + +void setupPfcBuffers( + cfg::SwitchConfig& cfg, + const std::vector& ports, + const std::vector& losslessPgIds, + PfcBufferParams buffer) { + setupPfc(cfg, ports); + + std::map> portPgConfigMap; + setupPortPgConfig( + portPgConfigMap, + losslessPgIds, + buffer.pgLimit, + buffer.pgHeadroom, + buffer.scalingFactor, + buffer.resumeOffset); + cfg.portPgConfigs() = std::move(portPgConfigMap); + + // create buffer pool + std::map bufferPoolCfgMap; + setupBufferPoolConfig( + bufferPoolCfgMap, buffer.globalShared, buffer.globalHeadroom); + cfg.bufferPoolConfigs() = std::move(bufferPoolCfgMap); +} + +} // namespace facebook::fboss::utility diff --git a/fboss/agent/test/utils/PfcTestUtils.h b/fboss/agent/test/utils/PfcTestUtils.h new file mode 100644 index 0000000000000..eae8978998840 --- /dev/null +++ b/fboss/agent/test/utils/PfcTestUtils.h @@ -0,0 +1,26 @@ +// (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary. + +#pragma once + +#include "fboss/agent/gen-cpp2/switch_config_types.h" +#include "fboss/agent/types.h" + +namespace facebook::fboss::utility { + +struct PfcBufferParams { + int globalShared = 20000; + int globalHeadroom = 5000; // keep this lower than globalShared + int pgLimit = 2200; + int pgHeadroom = 2200; // keep this lower than globalShared + std::optional scalingFactor = + facebook::fboss::cfg::MMUScalingFactor::ONE_128TH; + int resumeOffset = 1800; +}; + +void setupPfcBuffers( + cfg::SwitchConfig& cfg, + const std::vector& ports, + const std::vector& losslessPgIds, + PfcBufferParams buffer = PfcBufferParams{}); + +} // namespace facebook::fboss::utility diff --git a/fboss/agent/test/utils/TrafficPolicyTestUtils.cpp b/fboss/agent/test/utils/TrafficPolicyTestUtils.cpp index 350f7ba735572..26fd9d3291231 100644 --- a/fboss/agent/test/utils/TrafficPolicyTestUtils.cpp +++ b/fboss/agent/test/utils/TrafficPolicyTestUtils.cpp @@ -79,14 +79,14 @@ void addL2ClassIDAndTtlAcl( const std::string& aclName, cfg::AclLookupClass lookupClassL2, std::optional ttl) { - auto numCfgAcls = config->acls()->size(); - config->acls()->resize(numCfgAcls + 1); - *config->acls()[numCfgAcls].name() = aclName; - - config->acls()[numCfgAcls].lookupClassL2() = lookupClassL2; + auto acl = cfg::AclEntry(); + *acl.name() = aclName; + acl.lookupClassL2() = lookupClassL2; if (ttl.has_value()) { - config->acls()[numCfgAcls].ttl() = ttl.value(); + acl.ttl() = ttl.value(); } + + utility::addAclEntry(config, acl, utility::kDefaultAclTable()); } void addNeighborClassIDAndTtlAcl( @@ -94,47 +94,50 @@ void addNeighborClassIDAndTtlAcl( const std::string& aclName, cfg::AclLookupClass lookupClassNeighbor, std::optional ttl) { - auto numCfgAcls = config->acls()->size(); - config->acls()->resize(numCfgAcls + 1); - *config->acls()[numCfgAcls].name() = aclName; - - config->acls()[numCfgAcls].lookupClassNeighbor() = lookupClassNeighbor; + auto acl = cfg::AclEntry(); + *acl.name() = aclName; + acl.lookupClassNeighbor() = lookupClassNeighbor; if (ttl.has_value()) { - config->acls()[numCfgAcls].ttl() = ttl.value(); + acl.ttl() = ttl.value(); } + + utility::addAclEntry(config, acl, utility::kDefaultAclTable()); } void addL2ClassIDDropAcl( cfg::SwitchConfig* config, const std::string& aclName, cfg::AclLookupClass lookupClassL2) { - auto numCfgAcls = config->acls()->size(); - config->acls()->resize(numCfgAcls + 1); - config->acls()[numCfgAcls].name() = aclName; - config->acls()[numCfgAcls].lookupClassL2() = lookupClassL2; - config->acls()[numCfgAcls].actionType() = cfg::AclActionType::DENY; + auto acl = cfg::AclEntry(); + *acl.name() = aclName; + acl.lookupClassL2() = lookupClassL2; + acl.actionType() = cfg::AclActionType::DENY; + + utility::addAclEntry(config, acl, utility::kDefaultAclTable()); } void addNeighborClassIDDropAcl( cfg::SwitchConfig* config, const std::string& aclName, cfg::AclLookupClass lookupClassNeighbor) { - auto numCfgAcls = config->acls()->size(); - config->acls()->resize(numCfgAcls + 1); - config->acls()[numCfgAcls].name() = aclName; - config->acls()[numCfgAcls].lookupClassNeighbor() = lookupClassNeighbor; - config->acls()[numCfgAcls].actionType() = cfg::AclActionType::DENY; + auto acl = cfg::AclEntry(); + *acl.name() = aclName; + acl.lookupClassNeighbor() = lookupClassNeighbor; + acl.actionType() = cfg::AclActionType::DENY; + + utility::addAclEntry(config, acl, utility::kDefaultAclTable()); } void addRouteClassIDDropAcl( cfg::SwitchConfig* config, const std::string& aclName, cfg::AclLookupClass lookupClassRoute) { - auto numCfgAcls = config->acls()->size(); - config->acls()->resize(numCfgAcls + 1); - config->acls()[numCfgAcls].name() = aclName; - config->acls()[numCfgAcls].lookupClassRoute() = lookupClassRoute; - config->acls()[numCfgAcls].actionType() = cfg::AclActionType::DENY; + auto acl = cfg::AclEntry(); + *acl.name() = aclName; + acl.lookupClassRoute() = lookupClassRoute; + acl.actionType() = cfg::AclActionType::DENY; + + utility::addAclEntry(config, acl, utility::kDefaultAclTable()); } void addRouteClassIDAndTtlAcl( @@ -142,14 +145,14 @@ void addRouteClassIDAndTtlAcl( const std::string& aclName, cfg::AclLookupClass lookupClassRoute, std::optional ttl) { - auto numCfgAcls = config->acls()->size(); - config->acls()->resize(numCfgAcls + 1); - *config->acls()[numCfgAcls].name() = aclName; - - config->acls()[numCfgAcls].lookupClassRoute() = lookupClassRoute; + auto acl = cfg::AclEntry(); + *acl.name() = aclName; + acl.lookupClassRoute() = lookupClassRoute; if (ttl.has_value()) { - config->acls()[numCfgAcls].ttl() = ttl.value(); + acl.ttl() = ttl.value(); } + + utility::addAclEntry(config, acl, utility::kDefaultAclTable()); } void addQueueMatcher( diff --git a/fboss/agent/test/utils/VoqTestUtils.cpp b/fboss/agent/test/utils/VoqTestUtils.cpp index d28b814593173..7ab0e5b1a37ae 100644 --- a/fboss/agent/test/utils/VoqTestUtils.cpp +++ b/fboss/agent/test/utils/VoqTestUtils.cpp @@ -25,6 +25,7 @@ constexpr auto kNumEdsw = 16; constexpr auto kNumRdswSysPort = 44; constexpr auto kNumEdswSysPort = 26; constexpr auto kJ2NumSysPort = 20; +constexpr auto kNumVoq = 8; int getPerNodeSysPorts(const HwAsic* asic, int remoteSwitchId) { if (asic->getAsicType() == cfg::AsicType::ASIC_TYPE_JERICHO2) { @@ -35,6 +36,66 @@ int getPerNodeSysPorts(const HwAsic* asic, int remoteSwitchId) { } return kNumEdswSysPort; } + +std::shared_ptr makeRemoteSysPort( + SystemPortID portId, + SwitchID remoteSwitchId, + int coreIndex, + int corePortIndex, + int64_t speed) { + auto remoteSysPort = std::make_shared(portId); + auto voqConfig = getDefaultVoqConfig(); + remoteSysPort->setName(folly::to( + "hwTestSwitch", remoteSwitchId, ":eth/", portId, "/1")); + remoteSysPort->setSwitchId(remoteSwitchId); + remoteSysPort->setNumVoqs(kNumVoq); + remoteSysPort->setCoreIndex(coreIndex); + remoteSysPort->setCorePortIndex(corePortIndex); + remoteSysPort->setSpeedMbps(speed); + remoteSysPort->resetPortQueues(voqConfig); + remoteSysPort->setScope(cfg::Scope::GLOBAL); + return remoteSysPort; +} + +std::shared_ptr makeRemoteInterface( + InterfaceID intfId, + const Interface::Addresses& subnets) { + auto remoteIntf = std::make_shared( + intfId, + RouterID(0), + std::optional(std::nullopt), + folly::StringPiece("RemoteIntf"), + folly::MacAddress("c6:ca:2b:2a:b1:b6"), + 9000, + false, + false, + cfg::InterfaceType::SYSTEM_PORT); + remoteIntf->setAddresses(subnets); + remoteIntf->setScope(cfg::Scope::GLOBAL); + return remoteIntf; +} + +void updateRemoteIntfWithNeighbor( + std::shared_ptr& remoteIntf, + InterfaceID intfId, + PortDescriptor port, + const folly::IPAddressV6& neighborIp, + std::optional encapIndex) { + const folly::MacAddress kNeighborMac{"2:3:4:5:6:7"}; + state::NeighborEntryFields ndp; + auto ndpTable = remoteIntf->getNdpTable()->clone(); + ndp.mac() = kNeighborMac.toString(); + ndp.ipaddress() = neighborIp.str(); + ndp.portId() = port.toThrift(); + ndp.interfaceId() = static_cast(intfId); + ndp.state() = state::NeighborState::Reachable; + if (encapIndex) { + ndp.encapIndex() = *encapIndex; + } + ndp.isLocal() = false; + ndpTable->emplace(neighborIp.str(), std::move(ndp)); + remoteIntf->setNdpTable(ndpTable->toThrift()); +} } // namespace int getDsfNodeCount(const HwAsic* asic) { @@ -64,10 +125,14 @@ std::optional> addRemoteDsfNodeCfg( CHECK( !numRemoteNodes.has_value() || numRemoteNodes.value() < getDsfNodeCount(asic.get())); - int totalNodes = numRemoteNodes.has_value() ? numRemoteNodes.value() + 1 - : getDsfNodeCount(asic.get()); - int systemPortMin = getPerNodeSysPorts(asic.get(), 1); - for (int remoteSwitchId = numCores; remoteSwitchId < totalNodes * numCores; + int totalNodes = numRemoteNodes.has_value() + ? numRemoteNodes.value() + curDsfNodes.size() + : getDsfNodeCount(asic.get()); + int remoteNodeStart = dsfNodes.rbegin()->first + numCores; + int systemPortMin = getPerNodeSysPorts(asic.get(), dsfNodes.begin()->first) * + curDsfNodes.size(); + for (int remoteSwitchId = remoteNodeStart; + remoteSwitchId < totalNodes * numCores; remoteSwitchId += numCores) { cfg::Range64 systemPortRange; systemPortRange.minimum() = systemPortMin; @@ -77,7 +142,8 @@ std::optional> addRemoteDsfNodeCfg( *asic, SwitchID(remoteSwitchId), systemPortMin, - *systemPortRange.maximum()); + *systemPortRange.maximum(), + *firstDsfNode.platformType()); dsfNodes.insert({remoteSwitchId, remoteDsfNodeCfg}); systemPortMin = *systemPortRange.maximum() + 1; } @@ -95,15 +161,12 @@ std::shared_ptr addRemoteSysPort( const auto& localPorts = newState->getSystemPorts()->cbegin()->second; auto localPort = localPorts->cbegin()->second; auto remoteSystemPorts = newState->getRemoteSystemPorts()->modify(&newState); - auto remoteSysPort = std::make_shared(portId); - remoteSysPort->setName(folly::to( - "hwTestSwitch", remoteSwitchId, ":eth/", portId, "/1")); - remoteSysPort->setSwitchId(remoteSwitchId); - remoteSysPort->setNumVoqs(localPort->getNumVoqs()); - remoteSysPort->setCoreIndex(coreIndex); - remoteSysPort->setCorePortIndex(corePortIndex); - remoteSysPort->setSpeedMbps(localPort->getSpeedMbps()); - remoteSysPort->resetPortQueues(getDefaultVoqConfig()); + auto remoteSysPort = makeRemoteSysPort( + portId, + remoteSwitchId, + coreIndex, + corePortIndex, + localPort->getSpeedMbps()); remoteSystemPorts->addNode(remoteSysPort, scopeResolver.scope(remoteSysPort)); return newState; } @@ -124,17 +187,7 @@ std::shared_ptr addRemoteInterface( const Interface::Addresses& subnets) { auto newState = currState; auto newRemoteInterfaces = newState->getRemoteInterfaces()->modify(&newState); - auto newRemoteInterface = std::make_shared( - intfId, - RouterID(0), - std::optional(std::nullopt), - folly::StringPiece("RemoteIntf"), - folly::MacAddress("c6:ca:2b:2a:b1:b6"), - 9000, - false, - false, - cfg::InterfaceType::SYSTEM_PORT); - newRemoteInterface->setAddresses(subnets); + auto newRemoteInterface = makeRemoteInterface(intfId, subnets); newRemoteInterfaces->addNode( newRemoteInterface, scopeResolver.scope(newRemoteInterface, newState)); return newState; @@ -182,16 +235,20 @@ std::shared_ptr addRemoveRemoteNeighbor( return outState; } -std::shared_ptr setupRemoteIntfAndSysPorts( - std::shared_ptr currState, - const SwitchIdScopeResolver& scopeResolver, +void populateRemoteIntfAndSysPorts( + std::map>& switchId2SystemPorts, + std::map>& switchId2Rifs, const cfg::SwitchConfig& config, bool useEncapIndex) { - auto newState = currState->clone(); for (const auto& [remoteSwitchId, dsfNode] : *config.dsfNodes()) { - if (remoteSwitchId == 0) { + if ((*config.switchSettings()) + .switchIdToSwitchInfo() + ->contains(remoteSwitchId)) { continue; } + std::shared_ptr remoteSysPorts = + std::make_shared(); + std::shared_ptr remoteRifs = std::make_shared(); CHECK(dsfNode.systemPortRange().has_value()); const auto minPortID = *dsfNode.systemPortRange()->minimum(); const auto maxPortID = *dsfNode.systemPortRange()->maximum(); @@ -210,16 +267,15 @@ std::shared_ptr setupRemoteIntfAndSysPorts( auto thirdOctet = i - minPortID; folly::IPAddressV6 neighborIp(folly::to( firstOctet, ":", secondOctet, ":", thirdOctet, "::2")); - newState = addRemoteSysPort( - newState, - scopeResolver, + auto remoteSysPort = makeRemoteSysPort( remoteSysPortId, SwitchID(remoteSwitchId), (i - minPortID - kRemoteSysPortOffset) / kNumPortPerCore, - (i - minPortID) % kNumPortPerCore); - newState = addRemoteInterface( - newState, - scopeResolver, + (i - minPortID) % kNumPortPerCore, + static_cast(cfg::PortSpeed::FOURHUNDREDG)); + remoteSysPorts->addSystemPort(remoteSysPort); + + auto remoteRif = makeRemoteInterface( remoteIntfId, { {folly::IPAddress(folly::to( @@ -229,17 +285,14 @@ std::shared_ptr setupRemoteIntfAndSysPorts( firstOctet, ".", secondOctet, ".", thirdOctet, ".1")), 24}, }); - newState = addRemoveRemoteNeighbor( - newState, - scopeResolver, - neighborIp, - remoteIntfId, - portDesc, - true /* add */, - encapEndx); + + updateRemoteIntfWithNeighbor( + remoteRif, remoteIntfId, portDesc, neighborIp, encapEndx); + remoteRifs->addNode(remoteRif); } + switchId2SystemPorts[SwitchID(remoteSwitchId)] = remoteSysPorts; + switchId2Rifs[SwitchID(remoteSwitchId)] = remoteRifs; } - return newState; } QueueConfig getDefaultVoqConfig() { diff --git a/fboss/agent/test/utils/VoqTestUtils.h b/fboss/agent/test/utils/VoqTestUtils.h index f4f334cedee28..7c31baf6e5fd2 100644 --- a/fboss/agent/test/utils/VoqTestUtils.h +++ b/fboss/agent/test/utils/VoqTestUtils.h @@ -54,12 +54,6 @@ std::shared_ptr addRemoveRemoteNeighbor( bool add, std::optional encapIndex = std::nullopt); -std::shared_ptr setupRemoteIntfAndSysPorts( - std::shared_ptr currState, - const SwitchIdScopeResolver& scopeResolver, - const cfg::SwitchConfig& config, - bool useEncapIndex); - QueueConfig getDefaultVoqConfig(); std::optional getDummyEncapIndex(TestEnsembleIf* ensemble); @@ -68,5 +62,11 @@ boost::container::flat_set resolveRemoteNhops( TestEnsembleIf* ensemble, utility::EcmpSetupTargetedPorts6& ecmpHelper); +void populateRemoteIntfAndSysPorts( + std::map>& switchId2SystemPorts, + std::map>& switchId2Rifs, + const cfg::SwitchConfig& config, + bool useEncapIndex); + } // namespace utility } // namespace facebook::fboss diff --git a/fboss/agent/thrift_packet_stream/BUCK b/fboss/agent/thrift_packet_stream/BUCK index f20e56de0756b..a492b356bd2f7 100644 --- a/fboss/agent/thrift_packet_stream/BUCK +++ b/fboss/agent/thrift_packet_stream/BUCK @@ -14,7 +14,7 @@ cpp_library( "//fboss/agent/if:packet_stream-cpp2-clients", "//folly:cancellation_token", "//folly:synchronized", - "//folly/experimental/coro:blocking_wait", + "//folly/coro:blocking_wait", "//folly/io/async:async_socket", "//folly/io/async:scoped_event_base_thread", "//folly/logging:logging", diff --git a/fboss/agent/thrift_packet_stream/PacketStreamClient.h b/fboss/agent/thrift_packet_stream/PacketStreamClient.h index 6376d51573c1c..a5efdb37fc63d 100644 --- a/fboss/agent/thrift_packet_stream/PacketStreamClient.h +++ b/fboss/agent/thrift_packet_stream/PacketStreamClient.h @@ -4,7 +4,7 @@ #include #if FOLLY_HAS_COROUTINES -#include +#include #endif #include #include diff --git a/fboss/cli/fboss2/BUCK b/fboss/cli/fboss2/BUCK index 9a3dfd7e37397..97c5c54b51bfe 100644 --- a/fboss/cli/fboss2/BUCK +++ b/fboss/cli/fboss2/BUCK @@ -271,6 +271,7 @@ cpp_library( "commands/show/facebook/bgp/ribpolicy/CmdShowBgpRibPolicyUtils.cpp", "commands/show/facebook/config/CmdShowConfigUtils.cpp", "commands/show/facebook/environment/env_keys.cpp", + "commands/show/facebook/environment/sensor/CmdShowEnvironmentSensor.cpp", "commands/show/facebook/fsdb/CmdShowFsdbUtils.cpp", "commands/show/route/utils.cpp", "facebook/CmdHandlerImpl.cpp", @@ -489,6 +490,7 @@ cpp_library( "//employee/if:thrift-cpp2-types", "//fastcli:utils-cpp", "//fboss/agent:address_utils", + "//fboss/agent/hw:hardware_stats-cpp2-types", "//fboss/agent/if:common-cpp2-types", "//fboss/agent/if:ctrl-cpp2-clients", "//fboss/agent/if:ctrl-cpp2-services", @@ -635,10 +637,10 @@ cpp_library( "//folly:stop_watch", "//folly:string", "//folly/container:access", + "//folly/coro:async_pipe", + "//folly/coro:blocking_wait", + "//folly/coro:task", "//folly/executors:io_thread_pool_executor", - "//folly/experimental/coro:async_pipe", - "//folly/experimental/coro:blocking_wait", - "//folly/experimental/coro:task", "//folly/gen:base", "//folly/json:dynamic", "//folly/logging:logging", diff --git a/fboss/cli/fboss2/commands/show/interface/counters/CmdShowInterfaceCounters.h b/fboss/cli/fboss2/commands/show/interface/counters/CmdShowInterfaceCounters.h index 119440c81a59d..9b2602e2f4e80 100644 --- a/fboss/cli/fboss2/commands/show/interface/counters/CmdShowInterfaceCounters.h +++ b/fboss/cli/fboss2/commands/show/interface/counters/CmdShowInterfaceCounters.h @@ -10,6 +10,7 @@ #pragma once +#include "fboss/agent/hw/gen-cpp2/hardware_stats_constants.h" #include "fboss/cli/fboss2/CmdHandler.h" #include "fboss/cli/fboss2/commands/show/interface/CmdShowInterface.h" #include "fboss/cli/fboss2/commands/show/interface/counters/gen-cpp2/model_types.h" @@ -105,17 +106,23 @@ class CmdShowInterfaceCounters : public CmdHandler< "Multicast Pkts(out)", "Broadcast Pkts(out)"}); + auto makeStr = [](auto counterVal) -> std::string { + const std::string kNA = "n/a"; + return counterVal == hardware_stats_constants::STAT_UNINITIALIZED() + ? kNA + : std::to_string(counterVal); + }; for (const auto& counter : model.get_int_counters()) { table.addRow({ counter.get_interfaceName(), - std::to_string(counter.get_inputBytes()), - std::to_string(counter.get_inputUcastPkts()), - std::to_string(counter.get_inputMulticastPkts()), - std::to_string(counter.get_inputBroadcastPkts()), - std::to_string(counter.get_outputBytes()), - std::to_string(counter.get_outputUcastPkts()), - std::to_string(counter.get_outputMulticastPkts()), - std::to_string(counter.get_outputBroadcastPkts()), + makeStr(counter.get_inputBytes()), + makeStr(counter.get_inputUcastPkts()), + makeStr(counter.get_inputMulticastPkts()), + makeStr(counter.get_inputBroadcastPkts()), + makeStr(counter.get_outputBytes()), + makeStr(counter.get_outputUcastPkts()), + makeStr(counter.get_outputMulticastPkts()), + makeStr(counter.get_outputBroadcastPkts()), }); } diff --git a/fboss/cli/fboss2/commands/show/lldp/CmdShowLldp.h b/fboss/cli/fboss2/commands/show/lldp/CmdShowLldp.h index ca623b822fcc4..fe6b1207a8573 100644 --- a/fboss/cli/fboss2/commands/show/lldp/CmdShowLldp.h +++ b/fboss/cli/fboss2/commands/show/lldp/CmdShowLldp.h @@ -194,6 +194,26 @@ class CmdShowLldp : public CmdHandler { if (RE2::FullMatch(portDescription, fsw_regex)) { return results[0] + "." + results[1]; } + const RE2 ctsw_regex("^ctsw.*"); + if (RE2::FullMatch(portDescription, ctsw_regex)) { + return results[0] + "." + results[1]; + } + const RE2 rsw_regex("^rsw.*"); + if (RE2::FullMatch(portDescription, rsw_regex)) { + return results[0] + "." + results[1]; + } + const RE2 rusw_regex("^rusw.*"); + if (RE2::FullMatch(portDescription, rusw_regex)) { + return results[0] + "." + results[1]; + } + const RE2 rtsw_regex("^rtsw.*"); + if (RE2::FullMatch(portDescription, rtsw_regex)) { + return results[0] + "." + results[1]; + } + const RE2 resw_regex("^resw.*"); + if (RE2::FullMatch(portDescription, resw_regex)) { + return results[0] + "." + results[1]; + } // default to empty string, entire port descriptions is in a separate column return ""; @@ -214,8 +234,9 @@ class CmdShowLldp : public CmdHandler { const auto portInfo = getPortInfo(entry.get_localPort(), portEntries); if (queriedIfs.size() == 0 || queriedSet.count(portInfo.get_name())) { const auto operState = portInfo.get_operState(); - const auto expected_peer = - extractExpectedPort(portInfo.get_description()); + const auto expected_peer = portInfo.expectedLLDPeerName().has_value() + ? portInfo.expectedLLDPeerName().value() + : extractExpectedPort(portInfo.get_description()); if (auto localPortName = entry.get_localPortName()) { lldpDetails.localPort() = *localPortName; } diff --git a/fboss/cli/fboss2/commands/show/route/CmdShowRouteDetails.h b/fboss/cli/fboss2/commands/show/route/CmdShowRouteDetails.h index be3f1c3ab595c..eb3eca440cd51 100644 --- a/fboss/cli/fboss2/commands/show/route/CmdShowRouteDetails.h +++ b/fboss/cli/fboss2/commands/show/route/CmdShowRouteDetails.h @@ -15,6 +15,7 @@ #include #include #include "fboss/agent/if/gen-cpp2/common_types.h" +#include "fboss/agent/if/gen-cpp2/ctrl_types.h" #include "fboss/cli/fboss2/CmdHandler.h" #include "fboss/cli/fboss2/commands/show/route/CmdShowRoute.h" #include "fboss/cli/fboss2/commands/show/route/gen-cpp2/model_types.h" @@ -79,8 +80,9 @@ class CmdShowRouteDetails entry.get_isConnected() ? " (connected)" : ""); for (const auto& clAndNxthops : entry.get_nextHopMulti()) { - out << fmt::format( - " Nexthops from client {}\n", clAndNxthops.get_clientId()); + auto clientId = static_cast(*clAndNxthops.clientId()); + auto clientName = apache::thrift::util::enumNameSafe(clientId); + out << fmt::format(" Nexthops from client {}\n", clientName); for (const auto& nextHop : clAndNxthops.get_nextHops()) { out << fmt::format( " {}\n", show::route::utils::getNextHopInfoStr(nextHop)); diff --git a/fboss/cli/fboss2/commands/show/transceiver/CmdShowTransceiver.h b/fboss/cli/fboss2/commands/show/transceiver/CmdShowTransceiver.h index 83bf57e3df320..03b8e40e1278c 100644 --- a/fboss/cli/fboss2/commands/show/transceiver/CmdShowTransceiver.h +++ b/fboss/cli/fboss2/commands/show/transceiver/CmdShowTransceiver.h @@ -321,7 +321,8 @@ class CmdShowTransceiver details.rxPower() = rxPower; details.rxSnr() = rxSnr; } - model.transceivers()->emplace(transceiverId, std::move(details)); + model.transceivers()->emplace( + portEntries[portId].get_name(), std::move(details)); } return model; diff --git a/fboss/cli/fboss2/commands/show/transceiver/model.thrift b/fboss/cli/fboss2/commands/show/transceiver/model.thrift index f1c00f54bf043..9f4acd3be814e 100644 --- a/fboss/cli/fboss2/commands/show/transceiver/model.thrift +++ b/fboss/cli/fboss2/commands/show/transceiver/model.thrift @@ -3,8 +3,8 @@ namespace cpp2 facebook.fboss.cli include "fboss/qsfp_service/if/transceiver.thrift" struct ShowTransceiverModel { - /* key: transceiverId, value: TransceiverDetail */ - 1: map transceivers; + /* key: portName, value: TransceiverDetail */ + 1: map transceivers; } struct TransceiverDetail { diff --git a/fboss/cli/fboss2/test/CmdShowRouteDetailsTest.cpp b/fboss/cli/fboss2/test/CmdShowRouteDetailsTest.cpp index 9e164623c7c37..a655bd6586dff 100644 --- a/fboss/cli/fboss2/test/CmdShowRouteDetailsTest.cpp +++ b/fboss/cli/fboss2/test/CmdShowRouteDetailsTest.cpp @@ -237,7 +237,7 @@ TEST_F(CmdShowRouteDetailsTestFixture, printOutput) { std::string output = ss.str(); std::string expectOutput = R"( Network Address: 2401:db00::/32 - Nexthops from client 0 + Nexthops from client BGPD 2401:db00:e32f:8fc::2 weight 1 MPLS -> SWAP : 1 Action: Nexthops Forwarding via: @@ -247,7 +247,7 @@ Network Address: 2401:db00::/32 Class Id: DST_CLASS_L3_DPR(20) Network Address: 176.161.6.0/32 (connected) - Nexthops from client 1 + Nexthops from client STATIC_ROUTE 240.161.6.0 Action: Nexthops Forwarding via: diff --git a/fboss/cli/fboss2/test/CmdShowTransceiverTest.cpp b/fboss/cli/fboss2/test/CmdShowTransceiverTest.cpp index 579e544658d19..5ff7575973fc2 100644 --- a/fboss/cli/fboss2/test/CmdShowTransceiverTest.cpp +++ b/fboss/cli/fboss2/test/CmdShowTransceiverTest.cpp @@ -219,12 +219,12 @@ cli::ShowTransceiverModel createTransceiverModel() { setValidationStatus(entry6, "Validated", "--"); setOperAttributes(entry6, 30.0, 30.0); - model.transceivers()->emplace(1, std::move(entry1)); - model.transceivers()->emplace(2, std::move(entry2)); - model.transceivers()->emplace(3, std::move(entry3)); - model.transceivers()->emplace(4, std::move(entry4)); - model.transceivers()->emplace(5, std::move(entry5)); - model.transceivers()->emplace(6, std::move(entry6)); + model.transceivers()->emplace("eth1/1/1", std::move(entry1)); + model.transceivers()->emplace("eth1/2/1", std::move(entry2)); + model.transceivers()->emplace("eth1/3/1", std::move(entry3)); + model.transceivers()->emplace("eth1/4/1", std::move(entry4)); + model.transceivers()->emplace("eth1/5/1", std::move(entry5)); + model.transceivers()->emplace("eth1/6/1", std::move(entry6)); return model; } diff --git a/fboss/cli/fboss2/utils/Table.h b/fboss/cli/fboss2/utils/Table.h index 555dbd845040f..2b00a21777e6f 100644 --- a/fboss/cli/fboss2/utils/Table.h +++ b/fboss/cli/fboss2/utils/Table.h @@ -51,6 +51,13 @@ class Table { StyledCell& operator=(StyledCell& other) = default; + static StyledCell errorIfPos(int val) { + if (val > 1) { + return StyledCell{std::to_string(val), ERROR}; + } + return StyledCell{std::to_string(val)}; + } + std::string getData() const { return data_; } diff --git a/fboss/fsdb/client/BUCK b/fboss/fsdb/client/BUCK index 283937518c742..4680ece5289ec 100644 --- a/fboss/fsdb/client/BUCK +++ b/fboss/fsdb/client/BUCK @@ -16,7 +16,7 @@ cpp_library( "//fboss/fsdb/if:fsdb_oper-cpp2-types", "//fboss/lib:common_thrift_utils", "//folly:network_address", - "//folly/experimental/coro:async_scope", + "//folly/coro:async_scope", "//folly/io/async:async_socket_transport", "//folly/io/async:scoped_event_base_thread", "//folly/logging:logging", @@ -57,12 +57,13 @@ cpp_library( "//fboss/fsdb/if:fsdb-cpp2-services", "//fboss/fsdb/if:fsdb_common-cpp2-types", "//fboss/fsdb/if:fsdb_oper-cpp2-types", + "//fboss/util:logging", "//folly:format", "//folly:string", "//folly:synchronized", "//folly/concurrency:dynamic_bounded_queue", - "//folly/experimental/coro:async_generator", - "//folly/experimental/coro:async_pipe", + "//folly/coro:async_generator", + "//folly/coro:async_pipe", "//folly/io/async:scoped_event_base_thread", "//folly/logging:logging", ], diff --git a/fboss/fsdb/client/FsdbPublisher.h b/fboss/fsdb/client/FsdbPublisher.h index 030424342ef3d..c43971c10c57e 100644 --- a/fboss/fsdb/client/FsdbPublisher.h +++ b/fboss/fsdb/client/FsdbPublisher.h @@ -5,8 +5,8 @@ #include #include #include -#include -#include +#include +#include #include "fboss/fsdb/client/FsdbStreamClient.h" #include "fboss/fsdb/if/gen-cpp2/fsdb_oper_types.h" diff --git a/fboss/fsdb/client/FsdbStreamClient.h b/fboss/fsdb/client/FsdbStreamClient.h index d484ef96f410f..648637350e5d0 100644 --- a/fboss/fsdb/client/FsdbStreamClient.h +++ b/fboss/fsdb/client/FsdbStreamClient.h @@ -4,7 +4,7 @@ #include #include -#include +#include #include #include #include diff --git a/fboss/fsdb/client/FsdbSubManager.h b/fboss/fsdb/client/FsdbSubManager.h index e7af1c36366d1..dc5c98da4e02f 100644 --- a/fboss/fsdb/client/FsdbSubManager.h +++ b/fboss/fsdb/client/FsdbSubManager.h @@ -50,7 +50,7 @@ class FsdbSubManager { struct SubUpdate { // Data will always received the FSDB root in the form of raw thrift or // thrift_cow object, depending on type of subscriber - Data data; + const Data data; // SubscriptionKeys that changed, can be compared against keys returned from // addPath std::vector updatedKeys; @@ -174,6 +174,7 @@ class FsdbSubManager { // TODO: support patching a raw thrift object root_.patch(std::move(patch)); } + root_.publish(); SubUpdate update{ root_.root(), std::move(changedKeys), std::move(changedPaths)}; cb(std::move(update)); diff --git a/fboss/fsdb/client/FsdbSubscriber.h b/fboss/fsdb/client/FsdbSubscriber.h index 0398593697d2c..4a5e6e085afbe 100644 --- a/fboss/fsdb/client/FsdbSubscriber.h +++ b/fboss/fsdb/client/FsdbSubscriber.h @@ -6,10 +6,11 @@ #include "fboss/fsdb/common/PathHelpers.h" #include "fboss/fsdb/if/gen-cpp2/fsdb_common_types.h" #include "fboss/fsdb/if/gen-cpp2/fsdb_oper_types.h" +#include "fboss/util/Logging.h" #include #include -#include +#include #include diff --git a/fboss/fsdb/client/test/BUCK b/fboss/fsdb/client/test/BUCK index 6faf7efab50b1..ebb2f37ee062b 100644 --- a/fboss/fsdb/client/test/BUCK +++ b/fboss/fsdb/client/test/BUCK @@ -15,8 +15,8 @@ cpp_unittest( "//fboss/fsdb/client:fsdb_stream_client", "//fboss/fsdb/common:flags", "//fboss/lib:common_utils", - "//folly/experimental/coro:async_generator", - "//folly/experimental/coro:async_pipe", + "//folly/coro:async_generator", + "//folly/coro:async_pipe", "//folly/io/async:scoped_event_base_thread", "//folly/logging:logging", ], diff --git a/fboss/fsdb/client/test/FsdbPubSubManagerTest.cpp b/fboss/fsdb/client/test/FsdbPubSubManagerTest.cpp index 9b69f6f5c65e8..ec5b2d925d145 100644 --- a/fboss/fsdb/client/test/FsdbPubSubManagerTest.cpp +++ b/fboss/fsdb/client/test/FsdbPubSubManagerTest.cpp @@ -9,8 +9,8 @@ #include "fboss/fsdb/common/Flags.h" #include "fboss/lib/CommonUtils.h" -#include -#include +#include +#include #include #include diff --git a/fboss/fsdb/client/test/FsdbPublisherTest.cpp b/fboss/fsdb/client/test/FsdbPublisherTest.cpp index 7ff3be0d120d6..715fc65321cca 100644 --- a/fboss/fsdb/client/test/FsdbPublisherTest.cpp +++ b/fboss/fsdb/client/test/FsdbPublisherTest.cpp @@ -4,8 +4,8 @@ #include "fboss/fsdb/common/Flags.h" #include "fboss/lib/CommonUtils.h" -#include -#include +#include +#include #include #include #include diff --git a/fboss/fsdb/client/test/FsdbStreamClientTest.cpp b/fboss/fsdb/client/test/FsdbStreamClientTest.cpp index 6ae711852d722..65539e2fb3a44 100644 --- a/fboss/fsdb/client/test/FsdbStreamClientTest.cpp +++ b/fboss/fsdb/client/test/FsdbStreamClientTest.cpp @@ -7,8 +7,8 @@ #include "fboss/lib/CommonUtils.h" #include -#include -#include +#include +#include #include #include #include diff --git a/fboss/fsdb/if/oss/fsdb_model_thriftpath.h b/fboss/fsdb/if/oss/fsdb_model_thriftpath.h index ec262a06c278a..e257a884a9977 100755 --- a/fboss/fsdb/if/oss/fsdb_model_thriftpath.h +++ b/fboss/fsdb/if/oss/fsdb_model_thriftpath.h @@ -17113,7 +17113,7 @@ std::pair>, std::pair>, std::pair>, -std::pair>>; +std::pair>>; using ChildrenById = fatal::tuple< std::pair, Child<::facebook::fboss::cfg::L2LearningMode, ::apache::thrift::type_class::enumeration, ::apache::thrift::type::enum_t<::facebook::fboss::cfg::L2LearningMode>>>, std::pair, Child>, std::pair, Child>, @@ -17198,7 +17198,7 @@ std::pair>, std::pair>, std::pair>, -std::pair>>::template type_of; +std::pair>>::template type_of; template using TypeFor = typename Children::template type_of; @@ -17245,7 +17245,7 @@ std::pair auto operator()(const std::integral_constant&) { @@ -17290,7 +17290,7 @@ std::pair diff --git a/fboss/fsdb/oper/BUCK b/fboss/fsdb/oper/BUCK index 15abb26687a00..a2397166ff518 100644 --- a/fboss/fsdb/oper/BUCK +++ b/fboss/fsdb/oper/BUCK @@ -49,10 +49,10 @@ cpp_library( "//folly:string", "//folly:traits", "//folly/container:f14_hash", - "//folly/experimental/coro:async_pipe", - "//folly/experimental/coro:async_scope", - "//folly/experimental/coro:blocking_wait", - "//folly/experimental/coro:sleep", + "//folly/coro:async_pipe", + "//folly/coro:async_scope", + "//folly/coro:blocking_wait", + "//folly/coro:sleep", "//folly/io/async:async_base", "//folly/json:dynamic", "//folly/logging:logging", @@ -89,10 +89,10 @@ cpp_library( "//fboss/thrift_cow/storage:storage", "//folly:expected", "//folly:synchronized", - "//folly/experimental/coro:async_generator", - "//folly/experimental/coro:async_scope", - "//folly/experimental/coro:blocking_wait", - "//folly/experimental/coro:sleep", + "//folly/coro:async_generator", + "//folly/coro:async_scope", + "//folly/coro:blocking_wait", + "//folly/coro:sleep", "//folly/io/async:async_base", "//folly/io/async:scoped_event_base_thread", "//folly/json:dynamic", @@ -147,8 +147,8 @@ cpp_binary( "//fboss/thrift_cow/nodes:serializer", "//folly:file_util", "//folly:string", - "//folly/experimental/coro:blocking_wait", - "//folly/experimental/coro:task", + "//folly/coro:blocking_wait", + "//folly/coro:task", "//folly/init:init", "//servicerouter/client/cpp2:cpp2", ], diff --git a/fboss/fsdb/oper/CowSubscriptionManager.h b/fboss/fsdb/oper/CowSubscriptionManager.h index 0f103649525b7..4a5fe45ca8e69 100644 --- a/fboss/fsdb/oper/CowSubscriptionManager.h +++ b/fboss/fsdb/oper/CowSubscriptionManager.h @@ -164,6 +164,10 @@ class CowSubscriptionManager SubscriptionStore& store, const std::shared_ptr& newRoot, const SubscriptionMetadataServer& metadataServer) { + if (!store.initialSyncNeeded().numSubsRecursive()) { + return; + } + auto processPath = [&](CowInitialSyncTraverseHelper& traverser, const auto& node) { SubscriptionPathStore* lookup = traverser.currentStore(); diff --git a/fboss/fsdb/oper/NaivePeriodicSubscribableStorage.h b/fboss/fsdb/oper/NaivePeriodicSubscribableStorage.h index b095b01e6ec18..51dc39c574bc6 100644 --- a/fboss/fsdb/oper/NaivePeriodicSubscribableStorage.h +++ b/fboss/fsdb/oper/NaivePeriodicSubscribableStorage.h @@ -11,7 +11,7 @@ #include #include -#include +#include #include #include #include diff --git a/fboss/fsdb/oper/NaivePeriodicSubscribableStorageBase.cpp b/fboss/fsdb/oper/NaivePeriodicSubscribableStorageBase.cpp index 0101545ff2e68..f2ddbae3b33cf 100644 --- a/fboss/fsdb/oper/NaivePeriodicSubscribableStorageBase.cpp +++ b/fboss/fsdb/oper/NaivePeriodicSubscribableStorageBase.cpp @@ -3,7 +3,7 @@ #include "fboss/fsdb/oper/NaivePeriodicSubscribableStorageBase.h" #include -#include +#include #include #ifndef IS_OSS diff --git a/fboss/fsdb/oper/NaivePeriodicSubscribableStorageBase.h b/fboss/fsdb/oper/NaivePeriodicSubscribableStorageBase.h index 22adb376806a7..dc68b8a52649c 100644 --- a/fboss/fsdb/oper/NaivePeriodicSubscribableStorageBase.h +++ b/fboss/fsdb/oper/NaivePeriodicSubscribableStorageBase.h @@ -10,7 +10,7 @@ #include "fboss/thrift_cow/gen-cpp2/patch_types.h" #include -#include +#include #include #include diff --git a/fboss/fsdb/oper/SubscribableStorage.h b/fboss/fsdb/oper/SubscribableStorage.h index dbe5f83b22ea9..88b3241f73fee 100644 --- a/fboss/fsdb/oper/SubscribableStorage.h +++ b/fboss/fsdb/oper/SubscribableStorage.h @@ -7,8 +7,8 @@ #include #include #include -#include -#include +#include +#include #include #include #include diff --git a/fboss/fsdb/oper/Subscription.cpp b/fboss/fsdb/oper/Subscription.cpp index aca239e128ba4..cbd307cad73f6 100644 --- a/fboss/fsdb/oper/Subscription.cpp +++ b/fboss/fsdb/oper/Subscription.cpp @@ -3,8 +3,8 @@ #include "fboss/fsdb/oper/Subscription.h" #include -#include -#include +#include +#include #include namespace facebook::fboss::fsdb { diff --git a/fboss/fsdb/oper/Subscription.h b/fboss/fsdb/oper/Subscription.h index f99c7a4d6fc08..9f4e14092b200 100644 --- a/fboss/fsdb/oper/Subscription.h +++ b/fboss/fsdb/oper/Subscription.h @@ -11,8 +11,8 @@ #include "fboss/thrift_cow/gen-cpp2/patch_types.h" #include -#include -#include +#include +#include #include #include diff --git a/fboss/fsdb/oper/test_client.cpp b/fboss/fsdb/oper/test_client.cpp index 8c33df98b93bf..bd7f48d70bd2d 100644 --- a/fboss/fsdb/oper/test_client.cpp +++ b/fboss/fsdb/oper/test_client.cpp @@ -4,8 +4,8 @@ #include #include -#include -#include +#include +#include #include #include "fboss/fsdb/if/FsdbModel.h" #include "fboss/fsdb/if/gen-cpp2/FsdbService.h" diff --git a/fboss/fsdb/oper/tests/BUCK b/fboss/fsdb/oper/tests/BUCK index 43e0df21e1960..5a70870b4f5f1 100644 --- a/fboss/fsdb/oper/tests/BUCK +++ b/fboss/fsdb/oper/tests/BUCK @@ -10,8 +10,8 @@ cpp_unittest( ], deps = [ "//fboss/fsdb/oper:subscription_manager", - "//folly/experimental/coro:blocking_wait", - "//folly/experimental/coro:timeout", + "//folly/coro:blocking_wait", + "//folly/coro:timeout", "//folly/io/async:scoped_event_base_thread", ], ) @@ -33,12 +33,12 @@ cpp_unittest( "//fboss/lib:common_utils", "//fboss/thrift_cow/visitors:visitors", "//folly:random", - "//folly/experimental/coro:async_generator", - "//folly/experimental/coro:blocking_wait", - "//folly/experimental/coro:collect", - "//folly/experimental/coro:gtest_helpers", - "//folly/experimental/coro:task", - "//folly/experimental/coro:timeout", + "//folly/coro:async_generator", + "//folly/coro:blocking_wait", + "//folly/coro:collect", + "//folly/coro:gtest_helpers", + "//folly/coro:task", + "//folly/coro:timeout", "//folly/json:dynamic", "//thrift/lib/cpp2/folly_dynamic:folly_dynamic", ], diff --git a/fboss/fsdb/oper/tests/SubscribableStorageTests.cpp b/fboss/fsdb/oper/tests/SubscribableStorageTests.cpp index 3015ecd63f2cc..bcff36f21bd5d 100644 --- a/fboss/fsdb/oper/tests/SubscribableStorageTests.cpp +++ b/fboss/fsdb/oper/tests/SubscribableStorageTests.cpp @@ -10,12 +10,12 @@ #include #include #include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include #include "fboss/fsdb/oper/ExtendedPathBuilder.h" #include "fboss/fsdb/tests/gen-cpp2-thriftpath/thriftpath_test.h" // @manual=//fboss/fsdb/tests:thriftpath_test_thrift-cpp2-thriftpath diff --git a/fboss/fsdb/oper/tests/SubscriptionTests.cpp b/fboss/fsdb/oper/tests/SubscriptionTests.cpp index 3ccd981f1eca7..aea19007caff8 100644 --- a/fboss/fsdb/oper/tests/SubscriptionTests.cpp +++ b/fboss/fsdb/oper/tests/SubscriptionTests.cpp @@ -2,8 +2,8 @@ #include -#include -#include +#include +#include #include #include diff --git a/fboss/fsdb/server/BUCK b/fboss/fsdb/server/BUCK index 64e218c24bc7f..e87c5894a80cf 100644 --- a/fboss/fsdb/server/BUCK +++ b/fboss/fsdb/server/BUCK @@ -46,8 +46,8 @@ cpp_library( "//folly:file_util", "//folly:synchronized", "//folly/container:f14_hash", - "//folly/experimental/coro:blocking_wait", - "//folly/experimental/coro:timeout", + "//folly/coro:blocking_wait", + "//folly/coro:timeout", "//folly/io/async:scoped_event_base_thread", "//folly/logging:logging", "//thrift/lib/cpp/server:server_event_handler", diff --git a/fboss/fsdb/server/ServiceHandler.cpp b/fboss/fsdb/server/ServiceHandler.cpp index b98f36d612d3d..27f178bb55d14 100644 --- a/fboss/fsdb/server/ServiceHandler.cpp +++ b/fboss/fsdb/server/ServiceHandler.cpp @@ -4,8 +4,8 @@ #include "fboss/fsdb/if/gen-cpp2/fsdb_common_types.h" #include -#include -#include +#include +#include #include #include "fboss/fsdb/if/gen-cpp2/fsdb_common_constants.h" #include "fboss/fsdb/oper/PathValidator.h" diff --git a/fboss/fsdb/tests/client/BUCK b/fboss/fsdb/tests/client/BUCK index 03b66e7a2cf88..9013583bec0c1 100644 --- a/fboss/fsdb/tests/client/BUCK +++ b/fboss/fsdb/tests/client/BUCK @@ -43,7 +43,7 @@ cpp_unittest( "//fboss/fsdb/oper:extended_path_builder", "//fboss/fsdb/tests/utils:fsdb_test_server", "//fboss/lib:common_utils", - "//folly/experimental/coro:blocking_wait", + "//folly/coro:blocking_wait", "//folly/io/async:scoped_event_base_thread", "//folly/logging:log_level", "//folly/logging:logging", diff --git a/fboss/fsdb/tests/client/FsdbPubSubTest.cpp b/fboss/fsdb/tests/client/FsdbPubSubTest.cpp index e6f6b0af1f22c..011b3fd05eefd 100644 --- a/fboss/fsdb/tests/client/FsdbPubSubTest.cpp +++ b/fboss/fsdb/tests/client/FsdbPubSubTest.cpp @@ -6,7 +6,7 @@ #include "fboss/fsdb/tests/utils/FsdbTestServer.h" #include "fboss/lib/CommonUtils.h" -#include +#include #include #include #include diff --git a/fboss/fsdb/tests/client/FsdbPublisherTest.cpp b/fboss/fsdb/tests/client/FsdbPublisherTest.cpp index ce1995ae1c247..39388542c0dcf 100644 --- a/fboss/fsdb/tests/client/FsdbPublisherTest.cpp +++ b/fboss/fsdb/tests/client/FsdbPublisherTest.cpp @@ -10,7 +10,7 @@ #include "fboss/lib/CommonUtils.h" #include -#include +#include #include #include diff --git a/fboss/lib/BUCK b/fboss/lib/BUCK index 04ec441734378..289caeea95c78 100644 --- a/fboss/lib/BUCK +++ b/fboss/lib/BUCK @@ -255,8 +255,8 @@ cpp_library( exported_deps = [ "//fb303:thread_cached_service_data", "//folly:network_address", - "//folly/experimental/coro:async_scope", - "//folly/experimental/coro:blocking_wait", + "//folly/coro:async_scope", + "//folly/coro:blocking_wait", "//folly/io/async:async_base", "//folly/logging:logging", ], diff --git a/fboss/lib/CommonThriftUtils.cpp b/fboss/lib/CommonThriftUtils.cpp index 78e4441551de5..0f568d3978250 100644 --- a/fboss/lib/CommonThriftUtils.cpp +++ b/fboss/lib/CommonThriftUtils.cpp @@ -9,7 +9,7 @@ */ #include "fboss/lib/CommonThriftUtils.h" -#include +#include #include #include #include diff --git a/fboss/lib/CommonThriftUtils.h b/fboss/lib/CommonThriftUtils.h index 42f3c58156cd1..fb50a5abdfa1a 100644 --- a/fboss/lib/CommonThriftUtils.h +++ b/fboss/lib/CommonThriftUtils.h @@ -11,7 +11,7 @@ #include #include -#include +#include #include #include diff --git a/fboss/lib/platforms/FruIdFields.h b/fboss/lib/platforms/FruIdFields.h index b1c789f584d75..4cdb7f81cf494 100644 --- a/fboss/lib/platforms/FruIdFields.h +++ b/fboss/lib/platforms/FruIdFields.h @@ -8,27 +8,41 @@ namespace facebook::fboss { constexpr auto kInfo = "Information"; + +// Common Information keys constexpr auto kSysMfgDate = "System Manufacturing Date"; constexpr auto kSysMfg = "System Manufacturer"; constexpr auto kSysAmbPartNum = "System Assembly Part Number"; constexpr auto kAmbAt = "Assembled At"; constexpr auto kPcbMfg = "PCB Manufacturer"; -constexpr auto kProdAssetTag = "Product Asset Tag"; constexpr auto kProdName = "Product Name"; constexpr auto kProdVersion = "Product Version"; constexpr auto kProductionState = "Product Production State"; constexpr auto kProdPartNum = "Product Part Number"; constexpr auto kSerialNum = "Product Serial Number"; constexpr auto kSubVersion = "Product Sub-Version"; -constexpr auto kOdmPcbaPartNum = "ODM PCBA Part Number"; -constexpr auto kOdmPcbaSerialNum = "ODM PCBA Serial Number"; +constexpr auto kVersion = "Version"; + +// Information keys for BMC based platforms constexpr auto kFbPcbaPartNum = "Facebook PCBA Part Number"; constexpr auto kFbPcbPartNum = "Facebook PCB Part Number"; +constexpr auto kOdmPcbaPartNum = "ODM PCBA Part Number"; +constexpr auto kOdmPcbaSerialNum = "ODM PCBA Serial Number"; +constexpr auto kFabricLocation = "Location on Fabric"; +constexpr auto kLocalMac = "Local MAC"; constexpr auto kExtMacSize = "Extended MAC Address Size"; constexpr auto kExtMacBase = "Extended MAC Base"; -constexpr auto kLocalMac = "Local MAC"; -constexpr auto kVersion = "Version"; -constexpr auto kFabricLocation = "Location on Fabric"; +constexpr auto kProdAssetTag = "Product Asset Tag"; + +// Information keys for BMC-Lite platforms +constexpr auto kFbPcbaPartNumBmcLite = "Meta PCBA Part Number"; +constexpr auto kFbPcbPartNumBmcLite = "Meta PCB Part Number"; +constexpr auto kOdmPcbaPartNumBmcLite = "ODM/JDM PCBA Part Number"; +constexpr auto kOdmPcbaSerialNumBmcLite = "ODM/JDM PCBA Serial Number"; +constexpr auto kFabricLocationBmcLite = "EEPROM location on Fabric"; +constexpr auto kLocalMacBmcLite = "BMC MAC Base"; +constexpr auto kExtMacSizeBmcLite = "Switch ASIC MAC Address Size"; +constexpr auto kExtMacBaseBmcLite = "Switch ASIC MAC Base"; // Dummy Fruid for fake platform inline const std::string& getFakeFruIdJson() { diff --git a/fboss/lib/platforms/PlatformProductInfo.cpp b/fboss/lib/platforms/PlatformProductInfo.cpp index 2c979678cf23e..807cb20e71ac1 100644 --- a/fboss/lib/platforms/PlatformProductInfo.cpp +++ b/fboss/lib/platforms/PlatformProductInfo.cpp @@ -217,6 +217,18 @@ void PlatformProductInfo::initMode() { } } +std::string PlatformProductInfo::getField( + const folly::dynamic& info, + const std::vector& keys) { + for (const auto& key : keys) { + if (info.count(key)) { + return folly::to(info[key].asString()); + } + } + // If field does not exist in fruid.json, return empty string + return ""; +} + void PlatformProductInfo::parse(std::string data) { dynamic info; try { @@ -233,43 +245,60 @@ void PlatformProductInfo::parse(std::string data) { // } info = parseJson(data); } - productInfo_.oem() = folly::to(info[kSysMfg].asString()); - productInfo_.product() = folly::to(info[kProdName].asString()); - productInfo_.serial() = folly::to(info[kSerialNum].asString()); - productInfo_.mfgDate() = folly::to(info[kSysMfgDate].asString()); - productInfo_.systemPartNumber() = - folly::to(info[kSysAmbPartNum].asString()); - productInfo_.assembledAt() = folly::to(info[kAmbAt].asString()); - productInfo_.pcbManufacturer() = - folly::to(info[kPcbMfg].asString()); - productInfo_.assetTag() = - folly::to(info[kProdAssetTag].asString()); - productInfo_.partNumber() = - folly::to(info[kProdPartNum].asString()); - productInfo_.odmPcbaPartNumber() = - folly::to(info[kOdmPcbaPartNum].asString()); - productInfo_.odmPcbaSerial() = - folly::to(info[kOdmPcbaSerialNum].asString()); - productInfo_.fbPcbaPartNumber() = - folly::to(info[kFbPcbaPartNum].asString()); - productInfo_.fbPcbPartNumber() = - folly::to(info[kFbPcbPartNum].asString()); - productInfo_.fabricLocation() = - folly::to(info[kFabricLocation].asString()); + productInfo_.product() = getField(info, {kProdName}); + // Product Name is a required field, throw if it is not present in fruid.json. + // It will be populated from fbwhoami if missing in fruid.json. + if (productInfo_.product()->empty()) { + throw FbossError("Product Name not found in fruid.json"); + } + productInfo_.oem() = getField(info, {kSysMfg}); + productInfo_.serial() = getField(info, {kSerialNum}); + productInfo_.mfgDate() = getField(info, {kSysMfgDate}); + productInfo_.systemPartNumber() = getField(info, {kSysAmbPartNum}); + productInfo_.assembledAt() = getField(info, {kAmbAt}); + productInfo_.pcbManufacturer() = getField(info, {kPcbMfg}); + productInfo_.partNumber() = getField(info, {kProdPartNum}); // FB only - we apply custom logic to construct unique SN for // cases where we create multiple assets for a single physical // card in chassis. setFBSerial(); - productInfo_.version() = info[kVersion].asInt(); + + // Optional field in Information + if (info.count(kVersion)) { + productInfo_.version() = info[kVersion].asInt(); + } productInfo_.subVersion() = info[kSubVersion].asInt(); productInfo_.productionState() = info[kProductionState].asInt(); productInfo_.productVersion() = info[kProdVersion].asInt(); - productInfo_.bmcMac() = folly::to(info[kLocalMac].asString()); - productInfo_.mgmtMac() = folly::to(info[kExtMacBase].asString()); - auto macBase = MacAddress(info[kExtMacBase].asString()).u64HBO() + 1; + + // There are different keys for these values in BMC + // and BMC-Lite platforms. + productInfo_.fbPcbaPartNumber() = + getField(info, {kFbPcbaPartNum, kFbPcbaPartNumBmcLite}); + productInfo_.fbPcbPartNumber() = + getField(info, {kFbPcbPartNum, kFbPcbPartNumBmcLite}); + productInfo_.odmPcbaPartNumber() = + getField(info, {kOdmPcbaPartNum, kOdmPcbaPartNumBmcLite}); + productInfo_.odmPcbaSerial() = + getField(info, {kOdmPcbaSerialNum, kOdmPcbaSerialNumBmcLite}); + productInfo_.fabricLocation() = + getField(info, {kFabricLocation, kFabricLocationBmcLite}); + productInfo_.bmcMac() = getField(info, {kLocalMac, kLocalMacBmcLite}); + productInfo_.mgmtMac() = getField(info, {kExtMacBase, kExtMacBaseBmcLite}); + auto macBase = MacAddress(productInfo_.mgmtMac().value()).u64HBO() + 1; productInfo_.macRangeStart() = MacAddress::fromHBO(macBase).toString(); - productInfo_.macRangeSize() = info[kExtMacSize].asInt() - 1; + if (info.count(kExtMacSize)) { + productInfo_.macRangeSize() = info[kExtMacSize].asInt() - 1; + } else if (info.count(kExtMacSizeBmcLite)) { + productInfo_.macRangeSize() = info[kExtMacSizeBmcLite].asInt() - 1; + } + + // Product Asset Tag is not present in BMC-Lite platforms. + if (info.count(kProdAssetTag)) { + productInfo_.assetTag() = getField(info, {kProdAssetTag}); + } + XLOG(INFO) << "Success parsing product info fields"; } std::unique_ptr fakeProductInfo() { diff --git a/fboss/lib/platforms/PlatformProductInfo.h b/fboss/lib/platforms/PlatformProductInfo.h index c227e244cf7ae..a8e3b7aa81c2c 100644 --- a/fboss/lib/platforms/PlatformProductInfo.h +++ b/fboss/lib/platforms/PlatformProductInfo.h @@ -10,6 +10,7 @@ #pragma once #include +#include #include "fboss/agent/if/gen-cpp2/product_info_types.h" #include "fboss/lib/if/gen-cpp2/fboss_common_types.h" @@ -41,6 +42,14 @@ class PlatformProductInfo { void initFromFbWhoAmI(); void initMode(); void parse(std::string data); + /* + * Check if certain key(s) exists and return its value. + * BMC and BMC-Lite platforms have different keys + * for some Information values. + */ + std::string getField( + const folly::dynamic& info, + const std::vector& keys); ProductInfo productInfo_; folly::StringPiece path_; diff --git a/fboss/oss/hw_bench_configs/meru400biu.agent.materialized_JSON b/fboss/oss/hw_bench_configs/meru400biu.agent.materialized_JSON index 0f7c63227a428..fe3ded6b18db0 100644 --- a/fboss/oss/hw_bench_configs/meru400biu.agent.materialized_JSON +++ b/fboss/oss/hw_bench_configs/meru400biu.agent.materialized_JSON @@ -130,7 +130,7 @@ }, "systemPortRange": { "minimum": 10, - "maximum": 30 + "maximum": 29 }, "switchMac": "02:00:00:00:00:01", "connectionHandle": "68:00" @@ -153,7 +153,7 @@ ], "systemPortRange": { "minimum": 10, - "maximum": 30 + "maximum": 29 }, "nodeMac": "02:00:00:00:0F:0B", "asicType": 11, diff --git a/fboss/oss/hw_bench_configs/meru800bia.agent.materialized_JSON b/fboss/oss/hw_bench_configs/meru800bia.agent.materialized_JSON index 2c69c1052ffd2..11394c0d98fb5 100644 --- a/fboss/oss/hw_bench_configs/meru800bia.agent.materialized_JSON +++ b/fboss/oss/hw_bench_configs/meru800bia.agent.materialized_JSON @@ -155,7 +155,7 @@ }, "systemPortRange": { "minimum": 10, - "maximum": 54 + "maximum": 53 }, "switchMac": "02:00:00:00:00:01", "connectionHandle": "15:00" @@ -178,7 +178,7 @@ ], "systemPortRange": { "minimum": 10, - "maximum": 54 + "maximum": 53 }, "nodeMac": "18*800G-8", "asicType": 14, diff --git a/fboss/oss/hw_known_bad_tests/sai_agent_known_bad_tests.materialized_JSON b/fboss/oss/hw_known_bad_tests/sai_agent_known_bad_tests.materialized_JSON index 84b46da07bd4b..8adb9313495cd 100644 --- a/fboss/oss/hw_known_bad_tests/sai_agent_known_bad_tests.materialized_JSON +++ b/fboss/oss/hw_known_bad_tests/sai_agent_known_bad_tests.materialized_JSON @@ -26,7 +26,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -43,9 +43,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -70,6 +67,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].UnresolvedRouteNextHopToLowPriQueue$" }, @@ -110,7 +119,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -127,9 +136,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -154,6 +160,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].VerifyCoppPpsLowPri$" }, @@ -295,7 +313,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -312,9 +330,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -339,6 +354,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.cold_boot.AgentPacketSendReceiveLagTest.LacpPacketReceiveSrcPort$" }, @@ -367,7 +394,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -384,9 +411,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -411,6 +435,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].VerifyCoppPpsLowPri$" }, @@ -573,7 +609,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -590,9 +626,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -617,6 +650,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].UnresolvedRouteNextHopToLowPriQueue$" }, @@ -657,7 +702,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -674,9 +719,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -701,6 +743,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].VerifyCoppPpsLowPri$" }, @@ -800,7 +854,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -817,9 +871,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -844,6 +895,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.cold_boot.AgentPacketSendReceiveLagTest.LacpPacketReceiveSrcPort$" }, @@ -872,7 +935,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -889,9 +952,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -916,6 +976,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].VerifyCoppPpsLowPri$" }, @@ -1063,7 +1135,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -1080,9 +1152,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -1107,6 +1176,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].UnresolvedRouteNextHopToLowPriQueue$" }, @@ -1147,7 +1228,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -1164,9 +1245,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -1191,6 +1269,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].VerifyCoppPpsLowPri$" }, @@ -1404,7 +1494,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -1421,9 +1511,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -1448,6 +1535,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.cold_boot.AgentPacketSendReceiveLagTest.LacpPacketReceiveSrcPort$" }, @@ -1476,7 +1575,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -1493,9 +1592,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -1520,6 +1616,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].VerifyCoppPpsLowPri$" }, @@ -1691,7 +1799,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -1708,9 +1816,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -1735,6 +1840,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].UnresolvedRouteNextHopToLowPriQueue$" }, @@ -1775,7 +1892,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -1792,9 +1909,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -1819,6 +1933,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].VerifyCoppPpsLowPri$" }, @@ -1939,7 +2065,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -1956,9 +2082,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -1983,6 +2106,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.cold_boot.AgentPacketSendReceiveLagTest.LacpPacketReceiveSrcPort$" }, @@ -2011,7 +2146,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -2028,9 +2163,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -2055,6 +2187,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].VerifyCoppPpsLowPri$" }, @@ -2175,7 +2319,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -2192,9 +2336,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -2219,6 +2360,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.cold_boot.AgentPacketSendReceiveLagTest.LacpPacketReceiveSrcPort$" }, @@ -2247,7 +2400,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -2264,9 +2417,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -2291,6 +2441,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].VerifyCoppPpsLowPri$" }, @@ -2543,7 +2705,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -2560,9 +2722,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -2587,6 +2746,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].UnresolvedRouteNextHopToLowPriQueue$" }, @@ -2627,7 +2798,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -2644,9 +2815,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -2671,6 +2839,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].VerifyCoppPpsLowPri$" }, @@ -2911,7 +3091,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -2928,9 +3108,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -2955,6 +3132,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.cold_boot.AgentPacketSendReceiveLagTest.LacpPacketReceiveSrcPort$" }, @@ -2983,7 +3172,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -3000,9 +3189,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -3027,6 +3213,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].VerifyCoppPpsLowPri$" }, @@ -3102,7 +3300,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -3119,9 +3317,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -3146,6 +3341,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].UnresolvedRouteNextHopToLowPriQueue$" }, @@ -3186,7 +3393,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -3203,9 +3410,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -3230,6 +3434,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].VerifyCoppPpsLowPri$" }, @@ -3293,7 +3509,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -3310,9 +3526,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -3337,6 +3550,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.cold_boot.AgentPacketSendReceiveLagTest.LacpPacketReceiveSrcPort$" }, @@ -3365,7 +3590,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -3382,9 +3607,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -3409,6 +3631,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].VerifyCoppPpsLowPri$" }, @@ -3568,7 +3802,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -3585,9 +3819,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -3612,6 +3843,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].UnresolvedRouteNextHopToLowPriQueue$" }, @@ -3652,7 +3895,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -3669,9 +3912,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -3696,6 +3936,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].VerifyCoppPpsLowPri$" }, @@ -3843,7 +4095,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -3860,9 +4112,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -3887,6 +4136,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.cold_boot.AgentPacketSendReceiveLagTest.LacpPacketReceiveSrcPort$" }, @@ -3915,7 +4176,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -3932,9 +4193,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -3959,6 +4217,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].VerifyCoppPpsLowPri$" }, @@ -4211,7 +4481,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -4228,9 +4498,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -4255,6 +4522,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].UnresolvedRouteNextHopToLowPriQueue$" }, @@ -4295,7 +4574,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -4312,9 +4591,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -4339,6 +4615,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].VerifyCoppPpsLowPri$" }, @@ -4579,7 +4867,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -4596,9 +4884,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -4623,6 +4908,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.cold_boot.AgentPacketSendReceiveLagTest.LacpPacketReceiveSrcPort$" }, @@ -4651,7 +4948,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -4668,9 +4965,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -4678,22 +4972,46 @@ "test_name_regex": "AgentSflowMirrorOnTrunkTestV[46].*$" }, { - "test_name_regex": "AgentSflowMirrorTruncateTestV[46].*$" + "test_name_regex": "AgentSflowMirrorTruncateTestV[46].*$" + }, + { + "test_name_regex": "AgentMacLearningTest.VerifyHwAgingForPort$" + }, + { + "test_name_regex": "AgentMacLearningTest.VerifyHwAgingForTrunk$" + }, + { + "test_name_regex": "AgentMacLearningTest.VerifyHwLearningForPort$" + }, + { + "test_name_regex": "AgentMacLearningTest.VerifyHwLearningForTrunk$" + }, + { + "test_name_regex": "AgentIngressEgress.*$" + }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" }, { - "test_name_regex": "AgentMacLearningTest.VerifyHwAgingForPort$" + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" }, { - "test_name_regex": "AgentMacLearningTest.VerifyHwAgingForTrunk$" + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" }, { - "test_name_regex": "AgentMacLearningTest.VerifyHwLearningForPort$" + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" }, { - "test_name_regex": "AgentMacLearningTest.VerifyHwLearningForTrunk$" + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" }, { - "test_name_regex": "AgentIngressEgress.*$" + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" }, { "test_name_regex": "AgentCoppTest/[01].VerifyCoppPpsLowPri$" @@ -4770,7 +5088,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -4787,9 +5105,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -4814,6 +5129,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].UnresolvedRouteNextHopToLowPriQueue$" }, @@ -4854,7 +5181,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -4871,9 +5198,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -4898,6 +5222,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].VerifyCoppPpsLowPri$" }, @@ -4961,7 +5297,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -4978,9 +5314,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -5005,6 +5338,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.cold_boot.AgentPacketSendReceiveLagTest.LacpPacketReceiveSrcPort$" }, @@ -5033,7 +5378,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -5050,9 +5395,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -5077,6 +5419,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].VerifyCoppPpsLowPri$" }, @@ -5152,7 +5506,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -5169,9 +5523,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -5196,6 +5547,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].UnresolvedRouteNextHopToLowPriQueue$" }, @@ -5236,7 +5599,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -5253,9 +5616,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -5280,6 +5640,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].VerifyCoppPpsLowPri$" }, @@ -5397,7 +5769,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -5414,9 +5786,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -5441,6 +5810,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.cold_boot.AgentPacketSendReceiveLagTest.LacpPacketReceiveSrcPort$" }, @@ -5469,7 +5850,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -5486,9 +5867,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -5513,6 +5891,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].VerifyCoppPpsLowPri$" }, @@ -5675,7 +6065,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -5692,9 +6082,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -5719,6 +6106,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].UnresolvedRouteNextHopToLowPriQueue$" }, @@ -5759,7 +6158,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -5776,9 +6175,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -5803,6 +6199,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].VerifyCoppPpsLowPri$" }, @@ -5902,7 +6310,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -5919,9 +6327,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -5946,6 +6351,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.cold_boot.AgentPacketSendReceiveLagTest.LacpPacketReceiveSrcPort$" }, @@ -5974,7 +6391,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -5991,9 +6408,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -6018,6 +6432,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].VerifyCoppPpsLowPri$" }, @@ -6165,7 +6591,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -6182,9 +6608,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -6209,6 +6632,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].UnresolvedRouteNextHopToLowPriQueue$" }, @@ -6249,7 +6684,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -6266,9 +6701,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -6293,6 +6725,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].VerifyCoppPpsLowPri$" }, @@ -6506,7 +6950,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -6523,9 +6967,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -6550,6 +6991,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.cold_boot.AgentPacketSendReceiveLagTest.LacpPacketReceiveSrcPort$" }, @@ -6578,7 +7031,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -6595,9 +7048,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -6622,6 +7072,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].VerifyCoppPpsLowPri$" }, @@ -6793,7 +7255,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -6810,9 +7272,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -6837,6 +7296,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].UnresolvedRouteNextHopToLowPriQueue$" }, @@ -6877,7 +7348,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -6894,9 +7365,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -6921,6 +7389,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].VerifyCoppPpsLowPri$" }, @@ -7107,7 +7587,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -7124,9 +7604,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -7151,6 +7628,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.cold_boot.AgentPacketSendReceiveLagTest.LacpPacketReceiveSrcPort$" } @@ -7301,7 +7790,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -7318,9 +7807,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -7345,6 +7831,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].UnresolvedRouteNextHopToLowPriQueue$" }, @@ -7465,7 +7963,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -7482,9 +7980,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -7509,6 +8004,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.cold_boot.AgentPacketSendReceiveLagTest.LacpPacketReceiveSrcPort$" } @@ -7617,7 +8124,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -7634,9 +8141,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -7661,6 +8165,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].UnresolvedRouteNextHopToLowPriQueue$" }, @@ -7781,7 +8297,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -7798,9 +8314,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -7825,6 +8338,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.cold_boot.AgentPacketSendReceiveLagTest.LacpPacketReceiveSrcPort$" } @@ -7933,7 +8458,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -7950,9 +8475,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -7977,6 +8499,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].UnresolvedRouteNextHopToLowPriQueue$" }, @@ -8118,7 +8652,7 @@ "test_name_regex": "AgentUdfAclCounterTest.*$" }, { - "test_name_regex": "AgentFlowletAclCounterTest.*$" + "test_name_regex": "AgentFlowlet*$" }, { "test_name_regex": "AgentCoppQosTest.HighVsLowerPriorityCpuQueueTrafficPrioritization$" @@ -8135,9 +8669,6 @@ { "test_name_regex": "AgentMacLearningBatchEntriesTest.*$" }, - { - "test_name_regex": "AgentFlowletSwitchingTest.*$" - }, { "test_name_regex": "AgentSflowMirrorTestV[46].*$" }, @@ -8162,6 +8693,18 @@ { "test_name_regex": "AgentIngressEgress.*$" }, + { + "test_name_regex": "AgentIngressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentIngressAclErspanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclSpanMirroringTest.*$" + }, + { + "test_name_regex": "AgentEgressAclErspanMirroringTest.*$" + }, { "test_name_regex": "AgentCoppTest/[01].UnresolvedRouteNextHopToLowPriQueue$" }, diff --git a/fboss/oss/hw_known_bad_tests/sai_known_bad_tests.materialized_JSON b/fboss/oss/hw_known_bad_tests/sai_known_bad_tests.materialized_JSON index dad3930b7cb39..caa6fddb8ebd8 100644 --- a/fboss/oss/hw_known_bad_tests/sai_known_bad_tests.materialized_JSON +++ b/fboss/oss/hw_known_bad_tests/sai_known_bad_tests.materialized_JSON @@ -19,9 +19,6 @@ { "test_name_regex": "HwHashConsistencyTest.UdpEgressLinksOnEcmpExpand" }, - { - "test_name_regex": "HwPfcTest.PfcWatchdog*" - }, { "test_name_regex": "HwVerifyPfcConfigInHwTest.PfcWatchdog*" }, @@ -420,9 +417,6 @@ { "test_name_regex": "HwMacSwLearningModeTest.VerifyCallbacksOnMacEntryChange" }, - { - "test_name_regex": "HwPfcTest.PfcWatchdog.*" - }, { "test_name_regex": "HwVerifyPfcConfigInHwTest.PfcWatchdog.*" }, @@ -1031,9 +1025,6 @@ { "test_name_regex": "HwMacSwLearningModeTest.VerifyCallbacksOnMacEntryChange" }, - { - "test_name_regex": "HwPfcTest.PfcWatchdog.*" - }, { "test_name_regex": "HwVerifyPfcConfigInHwTest.PfcWatchdog.*" }, @@ -1136,6 +1127,9 @@ { "test_name_regex": "HwProdInvariantsRswStrictPriorityTest" }, + { + "test_name_regex": "HwTest_PROFILE_100G_4_NRZ_RS528_OPTICAL.TestProfile" + }, { "test_name_regex": "HwDscpQueueMappingTest.VerifyAclAndQosMap" }, @@ -1588,9 +1582,6 @@ { "test_name_regex": "HwTrafficPfcTest.*" }, - { - "test_name_regex": "HwPfcTest.*" - }, { "test_name_regex": "HwVerifyPfcConfigInHwTest.*" }, @@ -2232,9 +2223,6 @@ { "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.warm_boot_for_warm_boot.0.HwEmptyTest.CheckInit.HwFlexPortTest.FlexPortFOURX25G" }, - { - "test_name_regex": "roundtrip.trunk_2_preprod_2_trunk.warm_boot_for_warm_boot.0.HwEmptyTest.CheckInit.HwPfcTest.*" - }, { "test_name_regex": "roundtrip.trunk_2_preprod_2_trunk.warm_boot_for_warm_boot.0.HwEmptyTest.CheckInit.HwVerifyPfcConfigInHwTest.*" }, @@ -2313,9 +2301,6 @@ { "test_name_regex": "HwLoadBalancerNegativeProtocolMatchTestV6RoCE.*" }, - { - "test_name_regex": "HwPfcTest.PfcWatchdog.*" - }, { "test_name_regex": "HwVerifyPfcConfigInHwTest.PfcWatchdog.*" }, @@ -2615,9 +2600,6 @@ { "test_name_regex": "HwMacSwLearningModeTest.VerifyCallbacksOnMacEntryChange" }, - { - "test_name_regex": "HwPfcTest.PfcWatchdog.*" - }, { "test_name_regex": "HwVerifyPfcConfigInHwTest.PfcWatchdog.*" }, @@ -3160,9 +3142,6 @@ { "test_name_regex": "HwMacSwLearningModeTest.VerifyCallbacksOnMacEntryChange" }, - { - "test_name_regex": "HwPfcTest.PfcWatchdog.*" - }, { "test_name_regex": "HwVerifyPfcConfigInHwTest.PfcWatchdog.*" }, @@ -3264,6 +3243,9 @@ }, { "test_name_regex": "HwProdInvariantsRswStrictPriorityTest" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_4_NRZ_RS528_OPTICAL.TestProfile" } ], "brcm/11.3.0.0_dnx_odp/11.3.0.0_dnx_odp/jericho3": [ @@ -3419,9 +3401,6 @@ { "test_name_regex": "HwHashConsistencyTest.UdpEgressLinksOnEcmpExpand" }, - { - "test_name_regex": "HwPfcTest.PfcWatchdog*" - }, { "test_name_regex": "HwVerifyPfcConfigInHwTest.PfcWatchdog*" }, @@ -3738,9 +3717,6 @@ { "test_name_regex": "HwRouteTest/[01].VerifyClassIdWithNhopResolutionFlap" }, - { - "test_name_regex": "HwPfcTest.PfcWatchdog*" - }, { "test_name_regex": "HwVerifyPfcConfigInHwTest.PfcWatchdog*" }, @@ -4083,9 +4059,6 @@ { "test_name_regex": "HwOlympicQosTests.*" }, - { - "test_name_regex": "HwPfcTest.*" - }, { "test_name_regex": "HwVerifyPfcConfigInHwTest.*" }, @@ -4562,9 +4535,6 @@ { "test_name_regex": "HwTrafficPfcTest.*" }, - { - "test_name_regex": "HwPfcTest.*" - }, { "test_name_regex": "HwVerifyPfcConfigInHwTest.*" }, @@ -5206,9 +5176,6 @@ { "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.warm_boot_for_warm_boot.0.HwEmptyTest.CheckInit.HwFlexPortTest.FlexPortFOURX25G" }, - { - "test_name_regex": "roundtrip.trunk_2_preprod_2_trunk.warm_boot_for_warm_boot.0.HwEmptyTest.CheckInit.HwPfcTest.*" - }, { "test_name_regex": "roundtrip.trunk_2_preprod_2_trunk.warm_boot_for_warm_boot.0.HwEmptyTest.CheckInit.HwVerifyPfcConfigInHwTest.*" }, @@ -5287,9 +5254,6 @@ { "test_name_regex": "HwLoadBalancerNegativeProtocolMatchTestV6RoCE.*" }, - { - "test_name_regex": "HwPfcTest.PfcWatchdog.*" - }, { "test_name_regex": "HwVerifyPfcConfigInHwTest.PfcWatchdog.*" }, @@ -5586,9 +5550,6 @@ { "test_name_regex": "HwMacSwLearningModeTest.VerifyCallbacksOnMacEntryChange" }, - { - "test_name_regex": "HwPfcTest.PfcWatchdog.*" - }, { "test_name_regex": "HwVerifyPfcConfigInHwTest.PfcWatchdog.*" }, @@ -6257,9 +6218,6 @@ { "test_name_regex": "HwTrafficPfcTest.*" }, - { - "test_name_regex": "HwPfcTest.*" - }, { "test_name_regex": "HwVerifyPfcConfigInHwTest.*" }, @@ -6401,9 +6359,6 @@ { "test_name_regex": "HwTrafficPfcTest.*" }, - { - "test_name_regex": "HwPfcTest.*" - }, { "test_name_regex": "HwVerifyPfcConfigInHwTest.*" }, @@ -6928,9 +6883,6 @@ { "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.warm_boot_for_warm_boot.0.HwEmptyTest.CheckInit.HwFlexPortTest.FlexPortFOURX25G" }, - { - "test_name_regex": "roundtrip.trunk_2_preprod_2_trunk.warm_boot_for_warm_boot.0.HwEmptyTest.CheckInit.HwPfcTest.*" - }, { "test_name_regex": "roundtrip.trunk_2_preprod_2_trunk.warm_boot_for_warm_boot.0.HwEmptyTest.CheckInit.HwVerifyPfcConfigInHwTest.*" }, @@ -7009,9 +6961,6 @@ { "test_name_regex": "HwLoadBalancerNegativeProtocolMatchTestV6RoCE.*" }, - { - "test_name_regex": "HwPfcTest.PfcWatchdog.*" - }, { "test_name_regex": "HwVerifyPfcConfigInHwTest.PfcWatchdog.*" }, @@ -7051,9 +7000,6 @@ { "test_name_regex": "HwTrafficPfcTest.*" }, - { - "test_name_regex": "HwPfcTest.*" - }, { "test_name_regex": "HwVerifyPfcConfigInHwTest.*" }, @@ -7335,9 +7281,6 @@ { "test_name_regex": "HwMacSwLearningModeTest.VerifyCallbacksOnMacEntryChange" }, - { - "test_name_regex": "HwPfcTest.PfcWatchdog.*" - }, { "test_name_regex": "HwVerifyPfcConfigInHwTest.PfcWatchdog.*" }, @@ -7623,9 +7566,6 @@ { "test_name_regex": "HwTrafficPfcTest.*" }, - { - "test_name_regex": "HwPfcTest.*" - }, { "test_name_regex": "HwVerifyPfcConfigInHwTest.*" }, @@ -7907,9 +7847,6 @@ { "test_name_regex": "HwMacSwLearningModeTest.VerifyCallbacksOnMacEntryChange" }, - { - "test_name_regex": "HwPfcTest.PfcWatchdog.*" - }, { "test_name_regex": "HwVerifyPfcConfigInHwTest.PfcWatchdog.*" }, @@ -8644,9 +8581,6 @@ { "test_name_regex": "HwTrafficPfcTest.*" }, - { - "test_name_regex": "HwPfcTest.*" - }, { "test_name_regex": "HwVerifyPfcConfigInHwTest.*" }, @@ -9288,9 +9222,6 @@ { "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.warm_boot_for_warm_boot.0.HwEmptyTest.CheckInit.HwFlexPortTest.FlexPortFOURX25G" }, - { - "test_name_regex": "roundtrip.trunk_2_preprod_2_trunk.warm_boot_for_warm_boot.0.HwEmptyTest.CheckInit.HwPfcTest.*" - }, { "test_name_regex": "roundtrip.trunk_2_preprod_2_trunk.warm_boot_for_warm_boot.0.HwEmptyTest.CheckInit.HwVerifyPfcConfigInHwTest.*" }, @@ -9369,9 +9300,6 @@ { "test_name_regex": "HwLoadBalancerNegativeProtocolMatchTestV6RoCE.*" }, - { - "test_name_regex": "HwPfcTest.PfcWatchdog.*" - }, { "test_name_regex": "HwVerifyPfcConfigInHwTest.PfcWatchdog.*" }, @@ -9671,9 +9599,6 @@ { "test_name_regex": "HwMacSwLearningModeTest.VerifyCallbacksOnMacEntryChange" }, - { - "test_name_regex": "HwPfcTest.PfcWatchdog.*" - }, { "test_name_regex": "HwVerifyPfcConfigInHwTest.PfcWatchdog.*" }, @@ -9961,9 +9886,6 @@ { "test_name_regex": "HwTrafficPfcTest.*" }, - { - "test_name_regex": "HwPfcTest.*" - }, { "test_name_regex": "HwVerifyPfcConfigInHwTest.*" }, @@ -10353,9 +10275,6 @@ { "test_name_regex": "HwTrafficPfcTest.*" }, - { - "test_name_regex": "HwPfcTest.*" - }, { "test_name_regex": "HwVerifyPfcConfigInHwTest.*" }, @@ -11051,9 +10970,6 @@ { "test_name_regex": "HwTrafficPfcTest.*" }, - { - "test_name_regex": "HwPfcTest.*" - }, { "test_name_regex": "HwVerifyPfcConfigInHwTest.*" }, @@ -11461,9 +11377,6 @@ { "test_name_regex": "HwTrafficPfcTest.*" }, - { - "test_name_regex": "HwPfcTest.*" - }, { "test_name_regex": "HwVerifyPfcConfigInHwTest.*" }, @@ -12162,9 +12075,6 @@ { "test_name_regex": "HwTrafficPfcTest.*" }, - { - "test_name_regex": "HwPfcTest.*" - }, { "test_name_regex": "HwVerifyPfcConfigInHwTest.*" }, diff --git a/fboss/oss/link_known_bad_tests/fboss_link_known_bad_tests.materialized_JSON b/fboss/oss/link_known_bad_tests/fboss_link_known_bad_tests.materialized_JSON index 1dd1deaf614d2..911b8940c5dc3 100644 --- a/fboss/oss/link_known_bad_tests/fboss_link_known_bad_tests.materialized_JSON +++ b/fboss/oss/link_known_bad_tests/fboss_link_known_bad_tests.materialized_JSON @@ -10318,6 +10318,9 @@ { "test_name_regex": "LacpTest.lacpFlap$" }, + { + "test_name_regex": "roundtrip.*.iPhyInfoTest$" + }, { "test_name_regex": "LinkTest.verifyIphyFecCounters$" } @@ -10386,6 +10389,9 @@ { "test_name_regex": "LacpTest.lacpFlap$" }, + { + "test_name_regex": "roundtrip.*.iPhyInfoTest$" + }, { "test_name_regex": "LinkTest.verifyIphyFecCounters$" } @@ -10454,6 +10460,9 @@ { "test_name_regex": "LacpTest.lacpFlap$" }, + { + "test_name_regex": "roundtrip.*.iPhyInfoTest$" + }, { "test_name_regex": "LinkTest.verifyIphyFecCounters$" } @@ -10522,6 +10531,9 @@ { "test_name_regex": "LacpTest.lacpFlap$" }, + { + "test_name_regex": "roundtrip.*.iPhyInfoTest$" + }, { "test_name_regex": "LinkTest.verifyIphyFecCounters$" } @@ -10590,6 +10602,9 @@ { "test_name_regex": "LacpTest.lacpFlap$" }, + { + "test_name_regex": "roundtrip.*.iPhyInfoTest$" + }, { "test_name_regex": "LinkTest.verifyIphyFecCounters$" } @@ -10658,6 +10673,9 @@ { "test_name_regex": "LacpTest.lacpFlap$" }, + { + "test_name_regex": "roundtrip.*.iPhyInfoTest$" + }, { "test_name_regex": "LinkTest.verifyIphyFecCounters$" } @@ -10726,6 +10744,9 @@ { "test_name_regex": "LacpTest.lacpFlap$" }, + { + "test_name_regex": "roundtrip.*.iPhyInfoTest$" + }, { "test_name_regex": "LinkTest.verifyIphyFecCounters$" } @@ -10794,6 +10815,9 @@ { "test_name_regex": "LacpTest.lacpFlap$" }, + { + "test_name_regex": "roundtrip.*.iPhyInfoTest$" + }, { "test_name_regex": "LinkTest.verifyIphyFecCounters$" } diff --git a/fboss/oss/link_test_configs/janga800bic.materialized_JSON b/fboss/oss/link_test_configs/janga800bic.materialized_JSON index fcecea2b1d68b..9980ed906c761 100644 --- a/fboss/oss/link_test_configs/janga800bic.materialized_JSON +++ b/fboss/oss/link_test_configs/janga800bic.materialized_JSON @@ -13124,7 +13124,7 @@ "scope": 1 }, { - "intfID": 187, + "intfID": 55, "routerID": 0, "vlanID": 0, "ipAddresses": [ @@ -13250,6 +13250,36 @@ "l4DstPort": 179, "lookupClassRoute": 1, "etherType": 34525 + }, + { + "name": "cpuPolicing-mid-lldp-dstMac0E", + "actionType": 1, + "dstMac": "01:80:c2:00:00:0e", + "etherType": 35020 + }, + { + "name": "cpuPolicing-mid-lldp-dstMac03", + "actionType": 1, + "dstMac": "01:80:c2:00:00:03", + "etherType": 35020 + }, + { + "name": "cpuPolicing-mid-lldp-dstMac00", + "actionType": 1, + "dstMac": "01:80:c2:00:00:00", + "etherType": 35020 + }, + { + "name": "cpuPolicing-mid-Ip2Me-Ip4", + "actionType": 1, + "lookupClassRoute": 1, + "etherType": 2048 + }, + { + "name": "cpuPolicing-mid-Ip2Me-Ip6", + "actionType": 1, + "lookupClassRoute": 1, + "etherType": 34525 } ], "maxNeighborProbes": 300, @@ -13411,6 +13441,66 @@ "tcValue": 7 } } + }, + { + "matcher": "cpuPolicing-mid-lldp-dstMac0E", + "action": { + "sendToQueue": { + "queueId": 2 + }, + "toCpuAction": 0, + "setTc": { + "tcValue": 2 + } + } + }, + { + "matcher": "cpuPolicing-mid-lldp-dstMac03", + "action": { + "sendToQueue": { + "queueId": 2 + }, + "toCpuAction": 0, + "setTc": { + "tcValue": 2 + } + } + }, + { + "matcher": "cpuPolicing-mid-lldp-dstMac00", + "action": { + "sendToQueue": { + "queueId": 2 + }, + "toCpuAction": 0, + "setTc": { + "tcValue": 2 + } + } + }, + { + "matcher": "cpuPolicing-mid-Ip2Me-Ip4", + "action": { + "sendToQueue": { + "queueId": 2 + }, + "toCpuAction": 0, + "setTc": { + "tcValue": 2 + } + } + }, + { + "matcher": "cpuPolicing-mid-Ip2Me-Ip6", + "action": { + "sendToQueue": { + "queueId": 2 + }, + "toCpuAction": 0, + "setTc": { + "tcValue": 2 + } + } } ] }, @@ -13431,14 +13521,6 @@ "rxReason": 13, "queueId": 7 }, - { - "rxReason": 9, - "queueId": 2 - }, - { - "rxReason": 7, - "queueId": 2 - }, { "rxReason": 2, "queueId": 2 @@ -13519,7 +13601,7 @@ }, "systemPortRange": { "minimum": 10, - "maximum": 54 + "maximum": 53 }, "switchMac": "02:00:00:00:00:01", "connectionHandle": "15:00" @@ -13533,8 +13615,8 @@ "maximum": 4095 }, "systemPortRange": { - "minimum": 186, - "maximum": 230 + "minimum": 54, + "maximum": 97 }, "switchMac": "02:00:00:00:00:01", "connectionHandle": "18:00" @@ -13557,22 +13639,22 @@ ], "systemPortRange": { "minimum": 10, - "maximum": 54 + "maximum": 53 }, "nodeMac": "02:00:00:00:0F:0B", "asicType": 14, "platformType": 32 }, "4": { - "name": "intfNode4", + "name": "intfNode1", "switchId": 4, "type": 2, "loopbackIps": [ ], "systemPortRange": { - "minimum": 186, - "maximum": 230 + "minimum": 54, + "maximum": 97 }, "nodeMac": "02:00:00:00:0F:0B", "asicType": 14, diff --git a/fboss/oss/link_test_configs/meru400biu.materialized_JSON b/fboss/oss/link_test_configs/meru400biu.materialized_JSON index 647b6e9a100e5..22ef1d7fe7c21 100644 --- a/fboss/oss/link_test_configs/meru400biu.materialized_JSON +++ b/fboss/oss/link_test_configs/meru400biu.materialized_JSON @@ -7695,7 +7695,7 @@ }, "systemPortRange": { "minimum": 10, - "maximum": 30 + "maximum": 29 }, "switchMac": "02:00:00:00:00:01", "connectionHandle": "68:00" @@ -7718,7 +7718,7 @@ ], "systemPortRange": { "minimum": 10, - "maximum": 30 + "maximum": 29 }, "nodeMac": "02:00:00:00:0F:0B", "asicType": 11, diff --git a/fboss/oss/link_test_configs/meru800bia.materialized_JSON b/fboss/oss/link_test_configs/meru800bia.materialized_JSON index 0e7532f643fcd..66300b67e246b 100644 --- a/fboss/oss/link_test_configs/meru800bia.materialized_JSON +++ b/fboss/oss/link_test_configs/meru800bia.materialized_JSON @@ -19,7 +19,7 @@ "parserType": 1, "routable": true, "ingressVlan": 0, - "speed": 10000, + "speed": 100000, "name": "rcy1/1/441", "description": "", "queues_DEPRECATED": [ @@ -38,7 +38,7 @@ "lookupClasses": [ ], - "profileID": 11, + "profileID": 49, "portType": 3, "expectedNeighborReachability": [ @@ -54,7 +54,7 @@ "parserType": 1, "routable": true, "ingressVlan": 0, - "speed": 10000, + "speed": 100000, "name": "rcy1/1/442", "description": "", "queues_DEPRECATED": [ @@ -73,7 +73,7 @@ "lookupClasses": [ ], - "profileID": 11, + "profileID": 49, "portType": 3, "expectedNeighborReachability": [ @@ -89,7 +89,7 @@ "parserType": 1, "routable": true, "ingressVlan": 0, - "speed": 10000, + "speed": 100000, "name": "rcy1/1/443", "description": "", "queues_DEPRECATED": [ @@ -108,7 +108,7 @@ "lookupClasses": [ ], - "profileID": 11, + "profileID": 49, "portType": 3, "expectedNeighborReachability": [ @@ -124,7 +124,7 @@ "parserType": 1, "routable": true, "ingressVlan": 0, - "speed": 10000, + "speed": 100000, "name": "rcy1/1/444", "description": "", "queues_DEPRECATED": [ @@ -143,7 +143,7 @@ "lookupClasses": [ ], - "profileID": 11, + "profileID": 49, "portType": 3, "expectedNeighborReachability": [ @@ -159,7 +159,7 @@ "parserType": 1, "routable": true, "ingressVlan": 0, - "speed": 10000, + "speed": 100000, "name": "rcy1/1/445", "description": "", "queues_DEPRECATED": [ @@ -178,7 +178,7 @@ "lookupClasses": [ ], - "profileID": 11, + "profileID": 49, "portType": 3, "expectedNeighborReachability": [ @@ -194,7 +194,7 @@ "parserType": 1, "routable": true, "ingressVlan": 0, - "speed": 10000, + "speed": 100000, "name": "evt1/1/506", "description": "", "queues_DEPRECATED": [ @@ -213,7 +213,7 @@ "lookupClasses": [ ], - "profileID": 11, + "profileID": 49, "portType": 5, "expectedNeighborReachability": [ @@ -7369,6 +7369,36 @@ "lookupClassRoute": 1, "etherType": 34525 }, + { + "name": "cpuPolicing-mid-lldp-dstMac0E", + "actionType": 1, + "dstMac": "01:80:c2:00:00:0e", + "etherType": 35020 + }, + { + "name": "cpuPolicing-mid-lldp-dstMac03", + "actionType": 1, + "dstMac": "01:80:c2:00:00:03", + "etherType": 35020 + }, + { + "name": "cpuPolicing-mid-lldp-dstMac00", + "actionType": 1, + "dstMac": "01:80:c2:00:00:00", + "etherType": 35020 + }, + { + "name": "cpuPolicing-mid-Ip2Me-Ip4", + "actionType": 1, + "lookupClassRoute": 1, + "etherType": 2048 + }, + { + "name": "cpuPolicing-mid-Ip2Me-Ip6", + "actionType": 1, + "lookupClassRoute": 1, + "etherType": 34525 + }, { "dstIp": "ff00::/8", "name": "drop-v6-multicast", @@ -7547,6 +7577,66 @@ "tcValue": 7 } } + }, + { + "matcher": "cpuPolicing-mid-lldp-dstMac0E", + "action": { + "sendToQueue": { + "queueId": 3 + }, + "toCpuAction": 1, + "setTc": { + "tcValue": 3 + } + } + }, + { + "matcher": "cpuPolicing-mid-lldp-dstMac03", + "action": { + "sendToQueue": { + "queueId": 3 + }, + "toCpuAction": 1, + "setTc": { + "tcValue": 3 + } + } + }, + { + "matcher": "cpuPolicing-mid-lldp-dstMac00", + "action": { + "sendToQueue": { + "queueId": 3 + }, + "toCpuAction": 1, + "setTc": { + "tcValue": 3 + } + } + }, + { + "matcher": "cpuPolicing-mid-Ip2Me-Ip4", + "action": { + "sendToQueue": { + "queueId": 3 + }, + "toCpuAction": 1, + "setTc": { + "tcValue": 3 + } + } + }, + { + "matcher": "cpuPolicing-mid-Ip2Me-Ip6", + "action": { + "sendToQueue": { + "queueId": 3 + }, + "toCpuAction": 1, + "setTc": { + "tcValue": 3 + } + } } ] }, @@ -7567,14 +7657,6 @@ "rxReason": 13, "queueId": 7 }, - { - "rxReason": 9, - "queueId": 3 - }, - { - "rxReason": 7, - "queueId": 3 - }, { "rxReason": 2, "queueId": 3 @@ -7655,7 +7737,7 @@ }, "systemPortRange": { "minimum": 10, - "maximum": 54 + "maximum": 53 }, "switchMac": "02:00:00:00:00:01", "connectionHandle": "15:00" @@ -7678,7 +7760,7 @@ ], "systemPortRange": { "minimum": 10, - "maximum": 54 + "maximum": 53 }, "nodeMac": "02:00:00:00:0F:0B", "asicType": 14, @@ -8702,8 +8784,10 @@ "port_init_speed_cd.BCM8889X": "400000", "port_init_speed_ce.BCM8889X": "100000", "port_init_speed_d3c.BCM8889X": "800000", + "port_init_speed_eventor.BCM8889X": "100000", "port_init_speed_fabric.BCM8889X": "106250", "port_init_speed_le.BCM8889X": "50000", + "port_init_speed_rcy.BCM8889X": "100000", "port_init_speed_sat.BCM8889X": "400000", "port_init_speed_xe.BCM8889X": "25000", "port_init_speed_xe13.BCM8889X": "10000", diff --git a/fboss/oss/production_features/asic_production_features.materialized_JSON b/fboss/oss/production_features/asic_production_features.materialized_JSON index 70d4d385e2f3c..32bd514eeb8cf 100644 --- a/fboss/oss/production_features/asic_production_features.materialized_JSON +++ b/fboss/oss/production_features/asic_production_features.materialized_JSON @@ -182,7 +182,8 @@ 38, 39, 40, - 42 + 42, + 43 ], "tomahawk5": [ 2, @@ -430,7 +431,8 @@ "HGRID_DU_ROUTE_SCALE", "HGRID_UU_ROUTE_SCALE", "HUNDRED_THOUSAND_ROUTE_SCALE", - "PFC" + "PFC", + "UDF_WR_IMMEDIATE_ACL" ], "tomahawk5": [ "CPU_RX_TX", diff --git a/fboss/oss/qsfp_test_configs/janga800bic.materialized_JSON b/fboss/oss/qsfp_test_configs/janga800bic.materialized_JSON index d7b1b51c633f1..a1d63c78b2d51 100644 --- a/fboss/oss/qsfp_test_configs/janga800bic.materialized_JSON +++ b/fboss/oss/qsfp_test_configs/janga800bic.materialized_JSON @@ -102,7 +102,7 @@ "versions": [ { "fwType": 1, - "version": "1.13" + "version": "1.15" } ] }, @@ -206,7 +206,7 @@ "versions": [ { "fwType": 1, - "version": "36.240" + "version": "36.194" } ] }, @@ -214,7 +214,7 @@ "versions": [ { "fwType": 1, - "version": "36.240" + "version": "36.194" } ] }, @@ -222,7 +222,7 @@ "versions": [ { "fwType": 1, - "version": "103.243" + "version": "103.244" } ] } diff --git a/fboss/oss/qsfp_test_configs/meru400bfu.materialized_JSON b/fboss/oss/qsfp_test_configs/meru400bfu.materialized_JSON index 7d7860d6f956a..ca3064b6d1fe4 100644 --- a/fboss/oss/qsfp_test_configs/meru400bfu.materialized_JSON +++ b/fboss/oss/qsfp_test_configs/meru400bfu.materialized_JSON @@ -75,7 +75,7 @@ "versions": [ { "fwType": 1, - "version": "1.13" + "version": "1.15" } ] }, @@ -179,7 +179,7 @@ "versions": [ { "fwType": 1, - "version": "36.240" + "version": "36.194" } ] }, @@ -187,7 +187,7 @@ "versions": [ { "fwType": 1, - "version": "36.240" + "version": "36.194" } ] }, @@ -195,7 +195,7 @@ "versions": [ { "fwType": 1, - "version": "103.243" + "version": "103.244" } ] } diff --git a/fboss/oss/qsfp_test_configs/meru400biu.materialized_JSON b/fboss/oss/qsfp_test_configs/meru400biu.materialized_JSON index 8304604b243f7..7920a82cc6999 100644 --- a/fboss/oss/qsfp_test_configs/meru400biu.materialized_JSON +++ b/fboss/oss/qsfp_test_configs/meru400biu.materialized_JSON @@ -80,7 +80,7 @@ "versions": [ { "fwType": 1, - "version": "1.13" + "version": "1.15" } ] }, @@ -184,7 +184,7 @@ "versions": [ { "fwType": 1, - "version": "36.240" + "version": "36.194" } ] }, @@ -192,7 +192,7 @@ "versions": [ { "fwType": 1, - "version": "36.240" + "version": "36.194" } ] }, @@ -200,7 +200,7 @@ "versions": [ { "fwType": 1, - "version": "103.243" + "version": "103.244" } ] } diff --git a/fboss/oss/qsfp_test_configs/tahan800bc.materialized_JSON b/fboss/oss/qsfp_test_configs/tahan800bc.materialized_JSON index f175489bbf7bc..f3f5238636833 100644 --- a/fboss/oss/qsfp_test_configs/tahan800bc.materialized_JSON +++ b/fboss/oss/qsfp_test_configs/tahan800bc.materialized_JSON @@ -61,7 +61,7 @@ "versions": [ { "fwType": 1, - "version": "1.13" + "version": "1.15" } ] }, @@ -165,7 +165,7 @@ "versions": [ { "fwType": 1, - "version": "36.240" + "version": "36.194" } ] }, @@ -173,7 +173,7 @@ "versions": [ { "fwType": 1, - "version": "36.240" + "version": "36.194" } ] }, @@ -181,7 +181,7 @@ "versions": [ { "fwType": 1, - "version": "103.243" + "version": "103.244" } ] } diff --git a/fboss/oss/qsfp_unsupported_tests/fboss_qsfp_unsupported_tests.materialized_JSON b/fboss/oss/qsfp_unsupported_tests/fboss_qsfp_unsupported_tests.materialized_JSON index a4c73b12917e4..e35a742ac2546 100644 --- a/fboss/oss/qsfp_unsupported_tests/fboss_qsfp_unsupported_tests.materialized_JSON +++ b/fboss/oss/qsfp_unsupported_tests/fboss_qsfp_unsupported_tests.materialized_JSON @@ -171,6 +171,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "darwin/physdk-credo-0.8.4/credo-0.8.4": [ @@ -344,6 +347,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "darwin_mix/physdk-credo-0.7.2/credo-0.7.2": [ @@ -517,6 +523,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "darwin_mix/physdk-credo-0.8.4/credo-0.8.4": [ @@ -690,6 +699,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "darwin_original/physdk-credo-0.7.2/credo-0.7.2": [ @@ -857,6 +869,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "darwin_original/physdk-credo-0.8.4/credo-0.8.4": [ @@ -1024,6 +1039,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "elbert_2x16Q_6x8DD/physdk-credo-0.7.2/credo-0.7.2": [ @@ -1164,6 +1182,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "elbert_2x16Q_6x8DD/physdk-credo-0.8.4/credo-0.8.4": [ @@ -1304,6 +1325,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "elbert_5x16Q_3x8DD/physdk-credo-0.7.2/credo-0.7.2": [ @@ -1444,6 +1468,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "elbert_5x16Q_3x8DD/physdk-credo-0.8.4/credo-0.8.4": [ @@ -1584,6 +1611,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "elbert_8x16Q/physdk-credo-0.7.2/credo-0.7.2": [ @@ -1739,6 +1769,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "elbert_8x16Q/physdk-credo-0.8.4/credo-0.8.4": [ @@ -1894,6 +1927,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "fuji_5x16Q/physdk-barchetta2-5.2/barchetta2-5.2": [ @@ -1966,9 +2002,6 @@ { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_COPPER.TestProfile$" }, - { - "test_name_regex": "HwTest_PROFILE_100G_4_NRZ_RS528_COPPER.TestProfile$" - }, { "test_name_regex": "HwTest_PROFILE_100G_4_NRZ_RS528_OPTICAL.TestProfile$" }, @@ -2040,6 +2073,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "fuji_8x16Q/physdk-barchetta2-5.2/barchetta2-5.2": [ @@ -2180,6 +2216,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "janga800bic/physdk-credo-0.7.2/credo-0.7.2": [ @@ -2353,6 +2392,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "janga800bic/physdk-credo-0.8.4/credo-0.8.4": [ @@ -2526,6 +2568,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "meru400bfu/physdk-credo-0.7.2/credo-0.7.2": [ @@ -2699,6 +2744,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "meru400bfu/physdk-credo-0.8.4/credo-0.8.4": [ @@ -2872,6 +2920,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "meru400biu/physdk-credo-0.7.2/credo-0.7.2": [ @@ -3042,6 +3093,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "meru400biu/physdk-credo-0.8.4/credo-0.8.4": [ @@ -3212,6 +3266,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "meru800bfa/physdk-credo-0.7.2/credo-0.7.2": [ @@ -3388,6 +3445,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "meru800bfa/physdk-credo-0.8.4/credo-0.8.4": [ @@ -3564,6 +3624,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "meru800bia/physdk-credo-0.7.2/credo-0.7.2": [ @@ -3734,6 +3797,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "meru800bia/physdk-credo-0.8.4/credo-0.8.4": [ @@ -3904,6 +3970,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "minipack_7x16Q_1x16O/physdk-millenio-5.5/millenio-5.5": [ @@ -4059,6 +4128,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "montblanc/physdk-credo-0.7.2/credo-0.7.2": [ @@ -4226,6 +4298,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "montblanc/physdk-credo-0.8.4/credo-0.8.4": [ @@ -4393,6 +4468,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "morgan800cc/physdk-credo-0.7.2/credo-0.7.2": [ @@ -4563,6 +4641,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "morgan800cc/physdk-credo-0.8.4/credo-0.8.4": [ @@ -4733,6 +4814,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "tahan800bc/physdk-credo-0.7.2/credo-0.7.2": [ @@ -4903,6 +4987,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "tahan800bc/physdk-credo-0.8.4/credo-0.8.4": [ @@ -5073,6 +5160,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "wedge100s/physdk-credo-0.7.2/credo-0.7.2": [ @@ -5249,6 +5339,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "wedge100s/physdk-credo-0.8.4/credo-0.8.4": [ @@ -5425,6 +5518,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "wedge400/physdk-credo-0.7.2/credo-0.7.2": [ @@ -5580,6 +5676,9 @@ }, { "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_RS544_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "wedge400/physdk-credo-0.8.4/credo-0.8.4": [ @@ -5735,6 +5834,9 @@ }, { "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_RS544_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "wedge400c/physdk-credo-0.7.2/credo-0.7.2": [ @@ -5902,6 +6004,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "wedge400c/physdk-credo-0.8.4/credo-0.8.4": [ @@ -6069,6 +6174,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "yamp_8x16Q/physdk-credo-0.7.2/credo-0.7.2": [ @@ -6218,6 +6326,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ], "yamp_8x16Q/physdk-credo-0.8.4/credo-0.8.4": [ @@ -6367,6 +6478,9 @@ }, { "test_name_regex": "HwTest_PROFILE_50G_2_NRZ_RS528_OPTICAL.TestProfile$" + }, + { + "test_name_regex": "HwTest_PROFILE_100G_1_PAM4_NOFEC_COPPER.TestProfile$" } ] } diff --git a/fboss/oss/sai_hw_unsupported_tests/sai_hw_unsupported_tests.materialized_JSON b/fboss/oss/sai_hw_unsupported_tests/sai_hw_unsupported_tests.materialized_JSON index 86ad9fdf85c7b..13ab0fc515cdc 100644 --- a/fboss/oss/sai_hw_unsupported_tests/sai_hw_unsupported_tests.materialized_JSON +++ b/fboss/oss/sai_hw_unsupported_tests/sai_hw_unsupported_tests.materialized_JSON @@ -261,6 +261,21 @@ { "test_name_regex": "roundtrip.trunk_2_preprod_2_trunk.*HwTest_PROFILE_400G_8_PAM4_RS544X2N_COPPER" }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*SaiQPHRollbackTest.rollback" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostTest/[0134].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostRouteTest/[01].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostL2Test.*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentAclPriorityTest/[0].*" + }, { "test_name_regex": "HwAqmTest.verifyPerQueueEcnMarkedStats$" }, @@ -312,9 +327,6 @@ { "test_name_regex": "HwPacketSendTest.PortTxEnableTest" }, - { - "test_name_regex": "HwPfcTest.*" - }, { "test_name_regex": "HwVerifyPfcConfigInHwTest.*" }, @@ -386,6 +398,21 @@ { "test_name_regex": "roundtrip.trunk_2_preprod_2_trunk.*HwTest_PROFILE_400G_8_PAM4_RS544X2N_COPPER" }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*SaiQPHRollbackTest.rollback" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostTest/[0134].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostRouteTest/[01].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostL2Test.*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentAclPriorityTest/[0].*" + }, { "test_name_regex": "HwAqmTest.verifyPerQueueEcnMarkedStats$" }, @@ -437,9 +464,6 @@ { "test_name_regex": "HwPacketSendTest.PortTxEnableTest" }, - { - "test_name_regex": "HwPfcTest.*" - }, { "test_name_regex": "HwVerifyPfcConfigInHwTest.*" }, @@ -511,6 +535,21 @@ { "test_name_regex": "roundtrip.trunk_2_preprod_2_trunk.*HwTest_PROFILE_400G_8_PAM4_RS544X2N_COPPER" }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*SaiQPHRollbackTest.rollback" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostTest/[0134].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostRouteTest/[01].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostL2Test.*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentAclPriorityTest/[0].*" + }, { "test_name_regex": "HwAqmTest.verifyPerQueueEcnMarkedStats$" }, @@ -564,6 +603,21 @@ { "test_name_regex": "roundtrip.trunk_2_preprod_2_trunk.*HwTest_PROFILE_400G_8_PAM4_RS544X2N_COPPER" }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*SaiQPHRollbackTest.rollback" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostTest/[0134].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostRouteTest/[01].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostL2Test.*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentAclPriorityTest/[0].*" + }, { "test_name_regex": "HwAqmTest.verifyPerQueueEcnMarkedStats$" }, @@ -602,6 +656,21 @@ { "test_name_regex": "roundtrip.trunk_2_preprod_2_trunk.*HwTest_PROFILE_400G_8_PAM4_RS544X2N_COPPER" }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*SaiQPHRollbackTest.rollback" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostTest/[0134].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostRouteTest/[01].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostL2Test.*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentAclPriorityTest/[0].*" + }, { "test_name_regex": "HwAqmTest.verifyPerQueueEcnMarkedStats$" }, @@ -640,6 +709,21 @@ { "test_name_regex": "roundtrip.trunk_2_preprod_2_trunk.*HwTest_PROFILE_400G_8_PAM4_RS544X2N_COPPER" }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*SaiQPHRollbackTest.rollback" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostTest/[0134].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostRouteTest/[01].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostL2Test.*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentAclPriorityTest/[0].*" + }, { "test_name_regex": "HwAqmTest.verifyPerQueueEcnMarkedStats$" }, @@ -1409,6 +1493,21 @@ { "test_name_regex": "roundtrip.trunk_2_preprod_2_trunk.*HwTest_PROFILE_400G_8_PAM4_RS544X2N_COPPER" }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*SaiQPHRollbackTest.rollback" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostTest/[0134].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostRouteTest/[01].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostL2Test.*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentAclPriorityTest/[0].*" + }, { "test_name_regex": "HwAqmTest.verifyPerQueueEcnMarkedStats$" }, @@ -1462,6 +1561,21 @@ { "test_name_regex": "roundtrip.trunk_2_preprod_2_trunk.*HwTest_PROFILE_400G_8_PAM4_RS544X2N_COPPER" }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*SaiQPHRollbackTest.rollback" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostTest/[0134].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostRouteTest/[01].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostL2Test.*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentAclPriorityTest/[0].*" + }, { "test_name_regex": "HwAqmTest.verifyPerQueueEcnMarkedStats$" }, @@ -1500,6 +1614,21 @@ { "test_name_regex": "roundtrip.trunk_2_preprod_2_trunk.*HwTest_PROFILE_400G_8_PAM4_RS544X2N_COPPER" }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*SaiQPHRollbackTest.rollback" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostTest/[0134].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostRouteTest/[01].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostL2Test.*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentAclPriorityTest/[0].*" + }, { "test_name_regex": "HwAqmTest.verifyPerQueueEcnMarkedStats$" }, @@ -1538,6 +1667,21 @@ { "test_name_regex": "roundtrip.trunk_2_preprod_2_trunk.*HwTest_PROFILE_400G_8_PAM4_RS544X2N_COPPER" }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*SaiQPHRollbackTest.rollback" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostTest/[0134].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostRouteTest/[01].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostL2Test.*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentAclPriorityTest/[0].*" + }, { "test_name_regex": "HwAqmTest.verifyPerQueueEcnMarkedStats$" }, @@ -1591,6 +1735,21 @@ { "test_name_regex": "roundtrip.trunk_2_preprod_2_trunk.*HwTest_PROFILE_400G_8_PAM4_RS544X2N_COPPER" }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*SaiQPHRollbackTest.rollback" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostTest/[0134].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostRouteTest/[01].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostL2Test.*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentAclPriorityTest/[0].*" + }, { "test_name_regex": "HwAqmTest.verifyPerQueueEcnMarkedStats$" }, @@ -1629,6 +1788,21 @@ { "test_name_regex": "roundtrip.trunk_2_preprod_2_trunk.*HwTest_PROFILE_400G_8_PAM4_RS544X2N_COPPER" }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*SaiQPHRollbackTest.rollback" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostTest/[0134].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostRouteTest/[01].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostL2Test.*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentAclPriorityTest/[0].*" + }, { "test_name_regex": "HwAqmTest.verifyPerQueueEcnMarkedStats$" }, @@ -1667,6 +1841,21 @@ { "test_name_regex": "roundtrip.trunk_2_preprod_2_trunk.*HwTest_PROFILE_400G_8_PAM4_RS544X2N_COPPER" }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*SaiQPHRollbackTest.rollback" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostTest/[0134].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostRouteTest/[01].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostL2Test.*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentAclPriorityTest/[0].*" + }, { "test_name_regex": "HwAqmTest.verifyPerQueueEcnMarkedStats$" }, @@ -1718,9 +1907,6 @@ { "test_name_regex": "HwPacketSendTest.PortTxEnableTest" }, - { - "test_name_regex": "HwPfcTest.*" - }, { "test_name_regex": "HwVerifyPfcConfigInHwTest.*" }, @@ -1792,6 +1978,21 @@ { "test_name_regex": "roundtrip.trunk_2_preprod_2_trunk.*HwTest_PROFILE_400G_8_PAM4_RS544X2N_COPPER" }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*SaiQPHRollbackTest.rollback" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostTest/[0134].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostRouteTest/[01].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostL2Test.*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentAclPriorityTest/[0].*" + }, { "test_name_regex": "HwAqmTest.verifyPerQueueEcnMarkedStats$" }, @@ -1845,6 +2046,21 @@ { "test_name_regex": "roundtrip.trunk_2_preprod_2_trunk.*HwTest_PROFILE_400G_8_PAM4_RS544X2N_COPPER" }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*SaiQPHRollbackTest.rollback" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostTest/[0134].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostRouteTest/[01].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostL2Test.*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentAclPriorityTest/[0].*" + }, { "test_name_regex": "HwAqmTest.verifyPerQueueEcnMarkedStats$" }, @@ -1883,6 +2099,21 @@ { "test_name_regex": "roundtrip.trunk_2_preprod_2_trunk.*HwTest_PROFILE_400G_8_PAM4_RS544X2N_COPPER" }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*SaiQPHRollbackTest.rollback" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostTest/[0134].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostRouteTest/[01].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostL2Test.*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentAclPriorityTest/[0].*" + }, { "test_name_regex": "HwAqmTest.verifyPerQueueEcnMarkedStats$" }, @@ -2004,6 +2235,21 @@ { "test_name_regex": "roundtrip.trunk_2_preprod_2_trunk.*HwTest_PROFILE_400G_8_PAM4_RS544X2N_COPPER" }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*SaiQPHRollbackTest.rollback" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostTest/[0134].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostRouteTest/[01].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostL2Test.*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentAclPriorityTest/[0].*" + }, { "test_name_regex": "HwAclCounterTest/[01].*$" }, @@ -2042,6 +2288,21 @@ { "test_name_regex": "roundtrip.trunk_2_preprod_2_trunk.*HwTest_PROFILE_400G_8_PAM4_RS544X2N_COPPER" }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*SaiQPHRollbackTest.rollback" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostTest/[0134].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostRouteTest/[01].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostL2Test.*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentAclPriorityTest/[0].*" + }, { "test_name_regex": "HwAclCounterTest/[01].*$" }, @@ -2080,6 +2341,21 @@ { "test_name_regex": "roundtrip.trunk_2_preprod_2_trunk.*HwTest_PROFILE_400G_8_PAM4_RS544X2N_COPPER" }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*SaiQPHRollbackTest.rollback" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostTest/[0134].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostRouteTest/[01].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostL2Test.*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentAclPriorityTest/[0].*" + }, { "test_name_regex": "HwAclCounterTest/[01].*$" }, @@ -2118,6 +2394,21 @@ { "test_name_regex": "roundtrip.trunk_2_preprod_2_trunk.*HwTest_PROFILE_400G_8_PAM4_RS544X2N_COPPER" }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*SaiQPHRollbackTest.rollback" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostTest/[0134].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostRouteTest/[01].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostL2Test.*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentAclPriorityTest/[0].*" + }, { "test_name_regex": "HwAclCounterTest/[01].*$" }, @@ -2156,6 +2447,21 @@ { "test_name_regex": "roundtrip.trunk_2_preprod_2_trunk.*HwTest_PROFILE_400G_8_PAM4_RS544X2N_COPPER" }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*SaiQPHRollbackTest.rollback" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostTest/[0134].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostRouteTest/[01].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostL2Test.*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentAclPriorityTest/[0].*" + }, { "test_name_regex": "HwAclCounterTest/[01].*$" }, @@ -2194,6 +2500,21 @@ { "test_name_regex": "roundtrip.trunk_2_preprod_2_trunk.*HwTest_PROFILE_400G_8_PAM4_RS544X2N_COPPER" }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*SaiQPHRollbackTest.rollback" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostTest/[0134].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostRouteTest/[01].*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentQueuePerHostL2Test.*" + }, + { + "test_name_regex": "roundtrip.preprod_2_trunk_2_preprod.*AgentAclPriorityTest/[0].*" + }, { "test_name_regex": "HwAclCounterTest/[01].*$" }, diff --git a/fboss/oss/stable_commits/github_hashes_09102024_085602.tar.gz b/fboss/oss/stable_commits/github_hashes_09102024_085602.tar.gz new file mode 100644 index 0000000000000..187e1105c341a Binary files /dev/null and b/fboss/oss/stable_commits/github_hashes_09102024_085602.tar.gz differ diff --git a/fboss/oss/stable_commits/latest_stable_hashes.tar.gz b/fboss/oss/stable_commits/latest_stable_hashes.tar.gz index c45079de9b6c2..e9d686058287d 120000 --- a/fboss/oss/stable_commits/latest_stable_hashes.tar.gz +++ b/fboss/oss/stable_commits/latest_stable_hashes.tar.gz @@ -1 +1 @@ -github_hashes_08152024_125517.tar.gz \ No newline at end of file +github_hashes_09102024_085602.tar.gz \ No newline at end of file diff --git a/fboss/platform/config_lib/BUCK b/fboss/platform/config_lib/BUCK index 23a3f28f187e7..1b1ef130e7fde 100644 --- a/fboss/platform/config_lib/BUCK +++ b/fboss/platform/config_lib/BUCK @@ -12,6 +12,7 @@ cpp_binary( ], deps = [ "//fboss/platform/data_corral_service/if:led_manager-cpp2-types", + "//fboss/platform/fan_service:utils", "//fboss/platform/fan_service/if:fan_service-cpp2-types", "//fboss/platform/fbdevd/if:fbdevd-cpp2-types", "//fboss/platform/fw_util/if:fw_util_config-cpp2-types", diff --git a/fboss/platform/configs/janga800bic/weutil.json b/fboss/platform/configs/janga800bic/weutil.json index 6ae52c9cc54f0..6b9168fbcc106 100644 --- a/fboss/platform/configs/janga800bic/weutil.json +++ b/fboss/platform/configs/janga800bic/weutil.json @@ -9,6 +9,9 @@ }, "RUNBMC" : { "path" : "/run/devmap/eeproms/RUNBMC_EEPROM" + }, + "COME_FRU" : { + "path" : "/run/devmap/eeproms/COME_FRU" } } } diff --git a/fboss/platform/configs/meru800bfa/led_manager.json b/fboss/platform/configs/meru800bfa/led_manager.json index 43c05ad1f8ee9..06aaedc3b5319 100644 --- a/fboss/platform/configs/meru800bfa/led_manager.json +++ b/fboss/platform/configs/meru800bfa/led_manager.json @@ -1,5 +1,104 @@ { - "systemLedConfig": {}, - "fruTypeLedConfigs": {}, - "fruConfigs": [] -} + "systemLedConfig": { + "presentLedColor": 1, + "presentLedSysfsPath": "/sys/class/leds/sys_led:green:status/brightness", + "absentLedColor": 2, + "absentLedSysfsPath": "/sys/class/leds/sys_led:red:status/brightness" + }, + "fruTypeLedConfigs": { + "FAN": { + "presentLedColor": 1, + "presentLedSysfsPath": "/sys/class/leds/fan_led:green:status/brightness", + "absentLedColor": 2, + "absentLedSysfsPath": "/sys/class/leds/fan_led:red:status/brightness" + }, + "PSU": { + "presentLedColor": 1, + "presentLedSysfsPath": "/sys/class/leds/psu_led:green:status/brightness", + "absentLedColor": 2, + "absentLedSysfsPath": "/sys/class/leds/psu_led:red:status/brightness" + } + }, + "fruConfigs": [ + { + "fruName": "FAN1", + "fruType": "FAN", + "presenceSysfsPath": "/run/devmap/sensors/FAN_CPLD0/fan1_present" + }, + { + "fruName": "FAN2", + "fruType": "FAN", + "presenceSysfsPath": "/run/devmap/sensors/FAN_CPLD0/fan2_present" + }, + { + "fruName": "FAN3", + "fruType": "FAN", + "presenceSysfsPath": "/run/devmap/sensors/FAN_CPLD0/fan3_present" + }, + { + "fruName": "FAN4", + "fruType": "FAN", + "presenceSysfsPath": "/run/devmap/sensors/FAN_CPLD0/fan4_present" + }, + { + "fruName": "FAN5", + "fruType": "FAN", + "presenceSysfsPath": "/run/devmap/sensors/FAN_CPLD1/fan1_present" + }, + { + "fruName": "FAN6", + "fruType": "FAN", + "presenceSysfsPath": "/run/devmap/sensors/FAN_CPLD1/fan2_present" + }, + { + "fruName": "FAN7", + "fruType": "FAN", + "presenceSysfsPath": "/run/devmap/sensors/FAN_CPLD1/fan3_present" + }, + { + "fruName": "FAN8", + "fruType": "FAN", + "presenceSysfsPath": "/run/devmap/sensors/FAN_CPLD1/fan4_present" + }, + { + "fruName": "FAN9", + "fruType": "FAN", + "presenceSysfsPath": "/run/devmap/sensors/FAN_CPLD2/fan1_present" + }, + { + "fruName": "FAN10", + "fruType": "FAN", + "presenceSysfsPath": "/run/devmap/sensors/FAN_CPLD2/fan2_present" + }, + { + "fruName": "FAN11", + "fruType": "FAN", + "presenceSysfsPath": "/run/devmap/sensors/FAN_CPLD2/fan3_present" + }, + { + "fruName": "FAN12", + "fruType": "FAN", + "presenceSysfsPath": "/run/devmap/sensors/FAN_CPLD2/fan4_present" + }, + { + "fruName": "PSU1", + "fruType": "PSU", + "presenceSysfsPath": "/run/devmap/fpgas/MERU800BFA_SMB_FPGA0/psu1_prsnt" + }, + { + "fruName": "PSU2", + "fruType": "PSU", + "presenceSysfsPath": "/run/devmap/fpgas/MERU800BFA_SMB_FPGA0/psu2_prsnt" + }, + { + "fruName": "PSU3", + "fruType": "PSU", + "presenceSysfsPath": "/run/devmap/fpgas/MERU800BFA_SMB_FPGA0/psu3_prsnt" + }, + { + "fruName": "PSU4", + "fruType": "PSU", + "presenceSysfsPath": "/run/devmap/fpgas/MERU800BFA_SMB_FPGA0/psu4_prsnt" + } + ] +} \ No newline at end of file diff --git a/fboss/platform/configs/meru800bfa/platform_manager.json b/fboss/platform/configs/meru800bfa/platform_manager.json index d42fd50e7740c..4e629bb40cde6 100644 --- a/fboss/platform/configs/meru800bfa/platform_manager.json +++ b/fboss/platform/configs/meru800bfa/platform_manager.json @@ -4441,7 +4441,7 @@ "/run/devmap/xcvrs/xcvr_128": "/SMB_SLOT@0/[OSFP_PORT128_XCVR]" }, "bspKmodsRpmName": "arista_bsp_kmods", - "bspKmodsRpmVersion": "0.7.3-1", + "bspKmodsRpmVersion": "0.7.4-1", "bspKmodsToReload": [ "scd-xcvr", "scd-spi", diff --git a/fboss/platform/configs/meru800bfa/sensor_service.json b/fboss/platform/configs/meru800bfa/sensor_service.json index 4a6df40885f40..0219be37db391 100644 --- a/fboss/platform/configs/meru800bfa/sensor_service.json +++ b/fboss/platform/configs/meru800bfa/sensor_service.json @@ -956,12 +956,12 @@ "PSU1_PIN": { "path": "/run/devmap/sensors/PSU1_PMBUS/power1_input", "compute": "@/1000000.0", - "type": 4 + "type": 0 }, "PSU1_POUT": { "path": "/run/devmap/sensors/PSU1_PMBUS/power2_input", "compute": "@/1000000.0", - "type": 4 + "type": 0 } }, "PSU2": { diff --git a/fboss/platform/configs/meru800bia/led_manager.json b/fboss/platform/configs/meru800bia/led_manager.json index 43c05ad1f8ee9..d48510147511f 100644 --- a/fboss/platform/configs/meru800bia/led_manager.json +++ b/fboss/platform/configs/meru800bia/led_manager.json @@ -1,5 +1,54 @@ { - "systemLedConfig": {}, - "fruTypeLedConfigs": {}, - "fruConfigs": [] -} + "systemLedConfig": { + "presentLedColor": 1, + "presentLedSysfsPath": "/sys/class/leds/sys_led:green:status/brightness", + "absentLedColor": 2, + "absentLedSysfsPath": "/sys/class/leds/sys_led:red:status/brightness" + }, + "fruTypeLedConfigs": { + "FAN": { + "presentLedColor": 1, + "presentLedSysfsPath": "/sys/class/leds/fan_led:green:status/brightness", + "absentLedColor": 2, + "absentLedSysfsPath": "/sys/class/leds/fan_led:red:status/brightness" + }, + "PSU": { + "presentLedColor": 1, + "presentLedSysfsPath": "/sys/class/leds/psu_led:green:status/brightness", + "absentLedColor": 2, + "absentLedSysfsPath": "/sys/class/leds/psu_led:red:status/brightness" + } + }, + "fruConfigs": [ + { + "fruName": "FAN1", + "fruType": "FAN", + "presenceSysfsPath": "/run/devmap/sensors/FAN_CPLD/fan1_present" + }, + { + "fruName": "FAN2", + "fruType": "FAN", + "presenceSysfsPath": "/run/devmap/sensors/FAN_CPLD/fan2_present" + }, + { + "fruName": "FAN3", + "fruType": "FAN", + "presenceSysfsPath": "/run/devmap/sensors/FAN_CPLD/fan3_present" + }, + { + "fruName": "FAN4", + "fruType": "FAN", + "presenceSysfsPath": "/run/devmap/sensors/FAN_CPLD/fan4_present" + }, + { + "fruName": "PSU1", + "fruType": "PSU", + "presenceSysfsPath": "/run/devmap/fpgas/MERU800BIA_SMB_FPGA/psu1_present" + }, + { + "fruName": "PSU2", + "fruType": "PSU", + "presenceSysfsPath": "/run/devmap/fpgas/MERU800BIA_SMB_FPGA/psu2_present" + } + ] +} \ No newline at end of file diff --git a/fboss/platform/configs/meru800bia/platform_manager.json b/fboss/platform/configs/meru800bia/platform_manager.json index 92dacbcca666f..cc111e265bbea 100644 --- a/fboss/platform/configs/meru800bia/platform_manager.json +++ b/fboss/platform/configs/meru800bia/platform_manager.json @@ -1546,7 +1546,7 @@ "/run/devmap/flashes/SMB_SPI_MASTER0_DEVICE1": "/SMB_SLOT@0/[SMB_SPI_MASTER0_DEVICE1]" }, "bspKmodsRpmName": "arista_bsp_kmods", - "bspKmodsRpmVersion": "0.7.3-1", + "bspKmodsRpmVersion": "0.7.4-1", "bspKmodsToReload": [ "scd-xcvr", "scd-spi", diff --git a/fboss/platform/configs/montblanc/fan_service.json b/fboss/platform/configs/montblanc/fan_service.json index 99a83a4eb94f0..a64e00952d931 100644 --- a/fboss/platform/configs/montblanc/fan_service.json +++ b/fboss/platform/configs/montblanc/fan_service.json @@ -6,6 +6,13 @@ "pwmTransitionValue": 50, "pwmLowerThreshold": 30, "pwmUpperThreshold": 70, + "watchdog": { + "access": { + "accessType": "ACCESS_TYPE_SYSFS", + "path": "/run/devmap/watchdogs/FAN_WATCHDOG" + }, + "value": 0 + }, "controlInterval": { "sensorReadInterval": 5, "pwmUpdateInterval": 5 @@ -82,25 +89,29 @@ "24": 30, "27": 30, "32": 35, - "37": 40 + "37": 40, + "42": 60 }, "normalDownTable": { "22": 30, "25": 30, "30": 35, - "35": 40 + "35": 40, + "40": 60 }, "failUpTable": { "24": 35, "27": 35, "32": 40, - "37": 45 + "37": 45, + "42": 65 }, "failDownTable": { "22": 35, "25": 35, "30": 40, - "35": 45 + "35": 45, + "40": 65 } }, { diff --git a/fboss/platform/configs/tahan800bc/weutil.json b/fboss/platform/configs/tahan800bc/weutil.json index 93f56afaf0d1f..5da2eede21245 100644 --- a/fboss/platform/configs/tahan800bc/weutil.json +++ b/fboss/platform/configs/tahan800bc/weutil.json @@ -2,14 +2,16 @@ "chassisEepromName" : "SMB" , "fruEepromList" : { "SMB" : { - "path" : "/run/devmap/eeproms/SMB_EEPROM", - "offset" : 0, - "idEepromFormatVer" : 4 + "path" : "/run/devmap/eeproms/SMB_EEPROM" }, "COME" : { - "path" : "/run/devmap/eeproms/COME_EEPROM", - "offset" : 0, - "idEepromFormatVer" : 4 + "path" : "/run/devmap/eeproms/COME_EEPROM" + }, + "COME_FRU" : { + "path" : "/run/devmap/eeproms/COME_FRU" + }, + "RUNBMC" : { + "path" : "/run/devmap/eeproms/RUNBMC_EEPROM" } } } diff --git a/fboss/platform/data_corral_service/hw_test/DataCorralServiceHwTest.cpp b/fboss/platform/data_corral_service/hw_test/DataCorralServiceHwTest.cpp index 1751fff22a362..3f15fcff30c80 100644 --- a/fboss/platform/data_corral_service/hw_test/DataCorralServiceHwTest.cpp +++ b/fboss/platform/data_corral_service/hw_test/DataCorralServiceHwTest.cpp @@ -25,14 +25,40 @@ using namespace facebook::fboss::platform; using namespace facebook::fboss::platform::data_corral_service; -namespace { +// When running OSS, users must supply config_file unlike in fb environment. +// getUncachedFruid test, DataCorral talks to WeUtil to parse eeprom +// content. Sincne config_file flag only store a single file, WeUtil will +// end up deserializing led_manger.json... +// To avoid this different user expectations, we could: +// 1) Figure out how to avoid passing config files in OSS. +// 2) See whether this can be avoided when we merge DataCorral into PM. +DEFINE_string( + led_manager_config_file, + "", + "[OSS-Only] Path to led_manager.json file used for DataCorral service configuration during HwTest."); +DEFINE_string( + weutil_config_file, + "", + "[OSS-Only] Path to weutil.json file used for weutil configuration during HWTest. " + "This will overwrite FLAGS_config_file when weutil initializes the config."); + class DataCorralServiceHwTest : public ::testing::Test { public: void SetUp() override { thriftHandler_ = std::make_shared(); + std::string jsonLedManagerConfig; + if (FLAGS_led_manager_config_file.empty()) { + jsonLedManagerConfig = ConfigLib().getLedManagerConfig(); + } else { + folly::readFile( + FLAGS_led_manager_config_file.c_str(), jsonLedManagerConfig); + } + if (!FLAGS_weutil_config_file.empty()) { + FLAGS_config_file = FLAGS_weutil_config_file; + } apache::thrift::SimpleJSONSerializer::deserialize( - ConfigLib().getLedManagerConfig(), ledManagerConfig_); + jsonLedManagerConfig, ledManagerConfig_); auto ledManager = std::make_shared( *ledManagerConfig_.systemLedConfig(), @@ -55,7 +81,6 @@ class DataCorralServiceHwTest : public ::testing::Test { std::shared_ptr thriftHandler_; LedManagerConfig ledManagerConfig_; }; -} // namespace TEST_F(DataCorralServiceHwTest, FruLedProgrammingSysfsCheck) { fruPresenceExplorer_->detectFruPresence(); @@ -123,6 +148,21 @@ int main(int argc, char* argv[]) { // Parse command line flags testing::InitGoogleTest(&argc, argv); facebook::fboss::platform::helpers::init(&argc, &argv); + if (!FLAGS_config_file.empty()) { + XLOG(ERR) + << "Please use --led_manager_config_file and --weutil_config_file instead of --config_file. " + << "For more info on the flags, run with --helpon=DataCorralServiceHwTest"; + return -1; + } +#ifdef IS_OSS + if (FLAGS_led_manager_config_file.empty() || + FLAGS_weutil_config_file.empty()) { + XLOG(ERR) + << "Please specify --led_manager_config_file and --weutil_config_file. " + << "For more info on the flags, run with --helpon=DataCorralServiceHwTest"; + return -1; + } +#endif // Run the tests return RUN_ALL_TESTS(); } diff --git a/fboss/platform/fan_service/BUCK b/fboss/platform/fan_service/BUCK index 19b068a00cca2..e836676810549 100644 --- a/fboss/platform/fan_service/BUCK +++ b/fboss/platform/fan_service/BUCK @@ -18,6 +18,7 @@ cpp_binary( "//fb303:logging", "//fboss/platform/config_lib:config_lib", "//fboss/platform/helpers:init", + "//fboss/platform/helpers:platform_name_lib", "//fboss/platform/sensor_service/if:sensor_service-cpp2-types", "//fboss/qsfp_service/lib:qsfp-service-client", "//folly/executors:function_scheduler", @@ -84,6 +85,7 @@ cpp_library( "//fboss/fsdb/if:fsdb_model", "//fboss/fsdb/if:fsdb_oper-cpp2-types", "//fboss/lib:common_file_utils", + "//fboss/lib:gpiod_line", "//fboss/platform/fan_service/if:fan_service-cpp2-services", "//fboss/platform/fan_service/if:fan_service-cpp2-types", "//fboss/platform/helpers:platform_utils", @@ -92,7 +94,7 @@ cpp_library( "//fboss/qsfp_service/if:state-cpp2-types", "//fboss/qsfp_service/if:stats-cpp2-types", "//fboss/qsfp_service/lib:qsfp-service-client", - "//folly/experimental/coro:blocking_wait", + "//folly/coro:blocking_wait", "//folly/futures:core", "//folly/io/async:async_base", "//folly/io/async:async_ssl_socket", @@ -103,6 +105,9 @@ cpp_library( "//security/ca/lib:cert_path_picker", "//thrift/lib/cpp2/protocol:protocol", ], + exported_external_deps = [ + ("libgpiod", None, "gpiod"), + ], ) custom_unittest( diff --git a/fboss/platform/fan_service/Bsp.h b/fboss/platform/fan_service/Bsp.h index 97edd48d0e085..c9794f495567e 100644 --- a/fboss/platform/fan_service/Bsp.h +++ b/fboss/platform/fan_service/Bsp.h @@ -11,7 +11,7 @@ #include #include -#include +#include #include #include diff --git a/fboss/platform/fan_service/ControlLogic.cpp b/fboss/platform/fan_service/ControlLogic.cpp index 351ada1a22eba..9a511615e546f 100644 --- a/fboss/platform/fan_service/ControlLogic.cpp +++ b/fboss/platform/fan_service/ControlLogic.cpp @@ -6,8 +6,10 @@ #include "fboss/platform/fan_service/ControlLogic.h" #include +#include #include "common/time/Time.h" +#include "fboss/lib/GpiodLine.h" #include "fboss/platform/fan_service/SensorData.h" #include "fboss/platform/fan_service/if/gen-cpp2/fan_service_config_constants.h" #include "fboss/platform/fan_service/if/gen-cpp2/fan_service_config_types.h" @@ -349,15 +351,35 @@ void ControlLogic::getOpticsUpdate() { bool ControlLogic::isFanPresentInDevice(const Fan& fan) { unsigned int readVal; bool readSuccessful = false; - try { - readVal = static_cast(pBsp_->readSysfs(*fan.presenceSysfsPath())); - readSuccessful = true; - } catch (std::exception&) { - XLOG(ERR) << "Failed to read sysfs " << *fan.presenceSysfsPath(); - } - auto fanPresent = (readSuccessful && readVal == *fan.fanPresentVal()); - if (!fanPresent) { - XLOG(INFO) << fmt::format("{}: is absent in the host", *fan.fanName()); + bool fanPresent = false; + if (fan.presenceSysfsPath()) { + try { + readVal = + static_cast(pBsp_->readSysfs(*fan.presenceSysfsPath())); + readSuccessful = true; + } catch (std::exception&) { + XLOG(ERR) << "Failed to read sysfs " << *fan.presenceSysfsPath(); + } + fanPresent = (readSuccessful && readVal == *fan.fanPresentVal()); + if (fanPresent) { + XLOG(INFO) << fmt::format( + "{}: is present in the host (through sysfs)", *fan.fanName()); + } else { + XLOG(INFO) << fmt::format( + "{}: is absent in the host (through sysfs)", *fan.fanName()); + } + } else if (fan.presenceGpio()) { + struct gpiod_chip* chip = + gpiod_chip_open(fan.presenceGpio()->path()->c_str()); + GpiodLine line(chip, *fan.presenceGpio()->lineIndex(), "gpioline"); + int16_t value = line.getValue(); + gpiod_chip_close(chip); + if (value == *fan.presenceGpio()->desiredValue()) { + fanPresent = true; + } else { + XLOG(INFO) << fmt::format( + "{}: is absent in the host (through gpio)", *fan.fanName()); + } } fb303::fbData->setCounter( fmt::format(kFanAbsent, *fan.fanName()), !fanPresent); @@ -568,6 +590,28 @@ void ControlLogic::updateControl(std::shared_ptr pS) { *fanStatuses[*fan.fanName()].lastSuccessfulAccessTime(); auto fanFailed = fanAccessFailed && (timeSinceLastSuccessfulAccess >= kFanFailThresholdInSec); + // If rpmMin or rpmMax is set, compare fanRpm with them to decide + // whether fan is failed + if (fan.rpmMin()) { + if (fanRpm < *fan.rpmMin()) { + fanFailed = true; + XLOG(ERR) << fmt::format( + "fan {} : rpm {} is below the minimum value {}", + *fan.fanName(), + fanRpm, + *fan.rpmMin()); + } + } + if (fan.rpmMax()) { + if (fanRpm > *fan.rpmMax()) { + fanFailed = true; + XLOG(ERR) << fmt::format( + "fan {} : rpm {} is above the maximum value {}", + *fan.fanName(), + fanRpm, + *fan.rpmMax()); + } + } if (fanFailed) { numFanFailed_++; } diff --git a/fboss/platform/fan_service/Main.cpp b/fboss/platform/fan_service/Main.cpp index 5fe807ccd12d3..6af4641060c15 100644 --- a/fboss/platform/fan_service/Main.cpp +++ b/fboss/platform/fan_service/Main.cpp @@ -17,6 +17,7 @@ #include "fboss/platform/fan_service/FanServiceHandler.h" #include "fboss/platform/fan_service/Utils.h" #include "fboss/platform/helpers/Init.h" +#include "fboss/platform/helpers/PlatformNameLib.h" using namespace facebook; using namespace facebook::fboss::platform; @@ -32,7 +33,9 @@ int main(int argc, char** argv) { fb303::registerFollyLoggingOptionHandlers(); helpers::init(&argc, &argv); - std::string fanServiceConfJson = ConfigLib().getFanServiceConfig(); + auto platformName = helpers::PlatformNameLib().getPlatformName(); + std::string fanServiceConfJson = + ConfigLib().getFanServiceConfig(platformName); auto config = apache::thrift::SimpleJSONSerializer::deserialize( fanServiceConfJson); diff --git a/fboss/platform/fan_service/PidLogic.cpp b/fboss/platform/fan_service/PidLogic.cpp index 0bb180fcc8d7a..fb797a72688ce 100644 --- a/fboss/platform/fan_service/PidLogic.cpp +++ b/fboss/platform/fan_service/PidLogic.cpp @@ -23,17 +23,18 @@ int16_t PidLogic::calculatePwm(float measurement) { auto derivative = (*error - lastError_) / dT_; newPwm = (*pidSetting_.kp() * error.value()) + (*pidSetting_.ki() * integral_) + (*pidSetting_.kd() * derivative); - if (newPwm < 0) { - newPwm = 0; - } - lastPwm_ = newPwm; - lastError_ = error.value(); } else { newPwm = lastPwm_; } if (measurement <= maxVal) { - integral_ = lastPwm_ / *pidSetting_.ki(); + integral_ = newPwm / *pidSetting_.ki(); + } + + if (newPwm < 0) { + newPwm = 0; + } else if (newPwm > 100) { + newPwm = 100; } XLOG(DBG1) << fmt::format( @@ -43,6 +44,9 @@ int16_t PidLogic::calculatePwm(float measurement) { lastPwm_, newPwm); + lastPwm_ = newPwm; + lastError_ = error.value_or(0); + return newPwm; } diff --git a/fboss/platform/fan_service/Utils.cpp b/fboss/platform/fan_service/Utils.cpp index a7a6d0e03be33..e499752a6dd66 100644 --- a/fboss/platform/fan_service/Utils.cpp +++ b/fboss/platform/fan_service/Utils.cpp @@ -86,16 +86,16 @@ bool Utils::isValidConfig(const FanServiceConfig& config) { XLOG(ERR) << "pwmSysfsPath cannot be empty"; return false; } - if (fan.presenceSysfsPath()->empty()) { - XLOG(ERR) << "presenceSysfsPath cannot be empty"; - return false; - } if (fan.ledSysfsPath()->empty()) { XLOG(ERR) << "ledSysfsPath cannot be empty"; return false; } - if ((!fan.presenceSysfsPath()) && (!fan.presenceGpio())) { - XLOG(ERR) << "either presenceSysfsPath or presenceGpio must be set"; + if (fan.presenceSysfsPath() && fan.presenceGpio()) { + XLOG(ERR) << "Both presenceSysfsPath and presenceGpio cannot be set"; + return false; + } + if (!fan.presenceSysfsPath() && !fan.presenceGpio()) { + XLOG(ERR) << "Either presenceSysfsPath or presenceGpio must be set"; return false; } } diff --git a/fboss/platform/fan_service/if/fan_service_config.thrift b/fboss/platform/fan_service/if/fan_service_config.thrift index 628488526acbd..9dcf940c971a6 100644 --- a/fboss/platform/fan_service/if/fan_service_config.thrift +++ b/fboss/platform/fan_service/if/fan_service_config.thrift @@ -79,6 +79,8 @@ struct Fan { 10: i32 fanGoodLedVal; 11: i32 fanFailLedVal; 12: optional Gpio presenceGpio; + 13: optional i32 rpmMin; + 14: optional i32 rpmMax; } struct Watchdog { diff --git a/fboss/platform/fw_util/BUCK b/fboss/platform/fw_util/BUCK index fae1cd0073bff..9c22c8b6924ea 100644 --- a/fboss/platform/fw_util/BUCK +++ b/fboss/platform/fw_util/BUCK @@ -17,6 +17,7 @@ cpp_binary( "//fboss/platform/config_lib:config_lib", "//fboss/platform/fw_util/if:fw_util_config-cpp2-types", "//fboss/platform/helpers:init_cli", + "//fboss/platform/helpers:platform_name_lib", "//fboss/platform/helpers:platform_utils", "//folly:string", "//folly:subprocess", diff --git a/fboss/platform/fw_util/FwUtilImpl.cpp b/fboss/platform/fw_util/FwUtilImpl.cpp index 64ee12a16eae0..5bda304bf9ae5 100644 --- a/fboss/platform/fw_util/FwUtilImpl.cpp +++ b/fboss/platform/fw_util/FwUtilImpl.cpp @@ -19,13 +19,15 @@ #include "fboss/platform/config_lib/ConfigLib.h" #include "fboss/platform/fw_util/Flags.h" #include "fboss/platform/fw_util/FwUtilImpl.h" +#include "fboss/platform/helpers/PlatformNameLib.h" #include "fboss/platform/helpers/PlatformUtils.h" using namespace folly::literals::shell_literals; namespace facebook::fboss::platform::fw_util { void FwUtilImpl::init() { - std::string fwUtilConfJson = ConfigLib().getFwUtilConfig(); + auto platformName = helpers::PlatformNameLib().getPlatformName(); + std::string fwUtilConfJson = ConfigLib().getFwUtilConfig(platformName); apache::thrift::SimpleJSONSerializer::deserialize( fwUtilConfJson, fwUtilConfig_); diff --git a/fboss/platform/helpers/BUCK b/fboss/platform/helpers/BUCK index 37e7b5cb1f6a8..22a339519d788 100644 --- a/fboss/platform/helpers/BUCK +++ b/fboss/platform/helpers/BUCK @@ -8,6 +8,7 @@ cpp_library( "PlatformNameLib.cpp", ], exported_deps = [ + ":platform_fs_utils", ":platform_utils", "//fb303:service_data", "//folly:string", diff --git a/fboss/platform/helpers/MockPlatformFsUtils.h b/fboss/platform/helpers/MockPlatformFsUtils.h index 76abd11243f44..c5069d89bf003 100644 --- a/fboss/platform/helpers/MockPlatformFsUtils.h +++ b/fboss/platform/helpers/MockPlatformFsUtils.h @@ -11,6 +11,16 @@ namespace facebook::fboss::platform { class MockPlatformFsUtils : public PlatformFsUtils { public: + MOCK_METHOD( + (bool), + createDirectories, + (const std::filesystem::path&), + (const)); + MOCK_METHOD( + (bool), + writeStringToFile, + (const std::string&, const std::filesystem::path&, bool, int), + (const)); MOCK_METHOD( (std::optional), getStringFileContent, diff --git a/fboss/platform/helpers/PlatformFsUtils.cpp b/fboss/platform/helpers/PlatformFsUtils.cpp index d87e22a71a97d..50ec5780688ef 100644 --- a/fboss/platform/helpers/PlatformFsUtils.cpp +++ b/fboss/platform/helpers/PlatformFsUtils.cpp @@ -28,6 +28,27 @@ fs::path concat(const fs::path& p1, const fs::path& p2) { return result.lexically_normal(); } +// Open, fsync, and close. Returns 0 on success, errno on failure. Uses folly +// for retry on EINTR. +int sync(const fs::path& path) { + // Use same flags as folly::readFile + int fd = folly::openNoInt(path.c_str(), O_RDONLY | O_CLOEXEC); + if (fd == -1) { + return errno; + } + int rc = folly::fsyncNoInt(fd); + if (rc == -1) { + folly::closeNoInt(fd); + return errno; + } + rc = folly::closeNoInt(fd); + fd = -1; + if (rc == -1) { + return errno; + } + return 0; +} + } // namespace namespace facebook::fboss::platform { @@ -45,9 +66,10 @@ bool PlatformFsUtils::createDirectories(const fs::path& path) const { fs::create_directories(concat(rootDir_, path), errCode); if (errCode.value() != 0) { XLOG(ERR) << fmt::format( - "Received error code {} from creating path {}", + "Received error code {} from creating path {}: {}", errCode.value(), - path.string()); + path.string(), + errCode.message()); } return errCode.value() == 0; } @@ -63,17 +85,51 @@ fs::directory_iterator PlatformFsUtils::ls(const fs::path& path) const { bool PlatformFsUtils::writeStringToFile( const std::string& content, const fs::path& path, + bool atomic, int flags) const { + const fs::path& prefixedPath = concat(rootDir_, path); if (!createDirectories(path.parent_path())) { return false; } - return folly::writeFile(content, concat(rootDir_, path).c_str(), flags); + int errorCode = 0; + if (atomic) { + auto options = folly::WriteFileAtomicOptions(); + options.setSyncType(folly::SyncType::WITH_SYNC); + errorCode = folly::writeFileAtomicNoThrow( + folly::StringPiece(prefixedPath.c_str()), content, options); + // On successful write, fsync the directory to ensure durable write, which + // writeFileAtomic explicitly does not guarantee. + if (errorCode == 0) { + errorCode = sync(prefixedPath.parent_path()); + } + } else { + bool written = folly::writeFile(content, prefixedPath.c_str(), flags); + // errno will be set to 2 when the file did not exist but was successfully + // created & written. Only set errCode on failed writes. + if (!written) { + errorCode = errno; + } + } + if (errorCode != 0) { + XLOG(ERR) << fmt::format( + "Received error code {} from writing to path {}: {}", + errorCode, + path.string(), + folly::errnoStr(errorCode)); + } + return errorCode == 0; } std::optional PlatformFsUtils::getStringFileContent( const fs::path& path) const { std::string value{}; if (!folly::readFile(concat(rootDir_, path).c_str(), value)) { + int errorCode = errno; + XLOG(ERR) << fmt::format( + "Received error code {} from reading from path {}: {}", + errorCode, + path.string(), + folly::errnoStr(errorCode)); return std::nullopt; } return folly::trimWhitespace(value).str(); diff --git a/fboss/platform/helpers/PlatformFsUtils.h b/fboss/platform/helpers/PlatformFsUtils.h index 6436220ed2237..dca302bbeb7da 100644 --- a/fboss/platform/helpers/PlatformFsUtils.h +++ b/fboss/platform/helpers/PlatformFsUtils.h @@ -31,19 +31,27 @@ class PlatformFsUtils { // - for given /x/y/z, directory y/z if x already exists. // No-op if parent directories already exist. // Returns true if created or already exist, otherwise false. - bool createDirectories(const std::filesystem::path& path) const; + virtual bool createDirectories(const std::filesystem::path& path) const; bool exists(const std::filesystem::path& path) const; std::filesystem::directory_iterator ls( const std::filesystem::path& path) const; - // Write string to file. Returns true if successful, otherwise false. File and - // directories will be created (recursively) if they don't exist. By default, - // if file already exists, it will be overwritten. + // Write string to file. Returns true if successful. File and directories will + // be created (recursively) if they don't exist. By default, if file already + // exists, it will be overwritten. + // + // If atomic is true, the file will be written atomically, i.e. there will + // never be partial writes. On returning true, the file write is guaranteed + // durable - up to whatever guarantees the filesystem provides for fsync + + // close. + // + // Note: `flags` are ignored when atomic = true. virtual bool writeStringToFile( const std::string& content, const std::filesystem::path& path, + bool atomic = false, int flags = O_WRONLY | O_CREAT | O_TRUNC) const; virtual std::optional getStringFileContent( diff --git a/fboss/platform/helpers/PlatformNameLib.cpp b/fboss/platform/helpers/PlatformNameLib.cpp index 8369e19233c16..2b559909a8034 100644 --- a/fboss/platform/helpers/PlatformNameLib.cpp +++ b/fboss/platform/helpers/PlatformNameLib.cpp @@ -2,6 +2,8 @@ #include "fboss/platform/helpers/PlatformNameLib.h" +#include + #include #include #include @@ -39,23 +41,38 @@ std::string sanitizePlatformName(const std::string& platformNameFromBios) { namespace facebook::fboss::platform::helpers { -std::string PlatformNameLib::getPlatformNameFromBios( - const PlatformUtils& platformUtils) const { +PlatformNameLib::PlatformNameLib( + const std::shared_ptr platformUtils, + const std::shared_ptr platformFsUtils) + : platformUtils_(platformUtils), platformFsUtils_(platformFsUtils) {} + +std::string PlatformNameLib::getPlatformNameFromBios(bool writeToCache) const { XLOG(INFO) << "Getting platform name from bios using dmedicode ..."; - auto [exitStatus, standardOut] = platformUtils.execCommand(dmidecodeCommand); + auto [exitStatus, standardOut] = + platformUtils_->execCommand(dmidecodeCommand); if (exitStatus != 0) { XLOG(ERR) << "Failed to get platform name from bios: " << stdout; throw std::runtime_error("Failed to get platform name from bios"); } standardOut = folly::trimWhitespace(standardOut).str(); XLOG(INFO) << "Platform name inferred from bios: " << standardOut; - return sanitizePlatformName(standardOut); + auto result = sanitizePlatformName(standardOut); + XLOG(INFO) << "Platform name mapped: " << result; + if (writeToCache) { + platformFsUtils_->writeStringToFile(result, kCachePath, true); + } + return result; } -std::optional PlatformNameLib::getPlatformName( - const PlatformUtils& platformUtils) const { +std::optional PlatformNameLib::getPlatformName() const { + auto nameFromCache = platformFsUtils_->getStringFileContent(kCachePath); + if (nameFromCache.has_value()) { + auto result = nameFromCache.value(); + XLOG(INFO) << "Platform name read from cache: " << result; + return result; + } try { - auto nameFromBios = getPlatformNameFromBios(platformUtils); + auto nameFromBios = getPlatformNameFromBios(); fb303::fbData->incrementCounter(kPlatformNameBiosReads, 1); return nameFromBios; } catch (const std::exception& e) { diff --git a/fboss/platform/helpers/PlatformNameLib.h b/fboss/platform/helpers/PlatformNameLib.h index 2a66257199aff..b298f96245712 100644 --- a/fboss/platform/helpers/PlatformNameLib.h +++ b/fboss/platform/helpers/PlatformNameLib.h @@ -5,6 +5,7 @@ #include #include +#include "fboss/platform/helpers/PlatformFsUtils.h" #include "fboss/platform/helpers/PlatformUtils.h" namespace facebook::fboss::platform::helpers { @@ -15,20 +16,31 @@ class PlatformNameLib { auto static constexpr kPlatformNameBiosReads = "platform_name_bios_reads"; auto static constexpr kPlatformNameBiosReadFailures = "platform_name_bios_read_failures"; + auto static constexpr kCacheDir = "/var/facebook/fboss/"; + // TODO: If extending beyond platform name, write out in JSON format instead. + auto static constexpr kCachePath = "/var/facebook/fboss/platform_name"; + + PlatformNameLib( + const std::shared_ptr platformUtils = + std::make_shared(), + const std::shared_ptr platformFsUtils = + std::make_shared()); virtual ~PlatformNameLib() = default; // Returns platform name from dmidecode. Platform names are UPPERCASE but // otherwise should match config names. Known dmidecode values are mapped to // config names. - virtual std::string getPlatformNameFromBios( - const PlatformUtils& platformUtils = PlatformUtils()) const; + virtual std::string getPlatformNameFromBios(bool writeToCache = false) const; // Returns platform name matching getPlatformNameFromBios, but (1) allows // forcing a name via parameter and (2) returns nullopt instead of throwing // exceptions. - virtual std::optional getPlatformName( - const PlatformUtils& platformUtils = PlatformUtils()) const; + virtual std::optional getPlatformName() const; + + private: + const std::shared_ptr platformUtils_; + const std::shared_ptr platformFsUtils_; }; } // namespace facebook::fboss::platform::helpers diff --git a/fboss/platform/helpers/tests/BUCK b/fboss/platform/helpers/tests/BUCK index 63a1c586c8258..cb9c735c15586 100644 --- a/fboss/platform/helpers/tests/BUCK +++ b/fboss/platform/helpers/tests/BUCK @@ -9,8 +9,11 @@ cpp_unittest( ], deps = [ "//fb303:service_data", + "//fboss/platform/helpers:mock_platform_fs_utils", "//fboss/platform/helpers:mock_platform_utils", + "//fboss/platform/helpers:platform_fs_utils", "//fboss/platform/helpers:platform_name_lib", + "//folly/testing:test_util", ], ) diff --git a/fboss/platform/helpers/tests/PlatformFsUtilsTest.cpp b/fboss/platform/helpers/tests/PlatformFsUtilsTest.cpp index 5b84d4cdc7456..5ebe75dcf7abf 100644 --- a/fboss/platform/helpers/tests/PlatformFsUtilsTest.cpp +++ b/fboss/platform/helpers/tests/PlatformFsUtilsTest.cpp @@ -67,4 +67,18 @@ TEST(PlatformFsUtilsTest, TemporaryRoot) { utils.getStringFileContent(tmpFilePathRelative), readContent.value()); } +TEST(PlatformFsUtilsTest, BasicWriteReadTest) { + fs::path tmpDirPath = + fs::path(folly::test::TemporaryDirectory().path().string()); + PlatformFsUtils utils{tmpDirPath}; + EXPECT_TRUE(utils.writeStringToFile("test", "/a/b/c/d")); + EXPECT_EQ(utils.getStringFileContent("/a/b/c/d"), "test"); + EXPECT_TRUE(utils.writeStringToFile("overwrite", "/a/b/c/d")); + EXPECT_EQ(utils.getStringFileContent("/a/b/c/d"), "overwrite"); + // Testing atomic writes here as basically just a sanity check. We rely on + // folly and their testing to maintain their atomicity guarantees. + EXPECT_TRUE(utils.writeStringToFile("test2", "/e/f/g/h", true)); + EXPECT_EQ(utils.getStringFileContent("/e/f/g/h"), "test2"); +} + } // namespace facebook::fboss::platform diff --git a/fboss/platform/helpers/tests/PlatformNameLibTest.cpp b/fboss/platform/helpers/tests/PlatformNameLibTest.cpp index 2066002a65fde..a0add2ede5adb 100644 --- a/fboss/platform/helpers/tests/PlatformNameLibTest.cpp +++ b/fboss/platform/helpers/tests/PlatformNameLibTest.cpp @@ -1,9 +1,12 @@ // (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary. #include +#include #include +#include "fboss/platform/helpers/MockPlatformFsUtils.h" #include "fboss/platform/helpers/MockPlatformUtils.h" +#include "fboss/platform/helpers/PlatformFsUtils.h" #include "fboss/platform/helpers/PlatformNameLib.h" using namespace ::testing; @@ -12,55 +15,56 @@ using namespace facebook::fboss::platform::helpers; namespace facebook::fboss::platform::helpers { TEST(PlatformNameLibTest, NameFromBios) { - auto platformUtils = MockPlatformUtils(); - auto platformNameLib = PlatformNameLib(); + auto platformUtils = std::make_shared(); + auto platformFsUtils = std::make_shared(); + auto platformNameLib = PlatformNameLib(platformUtils, platformFsUtils); // Mapped cases - EXPECT_CALL(platformUtils, execCommand(PlatformNameLib::dmidecodeCommand)) + EXPECT_CALL(*platformUtils, execCommand(PlatformNameLib::dmidecodeCommand)) .WillOnce(Return(std::pair{0, "janga"})); - EXPECT_EQ( - platformNameLib.getPlatformNameFromBios(platformUtils), "JANGA800BIC"); - EXPECT_CALL(platformUtils, execCommand(PlatformNameLib::dmidecodeCommand)) + EXPECT_EQ(platformNameLib.getPlatformNameFromBios(), "JANGA800BIC"); + EXPECT_CALL(*platformUtils, execCommand(PlatformNameLib::dmidecodeCommand)) .WillOnce(Return(std::pair{0, "Tahan"})); - EXPECT_EQ( - platformNameLib.getPlatformNameFromBios(platformUtils), "TAHAN800BC"); - EXPECT_CALL(platformUtils, execCommand(PlatformNameLib::dmidecodeCommand)) + EXPECT_EQ(platformNameLib.getPlatformNameFromBios(), "TAHAN800BC"); + EXPECT_CALL(*platformUtils, execCommand(PlatformNameLib::dmidecodeCommand)) .WillOnce(Return(std::pair{0, "MINIPACK3"})); - EXPECT_EQ( - platformNameLib.getPlatformNameFromBios(platformUtils), "MONTBLANC"); - EXPECT_CALL(platformUtils, execCommand(PlatformNameLib::dmidecodeCommand)) + EXPECT_EQ(platformNameLib.getPlatformNameFromBios(), "MONTBLANC"); + EXPECT_CALL(*platformUtils, execCommand(PlatformNameLib::dmidecodeCommand)) .WillOnce(Return(std::pair{0, "MINIPACK3_MCB"})); - EXPECT_EQ( - platformNameLib.getPlatformNameFromBios(platformUtils), "MONTBLANC"); + EXPECT_EQ(platformNameLib.getPlatformNameFromBios(), "MONTBLANC"); // Non-mapped - EXPECT_CALL(platformUtils, execCommand(PlatformNameLib::dmidecodeCommand)) + EXPECT_CALL(*platformUtils, execCommand(PlatformNameLib::dmidecodeCommand)) .WillOnce(Return(std::pair{0, "MORGAN800CC"})); - EXPECT_EQ( - platformNameLib.getPlatformNameFromBios(platformUtils), "MORGAN800CC"); + EXPECT_EQ(platformNameLib.getPlatformNameFromBios(), "MORGAN800CC"); // Error case - EXPECT_CALL(platformUtils, execCommand(PlatformNameLib::dmidecodeCommand)) + EXPECT_CALL(*platformUtils, execCommand(PlatformNameLib::dmidecodeCommand)) .WillOnce(Return(std::pair{1, ""})); - EXPECT_THROW( - platformNameLib.getPlatformNameFromBios(platformUtils), - std::runtime_error); + EXPECT_THROW(platformNameLib.getPlatformNameFromBios(), std::runtime_error); } -TEST(PlatformNameLibTest, GetPlatformName) { - auto platformUtils = MockPlatformUtils(); - auto platformNameLib = PlatformNameLib(); +TEST(PlatformNameLibTest, GetPlatformNameNoCache) { + auto platformUtils = std::make_shared(); + auto platformFsUtils = std::make_shared(); + auto platformNameLib = PlatformNameLib(platformUtils, platformFsUtils); + + // Cache reads always fail, other ops always succeed. + EXPECT_CALL(*platformFsUtils, createDirectories).WillRepeatedly(Return(true)); + EXPECT_CALL(*platformFsUtils, getStringFileContent) + .WillRepeatedly(Return(std::nullopt)); + EXPECT_CALL(*platformFsUtils, writeStringToFile).WillRepeatedly(Return(true)); // Success - EXPECT_CALL(platformUtils, execCommand(PlatformNameLib::dmidecodeCommand)) + EXPECT_CALL(*platformUtils, execCommand(PlatformNameLib::dmidecodeCommand)) .WillOnce(Return(std::pair{0, "janga"})); - EXPECT_EQ(platformNameLib.getPlatformName(platformUtils), "JANGA800BIC"); + EXPECT_EQ(platformNameLib.getPlatformName(), "JANGA800BIC"); EXPECT_EQ( facebook::fb303::fbData->getCounter( PlatformNameLib::kPlatformNameBiosReads), 1); // Failure - EXPECT_CALL(platformUtils, execCommand(PlatformNameLib::dmidecodeCommand)) + EXPECT_CALL(*platformUtils, execCommand(PlatformNameLib::dmidecodeCommand)) .WillOnce(Return(std::pair{1, ""})); - EXPECT_EQ(platformNameLib.getPlatformName(platformUtils), std::nullopt); + EXPECT_EQ(platformNameLib.getPlatformName(), std::nullopt); // One successful read has still occurred. EXPECT_EQ( facebook::fb303::fbData->getCounter( @@ -72,4 +76,60 @@ TEST(PlatformNameLibTest, GetPlatformName) { 1); } +TEST(PlatformNameLibTest, GetPlatformNameCache) { + fb303::fbData->zeroStats(); + auto tmpDir = folly::test::TemporaryDirectory(); + auto platformUtils = std::make_shared(); + auto platformFsUtils = + std::make_shared(tmpDir.path().string()); + auto platformNameLib = PlatformNameLib(platformUtils, platformFsUtils); + + EXPECT_CALL(*platformUtils, execCommand(PlatformNameLib::dmidecodeCommand)) + .Times(2) + .WillRepeatedly(Return(std::pair{0, "janga"})); + + // Successful bios read, no write to cache + EXPECT_EQ(platformNameLib.getPlatformName(), "JANGA800BIC"); + EXPECT_EQ( + facebook::fb303::fbData->getCounter( + PlatformNameLib::kPlatformNameBiosReads), + 1); + // Write to cache as PM would + EXPECT_EQ(platformNameLib.getPlatformNameFromBios(true), "JANGA800BIC"); + EXPECT_EQ( + facebook::fb303::fbData->getCounter( + PlatformNameLib::kPlatformNameBiosReads), + 1); + // Further calls to dmidecode fail + EXPECT_CALL(*platformUtils, execCommand(PlatformNameLib::dmidecodeCommand)) + .WillRepeatedly(Return(std::pair{1, ""})); + // Cache hit - success with no bios read + EXPECT_EQ(platformNameLib.getPlatformName(), "JANGA800BIC"); + EXPECT_EQ( + facebook::fb303::fbData->getCounter( + PlatformNameLib::kPlatformNameBiosReads), + 1); + // Cache hit 2 + EXPECT_EQ(platformNameLib.getPlatformName(), "JANGA800BIC"); + EXPECT_EQ( + facebook::fb303::fbData->getCounter( + PlatformNameLib::kPlatformNameBiosReads), + 1); + // Cache failure + dmidecode failure + auto platformFsUtilsNoRead = std::make_shared(); + auto platformNameLibNoRead = + PlatformNameLib(platformUtils, platformFsUtilsNoRead); + EXPECT_CALL(*platformFsUtilsNoRead, getStringFileContent) + .WillRepeatedly(Return(std::nullopt)); + EXPECT_EQ(platformNameLibNoRead.getPlatformName(), std::nullopt); + EXPECT_EQ( + facebook::fb303::fbData->getCounter( + PlatformNameLib::kPlatformNameBiosReads), + 1); + EXPECT_EQ( + facebook::fb303::fbData->getCounter( + PlatformNameLib::kPlatformNameBiosReadFailures), + 1); +} + } // namespace facebook::fboss::platform::helpers diff --git a/fboss/platform/platform_manager/ExplorationErrorMap.cpp b/fboss/platform/platform_manager/ExplorationErrorMap.cpp index 6a289bfd701c8..12ee5f6c898e4 100644 --- a/fboss/platform/platform_manager/ExplorationErrorMap.cpp +++ b/fboss/platform/platform_manager/ExplorationErrorMap.cpp @@ -9,7 +9,8 @@ namespace facebook::fboss::platform::platform_manager { namespace { const re2::RE2 kMeruRe{"meru800b[if]a"}; -} +const re2::RE2 kMeruPsuSlotPath{"/SMB_SLOT@0/PSU_SLOT@(?P[01])"}; +} // namespace ExplorationErrorMap::ExplorationErrorMap( const PlatformConfig& config, @@ -81,6 +82,20 @@ bool ExplorationErrorMap::isExpectedDeviceToFail( if (deviceName == "IDPROM") { return true; } + + // Case-P1 (Viper), Viper P1 only has one PSU slot when two are defined in + // config. Check if the other PSU slot has no error. + // In P2, we confirmed that two PSUs will be plugged-in. Unfortunately, + // since missing PmUnit in the slot, we can't distinguish P1 and P2. So if + // one PSU is missing, it'll be treated as expected which isn't hard + // error in P2. + if (uint slotNum; + re2::RE2::FullMatch(slotPath, kMeruPsuSlotPath, &slotNum)) { + if (!devicePathToErrors_.contains( + fmt::format("/SMB_SLOT@0/PSU_SLOT@{}", !slotNum))) { + return true; + } + } } else { auto pmUnitInfo = dataStore_.getPmUnitInfo(slotPath); auto productVersion = diff --git a/fboss/platform/platform_manager/PkgManager.cpp b/fboss/platform/platform_manager/PkgManager.cpp index f501fdebcb4fc..a3813d10ae800 100644 --- a/fboss/platform/platform_manager/PkgManager.cpp +++ b/fboss/platform/platform_manager/PkgManager.cpp @@ -52,11 +52,13 @@ PkgManager::PkgManager(const PlatformConfig& config) void PkgManager::processAll() const { loadUpstreamKmods(); + bool newRpmInstalled{false}; if (FLAGS_enable_pkg_mgmnt) { - if (FLAGS_local_rpm_path != "") { + if (!FLAGS_local_rpm_path.empty()) { fb303::fbData->setExportedValue( kBspKmodsRpmName, "local_rpm: " + FLAGS_local_rpm_path); processLocalRpms(); + newRpmInstalled = true; } else { fb303::fbData->setExportedValue(kBspKmodsRpmName, getKmodsRpmName()); fb303::fbData->setCounter( @@ -64,33 +66,37 @@ void PkgManager::processAll() const { kBspKmodsRpmVersionCounter, *platformConfig_.bspKmodsRpmVersion()), 1); - processRpms(); + newRpmInstalled = processRpms(); } } else { fb303::fbData->setExportedValue( kBspKmodsRpmName, "Not managing BSP package"); } - if (FLAGS_reload_kmods) { + if (FLAGS_reload_kmods || newRpmInstalled) { processKmods(); + } else { + loadBSPKmods(); } } -void PkgManager::processRpms() const { +bool PkgManager::processRpms() const { auto bspKmodsRpmName = getKmodsRpmName(); if (!isRpmInstalled(bspKmodsRpmName)) { XLOG(INFO) << fmt::format("Installing BSP Kmods {}", bspKmodsRpmName); + removeOldRpms(getKmodsRpmBaseWithKernelName()); installRpm(bspKmodsRpmName, 3 /* maxAttempts */); - processKmods(); + runDepmod(); + return true; } else { XLOG(INFO) << fmt::format( "BSP Kmods {} is already installed", bspKmodsRpmName); + return false; } } void PkgManager::processLocalRpms() const { installLocalRpm(3 /* maxAttempts */); - processKmods(); } void PkgManager::processKmods() const { @@ -106,6 +112,10 @@ void PkgManager::processKmods() const { for (int i = 0; i < platformConfig_.sharedKmodsToReload()->size(); ++i) { unloadKmod((*platformConfig_.sharedKmodsToReload())[i]); } + loadBSPKmods(); +} + +void PkgManager::loadBSPKmods() const { XLOG(INFO) << fmt::format( "Loading {} shared kernel modules", platformConfig_.sharedKmodsToReload()->size()); @@ -158,6 +168,46 @@ void PkgManager::installRpm(const std::string& rpmFullName, int maxAttempts) } } +void PkgManager::removeOldRpms(const std::string& rpmBaseName) const { + std::string stdOut{}; + int exitStatus{0}; + auto getInstalledRpmNamesCmd = fmt::format("rpm -qa | grep ^{}", rpmBaseName); + std::tie(exitStatus, stdOut) = + PlatformUtils().execCommand(getInstalledRpmNamesCmd); + if (exitStatus) { + XLOG(INFO) << "No old rpms to remove"; + return; + } + + std::vector installedRpms; + folly::split('\n', stdOut, installedRpms); + XLOG(INFO) << fmt::format( + "Removing old rpms: {}", folly::join(", ", installedRpms)); + auto removeOldRpmsCmd = + fmt::format("rpm -e --allmatches {}", folly::join(" ", installedRpms)); + std::tie(exitStatus, stdOut) = PlatformUtils().execCommand(removeOldRpmsCmd); + if (exitStatus) { + XLOG(ERR) << fmt::format( + "Command ({}) failed with exit code {}", removeOldRpmsCmd, exitStatus); + throw std::runtime_error(fmt::format( + "Failed to remove old rpms ({}) with exit code {}", + folly::join(" ", installedRpms), + exitStatus)); + } +} + +void PkgManager::runDepmod() const { + int exitStatus{0}; + std::string standardOut{}; + auto depmodCmd = "depmod -a"; + XLOG(INFO) << fmt::format("Running command ({})", depmodCmd); + std::tie(exitStatus, standardOut) = PlatformUtils().execCommand(depmodCmd); + if (exitStatus != 0) { + XLOG(ERR) << fmt::format( + "Command ({}) failed with exit code {}", depmodCmd, exitStatus); + } +} + void PkgManager::installLocalRpm(int maxAttempts) const { int exitStatus{0}, attempt{1}; std::string standardOut{}; @@ -208,6 +258,11 @@ void PkgManager::loadKmod(const std::string& moduleName) const { } } +std::string PkgManager::getKmodsRpmBaseWithKernelName() const { + return fmt::format( + "{}-{}", *platformConfig_.bspKmodsRpmName(), getHostKernelVersion()); +} + std::string PkgManager::getKmodsRpmName() const { return fmt::format( "{}-{}-{}", diff --git a/fboss/platform/platform_manager/PkgManager.h b/fboss/platform/platform_manager/PkgManager.h index 6ca474ba400ca..ea4b76b4212a5 100644 --- a/fboss/platform/platform_manager/PkgManager.h +++ b/fboss/platform/platform_manager/PkgManager.h @@ -4,23 +4,33 @@ #include "fboss/platform/platform_manager/gen-cpp2/platform_manager_config_types.h" +DECLARE_bool(enable_pkg_mgmnt); +DECLARE_bool(reload_kmods); +DECLARE_string(local_rpm_path); + namespace facebook::fboss::platform::platform_manager { class PkgManager { public: explicit PkgManager(const PlatformConfig& config); + virtual ~PkgManager() = default; void processAll() const; - void processRpms() const; - void processKmods() const; - void processLocalRpms() const; - void loadUpstreamKmods() const; + // Returns true if the rpm is newly installed, false otherwise. + virtual bool processRpms() const; + virtual void processKmods() const; + virtual void processLocalRpms() const; + virtual void loadBSPKmods() const; + virtual void loadUpstreamKmods() const; std::string getKmodsRpmName() const; + std::string getKmodsRpmBaseWithKernelName() const; private: void loadKmod(const std::string& moduleName) const; void unloadKmod(const std::string& moduleName) const; bool isRpmInstalled(const std::string& rpmFullName) const; void installRpm(const std::string& rpmFullName, int maxAttempts) const; + void removeOldRpms(const std::string& rpmBaseName) const; + void runDepmod() const; void installLocalRpm(int maxAttempts) const; const PlatformConfig& platformConfig_; diff --git a/fboss/platform/platform_manager/PlatformExplorer.cpp b/fboss/platform/platform_manager/PlatformExplorer.cpp index bfb205600d3c1..ead835997d92b 100644 --- a/fboss/platform/platform_manager/PlatformExplorer.cpp +++ b/fboss/platform/platform_manager/PlatformExplorer.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include "fboss/platform/helpers/PlatformFsUtils.h" #include "fboss/platform/helpers/PlatformUtils.h" @@ -36,11 +37,83 @@ std::string getSlotPath( } } +// Read an arbitrary version string from the file at given path, then attempt to +// parse as an X.Y(.Z) version number where each part is a valid 3-digit decimal +// integer. +// +// The file is expected to only contain the version string itself. If we fail to +// read a non-empty version string, or if the string contains whitespace or +// control characters, the string returned corresponds to an error. Otherwise, +// the version string is considered valid and returned, even if it cannot be +// parsed numerically. +// +// The returned integer is encoded as: +// X * 1,000,000 + Y * 1000 + Z +// If the version string only has 2 parts (X.Y) then Z=0. +// If the version string cannot be parsed into 3-digit decimal values in X.Y(.Z) +// format, then 0 is returned. +// +// Examples of integer values: +// 1. "1.2.3", return 1,002,003 +// 2. "4.5", return 4,005,000 +// 3. "12345.6789", return 0 (integers exceed 3 digits) +// 4. "foobar", return 0 +// 5. "foo.bar", return 0 +std::pair readVersionString( + const std::string& path, + const facebook::fboss::platform::PlatformFsUtils* platformFsUtils) { + static const re2::RE2 kFwVerXYPattern = + re2::RE2(PlatformExplorer::kFwVerXYPatternStr); + static const re2::RE2 kFwVerXYZPattern = + re2::RE2(PlatformExplorer::kFwVerXYZPatternStr); + const auto versionFileContent = platformFsUtils->getStringFileContent(path); + if (!versionFileContent) { + XLOGF( + ERR, + "Failed to open firmware version file {}: {}", + path, + folly::errnoStr(errno)); + return {fmt::format("ERROR_FILE_{}", errno), 0}; + } + const auto versionString = versionFileContent.value(); + if (versionString.empty()) { + XLOGF(ERR, "Empty firmware version file {}", path); + return {"ERROR_EMPTY_FILE", 0}; + } + if (folly::hasSpaceOrCntrlSymbols(versionString)) { + XLOGF( + ERR, + "Firmware version string \"{}\" from file {} contains whitespace or control characters.", + versionString, + path); + return {"ERROR_INVALID_STRING", 0}; + } + // These names are for ease of reference. Neither semver nor any other + // interpretation is enforced in fw_ver. + int major = 0; + int minor = 0; + int patch = 0; + bool match = re2::RE2::FullMatch( + versionString, kFwVerXYZPattern, &major, &minor, &patch) || + re2::RE2::FullMatch(versionString, kFwVerXYPattern, &major, &minor); + if (!match) { + XLOGF( + WARN, + "Firmware version string {} from file {} does not match XXX.YYY.ZZZ format. This may be OK if it's an expected checksum.", + versionString, + path); + return {versionString, 0}; + } + CHECK(major < 1000 && minor < 1000 && patch < 1000); + int odsValue = major * 1'000'000 + minor * 1000 + patch; + return {versionString, odsValue}; +} + // Read a singular version number from the file at given path. If there is any // error reading the file, log and return a default of 0. The version number // must be the first non-whitespace substring, but the file may contain // additional non-numeric data after the version (e.g. human-readable comments). -// TODO: Handle hwmon/info_rom cases (by standardizing them away, if possible). +// TODO: Handle info_rom cases (by standardizing them away, if possible). int readVersionNumber( const std::string& path, const PlatformFsUtils* platformFsUtils) { @@ -624,6 +697,8 @@ void PlatformExplorer::publishFirmwareVersions() { // Note: The vector is guaranteed to be non-empty due to the prefix check. CHECK(!linkPathParts.empty()); const auto deviceName = linkPathParts.back(); + std::string versionString; + int odsValue = 0; std::string verDirPath = linkPath; // Check for and handle hwmon case. e.g. // /run/devmap/cplds/FAN0_CPLD/hwmon/hwmon20/ @@ -637,26 +712,34 @@ void PlatformExplorer::publishFirmwareVersions() { } } } - const auto version = readVersionNumber( - fmt::format("{}/{}_ver", verDirPath, deviceType), - platformFsUtils_.get()); - const auto subversion = readVersionNumber( - fmt::format("{}/{}_sub_ver", verDirPath, deviceType), - platformFsUtils_.get()); - - std::string fullVersionString = fmt::format("{}.{}", version, subversion); - int odsValue = version * 1000 + subversion; + // New-style fw_ver + auto fwVerFilePath = std::filesystem::path(verDirPath) / "fw_ver"; + if (platformFsUtils_->exists(fwVerFilePath)) { + auto version = readVersionString(fwVerFilePath, platformFsUtils_.get()); + versionString = version.first; + odsValue = version.second; + } else { + const auto version = readVersionNumber( + fmt::format("{}/{}_ver", verDirPath, deviceType), + platformFsUtils_.get()); + const auto subversion = readVersionNumber( + fmt::format("{}/{}_sub_ver", verDirPath, deviceType), + platformFsUtils_.get()); + + versionString = fmt::format("{}.{}", version, subversion); + odsValue = version * 1000 + subversion; + } XLOGF( INFO, "Reporting firmware version for {} - version string:{} ODS value:{}", deviceName, - fullVersionString, + versionString, odsValue); fb303::fbData->setCounter( fmt::format(kFirmwareVersion, deviceName), odsValue); fb303::fbData->setCounter( - fmt::format(kGroupedFirmwareVersion, deviceName, fullVersionString), 1); + fmt::format(kGroupedFirmwareVersion, deviceName, versionString), 1); } } diff --git a/fboss/platform/platform_manager/PlatformExplorer.h b/fboss/platform/platform_manager/PlatformExplorer.h index 3209ae41e7019..cc7fc718b98e4 100644 --- a/fboss/platform/platform_manager/PlatformExplorer.h +++ b/fboss/platform/platform_manager/PlatformExplorer.h @@ -20,6 +20,11 @@ namespace facebook::fboss::platform::platform_manager { class PlatformExplorer { public: + // Regex patterns for matching fw_ver format. + auto static constexpr kFwVerXYPatternStr = R"((\d{1,3})\.(\d{1,3}))"; + auto static constexpr kFwVerXYZPatternStr = + R"((\d{1,3})\.(\d{1,3})\.(\d{1,3}))"; + auto static constexpr kFirmwareVersion = "{}.firmware_version"; auto static constexpr kGroupedFirmwareVersion = "{}.firmware_version.{}"; diff --git a/fboss/platform/platform_manager/Utils.cpp b/fboss/platform/platform_manager/Utils.cpp index be96de768a43e..0ca25e8c8118b 100644 --- a/fboss/platform/platform_manager/Utils.cpp +++ b/fboss/platform/platform_manager/Utils.cpp @@ -65,7 +65,7 @@ void verifyPlatformNameMatches( PlatformConfig Utils::getConfig() { std::string platformNameFromBios = - helpers::PlatformNameLib().getPlatformNameFromBios(); + helpers::PlatformNameLib().getPlatformNameFromBios(true); std::string configJson = ConfigLib().getPlatformManagerConfig(platformNameFromBios); PlatformConfig config; diff --git a/fboss/platform/platform_manager/tests/BUCK b/fboss/platform/platform_manager/tests/BUCK index 2f80f2940e080..32fc8df141cca 100644 --- a/fboss/platform/platform_manager/tests/BUCK +++ b/fboss/platform/platform_manager/tests/BUCK @@ -93,3 +93,14 @@ cpp_unittest( "//fboss/platform/platform_manager:platform_explorer", ], ) + +cpp_unittest( + name = "pkg_manager_test", + srcs = [ + "PkgManagerTest.cpp", + ], + deps = [ + "fbcode//fboss/platform/platform_manager:pkg_manager", + "fbsource//third-party/googletest:gmock", + ], +) diff --git a/fboss/platform/platform_manager/tests/PkgManagerTest.cpp b/fboss/platform/platform_manager/tests/PkgManagerTest.cpp new file mode 100644 index 0000000000000..c8bdd4bd225d2 --- /dev/null +++ b/fboss/platform/platform_manager/tests/PkgManagerTest.cpp @@ -0,0 +1,90 @@ +// (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary. + +#include +#include + +#include "fboss/platform/platform_manager/PkgManager.h" + +using namespace ::testing; +namespace facebook::fboss::platform::platform_manager { +class MockPkgManager : public PkgManager { + public: + explicit MockPkgManager(const PlatformConfig& config) : PkgManager(config) {} + MOCK_METHOD(bool, processRpms, (), (const)); + MOCK_METHOD(void, processKmods, (), (const)); + MOCK_METHOD(void, processLocalRpms, (), (const)); + MOCK_METHOD(void, loadBSPKmods, (), (const)); + MOCK_METHOD(void, loadUpstreamKmods, (), (const)); +}; + +class PkgManagerTest : public testing::Test { + public: + void SetUp() override { + FLAGS_local_rpm_path = ""; + } + PlatformConfig platformConfig_; + MockPkgManager mockPkgManager_{platformConfig_}; +}; + +TEST_F(PkgManagerTest, EnablePkgMgmnt) { + FLAGS_enable_pkg_mgmnt = true; + FLAGS_reload_kmods = false; + + EXPECT_CALL(mockPkgManager_, processLocalRpms()).Times(0); + // Case 1: When new rpm installed + EXPECT_CALL(mockPkgManager_, loadUpstreamKmods()).Times(1); + EXPECT_CALL(mockPkgManager_, processRpms()).WillOnce(Return(true)); + EXPECT_CALL(mockPkgManager_, processKmods()).Times(1); + EXPECT_CALL(mockPkgManager_, loadBSPKmods()).Times(0); + EXPECT_NO_THROW(mockPkgManager_.processAll()); + // Case 2: When rpm is already installed + EXPECT_CALL(mockPkgManager_, loadUpstreamKmods()).Times(1); + EXPECT_CALL(mockPkgManager_, processRpms()).WillOnce(Return(false)); + EXPECT_CALL(mockPkgManager_, processKmods()).Times(0); + EXPECT_CALL(mockPkgManager_, loadBSPKmods()).Times(1); + EXPECT_NO_THROW(mockPkgManager_.processAll()); +} + +TEST_F(PkgManagerTest, EnablePkgMgmntWithReloadKmods) { + FLAGS_enable_pkg_mgmnt = true; + FLAGS_reload_kmods = true; + + EXPECT_CALL(mockPkgManager_, processLocalRpms()).Times(0); + // Case 1: When new rpm installed and expect to reload kmods once. + EXPECT_CALL(mockPkgManager_, loadUpstreamKmods()).Times(1); + EXPECT_CALL(mockPkgManager_, processRpms()).WillOnce(Return(true)); + EXPECT_CALL(mockPkgManager_, processKmods()).Times(1); + EXPECT_CALL(mockPkgManager_, loadBSPKmods()).Times(0); + EXPECT_NO_THROW(mockPkgManager_.processAll()); + // Case 2: When rpm is already installed and still expect to reload kmods + // once because of FLAGS_reload_kmods being true. + EXPECT_CALL(mockPkgManager_, loadUpstreamKmods()).Times(1); + EXPECT_CALL(mockPkgManager_, processRpms()).WillOnce(Return(false)); + EXPECT_CALL(mockPkgManager_, processKmods()).Times(1); + EXPECT_CALL(mockPkgManager_, loadBSPKmods()).Times(0); + EXPECT_NO_THROW(mockPkgManager_.processAll()); +} + +TEST_F(PkgManagerTest, DisablePkgMgmnt) { + FLAGS_enable_pkg_mgmnt = false; + FLAGS_reload_kmods = false; + + EXPECT_CALL(mockPkgManager_, loadUpstreamKmods()).Times(1); + EXPECT_CALL(mockPkgManager_, processLocalRpms()).Times(0); + EXPECT_CALL(mockPkgManager_, processRpms()).Times(0); + EXPECT_CALL(mockPkgManager_, processKmods()).Times(0); + EXPECT_CALL(mockPkgManager_, loadBSPKmods()).Times(1); + EXPECT_NO_THROW(mockPkgManager_.processAll()); +} +TEST_F(PkgManagerTest, DisablePkgMgmntWithReloadKmods) { + FLAGS_enable_pkg_mgmnt = false; + FLAGS_reload_kmods = true; + + EXPECT_CALL(mockPkgManager_, loadUpstreamKmods()).Times(1); + EXPECT_CALL(mockPkgManager_, processLocalRpms()).Times(0); + EXPECT_CALL(mockPkgManager_, processRpms()).Times(0); + EXPECT_CALL(mockPkgManager_, processKmods()).Times(1); + EXPECT_CALL(mockPkgManager_, loadBSPKmods()).Times(0); + EXPECT_NO_THROW(mockPkgManager_.processAll()); +} +}; // namespace facebook::fboss::platform::platform_manager diff --git a/fboss/platform/platform_manager/tests/PlatformExplorerTest.cpp b/fboss/platform/platform_manager/tests/PlatformExplorerTest.cpp index 62d0c112e3a69..5acd0db0e35b7 100644 --- a/fboss/platform/platform_manager/tests/PlatformExplorerTest.cpp +++ b/fboss/platform/platform_manager/tests/PlatformExplorerTest.cpp @@ -60,12 +60,33 @@ TEST(PlatformExplorerTest, PublishFirmwareVersions) { writeVersions( cpldHwmonPath + "/hwmon/hwmon20", "cpld", "99", "99", platformFsUtils); + // New-style fw_ver file + std::string fpgaFwVerPath = "/run/devmap/fpgas/TEST_FPGA_FWVER"; + EXPECT_TRUE(platformFsUtils->writeStringToFile( + "1.2", fmt::format("{}/fw_ver", fpgaFwVerPath))); + // fw_ver should be prioritized over old-style + std::string cpldFwVerPath = "/run/devmap/cplds/TEST_CPLD_FWVER"; + writeVersions(cpldFwVerPath, "cpld", "999", "999", platformFsUtils); + EXPECT_TRUE(platformFsUtils->writeStringToFile( + "123.456.789", fmt::format("{}/fw_ver", cpldFwVerPath))); + std::string cpldBadFwVerPath = "/run/devmap/cplds/TEST_CPLD_BADFWVER"; + EXPECT_TRUE(platformFsUtils->writeStringToFile( + "123.456.789 // comment", fmt::format("{}/fw_ver", cpldBadFwVerPath))); + // Case with fw_ver under hwmon + std::string cpldHwmonFwVerPath = "/run/devmap/cplds/FAN0_CPLD_FWVER"; + EXPECT_TRUE(platformFsUtils->writeStringToFile( + "1.2.3", fmt::format("{}/hwmon/hwmon20/fw_ver", cpldHwmonFwVerPath))); + PlatformConfig platformConfig; platformConfig.symbolicLinkToDevicePath()[fpgaPath] = ""; platformConfig.symbolicLinkToDevicePath()[cpldPath] = ""; platformConfig.symbolicLinkToDevicePath()[cpldPath2] = ""; platformConfig.symbolicLinkToDevicePath()[fpgaPathBadInt] = ""; platformConfig.symbolicLinkToDevicePath()[cpldHwmonPath] = ""; + platformConfig.symbolicLinkToDevicePath()[fpgaFwVerPath] = ""; + platformConfig.symbolicLinkToDevicePath()[cpldFwVerPath] = ""; + platformConfig.symbolicLinkToDevicePath()[cpldBadFwVerPath] = ""; + platformConfig.symbolicLinkToDevicePath()[cpldHwmonFwVerPath] = ""; PlatformExplorer explorer(platformConfig, platformFsUtils); explorer.publishFirmwareVersions(); @@ -75,6 +96,11 @@ TEST(PlatformExplorerTest, PublishFirmwareVersions) { expectVersions("TEST_CPLD_MIXED", "15.9", 15009); expectVersions("TEST_FPGA_BAD_INT", "0.0", 0); expectVersions("FAN0_CPLD", "99.99", 99099); + + expectVersions("TEST_FPGA_FWVER", "1.2", 1'002'000); + expectVersions("TEST_CPLD_FWVER", "123.456.789", 123456789); + expectVersions("TEST_CPLD_BADFWVER", "ERROR_INVALID_STRING", 0); + expectVersions("FAN0_CPLD_FWVER", "1.2.3", 1'002'003); } } // namespace facebook::fboss::platform::platform_manager diff --git a/fboss/platform/rackmon/if/rackmonsvc.thrift b/fboss/platform/rackmon/if/rackmonsvc.thrift index 942da13155a58..b63a803bac989 100644 --- a/fboss/platform/rackmon/if/rackmonsvc.thrift +++ b/fboss/platform/rackmon/if/rackmonsvc.thrift @@ -279,6 +279,13 @@ service RackmonCtrl { 1: MonitorDataFilter filter, ) throws (1: fboss.FbossBaseError error); + /* + * Reload register matching the provided filter + */ + void reload(1: MonitorDataFilter filter, 2: bool synchronous = true) throws ( + 1: fboss.FbossBaseError error, + ); + /* * Send commands to control rackmond's behavior, such as pause/resume * rackmond's core loop. diff --git a/fboss/platform/sensor_service/BUCK b/fboss/platform/sensor_service/BUCK index b1178b07f0229..5ebe19e2a810b 100644 --- a/fboss/platform/sensor_service/BUCK +++ b/fboss/platform/sensor_service/BUCK @@ -26,6 +26,7 @@ cpp_library( "//fboss/fsdb/if:fsdb_model", "//fboss/fsdb/if:fsdb_oper-cpp2-types", "//fboss/platform/config_lib:config_lib", + "//fboss/platform/helpers:platform_name_lib", "//fboss/platform/sensor_service/if:sensor_config-cpp2-types", "//fboss/platform/sensor_service/if:sensor_service-cpp2-types", "//folly:file_util", diff --git a/fboss/platform/sensor_service/SensorServiceImpl.cpp b/fboss/platform/sensor_service/SensorServiceImpl.cpp index 2c4626f58dc21..892b4f326b25f 100644 --- a/fboss/platform/sensor_service/SensorServiceImpl.cpp +++ b/fboss/platform/sensor_service/SensorServiceImpl.cpp @@ -18,6 +18,7 @@ #include #include "fboss/platform/config_lib/ConfigLib.h" +#include "fboss/platform/helpers/PlatformNameLib.h" #include "fboss/platform/sensor_service/FsdbSyncer.h" #include "fboss/platform/sensor_service/SensorServiceImpl.h" #include "fboss/platform/sensor_service/Utils.h" @@ -31,7 +32,8 @@ DEFINE_int32( namespace facebook::fboss::platform::sensor_service { SensorServiceImpl::SensorServiceImpl() { - std::string sensorConfJson = ConfigLib().getSensorServiceConfig(); + auto platformName = helpers::PlatformNameLib().getPlatformName(); + std::string sensorConfJson = ConfigLib().getSensorServiceConfig(platformName); XLOG(DBG2) << "Read sensor config: " << sensorConfJson; apache::thrift::SimpleJSONSerializer::deserialize( sensorConfJson, sensorConfig_); diff --git a/fboss/platform/sensor_service/Utils.cpp b/fboss/platform/sensor_service/Utils.cpp index 2292272271138..a571d9ae9c4b4 100644 --- a/fboss/platform/sensor_service/Utils.cpp +++ b/fboss/platform/sensor_service/Utils.cpp @@ -4,11 +4,12 @@ #include #include -#include #include #include +namespace facebook::fboss::platform::sensor_service { + namespace { // Compare the two array reprsentation of // productionState,productVersion,productSubVersion. @@ -28,8 +29,19 @@ bool greaterEqual( } return greaterEqual(l1, l2, ++i); } +// Same as above greaterEqual except it takes VersionedPmSensor +bool greaterEqual( + const VersionedPmSensor& vSensor1, + const VersionedPmSensor& vSensor2) { + return greaterEqual( + {*vSensor1.productProductionState(), + *vSensor1.productVersion(), + *vSensor1.productSubVersion()}, + {*vSensor2.productProductionState(), + *vSensor2.productVersion(), + *vSensor2.productSubVersion()}); +} } // namespace -namespace facebook::fboss::platform::sensor_service { uint64_t Utils::nowInSecs() { return std::chrono::duration_cast( @@ -79,7 +91,13 @@ std::optional Utils::resolveVersionedSensors( {*versionedSensor.productProductionState(), *versionedSensor.productVersion(), *versionedSensor.productSubVersion()})) { - resolvedVersionedSensor = versionedSensor; + resolvedVersionedSensor = std::max( + versionedSensor, + // Default VersionedPmSensor if null i.e (0,0,0) + resolvedVersionedSensor.value_or(VersionedPmSensor{}), + [](const auto& vSensor1, const auto& vSensor2) { + return !greaterEqual(vSensor1, vSensor2); + }); } } return resolvedVersionedSensor; diff --git a/fboss/platform/sensor_service/test/UtilsTest.cpp b/fboss/platform/sensor_service/test/UtilsTest.cpp index 5a78281665199..2ff1f1f3ed485 100644 --- a/fboss/platform/sensor_service/test/UtilsTest.cpp +++ b/fboss/platform/sensor_service/test/UtilsTest.cpp @@ -90,5 +90,17 @@ TEST_F(UtilsTests, PmUnitInfoFetcherTest) { EXPECT_NE(resolvedVersionedSensor, std::nullopt); EXPECT_TRUE( isEqual(*resolvedVersionedSensor, createVersionedPmSensor(1, 1, 4))); + // Case-4: Matching Unordered VersionedPmSensors + EXPECT_CALL(fetcher_, fetch(_)) + .WillOnce(Return(std::array{3, 1, 20})); + resolvedVersionedSensor = Utils().resolveVersionedSensors( + fetcher_, + slotPath_, + {createVersionedPmSensor(3, 1, 20), + createVersionedPmSensor(2, 1, 20), + createVersionedPmSensor(2, 3, 20)}); + EXPECT_NE(resolvedVersionedSensor, std::nullopt); + EXPECT_TRUE( + isEqual(*resolvedVersionedSensor, createVersionedPmSensor(3, 1, 20))); } } // namespace facebook::fboss::platform::sensor_service diff --git a/fboss/platform/weutil/BUCK b/fboss/platform/weutil/BUCK index 04d5dce2d4d48..1cb248999f355 100644 --- a/fboss/platform/weutil/BUCK +++ b/fboss/platform/weutil/BUCK @@ -21,6 +21,7 @@ cpp_library( "//fboss/lib/platforms:platform_mode", "//fboss/lib/platforms:product-info", "//fboss/platform/config_lib:config_lib", + "//fboss/platform/helpers:platform_name_lib", "//fboss/platform/helpers:platform_utils", "//fboss/platform/weutil/if:weutil_config-cpp2-types", "//folly:conv", diff --git a/fboss/platform/weutil/FbossEepromParser.cpp b/fboss/platform/weutil/FbossEepromParser.cpp index 0d7daab046d83..eb65b7fa05aca 100644 --- a/fboss/platform/weutil/FbossEepromParser.cpp +++ b/fboss/platform/weutil/FbossEepromParser.cpp @@ -57,7 +57,7 @@ const std::vector kFieldDictionaryV3 = { {13, "System Manufacturer", FIELD_STRING, 8, 121}, {14, "System Manufacturing Date", FIELD_DATE, 4, 129}, {15, "PCB Manufacturer", FIELD_STRING, 8, 133}, - {16, "Assembled at", FIELD_STRING, 8, 141}, + {16, "Assembled At", FIELD_STRING, 8, 141}, {17, "Local MAC", FIELD_LEGACY_MAC, 12, 149}, {17, "Extended MAC Base", FIELD_LEGACY_MAC, 12, 161}, {18, "Extended MAC Address Size", FIELD_LE_UINT, 2, 173}, @@ -80,7 +80,7 @@ const std::vector kFieldDictionaryV4 = { {12, "System Manufacturer", FIELD_STRING, VARIABLE, VARIABLE}, {13, "System Manufacturing Date", FIELD_STRING, 8, VARIABLE}, {14, "PCB Manufacturer", FIELD_STRING, VARIABLE, VARIABLE}, - {15, "Assembled at", FIELD_STRING, VARIABLE, VARIABLE}, + {15, "Assembled At", FIELD_STRING, VARIABLE, VARIABLE}, {16, "Local MAC", FIELD_V4_MAC, 6, VARIABLE}, {17, "Extended MAC Base", FIELD_V4_MAC, 6, VARIABLE}, {18, "Extended MAC Address Size", FIELD_LE_UINT, 2, VARIABLE}, @@ -104,7 +104,7 @@ const std::vector kFieldDictionaryV5 = { {12, "System Manufacturer", FIELD_STRING, VARIABLE, VARIABLE}, {13, "System Manufacturing Date", FIELD_STRING, 8, VARIABLE}, {14, "PCB Manufacturer", FIELD_STRING, VARIABLE, VARIABLE}, - {15, "Assembled at", FIELD_STRING, VARIABLE, VARIABLE}, + {15, "Assembled At", FIELD_STRING, VARIABLE, VARIABLE}, {16, "EEPROM location on Fabric", FIELD_STRING, VARIABLE, VARIABLE}, {17, "X86 CPU MAC", FIELD_V5_MAC, 8, VARIABLE}, {18, "BMC MAC", FIELD_V5_MAC, 8, VARIABLE}, @@ -408,11 +408,15 @@ FbossEepromParser::prepareEepromFieldMap( std::vector fieldDictionary; fieldDictionary = getEepromFieldDict(eepromVer); + // Add the EEPROM version to parsed result. It's not part of the + // field dictionary, so we add it here. + result.push_back({"Version", std::to_string(eepromVer)}); + for (auto dictItem : fieldDictionary) { std::string key = dictItem.fieldName; std::string value; auto match = parsedValue.find(dictItem.typeCode); - // "NA" is reservered, and not for display + // "NA" is reserved, and not for display if (key == "NA") { continue; } diff --git a/fboss/platform/weutil/Weutil.cpp b/fboss/platform/weutil/Weutil.cpp index d9b13a2d96666..649ffde173b62 100644 --- a/fboss/platform/weutil/Weutil.cpp +++ b/fboss/platform/weutil/Weutil.cpp @@ -8,6 +8,7 @@ #include "fboss/lib/platforms/PlatformMode.h" #include "fboss/lib/platforms/PlatformProductInfo.h" #include "fboss/platform/config_lib/ConfigLib.h" +#include "fboss/platform/helpers/PlatformNameLib.h" #include "fboss/platform/weutil/WeutilDarwin.h" #include "fboss/platform/weutil/WeutilImpl.h" #include "fboss/platform/weutil/if/gen-cpp2/weutil_config_types.h" @@ -18,7 +19,8 @@ namespace { weutil_config::WeutilConfig getWeUtilConfig() { weutil_config::WeutilConfig thriftConfig; - std::string weutilConfigJson = ConfigLib().getWeutilConfig(); + auto platformName = helpers::PlatformNameLib().getPlatformName(); + std::string weutilConfigJson = ConfigLib().getWeutilConfig(platformName); apache::thrift::SimpleJSONSerializer::deserialize< weutil_config::WeutilConfig>(weutilConfigJson, thriftConfig); XLOG(DBG1) << apache::thrift::SimpleJSONSerializer::serialize( diff --git a/fboss/platform/weutil/WeutilImpl.cpp b/fboss/platform/weutil/WeutilImpl.cpp index cbb3097e2df4a..11082c8825e27 100644 --- a/fboss/platform/weutil/WeutilImpl.cpp +++ b/fboss/platform/weutil/WeutilImpl.cpp @@ -29,33 +29,19 @@ void WeutilImpl::printInfo() { void WeutilImpl::printInfoJson() { auto info = getContents(); - - int cursor = 0; - std::vector items; - for (auto [key, value] : info) { - // CRC16 is not needed in JSON output + folly::dynamic eepromObject = folly::dynamic::object; + for (const auto& [key, value] : parser_.getContents()) { if (key == "CRC16") { continue; } - items.push_back(fmt::format("\"{}\": \"{}\"", key, value)); - } - int vectorSize = items.size(); - // Manually create JSON object without using folly, so that this code - // will be ported to BMC later - // Print the first part of the JSON - fixed entry to make a JSON - std::cout << "{"; - std::cout << "\"Information\": {"; - // Print the second part of the JSON, the dynamic entry - for (auto& item : items) { - std::cout << item; - if (cursor++ != vectorSize - 1) { - std::cout << ", "; - } + eepromObject[key] = value; } - // Finally, print the third part of the JSON - fixed entry - std::cout << "}, \"Actions\": [], \"Resources\": []"; - std::cout << "}" << std::endl; + folly::dynamic json = folly::dynamic::object; + json["Information"] = eepromObject; + json["Actions"] = folly::dynamic::array(); + json["Resources"] = folly::dynamic::array(); + std::cout << folly::toPrettyJson(json) << std::endl; } } // namespace facebook::fboss::platform diff --git a/fboss/platform/weutil/test/FbossEepromParserTest.cpp b/fboss/platform/weutil/test/FbossEepromParserTest.cpp index d5d80e6caa7c0..30baec0387955 100644 --- a/fboss/platform/weutil/test/FbossEepromParserTest.cpp +++ b/fboss/platform/weutil/test/FbossEepromParserTest.cpp @@ -1,6 +1,5 @@ // (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary. -#include #include #include @@ -33,6 +32,7 @@ EepromData eepromV4 = { 0x00, 0x13, 0x03, 0x4d, 0x43, 0x42, 0xfa, 0x02, 0x44, 0x11}; EepromContents expectedContentsV4 = { + {"Version", "4"}, {"Product Name", "MINIPACK3_MCB"}, {"Product Part Number", ""}, {"System Assembly Part Number", " "}, @@ -47,7 +47,7 @@ EepromContents expectedContentsV4 = { {"System Manufacturer", "CLS"}, {"System Manufacturing Date", "20230610"}, {"PCB Manufacturer", "WUS"}, - {"Assembled at", "CTH"}, + {"Assembled At", "CTH"}, {"Local MAC", "00:00:00:00:00:00"}, {"Extended MAC Base", "00:00:00:00:00:00"}, {"Extended MAC Address Size", "0"}, @@ -79,6 +79,7 @@ EepromData eepromV5 = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; EepromContents expectedContentsV5 = { + {"Version", "5"}, {"Product Name", "FIRST_SQUEEZE"}, {"Product Part Number", "20123456"}, {"System Assembly Part Number", "SYSA1234"}, @@ -93,7 +94,7 @@ EepromContents expectedContentsV5 = { {"System Manufacturer", "UNA_MAS"}, {"System Manufacturing Date", "20130203"}, {"PCB Manufacturer", "TERZO"}, - {"Assembled at", "JUICETORY"}, + {"Assembled At", "JUICETORY"}, {"EEPROM location on Fabric", "BUDOKAN"}, {"X86 CPU MAC Base", "11:22:33:44:55:66"}, {"X86 CPU MAC Address Size", "258"}, @@ -130,6 +131,7 @@ EepromData eepromV5WrongCrc = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; EepromContents expectedContentsV5WrongCrc = { + {"Version", "5"}, {"Product Name", "FIRST_SQUEEZE"}, {"Product Part Number", "20123456"}, {"System Assembly Part Number", "SYSA1234"}, @@ -144,7 +146,7 @@ EepromContents expectedContentsV5WrongCrc = { {"System Manufacturer", "UNA_MAS"}, {"System Manufacturing Date", "20130203"}, {"PCB Manufacturer", "TERZO"}, - {"Assembled at", "JUICETORY"}, + {"Assembled At", "JUICETORY"}, {"EEPROM location on Fabric", "BUDOKAN"}, {"X86 CPU MAC Base", "11:22:33:44:55:66"}, {"X86 CPU MAC Address Size", "258"}, diff --git a/fboss/qsfp_service/TransceiverManager.cpp b/fboss/qsfp_service/TransceiverManager.cpp index df2d852a506c4..e8abe910ffcbf 100644 --- a/fboss/qsfp_service/TransceiverManager.cpp +++ b/fboss/qsfp_service/TransceiverManager.cpp @@ -2769,7 +2769,7 @@ std::vector TransceiverManager::refreshTransceivers( XLOG(INFO) << "Finished refreshing " << nTransceivers << " transceivers"; } - publishTransceiversToFsdb(); + publishTransceiversToFsdb(transceiverIds); return transceiverIds; } diff --git a/fboss/qsfp_service/TransceiverManager.h b/fboss/qsfp_service/TransceiverManager.h index a80edba12c09f..9e9b25b7a8b60 100644 --- a/fboss/qsfp_service/TransceiverManager.h +++ b/fboss/qsfp_service/TransceiverManager.h @@ -137,7 +137,8 @@ class TransceiverManager { const std::unordered_set& transceivers); /// Called to publish transceivers after a refresh - virtual void publishTransceiversToFsdb() = 0; + virtual void publishTransceiversToFsdb( + const std::vector& ids) = 0; virtual int scanTransceiverPresence( std::unique_ptr> ids) = 0; diff --git a/fboss/qsfp_service/platforms/wedge/WedgeManager.cpp b/fboss/qsfp_service/platforms/wedge/WedgeManager.cpp index 0a82bfd9566e1..fc6ac79d5a60d 100644 --- a/fboss/qsfp_service/platforms/wedge/WedgeManager.cpp +++ b/fboss/qsfp_service/platforms/wedge/WedgeManager.cpp @@ -488,17 +488,32 @@ void WedgeManager::updateTcvrStateInFsdb( fsdbSyncManager_->updateTcvrState(tcvrID, std::move(newState)); } -void WedgeManager::publishTransceiversToFsdb() { +void WedgeManager::publishTransceiversToFsdb( + const std::vector& ids) { if (!FLAGS_publish_stats_to_fsdb) { return; } - // Get the transceiver info for all transceivers TcvrInfoMap tcvrInfos; getTransceiversInfo(tcvrInfos, std::make_unique>()); + + // Publish states on refreshed transceivers + for (int32_t id : ids.empty() ? folly::gen::range(0, getNumQsfpModules()) | + folly::gen::eachAs() | + folly::gen::as>() + : ids) { + auto iter = tcvrInfos.find(id); + if (iter == tcvrInfos.end()) { + continue; + } + updateTcvrStateInFsdb( + TransceiverID(id), std::move(*iter->second.tcvrState())); + } + + // Publish all stats (No deltas. Just publish the best we have for all + // transceivers.) QsfpFsdbSyncManager::TcvrStatsMap stats; - for (auto& [id, info] : tcvrInfos) { - updateTcvrStateInFsdb(TransceiverID(id), std::move(*info.tcvrState())); + for (const auto& [id, info] : tcvrInfos) { stats[id] = *info.tcvrStats(); } fsdbSyncManager_->updateTcvrStats(std::move(stats)); diff --git a/fboss/qsfp_service/platforms/wedge/WedgeManager.h b/fboss/qsfp_service/platforms/wedge/WedgeManager.h index c465b7e508c36..fc8f0456576ca 100644 --- a/fboss/qsfp_service/platforms/wedge/WedgeManager.h +++ b/fboss/qsfp_service/platforms/wedge/WedgeManager.h @@ -61,7 +61,8 @@ class WedgeManager : public TransceiverManager { return 16; } std::vector refreshTransceivers() override; - void publishTransceiversToFsdb() override; + void publishTransceiversToFsdb( + const std::vector& ids) override; int scanTransceiverPresence( std::unique_ptr> ids) override; diff --git a/fboss/thrift_cow/nodes/BUCK b/fboss/thrift_cow/nodes/BUCK index 6337591d89bc4..95150885b26f0 100644 --- a/fboss/thrift_cow/nodes/BUCK +++ b/fboss/thrift_cow/nodes/BUCK @@ -53,9 +53,9 @@ cpp_library( "//folly:conv", "//folly:fbstring", "//folly/json:dynamic", + "//thrift/lib/cpp2/folly_dynamic:folly_dynamic", "//thrift/lib/cpp2/protocol:protocol", "//thrift/lib/cpp2/protocol/detail:protocol_methods", - "//thrift/lib/cpp2/reflection:folly_dynamic", "//thrift/lib/cpp2/reflection:reflection", ], ) diff --git a/fboss/thrift_cow/nodes/ThriftListNode-inl.h b/fboss/thrift_cow/nodes/ThriftListNode-inl.h index a3fc2c6bc596a..42cfc877062f6 100644 --- a/fboss/thrift_cow/nodes/ThriftListNode-inl.h +++ b/fboss/thrift_cow/nodes/ThriftListNode-inl.h @@ -12,7 +12,7 @@ #include #include -#include +#include #include #include "fboss/agent/state/NodeBase-defs.h" #include "fboss/thrift_cow/nodes/Serializer.h" @@ -47,6 +47,8 @@ struct ThriftListFields { using StorageType = std::vector; using iterator = typename StorageType::iterator; using const_iterator = typename StorageType::const_iterator; + using Tag = apache::thrift::type::list< + apache::thrift::type::infer_tag>; // whether the contained type is another Cow node, or a primitive static constexpr bool HasChildNodes = ChildTraits::isChild::value; @@ -85,15 +87,15 @@ struct ThriftListFields { folly::dynamic toDynamic() const { folly::dynamic out; - apache::thrift::to_dynamic( - out, toThrift(), apache::thrift::dynamic_format::JSON_1); + facebook::thrift::to_dynamic( + out, toThrift(), facebook::thrift::dynamic_format::JSON_1); return out; } void fromDynamic(const folly::dynamic& value) { TType thrift; - apache::thrift::from_dynamic( - thrift, value, apache::thrift::dynamic_format::JSON_1); + facebook::thrift::from_dynamic( + thrift, value, facebook::thrift::dynamic_format::JSON_1); fromThrift(thrift); } diff --git a/fboss/thrift_cow/nodes/ThriftMapNode-inl.h b/fboss/thrift_cow/nodes/ThriftMapNode-inl.h index 897a8ca9479ce..fd4b1d190ac7c 100644 --- a/fboss/thrift_cow/nodes/ThriftMapNode-inl.h +++ b/fboss/thrift_cow/nodes/ThriftMapNode-inl.h @@ -12,8 +12,8 @@ #include #include +#include #include -#include #include #include "fboss/agent/state/NodeBase-defs.h" #include "fboss/thrift_cow/nodes/NodeUtils.h" @@ -60,6 +60,9 @@ struct ThriftMapFields { std::map; using iterator = typename StorageType::iterator; using const_iterator = typename StorageType::const_iterator; + using Tag = apache::thrift::type::map< + apache::thrift::type::infer_tag, + apache::thrift::type::infer_tag>; // whether the contained type is another Cow node, or a primitive node static constexpr bool HasChildNodes = ValueTraits::isChild::value; @@ -106,15 +109,15 @@ struct ThriftMapFields { folly::dynamic toDynamic() const { folly::dynamic out; - apache::thrift::to_dynamic( - out, toThrift(), apache::thrift::dynamic_format::JSON_1); + facebook::thrift::to_dynamic( + out, toThrift(), facebook::thrift::dynamic_format::JSON_1); return out; } void fromDynamic(const folly::dynamic& value) { TType thrift; - apache::thrift::from_dynamic( - thrift, value, apache::thrift::dynamic_format::JSON_1); + facebook::thrift::from_dynamic( + thrift, value, facebook::thrift::dynamic_format::JSON_1); fromThrift(thrift); } #endif diff --git a/fboss/thrift_cow/nodes/ThriftPrimitiveNode-inl.h b/fboss/thrift_cow/nodes/ThriftPrimitiveNode-inl.h index 28ae636d94d82..d5da657ecabd1 100644 --- a/fboss/thrift_cow/nodes/ThriftPrimitiveNode-inl.h +++ b/fboss/thrift_cow/nodes/ThriftPrimitiveNode-inl.h @@ -12,8 +12,8 @@ // TODO: replace with our own ThriftTraverseResult #include +#include #include -#include #include #include "fboss/agent/state/NodeBase-defs.h" #include "fboss/fsdb/if/gen-cpp2/fsdb_oper_types.h" @@ -90,8 +90,8 @@ class ThriftPrimitiveNode : public thrift_cow::Serializable { folly::dynamic toFollyDynamic() const { folly::dynamic out; - apache::thrift::to_dynamic( - out, toThrift(), apache::thrift::dynamic_format::JSON_1); + facebook::thrift::to_dynamic( + out, toThrift(), facebook::thrift::dynamic_format::JSON_1); return out; } @@ -99,8 +99,8 @@ class ThriftPrimitiveNode : public thrift_cow::Serializable { auto fromFollyDynamic(const folly::dynamic& value) -> std::enable_if_t { ThriftType thrift; - apache::thrift::from_dynamic( - thrift, value, apache::thrift::dynamic_format::JSON_1); + facebook::thrift::from_dynamic( + thrift, value, facebook::thrift::dynamic_format::JSON_1); fromThrift(thrift); } diff --git a/fboss/thrift_cow/nodes/ThriftSetNode-inl.h b/fboss/thrift_cow/nodes/ThriftSetNode-inl.h index a6db1f284357d..1af943f3742fb 100644 --- a/fboss/thrift_cow/nodes/ThriftSetNode-inl.h +++ b/fboss/thrift_cow/nodes/ThriftSetNode-inl.h @@ -13,8 +13,8 @@ #include #include #include +#include #include -#include #include #include "fboss/agent/state/NodeBase-defs.h" #include "fboss/thrift_cow/nodes/Serializer.h" @@ -50,6 +50,8 @@ struct ThriftSetFields { using StorageType = std::unordered_set; using iterator = typename StorageType::iterator; using const_iterator = typename StorageType::const_iterator; + using Tag = apache::thrift::type::set< + apache::thrift::type::infer_tag>; // constructors: // One takes a thrift type directly, one starts with empty vector @@ -86,15 +88,15 @@ struct ThriftSetFields { folly::dynamic toDynamic() const { folly::dynamic out; - apache::thrift::to_dynamic( - out, toThrift(), apache::thrift::dynamic_format::JSON_1); + facebook::thrift::to_dynamic( + out, toThrift(), facebook::thrift::dynamic_format::JSON_1); return out; } void fromDynamic(const folly::dynamic& value) { TType thrift; - apache::thrift::from_dynamic( - thrift, value, apache::thrift::dynamic_format::JSON_1); + facebook::thrift::from_dynamic( + thrift, value, facebook::thrift::dynamic_format::JSON_1); fromThrift(thrift); } diff --git a/fboss/thrift_cow/nodes/ThriftStructNode-inl.h b/fboss/thrift_cow/nodes/ThriftStructNode-inl.h index 1b82d16396b36..ab22d3e59887a 100644 --- a/fboss/thrift_cow/nodes/ThriftStructNode-inl.h +++ b/fboss/thrift_cow/nodes/ThriftStructNode-inl.h @@ -14,8 +14,8 @@ #include #include #include +#include #include -#include #include #include "fboss/agent/state/NodeBase-defs.h" #include "fboss/fsdb/if/gen-cpp2/fsdb_oper_types.h" @@ -228,15 +228,15 @@ struct ThriftStructFields { folly::dynamic toDynamic() const { folly::dynamic out; - apache::thrift::to_dynamic( - out, toThrift(), apache::thrift::dynamic_format::JSON_1); + facebook::thrift::to_dynamic( + out, toThrift(), facebook::thrift::dynamic_format::JSON_1); return out; } void fromDynamic(const folly::dynamic& value) { TType thrift; - apache::thrift::from_dynamic( - thrift, value, apache::thrift::dynamic_format::JSON_1); + facebook::thrift::from_dynamic( + thrift, value, facebook::thrift::dynamic_format::JSON_1); fromThrift(thrift); } diff --git a/fboss/thrift_cow/nodes/ThriftUnionNode-inl.h b/fboss/thrift_cow/nodes/ThriftUnionNode-inl.h index 5f42b6a4da4fb..1a400fed16573 100644 --- a/fboss/thrift_cow/nodes/ThriftUnionNode-inl.h +++ b/fboss/thrift_cow/nodes/ThriftUnionNode-inl.h @@ -12,7 +12,7 @@ #include #include -#include +#include #include #include "fboss/agent/state/NodeBase-defs.h" #include "fboss/thrift_cow/nodes/Types.h" @@ -293,15 +293,15 @@ struct ThriftUnionFields { folly::dynamic toDynamic() const { folly::dynamic out; - apache::thrift::to_dynamic( - out, toThrift(), apache::thrift::dynamic_format::JSON_1); + facebook::thrift::to_dynamic( + out, toThrift(), facebook::thrift::dynamic_format::JSON_1); return out; } void fromDynamic(const folly::dynamic& value) { TType thrift; - apache::thrift::from_dynamic( - thrift, value, apache::thrift::dynamic_format::JSON_1); + facebook::thrift::from_dynamic( + thrift, value, facebook::thrift::dynamic_format::JSON_1); fromThrift(thrift); } #endif diff --git a/fboss/thrift_cow/nodes/tests/BUCK b/fboss/thrift_cow/nodes/tests/BUCK index 7758f57ae69e4..b6f63a52150db 100644 --- a/fboss/thrift_cow/nodes/tests/BUCK +++ b/fboss/thrift_cow/nodes/tests/BUCK @@ -36,8 +36,8 @@ cpp_unittest( "//fboss/thrift_cow/nodes:nodes", "//fboss/thrift_cow/nodes:serializer", "//fboss/thrift_cow/visitors/tests:visitor_test_utils", + "//thrift/lib/cpp2/folly_dynamic:folly_dynamic", "//thrift/lib/cpp2/protocol:protocol", - "//thrift/lib/cpp2/reflection:folly_dynamic", "//thrift/lib/cpp2/reflection:reflection", "//thrift/lib/cpp2/reflection:testing", ], diff --git a/fboss/thrift_cow/nodes/tests/ThriftListNodeTests.cpp b/fboss/thrift_cow/nodes/tests/ThriftListNodeTests.cpp index 9d266288d885e..36c1eada05fc0 100644 --- a/fboss/thrift_cow/nodes/tests/ThriftListNodeTests.cpp +++ b/fboss/thrift_cow/nodes/tests/ThriftListNodeTests.cpp @@ -9,8 +9,8 @@ */ #include +#include #include -#include #include #include #include "fboss/agent/gen-cpp2/switch_config_fatal_types.h" @@ -365,15 +365,15 @@ TEST(ThriftListNodeTests, ThriftListNodeStructsVisit) { auto result = visitPath(fields, path.begin(), path.end(), f); ASSERT_EQ(result, ThriftTraverseResult::OK); folly::dynamic expected; - apache::thrift::to_dynamic( - expected, data[0], apache::thrift::dynamic_format::JSON_1); + facebook::thrift::to_dynamic( + expected, data[0], facebook::thrift::dynamic_format::JSON_1); ASSERT_EQ(out, expected); path = {"1"}; result = visitPath(fields, path.begin(), path.end(), f); ASSERT_EQ(result, ThriftTraverseResult::OK); - apache::thrift::to_dynamic( - expected, data[1], apache::thrift::dynamic_format::JSON_1); + facebook::thrift::to_dynamic( + expected, data[1], facebook::thrift::dynamic_format::JSON_1); ASSERT_EQ(out, expected); path = {"0", "nonexistent"}; @@ -407,19 +407,19 @@ TEST(ThriftListNodeTests, ThriftListNodeStructsVisitMutable) { auto result = visitPath(fields, path.begin(), path.end(), read); ASSERT_EQ(result, ThriftTraverseResult::OK); folly::dynamic expected; - apache::thrift::to_dynamic( - expected, data[0], apache::thrift::dynamic_format::JSON_1); + facebook::thrift::to_dynamic( + expected, data[0], facebook::thrift::dynamic_format::JSON_1); ASSERT_EQ(out, expected); path = {"1"}; result = visitPath(fields, path.begin(), path.end(), read); ASSERT_EQ(result, ThriftTraverseResult::OK); - apache::thrift::to_dynamic( - expected, data[1], apache::thrift::dynamic_format::JSON_1); + facebook::thrift::to_dynamic( + expected, data[1], facebook::thrift::dynamic_format::JSON_1); ASSERT_EQ(out, expected); - apache::thrift::to_dynamic( - toWrite, buildPortRange(1, 2), apache::thrift::dynamic_format::JSON_1); + facebook::thrift::to_dynamic( + toWrite, buildPortRange(1, 2), facebook::thrift::dynamic_format::JSON_1); path = {"0"}; result = visitPath(fields, path.begin(), path.end(), write); diff --git a/fboss/thrift_cow/nodes/tests/ThriftMapNodeTests.cpp b/fboss/thrift_cow/nodes/tests/ThriftMapNodeTests.cpp index 01d011c5a7a69..a47418e3e41f9 100644 --- a/fboss/thrift_cow/nodes/tests/ThriftMapNodeTests.cpp +++ b/fboss/thrift_cow/nodes/tests/ThriftMapNodeTests.cpp @@ -9,8 +9,8 @@ */ #include +#include #include -#include #include #include #include "fboss/agent/gen-cpp2/switch_config_fatal_types.h" @@ -392,8 +392,10 @@ TEST(ThriftMapNodeTests, ThriftMapNodeStructsVisit) { auto result = visitPath(node, path.begin(), path.end(), f); ASSERT_EQ(result, ThriftTraverseResult::OK); folly::dynamic expected; - apache::thrift::to_dynamic( - expected, data[TestEnum::FIRST], apache::thrift::dynamic_format::JSON_1); + facebook::thrift::to_dynamic( + expected, + data[TestEnum::FIRST], + facebook::thrift::dynamic_format::JSON_1); ASSERT_EQ(out, expected); // visit by enum value should also work @@ -405,8 +407,10 @@ TEST(ThriftMapNodeTests, ThriftMapNodeStructsVisit) { path = {"SECOND"}; result = visitPath(node, path.begin(), path.end(), f); ASSERT_EQ(result, ThriftTraverseResult::OK); - apache::thrift::to_dynamic( - expected, data[TestEnum::SECOND], apache::thrift::dynamic_format::JSON_1); + facebook::thrift::to_dynamic( + expected, + data[TestEnum::SECOND], + facebook::thrift::dynamic_format::JSON_1); ASSERT_EQ(out, expected); path = {"2"}; @@ -466,15 +470,19 @@ TEST(ThriftMapNodeTests, ThriftMapNodeStructsVisitMutable) { auto result = visitPath(node, path.begin(), path.end(), read); ASSERT_EQ(result, ThriftTraverseResult::OK); folly::dynamic expected; - apache::thrift::to_dynamic( - expected, data[TestEnum::FIRST], apache::thrift::dynamic_format::JSON_1); + facebook::thrift::to_dynamic( + expected, + data[TestEnum::FIRST], + facebook::thrift::dynamic_format::JSON_1); ASSERT_EQ(out, expected); path = {"SECOND"}; result = visitPath(node, path.begin(), path.end(), read); ASSERT_EQ(result, ThriftTraverseResult::OK); - apache::thrift::to_dynamic( - expected, data[TestEnum::SECOND], apache::thrift::dynamic_format::JSON_1); + facebook::thrift::to_dynamic( + expected, + data[TestEnum::SECOND], + facebook::thrift::dynamic_format::JSON_1); ASSERT_EQ(out, expected); path = {"THIRD"}; @@ -492,8 +500,8 @@ TEST(ThriftMapNodeTests, ThriftMapNodeStructsVisitMutable) { ASSERT_EQ(out, 1000); path = {"FIRST"}; - apache::thrift::to_dynamic( - toWrite, buildPortRange(1, 2), apache::thrift::dynamic_format::JSON_1); + facebook::thrift::to_dynamic( + toWrite, buildPortRange(1, 2), facebook::thrift::dynamic_format::JSON_1); result = visitPath(node, path.begin(), path.end(), write); ASSERT_EQ(result, ThriftTraverseResult::OK); result = visitPath(node, path.begin(), path.end(), read); diff --git a/fboss/thrift_cow/nodes/tests/ThriftSetNodeTests.cpp b/fboss/thrift_cow/nodes/tests/ThriftSetNodeTests.cpp index bb25701df6a85..e5ca5006025b3 100644 --- a/fboss/thrift_cow/nodes/tests/ThriftSetNodeTests.cpp +++ b/fboss/thrift_cow/nodes/tests/ThriftSetNodeTests.cpp @@ -9,8 +9,8 @@ */ #include +#include #include -#include #include #include #include "fboss/agent/gen-cpp2/switch_config_fatal_types.h" diff --git a/fboss/thrift_cow/nodes/tests/ThriftStructNodeTests.cpp b/fboss/thrift_cow/nodes/tests/ThriftStructNodeTests.cpp index 446da9c99b879..75dcf91621e5a 100644 --- a/fboss/thrift_cow/nodes/tests/ThriftStructNodeTests.cpp +++ b/fboss/thrift_cow/nodes/tests/ThriftStructNodeTests.cpp @@ -9,8 +9,8 @@ */ #include +#include #include -#include #include #include #include "fboss/agent/gen-cpp2/switch_config_fatal_types.h" diff --git a/fboss/thrift_cow/storage/tests/BUCK b/fboss/thrift_cow/storage/tests/BUCK index a407f5fb153fd..35ce09effc360 100644 --- a/fboss/thrift_cow/storage/tests/BUCK +++ b/fboss/thrift_cow/storage/tests/BUCK @@ -23,7 +23,7 @@ cpp_unittest( "//folly:string", "//folly/json:dynamic", "//folly/logging:logging", + "//thrift/lib/cpp2/folly_dynamic:folly_dynamic", "//thrift/lib/cpp2/protocol:protocol", - "//thrift/lib/cpp2/reflection:folly_dynamic", ], ) diff --git a/fboss/thrift_cow/storage/tests/CowStorageMgrTests.cpp b/fboss/thrift_cow/storage/tests/CowStorageMgrTests.cpp index 10b71b74e998f..21047fc0c55bb 100644 --- a/fboss/thrift_cow/storage/tests/CowStorageMgrTests.cpp +++ b/fboss/thrift_cow/storage/tests/CowStorageMgrTests.cpp @@ -5,9 +5,9 @@ #include #include +#include #include #include -#include #include "fboss/fsdb/tests/gen-cpp2/thriftpath_test_fatal_types.h" #include "fboss/fsdb/tests/gen-cpp2/thriftpath_test_types.h" #include "fboss/fsdb/tests/gen-cpp2/thriftpath_test_types_custom_protocol.h" @@ -30,8 +30,8 @@ TestStruct createTestStruct() { dynamic::object("3", dynamic::object("min", 100)("max", 200)))( "enumSet", dynamic::array(1))("integralSet", dynamic::array(5)); - return apache::thrift::from_dynamic( - testDyn, apache::thrift::dynamic_format::JSON_1); + return facebook::thrift::from_dynamic( + testDyn, facebook::thrift::dynamic_format::JSON_1); } CowStorage createTestStorage() { diff --git a/fboss/thrift_cow/storage/tests/CowStorageTests.cpp b/fboss/thrift_cow/storage/tests/CowStorageTests.cpp index 8f6d5c0213ed2..639510a7bf58d 100644 --- a/fboss/thrift_cow/storage/tests/CowStorageTests.cpp +++ b/fboss/thrift_cow/storage/tests/CowStorageTests.cpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include "fboss/fsdb/oper/ExtendedPathBuilder.h" #include "fboss/fsdb/tests/gen-cpp2-thriftpath/thriftpath_test.h" // @manual=//fboss/fsdb/tests:thriftpath_test_thrift-cpp2-thriftpath #include "fboss/fsdb/tests/gen-cpp2/thriftpath_test_fatal_types.h" @@ -33,8 +33,8 @@ dynamic createTestDynamic() { TestStruct createTestStruct() { auto testDyn = createTestDynamic(); - return apache::thrift::from_dynamic( - testDyn, apache::thrift::dynamic_format::JSON_1); + return facebook::thrift::from_dynamic( + testDyn, facebook::thrift::dynamic_format::JSON_1); } TestStruct createTestStructForExtendedTests() { @@ -45,8 +45,8 @@ TestStruct createTestStructForExtendedTests() { testDyn["setOfI32"].push_back(i); } - return apache::thrift::from_dynamic( - testDyn, apache::thrift::dynamic_format::JSON_1); + return facebook::thrift::from_dynamic( + testDyn, facebook::thrift::dynamic_format::JSON_1); } template @@ -79,8 +79,8 @@ TEST(CowStorageTests, GetThrift) { thriftpath::RootThriftPath root; - auto testStruct = apache::thrift::from_dynamic( - createTestDynamic(), apache::thrift::dynamic_format::JSON_1); + auto testStruct = facebook::thrift::from_dynamic( + createTestDynamic(), facebook::thrift::dynamic_format::JSON_1); auto storage = CowStorage(testStruct); EXPECT_EQ(storage.get(root.tx()).value(), true); @@ -96,8 +96,8 @@ TEST(CowStorageTests, GetEncoded) { thriftpath::RootThriftPath root; - auto testStruct = apache::thrift::from_dynamic( - createTestDynamic(), apache::thrift::dynamic_format::JSON_1); + auto testStruct = facebook::thrift::from_dynamic( + createTestDynamic(), facebook::thrift::dynamic_format::JSON_1); auto storage = CowStorage(testStruct); auto result = storage.get_encoded(root.tx(), OperProtocol::SIMPLE_JSON); @@ -137,8 +137,8 @@ TEST(CowStorageTests, GetEncodedMetadata) { thriftpath::RootThriftPath root; - auto testStruct = apache::thrift::from_dynamic( - createTestDynamic(), apache::thrift::dynamic_format::JSON_1); + auto testStruct = facebook::thrift::from_dynamic( + createTestDynamic(), facebook::thrift::dynamic_format::JSON_1); auto storage = CowStorage(testStruct); auto result = storage.get_encoded(root.tx(), OperProtocol::SIMPLE_JSON); @@ -183,8 +183,8 @@ TEST(CowStorageTests, SetThrift) { thriftpath::RootThriftPath root; - auto testStruct = apache::thrift::from_dynamic( - createTestDynamic(), apache::thrift::dynamic_format::JSON_1); + auto testStruct = facebook::thrift::from_dynamic( + createTestDynamic(), facebook::thrift::dynamic_format::JSON_1); auto storage = CowStorage(testStruct); EXPECT_EQ(storage.get(root.tx()).value(), true); @@ -217,8 +217,8 @@ TEST(CowStorageTests, AddThrift) { thriftpath::RootThriftPath root; - auto testStruct = apache::thrift::from_dynamic( - createTestDynamic(), apache::thrift::dynamic_format::JSON_1); + auto testStruct = facebook::thrift::from_dynamic( + createTestDynamic(), facebook::thrift::dynamic_format::JSON_1); auto storage = CowStorage(testStruct); EXPECT_EQ(storage.get(root.tx()).value(), true); @@ -256,8 +256,8 @@ TEST(CowStorageTests, AddDynamic) { thriftpath::RootThriftPath root; - auto testStruct = apache::thrift::from_dynamic( - createTestDynamic(), apache::thrift::dynamic_format::JSON_1); + auto testStruct = facebook::thrift::from_dynamic( + createTestDynamic(), facebook::thrift::dynamic_format::JSON_1); auto storage = CowStorage(testStruct); EXPECT_EQ(storage.get(root.tx()).value(), true); @@ -272,8 +272,8 @@ TEST(CowStorageTests, RemoveThrift) { thriftpath::RootThriftPath root; - auto testStruct = apache::thrift::from_dynamic( - createTestDynamic(), apache::thrift::dynamic_format::JSON_1); + auto testStruct = facebook::thrift::from_dynamic( + createTestDynamic(), facebook::thrift::dynamic_format::JSON_1); auto storage = CowStorage(testStruct); EXPECT_EQ(storage.get(root.tx()).value(), true); @@ -329,8 +329,8 @@ TEST(CowStorageTests, PatchDelta) { thriftpath::RootThriftPath root; - auto testStruct = apache::thrift::from_dynamic( - createTestDynamic(), apache::thrift::dynamic_format::JSON_1); + auto testStruct = facebook::thrift::from_dynamic( + createTestDynamic(), facebook::thrift::dynamic_format::JSON_1); auto storage = CowStorage(testStruct); // publish to ensure we can patch published storage diff --git a/fboss/thrift_cow/visitors/tests/BUCK b/fboss/thrift_cow/visitors/tests/BUCK index 158cbbe7a57ba..410597effadd4 100644 --- a/fboss/thrift_cow/visitors/tests/BUCK +++ b/fboss/thrift_cow/visitors/tests/BUCK @@ -16,7 +16,7 @@ cpp_library( "//fboss/thrift_cow/nodes/tests:test-cpp2-reflection", "//fboss/thrift_cow/visitors:visitors", "//folly/json:dynamic", - "//thrift/lib/cpp2/reflection:folly_dynamic", + "//thrift/lib/cpp2/folly_dynamic:folly_dynamic", ], ) @@ -48,6 +48,6 @@ cpp_unittest( "//folly:string", "//folly/json:dynamic", "//folly/logging:logging", - "//thrift/lib/cpp2/reflection:folly_dynamic", + "//thrift/lib/cpp2/folly_dynamic:folly_dynamic", ], ) diff --git a/fboss/thrift_cow/visitors/tests/DeltaVisitorTests.cpp b/fboss/thrift_cow/visitors/tests/DeltaVisitorTests.cpp index 0278e3023f90a..3898af2e6bd8a 100644 --- a/fboss/thrift_cow/visitors/tests/DeltaVisitorTests.cpp +++ b/fboss/thrift_cow/visitors/tests/DeltaVisitorTests.cpp @@ -8,7 +8,7 @@ #include #include -#include +#include #include "fboss/thrift_cow/nodes/Types.h" #include "fboss/thrift_cow/nodes/tests/gen-cpp2/test_fatal_types.h" diff --git a/fboss/thrift_cow/visitors/tests/ExtendedPathVisitorTests.cpp b/fboss/thrift_cow/visitors/tests/ExtendedPathVisitorTests.cpp index 39d89d6e2fd3c..34736d7f679f8 100644 --- a/fboss/thrift_cow/visitors/tests/ExtendedPathVisitorTests.cpp +++ b/fboss/thrift_cow/visitors/tests/ExtendedPathVisitorTests.cpp @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include "fboss/agent/gen-cpp2/switch_config_types.h" #include "fboss/fsdb/oper/ExtendedPathBuilder.h" @@ -45,8 +45,8 @@ TestStruct createTestStruct() { dynamic::object("min", 3)("max", 4)); } - return apache::thrift::from_dynamic( - testDyn, apache::thrift::dynamic_format::JSON_1); + return facebook::thrift::from_dynamic( + testDyn, facebook::thrift::dynamic_format::JSON_1); } } // namespace diff --git a/fboss/thrift_cow/visitors/tests/PathVisitorTests.cpp b/fboss/thrift_cow/visitors/tests/PathVisitorTests.cpp index cf89b6cea30fe..7c6ada6271568 100644 --- a/fboss/thrift_cow/visitors/tests/PathVisitorTests.cpp +++ b/fboss/thrift_cow/visitors/tests/PathVisitorTests.cpp @@ -8,7 +8,7 @@ #include #include -#include +#include #include "fboss/agent/gen-cpp2/switch_config_types.h" #include "fboss/thrift_cow/nodes/Types.h" #include "fboss/thrift_cow/nodes/tests/gen-cpp2/test_fatal_types.h" @@ -51,8 +51,8 @@ TEST(PathVisitorTests, AccessFieldInContainer) { cfg::L4PortRange got; auto processPath = pvlambda([&got](auto& node, auto begin, auto end) { EXPECT_EQ(begin, end); - got = apache::thrift::from_dynamic( - node.toFollyDynamic(), apache::thrift::dynamic_format::JSON_1); + got = facebook::thrift::from_dynamic( + node.toFollyDynamic(), facebook::thrift::dynamic_format::JSON_1); }); std::vector path{"mapOfEnumToStruct", "3"}; diff --git a/fboss/thrift_cow/visitors/tests/RecurseVisitorTests.cpp b/fboss/thrift_cow/visitors/tests/RecurseVisitorTests.cpp index 85e1bbbe2d680..633551d3e57c0 100644 --- a/fboss/thrift_cow/visitors/tests/RecurseVisitorTests.cpp +++ b/fboss/thrift_cow/visitors/tests/RecurseVisitorTests.cpp @@ -7,7 +7,7 @@ #include #include -#include +#include #include "fboss/thrift_cow/nodes/Types.h" #include "fboss/thrift_cow/nodes/tests/gen-cpp2/test_fatal_types.h" @@ -40,8 +40,8 @@ folly::dynamic createTestDynamic() { } TestStruct createTestStruct(folly::dynamic testDyn) { - return apache::thrift::from_dynamic( - std::move(testDyn), apache::thrift::dynamic_format::JSON_1); + return facebook::thrift::from_dynamic( + std::move(testDyn), facebook::thrift::dynamic_format::JSON_1); } } // namespace diff --git a/fboss/thrift_cow/visitors/tests/VisitorTestUtils.cpp b/fboss/thrift_cow/visitors/tests/VisitorTestUtils.cpp index d827474a28641..8c0b791c88391 100644 --- a/fboss/thrift_cow/visitors/tests/VisitorTestUtils.cpp +++ b/fboss/thrift_cow/visitors/tests/VisitorTestUtils.cpp @@ -2,7 +2,7 @@ #include "fboss/thrift_cow/visitors/tests/VisitorTestUtils.h" #include -#include +#include namespace facebook::fboss::thrift_cow { @@ -15,8 +15,8 @@ TestStruct createSimpleTestStruct() { "mapOfEnumToStruct", dynamic::object("3", dynamic::object("min", 100)("max", 200))); - return apache::thrift::from_dynamic( - testDyn, apache::thrift::dynamic_format::JSON_1); + return facebook::thrift::from_dynamic( + testDyn, facebook::thrift::dynamic_format::JSON_1); } } // namespace facebook::fboss::thrift_cow diff --git a/fboss/thrift_visitors/tests/ThriftLeafVisitorTests.cpp b/fboss/thrift_visitors/tests/ThriftLeafVisitorTests.cpp index 684af24e93410..cd6a308659c37 100644 --- a/fboss/thrift_visitors/tests/ThriftLeafVisitorTests.cpp +++ b/fboss/thrift_visitors/tests/ThriftLeafVisitorTests.cpp @@ -39,7 +39,7 @@ TEST(ThriftLeafVisitorTests, TraverseOk) { auto addLeaf = [&](auto&& path, Tag, auto&& node) { folly::dynamic dyn; - facebook::thrift::to_dynamic( + facebook::thrift::to_dynamic( dyn, node, facebook::thrift::dynamic_format::JSON_1); leaves.emplace_back(path, dyn); }; diff --git a/fboss/util/BUCK b/fboss/util/BUCK index 93309b3234971..4e2d98eda220f 100644 --- a/fboss/util/BUCK +++ b/fboss/util/BUCK @@ -115,6 +115,13 @@ cpp_library( ], ) +cpp_library( + name = "logging", + headers = [ + "Logging.h", + ], +) + cpp_binary( name = "nic_util", srcs = [ diff --git a/fboss/util/Logging.h b/fboss/util/Logging.h new file mode 100644 index 0000000000000..3994938f13d75 --- /dev/null +++ b/fboss/util/Logging.h @@ -0,0 +1,11 @@ +// (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary. + +#pragma once + +namespace facebook::fboss { + +auto constexpr kDsfCtrlLogPrefix = "DSF_CTRL_EVENT: "; + +auto constexpr kNetworkEventLogPrefix = "[NEL]"; + +} // namespace facebook::fboss diff --git a/shim/BUCK b/shim/BUCK index 56fe035920b66..e25618a0730b1 100644 --- a/shim/BUCK +++ b/shim/BUCK @@ -12,6 +12,12 @@ oncall("open_source") system_cxx_toolchain( name = "cxx", cxx_flags = ["-std=c++20"], + link_flags = select({ + "DEFAULT": [], + "prelude//os:linux": [ + "-latomic", + ], + }), visibility = ["PUBLIC"], ) diff --git a/shim/shims.bzl b/shim/shims.bzl index c99042b16c124..f48e8583cbd47 100644 --- a/shim/shims.bzl +++ b/shim/shims.bzl @@ -49,6 +49,12 @@ _HEADER_SUFFIXES = ( "-defs.tcc", ) +CPP_UNITTEST_MAIN_DEP = "shim//third-party/googletest:cpp_unittest_main" +CPP_UNITTEST_LIB_DEPS = [ + "shim//third-party/googletest:gtest", + "shim//third-party/googletest:gmock", +] + def _get_headers_from_sources(srcs): """ Return the headers likely associated with the given sources @@ -198,14 +204,12 @@ def cpp_unittest( extract_helper_lib = None, compiler_specific_flags = None, default_strip_mode = None, - srcs = [], **kwargs): _unused = (supports_static_listing, allocator, owner, tags, emails, extract_helper_lib, compiler_specific_flags, default_strip_mode) # @unused - srcs = srcs + ["shim//third-party/googletest:gtest_main.cpp"] + deps = deps + [CPP_UNITTEST_MAIN_DEP] + CPP_UNITTEST_LIB_DEPS prelude.cxx_test( deps = _maybe_select_map(deps + external_deps_to_targets(external_deps), _fix_deps), visibility = visibility, - srcs = srcs, **kwargs ) diff --git a/shim/third-party/boost/BUCK b/shim/third-party/boost/BUCK index c2033cba3571c..85c2fd684ee68 100644 --- a/shim/third-party/boost/BUCK +++ b/shim/third-party/boost/BUCK @@ -5,34 +5,27 @@ # License, Version 2.0 found in the LICENSE-APACHE file in the root directory # of this source tree. -load("@shim//third-party:third_party.bzl", "third_party_library") -load("@shim//third-party/boost:boost.bzl", "boost_libs") +load("@shim//third-party/boost:boost.bzl", "boost_header_only", "boost_libs") oncall("open_source") boost_libs([ "container", - "range", - "algorithm", - "regex", - "program_options", - "filesystem", - "multi_index", "context", - "variant", - "lexical_cast", + "filesystem", + "program_options", "random", - "sort", - "interprocess", + "regex", + "thread", ]) -# Empty target to satisfy some build rules: -third_party_library( - name = "boost_preprocessor", - homebrew_package_name = "boost", -) - -third_party_library( - name = "boost_thread", - homebrew_package_name = "boost", -) +boost_header_only([ + "algorithm", + "interprocess", + "lexical_cast", + "multi_index", + "preprocessor", + "range", + "sort", + "variant", +]) diff --git a/shim/third-party/boost/boost.bzl b/shim/third-party/boost/boost.bzl index 51a8aef411fa5..30f880b3e45df 100644 --- a/shim/third-party/boost/boost.bzl +++ b/shim/third-party/boost/boost.bzl @@ -10,12 +10,30 @@ load("@shim//third-party:third_party.bzl", "third_party_library") def boost_libs(xs): third_party_library( name = "boost", - ubuntu_package_name = "libboost-all-dev", - homebrew_package_name = "boost", + repo_package_names = { + "fedora": "boost-devel", + "homebrew": "boost", + "ubuntu": "libboost-all-dev", + }, ) for x in xs: third_party_library( name = "boost_{}".format(x), - homebrew_package_name = "boost", - homebrew_linker_flags = ["-lboost_{}".format(x)], + repo_package_names = { + "fedora": "boost-devel", + "homebrew": "boost", + "ubuntu": "libboost-all-dev", + }, + linker_flags = ["-lboost_{}".format(x)], + ) + +def boost_header_only(xs): + for x in xs: + third_party_library( + name = "boost_{}".format(x), + repo_package_names = { + "fedora": "boost-devel", + "homebrew": "boost", + "ubuntu": "libboost-all-dev", + }, ) diff --git a/shim/third-party/brotli/BUCK b/shim/third-party/brotli/BUCK index 94da07c9d176a..1eb22fa559dab 100644 --- a/shim/third-party/brotli/BUCK +++ b/shim/third-party/brotli/BUCK @@ -11,12 +11,20 @@ oncall("open_source") third_party_library( name = "brotli_decode", - homebrew_package_name = "brotli", pkgconfig_name = "libbrotlidec", + repo_package_names = { + "fedora": "brotli-devel", + "homebrew": "brotli", + "ubuntu": "libbrotli-dev", + }, ) third_party_library( name = "brotli_encode", - homebrew_package_name = "brotli", pkgconfig_name = "libbrotlienc", + repo_package_names = { + "fedora": "brotli-devel", + "homebrew": "brotli", + "ubuntu": "libbrotli-dev", + }, ) diff --git a/shim/third-party/bzip2/BUCK b/shim/third-party/bzip2/BUCK index 8c97c210f1857..bc5ef8afdaff2 100644 --- a/shim/third-party/bzip2/BUCK +++ b/shim/third-party/bzip2/BUCK @@ -11,5 +11,13 @@ oncall("open_source") third_party_library( name = "bz2", - homebrew_package_name = "bzip2", + pkgconfig_fallback = struct( + linker_flags = ["-lbz2"], + ), + pkgconfig_name = "bzip2", + repo_package_names = { + "fedora": "bzip2-devel", + "homebrew": "bzip2", + "ubuntu": "libbz2-dev", + }, ) diff --git a/shim/third-party/double_conversion/BUCK b/shim/third-party/double_conversion/BUCK index 77f4ecdc3a433..9e4722e70d688 100644 --- a/shim/third-party/double_conversion/BUCK +++ b/shim/third-party/double_conversion/BUCK @@ -11,6 +11,10 @@ oncall("open_source") third_party_library( name = "double_conversion", - homebrew_linker_flags = ["-ldouble-conversion"], - homebrew_package_name = "double-conversion", + linker_flags = ["-ldouble-conversion"], + repo_package_names = { + "fedora": "double-conversion-devel", + "homebrew": "double-conversion", + "ubuntu": "libdouble-conversion-dev", + }, ) diff --git a/shim/third-party/fast_float/BUCK b/shim/third-party/fast_float/BUCK new file mode 100644 index 0000000000000..8b2afa8592026 --- /dev/null +++ b/shim/third-party/fast_float/BUCK @@ -0,0 +1,19 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under both the MIT license found in the +# LICENSE-MIT file in the root directory of this source tree and the Apache +# License, Version 2.0 found in the LICENSE-APACHE file in the root directory +# of this source tree. + +load("@shim//third-party:third_party.bzl", "third_party_library") + +oncall("open_source") + +third_party_library( + name = "fast_float", + repo_package_names = { + "fedora": "fast_float-devel", + "homebrew": "fast_float", + "ubuntu": "libfast-float-dev", + }, +) diff --git a/shim/third-party/fmt/BUCK b/shim/third-party/fmt/BUCK index 13e98e8832832..167afa9ff771c 100644 --- a/shim/third-party/fmt/BUCK +++ b/shim/third-party/fmt/BUCK @@ -11,6 +11,10 @@ oncall("open_source") third_party_library( name = "fmt", - homebrew_package_name = "fmt", pkgconfig_name = "fmt", + repo_package_names = { + "fedora": "fmt-devel", + "homebrew": "fmt", + "ubuntu": "libfmt-dev", + }, ) diff --git a/shim/third-party/gflags/BUCK b/shim/third-party/gflags/BUCK index 9251d18ee52c6..d8d5a6266c90f 100644 --- a/shim/third-party/gflags/BUCK +++ b/shim/third-party/gflags/BUCK @@ -11,6 +11,10 @@ oncall("open_source") third_party_library( name = "gflags", - homebrew_package_name = "gflags", pkgconfig_name = "gflags", + repo_package_names = { + "fedora": "gflags-devel", + "homebrew": "gflags", + "ubuntu": "libgflags-dev", + }, ) diff --git a/shim/third-party/glog/BUCK b/shim/third-party/glog/BUCK index adf3bce681963..ea0ba676ea773 100644 --- a/shim/third-party/glog/BUCK +++ b/shim/third-party/glog/BUCK @@ -11,8 +11,13 @@ oncall("open_source") third_party_library( name = "glog", - homebrew_package_name = "glog", pkgconfig_name = "libglog", - ubuntu_package_name = "libgoogle-glog-dev", - deps = ["shim//third-party/gflags:gflags"], + repo_package_names = { + "fedora": "glog-devel", + "homebrew": "glog", + "ubuntu": "libgoogle-glog-dev", + }, + deps = [ + "shim//third-party/gflags:gflags", + ], ) diff --git a/shim/third-party/googletest/BUCK b/shim/third-party/googletest/BUCK index dbd3249578b43..56b02040cb863 100644 --- a/shim/third-party/googletest/BUCK +++ b/shim/third-party/googletest/BUCK @@ -5,23 +5,33 @@ # License, Version 2.0 found in the LICENSE-APACHE file in the root directory # of this source tree. -load("@shim//build_defs:export_files.bzl", "export_file") load("@shim//third-party:third_party.bzl", "third_party_library") oncall("open_source") third_party_library( name = "gtest", - homebrew_package_name = "googletest", - pkgconfig_name = "GTest", + pkgconfig_name = "gtest", + repo_package_names = { + "fedora": "gtest-devel", + "homebrew": "googletest", + "ubuntu": "libgtest-dev", + }, ) -alias( +third_party_library( name = "gmock", - actual = ":gtest", - visibility = ["PUBLIC"], + pkgconfig_name = "gmock", + repo_package_names = { + "fedora": "gmock-devel", + "homebrew": "googletest", + "ubuntu": "libgmock-dev", + }, ) -export_file( - name = "gtest_main.cpp", +cxx_library( + name = "cpp_unittest_main", + srcs = ["gtest_main.cpp"], + visibility = ["PUBLIC"], + deps = [":gtest"], ) diff --git a/shim/third-party/jemalloc/BUCK b/shim/third-party/jemalloc/BUCK index 16cb5b4ca329f..b4b040e0e3f63 100644 --- a/shim/third-party/jemalloc/BUCK +++ b/shim/third-party/jemalloc/BUCK @@ -11,6 +11,10 @@ oncall("open_source") third_party_library( name = "headers", - homebrew_package_name = "jemalloc", pkgconfig_name = "jemalloc", + repo_package_names = { + "fedora": "jemalloc-devel", + "homebrew": "jemalloc", + "ubuntu": "libjemalloc-dev", + }, ) diff --git a/shim/third-party/jvm/BUCK b/shim/third-party/jvm/BUCK index 9de6e20cf2960..09c70401fd2ae 100644 --- a/shim/third-party/jvm/BUCK +++ b/shim/third-party/jvm/BUCK @@ -11,5 +11,7 @@ oncall("open_source") third_party_library( name = "jvm", - homebrew_package_name = "openjdk", + repo_package_names = { + "homebrew": "openjdk", + }, ) diff --git a/shim/third-party/libaio/BUCK b/shim/third-party/libaio/BUCK index 0378186541e0e..529313dd48f80 100644 --- a/shim/third-party/libaio/BUCK +++ b/shim/third-party/libaio/BUCK @@ -11,4 +11,10 @@ oncall("open_source") third_party_library( name = "aio", + linker_flags = ["-laio"], + repo_package_names = { + "fedora": "libaio-devel", + "homebrew": "libaio", + "ubuntu": "libaio-dev", + }, ) diff --git a/shim/third-party/libdwarf/BUCK b/shim/third-party/libdwarf/BUCK index 93c867f38bce8..1d28507840a56 100644 --- a/shim/third-party/libdwarf/BUCK +++ b/shim/third-party/libdwarf/BUCK @@ -11,6 +11,13 @@ oncall("open_source") third_party_library( name = "dwarf", - homebrew_package_name = "libdwarf", + pkgconfig_fallback = struct( + preprocessor_flags = ["-I/usr/include/libdwarf"], + ), pkgconfig_name = "libdwarf", + repo_package_names = { + "fedora": "libdwarf-devel", + "homebrew": "libdwarf", + "ubuntu": "libdwarf-dev", + }, ) diff --git a/shim/third-party/libevent/BUCK b/shim/third-party/libevent/BUCK index a196c6e2d096b..6d9b5a5db605a 100644 --- a/shim/third-party/libevent/BUCK +++ b/shim/third-party/libevent/BUCK @@ -12,5 +12,8 @@ oncall("open_source") third_party_library( name = "libevent", pkgconfig_name = "libevent", - ubuntu_package_name = "libevent-dev", + repo_package_names = { + "fedora": "libevent-devel", + "ubuntu": "libevent-dev", + }, ) diff --git a/shim/third-party/libgcc/BUCK b/shim/third-party/libgcc/BUCK index 66aa52840b924..b4ab81b6da531 100644 --- a/shim/third-party/libgcc/BUCK +++ b/shim/third-party/libgcc/BUCK @@ -11,5 +11,7 @@ oncall("open_source") third_party_library( name = "stdc++fs", - homebrew_package_name = "gcc", + repo_package_names = { + "homebrew": "gcc", + }, ) diff --git a/shim/third-party/liboqs/BUCK b/shim/third-party/liboqs/BUCK index c5a3d051ef3c4..e016f16b87a62 100644 --- a/shim/third-party/liboqs/BUCK +++ b/shim/third-party/liboqs/BUCK @@ -11,6 +11,9 @@ oncall("open_source") third_party_library( name = "oqs", - homebrew_package_name = "liboqs", pkgconfig_name = "liboqs", + repo_package_names = { + "fedora": "liboqs-devel", + "homebrew": "liboqs", + }, ) diff --git a/shim/third-party/libsodium/BUCK b/shim/third-party/libsodium/BUCK index 29c6deeab1d9f..91e6fa30ccc18 100644 --- a/shim/third-party/libsodium/BUCK +++ b/shim/third-party/libsodium/BUCK @@ -11,7 +11,10 @@ oncall("open_source") third_party_library( name = "sodium", - homebrew_package_name = "libsodium", pkgconfig_name = "libsodium", - ubuntu_package_name = "libsodium-dev", + repo_package_names = { + "fedora": "libsodium-devel", + "homebrew": "libsodium", + "ubuntu": "libsodium-dev", + }, ) diff --git a/shim/third-party/libunwind/BUCK b/shim/third-party/libunwind/BUCK index f7f8d20672314..100558f76b925 100644 --- a/shim/third-party/libunwind/BUCK +++ b/shim/third-party/libunwind/BUCK @@ -12,5 +12,9 @@ oncall("open_source") third_party_library( name = "unwind", pkgconfig_name = "libunwind", - ubuntu_package_name = "libunwind-dev", + repo_package_names = { + "fedora": "libunwind-devel", + "homebrew": "libunwind", + "ubuntu": "libunwind-dev", + }, ) diff --git a/shim/third-party/liburing/BUCK b/shim/third-party/liburing/BUCK new file mode 100644 index 0000000000000..1fd68a7ba318f --- /dev/null +++ b/shim/third-party/liburing/BUCK @@ -0,0 +1,19 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under both the MIT license found in the +# LICENSE-MIT file in the root directory of this source tree and the Apache +# License, Version 2.0 found in the LICENSE-APACHE file in the root directory +# of this source tree. + +load("@shim//third-party:third_party.bzl", "third_party_library") + +oncall("open_source") + +third_party_library( + name = "uring", + pkgconfig_name = "liburing", + repo_package_names = { + "fedora": "liburing-devel", + "ubuntu": "liburing-dev", + }, +) diff --git a/shim/third-party/lz4/BUCK b/shim/third-party/lz4/BUCK index 8d321b0b18d2b..a8cbc3cf134c6 100644 --- a/shim/third-party/lz4/BUCK +++ b/shim/third-party/lz4/BUCK @@ -12,4 +12,9 @@ oncall("open_source") third_party_library( name = "lz4", pkgconfig_name = "liblz4", + repo_package_names = { + "fedora": "lz4-devel", + "homebrew": "lz4", + "ubuntu": "liblz4-dev", + }, ) diff --git a/shim/third-party/openssl/BUCK b/shim/third-party/openssl/BUCK index 0bfbbf20c5e5c..30ff1c6a2ca33 100644 --- a/shim/third-party/openssl/BUCK +++ b/shim/third-party/openssl/BUCK @@ -11,8 +11,12 @@ oncall("open_source") third_party_library( name = "ssl", - homebrew_package_name = "openssl", pkgconfig_name = "openssl", + repo_package_names = { + "fedora": "openssl-devel", + "homebrew": "openssl", + "ubuntu": "libssl-dev", + }, ) alias( diff --git a/shim/third-party/python/BUCK b/shim/third-party/python/BUCK index dfa541bdaf0a4..a11805fccc057 100644 --- a/shim/third-party/python/BUCK +++ b/shim/third-party/python/BUCK @@ -12,6 +12,10 @@ oncall("open_source") third_party_library( name = "python", homebrew_header_path = "Frameworks/Python.framework/Headers", - homebrew_package_name = "python3", pkgconfig_name = "python3", + repo_package_names = { + "fedora": "python3-devel", + "homebrew": "python3", + "ubuntu": "python3-dev", + }, ) diff --git a/shim/third-party/range-v3/BUCK b/shim/third-party/range-v3/BUCK index 62997c6014097..1ad95ed971118 100644 --- a/shim/third-party/range-v3/BUCK +++ b/shim/third-party/range-v3/BUCK @@ -9,4 +9,11 @@ load("@shim//third-party:third_party.bzl", "third_party_library") oncall("open_source") -third_party_library(name = "range-v3") +third_party_library( + name = "range-v3", + repo_package_names = { + "fedora": "range-v3-devel", + "homebrew": "range-v3", + "ubuntu": "librange-v3-dev", + }, +) diff --git a/shim/third-party/snappy/BUCK b/shim/third-party/snappy/BUCK index b5bc134c80a50..ce83f2d54b273 100644 --- a/shim/third-party/snappy/BUCK +++ b/shim/third-party/snappy/BUCK @@ -9,4 +9,12 @@ load("@shim//third-party:third_party.bzl", "third_party_library") oncall("open_source") -third_party_library(name = "snappy") +third_party_library( + name = "snappy", + pkgconfig_name = "snappy", + repo_package_names = { + "fedora": "snappy-devel", + "homebrew": "snappy", + "ubuntu": "libsnappy-dev", + }, +) diff --git a/shim/third-party/third_party.bzl b/shim/third-party/third_party.bzl index fee56b64a298a..332412de41d42 100644 --- a/shim/third-party/third_party.bzl +++ b/shim/third-party/third_party.bzl @@ -8,63 +8,88 @@ load("@prelude//third-party:pkgconfig.bzl", "external_pkgconfig_library") load("@shim//build_defs:prebuilt_cpp_library.bzl", "prebuilt_cpp_library") -def homebrew_library( - package_name, - name = None, - default_target_platform = "prelude//platforms:default", +def third_party_library( + name, visibility = ["PUBLIC"], - deps = None, - header_path = None, + deps = [], + pkgconfig_name = None, + repo_package_names = {}, linker_flags = None, - labels = []): - brew_headers = package_name + "__brew_headers" - brew_libs = package_name + "__brew_libs" - if name != None: - brew_headers = name + "__" + brew_headers - brew_libs = name + "__" + brew_libs + homebrew_header_path = None, + pkgconfig_fallback = None): + # Labels defined here are used to extract third-party libs so they can be installed + labels = [] + for repo, package_name in repo_package_names.items(): + labels.append("third-party:{}:{}".format(repo, package_name)) + + # Prefer pkgconfig + if pkgconfig_name != None: + for repo in repo_package_names.keys(): + labels.append("third-party:{}:pkg-config".format(repo)) + + external_pkgconfig_library( + name = pkgconfig_name, + visibility = visibility if name == pkgconfig_name else [], + labels = labels, + deps = deps, + fallback = pkgconfig_fallback, + ) + if name != pkgconfig_name: + native.alias( + name = name, + actual = ":{}".format(pkgconfig_name), + visibility = visibility, + ) + else: + linker_flags = linker_flags or [] + exported_preprocessor_flags = [] + + os = host_info().os + if os.is_macos and "homebrew" in repo_package_names: + # Add brew lookup paths + homebrew_package_name = repo_package_names["homebrew"] + linker_flags += _homebrew_linker_flags( + name = name, + homebrew_package_name = homebrew_package_name, + ) + exported_preprocessor_flags += _homebrew_preprocessor_flags( + name = name, + homebrew_package_name = homebrew_package_name, + homebrew_header_path = homebrew_header_path, + ) + + prebuilt_cpp_library( + name = name, + visibility = visibility, + exported_deps = deps, + exported_preprocessor_flags = exported_preprocessor_flags, + linker_flags = linker_flags, + labels = labels, + ) + +def _homebrew_linker_flags(name, homebrew_package_name): + homebrew_libs = "{}__{}__homebrew_libs".format(name, homebrew_package_name) # @lint-ignore BUCKLINT native.genrule( - name = brew_headers, - default_target_platform = default_target_platform, + name = homebrew_libs, out = "out", - cmd = "echo \"-I`brew --prefix {}`/{}\" > $OUT".format(package_name, header_path or "include"), + cmd = "echo \"-L`brew --prefix {}`/lib\" > $OUT".format(homebrew_package_name), ) + return ["@$(location :{})".format(homebrew_libs)] + +def _homebrew_preprocessor_flags(name, homebrew_package_name, homebrew_header_path): + homebrew_headers = "{}__{}__homebrew_headers".format(name, homebrew_package_name) + # @lint-ignore BUCKLINT native.genrule( - name = brew_libs, - default_target_platform = default_target_platform, + name = homebrew_headers, out = "out", - cmd = "echo \"-L`brew --prefix {}`/lib\" > $OUT".format(package_name), - ) - - linker_flags = linker_flags or [] - linker_flags.append("@$(location :{})".format(brew_libs)) - - prebuilt_cpp_library( - name = name or package_name, - default_target_platform = default_target_platform, - visibility = visibility, - exported_deps = deps, - exported_preprocessor_flags = ["@$(location :{})".format(brew_headers)], - linker_flags = linker_flags, - labels = labels, + cmd = "echo \"-I`brew --prefix {}`/{}\" > $OUT".format( + homebrew_package_name, + homebrew_header_path or "include", + ), ) -def third_party_library(name, visibility = ["PUBLIC"], deps = [], homebrew_package_name = None, ubuntu_package_name = None, pkgconfig_name = None, homebrew_header_path = None, default_target_platform = "prelude//platforms:default", homebrew_linker_flags = None): - # Labels defined here are used to extract third-party libs so they can be installed: - labels = [] - if homebrew_package_name != None: - labels.append("third-party:homebrew:" + homebrew_package_name) - if ubuntu_package_name != None: - labels.append("third-party:ubuntu:" + ubuntu_package_name) - - if pkgconfig_name != None: - labels.append("third-party:homebrew:pkg-config") - labels.append("third-party:ubuntu:pkg-config") - external_pkgconfig_library(name = pkgconfig_name, visibility = visibility if name == pkgconfig_name else [], labels = labels, default_target_platform = default_target_platform, deps = deps) - if name != pkgconfig_name: - native.alias(name = name, actual = ":{}".format(pkgconfig_name), visibility = visibility) - return - homebrew_library(name = name, package_name = homebrew_package_name or name, visibility = visibility, deps = deps, header_path = homebrew_header_path, linker_flags = homebrew_linker_flags, default_target_platform = default_target_platform, labels = labels) + return ["@$(location :{})".format(homebrew_headers)] diff --git a/shim/third-party/xz/BUCK b/shim/third-party/xz/BUCK index 9d9c718426ea6..9bda970b7047b 100644 --- a/shim/third-party/xz/BUCK +++ b/shim/third-party/xz/BUCK @@ -11,6 +11,10 @@ oncall("open_source") third_party_library( name = "lzma", - homebrew_package_name = "xz", pkgconfig_name = "liblzma", + repo_package_names = { + "fedora": "xz-devel", + "homebrew": "liblzma", + "ubuntu": "liblz4-dev", + }, ) diff --git a/shim/third-party/zlib/BUCK b/shim/third-party/zlib/BUCK index 7d21a49b1e396..d1704bc453bc1 100644 --- a/shim/third-party/zlib/BUCK +++ b/shim/third-party/zlib/BUCK @@ -11,6 +11,10 @@ oncall("open_source") third_party_library( name = "z", - homebrew_package_name = "zlib", pkgconfig_name = "zlib", + repo_package_names = { + "fedora": "zlib-devel", + "homebrew": "zlib", + "ubuntu": "zlib1g", + }, ) diff --git a/shim/third-party/zstd/BUCK b/shim/third-party/zstd/BUCK index f92cf85a45daf..1ecce79a1cec7 100644 --- a/shim/third-party/zstd/BUCK +++ b/shim/third-party/zstd/BUCK @@ -12,4 +12,9 @@ oncall("open_source") third_party_library( name = "zstd", pkgconfig_name = "libzstd", + repo_package_names = { + "fedora": "libzstd-devel", + "homebrew": "zstd", + "ubuntu": "libzstd-dev", + }, ) diff --git a/shim/tools/build_defs/fb_native_wrapper.bzl b/shim/tools/build_defs/fb_native_wrapper.bzl new file mode 100644 index 0000000000000..f6795d7ff4313 --- /dev/null +++ b/shim/tools/build_defs/fb_native_wrapper.bzl @@ -0,0 +1,8 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under both the MIT license found in the +# LICENSE-MIT file in the root directory of this source tree and the Apache +# License, Version 2.0 found in the LICENSE-APACHE file in the root directory +# of this source tree. + +fb_native = native