Bug 2369: Fixed NPE in update-flow RPC.
[openflowplugin.git] / openflowplugin / src / main / java / org / opendaylight / openflowplugin / openflow / md / core / sal / convertor / FlowConvertor.java
index ceba5276d126efa5f0c4a7c95e2e6fa22be80bb4..a9ad360cc51245988cb9570f6adfad42a36d92b4 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2013 Ericsson. and others.  All rights reserved.
+ * Copyright (c) 2013-2014 Ericsson. and others.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
@@ -11,7 +11,8 @@ package org.opendaylight.openflowplugin.openflow.md.core.sal.convertor;
 import com.google.common.base.Objects;
 import com.google.common.base.Optional;
 import com.google.common.collect.Ordering;
-import org.opendaylight.openflowplugin.openflow.md.OFConstants;
+
+import org.opendaylight.openflowplugin.api.OFConstants;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.OrderComparator;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flowflag.FlowFlagReactor;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.MatchReactor;
@@ -48,6 +49,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instru
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.actions._case.WriteActions;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.metadata._case.WriteMetadata;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatch;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ActionsInstruction;
@@ -82,12 +84,13 @@ public class FlowConvertor {
     private static final Logger logger = LoggerFactory.getLogger(FlowConvertor.class);
 
     // Default values for when things are null
-    private static final BigInteger DEFAULT_COOKIE = BigInteger.ZERO;
-    private static final BigInteger DEFAULT_COOKIE_MASK = BigInteger.ZERO;
     private static final TableId DEFAULT_TABLE_ID = new TableId(0L);
-    private static final Integer DEFAULT_IDLE_TIMEOUT = 5 * 60;
-    private static final Integer DEFAULT_HARD_TIMEOUT = 10 * 60;
-    private static final Integer DEFAULT_PRIORITY = Integer.parseInt("8000", 16);
+    /** Default idle timeout */
+    public static final Integer DEFAULT_IDLE_TIMEOUT = 5 * 60;
+    /** Default hard timeout */
+    public static final Integer DEFAULT_HARD_TIMEOUT = 10 * 60;
+    /** Default priority */
+    public static final Integer DEFAULT_PRIORITY = Integer.parseInt("8000", 16);
     private static final Long DEFAULT_BUFFER_ID = Long.parseLong("ffffffff", 16);
     private static final Long OFPP_ANY = Long.parseLong("ffffffff", 16);
     private static final Long DEFAULT_OUT_PORT = OFPP_ANY;
@@ -133,13 +136,13 @@ public class FlowConvertor {
         if (flow.getCookie() != null) {
             flowMod.setCookie(flow.getCookie().getValue());
         } else {
-            flowMod.setCookie(DEFAULT_COOKIE);
+            flowMod.setCookie(OFConstants.DEFAULT_COOKIE);
         }
 
         if (flow.getCookieMask() != null) {
             flowMod.setCookieMask(flow.getCookieMask().getValue());
         } else {
-            flowMod.setCookieMask(DEFAULT_COOKIE_MASK);
+            flowMod.setCookieMask(OFConstants.DEFAULT_COOKIE_MASK);
         }
 
         if (flow.getTableId() != null) {
@@ -204,8 +207,8 @@ public class FlowConvertor {
         MatchReactor.getInstance().convert(flow.getMatch(), version, flowMod,datapathid);
 
         if (flow.getInstructions() != null) {
-            flowMod.setInstruction(toInstructions(flow.getInstructions(), version,datapathid));
-            flowMod.setAction(getActions(flow.getInstructions(), version,datapathid));
+            flowMod.setInstruction(toInstructions(flow, version,datapathid));
+            flowMod.setAction(getActions(version,datapathid, flow));
         }
         flowMod.setVersion(version);
         
@@ -213,10 +216,11 @@ public class FlowConvertor {
     }
 
     private static List<Instruction> toInstructions(
-            org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions instructions,
+            Flow flow,
             short version,BigInteger datapathid) {
         List<Instruction> instructionsList = new ArrayList<>();
 
+        org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions instructions = flow.getInstructions();
         for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction instruction : instructions
                 .getInstruction()) {
             InstructionBuilder instructionBuilder = new InstructionBuilder();
@@ -255,7 +259,7 @@ public class FlowConvertor {
                         .setType(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.WriteActions.class);
                 ActionsInstructionBuilder actionsInstructionBuilder = new ActionsInstructionBuilder();
                 actionsInstructionBuilder.setAction(ActionConvertor.getActions(writeActions.getAction(),
-                        version,datapathid));
+                        version,datapathid, flow));
                 instructionBuilder.addAugmentation(ActionsInstruction.class, actionsInstructionBuilder.build());
                 instructionsList.add(instructionBuilder.build());
             }
@@ -267,7 +271,7 @@ public class FlowConvertor {
                         .setType(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.ApplyActions.class);
                 ActionsInstructionBuilder actionsInstructionBuilder = new ActionsInstructionBuilder();
                 actionsInstructionBuilder.setAction(ActionConvertor.getActions(applyActions.getAction(),
-                        version,datapathid));
+                        version,datapathid, flow));
                 instructionBuilder.addAugmentation(ActionsInstruction.class, actionsInstructionBuilder.build());
                 instructionsList.add(instructionBuilder.build());
             }
@@ -295,10 +299,12 @@ public class FlowConvertor {
         return instructionsList;
     }
     
-    private static List<Action> getActions(
+    /*private static List<Action> getActions(
             org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions instructions,
-            short version,BigInteger datapathid) {
-
+            short version,BigInteger datapathid) {*/
+    private static List<Action> getActions(short version,BigInteger datapathid, Flow flow) {
+        
+        org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions instructions = flow.getInstructions();
         List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction> sortedInstructions =
             Ordering.from(OrderComparator.<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction>toInstance())
                 .sortedCopy(instructions.getInstruction());
@@ -310,7 +316,7 @@ public class FlowConvertor {
             if (curInstruction instanceof ApplyActionsCase) {
                 ApplyActionsCase applyActionscase = (ApplyActionsCase) curInstruction;
                 ApplyActions applyActions = applyActionscase.getApplyActions();
-                return ActionConvertor.getActions(applyActions.getAction(), version,datapathid);
+                return ActionConvertor.getActions(applyActions.getAction(), version,datapathid, flow);
             }
         }
         return null;
@@ -356,16 +362,17 @@ public class FlowConvertor {
     private static List<FlowModInputBuilder> handleSetVlanIdForOF13(Flow srcFlow, short version, BigInteger datapathId) {
         List<FlowModInputBuilder> list = new ArrayList<>();
 
-        boolean hasVlanMatch = (srcFlow.getMatch() != null && srcFlow.getMatch().getVlanMatch() != null);
+        VlanMatch srcVlanMatch = srcFlow.getMatch().getVlanMatch();
+        boolean hasVlanMatch = (srcFlow.getMatch() != null && srcVlanMatch != null);
         if (hasVlanMatch) {
             //create flow with setfield and match
             // match on vlan tag or vlanid with no mask
-            VlanMatchBuilder vlanMatchBuilder = new VlanMatchBuilder();
+            VlanMatchBuilder vlanMatchBuilder = new VlanMatchBuilder(srcVlanMatch);
             VlanIdBuilder vlanIdBuilder = new VlanIdBuilder();
-            vlanIdBuilder.setVlanIdPresent(true);
-            vlanIdBuilder.setVlanId(srcFlow.getMatch().getVlanMatch().getVlanId().getVlanId());
+            vlanIdBuilder.setVlanIdPresent(srcVlanMatch.getVlanId().isVlanIdPresent());
+            vlanIdBuilder.setVlanId(srcVlanMatch.getVlanId().getVlanId());
             vlanMatchBuilder.setVlanId(vlanIdBuilder.build());
-            Match match = new MatchBuilder().setVlanMatch(vlanMatchBuilder.build()).build();
+            Match match = new MatchBuilder(srcFlow.getMatch()).setVlanMatch(vlanMatchBuilder.build()).build();
 
             Optional<? extends Flow> optional = injectMatchToFlow(srcFlow, match);
             if (optional.isPresent()) {
@@ -380,7 +387,7 @@ public class FlowConvertor {
             vlanIdBuilder.setVlanIdPresent(false);
             vlanIdBuilder.setVlanId(new VlanId(0));
             vlanMatchBuilder.setVlanId(vlanIdBuilder.build());
-            Match match1 = new MatchBuilder().setVlanMatch(vlanMatchBuilder.build()).build();
+            Match match1 = new MatchBuilder(srcFlow.getMatch()).setVlanMatch(vlanMatchBuilder.build()).build();
 
             Optional<? extends Flow> optional1 = injectMatchAndAction(srcFlow, match1);
             if (optional1.isPresent()) {
@@ -394,7 +401,7 @@ public class FlowConvertor {
             vlanIdBuilder2.setVlanIdPresent(true);
             vlanIdBuilder2.setVlanId(new VlanId(0));
             vlanMatchBuilder2.setVlanId(vlanIdBuilder2.build());
-            Match match2 = new MatchBuilder().setVlanMatch(vlanMatchBuilder2.build()).build();
+            Match match2 = new MatchBuilder(srcFlow.getMatch()).setVlanMatch(vlanMatchBuilder2.build()).build();
             Optional<? extends Flow> optional2 = injectMatchToFlow(srcFlow, match2);
             if (optional2.isPresent()) {
                 list.add(toFlowModInput(optional2.get(), version, datapathId));
@@ -445,21 +452,27 @@ public class FlowConvertor {
         List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction> targetInstructionList = new ArrayList<>(srcInstructionList.size());
         List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> targetActionList = new ArrayList<>();
 
+        org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder instructionBuilder =
+                new org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder();
+        
         for (int i=0; i < srcInstructionList.size(); i++) {
-            org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction srcInstruction = srcInstructionList.get(i);
-            org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curSrcInstruction = srcInstruction.getInstruction();
-
+            org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction srcInstruction = 
+                    srcInstructionList.get(i);
+            org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curSrcInstruction = 
+                    srcInstruction.getInstruction();
+            
             if (curSrcInstruction instanceof ApplyActionsCase) {
                 ApplyActionsCase applyActionscase = (ApplyActionsCase) curSrcInstruction;
                 ApplyActions applyActions = applyActionscase.getApplyActions();
                 List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> srcActionList = applyActions.getAction();
 
-                boolean orderIncrement = false;
+                int offset = 0;
                 for (int j=0; j < srcActionList.size(); j++) {
                     // check if its a set-vlan-action. If yes, then add the injected-action
 
-                    if(srcActionList.get(j).getAction() instanceof SetVlanIdActionCase) {
-                        SetVlanIdActionCase setVlanIdActionCase = (SetVlanIdActionCase) srcActionList.get(j).getAction();
+                    org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action actionItem = srcActionList.get(j);
+                    if(actionItem.getAction() instanceof SetVlanIdActionCase) {
+                        SetVlanIdActionCase setVlanIdActionCase = (SetVlanIdActionCase) actionItem.getAction();
 
                         PushVlanActionCaseBuilder pushVlanActionCaseBuilder = new PushVlanActionCaseBuilder();
                         PushVlanActionBuilder pushVlanActionBuilder = new PushVlanActionBuilder();
@@ -475,49 +488,39 @@ public class FlowConvertor {
 
                         org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder actionBuilder = new ActionBuilder();
                         actionBuilder.setAction(injectedAction)
-                            .setKey(srcActionList.get(j).getKey())
-                            .setOrder(srcActionList.get(j).getOrder());
+                            .setKey(actionItem.getKey())
+                            .setOrder(actionItem.getOrder() + offset);
 
                         targetActionList.add(actionBuilder.build());
-
-                        orderIncrement = true;
+                        offset ++;
                     }
 
-                    if (orderIncrement) {
+                    if (offset > 0) {
                         // we need to increment the order for all the actions added after injection
                         org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder actionBuilder =
-                            new org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder(srcActionList.get(j));
-                        actionBuilder.setOrder(srcActionList.get(j).getOrder() + 1);
-                        targetActionList.add(actionBuilder.build());
-                    } else {
-                        targetActionList.add(srcActionList.get(j));
+                            new org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder(actionItem);
+                        actionBuilder.setOrder(actionItem.getOrder() + offset);
+                        actionItem = actionBuilder.build();
                     }
+                    
+                    targetActionList.add(actionItem);
                 }
 
                 ApplyActionsCaseBuilder applyActionsCaseBuilder = new ApplyActionsCaseBuilder();
                 ApplyActionsBuilder applyActionsBuilder = new ApplyActionsBuilder();
                 applyActionsBuilder.setAction(targetActionList);
                 applyActionsCaseBuilder.setApplyActions(applyActionsBuilder.build());
-
-                org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder builder =
-                    new org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder();
-
-                targetInstructionList.add(
-                    builder.setKey(srcInstruction.getKey())
-                        .setOrder(srcInstruction.getOrder())
-                        .setInstruction(applyActionsCaseBuilder.build())
-                        .build());
-
-
+                    
+                instructionBuilder.setInstruction(applyActionsCaseBuilder.build());
             } else {
-                org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder builder =
-                    new org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder();
-                targetInstructionList.add(
-                    builder.setKey(srcInstruction.getKey())
-                        .setOrder(srcInstruction.getOrder())
-                        .setInstruction(curSrcInstruction)
-                        .build());
+                instructionBuilder.setInstruction(curSrcInstruction);
             }
+            
+            instructionBuilder
+                .setKey(srcInstruction.getKey())
+                .setOrder(srcInstruction.getOrder());
+            targetInstructionList.add(instructionBuilder.build());
+            
         }
 
         return targetInstructionList;