2 * Copyright (c) 2013-2014 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;
11 import com.google.common.base.Objects;
12 import com.google.common.base.Optional;
13 import com.google.common.collect.Ordering;
15 import org.opendaylight.openflowplugin.api.OFConstants;
16 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.OrderComparator;
17 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flowflag.FlowFlagReactor;
18 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.MatchReactor;
19 import org.opendaylight.openflowplugin.openflow.md.util.ByteUtil;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.VlanCfi;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCase;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCaseBuilder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdActionCase;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.push.vlan.action._case.PushVlanActionBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlow;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlowBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ClearActionsCase;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.GoToTableCase;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.MeterCase;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteActionsCase;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteMetadataCase;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActions;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.clear.actions._case.ClearActions;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.go.to.table._case.GoToTable;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.meter._case.Meter;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.actions._case.WriteActions;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.metadata._case.WriteMetadata;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatch;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ActionsInstruction;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ActionsInstructionBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MetadataInstruction;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MetadataInstructionBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MeterIdInstruction;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MeterIdInstructionBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.TableIdInstruction;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.TableIdInstructionBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.actions.grouping.Action;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instructions.grouping.Instruction;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instructions.grouping.InstructionBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowModCommand;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MatchTypeBase;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortNumber;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.TableId;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.OxmMatchType;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.oxm.fields.grouping.MatchEntries;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowModInputBuilder;
73 import org.slf4j.Logger;
74 import org.slf4j.LoggerFactory;
76 import java.math.BigInteger;
77 import java.util.ArrayList;
78 import java.util.List;
81 * Utility class for converting a MD-SAL Flow into the OF flow mod
83 public class FlowConvertor {
84 private static final Logger logger = LoggerFactory.getLogger(FlowConvertor.class);
86 // Default values for when things are null
87 private static final TableId DEFAULT_TABLE_ID = new TableId(0L);
88 /** Default idle timeout */
89 public static final Integer DEFAULT_IDLE_TIMEOUT = 5 * 60;
90 /** Default hard timeout */
91 public static final Integer DEFAULT_HARD_TIMEOUT = 10 * 60;
92 /** Default priority */
93 public static final Integer DEFAULT_PRIORITY = Integer.parseInt("8000", 16);
94 private static final Long DEFAULT_BUFFER_ID = Long.parseLong("ffffffff", 16);
95 private static final Long OFPP_ANY = Long.parseLong("ffffffff", 16);
96 private static final Long DEFAULT_OUT_PORT = OFPP_ANY;
97 private static final Long OFPG_ANY = Long.parseLong("ffffffff", 16);
98 private static final Long DEFAULT_OUT_GROUP = OFPG_ANY;
99 /** flow flag: remove */
100 public static final boolean DEFAULT_OFPFF_FLOW_REM = false;
101 /** flow flag: check overlap */
102 public static final boolean DEFAULT_OFPFF_CHECK_OVERLAP = false;
103 /** flow flag: reset counts */
104 public static final boolean DEFAULT_OFPFF_RESET_COUNTS = false;
105 /** flow flag: don't keep track of packet counts */
106 public static final boolean DEFAULT_OFPFF_NO_PKT_COUNTS = false;
107 /** flow flag: don't keep track of byte counts */
108 public static final boolean DEFAULT_OFPFF_NO_BYT_COUNTS = false;
109 /** flow flag: emergency [OFP-1.0] */
110 public static final boolean DEFAULT_OFPFF_EMERGENCY = false;
112 public static final Class<? extends MatchTypeBase> DEFAULT_MATCH_TYPE = OxmMatchType.class;
113 /** default match entries - empty */
114 public static final List<MatchEntries> DEFAULT_MATCH_ENTRIES = new ArrayList<MatchEntries>();
118 * This method converts the SAL Flow to OF Flow.
119 * It checks if there is a set-vlan-id (1.0) action made on OF1.3.
120 * If yes its handled separately
122 public static List<FlowModInputBuilder> toFlowModInputs(Flow srcFlow, short version, BigInteger datapathId) {
123 List<FlowModInputBuilder> list = new ArrayList<>();
125 if (version >= OFConstants.OFP_VERSION_1_3 && isSetVlanIdActionCasePresent(srcFlow)) {
126 list.addAll(handleSetVlanIdForOF13(srcFlow, version, datapathId));
128 list.add(toFlowModInput(srcFlow, version, datapathId));
133 public static FlowModInputBuilder toFlowModInput(Flow flow, short version, BigInteger datapathid) {
135 FlowModInputBuilder flowMod = new FlowModInputBuilder();
136 if (flow.getCookie() != null) {
137 flowMod.setCookie(flow.getCookie().getValue());
139 flowMod.setCookie(OFConstants.DEFAULT_COOKIE);
142 if (flow.getCookieMask() != null) {
143 flowMod.setCookieMask(flow.getCookieMask().getValue());
145 flowMod.setCookieMask(OFConstants.DEFAULT_COOKIE_MASK);
148 if (flow.getTableId() != null) {
149 flowMod.setTableId(new TableId(flow.getTableId().longValue()));
151 flowMod.setTableId(DEFAULT_TABLE_ID);
154 if (flow instanceof AddFlowInput) {
155 flowMod.setCommand(FlowModCommand.OFPFCADD);
156 } else if (flow instanceof RemoveFlowInput) {
157 if (Objects.firstNonNull(flow.isStrict(), Boolean.FALSE)) {
158 flowMod.setCommand(FlowModCommand.OFPFCDELETESTRICT);
160 flowMod.setCommand(FlowModCommand.OFPFCDELETE);
162 } else if (flow instanceof UpdatedFlow) {
163 if (Objects.firstNonNull(flow.isStrict(), Boolean.FALSE)) {
164 flowMod.setCommand(FlowModCommand.OFPFCMODIFYSTRICT);
166 flowMod.setCommand(FlowModCommand.OFPFCMODIFY);
170 if (flow.getIdleTimeout() != null) {
171 flowMod.setIdleTimeout(flow.getIdleTimeout());
173 flowMod.setIdleTimeout(DEFAULT_IDLE_TIMEOUT);
175 if (flow.getHardTimeout() != null) {
176 flowMod.setHardTimeout(flow.getHardTimeout());
178 flowMod.setHardTimeout(DEFAULT_HARD_TIMEOUT);
180 if (flow.getPriority() != null) {
181 flowMod.setPriority(flow.getPriority());
183 flowMod.setPriority(DEFAULT_PRIORITY);
185 if (flow.getBufferId() != null) {
186 flowMod.setBufferId(flow.getBufferId());
188 flowMod.setBufferId(DEFAULT_BUFFER_ID);
191 if (flow.getOutPort() != null) {
192 flowMod.setOutPort(new PortNumber(flow.getOutPort().longValue()));
194 flowMod.setOutPort(new PortNumber(DEFAULT_OUT_PORT));
196 if (flow.getOutGroup() != null) {
197 flowMod.setOutGroup(flow.getOutGroup());
199 flowMod.setOutGroup(DEFAULT_OUT_GROUP);
203 // convert and inject flowFlags
204 FlowFlagReactor.getInstance().convert(flow.getFlags(), version, flowMod,datapathid);
206 // convert and inject match
207 MatchReactor.getInstance().convert(flow.getMatch(), version, flowMod,datapathid);
209 if (flow.getInstructions() != null) {
210 flowMod.setInstruction(toInstructions(flow, version,datapathid));
211 flowMod.setAction(getActions(version,datapathid, flow));
213 flowMod.setVersion(version);
218 private static List<Instruction> toInstructions(
220 short version,BigInteger datapathid) {
221 List<Instruction> instructionsList = new ArrayList<>();
223 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions instructions = flow.getInstructions();
224 for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction instruction : instructions
226 InstructionBuilder instructionBuilder = new InstructionBuilder();
227 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curInstruction = instruction
229 if (curInstruction instanceof GoToTableCase) {
230 GoToTableCase goToTablecase = (GoToTableCase) curInstruction;
231 GoToTable goToTable = goToTablecase.getGoToTable();
233 .setType(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.GotoTable.class);
234 TableIdInstructionBuilder tableBuilder = new TableIdInstructionBuilder();
235 tableBuilder.setTableId(goToTable.getTableId());
236 instructionBuilder.addAugmentation(TableIdInstruction.class, tableBuilder.build());
237 instructionsList.add(instructionBuilder.build());
240 else if (curInstruction instanceof WriteMetadataCase) {
241 WriteMetadataCase writeMetadatacase = (WriteMetadataCase) curInstruction;
242 WriteMetadata writeMetadata = writeMetadatacase.getWriteMetadata();
244 .setType(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.WriteMetadata.class);
245 MetadataInstructionBuilder metadataBuilder = new MetadataInstructionBuilder();
246 metadataBuilder.setMetadata(ByteUtil.convertBigIntegerToNBytes(writeMetadata.getMetadata(),
247 OFConstants.SIZE_OF_LONG_IN_BYTES));
249 .setMetadataMask(ByteUtil.convertBigIntegerToNBytes(writeMetadata.getMetadataMask(),
250 OFConstants.SIZE_OF_LONG_IN_BYTES));
251 instructionBuilder.addAugmentation(MetadataInstruction.class, metadataBuilder.build());
252 instructionsList.add(instructionBuilder.build());
255 else if (curInstruction instanceof WriteActionsCase) {
256 WriteActionsCase writeActionscase = (WriteActionsCase) curInstruction;
257 WriteActions writeActions = writeActionscase.getWriteActions();
259 .setType(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.WriteActions.class);
260 ActionsInstructionBuilder actionsInstructionBuilder = new ActionsInstructionBuilder();
261 actionsInstructionBuilder.setAction(ActionConvertor.getActions(writeActions.getAction(),
262 version,datapathid, flow));
263 instructionBuilder.addAugmentation(ActionsInstruction.class, actionsInstructionBuilder.build());
264 instructionsList.add(instructionBuilder.build());
267 else if (curInstruction instanceof ApplyActionsCase) {
268 ApplyActionsCase applyActionscase = (ApplyActionsCase) curInstruction;
269 ApplyActions applyActions = applyActionscase.getApplyActions();
271 .setType(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.ApplyActions.class);
272 ActionsInstructionBuilder actionsInstructionBuilder = new ActionsInstructionBuilder();
273 actionsInstructionBuilder.setAction(ActionConvertor.getActions(applyActions.getAction(),
274 version,datapathid, flow));
275 instructionBuilder.addAugmentation(ActionsInstruction.class, actionsInstructionBuilder.build());
276 instructionsList.add(instructionBuilder.build());
279 else if (curInstruction instanceof ClearActionsCase) {
280 ClearActionsCase clearActionscase = (ClearActionsCase) curInstruction;
281 ClearActions clearActions = clearActionscase.getClearActions();
283 .setType(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.ClearActions.class);
284 instructionsList.add(instructionBuilder.build());
287 else if (curInstruction instanceof MeterCase) {
288 MeterCase metercase = (MeterCase) curInstruction;
289 Meter meter = metercase.getMeter();
291 .setType(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.Meter.class);
292 MeterIdInstructionBuilder meterBuilder = new MeterIdInstructionBuilder();
293 Long meterId = meter.getMeterId().getValue();
294 meterBuilder.setMeterId(meterId);
295 instructionBuilder.addAugmentation(MeterIdInstruction.class, meterBuilder.build());
296 instructionsList.add(instructionBuilder.build());
299 return instructionsList;
302 /*private static List<Action> getActions(
303 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions instructions,
304 short version,BigInteger datapathid) {*/
305 private static List<Action> getActions(short version,BigInteger datapathid, Flow flow) {
307 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions instructions = flow.getInstructions();
308 List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction> sortedInstructions =
309 Ordering.from(OrderComparator.<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction>toInstance())
310 .sortedCopy(instructions.getInstruction());
312 for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction instruction : sortedInstructions) {
313 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curInstruction = instruction
316 if (curInstruction instanceof ApplyActionsCase) {
317 ApplyActionsCase applyActionscase = (ApplyActionsCase) curInstruction;
318 ApplyActions applyActions = applyActionscase.getApplyActions();
319 return ActionConvertor.getActions(applyActions.getAction(), version,datapathid, flow);
325 // check if set vlanid action is present in the flow
326 private static boolean isSetVlanIdActionCasePresent(Flow flow) {
327 boolean isPresent = false;
328 // we are trying to find if there is a set-vlan-id action (OF1.0) action present in the flow.
329 // If yes,then we would need to two flows
330 if (flow.getInstructions() != null) {
331 for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction instruction :
332 flow.getInstructions().getInstruction()) {
333 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curInstruction =
334 instruction.getInstruction();
336 if (curInstruction instanceof ApplyActionsCase) {
337 ApplyActionsCase applyActionscase = (ApplyActionsCase) curInstruction;
338 ApplyActions applyActions = applyActionscase.getApplyActions();
339 for (org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action action :
340 applyActions.getAction()) {
341 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<>();
365 VlanMatch srcVlanMatch = srcFlow.getMatch().getVlanMatch();
366 boolean hasVlanMatch = (srcFlow.getMatch() != null && 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(srcFlow.getMatch()).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 VlanMatchBuilder vlanMatchBuilder = new VlanMatchBuilder();
386 VlanIdBuilder vlanIdBuilder = new VlanIdBuilder();
387 vlanIdBuilder.setVlanIdPresent(false);
388 vlanIdBuilder.setVlanId(new VlanId(0));
389 vlanMatchBuilder.setVlanId(vlanIdBuilder.build());
390 Match match1 = new MatchBuilder(srcFlow.getMatch()).setVlanMatch(vlanMatchBuilder.build()).build();
392 Optional<? extends Flow> optional1 = injectMatchAndAction(srcFlow, match1);
393 if (optional1.isPresent()) {
394 list.add(toFlowModInput(optional1.get(), version, datapathId));
398 // match on vlan tag with mask
399 VlanMatchBuilder vlanMatchBuilder2 = new VlanMatchBuilder();
400 VlanIdBuilder vlanIdBuilder2 = new VlanIdBuilder();
401 vlanIdBuilder2.setVlanIdPresent(true);
402 vlanIdBuilder2.setVlanId(new VlanId(0));
403 vlanMatchBuilder2.setVlanId(vlanIdBuilder2.build());
404 Match match2 = new MatchBuilder(srcFlow.getMatch()).setVlanMatch(vlanMatchBuilder2.build()).build();
405 Optional<? extends Flow> optional2 = injectMatchToFlow(srcFlow, match2);
406 if (optional2.isPresent()) {
407 list.add(toFlowModInput(optional2.get(), version, datapathId));
414 private static Optional<? extends Flow> injectMatchToFlow(Flow sourceFlow, Match match) {
415 if (sourceFlow instanceof AddFlowInput) {
416 return Optional.<AddFlowInput>of(new AddFlowInputBuilder(sourceFlow).setMatch(match).build());
417 } else if (sourceFlow instanceof RemoveFlowInput) {
418 return Optional.<RemoveFlowInput>of(new RemoveFlowInputBuilder(sourceFlow).setMatch(match).build());
419 } else if (sourceFlow instanceof UpdatedFlow) {
420 return Optional.<UpdatedFlow>of(new UpdatedFlowBuilder(sourceFlow).setMatch(match).build());
422 return Optional.<Flow>absent();
426 private static Optional<? extends Flow> injectMatchAndAction(Flow sourceFlow, Match match) {
428 Instructions instructions = (new InstructionsBuilder())
429 .setInstruction(injectPushActionToInstruction(sourceFlow))
432 if (sourceFlow instanceof AddFlowInput) {
433 return Optional.<AddFlowInput>of(new AddFlowInputBuilder(sourceFlow)
434 .setMatch(match).setInstructions(instructions).build());
435 } else if (sourceFlow instanceof RemoveFlowInput) {
436 return Optional.<RemoveFlowInput>of(new RemoveFlowInputBuilder(sourceFlow)
437 .setMatch(match).setInstructions(instructions).build());
438 } else if (sourceFlow instanceof UpdatedFlow) {
439 return Optional.<UpdatedFlow>of(new UpdatedFlowBuilder(sourceFlow)
440 .setMatch(match).setInstructions(instructions).build());
442 return Optional.<Flow>absent();
446 private static List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction>
447 injectPushActionToInstruction(final Flow sourceFlow) {
449 List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction> srcInstructionList =
450 sourceFlow.getInstructions().getInstruction();
452 List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction> targetInstructionList = new ArrayList<>(srcInstructionList.size());
453 List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> targetActionList = new ArrayList<>();
455 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder instructionBuilder =
456 new org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder();
458 for (int i=0; i < srcInstructionList.size(); i++) {
459 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction srcInstruction =
460 srcInstructionList.get(i);
461 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curSrcInstruction =
462 srcInstruction.getInstruction();
464 if (curSrcInstruction instanceof ApplyActionsCase) {
465 ApplyActionsCase applyActionscase = (ApplyActionsCase) curSrcInstruction;
466 ApplyActions applyActions = applyActionscase.getApplyActions();
467 List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> srcActionList = applyActions.getAction();
470 for (int j=0; j < srcActionList.size(); j++) {
471 // check if its a set-vlan-action. If yes, then add the injected-action
473 org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action actionItem = srcActionList.get(j);
474 if(actionItem.getAction() instanceof SetVlanIdActionCase) {
475 SetVlanIdActionCase setVlanIdActionCase = (SetVlanIdActionCase) actionItem.getAction();
477 PushVlanActionCaseBuilder pushVlanActionCaseBuilder = new PushVlanActionCaseBuilder();
478 PushVlanActionBuilder pushVlanActionBuilder = new PushVlanActionBuilder();
480 pushVlanActionBuilder.setCfi(new VlanCfi(1))
481 .setVlanId(setVlanIdActionCase.getSetVlanIdAction().getVlanId())
482 .setEthernetType(sourceFlow.getMatch().getEthernetMatch()
483 .getEthernetType().getType().getValue().intValue())
484 .setTag(sourceFlow.getMatch().getEthernetMatch()
485 .getEthernetType().getType().getValue().intValue());
486 pushVlanActionCaseBuilder.setPushVlanAction(pushVlanActionBuilder.build());
487 PushVlanActionCase injectedAction = pushVlanActionCaseBuilder.build();
489 org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder actionBuilder = new ActionBuilder();
490 actionBuilder.setAction(injectedAction)
491 .setKey(actionItem.getKey())
492 .setOrder(actionItem.getOrder() + offset);
494 targetActionList.add(actionBuilder.build());
499 // we need to increment the order for all the actions added after injection
500 org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder actionBuilder =
501 new org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder(actionItem);
502 actionBuilder.setOrder(actionItem.getOrder() + offset);
503 actionItem = actionBuilder.build();
506 targetActionList.add(actionItem);
509 ApplyActionsCaseBuilder applyActionsCaseBuilder = new ApplyActionsCaseBuilder();
510 ApplyActionsBuilder applyActionsBuilder = new ApplyActionsBuilder();
511 applyActionsBuilder.setAction(targetActionList);
512 applyActionsCaseBuilder.setApplyActions(applyActionsBuilder.build());
514 instructionBuilder.setInstruction(applyActionsCaseBuilder.build());
516 instructionBuilder.setInstruction(curSrcInstruction);
520 .setKey(srcInstruction.getKey())
521 .setOrder(srcInstruction.getOrder());
522 targetInstructionList.add(instructionBuilder.build());
526 return targetInstructionList;