69dfe10e8e5ac1958ae5653369c957a3b4a00ddf
[openflowplugin.git] / openflowplugin / src / test / java / org / opendaylight / openflowplugin / openflow / md / core / sal / convertor / flow / FlowConvertorTest.java
1 /*
2  * Copyright (c) 2014 Pantheon Technologies s.r.o. 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 package org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flow;
9
10 import static org.junit.Assert.assertArrayEquals;
11 import static org.junit.Assert.assertEquals;
12 import static org.junit.Assert.assertTrue;
13
14 import java.util.List;
15 import java.util.Map;
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;
77
78 /**
79  * Unit tests for flow conversion.
80  *
81  * @author michal.polkorab
82  */
83 public class FlowConvertorTest {
84     private ConvertorManager convertorManager;
85
86     @Before
87     public void setUp() {
88         convertorManager = ConvertorManagerFactory.createDefaultManager();
89     }
90
91     /**
92      * Tests {@link FlowConvertor#convert(Flow, VersionDatapathIdConvertorData)} }.
93      */
94     @Test
95     public void test() {
96         RemoveFlowInput flow = new RemoveFlowInputBuilder()
97             .setBarrier(false)
98             .setCookie(new FlowCookie(Uint64.valueOf(4)))
99             .setCookieMask(new FlowCookie(Uint64.valueOf(5)))
100             .setTableId(Uint8.valueOf(6))
101             .setStrict(true)
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))
108             .setFlags(null)
109             .setMatch(null)
110             .build();
111
112         VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(OFConstants.OFP_VERSION_1_3);
113         data.setDatapathId(Uint64.valueOf(42));
114
115         List<FlowModInputBuilder> flowMod = convert(flow, data);
116
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());
133     }
134
135     /**
136      * Tests {@link FlowConvertor#convert(Flow, VersionDatapathIdConvertorData)} }.
137      */
138     @Test
139     public void testOnlyModifyStrictCommand() {
140         UpdatedFlowBuilder flowBuilder = new UpdatedFlowBuilder();
141         flowBuilder.setStrict(true);
142         UpdatedFlow flow = flowBuilder.build();
143
144         VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(OFConstants.OFP_VERSION_1_0);
145         data.setDatapathId(Uint64.valueOf(42));
146
147         List<FlowModInputBuilder> flowMod = convert(flow, data);
148
149         assertEquals("Wrong version", 1, flowMod.get(0).getVersion().intValue());
150         assertEquals("Wrong command", FlowModCommand.OFPFCADD, flowMod.get(0).getCommand());
151     }
152
153     /**
154      * Tests {@link FlowConvertor#convert(Flow, VersionDatapathIdConvertorData)} }.
155      */
156     @Test
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())
163                         .build())
164                     .build(),
165                     new InstructionBuilder().setOrder(1).setInstruction(new WriteMetadataCaseBuilder()
166                         .setWriteMetadata(new WriteMetadataBuilder()
167                             .setMetadata(Uint64.valueOf(2))
168                             .setMetadataMask(Uint64.valueOf(3))
169                             .build())
170                         .build())
171                     .build(),
172                     new InstructionBuilder().setOrder(2).setInstruction(new WriteActionsCaseBuilder()
173                         .setWriteActions(new WriteActionsBuilder().setAction(Map.of()).build())
174                         .build())
175                     .build(),
176                     new InstructionBuilder().setOrder(3).setInstruction(new ApplyActionsCaseBuilder()
177                         .setApplyActions(new ApplyActionsBuilder().setAction(Map.of()).build())
178                         .build())
179                     .build(),
180                     new InstructionBuilder().setOrder(4).setInstruction(new ClearActionsCaseBuilder()
181                         .setClearActions(new ClearActionsBuilder().setAction(Map.of()).build())
182                         .build())
183                     .build(),
184                     new InstructionBuilder().setOrder(5).setInstruction(new MeterCaseBuilder()
185                         .setMeter(new MeterBuilder().setMeterId(new MeterId(Uint32.valueOf(5))).build())
186                         .build())
187                     .build()))
188                 .build())
189             .build();
190
191         VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(OFConstants.OFP_VERSION_1_0);
192         data.setDatapathId(Uint64.valueOf(42));
193         List<FlowModInputBuilder> flowMod = convert(flow, data);
194
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());
214
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());
237     }
238
239     @Test
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())
245                         .build(),
246                 0);
247
248         mockFlow.setMatch(new MatchBuilder().setEthernetMatch(createEthernetMatch()).build());
249         mockFlow.setInstructions(new InstructionsBuilder()
250             .setInstruction(BindingMap.of(new InstructionBuilder()
251                 .setOrder(0)
252                 .setInstruction(new ApplyActionsCaseBuilder()
253                     .setApplyActions(new ApplyActionsBuilder().setAction(BindingMap.of(action1)).build())
254                     .build())
255                 .build()))
256             .build());
257
258         VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(OFConstants.OFP_VERSION_1_3);
259         data.setDatapathId(Uint64.ONE);
260
261         List<FlowModInputBuilder> flowModInputBuilders = convert(mockFlow, data);
262
263         assertEquals(2, flowModInputBuilders.size());
264     }
265
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();
270     }
271
272     private static Action createAction(
273             final org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action actionCase,
274             final int order) {
275         Action action = new ActionBuilder().setOrder(order).setAction(actionCase).build();
276         return action;
277     }
278
279     private static EthernetMatch createEthernetMatch() {
280         return new EthernetMatchBuilder()
281                 .setEthernetType(new EthernetTypeBuilder().setType(new EtherType(Uint32.valueOf(33024))).build())
282                 .build();
283     }
284
285     private static class MockFlow extends AbstractAugmentable<AddFlowInput> implements AddFlowInput {
286         private Instructions instructions;
287         private Match match;
288
289         public void setInstructions(final Instructions instructions) {
290             this.instructions = instructions;
291         }
292
293         public void setMatch(final Match match) {
294             this.match = match;
295         }
296
297         @Override
298         public FlowRef getFlowRef() {
299             return null;
300         }
301
302         @Override
303         public FlowTableRef getFlowTable() {
304             return null;
305         }
306
307         @Override
308         public Match getMatch() {
309             return match;
310         }
311
312         @Override
313         public Instructions getInstructions() {
314             return instructions;
315         }
316
317         @Override
318         public String getContainerName() {
319             return null;
320         }
321
322         @Override
323         public FlowCookie getCookieMask() {
324             return null;
325         }
326
327         @Override
328         public Uint32 getBufferId() {
329             return null;
330         }
331
332         @Override
333         public Uint64 getOutPort() {
334             return null;
335         }
336
337         @Override
338         public Uint32 getOutGroup() {
339             return null;
340         }
341
342         @Override
343         public org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowModFlags getFlags() {
344             return null;
345         }
346
347         @Override
348         public String getFlowName() {
349             return null;
350         }
351
352         @Override
353         public Boolean getInstallHw() {
354             return null;
355         }
356
357         @Override
358         public Boolean getBarrier() {
359             return null;
360         }
361
362         @Override
363         public Boolean getStrict() {
364             return null;
365         }
366
367         @Override
368         public Uint16 getPriority() {
369             return null;
370         }
371
372         @Override
373         public Uint16 getIdleTimeout() {
374             return null;
375         }
376
377         @Override
378         public Uint16 getHardTimeout() {
379             return null;
380         }
381
382         @Override
383         public FlowCookie getCookie() {
384             return null;
385         }
386
387         @Override
388         public Uint8 getTableId() {
389             return null;
390         }
391
392         @Override
393         public NodeRef getNode() {
394             return null;
395         }
396
397         @Override
398         public Uri getTransactionUri() {
399             return null;
400         }
401
402         @Override
403         public Match nonnullMatch() {
404             return Objects.requireNonNullElse(getMatch(), MatchBuilder.empty());
405         }
406
407         @Override
408         public Instructions nonnullInstructions() {
409             return Objects.requireNonNullElse(getInstructions(), InstructionsBuilder.empty());
410         }
411     }
412 }