Skip to content

Commit 5b0a989

Browse files
kishanpsVSuryaprasad-HCL
authored andcommitted
[Thinkit] Add test to verify match on CPU behavior.Refactor IrUpdates to use entities instead of table entries.enclose missed table_entries in entity.Add ACL QoS table to FBR instances.Transition to using entities instead of table entries.Add an option to NOT push P4Info.Support non-mirrored testbeds. Mask bug where control switch interfaces don't come up. Slightly improve naming and scoping.
1 parent cca261d commit 5b0a989

File tree

4 files changed

+301
-130
lines changed

4 files changed

+301
-130
lines changed

tests/forwarding/BUILD.bazel

-6
Original file line numberDiff line numberDiff line change
@@ -280,13 +280,11 @@ cc_library(
280280
"//gutil:status_matchers",
281281
"//lib/gnmi:gnmi_helper",
282282
"//lib/gnmi:openconfig_cc_proto",
283-
"//lib/p4rt:p4rt_port",
284283
"//p4_fuzzer:annotation_util",
285284
"//p4_fuzzer:fuzzer_cc_proto",
286285
"//p4_fuzzer:fuzzer_config",
287286
"//p4_fuzzer:mutation_and_fuzz_util",
288287
"//p4_fuzzer:switch_state",
289-
"//p4_pdpi:ir",
290288
"//p4_pdpi:ir_cc_proto",
291289
"//p4_pdpi:p4_runtime_session",
292290
"//p4_pdpi:p4_runtime_session_extras",
@@ -305,16 +303,12 @@ cc_library(
305303
"@com_github_p4lang_p4runtime//:p4info_cc_proto",
306304
"@com_github_p4lang_p4runtime//:p4runtime_cc_proto",
307305
"@com_google_absl//absl/algorithm:container",
308-
"@com_google_absl//absl/container:btree",
309-
"@com_google_absl//absl/container:flat_hash_map",
310-
"@com_google_absl//absl/container:flat_hash_set",
311306
"@com_google_absl//absl/random",
312307
"@com_google_absl//absl/status",
313308
"@com_google_absl//absl/status:statusor",
314309
"@com_google_absl//absl/strings",
315310
"@com_google_absl//absl/strings:str_format",
316311
"@com_google_absl//absl/time",
317-
"@com_google_absl//absl/types:span",
318312
"@com_google_googletest//:gtest",
319313
"@com_google_protobuf//:protobuf",
320314
],

tests/forwarding/l3_admit_test.cc

+206-45
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ namespace {
6161
// otherwise it can use this constant to say no VLAN ID should be set.
6262
constexpr absl::string_view kNoVlanId = "";
6363

64+
// send_to_ingress is a special port created on the switch which allows the CPU
65+
// to inject a packet into the ingress pipeline.
66+
constexpr absl::string_view kSendToIngress = "send_to_ingress";
67+
6468
absl::Status AddAndSetDefaultVrf(pdpi::P4RuntimeSession& session,
6569
const pdpi::IrP4Info& ir_p4info,
6670
const std::string& vrf_id) {
@@ -69,14 +73,16 @@ absl::Status AddAndSetDefaultVrf(pdpi::P4RuntimeSession& session,
6973
RETURN_IF_ERROR(gutil::ReadProtoFromString(
7074
absl::Substitute(R"pb(
7175
type: INSERT
72-
table_entry {
73-
table_name: "acl_pre_ingress_table"
74-
priority: 2000
75-
action {
76-
name: "set_vrf"
77-
params {
78-
name: "vrf_id"
79-
value { str: "$0" }
76+
entity {
77+
table_entry {
78+
table_name: "acl_pre_ingress_table"
79+
priority: 2000
80+
action {
81+
name: "set_vrf"
82+
params {
83+
name: "vrf_id"
84+
value { str: "$0" }
85+
}
8086
}
8187
}
8288
}
@@ -101,21 +107,23 @@ absl::Status AllowVrfTrafficToDstMac(pdpi::P4RuntimeSession& session,
101107
RETURN_IF_ERROR(gutil::ReadProtoFromString(
102108
absl::Substitute(R"pb(
103109
type: INSERT
104-
table_entry {
105-
table_name: "acl_pre_ingress_table"
106-
matches {
107-
name: "dst_mac"
108-
ternary {
109-
value { mac: "$0" }
110-
mask { mac: "ff:ff:ff:ff:ff:ff" }
110+
entity {
111+
table_entry {
112+
table_name: "acl_pre_ingress_table"
113+
matches {
114+
name: "dst_mac"
115+
ternary {
116+
value { mac: "$0" }
117+
mask { mac: "ff:ff:ff:ff:ff:ff" }
118+
}
111119
}
112-
}
113-
priority: 2000
114-
action {
115-
name: "set_vrf"
116-
params {
117-
name: "vrf_id"
118-
value { str: "$1" }
120+
priority: 2000
121+
action {
122+
name: "set_vrf"
123+
params {
124+
name: "vrf_id"
125+
value { str: "$1" }
126+
}
119127
}
120128
}
121129
}
@@ -138,14 +146,16 @@ absl::Status PuntAllPacketsToController(pdpi::P4RuntimeSession& session,
138146
R"pb(
139147
updates {
140148
type: INSERT
141-
table_entry {
142-
table_name: "acl_ingress_table"
143-
priority: 2
144-
action {
145-
name: "acl_trap",
146-
params {
147-
name: "qos_queue"
148-
value { str: "0x1" }
149+
entity {
150+
table_entry {
151+
table_name: "acl_ingress_table"
152+
priority: 2
153+
action {
154+
name: "acl_trap",
155+
params {
156+
name: "qos_queue"
157+
value { str: "0x1" }
158+
}
149159
}
150160
}
151161
}
@@ -280,7 +290,7 @@ absl::StatusOr<std::string> UdpPacket(absl::string_view dst_mac,
280290

281291
absl::Status SendUdpPacket(pdpi::P4RuntimeSession& session,
282292
const pdpi::IrP4Info& ir_p4info,
283-
const std::string& port_id, int packet_count,
293+
absl::string_view port_id, int packet_count,
284294
absl::string_view dst_mac, absl::string_view vlan_id,
285295
absl::string_view dst_ip,
286296
absl::string_view payload) {
@@ -292,8 +302,15 @@ absl::Status SendUdpPacket(pdpi::P4RuntimeSession& session,
292302
UdpPacket(dst_mac, vlan_id, dst_ip,
293303
absl::Substitute("[Packet:$0] $1", i, payload)));
294304
// Rate limit to 500pps to avoid punt packet drops on the control switch.
295-
RETURN_IF_ERROR(InjectEgressPacket(port_id, packet, ir_p4info, &session,
296-
/*packet_delay=*/absl::Milliseconds(2)));
305+
if (port_id == kSendToIngress) {
306+
RETURN_IF_ERROR(
307+
InjectIngressPacket(packet, ir_p4info, &session,
308+
/*packet_delay=*/absl::Milliseconds(2)));
309+
} else {
310+
RETURN_IF_ERROR(
311+
InjectEgressPacket(std::string{port_id}, packet, ir_p4info, &session,
312+
/*packet_delay=*/absl::Milliseconds(2)));
313+
}
297314
}
298315
return absl::OkStatus();
299316
}
@@ -805,18 +822,20 @@ TEST_P(L3AdmitTestFixture, VlanOverrideAdmitsAllPacketsToL3Routing) {
805822
R"pb(
806823
updates {
807824
type: INSERT
808-
table_entry {
809-
table_name: "acl_pre_ingress_vlan_table"
810-
priority: 10
811-
matches {
812-
name: "is_ipv4"
813-
optional { value { hex_str: "0x1" } }
814-
}
815-
action {
816-
name: "set_outer_vlan_id",
817-
params {
818-
name: "vlan_id"
819-
value { hex_str: "0xfff" }
825+
entity {
826+
table_entry {
827+
table_name: "acl_pre_ingress_vlan_table"
828+
priority: 10
829+
matches {
830+
name: "is_ipv4"
831+
optional { value { hex_str: "0x1" } }
832+
}
833+
action {
834+
name: "set_outer_vlan_id",
835+
params {
836+
name: "vlan_id"
837+
value { hex_str: "0xfff" }
838+
}
820839
}
821840
}
822841
}
@@ -877,4 +896,146 @@ TEST_P(L3AdmitTestFixture, VlanOverrideAdmitsAllPacketsToL3Routing) {
877896
EXPECT_EQ(good_packet_count, kNumberOfTestPackets);
878897
}
879898

899+
TEST_P(L3AdmitTestFixture, RoutedPacketsCanMatchOnCpuPort) {
900+
901+
// Only run this test if the ACL_INGRESS_QOS_TABLE exists and we can match on
902+
// the IN_PORT.
903+
if (!TableHasMatchField(ir_p4info_, "acl_ingress_qos_table", "in_port")) {
904+
GTEST_SKIP() << "Skipping because ACL_INGRESS_QOS_TABLE does not exist.";
905+
}
906+
907+
// Get SUT and control ports to test on.
908+
ASSERT_OK_AND_ASSIGN(
909+
auto gnmi_stub_sut,
910+
GetParam().testbed_interface->GetMirrorTestbed().Sut().CreateGnmiStub());
911+
ASSERT_OK_AND_ASSIGN(
912+
auto gnmi_stub_control,
913+
GetParam().testbed_interface->GetMirrorTestbed().Sut().CreateGnmiStub());
914+
ASSERT_OK_AND_ASSIGN(std::string sut_port,
915+
pins_test::GetAnyUpInterfacePortId(*gnmi_stub_sut));
916+
ASSERT_OK_AND_ASSIGN(std::string control_port,
917+
pins_test::GetAnyUpInterfacePortId(*gnmi_stub_control));
918+
919+
// Punt all traffic arriving at the control switch, and collect them to verify
920+
// forwarding.
921+
ASSERT_OK(
922+
PuntAllPacketsToController(*control_switch_p4rt_session_, ir_p4info_));
923+
924+
// Add an L3 route to enable forwarding.
925+
L3Route l3_route{
926+
.vrf_id = "vrf-1",
927+
.switch_mac = "00:00:00:00:00:01",
928+
.switch_ip = std::make_pair("10.0.0.1", 32),
929+
.peer_port = sut_port,
930+
.peer_mac = "00:00:00:00:00:02",
931+
.peer_ip = "fe80::2",
932+
.router_interface_id = "rif-1",
933+
.nexthop_id = "nexthop-1",
934+
};
935+
ASSERT_OK(
936+
AddAndSetDefaultVrf(*sut_p4rt_session_, ir_p4info_, l3_route.vrf_id));
937+
ASSERT_OK(AddL3Route(*sut_p4rt_session_, ir_p4info_, l3_route));
938+
939+
// Admit only 1 MAC address to the forwarding pipeline.
940+
ASSERT_OK(AdmitL3Route(
941+
*sut_p4rt_session_, ir_p4info_,
942+
L3AdmitOptions{
943+
.priority = 2070,
944+
.dst_mac = std ::make_pair("00:01:02:03:04:05", "FF:FF:FF:FF:FF:FF"),
945+
}));
946+
947+
{
948+
// Write QoS rule that will drop any packet, and a higher priority rule that
949+
// will only allow ports matching on the CPU port.
950+
pdpi::IrWriteRequest ir_write_request;
951+
ASSERT_OK(gutil::ReadProtoFromString(
952+
R"pb(
953+
updates {
954+
type: INSERT
955+
entity {
956+
table_entry {
957+
table_name: "acl_ingress_qos_table"
958+
priority: 10
959+
action {
960+
name: "acl_drop",
961+
}
962+
}
963+
}
964+
}
965+
updates {
966+
type: INSERT
967+
entity {
968+
table_entry {
969+
table_name: "acl_ingress_qos_table"
970+
priority: 11
971+
matches {
972+
name: "in_port"
973+
optional {
974+
value {
975+
str: "4294967293" # OPENFLOW_PORT_CONTROLLER
976+
}
977+
}
978+
}
979+
action {
980+
name: "acl_forward",
981+
}
982+
}
983+
}
984+
}
985+
)pb",
986+
&ir_write_request));
987+
ASSERT_OK_AND_ASSIGN(
988+
p4::v1::WriteRequest pi_write_request,
989+
pdpi::IrWriteRequestToPi(ir_p4info_, ir_write_request));
990+
ASSERT_OK(pdpi::SetMetadataAndSendPiWriteRequest(sut_p4rt_session_.get(),
991+
pi_write_request));
992+
}
993+
994+
// Send 2 sets of packets to the switch. The packets are exactly the same, but
995+
// the first set of packets will be sent to the SUT from the control switch
996+
// (i.e. they arrive on a physical port). The second set of packets will be
997+
// sent through the "send_to_ingress" port.
998+
const int kNumberOfTestPackets = 100;
999+
1000+
// Send the "bad" packets first to give them the most time.
1001+
const std::string kBadPayload =
1002+
"Testing L3 forwarding. This packet should be dropped.";
1003+
ASSERT_OK(SendUdpPacket(*control_switch_p4rt_session_, ir_p4info_,
1004+
control_port, kNumberOfTestPackets,
1005+
/*dst_mac=*/"00:01:02:03:04:05", kNoVlanId,
1006+
/*dst_ip=*/"10.0.0.1", kBadPayload));
1007+
1008+
// Then send the "good" packets.
1009+
const std::string kGoodPayload =
1010+
"Testing L3 forwarding. This packet should arrive to packet in.";
1011+
ASSERT_OK(SendUdpPacket(*sut_p4rt_session_, ir_p4info_, kSendToIngress,
1012+
kNumberOfTestPackets, /*dst_mac=*/"00:01:02:03:04:05",
1013+
kNoVlanId, /*dst_ip=*/"10.0.0.1", kGoodPayload));
1014+
1015+
int good_packet_count = 0;
1016+
int bad_packet_count = 0;
1017+
ASSERT_OK(control_switch_p4rt_session_->HandleNextNStreamMessages(
1018+
[&](const p4::v1::StreamMessageResponse& message) {
1019+
// Verify this is the packet we expect.
1020+
packetlib::Packet packet_in =
1021+
packetlib::ParsePacket(message.packet().payload());
1022+
if (absl::StrContains(packet_in.payload(), kGoodPayload)) {
1023+
++good_packet_count;
1024+
return true;
1025+
}
1026+
if (absl::StrContains(packet_in.payload(), kBadPayload)) {
1027+
++bad_packet_count;
1028+
return false;
1029+
}
1030+
LOG(WARNING) << "Unexpected P4 Stream response: "
1031+
<< message.DebugString();
1032+
return false;
1033+
},
1034+
kNumberOfTestPackets, /*timeout=*/absl::Minutes(1)));
1035+
LOG(INFO) << "Done collecting packets.";
1036+
1037+
EXPECT_EQ(good_packet_count, kNumberOfTestPackets);
1038+
EXPECT_EQ(bad_packet_count, 0);
1039+
}
1040+
8801041
} // namespace pins

0 commit comments

Comments
 (0)