Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Comb] Add util functions for QoS and buffer profiles overriding and getting gNMIConfig. #964

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions tests/qos/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -188,11 +188,10 @@ cc_library(
"//lib/gnmi:gnmi_helper",
"//lib/gnmi:openconfig_cc_proto",
"//lib/utils:json_utils",
"//thinkit:generic_testbed",
"//thinkit:mirror_testbed",
"//thinkit/proto:generic_testbed_cc_proto",
"@com_github_gnmi//proto/gnmi:gnmi_cc_proto",
"@com_github_gnmi//proto/gnmi:gnmi_cc_grpc_proto",
"@com_github_nlohmann_json//:nlohmann_json",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
Expand Down
3 changes: 1 addition & 2 deletions tests/qos/frontpanel_qos_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,7 @@ absl::StatusOr<Cleanup> ConfigureFairBufferConfigForPortUntilEndOfScope(
buffer_config_by_queue_name;
// TODO: Read queue names from switch instead of
// hard-coding them here.
for (absl::string_view queue_name :
{"LLQ1", "LLQ2", "BE1", "AF1", "AF2", "AF3", "AF4", "NC1"}) {
for (absl::string_view queue_name : kAllQueuesNames) {
buffer_config_by_queue_name[queue_name] = BufferParameters{
.dedicated_buffer = 0,
.use_shared_buffer = true,
Expand Down
98 changes: 96 additions & 2 deletions tests/qos/qos_test_util.cc
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
#include "tests/qos/qos_test_util.h"

#include <array>

#include "absl/container/flat_hash_map.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/numbers.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "absl/strings/strip.h"
#include "absl/strings/substitute.h"
#include "absl/time/clock.h"
#include "absl/time/time.h"
#include "google/protobuf/util/json_util.h"
#include "gutil/collections.h"
#include "gutil/proto.h"
#include "gutil/status.h"
#include "include/nlohmann/json.hpp"
#include "lib/gnmi/gnmi_helper.h"
#include "lib/gnmi/openconfig.pb.h"
#include "lib/utils/json_utils.h"
Expand Down Expand Up @@ -337,6 +337,18 @@ absl::Status SetSchedulerPolicyParameters(
return absl::OkStatus();
}

absl::Status ReplaceCpuSchedulerPolicyParametersForAllQueues(
gnmi::gNMI::StubInterface &gnmi_stub, SchedulerParameters scheduler_param) {
ASSIGN_OR_RETURN(std::string scheduler_policy_name,
GetSchedulerPolicyNameByEgressPort("CPU", gnmi_stub));
absl::flat_hash_map<std::string, SchedulerParameters> scheduler_params;
for (absl::string_view queue_name : kAllQueuesNames) {
scheduler_params[queue_name] = scheduler_param;
}
return SetSchedulerPolicyParameters(scheduler_policy_name, scheduler_params,
gnmi_stub);
}

absl::StatusOr<absl::flat_hash_map<std::string, int64_t>>
GetSchedulerPolicyWeightsByQueue(absl::string_view scheduler_policy_name,
gnmi::gNMI::StubInterface &gnmi) {
Expand Down Expand Up @@ -590,4 +602,86 @@ absl::Status SetBufferConfigParameters(
return absl::OkStatus();
}

absl::Status DisablePuntRateLimits(gnmi::gNMI::StubInterface &gnmi_stub) {
// Effectively Disabling punt rate limiting on both control switch and SUT
// by setting both committed and peak information rate to 1 million pkt/s and
// both committed and excess burst rate to 1'000 pkts.
constexpr int64_t k1Million = 1'000'000;
constexpr int64_t k1Thousand = 1'000;
SchedulerParameters scheduler_params = SchedulerParameters{
.committed_information_rate = k1Million,
.committed_burst_size = k1Thousand,
.peak_information_rate = k1Million,
.excess_burst_size = k1Thousand,
};
RETURN_IF_ERROR(ReplaceCpuSchedulerPolicyParametersForAllQueues(
gnmi_stub, scheduler_params));
return absl::OkStatus();
}

absl::Status
UpdateBufferAllocationForAllCpuQueues(gnmi::gNMI::StubInterface &gnmi_stub,
int buffer_size) {
absl::flat_hash_map<std::string, BufferParameters>
buffer_config_by_queue_name;
for (absl::string_view queue_name : kAllQueuesNames) {
buffer_config_by_queue_name[queue_name] = BufferParameters{
.dedicated_buffer = 0,
.use_shared_buffer = true,
.shared_buffer_limit_type = "openconfig-qos:STATIC",
.dynamic_limit_scaling_factor = 0,
.shared_static_limit = buffer_size,
};
}
ASSIGN_OR_RETURN(const std::string buffer_profile_name,
GetBufferAllocationProfileByEgressPort("CPU", gnmi_stub));
RETURN_IF_ERROR(SetBufferConfigParameters(
buffer_profile_name, buffer_config_by_queue_name, gnmi_stub));
return absl::OkStatus();
}

absl::Status
EffectivelyDisablePuntLimitsForSwitch(SwitchRoleToDisablePuntFlowQoS role,
thinkit::MirrorTestbed &testbed) {
std::unique_ptr<gnmi::gNMI::StubInterface> gnmi_stub;
switch (role) {
case SwitchRoleToDisablePuntFlowQoS::kSwitchUnderTest: {
ASSIGN_OR_RETURN(gnmi_stub, testbed.Sut().CreateGnmiStub());
break;
}
case SwitchRoleToDisablePuntFlowQoS::kControlSwitch: {
ASSIGN_OR_RETURN(gnmi_stub, testbed.ControlSwitch().CreateGnmiStub());
break;
}
}
std::string switch_role_name = SwtichRoleToDisableQoSToString(role);

ASSIGN_OR_RETURN(auto gnmi_config_before_qos_and_buffer_change,
pins_test::GetGnmiConfig(*gnmi_stub));
RETURN_IF_ERROR(testbed.Environment().StoreTestArtifact(
absl::StrCat(switch_role_name,
"_gnmi_config_before_qos_and_buffer_change.pb.txt"),
gnmi_config_before_qos_and_buffer_change));
RETURN_IF_ERROR(pins_test::DisablePuntRateLimits(*gnmi_stub));
LOG(INFO) << "Disabling punt rate limits complete for " << switch_role_name;

// The default buffer size for CPU on most switches is 18'432. We use 4x of
// the current value to prevent packet loss.
constexpr int kBufferSizeForCpuInBype = 18432 * 4;
RETURN_IF_ERROR(pins_test::UpdateBufferAllocationForAllCpuQueues(
*gnmi_stub, kBufferSizeForCpuInBype));

LOG(INFO) << "Update buffer allocation for all CPU queues complete for "
<< switch_role_name << ". All CPU queues now have "
<< kBufferSizeForCpuInBype << " bytes for their buffers.";

ASSIGN_OR_RETURN(auto gnmi_config_after_qos_and_buffer_change,
pins_test::GetGnmiConfig(*gnmi_stub));
RETURN_IF_ERROR(testbed.Environment().StoreTestArtifact(
absl::StrCat(switch_role_name,
"_gnmi_config_after_qos_and_buffer_change.pb.txt"),
gnmi_config_after_qos_and_buffer_change));
return absl::OkStatus();
}

} // namespace pins_test
43 changes: 42 additions & 1 deletion tests/qos/qos_test_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#include "lib/gnmi/openconfig.pb.h"
#include "proto/gnmi/gnmi.grpc.pb.h"
#include "proto/gnmi/gnmi.pb.h"
#include "thinkit/generic_testbed.h"
#include "thinkit/mirror_testbed.h"
#include "thinkit/proto/generic_testbed.pb.h"

namespace pins_test {
Expand All @@ -24,6 +24,26 @@ namespace pins_test {
// 10 seconds.
constexpr absl::Duration kMaxQueueCounterUpdateTime = absl::Seconds(25);

// TODO read the queue names from the switch instead of using
// hand-coded names.
constexpr std::array<absl::string_view, 8> kAllQueuesNames = {
"LLQ1", "LLQ2", "BE1", "AF1", "AF2", "AF3", "AF4", "NC1"};

enum class SwitchRoleToDisablePuntFlowQoS {
kControlSwitch,
kSwitchUnderTest,
};

inline std::string
SwtichRoleToDisableQoSToString(SwitchRoleToDisablePuntFlowQoS role) {
switch (role) {
case SwitchRoleToDisablePuntFlowQoS::kControlSwitch:
return "control_switch";
case SwitchRoleToDisablePuntFlowQoS::kSwitchUnderTest:
return "switch_under_test";
}
}

// These are the counters we track in these tests.
struct QueueCounters {
int64_t num_packets_transmitted = 0;
Expand Down Expand Up @@ -129,6 +149,10 @@ absl::Status SetSchedulerPolicyParameters(
gnmi::gNMI::StubInterface &gnmi,
absl::Duration convergence_timeout = absl::Seconds(10));

// Updates all CPU queues' scheduler policy parameters with `scheduler_params`.
absl::Status UpdateSchedulerPolicyParametersForAllCpuQueues(
gnmi::gNMI::StubInterface &gnmi_stub, SchedulerParameters scheduler_params);

// Reads the weights of all round-robin schedulers belonging to the given
// scheduler policy from the state path, and returns them keyed by the name of
// the queue they apply to.
Expand Down Expand Up @@ -204,6 +228,23 @@ absl::Status SetBufferConfigParameters(
gnmi::gNMI::StubInterface &gnmi,
absl::Duration convergence_timeout = absl::Seconds(10));

// Disables punt rate limits on all CPU queues for the switch `gnmi_stub`
// connects to.
absl::Status DisablePuntRateLimits(gnmi::gNMI::StubInterface &gnmi_stub);

// Updates buffer allocation profile for all CPU queues with `buffer_size` for
// the switch `gnmi_stub` connects to.
absl::Status
UpdateBufferAllocationForAllCpuQueues(gnmi::gNMI::StubInterface &gnmi_stub,
int buffer_size);

// Disables QoS limits for punting for switch with `role`.
// Scheduler policies and buffer allocation will be set to very high value to
// effectively remove limits for punting.
absl::Status
EffectivelyDisablePuntLimitsForSwitch(SwitchRoleToDisablePuntFlowQoS role,
thinkit::MirrorTestbed &testbed);

} // namespace pins_test

#endif // PINS_TESTS_QOS_QOS_TEST_UTIL_H_
Loading