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