Improvement in fabric.p4 and bng.p4

- fabric.p4 now supports double tagged hosts
- bng.p4 now only manages PPPoE termination
- bng_ingress moved at the end of the fabric pipeline

Change-Id: Iff62238fde9ec6ddf7311312a98c041e3ab3aa8d
diff --git a/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/FabricConstants.java b/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/FabricConstants.java
index f1bb185..36d9f25 100644
--- a/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/FabricConstants.java
+++ b/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/FabricConstants.java
@@ -37,6 +37,8 @@
             PiMatchFieldId.of("ig_port");
     public static final PiMatchFieldId HDR_VLAN_IS_VALID =
             PiMatchFieldId.of("vlan_is_valid");
+    public static final PiMatchFieldId HDR_EG_PORT =
+            PiMatchFieldId.of("eg_port");
     public static final PiMatchFieldId HDR_IPV6_SRC_NET_ID =
             PiMatchFieldId.of("ipv6_src_net_id");
     public static final PiMatchFieldId HDR_C_TAG = PiMatchFieldId.of("c_tag");
@@ -44,6 +46,8 @@
             PiMatchFieldId.of("ipv4_src");
     public static final PiMatchFieldId HDR_IPV6_DST =
             PiMatchFieldId.of("ipv6_dst");
+    public static final PiMatchFieldId HDR_IS_MPLS =
+            PiMatchFieldId.of("is_mpls");
     public static final PiMatchFieldId HDR_L4_DPORT =
             PiMatchFieldId.of("l4_dport");
     public static final PiMatchFieldId HDR_PPPOE_CODE =
@@ -63,8 +67,6 @@
             PiMatchFieldId.of("ipv4_dst");
     public static final PiMatchFieldId HDR_IPV6_TRAFFIC_CLASS =
             PiMatchFieldId.of("ipv6_traffic_class");
-    public static final PiMatchFieldId HDR_IPV6_DST_NET_ID =
-            PiMatchFieldId.of("ipv6_dst_net_id");
     public static final PiMatchFieldId HDR_ETH_TYPE =
             PiMatchFieldId.of("eth_type");
     public static final PiMatchFieldId HDR_NEXT_ID =
@@ -73,6 +75,8 @@
             PiMatchFieldId.of("l4_sport");
     public static final PiMatchFieldId HDR_ICMP_CODE =
             PiMatchFieldId.of("icmp_code");
+    public static final PiMatchFieldId HDR_INNER_VLAN_ID =
+            PiMatchFieldId.of("inner_vlan_id");
     public static final PiMatchFieldId HDR_IPV4_ECN =
             PiMatchFieldId.of("ipv4_ecn");
     public static final PiMatchFieldId HDR_PPPOE_SESSION_ID =
@@ -83,8 +87,10 @@
             PiMatchFieldId.of("line_id");
     public static final PiMatchFieldId HDR_IPV4_DSCP =
             PiMatchFieldId.of("ipv4_dscp");
-    public static final PiMatchFieldId HDR_EG_PORT =
-            PiMatchFieldId.of("eg_port");
+    public static final PiMatchFieldId HDR_IS_IPV4 =
+            PiMatchFieldId.of("is_ipv4");
+    public static final PiMatchFieldId HDR_IS_IPV6 =
+            PiMatchFieldId.of("is_ipv6");
     public static final PiMatchFieldId HDR_GTP_IPV4_DST =
             PiMatchFieldId.of("gtp_ipv4_dst");
     public static final PiMatchFieldId HDR_INT_IS_VALID =
@@ -98,10 +104,10 @@
     // Table IDs
     public static final PiTableId FABRIC_INGRESS_NEXT_HASHED =
             PiTableId.of("FabricIngress.next.hashed");
+    public static final PiTableId FABRIC_INGRESS_BNG_INGRESS_T_LINE_MAP =
+            PiTableId.of("FabricIngress.bng_ingress.t_line_map");
     public static final PiTableId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_TB_INT_INSERT =
             PiTableId.of("FabricEgress.process_int_main.process_int_transit.tb_int_insert");
-    public static final PiTableId FABRIC_EGRESS_BNG_EGRESS_DOWNSTREAM_T_SESSION_ENCAP =
-            PiTableId.of("FabricEgress.bng_egress.downstream.t_session_encap");
     public static final PiTableId FABRIC_INGRESS_FILTERING_FWD_CLASSIFIER =
             PiTableId.of("FabricIngress.filtering.fwd_classifier");
     public static final PiTableId FABRIC_INGRESS_NEXT_XCONNECT =
@@ -130,16 +136,12 @@
             PiTableId.of("FabricIngress.bng_ingress.upstream.t_pppoe_term_v4");
     public static final PiTableId FABRIC_INGRESS_SPGW_INGRESS_S1U_FILTER_TABLE =
             PiTableId.of("FabricIngress.spgw_ingress.s1u_filter_table");
-    public static final PiTableId FABRIC_INGRESS_BNG_INGRESS_DOWNSTREAM_T_LINE_MAP_V6 =
-            PiTableId.of("FabricIngress.bng_ingress.downstream.t_line_map_v6");
-    public static final PiTableId FABRIC_INGRESS_BNG_INGRESS_DOWNSTREAM_T_LINE_MAP_V4 =
-            PiTableId.of("FabricIngress.bng_ingress.downstream.t_line_map_v4");
     public static final PiTableId FABRIC_INGRESS_FORWARDING_BRIDGING =
             PiTableId.of("FabricIngress.forwarding.bridging");
-    public static final PiTableId FABRIC_INGRESS_BNG_INGRESS_UPSTREAM_T_LINE_MAP =
-            PiTableId.of("FabricIngress.bng_ingress.upstream.t_line_map");
     public static final PiTableId FABRIC_INGRESS_SPGW_INGRESS_DL_SESS_LOOKUP =
             PiTableId.of("FabricIngress.spgw_ingress.dl_sess_lookup");
+    public static final PiTableId FABRIC_INGRESS_BNG_INGRESS_DOWNSTREAM_T_LINE_SESSION_MAP =
+            PiTableId.of("FabricIngress.bng_ingress.downstream.t_line_session_map");
     public static final PiTableId FABRIC_EGRESS_EGRESS_NEXT_EGRESS_VLAN =
             PiTableId.of("FabricEgress.egress_next.egress_vlan");
     public static final PiTableId FABRIC_INGRESS_PROCESS_SET_SOURCE_SINK_TB_SET_SINK =
@@ -219,6 +221,8 @@
             PiActionId.of("FabricIngress.forwarding.set_next_id_bridging");
     public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_SOURCE_INT_SOURCE_DSCP =
             PiActionId.of("FabricEgress.process_int_main.process_int_source.int_source_dscp");
+    public static final PiActionId FABRIC_INGRESS_NEXT_SET_DOUBLE_VLAN =
+            PiActionId.of("FabricIngress.next.set_double_vlan");
     public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INIT_METADATA =
             PiActionId.of("FabricEgress.process_int_main.process_int_transit.init_metadata");
     public static final PiActionId FABRIC_INGRESS_ACL_DROP =
@@ -227,10 +231,14 @@
             PiActionId.of("FabricIngress.acl.set_clone_session_id");
     public static final PiActionId FABRIC_INGRESS_BNG_INGRESS_UPSTREAM_PUNT_TO_CPU =
             PiActionId.of("FabricIngress.bng_ingress.upstream.punt_to_cpu");
-    public static final PiActionId FABRIC_INGRESS_BNG_INGRESS_UPSTREAM_SET_LINE =
-            PiActionId.of("FabricIngress.bng_ingress.upstream.set_line");
+    public static final PiActionId FABRIC_INGRESS_BNG_INGRESS_DOWNSTREAM_DROP =
+            PiActionId.of("FabricIngress.bng_ingress.downstream.drop");
+    public static final PiActionId FABRIC_INGRESS_NEXT_SET_VLAN =
+            PiActionId.of("FabricIngress.next.set_vlan");
     public static final PiActionId FABRIC_INGRESS_ACL_NOP_ACL =
             PiActionId.of("FabricIngress.acl.nop_acl");
+    public static final PiActionId FABRIC_INGRESS_BNG_INGRESS_SET_LINE =
+            PiActionId.of("FabricIngress.bng_ingress.set_line");
     public static final PiActionId FABRIC_INGRESS_BNG_INGRESS_UPSTREAM_TERM_DISABLED =
             PiActionId.of("FabricIngress.bng_ingress.upstream.term_disabled");
     public static final PiActionId FABRIC_INGRESS_ACL_SET_NEXT_ID_ACL =
@@ -251,8 +259,6 @@
             PiActionId.of("FabricIngress.next.output_hashed");
     public static final PiActionId FABRIC_INGRESS_FORWARDING_POP_MPLS_AND_NEXT =
             PiActionId.of("FabricIngress.forwarding.pop_mpls_and_next");
-    public static final PiActionId FABRIC_INGRESS_BNG_INGRESS_DOWNSTREAM_SET_LINE_NEXT =
-            PiActionId.of("FabricIngress.bng_ingress.downstream.set_line_next");
     public static final PiActionId FABRIC_EGRESS_BNG_EGRESS_DOWNSTREAM_ENCAP_V6 =
             PiActionId.of("FabricEgress.bng_egress.downstream.encap_v6");
     public static final PiActionId FABRIC_INGRESS_NEXT_MPLS_ROUTING_SIMPLE =
@@ -261,8 +267,6 @@
             PiActionId.of("FabricIngress.acl.punt_to_cpu");
     public static final PiActionId FABRIC_INGRESS_BNG_INGRESS_DOWNSTREAM_QOS_PRIO =
             PiActionId.of("FabricIngress.bng_ingress.downstream.qos_prio");
-    public static final PiActionId FABRIC_INGRESS_NEXT_SET_VLAN =
-            PiActionId.of("FabricIngress.next.set_vlan");
     public static final PiActionId FABRIC_EGRESS_EGRESS_NEXT_POP_VLAN =
             PiActionId.of("FabricEgress.egress_next.pop_vlan");
     public static final PiActionId FABRIC_INGRESS_PROCESS_SET_SOURCE_SINK_INT_SET_SINK =
@@ -280,21 +284,21 @@
             PiActionId.of("FabricIngress.next.output_simple");
     public static final PiActionId FABRIC_INGRESS_FILTERING_DENY =
             PiActionId.of("FabricIngress.filtering.deny");
+    public static final PiActionId FABRIC_INGRESS_BNG_INGRESS_DOWNSTREAM_SET_SESSION =
+            PiActionId.of("FabricIngress.bng_ingress.downstream.set_session");
     public static final PiActionId FABRIC_INGRESS_NEXT_SET_MCAST_GROUP_ID =
             PiActionId.of("FabricIngress.next.set_mcast_group_id");
     public static final PiActionId FABRIC_INGRESS_FILTERING_SET_FORWARDING_TYPE =
             PiActionId.of("FabricIngress.filtering.set_forwarding_type");
-    public static final PiActionId FABRIC_INGRESS_BNG_INGRESS_DOWNSTREAM_SET_LINE_DROP =
-            PiActionId.of("FabricIngress.bng_ingress.downstream.set_line_drop");
     public static final PiActionId FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_REPORT_DO_REPORT_ENCAPSULATION =
             PiActionId.of("FabricEgress.process_int_main.process_int_report.do_report_encapsulation");
     public static final PiActionId NO_ACTION = PiActionId.of("NoAction");
     public static final PiActionId FABRIC_INGRESS_NEXT_OUTPUT_XCONNECT =
             PiActionId.of("FabricIngress.next.output_xconnect");
     // Action Param IDs
+    public static final PiActionParamId DMAC = PiActionParamId.of("dmac");
     public static final PiActionParamId MON_PORT =
             PiActionParamId.of("mon_port");
-    public static final PiActionParamId C_TAG = PiActionParamId.of("c_tag");
     public static final PiActionParamId S1U_SGW_ADDR =
             PiActionParamId.of("s1u_sgw_addr");
     public static final PiActionParamId SMAC = PiActionParamId.of("smac");
@@ -306,7 +310,8 @@
     public static final PiActionParamId NEXT_ID = PiActionParamId.of("next_id");
     public static final PiActionParamId INS_CNT = PiActionParamId.of("ins_cnt");
     public static final PiActionParamId SRC_MAC = PiActionParamId.of("src_mac");
-    public static final PiActionParamId DMAC = PiActionParamId.of("dmac");
+    public static final PiActionParamId INNER_VLAN_ID =
+            PiActionParamId.of("inner_vlan_id");
     public static final PiActionParamId PPPOE_SESSION_ID =
             PiActionParamId.of("pppoe_session_id");
     public static final PiActionParamId MON_MAC = PiActionParamId.of("mon_mac");
@@ -318,6 +323,8 @@
     public static final PiActionParamId LINE_ID = PiActionParamId.of("line_id");
     public static final PiActionParamId FWD_TYPE =
             PiActionParamId.of("fwd_type");
+    public static final PiActionParamId OUTER_VLAN_ID =
+            PiActionParamId.of("outer_vlan_id");
     public static final PiActionParamId INS_MASK0407 =
             PiActionParamId.of("ins_mask0407");
     public static final PiActionParamId TEID = PiActionParamId.of("teid");
diff --git a/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/FabricInterpreter.java b/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/FabricInterpreter.java
index dcd872b..e5e90ed 100644
--- a/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/FabricInterpreter.java
+++ b/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/FabricInterpreter.java
@@ -91,6 +91,7 @@
                     .put(Criterion.Type.ETH_TYPE, FabricConstants.HDR_ETH_TYPE)
                     .put(Criterion.Type.MPLS_LABEL, FabricConstants.HDR_MPLS_LABEL)
                     .put(Criterion.Type.VLAN_VID, FabricConstants.HDR_VLAN_ID)
+                    .put(Criterion.Type.INNER_VLAN_VID, FabricConstants.HDR_INNER_VLAN_ID)
                     .put(Criterion.Type.IPV4_DST, FabricConstants.HDR_IPV4_DST)
                     .put(Criterion.Type.IPV4_SRC, FabricConstants.HDR_IPV4_SRC)
                     .put(Criterion.Type.IPV6_DST, FabricConstants.HDR_IPV6_DST)
diff --git a/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/pipeliner/FilteringObjectiveTranslator.java b/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/pipeliner/FilteringObjectiveTranslator.java
index 67d7b3a..e86f270 100644
--- a/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/pipeliner/FilteringObjectiveTranslator.java
+++ b/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/pipeliner/FilteringObjectiveTranslator.java
@@ -17,6 +17,7 @@
 package org.onosproject.pipelines.fabric.pipeliner;
 
 import com.google.common.collect.Lists;
+import org.onlab.packet.EthType;
 import org.onlab.packet.Ethernet;
 import org.onlab.packet.MacAddress;
 import org.onlab.packet.VlanId;
@@ -63,12 +64,6 @@
             .withId(FabricConstants.FABRIC_INGRESS_FILTERING_DENY)
             .build();
 
-    private static final PiCriterion VLAN_VALID = PiCriterion.builder()
-            .matchExact(FabricConstants.HDR_VLAN_IS_VALID, ONE)
-            .build();
-    private static final PiCriterion VLAN_INVALID = PiCriterion.builder()
-            .matchExact(FabricConstants.HDR_VLAN_IS_VALID, ZERO)
-            .build();
 
     FilteringObjectiveTranslator(DeviceId deviceId, FabricCapabilities capabilities) {
         super(deviceId, capabilities);
@@ -88,14 +83,17 @@
         }
 
         final PortCriterion inPort = (PortCriterion) obj.key();
-        final VlanIdCriterion vlan = (VlanIdCriterion) criterion(
+
+        final VlanIdCriterion outerVlan = (VlanIdCriterion) criterion(
                 obj.conditions(), Criterion.Type.VLAN_VID);
+        final VlanIdCriterion innerVlan = (VlanIdCriterion) criterion(
+                obj.conditions(), Criterion.Type.INNER_VLAN_VID);
         final EthCriterion ethDst = (EthCriterion) criterion(
                 obj.conditions(), Criterion.Type.ETH_DST);
         final EthCriterion ethDstMasked = (EthCriterion) criterion(
                 obj.conditions(), Criterion.Type.ETH_DST_MASKED);
 
-        ingressPortVlanRule(obj, inPort, vlan, resultBuilder);
+        ingressPortVlanRule(obj, inPort, outerVlan, innerVlan, resultBuilder);
         fwdClassifierRules(obj, inPort, ethDst, ethDstMasked, resultBuilder);
 
         return resultBuilder.build();
@@ -104,18 +102,28 @@
     private void ingressPortVlanRule(
             FilteringObjective obj,
             Criterion inPortCriterion,
-            VlanIdCriterion vlanCriterion,
+            VlanIdCriterion outerVlanCriterion,
+            VlanIdCriterion innerVlanCriterion,
             ObjectiveTranslation.Builder resultBuilder)
             throws FabricPipelinerException {
 
-        final boolean vlanValid = vlanCriterion != null
-                && !vlanCriterion.vlanId().equals(VlanId.NONE);
+        final boolean outerVlanValid = outerVlanCriterion != null
+                && !outerVlanCriterion.vlanId().equals(VlanId.NONE);
+        final boolean innerVlanValid = innerVlanCriterion != null
+                && !innerVlanCriterion.vlanId().equals(VlanId.NONE);
+
+        final PiCriterion piCriterion = PiCriterion.builder()
+                .matchExact(FabricConstants.HDR_VLAN_IS_VALID, outerVlanValid ? ONE : ZERO)
+                .build();
 
         final TrafficSelector.Builder selector = DefaultTrafficSelector.builder()
                 .add(inPortCriterion)
-                .add(vlanValid ? VLAN_VALID : VLAN_INVALID);
-        if (vlanValid) {
-            selector.add(vlanCriterion);
+                .add(piCriterion);
+        if (outerVlanValid) {
+            selector.add(outerVlanCriterion);
+        }
+        if (innerVlanValid) {
+            selector.add(innerVlanCriterion);
         }
 
         final TrafficTreatment treatment;
@@ -127,7 +135,6 @@
             treatment = obj.meta() == null
                     ? DefaultTrafficTreatment.emptyTreatment() : obj.meta();
         }
-
         resultBuilder.addFlowRule(flowRule(
                 obj, FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN,
                 selector.build(), treatment));
@@ -214,7 +221,7 @@
             throws FabricPipelinerException {
         final TrafficSelector selector = DefaultTrafficSelector.builder()
                 .matchInPort(inPort)
-                .matchEthType(ethType)
+                .matchPi(mapEthTypeFwdClassifier(ethType))
                 .matchEthDstMasked(dstMac, dstMacMask == null
                         ? MacAddress.EXACT_MASK : dstMacMask)
                 .build();
@@ -234,4 +241,38 @@
                 .build();
 
     }
+
+    static PiCriterion mapEthTypeFwdClassifier(short ethType) {
+        // Map the Ethernet type to the validity bits of the fabric pipeline
+        switch (EthType.EtherType.lookup(ethType)) {
+            case IPV4: {
+                return PiCriterion.builder()
+                        .matchExact(FabricConstants.HDR_IS_IPV4, ONE)
+                        .matchExact(FabricConstants.HDR_IS_IPV6, ZERO)
+                        .matchExact(FabricConstants.HDR_IS_MPLS, ZERO)
+                        .build();
+            }
+            case IPV6: {
+                return PiCriterion.builder()
+                        .matchExact(FabricConstants.HDR_IS_IPV4, ZERO)
+                        .matchExact(FabricConstants.HDR_IS_IPV6, ONE)
+                        .matchExact(FabricConstants.HDR_IS_MPLS, ZERO)
+                        .build();
+            }
+            case MPLS_UNICAST: {
+                return PiCriterion.builder()
+                        .matchExact(FabricConstants.HDR_IS_IPV4, ZERO)
+                        .matchExact(FabricConstants.HDR_IS_IPV6, ZERO)
+                        .matchExact(FabricConstants.HDR_IS_MPLS, ONE)
+                        .build();
+            }
+            default: {
+                return PiCriterion.builder()
+                        .matchExact(FabricConstants.HDR_IS_IPV4, ZERO)
+                        .matchExact(FabricConstants.HDR_IS_IPV6, ZERO)
+                        .matchExact(FabricConstants.HDR_IS_MPLS, ZERO)
+                        .build();
+            }
+        }
+    }
 }