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;
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;
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.
81 * VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(version);
82 * data.setDatapathId(datapathId);
83 * Optional<List<FlowModInputBuilder>> ofFlow = convertorManager.convert(salFlow, data);
87 public class FlowConvertor extends Convertor<Flow, List<FlowModInputBuilder>, VersionDatapathIdConvertorData> {
89 * Default idle timeout.
91 public static final Uint16 DEFAULT_IDLE_TIMEOUT = Uint16.ZERO;
94 * Default hard timeout.
96 public static final Uint16 DEFAULT_HARD_TIMEOUT = Uint16.ZERO;
101 public static final Uint16 DEFAULT_PRIORITY = Uint16.valueOf(0x8000);
106 public static final boolean DEFAULT_OFPFF_FLOW_REM = false;
109 * flow flag: check overlap.
111 public static final boolean DEFAULT_OFPFF_CHECK_OVERLAP = false;
114 * flow flag: reset counts.
116 public static final boolean DEFAULT_OFPFF_RESET_COUNTS = false;
119 * flow flag: don't keep track of packet counts.
121 public static final boolean DEFAULT_OFPFF_NO_PKT_COUNTS = false;
124 * flow flag: don't keep track of byte counts.
126 public static final boolean DEFAULT_OFPFF_NO_BYT_COUNTS = false;
129 * flow flag: emergency [OFP-1.0].
131 public static final boolean DEFAULT_OFPFF_EMERGENCY = false;
136 public static final Class<? extends MatchTypeBase> DEFAULT_MATCH_TYPE = OxmMatchType.class;
139 * default match entries - empty.
141 public static final List<MatchEntry> DEFAULT_MATCH_ENTRIES = ImmutableList.of();
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());
168 private static final List<Class<?>> TYPES = Arrays.asList(Flow.class, AddFlowInput.class,
169 RemoveFlowInput.class, UpdatedFlow.class);
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());
179 VLAN_MATCH_FALSE = vlanMatchBuilder.build();
181 VlanMatchBuilder vlanMatchBuilder2 = new VlanMatchBuilder();
182 VlanIdBuilder vlanIdBuilder2 = new VlanIdBuilder();
183 vlanIdBuilder2.setVlanIdPresent(true);
184 vlanIdBuilder2.setVlanId(zeroVlan);
185 vlanMatchBuilder2.setVlanId(vlanIdBuilder2.build());
187 VLAN_MATCH_TRUE = vlanMatchBuilder2.build();
190 private FlowModInputBuilder toFlowModInput(final Flow flow,
191 final VersionDatapathIdConvertorData versionConverterData) {
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);
205 // convert and inject flowFlags
206 final Optional<Object> conversion = getConvertorExecutor().convert(flow.getFlags(), versionConverterData);
207 FlowFlagsInjector.inject(conversion, flowMod, versionConverterData.getVersion());
209 // convert and inject match
210 final Optional<Object> conversionMatch = getConvertorExecutor().convert(flow.getMatch(), versionConverterData);
211 MatchInjector.inject(conversionMatch, flowMod, versionConverterData.getVersion());
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));
220 flowMod.setVersion(versionConverterData.getVersion());
224 private static void salToOFFlowOutGroup(final Flow flow, final FlowModInputBuilder flowMod) {
225 if (flow.getOutGroup() != null) {
226 flowMod.setOutGroup(flow.getOutGroup());
228 flowMod.setOutGroup(DEFAULT_OUT_GROUP);
232 private static void salToOFFlowOutPort(final Flow flow, final FlowModInputBuilder flowMod) {
233 if (flow.getOutPort() != null) {
234 flowMod.setOutPort(new PortNumber(flow.getOutPort().longValue()));
236 flowMod.setOutPort(new PortNumber(DEFAULT_OUT_PORT));
240 private static void salToOFFlowBufferId(final Flow flow, final FlowModInputBuilder flowMod) {
241 if (flow.getBufferId() != null) {
242 flowMod.setBufferId(flow.getBufferId());
244 flowMod.setBufferId(DEFAULT_BUFFER_ID);
248 private static void salToOFFlowPriority(final Flow flow, final FlowModInputBuilder flowMod) {
249 if (flow.getPriority() != null) {
250 flowMod.setPriority(flow.getPriority());
252 flowMod.setPriority(DEFAULT_PRIORITY);
256 private static void salToOFFlowHardTimeout(final Flow flow, final FlowModInputBuilder flowMod) {
257 if (flow.getHardTimeout() != null) {
258 flowMod.setHardTimeout(flow.getHardTimeout());
260 flowMod.setHardTimeout(DEFAULT_HARD_TIMEOUT);
264 private static void salToOFFlowIdleTimeout(final Flow flow, final FlowModInputBuilder flowMod) {
265 if (flow.getIdleTimeout() != null) {
266 flowMod.setIdleTimeout(flow.getIdleTimeout());
268 flowMod.setIdleTimeout(DEFAULT_IDLE_TIMEOUT);
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);
279 flowMod.setCommand(FlowModCommand.OFPFCDELETE);
284 private static void salToOFFlowTableId(final Flow flow, final FlowModInputBuilder flowMod) {
285 if (flow.getTableId() != null) {
286 flowMod.setTableId(new TableId(flow.getTableId().longValue()));
288 flowMod.setTableId(DEFAULT_TABLE_ID);
292 private static void salToOFFlowCookieMask(final Flow flow, final FlowModInputBuilder flowMod) {
293 if (flow.getCookieMask() != null) {
294 flowMod.setCookieMask(flow.getCookieMask().getValue());
296 flowMod.setCookieMask(OFConstants.DEFAULT_COOKIE_MASK);
300 private static void salToOFFlowCookie(final Flow flow, final FlowModInputBuilder flowMod) {
301 if (flow.getCookie() != null) {
302 flowMod.setCookie(flow.getCookie().getValue());
304 flowMod.setCookie(OFConstants.DEFAULT_COOKIE);
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));
314 Instructions instructions = flow.getInstructions();
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();
321 Optional<Instruction> result = PROCESSOR.process(curInstruction, data, getConvertorExecutor());
323 if (result.isPresent()) {
324 instructionsList.add(result.get());
328 return instructionsList;
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());
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();
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();
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());
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();
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) {
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]
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]
397 private List<FlowModInputBuilder> handleSetVlanIdForOF13(final Flow srcFlow,
398 final VersionDatapathIdConvertorData versionDatapathIdConverterData) {
399 List<FlowModInputBuilder> list = new ArrayList<>(2);
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();
413 Optional<? extends Flow> optional = injectMatchToFlow(srcFlow, match);
414 if (optional.isPresent()) {
415 list.add(toFlowModInput(optional.get(), versionDatapathIdConverterData));
420 // match on no vlan tag with no mask
421 Match match1 = new MatchBuilder(srcMatch).setVlanMatch(VLAN_MATCH_FALSE).build();
423 Optional<? extends Flow> optional1 = injectMatchAndAction(srcFlow, match1);
424 if (optional1.isPresent()) {
425 list.add(toFlowModInput(optional1.get(), versionDatapathIdConverterData));
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));
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());
448 return Optional.empty();
452 private static Optional<? extends Flow> injectMatchAndAction(final Flow sourceFlow, final Match match) {
454 Instructions instructions = new InstructionsBuilder()
455 .setInstruction(injectPushActionToInstruction(sourceFlow))
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());
468 return Optional.empty();
472 private static List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction>
473 injectPushActionToInstruction(final Flow sourceFlow) {
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();
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<>();
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();
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();
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();
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
508 if (actionItem.getAction() instanceof SetVlanIdActionCase) {
509 SetVlanIdActionCase setVlanIdActionCase = (SetVlanIdActionCase) actionItem.getAction();
511 PushVlanActionCaseBuilder pushVlanActionCaseBuilder = new PushVlanActionCaseBuilder();
512 PushVlanActionBuilder pushVlanActionBuilder = new PushVlanActionBuilder();
514 pushVlanActionBuilder.setCfi(PUSH_CFI)
515 .setVlanId(setVlanIdActionCase.getSetVlanIdAction().getVlanId())
516 .setEthernetType(PUSH_VLAN)
518 pushVlanActionCaseBuilder.setPushVlanAction(pushVlanActionBuilder.build());
519 PushVlanActionCase injectedAction = pushVlanActionCaseBuilder.build();
521 ActionBuilder actionBuilder = new ActionBuilder();
522 actionBuilder.setAction(injectedAction)
523 .withKey(actionItem.key())
524 .setOrder(actionItem.getOrder() + offset);
526 targetActionList.add(actionBuilder.build());
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();
539 targetActionList.add(actionItem);
542 ApplyActionsCaseBuilder applyActionsCaseBuilder = new ApplyActionsCaseBuilder();
543 ApplyActionsBuilder applyActionsBuilder = new ApplyActionsBuilder();
544 applyActionsBuilder.setAction(targetActionList);
545 applyActionsCaseBuilder.setApplyActions(applyActionsBuilder.build());
547 instructionBuilder.setInstruction(applyActionsCaseBuilder.build());
549 instructionBuilder.setInstruction(curSrcInstruction);
553 .withKey(srcInstruction.key())
554 .setOrder(srcInstruction.getOrder());
555 targetInstructionList.add(instructionBuilder.build());
559 return targetInstructionList;
563 public Collection<Class<?>> getTypes() {
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);
572 return Collections.singletonList(toFlowModInput(source, data));