diff --git a/tests/qos/BUILD.bazel b/tests/qos/BUILD.bazel index b98cee72..047b0692 100644 --- a/tests/qos/BUILD.bazel +++ b/tests/qos/BUILD.bazel @@ -96,11 +96,15 @@ cc_library( ":qos_test_util", "//dvaas:test_vector_cc_proto", "//gutil:collections", + "//gutil:proto", + "//gutil:status", "//gutil:status_matchers", "//gutil:testing", "//lib:ixia_helper", "//lib/gnmi:gnmi_helper", + "//lib/utils:json_utils", "//p4_pdpi:ir", + "//p4_pdpi:ir_cc_proto", "//p4_pdpi:p4_runtime_session", "//p4_pdpi:pd", "//p4_pdpi/netaddr:ipv4_address", @@ -113,10 +117,14 @@ cc_library( "//tests/lib:switch_test_setup_helpers", "//thinkit:generic_testbed", "//thinkit:generic_testbed_fixture", + "@com_github_gnmi//proto/gnmi:gnmi_cc_grpc_proto", "@com_github_p4lang_p4runtime//:p4info_cc_proto", - "@com_google_absl//absl/cleanup", + "@com_github_p4lang_p4runtime//:p4runtime_cc_proto", + "@com_google_absl//absl/cleanup", + "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", + "@com_google_absl//absl/strings:str_format", "@com_google_absl//absl/time", "@com_google_googletest//:gtest", ], diff --git a/tests/qos/frontpanel_qos_test.cc b/tests/qos/frontpanel_qos_test.cc index 156a5f42..89977b6e 100644 --- a/tests/qos/frontpanel_qos_test.cc +++ b/tests/qos/frontpanel_qos_test.cc @@ -14,25 +14,38 @@ #include "tests/qos/frontpanel_qos_test.h" +#include +#include +#include #include +#include +#include #include // NOLINT #include #include "absl/cleanup/cleanup.h" +#include "absl/container/flat_hash_map.h" #include "absl/status/status.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/str_format.h" +#include "absl/strings/str_replace.h" #include "absl/strings/string_view.h" #include "absl/strings/substitute.h" +#include "absl/time/clock.h" #include "absl/time/time.h" #include "dvaas/test_vector.pb.h" -#include "gmock/gmock.h" -#include "gtest/gtest.h" #include "gutil/collections.h" +#include "gutil/proto.h" +#include "gutil/status.h" #include "gutil/status_matchers.h" #include "gutil/testing.h" #include "lib/gnmi/gnmi_helper.h" #include "lib/ixia_helper.h" +#include "lib/utils/json_utils.h" +#include "p4/v1/p4runtime.pb.h" #include "p4_pdpi/ir.h" +#include "p4_pdpi/ir.pb.h" #include "p4_pdpi/netaddr/ipv4_address.h" #include "p4_pdpi/netaddr/ipv6_address.h" #include "p4_pdpi/netaddr/mac_address.h" @@ -40,27 +53,146 @@ #include "p4_pdpi/packetlib/packetlib.h" #include "p4_pdpi/packetlib/packetlib.pb.h" #include "p4_pdpi/pd.h" +#include "proto/gnmi/gnmi.grpc.pb.h" #include "sai_p4/instantiations/google/sai_pd.pb.h" #include "tests/forwarding/util.h" #include "tests/lib/switch_test_setup_helpers.h" #include "tests/qos/packet_in_receiver.h" #include "tests/qos/qos_test_util.h" +#include "thinkit/generic_testbed.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" namespace pins_test { -struct EcnTestPacketCounters { - absl::Mutex mutex; - int num_packets_punted ABSL_GUARDED_BY(mutex) = 0; - int num_packets_ecn_marked ABSL_GUARDED_BY(mutex) = 0; -}; +using ::json_yang::FormatJsonBestEffort; +using ::testing::Eq; +using ::testing::Field; +using ::testing::ResultOf; -void ResetEcnTestPacketCounters(EcnTestPacketCounters &packet_receive_info) { - absl::MutexLock lock(&packet_receive_info.mutex); - packet_receive_info.num_packets_punted = 0; - packet_receive_info.num_packets_ecn_marked = 0; +template std::string ToString(const T &t) { + std::stringstream ss; + ss << t; + return ss.str(); +} + +// Connects to Ixia on the given testbed and returns a string handle identifying +// the connection (aka "topology ref"). +absl::StatusOr ConnectToIxia(thinkit::GenericTestbed &testbed) { + ASSIGN_OR_RETURN(auto gnmi_stub, testbed.Sut().CreateGnmiStub()); + ASSIGN_OR_RETURN(std::vector ready_links, + GetReadyIxiaLinks(testbed, *gnmi_stub)); + if (ready_links.empty()) { + return gutil::UnavailableErrorBuilder() << "no Ixia-to-SUT link up"; + } + absl::string_view ixia_interface = ready_links[0].ixia_interface; + ASSIGN_OR_RETURN(ixia::IxiaPortInfo ixia_port_info, + ixia::ExtractPortInfo(ixia_interface)); + ASSIGN_OR_RETURN( + std::string ixia_connection_handle, + pins_test::ixia::IxiaConnect(ixia_port_info.hostname, testbed)); + return ixia_connection_handle; +} + +// Installs the given table `entries` using the given P4Runtime session, +// respecting dependencies between entries by sequencing them into batches +// according to `p4info`. +absl::Status InstallPdTableEntries(const sai::TableEntries &entries, + const pdpi::IrP4Info &p4info, + pdpi::P4RuntimeSession &p4rt_session) { + std::vector pi_entries; + for (const sai::TableEntry &entry : entries.entries()) { + ASSIGN_OR_RETURN(pi_entries.emplace_back(), + pdpi::PartialPdTableEntryToPiTableEntry(p4info, entry)); + } + return pdpi::InstallPiTableEntries(&p4rt_session, p4info, pi_entries); +} +absl::Status InstallPdTableEntries(const sai::TableEntries &entries, + const p4::config::v1::P4Info &p4info, + pdpi::P4RuntimeSession &p4rt_session) { + ASSIGN_OR_RETURN(pdpi::IrP4Info ir_p4info, pdpi::CreateIrP4Info(p4info)); + return InstallPdTableEntries(entries, ir_p4info, p4rt_session); +} + +// Returns a set of table entries that will cause a switch to forward all L3 +// packets unconditionally out of the given port. +absl::StatusOr +ConstructEntriesToForwardAllTrafficToGivenPort(absl::string_view p4rt_port_id) { + // By convention, we use link local IPv6 addresses as neighbor IDs. + const std::string kNeighborId = + netaddr::MacAddress(2, 2, 2, 2, 2, 2).ToLinkLocalIpv6Address().ToString(); + return gutil::ParseTextProto(absl::Substitute( + R"pb( + entries { + l3_admit_table_entry { + match {} # Wildcard. + action { admit_to_l3 {} } + priority: 1 + } + } + entries { + acl_pre_ingress_table_entry { + match {} # Wildcard. + action { set_vrf { vrf_id: "vrf" } } + priority: 1 + } + } + entries { + vrf_table_entry { + match { vrf_id: "vrf" } + action { no_action {} } + } + } + entries { + ipv4_table_entry { + match { vrf_id: "vrf" } + action { set_nexthop_id { nexthop_id: "nexthop" } } + } + } + entries { + ipv6_table_entry { + match { vrf_id: "vrf" } + action { set_nexthop_id { nexthop_id: "nexthop" } } + } + } + entries { + nexthop_table_entry { + match { nexthop_id: "nexthop" } + action { + set_ip_nexthop { router_interface_id: "rif" neighbor_id: "$0" } + } + } + } + entries { + router_interface_table_entry { + match { router_interface_id: "rif" } + action { + set_port_and_src_mac { port: "$1" src_mac: "66:55:44:33:22:11" } + } + } + } + entries { + neighbor_table_entry { + match { router_interface_id: "rif" neighbor_id: "$0" } + action { set_dst_mac { dst_mac: "02:02:02:02:02:02" } } + } + } + )pb", + kNeighborId, p4rt_port_id)); } -TEST_P(FrontpanelQosTest, PacketsGetMappedToCorrectQueuesBasedOnDscp) { +// The purpose of this test is to verify that: +// - Incoming IP packets are mapped to queues according to their DSCP. +// - Queue peak information rates (PIRs) are enforced. +// - Queue egress counters increment correctly. +// +// We test this (for each DSCP, for IPv4 & IPv6) by sending test packets of a +// fixed DSCP at line rate, observing the rate at which the SUT forwards them, +// and inferring which queue was used by cross checking against the PIRs of the +// queues, which we configure to be exponentially spaced. +TEST_P(FrontpanelQosTest, + PacketsGetMappedToCorrectQueuesBasedOnDscpAndQueuePeakRatesAreEnforced) { + LOG(INFO) << "-- Test started ----------------------------------------------"; // Pick a testbed with SUT connected to an Ixia on 2 ports, so we can // oversubscribe switch egress port. auto requirements = gutil::ParseProtoOrDie( @@ -71,13 +203,283 @@ TEST_P(FrontpanelQosTest, PacketsGetMappedToCorrectQueuesBasedOnDscp) { std::unique_ptr testbed, GetParam().testbed_interface->GetTestbedWithRequirements(requirements)); - // TODO: actual testing. + // Pick 2 SUT ports connected to the Ixia, one for receiving test packets and + // one for forwarding them back. + ASSERT_OK_AND_ASSIGN(auto gnmi_stub, testbed->Sut().CreateGnmiStub()); + ASSERT_OK_AND_ASSIGN(std::vector ready_links, + GetReadyIxiaLinks(*testbed, *gnmi_stub)); + ASSERT_GE(ready_links.size(), 2) + << "Test requires at least 2 SUT ports connected to an Ixia"; + const std::string kIxiaSrcPort = ready_links[0].ixia_interface; + const std::string kIxiaDstPort = ready_links[1].ixia_interface; + const std::string kSutIngressPort = ready_links[0].sut_interface; + const std::string kSutEgressPort = ready_links[1].sut_interface; + LOG(INFO) << absl::StrFormat( + "Test packet route: [Ixia: %s] => [SUT: %s] -> [SUT: %s] => [Ixia: %s]", + kIxiaSrcPort, kSutIngressPort, kSutEgressPort, kIxiaDstPort); + ASSERT_OK_AND_ASSIGN( + const std::string kSutEgressPortScheduler, + GetSchedulerPolicyNameByEgressPort(kSutEgressPort, *gnmi_stub)); + absl::flat_hash_map p4rt_id_by_interface; + ASSERT_OK_AND_ASSIGN(p4rt_id_by_interface, + GetAllInterfaceNameToPortId(*gnmi_stub)); + ASSERT_OK_AND_ASSIGN( + const std::string kSutEgressPortP4rtId, + gutil::FindOrStatus(p4rt_id_by_interface, kSutEgressPort)); + + // Configure the switch to send all incomming packets out of the chosen egress + // port. + ASSERT_OK_AND_ASSIGN( + std::unique_ptr sut_p4rt, + ConfigureSwitchAndReturnP4RuntimeSession( + testbed->Sut(), /*gnmi_config=*/std::nullopt, GetParam().p4info)); + ASSERT_OK_AND_ASSIGN( + const sai::TableEntries kTableEntries, + ConstructEntriesToForwardAllTrafficToGivenPort(kSutEgressPortP4rtId)); + ASSERT_OK(testbed->Environment().StoreTestArtifact("pd_entries.textproto", + kTableEntries)); + ASSERT_OK(InstallPdTableEntries(kTableEntries, GetParam().p4info, *sut_p4rt)); + + // Fix test parameters and PIRs (peak information rates, in bytes + // per second) for each DSCP. + constexpr int64_t kTestFrameSizeInBytes = 1000; // 1 KB + constexpr int64_t kTestFrameCount = 30'000'000; // 30 GB + constexpr int64_t kTestFramesPerSecond = kTestFrameCount / 3; // for 3 s + constexpr int64_t kTestFrameSpeedInBytesPerSecond = // 10 GB/s + kTestFramesPerSecond * kTestFrameSizeInBytes; + // We use exponentially spaced PIRs, with a base rate that's high enough for + // buffers to drain quickly. That way we don't have to drain buffers manually + // between test traffic flows. + constexpr int64_t kPirBaseSpeedInBytesPerSecond = 40'000'000; // 40 MB/s. + const absl::flat_hash_map kPirByQueueName = { + {"BE1", 1 * kPirBaseSpeedInBytesPerSecond}, + {"AF1", 2 * kPirBaseSpeedInBytesPerSecond}, + {"AF2", 4 * kPirBaseSpeedInBytesPerSecond}, + {"AF3", 8 * kPirBaseSpeedInBytesPerSecond}, + {"LLQ1", 16 * kPirBaseSpeedInBytesPerSecond}, + {"LLQ2", 32 * kPirBaseSpeedInBytesPerSecond}, + // TODO: Also test strict queues once reconfiguring them is + // supported. + // {"AF4", 64 * kPirBaseSpeedInBytesPerSecond}, + // {"NC1", 128 * kPirBaseSpeedInBytesPerSecond}, + }; + + // Ensure the test parameters are compatible with the testbed. + ASSERT_OK_AND_ASSIGN( + const int64_t kSutIngressPortSpeedInBitsPerSecond, + GetPortSpeedInBitsPerSecond(kSutIngressPort, *gnmi_stub)); + ASSERT_OK_AND_ASSIGN(const int64_t kSutEgressPortSpeedInBitsPerSecond, + GetPortSpeedInBitsPerSecond(kSutEgressPort, *gnmi_stub)); + ASSERT_LE(kTestFrameSpeedInBytesPerSecond, + kSutIngressPortSpeedInBitsPerSecond / 8) + << "ingress port is too slow to sustain test packet speed"; + ASSERT_LE(kTestFrameSpeedInBytesPerSecond, + kSutEgressPortSpeedInBitsPerSecond / 8) + << "egress port is too slow to sustain test packet speed"; + for (const auto &[queue, pir] : kPirByQueueName) { + ASSERT_GE(kTestFrameSpeedInBytesPerSecond, 2 * pir) + << "test packet speed is too low to meaningfully exceed PIR"; + } + + // Before we update the scheduler config, save the current config and prepare + // to restore it at the end of the test. + ASSERT_OK_AND_ASSIGN( + const std::string kInitialSchedulerConfig, + GetSchedulerPolicyConfig(kSutEgressPortScheduler, *gnmi_stub)); + const auto kRestoreSchedulerConfig = absl::Cleanup([&] { + // TODO: The switch does not currently accept its own config + // on the write path, we need to fix it first. Remove this workaround once + // the issue is addressed. + std::string fixed_config = absl::StrReplaceAll(kInitialSchedulerConfig, + { + {R"(,"weight":"0")", ""}, + }); + EXPECT_OK(UpdateSchedulerPolicyConfig(kSutEgressPortScheduler, fixed_config, + *gnmi_stub)) + << "failed to restore initial scheduler config -- switch config may be " + "corrupted, causing subsequent test to fail"; + }); + // Update scheduler config. + { + absl::flat_hash_map params; + for (auto &[queue, pir] : kPirByQueueName) { + params[queue].peak_information_rate = pir; + // To avoid a large initial burst of forwarded packets when we start the + // test packet flow, we use a minimally-sized token buffer. This is to + // ensure that the observed information rate will closely matche the peak + // information rate. See RFC 2698 for details. + params[queue].excess_burst_size = kTestFrameSizeInBytes; + // TODO: Consider picking this uniformly from [0, PIR] instead. + params[queue].committed_information_rate = 0; + params[queue].committed_burst_size = 0; + } + ASSERT_OK(SetSchedulerPolicyParameters(kSutEgressPortScheduler, params, + *gnmi_stub)); + } + // Dump initial and modified configs, to ease debugging. + ASSERT_OK(testbed->Environment().StoreTestArtifact( + absl::StrCat(kSutEgressPortScheduler, "_before_update.json"), + FormatJsonBestEffort(kInitialSchedulerConfig))); + ASSERT_OK_AND_ASSIGN( + std::string updated_scheduler_config, + GetSchedulerPolicyConfig(kSutEgressPortScheduler, *gnmi_stub)); + ASSERT_OK(testbed->Environment().StoreTestArtifact( + absl::StrCat(kSutEgressPortScheduler, "_after_update.json"), + FormatJsonBestEffort(updated_scheduler_config))); + + // Connect to Ixia and fix global parameters. + ASSERT_OK_AND_ASSIGN(const std::string kIxiaHandle, ConnectToIxia(*testbed)); + ASSERT_OK_AND_ASSIGN(const std::string kIxiaSrcPortHandle, + ixia::IxiaVport(kIxiaHandle, kIxiaSrcPort, *testbed)); + ASSERT_OK_AND_ASSIGN(const std::string kIxiaDstPortHandle, + ixia::IxiaVport(kIxiaHandle, kIxiaDstPort, *testbed)); + + // Actual testing -- inject test IPv4 and IPv6 packets for each DSCP, and + // check the behavior is as eexpted. + constexpr int kMaxDscp = 63; + for (int dscp = 0; dscp <= kMaxDscp; ++dscp) { + SCOPED_TRACE(absl::StrCat("DSCP = ", dscp)); + for (bool is_ipv4 : {true, false}) { + SCOPED_TRACE(absl::StrCat("IP version: ", is_ipv4 ? "IPv4" : "IPv6")); + + // Figure out which queue we will be targeting and some queue parameters. + ASSERT_OK_AND_ASSIGN( + const std::string kTargetQueue, + GetQueueNameByDscpAndPort(dscp, kSutEgressPort, *gnmi_stub)); + // TODO(b/230107242: Test strict queues once that is supported. + if (kTargetQueue == "AF4" || kTargetQueue == "NC1") { + LOG(WARNING) << "skipping test for unuspported queue '" << kTargetQueue + << "'"; + continue; + } + ASSERT_OK_AND_ASSIGN(const int kTargetQueuePir, + gutil::FindOrStatus(kPirByQueueName, kTargetQueue)); + ASSERT_OK_AND_ASSIGN( + const QueueCounters kInitialQueueCounters, + GetGnmiQueueCounters(kSutEgressPort, kTargetQueue, *gnmi_stub)); + + // Configure & start test packet flow. + const std::string kTrafficName = + absl::StrCat((is_ipv4 ? "IPv4" : "IPv6"), " traffic for DSCP ", dscp, + ", targeting queue ", kTargetQueue, + " with PIR = ", kTargetQueuePir, " bytes/second"); + SCOPED_TRACE(kTrafficName); + ASSERT_OK_AND_ASSIGN(const std::string kIxiaTrafficHandle, + ixia::SetUpTrafficItem(kIxiaSrcPortHandle, + kIxiaDstPortHandle, + kTrafficName, *testbed)); + auto delete_traffic_item = absl::Cleanup([&, kIxiaTrafficHandle] { + ASSERT_OK(ixia::DeleteTrafficItem(kIxiaTrafficHandle, *testbed)); + }); + auto traffix_parameters = ixia::TrafficParameters{ + .frame_count = kTestFrameCount, + .frame_size_in_bytes = kTestFrameSizeInBytes, + .traffic_speed = ixia::FramesPerSecond{kTestFramesPerSecond}, + }; + if (is_ipv4) { + traffix_parameters.ip_parameters = ixia::Ipv4TrafficParameters{ + .src_ipv4 = netaddr::Ipv4Address(192, 168, 2, dscp + 1), + .dst_ipv4 = netaddr::Ipv4Address(172, 0, 0, dscp + 1), + // Set ECN 0 to avoid RED drops. + .priority = ixia::IpPriority{.dscp = dscp, .ecn = 1}, + }; + } else { + traffix_parameters.ip_parameters = ixia::Ipv6TrafficParameters{ + .src_ipv6 = + netaddr::Ipv6Address(0x1000, 0, 0, 0, 0, 0, 0, dscp + 1), + .dst_ipv6 = + netaddr::Ipv6Address(0x2000, 0, 0, 0, 0, 0, 0, dscp + 1), + // Set ECN 0 to avoid RED drops. + .priority = ixia::IpPriority{.dscp = dscp, .ecn = 0}, + }; + } + LOG(INFO) << "-- starting " << kTrafficName; + ASSERT_OK(ixia::SetTrafficParameters(kIxiaTrafficHandle, + traffix_parameters, *testbed)); + // Occasionally the Ixia API cannot keep up and starting traffic fails, + // so we try up to 3 times. + ASSERT_OK(pins::TryUpToNTimes(3, /*delay=*/absl::Seconds(1), [&] { + return ixia::StartTraffic(kIxiaTrafficHandle, kIxiaHandle, *testbed); + })); + const absl::Duration kTrafficDuration = + absl::Seconds(kTestFrameCount / kTestFramesPerSecond); + LOG(INFO) << "traffic started, waiting for " << kTrafficDuration + << " to complete"; + absl::SleepFor(kTrafficDuration); + + // Check observed traffic rate against target queue PIR. + ASSERT_OK_AND_ASSIGN( + const ixia::TrafficItemStats kIxiaTrafficStats, + ixia::GetTrafficItemStats(kIxiaHandle, kTrafficName, *testbed)); + const int kObservedTrafficRate = + ixia::BytesPerSecondReceived(kIxiaTrafficStats); + LOG(INFO) << "observed traffic rate (bytes/second): " + << kObservedTrafficRate; + const int kAbsoluteError = kObservedTrafficRate - kTargetQueuePir; + const double kRelativeErrorPercent = + 100. * kAbsoluteError / kTargetQueuePir; + constexpr double kTolerancePercent = 10; // +-10% tolerance. + if (std::abs(kRelativeErrorPercent) <= kTolerancePercent) { + LOG(INFO) + << "observed traffic rate matches expected traffic rate (error: " + << kRelativeErrorPercent << "%)"; + } else { + ADD_FAILURE() << "observed traffic rate of " << kObservedTrafficRate + << " bytes/second is not within " << kTolerancePercent + << "% of the PIR of the queue '" << kTargetQueue + << "' targeted by traffic (PIR = " << kTargetQueuePir + << " bytes/second, error = " << kRelativeErrorPercent + << "%)"; + } + + // Verify that the target egress queue counters incremented. + const absl::Time kDeadline = absl::Now() + kMaxQueueCounterUpdateTime; + LOG(INFO) << "polling queue counters (this may take up to " + << kMaxQueueCounterUpdateTime << ")"; + QueueCounters final_counters, delta_counters; + do { + ASSERT_OK_AND_ASSIGN( + final_counters, + GetGnmiQueueCounters(kSutEgressPort, kTargetQueue, *gnmi_stub)); + delta_counters = final_counters - kInitialQueueCounters; + } while (TotalPacketsForQueue(delta_counters) < + kIxiaTrafficStats.num_tx_frames() && + absl::Now() < kDeadline); + LOG(INFO) << "queue counters incremented by " << delta_counters; + SCOPED_TRACE(absl::StrCat("Counters for queue ", kTargetQueue, + " did not change as expected within ", + ToString(kMaxQueueCounterUpdateTime), + " after injecting/receiving back ", + kIxiaTrafficStats.num_tx_frames(), "/", + kIxiaTrafficStats.num_rx_frames(), + " test packets from/at the Ixia.\nBefore: ", + ToString(kInitialQueueCounters), + "\nAfter :", ToString(final_counters))); + EXPECT_THAT(delta_counters, + ResultOf(TotalPacketsForQueue, + Eq(kIxiaTrafficStats.num_tx_frames()))); + EXPECT_THAT(delta_counters, Field(&QueueCounters::num_packets_transmitted, + Eq(kIxiaTrafficStats.num_rx_frames()))); + } + } + LOG(INFO) << "-- Test done -------------------------------------------------"; } -// Set up the switch to forward inbound packets to the egress port using default -// route in VRF. -// The rules will forward all matching packets matching source MAC address -// to the egress port specified. +struct EcnTestPacketCounters { + absl::Mutex mutex; + int num_packets_punted ABSL_GUARDED_BY(mutex) = 0; + int num_packets_ecn_marked ABSL_GUARDED_BY(mutex) = 0; +}; + +void ResetEcnTestPacketCounters(EcnTestPacketCounters &packet_receive_info) { + absl::MutexLock lock(&packet_receive_info.mutex); + packet_receive_info.num_packets_punted = 0; + packet_receive_info.num_packets_ecn_marked = 0; +} + +// Set up the switch to forward inbound packets to the egress port using +// default route in VRF. The rules will forward all matching packets matching +// source MAC address to the egress port specified. // // Also set up a Copy rule to CPU to punt egress packets to test for // any inspection. @@ -270,16 +672,17 @@ absl::StatusOr SetUpIxiaForEcnTest( ASSIGN_OR_RETURN( traffic_refs.emplace_back(), pins_test::ixia::SetUpTrafficItem(vport2_ref, vport3_ref, testbed)); - - return EcnTestIxiaSetUpResult{.topology_ref = topology_ref, - .traffic_refs = traffic_refs}; -} + return EcnTestIxiaSetUpResult{ + .topology_ref = topology_ref, + .traffic_refs = traffic_refs, + }; +} -// This test verifies ECN marking due to configured WRED profile on port queue. -// The test verifies the following: +// This test verifies ECN marking due to configured WRED profile on port +// queue. The test verifies the following: // 1. Switch marks Congestion Encountered bits in the ECN field for -// ECN capable traffic, when an egress port queue usage exceeds the threshold -// of the queue management profile configured for the queue. +// ECN capable traffic, when an egress port queue usage exceeds the +// threshold of the queue management profile configured for the queue. // 2. No marking when queue usage drops. // 3. The test also verifies that switch does not mark non-ECN capable traffic // even when threshold for queue usage exceeds. @@ -505,8 +908,9 @@ TEST_P(FrontpanelQosTest, TestWredEcnMarking) { traffic_ref1, frame_rate_at_line_speed_of_in_port1 + 1, *testbed)); - // TODO : kWredMaxThresholdInBytes is currently - // hardcoded in test. Get configured threshold configured from switch. + // TODO : kWredMaxThresholdInBytes is currently + // hardcoded in test. Get configured threshold configured from + // switch. constexpr int kWredMaxThresholdInBytes = 80000; // Send additional packets (twice the threshold) from second port, // to ensure threshold is crossed. @@ -556,9 +960,9 @@ TEST_P(FrontpanelQosTest, TestWredEcnMarking) { ResetEcnTestPacketCounters(packet_receive_info); absl::SleepFor(kStatsCollectionTime); - { - // We will be verifying for congestion bit in sampled packets received - // at Receiver. + { + // We will be verifying for congestion bit in sampled packets + // received at Receiver. absl::MutexLock lock(&packet_receive_info.mutex); LOG(INFO) << "Congestion : " << (is_congestion ? "true" : "false"); LOG(INFO) << "IPv4 : " << (is_ipv4 ? "true" : "false");