Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parsing P4Info for Actions and type-checking params. #114

Merged
merged 1 commit into from
Nov 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading