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.math.BigInteger;
16 import java.util.ArrayList;
17 import java.util.Arrays;
18 import java.util.Collection;
19 import java.util.Collections;
20 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.flow.service.rev130819.AddFlowInput;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlow;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlowBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActions;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatch;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.actions.grouping.Action;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instructions.grouping.Instruction;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowModCommand;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MatchTypeBase;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortNumber;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.TableId;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.OxmMatchType;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntry;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowModInputBuilder;
70 * Converts the SAL Flow to OF Flow. It checks if there is a set-vlan-id (1.0) action made on OF1.3.
71 * If yes its handled separately.
77 * VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(version);
78 * data.setDatapathId(datapathId);
79 * Optional<List<FlowModInputBuilder>> ofFlow = convertorManager.convert(salFlow, data);
83 public class FlowConvertor extends Convertor<Flow, List<FlowModInputBuilder>, VersionDatapathIdConvertorData> {
85 * Default idle timeout.
87 public static final Integer DEFAULT_IDLE_TIMEOUT = 0;
90 * Default hard timeout.
92 public static final Integer DEFAULT_HARD_TIMEOUT = 0;
97 public static final Integer DEFAULT_PRIORITY = Integer.parseInt("8000", 16);
102 public static final boolean DEFAULT_OFPFF_FLOW_REM = false;
105 * flow flag: check overlap.
107 public static final boolean DEFAULT_OFPFF_CHECK_OVERLAP = false;
110 * flow flag: reset counts.
112 public static final boolean DEFAULT_OFPFF_RESET_COUNTS = false;
115 * flow flag: don't keep track of packet counts.
117 public static final boolean DEFAULT_OFPFF_NO_PKT_COUNTS = false;
120 * flow flag: don't keep track of byte counts.
122 public static final boolean DEFAULT_OFPFF_NO_BYT_COUNTS = false;
125 * flow flag: emergency [OFP-1.0].
127 public static final boolean DEFAULT_OFPFF_EMERGENCY = false;
132 public static final Class<? extends MatchTypeBase> DEFAULT_MATCH_TYPE = OxmMatchType.class;
135 * default match entries - empty.
137 public static final List<MatchEntry> DEFAULT_MATCH_ENTRIES = ImmutableList.of();
139 // Default values for when things are null
140 private static final TableId DEFAULT_TABLE_ID = new TableId(0L);
141 private static final Long DEFAULT_BUFFER_ID = OFConstants.OFP_NO_BUFFER;
142 private static final Long OFPP_ANY = Long.parseLong("ffffffff", 16);
143 private static final Long DEFAULT_OUT_PORT = OFPP_ANY;
144 private static final Long OFPG_ANY = Long.parseLong("ffffffff", 16);
145 private static final Long DEFAULT_OUT_GROUP = OFPG_ANY;
146 private static final Integer PUSH_VLAN = 0x8100;
147 private static final Ordering<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction
148 .list.Instruction> INSTRUCTION_ORDERING = Ordering.from(OrderComparator.build());
149 private static final VlanMatch VLAN_MATCH_FALSE;
150 private static final VlanMatch VLAN_MATCH_TRUE;
151 private static final ConvertorProcessor<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026
152 .instruction.Instruction, Instruction, ActionConvertorData> PROCESSOR =
153 new ConvertorProcessor<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026
154 .instruction.Instruction, Instruction, ActionConvertorData>()
155 .addCase(new ApplyActionsCase())
156 .addCase(new ClearActionsCase())
157 .addCase(new GoToTableCase())
158 .addCase(new MeterCase())
159 .addCase(new WriteActionsCase())
160 .addCase(new WriteMetadataCase());
162 private static final List<Class<?>> TYPES = Arrays.asList(Flow.class, AddFlowInput.class,
163 RemoveFlowInput.class, UpdatedFlow.class);
166 final VlanId zeroVlan = new VlanId(0);
167 VlanMatchBuilder vlanMatchBuilder = new VlanMatchBuilder();
168 VlanIdBuilder vlanIdBuilder = new VlanIdBuilder();
169 vlanIdBuilder.setVlanIdPresent(false);
170 vlanIdBuilder.setVlanId(zeroVlan);
171 vlanMatchBuilder.setVlanId(vlanIdBuilder.build());
173 VLAN_MATCH_FALSE = vlanMatchBuilder.build();
175 VlanMatchBuilder vlanMatchBuilder2 = new VlanMatchBuilder();
176 VlanIdBuilder vlanIdBuilder2 = new VlanIdBuilder();
177 vlanIdBuilder2.setVlanIdPresent(true);
178 vlanIdBuilder2.setVlanId(zeroVlan);
179 vlanMatchBuilder2.setVlanId(vlanIdBuilder2.build());
181 VLAN_MATCH_TRUE = vlanMatchBuilder2.build();
184 private FlowModInputBuilder toFlowModInput(Flow flow, VersionDatapathIdConvertorData versionConverterData) {
186 FlowModInputBuilder flowMod = new FlowModInputBuilder();
187 salToOFFlowCookie(flow, flowMod);
188 salToOFFlowCookieMask(flow, flowMod);
189 salToOFFlowTableId(flow, flowMod);
190 salToOFFlowCommand(flow, flowMod);
191 salToOFFlowIdleTimeout(flow, flowMod);
192 salToOFFlowHardTimeout(flow, flowMod);
193 salToOFFlowPriority(flow, flowMod);
194 salToOFFlowBufferId(flow, flowMod);
195 salToOFFlowOutPort(flow, flowMod);
196 salToOFFlowOutGroup(flow, flowMod);
198 // convert and inject flowFlags
199 final Optional<Object> conversion = getConvertorExecutor().convert(flow.getFlags(), versionConverterData);
200 FlowFlagsInjector.inject(conversion, flowMod, versionConverterData.getVersion());
202 // convert and inject match
203 final Optional<Object> conversionMatch = getConvertorExecutor().convert(flow.getMatch(), versionConverterData);
204 MatchInjector.inject(conversionMatch, flowMod, versionConverterData.getVersion());
206 if (flow.getInstructions() != null) {
207 flowMod.setInstruction(toInstructions(flow, versionConverterData.getVersion(),
208 versionConverterData.getDatapathId()));
209 flowMod.setAction(getActions(versionConverterData.getVersion(),
210 versionConverterData.getDatapathId(), flow));
213 flowMod.setVersion(versionConverterData.getVersion());
217 private static void salToOFFlowOutGroup(Flow flow, FlowModInputBuilder flowMod) {
218 if (flow.getOutGroup() != null) {
219 flowMod.setOutGroup(flow.getOutGroup());
221 flowMod.setOutGroup(DEFAULT_OUT_GROUP);
225 private static void salToOFFlowOutPort(Flow flow, FlowModInputBuilder flowMod) {
226 if (flow.getOutPort() != null) {
227 flowMod.setOutPort(new PortNumber(flow.getOutPort().longValue()));
229 flowMod.setOutPort(new PortNumber(DEFAULT_OUT_PORT));
233 private static void salToOFFlowBufferId(Flow flow, FlowModInputBuilder flowMod) {
234 if (flow.getBufferId() != null) {
235 flowMod.setBufferId(flow.getBufferId());
237 flowMod.setBufferId(DEFAULT_BUFFER_ID);
241 private static void salToOFFlowPriority(Flow flow, FlowModInputBuilder flowMod) {
242 if (flow.getPriority() != null) {
243 flowMod.setPriority(flow.getPriority());
245 flowMod.setPriority(DEFAULT_PRIORITY);
249 private static void salToOFFlowHardTimeout(Flow flow, FlowModInputBuilder flowMod) {
250 if (flow.getHardTimeout() != null) {
251 flowMod.setHardTimeout(flow.getHardTimeout());
253 flowMod.setHardTimeout(DEFAULT_HARD_TIMEOUT);
257 private static void salToOFFlowIdleTimeout(Flow flow, FlowModInputBuilder flowMod) {
258 if (flow.getIdleTimeout() != null) {
259 flowMod.setIdleTimeout(flow.getIdleTimeout());
261 flowMod.setIdleTimeout(DEFAULT_IDLE_TIMEOUT);
265 private static void salToOFFlowCommand(Flow flow, FlowModInputBuilder flowMod) {
266 if (flow instanceof AddFlowInput || flow instanceof UpdatedFlow) {
267 flowMod.setCommand(FlowModCommand.OFPFCADD);
268 } else if (flow instanceof RemoveFlowInput) {
269 if (MoreObjects.firstNonNull(flow.isStrict(), Boolean.FALSE)) {
270 flowMod.setCommand(FlowModCommand.OFPFCDELETESTRICT);
272 flowMod.setCommand(FlowModCommand.OFPFCDELETE);
277 private static void salToOFFlowTableId(Flow flow, FlowModInputBuilder flowMod) {
278 if (flow.getTableId() != null) {
279 flowMod.setTableId(new TableId(flow.getTableId().longValue()));
281 flowMod.setTableId(DEFAULT_TABLE_ID);
285 private static void salToOFFlowCookieMask(Flow flow, FlowModInputBuilder flowMod) {
286 if (flow.getCookieMask() != null) {
287 flowMod.setCookieMask(flow.getCookieMask().getValue());
289 flowMod.setCookieMask(OFConstants.DEFAULT_COOKIE_MASK);
293 private static void salToOFFlowCookie(Flow flow, FlowModInputBuilder flowMod) {
294 if (flow.getCookie() != null) {
295 flowMod.setCookie(flow.getCookie().getValue());
297 flowMod.setCookie(OFConstants.DEFAULT_COOKIE);
301 private List<Instruction> toInstructions(Flow flow, short version, BigInteger datapathid) {
302 final List<Instruction> instructionsList = new ArrayList<>();
303 final ActionConvertorData data = new ActionConvertorData(version);
304 data.setDatapathId(datapathid);
305 data.setIpProtocol(FlowConvertorUtil.getIpProtocolFromFlow(flow));
307 Instructions instructions = flow.getInstructions();
309 for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction
310 instruction : instructions.getInstruction()) {
311 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction
312 curInstruction = instruction.getInstruction();
314 Optional<Instruction> result = PROCESSOR.process(curInstruction, data, getConvertorExecutor());
316 if (result.isPresent()) {
317 instructionsList.add(result.get());
321 return instructionsList;
324 private List<Action> getActions(short version, BigInteger datapathid, Flow flow) {
325 Instructions instructions = flow.getInstructions();
326 List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction>
327 sortedInstructions = INSTRUCTION_ORDERING.sortedCopy(instructions.getInstruction());
329 for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction
330 instruction : sortedInstructions) {
331 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction
332 curInstruction = instruction.getInstruction();
334 if (curInstruction instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026
335 .instruction.instruction.ApplyActionsCase) {
336 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction
337 .ApplyActionsCase applyActionscase = (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types
338 .rev131026.instruction.instruction.ApplyActionsCase) curInstruction;
339 ApplyActions applyActions = applyActionscase.getApplyActions();
341 final ActionConvertorData data = new ActionConvertorData(version);
342 data.setDatapathId(datapathid);
343 data.setIpProtocol(FlowConvertorUtil.getIpProtocolFromFlow(flow));
344 Optional<List<Action>> result = getConvertorExecutor().convert(applyActions.getAction(), data);
345 return result.orElse(Collections.emptyList());
352 // check if set vlanid action is present in the flow
353 private static boolean isSetVlanIdActionCasePresent(Flow flow) {
354 // we are trying to find if there is a set-vlan-id action (OF1.0) action present in the flow.
355 // If yes,then we would need to two flows
356 if (flow.getInstructions() != null && flow.getInstructions().getInstruction() != null) {
357 for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction
358 instruction : flow.getInstructions().getInstruction()) {
359 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction
360 curInstruction = instruction.getInstruction();
362 if (curInstruction instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026
363 .instruction.instruction.ApplyActionsCase) {
364 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction
365 .ApplyActionsCase applyActionscase = (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types
366 .rev131026.instruction.instruction.ApplyActionsCase) curInstruction;
367 ApplyActions applyActions = applyActionscase.getApplyActions();
368 for (org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action
369 action : applyActions.getAction()) {
370 if (action.getAction() instanceof SetVlanIdActionCase) {
382 * A) If user provided flow's match includes vlan match  and action has set_vlan_field
383 * Install following rules.
384 * Â Â 1) match on (OFPVID_PRESENT |value) without mask + action [set_field]
386 * B) if user provided flow's match doesn't include vlan match but action has set_vlan field
387 * Â Â 1) Match on (OFPVID_NONEÂ ) without mask + action [push vlan tag + set_field]
388 * Â Â 2) Match on (OFPVID_PRESENT) with mask (OFPVID_PRESENT ) + action [ set_field]
390 private List<FlowModInputBuilder> handleSetVlanIdForOF13(Flow srcFlow,
391 VersionDatapathIdConvertorData versionDatapathIdConverterData) {
392 List<FlowModInputBuilder> list = new ArrayList<>(2);
394 final Match srcMatch = Preconditions.checkNotNull(srcFlow.getMatch());
395 final VlanMatch srcVlanMatch = srcMatch.getVlanMatch();
396 if (srcVlanMatch != null) {
397 //create flow with setfield and match
398 // match on vlan tag or vlanid with no mask
399 VlanMatchBuilder vlanMatchBuilder = new VlanMatchBuilder(srcVlanMatch);
400 VlanIdBuilder vlanIdBuilder = new VlanIdBuilder();
401 vlanIdBuilder.setVlanIdPresent(srcVlanMatch.getVlanId().isVlanIdPresent());
402 vlanIdBuilder.setVlanId(srcVlanMatch.getVlanId().getVlanId());
403 vlanMatchBuilder.setVlanId(vlanIdBuilder.build());
404 Match match = new MatchBuilder(srcMatch).setVlanMatch(vlanMatchBuilder.build()).build();
406 Optional<? extends Flow> optional = injectMatchToFlow(srcFlow, match);
407 if (optional.isPresent()) {
408 list.add(toFlowModInput(optional.get(), versionDatapathIdConverterData));
413 // match on no vlan tag with no mask
414 Match match1 = new MatchBuilder(srcMatch).setVlanMatch(VLAN_MATCH_FALSE).build();
416 Optional<? extends Flow> optional1 = injectMatchAndAction(srcFlow, match1);
417 if (optional1.isPresent()) {
418 list.add(toFlowModInput(optional1.get(), versionDatapathIdConverterData));
422 // match on vlan tag with mask
423 Match match2 = new MatchBuilder(srcMatch).setVlanMatch(VLAN_MATCH_TRUE).build();
424 Optional<? extends Flow> optional2 = injectMatchToFlow(srcFlow, match2);
425 if (optional2.isPresent()) {
426 list.add(toFlowModInput(optional2.get(), versionDatapathIdConverterData));
433 private static Optional<? extends Flow> injectMatchToFlow(Flow sourceFlow, Match match) {
434 if (sourceFlow instanceof AddFlowInput) {
435 return Optional.of(new AddFlowInputBuilder(sourceFlow).setMatch(match).build());
436 } else if (sourceFlow instanceof RemoveFlowInput) {
437 return Optional.of(new RemoveFlowInputBuilder(sourceFlow).setMatch(match).build());
438 } else if (sourceFlow instanceof UpdatedFlow) {
439 return Optional.of(new UpdatedFlowBuilder(sourceFlow).setMatch(match).build());
441 return Optional.empty();
445 private static Optional<? extends Flow> injectMatchAndAction(Flow sourceFlow, Match match) {
447 Instructions instructions = new InstructionsBuilder()
448 .setInstruction(injectPushActionToInstruction(sourceFlow))
451 if (sourceFlow instanceof AddFlowInput) {
452 return Optional.of(new AddFlowInputBuilder(sourceFlow)
453 .setMatch(match).setInstructions(instructions).build());
454 } else if (sourceFlow instanceof RemoveFlowInput) {
455 return Optional.of(new RemoveFlowInputBuilder(sourceFlow)
456 .setMatch(match).setInstructions(instructions).build());
457 } else if (sourceFlow instanceof UpdatedFlow) {
458 return Optional.of(new UpdatedFlowBuilder(sourceFlow)
459 .setMatch(match).setInstructions(instructions).build());
461 return Optional.empty();
465 private static List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction>
466 injectPushActionToInstruction(final Flow sourceFlow) {
468 List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction>
469 srcInstructionList = sourceFlow.getInstructions().getInstruction();
471 List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction>
472 targetInstructionList = new ArrayList<>(srcInstructionList.size());
473 List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action>
474 targetActionList = new ArrayList<>();
476 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder
477 instructionBuilder = new org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction
478 .list.InstructionBuilder();
480 for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction
481 srcInstruction : srcInstructionList) {
482 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction
483 curSrcInstruction = srcInstruction.getInstruction();
485 if (curSrcInstruction instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026
486 .instruction.instruction.ApplyActionsCase) {
487 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction
488 .ApplyActionsCase applyActionscase = (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types
489 .rev131026.instruction.instruction.ApplyActionsCase) curSrcInstruction;
490 ApplyActions applyActions = applyActionscase.getApplyActions();
491 List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action>
492 srcActionList = applyActions.getAction();
495 for (org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action
496 actionItem : srcActionList) {
497 // check if its a set-vlan-action. If yes, then add the injected-action
499 if (actionItem.getAction() instanceof SetVlanIdActionCase) {
500 SetVlanIdActionCase setVlanIdActionCase = (SetVlanIdActionCase) actionItem.getAction();
502 PushVlanActionCaseBuilder pushVlanActionCaseBuilder = new PushVlanActionCaseBuilder();
503 PushVlanActionBuilder pushVlanActionBuilder = new PushVlanActionBuilder();
505 pushVlanActionBuilder.setCfi(new VlanCfi(1))
506 .setVlanId(setVlanIdActionCase.getSetVlanIdAction().getVlanId())
507 .setEthernetType(PUSH_VLAN)
509 pushVlanActionCaseBuilder.setPushVlanAction(pushVlanActionBuilder.build());
510 PushVlanActionCase injectedAction = pushVlanActionCaseBuilder.build();
512 ActionBuilder actionBuilder = new ActionBuilder();
513 actionBuilder.setAction(injectedAction)
514 .setKey(actionItem.getKey())
515 .setOrder(actionItem.getOrder() + offset);
517 targetActionList.add(actionBuilder.build());
522 // we need to increment the order for all the actions added after injection
523 ActionBuilder actionBuilder =
524 new ActionBuilder(actionItem);
525 actionBuilder.setOrder(actionItem.getOrder() + offset);
526 actionItem = actionBuilder.build();
529 targetActionList.add(actionItem);
532 ApplyActionsCaseBuilder applyActionsCaseBuilder = new ApplyActionsCaseBuilder();
533 ApplyActionsBuilder applyActionsBuilder = new ApplyActionsBuilder();
534 applyActionsBuilder.setAction(targetActionList);
535 applyActionsCaseBuilder.setApplyActions(applyActionsBuilder.build());
537 instructionBuilder.setInstruction(applyActionsCaseBuilder.build());
539 instructionBuilder.setInstruction(curSrcInstruction);
543 .setKey(srcInstruction.getKey())
544 .setOrder(srcInstruction.getOrder());
545 targetInstructionList.add(instructionBuilder.build());
549 return targetInstructionList;
553 public Collection<Class<?>> getTypes() {
558 public List<FlowModInputBuilder> convert(Flow source, VersionDatapathIdConvertorData data) {
559 if (data.getVersion() >= OFConstants.OFP_VERSION_1_3 && isSetVlanIdActionCasePresent(source)) {
560 return handleSetVlanIdForOF13(source, data);
562 return Collections.singletonList(toFlowModInput(source, data));