Skip to content

Commit

Permalink
Parsing P4Info for Actions and type-checking params.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 576945971
  • Loading branch information
PINS Team authored and Bara Kopi committed Nov 6, 2023
1 parent 3fbb0aa commit 94a88b3
Show file tree
Hide file tree
Showing 15 changed files with 682 additions and 85 deletions.
77 changes: 77 additions & 0 deletions e2e_tests/action_restrictions_invalid.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#include <v1model.p4>

type bit<16> custom_type_t;

struct headers {};
struct metadata {
bit<16> foo;
custom_type_t bar;
};

#define MULTICAST_GROUP_ID_BITWIDTH 16
typedef bit<MULTICAST_GROUP_ID_BITWIDTH> multicast_group_id_t;

parser MyParser(packet_in packet,
out headers hdr,
inout metadata meta,
inout standard_metadata_t standard_metadata) {
state start {
transition accept;
}
}

control MyVerifyChecksum(inout headers hdr, inout metadata meta) {
apply { }
}

control MyIngress(inout headers hdr,
inout metadata meta,
inout standard_metadata_t standard_metadata) {

@id(123)
@action_restriction("multicast_group_id != 0")
action act_1(multicast_group_id_t multicast_group_id) {
meta.foo = multicast_group_id;
}

@id(1234)
@action_restriction("custom_type_param != 0")
action act_2(custom_type_t custom_type_param) {
meta.bar = custom_type_param;
}

table tbl {
key = { }
actions = {
act_1;
act_2;
}
}

apply {
tbl.apply();
}
}

control MyEgress(inout headers hdr,
inout metadata meta,
inout standard_metadata_t standard_metadata) {
apply { }
}

control MyComputeChecksum(inout headers hdr, inout metadata meta) {
apply { }
}

control MyDeparser(packet_out packet, in headers hdr) {
apply { }
}

V1Switch(
MyParser(),
MyVerifyChecksum(),
MyIngress(),
MyEgress(),
MyComputeChecksum(),
MyDeparser()
) main;
67 changes: 67 additions & 0 deletions e2e_tests/action_restrictions_valid.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#include <v1model.p4>

struct headers {};
struct metadata {
bit<16> foo;
};

#define MULTICAST_GROUP_ID_BITWIDTH 16
typedef bit<MULTICAST_GROUP_ID_BITWIDTH> multicast_group_id_t;

parser MyParser(packet_in packet,
out headers hdr,
inout metadata meta,
inout standard_metadata_t standard_metadata) {
state start {
transition accept;
}
}

control MyVerifyChecksum(inout headers hdr, inout metadata meta) {
apply { }
}

control MyIngress(inout headers hdr,
inout metadata meta,
inout standard_metadata_t standard_metadata) {

@id(123)
@action_restriction("multicast_group_id != 0")
action act_1(multicast_group_id_t multicast_group_id) {
meta.foo = multicast_group_id;
}

table tbl {
key = { }
actions = {
act_1;
}
}

apply {
tbl.apply();
}
}

control MyEgress(inout headers hdr,
inout metadata meta,
inout standard_metadata_t standard_metadata) {
apply { }
}

control MyComputeChecksum(inout headers hdr, inout metadata meta) {
apply { }
}

control MyDeparser(packet_out packet, in headers hdr) {
apply { }
}

V1Switch(
MyParser(),
MyVerifyChecksum(),
MyIngress(),
MyEgress(),
MyComputeChecksum(),
MyDeparser()
) main;
9 changes: 8 additions & 1 deletion gutils/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,14 @@ 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:tokenizer",
],
)

cc_library(
Expand Down
61 changes: 61 additions & 0 deletions gutils/proto.cc
Original file line number Diff line number Diff line change
@@ -1,10 +1,48 @@
#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/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 +60,27 @@ bool ProtoEqual(const google::protobuf::Message &message1,
return ProtoEqual(message1, message2, differ);
}

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(GUTILS_LOC)
<< "string <" << proto_string << "> did not parse as a"
<< message->GetTypeName() << ":\n"
<< all_errors;
}

return absl::OkStatus();
}

} // namespace gutils
7 changes: 7 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,10 @@ bool ProtoEqual(const google::protobuf::Message &message1,
bool ProtoEqual(const google::protobuf::Message &message1,
const google::protobuf::Message &message2);

// 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;
}
}
16 changes: 16 additions & 0 deletions p4_constraints/backend/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,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 @@ -208,3 +209,18 @@ cc_test(
"@com_google_googletest//:gtest_main",
],
)

cc_test(
name = "constraint_info_test",
srcs = ["constraint_info_test.cc"],
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 94a88b3

Please sign in to comment.