Bug 1588 - OFConstants.java moved to openflowplugin-api module
[openflowplugin.git] / openflowplugin / src / main / java / org / opendaylight / openflowplugin / openflow / md / core / sal / convertor / FlowConvertor.java
1 /**
2  * Copyright (c) 2013 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 com.google.common.base.Objects;
12 import com.google.common.base.Optional;
13 import com.google.common.collect.Ordering;
14 import org.opendaylight.openflowplugin.api.OFConstants;
15 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.OrderComparator;
16 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flowflag.FlowFlagReactor;
17 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.MatchReactor;
18 import org.opendaylight.openflowplugin.openflow.md.util.ByteUtil;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.VlanCfi;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCase;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCaseBuilder;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdActionCase;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.push.vlan.action._case.PushVlanActionBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlow;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlowBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ClearActionsCase;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.GoToTableCase;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.MeterCase;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteActionsCase;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteMetadataCase;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActions;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.clear.actions._case.ClearActions;
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.VlanMatchBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ActionsInstruction;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ActionsInstructionBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MetadataInstruction;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MetadataInstructionBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MeterIdInstruction;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MeterIdInstructionBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.TableIdInstruction;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.TableIdInstructionBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.actions.grouping.Action;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instructions.grouping.Instruction;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instructions.grouping.InstructionBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowModCommand;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MatchTypeBase;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortNumber;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.TableId;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.OxmMatchType;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.oxm.fields.grouping.MatchEntries;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowModInputBuilder;
71 import org.slf4j.Logger;
72 import org.slf4j.LoggerFactory;
73
74 import java.math.BigInteger;
75 import java.util.ArrayList;
76 import java.util.List;
77
78 /**
79  * Utility class for converting a MD-SAL Flow into the OF flow mod
80  */
81 public class FlowConvertor {
82     private static final Logger logger = LoggerFactory.getLogger(FlowConvertor.class);
83
84     // Default values for when things are null
85     private static final BigInteger DEFAULT_COOKIE = BigInteger.ZERO;
86     private static final BigInteger DEFAULT_COOKIE_MASK = BigInteger.ZERO;
87     private static final TableId DEFAULT_TABLE_ID = new TableId(0L);
88     private static final Integer DEFAULT_IDLE_TIMEOUT = 5 * 60;
89     private static final Integer DEFAULT_HARD_TIMEOUT = 10 * 60;
90     private static final Integer DEFAULT_PRIORITY = Integer.parseInt("8000", 16);
91     private static final Long DEFAULT_BUFFER_ID = Long.parseLong("ffffffff", 16);
92     private static final Long OFPP_ANY = Long.parseLong("ffffffff", 16);
93     private static final Long DEFAULT_OUT_PORT = OFPP_ANY;
94     private static final Long OFPG_ANY = Long.parseLong("ffffffff", 16);
95     private static final Long DEFAULT_OUT_GROUP = OFPG_ANY;
96     /** flow flag: remove */
97     public static final boolean DEFAULT_OFPFF_FLOW_REM = true;
98     /** flow flag: check overlap */
99     public static final boolean DEFAULT_OFPFF_CHECK_OVERLAP = false;
100     /** flow flag: reset counts */
101     public static final boolean DEFAULT_OFPFF_RESET_COUNTS = false;
102     /** flow flag: don't keep track of packet counts */
103     public static final boolean DEFAULT_OFPFF_NO_PKT_COUNTS = false;
104     /** flow flag: don't keep track of byte counts */
105     public static final boolean DEFAULT_OFPFF_NO_BYT_COUNTS = false;
106     /** flow flag: emergency [OFP-1.0] */
107     public static final boolean DEFAULT_OFPFF_EMERGENCY = false;
108     /** OxmMatch type */
109     public static final Class<? extends MatchTypeBase> DEFAULT_MATCH_TYPE = OxmMatchType.class;
110     /** default match entries - empty */
111     public static final List<MatchEntries> DEFAULT_MATCH_ENTRIES = new ArrayList<MatchEntries>();
112
113
114     /**
115      * This method converts the SAL Flow to OF Flow.
116      * It checks if there is a set-vlan-id (1.0) action made on OF1.3.
117      * If yes its handled separately
118      */
119     public static List<FlowModInputBuilder> toFlowModInputs(Flow srcFlow, short version, BigInteger datapathId) {
120         List<FlowModInputBuilder> list = new ArrayList<>();
121
122         if (version >= OFConstants.OFP_VERSION_1_3 && isSetVlanIdActionCasePresent(srcFlow)) {
123             list.addAll(handleSetVlanIdForOF13(srcFlow, version, datapathId));
124         } else {
125             list.add(toFlowModInput(srcFlow, version, datapathId));
126         }
127         return list;
128     }
129
130     public static FlowModInputBuilder toFlowModInput(Flow flow, short version, BigInteger datapathid) {
131
132         FlowModInputBuilder flowMod = new FlowModInputBuilder();
133         if (flow.getCookie() != null) {
134             flowMod.setCookie(flow.getCookie().getValue());
135         } else {
136             flowMod.setCookie(DEFAULT_COOKIE);
137         }
138
139         if (flow.getCookieMask() != null) {
140             flowMod.setCookieMask(flow.getCookieMask().getValue());
141         } else {
142             flowMod.setCookieMask(DEFAULT_COOKIE_MASK);
143         }
144
145         if (flow.getTableId() != null) {
146             flowMod.setTableId(new TableId(flow.getTableId().longValue()));
147         } else {
148             flowMod.setTableId(DEFAULT_TABLE_ID);
149         }
150
151         if (flow instanceof AddFlowInput) {
152             flowMod.setCommand(FlowModCommand.OFPFCADD);
153         } else if (flow instanceof RemoveFlowInput) {
154             if (Objects.firstNonNull(flow.isStrict(), Boolean.FALSE)) {
155                 flowMod.setCommand(FlowModCommand.OFPFCDELETESTRICT);
156             } else {
157                 flowMod.setCommand(FlowModCommand.OFPFCDELETE);
158             }
159         } else if (flow instanceof UpdatedFlow) {
160             if (Objects.firstNonNull(flow.isStrict(), Boolean.FALSE)) {
161                 flowMod.setCommand(FlowModCommand.OFPFCMODIFYSTRICT);
162             } else {
163                 flowMod.setCommand(FlowModCommand.OFPFCMODIFY);
164             }
165         }
166
167         if (flow.getIdleTimeout() != null) {
168             flowMod.setIdleTimeout(flow.getIdleTimeout());
169         } else {
170             flowMod.setIdleTimeout(DEFAULT_IDLE_TIMEOUT);
171         }
172         if (flow.getHardTimeout() != null) {
173             flowMod.setHardTimeout(flow.getHardTimeout());
174         } else {
175             flowMod.setHardTimeout(DEFAULT_HARD_TIMEOUT);
176         }
177         if (flow.getPriority() != null) {
178             flowMod.setPriority(flow.getPriority());
179         } else {
180             flowMod.setPriority(DEFAULT_PRIORITY);
181         }
182         if (flow.getBufferId() != null) {
183             flowMod.setBufferId(flow.getBufferId());
184         } else {
185             flowMod.setBufferId(DEFAULT_BUFFER_ID);
186         }
187
188         if (flow.getOutPort() != null) {
189             flowMod.setOutPort(new PortNumber(flow.getOutPort().longValue()));
190         } else {
191             flowMod.setOutPort(new PortNumber(DEFAULT_OUT_PORT));
192         }
193         if (flow.getOutGroup() != null) {
194             flowMod.setOutGroup(flow.getOutGroup());
195         } else {
196             flowMod.setOutGroup(DEFAULT_OUT_GROUP);
197         }
198
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.getInstructions(), version,datapathid));
208             flowMod.setAction(getActions(flow.getInstructions(), version,datapathid));
209         }
210         flowMod.setVersion(version);
211         
212         return flowMod;
213     }
214
215     private static List<Instruction> toInstructions(
216             org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions instructions,
217             short version,BigInteger datapathid) {
218         List<Instruction> instructionsList = new ArrayList<>();
219
220         for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction instruction : instructions
221                 .getInstruction()) {
222             InstructionBuilder instructionBuilder = new InstructionBuilder();
223             org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curInstruction = instruction
224                     .getInstruction();
225             if (curInstruction instanceof GoToTableCase) {
226                 GoToTableCase goToTablecase = (GoToTableCase) curInstruction;
227                 GoToTable goToTable = goToTablecase.getGoToTable();
228                 instructionBuilder
229                         .setType(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.GotoTable.class);
230                 TableIdInstructionBuilder tableBuilder = new TableIdInstructionBuilder();
231                 tableBuilder.setTableId(goToTable.getTableId());
232                 instructionBuilder.addAugmentation(TableIdInstruction.class, tableBuilder.build());
233                 instructionsList.add(instructionBuilder.build());
234             }
235
236             else if (curInstruction instanceof WriteMetadataCase) {
237                 WriteMetadataCase writeMetadatacase = (WriteMetadataCase) curInstruction;
238                 WriteMetadata writeMetadata = writeMetadatacase.getWriteMetadata();
239                 instructionBuilder
240                         .setType(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.WriteMetadata.class);
241                 MetadataInstructionBuilder metadataBuilder = new MetadataInstructionBuilder();
242                 metadataBuilder.setMetadata(ByteUtil.convertBigIntegerToNBytes(writeMetadata.getMetadata(),
243                                                                                OFConstants.SIZE_OF_LONG_IN_BYTES));
244                 metadataBuilder
245                         .setMetadataMask(ByteUtil.convertBigIntegerToNBytes(writeMetadata.getMetadataMask(),
246                                                                             OFConstants.SIZE_OF_LONG_IN_BYTES));
247                 instructionBuilder.addAugmentation(MetadataInstruction.class, metadataBuilder.build());
248                 instructionsList.add(instructionBuilder.build());
249             }
250
251             else if (curInstruction instanceof WriteActionsCase) {
252                 WriteActionsCase writeActionscase = (WriteActionsCase) curInstruction;
253                 WriteActions writeActions = writeActionscase.getWriteActions();
254                 instructionBuilder
255                         .setType(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.WriteActions.class);
256                 ActionsInstructionBuilder actionsInstructionBuilder = new ActionsInstructionBuilder();
257                 actionsInstructionBuilder.setAction(ActionConvertor.getActions(writeActions.getAction(),
258                         version,datapathid));
259                 instructionBuilder.addAugmentation(ActionsInstruction.class, actionsInstructionBuilder.build());
260                 instructionsList.add(instructionBuilder.build());
261             }
262
263             else if (curInstruction instanceof ApplyActionsCase) {
264                 ApplyActionsCase applyActionscase = (ApplyActionsCase) curInstruction;
265                 ApplyActions applyActions = applyActionscase.getApplyActions();
266                 instructionBuilder
267                         .setType(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.ApplyActions.class);
268                 ActionsInstructionBuilder actionsInstructionBuilder = new ActionsInstructionBuilder();
269                 actionsInstructionBuilder.setAction(ActionConvertor.getActions(applyActions.getAction(),
270                         version,datapathid));
271                 instructionBuilder.addAugmentation(ActionsInstruction.class, actionsInstructionBuilder.build());
272                 instructionsList.add(instructionBuilder.build());
273             }
274
275             else if (curInstruction instanceof ClearActionsCase) {
276                 ClearActionsCase clearActionscase = (ClearActionsCase) curInstruction;
277                 ClearActions clearActions = clearActionscase.getClearActions();
278                 instructionBuilder
279                         .setType(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.ClearActions.class);
280                 instructionsList.add(instructionBuilder.build());
281             }
282
283             else if (curInstruction instanceof MeterCase) {
284                 MeterCase metercase = (MeterCase) curInstruction;
285                 Meter meter = metercase.getMeter();
286                 instructionBuilder
287                         .setType(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.Meter.class);
288                 MeterIdInstructionBuilder meterBuilder = new MeterIdInstructionBuilder();
289                 Long meterId = meter.getMeterId().getValue();
290                 meterBuilder.setMeterId(meterId);
291                 instructionBuilder.addAugmentation(MeterIdInstruction.class, meterBuilder.build());
292                 instructionsList.add(instructionBuilder.build());
293             }
294         }
295         return instructionsList;
296     }
297     
298     private static List<Action> getActions(
299             org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions instructions,
300             short version,BigInteger datapathid) {
301
302         List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction> sortedInstructions =
303             Ordering.from(OrderComparator.<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction>toInstance())
304                 .sortedCopy(instructions.getInstruction());
305
306         for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction instruction : sortedInstructions) {
307             org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curInstruction = instruction
308                     .getInstruction();
309
310             if (curInstruction instanceof ApplyActionsCase) {
311                 ApplyActionsCase applyActionscase = (ApplyActionsCase) curInstruction;
312                 ApplyActions applyActions = applyActionscase.getApplyActions();
313                 return ActionConvertor.getActions(applyActions.getAction(), version,datapathid);
314             }
315         }
316         return null;
317     }
318
319     // check if set vlanid action is present in the flow
320     private static boolean isSetVlanIdActionCasePresent(Flow flow) {
321         boolean isPresent = false;
322         // we are trying to find if there is a set-vlan-id action (OF1.0) action present in the flow.
323         // If yes,then we would need to two flows
324         if (flow.getInstructions() != null) {
325             for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction instruction :
326                 flow.getInstructions().getInstruction()) {
327                 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curInstruction =
328                     instruction.getInstruction();
329
330                 if (curInstruction instanceof ApplyActionsCase) {
331                     ApplyActionsCase applyActionscase = (ApplyActionsCase) curInstruction;
332                     ApplyActions applyActions = applyActionscase.getApplyActions();
333                     for (org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action action :
334                             applyActions.getAction()) {
335                         if (action.getAction() instanceof SetVlanIdActionCase) {
336                             isPresent = true;
337                             break;
338                         }
339                     }
340                 }
341             }
342         }
343         return isPresent;
344     }
345
346
347     /**
348      * A) If user provided flow's match includes vlan match Â and action has set_vlan_field
349      * Install following rules
350      *  Â 1) match on (OFPVID_PRESENT |value) without mask + action [set_field]
351      *
352      * B) if user provided flow's match doesn't include vlan match but action has set_vlan field
353      *  Â  1) Match on (OFPVID_NONE ) without mask + action [push vlan tag + set_field]
354      *  Â  2) Match on (OFPVID_PRESENT) with mask (OFPVID_PRESENT ) + action [ set_field]
355      */
356     private static List<FlowModInputBuilder> handleSetVlanIdForOF13(Flow srcFlow, short version, BigInteger datapathId) {
357         List<FlowModInputBuilder> list = new ArrayList<>();
358
359         boolean hasVlanMatch = (srcFlow.getMatch() != null && srcFlow.getMatch().getVlanMatch() != null);
360         if (hasVlanMatch) {
361             //create flow with setfield and match
362             // match on vlan tag or vlanid with no mask
363             VlanMatchBuilder vlanMatchBuilder = new VlanMatchBuilder();
364             VlanIdBuilder vlanIdBuilder = new VlanIdBuilder();
365             vlanIdBuilder.setVlanIdPresent(true);
366             vlanIdBuilder.setVlanId(srcFlow.getMatch().getVlanMatch().getVlanId().getVlanId());
367             vlanMatchBuilder.setVlanId(vlanIdBuilder.build());
368             Match match = new MatchBuilder().setVlanMatch(vlanMatchBuilder.build()).build();
369
370             Optional<? extends Flow> optional = injectMatchToFlow(srcFlow, match);
371             if (optional.isPresent()) {
372                 list.add(toFlowModInput(optional.get(), version, datapathId));
373             }
374         } else {
375             // create 2 flows
376             //flow 1
377             // match on no vlan tag with no mask
378             VlanMatchBuilder vlanMatchBuilder = new VlanMatchBuilder();
379             VlanIdBuilder vlanIdBuilder = new VlanIdBuilder();
380             vlanIdBuilder.setVlanIdPresent(false);
381             vlanIdBuilder.setVlanId(new VlanId(0));
382             vlanMatchBuilder.setVlanId(vlanIdBuilder.build());
383             Match match1 = new MatchBuilder().setVlanMatch(vlanMatchBuilder.build()).build();
384
385             Optional<? extends Flow> optional1 = injectMatchAndAction(srcFlow, match1);
386             if (optional1.isPresent()) {
387                 list.add(toFlowModInput(optional1.get(), version, datapathId));
388             }
389
390             //flow2
391             // match on vlan tag with mask
392             VlanMatchBuilder vlanMatchBuilder2 = new VlanMatchBuilder();
393             VlanIdBuilder vlanIdBuilder2 = new VlanIdBuilder();
394             vlanIdBuilder2.setVlanIdPresent(true);
395             vlanIdBuilder2.setVlanId(new VlanId(0));
396             vlanMatchBuilder2.setVlanId(vlanIdBuilder2.build());
397             Match match2 = new MatchBuilder().setVlanMatch(vlanMatchBuilder2.build()).build();
398             Optional<? extends Flow> optional2 = injectMatchToFlow(srcFlow, match2);
399             if (optional2.isPresent()) {
400                 list.add(toFlowModInput(optional2.get(), version, datapathId));
401             }
402         }
403         return list;
404     }
405
406
407     private static Optional<? extends Flow> injectMatchToFlow(Flow sourceFlow, Match match) {
408         if (sourceFlow instanceof AddFlowInput) {
409             return Optional.<AddFlowInput>of(new AddFlowInputBuilder(sourceFlow).setMatch(match).build());
410         } else if (sourceFlow instanceof RemoveFlowInput) {
411             return Optional.<RemoveFlowInput>of(new RemoveFlowInputBuilder(sourceFlow).setMatch(match).build());
412         } else if (sourceFlow instanceof UpdatedFlow) {
413             return Optional.<UpdatedFlow>of(new UpdatedFlowBuilder(sourceFlow).setMatch(match).build());
414         } else {
415             return Optional.<Flow>absent();
416         }
417     }
418
419     private static Optional<? extends Flow> injectMatchAndAction(Flow sourceFlow, Match match) {
420
421         Instructions instructions = (new InstructionsBuilder())
422             .setInstruction(injectPushActionToInstruction(sourceFlow))
423             .build();
424
425         if (sourceFlow instanceof AddFlowInput) {
426             return Optional.<AddFlowInput>of(new AddFlowInputBuilder(sourceFlow)
427                 .setMatch(match).setInstructions(instructions).build());
428         } else if (sourceFlow instanceof RemoveFlowInput) {
429             return Optional.<RemoveFlowInput>of(new RemoveFlowInputBuilder(sourceFlow)
430                 .setMatch(match).setInstructions(instructions).build());
431         } else if (sourceFlow instanceof UpdatedFlow) {
432             return Optional.<UpdatedFlow>of(new UpdatedFlowBuilder(sourceFlow)
433                 .setMatch(match).setInstructions(instructions).build());
434         } else {
435             return Optional.<Flow>absent();
436         }
437     }
438
439     private static List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction>
440         injectPushActionToInstruction(final Flow sourceFlow) {
441
442         List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction> srcInstructionList =
443             sourceFlow.getInstructions().getInstruction();
444
445         List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction> targetInstructionList = new ArrayList<>(srcInstructionList.size());
446         List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> targetActionList = new ArrayList<>();
447
448         for (int i=0; i < srcInstructionList.size(); i++) {
449             org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction srcInstruction = srcInstructionList.get(i);
450             org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curSrcInstruction = srcInstruction.getInstruction();
451
452             if (curSrcInstruction instanceof ApplyActionsCase) {
453                 ApplyActionsCase applyActionscase = (ApplyActionsCase) curSrcInstruction;
454                 ApplyActions applyActions = applyActionscase.getApplyActions();
455                 List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> srcActionList = applyActions.getAction();
456
457                 boolean orderIncrement = false;
458                 for (int j=0; j < srcActionList.size(); j++) {
459                     // check if its a set-vlan-action. If yes, then add the injected-action
460
461                     if(srcActionList.get(j).getAction() instanceof SetVlanIdActionCase) {
462                         SetVlanIdActionCase setVlanIdActionCase = (SetVlanIdActionCase) srcActionList.get(j).getAction();
463
464                         PushVlanActionCaseBuilder pushVlanActionCaseBuilder = new PushVlanActionCaseBuilder();
465                         PushVlanActionBuilder pushVlanActionBuilder = new PushVlanActionBuilder();
466
467                         pushVlanActionBuilder.setCfi(new VlanCfi(1))
468                             .setVlanId(setVlanIdActionCase.getSetVlanIdAction().getVlanId())
469                             .setEthernetType(sourceFlow.getMatch().getEthernetMatch()
470                                 .getEthernetType().getType().getValue().intValue())
471                             .setTag(sourceFlow.getMatch().getEthernetMatch()
472                                 .getEthernetType().getType().getValue().intValue());
473                         pushVlanActionCaseBuilder.setPushVlanAction(pushVlanActionBuilder.build());
474                         PushVlanActionCase injectedAction = pushVlanActionCaseBuilder.build();
475
476                         org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder actionBuilder = new ActionBuilder();
477                         actionBuilder.setAction(injectedAction)
478                             .setKey(srcActionList.get(j).getKey())
479                             .setOrder(srcActionList.get(j).getOrder());
480
481                         targetActionList.add(actionBuilder.build());
482
483                         orderIncrement = true;
484                     }
485
486                     if (orderIncrement) {
487                         // we need to increment the order for all the actions added after injection
488                         org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder actionBuilder =
489                             new org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder(srcActionList.get(j));
490                         actionBuilder.setOrder(srcActionList.get(j).getOrder() + 1);
491                         targetActionList.add(actionBuilder.build());
492                     } else {
493                         targetActionList.add(srcActionList.get(j));
494                     }
495                 }
496
497                 ApplyActionsCaseBuilder applyActionsCaseBuilder = new ApplyActionsCaseBuilder();
498                 ApplyActionsBuilder applyActionsBuilder = new ApplyActionsBuilder();
499                 applyActionsBuilder.setAction(targetActionList);
500                 applyActionsCaseBuilder.setApplyActions(applyActionsBuilder.build());
501
502                 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder builder =
503                     new org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder();
504
505                 targetInstructionList.add(
506                     builder.setKey(srcInstruction.getKey())
507                         .setOrder(srcInstruction.getOrder())
508                         .setInstruction(applyActionsCaseBuilder.build())
509                         .build());
510
511
512             } else {
513                 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder builder =
514                     new org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder();
515                 targetInstructionList.add(
516                     builder.setKey(srcInstruction.getKey())
517                         .setOrder(srcInstruction.getOrder())
518                         .setInstruction(curSrcInstruction)
519                         .build());
520             }
521         }
522
523         return targetInstructionList;
524     }
525
526 }