2 * Copyright (c) 2013, 2015 Ericsson. and others. All rights reserved.
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
9 package org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flow;
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.Optional;
21 import org.opendaylight.openflowplugin.api.OFConstants;
22 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.action.data.ActionConvertorData;
23 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.Convertor;
24 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.ConvertorProcessor;
25 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.OrderComparator;
26 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionDatapathIdConvertorData;
27 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flow.cases.ApplyActionsCase;
28 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flow.cases.ClearActionsCase;
29 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flow.cases.GoToTableCase;
30 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flow.cases.MeterCase;
31 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flow.cases.WriteActionsCase;
32 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flow.cases.WriteMetadataCase;
33 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.MatchInjector;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.VlanCfi;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCase;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCaseBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdActionCase;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.push.vlan.action._case.PushVlanActionBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlow;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlowBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActions;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatch;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.actions.grouping.Action;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instructions.grouping.Instruction;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowModCommand;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MatchTypeBase;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortNumber;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.TableId;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.OxmMatchType;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntry;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowModInputBuilder;
67 import org.opendaylight.yangtools.yang.common.Uint16;
68 import org.opendaylight.yangtools.yang.common.Uint32;
69 import org.opendaylight.yangtools.yang.common.Uint64;
72 * Converts the SAL Flow to OF Flow. It checks if there is a set-vlan-id (1.0) action made on OF1.3.
73 * If yes its handled separately.
79 * VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(version);
80 * data.setDatapathId(datapathId);
81 * Optional<List<FlowModInputBuilder>> ofFlow = convertorManager.convert(salFlow, data);
85 public class FlowConvertor extends Convertor<Flow, List<FlowModInputBuilder>, VersionDatapathIdConvertorData> {
87 * Default idle timeout.
89 public static final Uint16 DEFAULT_IDLE_TIMEOUT = Uint16.ZERO;
92 * Default hard timeout.
94 public static final Uint16 DEFAULT_HARD_TIMEOUT = Uint16.ZERO;
99 public static final Uint16 DEFAULT_PRIORITY = Uint16.valueOf(0x8000);
104 public static final boolean DEFAULT_OFPFF_FLOW_REM = false;
107 * flow flag: check overlap.
109 public static final boolean DEFAULT_OFPFF_CHECK_OVERLAP = false;
112 * flow flag: reset counts.
114 public static final boolean DEFAULT_OFPFF_RESET_COUNTS = false;
117 * flow flag: don't keep track of packet counts.
119 public static final boolean DEFAULT_OFPFF_NO_PKT_COUNTS = false;
122 * flow flag: don't keep track of byte counts.
124 public static final boolean DEFAULT_OFPFF_NO_BYT_COUNTS = false;
127 * flow flag: emergency [OFP-1.0].
129 public static final boolean DEFAULT_OFPFF_EMERGENCY = false;
134 public static final Class<? extends MatchTypeBase> DEFAULT_MATCH_TYPE = OxmMatchType.class;
137 * default match entries - empty.
139 public static final List<MatchEntry> DEFAULT_MATCH_ENTRIES = ImmutableList.of();
141 // Default values for when things are null
142 private static final TableId DEFAULT_TABLE_ID = new TableId(Uint32.ZERO);
143 private static final Uint32 DEFAULT_BUFFER_ID = OFConstants.OFP_NO_BUFFER;
144 private static final Uint32 OFPP_ANY = Uint32.MAX_VALUE;
145 private static final Uint32 DEFAULT_OUT_PORT = OFPP_ANY;
146 private static final Uint32 OFPG_ANY = Uint32.MAX_VALUE;
147 private static final Uint32 DEFAULT_OUT_GROUP = OFPG_ANY;
148 private static final Uint16 PUSH_VLAN = Uint16.valueOf(0x8100);
149 private static final Integer PUSH_TAG = PUSH_VLAN.toJava();
150 private static final VlanCfi PUSH_CFI = new VlanCfi(1);
151 private static final Ordering<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction
152 .list.Instruction> INSTRUCTION_ORDERING = Ordering.from(OrderComparator.build());
153 private static final VlanMatch VLAN_MATCH_FALSE;
154 private static final VlanMatch VLAN_MATCH_TRUE;
155 private static final ConvertorProcessor<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026
156 .instruction.Instruction, Instruction, ActionConvertorData> PROCESSOR =
157 new ConvertorProcessor<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026
158 .instruction.Instruction, Instruction, ActionConvertorData>()
159 .addCase(new ApplyActionsCase())
160 .addCase(new ClearActionsCase())
161 .addCase(new GoToTableCase())
162 .addCase(new MeterCase())
163 .addCase(new WriteActionsCase())
164 .addCase(new WriteMetadataCase());
166 private static final List<Class<?>> TYPES = Arrays.asList(Flow.class, AddFlowInput.class,
167 RemoveFlowInput.class, UpdatedFlow.class);
170 final VlanId zeroVlan = new VlanId(Uint16.ZERO);
171 VlanMatchBuilder vlanMatchBuilder = new VlanMatchBuilder();
172 VlanIdBuilder vlanIdBuilder = new VlanIdBuilder();
173 vlanIdBuilder.setVlanIdPresent(false);
174 vlanIdBuilder.setVlanId(zeroVlan);
175 vlanMatchBuilder.setVlanId(vlanIdBuilder.build());
177 VLAN_MATCH_FALSE = vlanMatchBuilder.build();
179 VlanMatchBuilder vlanMatchBuilder2 = new VlanMatchBuilder();
180 VlanIdBuilder vlanIdBuilder2 = new VlanIdBuilder();
181 vlanIdBuilder2.setVlanIdPresent(true);
182 vlanIdBuilder2.setVlanId(zeroVlan);
183 vlanMatchBuilder2.setVlanId(vlanIdBuilder2.build());
185 VLAN_MATCH_TRUE = vlanMatchBuilder2.build();
188 private FlowModInputBuilder toFlowModInput(final Flow flow,
189 final VersionDatapathIdConvertorData versionConverterData) {
191 FlowModInputBuilder flowMod = new FlowModInputBuilder();
192 salToOFFlowCookie(flow, flowMod);
193 salToOFFlowCookieMask(flow, flowMod);
194 salToOFFlowTableId(flow, flowMod);
195 salToOFFlowCommand(flow, flowMod);
196 salToOFFlowIdleTimeout(flow, flowMod);
197 salToOFFlowHardTimeout(flow, flowMod);
198 salToOFFlowPriority(flow, flowMod);
199 salToOFFlowBufferId(flow, flowMod);
200 salToOFFlowOutPort(flow, flowMod);
201 salToOFFlowOutGroup(flow, flowMod);
203 // convert and inject flowFlags
204 final Optional<Object> conversion = getConvertorExecutor().convert(flow.getFlags(), versionConverterData);
205 FlowFlagsInjector.inject(conversion, flowMod, versionConverterData.getVersion());
207 // convert and inject match
208 final Optional<Object> conversionMatch = getConvertorExecutor().convert(flow.getMatch(), versionConverterData);
209 MatchInjector.inject(conversionMatch, flowMod, versionConverterData.getVersion());
211 if (flow.getInstructions() != null) {
212 flowMod.setInstruction(toInstructions(flow, versionConverterData.getVersion(),
213 versionConverterData.getDatapathId()));
214 flowMod.setAction(getActions(versionConverterData.getVersion(),
215 versionConverterData.getDatapathId(), flow));
218 flowMod.setVersion(versionConverterData.getVersion());
222 private static void salToOFFlowOutGroup(final Flow flow, final FlowModInputBuilder flowMod) {
223 if (flow.getOutGroup() != null) {
224 flowMod.setOutGroup(flow.getOutGroup());
226 flowMod.setOutGroup(DEFAULT_OUT_GROUP);
230 private static void salToOFFlowOutPort(final Flow flow, final FlowModInputBuilder flowMod) {
231 if (flow.getOutPort() != null) {
232 flowMod.setOutPort(new PortNumber(flow.getOutPort().longValue()));
234 flowMod.setOutPort(new PortNumber(DEFAULT_OUT_PORT));
238 private static void salToOFFlowBufferId(final Flow flow, final FlowModInputBuilder flowMod) {
239 if (flow.getBufferId() != null) {
240 flowMod.setBufferId(flow.getBufferId());
242 flowMod.setBufferId(DEFAULT_BUFFER_ID);
246 private static void salToOFFlowPriority(final Flow flow, final FlowModInputBuilder flowMod) {
247 if (flow.getPriority() != null) {
248 flowMod.setPriority(flow.getPriority());
250 flowMod.setPriority(DEFAULT_PRIORITY);
254 private static void salToOFFlowHardTimeout(final Flow flow, final FlowModInputBuilder flowMod) {
255 if (flow.getHardTimeout() != null) {
256 flowMod.setHardTimeout(flow.getHardTimeout());
258 flowMod.setHardTimeout(DEFAULT_HARD_TIMEOUT);
262 private static void salToOFFlowIdleTimeout(final Flow flow, final FlowModInputBuilder flowMod) {
263 if (flow.getIdleTimeout() != null) {
264 flowMod.setIdleTimeout(flow.getIdleTimeout());
266 flowMod.setIdleTimeout(DEFAULT_IDLE_TIMEOUT);
270 private static void salToOFFlowCommand(final Flow flow, final FlowModInputBuilder flowMod) {
271 if (flow instanceof AddFlowInput || flow instanceof UpdatedFlow) {
272 flowMod.setCommand(FlowModCommand.OFPFCADD);
273 } else if (flow instanceof RemoveFlowInput) {
274 if (MoreObjects.firstNonNull(flow.isStrict(), Boolean.FALSE)) {
275 flowMod.setCommand(FlowModCommand.OFPFCDELETESTRICT);
277 flowMod.setCommand(FlowModCommand.OFPFCDELETE);
282 private static void salToOFFlowTableId(final Flow flow, final FlowModInputBuilder flowMod) {
283 if (flow.getTableId() != null) {
284 flowMod.setTableId(new TableId(flow.getTableId().longValue()));
286 flowMod.setTableId(DEFAULT_TABLE_ID);
290 private static void salToOFFlowCookieMask(final Flow flow, final FlowModInputBuilder flowMod) {
291 if (flow.getCookieMask() != null) {
292 flowMod.setCookieMask(flow.getCookieMask().getValue());
294 flowMod.setCookieMask(OFConstants.DEFAULT_COOKIE_MASK);
298 private static void salToOFFlowCookie(final Flow flow, final FlowModInputBuilder flowMod) {
299 if (flow.getCookie() != null) {
300 flowMod.setCookie(flow.getCookie().getValue());
302 flowMod.setCookie(OFConstants.DEFAULT_COOKIE);
306 private List<Instruction> toInstructions(final Flow flow, final short version, final Uint64 datapathid) {
307 final List<Instruction> instructionsList = new ArrayList<>();
308 final ActionConvertorData data = new ActionConvertorData(version);
309 data.setDatapathId(datapathid);
310 data.setIpProtocol(FlowConvertorUtil.getIpProtocolFromFlow(flow));
312 Instructions instructions = flow.getInstructions();
314 for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction
315 instruction : instructions.getInstruction()) {
316 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction
317 curInstruction = instruction.getInstruction();
319 Optional<Instruction> result = PROCESSOR.process(curInstruction, data, getConvertorExecutor());
321 if (result.isPresent()) {
322 instructionsList.add(result.get());
326 return instructionsList;
329 private List<Action> getActions(final short version, final Uint64 datapathid, final Flow flow) {
330 Instructions instructions = flow.getInstructions();
331 List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction>
332 sortedInstructions = INSTRUCTION_ORDERING.sortedCopy(instructions.getInstruction());
334 for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction
335 instruction : sortedInstructions) {
336 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction
337 curInstruction = instruction.getInstruction();
339 if (curInstruction instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026
340 .instruction.instruction.ApplyActionsCase) {
341 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction
342 .ApplyActionsCase applyActionscase = (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types
343 .rev131026.instruction.instruction.ApplyActionsCase) curInstruction;
344 ApplyActions applyActions = applyActionscase.getApplyActions();
346 final ActionConvertorData data = new ActionConvertorData(version);
347 data.setDatapathId(datapathid);
348 data.setIpProtocol(FlowConvertorUtil.getIpProtocolFromFlow(flow));
349 Optional<List<Action>> result = getConvertorExecutor().convert(applyActions.getAction(), data);
350 return result.orElse(Collections.emptyList());
357 // check if set vlanid action is present in the flow
358 private static boolean isSetVlanIdActionCasePresent(final Flow flow) {
359 // we are trying to find if there is a set-vlan-id action (OF1.0) action present in the flow.
360 // If yes,then we would need to two flows
361 if (flow.getInstructions() != null && flow.getInstructions().getInstruction() != null) {
362 for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction
363 instruction : flow.getInstructions().getInstruction()) {
364 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction
365 curInstruction = instruction.getInstruction();
367 if (curInstruction instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026
368 .instruction.instruction.ApplyActionsCase) {
369 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction
370 .ApplyActionsCase applyActionscase = (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types
371 .rev131026.instruction.instruction.ApplyActionsCase) curInstruction;
372 ApplyActions applyActions = applyActionscase.getApplyActions();
373 for (org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action
374 action : applyActions.getAction()) {
375 if (action.getAction() instanceof SetVlanIdActionCase) {
387 * A) If user provided flow's match includes vlan match  and action has set_vlan_field
388 * Install following rules.
389 * Â Â 1) match on (OFPVID_PRESENT |value) without mask + action [set_field]
391 * B) if user provided flow's match doesn't include vlan match but action has set_vlan field
392 * Â Â 1) Match on (OFPVID_NONEÂ ) without mask + action [push vlan tag + set_field]
393 * Â Â 2) Match on (OFPVID_PRESENT) with mask (OFPVID_PRESENT ) + action [ set_field]
395 private List<FlowModInputBuilder> handleSetVlanIdForOF13(final Flow srcFlow,
396 final VersionDatapathIdConvertorData versionDatapathIdConverterData) {
397 List<FlowModInputBuilder> list = new ArrayList<>(2);
399 final Match srcMatch = Preconditions.checkNotNull(srcFlow.getMatch());
400 final VlanMatch srcVlanMatch = srcMatch.getVlanMatch();
401 if (srcVlanMatch != null) {
402 //create flow with setfield and match
403 // match on vlan tag or vlanid with no mask
404 VlanMatchBuilder vlanMatchBuilder = new VlanMatchBuilder(srcVlanMatch);
405 VlanIdBuilder vlanIdBuilder = new VlanIdBuilder();
406 vlanIdBuilder.setVlanIdPresent(srcVlanMatch.getVlanId().isVlanIdPresent());
407 vlanIdBuilder.setVlanId(srcVlanMatch.getVlanId().getVlanId());
408 vlanMatchBuilder.setVlanId(vlanIdBuilder.build());
409 Match match = new MatchBuilder(srcMatch).setVlanMatch(vlanMatchBuilder.build()).build();
411 Optional<? extends Flow> optional = injectMatchToFlow(srcFlow, match);
412 if (optional.isPresent()) {
413 list.add(toFlowModInput(optional.get(), versionDatapathIdConverterData));
418 // match on no vlan tag with no mask
419 Match match1 = new MatchBuilder(srcMatch).setVlanMatch(VLAN_MATCH_FALSE).build();
421 Optional<? extends Flow> optional1 = injectMatchAndAction(srcFlow, match1);
422 if (optional1.isPresent()) {
423 list.add(toFlowModInput(optional1.get(), versionDatapathIdConverterData));
427 // match on vlan tag with mask
428 Match match2 = new MatchBuilder(srcMatch).setVlanMatch(VLAN_MATCH_TRUE).build();
429 Optional<? extends Flow> optional2 = injectMatchToFlow(srcFlow, match2);
430 if (optional2.isPresent()) {
431 list.add(toFlowModInput(optional2.get(), versionDatapathIdConverterData));
438 private static Optional<? extends Flow> injectMatchToFlow(final Flow sourceFlow, final Match match) {
439 if (sourceFlow instanceof AddFlowInput) {
440 return Optional.of(new AddFlowInputBuilder(sourceFlow).setMatch(match).build());
441 } else if (sourceFlow instanceof RemoveFlowInput) {
442 return Optional.of(new RemoveFlowInputBuilder(sourceFlow).setMatch(match).build());
443 } else if (sourceFlow instanceof UpdatedFlow) {
444 return Optional.of(new UpdatedFlowBuilder(sourceFlow).setMatch(match).build());
446 return Optional.empty();
450 private static Optional<? extends Flow> injectMatchAndAction(final Flow sourceFlow, final Match match) {
452 Instructions instructions = new InstructionsBuilder()
453 .setInstruction(injectPushActionToInstruction(sourceFlow))
456 if (sourceFlow instanceof AddFlowInput) {
457 return Optional.of(new AddFlowInputBuilder(sourceFlow)
458 .setMatch(match).setInstructions(instructions).build());
459 } else if (sourceFlow instanceof RemoveFlowInput) {
460 return Optional.of(new RemoveFlowInputBuilder(sourceFlow)
461 .setMatch(match).setInstructions(instructions).build());
462 } else if (sourceFlow instanceof UpdatedFlow) {
463 return Optional.of(new UpdatedFlowBuilder(sourceFlow)
464 .setMatch(match).setInstructions(instructions).build());
466 return Optional.empty();
470 private static List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction>
471 injectPushActionToInstruction(final Flow sourceFlow) {
473 List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction>
474 srcInstructionList = sourceFlow.getInstructions().getInstruction();
476 List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction>
477 targetInstructionList = new ArrayList<>(srcInstructionList.size());
478 List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action>
479 targetActionList = new ArrayList<>();
481 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder
482 instructionBuilder = new org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction
483 .list.InstructionBuilder();
485 for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction
486 srcInstruction : srcInstructionList) {
487 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction
488 curSrcInstruction = srcInstruction.getInstruction();
490 if (curSrcInstruction instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026
491 .instruction.instruction.ApplyActionsCase) {
492 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction
493 .ApplyActionsCase applyActionscase = (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types
494 .rev131026.instruction.instruction.ApplyActionsCase) curSrcInstruction;
495 ApplyActions applyActions = applyActionscase.getApplyActions();
496 List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action>
497 srcActionList = applyActions.getAction();
500 for (org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action
501 actionItem : srcActionList) {
502 // check if its a set-vlan-action. If yes, then add the injected-action
504 if (actionItem.getAction() instanceof SetVlanIdActionCase) {
505 SetVlanIdActionCase setVlanIdActionCase = (SetVlanIdActionCase) actionItem.getAction();
507 PushVlanActionCaseBuilder pushVlanActionCaseBuilder = new PushVlanActionCaseBuilder();
508 PushVlanActionBuilder pushVlanActionBuilder = new PushVlanActionBuilder();
510 pushVlanActionBuilder.setCfi(PUSH_CFI)
511 .setVlanId(setVlanIdActionCase.getSetVlanIdAction().getVlanId())
512 .setEthernetType(PUSH_VLAN)
514 pushVlanActionCaseBuilder.setPushVlanAction(pushVlanActionBuilder.build());
515 PushVlanActionCase injectedAction = pushVlanActionCaseBuilder.build();
517 ActionBuilder actionBuilder = new ActionBuilder();
518 actionBuilder.setAction(injectedAction)
519 .withKey(actionItem.key())
520 .setOrder(actionItem.getOrder() + offset);
522 targetActionList.add(actionBuilder.build());
527 // we need to increment the order for all the actions added after injection
528 ActionBuilder actionBuilder =
529 new ActionBuilder(actionItem);
530 actionBuilder.setOrder(actionItem.getOrder() + offset);
531 actionItem = actionBuilder.build();
534 targetActionList.add(actionItem);
537 ApplyActionsCaseBuilder applyActionsCaseBuilder = new ApplyActionsCaseBuilder();
538 ApplyActionsBuilder applyActionsBuilder = new ApplyActionsBuilder();
539 applyActionsBuilder.setAction(targetActionList);
540 applyActionsCaseBuilder.setApplyActions(applyActionsBuilder.build());
542 instructionBuilder.setInstruction(applyActionsCaseBuilder.build());
544 instructionBuilder.setInstruction(curSrcInstruction);
548 .withKey(srcInstruction.key())
549 .setOrder(srcInstruction.getOrder());
550 targetInstructionList.add(instructionBuilder.build());
554 return targetInstructionList;
558 public Collection<Class<?>> getTypes() {
563 public List<FlowModInputBuilder> convert(final Flow source, final VersionDatapathIdConvertorData data) {
564 if (data.getVersion() >= OFConstants.OFP_VERSION_1_3 && isSetVlanIdActionCasePresent(source)) {
565 return handleSetVlanIdForOF13(source, data);
567 return Collections.singletonList(toFlowModInput(source, data));