Skip to content

Commit

Permalink
Add ECMP to DLB data path test
Browse files Browse the repository at this point in the history
Summary:
1. Update the ECMP object with DLB config in post warm boot
2. Verify the DLB data path

Differential Revision:
D50400205

Privacy Context Container: L1125642

fbshipit-source-id: e0ee54894cd42382325e8d5cf8919c342d359721
  • Loading branch information
rskumaran-fb authored and facebook-github-bot committed Oct 23, 2023
1 parent 37439b0 commit 042ab45
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 39 deletions.
23 changes: 23 additions & 0 deletions fboss/agent/hw/test/LoadBalancerUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "fboss/agent/LoadBalancerConfigApplier.h"
#include "fboss/agent/Platform.h"
#include "fboss/agent/SwitchIdScopeResolver.h"
#include "fboss/agent/hw/test/ConfigFactory.h"
#include "fboss/agent/hw/test/HwSwitchEnsemble.h"
#include "fboss/agent/hw/test/HwTestPacketUtils.h"
#include "fboss/agent/packet/PktFactory.h"
Expand Down Expand Up @@ -181,6 +182,28 @@ cfg::FlowletSwitchingConfig getDefaultFlowletSwitchingConfig(void) {
return flowletCfg;
}

void addFlowletConfigs(
cfg::SwitchConfig& cfg,
const std::vector<PortID>& ports) {
cfg::FlowletSwitchingConfig flowletCfg =
utility::getDefaultFlowletSwitchingConfig();
cfg.flowletSwitchingConfig() = flowletCfg;

std::map<std::string, cfg::PortFlowletConfig> portFlowletCfgMap;
cfg::PortFlowletConfig portFlowletConfig;
portFlowletConfig.scalingFactor() = kScalingFactor;
portFlowletConfig.loadWeight() = kLoadWeight;
portFlowletConfig.queueWeight() = kQueueWeight;
portFlowletCfgMap.insert(std::make_pair("default", portFlowletConfig));
cfg.portFlowletConfigs() = portFlowletCfgMap;

std::vector<PortID> portIds(ports.begin(), ports.begin() + ports.size());
for (auto portId : portIds) {
auto portCfg = utility::findCfgPort(cfg, portId);
portCfg->flowletConfigName() = "default";
}
}

static cfg::UdfConfig addUdfConfig(
const std::string& udfGroup,
const int offsetBytes,
Expand Down
6 changes: 6 additions & 0 deletions fboss/agent/hw/test/LoadBalancerUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ inline const int kUdfAclRoceOpcodeFieldSizeInBytes(1);
inline const int kUdfL4DstPort(4791);
inline const int kRandomUdfL4SrcPort(62946);
inline const int kUdfRoceOpcode(11);
inline const int kScalingFactor(100);
inline const int kLoadWeight(70);
inline const int kQueueWeight(30);

cfg::LoadBalancer getEcmpHalfHashConfig(const HwAsic& asic);
cfg::LoadBalancer getEcmpFullHashConfig(const HwAsic& asic);
Expand Down Expand Up @@ -184,5 +187,8 @@ bool isHwDeterministicSeed(
LoadBalancerID id);

cfg::FlowletSwitchingConfig getDefaultFlowletSwitchingConfig();
void addFlowletConfigs(
cfg::SwitchConfig& cfg,
const std::vector<PortID>& ports);

} // namespace facebook::fboss::utility
53 changes: 40 additions & 13 deletions fboss/agent/hw/test/dataplane_tests/HwLoadBalancerTests.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,6 @@
#define RUN_HW_LOAD_BALANCER_TEST_FOR_DLB( \
TEST_FIXTURE, MULTIPATH_TYPE, HASH_TYPE, TRAFFIC_TYPE) \
TEST_F(TEST_FIXTURE, TEST_NAME(MULTIPATH_TYPE, HASH_TYPE, TRAFFIC_TYPE)) { \
if (BOOST_PP_STRINGIZE(MULTIPATH_TYPE) == std::string{"WideUcmp"} && \
!getPlatform()->getAsic()->isSupported( \
HwAsic::Feature::WIDE_ECMP)) { \
return; \
} \
static bool kLoopThroughFrontPanelPort = \
(BOOST_PP_STRINGIZE(TRAFFIC_TYPE) != std::string{"Cpu"}); \
runDynamicLoadBalanceTest( \
Expand All @@ -93,6 +88,21 @@
35); \
}

#define RUN_HW_LOAD_BALANCER_TEST_FOR_ECMP_TO_DLB( \
TEST_FIXTURE, MULTIPATH_TYPE, HASH_TYPE, TRAFFIC_TYPE) \
TEST_F(TEST_FIXTURE, TEST_NAME(MULTIPATH_TYPE, HASH_TYPE, TRAFFIC_TYPE)) { \
static bool kLoopThroughFrontPanelPort = \
(BOOST_PP_STRINGIZE(TRAFFIC_TYPE) != std::string{"Cpu"}); \
runLoadBalanceTest( \
8, \
facebook::fboss::utility::getEcmp##HASH_TYPE##HashConfig( \
*getPlatform()->getAsic()), \
facebook::fboss::utility::kHwTest##MULTIPATH_TYPE##Weights(), \
kLoopThroughFrontPanelPort, \
false, /* since ECMP expected to send traffic on single link */ \
35 /* DLB needs 30% deviation */); \
}

#define RUN_SHRINK_EXPAND_HW_LOAD_BALANCER_TEST(TEST_FIXTURE, HASH_TYPE) \
TEST_F(TEST_FIXTURE, ECMP_SHRINK_EXPAND_TEST_NAME(HASH_TYPE)) { \
runEcmpShrinkExpandLoadBalanceTest( \
Expand Down Expand Up @@ -230,21 +240,38 @@ class HwLoadBalancerTest : public HwLinkStateDependentTest {
}
auto setup = [=]() { programECMP(ecmpWidth, loadBalancer, weights); };
auto verify = [=]() {
// DLB engine can not detect port member hardware status
// when in "phy" loopback mode.
// Hence we are setting it forcibly here again for all the ecmp members.
if (FLAGS_flowletSwitchingEnable) {
XLOG(DBG3) << "setting ECMP Member Status: ";
utility::setEcmpMemberStatus(getHwSwitch());
}
pumpTrafficPortAndVerifyLoadBalanced(
ecmpWidth,
weights,
loopThroughFrontPanel,
deviation,
loadBalanceExpected);
};
verifyAcrossWarmBoots(setup, verify);

auto setupPostWB = [&]() {
if (FLAGS_flowletSwitchingEnable) {
auto cfg = initialConfig();
// Add flowlet config to convert ECMP to DLB
utility::addFlowletConfigs(cfg, masterLogicalPortIds());
applyNewConfig(cfg);
}
};

auto verifyPostWB = [&]() {
if (FLAGS_flowletSwitchingEnable) {
XLOG(DBG3) << "setting ECMP Member Status: ";
utility::setEcmpMemberStatus(getHwSwitch());
loadBalanceExpected = true;
pumpTrafficPortAndVerifyLoadBalanced(
ecmpWidth,
weights,
loopThroughFrontPanel,
deviation,
loadBalanceExpected);
}
};

verifyAcrossWarmBoots(setup, verify, setupPostWB, verifyPostWB);
}

void runEcmpShrinkExpandLoadBalanceTest(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* 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 "fboss/agent/Platform.h"
#include "fboss/agent/hw/switch_asics/HwAsic.h"
#include "fboss/agent/hw/test/HwTestPacketUtils.h"
#include "fboss/agent/hw/test/dataplane_tests/HwLoadBalancerTests.h"

namespace facebook::fboss {

class HwLoadBalancerTestV6EcmpToFlowlet
: public HwLoadBalancerTest<utility::HwIpV6RoCEEcmpDataPlaneTestUtil> {
std::unique_ptr<utility::HwIpV6RoCEEcmpDataPlaneTestUtil> getECMPHelper()
override {
return std::make_unique<utility::HwIpV6RoCEEcmpDataPlaneTestUtil>(
getHwSwitchEnsemble(), RouterID(0));
}

private:
cfg::SwitchConfig initialConfig() const override {
auto hwSwitch = getHwSwitch();
auto cfg = utility::onePortPerInterfaceConfig(
hwSwitch, masterLogicalPortIds(), getAsic()->desiredLoopbackModes());
return cfg;
}

void SetUp() override {
FLAGS_flowletSwitchingEnable = true;
HwLoadBalancerTest::SetUp();
}
};

RUN_HW_LOAD_BALANCER_TEST_FOR_ECMP_TO_DLB(
HwLoadBalancerTestV6EcmpToFlowlet,
Ecmp,
Full,
FrontPanel)

} // namespace facebook::fboss
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,6 @@
#include "fboss/agent/hw/test/HwTestPacketUtils.h"
#include "fboss/agent/hw/test/dataplane_tests/HwLoadBalancerTests.h"

namespace {
const int kScalingFactor = 100;
const int kLoadWeight = 70;
const int kQueueWeight = 30;
} // namespace

namespace facebook::fboss {

class HwLoadBalancerTestV6Flowlet
Expand All @@ -34,26 +28,7 @@ class HwLoadBalancerTestV6Flowlet
auto hwSwitch = getHwSwitch();
auto cfg = utility::onePortPerInterfaceConfig(
hwSwitch, masterLogicalPortIds(), getAsic()->desiredLoopbackModes());
cfg::FlowletSwitchingConfig flowletCfg =
utility::getDefaultFlowletSwitchingConfig();
cfg.flowletSwitchingConfig() = flowletCfg;

std::map<std::string, cfg::PortFlowletConfig> portFlowletCfgMap;
cfg::PortFlowletConfig portFlowletConfig;
portFlowletConfig.scalingFactor() = kScalingFactor;
portFlowletConfig.loadWeight() = kLoadWeight;
portFlowletConfig.queueWeight() = kQueueWeight;
portFlowletCfgMap.insert(std::make_pair("default", portFlowletConfig));
cfg.portFlowletConfigs() = portFlowletCfgMap;

auto allPorts = masterLogicalInterfacePortIds();
std::vector<PortID> portIds(
allPorts.begin(), allPorts.begin() + allPorts.size());
for (auto portId : portIds) {
auto portCfg = utility::findCfgPort(cfg, portId);
portCfg->flowletConfigName() = "default";
}

utility::addFlowletConfigs(cfg, masterLogicalPortIds());
return cfg;
}

Expand Down

0 comments on commit 042ab45

Please sign in to comment.