diff --git a/backends/ubpf/ubpfControl.cpp b/backends/ubpf/ubpfControl.cpp index eba8a1ad66..a3992d759e 100644 --- a/backends/ubpf/ubpfControl.cpp +++ b/backends/ubpf/ubpfControl.cpp @@ -429,8 +429,21 @@ namespace UBPF { } bool UBPFControlBodyTranslator::preorder(const IR::IfStatement *statement) { + bool isHit = P4::TableApplySolver::isHit(statement->condition, control->program->refMap, + control->program->typeMap); + if (isHit) { + // visit first the table, and then the conditional + auto member = statement->condition->to(); + CHECK_NULL(member); + visit(member->expr); // table application. Sets 'hitVariable' + builder->emitIndent(); + } + builder->append("if ("); - visit(statement->condition); + if (isHit) + builder->append(control->hitVariable); + else + visit(statement->condition); builder->append(") "); if (!statement->ifTrue->is()) { builder->blockStart(); diff --git a/testdata/p4_16_samples/issue3483_ubpf.p4 b/testdata/p4_16_samples/issue3483_ubpf.p4 new file mode 100644 index 0000000000..d8c8a0ebf5 --- /dev/null +++ b/testdata/p4_16_samples/issue3483_ubpf.p4 @@ -0,0 +1,74 @@ +#include + +#include "ebpf_headers.p4" + +struct Headers_t +{ + Ethernet_h ethernet; + IPv4_h ipv4; +} + +struct Meta { + bit b; +} + +parser prs(packet_in p, out Headers_t headers, inout Meta meta, inout standard_metadata std_meta) +{ + state start + { + p.extract(headers.ethernet); + transition select(headers.ethernet.etherType) + { + 16w0x800 : ip; + default : reject; + } + } + + state ip + { + p.extract(headers.ipv4); + transition accept; + } +} + +control pipe(inout Headers_t headers, inout Meta meta, inout standard_metadata unused) +{ + action Reject(IPv4Address add) + { + headers.ipv4.srcAddr = add; + } + + table Check_src_ip { + key = { headers.ipv4.srcAddr : exact; } + actions = + { + Reject; + NoAction; + } + + default_action = NoAction; + } + + apply { + if (!Check_src_ip.apply().hit) { + meta.b = 1; + } + + switch (Check_src_ip.apply().action_run) { + Reject: { + meta.b = 0; + } + NoAction: {} + } + } +} + +control dprs(packet_out packet, in Headers_t headers) { + apply { + packet.emit(headers.ethernet); + packet.emit(headers.ipv4); + } +} + + +ubpf(prs(), pipe(), dprs()) main; diff --git a/testdata/p4_16_samples_outputs/issue3483_ubpf-first.p4 b/testdata/p4_16_samples_outputs/issue3483_ubpf-first.p4 new file mode 100644 index 0000000000..4072958300 --- /dev/null +++ b/testdata/p4_16_samples_outputs/issue3483_ubpf-first.p4 @@ -0,0 +1,88 @@ +#include +#include + +@ethernetaddress typedef bit<48> EthernetAddress; +@ipv4address typedef bit<32> IPv4Address; +header Ethernet_h { + EthernetAddress dstAddr; + EthernetAddress srcAddr; + bit<16> etherType; +} + +header IPv4_h { + bit<4> version; + bit<4> ihl; + bit<8> diffserv; + bit<16> totalLen; + bit<16> identification; + bit<3> flags; + bit<13> fragOffset; + bit<8> ttl; + bit<8> protocol; + bit<16> hdrChecksum; + IPv4Address srcAddr; + IPv4Address dstAddr; +} + +struct Headers_t { + Ethernet_h ethernet; + IPv4_h ipv4; +} + +struct Meta { + bit<1> b; +} + +parser prs(packet_in p, out Headers_t headers, inout Meta meta, inout standard_metadata std_meta) { + state start { + p.extract(headers.ethernet); + transition select(headers.ethernet.etherType) { + 16w0x800: ip; + default: reject; + } + } + state ip { + p.extract(headers.ipv4); + transition accept; + } +} + +control pipe(inout Headers_t headers, inout Meta meta, inout standard_metadata unused) { + action Reject(IPv4Address add) { + headers.ipv4.srcAddr = add; + } + table Check_src_ip { + key = { + headers.ipv4.srcAddr: exact @name("headers.ipv4.srcAddr") ; + } + actions = { + Reject(); + NoAction(); + } + default_action = NoAction(); + } + apply { + if (Check_src_ip.apply().hit) { + ; + } else { + meta.b = 1w1; + } + switch (Check_src_ip.apply().action_run) { + Reject: { + meta.b = 1w0; + } + NoAction: { + } + } + } +} + +control dprs(packet_out packet, in Headers_t headers) { + apply { + packet.emit(headers.ethernet); + packet.emit(headers.ipv4); + } +} + +ubpf(prs(), pipe(), dprs()) main; + diff --git a/testdata/p4_16_samples_outputs/issue3483_ubpf-frontend.p4 b/testdata/p4_16_samples_outputs/issue3483_ubpf-frontend.p4 new file mode 100644 index 0000000000..48e3931982 --- /dev/null +++ b/testdata/p4_16_samples_outputs/issue3483_ubpf-frontend.p4 @@ -0,0 +1,90 @@ +#include +#include + +@ethernetaddress typedef bit<48> EthernetAddress; +@ipv4address typedef bit<32> IPv4Address; +header Ethernet_h { + EthernetAddress dstAddr; + EthernetAddress srcAddr; + bit<16> etherType; +} + +header IPv4_h { + bit<4> version; + bit<4> ihl; + bit<8> diffserv; + bit<16> totalLen; + bit<16> identification; + bit<3> flags; + bit<13> fragOffset; + bit<8> ttl; + bit<8> protocol; + bit<16> hdrChecksum; + IPv4Address srcAddr; + IPv4Address dstAddr; +} + +struct Headers_t { + Ethernet_h ethernet; + IPv4_h ipv4; +} + +struct Meta { + bit<1> b; +} + +parser prs(packet_in p, out Headers_t headers, inout Meta meta, inout standard_metadata std_meta) { + state start { + p.extract(headers.ethernet); + transition select(headers.ethernet.etherType) { + 16w0x800: ip; + default: reject; + } + } + state ip { + p.extract(headers.ipv4); + transition accept; + } +} + +control pipe(inout Headers_t headers, inout Meta meta, inout standard_metadata unused) { + @noWarn("unused") @name(".NoAction") action NoAction_1() { + } + @name("pipe.Reject") action Reject(@name("add") IPv4Address add) { + headers.ipv4.srcAddr = add; + } + @name("pipe.Check_src_ip") table Check_src_ip_0 { + key = { + headers.ipv4.srcAddr: exact @name("headers.ipv4.srcAddr") ; + } + actions = { + Reject(); + NoAction_1(); + } + default_action = NoAction_1(); + } + apply { + if (Check_src_ip_0.apply().hit) { + ; + } else { + meta.b = 1w1; + } + switch (Check_src_ip_0.apply().action_run) { + Reject: { + meta.b = 1w0; + } + NoAction_1: { + } + } + } +} + +control dprs(packet_out packet, in Headers_t headers) { + apply { + packet.emit(headers.ethernet); + packet.emit(headers.ipv4); + } +} + +ubpf(prs(), pipe(), dprs()) main; + diff --git a/testdata/p4_16_samples_outputs/issue3483_ubpf-midend.p4 b/testdata/p4_16_samples_outputs/issue3483_ubpf-midend.p4 new file mode 100644 index 0000000000..cdf5dd404b --- /dev/null +++ b/testdata/p4_16_samples_outputs/issue3483_ubpf-midend.p4 @@ -0,0 +1,117 @@ +#include +#include + +@ethernetaddress typedef bit<48> EthernetAddress; +@ipv4address typedef bit<32> IPv4Address; +header Ethernet_h { + EthernetAddress dstAddr; + EthernetAddress srcAddr; + bit<16> etherType; +} + +header IPv4_h { + bit<4> version; + bit<4> ihl; + bit<8> diffserv; + bit<16> totalLen; + bit<16> identification; + bit<3> flags; + bit<13> fragOffset; + bit<8> ttl; + bit<8> protocol; + bit<16> hdrChecksum; + IPv4Address srcAddr; + IPv4Address dstAddr; +} + +struct Headers_t { + Ethernet_h ethernet; + IPv4_h ipv4; +} + +struct Meta { + bit<1> b; +} + +parser prs(packet_in p, out Headers_t headers, inout Meta meta, inout standard_metadata std_meta) { + state start { + p.extract(headers.ethernet); + transition select(headers.ethernet.etherType) { + 16w0x800: ip; + default: reject; + } + } + state ip { + p.extract(headers.ipv4); + transition accept; + } +} + +control pipe(inout Headers_t headers, inout Meta meta, inout standard_metadata unused) { + @noWarn("unused") @name(".NoAction") action NoAction_1() { + } + @name("pipe.Reject") action Reject(@name("add") IPv4Address add) { + headers.ipv4.srcAddr = add; + } + @name("pipe.Check_src_ip") table Check_src_ip_0 { + key = { + headers.ipv4.srcAddr: exact @name("headers.ipv4.srcAddr") ; + } + actions = { + Reject(); + NoAction_1(); + } + default_action = NoAction_1(); + } + @hidden action issue3483_ubpf54() { + meta.b = 1w1; + } + @hidden action issue3483_ubpf59() { + meta.b = 1w0; + } + @hidden table tbl_issue3483_ubpf54 { + actions = { + issue3483_ubpf54(); + } + const default_action = issue3483_ubpf54(); + } + @hidden table tbl_issue3483_ubpf59 { + actions = { + issue3483_ubpf59(); + } + const default_action = issue3483_ubpf59(); + } + apply { + if (Check_src_ip_0.apply().hit) { + ; + } else { + tbl_issue3483_ubpf54.apply(); + } + switch (Check_src_ip_0.apply().action_run) { + Reject: { + tbl_issue3483_ubpf59.apply(); + } + NoAction_1: { + } + } + } +} + +control dprs(packet_out packet, in Headers_t headers) { + @hidden action issue3483_ubpf68() { + packet.emit(headers.ethernet); + packet.emit(headers.ipv4); + } + @hidden table tbl_issue3483_ubpf68 { + actions = { + issue3483_ubpf68(); + } + const default_action = issue3483_ubpf68(); + } + apply { + tbl_issue3483_ubpf68.apply(); + } +} + +ubpf(prs(), pipe(), dprs()) main; + diff --git a/testdata/p4_16_samples_outputs/issue3483_ubpf.p4 b/testdata/p4_16_samples_outputs/issue3483_ubpf.p4 new file mode 100644 index 0000000000..9f283a36b8 --- /dev/null +++ b/testdata/p4_16_samples_outputs/issue3483_ubpf.p4 @@ -0,0 +1,86 @@ +#include +#include + +@ethernetaddress typedef bit<48> EthernetAddress; +@ipv4address typedef bit<32> IPv4Address; +header Ethernet_h { + EthernetAddress dstAddr; + EthernetAddress srcAddr; + bit<16> etherType; +} + +header IPv4_h { + bit<4> version; + bit<4> ihl; + bit<8> diffserv; + bit<16> totalLen; + bit<16> identification; + bit<3> flags; + bit<13> fragOffset; + bit<8> ttl; + bit<8> protocol; + bit<16> hdrChecksum; + IPv4Address srcAddr; + IPv4Address dstAddr; +} + +struct Headers_t { + Ethernet_h ethernet; + IPv4_h ipv4; +} + +struct Meta { + bit<1> b; +} + +parser prs(packet_in p, out Headers_t headers, inout Meta meta, inout standard_metadata std_meta) { + state start { + p.extract(headers.ethernet); + transition select(headers.ethernet.etherType) { + 16w0x800: ip; + default: reject; + } + } + state ip { + p.extract(headers.ipv4); + transition accept; + } +} + +control pipe(inout Headers_t headers, inout Meta meta, inout standard_metadata unused) { + action Reject(IPv4Address add) { + headers.ipv4.srcAddr = add; + } + table Check_src_ip { + key = { + headers.ipv4.srcAddr: exact; + } + actions = { + Reject; + NoAction; + } + default_action = NoAction; + } + apply { + if (!Check_src_ip.apply().hit) { + meta.b = 1; + } + switch (Check_src_ip.apply().action_run) { + Reject: { + meta.b = 0; + } + NoAction: { + } + } + } +} + +control dprs(packet_out packet, in Headers_t headers) { + apply { + packet.emit(headers.ethernet); + packet.emit(headers.ipv4); + } +} + +ubpf(prs(), pipe(), dprs()) main; + diff --git a/testdata/p4_16_samples_outputs/issue3483_ubpf.p4-stderr b/testdata/p4_16_samples_outputs/issue3483_ubpf.p4-stderr new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testdata/p4_16_samples_outputs/issue3483_ubpf.p4.entries.txt b/testdata/p4_16_samples_outputs/issue3483_ubpf.p4.entries.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testdata/p4_16_samples_outputs/issue3483_ubpf.p4.p4info.txt b/testdata/p4_16_samples_outputs/issue3483_ubpf.p4.p4info.txt new file mode 100644 index 0000000000..c47d398e06 --- /dev/null +++ b/testdata/p4_16_samples_outputs/issue3483_ubpf.p4.p4info.txt @@ -0,0 +1,45 @@ +pkg_info { + arch: "ubpf" +} +tables { + preamble { + id: 43471039 + name: "pipe.Check_src_ip" + alias: "Check_src_ip" + } + match_fields { + id: 1 + name: "headers.ipv4.srcAddr" + bitwidth: 32 + match_type: EXACT + } + action_refs { + id: 18876683 + } + action_refs { + id: 21257015 + } + size: 1024 +} +actions { + preamble { + id: 21257015 + name: "NoAction" + alias: "NoAction" + annotations: "@noWarn(\"unused\")" + } +} +actions { + preamble { + id: 18876683 + name: "pipe.Reject" + alias: "Reject" + } + params { + id: 1 + name: "add" + bitwidth: 32 + } +} +type_info { +}