c4dc5c7c318e80285eb5ac52bf2ff4ecdd2a0bd8
[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
9 package org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flow;
10
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;
72
73 /**
74  * Unit tests for flow conversion.
75  *
76  * @author michal.polkorab
77  */
78 public class FlowConvertorTest {
79     private ConvertorManager convertorManager;
80
81     @Before
82     public void setUp() {
83         convertorManager = ConvertorManagerFactory.createDefaultManager();
84     }
85
86     /**
87      * Tests {@link FlowConvertor#convert(Flow, VersionDatapathIdConvertorData)} }.
88      */
89     @Test
90     public void test() {
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();
106
107         VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(OFConstants.OFP_VERSION_1_3);
108         data.setDatapathId(new BigInteger("42"));
109
110         List<FlowModInputBuilder> flowMod = convert(flow, data);
111
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());
129     }
130
131     /**
132      * Tests {@link FlowConvertor#convert(Flow, VersionDatapathIdConvertorData)} }.
133      */
134     @Test
135     public void testOnlyModifyStrictCommand() {
136         UpdatedFlowBuilder flowBuilder = new UpdatedFlowBuilder();
137         flowBuilder.setStrict(true);
138         UpdatedFlow flow = flowBuilder.build();
139
140         VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(OFConstants.OFP_VERSION_1_0);
141         data.setDatapathId(new BigInteger("42"));
142
143         List<FlowModInputBuilder> flowMod = convert(flow, data);
144
145         Assert.assertEquals("Wrong version", 1, flowMod.get(0).getVersion().intValue());
146         Assert.assertEquals("Wrong command", FlowModCommand.OFPFCADD, flowMod.get(0).getCommand());
147     }
148
149     /**
150      * Tests {@link FlowConvertor#convert(Flow, VersionDatapathIdConvertorData)} }.
151      */
152     @Test
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);
161
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());
208
209         InstructionsBuilder instructionsBuilder = new InstructionsBuilder();
210         instructionsBuilder.setInstruction(instructions);
211
212         AddFlowInputBuilder flowBuilder = new AddFlowInputBuilder();
213         flowBuilder.setInstructions(instructionsBuilder.build());
214         AddFlowInput flow = flowBuilder.build();
215
216         VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(OFConstants.OFP_VERSION_1_0);
217         data.setDatapathId(new BigInteger("42"));
218         List<FlowModInputBuilder> flowMod = convert(flow, data);
219
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());
239
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());
262     }
263
264     @Test
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())
270                         .build(),
271                 0);
272
273         mockFlow.setMatch(new MatchBuilder().setEthernetMatch(createEthernetMatch()).build());
274         mockFlow.setInstructions(toApplyInstruction(Collections.singletonList(action1)));
275
276         VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(OFConstants.OFP_VERSION_1_3);
277         data.setDatapathId(BigInteger.ONE);
278
279         List<FlowModInputBuilder> flowModInputBuilders = convert(mockFlow, data);
280
281         Assert.assertEquals(2, flowModInputBuilders.size());
282
283     }
284
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();
289     }
290
291     private static Action createAction(
292             final org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action actionCase,
293             final int order) {
294         Action action = new ActionBuilder().setOrder(order).setAction(actionCase).build();
295         return action;
296     }
297
298     private static EthernetMatch createEthernetMatch() {
299         EthernetMatchBuilder ethernetMatchBuilder = new EthernetMatchBuilder();
300         ethernetMatchBuilder.setEthernetType(new EthernetTypeBuilder().setType(new EtherType(33024L)).build());
301         return ethernetMatchBuilder.build();
302     }
303
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())
309                 .build())).build();
310     }
311
312     private static class MockFlow implements AddFlowInput {
313         private Instructions instructions;
314         private Match match;
315
316         public void setInstructions(final Instructions instructions) {
317             this.instructions = instructions;
318         }
319
320         public void setMatch(final Match match) {
321             this.match = match;
322         }
323
324
325         @Override
326         public FlowRef getFlowRef() {
327             return null;
328         }
329
330         @Override
331         public <E extends Augmentation<AddFlowInput>> E augmentation(final Class<E> augmentationType) {
332             return null;
333         }
334
335         @Override
336         public FlowTableRef getFlowTable() {
337             return null;
338         }
339
340         @Override
341         public Match getMatch() {
342             return match;
343         }
344
345         @Override
346         public Instructions getInstructions() {
347             return instructions;
348         }
349
350         @Override
351         public String getContainerName() {
352             return null;
353         }
354
355         @Override
356         public FlowCookie getCookieMask() {
357             return null;
358         }
359
360         @Override
361         public Long getBufferId() {
362             return null;
363         }
364
365         @Override
366         public BigInteger getOutPort() {
367             return null;
368         }
369
370         @Override
371         public Long getOutGroup() {
372             return null;
373         }
374
375         @Override
376         public org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowModFlags getFlags() {
377             return null;
378         }
379
380         @Override
381         public String getFlowName() {
382             return null;
383         }
384
385         @Override
386         public Boolean isInstallHw() {
387             return null;
388         }
389
390         @Override
391         public Boolean isBarrier() {
392             return null;
393         }
394
395         @Override
396         public Boolean isStrict() {
397             return null;
398         }
399
400         @Override
401         public Integer getPriority() {
402             return null;
403         }
404
405         @Override
406         public Integer getIdleTimeout() {
407             return null;
408         }
409
410         @Override
411         public Integer getHardTimeout() {
412             return null;
413         }
414
415         @Override
416         public FlowCookie getCookie() {
417             return null;
418         }
419
420         @Override
421         public Short getTableId() {
422             return null;
423         }
424
425         @Override
426         public NodeRef getNode() {
427             return null;
428         }
429
430         @Override
431         public Uri getTransactionUri() {
432             return null;
433         }
434
435         @Override
436         public Class<AddFlowInput> implementedInterface() {
437             return AddFlowInput.class;
438         }
439     }
440 }