Skip to content

Commit

Permalink
Parsing P4Info for Actions and type-checking params.
Browse files Browse the repository at this point in the history
In this CL, InferAndCheckTypes was extended to perform type checking on action constraints in addition to table constraints, requiring action param info to be parsed and stored. This is part of the step to extend P4ToConstraintInfo to parse and store action constraints (see https://docs.google.com/document/d/11Nkn3_BAa43OX4I-_DPsoUokebGdRYx6QAk7eGVAyLc/edit?resourcekey=0-gO31LvkRyylb07KB1m3RMg#heading=h.8eovq8t5ess2)

PiperOrigin-RevId: 576945971
  • Loading branch information
PINS Team authored and Bara Kopi committed Nov 3, 2023
1 parent 3fbb0aa commit 115f7f2
Show file tree
Hide file tree
Showing 17 changed files with 826 additions and 85 deletions.
10 changes: 9 additions & 1 deletion gutils/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,15 @@ cc_library(
"proto.h",
],
visibility = ["//visibility:public"],
deps = ["@com_google_protobuf//:protobuf"],
deps = [
":source_location",
":status",
"@com_google_absl//absl/status",
"@com_google_absl//absl/strings",
"@com_google_protobuf//:protobuf",
"@com_google_protobuf//src/google/protobuf/io",
"@com_google_protobuf//src/google/protobuf/io:tokenizer",
],
)

cc_library(
Expand Down
87 changes: 87 additions & 0 deletions gutils/proto.cc
Original file line number Diff line number Diff line change
@@ -1,10 +1,49 @@
#include "gutils/proto.h"

#include <fcntl.h>

#include <string>
#include <string_view>

#include "absl/status/status.h"
#include "absl/strings/substitute.h"
#include "google/protobuf/io/tokenizer.h"
#include "google/protobuf/io/zero_copy_stream_impl.h"
#include "google/protobuf/message.h"
#include "google/protobuf/text_format.h"
#include "google/protobuf/util/message_differencer.h"
#include "gutils/source_location.h"
#include "gutils/status_builder.h"

namespace gutils {

// Collects errors by appending them to a given string.
class StringErrorCollector : public google::protobuf::io::ErrorCollector {
public:
// String error_text is unowned and must remain valid during the use of
// StringErrorCollector.
explicit StringErrorCollector(std::string *error_text)
: error_text_{error_text} {};
StringErrorCollector(const StringErrorCollector &) = delete;
StringErrorCollector &operator=(const StringErrorCollector &) = delete;

// Implementation of protobuf::io::ErrorCollector::AddError.
void AddError(int line, int column, const std::string &message) override {
if (error_text_ != nullptr) {
absl::SubstituteAndAppend(error_text_, "$0($1): $2\n", line, column,
message);
}
}

// Implementation of protobuf::io::ErrorCollector::AddWarning.
void AddWarning(int line, int column, const std::string &message) override {
AddError(line, column, message);
}

private:
std::string *const error_text_;
};

bool ProtoEqual(const google::protobuf::Message &message1,
const google::protobuf::Message &message2,
google::protobuf::util::MessageDifferencer &differ) {
Expand All @@ -22,4 +61,52 @@ bool ProtoEqual(const google::protobuf::Message &message1,
return ProtoEqual(message1, message2, differ);
}

absl::Status ReadProtoFromFile(std::string_view filename,
google::protobuf::Message *message) {
// Verifies that the version of the library that we linked against is
// compatible with the version of the headers we compiled against.
/* copybara:insert(not needed nor possible in google3, as it is a mono repo)
GOOGLE_PROTOBUF_VERIFY_VERSION;
*/

int fd = open(std::string(filename).c_str(), O_RDONLY);
if (fd < 0) {
return gutils::InvalidArgumentErrorBuilder(GUTILS_LOC)
<< "Error opening the file " << filename;
}

google::protobuf::io::FileInputStream file_stream(fd);
file_stream.SetCloseOnDelete(true);

if (!google::protobuf::TextFormat::Parse(&file_stream, message)) {
return gutils::InvalidArgumentErrorBuilder(GUTILS_LOC)
<< "Failed to parse file " << filename;
}

return absl::OkStatus();
}

absl::Status ReadProtoFromString(std::string_view proto_string,
google::protobuf::Message *message) {
// Verifies that the version of the library that we linked against is
// compatible with the version of the headers we compiled against.
/* copybara:insert(not needed nor possible in google3, as it is a mono repo)
GOOGLE_PROTOBUF_VERIFY_VERSION;
*/

google::protobuf::TextFormat::Parser parser;
std::string all_errors;
StringErrorCollector collector(&all_errors);
parser.RecordErrorsTo(&collector);

if (!parser.ParseFromString(std::string(proto_string), message)) {
return InvalidArgumentErrorBuilder()
<< "string <" << proto_string << "> did not parse as a"
<< message->GetTypeName() << ":\n"
<< all_errors;
}

return absl::OkStatus();
}

} // namespace gutils
11 changes: 11 additions & 0 deletions gutils/proto.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#ifndef THIRD_PARTY_P4LANG_P4_CONSTRAINTS_GUTILS_PROTO_H_
#define THIRD_PARTY_P4LANG_P4_CONSTRAINTS_GUTILS_PROTO_H_

#include <string_view>

#include "absl/status/status.h"
#include "google/protobuf/message.h"
#include "google/protobuf/util/message_differencer.h"

Expand All @@ -14,6 +17,14 @@ bool ProtoEqual(const google::protobuf::Message &message1,
bool ProtoEqual(const google::protobuf::Message &message1,
const google::protobuf::Message &message2);

// Read the contents of the file into a protobuf.
absl::Status ReadProtoFromFile(std::string_view filename,
google::protobuf::Message *message);

// Read the contents of the string into a protobuf.
absl::Status ReadProtoFromString(std::string_view proto_string,
google::protobuf::Message *message);

} // namespace gutils

#endif // THIRD_PARTY_P4LANG_P4_CONSTRAINTS_GUTILS_PROTO_H_
5 changes: 5 additions & 0 deletions p4_constraints/ast.proto
Original file line number Diff line number Diff line change
Expand Up @@ -184,5 +184,10 @@ message SourceLocation {
// If present, `line` and `column` are relative to an @entry_restriction
// annotation attached to a table of the given name.
string table_name = 4;

// P4 action name. Prefer `file_path` whenever possible.
// If present, `line` and `column` are relative to an @action_restriction
// annotation attached to an action of the given name.
string action_name = 5;
}
}
35 changes: 35 additions & 0 deletions p4_constraints/backend/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
load("//e2e_tests:p4check.bzl", "cmd_diff_test")
load("@com_github_p4lang_p4c//:bazel/p4_library.bzl", "p4_library")

package(
default_visibility = ["//visibility:public"],
Expand Down Expand Up @@ -83,6 +84,7 @@ cc_library(
"//p4_constraints/frontend:constraint_kind",
"//p4_constraints/frontend:parser",
"@com_github_p4lang_p4runtime//:p4info_cc_proto",
"@com_github_p4lang_p4runtime//:p4types_cc_proto",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/log",
"@com_google_absl//absl/log:check",
Expand Down Expand Up @@ -183,6 +185,20 @@ cc_library(
],
)

p4_library(
name = "p4_programs/action_restrictions_valid",
src = "p4_programs/action_restrictions_valid.p4",
p4info_out = "p4_programs/action_restrictions_valid.p4info.pb.txt",
visibility = ["//visibility:private"],
)

p4_library(
name = "p4_programs/action_restrictions_invalid",
src = "p4_programs/action_restrictions_invalid.p4",
p4info_out = "p4_programs/action_restrictions_invalid.p4info.pb.txt",
visibility = ["//visibility:private"],
)

cc_test(
name = "symbolic_interpreter_test",
srcs = ["symbolic_interpreter_test.cc"],
Expand All @@ -208,3 +224,22 @@ cc_test(
"@com_google_googletest//:gtest_main",
],
)

cc_test(
name = "constraint_info_test",
srcs = ["constraint_info_test.cc"],
data = [
"p4_programs/action_restrictions_invalid.p4info.pb.txt",
"p4_programs/action_restrictions_valid.p4info.pb.txt",
],
deps = [
":constraint_info",
"//gutils:proto",
"//gutils:status_matchers",
"@com_github_p4lang_p4runtime//:p4info_cc_proto",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/log:check",
"@com_google_absl//absl/status:statusor",
"@com_google_googletest//:gtest_main",
],
)
Loading

0 comments on commit 115f7f2

Please sign in to comment.