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
8 package org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flow;
10 import static org.junit.Assert.assertArrayEquals;
11 import static org.junit.Assert.assertEquals;
12 import static org.junit.Assert.assertTrue;
14 import java.util.List;
16 import java.util.Objects;
17 import java.util.Optional;
18 import org.junit.Before;
19 import org.junit.Test;
20 import org.opendaylight.openflowplugin.api.OFConstants;
21 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManager;
22 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManagerFactory;
23 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionDatapathIdConvertorData;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdActionCaseBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.vlan.id.action._case.SetVlanIdActionBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowTableRef;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlow;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlowBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ClearActionsCaseBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.GoToTableCaseBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.MeterCaseBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteActionsCaseBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteMetadataCaseBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.clear.actions._case.ClearActionsBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.go.to.table._case.GoToTableBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.meter._case.MeterBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.actions._case.WriteActionsBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.metadata._case.WriteMetadataBuilder;
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.AbstractAugmentable;
72 import org.opendaylight.yangtools.yang.binding.util.BindingMap;
73 import org.opendaylight.yangtools.yang.common.Uint16;
74 import org.opendaylight.yangtools.yang.common.Uint32;
75 import org.opendaylight.yangtools.yang.common.Uint64;
76 import org.opendaylight.yangtools.yang.common.Uint8;
79 * Unit tests for flow conversion.
81 * @author michal.polkorab
83 public class FlowConvertorTest {
84 private ConvertorManager convertorManager;
88 convertorManager = ConvertorManagerFactory.createDefaultManager();
92 * Tests {@link FlowConvertor#convert(Flow, VersionDatapathIdConvertorData)} }.
96 RemoveFlowInput flow = new RemoveFlowInputBuilder()
98 .setCookie(new FlowCookie(Uint64.valueOf(4)))
99 .setCookieMask(new FlowCookie(Uint64.valueOf(5)))
100 .setTableId(Uint8.valueOf(6))
102 .setIdleTimeout(Uint16.valueOf(50))
103 .setHardTimeout(Uint16.valueOf(500))
104 .setPriority(Uint16.valueOf(40))
105 .setBufferId(Uint32.valueOf(18))
106 .setOutPort(Uint64.valueOf(65535))
107 .setOutGroup(Uint32.valueOf(5000))
112 VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(OFConstants.OFP_VERSION_1_3);
113 data.setDatapathId(Uint64.valueOf(42));
115 List<FlowModInputBuilder> flowMod = convert(flow, data);
117 assertEquals("Wrong version", 4, flowMod.get(0).getVersion().intValue());
118 assertEquals("Wrong cookie", 4, flowMod.get(0).getCookie().intValue());
119 assertEquals("Wrong cookie mask", 5, flowMod.get(0).getCookieMask().intValue());
120 assertEquals("Wrong table id", 6, flowMod.get(0).getTableId().getValue().intValue());
121 assertEquals("Wrong command", FlowModCommand.OFPFCDELETESTRICT, flowMod.get(0).getCommand());
122 assertEquals("Wrong idle timeout", 50, flowMod.get(0).getIdleTimeout().intValue());
123 assertEquals("Wrong hard timeout", 500, flowMod.get(0).getHardTimeout().intValue());
124 assertEquals("Wrong priority", 40, flowMod.get(0).getPriority().intValue());
125 assertEquals("Wrong buffer id", 18, flowMod.get(0).getBufferId().intValue());
126 assertEquals("Wrong out port", 65535, flowMod.get(0).getOutPort().getValue().intValue());
127 assertEquals("Wrong out group", 5000, flowMod.get(0).getOutGroup().intValue());
128 assertEquals("Wrong flags", new FlowModFlags(false, false, false, false, false), flowMod.get(0).getFlags());
129 assertEquals("Wrong match",
130 org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.OxmMatchType.VALUE,
131 flowMod.get(0).getMatch().getType());
132 assertEquals("Wrong match entries size", 0, flowMod.get(0).getMatch().nonnullMatchEntry().size());
136 * Tests {@link FlowConvertor#convert(Flow, VersionDatapathIdConvertorData)} }.
139 public void testOnlyModifyStrictCommand() {
140 UpdatedFlowBuilder flowBuilder = new UpdatedFlowBuilder();
141 flowBuilder.setStrict(true);
142 UpdatedFlow flow = flowBuilder.build();
144 VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(OFConstants.OFP_VERSION_1_0);
145 data.setDatapathId(Uint64.valueOf(42));
147 List<FlowModInputBuilder> flowMod = convert(flow, data);
149 assertEquals("Wrong version", 1, flowMod.get(0).getVersion().intValue());
150 assertEquals("Wrong command", FlowModCommand.OFPFCADD, flowMod.get(0).getCommand());
154 * Tests {@link FlowConvertor#convert(Flow, VersionDatapathIdConvertorData)} }.
157 public void testInstructionsTranslation() {
158 AddFlowInput flow = new AddFlowInputBuilder()
159 .setInstructions(new InstructionsBuilder()
160 .setInstruction(BindingMap.ordered(
161 new InstructionBuilder().setOrder(0).setInstruction(new GoToTableCaseBuilder()
162 .setGoToTable(new GoToTableBuilder().setTableId(Uint8.ONE).build())
165 new InstructionBuilder().setOrder(1).setInstruction(new WriteMetadataCaseBuilder()
166 .setWriteMetadata(new WriteMetadataBuilder()
167 .setMetadata(Uint64.valueOf(2))
168 .setMetadataMask(Uint64.valueOf(3))
172 new InstructionBuilder().setOrder(2).setInstruction(new WriteActionsCaseBuilder()
173 .setWriteActions(new WriteActionsBuilder().setAction(Map.of()).build())
176 new InstructionBuilder().setOrder(3).setInstruction(new ApplyActionsCaseBuilder()
177 .setApplyActions(new ApplyActionsBuilder().setAction(Map.of()).build())
180 new InstructionBuilder().setOrder(4).setInstruction(new ClearActionsCaseBuilder()
181 .setClearActions(new ClearActionsBuilder().setAction(Map.of()).build())
184 new InstructionBuilder().setOrder(5).setInstruction(new MeterCaseBuilder()
185 .setMeter(new MeterBuilder().setMeterId(new MeterId(Uint32.valueOf(5))).build())
191 VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(OFConstants.OFP_VERSION_1_0);
192 data.setDatapathId(Uint64.valueOf(42));
193 List<FlowModInputBuilder> flowMod = convert(flow, data);
195 assertEquals("Wrong version", 1, flowMod.get(0).getVersion().intValue());
196 assertEquals("Wrong command", FlowModCommand.OFPFCADD, flowMod.get(0).getCommand());
197 assertEquals("Wrong instructions size", 6, flowMod.get(0).getInstruction().size());
198 org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instructions
199 .grouping.Instruction instruction = flowMod.get(0).getInstruction().get(0);
200 assertEquals("Wrong type", "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common"
201 + ".instruction.rev130731.instruction.grouping.instruction.choice.GotoTableCase",
202 instruction.getInstructionChoice().implementedInterface().getName());
203 GotoTableCase gotoTableCase = (GotoTableCase) instruction.getInstructionChoice();
204 assertEquals("Wrong table id", 1, gotoTableCase.getGotoTable().getTableId().intValue());
205 instruction = flowMod.get(0).getInstruction().get(1);
206 assertEquals("Wrong type", "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common"
207 + ".instruction.rev130731.instruction.grouping.instruction.choice.WriteMetadataCase",
208 instruction.getInstructionChoice().implementedInterface().getName());
209 WriteMetadataCase writeMetadataCase = (WriteMetadataCase) instruction.getInstructionChoice();
210 assertArrayEquals("Wrong metadata", new byte[]{0, 0, 0, 0, 0, 0, 0, 2},
211 writeMetadataCase.getWriteMetadata().getMetadata());
212 assertArrayEquals("Wrong metadata mask", new byte[]{0, 0, 0, 0, 0, 0, 0, 3},
213 writeMetadataCase.getWriteMetadata().getMetadataMask());
215 instruction = flowMod.get(0).getInstruction().get(2);
216 assertEquals("Wrong type", "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common"
217 + ".instruction.rev130731.instruction.grouping.instruction.choice.WriteActionsCase",
218 instruction.getInstructionChoice().implementedInterface().getName());
219 WriteActionsCase writeActionsCase = (WriteActionsCase) instruction.getInstructionChoice();
220 assertEquals("Wrong actions size", 0, writeActionsCase.getWriteActions().nonnullAction().size());
221 instruction = flowMod.get(0).getInstruction().get(3);
222 assertEquals("Wrong type", "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common"
223 + ".instruction.rev130731.instruction.grouping.instruction.choice.ApplyActionsCase",
224 instruction.getInstructionChoice().implementedInterface().getName());
225 ApplyActionsCase applyActionsCase = (ApplyActionsCase) instruction.getInstructionChoice();
226 assertEquals("Wrong actions size", 0, applyActionsCase.getApplyActions().nonnullAction().size());
227 instruction = flowMod.get(0).getInstruction().get(4);
228 assertEquals("Wrong type", "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common"
229 + ".instruction.rev130731.instruction.grouping.instruction.choice.ClearActionsCase",
230 instruction.getInstructionChoice().implementedInterface().getName());
231 instruction = flowMod.get(0).getInstruction().get(5);
232 assertEquals("Wrong type", "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common"
233 + ".instruction.rev130731.instruction.grouping.instruction.choice.MeterCase",
234 instruction.getInstructionChoice().implementedInterface().getName());
235 MeterCase meterCase = (MeterCase) instruction.getInstructionChoice();
236 assertEquals("Wrong meter id", 5, meterCase.getMeter().getMeterId().intValue());
240 public void testCloneAndAugmentFlowWithSetVlanId() {
241 MockFlow mockFlow = new MockFlow();
242 Action action1 = createAction(
243 new SetVlanIdActionCaseBuilder().setSetVlanIdAction(
244 new SetVlanIdActionBuilder().setVlanId(new VlanId(Uint16.TEN)).build())
248 mockFlow.setMatch(new MatchBuilder().setEthernetMatch(createEthernetMatch()).build());
249 mockFlow.setInstructions(new InstructionsBuilder()
250 .setInstruction(BindingMap.of(new InstructionBuilder()
252 .setInstruction(new ApplyActionsCaseBuilder()
253 .setApplyActions(new ApplyActionsBuilder().setAction(BindingMap.of(action1)).build())
258 VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(OFConstants.OFP_VERSION_1_3);
259 data.setDatapathId(Uint64.ONE);
261 List<FlowModInputBuilder> flowModInputBuilders = convert(mockFlow, data);
263 assertEquals(2, flowModInputBuilders.size());
266 private List<FlowModInputBuilder> convert(final Flow flow, final VersionDatapathIdConvertorData data) {
267 Optional<List<FlowModInputBuilder>> flowModOptional = convertorManager.convert(flow, data);
268 assertTrue("Flow convertor not found", flowModOptional.isPresent());
269 return flowModOptional.get();
272 private static Action createAction(
273 final org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action actionCase,
275 Action action = new ActionBuilder().setOrder(order).setAction(actionCase).build();
279 private static EthernetMatch createEthernetMatch() {
280 return new EthernetMatchBuilder()
281 .setEthernetType(new EthernetTypeBuilder().setType(new EtherType(Uint32.valueOf(33024))).build())
285 private static class MockFlow extends AbstractAugmentable<AddFlowInput> implements AddFlowInput {
286 private Instructions instructions;
289 public void setInstructions(final Instructions instructions) {
290 this.instructions = instructions;
293 public void setMatch(final Match match) {
298 public FlowRef getFlowRef() {
303 public FlowTableRef getFlowTable() {
308 public Match getMatch() {
313 public Instructions getInstructions() {
318 public String getContainerName() {
323 public FlowCookie getCookieMask() {
328 public Uint32 getBufferId() {
333 public Uint64 getOutPort() {
338 public Uint32 getOutGroup() {
343 public org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowModFlags getFlags() {
348 public String getFlowName() {
353 public Boolean getInstallHw() {
358 public Boolean getBarrier() {
363 public Boolean getStrict() {
368 public Uint16 getPriority() {
373 public Uint16 getIdleTimeout() {
378 public Uint16 getHardTimeout() {
383 public FlowCookie getCookie() {
388 public Uint8 getTableId() {
393 public NodeRef getNode() {
398 public Uri getTransactionUri() {
403 public Match nonnullMatch() {
404 return Objects.requireNonNullElse(getMatch(), MatchBuilder.empty());
408 public Instructions nonnullInstructions() {
409 return Objects.requireNonNullElse(getInstructions(), InstructionsBuilder.empty());