Skip to content

Commit

Permalink
Fix bmv2 backend crash for unused action selectors
Browse files Browse the repository at this point in the history
When an action selector is declared as a control local but never
referenced by a table, the compiler cannot figure out the selector
input, which means the action selector cannot be included in the bmv2
JSON.
  • Loading branch information
antoninbas committed May 5, 2017
1 parent 4dbab3d commit 7c2f154
Show file tree
Hide file tree
Showing 7 changed files with 303 additions and 4 deletions.
17 changes: 13 additions & 4 deletions backends/bmv2/jsonconverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,10 @@ class SharedActionSelectorCheck : public Inspector {
explicit SharedActionSelectorCheck(JsonConverter* converter) : converter(converter)
{ CHECK_NULL(converter); }

const Input &get_selector_input(const IR::Declaration_Instance* selector) const {
return selector_input_map.at(selector);
const Input *get_selector_input(const IR::Declaration_Instance* selector) const {
auto it = selector_input_map.find(selector);
if (it == selector_input_map.end()) return nullptr; // selector never used
return &it->second;
}

bool preorder(const IR::P4Table* table) override {
Expand Down Expand Up @@ -2096,10 +2098,17 @@ Util::IJson* JsonConverter::convertControl(const IR::ControlBlock* block, cstrin
BUG_CHECK(hash->is<IR::Declaration_ID>(), "%1%: expected a member", hash);
auto algo = convertHashAlgorithm(hash->to<IR::Declaration_ID>()->name);
selector->emplace("algo", algo);
const auto &input = selector_check.get_selector_input(
auto input = selector_check.get_selector_input(
c->to<IR::Declaration_Instance>());
if (input == nullptr) {
// the selector is never used by any table, we cannot figure out its
// input and therefore cannot include it in the JSON
::warning("Action selector '%1%' is never referenced by a table "
"and cannot be included in bmv2 JSON", c);
continue;
}
auto j_input = mkArrayField(selector, "input");
for (auto expr : input) {
for (auto expr : *input) {
auto jk = conv->convert(expr);
j_input->append(jk);
}
Expand Down
52 changes: 52 additions & 0 deletions testdata/p4_16_samples/action_selector_unused-bmv2.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#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() { smeta.drop = 1; }

action_selector (HashAlgorithm.identity, 32w1024, 32w10) as;

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

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(in 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
@@ -0,0 +1,60 @@
#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() {
smeta.drop = 1w1;
}
action_selector(HashAlgorithm.identity, 32w1024, 32w10) as;
table indirect_ws {
key = {
meta.hash1: selector @name("meta.hash1") ;
}
actions = {
drop();
NoAction();
}
const default_action = NoAction();
implementation = as;
}
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(in 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;
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#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;
}
}

control IngressI(inout H hdr, inout M meta, inout standard_metadata_t smeta) {
@name("drop") action drop_0() {
smeta.drop = 1w1;
}
@name("as") action_selector(HashAlgorithm.identity, 32w1024, 32w10) as_0;
@name("indirect_ws") table indirect_ws_0 {
key = {
meta.hash1: selector @name("meta.hash1") ;
}
actions = {
drop_0();
NoAction();
}
const default_action = NoAction();
implementation = as_0;
}
apply {
indirect_ws_0.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(in 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;
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#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;
}
}

control IngressI(inout H hdr, inout M meta, inout standard_metadata_t smeta) {
@name("NoAction") action NoAction_0() {
}
@name("drop") action drop_0() {
smeta.drop = 1w1;
}
@name("as") action_selector(HashAlgorithm.identity, 32w1024, 32w10) as;
@name("indirect_ws") table indirect_ws {
key = {
meta.hash1: selector @name("meta.hash1") ;
}
actions = {
drop_0();
NoAction_0();
}
const default_action = NoAction_0();
implementation = as;
}
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(in 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;
60 changes: 60 additions & 0 deletions testdata/p4_16_samples_outputs/action_selector_unused-bmv2.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#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() {
smeta.drop = 1;
}
action_selector(HashAlgorithm.identity, 32w1024, 32w10) as;
table indirect_ws {
key = {
meta.hash1: selector;
}
actions = {
drop;
NoAction;
}
const default_action = NoAction();
implementation = as;
}
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(in H hdr, inout M meta) {
apply {
}
}

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

V1Switch(ParserI(), VerifyChecksumI(), IngressI(), EgressI(), ComputeChecksumI(), DeparserI()) main;
Empty file.

0 comments on commit 7c2f154

Please sign in to comment.