Bug 5540 - ActionConvertor, ActionResponseConvertor
[openflowplugin.git] / openflowplugin / src / main / java / org / opendaylight / openflowplugin / openflow / md / core / sal / convertor / FlowConvertor.java
1 /**
2  * Copyright (c) 2013, 2015 Ericsson. and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.openflowplugin.openflow.md.core.sal.convertor;
10
11 import com.google.common.base.MoreObjects;
12 import com.google.common.base.Optional;
13 import com.google.common.base.Preconditions;
14 import com.google.common.collect.Ordering;
15 import java.math.BigInteger;
16 import java.util.ArrayList;
17 import java.util.Collections;
18 import java.util.List;
19 import org.opendaylight.openflowplugin.api.OFConstants;
20 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.action.data.ActionConvertorData;
21 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.OrderComparator;
22 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flowflag.FlowFlagReactor;
23 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.MatchReactor;
24 import org.opendaylight.openflowplugin.openflow.md.util.ByteUtil;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.VlanCfi;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCase;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCaseBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdActionCase;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.push.vlan.action._case.PushVlanActionBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlow;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlowBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ClearActionsCase;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.GoToTableCase;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.MeterCase;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteActionsCase;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteMetadataCase;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActions;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.go.to.table._case.GoToTable;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.meter._case.Meter;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.actions._case.WriteActions;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.metadata._case.WriteMetadata;
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.instruction.grouping.instruction.choice.ClearActionsCaseBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.GotoTableCaseBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.MeterCaseBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.WriteActionsCaseBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.WriteMetadataCaseBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice._goto.table._case.GotoTableBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.meter._case.MeterBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.write.actions._case.WriteActionsBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.write.metadata._case.WriteMetadataBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instructions.grouping.Instruction;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instructions.grouping.InstructionBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowModCommand;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MatchTypeBase;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortNumber;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.TableId;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.OxmMatchType;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntry;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowModInputBuilder;
78 import org.slf4j.Logger;
79 import org.slf4j.LoggerFactory;
80
81 /**
82  * Utility class for converting a MD-SAL Flow into the OF flow mod
83  */
84 public class FlowConvertor {
85     private static final Logger LOG = LoggerFactory.getLogger(FlowConvertor.class);
86
87     // Default values for when things are null
88     private static final TableId DEFAULT_TABLE_ID = new TableId(0L);
89     /**
90      * Default idle timeout
91      */
92     public static final Integer DEFAULT_IDLE_TIMEOUT = 0;
93     /**
94      * Default hard timeout
95      */
96     public static final Integer DEFAULT_HARD_TIMEOUT = 0;
97     /**
98      * Default priority
99      */
100     public static final Integer DEFAULT_PRIORITY = Integer.parseInt("8000", 16);
101     private static final Long DEFAULT_BUFFER_ID = OFConstants.OFP_NO_BUFFER;
102     private static final Long OFPP_ANY = Long.parseLong("ffffffff", 16);
103     private static final Long DEFAULT_OUT_PORT = OFPP_ANY;
104     private static final Long OFPG_ANY = Long.parseLong("ffffffff", 16);
105     private static final Long DEFAULT_OUT_GROUP = OFPG_ANY;
106     /**
107      * flow flag: remove
108      */
109     public static final boolean DEFAULT_OFPFF_FLOW_REM = false;
110     /**
111      * flow flag: check overlap
112      */
113     public static final boolean DEFAULT_OFPFF_CHECK_OVERLAP = false;
114     /**
115      * flow flag: reset counts
116      */
117     public static final boolean DEFAULT_OFPFF_RESET_COUNTS = false;
118     /**
119      * flow flag: don't keep track of packet counts
120      */
121     public static final boolean DEFAULT_OFPFF_NO_PKT_COUNTS = false;
122     /**
123      * flow flag: don't keep track of byte counts
124      */
125     public static final boolean DEFAULT_OFPFF_NO_BYT_COUNTS = false;
126     /**
127      * flow flag: emergency [OFP-1.0]
128      */
129     public static final boolean DEFAULT_OFPFF_EMERGENCY = false;
130     /**
131      * OxmMatch type
132      */
133     public static final Class<? extends MatchTypeBase> DEFAULT_MATCH_TYPE = OxmMatchType.class;
134     /**
135      * default match entries - empty
136      */
137     public static final List<MatchEntry> DEFAULT_MATCH_ENTRIES = new ArrayList<MatchEntry>();
138     private static final Integer PUSH_VLAN = 0x8100;
139
140     private static final Ordering<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction> INSTRUCTION_ORDERING =
141             Ordering.from(OrderComparator.<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction>build());
142
143     private static final VlanMatch VLAN_MATCH_FALSE;
144     private static final VlanMatch VLAN_MATCH_TRUE;
145
146     static {
147         final VlanId zeroVlan = new VlanId(0);
148         VlanMatchBuilder vlanMatchBuilder = new VlanMatchBuilder();
149         VlanIdBuilder vlanIdBuilder = new VlanIdBuilder();
150         vlanIdBuilder.setVlanIdPresent(false);
151         vlanIdBuilder.setVlanId(zeroVlan);
152         vlanMatchBuilder.setVlanId(vlanIdBuilder.build());
153
154         VLAN_MATCH_FALSE = vlanMatchBuilder.build();
155
156         VlanMatchBuilder vlanMatchBuilder2 = new VlanMatchBuilder();
157         VlanIdBuilder vlanIdBuilder2 = new VlanIdBuilder();
158         vlanIdBuilder2.setVlanIdPresent(true);
159         vlanIdBuilder2.setVlanId(zeroVlan);
160         vlanMatchBuilder2.setVlanId(vlanIdBuilder2.build());
161
162         VLAN_MATCH_TRUE = vlanMatchBuilder2.build();
163     }
164
165     private FlowConvertor() {
166         //hiding implicit constructor
167     }
168
169     /**
170      * This method converts the SAL Flow to OF Flow.
171      * It checks if there is a set-vlan-id (1.0) action made on OF1.3.
172      * If yes its handled separately
173      *
174      * @param srcFlow source flow
175      * @param version openflow version
176      * @param datapathId datapath id
177      * @return list of flow mod build
178      */
179     public static List<FlowModInputBuilder> toFlowModInputs(Flow srcFlow, short version, BigInteger datapathId) {
180         if (version >= OFConstants.OFP_VERSION_1_3 && isSetVlanIdActionCasePresent(srcFlow)) {
181             return handleSetVlanIdForOF13(srcFlow, version, datapathId);
182         } else {
183             return Collections.singletonList(toFlowModInput(srcFlow, version, datapathId));
184         }
185     }
186
187     private static FlowModInputBuilder toFlowModInput(Flow flow, short version, BigInteger datapathid) {
188
189         FlowModInputBuilder flowMod = new FlowModInputBuilder();
190         salToOFFlowCookie(flow, flowMod);
191         salToOFFlowCookieMask(flow, flowMod);
192         salToOFFlowTableId(flow, flowMod);
193         salToOFFlowCommand(flow, flowMod);
194         salToOFFlowIdleTimeout(flow, flowMod);
195         salToOFFlowHardTimeout(flow, flowMod);
196         salToOFFlowPriority(flow, flowMod);
197         salToOFFlowBufferId(flow, flowMod);
198         salToOFFlowOutPort(flow, flowMod);
199         salToOFFlowOutGroup(flow, flowMod);
200
201         // convert and inject flowFlags
202         FlowFlagReactor.getInstance().convert(flow.getFlags(), version, flowMod);
203
204         // convert and inject match
205         MatchReactor.getInstance().convert(flow.getMatch(), version, flowMod);
206
207         if (flow.getInstructions() != null) {
208             flowMod.setInstruction(toInstructions(flow, version, datapathid));
209             flowMod.setAction(getActions(version, datapathid, flow));
210         }
211         flowMod.setVersion(version);
212
213         return flowMod;
214     }
215
216     private static void salToOFFlowOutGroup(Flow flow, FlowModInputBuilder flowMod) {
217         if (flow.getOutGroup() != null) {
218             flowMod.setOutGroup(flow.getOutGroup());
219         } else {
220             flowMod.setOutGroup(DEFAULT_OUT_GROUP);
221         }
222     }
223
224     private static void salToOFFlowOutPort(Flow flow, FlowModInputBuilder flowMod) {
225         if (flow.getOutPort() != null) {
226             flowMod.setOutPort(new PortNumber(flow.getOutPort().longValue()));
227         } else {
228             flowMod.setOutPort(new PortNumber(DEFAULT_OUT_PORT));
229         }
230     }
231
232     private static void salToOFFlowBufferId(Flow flow, FlowModInputBuilder flowMod) {
233         if (flow.getBufferId() != null) {
234             flowMod.setBufferId(flow.getBufferId());
235         } else {
236             flowMod.setBufferId(DEFAULT_BUFFER_ID);
237         }
238     }
239
240     private static void salToOFFlowPriority(Flow flow, FlowModInputBuilder flowMod) {
241         if (flow.getPriority() != null) {
242             flowMod.setPriority(flow.getPriority());
243         } else {
244             flowMod.setPriority(DEFAULT_PRIORITY);
245         }
246     }
247
248     private static void salToOFFlowHardTimeout(Flow flow, FlowModInputBuilder flowMod) {
249         if (flow.getHardTimeout() != null) {
250             flowMod.setHardTimeout(flow.getHardTimeout());
251         } else {
252             flowMod.setHardTimeout(DEFAULT_HARD_TIMEOUT);
253         }
254     }
255
256     private static void salToOFFlowIdleTimeout(Flow flow, FlowModInputBuilder flowMod) {
257         if (flow.getIdleTimeout() != null) {
258             flowMod.setIdleTimeout(flow.getIdleTimeout());
259         } else {
260             flowMod.setIdleTimeout(DEFAULT_IDLE_TIMEOUT);
261         }
262     }
263
264     private static void salToOFFlowCommand(Flow flow, FlowModInputBuilder flowMod) {
265         if (flow instanceof AddFlowInput || flow instanceof UpdatedFlow) {
266             flowMod.setCommand(FlowModCommand.OFPFCADD);
267         } else if (flow instanceof RemoveFlowInput) {
268             if (MoreObjects.firstNonNull(flow.isStrict(), Boolean.FALSE)) {
269                 flowMod.setCommand(FlowModCommand.OFPFCDELETESTRICT);
270             } else {
271                 flowMod.setCommand(FlowModCommand.OFPFCDELETE);
272             }
273         }
274     }
275
276     private static void salToOFFlowTableId(Flow flow, FlowModInputBuilder flowMod) {
277         if (flow.getTableId() != null) {
278             flowMod.setTableId(new TableId(flow.getTableId().longValue()));
279         } else {
280             flowMod.setTableId(DEFAULT_TABLE_ID);
281         }
282     }
283
284     private static void salToOFFlowCookieMask(Flow flow, FlowModInputBuilder flowMod) {
285         if (flow.getCookieMask() != null) {
286             flowMod.setCookieMask(flow.getCookieMask().getValue());
287         } else {
288             flowMod.setCookieMask(OFConstants.DEFAULT_COOKIE_MASK);
289         }
290     }
291
292     private static void salToOFFlowCookie(Flow flow, FlowModInputBuilder flowMod) {
293         if (flow.getCookie() != null) {
294             flowMod.setCookie(flow.getCookie().getValue());
295         } else {
296             flowMod.setCookie(OFConstants.DEFAULT_COOKIE);
297         }
298     }
299
300     private static List<Instruction> toInstructions(
301             Flow flow,
302             short version, BigInteger datapathid) {
303         List<Instruction> instructionsList = new ArrayList<>();
304
305         org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions instructions = flow.getInstructions();
306         for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction instruction : instructions
307                 .getInstruction()) {
308             InstructionBuilder instructionBuilder = new InstructionBuilder();
309             org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curInstruction = instruction
310                     .getInstruction();
311             ActionConvertorData data = new ActionConvertorData(version);
312             data.setDatapathId(datapathid);
313
314             if (flow.getMatch() != null && flow.getMatch().getIpMatch() != null) {
315                 data.setIpProtocol(flow.getMatch().getIpMatch().getIpProtocol());
316             }
317
318             if (curInstruction instanceof GoToTableCase) {
319                 GoToTableCase goToTablecase = (GoToTableCase) curInstruction;
320                 GoToTable goToTable = goToTablecase.getGoToTable();
321                 GotoTableCaseBuilder gotoTableCaseBuilder = new GotoTableCaseBuilder();
322                 GotoTableBuilder gotoTableBuilder = new GotoTableBuilder();
323                 gotoTableBuilder.setTableId(goToTable.getTableId());
324                 gotoTableCaseBuilder.setGotoTable(gotoTableBuilder.build());
325                 instructionBuilder.setInstructionChoice(gotoTableCaseBuilder.build());
326                 instructionsList.add(instructionBuilder.build());
327             } else if (curInstruction instanceof WriteMetadataCase) {
328                 WriteMetadataCase writeMetadatacase = (WriteMetadataCase) curInstruction;
329                 WriteMetadata writeMetadata = writeMetadatacase.getWriteMetadata();
330
331                 WriteMetadataCaseBuilder writeMetadataCaseBuilder = new WriteMetadataCaseBuilder();
332                 WriteMetadataBuilder writeMetadataBuilder = new WriteMetadataBuilder();
333                 writeMetadataBuilder.setMetadata(ByteUtil.convertBigIntegerToNBytes(writeMetadata.getMetadata(),
334                                                                              OFConstants.SIZE_OF_LONG_IN_BYTES));
335                 writeMetadataBuilder.setMetadataMask(ByteUtil.convertBigIntegerToNBytes(writeMetadata.getMetadataMask(),
336                                                                                      OFConstants.SIZE_OF_LONG_IN_BYTES));
337                 writeMetadataCaseBuilder.setWriteMetadata(writeMetadataBuilder.build());
338                 instructionBuilder.setInstructionChoice(writeMetadataCaseBuilder.build());
339                 instructionsList.add(instructionBuilder.build());
340             } else if (curInstruction instanceof WriteActionsCase) {
341                 WriteActionsCase writeActionscase = (WriteActionsCase) curInstruction;
342                 WriteActions writeActions = writeActionscase.getWriteActions();
343                 WriteActionsCaseBuilder writeActionsCaseBuilder = new WriteActionsCaseBuilder();
344                 WriteActionsBuilder writeActionsBuilder = new WriteActionsBuilder();
345
346                 final java.util.Optional<List<Action>> actions = ConvertorManager.getInstance().convert(
347                         writeActions.getAction(), data);
348
349                 writeActionsBuilder.setAction(actions.orElse(Collections.emptyList()));
350                 writeActionsCaseBuilder.setWriteActions(writeActionsBuilder.build());
351                 instructionBuilder.setInstructionChoice(writeActionsCaseBuilder.build());
352                 instructionsList.add(instructionBuilder.build());
353             } else if (curInstruction instanceof ApplyActionsCase) {
354                 ApplyActionsCase applyActionscase = (ApplyActionsCase) curInstruction;
355                 ApplyActions applyActions = applyActionscase.getApplyActions();
356                 org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.ApplyActionsCaseBuilder applyActionsCaseBuilder =
357                         new org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.ApplyActionsCaseBuilder();
358                 org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.apply.actions._case.ApplyActionsBuilder applyActionsBuilder =
359                         new org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.apply.actions._case.ApplyActionsBuilder();
360                 final java.util.Optional<List<Action>> actionList = ConvertorManager.getInstance().convert(
361                         applyActions.getAction(), data);
362
363                 applyActionsBuilder.setAction(actionList.orElse(Collections.emptyList()));
364                 applyActionsCaseBuilder.setApplyActions(applyActionsBuilder.build());
365                 instructionBuilder.setInstructionChoice(applyActionsCaseBuilder.build());
366                 instructionsList.add(instructionBuilder.build());
367             } else if (curInstruction instanceof ClearActionsCase) {
368                 ClearActionsCaseBuilder clearActionsCaseBuilder = new ClearActionsCaseBuilder();
369                 instructionBuilder.setInstructionChoice(clearActionsCaseBuilder.build());
370                 instructionsList.add(instructionBuilder.build());
371             } else if (curInstruction instanceof MeterCase) {
372                 MeterCase metercase = (MeterCase) curInstruction;
373                 Meter meter = metercase.getMeter();
374                 MeterCaseBuilder meterCaseBuilder = new MeterCaseBuilder();
375                 MeterBuilder meterBuilder = new MeterBuilder();
376                 Long meterId = meter.getMeterId().getValue();
377                 meterBuilder.setMeterId(meterId);
378                 meterCaseBuilder.setMeter(meterBuilder.build());
379                 instructionBuilder.setInstructionChoice(meterCaseBuilder.build());
380                 instructionsList.add(instructionBuilder.build());
381             }
382         }
383         return instructionsList;
384     }
385
386     private static List<Action> getActions(short version, BigInteger datapathid, Flow flow) {
387
388         org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions instructions = flow.getInstructions();
389         List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction> sortedInstructions =
390                 INSTRUCTION_ORDERING.sortedCopy(instructions.getInstruction());
391
392         for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction instruction : sortedInstructions) {
393             org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curInstruction = instruction
394                     .getInstruction();
395
396             if (curInstruction instanceof ApplyActionsCase) {
397                 ApplyActionsCase applyActionscase = (ApplyActionsCase) curInstruction;
398                 ApplyActions applyActions = applyActionscase.getApplyActions();
399                 final ActionConvertorData data = new ActionConvertorData(version);
400                 data.setDatapathId(datapathid);
401
402                 if (flow.getMatch() != null && flow.getMatch().getIpMatch() != null) {
403                     data.setIpProtocol(flow.getMatch().getIpMatch().getIpProtocol());
404                 }
405
406                 java.util.Optional<List<Action>> result = ConvertorManager.getInstance().convert(applyActions.getAction(), data);
407                 return result.orElse(Collections.emptyList());
408             }
409         }
410         return null;
411     }
412
413     // check if set vlanid action is present in the flow
414     private static boolean isSetVlanIdActionCasePresent(Flow flow) {
415         // we are trying to find if there is a set-vlan-id action (OF1.0) action present in the flow.
416         // If yes,then we would need to two flows
417         if (flow.getInstructions() != null) {
418             for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction instruction :
419                     flow.getInstructions().getInstruction()) {
420                 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curInstruction =
421                         instruction.getInstruction();
422
423                 if (curInstruction instanceof ApplyActionsCase) {
424                     ApplyActionsCase applyActionscase = (ApplyActionsCase) curInstruction;
425                     ApplyActions applyActions = applyActionscase.getApplyActions();
426                     for (org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action action :
427                             applyActions.getAction()) {
428                         if (action.getAction() instanceof SetVlanIdActionCase) {
429                             return true;
430                         }
431                     }
432                 }
433             }
434         }
435         return false;
436     }
437
438
439     /**
440      * A) If user provided flow's match includes vlan match Â and action has set_vlan_field
441      * Install following rules
442      * Â  Â 1) match on (OFPVID_PRESENT |value) without mask + action [set_field]
443      * <p/>
444      * B) if user provided flow's match doesn't include vlan match but action has set_vlan field
445      * Â  Â  1) Match on (OFPVID_NONE ) without mask + action [push vlan tag + set_field]
446      * Â  Â  2) Match on (OFPVID_PRESENT) with mask (OFPVID_PRESENT ) + action [ set_field]
447      */
448     private static List<FlowModInputBuilder> handleSetVlanIdForOF13(Flow srcFlow, short version, BigInteger datapathId) {
449         List<FlowModInputBuilder> list = new ArrayList<>(2);
450
451         final Match srcMatch = Preconditions.checkNotNull(srcFlow.getMatch());
452         final VlanMatch srcVlanMatch = srcMatch.getVlanMatch();
453         if (srcVlanMatch != null) {
454             //create flow with setfield and match
455             // match on vlan tag or vlanid with no mask
456             VlanMatchBuilder vlanMatchBuilder = new VlanMatchBuilder(srcVlanMatch);
457             VlanIdBuilder vlanIdBuilder = new VlanIdBuilder();
458             vlanIdBuilder.setVlanIdPresent(srcVlanMatch.getVlanId().isVlanIdPresent());
459             vlanIdBuilder.setVlanId(srcVlanMatch.getVlanId().getVlanId());
460             vlanMatchBuilder.setVlanId(vlanIdBuilder.build());
461             Match match = new MatchBuilder(srcMatch).setVlanMatch(vlanMatchBuilder.build()).build();
462
463             Optional<? extends Flow> optional = injectMatchToFlow(srcFlow, match);
464             if (optional.isPresent()) {
465                 list.add(toFlowModInput(optional.get(), version, datapathId));
466             }
467         } else {
468             // create 2 flows
469             //flow 1
470             // match on no vlan tag with no mask
471             Match match1 = new MatchBuilder(srcMatch).setVlanMatch(VLAN_MATCH_FALSE).build();
472
473             Optional<? extends Flow> optional1 = injectMatchAndAction(srcFlow, match1);
474             if (optional1.isPresent()) {
475                 list.add(toFlowModInput(optional1.get(), version, datapathId));
476             }
477
478             //flow2
479             // match on vlan tag with mask
480             Match match2 = new MatchBuilder(srcMatch).setVlanMatch(VLAN_MATCH_TRUE).build();
481             Optional<? extends Flow> optional2 = injectMatchToFlow(srcFlow, match2);
482             if (optional2.isPresent()) {
483                 list.add(toFlowModInput(optional2.get(), version, datapathId));
484             }
485         }
486         return list;
487     }
488
489
490     private static Optional<? extends Flow> injectMatchToFlow(Flow sourceFlow, Match match) {
491         if (sourceFlow instanceof AddFlowInput) {
492             return Optional.<AddFlowInput>of(new AddFlowInputBuilder(sourceFlow).setMatch(match).build());
493         } else if (sourceFlow instanceof RemoveFlowInput) {
494             return Optional.<RemoveFlowInput>of(new RemoveFlowInputBuilder(sourceFlow).setMatch(match).build());
495         } else if (sourceFlow instanceof UpdatedFlow) {
496             return Optional.<UpdatedFlow>of(new UpdatedFlowBuilder(sourceFlow).setMatch(match).build());
497         } else {
498             return Optional.<Flow>absent();
499         }
500     }
501
502     private static Optional<? extends Flow> injectMatchAndAction(Flow sourceFlow, Match match) {
503
504         Instructions instructions = (new InstructionsBuilder())
505                 .setInstruction(injectPushActionToInstruction(sourceFlow))
506                 .build();
507
508         if (sourceFlow instanceof AddFlowInput) {
509             return Optional.<AddFlowInput>of(new AddFlowInputBuilder(sourceFlow)
510                     .setMatch(match).setInstructions(instructions).build());
511         } else if (sourceFlow instanceof RemoveFlowInput) {
512             return Optional.<RemoveFlowInput>of(new RemoveFlowInputBuilder(sourceFlow)
513                     .setMatch(match).setInstructions(instructions).build());
514         } else if (sourceFlow instanceof UpdatedFlow) {
515             return Optional.<UpdatedFlow>of(new UpdatedFlowBuilder(sourceFlow)
516                     .setMatch(match).setInstructions(instructions).build());
517         } else {
518             return Optional.<Flow>absent();
519         }
520     }
521
522     private static List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction>
523     injectPushActionToInstruction(final Flow sourceFlow) {
524
525         List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction> srcInstructionList =
526                 sourceFlow.getInstructions().getInstruction();
527
528         List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction> targetInstructionList = new ArrayList<>(srcInstructionList.size());
529         List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> targetActionList = new ArrayList<>();
530
531         org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder instructionBuilder =
532                 new org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder();
533
534         for (int i = 0; i < srcInstructionList.size(); i++) {
535             org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction srcInstruction =
536                     srcInstructionList.get(i);
537             org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curSrcInstruction =
538                     srcInstruction.getInstruction();
539
540             if (curSrcInstruction instanceof ApplyActionsCase) {
541                 ApplyActionsCase applyActionscase = (ApplyActionsCase) curSrcInstruction;
542                 ApplyActions applyActions = applyActionscase.getApplyActions();
543                 List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> srcActionList = applyActions.getAction();
544
545                 int offset = 0;
546                 for (int j = 0; j < srcActionList.size(); j++) {
547                     // check if its a set-vlan-action. If yes, then add the injected-action
548
549                     org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action actionItem = srcActionList.get(j);
550                     if (actionItem.getAction() instanceof SetVlanIdActionCase) {
551                         SetVlanIdActionCase setVlanIdActionCase = (SetVlanIdActionCase) actionItem.getAction();
552
553                         PushVlanActionCaseBuilder pushVlanActionCaseBuilder = new PushVlanActionCaseBuilder();
554                         PushVlanActionBuilder pushVlanActionBuilder = new PushVlanActionBuilder();
555
556                         pushVlanActionBuilder.setCfi(new VlanCfi(1))
557                                 .setVlanId(setVlanIdActionCase.getSetVlanIdAction().getVlanId())
558                                 .setEthernetType(PUSH_VLAN)
559                                 .setTag(PUSH_VLAN);
560                         pushVlanActionCaseBuilder.setPushVlanAction(pushVlanActionBuilder.build());
561                         PushVlanActionCase injectedAction = pushVlanActionCaseBuilder.build();
562
563                         org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder actionBuilder = new ActionBuilder();
564                         actionBuilder.setAction(injectedAction)
565                                 .setKey(actionItem.getKey())
566                                 .setOrder(actionItem.getOrder() + offset);
567
568                         targetActionList.add(actionBuilder.build());
569                         offset++;
570                     }
571
572                     if (offset > 0) {
573                         // we need to increment the order for all the actions added after injection
574                         org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder actionBuilder =
575                                 new org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder(actionItem);
576                         actionBuilder.setOrder(actionItem.getOrder() + offset);
577                         actionItem = actionBuilder.build();
578                     }
579
580                     targetActionList.add(actionItem);
581                 }
582
583                 ApplyActionsCaseBuilder applyActionsCaseBuilder = new ApplyActionsCaseBuilder();
584                 ApplyActionsBuilder applyActionsBuilder = new ApplyActionsBuilder();
585                 applyActionsBuilder.setAction(targetActionList);
586                 applyActionsCaseBuilder.setApplyActions(applyActionsBuilder.build());
587
588                 instructionBuilder.setInstruction(applyActionsCaseBuilder.build());
589             } else {
590                 instructionBuilder.setInstruction(curSrcInstruction);
591             }
592
593             instructionBuilder
594                     .setKey(srcInstruction.getKey())
595                     .setOrder(srcInstruction.getOrder());
596             targetInstructionList.add(instructionBuilder.build());
597
598         }
599
600         return targetInstructionList;
601     }
602
603 }