Fix checkstyle error for java 8 build success
[openflowplugin.git] / openflowplugin / src / main / java / org / opendaylight / openflowplugin / openflow / md / core / sal / convertor / FlowConvertor.java
1 /**
2  * Copyright (c) 2013, 2015 Ericsson. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.openflowplugin.openflow.md.core.sal.convertor;
10
11 import java.math.BigInteger;
12 import java.util.ArrayList;
13 import java.util.Collections;
14 import java.util.List;
15 import org.opendaylight.openflowplugin.api.OFConstants;
16 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.OrderComparator;
17 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flowflag.FlowFlagReactor;
18 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.MatchReactor;
19 import org.opendaylight.openflowplugin.openflow.md.util.ByteUtil;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.VlanCfi;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCase;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCaseBuilder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdActionCase;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.push.vlan.action._case.PushVlanActionBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlow;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlowBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ClearActionsCase;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.GoToTableCase;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.MeterCase;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteActionsCase;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteMetadataCase;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActions;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.go.to.table._case.GoToTable;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.meter._case.Meter;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.actions._case.WriteActions;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.metadata._case.WriteMetadata;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatch;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.actions.grouping.Action;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.ClearActionsCaseBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.GotoTableCaseBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.MeterCaseBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.WriteActionsCaseBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.WriteMetadataCaseBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice._goto.table._case.GotoTableBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.meter._case.MeterBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.write.actions._case.WriteActionsBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.write.metadata._case.WriteMetadataBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instructions.grouping.Instruction;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instructions.grouping.InstructionBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowModCommand;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MatchTypeBase;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortNumber;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.TableId;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.OxmMatchType;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntry;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowModInputBuilder;
73 import org.slf4j.Logger;
74 import org.slf4j.LoggerFactory;
75 import com.google.common.base.MoreObjects;
76 import com.google.common.base.Optional;
77 import com.google.common.base.Preconditions;
78 import com.google.common.collect.Ordering;
79
80 /**
81  * Utility class for converting a MD-SAL Flow into the OF flow mod
82  */
83 public class FlowConvertor {
84     private static final Logger LOG = LoggerFactory.getLogger(FlowConvertor.class);
85
86     // Default values for when things are null
87     private static final TableId DEFAULT_TABLE_ID = new TableId(0L);
88     /**
89      * Default idle timeout
90      */
91     public static final Integer DEFAULT_IDLE_TIMEOUT = 0;
92     /**
93      * Default hard timeout
94      */
95     public static final Integer DEFAULT_HARD_TIMEOUT = 0;
96     /**
97      * Default priority
98      */
99     public static final Integer DEFAULT_PRIORITY = Integer.parseInt("8000", 16);
100     private static final Long DEFAULT_BUFFER_ID = OFConstants.OFP_NO_BUFFER;
101     private static final Long OFPP_ANY = Long.parseLong("ffffffff", 16);
102     private static final Long DEFAULT_OUT_PORT = OFPP_ANY;
103     private static final Long OFPG_ANY = Long.parseLong("ffffffff", 16);
104     private static final Long DEFAULT_OUT_GROUP = OFPG_ANY;
105     /**
106      * flow flag: remove
107      */
108     public static final boolean DEFAULT_OFPFF_FLOW_REM = false;
109     /**
110      * flow flag: check overlap
111      */
112     public static final boolean DEFAULT_OFPFF_CHECK_OVERLAP = false;
113     /**
114      * flow flag: reset counts
115      */
116     public static final boolean DEFAULT_OFPFF_RESET_COUNTS = false;
117     /**
118      * flow flag: don't keep track of packet counts
119      */
120     public static final boolean DEFAULT_OFPFF_NO_PKT_COUNTS = false;
121     /**
122      * flow flag: don't keep track of byte counts
123      */
124     public static final boolean DEFAULT_OFPFF_NO_BYT_COUNTS = false;
125     /**
126      * flow flag: emergency [OFP-1.0]
127      */
128     public static final boolean DEFAULT_OFPFF_EMERGENCY = false;
129     /**
130      * OxmMatch type
131      */
132     public static final Class<? extends MatchTypeBase> DEFAULT_MATCH_TYPE = OxmMatchType.class;
133     /**
134      * default match entries - empty
135      */
136     public static final List<MatchEntry> DEFAULT_MATCH_ENTRIES = new ArrayList<MatchEntry>();
137     private static final Integer PUSH_VLAN = 0x8100;
138
139     private static final Ordering<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction> INSTRUCTION_ORDERING =
140             Ordering.from(OrderComparator.<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction>build());
141
142     private static final VlanMatch VLAN_MATCH_FALSE;
143     private static final VlanMatch VLAN_MATCH_TRUE;
144
145     static {
146         final VlanId zeroVlan = new VlanId(0);
147         VlanMatchBuilder vlanMatchBuilder = new VlanMatchBuilder();
148         VlanIdBuilder vlanIdBuilder = new VlanIdBuilder();
149         vlanIdBuilder.setVlanIdPresent(false);
150         vlanIdBuilder.setVlanId(zeroVlan);
151         vlanMatchBuilder.setVlanId(vlanIdBuilder.build());
152
153         VLAN_MATCH_FALSE = vlanMatchBuilder.build();
154
155         VlanMatchBuilder vlanMatchBuilder2 = new VlanMatchBuilder();
156         VlanIdBuilder vlanIdBuilder2 = new VlanIdBuilder();
157         vlanIdBuilder2.setVlanIdPresent(true);
158         vlanIdBuilder2.setVlanId(zeroVlan);
159         vlanMatchBuilder2.setVlanId(vlanIdBuilder2.build());
160
161         VLAN_MATCH_TRUE = vlanMatchBuilder2.build();
162     }
163
164     private FlowConvertor() {
165         //hiding implicit constructor
166     }
167
168     /**
169      * This method converts the SAL Flow to OF Flow.
170      * It checks if there is a set-vlan-id (1.0) action made on OF1.3.
171      * If yes its handled separately
172      *
173      * @param srcFlow source flow
174      * @param version openflow version
175      * @param datapathId datapath id
176      * @return list of flow mod build
177      */
178     public static List<FlowModInputBuilder> toFlowModInputs(Flow srcFlow, short version, BigInteger datapathId) {
179         if (version >= OFConstants.OFP_VERSION_1_3 && isSetVlanIdActionCasePresent(srcFlow)) {
180             return handleSetVlanIdForOF13(srcFlow, version, datapathId);
181         } else {
182             return Collections.singletonList(toFlowModInput(srcFlow, version, datapathId));
183         }
184     }
185
186     private static FlowModInputBuilder toFlowModInput(Flow flow, short version, BigInteger datapathid) {
187
188         FlowModInputBuilder flowMod = new FlowModInputBuilder();
189         salToOFFlowCookie(flow, flowMod);
190         salToOFFlowCookieMask(flow, flowMod);
191         salToOFFlowTableId(flow, flowMod);
192         salToOFFlowCommand(flow, flowMod);
193         salToOFFlowIdleTimeout(flow, flowMod);
194         salToOFFlowHardTimeout(flow, flowMod);
195         salToOFFlowPriority(flow, flowMod);
196         salToOFFlowBufferId(flow, flowMod);
197         salToOFFlowOutPort(flow, flowMod);
198         salToOFFlowOutGroup(flow, flowMod);
199
200         // convert and inject flowFlags
201         FlowFlagReactor.getInstance().convert(flow.getFlags(), version, flowMod, datapathid);
202
203         // convert and inject match
204         MatchReactor.getInstance().convert(flow.getMatch(), version, flowMod, datapathid);
205
206         if (flow.getInstructions() != null) {
207             flowMod.setInstruction(toInstructions(flow, version, datapathid));
208             flowMod.setAction(getActions(version, datapathid, flow));
209         }
210         flowMod.setVersion(version);
211
212         return flowMod;
213     }
214
215     private static void salToOFFlowOutGroup(Flow flow, FlowModInputBuilder flowMod) {
216         if (flow.getOutGroup() != null) {
217             flowMod.setOutGroup(flow.getOutGroup());
218         } else {
219             flowMod.setOutGroup(DEFAULT_OUT_GROUP);
220         }
221     }
222
223     private static void salToOFFlowOutPort(Flow flow, FlowModInputBuilder flowMod) {
224         if (flow.getOutPort() != null) {
225             flowMod.setOutPort(new PortNumber(flow.getOutPort().longValue()));
226         } else {
227             flowMod.setOutPort(new PortNumber(DEFAULT_OUT_PORT));
228         }
229     }
230
231     private static void salToOFFlowBufferId(Flow flow, FlowModInputBuilder flowMod) {
232         if (flow.getBufferId() != null) {
233             flowMod.setBufferId(flow.getBufferId());
234         } else {
235             flowMod.setBufferId(DEFAULT_BUFFER_ID);
236         }
237     }
238
239     private static void salToOFFlowPriority(Flow flow, FlowModInputBuilder flowMod) {
240         if (flow.getPriority() != null) {
241             flowMod.setPriority(flow.getPriority());
242         } else {
243             flowMod.setPriority(DEFAULT_PRIORITY);
244         }
245     }
246
247     private static void salToOFFlowHardTimeout(Flow flow, FlowModInputBuilder flowMod) {
248         if (flow.getHardTimeout() != null) {
249             flowMod.setHardTimeout(flow.getHardTimeout());
250         } else {
251             flowMod.setHardTimeout(DEFAULT_HARD_TIMEOUT);
252         }
253     }
254
255     private static void salToOFFlowIdleTimeout(Flow flow, FlowModInputBuilder flowMod) {
256         if (flow.getIdleTimeout() != null) {
257             flowMod.setIdleTimeout(flow.getIdleTimeout());
258         } else {
259             flowMod.setIdleTimeout(DEFAULT_IDLE_TIMEOUT);
260         }
261     }
262
263     private static void salToOFFlowCommand(Flow flow, FlowModInputBuilder flowMod) {
264         if (flow instanceof AddFlowInput) {
265             flowMod.setCommand(FlowModCommand.OFPFCADD);
266         } else if (flow instanceof RemoveFlowInput) {
267             if (MoreObjects.firstNonNull(flow.isStrict(), Boolean.FALSE)) {
268                 flowMod.setCommand(FlowModCommand.OFPFCDELETESTRICT);
269             } else {
270                 flowMod.setCommand(FlowModCommand.OFPFCDELETE);
271             }
272         } else if (flow instanceof UpdatedFlow) {
273             if (MoreObjects.firstNonNull(flow.isStrict(), Boolean.FALSE)) {
274                 flowMod.setCommand(FlowModCommand.OFPFCMODIFYSTRICT);
275             } else {
276                 flowMod.setCommand(FlowModCommand.OFPFCMODIFY);
277             }
278         }
279     }
280
281     private static void salToOFFlowTableId(Flow flow, FlowModInputBuilder flowMod) {
282         if (flow.getTableId() != null) {
283             flowMod.setTableId(new TableId(flow.getTableId().longValue()));
284         } else {
285             flowMod.setTableId(DEFAULT_TABLE_ID);
286         }
287     }
288
289     private static void salToOFFlowCookieMask(Flow flow, FlowModInputBuilder flowMod) {
290         if (flow.getCookieMask() != null) {
291             flowMod.setCookieMask(flow.getCookieMask().getValue());
292         } else {
293             flowMod.setCookieMask(OFConstants.DEFAULT_COOKIE_MASK);
294         }
295     }
296
297     private static void salToOFFlowCookie(Flow flow, FlowModInputBuilder flowMod) {
298         if (flow.getCookie() != null) {
299             flowMod.setCookie(flow.getCookie().getValue());
300         } else {
301             flowMod.setCookie(OFConstants.DEFAULT_COOKIE);
302         }
303     }
304
305     private static List<Instruction> toInstructions(
306             Flow flow,
307             short version, BigInteger datapathid) {
308         List<Instruction> instructionsList = new ArrayList<>();
309
310         org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions instructions = flow.getInstructions();
311         for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction instruction : instructions
312                 .getInstruction()) {
313             InstructionBuilder instructionBuilder = new InstructionBuilder();
314             org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curInstruction = instruction
315                     .getInstruction();
316             if (curInstruction instanceof GoToTableCase) {
317                 GoToTableCase goToTablecase = (GoToTableCase) curInstruction;
318                 GoToTable goToTable = goToTablecase.getGoToTable();
319                 GotoTableCaseBuilder gotoTableCaseBuilder = new GotoTableCaseBuilder();
320                 GotoTableBuilder gotoTableBuilder = new GotoTableBuilder();
321                 gotoTableBuilder.setTableId(goToTable.getTableId());
322                 gotoTableCaseBuilder.setGotoTable(gotoTableBuilder.build());
323                 instructionBuilder.setInstructionChoice(gotoTableCaseBuilder.build());
324                 instructionsList.add(instructionBuilder.build());
325             } else if (curInstruction instanceof WriteMetadataCase) {
326                 WriteMetadataCase writeMetadatacase = (WriteMetadataCase) curInstruction;
327                 WriteMetadata writeMetadata = writeMetadatacase.getWriteMetadata();
328
329                 WriteMetadataCaseBuilder writeMetadataCaseBuilder = new WriteMetadataCaseBuilder();
330                 WriteMetadataBuilder writeMetadataBuilder = new WriteMetadataBuilder();
331                 writeMetadataBuilder.setMetadata(ByteUtil.convertBigIntegerToNBytes(writeMetadata.getMetadata(),
332                                                                              OFConstants.SIZE_OF_LONG_IN_BYTES));
333                 writeMetadataBuilder.setMetadataMask(ByteUtil.convertBigIntegerToNBytes(writeMetadata.getMetadataMask(),
334                                                                                      OFConstants.SIZE_OF_LONG_IN_BYTES));
335                 writeMetadataCaseBuilder.setWriteMetadata(writeMetadataBuilder.build());
336                 instructionBuilder.setInstructionChoice(writeMetadataCaseBuilder.build());
337                 instructionsList.add(instructionBuilder.build());
338             } else if (curInstruction instanceof WriteActionsCase) {
339                 WriteActionsCase writeActionscase = (WriteActionsCase) curInstruction;
340                 WriteActions writeActions = writeActionscase.getWriteActions();
341                 WriteActionsCaseBuilder writeActionsCaseBuilder = new WriteActionsCaseBuilder();
342                 WriteActionsBuilder writeActionsBuilder = new WriteActionsBuilder();
343                 writeActionsBuilder.setAction(ActionConvertor.getActions(writeActions.getAction(),version, datapathid, flow));
344                 writeActionsCaseBuilder.setWriteActions(writeActionsBuilder.build());
345                 instructionBuilder.setInstructionChoice(writeActionsCaseBuilder.build());
346                 instructionsList.add(instructionBuilder.build());
347             } else if (curInstruction instanceof ApplyActionsCase) {
348                 ApplyActionsCase applyActionscase = (ApplyActionsCase) curInstruction;
349                 ApplyActions applyActions = applyActionscase.getApplyActions();
350                 org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.ApplyActionsCaseBuilder applyActionsCaseBuilder =
351                         new org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.ApplyActionsCaseBuilder();
352                 org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.apply.actions._case.ApplyActionsBuilder applyActionsBuilder =
353                         new org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.apply.actions._case.ApplyActionsBuilder();
354                 applyActionsBuilder.setAction(ActionConvertor.getActions(applyActions.getAction(), version, datapathid, flow));
355                 applyActionsCaseBuilder.setApplyActions(applyActionsBuilder.build());
356                 instructionBuilder.setInstructionChoice(applyActionsCaseBuilder.build());
357                 instructionsList.add(instructionBuilder.build());
358             } else if (curInstruction instanceof ClearActionsCase) {
359                 ClearActionsCaseBuilder clearActionsCaseBuilder = new ClearActionsCaseBuilder();
360                 instructionBuilder.setInstructionChoice(clearActionsCaseBuilder.build());
361                 instructionsList.add(instructionBuilder.build());
362             } else if (curInstruction instanceof MeterCase) {
363                 MeterCase metercase = (MeterCase) curInstruction;
364                 Meter meter = metercase.getMeter();
365                 MeterCaseBuilder meterCaseBuilder = new MeterCaseBuilder();
366                 MeterBuilder meterBuilder = new MeterBuilder();
367                 Long meterId = meter.getMeterId().getValue();
368                 meterBuilder.setMeterId(meterId);
369                 meterCaseBuilder.setMeter(meterBuilder.build());
370                 instructionBuilder.setInstructionChoice(meterCaseBuilder.build());
371                 instructionsList.add(instructionBuilder.build());
372             }
373         }
374         return instructionsList;
375     }
376
377     private static List<Action> getActions(short version, BigInteger datapathid, Flow flow) {
378
379         org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions instructions = flow.getInstructions();
380         List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction> sortedInstructions =
381                 INSTRUCTION_ORDERING.sortedCopy(instructions.getInstruction());
382
383         for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction instruction : sortedInstructions) {
384             org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curInstruction = instruction
385                     .getInstruction();
386
387             if (curInstruction instanceof ApplyActionsCase) {
388                 ApplyActionsCase applyActionscase = (ApplyActionsCase) curInstruction;
389                 ApplyActions applyActions = applyActionscase.getApplyActions();
390                 return ActionConvertor.getActions(applyActions.getAction(), version, datapathid, flow);
391             }
392         }
393         return null;
394     }
395
396     // check if set vlanid action is present in the flow
397     private static boolean isSetVlanIdActionCasePresent(Flow flow) {
398         // we are trying to find if there is a set-vlan-id action (OF1.0) action present in the flow.
399         // If yes,then we would need to two flows
400         if (flow.getInstructions() != null) {
401             for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction instruction :
402                     flow.getInstructions().getInstruction()) {
403                 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curInstruction =
404                         instruction.getInstruction();
405
406                 if (curInstruction instanceof ApplyActionsCase) {
407                     ApplyActionsCase applyActionscase = (ApplyActionsCase) curInstruction;
408                     ApplyActions applyActions = applyActionscase.getApplyActions();
409                     for (org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action action :
410                             applyActions.getAction()) {
411                         if (action.getAction() instanceof SetVlanIdActionCase) {
412                             return true;
413                         }
414                     }
415                 }
416             }
417         }
418         return false;
419     }
420
421
422     /**
423      * A) If user provided flow's match includes vlan match Â and action has set_vlan_field
424      * Install following rules
425      * Â  Â 1) match on (OFPVID_PRESENT |value) without mask + action [set_field]
426      * <p/>
427      * B) if user provided flow's match doesn't include vlan match but action has set_vlan field
428      * Â  Â  1) Match on (OFPVID_NONE ) without mask + action [push vlan tag + set_field]
429      * Â  Â  2) Match on (OFPVID_PRESENT) with mask (OFPVID_PRESENT ) + action [ set_field]
430      */
431     private static List<FlowModInputBuilder> handleSetVlanIdForOF13(Flow srcFlow, short version, BigInteger datapathId) {
432         List<FlowModInputBuilder> list = new ArrayList<>(2);
433
434         final Match srcMatch = Preconditions.checkNotNull(srcFlow.getMatch());
435         final VlanMatch srcVlanMatch = srcMatch.getVlanMatch();
436         if (srcVlanMatch != null) {
437             //create flow with setfield and match
438             // match on vlan tag or vlanid with no mask
439             VlanMatchBuilder vlanMatchBuilder = new VlanMatchBuilder(srcVlanMatch);
440             VlanIdBuilder vlanIdBuilder = new VlanIdBuilder();
441             vlanIdBuilder.setVlanIdPresent(srcVlanMatch.getVlanId().isVlanIdPresent());
442             vlanIdBuilder.setVlanId(srcVlanMatch.getVlanId().getVlanId());
443             vlanMatchBuilder.setVlanId(vlanIdBuilder.build());
444             Match match = new MatchBuilder(srcMatch).setVlanMatch(vlanMatchBuilder.build()).build();
445
446             Optional<? extends Flow> optional = injectMatchToFlow(srcFlow, match);
447             if (optional.isPresent()) {
448                 list.add(toFlowModInput(optional.get(), version, datapathId));
449             }
450         } else {
451             // create 2 flows
452             //flow 1
453             // match on no vlan tag with no mask
454             Match match1 = new MatchBuilder(srcMatch).setVlanMatch(VLAN_MATCH_FALSE).build();
455
456             Optional<? extends Flow> optional1 = injectMatchAndAction(srcFlow, match1);
457             if (optional1.isPresent()) {
458                 list.add(toFlowModInput(optional1.get(), version, datapathId));
459             }
460
461             //flow2
462             // match on vlan tag with mask
463             Match match2 = new MatchBuilder(srcMatch).setVlanMatch(VLAN_MATCH_TRUE).build();
464             Optional<? extends Flow> optional2 = injectMatchToFlow(srcFlow, match2);
465             if (optional2.isPresent()) {
466                 list.add(toFlowModInput(optional2.get(), version, datapathId));
467             }
468         }
469         return list;
470     }
471
472
473     private static Optional<? extends Flow> injectMatchToFlow(Flow sourceFlow, Match match) {
474         if (sourceFlow instanceof AddFlowInput) {
475             return Optional.<AddFlowInput>of(new AddFlowInputBuilder(sourceFlow).setMatch(match).build());
476         } else if (sourceFlow instanceof RemoveFlowInput) {
477             return Optional.<RemoveFlowInput>of(new RemoveFlowInputBuilder(sourceFlow).setMatch(match).build());
478         } else if (sourceFlow instanceof UpdatedFlow) {
479             return Optional.<UpdatedFlow>of(new UpdatedFlowBuilder(sourceFlow).setMatch(match).build());
480         } else {
481             return Optional.<Flow>absent();
482         }
483     }
484
485     private static Optional<? extends Flow> injectMatchAndAction(Flow sourceFlow, Match match) {
486
487         Instructions instructions = (new InstructionsBuilder())
488                 .setInstruction(injectPushActionToInstruction(sourceFlow))
489                 .build();
490
491         if (sourceFlow instanceof AddFlowInput) {
492             return Optional.<AddFlowInput>of(new AddFlowInputBuilder(sourceFlow)
493                     .setMatch(match).setInstructions(instructions).build());
494         } else if (sourceFlow instanceof RemoveFlowInput) {
495             return Optional.<RemoveFlowInput>of(new RemoveFlowInputBuilder(sourceFlow)
496                     .setMatch(match).setInstructions(instructions).build());
497         } else if (sourceFlow instanceof UpdatedFlow) {
498             return Optional.<UpdatedFlow>of(new UpdatedFlowBuilder(sourceFlow)
499                     .setMatch(match).setInstructions(instructions).build());
500         } else {
501             return Optional.<Flow>absent();
502         }
503     }
504
505     private static List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction>
506     injectPushActionToInstruction(final Flow sourceFlow) {
507
508         List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction> srcInstructionList =
509                 sourceFlow.getInstructions().getInstruction();
510
511         List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction> targetInstructionList = new ArrayList<>(srcInstructionList.size());
512         List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> targetActionList = new ArrayList<>();
513
514         org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder instructionBuilder =
515                 new org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder();
516
517         for (int i = 0; i < srcInstructionList.size(); i++) {
518             org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction srcInstruction =
519                     srcInstructionList.get(i);
520             org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curSrcInstruction =
521                     srcInstruction.getInstruction();
522
523             if (curSrcInstruction instanceof ApplyActionsCase) {
524                 ApplyActionsCase applyActionscase = (ApplyActionsCase) curSrcInstruction;
525                 ApplyActions applyActions = applyActionscase.getApplyActions();
526                 List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> srcActionList = applyActions.getAction();
527
528                 int offset = 0;
529                 for (int j = 0; j < srcActionList.size(); j++) {
530                     // check if its a set-vlan-action. If yes, then add the injected-action
531
532                     org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action actionItem = srcActionList.get(j);
533                     if (actionItem.getAction() instanceof SetVlanIdActionCase) {
534                         SetVlanIdActionCase setVlanIdActionCase = (SetVlanIdActionCase) actionItem.getAction();
535
536                         PushVlanActionCaseBuilder pushVlanActionCaseBuilder = new PushVlanActionCaseBuilder();
537                         PushVlanActionBuilder pushVlanActionBuilder = new PushVlanActionBuilder();
538
539                         pushVlanActionBuilder.setCfi(new VlanCfi(1))
540                                 .setVlanId(setVlanIdActionCase.getSetVlanIdAction().getVlanId())
541                                 .setEthernetType(PUSH_VLAN)
542                                 .setTag(PUSH_VLAN);
543                         pushVlanActionCaseBuilder.setPushVlanAction(pushVlanActionBuilder.build());
544                         PushVlanActionCase injectedAction = pushVlanActionCaseBuilder.build();
545
546                         org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder actionBuilder = new ActionBuilder();
547                         actionBuilder.setAction(injectedAction)
548                                 .setKey(actionItem.getKey())
549                                 .setOrder(actionItem.getOrder() + offset);
550
551                         targetActionList.add(actionBuilder.build());
552                         offset++;
553                     }
554
555                     if (offset > 0) {
556                         // we need to increment the order for all the actions added after injection
557                         org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder actionBuilder =
558                                 new org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder(actionItem);
559                         actionBuilder.setOrder(actionItem.getOrder() + offset);
560                         actionItem = actionBuilder.build();
561                     }
562
563                     targetActionList.add(actionItem);
564                 }
565
566                 ApplyActionsCaseBuilder applyActionsCaseBuilder = new ApplyActionsCaseBuilder();
567                 ApplyActionsBuilder applyActionsBuilder = new ApplyActionsBuilder();
568                 applyActionsBuilder.setAction(targetActionList);
569                 applyActionsCaseBuilder.setApplyActions(applyActionsBuilder.build());
570
571                 instructionBuilder.setInstruction(applyActionsCaseBuilder.build());
572             } else {
573                 instructionBuilder.setInstruction(curSrcInstruction);
574             }
575
576             instructionBuilder
577                     .setKey(srcInstruction.getKey())
578                     .setOrder(srcInstruction.getOrder());
579             targetInstructionList.add(instructionBuilder.build());
580
581         }
582
583         return targetInstructionList;
584     }
585
586 }