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