oxidecomputer / p4

A P4 compiler
Mozilla Public License 2.0
111 stars 5 forks source link

Table collision on valid P4 when instantiating control twice #8

Closed rcgoodfellow closed 2 years ago

rcgoodfellow commented 2 years ago

The following P4 generates bad rust output.

What's happening here is the same control resolver is instantiated multiple times, once from the foo control and once from the bar control. Because generated rust names for tables are based entirely on the name of control they are a part of and the name of the table e.g. $control_table_$table this means that multiple instantiations will cause collisions. The code generated from the P4 below at time of writing is recorded in this gist.

One possible solution is to make the generated names more specific. Another arguably much better solution would be to not have control objects be implicitly global, but rather have them be local to the scope in which they're created. This is a pretty major change and will require a lot of rework, but is probably a better path forward.

#include <p4/examples/codegen/core.p4>
#include <p4/examples/codegen/softnpu.p4>

SoftNPU(
    parse(),
    ingress()
) main;

struct headers_t { }

parser parse(
    packet_in pkt,
    out headers_t headers,
    inout IngressMetadata ingress,
){
    state start { transition accept; }
}

control resolver(
    in bit<32> x,
    out bool resolved,
) {
    action resolve() {
        resolved = true;
    }
    table arp {
        key = { x: exact; }
        actions = { resolve; }
        default_action = NoAction;
    }
    apply { arp.apply(); }
}

control foo() {
    resolver() resolver;
    apply {
        resolver.apply(32w47);
    }
}

control bar() {
    resolver() resolver;
    apply { resolver.apply(32w1701); }
}

control ingress(
    inout headers_t hdr,
    inout IngressMetadata ingress,
    inout EgressMetadata egress,
) {
    foo() foo;
    bar() bar;

    apply {
        bar.apply();
        foo.apply();
    }
}