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.util.ArrayList;
12 import java.util.Collections;
13 import java.util.List;
14 import java.util.Optional;
15 import org.junit.Assert;
16 import org.junit.Before;
17 import org.junit.Test;
18 import org.opendaylight.openflowplugin.api.OFConstants;
19 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManager;
20 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManagerFactory;
21 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionDatapathIdConvertorData;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdActionCaseBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.vlan.id.action._case.SetVlanIdActionBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowTableRef;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlow;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlowBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ClearActionsCaseBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.GoToTableCaseBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.MeterCaseBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteActionsCaseBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteMetadataCaseBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.clear.actions._case.ClearActionsBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.go.to.table._case.GoToTableBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.meter._case.MeterBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.actions._case.WriteActionsBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.metadata._case.WriteMetadataBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.ApplyActionsCase;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.GotoTableCase;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.MeterCase;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.WriteActionsCase;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.WriteMetadataCase;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowModCommand;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowModFlags;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowModInputBuilder;
70 import org.opendaylight.yangtools.yang.binding.AbstractAugmentable;
71 import org.opendaylight.yangtools.yang.common.Uint16;
72 import org.opendaylight.yangtools.yang.common.Uint32;
73 import org.opendaylight.yangtools.yang.common.Uint64;
74 import org.opendaylight.yangtools.yang.common.Uint8;
77 * Unit tests for flow conversion.
79 * @author michal.polkorab
81 public class FlowConvertorTest {
82 private ConvertorManager convertorManager;
86 convertorManager = ConvertorManagerFactory.createDefaultManager();
90 * Tests {@link FlowConvertor#convert(Flow, VersionDatapathIdConvertorData)} }.
94 RemoveFlowInputBuilder flowBuilder = new RemoveFlowInputBuilder();
95 flowBuilder.setBarrier(false);
96 flowBuilder.setCookie(new FlowCookie(Uint64.valueOf(4)));
97 flowBuilder.setCookieMask(new FlowCookie(Uint64.valueOf(5)));
98 flowBuilder.setTableId(Uint8.valueOf(6));
99 flowBuilder.setStrict(true);
100 flowBuilder.setIdleTimeout(Uint16.valueOf(50));
101 flowBuilder.setHardTimeout(Uint16.valueOf(500));
102 flowBuilder.setPriority(Uint16.valueOf(40));
103 flowBuilder.setBufferId(Uint32.valueOf(18));
104 flowBuilder.setOutPort(Uint64.valueOf(65535));
105 flowBuilder.setOutGroup(Uint32.valueOf(5000));
106 flowBuilder.setFlags(null);
107 flowBuilder.setMatch(null);
108 RemoveFlowInput flow = flowBuilder.build();
110 VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(OFConstants.OFP_VERSION_1_3);
111 data.setDatapathId(Uint64.valueOf(42));
113 List<FlowModInputBuilder> flowMod = convert(flow, data);
115 Assert.assertEquals("Wrong version", 4, flowMod.get(0).getVersion().intValue());
116 Assert.assertEquals("Wrong cookie", 4, flowMod.get(0).getCookie().intValue());
117 Assert.assertEquals("Wrong cookie mask", 5, flowMod.get(0).getCookieMask().intValue());
118 Assert.assertEquals("Wrong table id", 6, flowMod.get(0).getTableId().getValue().intValue());
119 Assert.assertEquals("Wrong command", FlowModCommand.OFPFCDELETESTRICT, flowMod.get(0).getCommand());
120 Assert.assertEquals("Wrong idle timeout", 50, flowMod.get(0).getIdleTimeout().intValue());
121 Assert.assertEquals("Wrong hard timeout", 500, flowMod.get(0).getHardTimeout().intValue());
122 Assert.assertEquals("Wrong priority", 40, flowMod.get(0).getPriority().intValue());
123 Assert.assertEquals("Wrong buffer id", 18, flowMod.get(0).getBufferId().intValue());
124 Assert.assertEquals("Wrong out port", 65535, flowMod.get(0).getOutPort().getValue().intValue());
125 Assert.assertEquals("Wrong out group", 5000, flowMod.get(0).getOutGroup().intValue());
126 Assert.assertEquals("Wrong flags", new FlowModFlags(false, false, false, false, false),
127 flowMod.get(0).getFlags());
128 Assert.assertEquals("Wrong match",
129 "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.OxmMatchType",
130 flowMod.get(0).getMatch().getType().getName());
131 Assert.assertEquals("Wrong match entries size", 0, flowMod.get(0).getMatch().nonnullMatchEntry().size());
135 * Tests {@link FlowConvertor#convert(Flow, VersionDatapathIdConvertorData)} }.
138 public void testOnlyModifyStrictCommand() {
139 UpdatedFlowBuilder flowBuilder = new UpdatedFlowBuilder();
140 flowBuilder.setStrict(true);
141 UpdatedFlow flow = flowBuilder.build();
143 VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(OFConstants.OFP_VERSION_1_0);
144 data.setDatapathId(Uint64.valueOf(42));
146 List<FlowModInputBuilder> flowMod = convert(flow, data);
148 Assert.assertEquals("Wrong version", 1, flowMod.get(0).getVersion().intValue());
149 Assert.assertEquals("Wrong command", FlowModCommand.OFPFCADD, flowMod.get(0).getCommand());
153 * Tests {@link FlowConvertor#convert(Flow, VersionDatapathIdConvertorData)} }.
156 public void testInstructionsTranslation() {
157 InstructionBuilder instructionBuilder = new InstructionBuilder();
158 GoToTableCaseBuilder goToCaseBuilder = new GoToTableCaseBuilder();
159 GoToTableBuilder goToBuilder = new GoToTableBuilder();
160 goToBuilder.setTableId(Uint8.ONE);
161 goToCaseBuilder.setGoToTable(goToBuilder.build());
162 instructionBuilder.setInstruction(goToCaseBuilder.build());
163 instructionBuilder.setOrder(0);
165 List<Instruction> instructions = new ArrayList<>();
166 instructions.add(instructionBuilder.build());
167 instructionBuilder = new InstructionBuilder();
168 WriteMetadataCaseBuilder metaCaseBuilder = new WriteMetadataCaseBuilder();
169 WriteMetadataBuilder metaBuilder = new WriteMetadataBuilder();
170 metaBuilder.setMetadata(Uint64.valueOf(2));
171 metaBuilder.setMetadataMask(Uint64.valueOf(3));
172 metaCaseBuilder.setWriteMetadata(metaBuilder.build());
173 instructionBuilder.setInstruction(metaCaseBuilder.build());
174 instructionBuilder.setOrder(1);
175 instructions.add(instructionBuilder.build());
176 instructionBuilder = new InstructionBuilder();
177 WriteActionsCaseBuilder writeCaseBuilder = new WriteActionsCaseBuilder();
178 WriteActionsBuilder writeBuilder = new WriteActionsBuilder();
179 List<Action> actions = new ArrayList<>();
180 writeBuilder.setAction(actions);
181 writeCaseBuilder.setWriteActions(writeBuilder.build());
182 instructionBuilder.setInstruction(writeCaseBuilder.build());
183 instructionBuilder.setOrder(2);
184 instructions.add(instructionBuilder.build());
185 instructionBuilder = new InstructionBuilder();
186 ApplyActionsCaseBuilder applyCaseBuilder = new ApplyActionsCaseBuilder();
187 ApplyActionsBuilder applyBuilder = new ApplyActionsBuilder();
188 actions = new ArrayList<>();
189 applyBuilder.setAction(actions);
190 applyCaseBuilder.setApplyActions(applyBuilder.build());
191 instructionBuilder.setInstruction(applyCaseBuilder.build());
192 instructionBuilder.setOrder(3);
193 instructions.add(instructionBuilder.build());
194 instructionBuilder = new InstructionBuilder();
195 ClearActionsCaseBuilder clearCaseBuilder = new ClearActionsCaseBuilder();
196 ClearActionsBuilder clearBuilder = new ClearActionsBuilder();
197 actions = new ArrayList<>();
198 clearBuilder.setAction(actions);
199 clearCaseBuilder.setClearActions(clearBuilder.build());
200 instructionBuilder.setInstruction(clearCaseBuilder.build());
201 instructionBuilder.setOrder(4);
202 instructions.add(instructionBuilder.build());
203 instructionBuilder = new InstructionBuilder();
204 MeterCaseBuilder meterCaseBuilder = new MeterCaseBuilder();
205 MeterBuilder meterBuilder = new MeterBuilder();
206 meterBuilder.setMeterId(new MeterId(Uint32.valueOf(5)));
207 meterCaseBuilder.setMeter(meterBuilder.build());
208 instructionBuilder.setInstruction(meterCaseBuilder.build());
209 instructionBuilder.setOrder(5);
210 instructions.add(instructionBuilder.build());
212 InstructionsBuilder instructionsBuilder = new InstructionsBuilder();
213 instructionsBuilder.setInstruction(instructions);
215 AddFlowInputBuilder flowBuilder = new AddFlowInputBuilder();
216 flowBuilder.setInstructions(instructionsBuilder.build());
217 AddFlowInput flow = flowBuilder.build();
219 VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(OFConstants.OFP_VERSION_1_0);
220 data.setDatapathId(Uint64.valueOf(42));
221 List<FlowModInputBuilder> flowMod = convert(flow, data);
223 Assert.assertEquals("Wrong version", 1, flowMod.get(0).getVersion().intValue());
224 Assert.assertEquals("Wrong command", FlowModCommand.OFPFCADD, flowMod.get(0).getCommand());
225 Assert.assertEquals("Wrong instructions size", 6, flowMod.get(0).getInstruction().size());
226 org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instructions
227 .grouping.Instruction instruction = flowMod.get(0).getInstruction().get(0);
228 Assert.assertEquals("Wrong type", "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common"
229 + ".instruction.rev130731.instruction.grouping.instruction.choice.GotoTableCase",
230 instruction.getInstructionChoice().implementedInterface().getName());
231 GotoTableCase gotoTableCase = (GotoTableCase) instruction.getInstructionChoice();
232 Assert.assertEquals("Wrong table id", 1, gotoTableCase.getGotoTable().getTableId().intValue());
233 instruction = flowMod.get(0).getInstruction().get(1);
234 Assert.assertEquals("Wrong type", "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common"
235 + ".instruction.rev130731.instruction.grouping.instruction.choice.WriteMetadataCase",
236 instruction.getInstructionChoice().implementedInterface().getName());
237 WriteMetadataCase writeMetadataCase = (WriteMetadataCase) instruction.getInstructionChoice();
238 Assert.assertArrayEquals("Wrong metadata", new byte[]{0, 0, 0, 0, 0, 0, 0, 2},
239 writeMetadataCase.getWriteMetadata().getMetadata());
240 Assert.assertArrayEquals("Wrong metadata mask", new byte[]{0, 0, 0, 0, 0, 0, 0, 3},
241 writeMetadataCase.getWriteMetadata().getMetadataMask());
243 instruction = flowMod.get(0).getInstruction().get(2);
244 Assert.assertEquals("Wrong type", "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common"
245 + ".instruction.rev130731.instruction.grouping.instruction.choice.WriteActionsCase",
246 instruction.getInstructionChoice().implementedInterface().getName());
247 WriteActionsCase writeActionsCase = (WriteActionsCase) instruction.getInstructionChoice();
248 Assert.assertEquals("Wrong actions size", 0, writeActionsCase.getWriteActions().nonnullAction().size());
249 instruction = flowMod.get(0).getInstruction().get(3);
250 Assert.assertEquals("Wrong type", "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common"
251 + ".instruction.rev130731.instruction.grouping.instruction.choice.ApplyActionsCase",
252 instruction.getInstructionChoice().implementedInterface().getName());
253 ApplyActionsCase applyActionsCase = (ApplyActionsCase) instruction.getInstructionChoice();
254 Assert.assertEquals("Wrong actions size", 0, applyActionsCase.getApplyActions().nonnullAction().size());
255 instruction = flowMod.get(0).getInstruction().get(4);
256 Assert.assertEquals("Wrong type", "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common"
257 + ".instruction.rev130731.instruction.grouping.instruction.choice.ClearActionsCase",
258 instruction.getInstructionChoice().implementedInterface().getName());
259 instruction = flowMod.get(0).getInstruction().get(5);
260 Assert.assertEquals("Wrong type", "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common"
261 + ".instruction.rev130731.instruction.grouping.instruction.choice.MeterCase",
262 instruction.getInstructionChoice().implementedInterface().getName());
263 MeterCase meterCase = (MeterCase) instruction.getInstructionChoice();
264 Assert.assertEquals("Wrong meter id", 5, meterCase.getMeter().getMeterId().intValue());
268 public void testCloneAndAugmentFlowWithSetVlanId() {
269 MockFlow mockFlow = new MockFlow();
270 Action action1 = createAction(
271 new SetVlanIdActionCaseBuilder().setSetVlanIdAction(
272 new SetVlanIdActionBuilder().setVlanId(new VlanId(Uint16.TEN)).build())
276 mockFlow.setMatch(new MatchBuilder().setEthernetMatch(createEthernetMatch()).build());
277 mockFlow.setInstructions(toApplyInstruction(Collections.singletonList(action1)));
279 VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(OFConstants.OFP_VERSION_1_3);
280 data.setDatapathId(Uint64.ONE);
282 List<FlowModInputBuilder> flowModInputBuilders = convert(mockFlow, data);
284 Assert.assertEquals(2, flowModInputBuilders.size());
288 private List<FlowModInputBuilder> convert(final Flow flow, final VersionDatapathIdConvertorData data) {
289 Optional<List<FlowModInputBuilder>> flowModOptional = convertorManager.convert(flow, data);
290 Assert.assertTrue("Flow convertor not found", flowModOptional.isPresent());
291 return flowModOptional.get();
294 private static Action createAction(
295 final org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action actionCase,
297 Action action = new ActionBuilder().setOrder(order).setAction(actionCase).build();
301 private static EthernetMatch createEthernetMatch() {
302 return new EthernetMatchBuilder()
303 .setEthernetType(new EthernetTypeBuilder().setType(new EtherType(Uint32.valueOf(33024))).build())
307 private static Instructions toApplyInstruction(
308 final List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list
310 return new InstructionsBuilder().setInstruction(Collections.singletonList(new InstructionBuilder().setOrder(0)
311 .setInstruction(new ApplyActionsCaseBuilder()
312 .setApplyActions(new ApplyActionsBuilder().setAction(actions).build()).build())
316 private static class MockFlow extends AbstractAugmentable<AddFlowInput> implements AddFlowInput {
317 private Instructions instructions;
320 public void setInstructions(final Instructions instructions) {
321 this.instructions = instructions;
324 public void setMatch(final Match match) {
329 public FlowRef getFlowRef() {
334 public FlowTableRef getFlowTable() {
339 public Match getMatch() {
344 public Instructions getInstructions() {
349 public String getContainerName() {
354 public FlowCookie getCookieMask() {
359 public Uint32 getBufferId() {
364 public Uint64 getOutPort() {
369 public Uint32 getOutGroup() {
374 public org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowModFlags getFlags() {
379 public String getFlowName() {
384 public Boolean isInstallHw() {
389 public Boolean isBarrier() {
394 public Boolean isStrict() {
399 public Uint16 getPriority() {
404 public Uint16 getIdleTimeout() {
409 public Uint16 getHardTimeout() {
414 public FlowCookie getCookie() {
419 public Uint8 getTableId() {
424 public NodeRef getNode() {
429 public Uri getTransactionUri() {