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.Ordering;
14 import java.math.BigInteger;
15 import java.util.ArrayList;
16 import java.util.Collections;
17 import java.util.List;
18 import java.util.Optional;
19 import org.opendaylight.openflowplugin.api.OFConstants;
20 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManager;
21 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.action.data.ActionConvertorData;
22 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.Convertor;
23 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.ConvertorProcessor;
24 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.OrderComparator;
25 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionDatapathIdConvertorData;
26 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flow.cases.ApplyActionsCase;
27 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flow.cases.ClearActionsCase;
28 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flow.cases.GoToTableCase;
29 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flow.cases.MeterCase;
30 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flow.cases.WriteActionsCase;
31 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flow.cases.WriteMetadataCase;
32 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flow.flowflag.FlowFlagReactor;
33 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.MatchReactor;
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.binding.DataContainer;
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.
76 * VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(version);
77 * data.setDatapathId(datapathId);
78 * Optional<List<FlowModInputBuilder>> ofFlow = ConvertorManager.getInstance().convert(salFlow, data);
82 public class FlowConvertor implements Convertor<Flow, List<FlowModInputBuilder>, VersionDatapathIdConvertorData> {
84 * Default idle timeout
86 public static final Integer DEFAULT_IDLE_TIMEOUT = 0;
88 * Default hard timeout
90 public static final Integer DEFAULT_HARD_TIMEOUT = 0;
94 public static final Integer DEFAULT_PRIORITY = Integer.parseInt("8000", 16);
98 public static final boolean DEFAULT_OFPFF_FLOW_REM = false;
100 * flow flag: check overlap
102 public static final boolean DEFAULT_OFPFF_CHECK_OVERLAP = false;
104 * flow flag: reset counts
106 public static final boolean DEFAULT_OFPFF_RESET_COUNTS = false;
108 * flow flag: don't keep track of packet counts
110 public static final boolean DEFAULT_OFPFF_NO_PKT_COUNTS = false;
112 * flow flag: don't keep track of byte counts
114 public static final boolean DEFAULT_OFPFF_NO_BYT_COUNTS = false;
116 * flow flag: emergency [OFP-1.0]
118 public static final boolean DEFAULT_OFPFF_EMERGENCY = false;
122 public static final Class<? extends MatchTypeBase> DEFAULT_MATCH_TYPE = OxmMatchType.class;
124 * default match entries - empty
126 public static final List<MatchEntry> DEFAULT_MATCH_ENTRIES = new ArrayList<>();
128 // Default values for when things are null
129 private static final TableId DEFAULT_TABLE_ID = new TableId(0L);
130 private static final Long DEFAULT_BUFFER_ID = OFConstants.OFP_NO_BUFFER;
131 private static final Long OFPP_ANY = Long.parseLong("ffffffff", 16);
132 private static final Long DEFAULT_OUT_PORT = OFPP_ANY;
133 private static final Long OFPG_ANY = Long.parseLong("ffffffff", 16);
134 private static final Long DEFAULT_OUT_GROUP = OFPG_ANY;
135 private static final Integer PUSH_VLAN = 0x8100;
136 private static final Ordering<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction> INSTRUCTION_ORDERING = Ordering.from(OrderComparator.build());
137 private static final VlanMatch VLAN_MATCH_FALSE;
138 private static final VlanMatch VLAN_MATCH_TRUE;
139 private static final ConvertorProcessor<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction, Instruction, ActionConvertorData> PROCESSOR = new ConvertorProcessor<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction, Instruction, ActionConvertorData>()
140 .addCase(new ApplyActionsCase())
141 .addCase(new ClearActionsCase())
142 .addCase(new GoToTableCase())
143 .addCase(new MeterCase())
144 .addCase(new WriteActionsCase())
145 .addCase(new WriteMetadataCase());
148 final VlanId zeroVlan = new VlanId(0);
149 VlanMatchBuilder vlanMatchBuilder = new VlanMatchBuilder();
150 VlanIdBuilder vlanIdBuilder = new VlanIdBuilder();
151 vlanIdBuilder.setVlanIdPresent(false);
152 vlanIdBuilder.setVlanId(zeroVlan);
153 vlanMatchBuilder.setVlanId(vlanIdBuilder.build());
155 VLAN_MATCH_FALSE = vlanMatchBuilder.build();
157 VlanMatchBuilder vlanMatchBuilder2 = new VlanMatchBuilder();
158 VlanIdBuilder vlanIdBuilder2 = new VlanIdBuilder();
159 vlanIdBuilder2.setVlanIdPresent(true);
160 vlanIdBuilder2.setVlanId(zeroVlan);
161 vlanMatchBuilder2.setVlanId(vlanIdBuilder2.build());
163 VLAN_MATCH_TRUE = vlanMatchBuilder2.build();
166 private static FlowModInputBuilder toFlowModInput(Flow flow, short version, BigInteger datapathid) {
168 FlowModInputBuilder flowMod = new FlowModInputBuilder();
169 salToOFFlowCookie(flow, flowMod);
170 salToOFFlowCookieMask(flow, flowMod);
171 salToOFFlowTableId(flow, flowMod);
172 salToOFFlowCommand(flow, flowMod);
173 salToOFFlowIdleTimeout(flow, flowMod);
174 salToOFFlowHardTimeout(flow, flowMod);
175 salToOFFlowPriority(flow, flowMod);
176 salToOFFlowBufferId(flow, flowMod);
177 salToOFFlowOutPort(flow, flowMod);
178 salToOFFlowOutGroup(flow, flowMod);
180 // convert and inject flowFlags
181 FlowFlagReactor.getInstance().convert(flow.getFlags(), version, flowMod);
183 // convert and inject match
184 MatchReactor.getInstance().convert(flow.getMatch(), version, flowMod);
186 if (flow.getInstructions() != null) {
187 flowMod.setInstruction(toInstructions(flow, version, datapathid));
188 flowMod.setAction(getActions(version, datapathid, flow));
191 flowMod.setVersion(version);
196 private static void salToOFFlowOutGroup(Flow flow, FlowModInputBuilder flowMod) {
197 if (flow.getOutGroup() != null) {
198 flowMod.setOutGroup(flow.getOutGroup());
200 flowMod.setOutGroup(DEFAULT_OUT_GROUP);
204 private static void salToOFFlowOutPort(Flow flow, FlowModInputBuilder flowMod) {
205 if (flow.getOutPort() != null) {
206 flowMod.setOutPort(new PortNumber(flow.getOutPort().longValue()));
208 flowMod.setOutPort(new PortNumber(DEFAULT_OUT_PORT));
212 private static void salToOFFlowBufferId(Flow flow, FlowModInputBuilder flowMod) {
213 if (flow.getBufferId() != null) {
214 flowMod.setBufferId(flow.getBufferId());
216 flowMod.setBufferId(DEFAULT_BUFFER_ID);
220 private static void salToOFFlowPriority(Flow flow, FlowModInputBuilder flowMod) {
221 if (flow.getPriority() != null) {
222 flowMod.setPriority(flow.getPriority());
224 flowMod.setPriority(DEFAULT_PRIORITY);
228 private static void salToOFFlowHardTimeout(Flow flow, FlowModInputBuilder flowMod) {
229 if (flow.getHardTimeout() != null) {
230 flowMod.setHardTimeout(flow.getHardTimeout());
232 flowMod.setHardTimeout(DEFAULT_HARD_TIMEOUT);
236 private static void salToOFFlowIdleTimeout(Flow flow, FlowModInputBuilder flowMod) {
237 if (flow.getIdleTimeout() != null) {
238 flowMod.setIdleTimeout(flow.getIdleTimeout());
240 flowMod.setIdleTimeout(DEFAULT_IDLE_TIMEOUT);
244 private static void salToOFFlowCommand(Flow flow, FlowModInputBuilder flowMod) {
245 if (flow instanceof AddFlowInput || flow instanceof UpdatedFlow) {
246 flowMod.setCommand(FlowModCommand.OFPFCADD);
247 } else if (flow instanceof RemoveFlowInput) {
248 if (MoreObjects.firstNonNull(flow.isStrict(), Boolean.FALSE)) {
249 flowMod.setCommand(FlowModCommand.OFPFCDELETESTRICT);
251 flowMod.setCommand(FlowModCommand.OFPFCDELETE);
256 private static void salToOFFlowTableId(Flow flow, FlowModInputBuilder flowMod) {
257 if (flow.getTableId() != null) {
258 flowMod.setTableId(new TableId(flow.getTableId().longValue()));
260 flowMod.setTableId(DEFAULT_TABLE_ID);
264 private static void salToOFFlowCookieMask(Flow flow, FlowModInputBuilder flowMod) {
265 if (flow.getCookieMask() != null) {
266 flowMod.setCookieMask(flow.getCookieMask().getValue());
268 flowMod.setCookieMask(OFConstants.DEFAULT_COOKIE_MASK);
272 private static void salToOFFlowCookie(Flow flow, FlowModInputBuilder flowMod) {
273 if (flow.getCookie() != null) {
274 flowMod.setCookie(flow.getCookie().getValue());
276 flowMod.setCookie(OFConstants.DEFAULT_COOKIE);
280 private static List<Instruction> toInstructions(Flow flow, short version, BigInteger datapathid) {
281 final List<Instruction> instructionsList = new ArrayList<>();
282 final ActionConvertorData data = new ActionConvertorData(version);
283 data.setDatapathId(datapathid);
284 data.setIpProtocol(FlowConvertorUtil.getIpProtocolFromFlow(flow));
286 Instructions instructions = flow.getInstructions();
288 for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction instruction : instructions
290 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curInstruction = instruction
293 Optional<Instruction> result = PROCESSOR.process(curInstruction, data);
295 if (result.isPresent()) {
296 instructionsList.add(result.get());
300 return instructionsList;
303 private static List<Action> getActions(short version, BigInteger datapathid, Flow flow) {
304 Instructions instructions = flow.getInstructions();
305 List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction> sortedInstructions =
306 INSTRUCTION_ORDERING.sortedCopy(instructions.getInstruction());
308 for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction instruction : sortedInstructions) {
309 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curInstruction = instruction
312 if (curInstruction instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase) {
313 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase applyActionscase = (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase) curInstruction;
314 ApplyActions applyActions = applyActionscase.getApplyActions();
316 final ActionConvertorData data = new ActionConvertorData(version);
317 data.setDatapathId(datapathid);
318 data.setIpProtocol(FlowConvertorUtil.getIpProtocolFromFlow(flow));
319 Optional<List<Action>> result = ConvertorManager.getInstance().convert(applyActions.getAction(), data);
320 return result.orElse(Collections.emptyList());
327 // check if set vlanid action is present in the flow
328 private static boolean isSetVlanIdActionCasePresent(Flow flow) {
329 // we are trying to find if there is a set-vlan-id action (OF1.0) action present in the flow.
330 // If yes,then we would need to two flows
331 if (flow.getInstructions() != null && flow.getInstructions().getInstruction() != null) {
332 for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction instruction :
333 flow.getInstructions().getInstruction()) {
334 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curInstruction =
335 instruction.getInstruction();
337 if (curInstruction instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase) {
338 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase applyActionscase = (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase) curInstruction;
339 ApplyActions applyActions = applyActionscase.getApplyActions();
340 for (org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action action :
341 applyActions.getAction()) {
342 if (action.getAction() instanceof SetVlanIdActionCase) {
354 * A) If user provided flow's match includes vlan match  and action has set_vlan_field
355 * Install following rules
356 * Â Â 1) match on (OFPVID_PRESENT |value) without mask + action [set_field]
358 * B) if user provided flow's match doesn't include vlan match but action has set_vlan field
359 * Â Â 1) Match on (OFPVID_NONEÂ ) without mask + action [push vlan tag + set_field]
360 * Â Â 2) Match on (OFPVID_PRESENT) with mask (OFPVID_PRESENT ) + action [ set_field]
362 private static List<FlowModInputBuilder> handleSetVlanIdForOF13(Flow srcFlow, short version, BigInteger datapathId) {
363 List<FlowModInputBuilder> list = new ArrayList<>(2);
365 final Match srcMatch = Preconditions.checkNotNull(srcFlow.getMatch());
366 final VlanMatch srcVlanMatch = srcMatch.getVlanMatch();
367 if (srcVlanMatch != null) {
368 //create flow with setfield and match
369 // match on vlan tag or vlanid with no mask
370 VlanMatchBuilder vlanMatchBuilder = new VlanMatchBuilder(srcVlanMatch);
371 VlanIdBuilder vlanIdBuilder = new VlanIdBuilder();
372 vlanIdBuilder.setVlanIdPresent(srcVlanMatch.getVlanId().isVlanIdPresent());
373 vlanIdBuilder.setVlanId(srcVlanMatch.getVlanId().getVlanId());
374 vlanMatchBuilder.setVlanId(vlanIdBuilder.build());
375 Match match = new MatchBuilder(srcMatch).setVlanMatch(vlanMatchBuilder.build()).build();
377 Optional<? extends Flow> optional = injectMatchToFlow(srcFlow, match);
378 if (optional.isPresent()) {
379 list.add(toFlowModInput(optional.get(), version, datapathId));
384 // match on no vlan tag with no mask
385 Match match1 = new MatchBuilder(srcMatch).setVlanMatch(VLAN_MATCH_FALSE).build();
387 Optional<? extends Flow> optional1 = injectMatchAndAction(srcFlow, match1);
388 if (optional1.isPresent()) {
389 list.add(toFlowModInput(optional1.get(), version, datapathId));
393 // match on vlan tag with mask
394 Match match2 = new MatchBuilder(srcMatch).setVlanMatch(VLAN_MATCH_TRUE).build();
395 Optional<? extends Flow> optional2 = injectMatchToFlow(srcFlow, match2);
396 if (optional2.isPresent()) {
397 list.add(toFlowModInput(optional2.get(), version, datapathId));
404 private static Optional<? extends Flow> injectMatchToFlow(Flow sourceFlow, Match match) {
405 if (sourceFlow instanceof AddFlowInput) {
406 return Optional.of(new AddFlowInputBuilder(sourceFlow).setMatch(match).build());
407 } else if (sourceFlow instanceof RemoveFlowInput) {
408 return Optional.of(new RemoveFlowInputBuilder(sourceFlow).setMatch(match).build());
409 } else if (sourceFlow instanceof UpdatedFlow) {
410 return Optional.of(new UpdatedFlowBuilder(sourceFlow).setMatch(match).build());
412 return Optional.empty();
416 private static Optional<? extends Flow> injectMatchAndAction(Flow sourceFlow, Match match) {
418 Instructions instructions = (new InstructionsBuilder())
419 .setInstruction(injectPushActionToInstruction(sourceFlow))
422 if (sourceFlow instanceof AddFlowInput) {
423 return Optional.of(new AddFlowInputBuilder(sourceFlow)
424 .setMatch(match).setInstructions(instructions).build());
425 } else if (sourceFlow instanceof RemoveFlowInput) {
426 return Optional.of(new RemoveFlowInputBuilder(sourceFlow)
427 .setMatch(match).setInstructions(instructions).build());
428 } else if (sourceFlow instanceof UpdatedFlow) {
429 return Optional.of(new UpdatedFlowBuilder(sourceFlow)
430 .setMatch(match).setInstructions(instructions).build());
432 return Optional.empty();
436 private static List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction>
437 injectPushActionToInstruction(final Flow sourceFlow) {
439 List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction> srcInstructionList =
440 sourceFlow.getInstructions().getInstruction();
442 List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction> targetInstructionList = new ArrayList<>(srcInstructionList.size());
443 List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> targetActionList = new ArrayList<>();
445 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder instructionBuilder =
446 new org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder();
448 for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction srcInstruction : srcInstructionList) {
449 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curSrcInstruction =
450 srcInstruction.getInstruction();
452 if (curSrcInstruction instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase) {
453 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase applyActionscase = (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase) curSrcInstruction;
454 ApplyActions applyActions = applyActionscase.getApplyActions();
455 List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> srcActionList = applyActions.getAction();
458 for (org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action actionItem : srcActionList) {
459 // check if its a set-vlan-action. If yes, then add the injected-action
461 if (actionItem.getAction() instanceof SetVlanIdActionCase) {
462 SetVlanIdActionCase setVlanIdActionCase = (SetVlanIdActionCase) actionItem.getAction();
464 PushVlanActionCaseBuilder pushVlanActionCaseBuilder = new PushVlanActionCaseBuilder();
465 PushVlanActionBuilder pushVlanActionBuilder = new PushVlanActionBuilder();
467 pushVlanActionBuilder.setCfi(new VlanCfi(1))
468 .setVlanId(setVlanIdActionCase.getSetVlanIdAction().getVlanId())
469 .setEthernetType(PUSH_VLAN)
471 pushVlanActionCaseBuilder.setPushVlanAction(pushVlanActionBuilder.build());
472 PushVlanActionCase injectedAction = pushVlanActionCaseBuilder.build();
474 ActionBuilder actionBuilder = new ActionBuilder();
475 actionBuilder.setAction(injectedAction)
476 .setKey(actionItem.getKey())
477 .setOrder(actionItem.getOrder() + offset);
479 targetActionList.add(actionBuilder.build());
484 // we need to increment the order for all the actions added after injection
485 ActionBuilder actionBuilder =
486 new ActionBuilder(actionItem);
487 actionBuilder.setOrder(actionItem.getOrder() + offset);
488 actionItem = actionBuilder.build();
491 targetActionList.add(actionItem);
494 ApplyActionsCaseBuilder applyActionsCaseBuilder = new ApplyActionsCaseBuilder();
495 ApplyActionsBuilder applyActionsBuilder = new ApplyActionsBuilder();
496 applyActionsBuilder.setAction(targetActionList);
497 applyActionsCaseBuilder.setApplyActions(applyActionsBuilder.build());
499 instructionBuilder.setInstruction(applyActionsCaseBuilder.build());
501 instructionBuilder.setInstruction(curSrcInstruction);
505 .setKey(srcInstruction.getKey())
506 .setOrder(srcInstruction.getOrder());
507 targetInstructionList.add(instructionBuilder.build());
511 return targetInstructionList;
515 public Class<? extends DataContainer> getType() {
520 public List<FlowModInputBuilder> convert(Flow source, VersionDatapathIdConvertorData data) {
521 if (data.getVersion() >= OFConstants.OFP_VERSION_1_3 && isSetVlanIdActionCasePresent(source)) {
522 return handleSetVlanIdForOF13(source, data.getVersion(), data.getDatapathId());
524 return Collections.singletonList(toFlowModInput(source, data.getVersion(), data.getDatapathId()));