Skip to content

Commit

Permalink
Merge branch 'main' into Test_5
Browse files Browse the repository at this point in the history
  • Loading branch information
VSuryaprasad-HCL authored Dec 13, 2024
2 parents 557e278 + 87c7936 commit b3234dc
Show file tree
Hide file tree
Showing 14 changed files with 1,384 additions and 128 deletions.
82 changes: 42 additions & 40 deletions dvaas/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,47 @@ package(
licenses = ["notice"],
)

cc_library(
name = "dataplane_validation",
srcs = ["dataplane_validation.cc"],
hdrs = ["dataplane_validation.h"],
deps = [
":output_writer",
":packet_injection",
":port_id_map",
":switch_api",
":test_run_validation",
":test_vector",
":test_vector_cc_proto",
":user_provided_packet_test_vector",
":validation_result",
"//gutil:status",
"//gutil:test_artifact_writer",
"//gutil:version",
"//lib/gnmi:gnmi_helper",
"//lib/gnmi:openconfig_cc_proto",
"//lib/p4rt:p4rt_port",
"//p4_pdpi:ir_cc_proto",
"//p4_pdpi:p4_runtime_session",
"//p4_pdpi:p4_runtime_session_extras",
"//p4_pdpi/packetlib:packetlib_cc_proto",
"//p4_symbolic/packet_synthesizer:packet_synthesizer_cc_proto",
"//tests/lib:switch_test_setup_helpers",
"//thinkit:mirror_testbed",
"@com_github_gnmi//proto/gnmi:gnmi_cc_proto",
"@com_github_google_glog//:glog",
"@com_github_p4lang_p4runtime//:p4runtime_cc_proto",
"@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/time",
"@com_google_absl//absl/types:span",
"@com_google_protobuf//:protobuf",
],
)

cc_library(
name = "validation_result",
srcs = ["validation_result.cc"],
Expand All @@ -29,6 +70,7 @@ cc_library(
":test_vector_cc_proto",
":test_vector_stats",
"//gutil:status",
"//p4_symbolic/packet_synthesizer:packet_synthesizer_cc_proto",
"@com_github_google_glog//:glog",
"@com_google_absl//absl/algorithm:container",
"@com_google_absl//absl/container:flat_hash_set",
Expand Down Expand Up @@ -358,43 +400,3 @@ cmd_diff_test(
expected = ":test_run_validation_test.expected.output",
tools = [":test_run_validation_test_runner"],
)

cc_library(
name = "dataplane_validation",
srcs = ["dataplane_validation.cc"],
hdrs = ["dataplane_validation.h"],
deps = [
":output_writer",
":packet_injection",
":port_id_map",
":switch_api",
":test_run_validation",
":test_vector",
":test_vector_cc_proto",
":user_provided_packet_test_vector",
":validation_result",
"//gutil:status",
"//gutil:test_artifact_writer",
"//gutil:version",
"//lib/gnmi:gnmi_helper",
"//lib/gnmi:openconfig_cc_proto",
"//lib/p4rt:p4rt_port",
"//p4_pdpi:ir_cc_proto",
"//p4_pdpi:p4_runtime_session",
"//p4_pdpi:p4_runtime_session_extras",
"//p4_pdpi/packetlib:packetlib_cc_proto",
"//p4_symbolic/packet_synthesizer:packet_synthesizer_cc_proto",
"//tests/lib:switch_test_setup_helpers",
"//thinkit:mirror_testbed",
"@com_github_gnmi//proto/gnmi:gnmi_cc_proto",
"@com_github_google_glog//:glog",
"@com_github_p4lang_p4runtime//:p4runtime_cc_proto",
"@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/types:span",
"@com_google_protobuf//:protobuf",
],
)
67 changes: 41 additions & 26 deletions dvaas/dataplane_validation.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "dvaas/user_provided_packet_test_vector.h"
#include "dvaas/validation_result.h"
#include "glog/logging.h"
#include "gutil/proto.h"
#include "gutil/status.h"
#include "gutil/test_artifact_writer.h"
#include "gutil/version.h"
Expand Down Expand Up @@ -165,7 +166,7 @@ absl::StatusOr<P4Specification> InferP4Specification(
// Generates and returns test vectors using the backend functions
// `SynthesizePackets` and `GeneratePacketTestVectors`. Reads the table entries,
// P4Info, and relevant P4RT port IDs from the switch.
absl::StatusOr<PacketTestVectorById> GenerateTestVectors(
absl::StatusOr<GenerateTestVectorsResult> GenerateTestVectors(
const DataplaneValidationParams& params, SwitchApi& sut,
DataplaneValidationBackend& backend, gutil::TestArtifactWriter& writer) {
// Determine the P4 specification to test against.
Expand All @@ -176,10 +177,10 @@ absl::StatusOr<PacketTestVectorById> GenerateTestVectors(
RETURN_IF_ERROR(writer.AppendToTestArtifact(
"sut_bmv2_config.txt", p4_spec.bmv2_config.DebugString()));

// Read P4Info and entries from SUT, sorted for determinism.
// Read P4Info and control plane entities from SUT, sorted for determinism.
ASSIGN_OR_RETURN(pdpi::IrP4Info ir_p4info, pdpi::GetIrP4Info(*sut.p4rt));
ASSIGN_OR_RETURN(pdpi::IrTableEntries entries,
pdpi::ReadIrTableEntriesSorted(*sut.p4rt));
ASSIGN_OR_RETURN(pdpi::IrEntities entities,
pdpi::ReadIrEntitiesSorted(*sut.p4rt));

// Get enabled Ethernet ports from SUT's GNMI config.
ASSIGN_OR_RETURN(std::vector<pins_test::P4rtPortId> ports,
Expand All @@ -190,24 +191,35 @@ absl::StatusOr<PacketTestVectorById> GenerateTestVectors(
}
const P4rtPortId& default_ingress_port = ports[0];

GenerateTestVectorsResult generate_test_vectors_result;

// Synthesize test packets.
LOG(INFO) << "Synthesizing test packets";
ASSIGN_OR_RETURN(
std::vector<SynthesizedPacket> synthesized_packets,
backend.SynthesizePackets(ir_p4info, entries, p4_spec.p4_symbolic_config,
ports, [&](absl::string_view stats) {
return writer.AppendToTestArtifact(
"test_packet_stats.txt", stats);
}));
RETURN_IF_ERROR(writer.AppendToTestArtifact("synthesized_packets.txt",
ToString(synthesized_packets)));
ASSIGN_OR_RETURN(generate_test_vectors_result.packet_synthesis_result,
backend.SynthesizePackets(
ir_p4info, entities, p4_spec.p4_symbolic_config, ports,
[&](absl::string_view stats) {
return writer.AppendToTestArtifact(
"test_packet_stats.txt", stats);
},
params.packet_synthesis_time_limit));

RETURN_IF_ERROR(writer.AppendToTestArtifact(
"synthesized_packets.txt",
ToString(generate_test_vectors_result.packet_synthesis_result
.synthesized_packets)));

// Generate test vectors with output prediction from the synthesized
// packets.
LOG(INFO) << "Generating test vectors with output prediction";
return backend.GeneratePacketTestVectors(
ir_p4info, entries, p4_spec.bmv2_config, ports, synthesized_packets,
default_ingress_port);
ASSIGN_OR_RETURN(generate_test_vectors_result.packet_test_vector_by_id,
backend.GeneratePacketTestVectors(
ir_p4info, entities, p4_spec.bmv2_config, ports,
generate_test_vectors_result.packet_synthesis_result
.synthesized_packets,
default_ingress_port));

return generate_test_vectors_result;
}

absl::StatusOr<ValidationResult> DataplaneValidator::ValidateDataplane(
Expand All @@ -223,19 +235,19 @@ absl::StatusOr<ValidationResult> DataplaneValidator::ValidateDataplane(
ASSIGN_OR_RETURN(pdpi::IrP4Info ir_info,
pdpi::GetIrP4Info(*control_switch.p4rt));

// Clear control switch table entries and install punt entries instead.
RETURN_IF_ERROR(pdpi::ClearTableEntries(control_switch.p4rt.get()));
// Clear control switch entities and install punt entries instead.
RETURN_IF_ERROR(pdpi::ClearEntities(*control_switch.p4rt));
ASSIGN_OR_RETURN(pdpi::IrEntities punt_entries,
backend_->GetEntitiesToPuntAllPackets(ir_info));
RETURN_IF_ERROR(
pdpi::InstallIrEntities(*control_switch.p4rt, punt_entries));
}

// Read and store table entries on SUT as an artifact.
ASSIGN_OR_RETURN(pdpi::IrTableEntries entries,
pdpi::ReadIrTableEntriesSorted(*sut.p4rt));
RETURN_IF_ERROR(writer->AppendToTestArtifact("sut_ir_table_entries.txt",
entries.DebugString()));
ASSIGN_OR_RETURN(pdpi::IrEntities entities,
pdpi::ReadIrEntitiesSorted(*sut.p4rt));
RETURN_IF_ERROR(writer->AppendToTestArtifact(
"sut_ir_entities.txtpb", gutil::PrintTextProto(entities)));

// Store port mapping as an artifact (identity if not given a value).
MirrorTestbedP4rtPortIdMap mirror_testbed_port_map =
Expand All @@ -246,10 +258,12 @@ absl::StatusOr<ValidationResult> DataplaneValidator::ValidateDataplane(
mirror_testbed_port_map, *sut.gnmi, *control_switch.gnmi, *writer));

// Generate test vectors.
PacketTestVectorById test_vectors;
GenerateTestVectorsResult generate_test_vectors_result;
PacketTestVectorById& test_vectors =
generate_test_vectors_result.packet_test_vector_by_id;
if (params.packet_test_vector_override.empty()) {
LOG(INFO) << "Auto-generating test vectors";
ASSIGN_OR_RETURN(test_vectors,
ASSIGN_OR_RETURN(generate_test_vectors_result,
GenerateTestVectors(params, sut, *backend_, *writer));
} else {
LOG(INFO) << "Checking user-provided test vectors for well-formedness";
Expand Down Expand Up @@ -279,8 +293,9 @@ absl::StatusOr<ValidationResult> DataplaneValidator::ValidateDataplane(
RETURN_IF_ERROR(writer->AppendToTestArtifact("test_runs.textproto",
test_runs.DebugString()));

ValidationResult validation_result(std::move(test_runs),
params.switch_output_diff_params);
ValidationResult validation_result(
std::move(test_runs), params.switch_output_diff_params,
generate_test_vectors_result.packet_synthesis_result);
RETURN_IF_ERROR(writer->AppendToTestArtifact(
"test_vector_failures.txt",
absl::StrJoin(validation_result.GetAllFailures(), "\n\n")));
Expand Down
37 changes: 25 additions & 12 deletions dvaas/dataplane_validation.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ limitations under the License.
#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/status/statusor.h"
#include "absl/time/time.h"
#include "absl/types/span.h"
#include "dvaas/output_writer.h"
#include "dvaas/packet_injection.h"
Expand Down Expand Up @@ -102,6 +103,12 @@ struct DataplaneValidationParams {
// NOTE: Not required for valid mirror testbeds. This is a workaround for
// non-standard testbeds only.
std::optional<MirrorTestbedP4rtPortIdMap> mirror_testbed_port_map_override;

// Maximum allowed time for dataplane validation to synthesize test packets.
// If nullopt, packet synthesizer runs to completion for its coverage goals.
// Otherwise, if packet synthesis timed out, the synthesis results cover the
// coverage goals only partially.
std::optional<absl::Duration> packet_synthesis_time_limit = std::nullopt;
};

// Forward declaration. See below for description.
Expand Down Expand Up @@ -213,13 +220,12 @@ class DataplaneValidationBackend {
// specific packet synthesis implementation (our current implementation is not
// even open-source yet), so DVaaS takes the synthesis function as an input
// parameter.
virtual absl::StatusOr<
std::vector<p4_symbolic::packet_synthesizer::SynthesizedPacket>>
SynthesizePackets(const pdpi::IrP4Info& ir_p4info,
const pdpi::IrTableEntries& ir_entries,
const p4::v1::ForwardingPipelineConfig& p4_symbolic_config,
absl::Span<const pins_test::P4rtPortId> ports,
const OutputWriterFunctionType& write_stats) const = 0;
virtual absl::StatusOr<PacketSynthesisResult> SynthesizePackets(
const pdpi::IrP4Info& ir_p4info, const pdpi::IrEntities& ir_entities,
const p4::v1::ForwardingPipelineConfig& p4_symbolic_config,
absl::Span<const pins_test::P4rtPortId> ports,
const OutputWriterFunctionType& write_stats,
std::optional<absl::Duration> time_limit = std::nullopt) const = 0;

// Generates a map of test ID to PacketTestVector with output prediction
// given a list of `synthesized_packets` for the given input (program,
Expand All @@ -237,7 +243,7 @@ class DataplaneValidationBackend {
// 3. The packet will be padded to minimum size and the computed fields
// recomputed.
virtual absl::StatusOr<PacketTestVectorById> GeneratePacketTestVectors(
const pdpi::IrP4Info& ir_p4info, const pdpi::IrTableEntries& ir_entries,
const pdpi::IrP4Info& ir_p4info, const pdpi::IrEntities& ir_entities,
const p4::v1::ForwardingPipelineConfig& bmv2_config,
absl::Span<const pins_test::P4rtPortId> ports,
std::vector<p4_symbolic::packet_synthesizer::SynthesizedPacket>&
Expand Down Expand Up @@ -267,10 +273,17 @@ class DataplaneValidationBackend {
virtual ~DataplaneValidationBackend() = default;
};

// Generates and returns test vectors using the backend functions
// `SynthesizePackets` and `GeneratePacketTestVectors`. Reads the table entries,
// P4Info, and relevant P4RT port IDs from the switch.
absl::StatusOr<PacketTestVectorById> GenerateTestVectors(
// Stores test vectors as well as the result of automated test packet synthesis
// (if any).
struct GenerateTestVectorsResult {
PacketTestVectorById packet_test_vector_by_id;
PacketSynthesisResult packet_synthesis_result;
};

// Generates and returns test vectors as well as packet synthesis result using
// the backend functions `SynthesizePackets` and `GeneratePacketTestVectors`.
// Reads the table entries, P4Info, and relevant P4RT port IDs from the switch.
absl::StatusOr<GenerateTestVectorsResult> GenerateTestVectors(
const DataplaneValidationParams& params, SwitchApi& sut,
DataplaneValidationBackend& backend, gutil::TestArtifactWriter& writer);

Expand Down
Loading

0 comments on commit b3234dc

Please sign in to comment.