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 java.math.BigInteger;
12 import java.util.ArrayList;
13 import java.util.List;
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.go.to.table._case.GoToTable;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.meter._case.Meter;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.actions._case.WriteActions;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.metadata._case.WriteMetadata;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatch;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.actions.grouping.Action;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.ClearActionsCaseBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.GotoTableCaseBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.MeterCaseBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.WriteActionsCaseBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.WriteMetadataCaseBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice._goto.table._case.GotoTableBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.meter._case.MeterBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.write.actions._case.WriteActionsBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.write.metadata._case.WriteMetadataBuilder;
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.rev150225.OxmMatchType;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntry;
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 com.google.common.base.Objects;
77 import com.google.common.base.Optional;
78 import com.google.common.collect.Ordering;
81 * Utility class for converting a MD-SAL Flow into the OF flow mod
83 public class FlowConvertor {
84 private static final Logger LOG = LoggerFactory.getLogger(FlowConvertor.class);
86 // Default values for when things are null
87 private static final TableId DEFAULT_TABLE_ID = new TableId(0L);
89 * Default idle timeout
91 public static final Integer DEFAULT_IDLE_TIMEOUT = 5 * 60;
93 * Default hard timeout
95 public static final Integer DEFAULT_HARD_TIMEOUT = 10 * 60;
99 public static final Integer DEFAULT_PRIORITY = Integer.parseInt("8000", 16);
100 private static final Long DEFAULT_BUFFER_ID = OFConstants.OFP_NO_BUFFER;
101 private static final Long OFPP_ANY = Long.parseLong("ffffffff", 16);
102 private static final Long DEFAULT_OUT_PORT = OFPP_ANY;
103 private static final Long OFPG_ANY = Long.parseLong("ffffffff", 16);
104 private static final Long DEFAULT_OUT_GROUP = OFPG_ANY;
108 public static final boolean DEFAULT_OFPFF_FLOW_REM = false;
110 * flow flag: check overlap
112 public static final boolean DEFAULT_OFPFF_CHECK_OVERLAP = false;
114 * flow flag: reset counts
116 public static final boolean DEFAULT_OFPFF_RESET_COUNTS = false;
118 * flow flag: don't keep track of packet counts
120 public static final boolean DEFAULT_OFPFF_NO_PKT_COUNTS = false;
122 * flow flag: don't keep track of byte counts
124 public static final boolean DEFAULT_OFPFF_NO_BYT_COUNTS = false;
126 * flow flag: emergency [OFP-1.0]
128 public static final boolean DEFAULT_OFPFF_EMERGENCY = false;
132 public static final Class<? extends MatchTypeBase> DEFAULT_MATCH_TYPE = OxmMatchType.class;
134 * default match entries - empty
136 public static final List<MatchEntry> DEFAULT_MATCH_ENTRIES = new ArrayList<MatchEntry>();
139 private FlowConvertor() {
140 //hiding implicit constructor
144 * This method converts the SAL Flow to OF Flow.
145 * It checks if there is a set-vlan-id (1.0) action made on OF1.3.
146 * If yes its handled separately
148 public static List<FlowModInputBuilder> toFlowModInputs(Flow srcFlow, short version, BigInteger datapathId) {
149 List<FlowModInputBuilder> list = new ArrayList<>();
151 if (version >= OFConstants.OFP_VERSION_1_3 && isSetVlanIdActionCasePresent(srcFlow)) {
152 list.addAll(handleSetVlanIdForOF13(srcFlow, version, datapathId));
154 list.add(toFlowModInput(srcFlow, version, datapathId));
159 public static FlowModInputBuilder toFlowModInput(Flow flow, short version, BigInteger datapathid) {
161 FlowModInputBuilder flowMod = new FlowModInputBuilder();
162 salToOFFlowCookie(flow, flowMod);
163 salToOFFlowCookieMask(flow, flowMod);
164 salToOFFlowTableId(flow, flowMod);
165 salToOFFlowCommand(flow, flowMod);
166 salToOFFlowIdleTimeout(flow, flowMod);
167 salToOFFlowHardTimeout(flow, flowMod);
168 salToOFFlowPriority(flow, flowMod);
169 salToOFFlowBufferId(flow, flowMod);
170 salToOFFlowOutPort(flow, flowMod);
171 salToOFFlowOutGroup(flow, flowMod);
173 // convert and inject flowFlags
174 FlowFlagReactor.getInstance().convert(flow.getFlags(), version, flowMod, datapathid);
176 // convert and inject match
177 MatchReactor.getInstance().convert(flow.getMatch(), version, flowMod, datapathid);
179 if (flow.getInstructions() != null) {
180 flowMod.setInstruction(toInstructions(flow, version, datapathid));
181 flowMod.setAction(getActions(version, datapathid, flow));
183 flowMod.setVersion(version);
188 private static void salToOFFlowOutGroup(Flow flow, FlowModInputBuilder flowMod) {
189 if (flow.getOutGroup() != null) {
190 flowMod.setOutGroup(flow.getOutGroup());
192 flowMod.setOutGroup(DEFAULT_OUT_GROUP);
196 private static void salToOFFlowOutPort(Flow flow, FlowModInputBuilder flowMod) {
197 if (flow.getOutPort() != null) {
198 flowMod.setOutPort(new PortNumber(flow.getOutPort().longValue()));
200 flowMod.setOutPort(new PortNumber(DEFAULT_OUT_PORT));
204 private static void salToOFFlowBufferId(Flow flow, FlowModInputBuilder flowMod) {
205 if (flow.getBufferId() != null) {
206 flowMod.setBufferId(flow.getBufferId());
208 flowMod.setBufferId(DEFAULT_BUFFER_ID);
212 private static void salToOFFlowPriority(Flow flow, FlowModInputBuilder flowMod) {
213 if (flow.getPriority() != null) {
214 flowMod.setPriority(flow.getPriority());
216 flowMod.setPriority(DEFAULT_PRIORITY);
220 private static void salToOFFlowHardTimeout(Flow flow, FlowModInputBuilder flowMod) {
221 if (flow.getHardTimeout() != null) {
222 flowMod.setHardTimeout(flow.getHardTimeout());
224 flowMod.setHardTimeout(DEFAULT_HARD_TIMEOUT);
228 private static void salToOFFlowIdleTimeout(Flow flow, FlowModInputBuilder flowMod) {
229 if (flow.getIdleTimeout() != null) {
230 flowMod.setIdleTimeout(flow.getIdleTimeout());
232 flowMod.setIdleTimeout(DEFAULT_IDLE_TIMEOUT);
236 private static void salToOFFlowCommand(Flow flow, FlowModInputBuilder flowMod) {
237 if (flow instanceof AddFlowInput) {
238 flowMod.setCommand(FlowModCommand.OFPFCADD);
239 } else if (flow instanceof RemoveFlowInput) {
240 if (Objects.firstNonNull(flow.isStrict(), Boolean.FALSE)) {
241 flowMod.setCommand(FlowModCommand.OFPFCDELETESTRICT);
243 flowMod.setCommand(FlowModCommand.OFPFCDELETE);
245 } else if (flow instanceof UpdatedFlow) {
246 if (Objects.firstNonNull(flow.isStrict(), Boolean.FALSE)) {
247 flowMod.setCommand(FlowModCommand.OFPFCMODIFYSTRICT);
249 flowMod.setCommand(FlowModCommand.OFPFCMODIFY);
254 private static void salToOFFlowTableId(Flow flow, FlowModInputBuilder flowMod) {
255 if (flow.getTableId() != null) {
256 flowMod.setTableId(new TableId(flow.getTableId().longValue()));
258 flowMod.setTableId(DEFAULT_TABLE_ID);
262 private static void salToOFFlowCookieMask(Flow flow, FlowModInputBuilder flowMod) {
263 if (flow.getCookieMask() != null) {
264 flowMod.setCookieMask(flow.getCookieMask().getValue());
266 flowMod.setCookieMask(OFConstants.DEFAULT_COOKIE_MASK);
270 private static void salToOFFlowCookie(Flow flow, FlowModInputBuilder flowMod) {
271 if (flow.getCookie() != null) {
272 flowMod.setCookie(flow.getCookie().getValue());
274 flowMod.setCookie(OFConstants.DEFAULT_COOKIE);
278 private static List<Instruction> toInstructions(
280 short version, BigInteger datapathid) {
281 List<Instruction> instructionsList = new ArrayList<>();
283 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions instructions = flow.getInstructions();
284 for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction instruction : instructions
286 InstructionBuilder instructionBuilder = new InstructionBuilder();
287 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curInstruction = instruction
289 if (curInstruction instanceof GoToTableCase) {
290 GoToTableCase goToTablecase = (GoToTableCase) curInstruction;
291 GoToTable goToTable = goToTablecase.getGoToTable();
292 GotoTableCaseBuilder gotoTableCaseBuilder = new GotoTableCaseBuilder();
293 GotoTableBuilder gotoTableBuilder = new GotoTableBuilder();
294 gotoTableBuilder.setTableId(goToTable.getTableId());
295 gotoTableCaseBuilder.setGotoTable(gotoTableBuilder.build());
296 instructionBuilder.setInstructionChoice(gotoTableCaseBuilder.build());
297 instructionsList.add(instructionBuilder.build());
298 } else if (curInstruction instanceof WriteMetadataCase) {
299 WriteMetadataCase writeMetadatacase = (WriteMetadataCase) curInstruction;
300 WriteMetadata writeMetadata = writeMetadatacase.getWriteMetadata();
302 WriteMetadataCaseBuilder writeMetadataCaseBuilder = new WriteMetadataCaseBuilder();
303 WriteMetadataBuilder writeMetadataBuilder = new WriteMetadataBuilder();
304 writeMetadataBuilder.setMetadata(ByteUtil.convertBigIntegerToNBytes(writeMetadata.getMetadata(),
305 OFConstants.SIZE_OF_LONG_IN_BYTES));
306 writeMetadataBuilder.setMetadataMask(ByteUtil.convertBigIntegerToNBytes(writeMetadata.getMetadataMask(),
307 OFConstants.SIZE_OF_LONG_IN_BYTES));
308 writeMetadataCaseBuilder.setWriteMetadata(writeMetadataBuilder.build());
309 instructionBuilder.setInstructionChoice(writeMetadataCaseBuilder.build());
310 instructionsList.add(instructionBuilder.build());
311 } else if (curInstruction instanceof WriteActionsCase) {
312 WriteActionsCase writeActionscase = (WriteActionsCase) curInstruction;
313 WriteActions writeActions = writeActionscase.getWriteActions();
314 WriteActionsCaseBuilder writeActionsCaseBuilder = new WriteActionsCaseBuilder();
315 WriteActionsBuilder writeActionsBuilder = new WriteActionsBuilder();
316 writeActionsBuilder.setAction(ActionConvertor.getActions(writeActions.getAction(),version, datapathid, flow));
317 writeActionsCaseBuilder.setWriteActions(writeActionsBuilder.build());
318 instructionBuilder.setInstructionChoice(writeActionsCaseBuilder.build());
319 instructionsList.add(instructionBuilder.build());
320 } else if (curInstruction instanceof ApplyActionsCase) {
321 ApplyActionsCase applyActionscase = (ApplyActionsCase) curInstruction;
322 ApplyActions applyActions = applyActionscase.getApplyActions();
323 org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.ApplyActionsCaseBuilder applyActionsCaseBuilder =
324 new org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.ApplyActionsCaseBuilder();
325 org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.apply.actions._case.ApplyActionsBuilder applyActionsBuilder =
326 new org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.apply.actions._case.ApplyActionsBuilder();
327 applyActionsBuilder.setAction(ActionConvertor.getActions(applyActions.getAction(), version, datapathid, flow));
328 applyActionsCaseBuilder.setApplyActions(applyActionsBuilder.build());
329 instructionBuilder.setInstructionChoice(applyActionsCaseBuilder.build());
330 instructionsList.add(instructionBuilder.build());
331 } else if (curInstruction instanceof ClearActionsCase) {
332 ClearActionsCaseBuilder clearActionsCaseBuilder = new ClearActionsCaseBuilder();
333 instructionBuilder.setInstructionChoice(clearActionsCaseBuilder.build());
334 instructionsList.add(instructionBuilder.build());
335 } else if (curInstruction instanceof MeterCase) {
336 MeterCase metercase = (MeterCase) curInstruction;
337 Meter meter = metercase.getMeter();
338 MeterCaseBuilder meterCaseBuilder = new MeterCaseBuilder();
339 MeterBuilder meterBuilder = new MeterBuilder();
340 Long meterId = meter.getMeterId().getValue();
341 meterBuilder.setMeterId(meterId);
342 meterCaseBuilder.setMeter(meterBuilder.build());
343 instructionBuilder.setInstructionChoice(meterCaseBuilder.build());
344 instructionsList.add(instructionBuilder.build());
347 return instructionsList;
350 private static List<Action> getActions(short version, BigInteger datapathid, Flow flow) {
352 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions instructions = flow.getInstructions();
353 List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction> sortedInstructions =
354 Ordering.from(OrderComparator.<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction>build())
355 .sortedCopy(instructions.getInstruction());
357 for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction instruction : sortedInstructions) {
358 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curInstruction = instruction
361 if (curInstruction instanceof ApplyActionsCase) {
362 ApplyActionsCase applyActionscase = (ApplyActionsCase) curInstruction;
363 ApplyActions applyActions = applyActionscase.getApplyActions();
364 return ActionConvertor.getActions(applyActions.getAction(), version, datapathid, flow);
370 // check if set vlanid action is present in the flow
371 private static boolean isSetVlanIdActionCasePresent(Flow flow) {
372 boolean isPresent = false;
373 // we are trying to find if there is a set-vlan-id action (OF1.0) action present in the flow.
374 // If yes,then we would need to two flows
375 if (flow.getInstructions() != null) {
376 for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction instruction :
377 flow.getInstructions().getInstruction()) {
378 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curInstruction =
379 instruction.getInstruction();
381 if (curInstruction instanceof ApplyActionsCase) {
382 ApplyActionsCase applyActionscase = (ApplyActionsCase) curInstruction;
383 ApplyActions applyActions = applyActionscase.getApplyActions();
384 for (org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action action :
385 applyActions.getAction()) {
386 if (action.getAction() instanceof SetVlanIdActionCase) {
399 * A) If user provided flow's match includes vlan match  and action has set_vlan_field
400 * Install following rules
401 * Â Â 1) match on (OFPVID_PRESENT |value) without mask + action [set_field]
403 * B) if user provided flow's match doesn't include vlan match but action has set_vlan field
404 * Â Â 1) Match on (OFPVID_NONEÂ ) without mask + action [push vlan tag + set_field]
405 * Â Â 2) Match on (OFPVID_PRESENT) with mask (OFPVID_PRESENT ) + action [ set_field]
407 private static List<FlowModInputBuilder> handleSetVlanIdForOF13(Flow srcFlow, short version, BigInteger datapathId) {
408 List<FlowModInputBuilder> list = new ArrayList<>();
410 VlanMatch srcVlanMatch = srcFlow.getMatch().getVlanMatch();
411 boolean hasVlanMatch = (srcFlow.getMatch() != null && srcVlanMatch != null);
413 //create flow with setfield and match
414 // match on vlan tag or vlanid with no mask
415 VlanMatchBuilder vlanMatchBuilder = new VlanMatchBuilder(srcVlanMatch);
416 VlanIdBuilder vlanIdBuilder = new VlanIdBuilder();
417 vlanIdBuilder.setVlanIdPresent(srcVlanMatch.getVlanId().isVlanIdPresent());
418 vlanIdBuilder.setVlanId(srcVlanMatch.getVlanId().getVlanId());
419 vlanMatchBuilder.setVlanId(vlanIdBuilder.build());
420 Match match = new MatchBuilder(srcFlow.getMatch()).setVlanMatch(vlanMatchBuilder.build()).build();
422 Optional<? extends Flow> optional = injectMatchToFlow(srcFlow, match);
423 if (optional.isPresent()) {
424 list.add(toFlowModInput(optional.get(), version, datapathId));
429 // match on no vlan tag with no mask
430 VlanMatchBuilder vlanMatchBuilder = new VlanMatchBuilder();
431 VlanIdBuilder vlanIdBuilder = new VlanIdBuilder();
432 vlanIdBuilder.setVlanIdPresent(false);
433 vlanIdBuilder.setVlanId(new VlanId(0));
434 vlanMatchBuilder.setVlanId(vlanIdBuilder.build());
435 Match match1 = new MatchBuilder(srcFlow.getMatch()).setVlanMatch(vlanMatchBuilder.build()).build();
437 Optional<? extends Flow> optional1 = injectMatchAndAction(srcFlow, match1);
438 if (optional1.isPresent()) {
439 list.add(toFlowModInput(optional1.get(), version, datapathId));
443 // match on vlan tag with mask
444 VlanMatchBuilder vlanMatchBuilder2 = new VlanMatchBuilder();
445 VlanIdBuilder vlanIdBuilder2 = new VlanIdBuilder();
446 vlanIdBuilder2.setVlanIdPresent(true);
447 vlanIdBuilder2.setVlanId(new VlanId(0));
448 vlanMatchBuilder2.setVlanId(vlanIdBuilder2.build());
449 Match match2 = new MatchBuilder(srcFlow.getMatch()).setVlanMatch(vlanMatchBuilder2.build()).build();
450 Optional<? extends Flow> optional2 = injectMatchToFlow(srcFlow, match2);
451 if (optional2.isPresent()) {
452 list.add(toFlowModInput(optional2.get(), version, datapathId));
459 private static Optional<? extends Flow> injectMatchToFlow(Flow sourceFlow, Match match) {
460 if (sourceFlow instanceof AddFlowInput) {
461 return Optional.<AddFlowInput>of(new AddFlowInputBuilder(sourceFlow).setMatch(match).build());
462 } else if (sourceFlow instanceof RemoveFlowInput) {
463 return Optional.<RemoveFlowInput>of(new RemoveFlowInputBuilder(sourceFlow).setMatch(match).build());
464 } else if (sourceFlow instanceof UpdatedFlow) {
465 return Optional.<UpdatedFlow>of(new UpdatedFlowBuilder(sourceFlow).setMatch(match).build());
467 return Optional.<Flow>absent();
471 private static Optional<? extends Flow> injectMatchAndAction(Flow sourceFlow, Match match) {
473 Instructions instructions = (new InstructionsBuilder())
474 .setInstruction(injectPushActionToInstruction(sourceFlow))
477 if (sourceFlow instanceof AddFlowInput) {
478 return Optional.<AddFlowInput>of(new AddFlowInputBuilder(sourceFlow)
479 .setMatch(match).setInstructions(instructions).build());
480 } else if (sourceFlow instanceof RemoveFlowInput) {
481 return Optional.<RemoveFlowInput>of(new RemoveFlowInputBuilder(sourceFlow)
482 .setMatch(match).setInstructions(instructions).build());
483 } else if (sourceFlow instanceof UpdatedFlow) {
484 return Optional.<UpdatedFlow>of(new UpdatedFlowBuilder(sourceFlow)
485 .setMatch(match).setInstructions(instructions).build());
487 return Optional.<Flow>absent();
491 private static List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction>
492 injectPushActionToInstruction(final Flow sourceFlow) {
494 List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction> srcInstructionList =
495 sourceFlow.getInstructions().getInstruction();
497 List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction> targetInstructionList = new ArrayList<>(srcInstructionList.size());
498 List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> targetActionList = new ArrayList<>();
500 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder instructionBuilder =
501 new org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder();
503 for (int i = 0; i < srcInstructionList.size(); i++) {
504 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction srcInstruction =
505 srcInstructionList.get(i);
506 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curSrcInstruction =
507 srcInstruction.getInstruction();
509 if (curSrcInstruction instanceof ApplyActionsCase) {
510 ApplyActionsCase applyActionscase = (ApplyActionsCase) curSrcInstruction;
511 ApplyActions applyActions = applyActionscase.getApplyActions();
512 List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> srcActionList = applyActions.getAction();
515 for (int j = 0; j < srcActionList.size(); j++) {
516 // check if its a set-vlan-action. If yes, then add the injected-action
518 org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action actionItem = srcActionList.get(j);
519 if (actionItem.getAction() instanceof SetVlanIdActionCase) {
520 SetVlanIdActionCase setVlanIdActionCase = (SetVlanIdActionCase) actionItem.getAction();
522 PushVlanActionCaseBuilder pushVlanActionCaseBuilder = new PushVlanActionCaseBuilder();
523 PushVlanActionBuilder pushVlanActionBuilder = new PushVlanActionBuilder();
525 pushVlanActionBuilder.setCfi(new VlanCfi(1))
526 .setVlanId(setVlanIdActionCase.getSetVlanIdAction().getVlanId())
527 .setEthernetType(sourceFlow.getMatch().getEthernetMatch()
528 .getEthernetType().getType().getValue().intValue())
529 .setTag(sourceFlow.getMatch().getEthernetMatch()
530 .getEthernetType().getType().getValue().intValue());
531 pushVlanActionCaseBuilder.setPushVlanAction(pushVlanActionBuilder.build());
532 PushVlanActionCase injectedAction = pushVlanActionCaseBuilder.build();
534 org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder actionBuilder = new ActionBuilder();
535 actionBuilder.setAction(injectedAction)
536 .setKey(actionItem.getKey())
537 .setOrder(actionItem.getOrder() + offset);
539 targetActionList.add(actionBuilder.build());
544 // we need to increment the order for all the actions added after injection
545 org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder actionBuilder =
546 new org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder(actionItem);
547 actionBuilder.setOrder(actionItem.getOrder() + offset);
548 actionItem = actionBuilder.build();
551 targetActionList.add(actionItem);
554 ApplyActionsCaseBuilder applyActionsCaseBuilder = new ApplyActionsCaseBuilder();
555 ApplyActionsBuilder applyActionsBuilder = new ApplyActionsBuilder();
556 applyActionsBuilder.setAction(targetActionList);
557 applyActionsCaseBuilder.setApplyActions(applyActionsBuilder.build());
559 instructionBuilder.setInstruction(applyActionsCaseBuilder.build());
561 instructionBuilder.setInstruction(curSrcInstruction);
565 .setKey(srcInstruction.getKey())
566 .setOrder(srcInstruction.getOrder());
567 targetInstructionList.add(instructionBuilder.build());
571 return targetInstructionList;