16
16
17
17
#include < cstdint>
18
18
#include < memory>
19
+ #include < optional>
19
20
#include < ostream>
20
21
#include < string>
21
22
#include < variant>
24
25
#include " absl/cleanup/cleanup.h"
25
26
#include " absl/container/flat_hash_map.h"
26
27
#include " absl/container/flat_hash_set.h"
28
+ #include " absl/flags/declare.h"
29
+ #include " absl/flags/flag.h"
27
30
#include " absl/status/status.h"
28
31
#include " absl/status/statusor.h"
29
32
#include " absl/strings/escaping.h"
40
43
#include " absl/types/optional.h"
41
44
#include " absl/types/variant.h"
42
45
#include " glog/logging.h"
46
+ #include " gmock/gmock.h"
43
47
#include " google/protobuf/util/json_util.h"
48
+ #include " gtest/gtest.h"
44
49
#include " gutil/collections.h"
45
50
#include " gutil/overload.h"
46
51
#include " gutil/proto.h"
66
71
#include " p4_pdpi/pd.h"
67
72
#include " p4_pdpi/string_encodings/decimal_string.h"
68
73
#include " proto/gnmi/gnmi.pb.h"
74
+ #include " sai_p4/instantiations/google/instantiations.h"
69
75
#include " sai_p4/instantiations/google/sai_pd.pb.h"
76
+ #include " sai_p4/instantiations/google/versions.h"
70
77
#include " tests/forwarding/util.h"
71
78
#include " tests/lib/switch_test_setup_helpers.h"
72
79
#include " tests/qos/gnmi_parsers.h"
78
85
#include " thinkit/mirror_testbed.h"
79
86
#include " thinkit/proto/generic_testbed.pb.h"
80
87
#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);
83
90
84
91
namespace pins_test {
85
92
namespace {
@@ -237,6 +244,7 @@ absl::Status SetUpV6PuntToCPUWithRateLimitAndWildCardL3AdmitEntry(
237
244
match {} # Wildcard.
238
245
action { admit_to_l3 {} }
239
246
priority: 1
247
+ meter_config { bytes_per_second: $2 burst_bytes: $3 }
240
248
}
241
249
)pb" );
242
250
std::vector<p4::v1::TableEntry> pi_entries;
@@ -246,26 +254,69 @@ absl::Status SetUpV6PuntToCPUWithRateLimitAndWildCardL3AdmitEntry(
246
254
<< " Failed in PD table conversion to PI, entry: "
247
255
<< l3_admit_entry.DebugString () << " error: " );
248
256
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
255
267
}
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));
262
270
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) );
268
276
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
+ }
269
320
LOG (INFO) << " InstallPiTableEntries" ;
270
321
return pdpi::InstallPiTableEntries (&p4_session, ir_p4info, pi_entries);
271
322
}
@@ -285,8 +336,7 @@ absl::StatusOr<p4::v1::TableEntry> SetUpPuntToCPUWithRateLimit(
285
336
286
337
RETURN_IF_ERROR (pdpi::ClearTableEntries (&p4_session));
287
338
288
- // There can be 2 schemes for punting depending on
289
- // pipeline.
339
+ // There can be 2 schemes for punting depending on pipeline.
290
340
// If p4 info table has the "acl_ingress_qos_table" configured, then
291
341
// 1. Punt the packets using "acl_ingress_table" entry.
292
342
// 2. Rate limit the packets using a "acl_ingress_qos_table" entry, which
@@ -739,10 +789,6 @@ absl::StatusOr<openconfig::QueuesByName> GetCpuQueueStateViaGnmi(
739
789
gutil::ToAbslStatus (google::protobuf::util::JsonStringToMessage (
740
790
queues_json, &queues_proto, options)));
741
791
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.
746
792
openconfig::QueuesByName queues_by_name;
747
793
for (auto &queue : queues_proto.queues ()) {
748
794
ASSIGN_OR_RETURN (
@@ -849,6 +895,27 @@ TEST_P(CpuQosTestWithoutIxia,
849
895
ASSERT_OK_AND_ASSIGN (IpAddresses loopback_ips,
850
896
ParseLoopbackIps (sut_gnmi_config));
851
897
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
+
852
919
// Read CPU queue state prior to injecting test packets. The state should
853
920
// remain unchanged when we inject test packets.
854
921
ASSERT_OK_AND_ASSIGN (auto gnmi_stub, sut.CreateGnmiStub ());
@@ -1052,35 +1119,28 @@ TEST_P(CpuQosTestWithoutIxia, PuntToCpuWithVlanTag) {
1052
1119
ASSERT_OK (pins::InjectEgressPacket (
1053
1120
/* port=*/ link_used_for_test_packets.control_device_port_p4rt_name ,
1054
1121
/* packet=*/ raw_packet, ir_p4info, control_p4rt_session.get (),
1055
- /* packet_delay=*/ std::nullopt ));
1122
+ /* packet_delay=*/ absl::Milliseconds ( 10 ) ));
1056
1123
}
1057
1124
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 )));
1078
1138
}
1079
1139
LOG (INFO) << " -- END OF TEST -----------------------------------------------" ;
1080
1140
}
1081
1141
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 ) {
1084
1144
LOG (INFO) << " -- START OF TEST ---------------------------------------------" ;
1085
1145
1086
1146
// Check that a test packet generator function is specified.
@@ -1120,7 +1180,8 @@ TEST_P(CpuQosTestWithoutIxia, TrafficToLoopbackIpGetsMappedToCorrectQueues) {
1120
1180
<< link_used_for_test_packets;
1121
1181
1122
1182
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));
1124
1185
ASSERT_FALSE (test_packets.empty ())
1125
1186
<< " No packets to test, maybe no loopback IP is configured on switch?" ;
1126
1187
0 commit comments