[ONOS-7493] Segment routing may uninstall forwarding with no next id

Change-Id: Id78b9ed94633b7e96fdeebe185e28d6de386e3ec
diff --git a/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/pipeliner/FabricForwardingPipeliner.java b/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/pipeliner/FabricForwardingPipeliner.java
index e72042f..5424a49 100644
--- a/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/pipeliner/FabricForwardingPipeliner.java
+++ b/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/pipeliner/FabricForwardingPipeliner.java
@@ -169,12 +169,6 @@
         checkNotNull(vlanIdCriterion, "VlanId criterion should not be null");
         checkNotNull(ethDstCriterion, "EthDst criterion should not be null");
 
-        if (fwd.nextId() == null) {
-            log.warn("Forwarding objective for L2 unicast should contains next id");
-            resultBuilder.setError(ObjectiveError.BADPARAMS);
-            return;
-        }
-
         VlanId vlanId = vlanIdCriterion.vlanId();
         MacAddress ethDst = ethDstCriterion.mac();
 
@@ -182,7 +176,11 @@
                 .matchVlanId(vlanId)
                 .matchEthDst(ethDst)
                 .build();
-        TrafficTreatment treatment = buildSetNextIdTreatment(fwd.nextId());
+        TrafficTreatment treatment = fwd.treatment();
+        if (fwd.nextId() != null) {
+            treatment = buildSetNextIdTreatment(fwd.nextId());
+        }
+
         FlowRule flowRule = DefaultFlowRule.builder()
                 .withSelector(selector)
                 .withTreatment(treatment)
@@ -200,18 +198,16 @@
                                         ForwardingObjective fwd,
                                         PipelinerTranslationResult.Builder resultBuilder) {
         checkNotNull(vlanIdCriterion, "VlanId criterion should not be null");
-        if (fwd.nextId() == null) {
-            log.warn("Forwarding objective for L2 broadcast should contains next id");
-            resultBuilder.setError(ObjectiveError.BADPARAMS);
-            return;
-        }
 
         VlanId vlanId = vlanIdCriterion.vlanId();
 
         TrafficSelector selector = DefaultTrafficSelector.builder()
                 .matchVlanId(vlanId)
                 .build();
-        TrafficTreatment treatment = buildSetNextIdTreatment(fwd.nextId());
+        TrafficTreatment treatment = fwd.treatment();
+        if (fwd.nextId() != null) {
+            treatment = buildSetNextIdTreatment(fwd.nextId());
+        }
         FlowRule flowRule = DefaultFlowRule.builder()
                 .withSelector(selector)
                 .withTreatment(treatment)
@@ -228,16 +224,13 @@
     private void processIpv4UnicastRule(IPCriterion ipDstCriterion, ForwardingObjective fwd,
                                         PipelinerTranslationResult.Builder resultBuilder) {
         checkNotNull(ipDstCriterion, "IP dst criterion should not be null");
-        if (fwd.nextId() == null) {
-            log.warn("Forwarding objective for IPv4 unicast should contains next id");
-            resultBuilder.setError(ObjectiveError.BADPARAMS);
-            return;
-        }
         TrafficSelector selector = DefaultTrafficSelector.builder()
                 .matchIPDst(ipDstCriterion.ip())
                 .build();
-
-        TrafficTreatment treatment = buildSetNextIdTreatment(fwd.nextId());
+        TrafficTreatment treatment = fwd.treatment();
+        if (fwd.nextId() != null) {
+            treatment = buildSetNextIdTreatment(fwd.nextId());
+        }
         FlowRule flowRule = DefaultFlowRule.builder()
                 .withSelector(selector)
                 .withTreatment(treatment)
@@ -254,25 +247,25 @@
     private void processMplsRule(MplsCriterion mplsCriterion, ForwardingObjective fwd,
                                  PipelinerTranslationResult.Builder resultBuilder) {
         checkNotNull(mplsCriterion, "Mpls criterion should not be null");
-        if (fwd.nextId() == null) {
-            log.warn("Forwarding objective for MPLS should contains next id");
-            resultBuilder.setError(ObjectiveError.BADPARAMS);
-            return;
+        TrafficTreatment treatment;
+
+        treatment = fwd.treatment();
+        if (fwd.nextId() != null) {
+            PiActionParam nextIdParam = new PiActionParam(FabricConstants.ACT_PRM_NEXT_ID_ID,
+                                                          ImmutableByteSequence.copyFrom(fwd.nextId().byteValue()));
+            PiAction nextIdAction = PiAction.builder()
+                    .withId(FabricConstants.ACT_FORWARDING_POP_MPLS_AND_NEXT_ID)
+                    .withParameter(nextIdParam)
+                    .build();
+            treatment = DefaultTrafficTreatment.builder()
+                    .piTableAction(nextIdAction)
+                    .build();
         }
+
         TrafficSelector selector = DefaultTrafficSelector.builder()
                 .add(mplsCriterion)
                 .build();
 
-        PiActionParam nextIdParam = new PiActionParam(FabricConstants.ACT_PRM_NEXT_ID_ID,
-                                                      ImmutableByteSequence.copyFrom(fwd.nextId().byteValue()));
-        PiAction nextIdAction = PiAction.builder()
-                .withId(FabricConstants.ACT_FORWARDING_POP_MPLS_AND_NEXT_ID)
-                .withParameter(nextIdParam)
-                .build();
-        TrafficTreatment treatment = DefaultTrafficTreatment.builder()
-                .piTableAction(nextIdAction)
-                .build();
-
         FlowRule flowRule = DefaultFlowRule.builder()
                 .withSelector(selector)
                 .withTreatment(treatment)
@@ -286,6 +279,13 @@
         resultBuilder.addFlowRule(flowRule);
     }
 
+    /**
+     * Builds treatment with set_next_id action, returns empty treatment
+     * if next id is null.
+     *
+     * @param nextId the next id for action
+     * @return treatment with set_next_id action; empty treatment if next id is null
+     */
     private static TrafficTreatment buildSetNextIdTreatment(Integer nextId) {
         PiActionParam nextIdParam = new PiActionParam(FabricConstants.ACT_PRM_NEXT_ID_ID,
                                                       ImmutableByteSequence.copyFrom(nextId.byteValue()));