[SDFAB-102] Backport changes required for policies to fabric.p4 (Redirect)

Change-Id: I357c908d31abad9c3f8d74723d937ea948e54808
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 34ef4d1..ae86e3b 100644
--- a/pipelines/fabric/impl/src/main/resources/include/control/acl.p4
+++ b/pipelines/fabric/impl/src/main/resources/include/control/acl.p4
@@ -77,6 +77,7 @@
             hdr.icmp.icmp_code              : ternary @name("icmp_code"); // 8
             l4_sport                        : ternary @name("l4_sport");  // 16
             l4_dport                        : ternary @name("l4_dport");  // 16
+            fabric_metadata.port_type       : ternary @name("port_type"); // 2
         }
 
         actions = {
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 a8fae49..a96b522 100644
--- a/pipelines/fabric/impl/src/main/resources/include/control/filtering.p4
+++ b/pipelines/fabric/impl/src/main/resources/include/control/filtering.p4
@@ -35,17 +35,19 @@
         // Do ACL table in case we want to punt to cpu.
         fabric_metadata.skip_forwarding = _TRUE;
         fabric_metadata.skip_next = _TRUE;
+        fabric_metadata.port_type = PORT_TYPE_UNKNOWN;
         ingress_port_vlan_counter.count();
     }
 
-    action permit() {
+    action permit(port_type_t port_type) {
         // Allow packet as is.
+        fabric_metadata.port_type = port_type;
         ingress_port_vlan_counter.count();
     }
 
-    action permit_with_internal_vlan(vlan_id_t vlan_id) {
+    action permit_with_internal_vlan(vlan_id_t vlan_id, port_type_t port_type) {
         fabric_metadata.vlan_id = vlan_id;
-        permit();
+        permit(port_type);
     }
 
     // FIXME: remove the use of ternary match on inner VLAN.
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 11437b1..fca2e61 100644
--- a/pipelines/fabric/impl/src/main/resources/include/control/next.p4
+++ b/pipelines/fabric/impl/src/main/resources/include/control/next.p4
@@ -42,63 +42,12 @@
     }
 
     @hidden
-    action set_mpls_label(mpls_label_t label) {
-        fabric_metadata.mpls_label = label;
-    }
-
-    @hidden
     action routing(port_num_t port_num, mac_addr_t smac, mac_addr_t dmac) {
         rewrite_smac(smac);
         rewrite_dmac(dmac);
         output(port_num);
     }
 
-    @hidden
-    action mpls_routing(port_num_t port_num, mac_addr_t smac, mac_addr_t dmac,
-                        mpls_label_t label) {
-        set_mpls_label(label);
-        routing(port_num, smac, dmac);
-    }
-
-    /*
-     * Next VLAN table.
-     * Modify VLAN ID based on next ID.
-     */
-    direct_counter(CounterType.packets_and_bytes) next_vlan_counter;
-
-    action set_vlan(vlan_id_t vlan_id) {
-        fabric_metadata.vlan_id = vlan_id;
-        next_vlan_counter.count();
-    }
-
-#ifdef WITH_DOUBLE_VLAN_TERMINATION
-    action set_double_vlan(vlan_id_t outer_vlan_id, vlan_id_t inner_vlan_id) {
-        set_vlan(outer_vlan_id);
-        fabric_metadata.push_double_vlan = _TRUE;
-        fabric_metadata.inner_vlan_id = inner_vlan_id;
-#ifdef WITH_BNG
-        fabric_metadata.bng.s_tag = outer_vlan_id;
-        fabric_metadata.bng.c_tag = inner_vlan_id;
-#endif // WITH_BNG
-    }
-#endif // WITH_DOUBLE_VLAN_TERMINATION
-
-    table next_vlan {
-        key = {
-            fabric_metadata.next_id: exact @name("next_id");
-        }
-        actions = {
-            set_vlan;
-#ifdef WITH_DOUBLE_VLAN_TERMINATION
-            set_double_vlan;
-#endif // WITH_DOUBLE_VLAN_TERMINATION
-            @defaultonly nop;
-        }
-        const default_action = nop();
-        counters = next_vlan_counter;
-        size = NEXT_VLAN_TABLE_SIZE;
-    }
-
 #ifdef WITH_XCONNECT
     /*
      * Cross-connect table.
@@ -149,12 +98,6 @@
         simple_counter.count();
     }
 
-    action mpls_routing_simple(port_num_t port_num, mac_addr_t smac, mac_addr_t dmac,
-                               mpls_label_t label) {
-        mpls_routing(port_num, smac, dmac, label);
-        simple_counter.count();
-    }
-
     table simple {
         key = {
             fabric_metadata.next_id: exact @name("next_id");
@@ -162,7 +105,6 @@
         actions = {
             output_simple;
             routing_simple;
-            mpls_routing_simple;
             @defaultonly nop;
         }
         const default_action = nop();
@@ -193,12 +135,6 @@
         hashed_counter.count();
     }
 
-    action mpls_routing_hashed(port_num_t port_num, mac_addr_t smac, mac_addr_t dmac,
-                               mpls_label_t label) {
-        mpls_routing(port_num, smac, dmac, label);
-        hashed_counter.count();
-    }
-
     table hashed {
         key = {
             fabric_metadata.next_id: exact @name("next_id");
@@ -211,7 +147,6 @@
         actions = {
             output_hashed;
             routing_hashed;
-            mpls_routing_hashed;
             @defaultonly nop;
         }
         implementation = hashed_selector;
@@ -258,7 +193,6 @@
         hashed.apply();
 #endif // WITH_HASHED_NEXT
         multicast.apply();
-        next_vlan.apply();
     }
 }
 
diff --git a/pipelines/fabric/impl/src/main/resources/include/control/pre_next.p4 b/pipelines/fabric/impl/src/main/resources/include/control/pre_next.p4
new file mode 100644
index 0000000..9d4c5b6
--- /dev/null
+++ b/pipelines/fabric/impl/src/main/resources/include/control/pre_next.p4
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2021-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.
+ */
+
+#include <core.p4>
+#include <v1model.p4>
+
+#include "../header.p4"
+
+control PreNext(inout parsed_headers_t hdr,
+                inout fabric_metadata_t fabric_metadata) {
+    /*
+     * Next MPLS table.
+     * Set the MPLS label based on the next ID.
+     */
+
+    direct_counter(CounterType.packets_and_bytes) next_mpls_counter;
+
+    action set_mpls_label(mpls_label_t label) {
+        fabric_metadata.mpls_label = label;
+        next_mpls_counter.count();
+    }
+
+    table next_mpls {
+        key = {
+            fabric_metadata.next_id: exact @name("next_id");
+        }
+        actions = {
+            set_mpls_label;
+            @defaultonly nop;
+        }
+        const default_action = nop();
+        counters = next_mpls_counter;
+        size = NEXT_MPLS_TABLE_SIZE;
+    }
+
+    /*
+     * Next VLAN table.
+     * Modify VLAN ID based on next ID.
+     */
+
+    direct_counter(CounterType.packets_and_bytes) next_vlan_counter;
+
+    action set_vlan(vlan_id_t vlan_id) {
+        fabric_metadata.vlan_id = vlan_id;
+        next_vlan_counter.count();
+    }
+
+#ifdef WITH_DOUBLE_VLAN_TERMINATION
+    action set_double_vlan(vlan_id_t outer_vlan_id, vlan_id_t inner_vlan_id) {
+        set_vlan(outer_vlan_id);
+        fabric_metadata.push_double_vlan = _TRUE;
+        fabric_metadata.inner_vlan_id = inner_vlan_id;
+#ifdef WITH_BNG
+        fabric_metadata.bng.s_tag = outer_vlan_id;
+        fabric_metadata.bng.c_tag = inner_vlan_id;
+#endif // WITH_BNG
+    }
+#endif // WITH_DOUBLE_VLAN_TERMINATION
+
+    table next_vlan {
+        key = {
+            fabric_metadata.next_id: exact @name("next_id");
+        }
+        actions = {
+            set_vlan;
+#ifdef WITH_DOUBLE_VLAN_TERMINATION
+            set_double_vlan;
+#endif // WITH_DOUBLE_VLAN_TERMINATION
+            @defaultonly nop;
+        }
+        const default_action = nop();
+        counters = next_vlan_counter;
+        size = NEXT_VLAN_TABLE_SIZE;
+    }
+
+    apply {
+        next_mpls.apply();
+        next_vlan.apply();
+    }
+}
diff --git a/pipelines/fabric/impl/src/main/resources/include/define.p4 b/pipelines/fabric/impl/src/main/resources/include/define.p4
index 4a30837..36a5ec7 100644
--- a/pipelines/fabric/impl/src/main/resources/include/define.p4
+++ b/pipelines/fabric/impl/src/main/resources/include/define.p4
@@ -112,6 +112,18 @@
 const spgw_interface_t SPGW_IFACE_CORE = 8w2;
 const spgw_interface_t SPGW_IFACE_FROM_DBUF = 8w3;
 
+// PORT types. Set by the control plane using the actions
+// of the filtering.ingress_port_vlan table.
+typedef bit<2> port_type_t;
+// Default value. Set by deny action.
+const port_type_t PORT_TYPE_UNKNOWN = 0x0;
+// Host-facing port on a leaf switch.
+const port_type_t PORT_TYPE_EDGE = 0x1;
+// Switch-facing port on a leaf or spine switch.
+const port_type_t PORT_TYPE_INFRA = 0x2;
+// ASIC-internal port such as the recirculation one (used for INT or UE-to-UE).
+const port_type_t PORT_TYPE_INTERNAL = 0x3;
+
 const bit<16> ETHERTYPE_QINQ = 0x88A8;
 const bit<16> ETHERTYPE_QINQ_NON_STD = 0x9100;
 const bit<16> ETHERTYPE_VLAN = 0x8100;
diff --git a/pipelines/fabric/impl/src/main/resources/include/header.p4 b/pipelines/fabric/impl/src/main/resources/include/header.p4
index 6b47a60..b76ea01 100644
--- a/pipelines/fabric/impl/src/main/resources/include/header.p4
+++ b/pipelines/fabric/impl/src/main/resources/include/header.p4
@@ -210,6 +210,7 @@
 #ifdef WITH_INT
     int_metadata_t int_meta;
 #endif // WITH_INT
+    port_type_t   port_type;
 }
 
 struct parsed_headers_t {
diff --git a/pipelines/fabric/impl/src/main/resources/include/size.p4 b/pipelines/fabric/impl/src/main/resources/include/size.p4
index 2883094..caa8c14 100644
--- a/pipelines/fabric/impl/src/main/resources/include/size.p4
+++ b/pipelines/fabric/impl/src/main/resources/include/size.p4
@@ -17,6 +17,7 @@
 #define ROUTING_V6_TABLE_SIZE 1024
 #define ACL_TABLE_SIZE 1024
 #define XCONNECT_NEXT_TABLE_SIZE 1024
+#define NEXT_MPLS_TABLE_SIZE 1024
 #define NEXT_VLAN_TABLE_SIZE 1024
 #define SIMPLE_NEXT_TABLE_SIZE 1024
 #define HASHED_NEXT_TABLE_SIZE 1024