Skip to content

Commit 291a306

Browse files
[Thinkit] Use QoS table for meter rules. Add support for LACP packets in cpu_qos_without_ixia_test. Add Vrmu and ICMP to test packets for ToR.Disable broadcast on control when sending broadcast packets. (#1017)
* Dynamic buffer test for multicast * Add test for TTL and punt flows exceeding flow limits. Update test for additonal queues. Skip queues with passive traffic in certain CPU Qos tests. Remove inband qos queues and ip_src matcher from mapping test. * Use QoS table for meter rules. Add support for LACP packets in cpu_qos_without_ixia_test. Add Vrmu and ICMP to test packets for ToR.Disable broadcast on control when sending broadcast packets. --------- Co-authored-by: Srikishen Pondicherry Shanmugam <kishanps@google.com>
1 parent 26e2dba commit 291a306

File tree

3 files changed

+116
-51
lines changed

3 files changed

+116
-51
lines changed

tests/qos/BUILD.bazel

+3
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ cc_library(
5454
"//p4_pdpi:p4_runtime_session",
5555
"//p4_pdpi/packetlib:packetlib_cc_proto",
5656
"//p4_pdpi/string_encodings:decimal_string",
57+
"//sai_p4/instantiations/google:instantiations",
58+
"//sai_p4/instantiations/google:p4_versions",
5759
"//sai_p4/instantiations/google:sai_pd_cc_proto",
5860
"//tests/forwarding:util",
5961
"//tests/lib:switch_test_setup_helpers",
@@ -73,6 +75,7 @@ cc_library(
7375
"@com_google_absl//absl/cleanup",
7476
"@com_google_absl//absl/container:flat_hash_map",
7577
"@com_google_absl//absl/container:flat_hash_set",
78+
"@com_google_absl//absl/flags:flag",
7679
"@com_google_absl//absl/status",
7780
"@com_google_absl//absl/status:statusor",
7881
"@com_google_absl//absl/strings",

tests/qos/cpu_qos_test.cc

+110-49
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include <cstdint>
1818
#include <memory>
19+
#include <optional>
1920
#include <ostream>
2021
#include <string>
2122
#include <variant>
@@ -24,6 +25,8 @@
2425
#include "absl/cleanup/cleanup.h"
2526
#include "absl/container/flat_hash_map.h"
2627
#include "absl/container/flat_hash_set.h"
28+
#include "absl/flags/declare.h"
29+
#include "absl/flags/flag.h"
2730
#include "absl/status/status.h"
2831
#include "absl/status/statusor.h"
2932
#include "absl/strings/escaping.h"
@@ -40,7 +43,9 @@
4043
#include "absl/types/optional.h"
4144
#include "absl/types/variant.h"
4245
#include "glog/logging.h"
46+
#include "gmock/gmock.h"
4347
#include "google/protobuf/util/json_util.h"
48+
#include "gtest/gtest.h"
4449
#include "gutil/collections.h"
4550
#include "gutil/overload.h"
4651
#include "gutil/proto.h"
@@ -66,7 +71,9 @@
6671
#include "p4_pdpi/pd.h"
6772
#include "p4_pdpi/string_encodings/decimal_string.h"
6873
#include "proto/gnmi/gnmi.pb.h"
74+
#include "sai_p4/instantiations/google/instantiations.h"
6975
#include "sai_p4/instantiations/google/sai_pd.pb.h"
76+
#include "sai_p4/instantiations/google/versions.h"
7077
#include "tests/forwarding/util.h"
7178
#include "tests/lib/switch_test_setup_helpers.h"
7279
#include "tests/qos/gnmi_parsers.h"
@@ -78,8 +85,8 @@
7885
#include "thinkit/mirror_testbed.h"
7986
#include "thinkit/proto/generic_testbed.pb.h"
8087
#include "thinkit/switch.h"
81-
#include "gmock/gmock.h"
82-
#include "gtest/gtest.h"
88+
89+
ABSL_DECLARE_FLAG(std::optional<sai::Instantiation>, switch_instantiation);
8390

8491
namespace pins_test {
8592
namespace {
@@ -237,6 +244,7 @@ absl::Status SetUpV6PuntToCPUWithRateLimitAndWildCardL3AdmitEntry(
237244
match {} # Wildcard.
238245
action { admit_to_l3 {} }
239246
priority: 1
247+
meter_config { bytes_per_second: $2 burst_bytes: $3 }
240248
}
241249
)pb");
242250
std::vector<p4::v1::TableEntry> pi_entries;
@@ -246,26 +254,69 @@ absl::Status SetUpV6PuntToCPUWithRateLimitAndWildCardL3AdmitEntry(
246254
<< "Failed in PD table conversion to PI, entry: "
247255
<< l3_admit_entry.DebugString() << " error: ");
248256

249-
auto acl_entry = gutil::ParseProtoOrDie<sai::TableEntry>(absl::Substitute(
250-
R"pb(
251-
acl_ingress_table_entry {
252-
match {
253-
dst_mac { value: "$0" mask: "ff:ff:ff:ff:ff:ff" }
254-
is_ipv6 { value: "0x1" }
257+
if (ir_p4info.tables_by_name().contains("acl_ingress_qos_table")) {
258+
auto punt_entry = gutil::ParseProtoOrDie<sai::TableEntry>(absl::Substitute(
259+
R"pb(
260+
acl_ingress_table_entry {
261+
match {
262+
dst_mac { value: "$0" mask: "ff:ff:ff:ff:ff:ff" }
263+
is_ipv6 { value: "0x1" }
264+
}
265+
action { acl_trap { qos_queue: "$1" } }
266+
priority: 1
255267
}
256-
action { acl_trap { qos_queue: "$1" } }
257-
priority: 1
258-
meter_config { bytes_per_second: $2 burst_bytes: $3 }
259-
}
260-
)pb",
261-
dmac.ToString(), p4_queue, rate_bytes_per_second, burst_in_bytes));
268+
)pb",
269+
dmac.ToString(), p4_queue));
262270

263-
ASSIGN_OR_RETURN(
264-
pi_entries.emplace_back(),
265-
pdpi::PartialPdTableEntryToPiTableEntry(ir_p4info, acl_entry),
266-
_.SetPrepend() << "Failed in PD table conversion to PI, entry: "
267-
<< acl_entry.DebugString() << " error: ");
271+
LOG(INFO) << "Installing trap rule to queue " << p4_queue
272+
<< " in ACL punt table";
273+
ASSIGN_OR_RETURN(
274+
pi_entries.emplace_back(),
275+
pdpi::PartialPdTableEntryToPiTableEntry(ir_p4info, punt_entry));
268276

277+
auto qos_entry = gutil::ParseProtoOrDie<sai::TableEntry>(absl::Substitute(
278+
R"pb(
279+
acl_ingress_qos_table_entry {
280+
match {
281+
dst_mac { value: "$0" mask: "ff:ff:ff:ff:ff:ff" }
282+
is_ipv6 { value: "0x1" }
283+
}
284+
action {
285+
set_qos_queue_and_cancel_copy_above_rate_limit { qos_queue: "$1" }
286+
}
287+
priority: 4400
288+
meter_config { bytes_per_second: $2 burst_bytes: $3 }
289+
}
290+
)pb",
291+
dmac.ToString(), p4_queue, rate_bytes_per_second, burst_in_bytes));
292+
293+
LOG(INFO) << "Installing QoS rule to rate limit flow to a rate of "
294+
<< rate_bytes_per_second << "(Bps) and burst of "
295+
<< burst_in_bytes << "(Bytes)";
296+
ASSIGN_OR_RETURN(
297+
pi_entries.emplace_back(),
298+
pdpi::PartialPdTableEntryToPiTableEntry(ir_p4info, qos_entry));
299+
} else {
300+
auto acl_entry = gutil::ParseProtoOrDie<sai::TableEntry>(absl::Substitute(
301+
R"pb(
302+
acl_ingress_table_entry {
303+
match {
304+
dst_mac { value: "$0" mask: "ff:ff:ff:ff:ff:ff" }
305+
is_ipv6 { value: "0x1" }
306+
}
307+
action { acl_trap { qos_queue: "$1" } }
308+
priority: 1
309+
meter_config { bytes_per_second: $2 burst_bytes: $3 }
310+
}
311+
)pb",
312+
dmac.ToString(), p4_queue, rate_bytes_per_second, burst_in_bytes));
313+
314+
ASSIGN_OR_RETURN(
315+
pi_entries.emplace_back(),
316+
pdpi::PartialPdTableEntryToPiTableEntry(ir_p4info, acl_entry),
317+
_.SetPrepend() << "Failed in PD table conversion to PI, entry: "
318+
<< acl_entry.DebugString() << " error: ");
319+
}
269320
LOG(INFO) << "InstallPiTableEntries";
270321
return pdpi::InstallPiTableEntries(&p4_session, ir_p4info, pi_entries);
271322
}
@@ -285,8 +336,7 @@ absl::StatusOr<p4::v1::TableEntry> SetUpPuntToCPUWithRateLimit(
285336

286337
RETURN_IF_ERROR(pdpi::ClearTableEntries(&p4_session));
287338

288-
// There can be 2 schemes for punting depending on
289-
// pipeline.
339+
// There can be 2 schemes for punting depending on pipeline.
290340
// If p4 info table has the "acl_ingress_qos_table" configured, then
291341
// 1. Punt the packets using "acl_ingress_table" entry.
292342
// 2. Rate limit the packets using a "acl_ingress_qos_table" entry, which
@@ -739,10 +789,6 @@ absl::StatusOr<openconfig::QueuesByName> GetCpuQueueStateViaGnmi(
739789
gutil::ToAbslStatus(google::protobuf::util::JsonStringToMessage(
740790
queues_json, &queues_proto, options)));
741791

742-
// Convert `Queues` to `QueuesByName`, which is equivalent but more convenient
743-
// for diffing.
744-
// Today, subtree subscription to queues isn't working. Query each leaf
745-
// individually for the actual data.
746792
openconfig::QueuesByName queues_by_name;
747793
for (auto &queue : queues_proto.queues()) {
748794
ASSIGN_OR_RETURN(
@@ -849,6 +895,27 @@ TEST_P(CpuQosTestWithoutIxia,
849895
ASSERT_OK_AND_ASSIGN(IpAddresses loopback_ips,
850896
ParseLoopbackIps(sut_gnmi_config));
851897

898+
// Install ACL table entry to drop broadcast packets from Control to avoid
899+
// broadcast storm.
900+
ASSERT_OK_AND_ASSIGN(
901+
const sai::TableEntry pd_broadcast_drop_entry,
902+
gutil::ParseTextProto<sai::TableEntry>(R"pb(
903+
acl_ingress_table_entry {
904+
priority: 1
905+
match {
906+
dst_mac { value: "ff:ff:ff:ff:ff:ff" mask: "ff:ff:ff:ff:ff:ff" }
907+
}
908+
action { acl_drop {} }
909+
}
910+
)pb"));
911+
912+
ASSERT_OK_AND_ASSIGN(const p4::v1::TableEntry pi_drop_entry,
913+
pdpi::PartialPdTableEntryToPiTableEntry(
914+
ir_p4info, pd_broadcast_drop_entry));
915+
916+
ASSERT_OK(
917+
pdpi::InstallPiTableEntry(control_p4rt_session.get(), pi_drop_entry));
918+
852919
// Read CPU queue state prior to injecting test packets. The state should
853920
// remain unchanged when we inject test packets.
854921
ASSERT_OK_AND_ASSIGN(auto gnmi_stub, sut.CreateGnmiStub());
@@ -1052,35 +1119,28 @@ TEST_P(CpuQosTestWithoutIxia, PuntToCpuWithVlanTag) {
10521119
ASSERT_OK(pins::InjectEgressPacket(
10531120
/*port=*/link_used_for_test_packets.control_device_port_p4rt_name,
10541121
/*packet=*/raw_packet, ir_p4info, control_p4rt_session.get(),
1055-
/*packet_delay=*/std::nullopt));
1122+
/*packet_delay=*/absl::Milliseconds(10)));
10561123
}
10571124

1058-
// Verify we receive expected packets back.
1059-
absl::SleepFor(absl::Seconds(1));
1060-
int num_vlan_packets_received = 0;
1061-
ASSERT_OK_AND_ASSIGN(
1062-
std::vector<p4::v1::StreamMessageResponse> pi_responses,
1063-
sut_p4rt_session->ReadStreamChannelResponsesAndFinish());
1064-
for (const auto &pi_response : pi_responses) {
1065-
sai::StreamMessageResponse pd_response;
1066-
ASSERT_OK(pdpi::PiStreamMessageResponseToPd(ir_p4info, pi_response,
1067-
&pd_response))
1068-
<< " packet in PI to PD failed: " << pi_response.DebugString();
1069-
ASSERT_TRUE(pd_response.has_packet())
1070-
<< " received unexpected stream message for packet in: "
1071-
<< pd_response.DebugString();
1072-
packetlib::Packet punted_packet =
1073-
packetlib::ParsePacket(pd_response.packet().payload());
1074-
EXPECT_THAT(punted_packet, EqualsProto(test_packet));
1075-
num_vlan_packets_received += 1;
1076-
}
1077-
EXPECT_EQ(num_vlan_packets_received, kPacketCount);
1125+
EXPECT_OK(sut_p4rt_session->HandleNextNStreamMessages(
1126+
[&](const p4::v1::StreamMessageResponse &message) {
1127+
if (!message.has_packet()) return false;
1128+
packetlib::Packet punted_packet =
1129+
packetlib::ParsePacket(message.packet().payload());
1130+
if (!testing::Matches(EqualsProto(test_packet))(punted_packet)) {
1131+
LOG(WARNING) << "Received unknown packet: "
1132+
<< punted_packet.ShortDebugString();
1133+
return false;
1134+
}
1135+
return true;
1136+
},
1137+
kPacketCount, absl::Minutes(2)));
10781138
}
10791139
LOG(INFO) << "-- END OF TEST -----------------------------------------------";
10801140
}
10811141

1082-
// Purpose: Verify DSCP-to-queue mapping for traffic to switch loopback IP.
1083-
TEST_P(CpuQosTestWithoutIxia, TrafficToLoopbackIpGetsMappedToCorrectQueues) {
1142+
// Purpose: Verify protocol-to-queue mapping for traffic to switch.
1143+
TEST_P(CpuQosTestWithoutIxia, TrafficToSwitchInbandGetsMappedToCorrectQueues) {
10841144
LOG(INFO) << "-- START OF TEST ---------------------------------------------";
10851145

10861146
// Check that a test packet generator function is specified.
@@ -1120,7 +1180,8 @@ TEST_P(CpuQosTestWithoutIxia, TrafficToLoopbackIpGetsMappedToCorrectQueues) {
11201180
<< link_used_for_test_packets;
11211181

11221182
std::vector<PacketAndExpectedTargetQueue> test_packets =
1123-
GetParam().test_packet_generator_function(sut_gnmi_config);
1183+
GetParam().test_packet_generator_function(
1184+
sut_gnmi_config, absl::GetFlag(FLAGS_switch_instantiation));
11241185
ASSERT_FALSE(test_packets.empty())
11251186
<< "No packets to test, maybe no loopback IP is configured on switch?";
11261187

tests/qos/cpu_qos_test.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@
2929
#include "gutil/testing.h"
3030
#include "p4_pdpi/netaddr/mac_address.h"
3131
#include "p4_pdpi/packetlib/packetlib.pb.h"
32+
#include "sai_p4/instantiations/google/instantiations.h"
3233
#include "thinkit/generic_testbed.h"
3334
#include "thinkit/generic_testbed_fixture.h"
3435
#include "thinkit/mirror_testbed.h"
3536
#include "thinkit/mirror_testbed_fixture.h"
36-
#include "gtest/gtest.h"
3737

3838
namespace pins_test {
3939
// Structure holds packet and expected target queue passed in to test as
@@ -56,7 +56,8 @@ struct ParamsForTestsWithoutIxia {
5656
// Function to generate test packets and expected target queue passed into the
5757
// test for verification.
5858
std::function<std::vector<PacketAndExpectedTargetQueue>(
59-
absl::string_view gnmi_config)>
59+
absl::string_view gnmi_config,
60+
std::optional<sai::Instantiation> instantiation)>
6061
test_packet_generator_function;
6162
};
6263

0 commit comments

Comments
 (0)