eth_type moved outside ethernet header in fabric.p4

Change-Id: I3ae0813c5e8aba48767d5bb235fbbcfb75954010
(cherry picked from commit 693d76f189c59579837b559975c0ba767335dfc0)
diff --git a/pipelines/fabric/impl/src/main/resources/include/bng.p4 b/pipelines/fabric/impl/src/main/resources/include/bng.p4
index ede0001..5df18d5 100644
--- a/pipelines/fabric/impl/src/main/resources/include/bng.p4
+++ b/pipelines/fabric/impl/src/main/resources/include/bng.p4
@@ -64,8 +64,7 @@
 
     @hidden
     action term_enabled(bit<16> eth_type) {
-        hdr.inner_vlan_tag.eth_type = eth_type;
-        fmeta.last_eth_type = eth_type;
+        hdr.eth_type.value = eth_type;
         hdr.pppoe.setInvalid();
         c_terminated.count(fmeta.bng.line_id);
     }
@@ -266,8 +265,8 @@
 
     @hidden
     action encap() {
-        // Here we add PPPoE and modify the inner_vlan_tag Ethernet Type.
-        hdr.inner_vlan_tag.eth_type = ETHERTYPE_PPPOES;
+        // Here we add PPPoE and modify the Ethernet Type.
+        hdr.eth_type.value = ETHERTYPE_PPPOES;
         hdr.pppoe.setValid();
         hdr.pppoe.version = 4w1;
         hdr.pppoe.type_id = 4w1;
@@ -327,11 +326,11 @@
                 c_tag : exact @name("c_tag");
             }
              actions = {
-                @defaultonly nop;
                 set_line;
             }
             size = BNG_MAX_SUBSC;
-            const default_action = nop;
+            // By default set the line ID to 0
+            const default_action = set_line(0);
         }
 
         apply {
diff --git a/pipelines/fabric/impl/src/main/resources/include/control/acl.p4 b/pipelines/fabric/impl/src/main/resources/include/control/acl.p4
index 4c2df67..26267e9 100644
--- a/pipelines/fabric/impl/src/main/resources/include/control/acl.p4
+++ b/pipelines/fabric/impl/src/main/resources/include/control/acl.p4
@@ -66,7 +66,7 @@
             hdr.ethernet.dst_addr: ternary @name("eth_src"); // 48
             hdr.ethernet.src_addr: ternary @name("eth_dst"); // 48
             hdr.vlan_tag.vlan_id: ternary @name("vlan_id"); // 12
-            fabric_metadata.last_eth_type: ternary @name("eth_type"); //16
+            hdr.eth_type.value: ternary @name("eth_type"); //16
             hdr.ipv4.src_addr: ternary @name("ipv4_src"); // 32
             hdr.ipv4.dst_addr: ternary @name("ipv4_dst"); // 32
             hdr.icmp.icmp_type: ternary @name("icmp_type"); // 8
diff --git a/pipelines/fabric/impl/src/main/resources/include/control/filtering.p4 b/pipelines/fabric/impl/src/main/resources/include/control/filtering.p4
index a3213e9..17dba78 100644
--- a/pipelines/fabric/impl/src/main/resources/include/control/filtering.p4
+++ b/pipelines/fabric/impl/src/main/resources/include/control/filtering.p4
@@ -91,9 +91,8 @@
         key = {
             standard_metadata.ingress_port : exact @name("ig_port");
             hdr.ethernet.dst_addr          : ternary @name("eth_dst");
-            fabric_metadata.is_ipv4        : exact @name("is_ipv4");
-            fabric_metadata.is_ipv6        : exact @name("is_ipv6");
-            fabric_metadata.is_mpls        : exact @name("is_mpls");
+            hdr.eth_type.value             : ternary @name("eth_type");
+            fabric_metadata.ip_eth_type    : exact @name("ip_eth_type");
         }
         actions = {
             set_forwarding_type;
@@ -126,22 +125,6 @@
             fabric_metadata.mpls_ttl = DEFAULT_MPLS_TTL + 1;
         }
 
-        // Set last_eth_type checking the validity of the L2.5 headers
-        if (hdr.mpls.isValid()) {
-            fabric_metadata.last_eth_type = ETHERTYPE_MPLS;
-        } else {
-            if (hdr.vlan_tag.isValid()) {
-#if defined(WITH_XCONNECT) || defined(WITH_BNG) || defined(WITH_DOUBLE_VLAN_TERMINATION)
-                if(hdr.inner_vlan_tag.isValid()) {
-                    fabric_metadata.last_eth_type = hdr.inner_vlan_tag.eth_type;
-                } else
-#endif //  WITH_XCONNECT || WITH_BNG || WITH_DOUBLE_VLAN_TERMINATION
-                    fabric_metadata.last_eth_type = hdr.vlan_tag.eth_type;
-            } else {
-                fabric_metadata.last_eth_type = hdr.ethernet.eth_type;
-            }
-        }
-
         ingress_port_vlan.apply();
         fwd_classifier.apply();
     }
diff --git a/pipelines/fabric/impl/src/main/resources/include/control/forwarding.p4 b/pipelines/fabric/impl/src/main/resources/include/control/forwarding.p4
index 89544ea..7348c59 100644
--- a/pipelines/fabric/impl/src/main/resources/include/control/forwarding.p4
+++ b/pipelines/fabric/impl/src/main/resources/include/control/forwarding.p4
@@ -84,15 +84,22 @@
     /*
      * IPv4 Routing Table.
      */
+#ifdef WTIH_DEBUG
     direct_counter(CounterType.packets_and_bytes) routing_v4_counter;
+#endif // WITH_DEBUG
 
     action set_next_id_routing_v4(next_id_t next_id) {
         set_next_id(next_id);
+#ifdef WTIH_DEBUG
         routing_v4_counter.count();
+#endif // WITH_DEBUG
     }
 
     action nop_routing_v4() {
+        // no-op
+#ifdef WTIH_DEBUG
         routing_v4_counter.count();
+#endif // WITH_DEBUG
     }
 
     #ifdef _ROUTING_V4_TABLE_ANNOT
@@ -108,7 +115,9 @@
             @defaultonly nop;
         }
         const default_action = nop();
+#ifdef WTIH_DEBUG
         counters = routing_v4_counter;
+#endif // WITH_DEBUG
         size = ROUTING_V4_TABLE_SIZE;
     }
 
diff --git a/pipelines/fabric/impl/src/main/resources/include/control/next.p4 b/pipelines/fabric/impl/src/main/resources/include/control/next.p4
index e7f6e44..2ea719a 100644
--- a/pipelines/fabric/impl/src/main/resources/include/control/next.p4
+++ b/pipelines/fabric/impl/src/main/resources/include/control/next.p4
@@ -104,7 +104,6 @@
 
     action output_xconnect(port_num_t port_num) {
         output(port_num);
-        fabric_metadata.last_eth_type = ETHERTYPE_VLAN;
         xconnect_counter.count();
     }
 
@@ -174,6 +173,9 @@
      * Execute an action profile selector based on next id.
      */
     @max_group_size(HASHED_SELECTOR_MAX_GROUP_SIZE)
+    #ifdef _CUSTOM_HASHED_SELECTOR_ANNOTATION
+        _CUSTOM_HASHED_SELECTOR_ANNOTATION
+    #endif
     action_selector(HashAlgorithm.crc16, HASHED_ACT_PROFILE_SIZE, 32w16) hashed_selector;
     direct_counter(CounterType.packets_and_bytes) hashed_counter;
 
@@ -263,7 +265,7 @@
     action pop_mpls_if_present() {
         hdr.mpls.setInvalid();
         // Assuming there's an IP header after the MPLS one.
-        fabric_metadata.last_eth_type = fabric_metadata.ip_eth_type;
+        hdr.eth_type.value = fabric_metadata.ip_eth_type;
     }
 
     @hidden
@@ -273,7 +275,7 @@
         hdr.mpls.tc = 3w0;
         hdr.mpls.bos = 1w1; // BOS = TRUE
         hdr.mpls.ttl = fabric_metadata.mpls_ttl; // Decrement after push.
-        fabric_metadata.last_eth_type = ETHERTYPE_MPLS;
+        hdr.eth_type.value = ETHERTYPE_MPLS;
     }
 
     @hidden
@@ -283,23 +285,20 @@
         hdr.vlan_tag.setValid();
         hdr.vlan_tag.cfi = fabric_metadata.vlan_cfi;
         hdr.vlan_tag.pri = fabric_metadata.vlan_pri;
-        hdr.vlan_tag.eth_type = fabric_metadata.last_eth_type;
+        hdr.vlan_tag.eth_type = ETHERTYPE_VLAN;
         hdr.vlan_tag.vlan_id = fabric_metadata.vlan_id;
-        hdr.ethernet.eth_type = ETHERTYPE_VLAN;
     }
 
 #ifdef WITH_DOUBLE_VLAN_TERMINATION
     @hidden
     action push_inner_vlan() {
-        // Then push inner VLAN TAG, rewriting correclty the outer vlan eth_type
-        // and the ethernet eth_type
+        // Push inner VLAN TAG, rewriting correclty the outer vlan eth_type
         hdr.inner_vlan_tag.setValid();
         hdr.inner_vlan_tag.cfi = fabric_metadata.inner_vlan_cfi;
         hdr.inner_vlan_tag.pri = fabric_metadata.inner_vlan_pri;
         hdr.inner_vlan_tag.vlan_id = fabric_metadata.inner_vlan_id;
-        hdr.inner_vlan_tag.eth_type = fabric_metadata.last_eth_type;
+        hdr.inner_vlan_tag.eth_type = ETHERTYPE_VLAN;
         hdr.vlan_tag.eth_type = ETHERTYPE_VLAN;
-        hdr.ethernet.eth_type = ETHERTYPE_QINQ;
     }
 #endif // WITH_DOUBLE_VLAN_TERMINATION
 
@@ -310,7 +309,6 @@
     direct_counter(CounterType.packets_and_bytes) egress_vlan_counter;
 
     action pop_vlan() {
-        hdr.ethernet.eth_type = fabric_metadata.last_eth_type;
         hdr.vlan_tag.setInvalid();
         egress_vlan_counter.count();
     }
diff --git a/pipelines/fabric/impl/src/main/resources/include/define.p4 b/pipelines/fabric/impl/src/main/resources/include/define.p4
index 8058416..92aa182 100644
--- a/pipelines/fabric/impl/src/main/resources/include/define.p4
+++ b/pipelines/fabric/impl/src/main/resources/include/define.p4
@@ -23,6 +23,10 @@
 #define WITH_INT
 #endif
 
+#if defined(WITH_BNG)
+#define WITH_DOUBLE_VLAN_TERMINATION
+#endif
+
 #ifndef WITHOUT_XCONNECT
 #define WITH_XCONNECT
 #endif
diff --git a/pipelines/fabric/impl/src/main/resources/include/header.p4 b/pipelines/fabric/impl/src/main/resources/include/header.p4
index 09df685..b87237b 100644
--- a/pipelines/fabric/impl/src/main/resources/include/header.p4
+++ b/pipelines/fabric/impl/src/main/resources/include/header.p4
@@ -36,14 +36,19 @@
 header ethernet_t {
     mac_addr_t dst_addr;
     mac_addr_t src_addr;
-    bit<16> eth_type;
+}
+
+// NOTE: splitting the eth_type from the ethernet header helps to match on
+//  the actual eth_type without checking validity bit of the VLAN tags.
+header eth_type_t {
+    bit<16> value;
 }
 
 header vlan_tag_t {
+    bit<16> eth_type;
     bit<3> pri;
     bit<1> cfi;
     vlan_id_t vlan_id;
-    bit<16> eth_type;
 }
 
 header mpls_t {
@@ -166,10 +171,6 @@
 
 //Custom metadata definition
 struct fabric_metadata_t {
-    bit<16>       last_eth_type;
-    _BOOL         is_ipv4;
-    _BOOL         is_ipv6;
-    _BOOL         is_mpls;
     bit<16>       ip_eth_type;
     vlan_id_t     vlan_id;
     bit<3>        vlan_pri;
@@ -205,9 +206,10 @@
 struct parsed_headers_t {
     ethernet_t ethernet;
     vlan_tag_t vlan_tag;
-#if defined(WITH_XCONNECT) || defined(WITH_BNG) || defined(WITH_DOUBLE_VLAN_TERMINATION)
+#if defined(WITH_XCONNECT) || defined(WITH_DOUBLE_VLAN_TERMINATION)
     vlan_tag_t inner_vlan_tag;
-#endif // WITH_XCONNECT || WITH_BNG || WITH_DOUBLE_VLAN_TERMINATION
+#endif // WITH_XCONNECT || WITH_DOUBLE_VLAN_TERMINATION
+    eth_type_t eth_type;
 #ifdef WITH_BNG
     pppoe_t pppoe;
 #endif // WITH_BNG
@@ -231,6 +233,7 @@
 #ifdef WITH_INT_SINK
     // INT Report encap
     ethernet_t report_ethernet;
+    eth_type_t report_eth_type;
     ipv4_t report_ipv4;
     udp_t report_udp;
     // INT Report header (support only fixed)
diff --git a/pipelines/fabric/impl/src/main/resources/include/int/int_report.p4 b/pipelines/fabric/impl/src/main/resources/include/int/int_report.p4
index 8c48ba2..aaec185 100644
--- a/pipelines/fabric/impl/src/main/resources/include/int/int_report.p4
+++ b/pipelines/fabric/impl/src/main/resources/include/int/int_report.p4
@@ -50,7 +50,7 @@
         hdr.report_ethernet.setValid();
         hdr.report_ethernet.dst_addr = mon_mac;
         hdr.report_ethernet.src_addr = src_mac;
-        hdr.report_ethernet.eth_type = ETHERTYPE_IPV4;
+        hdr.report_eth_type.value = ETHERTYPE_IPV4;
 
         //Report IPV4 Header
         hdr.report_ipv4.setValid();
diff --git a/pipelines/fabric/impl/src/main/resources/include/parser.p4 b/pipelines/fabric/impl/src/main/resources/include/parser.p4
index 3fadebf..ee6b13c 100644
--- a/pipelines/fabric/impl/src/main/resources/include/parser.p4
+++ b/pipelines/fabric/impl/src/main/resources/include/parser.p4
@@ -40,45 +40,40 @@
 
     state parse_ethernet {
         packet.extract(hdr.ethernet);
-        fabric_metadata.last_eth_type = hdr.ethernet.eth_type;
         fabric_metadata.vlan_id = DEFAULT_VLAN_ID;
-        transition select(hdr.ethernet.eth_type){
+        transition select(packet.lookahead<bit<16>>()){
             ETHERTYPE_QINQ: parse_vlan_tag;
             ETHERTYPE_QINQ_NON_STD: parse_vlan_tag;
             ETHERTYPE_VLAN: parse_vlan_tag;
-            ETHERTYPE_MPLS: parse_mpls;
-            ETHERTYPE_IPV4: pre_parse_ipv4;
-#ifdef WITH_IPV6
-            ETHERTYPE_IPV6: pre_parse_ipv6;
-#endif // WITH_IPV6
-            default: accept;
+            default: parse_eth_type;
         }
     }
 
     state parse_vlan_tag {
         packet.extract(hdr.vlan_tag);
-        transition select(hdr.vlan_tag.eth_type){
-            ETHERTYPE_IPV4: pre_parse_ipv4;
-#ifdef WITH_IPV6
-            ETHERTYPE_IPV6: pre_parse_ipv6;
-#endif // WITH_IPV6
-            ETHERTYPE_MPLS: parse_mpls;
-#if defined(WITH_XCONNECT) || defined(WITH_BNG) || defined(WITH_DOUBLE_VLAN_TERMINATION)
+        transition select(packet.lookahead<bit<16>>()){
+#if defined(WITH_XCONNECT) || defined(WITH_DOUBLE_VLAN_TERMINATION)
             ETHERTYPE_VLAN: parse_inner_vlan_tag;
-#endif // WITH_XCONNECT
-            default: accept;
+#endif // WITH_XCONNECT || WITH_DOUBLE_VLAN_TERMINATION
+            default: parse_eth_type;
         }
     }
 
-#if defined(WITH_XCONNECT) || defined(WITH_BNG) || defined(WITH_DOUBLE_VLAN_TERMINATION)
+#if defined(WITH_XCONNECT) || defined(WITH_DOUBLE_VLAN_TERMINATION)
     state parse_inner_vlan_tag {
         packet.extract(hdr.inner_vlan_tag);
-        transition select(hdr.inner_vlan_tag.eth_type){
-            ETHERTYPE_IPV4: pre_parse_ipv4;
-#ifdef WITH_IPV6
-            ETHERTYPE_IPV6: pre_parse_ipv6;
-#endif // WITH_IPV6
+        transition parse_eth_type;
+    }
+#endif // WITH_XCONNECT || WITH_DOUBLE_VLAN_TERMINATION
+
+    state parse_eth_type {
+        packet.extract(hdr.eth_type);
+        transition select(hdr.eth_type.value) {
             ETHERTYPE_MPLS: parse_mpls;
+            ETHERTYPE_IPV4: parse_ipv4;
+#ifdef WITH_IPV6
+            ETHERTYPE_IPV6: parse_ipv6;
+#endif // WITH_IPV6
 #ifdef WITH_BNG
             ETHERTYPE_PPPOED: parse_pppoe;
             ETHERTYPE_PPPOES: parse_pppoe;
@@ -86,16 +81,15 @@
             default: accept;
         }
     }
-#endif // WITH_XCONNECT || WITH_BNG || WITH_DOUBLE_VLAN_TERMINATION
 
 #ifdef WITH_BNG
     state parse_pppoe {
         packet.extract(hdr.pppoe);
         transition select(hdr.pppoe.protocol) {
             PPPOE_PROTOCOL_MPLS: parse_mpls;
-            PPPOE_PROTOCOL_IP4: pre_parse_ipv4;
+            PPPOE_PROTOCOL_IP4: parse_ipv4;
 #ifdef WITH_IPV6
-            PPPOE_PROTOCOL_IP6: pre_parse_ipv6;
+            PPPOE_PROTOCOL_IP6: parse_ipv6;
 #endif // WITH_IPV6
             default: accept;
         }
@@ -104,7 +98,6 @@
 
     state parse_mpls {
         packet.extract(hdr.mpls);
-        fabric_metadata.is_mpls = _TRUE;
         fabric_metadata.mpls_label = hdr.mpls.label;
         fabric_metadata.mpls_ttl = hdr.mpls.ttl;
         // There is only one MPLS label for this fabric.
@@ -122,11 +115,6 @@
         }
     }
 
-    // Intermediate state to set is_ipv4
-    state pre_parse_ipv4 {
-        fabric_metadata.is_ipv4 = _TRUE;
-        transition parse_ipv4;
-    }
     state parse_ipv4 {
         packet.extract(hdr.ipv4);
         fabric_metadata.ip_proto = hdr.ipv4.protocol;
@@ -142,11 +130,6 @@
     }
 
 #ifdef WITH_IPV6
-    // Intermediate state to set is_ipv6
-    state pre_parse_ipv6 {
-        fabric_metadata.is_ipv6 = _TRUE;
-        transition parse_ipv6;
-    }
     state parse_ipv6 {
         packet.extract(hdr.ipv6);
         fabric_metadata.ip_proto = hdr.ipv6.next_hdr;
@@ -279,15 +262,17 @@
         packet.emit(hdr.packet_in);
 #ifdef WITH_INT_SINK
         packet.emit(hdr.report_ethernet);
+        packet.emit(hdr.report_eth_type);
         packet.emit(hdr.report_ipv4);
         packet.emit(hdr.report_udp);
         packet.emit(hdr.report_fixed_header);
 #endif // WITH_INT_SINK
         packet.emit(hdr.ethernet);
         packet.emit(hdr.vlan_tag);
-#if defined(WITH_XCONNECT) || defined(WITH_BNG) || defined(WITH_DOUBLE_VLAN_TERMINATION)
+#if defined(WITH_XCONNECT) || defined(WITH_DOUBLE_VLAN_TERMINATION)
         packet.emit(hdr.inner_vlan_tag);
-#endif // WITH_XCONNECT || WITH_BNG || WITH_DOUBLE_VLAN_TERMINATION
+#endif // WITH_XCONNECT || WITH_DOUBLE_VLAN_TERMINATION
+        packet.emit(hdr.eth_type);
 #ifdef WITH_BNG
         packet.emit(hdr.pppoe);
 #endif // WITH_BNG
@@ -325,4 +310,4 @@
     }
 }
 
-#endif
+#endif
\ No newline at end of file