From 6fc58155f2d15a6e4dcc2ee31c04498db5082b93 Mon Sep 17 00:00:00 2001 From: fruffy-g <147277354+fruffy-g@users.noreply.github.com> Date: Thu, 15 Feb 2024 07:46:05 -0500 Subject: [PATCH] [P4Testgen] Look up the alias in the P4Info instead of using the fully qualified control plane name for Protobuf IR tests. (#4425) --- .../testgen/targets/bmv2/test_backend.cpp | 5 ++- .../targets/bmv2/test_backend/common.cpp | 35 +++++++++++-------- .../targets/bmv2/test_backend/common.h | 3 ++ .../targets/bmv2/test_backend/protobuf_ir.cpp | 33 +++++++++++++++-- .../targets/bmv2/test_backend/protobuf_ir.h | 10 +++++- 5 files changed, 64 insertions(+), 22 deletions(-) diff --git a/backends/p4tools/modules/testgen/targets/bmv2/test_backend.cpp b/backends/p4tools/modules/testgen/targets/bmv2/test_backend.cpp index 3e48256d6bd..d501fb7b1de 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/test_backend.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/test_backend.cpp @@ -55,10 +55,9 @@ Bmv2TestBackend::Bmv2TestBackend(const Bmv2V1ModelProgramInfo &programInfo, } else if (testBackendString == "STF") { testWriter = new STF(testBackendConfiguration); } else if (testBackendString == "PROTOBUF") { - auto p4RuntimeAPI = programInfo.getP4RuntimeAPI(); - testWriter = new Protobuf(testBackendConfiguration, p4RuntimeAPI); + testWriter = new Protobuf(testBackendConfiguration, programInfo.getP4RuntimeAPI()); } else if (testBackendString == "PROTOBUF_IR") { - testWriter = new ProtobufIr(testBackendConfiguration); + testWriter = new ProtobufIr(testBackendConfiguration, programInfo.getP4RuntimeAPI()); } else if (testBackendString == "METADATA") { testWriter = new Metadata(testBackendConfiguration); } else { diff --git a/backends/p4tools/modules/testgen/targets/bmv2/test_backend/common.cpp b/backends/p4tools/modules/testgen/targets/bmv2/test_backend/common.cpp index ffc0ea90576..fb51b6d39aa 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/test_backend/common.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/test_backend/common.cpp @@ -66,6 +66,25 @@ inja::json::array_t Bmv2TestFramework::getMeter(const TestObjectMap &meterValues return meterJson; } +inja::json Bmv2TestFramework::getControlPlaneTable(const TableConfig &tblConfig) const { + inja::json tblJson; + tblJson["table_name"] = tblConfig.getTable()->controlPlaneName(); + const auto *tblRules = tblConfig.getRules(); + tblJson["rules"] = inja::json::array(); + for (const auto &tblRule : *tblRules) { + inja::json rule; + const auto *matches = tblRule.getMatches(); + const auto *actionCall = tblRule.getActionCall(); + const auto *actionArgs = actionCall->getArgs(); + rule["action_name"] = actionCall->getActionName().c_str(); + auto j = getControlPlaneForTable(*matches, *actionArgs); + rule["rules"] = std::move(j); + rule["priority"] = tblRule.getPriority(); + tblJson["rules"].push_back(rule); + } + return tblJson; +} + inja::json Bmv2TestFramework::getControlPlane(const TestSpec *testSpec) const { auto controlPlaneJson = inja::json::object(); // Map of actionProfiles and actionSelectors for easy reference. @@ -76,22 +95,8 @@ inja::json Bmv2TestFramework::getControlPlane(const TestSpec *testSpec) const { controlPlaneJson["tables"] = inja::json::array(); } for (const auto &testObject : tables) { - inja::json tblJson; - tblJson["table_name"] = testObject.first.c_str(); const auto *const tblConfig = testObject.second->checkedTo(); - const auto *tblRules = tblConfig->getRules(); - tblJson["rules"] = inja::json::array(); - for (const auto &tblRule : *tblRules) { - inja::json rule; - const auto *matches = tblRule.getMatches(); - const auto *actionCall = tblRule.getActionCall(); - const auto *actionArgs = actionCall->getArgs(); - rule["action_name"] = actionCall->getActionName().c_str(); - auto j = getControlPlaneForTable(*matches, *actionArgs); - rule["rules"] = std::move(j); - rule["priority"] = tblRule.getPriority(); - tblJson["rules"].push_back(rule); - } + inja::json tblJson = getControlPlaneTable(*tblConfig); // Collect action profiles and selectors associated with the table. checkForTableActionProfile( diff --git a/backends/p4tools/modules/testgen/targets/bmv2/test_backend/common.h b/backends/p4tools/modules/testgen/targets/bmv2/test_backend/common.h index 2151ac78266..86e73ca624b 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/test_backend/common.h +++ b/backends/p4tools/modules/testgen/targets/bmv2/test_backend/common.h @@ -31,6 +31,9 @@ class Bmv2TestFramework : public TestFramework { /// @returns the configuration for a meter call (may set the meter to GREEN, YELLOW, or RED) [[nodiscard]] virtual inja::json::array_t getMeter(const TestObjectMap &meterValues) const; + /// Converts a table configuration into Inja format. + [[nodiscard]] virtual inja::json getControlPlaneTable(const TableConfig &tblConfig) const; + /// Helper function for the control plane table inja objects. [[nodiscard]] virtual inja::json getControlPlaneForTable( const TableMatchMap &matches, const std::vector &args) const; diff --git a/backends/p4tools/modules/testgen/targets/bmv2/test_backend/protobuf_ir.cpp b/backends/p4tools/modules/testgen/targets/bmv2/test_backend/protobuf_ir.cpp index e09a945d7de..556c7fe3dc5 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/test_backend/protobuf_ir.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/test_backend/protobuf_ir.cpp @@ -4,11 +4,11 @@ #include #include #include -#include #include #include "backends/p4tools/common/lib/util.h" +#include "control-plane/p4infoApi.h" #include "lib/exceptions.h" #include "lib/log.h" #include "nlohmann/json.hpp" @@ -19,8 +19,9 @@ namespace P4Tools::P4Testgen::Bmv2 { -ProtobufIr::ProtobufIr(const TestBackendConfiguration &testBackendConfiguration) - : Bmv2TestFramework(testBackendConfiguration) {} +ProtobufIr::ProtobufIr(const TestBackendConfiguration &testBackendConfiguration, + P4::P4RuntimeAPI p4RuntimeApi) + : Bmv2TestFramework(testBackendConfiguration), p4RuntimeApi(p4RuntimeApi) {} std::string ProtobufIr::getFormatOfNode(const IR::IAnnotated *node) { const auto *formatAnnotation = node->getAnnotation("format"); @@ -253,6 +254,32 @@ void ProtobufIr::createKeyMatch(cstring fieldName, const TableMatch &fieldMatch, } } +inja::json ProtobufIr::getControlPlaneTable(const TableConfig &tblConfig) const { + inja::json tblJson; + const auto *p4RuntimeTableOpt = P4::ControlPlaneAPI::findP4RuntimeTable( + *p4RuntimeApi.p4Info, tblConfig.getTable()->controlPlaneName()); + BUG_CHECK(p4RuntimeTableOpt != nullptr, "Table not found in the P4Info file."); + tblJson["table_name"] = p4RuntimeTableOpt->preamble().alias(); + + const auto *tblRules = tblConfig.getRules(); + tblJson["rules"] = inja::json::array(); + for (const auto &tblRule : *tblRules) { + inja::json rule; + const auto *matches = tblRule.getMatches(); + const auto *actionCall = tblRule.getActionCall(); + const auto *actionArgs = actionCall->getArgs(); + const auto *p4RuntimeActionOpt = P4::ControlPlaneAPI::findP4RuntimeAction( + *p4RuntimeApi.p4Info, actionCall->getAction()->controlPlaneName()); + BUG_CHECK(p4RuntimeActionOpt != nullptr, "Action not found in the P4Info file."); + rule["action_name"] = p4RuntimeActionOpt->preamble().alias(); + auto j = getControlPlaneForTable(*matches, *actionArgs); + rule["rules"] = std::move(j); + rule["priority"] = tblRule.getPriority(); + tblJson["rules"].push_back(rule); + } + return tblJson; +} + inja::json ProtobufIr::getControlPlaneForTable(const TableMatchMap &matches, const std::vector &args) const { inja::json rulesJson; diff --git a/backends/p4tools/modules/testgen/targets/bmv2/test_backend/protobuf_ir.h b/backends/p4tools/modules/testgen/targets/bmv2/test_backend/protobuf_ir.h index 986244fd78a..43b123c4bf2 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/test_backend/protobuf_ir.h +++ b/backends/p4tools/modules/testgen/targets/bmv2/test_backend/protobuf_ir.h @@ -7,6 +7,7 @@ #include +#include "control-plane/p4RuntimeSerializer.h" #include "lib/cstring.h" #include "backends/p4tools/modules/testgen/lib/test_spec.h" @@ -31,7 +32,8 @@ struct ProtobufIrTest : public AbstractTest { /// Extracts information from the @testSpec to emit a Protobuf IR test case. class ProtobufIr : public Bmv2TestFramework { public: - explicit ProtobufIr(const TestBackendConfiguration &testBackendConfiguration); + explicit ProtobufIr(const TestBackendConfiguration &testBackendConfiguration, + P4::P4RuntimeAPI p4RuntimeApi); ~ProtobufIr() override = default; ProtobufIr(const ProtobufIr &) = default; @@ -46,6 +48,12 @@ class ProtobufIr : public Bmv2TestFramework { size_t testIdx, float currentCoverage) override; private: + /// The P4Runtime API generated by the compiler. This API can be used to look up the id of + /// tables. + P4::P4RuntimeAPI p4RuntimeApi; + + [[nodiscard]] inja::json getControlPlaneTable(const TableConfig &tblConfig) const override; + [[nodiscard]] inja::json getControlPlaneForTable( const TableMatchMap &matches, const std::vector &args) const override;