2 * Copyright (c) 2014 Pantheon Technologies s.r.o. 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.flow;
11 import java.math.BigInteger;
12 import java.util.ArrayList;
13 import java.util.Collections;
14 import java.util.List;
15 import java.util.Optional;
16 import org.junit.Assert;
17 import org.junit.Before;
18 import org.junit.Test;
19 import org.opendaylight.openflowplugin.api.OFConstants;
20 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManager;
21 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManagerFactory;
22 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionDatapathIdConvertorData;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdActionCaseBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.vlan.id.action._case.SetVlanIdActionBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowTableRef;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlow;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlowBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef;
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.ApplyActionsCaseBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ClearActionsCaseBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.GoToTableCaseBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.MeterCaseBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteActionsCaseBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteMetadataCaseBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.clear.actions._case.ClearActionsBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.go.to.table._case.GoToTableBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.meter._case.MeterBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.actions._case.WriteActionsBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.metadata._case.WriteMetadataBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.ApplyActionsCase;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.GotoTableCase;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.MeterCase;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.WriteActionsCase;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.WriteMetadataCase;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowModCommand;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowModFlags;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowModInputBuilder;
71 import org.opendaylight.yangtools.yang.binding.Augmentation;
74 * Unit tests for flow conversion.
76 * @author michal.polkorab
78 public class FlowConvertorTest {
79 private ConvertorManager convertorManager;
83 convertorManager = ConvertorManagerFactory.createDefaultManager();
87 * Tests {@link FlowConvertor#convert(Flow, VersionDatapathIdConvertorData)} }.
91 RemoveFlowInputBuilder flowBuilder = new RemoveFlowInputBuilder();
92 flowBuilder.setBarrier(false);
93 flowBuilder.setCookie(new FlowCookie(new BigInteger("4")));
94 flowBuilder.setCookieMask(new FlowCookie(new BigInteger("5")));
95 flowBuilder.setTableId((short) 6);
96 flowBuilder.setStrict(true);
97 flowBuilder.setIdleTimeout(50);
98 flowBuilder.setHardTimeout(500);
99 flowBuilder.setPriority(40);
100 flowBuilder.setBufferId(18L);
101 flowBuilder.setOutPort(new BigInteger("65535"));
102 flowBuilder.setOutGroup(5000L);
103 flowBuilder.setFlags(null);
104 flowBuilder.setMatch(null);
105 RemoveFlowInput flow = flowBuilder.build();
107 VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(OFConstants.OFP_VERSION_1_3);
108 data.setDatapathId(new BigInteger("42"));
110 List<FlowModInputBuilder> flowMod = convert(flow, data);
112 Assert.assertEquals("Wrong version", 4, flowMod.get(0).getVersion().intValue());
113 Assert.assertEquals("Wrong cookie", 4, flowMod.get(0).getCookie().intValue());
114 Assert.assertEquals("Wrong cookie mask", 5, flowMod.get(0).getCookieMask().intValue());
115 Assert.assertEquals("Wrong table id", 6, flowMod.get(0).getTableId().getValue().intValue());
116 Assert.assertEquals("Wrong command", FlowModCommand.OFPFCDELETESTRICT, flowMod.get(0).getCommand());
117 Assert.assertEquals("Wrong idle timeout", 50, flowMod.get(0).getIdleTimeout().intValue());
118 Assert.assertEquals("Wrong hard timeout", 500, flowMod.get(0).getHardTimeout().intValue());
119 Assert.assertEquals("Wrong priority", 40, flowMod.get(0).getPriority().intValue());
120 Assert.assertEquals("Wrong buffer id", 18, flowMod.get(0).getBufferId().intValue());
121 Assert.assertEquals("Wrong out port", 65535, flowMod.get(0).getOutPort().getValue().intValue());
122 Assert.assertEquals("Wrong out group", 5000, flowMod.get(0).getOutGroup().intValue());
123 Assert.assertEquals("Wrong flags", new FlowModFlags(false, false, false, false, false),
124 flowMod.get(0).getFlags());
125 Assert.assertEquals("Wrong match",
126 "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.OxmMatchType",
127 flowMod.get(0).getMatch().getType().getName());
128 Assert.assertEquals("Wrong match entries size", 0, flowMod.get(0).getMatch().getMatchEntry().size());
132 * Tests {@link FlowConvertor#convert(Flow, VersionDatapathIdConvertorData)} }.
135 public void testOnlyModifyStrictCommand() {
136 UpdatedFlowBuilder flowBuilder = new UpdatedFlowBuilder();
137 flowBuilder.setStrict(true);
138 UpdatedFlow flow = flowBuilder.build();
140 VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(OFConstants.OFP_VERSION_1_0);
141 data.setDatapathId(new BigInteger("42"));
143 List<FlowModInputBuilder> flowMod = convert(flow, data);
145 Assert.assertEquals("Wrong version", 1, flowMod.get(0).getVersion().intValue());
146 Assert.assertEquals("Wrong command", FlowModCommand.OFPFCADD, flowMod.get(0).getCommand());
150 * Tests {@link FlowConvertor#convert(Flow, VersionDatapathIdConvertorData)} }.
153 public void testInstructionsTranslation() {
154 InstructionBuilder instructionBuilder = new InstructionBuilder();
155 GoToTableCaseBuilder goToCaseBuilder = new GoToTableCaseBuilder();
156 GoToTableBuilder goToBuilder = new GoToTableBuilder();
157 goToBuilder.setTableId((short) 1);
158 goToCaseBuilder.setGoToTable(goToBuilder.build());
159 instructionBuilder.setInstruction(goToCaseBuilder.build());
160 instructionBuilder.setOrder(0);
162 List<Instruction> instructions = new ArrayList<>();
163 instructions.add(instructionBuilder.build());
164 instructionBuilder = new InstructionBuilder();
165 WriteMetadataCaseBuilder metaCaseBuilder = new WriteMetadataCaseBuilder();
166 WriteMetadataBuilder metaBuilder = new WriteMetadataBuilder();
167 metaBuilder.setMetadata(new BigInteger("2"));
168 metaBuilder.setMetadataMask(new BigInteger("3"));
169 metaCaseBuilder.setWriteMetadata(metaBuilder.build());
170 instructionBuilder.setInstruction(metaCaseBuilder.build());
171 instructionBuilder.setOrder(1);
172 instructions.add(instructionBuilder.build());
173 instructionBuilder = new InstructionBuilder();
174 WriteActionsCaseBuilder writeCaseBuilder = new WriteActionsCaseBuilder();
175 WriteActionsBuilder writeBuilder = new WriteActionsBuilder();
176 List<Action> actions = new ArrayList<>();
177 writeBuilder.setAction(actions);
178 writeCaseBuilder.setWriteActions(writeBuilder.build());
179 instructionBuilder.setInstruction(writeCaseBuilder.build());
180 instructionBuilder.setOrder(2);
181 instructions.add(instructionBuilder.build());
182 instructionBuilder = new InstructionBuilder();
183 ApplyActionsCaseBuilder applyCaseBuilder = new ApplyActionsCaseBuilder();
184 ApplyActionsBuilder applyBuilder = new ApplyActionsBuilder();
185 actions = new ArrayList<>();
186 applyBuilder.setAction(actions);
187 applyCaseBuilder.setApplyActions(applyBuilder.build());
188 instructionBuilder.setInstruction(applyCaseBuilder.build());
189 instructionBuilder.setOrder(3);
190 instructions.add(instructionBuilder.build());
191 instructionBuilder = new InstructionBuilder();
192 ClearActionsCaseBuilder clearCaseBuilder = new ClearActionsCaseBuilder();
193 ClearActionsBuilder clearBuilder = new ClearActionsBuilder();
194 actions = new ArrayList<>();
195 clearBuilder.setAction(actions);
196 clearCaseBuilder.setClearActions(clearBuilder.build());
197 instructionBuilder.setInstruction(clearCaseBuilder.build());
198 instructionBuilder.setOrder(4);
199 instructions.add(instructionBuilder.build());
200 instructionBuilder = new InstructionBuilder();
201 MeterCaseBuilder meterCaseBuilder = new MeterCaseBuilder();
202 MeterBuilder meterBuilder = new MeterBuilder();
203 meterBuilder.setMeterId(new MeterId(5L));
204 meterCaseBuilder.setMeter(meterBuilder.build());
205 instructionBuilder.setInstruction(meterCaseBuilder.build());
206 instructionBuilder.setOrder(5);
207 instructions.add(instructionBuilder.build());
209 InstructionsBuilder instructionsBuilder = new InstructionsBuilder();
210 instructionsBuilder.setInstruction(instructions);
212 AddFlowInputBuilder flowBuilder = new AddFlowInputBuilder();
213 flowBuilder.setInstructions(instructionsBuilder.build());
214 AddFlowInput flow = flowBuilder.build();
216 VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(OFConstants.OFP_VERSION_1_0);
217 data.setDatapathId(new BigInteger("42"));
218 List<FlowModInputBuilder> flowMod = convert(flow, data);
220 Assert.assertEquals("Wrong version", 1, flowMod.get(0).getVersion().intValue());
221 Assert.assertEquals("Wrong command", FlowModCommand.OFPFCADD, flowMod.get(0).getCommand());
222 Assert.assertEquals("Wrong instructions size", 6, flowMod.get(0).getInstruction().size());
223 org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instructions
224 .grouping.Instruction instruction = flowMod.get(0).getInstruction().get(0);
225 Assert.assertEquals("Wrong type", "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common"
226 + ".instruction.rev130731.instruction.grouping.instruction.choice.GotoTableCase",
227 instruction.getInstructionChoice().implementedInterface().getName());
228 GotoTableCase gotoTableCase = (GotoTableCase) instruction.getInstructionChoice();
229 Assert.assertEquals("Wrong table id", 1, gotoTableCase.getGotoTable().getTableId().intValue());
230 instruction = flowMod.get(0).getInstruction().get(1);
231 Assert.assertEquals("Wrong type", "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common"
232 + ".instruction.rev130731.instruction.grouping.instruction.choice.WriteMetadataCase",
233 instruction.getInstructionChoice().implementedInterface().getName());
234 WriteMetadataCase writeMetadataCase = (WriteMetadataCase) instruction.getInstructionChoice();
235 Assert.assertArrayEquals("Wrong metadata", new byte[]{0, 0, 0, 0, 0, 0, 0, 2},
236 writeMetadataCase.getWriteMetadata().getMetadata());
237 Assert.assertArrayEquals("Wrong metadata mask", new byte[]{0, 0, 0, 0, 0, 0, 0, 3},
238 writeMetadataCase.getWriteMetadata().getMetadataMask());
240 instruction = flowMod.get(0).getInstruction().get(2);
241 Assert.assertEquals("Wrong type", "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common"
242 + ".instruction.rev130731.instruction.grouping.instruction.choice.WriteActionsCase",
243 instruction.getInstructionChoice().implementedInterface().getName());
244 WriteActionsCase writeActionsCase = (WriteActionsCase) instruction.getInstructionChoice();
245 Assert.assertEquals("Wrong actions size", 0, writeActionsCase.getWriteActions().getAction().size());
246 instruction = flowMod.get(0).getInstruction().get(3);
247 Assert.assertEquals("Wrong type", "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common"
248 + ".instruction.rev130731.instruction.grouping.instruction.choice.ApplyActionsCase",
249 instruction.getInstructionChoice().implementedInterface().getName());
250 ApplyActionsCase applyActionsCase = (ApplyActionsCase) instruction.getInstructionChoice();
251 Assert.assertEquals("Wrong actions size", 0, applyActionsCase.getApplyActions().getAction().size());
252 instruction = flowMod.get(0).getInstruction().get(4);
253 Assert.assertEquals("Wrong type", "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common"
254 + ".instruction.rev130731.instruction.grouping.instruction.choice.ClearActionsCase",
255 instruction.getInstructionChoice().implementedInterface().getName());
256 instruction = flowMod.get(0).getInstruction().get(5);
257 Assert.assertEquals("Wrong type", "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common"
258 + ".instruction.rev130731.instruction.grouping.instruction.choice.MeterCase",
259 instruction.getInstructionChoice().implementedInterface().getName());
260 MeterCase meterCase = (MeterCase) instruction.getInstructionChoice();
261 Assert.assertEquals("Wrong meter id", 5, meterCase.getMeter().getMeterId().intValue());
265 public void testCloneAndAugmentFlowWithSetVlanId() {
266 MockFlow mockFlow = new MockFlow();
267 Action action1 = createAction(
268 new SetVlanIdActionCaseBuilder().setSetVlanIdAction(
269 new SetVlanIdActionBuilder().setVlanId(new VlanId(10)).build())
273 mockFlow.setMatch(new MatchBuilder().setEthernetMatch(createEthernetMatch()).build());
274 mockFlow.setInstructions(toApplyInstruction(Collections.singletonList(action1)));
276 VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(OFConstants.OFP_VERSION_1_3);
277 data.setDatapathId(BigInteger.ONE);
279 List<FlowModInputBuilder> flowModInputBuilders = convert(mockFlow, data);
281 Assert.assertEquals(2, flowModInputBuilders.size());
285 private List<FlowModInputBuilder> convert(Flow flow, VersionDatapathIdConvertorData data) {
286 Optional<List<FlowModInputBuilder>> flowModOptional = convertorManager.convert(flow, data);
287 Assert.assertTrue("Flow convertor not found", flowModOptional.isPresent());
288 return flowModOptional.get();
291 private static Action createAction(
292 final org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action actionCase,
294 Action action = new ActionBuilder().setOrder(order).setAction(actionCase).build();
298 private static EthernetMatch createEthernetMatch() {
299 EthernetMatchBuilder ethernetMatchBuilder = new EthernetMatchBuilder();
300 ethernetMatchBuilder.setEthernetType(new EthernetTypeBuilder().setType(new EtherType(33024L)).build());
301 return ethernetMatchBuilder.build();
304 private static Instructions toApplyInstruction(
305 List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> actions) {
306 return new InstructionsBuilder().setInstruction(Collections.singletonList(new InstructionBuilder().setOrder(0)
307 .setInstruction(new ApplyActionsCaseBuilder()
308 .setApplyActions(new ApplyActionsBuilder().setAction(actions).build()).build())
312 private static class MockFlow implements AddFlowInput {
313 private Instructions instructions;
316 public void setInstructions(final Instructions instructions) {
317 this.instructions = instructions;
320 public void setMatch(final Match match) {
326 public FlowRef getFlowRef() {
331 public <E extends Augmentation<AddFlowInput>> E augmentation(final Class<E> augmentationType) {
336 public FlowTableRef getFlowTable() {
341 public Match getMatch() {
346 public Instructions getInstructions() {
351 public String getContainerName() {
356 public FlowCookie getCookieMask() {
361 public Long getBufferId() {
366 public BigInteger getOutPort() {
371 public Long getOutGroup() {
376 public org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowModFlags getFlags() {
381 public String getFlowName() {
386 public Boolean isInstallHw() {
391 public Boolean isBarrier() {
396 public Boolean isStrict() {
401 public Integer getPriority() {
406 public Integer getIdleTimeout() {
411 public Integer getHardTimeout() {
416 public FlowCookie getCookie() {
421 public Short getTableId() {
426 public NodeRef getNode() {
431 public Uri getTransactionUri() {
436 public Class<AddFlowInput> implementedInterface() {
437 return AddFlowInput.class;