Skip to content

Commit

Permalink
[Dvaas] Fix bug where sut p4info is used to translate control switch …
Browse files Browse the repository at this point in the history
…packet ins

PiperOrigin-RevId: 540167525
  • Loading branch information
kishanps authored and VSuryaprasad-HCL committed Nov 26, 2024
1 parent 42d5096 commit ab0e031
Show file tree
Hide file tree
Showing 7 changed files with 174 additions and 66 deletions.
14 changes: 12 additions & 2 deletions dvaas/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -52,23 +52,25 @@ cc_library(
srcs = ["packet_injection.cc"],
hdrs = ["packet_injection.h"],
deps = [
":port_id_map",
":test_vector",
":test_vector_cc_proto",
"//gutil:status",
"//lib/p4rt:p4rt_port",
"//p4_pdpi:ir",
"//p4_pdpi:ir_cc_proto",
"//p4_pdpi:p4_runtime_session",
"//p4_pdpi/packetlib",
"//p4_pdpi/packetlib:packetlib_cc_proto",
"//tests/forwarding:util",
"@com_github_p4lang_p4runtime//:p4runtime_cc_proto",
"@com_google_absl//absl/container:btree",
"@com_google_absl//absl/container:flat_hash_set",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/time",
],
)

cc_library(
name = "test_run_validation",
srcs = ["test_run_validation.cc"],
Expand Down Expand Up @@ -101,6 +103,7 @@ cc_library(
hdrs = ["arriba_test_vector_validation.h"],
deps = [
":packet_injection",
":port_id_map",
":test_run_validation",
":test_vector",
":test_vector_cc_proto",
Expand All @@ -111,6 +114,7 @@ cc_library(
"//p4_pdpi:p4_runtime_session_extras",
"//sai_p4/instantiations/google/test_tools:test_entries",
"//thinkit:mirror_testbed",
"@com_github_google_glog//:glog",
"@com_github_p4lang_p4runtime//:p4runtime_cc_proto",
"@com_google_absl//absl/container:flat_hash_set",
"@com_google_absl//absl/status",
Expand Down Expand Up @@ -193,16 +197,22 @@ cc_library(
hdrs = ["port_id_map.h"],
deps = [
"//gutil:status",
"//gutil:test_artifact_writer",
"//lib/gnmi:gnmi_helper",
"//lib/p4rt:p4rt_port",
"@com_github_gnmi//proto/gnmi:gnmi_cc_grpc_proto",
"@com_google_absl//absl/algorithm:container",
"@com_google_absl//absl/container:btree",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/container:flat_hash_set",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:str_format",
],
)


cc_test(
name = "port_id_map_test",
srcs = ["port_id_map_test.cc"],
Expand Down
25 changes: 17 additions & 8 deletions dvaas/arriba_test_vector_validation.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2024 Google LLC
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -19,9 +19,11 @@
#include "absl/status/status.h"
#include "absl/strings/string_view.h"
#include "dvaas/packet_injection.h"
#include "dvaas/port_id_map.h"
#include "dvaas/test_run_validation.h"
#include "dvaas/test_vector.h"
#include "dvaas/test_vector.pb.h"
#include "glog/logging.h"
#include "gutil/status.h"
#include "gutil/test_artifact_writer.h"
#include "p4/v1/p4runtime.pb.h"
Expand All @@ -37,7 +39,8 @@ absl::Status ValidateAgaistArribaTestVector(
pdpi::P4RuntimeSession& sut, pdpi::P4RuntimeSession& control_switch,
const ArribaTestVector& arriba_test_vector,
const ArribaTestVectorValidationParams& params) {
// Prepare control switch.
// Prepare the control switch.
LOG(INFO) << "Installing entires to punt all packets on the control switch";
ASSIGN_OR_RETURN(p4::v1::GetForwardingPipelineConfigResponse config,
GetForwardingPipelineConfig(&control_switch));
ASSIGN_OR_RETURN(pdpi::IrP4Info ir_p4info,
Expand All @@ -50,7 +53,8 @@ absl::Status ValidateAgaistArribaTestVector(
RETURN_IF_ERROR(pdpi::ClearTableEntries(&control_switch));
RETURN_IF_ERROR(pdpi::InstallPiEntities(control_switch, punt_entities));

// Prepare SUT.
// Prepare the SUT.
LOG(INFO) << "Installing entries from the given test vector on the SUT";
RETURN_IF_ERROR(pdpi::ClearTableEntries(&sut));
RETURN_IF_ERROR(
pdpi::InstallIrTableEntries(sut, arriba_test_vector.ir_table_entries()));
Expand All @@ -66,11 +70,16 @@ absl::Status ValidateAgaistArribaTestVector(
gutil::BazelTestArtifactWriter artifact_writer;

// Send tests to switch and collect results.
ASSIGN_OR_RETURN(
PacketTestRuns test_runs,
SendTestPacketsAndCollectOutputs(sut, control_switch, test_vector_by_id,
packet_statistics,
params.max_packets_to_send_per_second));
ASSIGN_OR_RETURN(PacketTestRuns test_runs,
SendTestPacketsAndCollectOutputs(
sut, control_switch, test_vector_by_id,
{
.max_packets_to_send_per_second =
params.max_packets_to_send_per_second,
.mirror_testbed_port_map =
MirrorTestbedP4rtPortIdMap::CreateIdentityMap(),
},
packet_statistics));

// Compare the switch output with expected output for each test vector.
return ValidateTestRuns(test_runs, params.switch_output_diff_params,
Expand Down
8 changes: 4 additions & 4 deletions dvaas/arriba_test_vector_validation.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2024 Google LLC
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef PINS_DVAAS_ARRIBA_TEST_VECTOR_VALIDATION_H_
#define PINS_DVAAS_ARRIBA_TEST_VECTOR_VALIDATION_H_
#ifndef PINS_INFRA_DVAAS_ARRIBA_TEST_VECTOR_VALIDATION_H_
#define PINS_INFRA_DVAAS_ARRIBA_TEST_VECTOR_VALIDATION_H_

#include <vector>

Expand Down Expand Up @@ -66,4 +66,4 @@ absl::Status ValidateAgaistArribaTestVector(

} // namespace dvaas

#endif // PINS_DVAAS_ARRIBA_TEST_VECTOR_VALIDATION_H_
#endif // PINS_INFRA_DVAAS_ARRIBA_TEST_VECTOR_VALIDATION_H_
45 changes: 34 additions & 11 deletions dvaas/packet_injection.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2024 Google LLC
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -14,14 +14,20 @@

#include "dvaas/packet_injection.h"

#include <optional>
#include <string>
#include <vector>

#include "absl/container/btree_map.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/escaping.h"
#include "absl/time/time.h"
#include "dvaas/port_id_map.h"
#include "dvaas/test_vector.h"
#include "dvaas/test_vector.pb.h"
#include "gutil/status.h"
#include "lib/p4rt/p4rt_port.h"
#include "p4/v1/p4runtime.pb.h"
#include "p4_pdpi/ir.h"
#include "p4_pdpi/p4_runtime_session.h"
Expand All @@ -32,6 +38,8 @@
namespace dvaas {
namespace {

using pins_test::P4rtPortId;

// Utils.
// Reads P4Info from the `device` and convert it to IrP4Info.
absl::StatusOr<pdpi::IrP4Info> GetIrP4Info(
Expand Down Expand Up @@ -95,6 +103,20 @@ CollectStreamMessageResponsesAndReturnTaggedPacketIns(
return tagged_packet_ins;
}

// Returns the SUT egress port corresponding to the punted packet on control
// switch given the `mirror_testbed_port_map`.
absl::StatusOr<P4rtPortId> GetSutEgressPortFromControlSwitchPacketIn(
const pdpi::IrPacketIn& packet_in,
const MirrorTestbedP4rtPortIdMap& mirror_testbed_port_map) {
ASSIGN_OR_RETURN(const std::string control_switch_ingress_port_p4rt_encoding,
GetIngressPortFromIrPacketIn(packet_in));
ASSIGN_OR_RETURN(const P4rtPortId control_switch_ingress_port,
P4rtPortId::MakeFromP4rtEncoding(
control_switch_ingress_port_p4rt_encoding));
return mirror_testbed_port_map.GetSutPortConnectedToControlSwitchPort(
control_switch_ingress_port);
}

} // namespace

absl::StatusOr<std::string> GetIngressPortFromIrPacketIn(
Expand All @@ -109,10 +131,7 @@ absl::StatusOr<std::string> GetIngressPortFromIrPacketIn(
absl::StatusOr<PacketTestRuns> SendTestPacketsAndCollectOutputs(
pdpi::P4RuntimeSession& sut, pdpi::P4RuntimeSession& control_switch,
const PacketTestVectorById& packet_test_vector_by_id,
PacketStatistics& statistics,
std::optional<int> max_packets_to_send_per_second,
const IsExpectedUnsolicitedPacketFunctionType&
is_expected_unsolicited_packet) {
const PacketInjectionParams& parameters, PacketStatistics& statistics) {
LOG(INFO) << "Injecting test packets into the dataplane "
<< packet_test_vector_by_id.size();
statistics.total_packets_injected += packet_test_vector_by_id.size();
Expand All @@ -124,8 +143,9 @@ absl::StatusOr<PacketTestRuns> SendTestPacketsAndCollectOutputs(

// Compute per packet injection delay.
std::optional<absl::Duration> injection_delay;
if (max_packets_to_send_per_second.has_value()) {
injection_delay = absl::Milliseconds(1e3 / *max_packets_to_send_per_second);
if (parameters.max_packets_to_send_per_second.has_value()) {
injection_delay =
absl::Milliseconds(1e3 / *parameters.max_packets_to_send_per_second);
}

// Send packets.
Expand All @@ -149,7 +169,8 @@ absl::StatusOr<PacketTestRuns> SendTestPacketsAndCollectOutputs(
const absl::Duration kCollectionDuration = absl::Seconds(3);
absl::StatusOr<std::vector<TaggedPacketIn>> control_packet_ins =
CollectStreamMessageResponsesAndReturnTaggedPacketIns(
control_switch, kCollectionDuration, is_expected_unsolicited_packet);
control_switch, kCollectionDuration,
parameters.is_expected_unsolicited_packet);
RETURN_IF_ERROR(control_packet_ins.status())
<< "while collecting the output of control_switch";
LOG(INFO) << "Collected " << control_packet_ins->size()
Expand All @@ -158,7 +179,7 @@ absl::StatusOr<PacketTestRuns> SendTestPacketsAndCollectOutputs(

absl::StatusOr<std::vector<TaggedPacketIn>> sut_packet_ins =
CollectStreamMessageResponsesAndReturnTaggedPacketIns(
sut, kCollectionDuration, is_expected_unsolicited_packet);
sut, kCollectionDuration, parameters.is_expected_unsolicited_packet);
RETURN_IF_ERROR(sut_packet_ins.status())
<< "while collecting the output of SUT";
LOG(INFO) << "Collected " << sut_packet_ins->size()
Expand All @@ -181,8 +202,10 @@ absl::StatusOr<PacketTestRuns> SendTestPacketsAndCollectOutputs(
ASSIGN_OR_RETURN(
pdpi::IrPacketIn ir_packet_in,
pdpi::PiPacketInToIr(control_ir_p4info, packet_in.packet_in));
ASSIGN_OR_RETURN(*forwarded_output.mutable_port(),
GetIngressPortFromIrPacketIn(ir_packet_in));
ASSIGN_OR_RETURN(const P4rtPortId sut_egress_port,
GetSutEgressPortFromControlSwitchPacketIn(
ir_packet_in, parameters.mirror_testbed_port_map));
*forwarded_output.mutable_port() = sut_egress_port.GetP4rtEncoding();
}

// Processing the output of SUT.
Expand Down
30 changes: 20 additions & 10 deletions dvaas/packet_injection.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2024 Google LLC
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -12,16 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef PINS_DVAAS_PACKET_INJECTION_H_
#define PINS_DVAAS_PACKET_INJECTION_H_
#ifndef PINS_INFRA_DVAAS_PACKET_INJECTION_H_
#define PINS_INFRA_DVAAS_PACKET_INJECTION_H_

#include <functional>
#include <optional>
#include <string>
#include <vector>

#include "absl/container/flat_hash_set.h"
#include "absl/status/statusor.h"
#include "dvaas/port_id_map.h"
#include "dvaas/test_vector.h"
#include "dvaas/test_vector.pb.h"
#include "p4_pdpi/ir.pb.h"
Expand Down Expand Up @@ -72,18 +71,29 @@ inline bool DefaultIsExpectedUnsolicitedPacket(
absl::StatusOr<std::string> GetIngressPortFromIrPacketIn(
const pdpi::IrPacketIn& packet_in);

struct PacketInjectionParams {
// Max number of packets to be injected per second. If null, there will be no
// rate limit for packet injection.
std::optional<int> max_packets_to_send_per_second;
// For a packet in from SUT or control switch without a test tag (i.e. an
// "unsolicited packet"), if this function return false, packet injection
// fails immediately.
const IsExpectedUnsolicitedPacketFunctionType is_expected_unsolicited_packet =
DefaultIsExpectedUnsolicitedPacket;
// The mapping of P4RT port IDs for connected interfaces between SUT and the
// control switch.
MirrorTestbedP4rtPortIdMap mirror_testbed_port_map;
};

// Determines the switch's behavior when receiving test packets by:
// - Injecting those packets to the control switch egress to send to the SUT.
// - Determining the set of packets that were forwarded (punted from control
// switch) and punted (punted from SUT) for each input packet.
absl::StatusOr<PacketTestRuns> SendTestPacketsAndCollectOutputs(
pdpi::P4RuntimeSession& sut, pdpi::P4RuntimeSession& control_switch,
const PacketTestVectorById& packet_test_vector_by_id,
PacketStatistics& statistics,
std::optional<int> max_packets_to_send_per_second,
const IsExpectedUnsolicitedPacketFunctionType&
is_expected_unsolicited_packet = DefaultIsExpectedUnsolicitedPacket);
const PacketInjectionParams& parameters, PacketStatistics& statistics);

} // namespace dvaas

#endif // PINS_DVAAS_PACKET_INJECTION_H_
#endif // PINS_INFRA_DVAAS_PACKET_INJECTION_H_
Loading

0 comments on commit ab0e031

Please sign in to comment.