Test P4 program and data for SPGW

Change-Id: I188ca9014b52eb1d900e92da9ae632bc4ce1bdaf
diff --git a/pipelines/fabric/src/test/p4/spgw/.gitignore b/pipelines/fabric/src/test/p4/spgw/.gitignore
new file mode 100644
index 0000000..43474cc
--- /dev/null
+++ b/pipelines/fabric/src/test/p4/spgw/.gitignore
@@ -0,0 +1,2 @@
+main.json
+main.p4info
diff --git a/pipelines/fabric/src/test/p4/spgw/Makefile b/pipelines/fabric/src/test/p4/spgw/Makefile
new file mode 100644
index 0000000..6b1e705
--- /dev/null
+++ b/pipelines/fabric/src/test/p4/spgw/Makefile
@@ -0,0 +1,5 @@
+all:
+	p4c-bm2-ss -o main.json \
+        -DWITH_SPGW -I ../../../main/resources/ \
+        --p4runtime-file main.p4info \
+        --p4runtime-format text main.p4
diff --git a/pipelines/fabric/src/test/p4/spgw/downlink-post.pcap b/pipelines/fabric/src/test/p4/spgw/downlink-post.pcap
new file mode 100644
index 0000000..a3b76a7d
--- /dev/null
+++ b/pipelines/fabric/src/test/p4/spgw/downlink-post.pcap
Binary files differ
diff --git a/pipelines/fabric/src/test/p4/spgw/downlink-pre.pcap b/pipelines/fabric/src/test/p4/spgw/downlink-pre.pcap
new file mode 100644
index 0000000..465ab03
--- /dev/null
+++ b/pipelines/fabric/src/test/p4/spgw/downlink-pre.pcap
Binary files differ
diff --git a/pipelines/fabric/src/test/p4/spgw/entries.json b/pipelines/fabric/src/test/p4/spgw/entries.json
new file mode 100644
index 0000000..ea3d201
--- /dev/null
+++ b/pipelines/fabric/src/test/p4/spgw/entries.json
@@ -0,0 +1,37 @@
+{
+  "spgw": {
+    "addr": "localhost:5051",
+    "flows": [
+      {
+        "table_name": "spgw_ingress.ue_filter_table",
+        "match_fields": {
+          "ipv4.dst_addr": ["16.255.255.252", 32]
+        },
+        "action_name": "NoAction",
+        "action_params": {
+        }
+      },
+      {
+        "table_name": "spgw_ingress.s1u_filter_table",
+        "match_fields": {
+          "spgw_meta.s1u_sgw_addr": "192.168.102.13"
+        },
+        "action_name": "NoAction",
+        "action_params": {
+        }
+      },
+      {
+        "table_name": "spgw_ingress.dl_sess_lookup",
+        "match_fields": {
+          "ipv4.dst_addr": "16.255.255.252"
+        },
+        "action_name": "spgw_ingress.set_dl_sess_info",
+        "action_params": {
+          "teid": 1,
+          "s1u_enb_addr": "192.168.102.11",
+          "s1u_sgw_addr": "192.168.102.13"
+        }
+      }
+    ]
+  }
+}
diff --git a/pipelines/fabric/src/test/p4/spgw/main.p4 b/pipelines/fabric/src/test/p4/spgw/main.p4
new file mode 100644
index 0000000..916412c
--- /dev/null
+++ b/pipelines/fabric/src/test/p4/spgw/main.p4
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#define S1U_PORT 1
+#define SGI_PORT 2
+#define AS_MAC_ADDR  0x52540029c9b7
+#define S1U_MAC_ADDR 0xc242592d3a84
+#define SGI_MAC_ADDR 0x3ac1e253e150
+#define ENB_MAC_ADDR 0x525400057b59
+
+#include <core.p4>
+#include <v1model.p4>
+
+#include "include/define.p4"
+#include "include/header.p4"
+#include "include/checksum.p4"
+#include "include/parser.p4"
+#include "include/control/packetio.p4"
+
+#include "include/spgw.p4"
+
+control table0_control(inout parsed_headers_t hdr,
+                       inout fabric_metadata_t fabric_metadata,
+                       inout standard_metadata_t standard_metadata) {
+
+    action send_to_cpu() {
+        standard_metadata.egress_spec = CPU_PORT;
+        exit;
+    }
+
+    table table0 {
+        key = {
+            standard_metadata.ingress_port : ternary;
+            hdr.ethernet.src_addr          : ternary;
+            hdr.ethernet.dst_addr          : ternary;
+            hdr.ethernet.ether_type        : ternary;
+            hdr.ipv4.src_addr              : ternary;
+            hdr.ipv4.dst_addr              : ternary;
+            hdr.ipv4.protocol              : ternary;
+            fabric_metadata.l4_src_port     : ternary;
+            fabric_metadata.l4_dst_port     : ternary;
+        }
+        actions = {
+            send_to_cpu();
+            NoAction();
+        }
+        const default_action = NoAction();
+    }
+
+    apply {
+        table0.apply();
+    }
+}
+
+//------------------------------------------------------------------------------
+// INGRESS PIPELINE
+//------------------------------------------------------------------------------
+
+control ingress_impl(inout parsed_headers_t hdr,
+                     inout fabric_metadata_t fabric_metadata,
+                     inout standard_metadata_t standard_metadata) {
+
+    apply {
+
+        PacketIoIngress.apply(hdr, fabric_metadata, standard_metadata);
+
+        // Drop garbage, so we get a clean pcap.
+        if (standard_metadata.ingress_port == S1U_PORT
+                && hdr.ethernet.src_addr != ENB_MAC_ADDR) {
+            mark_to_drop();
+            exit;
+        } else if (standard_metadata.ingress_port == SGI_PORT
+                && hdr.ethernet.src_addr != AS_MAC_ADDR) {
+            mark_to_drop();
+            exit;
+        }
+
+        table0_control.apply(hdr, fabric_metadata, standard_metadata);
+
+        if (standard_metadata.egress_spec == CPU_PORT) {
+            return;
+        }
+
+        if (standard_metadata.ingress_port == S1U_PORT) {
+            if (hdr.ethernet.dst_addr != S1U_MAC_ADDR) {
+                mark_to_drop();
+                exit;
+            }
+            standard_metadata.egress_spec = SGI_PORT;
+            hdr.ethernet.src_addr = SGI_MAC_ADDR;
+            hdr.ethernet.dst_addr = AS_MAC_ADDR;
+        } else if (standard_metadata.ingress_port == SGI_PORT) {
+            if (hdr.ethernet.dst_addr != SGI_MAC_ADDR) {
+                mark_to_drop();
+                exit;
+            }
+            standard_metadata.egress_spec = S1U_PORT;
+            hdr.ethernet.src_addr = S1U_MAC_ADDR;
+            hdr.ethernet.dst_addr = ENB_MAC_ADDR;
+        }
+
+#ifdef WITH_SPGW_PCC_GATING
+        fabric_metadata.spgw.l4_src_port = fabric_metadata.l4_src_port;
+        fabric_metadata.spgw.l4_dst_port = fabric_metadata.l4_dst_port;
+#endif // WITH_SPGW_PCC_GATING
+        spgw_ingress.apply(hdr.gtpu_ipv4, hdr.gtpu_udp, hdr.gtpu,
+                           hdr.ipv4, hdr.udp, fabric_metadata.spgw);
+    }
+}
+
+//------------------------------------------------------------------------------
+// EGRESS PIPELINE
+//------------------------------------------------------------------------------
+
+control egress_impl(inout parsed_headers_t hdr,
+                    inout fabric_metadata_t fabric_metadata,
+                    inout standard_metadata_t standard_metadata) {
+    apply {
+        PacketIoEgress.apply(hdr, fabric_metadata, standard_metadata);
+        spgw_egress.apply(hdr.gtpu_ipv4, hdr.gtpu_udp, hdr.gtpu,
+                          fabric_metadata.spgw, standard_metadata);
+     }
+}
+
+//------------------------------------------------------------------------------
+// SWITCH INSTANTIATION
+//------------------------------------------------------------------------------
+
+V1Switch(FabricParser(),
+         FabricVerifyChecksum(),
+         ingress_impl(),
+         egress_impl(),
+         FabricComputeChecksum(),
+         FabricDeparser()) main;
diff --git a/pipelines/fabric/src/test/p4/spgw/uplink-post.pcap b/pipelines/fabric/src/test/p4/spgw/uplink-post.pcap
new file mode 100644
index 0000000..c02e7c6
--- /dev/null
+++ b/pipelines/fabric/src/test/p4/spgw/uplink-post.pcap
Binary files differ
diff --git a/pipelines/fabric/src/test/p4/spgw/uplink-pre.pcap b/pipelines/fabric/src/test/p4/spgw/uplink-pre.pcap
new file mode 100644
index 0000000..78064fa
--- /dev/null
+++ b/pipelines/fabric/src/test/p4/spgw/uplink-pre.pcap
Binary files differ