Skip to content

Commit

Permalink
Support new ActionProfile annotations for P4Runtime. (#4533)
Browse files Browse the repository at this point in the history
* Support new ActionProfile annotations for P4Runtime.

* Fix golden tests.

* Add tests for new annotations.

* Fix broken ebpf test.

* Fixed error message for bad 'max_member_weights' annotation and made the default value for 'selector_size_semantics' absence.

* Fix minor issues based on fruffy's comments.

* Fix build issues.
  • Loading branch information
jonathan-dilorenzo authored Mar 25, 2024
1 parent 204ee83 commit 450398d
Show file tree
Hide file tree
Showing 17 changed files with 565 additions and 22 deletions.
14 changes: 8 additions & 6 deletions control-plane/p4RuntimeAnnotations.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,20 +36,22 @@ class ParseP4RuntimeAnnotations : public ParseAnnotations {
PARSE("id", Constant),
PARSE("brief", StringLiteral),
PARSE("description", StringLiteral),
// This annotation is architecture-specific in theory, but
// given that it is "reserved" by the P4Runtime specification,
// I don't really have any qualms about adding it here. I
// don't think it is possible to just run a different
// ParseAnnotations pass in the constructor of the
// These annotations are architecture-specific in theory, but
// given that they are "reserved" by the P4Runtime
// specification, I don't really have any qualms about adding
// them here. I don't think it is possible to just run a
// different ParseAnnotations pass in the constructor of the
// architecture-specific P4RuntimeArchHandlerIface
// implementation, since ParseAnnotations modifies the
// program. I don't really like the possible alternatives
// either: 1) modify the P4RuntimeArchHandlerIface interface
// so that each implementation can provide a custom
// ParseAnnotations instance, or 2) run a ParseAnnotations
// pass "locally" (in this case on action profile instances
// since this annotation is for them).
// since these annotations are for them).
PARSE("max_group_size", Constant),
PARSE("selector_size_semantics", StringLiteral),
PARSE("max_member_weight", Constant),
{"p4runtime_translation", &ParseAnnotations::parseP4rtTranslationAnnotation},
}) {}
};
Expand Down
63 changes: 60 additions & 3 deletions control-plane/p4RuntimeArchStandard.h
Original file line number Diff line number Diff line change
Expand Up @@ -768,14 +768,19 @@ class P4RuntimeArchHandlerCommon : public P4RuntimeArchHandlerIface {
auto id = symbols.getId(SymbolType::P4RT_ACTION_PROFILE(), actionProfile.name);
setPreamble(profile->mutable_preamble(), id, actionProfile.name,
symbols.getAlias(actionProfile.name), actionProfile.annotations,
// exclude @max_group_size if present
[](cstring name) { return name == "max_group_size"; });
// exclude @max_group_size, @selector_size_semantics, and
// @max_member_weight if present
[](cstring name) {
return name == "max_group_size" || name == "selector_size_semantics" ||
name == "max_member_weight";
});
profile->set_with_selector(actionProfile.type == ActionProfileType::INDIRECT_WITH_SELECTOR);
profile->set_size(actionProfile.size);
auto maxGroupSizeAnnotation = actionProfile.annotations->getAnnotation("max_group_size");
if (maxGroupSizeAnnotation) {
if (actionProfile.type == ActionProfileType::INDIRECT_WITH_SELECTOR) {
auto maxGroupSizeConstant = maxGroupSizeAnnotation->expr[0]->to<IR::Constant>();
auto maxGroupSizeConstant =
maxGroupSizeAnnotation->expr[0]->checkedTo<IR::Constant>();
CHECK_NULL(maxGroupSizeConstant);
profile->set_max_group_size(maxGroupSizeConstant->asInt());
} else {
Expand All @@ -786,6 +791,58 @@ class P4RuntimeArchHandlerCommon : public P4RuntimeArchHandlerIface {
}
}

// By default, an action profile uses the SumOfWeights semantics.
auto selectorSizeSemanticsAnnotation =
actionProfile.annotations->getAnnotation("selector_size_semantics");
if (selectorSizeSemanticsAnnotation) {
if (actionProfile.type == ActionProfileType::INDIRECT_WITH_SELECTOR) {
auto selectorSizeSemantics =
selectorSizeSemanticsAnnotation->expr[0]->checkedTo<IR::StringLiteral>();
CHECK_NULL(selectorSizeSemantics);
// The expression may only contain 'sum_of_weights' or 'sum_of_members'
// in any case.
if (selectorSizeSemantics->value.toUpper() == "SUM_OF_WEIGHTS") {
profile->mutable_sum_of_weights();
} else if (selectorSizeSemantics->value.toUpper() == "SUM_OF_MEMBERS") {
profile->mutable_sum_of_members();
} else {
::error(ErrorType::ERR_INVALID,
"Expected selector_size_semantics value \"sum_of_weights\" or "
"\"sum_of_members\", but got '%1%'",
selectorSizeSemantics);
}
} else {
::warning(ErrorType::WARN_IGNORE,
"Ignoring annotation @selector_size_semantics on action "
"profile '%1%', which does not have a selector ",
actionProfile.annotations);
}
}

// By default, an action profile uses the SumOfWeights semantics.
auto maxMemberWeightAnnotation =
actionProfile.annotations->getAnnotation("max_member_weight");
if (maxMemberWeightAnnotation) {
if (actionProfile.type == ActionProfileType::INDIRECT_WITH_SELECTOR &&
profile->has_sum_of_members()) {
auto maxMemberWeightConstant =
maxMemberWeightAnnotation->expr[0]->checkedTo<IR::Constant>();
CHECK_NULL(maxMemberWeightConstant);
profile->mutable_sum_of_members()->set_max_member_weight(
maxMemberWeightConstant->asInt());
} else if (actionProfile.type != ActionProfileType::INDIRECT_WITH_SELECTOR) {
::warning(ErrorType::WARN_IGNORE,
"Ignoring annotation @max_member_weight on action profile "
"'%1%', which does not have a selector",
actionProfile.annotations);
} else {
::warning(ErrorType::WARN_IGNORE,
"Ignoring annotation @max_member_weight on action profile '%1%', "
"which does not use 'sum_of_members' as its SelectorSizeSemantics",
actionProfile.annotations);
}
}

auto tablesIt = actionProfilesRefs.find(actionProfile.name);
if (tablesIt != actionProfilesRefs.end()) {
for (const auto &table : tablesIt->second)
Expand Down
15 changes: 13 additions & 2 deletions testdata/p4_16_samples/action_profile_max_group_size_annotation.p4
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,25 @@ control IngressI(inout H hdr, inout M meta, inout standard_metadata_t smeta) {
key = { }
actions = { drop; NoAction; }
const default_action = NoAction();
@name("ap") @max_group_size(200) implementation = action_profile(32w128);
// For an action profile without an action selector, the
// `max_group_size`, `selector_size_semantics`, and `max_member_weight`
// annotations are meaningless and should result in a warning.
@name("ap") @max_group_size(200)
@selector_size_semantics("sum_of_weights") @max_member_weight(4000)
implementation = action_profile(32w128);
}

table indirect_ws {
key = { meta.hash1 : selector; }
actions = { drop; NoAction; }
const default_action = NoAction();
@name("ap_ws") @max_group_size(200) implementation = action_selector(HashAlgorithm.identity, 32w1024, 32w10);
@name("ap_ws") @max_group_size(200)
// For an action profile with an action selector using the `sum_of_weights`
// size semantics, the `max_member_weight` annotation is meaningless and
// should result in a warning.
@name("ap") @max_group_size(200)
@selector_size_semantics("sum_of_weights") @max_member_weight(4000)
implementation = action_selector(HashAlgorithm.identity, 32w1024, 32w10);
}

apply {
Expand Down
88 changes: 88 additions & 0 deletions testdata/p4_16_samples/action_profile_sum_of_members_annotation.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
Copyright 2019-present Barefoot Networks, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#include <core.p4>
#include <v1model.p4>

struct H { };
struct M {
bit<32> hash1;
}

parser ParserI(packet_in pk, out H hdr, inout M meta, inout standard_metadata_t smeta) {
state start { transition accept; }
}

action empty() { }

control IngressI(inout H hdr, inout M meta, inout standard_metadata_t smeta) {

action drop() { mark_to_drop(smeta); }

// For an action profile without an action selector, the
// `max_group_size`, `selector_size_semantics`, and `max_member_weight`
// annotations are meaningless and should result in a warning.
@name("ap") @max_group_size(200)
@selector_size_semantics("sum_of_members") @max_member_weight(4000)
action_profile(32w128) my_action_profile;

// For an action profile with an action selector using the `sum_of_members`
// size semantics, all of these annotations are meaningful and should result
// in no warnings.
@name("ap_ws") @max_group_size(200)
@selector_size_semantics("sum_of_members") @max_member_weight(4000)
action_selector(HashAlgorithm.identity, 32w1024, 32w10)
my_action_selector;

table indirect {
key = { }
actions = { drop; NoAction; }
const default_action = NoAction();
implementation = my_action_profile;
}

table indirect_ws {
key = { meta.hash1 : selector; }
actions = { drop; NoAction; }
const default_action = NoAction();
implementation = my_action_selector;
}

apply {
indirect.apply();
indirect_ws.apply();
}

};

control EgressI(inout H hdr, inout M meta, inout standard_metadata_t smeta) {
apply { }
};

control DeparserI(packet_out pk, in H hdr) {
apply { }
}

control VerifyChecksumI(inout H hdr, inout M meta) {
apply { }
}

control ComputeChecksumI(inout H hdr, inout M meta) {
apply { }
}

V1Switch(ParserI(), VerifyChecksumI(), IngressI(), EgressI(),
ComputeChecksumI(), DeparserI()) main;
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ control IngressI(inout H hdr, inout M meta, inout standard_metadata_t smeta) {
NoAction();
}
const default_action = NoAction();
@name("ap") @max_group_size(200) implementation = action_profile(32w128);
@name("ap") @max_group_size(200) @selector_size_semantics("sum_of_weights") @max_member_weight(4000) implementation = action_profile(32w128);
}
table indirect_ws {
key = {
Expand All @@ -38,7 +38,7 @@ control IngressI(inout H hdr, inout M meta, inout standard_metadata_t smeta) {
NoAction();
}
const default_action = NoAction();
@name("ap_ws") @max_group_size(200) implementation = action_selector(HashAlgorithm.identity, 32w1024, 32w10);
@name("ap_ws") @max_group_size(200) @name("ap") @max_group_size(200) @selector_size_semantics("sum_of_weights") @max_member_weight(4000) implementation = action_selector(HashAlgorithm.identity, 32w1024, 32w10);
}
apply {
indirect.apply();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ control IngressI(inout H hdr, inout M meta, inout standard_metadata_t smeta) {
NoAction_1();
}
const default_action = NoAction_1();
@name("ap") @max_group_size(200) implementation = action_profile(32w128);
@name("ap") @max_group_size(200) @selector_size_semantics("sum_of_weights") @max_member_weight(4000) implementation = action_profile(32w128);
}
@name("IngressI.indirect_ws") table indirect_ws_0 {
key = {
Expand All @@ -43,7 +43,7 @@ control IngressI(inout H hdr, inout M meta, inout standard_metadata_t smeta) {
NoAction_2();
}
const default_action = NoAction_2();
@name("ap_ws") @max_group_size(200) implementation = action_selector(HashAlgorithm.identity, 32w1024, 32w10);
@name("ap_ws") @max_group_size(200) @name("ap") @max_group_size(200) @selector_size_semantics("sum_of_weights") @max_member_weight(4000) implementation = action_selector(HashAlgorithm.identity, 32w1024, 32w10);
}
apply {
indirect_0.apply();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ control IngressI(inout H hdr, inout M meta, inout standard_metadata_t smeta) {
NoAction_1();
}
const default_action = NoAction_1();
@name("ap") @max_group_size(200) implementation = action_profile(32w128);
@name("ap") @max_group_size(200) @selector_size_semantics("sum_of_weights") @max_member_weight(4000) implementation = action_profile(32w128);
}
@name("IngressI.indirect_ws") table indirect_ws_0 {
key = {
Expand All @@ -43,7 +43,7 @@ control IngressI(inout H hdr, inout M meta, inout standard_metadata_t smeta) {
NoAction_2();
}
const default_action = NoAction_2();
@name("ap_ws") @max_group_size(200) implementation = action_selector(HashAlgorithm.identity, 32w1024, 32w10);
@name("ap_ws") @max_group_size(200) @name("ap") @max_group_size(200) @selector_size_semantics("sum_of_weights") @max_member_weight(4000) implementation = action_selector(HashAlgorithm.identity, 32w1024, 32w10);
}
apply {
indirect_0.apply();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ control IngressI(inout H hdr, inout M meta, inout standard_metadata_t smeta) {
NoAction;
}
const default_action = NoAction();
@name("ap") @max_group_size(200) implementation = action_profile(32w128);
@name("ap") @max_group_size(200) @selector_size_semantics("sum_of_weights") @max_member_weight(4000) implementation = action_profile(32w128);
}
table indirect_ws {
key = {
Expand All @@ -40,7 +40,7 @@ control IngressI(inout H hdr, inout M meta, inout standard_metadata_t smeta) {
NoAction;
}
const default_action = NoAction();
@name("ap_ws") @max_group_size(200) implementation = action_selector(HashAlgorithm.identity, 32w1024, 32w10);
@name("ap_ws") @max_group_size(200) @name("ap") @max_group_size(200) @selector_size_semantics("sum_of_weights") @max_member_weight(4000) implementation = action_selector(HashAlgorithm.identity, 32w1024, 32w10);
}
apply {
indirect.apply();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
action_profile_max_group_size_annotation.p4(39): [--Wwarn=ignore] warning: Ignoring annotation @max_group_size on action profile 'ap', which does not have a selector
@name("ap") @max_group_size(200) implementation = action_profile(32w128);
^^^^^^^^^^^^^^
action_profile_max_group_size_annotation.p4(44): [--Wwarn=ignore] warning: Ignoring annotation @max_group_size on action profile 'ap', which does not have a selector
implementation = action_profile(32w128);
^^^^^^^^^^^^^^
action_profile_max_group_size_annotation.p4(57): [--Wwarn=ignore] warning: Ignoring annotation @max_member_weight on action profile 'ap_ws', which does not use 'sum_of_members' as its SelectorSizeSemantics
implementation = action_selector(HashAlgorithm.identity, 32w1024, 32w10);
^^^^^^^^^^^^^^
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ action_profiles {
with_selector: true
size: 1024
max_group_size: 200
sum_of_weights {
}
}
type_info {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#include <core.p4>
#define V1MODEL_VERSION 20180101
#include <v1model.p4>

struct H {
}

struct M {
bit<32> hash1;
}

parser ParserI(packet_in pk, out H hdr, inout M meta, inout standard_metadata_t smeta) {
state start {
transition accept;
}
}

action empty() {
}
control IngressI(inout H hdr, inout M meta, inout standard_metadata_t smeta) {
action drop() {
mark_to_drop(smeta);
}
@name("ap") @max_group_size(200) @selector_size_semantics("sum_of_members") @max_member_weight(4000) action_profile(32w128) my_action_profile;
@name("ap_ws") @max_group_size(200) @selector_size_semantics("sum_of_members") @max_member_weight(4000) action_selector(HashAlgorithm.identity, 32w1024, 32w10) my_action_selector;
table indirect {
actions = {
drop();
NoAction();
}
const default_action = NoAction();
implementation = my_action_profile;
}
table indirect_ws {
key = {
meta.hash1: selector @name("meta.hash1");
}
actions = {
drop();
NoAction();
}
const default_action = NoAction();
implementation = my_action_selector;
}
apply {
indirect.apply();
indirect_ws.apply();
}
}

control EgressI(inout H hdr, inout M meta, inout standard_metadata_t smeta) {
apply {
}
}

control DeparserI(packet_out pk, in H hdr) {
apply {
}
}

control VerifyChecksumI(inout H hdr, inout M meta) {
apply {
}
}

control ComputeChecksumI(inout H hdr, inout M meta) {
apply {
}
}

V1Switch<H, M>(ParserI(), VerifyChecksumI(), IngressI(), EgressI(), ComputeChecksumI(), DeparserI()) main;
Loading

0 comments on commit 450398d

Please sign in to comment.