From f836c77c65926b0c7e42d7d749550973094b1fe5 Mon Sep 17 00:00:00 2001 From: mbudiu-vmw Date: Tue, 9 May 2017 09:49:49 -0700 Subject: [PATCH 1/4] Fix for issue #583 --- frontends/p4-14/typecheck.cpp | 34 ++- frontends/p4/fromv1.0/programStructure.cpp | 15 +- testdata/p4_14_samples/issue583.p4 | 250 ++++++++++++++++++ .../p4_14_samples_outputs/issue583-first.p4 | 235 ++++++++++++++++ .../issue583-frontend.p4 | 235 ++++++++++++++++ .../p4_14_samples_outputs/issue583-midend.p4 | 244 +++++++++++++++++ testdata/p4_14_samples_outputs/issue583.p4 | 235 ++++++++++++++++ .../p4_14_samples_outputs/issue583.p4-stderr | 7 + 8 files changed, 1240 insertions(+), 15 deletions(-) create mode 100644 testdata/p4_14_samples/issue583.p4 create mode 100644 testdata/p4_14_samples_outputs/issue583-first.p4 create mode 100644 testdata/p4_14_samples_outputs/issue583-frontend.p4 create mode 100644 testdata/p4_14_samples_outputs/issue583-midend.p4 create mode 100644 testdata/p4_14_samples_outputs/issue583.p4 create mode 100644 testdata/p4_14_samples_outputs/issue583.p4-stderr diff --git a/frontends/p4-14/typecheck.cpp b/frontends/p4-14/typecheck.cpp index 0915f556d43..ceab1964ac4 100644 --- a/frontends/p4-14/typecheck.cpp +++ b/frontends/p4-14/typecheck.cpp @@ -16,15 +16,18 @@ limitations under the License. #include "typecheck.h" -// P4 v1.0 and v1.1 type checking algorithm -// Initial type setting based on immediate context: -// - replace named reference to ActionParams in the bodies of ActionFunctions with the -// actual ActionParam -// - link header/metadata instances to the Type -// - replace named references to global header or metadata instances with ConcreteHeaderRef -// expressions that link directly to them. -// - set type for Member and HeaderStackItemRefs +/// P4-14 (v1.0 and v1.1) type checking algorithm +/// Initial type setting based on immediate context: +/// - replace named reference to ActionParams in the bodies of ActionFunctions with the +/// actual ActionParam +/// - link header/metadata instances to the Type +/// - replace named references to global header or metadata instances with ConcreteHeaderRef +/// expressions that link directly to them. +/// - set type for Member and HeaderStackItemRefs class TypeCheck::AssignInitialTypes : public Transform { + public: + AssignInitialTypes() { setName("AssignInitialTypes"); } + private: const IR::V1Program *global = nullptr; template @@ -194,8 +197,11 @@ combineTypes(const Util::SourceInfo &loc, const IR::Type *a, const IR::Type *b) return a; } -// bottom up type inferencing -- set the types of expression nodes based on operands +/// Bottom up type inferencing -- set the types of expression nodes based on operands. class TypeCheck::InferExpressionsBottomUp : public Modifier { + public: + InferExpressionsBottomUp() { setName("InferExpressionsBottomUp"); } + private: void setType(IR::Expression* currentNode, const IR::Type* type) { BUG_CHECK(currentNode == getCurrentNode(), "Expected to be called on the visitor's current node"); @@ -273,8 +279,11 @@ inferTypeFromContext(const Visitor::Context* ctxt, const IR::V1Program* global) return rv; } -// top down type inferencing -- set the type of expression nodes based on their uses. +/// Top down type inferencing -- set the type of expression nodes based on their uses. class TypeCheck::InferExpressionsTopDown : public Modifier { + public: + InferExpressionsTopDown() { setName("InferExpressionsTopDown"); } + private: const IR::V1Program *global = nullptr; profile_t init_apply(const IR::Node *root) override { global = root->to(); @@ -319,7 +328,7 @@ class TypeCheck::InferActionArgsBottomUp : public Inspector { prim->typecheck(); } } public: - explicit InferActionArgsBottomUp(TypeCheck &s) : self(s) {} + explicit InferActionArgsBottomUp(TypeCheck &s) : self(s) { setName("InferActionArgsBottomUp"); } }; class TypeCheck::InferActionArgsTopDown : public Inspector { @@ -360,6 +369,7 @@ class TypeCheck::InferActionArgsTopDown : public Inspector { // action argument, we need to visit the action argument nodes every // time they appear in the IR tree. visitDagOnce = false; + setName("InferActionArgsTopDown"); } }; @@ -396,7 +406,7 @@ class TypeCheck::AssignActionArgTypes : public Modifier { } public: - explicit AssignActionArgTypes(TypeCheck &s) : self(s) { } + explicit AssignActionArgTypes(TypeCheck &s) : self(s) { setName("AssignActionArgTypes"); } }; TypeCheck::TypeCheck() : PassManager({ diff --git a/frontends/p4/fromv1.0/programStructure.cpp b/frontends/p4/fromv1.0/programStructure.cpp index ad8ad8395ea..3fe5b2ce621 100644 --- a/frontends/p4/fromv1.0/programStructure.cpp +++ b/frontends/p4/fromv1.0/programStructure.cpp @@ -95,7 +95,7 @@ void ProgramStructure::checkHeaderType(const IR::Type_StructLike* hdr, bool meta } void ProgramStructure::createType(const IR::Type_StructLike* type, bool header, - std::unordered_set *converted) { + std::unordered_set *converted) { if (converted->count(type)) return; converted->emplace(type); @@ -126,14 +126,16 @@ void ProgramStructure::createTypes() { continue; createType(type, false, &converted); } + for (auto it : registers) { if (it.first->layout) { auto type = types.get(it.first->layout); - createType(type, false, &converted); + if (type->is()) + createType(type, false, &converted); } } - // Headers next + // Now headers converted.clear(); for (auto it : headers) { auto type = it.first->type; @@ -143,6 +145,13 @@ void ProgramStructure::createTypes() { auto type = it.first->type; createType(type, true, &converted); } + for (auto it : registers) { + if (it.first->layout) { + auto type = types.get(it.first->layout); + if (type->is()) + createType(type, true, &converted); + } + } } const IR::Type_Struct* ProgramStructure::createFieldListType(const IR::Expression* expression) { diff --git a/testdata/p4_14_samples/issue583.p4 b/testdata/p4_14_samples/issue583.p4 new file mode 100644 index 00000000000..2ff4859c40d --- /dev/null +++ b/testdata/p4_14_samples/issue583.p4 @@ -0,0 +1,250 @@ +header_type ethernet_t { + fields { + dstAddr : 48; + srcAddr : 48; + etherType : 16; + } +} + +header_type vlan_tag_t { + fields { + pcp : 3; + cfi : 1; + vid : 12; + etherType : 16; + } +} + +header_type ipv4_t { + fields { + version : 4; + ihl : 4; + diffserv : 8; + totalLen : 16; + identification : 16; + flags : 3; + fragOffset : 13; + ttl : 8; + protocol : 8; + hdrChecksum : 16; + srcAddr : 32; + dstAddr: 32; + } +} + +header_type ipv6_t { + fields { + version : 4; + trafficClass : 8; + flowLabel : 20; + payloadLen : 16; + nextHdr : 8; + hopLimit : 8; + srcAddr : 128; + dstAddr : 128; + } +} + +header_type icmp_t { + fields { + hdr_type : 8; + code : 8; + hdrChecksum : 16; + } +} + +header_type icmpv6_t { + fields { + hdr_type : 8; + code : 8; + hdrChecksum : 16; + } +} + +header_type tcp_t { + fields { + srcPort : 16; + dstPort : 16; + seqNo : 32; + ackNo : 32; + dataOffset : 4; + res : 3; + ecn : 3; + ctrl : 6; + window : 16; + checksum : 16; + urgentPtr : 16; + } +} + +header_type udp_t { + fields { + srcPort : 16; + dstPort : 16; + hdr_length : 16; + checksum : 16; + } +} + +header_type routing_metadata_t { + fields { + drop : 1; + } +} + +metadata routing_metadata_t routing_metadata; + +parser start { + set_metadata(routing_metadata.drop, 0); + return parse_ethernet; +} + +#define ETHERTYPE_VLAN 0x8100, 0x9100, 0x9200, 0x9300 +#define ETHERTYPE_IPV4 0x0800 +#define ETHERTYPE_IPV6 0x86dd +#define ETHERTYPE_ARP 0x0806 +#define ETHERTYPE_RARP 0x8035 + +header ethernet_t ethernet; + +parser parse_ethernet { + extract(ethernet); + return select(latest.etherType) { + ETHERTYPE_VLAN : parse_vlan; + ETHERTYPE_IPV4 : parse_ipv4; + ETHERTYPE_IPV6 : parse_ipv6; + } +} + +#define VLAN_DEPTH 4 +header vlan_tag_t vlan_tag_[VLAN_DEPTH]; + +parser parse_vlan { + extract(vlan_tag_[next]); + return select(latest.etherType) { + ETHERTYPE_VLAN : parse_vlan; + ETHERTYPE_IPV4 : parse_ipv4; + ETHERTYPE_IPV6 : parse_ipv6; + } +} + +#define IP_PROTOCOLS_ICMP 1 +#define IP_PROTOCOLS_TCP 6 +#define IP_PROTOCOLS_UDP 17 +#define IP_PROTOCOLS_ICMPV6 58 + +header ipv4_t ipv4; + +parser parse_ipv4 { + extract(ipv4); + return select(latest.fragOffset, latest.protocol) { + IP_PROTOCOLS_ICMP : parse_icmp; + IP_PROTOCOLS_TCP : parse_tcp; + IP_PROTOCOLS_UDP : parse_udp; + } +} + +header ipv6_t ipv6; + +parser parse_ipv6 { + extract(ipv6); + return select(latest.nextHdr) { + IP_PROTOCOLS_ICMPV6 : parse_icmpv6; + IP_PROTOCOLS_TCP : parse_tcp; + IP_PROTOCOLS_UDP : parse_udp; + } +} + +header icmp_t icmp; + +parser parse_icmp { + extract(icmp); + return ingress; +} + +header icmpv6_t icmpv6; + +parser parse_icmpv6 { + extract(icmpv6); + return ingress; +} + +header tcp_t tcp; + +parser parse_tcp { + extract(tcp); + return ingress; +} + + +header udp_t udp; + +parser parse_udp { + extract(udp); + return ingress; +} + +action hop(ttl, egress_spec) { + add_to_field(ttl, -1); + modify_field(standard_metadata.egress_spec, egress_spec, 0xFFFFFFFF); +} + +action hop_ipv4(egress_spec) { + hop(ipv4.ttl, egress_spec); +} + +/* This should not be necessary if drop is allowed in table action specs */ +action drop_pkt() { + drop(); +} + +table ipv4_routing { + reads { + ipv4.dstAddr : lpm; + } + actions { + drop_pkt; + hop_ipv4; + } +} + +action act() { + count(cnt1, 10); +} + +table table_2 { + reads { + ipv4.dstAddr : lpm; + } + actions { + act; + } +} + +counter cnt1 { + type : packets; + static : table_2; + instance_count : 32; +} + +register reg1 { + width : 20; + static : ipv4_routing; + instance_count : 100; + attributes : saturating, signed; +} + +register reg2 { + layout : ipv4_t; + direct : ipv4_routing; +} + + +control ingress { + apply(ipv4_routing); + apply(table_2); +} + +control egress { + +} \ No newline at end of file diff --git a/testdata/p4_14_samples_outputs/issue583-first.p4 b/testdata/p4_14_samples_outputs/issue583-first.p4 new file mode 100644 index 00000000000..bfc28aaf7ed --- /dev/null +++ b/testdata/p4_14_samples_outputs/issue583-first.p4 @@ -0,0 +1,235 @@ +#include +#include + +struct routing_metadata_t { + bit<1> drop; +} + +header ethernet_t { + bit<48> dstAddr; + bit<48> srcAddr; + bit<16> etherType; +} + +header icmp_t { + bit<8> hdr_type; + bit<8> code; + bit<16> hdrChecksum; +} + +header icmpv6_t { + bit<8> hdr_type; + bit<8> code; + bit<16> hdrChecksum; +} + +header ipv4_t { + 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; + bit<32> srcAddr; + bit<32> dstAddr; +} + +header ipv6_t { + bit<4> version; + bit<8> trafficClass; + bit<20> flowLabel; + bit<16> payloadLen; + bit<8> nextHdr; + bit<8> hopLimit; + bit<128> srcAddr; + bit<128> dstAddr; +} + +header tcp_t { + bit<16> srcPort; + bit<16> dstPort; + bit<32> seqNo; + bit<32> ackNo; + bit<4> dataOffset; + bit<3> res; + bit<3> ecn; + bit<6> ctrl; + bit<16> window; + bit<16> checksum; + bit<16> urgentPtr; +} + +header udp_t { + bit<16> srcPort; + bit<16> dstPort; + bit<16> hdr_length; + bit<16> checksum; +} + +header vlan_tag_t { + bit<3> pcp; + bit<1> cfi; + bit<12> vid; + bit<16> etherType; +} + +struct metadata { + @name("routing_metadata") + routing_metadata_t routing_metadata; +} + +struct headers { + @name("ethernet") + ethernet_t ethernet; + @name("icmp") + icmp_t icmp; + @name("icmpv6") + icmpv6_t icmpv6; + @name("ipv4") + ipv4_t ipv4; + @name("ipv6") + ipv6_t ipv6; + @name("tcp") + tcp_t tcp; + @name("udp") + udp_t udp; + @name("vlan_tag_") + vlan_tag_t[4] vlan_tag_; +} + +parser ParserImpl(packet_in packet, out headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + @name("parse_ethernet") state parse_ethernet { + packet.extract(hdr.ethernet); + transition select(hdr.ethernet.etherType) { + 16w0x8100: parse_vlan; + 16w0x9100: parse_vlan; + 16w0x9200: parse_vlan; + 16w0x9300: parse_vlan; + 16w0x800: parse_ipv4; + 16w0x86dd: parse_ipv6; + } + } + @name("parse_icmp") state parse_icmp { + packet.extract(hdr.icmp); + transition accept; + } + @name("parse_icmpv6") state parse_icmpv6 { + packet.extract(hdr.icmpv6); + transition accept; + } + @name("parse_ipv4") state parse_ipv4 { + packet.extract(hdr.ipv4); + transition select(hdr.ipv4.fragOffset, hdr.ipv4.protocol) { + (13w0, 8w1): parse_icmp; + (13w0, 8w6): parse_tcp; + (13w0, 8w17): parse_udp; + } + } + @name("parse_ipv6") state parse_ipv6 { + packet.extract(hdr.ipv6); + transition select(hdr.ipv6.nextHdr) { + 8w58: parse_icmpv6; + 8w6: parse_tcp; + 8w17: parse_udp; + } + } + @name("parse_tcp") state parse_tcp { + packet.extract(hdr.tcp); + transition accept; + } + @name("parse_udp") state parse_udp { + packet.extract(hdr.udp); + transition accept; + } + @name("parse_vlan") state parse_vlan { + packet.extract(hdr.vlan_tag_.next); + transition select(hdr.vlan_tag_.last.etherType) { + 16w0x8100: parse_vlan; + 16w0x9100: parse_vlan; + 16w0x9200: parse_vlan; + 16w0x9300: parse_vlan; + 16w0x800: parse_ipv4; + 16w0x86dd: parse_ipv6; + } + } + @name("start") state start { + meta.routing_metadata.drop = 1w0; + transition parse_ethernet; + } +} + +control egress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + apply { + } +} + +control ingress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + @name("cnt1") counter(32w32, CounterType.packets) cnt1; + @name(".drop_pkt") action drop_pkt() { + mark_to_drop(); + } + @name(".hop") action hop(inout bit<8> ttl, bit<9> egress_spec) { + ttl = ttl + 8w255; + standard_metadata.egress_spec[8:0] = egress_spec[8:0]; + } + @name(".hop_ipv4") action hop_ipv4(bit<9> egress_spec) { + hop(hdr.ipv4.ttl, egress_spec); + } + @name(".act") action act() { + cnt1.count(32w10); + } + @name("ipv4_routing") table ipv4_routing { + actions = { + drop_pkt(); + hop_ipv4(); + @default_only NoAction(); + } + key = { + hdr.ipv4.dstAddr: lpm @name("hdr.ipv4.dstAddr") ; + } + default_action = NoAction(); + } + @name("table_2") table table_2 { + actions = { + act(); + @default_only NoAction(); + } + key = { + hdr.ipv4.dstAddr: lpm @name("hdr.ipv4.dstAddr") ; + } + default_action = NoAction(); + } + apply { + ipv4_routing.apply(); + table_2.apply(); + } +} + +control DeparserImpl(packet_out packet, in headers hdr) { + apply { + packet.emit(hdr.ethernet); + packet.emit(hdr.vlan_tag_); + packet.emit(hdr.ipv6); + packet.emit(hdr.icmpv6); + packet.emit(hdr.ipv4); + packet.emit(hdr.udp); + packet.emit(hdr.tcp); + packet.emit(hdr.icmp); + } +} + +control verifyChecksum(in headers hdr, inout metadata meta) { + apply { + } +} + +control computeChecksum(inout headers hdr, inout metadata meta) { + apply { + } +} + +V1Switch(ParserImpl(), verifyChecksum(), ingress(), egress(), computeChecksum(), DeparserImpl()) main; diff --git a/testdata/p4_14_samples_outputs/issue583-frontend.p4 b/testdata/p4_14_samples_outputs/issue583-frontend.p4 new file mode 100644 index 00000000000..79dffbebfb9 --- /dev/null +++ b/testdata/p4_14_samples_outputs/issue583-frontend.p4 @@ -0,0 +1,235 @@ +#include +#include + +struct routing_metadata_t { + bit<1> drop; +} + +header ethernet_t { + bit<48> dstAddr; + bit<48> srcAddr; + bit<16> etherType; +} + +header icmp_t { + bit<8> hdr_type; + bit<8> code; + bit<16> hdrChecksum; +} + +header icmpv6_t { + bit<8> hdr_type; + bit<8> code; + bit<16> hdrChecksum; +} + +header ipv4_t { + 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; + bit<32> srcAddr; + bit<32> dstAddr; +} + +header ipv6_t { + bit<4> version; + bit<8> trafficClass; + bit<20> flowLabel; + bit<16> payloadLen; + bit<8> nextHdr; + bit<8> hopLimit; + bit<128> srcAddr; + bit<128> dstAddr; +} + +header tcp_t { + bit<16> srcPort; + bit<16> dstPort; + bit<32> seqNo; + bit<32> ackNo; + bit<4> dataOffset; + bit<3> res; + bit<3> ecn; + bit<6> ctrl; + bit<16> window; + bit<16> checksum; + bit<16> urgentPtr; +} + +header udp_t { + bit<16> srcPort; + bit<16> dstPort; + bit<16> hdr_length; + bit<16> checksum; +} + +header vlan_tag_t { + bit<3> pcp; + bit<1> cfi; + bit<12> vid; + bit<16> etherType; +} + +struct metadata { + @name("routing_metadata") + routing_metadata_t routing_metadata; +} + +struct headers { + @name("ethernet") + ethernet_t ethernet; + @name("icmp") + icmp_t icmp; + @name("icmpv6") + icmpv6_t icmpv6; + @name("ipv4") + ipv4_t ipv4; + @name("ipv6") + ipv6_t ipv6; + @name("tcp") + tcp_t tcp; + @name("udp") + udp_t udp; + @name("vlan_tag_") + vlan_tag_t[4] vlan_tag_; +} + +parser ParserImpl(packet_in packet, out headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + @name("parse_ethernet") state parse_ethernet { + packet.extract(hdr.ethernet); + transition select(hdr.ethernet.etherType) { + 16w0x8100: parse_vlan; + 16w0x9100: parse_vlan; + 16w0x9200: parse_vlan; + 16w0x9300: parse_vlan; + 16w0x800: parse_ipv4; + 16w0x86dd: parse_ipv6; + } + } + @name("parse_icmp") state parse_icmp { + packet.extract(hdr.icmp); + transition accept; + } + @name("parse_icmpv6") state parse_icmpv6 { + packet.extract(hdr.icmpv6); + transition accept; + } + @name("parse_ipv4") state parse_ipv4 { + packet.extract(hdr.ipv4); + transition select(hdr.ipv4.fragOffset, hdr.ipv4.protocol) { + (13w0, 8w1): parse_icmp; + (13w0, 8w6): parse_tcp; + (13w0, 8w17): parse_udp; + } + } + @name("parse_ipv6") state parse_ipv6 { + packet.extract(hdr.ipv6); + transition select(hdr.ipv6.nextHdr) { + 8w58: parse_icmpv6; + 8w6: parse_tcp; + 8w17: parse_udp; + } + } + @name("parse_tcp") state parse_tcp { + packet.extract(hdr.tcp); + transition accept; + } + @name("parse_udp") state parse_udp { + packet.extract(hdr.udp); + transition accept; + } + @name("parse_vlan") state parse_vlan { + packet.extract(hdr.vlan_tag_.next); + transition select(hdr.vlan_tag_.last.etherType) { + 16w0x8100: parse_vlan; + 16w0x9100: parse_vlan; + 16w0x9200: parse_vlan; + 16w0x9300: parse_vlan; + 16w0x800: parse_ipv4; + 16w0x86dd: parse_ipv6; + } + } + @name("start") state start { + meta.routing_metadata.drop = 1w0; + transition parse_ethernet; + } +} + +control egress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + apply { + } +} + +control ingress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + @name("cnt1") counter(32w32, CounterType.packets) cnt1_0; + @name(".drop_pkt") action drop_pkt_0() { + mark_to_drop(); + } + @name(".hop") action hop_0(inout bit<8> ttl_0, bit<9> egress_spec_0) { + ttl_0 = ttl_0 + 8w255; + standard_metadata.egress_spec[8:0] = egress_spec_0[8:0]; + } + @name(".hop_ipv4") action hop_ipv4_0(bit<9> egress_spec) { + hop_0(hdr.ipv4.ttl, egress_spec); + } + @name(".act") action act_0() { + cnt1_0.count(32w10); + } + @name("ipv4_routing") table ipv4_routing_0 { + actions = { + drop_pkt_0(); + hop_ipv4_0(); + @default_only NoAction(); + } + key = { + hdr.ipv4.dstAddr: lpm @name("hdr.ipv4.dstAddr") ; + } + default_action = NoAction(); + } + @name("table_2") table table_0 { + actions = { + act_0(); + @default_only NoAction(); + } + key = { + hdr.ipv4.dstAddr: lpm @name("hdr.ipv4.dstAddr") ; + } + default_action = NoAction(); + } + apply { + ipv4_routing_0.apply(); + table_0.apply(); + } +} + +control DeparserImpl(packet_out packet, in headers hdr) { + apply { + packet.emit(hdr.ethernet); + packet.emit(hdr.vlan_tag_); + packet.emit(hdr.ipv6); + packet.emit(hdr.icmpv6); + packet.emit(hdr.ipv4); + packet.emit(hdr.udp); + packet.emit(hdr.tcp); + packet.emit(hdr.icmp); + } +} + +control verifyChecksum(in headers hdr, inout metadata meta) { + apply { + } +} + +control computeChecksum(inout headers hdr, inout metadata meta) { + apply { + } +} + +V1Switch(ParserImpl(), verifyChecksum(), ingress(), egress(), computeChecksum(), DeparserImpl()) main; diff --git a/testdata/p4_14_samples_outputs/issue583-midend.p4 b/testdata/p4_14_samples_outputs/issue583-midend.p4 new file mode 100644 index 00000000000..4a73dc398e0 --- /dev/null +++ b/testdata/p4_14_samples_outputs/issue583-midend.p4 @@ -0,0 +1,244 @@ +#include +#include + +struct routing_metadata_t { + bit<1> drop; +} + +header ethernet_t { + bit<48> dstAddr; + bit<48> srcAddr; + bit<16> etherType; +} + +header icmp_t { + bit<8> hdr_type; + bit<8> code; + bit<16> hdrChecksum; +} + +header icmpv6_t { + bit<8> hdr_type; + bit<8> code; + bit<16> hdrChecksum; +} + +header ipv4_t { + 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; + bit<32> srcAddr; + bit<32> dstAddr; +} + +header ipv6_t { + bit<4> version; + bit<8> trafficClass; + bit<20> flowLabel; + bit<16> payloadLen; + bit<8> nextHdr; + bit<8> hopLimit; + bit<128> srcAddr; + bit<128> dstAddr; +} + +header tcp_t { + bit<16> srcPort; + bit<16> dstPort; + bit<32> seqNo; + bit<32> ackNo; + bit<4> dataOffset; + bit<3> res; + bit<3> ecn; + bit<6> ctrl; + bit<16> window; + bit<16> checksum; + bit<16> urgentPtr; +} + +header udp_t { + bit<16> srcPort; + bit<16> dstPort; + bit<16> hdr_length; + bit<16> checksum; +} + +header vlan_tag_t { + bit<3> pcp; + bit<1> cfi; + bit<12> vid; + bit<16> etherType; +} + +struct metadata { + @name("routing_metadata") + routing_metadata_t routing_metadata; +} + +struct headers { + @name("ethernet") + ethernet_t ethernet; + @name("icmp") + icmp_t icmp; + @name("icmpv6") + icmpv6_t icmpv6; + @name("ipv4") + ipv4_t ipv4; + @name("ipv6") + ipv6_t ipv6; + @name("tcp") + tcp_t tcp; + @name("udp") + udp_t udp; + @name("vlan_tag_") + vlan_tag_t[4] vlan_tag_; +} + +parser ParserImpl(packet_in packet, out headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + @name("parse_ethernet") state parse_ethernet { + packet.extract(hdr.ethernet); + transition select(hdr.ethernet.etherType) { + 16w0x8100: parse_vlan; + 16w0x9100: parse_vlan; + 16w0x9200: parse_vlan; + 16w0x9300: parse_vlan; + 16w0x800: parse_ipv4; + 16w0x86dd: parse_ipv6; + default: noMatch; + } + } + @name("parse_icmp") state parse_icmp { + packet.extract(hdr.icmp); + transition accept; + } + @name("parse_icmpv6") state parse_icmpv6 { + packet.extract(hdr.icmpv6); + transition accept; + } + @name("parse_ipv4") state parse_ipv4 { + packet.extract(hdr.ipv4); + transition select(hdr.ipv4.fragOffset, hdr.ipv4.protocol) { + (13w0, 8w1): parse_icmp; + (13w0, 8w6): parse_tcp; + (13w0, 8w17): parse_udp; + default: noMatch; + } + } + @name("parse_ipv6") state parse_ipv6 { + packet.extract(hdr.ipv6); + transition select(hdr.ipv6.nextHdr) { + 8w58: parse_icmpv6; + 8w6: parse_tcp; + 8w17: parse_udp; + default: noMatch; + } + } + @name("parse_tcp") state parse_tcp { + packet.extract(hdr.tcp); + transition accept; + } + @name("parse_udp") state parse_udp { + packet.extract(hdr.udp); + transition accept; + } + @name("parse_vlan") state parse_vlan { + packet.extract(hdr.vlan_tag_.next); + transition select(hdr.vlan_tag_.last.etherType) { + 16w0x8100: parse_vlan; + 16w0x9100: parse_vlan; + 16w0x9200: parse_vlan; + 16w0x9300: parse_vlan; + 16w0x800: parse_ipv4; + 16w0x86dd: parse_ipv6; + default: noMatch; + } + } + @name("start") state start { + meta.routing_metadata.drop = 1w0; + transition parse_ethernet; + } + state noMatch { + verify(false, error.NoMatch); + transition reject; + } +} + +control egress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + apply { + } +} + +control ingress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + @name("NoAction") action NoAction_0() { + } + @name("NoAction") action NoAction_3() { + } + @name("cnt1") counter(32w32, CounterType.packets) cnt1; + @name(".drop_pkt") action drop_pkt_0() { + mark_to_drop(); + } + @name(".hop_ipv4") action hop_ipv4_0(bit<9> egress_spec) { + standard_metadata.egress_spec[8:0] = egress_spec[8:0]; + hdr.ipv4.ttl = hdr.ipv4.ttl + 8w255; + } + @name(".act") action act_0() { + cnt1.count(32w10); + } + @name("ipv4_routing") table ipv4_routing { + actions = { + drop_pkt_0(); + hop_ipv4_0(); + @default_only NoAction_0(); + } + key = { + hdr.ipv4.dstAddr: lpm @name("hdr.ipv4.dstAddr") ; + } + default_action = NoAction_0(); + } + @name("table_2") table table_1 { + actions = { + act_0(); + @default_only NoAction_3(); + } + key = { + hdr.ipv4.dstAddr: lpm @name("hdr.ipv4.dstAddr") ; + } + default_action = NoAction_3(); + } + apply { + ipv4_routing.apply(); + table_1.apply(); + } +} + +control DeparserImpl(packet_out packet, in headers hdr) { + apply { + packet.emit(hdr.ethernet); + packet.emit(hdr.vlan_tag_); + packet.emit(hdr.ipv6); + packet.emit(hdr.icmpv6); + packet.emit(hdr.ipv4); + packet.emit(hdr.udp); + packet.emit(hdr.tcp); + packet.emit(hdr.icmp); + } +} + +control verifyChecksum(in headers hdr, inout metadata meta) { + apply { + } +} + +control computeChecksum(inout headers hdr, inout metadata meta) { + apply { + } +} + +V1Switch(ParserImpl(), verifyChecksum(), ingress(), egress(), computeChecksum(), DeparserImpl()) main; diff --git a/testdata/p4_14_samples_outputs/issue583.p4 b/testdata/p4_14_samples_outputs/issue583.p4 new file mode 100644 index 00000000000..f71d91a0e1d --- /dev/null +++ b/testdata/p4_14_samples_outputs/issue583.p4 @@ -0,0 +1,235 @@ +#include +#include + +struct routing_metadata_t { + bit<1> drop; +} + +header ethernet_t { + bit<48> dstAddr; + bit<48> srcAddr; + bit<16> etherType; +} + +header icmp_t { + bit<8> hdr_type; + bit<8> code; + bit<16> hdrChecksum; +} + +header icmpv6_t { + bit<8> hdr_type; + bit<8> code; + bit<16> hdrChecksum; +} + +header ipv4_t { + 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; + bit<32> srcAddr; + bit<32> dstAddr; +} + +header ipv6_t { + bit<4> version; + bit<8> trafficClass; + bit<20> flowLabel; + bit<16> payloadLen; + bit<8> nextHdr; + bit<8> hopLimit; + bit<128> srcAddr; + bit<128> dstAddr; +} + +header tcp_t { + bit<16> srcPort; + bit<16> dstPort; + bit<32> seqNo; + bit<32> ackNo; + bit<4> dataOffset; + bit<3> res; + bit<3> ecn; + bit<6> ctrl; + bit<16> window; + bit<16> checksum; + bit<16> urgentPtr; +} + +header udp_t { + bit<16> srcPort; + bit<16> dstPort; + bit<16> hdr_length; + bit<16> checksum; +} + +header vlan_tag_t { + bit<3> pcp; + bit<1> cfi; + bit<12> vid; + bit<16> etherType; +} + +struct metadata { + @name("routing_metadata") + routing_metadata_t routing_metadata; +} + +struct headers { + @name("ethernet") + ethernet_t ethernet; + @name("icmp") + icmp_t icmp; + @name("icmpv6") + icmpv6_t icmpv6; + @name("ipv4") + ipv4_t ipv4; + @name("ipv6") + ipv6_t ipv6; + @name("tcp") + tcp_t tcp; + @name("udp") + udp_t udp; + @name("vlan_tag_") + vlan_tag_t[4] vlan_tag_; +} + +parser ParserImpl(packet_in packet, out headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + @name("parse_ethernet") state parse_ethernet { + packet.extract(hdr.ethernet); + transition select(hdr.ethernet.etherType) { + 16w0x8100: parse_vlan; + 16w0x9100: parse_vlan; + 16w0x9200: parse_vlan; + 16w0x9300: parse_vlan; + 16w0x800: parse_ipv4; + 16w0x86dd: parse_ipv6; + } + } + @name("parse_icmp") state parse_icmp { + packet.extract(hdr.icmp); + transition accept; + } + @name("parse_icmpv6") state parse_icmpv6 { + packet.extract(hdr.icmpv6); + transition accept; + } + @name("parse_ipv4") state parse_ipv4 { + packet.extract(hdr.ipv4); + transition select(hdr.ipv4.fragOffset, hdr.ipv4.protocol) { + (13w0, 8w1): parse_icmp; + (13w0, 8w6): parse_tcp; + (13w0, 8w17): parse_udp; + } + } + @name("parse_ipv6") state parse_ipv6 { + packet.extract(hdr.ipv6); + transition select(hdr.ipv6.nextHdr) { + 8w58: parse_icmpv6; + 8w6: parse_tcp; + 8w17: parse_udp; + } + } + @name("parse_tcp") state parse_tcp { + packet.extract(hdr.tcp); + transition accept; + } + @name("parse_udp") state parse_udp { + packet.extract(hdr.udp); + transition accept; + } + @name("parse_vlan") state parse_vlan { + packet.extract(hdr.vlan_tag_.next); + transition select(hdr.vlan_tag_.last.etherType) { + 16w0x8100: parse_vlan; + 16w0x9100: parse_vlan; + 16w0x9200: parse_vlan; + 16w0x9300: parse_vlan; + 16w0x800: parse_ipv4; + 16w0x86dd: parse_ipv6; + } + } + @name("start") state start { + meta.routing_metadata.drop = (bit<1>)1w0; + transition parse_ethernet; + } +} + +control egress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + apply { + } +} + +control ingress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { + @name("cnt1") counter(32w32, CounterType.packets) cnt1; + @name(".drop_pkt") action drop_pkt() { + mark_to_drop(); + } + @name(".hop") action hop(inout bit<8> ttl, bit<9> egress_spec) { + ttl = (bit<8>)(ttl + 8w255); + standard_metadata.egress_spec[8:0] = egress_spec[8:0]; + } + @name(".hop_ipv4") action hop_ipv4(bit<9> egress_spec) { + hop(hdr.ipv4.ttl, egress_spec); + } + @name(".act") action act() { + cnt1.count((bit<32>)5w10); + } + @name("ipv4_routing") table ipv4_routing { + actions = { + drop_pkt; + hop_ipv4; + @default_only NoAction; + } + key = { + hdr.ipv4.dstAddr: lpm; + } + default_action = NoAction(); + } + @name("table_2") table table_2 { + actions = { + act; + @default_only NoAction; + } + key = { + hdr.ipv4.dstAddr: lpm; + } + default_action = NoAction(); + } + apply { + ipv4_routing.apply(); + table_2.apply(); + } +} + +control DeparserImpl(packet_out packet, in headers hdr) { + apply { + packet.emit(hdr.ethernet); + packet.emit(hdr.vlan_tag_); + packet.emit(hdr.ipv6); + packet.emit(hdr.icmpv6); + packet.emit(hdr.ipv4); + packet.emit(hdr.udp); + packet.emit(hdr.tcp); + packet.emit(hdr.icmp); + } +} + +control verifyChecksum(in headers hdr, inout metadata meta) { + apply { + } +} + +control computeChecksum(inout headers hdr, inout metadata meta) { + apply { + } +} + +V1Switch(ParserImpl(), verifyChecksum(), ingress(), egress(), computeChecksum(), DeparserImpl()) main; diff --git a/testdata/p4_14_samples_outputs/issue583.p4-stderr b/testdata/p4_14_samples_outputs/issue583.p4-stderr new file mode 100644 index 00000000000..8d7a9be669d --- /dev/null +++ b/testdata/p4_14_samples_outputs/issue583.p4-stderr @@ -0,0 +1,7 @@ +../testdata/p4_14_samples/issue583.p4(188): warning: -1: negative value with unsigned type + add_to_field(ttl, -1); + ^ +../testdata/p4_14_samples/issue583.p4(189): warning: 4294967295: value does not fit in 9 bits + modify_field(standard_metadata.egress_spec, egress_spec, 0xFFFFFFFF); + ^^^^^^^^^^ +warning: The order of headers in deparser is not uniquely determined by parser! From 163e9ae9a87f9a83865578ba90eabb5feeb59fd5 Mon Sep 17 00:00:00 2001 From: mbudiu-vmw Date: Tue, 9 May 2017 13:39:15 -0700 Subject: [PATCH 2/4] cpplint fixes --- frontends/p4-14/typecheck.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontends/p4-14/typecheck.cpp b/frontends/p4-14/typecheck.cpp index ceab1964ac4..a51d83c572e 100644 --- a/frontends/p4-14/typecheck.cpp +++ b/frontends/p4-14/typecheck.cpp @@ -27,6 +27,7 @@ limitations under the License. class TypeCheck::AssignInitialTypes : public Transform { public: AssignInitialTypes() { setName("AssignInitialTypes"); } + private: const IR::V1Program *global = nullptr; @@ -201,6 +202,7 @@ combineTypes(const Util::SourceInfo &loc, const IR::Type *a, const IR::Type *b) class TypeCheck::InferExpressionsBottomUp : public Modifier { public: InferExpressionsBottomUp() { setName("InferExpressionsBottomUp"); } + private: void setType(IR::Expression* currentNode, const IR::Type* type) { BUG_CHECK(currentNode == getCurrentNode(), From f9972cfb10055e03873cfe6a87c6be8238e00a77 Mon Sep 17 00:00:00 2001 From: mbudiu-vmw Date: Tue, 9 May 2017 18:39:42 -0700 Subject: [PATCH 3/4] Special handling for register layout types --- frontends/p4/fromv1.0/programStructure.cpp | 60 +++-- frontends/p4/fromv1.0/programStructure.h | 7 +- testdata/p4_14_errors/issue583.p4 | 250 ++++++++++++++++++ testdata/p4_14_samples/issue583.p4 | 5 +- .../p4_14_samples_outputs/issue583-first.p4 | 27 +- .../issue583-frontend.p4 | 27 +- .../p4_14_samples_outputs/issue583-midend.p4 | 27 +- testdata/p4_14_samples_outputs/issue583.p4 | 23 +- .../p4_14_samples_outputs/issue583.p4-stderr | 4 +- 9 files changed, 393 insertions(+), 37 deletions(-) create mode 100644 testdata/p4_14_errors/issue583.p4 diff --git a/frontends/p4/fromv1.0/programStructure.cpp b/frontends/p4/fromv1.0/programStructure.cpp index 3fe5b2ce621..2738a6f6add 100644 --- a/frontends/p4/fromv1.0/programStructure.cpp +++ b/frontends/p4/fromv1.0/programStructure.cpp @@ -94,10 +94,10 @@ void ProgramStructure::checkHeaderType(const IR::Type_StructLike* hdr, bool meta } } -void ProgramStructure::createType(const IR::Type_StructLike* type, bool header, +cstring ProgramStructure::createType(const IR::Type_StructLike* type, bool header, std::unordered_set *converted) { if (converted->count(type)) - return; + return type->name; converted->emplace(type); auto type_name = types.get(type); auto newType = type->apply(TypeConverter(this)); @@ -115,6 +115,7 @@ void ProgramStructure::createType(const IR::Type_StructLike* type, bool header, LOG3("Added type " << dbp(newType) << " named " << type_name << " from " << dbp(type)); declarations->push_back(newType); converted->emplace(newType); + return type_name; } void ProgramStructure::createTypes() { @@ -129,9 +130,27 @@ void ProgramStructure::createTypes() { for (auto it : registers) { if (it.first->layout) { - auto type = types.get(it.first->layout); - if (type->is()) - createType(type, false, &converted); + cstring layoutTypeName = it.first->layout; + auto type = types.get(layoutTypeName); + if (converted.count(type) || !type->is()) + continue; + auto st = type->to(); + if (type->is()) { + cstring newName = createType(type, false, &converted); + registerLayoutType.emplace(layoutTypeName, newName); + continue; + } + + BUG_CHECK(type->is(), "%1%: unexpected type", type); + // Must convert to a struct type + cstring type_name = makeUniqueName(st->name); + // Registers always use struct types + auto annos = addNameAnnotation(layoutTypeName, type->annotations); + auto newType = new IR::Type_Struct(type->srcInfo, type_name, annos, st->fields); + checkHeaderType(newType, false); + LOG3("Added type " << dbp(newType) << " named " << type_name << " from " << dbp(type)); + declarations->push_back(newType); + registerLayoutType.emplace(layoutTypeName, newType->name); } } @@ -145,13 +164,6 @@ void ProgramStructure::createTypes() { auto type = it.first->type; createType(type, true, &converted); } - for (auto it : registers) { - if (it.first->layout) { - auto type = types.get(it.first->layout); - if (type->is()) - createType(type, true, &converted); - } - } } const IR::Type_Struct* ProgramStructure::createFieldListType(const IR::Expression* expression) { @@ -273,6 +285,12 @@ class ProgramStructure::FixupExtern : public Modifier { }; void ProgramStructure::createExterns() { + for (auto r : registers) { + auto reg = r.first; + if (reg->direct) + ::error("%1%: direct registers are not supported yet", reg); + } + for (auto it : extern_types) declarations->push_back(it.first->apply(FixupExtern(*this, it.second))); } @@ -1285,10 +1303,12 @@ const IR::Statement* ProgramStructure::convertPrimitive(const IR::Primitive* pri if (!reg) { ::error("Expected a register reference %1%", ref); return nullptr; } + + const IR::Type* castType = nullptr; int width = reg->width; - if (width <= 0) - width = defaultRegisterWidth; - auto regElementType = IR::Type_Bits::get(width); + if (width > 0) + castType = IR::Type_Bits::get(width); + // Else this is a structured type, so no cast is inserted below. auto newname = registers.get(reg); auto registerref = new IR::PathExpression(newname); @@ -1297,8 +1317,9 @@ const IR::Statement* ProgramStructure::convertPrimitive(const IR::Primitive* pri auto args = new IR::Vector(); auto arg0 = new IR::Cast(primitive->operands.at(1)->srcInfo, v1model.registers.index_type, conv.convert(primitive->operands.at(1))); - auto arg1 = new IR::Cast(primitive->operands.at(2)->srcInfo, regElementType, - conv.convert(primitive->operands.at(2))); + const IR::Expression* arg1 = conv.convert(primitive->operands.at(2)); + if (castType != nullptr) + arg1 = new IR::Cast(primitive->operands.at(2)->srcInfo, castType, arg1); args->push_back(arg0); args->push_back(arg1); auto mc = new IR::MethodCallExpression(primitive->srcInfo, method, args); @@ -1472,7 +1493,10 @@ ProgramStructure::convert(const IR::Register* reg, cstring newName) { if (reg->width > 0) { regElementType = IR::Type_Bits::get(reg->width); } else if (reg->layout) { - regElementType = types.get(reg->layout); + cstring newName = ::get(registerLayoutType, reg->layout); + if (newName.isNullOrEmpty()) + newName = reg->layout; + regElementType = new IR::Type_Name(new IR::Path(newName)); } else { ::warning("%1%: Register width unspecified; using %2%", reg, defaultRegisterWidth); regElementType = IR::Type_Bits::get(defaultRegisterWidth); diff --git a/frontends/p4/fromv1.0/programStructure.h b/frontends/p4/fromv1.0/programStructure.h index 614f7066e70..ad608288b2f 100644 --- a/frontends/p4/fromv1.0/programStructure.h +++ b/frontends/p4/fromv1.0/programStructure.h @@ -135,6 +135,9 @@ class ProgramStructure { /// Type_Header. We can't use the P4-14 type object itself as a /// key, because it keeps changing. std::map finalHeaderType; + /// For registers whose layout is a header, this map contains the mapping + /// from the original layout type name to the final layout type name. + std::map registerLayoutType; /// Maps each inserted extract statement to the type of the header /// type that is being extracted. The extracts will need another @@ -194,8 +197,8 @@ class ProgramStructure { void createChecksumUpdates(); void createStructures(); void createExterns(); - void createType(const IR::Type_StructLike* type, bool header, - std::unordered_set *converted); + cstring createType(const IR::Type_StructLike* type, bool header, + std::unordered_set *converted); void createTypes(); void createParser(); void createControls(); diff --git a/testdata/p4_14_errors/issue583.p4 b/testdata/p4_14_errors/issue583.p4 new file mode 100644 index 00000000000..2ff4859c40d --- /dev/null +++ b/testdata/p4_14_errors/issue583.p4 @@ -0,0 +1,250 @@ +header_type ethernet_t { + fields { + dstAddr : 48; + srcAddr : 48; + etherType : 16; + } +} + +header_type vlan_tag_t { + fields { + pcp : 3; + cfi : 1; + vid : 12; + etherType : 16; + } +} + +header_type ipv4_t { + fields { + version : 4; + ihl : 4; + diffserv : 8; + totalLen : 16; + identification : 16; + flags : 3; + fragOffset : 13; + ttl : 8; + protocol : 8; + hdrChecksum : 16; + srcAddr : 32; + dstAddr: 32; + } +} + +header_type ipv6_t { + fields { + version : 4; + trafficClass : 8; + flowLabel : 20; + payloadLen : 16; + nextHdr : 8; + hopLimit : 8; + srcAddr : 128; + dstAddr : 128; + } +} + +header_type icmp_t { + fields { + hdr_type : 8; + code : 8; + hdrChecksum : 16; + } +} + +header_type icmpv6_t { + fields { + hdr_type : 8; + code : 8; + hdrChecksum : 16; + } +} + +header_type tcp_t { + fields { + srcPort : 16; + dstPort : 16; + seqNo : 32; + ackNo : 32; + dataOffset : 4; + res : 3; + ecn : 3; + ctrl : 6; + window : 16; + checksum : 16; + urgentPtr : 16; + } +} + +header_type udp_t { + fields { + srcPort : 16; + dstPort : 16; + hdr_length : 16; + checksum : 16; + } +} + +header_type routing_metadata_t { + fields { + drop : 1; + } +} + +metadata routing_metadata_t routing_metadata; + +parser start { + set_metadata(routing_metadata.drop, 0); + return parse_ethernet; +} + +#define ETHERTYPE_VLAN 0x8100, 0x9100, 0x9200, 0x9300 +#define ETHERTYPE_IPV4 0x0800 +#define ETHERTYPE_IPV6 0x86dd +#define ETHERTYPE_ARP 0x0806 +#define ETHERTYPE_RARP 0x8035 + +header ethernet_t ethernet; + +parser parse_ethernet { + extract(ethernet); + return select(latest.etherType) { + ETHERTYPE_VLAN : parse_vlan; + ETHERTYPE_IPV4 : parse_ipv4; + ETHERTYPE_IPV6 : parse_ipv6; + } +} + +#define VLAN_DEPTH 4 +header vlan_tag_t vlan_tag_[VLAN_DEPTH]; + +parser parse_vlan { + extract(vlan_tag_[next]); + return select(latest.etherType) { + ETHERTYPE_VLAN : parse_vlan; + ETHERTYPE_IPV4 : parse_ipv4; + ETHERTYPE_IPV6 : parse_ipv6; + } +} + +#define IP_PROTOCOLS_ICMP 1 +#define IP_PROTOCOLS_TCP 6 +#define IP_PROTOCOLS_UDP 17 +#define IP_PROTOCOLS_ICMPV6 58 + +header ipv4_t ipv4; + +parser parse_ipv4 { + extract(ipv4); + return select(latest.fragOffset, latest.protocol) { + IP_PROTOCOLS_ICMP : parse_icmp; + IP_PROTOCOLS_TCP : parse_tcp; + IP_PROTOCOLS_UDP : parse_udp; + } +} + +header ipv6_t ipv6; + +parser parse_ipv6 { + extract(ipv6); + return select(latest.nextHdr) { + IP_PROTOCOLS_ICMPV6 : parse_icmpv6; + IP_PROTOCOLS_TCP : parse_tcp; + IP_PROTOCOLS_UDP : parse_udp; + } +} + +header icmp_t icmp; + +parser parse_icmp { + extract(icmp); + return ingress; +} + +header icmpv6_t icmpv6; + +parser parse_icmpv6 { + extract(icmpv6); + return ingress; +} + +header tcp_t tcp; + +parser parse_tcp { + extract(tcp); + return ingress; +} + + +header udp_t udp; + +parser parse_udp { + extract(udp); + return ingress; +} + +action hop(ttl, egress_spec) { + add_to_field(ttl, -1); + modify_field(standard_metadata.egress_spec, egress_spec, 0xFFFFFFFF); +} + +action hop_ipv4(egress_spec) { + hop(ipv4.ttl, egress_spec); +} + +/* This should not be necessary if drop is allowed in table action specs */ +action drop_pkt() { + drop(); +} + +table ipv4_routing { + reads { + ipv4.dstAddr : lpm; + } + actions { + drop_pkt; + hop_ipv4; + } +} + +action act() { + count(cnt1, 10); +} + +table table_2 { + reads { + ipv4.dstAddr : lpm; + } + actions { + act; + } +} + +counter cnt1 { + type : packets; + static : table_2; + instance_count : 32; +} + +register reg1 { + width : 20; + static : ipv4_routing; + instance_count : 100; + attributes : saturating, signed; +} + +register reg2 { + layout : ipv4_t; + direct : ipv4_routing; +} + + +control ingress { + apply(ipv4_routing); + apply(table_2); +} + +control egress { + +} \ No newline at end of file diff --git a/testdata/p4_14_samples/issue583.p4 b/testdata/p4_14_samples/issue583.p4 index 2ff4859c40d..42bcc87e093 100644 --- a/testdata/p4_14_samples/issue583.p4 +++ b/testdata/p4_14_samples/issue583.p4 @@ -134,6 +134,7 @@ parser parse_vlan { #define IP_PROTOCOLS_ICMPV6 58 header ipv4_t ipv4; +metadata ipv4_t ipv4_meta; parser parse_ipv4 { extract(ipv4); @@ -196,6 +197,7 @@ action hop_ipv4(egress_spec) { /* This should not be necessary if drop is allowed in table action specs */ action drop_pkt() { drop(); + register_write(reg2, 0, ipv4_meta); } table ipv4_routing { @@ -236,7 +238,8 @@ register reg1 { register reg2 { layout : ipv4_t; - direct : ipv4_routing; + static : ipv4_routing; + instance_count : 100; } diff --git a/testdata/p4_14_samples_outputs/issue583-first.p4 b/testdata/p4_14_samples_outputs/issue583-first.p4 index bfc28aaf7ed..0706b9e23bc 100644 --- a/testdata/p4_14_samples_outputs/issue583-first.p4 +++ b/testdata/p4_14_samples_outputs/issue583-first.p4 @@ -1,6 +1,21 @@ #include #include +struct ipv4_t { + 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; + bit<32> srcAddr; + bit<32> dstAddr; +} + struct routing_metadata_t { bit<1> drop; } @@ -23,7 +38,7 @@ header icmpv6_t { bit<16> hdrChecksum; } -header ipv4_t { +@name("ipv4_t") header ipv4_t_0 { bit<4> version; bit<4> ihl; bit<8> diffserv; @@ -78,6 +93,8 @@ header vlan_tag_t { } struct metadata { + @name("ipv4_meta") + ipv4_t ipv4_meta; @name("routing_metadata") routing_metadata_t routing_metadata; } @@ -90,7 +107,7 @@ struct headers { @name("icmpv6") icmpv6_t icmpv6; @name("ipv4") - ipv4_t ipv4; + ipv4_t_0 ipv4; @name("ipv6") ipv6_t ipv6; @name("tcp") @@ -122,7 +139,7 @@ parser ParserImpl(packet_in packet, out headers hdr, inout metadata meta, inout transition accept; } @name("parse_ipv4") state parse_ipv4 { - packet.extract(hdr.ipv4); + packet.extract(hdr.ipv4); transition select(hdr.ipv4.fragOffset, hdr.ipv4.protocol) { (13w0, 8w1): parse_icmp; (13w0, 8w6): parse_tcp; @@ -169,8 +186,10 @@ control egress(inout headers hdr, inout metadata meta, inout standard_metadata_t control ingress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { @name("cnt1") counter(32w32, CounterType.packets) cnt1; + @name("reg2") register(32w100) reg2; @name(".drop_pkt") action drop_pkt() { mark_to_drop(); + reg2.write(32w0, meta.ipv4_meta); } @name(".hop") action hop(inout bit<8> ttl, bit<9> egress_spec) { ttl = ttl + 8w255; @@ -215,7 +234,7 @@ control DeparserImpl(packet_out packet, in headers hdr) { packet.emit(hdr.vlan_tag_); packet.emit(hdr.ipv6); packet.emit(hdr.icmpv6); - packet.emit(hdr.ipv4); + packet.emit(hdr.ipv4); packet.emit(hdr.udp); packet.emit(hdr.tcp); packet.emit(hdr.icmp); diff --git a/testdata/p4_14_samples_outputs/issue583-frontend.p4 b/testdata/p4_14_samples_outputs/issue583-frontend.p4 index 79dffbebfb9..ab8023688ad 100644 --- a/testdata/p4_14_samples_outputs/issue583-frontend.p4 +++ b/testdata/p4_14_samples_outputs/issue583-frontend.p4 @@ -1,6 +1,21 @@ #include #include +struct ipv4_t { + 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; + bit<32> srcAddr; + bit<32> dstAddr; +} + struct routing_metadata_t { bit<1> drop; } @@ -23,7 +38,7 @@ header icmpv6_t { bit<16> hdrChecksum; } -header ipv4_t { +@name("ipv4_t") header ipv4_t_0 { bit<4> version; bit<4> ihl; bit<8> diffserv; @@ -78,6 +93,8 @@ header vlan_tag_t { } struct metadata { + @name("ipv4_meta") + ipv4_t ipv4_meta; @name("routing_metadata") routing_metadata_t routing_metadata; } @@ -90,7 +107,7 @@ struct headers { @name("icmpv6") icmpv6_t icmpv6; @name("ipv4") - ipv4_t ipv4; + ipv4_t_0 ipv4; @name("ipv6") ipv6_t ipv6; @name("tcp") @@ -122,7 +139,7 @@ parser ParserImpl(packet_in packet, out headers hdr, inout metadata meta, inout transition accept; } @name("parse_ipv4") state parse_ipv4 { - packet.extract(hdr.ipv4); + packet.extract(hdr.ipv4); transition select(hdr.ipv4.fragOffset, hdr.ipv4.protocol) { (13w0, 8w1): parse_icmp; (13w0, 8w6): parse_tcp; @@ -169,8 +186,10 @@ control egress(inout headers hdr, inout metadata meta, inout standard_metadata_t control ingress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { @name("cnt1") counter(32w32, CounterType.packets) cnt1_0; + @name("reg2") register(32w100) reg2_0; @name(".drop_pkt") action drop_pkt_0() { mark_to_drop(); + reg2_0.write(32w0, meta.ipv4_meta); } @name(".hop") action hop_0(inout bit<8> ttl_0, bit<9> egress_spec_0) { ttl_0 = ttl_0 + 8w255; @@ -215,7 +234,7 @@ control DeparserImpl(packet_out packet, in headers hdr) { packet.emit(hdr.vlan_tag_); packet.emit(hdr.ipv6); packet.emit(hdr.icmpv6); - packet.emit(hdr.ipv4); + packet.emit(hdr.ipv4); packet.emit(hdr.udp); packet.emit(hdr.tcp); packet.emit(hdr.icmp); diff --git a/testdata/p4_14_samples_outputs/issue583-midend.p4 b/testdata/p4_14_samples_outputs/issue583-midend.p4 index 4a73dc398e0..8f9eebcb2c7 100644 --- a/testdata/p4_14_samples_outputs/issue583-midend.p4 +++ b/testdata/p4_14_samples_outputs/issue583-midend.p4 @@ -1,6 +1,21 @@ #include #include +struct ipv4_t { + 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; + bit<32> srcAddr; + bit<32> dstAddr; +} + struct routing_metadata_t { bit<1> drop; } @@ -23,7 +38,7 @@ header icmpv6_t { bit<16> hdrChecksum; } -header ipv4_t { +@name("ipv4_t") header ipv4_t_0 { bit<4> version; bit<4> ihl; bit<8> diffserv; @@ -78,6 +93,8 @@ header vlan_tag_t { } struct metadata { + @name("ipv4_meta") + ipv4_t ipv4_meta; @name("routing_metadata") routing_metadata_t routing_metadata; } @@ -90,7 +107,7 @@ struct headers { @name("icmpv6") icmpv6_t icmpv6; @name("ipv4") - ipv4_t ipv4; + ipv4_t_0 ipv4; @name("ipv6") ipv6_t ipv6; @name("tcp") @@ -123,7 +140,7 @@ parser ParserImpl(packet_in packet, out headers hdr, inout metadata meta, inout transition accept; } @name("parse_ipv4") state parse_ipv4 { - packet.extract(hdr.ipv4); + packet.extract(hdr.ipv4); transition select(hdr.ipv4.fragOffset, hdr.ipv4.protocol) { (13w0, 8w1): parse_icmp; (13w0, 8w6): parse_tcp; @@ -181,8 +198,10 @@ control ingress(inout headers hdr, inout metadata meta, inout standard_metadata_ @name("NoAction") action NoAction_3() { } @name("cnt1") counter(32w32, CounterType.packets) cnt1; + @name("reg2") register(32w100) reg2; @name(".drop_pkt") action drop_pkt_0() { mark_to_drop(); + reg2.write(32w0, meta.ipv4_meta); } @name(".hop_ipv4") action hop_ipv4_0(bit<9> egress_spec) { standard_metadata.egress_spec[8:0] = egress_spec[8:0]; @@ -224,7 +243,7 @@ control DeparserImpl(packet_out packet, in headers hdr) { packet.emit(hdr.vlan_tag_); packet.emit(hdr.ipv6); packet.emit(hdr.icmpv6); - packet.emit(hdr.ipv4); + packet.emit(hdr.ipv4); packet.emit(hdr.udp); packet.emit(hdr.tcp); packet.emit(hdr.icmp); diff --git a/testdata/p4_14_samples_outputs/issue583.p4 b/testdata/p4_14_samples_outputs/issue583.p4 index f71d91a0e1d..7a7d12d71f7 100644 --- a/testdata/p4_14_samples_outputs/issue583.p4 +++ b/testdata/p4_14_samples_outputs/issue583.p4 @@ -1,6 +1,21 @@ #include #include +struct ipv4_t { + 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; + bit<32> srcAddr; + bit<32> dstAddr; +} + struct routing_metadata_t { bit<1> drop; } @@ -23,7 +38,7 @@ header icmpv6_t { bit<16> hdrChecksum; } -header ipv4_t { +@name("ipv4_t") header ipv4_t_0 { bit<4> version; bit<4> ihl; bit<8> diffserv; @@ -78,6 +93,8 @@ header vlan_tag_t { } struct metadata { + @name("ipv4_meta") + ipv4_t ipv4_meta; @name("routing_metadata") routing_metadata_t routing_metadata; } @@ -90,7 +107,7 @@ struct headers { @name("icmpv6") icmpv6_t icmpv6; @name("ipv4") - ipv4_t ipv4; + ipv4_t_0 ipv4; @name("ipv6") ipv6_t ipv6; @name("tcp") @@ -169,8 +186,10 @@ control egress(inout headers hdr, inout metadata meta, inout standard_metadata_t control ingress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { @name("cnt1") counter(32w32, CounterType.packets) cnt1; + @name("reg2") register(32w100) reg2; @name(".drop_pkt") action drop_pkt() { mark_to_drop(); + reg2.write((bit<32>)0, meta.ipv4_meta); } @name(".hop") action hop(inout bit<8> ttl, bit<9> egress_spec) { ttl = (bit<8>)(ttl + 8w255); diff --git a/testdata/p4_14_samples_outputs/issue583.p4-stderr b/testdata/p4_14_samples_outputs/issue583.p4-stderr index 8d7a9be669d..e5d40402d9f 100644 --- a/testdata/p4_14_samples_outputs/issue583.p4-stderr +++ b/testdata/p4_14_samples_outputs/issue583.p4-stderr @@ -1,7 +1,7 @@ -../testdata/p4_14_samples/issue583.p4(188): warning: -1: negative value with unsigned type +../testdata/p4_14_samples/issue583.p4(189): warning: -1: negative value with unsigned type add_to_field(ttl, -1); ^ -../testdata/p4_14_samples/issue583.p4(189): warning: 4294967295: value does not fit in 9 bits +../testdata/p4_14_samples/issue583.p4(190): warning: 4294967295: value does not fit in 9 bits modify_field(standard_metadata.egress_spec, egress_spec, 0xFFFFFFFF); ^^^^^^^^^^ warning: The order of headers in deparser is not uniquely determined by parser! From 36d4da86b758844547d6876acb098de123f20d90 Mon Sep 17 00:00:00 2001 From: mbudiu-vmw Date: Wed, 10 May 2017 16:12:16 -0700 Subject: [PATCH 4/4] Fix for issue #583 --- ir/expression.def | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ir/expression.def b/ir/expression.def index 83c9a6a93bd..f036a26aeb2 100644 --- a/ir/expression.def +++ b/ir/expression.def @@ -134,7 +134,7 @@ class Constant : Literal { /// if noWarning is true, no warning is emitted void handleOverflow(bool noWarning); Constant(intmax_t v, unsigned base = 10) : - Literal(new Type_InfInt()), value(v), base(base) {} + Literal(new Type_InfInt()), value((long)v), base(base) {} Constant(mpz_class v, unsigned base = 10) : Literal(new Type_InfInt()), value(v), base(base) {} Constant(Util::SourceInfo si, mpz_class v, unsigned base = 10) :