Fix potential performance problems reported by findbugs
[openflowplugin.git] / openflowplugin / src / main / java / org / opendaylight / openflowplugin / openflow / md / core / sal / convertor / FlowConvertor.java
1 /**
2  * Copyright (c) 2013 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.List;
14
15 import org.opendaylight.openflowplugin.openflow.md.OFConstants;
16 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flowflag.FlowFlagReactor;
17 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.MatchReactor;
18 import org.opendaylight.openflowplugin.openflow.md.util.ByteUtil;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlow;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ClearActionsCase;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.GoToTableCase;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.MeterCase;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteActionsCase;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteMetadataCase;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActions;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.clear.actions._case.ClearActions;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.go.to.table._case.GoToTable;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.meter._case.Meter;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.actions._case.WriteActions;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.metadata._case.WriteMetadata;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ActionsInstruction;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ActionsInstructionBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MetadataInstruction;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MetadataInstructionBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MeterIdInstruction;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MeterIdInstructionBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.TableIdInstruction;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.TableIdInstructionBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.actions.grouping.Action;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instructions.grouping.Instruction;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instructions.grouping.InstructionBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowModCommand;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MatchTypeBase;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortNumber;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.TableId;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.OxmMatchType;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.oxm.fields.grouping.MatchEntries;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowModInputBuilder;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
55
56 import com.google.common.base.Objects;
57
58 /**
59  * Utility class for converting a MD-SAL Flow into the OF flow mod
60  */
61 public class FlowConvertor {
62     private static final Logger logger = LoggerFactory.getLogger(FlowConvertor.class);
63
64     // Default values for when things are null
65     private static final BigInteger DEFAULT_COOKIE = BigInteger.ZERO;
66     private static final BigInteger DEFAULT_COOKIE_MASK = BigInteger.ZERO;
67     private static final TableId DEFAULT_TABLE_ID = new TableId(0L);
68     private static final Integer DEFAULT_IDLE_TIMEOUT = 5 * 60;
69     private static final Integer DEFAULT_HARD_TIMEOUT = 10 * 60;
70     private static final Integer DEFAULT_PRIORITY = Integer.parseInt("8000", 16);
71     private static final Long DEFAULT_BUFFER_ID = Long.parseLong("ffffffff", 16);
72     private static final Long OFPP_ANY = Long.parseLong("ffffffff", 16);
73     private static final Long DEFAULT_OUT_PORT = OFPP_ANY;
74     private static final Long OFPG_ANY = Long.parseLong("ffffffff", 16);
75     private static final Long DEFAULT_OUT_GROUP = OFPG_ANY;
76     /** flow flag: remove */
77     public static final boolean DEFAULT_OFPFF_FLOW_REM = true;
78     /** flow flag: check overlap */
79     public static final boolean DEFAULT_OFPFF_CHECK_OVERLAP = false;
80     /** flow flag: reset counts */
81     public static final boolean DEFAULT_OFPFF_RESET_COUNTS = false;
82     /** flow flag: don't keep track of packet counts */
83     public static final boolean DEFAULT_OFPFF_NO_PKT_COUNTS = false;
84     /** flow flag: don't keep track of byte counts */
85     public static final boolean DEFAULT_OFPFF_NO_BYT_COUNTS = false;
86     /** flow flag: emergency [OFP-1.0] */
87     public static final boolean DEFAULT_OFPFF_EMERGENCY = false;
88     /** OxmMatch type */
89     public static final Class<? extends MatchTypeBase> DEFAULT_MATCH_TYPE = OxmMatchType.class;
90     /** default match entries - empty */
91     public static final List<MatchEntries> DEFAULT_MATCH_ENTRIES = new ArrayList<MatchEntries>();
92
93     public static FlowModInputBuilder toFlowModInput(Flow flow, short version,BigInteger datapathid) {
94         FlowModInputBuilder flowMod = new FlowModInputBuilder();
95         if (flow.getCookie() != null) {
96             flowMod.setCookie(flow.getCookie().getValue());
97         } else {
98             flowMod.setCookie(DEFAULT_COOKIE);
99         }
100
101         if (flow.getCookieMask() != null) {
102             flowMod.setCookieMask(flow.getCookieMask().getValue());
103         } else {
104             flowMod.setCookieMask(DEFAULT_COOKIE_MASK);
105         }
106
107         if (flow.getTableId() != null) {
108             flowMod.setTableId(new TableId(flow.getTableId().longValue()));
109         } else {
110             flowMod.setTableId(DEFAULT_TABLE_ID);
111         }
112
113         if (flow instanceof AddFlowInput) {
114             flowMod.setCommand(FlowModCommand.OFPFCADD);
115         } else if (flow instanceof RemoveFlowInput) {
116             if (Objects.firstNonNull(flow.isStrict(), Boolean.FALSE)) {
117                 flowMod.setCommand(FlowModCommand.OFPFCDELETESTRICT);
118             } else {
119                 flowMod.setCommand(FlowModCommand.OFPFCDELETE);
120             }
121         } else if (flow instanceof UpdatedFlow) {
122             if (Objects.firstNonNull(flow.isStrict(), Boolean.FALSE)) {
123                 flowMod.setCommand(FlowModCommand.OFPFCMODIFYSTRICT);
124             } else {
125                 flowMod.setCommand(FlowModCommand.OFPFCMODIFY);
126             }
127         }
128         if (flow.getIdleTimeout() != null) {
129             flowMod.setIdleTimeout(flow.getIdleTimeout());
130         } else {
131             flowMod.setIdleTimeout(DEFAULT_IDLE_TIMEOUT);
132         }
133         if (flow.getHardTimeout() != null) {
134             flowMod.setHardTimeout(flow.getHardTimeout());
135         } else {
136             flowMod.setHardTimeout(DEFAULT_HARD_TIMEOUT);
137         }
138         if (flow.getPriority() != null) {
139             flowMod.setPriority(flow.getPriority());
140         } else {
141             flowMod.setPriority(DEFAULT_PRIORITY);
142         }
143         if (flow.getBufferId() != null) {
144             flowMod.setBufferId(flow.getBufferId());
145         } else {
146             flowMod.setBufferId(DEFAULT_BUFFER_ID);
147         }
148
149         if (flow.getOutPort() != null) {
150             flowMod.setOutPort(new PortNumber(flow.getOutPort().longValue()));
151         } else {
152             flowMod.setOutPort(new PortNumber(DEFAULT_OUT_PORT));
153         }
154         if (flow.getOutGroup() != null) {
155             flowMod.setOutGroup(flow.getOutGroup());
156         } else {
157             flowMod.setOutGroup(DEFAULT_OUT_GROUP);
158         }
159
160         
161         // convert and inject flowFlags
162         FlowFlagReactor.getInstance().convert(flow.getFlags(), version, flowMod,datapathid);
163
164         // convert and inject match
165         MatchReactor.getInstance().convert(flow.getMatch(), version, flowMod,datapathid);
166
167         if (flow.getInstructions() != null) {
168             flowMod.setInstruction(toInstructions(flow.getInstructions(), version,datapathid));
169             flowMod.setAction(getActions(flow.getInstructions(), version,datapathid));
170         }
171         flowMod.setVersion(version);
172         
173         return flowMod;
174     }
175
176     private static List<Instruction> toInstructions(
177             org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions instructions,
178             short version,BigInteger datapathid) {
179         List<Instruction> instructionsList = new ArrayList<>();
180
181         for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction instruction : instructions
182                 .getInstruction()) {
183             InstructionBuilder instructionBuilder = new InstructionBuilder();
184             org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curInstruction = instruction
185                     .getInstruction();
186             if (curInstruction instanceof GoToTableCase) {
187                 GoToTableCase goToTablecase = (GoToTableCase) curInstruction;
188                 GoToTable goToTable = goToTablecase.getGoToTable();
189                 instructionBuilder
190                         .setType(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.GotoTable.class);
191                 TableIdInstructionBuilder tableBuilder = new TableIdInstructionBuilder();
192                 tableBuilder.setTableId(goToTable.getTableId());
193                 instructionBuilder.addAugmentation(TableIdInstruction.class, tableBuilder.build());
194                 instructionsList.add(instructionBuilder.build());
195             }
196
197             else if (curInstruction instanceof WriteMetadataCase) {
198                 WriteMetadataCase writeMetadatacase = (WriteMetadataCase) curInstruction;
199                 WriteMetadata writeMetadata = writeMetadatacase.getWriteMetadata();
200                 instructionBuilder
201                         .setType(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.WriteMetadata.class);
202                 MetadataInstructionBuilder metadataBuilder = new MetadataInstructionBuilder();
203                 metadataBuilder.setMetadata(ByteUtil.convertBigIntegerToNBytes(writeMetadata.getMetadata(),
204                                                                                OFConstants.SIZE_OF_LONG_IN_BYTES));
205                 metadataBuilder
206                         .setMetadataMask(ByteUtil.convertBigIntegerToNBytes(writeMetadata.getMetadataMask(),
207                                                                             OFConstants.SIZE_OF_LONG_IN_BYTES));
208                 instructionBuilder.addAugmentation(MetadataInstruction.class, metadataBuilder.build());
209                 instructionsList.add(instructionBuilder.build());
210             }
211
212             else if (curInstruction instanceof WriteActionsCase) {
213                 WriteActionsCase writeActionscase = (WriteActionsCase) curInstruction;
214                 WriteActions writeActions = writeActionscase.getWriteActions();
215                 instructionBuilder
216                         .setType(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.WriteActions.class);
217                 ActionsInstructionBuilder actionsInstructionBuilder = new ActionsInstructionBuilder();
218                 actionsInstructionBuilder.setAction(ActionConvertor.getActions(writeActions.getAction(),
219                         version,datapathid));
220                 instructionBuilder.addAugmentation(ActionsInstruction.class, actionsInstructionBuilder.build());
221                 instructionsList.add(instructionBuilder.build());
222             }
223
224             else if (curInstruction instanceof ApplyActionsCase) {
225                 ApplyActionsCase applyActionscase = (ApplyActionsCase) curInstruction;
226                 ApplyActions applyActions = applyActionscase.getApplyActions();
227                 instructionBuilder
228                         .setType(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.ApplyActions.class);
229                 ActionsInstructionBuilder actionsInstructionBuilder = new ActionsInstructionBuilder();
230                 actionsInstructionBuilder.setAction(ActionConvertor.getActions(applyActions.getAction(),
231                         version,datapathid));
232                 instructionBuilder.addAugmentation(ActionsInstruction.class, actionsInstructionBuilder.build());
233                 instructionsList.add(instructionBuilder.build());
234             }
235
236             else if (curInstruction instanceof ClearActionsCase) {
237                 ClearActionsCase clearActionscase = (ClearActionsCase) curInstruction;
238                 ClearActions clearActions = clearActionscase.getClearActions();
239                 instructionBuilder
240                         .setType(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.ClearActions.class);
241                 instructionsList.add(instructionBuilder.build());
242             }
243
244             else if (curInstruction instanceof MeterCase) {
245                 MeterCase metercase = (MeterCase) curInstruction;
246                 Meter meter = metercase.getMeter();
247                 instructionBuilder
248                         .setType(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.Meter.class);
249                 MeterIdInstructionBuilder meterBuilder = new MeterIdInstructionBuilder();
250                 Long meterId = meter.getMeterId().getValue();
251                 meterBuilder.setMeterId(meterId);
252                 instructionBuilder.addAugmentation(MeterIdInstruction.class, meterBuilder.build());
253                 instructionsList.add(instructionBuilder.build());
254             }
255         }
256         return instructionsList;
257     }
258     
259     private static List<Action> getActions(
260             org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions instructions,
261             short version,BigInteger datapathid) {
262
263         for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction instruction : instructions
264                 .getInstruction()) {
265             org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curInstruction = instruction
266                     .getInstruction();
267
268             if (curInstruction instanceof ApplyActionsCase) {
269                 ApplyActionsCase applyActionscase = (ApplyActionsCase) curInstruction;
270                 ApplyActions applyActions = applyActionscase.getApplyActions();
271                 return ActionConvertor.getActions(applyActions.getAction(), version,datapathid);
272             }
273
274         }
275         return null;
276     }
277 }