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