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