Backport fabric-tna dbuf support to v1model

Change-Id: I6a957d2474e94e1dcb7c3f598033ff243754372f
diff --git a/pipelines/fabric/impl/src/main/resources/include/control/spgw.p4 b/pipelines/fabric/impl/src/main/resources/include/control/spgw.p4
index 34a88b8..10c4467 100644
--- a/pipelines/fabric/impl/src/main/resources/include/control/spgw.p4
+++ b/pipelines/fabric/impl/src/main/resources/include/control/spgw.p4
@@ -30,13 +30,86 @@
 #define MAX_PDR_COUNTERS  2 * MAX_UES
 #define MAX_FARS          2 * MAX_UES
 
+control DecapGtpu(inout parsed_headers_t hdr,
+                  inout fabric_metadata_t fabric_md) {
+    @hidden
+    action decap_inner_common() {
+        // Correct parser-set metadata to use the inner header values
+        fabric_md.ip_eth_type   = ETHERTYPE_IPV4;
+        fabric_md.ip_proto      = hdr.inner_ipv4.protocol;
+        fabric_md.ipv4_src_addr = hdr.inner_ipv4.src_addr;
+        fabric_md.ipv4_dst_addr = hdr.inner_ipv4.dst_addr;
+        fabric_md.l4_sport      = fabric_md.inner_l4_sport;
+        fabric_md.l4_dport      = fabric_md.inner_l4_dport;
+        // Move GTPU and inner L3 headers out
+        hdr.ipv4 = hdr.inner_ipv4;
+        hdr.inner_ipv4.setInvalid();
+        hdr.gtpu.setInvalid();
+    }
+    @hidden
+    action decap_inner_tcp() {
+        decap_inner_common();
+        hdr.udp.setInvalid();
+        hdr.tcp = hdr.inner_tcp;
+        hdr.inner_tcp.setInvalid();
+    }
+    @hidden
+    action decap_inner_udp() {
+        decap_inner_common();
+        hdr.udp = hdr.inner_udp;
+        hdr.inner_udp.setInvalid();
+    }
+    @hidden
+    action decap_inner_icmp() {
+        decap_inner_common();
+        hdr.udp.setInvalid();
+        hdr.icmp = hdr.inner_icmp;
+        hdr.inner_icmp.setInvalid();
+    }
+    @hidden
+    action decap_inner_unknown() {
+        decap_inner_common();
+        hdr.udp.setInvalid();
+    }
+    @hidden
+    table decap_gtpu {
+        key = {
+            hdr.inner_tcp.isValid()  : exact;
+            hdr.inner_udp.isValid()  : exact;
+            hdr.inner_icmp.isValid() : exact;
+        }
+        actions = {
+            decap_inner_tcp;
+            decap_inner_udp;
+            decap_inner_icmp;
+            decap_inner_unknown;
+        }
+        const default_action = decap_inner_unknown;
+        const entries = {
+            (true,  false, false) : decap_inner_tcp();
+            (false, true,  false) : decap_inner_udp();
+            (false, false, true)  : decap_inner_icmp();
+        }
+        size = 4;
+    }
+    apply {
+        decap_gtpu.apply();
+    }
+}
 
 
 control SpgwIngress(inout parsed_headers_t hdr,
                     inout fabric_metadata_t fabric_md,
                     inout standard_metadata_t standard_metadata) {
 
+    //=============================//
+    //===== Misc Things ======//
+    //=============================//
+    
+    counter(MAX_PDR_COUNTERS, CounterType.packets_and_bytes) pdr_counter;
 
+    DecapGtpu() decap_gtpu_from_dbuf;
+    DecapGtpu() decap_gtpu;
 
 
     //=============================//
@@ -135,7 +208,8 @@
     action load_normal_far_attributes(bit<1> drop,
                                       bit<1> notify_cp) {
         // general far attributes
-        fabric_md.spgw.far_dropped  = (_BOOL)drop;
+        fabric_md.skip_forwarding = (_BOOL)drop;
+        fabric_md.skip_next = (_BOOL)drop;
         fabric_md.spgw.notify_spgwc = (_BOOL)notify_cp;
     }
     action load_tunnel_far_attributes(bit<1>      drop,
@@ -145,7 +219,8 @@
                                       bit<32>   tunnel_dst_addr,
                                       teid_t    teid) {
         // general far attributes
-        fabric_md.spgw.far_dropped  = (_BOOL)drop;
+        fabric_md.skip_forwarding = (_BOOL)drop;
+        fabric_md.skip_next = (_BOOL)drop;
         fabric_md.spgw.notify_spgwc = (_BOOL)notify_cp;
         // GTP tunnel attributes
         fabric_md.spgw.needs_gtpu_encap = _TRUE;
@@ -160,6 +235,17 @@
         fabric_md.l4_dport = UDP_PORT_GTPU;
     }
 
+    action load_dbuf_far_attributes(bit<1>    drop,
+                                    bit<1>    notify_cp,
+                                    bit<16>   tunnel_src_port,
+                                    bit<32>   tunnel_src_addr,
+                                    bit<32>   tunnel_dst_addr,
+                                    teid_t    teid) {
+        load_tunnel_far_attributes(drop, notify_cp, tunnel_src_port,
+                                   tunnel_src_addr, tunnel_dst_addr, teid);
+        fabric_md.spgw.skip_egress_pdr_ctr = _TRUE;
+    }
+
     table far_lookup {
         key = {
             fabric_md.spgw.far_id : exact @name("far_id");
@@ -167,74 +253,13 @@
         actions = {
             load_normal_far_attributes;
             load_tunnel_far_attributes;
+            load_dbuf_far_attributes;
         }
         // default is drop and don't notify CP
-        const default_action = load_normal_far_attributes(1, 1);
+        const default_action = load_normal_far_attributes(1, 0);
         size = MAX_FARS;
     }
 
-    //=============================//
-    //===== Misc Things ======//
-    //=============================//
-    
-    counter(MAX_PDR_COUNTERS, CounterType.packets_and_bytes) pdr_counter;
-
-
-    @hidden
-    action decap_inner_common() {
-        // Correct parser-set metadata to use the inner header values
-        fabric_md.ip_eth_type   = ETHERTYPE_IPV4;
-        fabric_md.ip_proto      = hdr.inner_ipv4.protocol;
-        fabric_md.ipv4_src_addr = hdr.inner_ipv4.src_addr;
-        fabric_md.ipv4_dst_addr = hdr.inner_ipv4.dst_addr;
-        fabric_md.l4_sport      = fabric_md.inner_l4_sport;
-        fabric_md.l4_dport      = fabric_md.inner_l4_dport;
-        // Move GTPU and inner L3 headers out
-        hdr.ipv4 = hdr.inner_ipv4;
-        hdr.inner_ipv4.setInvalid();
-        hdr.gtpu.setInvalid();
-    }
-    action decap_inner_tcp() {
-        decap_inner_common();
-        hdr.udp.setInvalid();
-        hdr.tcp = hdr.inner_tcp;
-        hdr.inner_tcp.setInvalid();
-    }
-    action decap_inner_udp() {
-        decap_inner_common();
-        hdr.udp = hdr.inner_udp;
-        hdr.inner_udp.setInvalid();
-    }
-    action decap_inner_icmp() {
-        decap_inner_common();
-        hdr.udp.setInvalid();
-        hdr.icmp = hdr.inner_icmp;
-        hdr.inner_icmp.setInvalid();
-    }
-    action decap_inner_unknown() {
-        decap_inner_common();
-        hdr.udp.setInvalid();
-    }
-    @hidden
-    table decap_gtpu {
-        key = {
-            hdr.inner_tcp.isValid()     : exact;
-            hdr.inner_udp.isValid()     : exact;
-            hdr.inner_icmp.isValid()    : exact;
-        }
-        actions = {
-            decap_inner_tcp;
-            decap_inner_udp;
-            decap_inner_icmp;
-            decap_inner_unknown;
-        }
-        const default_action = decap_inner_unknown;
-        const entries = {
-            (true,  false, false) : decap_inner_tcp();
-            (false, true,  false) : decap_inner_udp();
-            (false, false, true)  : decap_inner_icmp();
-        }
-    }
 
 
     //=============================//
@@ -243,50 +268,36 @@
     apply {
 
         // Interfaces
-        interface_lookup.apply();
+        if (interface_lookup.apply().hit) {
+            if (fabric_md.spgw.src_iface == SPGW_IFACE_FROM_DBUF) {
+                decap_gtpu_from_dbuf.apply(hdr, fabric_md);
+            }
+            // PDRs
+            if (hdr.gtpu.isValid()) {
+                uplink_pdr_lookup.apply();
+            } else {
+                downlink_pdr_lookup.apply();
+            }
+            if (fabric_md.spgw.src_iface != SPGW_IFACE_FROM_DBUF) {
+                pdr_counter.count(fabric_md.spgw.ctr_id);
+            }
 
-        // If interface table missed, or the interface skips PDRs/FARs (TODO: is that a thing?)
-        if (fabric_md.spgw.skip_spgw == _TRUE) return;
+            // GTPU Decapsulate
+            if (fabric_md.spgw.needs_gtpu_decap == _TRUE) { 
+                decap_gtpu.apply(hdr, fabric_md);
+            }
 
-        // PDRs
-        // Currently only best-case PDR tables to make v1model-to-tofino compiler happy
-        if (hdr.gtpu.isValid()) {
-            uplink_pdr_lookup.apply();
-        } else {
-            downlink_pdr_lookup.apply();
+            // FARs
+            // Load FAR info
+            far_lookup.apply();
+
+            // Nothing to be done immediately for forwarding or encapsulation.
+            // Forwarding is done by other parts of fabric.p4, and
+            // encapsulation is done in the egress
+
+            // Needed for correct GTPU encapsulation in egress
+            fabric_md.spgw.ipv4_len = hdr.ipv4.total_len;
         }
-        // Inefficient PDR table if efficient tables missed
-        // Removed to make v1model-to-tofino compiler happy. Not removed in TNA port
-        //if (fabric_md.spgw.pdr_hit == _FALSE) {
-        //    flexible_pdr_lookup.apply();
-        //}
-        pdr_counter.count(fabric_md.spgw.ctr_id);
-
-        // GTPU Decapsulate
-        if (fabric_md.spgw.needs_gtpu_decap == _TRUE) { 
-            decap_gtpu.apply();
-        }
-
-        // FARs
-        // Load FAR info
-        far_lookup.apply();
-
-        if (fabric_md.spgw.notify_spgwc == _TRUE) {
-            // TODO: cpu clone action here
-        }
-        if (fabric_md.spgw.far_dropped == _TRUE) {
-            // Do dropping in the same way as fabric's filtering.p4, so we can traverse
-            // the ACL table, which is good for cases like DHCP.
-            fabric_md.skip_forwarding = _TRUE;
-            fabric_md.skip_next = _TRUE;
-        }
-
-        // Nothing to be done immediately for forwarding or encapsulation.
-        // Forwarding is done by other parts of fabric.p4, and
-        // encapsulation is done in the egress
-
-        // Needed for correct GTPU encapsulation in egress
-        fabric_md.spgw.ipv4_len = hdr.ipv4.total_len;
     }
 }
 
@@ -340,11 +351,13 @@
     }
 
     apply {
-        if (fabric_md.spgw.skip_spgw == _TRUE) return;
-        pdr_counter.count(fabric_md.spgw.ctr_id);
-
-        if (fabric_md.spgw.needs_gtpu_encap == _TRUE) {
-            gtpu_encap();
+        if (fabric_md.spgw.skip_spgw == _FALSE) {
+            if (fabric_md.spgw.needs_gtpu_encap == _TRUE) {
+                gtpu_encap();
+            }
+            if (fabric_md.spgw.skip_egress_pdr_ctr == _FALSE) {
+                pdr_counter.count(fabric_md.spgw.ctr_id);
+            }
         }
     }
 }