Fabric.p4 cherry-picks from onos-2.2

Publish fabric.p4 constants with fabric-api artifact

For consumption by third-party apps who wish to operate directly on
fabric.p4 tables and other entities.

(cherry picked from commit 8f6b5cdabf7828f6f7c017f288aad87c7bd0911a)

Backport fabric-tna dbuf support to v1model
(cherry picked from commit 4d1d67fa3abb4d7517e5836fbb82c899acffa951)

Update SPGW p4 namespace to match fabric-tna
(cherry picked from commit 35e4d196eb61104e7f96c62361a100bb454ee1cf)

Change-Id: I3230a508a601180060e1041d4369a54f519658e1
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..00bfd94 100644
--- a/pipelines/fabric/impl/src/main/resources/include/control/spgw.p4
+++ b/pipelines/fabric/impl/src/main/resources/include/control/spgw.p4
@@ -30,156 +30,8 @@
 #define MAX_PDR_COUNTERS  2 * MAX_UES
 #define MAX_FARS          2 * MAX_UES
 
-
-
-control SpgwIngress(inout parsed_headers_t hdr,
-                    inout fabric_metadata_t fabric_md,
-                    inout standard_metadata_t standard_metadata) {
-
-
-
-
-    //=============================//
-    //===== Interface Tables ======//
-    //=============================//
-
-    action set_source_iface(spgw_interface_t src_iface, direction_t direction,
-                            bit<1> skip_spgw) {
-        // Interface type can be access, core, n6_lan, etc (see InterfaceType enum)
-        // If interface is from the control plane, direction can be either up or down
-        fabric_md.spgw.src_iface = src_iface;
-        fabric_md.spgw.direction = direction;
-        fabric_md.spgw.skip_spgw = (_BOOL)skip_spgw;
-    }
-    // TODO: check also that gtpu.msgtype == GTP_GPDU... somewhere
-    table interface_lookup {
-        key = {
-            hdr.ipv4.dst_addr  : lpm    @name("ipv4_dst_addr");  // outermost header
-            hdr.gtpu.isValid() : exact  @name("gtpu_is_valid");
-        }
-        actions = {
-            set_source_iface;
-        }
-        const default_action = set_source_iface(SPGW_IFACE_UNKNOWN, SPGW_DIR_UNKNOWN, 1);
-        size = MAX_INTERFACES;
-    }
-
-
-    //=============================//
-    //===== PDR Tables ======//
-    //=============================//
-
-    action set_pdr_attributes(pdr_ctr_id_t ctr_id,
-                              far_id_t far_id,
-                              bit<1> needs_gtpu_decap) {
-        fabric_md.spgw.pdr_hit = _TRUE;
-        fabric_md.spgw.ctr_id = ctr_id;
-        fabric_md.spgw.far_id = far_id;
-        fabric_md.spgw.needs_gtpu_decap = (_BOOL)needs_gtpu_decap;
-    }
-
-    // These two tables scale well and cover the average case PDR
-    table downlink_pdr_lookup {
-        key = {
-            // only available ipv4 header
-            hdr.ipv4.dst_addr : exact @name("ue_addr");
-        }
-        actions = {
-            set_pdr_attributes;
-        }
-        const default_action = set_pdr_attributes(DEFAULT_PDR_CTR_ID, DEFAULT_FAR_ID, 0);
-        size = MAX_DOWNLINK_PDRS;
-    }
-    table uplink_pdr_lookup {
-        key = {
-            hdr.ipv4.dst_addr           : exact @name("tunnel_ipv4_dst");
-            hdr.gtpu.teid               : exact @name("teid");
-        }
-        actions = {
-            set_pdr_attributes;
-        }
-        const default_action = set_pdr_attributes(DEFAULT_PDR_CTR_ID, DEFAULT_FAR_ID, 0);
-        size = MAX_UPLINK_PDRS;
-    }
-    // This table scales poorly and covers uncommon PDRs
-    table flexible_pdr_lookup {
-        key = {
-            fabric_md.spgw.src_iface    : ternary @name("src_iface");
-            // GTPU
-            hdr.gtpu.isValid()          : ternary @name("gtpu_is_valid");
-            hdr.gtpu.teid               : ternary @name("teid");
-            // SDF
-            // outer 5-tuple
-            hdr.ipv4.src_addr           : ternary @name("ipv4_src");
-            hdr.ipv4.dst_addr           : ternary @name("ipv4_dst");
-            hdr.ipv4.protocol           : ternary @name("ip_proto");
-            fabric_md.l4_sport          : ternary @name("l4_sport");
-            fabric_md.l4_dport          : ternary @name("l4_dport");
-            // inner 5-tuple
-            hdr.inner_ipv4.src_addr     : ternary @name("inner_ipv4_src");
-            hdr.inner_ipv4.dst_addr     : ternary @name("inner_ipv4_dst");
-            hdr.inner_ipv4.protocol     : ternary @name("inner_ip_proto");
-            fabric_md.inner_l4_sport    : ternary @name("inner_l4_sport");
-            fabric_md.inner_l4_dport    : ternary @name("inner_l4_dport");
-        }
-        actions = {
-            set_pdr_attributes;
-        }
-        const default_action = set_pdr_attributes(DEFAULT_PDR_CTR_ID, DEFAULT_FAR_ID, 0);
-    }
-
-    //=============================//
-    //===== FAR Tables ======//
-    //=============================//
-
-    action load_normal_far_attributes(bit<1> drop,
-                                      bit<1> notify_cp) {
-        // general far attributes
-        fabric_md.spgw.far_dropped  = (_BOOL)drop;
-        fabric_md.spgw.notify_spgwc = (_BOOL)notify_cp;
-    }
-    action load_tunnel_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) {
-        // general far attributes
-        fabric_md.spgw.far_dropped  = (_BOOL)drop;
-        fabric_md.spgw.notify_spgwc = (_BOOL)notify_cp;
-        // GTP tunnel attributes
-        fabric_md.spgw.needs_gtpu_encap = _TRUE;
-        fabric_md.spgw.teid = teid;
-        fabric_md.spgw.tunnel_src_port = tunnel_src_port;
-        fabric_md.spgw.tunnel_src_addr = tunnel_src_addr;
-        fabric_md.spgw.tunnel_dst_addr = tunnel_dst_addr;
-        // update metadata for correct routing/hashing
-        fabric_md.ipv4_src_addr = tunnel_src_addr;
-        fabric_md.ipv4_dst_addr = tunnel_dst_addr;
-        fabric_md.l4_sport = tunnel_src_port;
-        fabric_md.l4_dport = UDP_PORT_GTPU;
-    }
-
-    table far_lookup {
-        key = {
-            fabric_md.spgw.far_id : exact @name("far_id");
-        }
-        actions = {
-            load_normal_far_attributes;
-            load_tunnel_far_attributes;
-        }
-        // default is drop and don't notify CP
-        const default_action = load_normal_far_attributes(1, 1);
-        size = MAX_FARS;
-    }
-
-    //=============================//
-    //===== Misc Things ======//
-    //=============================//
-    
-    counter(MAX_PDR_COUNTERS, CounterType.packets_and_bytes) pdr_counter;
-
-
+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
@@ -194,23 +46,27 @@
         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();
@@ -218,9 +74,9 @@
     @hidden
     table decap_gtpu {
         key = {
-            hdr.inner_tcp.isValid()     : exact;
-            hdr.inner_udp.isValid()     : exact;
-            hdr.inner_icmp.isValid()    : exact;
+            hdr.inner_tcp.isValid()  : exact;
+            hdr.inner_udp.isValid()  : exact;
+            hdr.inner_icmp.isValid() : exact;
         }
         actions = {
             decap_inner_tcp;
@@ -234,6 +90,149 @@
             (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;
+
+
+    //=============================//
+    //===== Interface Tables ======//
+    //=============================//
+
+    action load_iface(spgw_interface_t src_iface) {
+        // Interface type can be access, core, from_dbuf (see InterfaceType enum)
+        fabric_md.spgw.src_iface = src_iface;
+        fabric_md.spgw.skip_spgw = _FALSE;
+    }
+    action iface_miss() {
+        fabric_md.spgw.src_iface = SPGW_IFACE_UNKNOWN;
+        fabric_md.spgw.skip_spgw = _TRUE;
+    }
+
+    // TODO: check also that gtpu.msgtype == GTP_GPDU... somewhere
+    table interfaces {
+        key = {
+            hdr.ipv4.dst_addr  : lpm    @name("ipv4_dst_addr");  // outermost header
+            hdr.gtpu.isValid() : exact  @name("gtpu_is_valid");
+        }
+        actions = {
+            load_iface;
+            @defaultonly iface_miss;
+        }
+        const default_action = iface_miss();
+        size = MAX_INTERFACES;
+    }
+
+
+    //=============================//
+    //===== PDR Tables ======//
+    //=============================//
+
+    action load_pdr(pdr_ctr_id_t ctr_id,
+                    far_id_t far_id,
+                    bit<1> needs_gtpu_decap) {
+        fabric_md.spgw.ctr_id = ctr_id;
+        fabric_md.spgw.far_id = far_id;
+        fabric_md.spgw.needs_gtpu_decap = (_BOOL)needs_gtpu_decap;
+    }
+
+    // These two tables scale well and cover the average case PDR
+    table downlink_pdrs {
+        key = {
+            // only available ipv4 header
+            hdr.ipv4.dst_addr : exact @name("ue_addr");
+        }
+        actions = {
+            load_pdr;
+        }
+        size = MAX_DOWNLINK_PDRS;
+    }
+
+    table uplink_pdrs {
+        key = {
+            hdr.ipv4.dst_addr           : exact @name("tunnel_ipv4_dst");
+            hdr.gtpu.teid               : exact @name("teid");
+        }
+        actions = {
+            load_pdr;
+        }
+        size = MAX_UPLINK_PDRS;
+    }
+
+    //=============================//
+    //===== FAR Tables ======//
+    //=============================//
+
+    action load_normal_far(bit<1> drop,
+                           bit<1> notify_cp) {
+        // general far attributes
+        fabric_md.skip_forwarding = (_BOOL)drop;
+        fabric_md.skip_next = (_BOOL)drop;
+        fabric_md.spgw.notify_spgwc = (_BOOL)notify_cp;
+    }
+    action load_tunnel_far(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) {
+        // general far attributes
+        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;
+        fabric_md.spgw.teid = teid;
+        fabric_md.spgw.tunnel_src_port = tunnel_src_port;
+        fabric_md.spgw.tunnel_src_addr = tunnel_src_addr;
+        fabric_md.spgw.tunnel_dst_addr = tunnel_dst_addr;
+        // update metadata for correct routing/hashing
+        fabric_md.ipv4_src_addr = tunnel_src_addr;
+        fabric_md.ipv4_dst_addr = tunnel_dst_addr;
+        fabric_md.l4_sport = tunnel_src_port;
+        fabric_md.l4_dport = UDP_PORT_GTPU;
+    }
+
+    action load_dbuf_far(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(drop, notify_cp, tunnel_src_port,
+                                   tunnel_src_addr, tunnel_dst_addr, teid);
+        fabric_md.spgw.skip_egress_pdr_ctr = _TRUE;
+    }
+
+    table fars {
+        key = {
+            fabric_md.spgw.far_id : exact @name("far_id");
+        }
+        actions = {
+            load_normal_far;
+            load_tunnel_far;
+            load_dbuf_far;
+        }
+        // default is drop and don't notify CP
+        const default_action = load_normal_far(1, 0);
+        size = MAX_FARS;
     }
 
 
@@ -243,50 +242,36 @@
     apply {
 
         // Interfaces
-        interface_lookup.apply();
+        if (interfaces.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_pdrs.apply();
+            } else {
+                downlink_pdrs.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
+            fars.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 +325,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);
+            }
         }
     }
 }