/*
* Copyright (c) 2014 Pantheon Technologies s.r.o. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flow;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManager;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManagerFactory;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionDatapathIdConvertorData;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdActionCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.vlan.id.action._case.SetVlanIdActionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowTableRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlowBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ClearActionsCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.GoToTableCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.MeterCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteActionsCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteMetadataCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.clear.actions._case.ClearActionsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.go.to.table._case.GoToTableBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.meter._case.MeterBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.actions._case.WriteActionsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.metadata._case.WriteMetadataBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.ApplyActionsCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.GotoTableCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.MeterCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.WriteActionsCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.WriteMetadataCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowModCommand;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowModFlags;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowModInputBuilder;
import org.opendaylight.yangtools.yang.binding.Augmentation;
import org.opendaylight.yangtools.yang.binding.DataContainer;
/**
* @author michal.polkorab
*
*/
public class FlowConvertorTest {
private ConvertorManager convertorManager;
@Before
public void setUp() {
convertorManager = ConvertorManagerFactory.createDefaultManager();
}
/**
* Tests {@link org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flow.FlowConvertor#convert(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow, org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionDatapathIdConvertorData)} }
*/
@Test
public void test() {
RemoveFlowInputBuilder flowBuilder = new RemoveFlowInputBuilder();
flowBuilder.setBarrier(false);
flowBuilder.setCookie(new FlowCookie(new BigInteger("4")));
flowBuilder.setCookieMask(new FlowCookie(new BigInteger("5")));
flowBuilder.setTableId((short) 6);
flowBuilder.setStrict(true);
flowBuilder.setIdleTimeout(50);
flowBuilder.setHardTimeout(500);
flowBuilder.setPriority(40);
flowBuilder.setBufferId(18L);
flowBuilder.setOutPort(new BigInteger("65535"));
flowBuilder.setOutGroup(5000L);
flowBuilder.setFlags(null);
flowBuilder.setMatch(null);
RemoveFlowInput flow = flowBuilder.build();
VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(OFConstants.OFP_VERSION_1_3);
data.setDatapathId(new BigInteger("42"));
List<FlowModInputBuilder> flowMod = convert(flow, data);
Assert.assertEquals("Wrong version", 4, flowMod.get(0).getVersion().intValue());
Assert.assertEquals("Wrong cookie", 4, flowMod.get(0).getCookie().intValue());
Assert.assertEquals("Wrong cookie mask", 5, flowMod.get(0).getCookieMask().intValue());
Assert.assertEquals("Wrong table id", 6, flowMod.get(0).getTableId().getValue().intValue());
Assert.assertEquals("Wrong command", FlowModCommand.OFPFCDELETESTRICT, flowMod.get(0).getCommand());
Assert.assertEquals("Wrong idle timeout", 50, flowMod.get(0).getIdleTimeout().intValue());
Assert.assertEquals("Wrong hard timeout", 500, flowMod.get(0).getHardTimeout().intValue());
Assert.assertEquals("Wrong priority", 40, flowMod.get(0).getPriority().intValue());
Assert.assertEquals("Wrong buffer id", 18, flowMod.get(0).getBufferId().intValue());
Assert.assertEquals("Wrong out port", 65535, flowMod.get(0).getOutPort().getValue().intValue());
Assert.assertEquals("Wrong out group", 5000, flowMod.get(0).getOutGroup().intValue());
Assert.assertEquals("Wrong flags", new FlowModFlags(false, false, false, false, false), flowMod.get(0).getFlags());
Assert.assertEquals("Wrong match", "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.OxmMatchType",
flowMod.get(0).getMatch().getType().getName());
Assert.assertEquals("Wrong match entries size", 0, flowMod.get(0).getMatch().getMatchEntry().size());
}
/**
* Tests {@link org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flow.FlowConvertor#convert(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow, org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionDatapathIdConvertorData)} }
*/
@Test
public void testOnlyModifyStrictCommand() {
UpdatedFlowBuilder flowBuilder = new UpdatedFlowBuilder();
flowBuilder.setStrict(true);
UpdatedFlow flow = flowBuilder.build();
VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(OFConstants.OFP_VERSION_1_0);
data.setDatapathId(new BigInteger("42"));
List<FlowModInputBuilder> flowMod = convert(flow, data);
Assert.assertEquals("Wrong version", 1, flowMod.get(0).getVersion().intValue());
Assert.assertEquals("Wrong command", FlowModCommand.OFPFCADD, flowMod.get(0).getCommand());
}
/**
* Tests {@link org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flow.FlowConvertor#convert(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow, org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionDatapathIdConvertorData)} }
*/
@Test
public void testInstructionsTranslation() {
AddFlowInputBuilder flowBuilder = new AddFlowInputBuilder();
InstructionsBuilder instructionsBuilder = new InstructionsBuilder();
List<Instruction> instructions = new ArrayList<>();
InstructionBuilder instructionBuilder = new InstructionBuilder();
GoToTableCaseBuilder goToCaseBuilder = new GoToTableCaseBuilder();
GoToTableBuilder goToBuilder = new GoToTableBuilder();
goToBuilder.setTableId((short) 1);
goToCaseBuilder.setGoToTable(goToBuilder.build());
instructionBuilder.setInstruction(goToCaseBuilder.build());
instructionBuilder.setOrder(0);
instructions.add(instructionBuilder.build());
instructionBuilder = new InstructionBuilder();
WriteMetadataCaseBuilder metaCaseBuilder = new WriteMetadataCaseBuilder();
WriteMetadataBuilder metaBuilder = new WriteMetadataBuilder();
metaBuilder.setMetadata(new BigInteger("2"));
metaBuilder.setMetadataMask(new BigInteger("3"));
metaCaseBuilder.setWriteMetadata(metaBuilder.build());
instructionBuilder.setInstruction(metaCaseBuilder.build());
instructionBuilder.setOrder(1);
instructions.add(instructionBuilder.build());
instructionBuilder = new InstructionBuilder();
WriteActionsCaseBuilder writeCaseBuilder = new WriteActionsCaseBuilder();
WriteActionsBuilder writeBuilder = new WriteActionsBuilder();
List<Action> actions = new ArrayList<>();
writeBuilder.setAction(actions);
writeCaseBuilder.setWriteActions(writeBuilder.build());
instructionBuilder.setInstruction(writeCaseBuilder.build());
instructionBuilder.setOrder(2);
instructions.add(instructionBuilder.build());
instructionBuilder = new InstructionBuilder();
ApplyActionsCaseBuilder applyCaseBuilder = new ApplyActionsCaseBuilder();
ApplyActionsBuilder applyBuilder = new ApplyActionsBuilder();
actions = new ArrayList<>();
applyBuilder.setAction(actions);
applyCaseBuilder.setApplyActions(applyBuilder.build());
instructionBuilder.setInstruction(applyCaseBuilder.build());
instructionBuilder.setOrder(3);
instructions.add(instructionBuilder.build());
instructionBuilder = new InstructionBuilder();
ClearActionsCaseBuilder clearCaseBuilder = new ClearActionsCaseBuilder();
ClearActionsBuilder clearBuilder = new ClearActionsBuilder();
actions = new ArrayList<>();
clearBuilder.setAction(actions);
clearCaseBuilder.setClearActions(clearBuilder.build());
instructionBuilder.setInstruction(clearCaseBuilder.build());
instructionBuilder.setOrder(4);
instructions.add(instructionBuilder.build());
instructionBuilder = new InstructionBuilder();
MeterCaseBuilder meterCaseBuilder = new MeterCaseBuilder();
MeterBuilder meterBuilder = new MeterBuilder();
meterBuilder.setMeterId(new MeterId(5L));
meterCaseBuilder.setMeter(meterBuilder.build());
instructionBuilder.setInstruction(meterCaseBuilder.build());
instructionBuilder.setOrder(5);
instructions.add(instructionBuilder.build());
instructionsBuilder.setInstruction(instructions);
flowBuilder.setInstructions(instructionsBuilder.build());
AddFlowInput flow = flowBuilder.build();
VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(OFConstants.OFP_VERSION_1_0);
data.setDatapathId(new BigInteger("42"));
List<FlowModInputBuilder> flowMod = convert(flow, data);
Assert.assertEquals("Wrong version", 1, flowMod.get(0).getVersion().intValue());
Assert.assertEquals("Wrong command", FlowModCommand.OFPFCADD, flowMod.get(0).getCommand());
Assert.assertEquals("Wrong instructions size", 6, flowMod.get(0).getInstruction().size());
org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instructions
.grouping.Instruction instruction = flowMod.get(0).getInstruction().get(0);
Assert.assertEquals("Wrong type", "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common"
+ ".instruction.rev130731.instruction.grouping.instruction.choice.GotoTableCase", instruction.getInstructionChoice().getImplementedInterface().getName());
GotoTableCase gotoTableCase = (GotoTableCase) instruction.getInstructionChoice();
Assert.assertEquals("Wrong table id", 1, gotoTableCase.getGotoTable().getTableId().intValue());
instruction = flowMod.get(0).getInstruction().get(1);
Assert.assertEquals("Wrong type", "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common"
+ ".instruction.rev130731.instruction.grouping.instruction.choice.WriteMetadataCase", instruction.getInstructionChoice().getImplementedInterface().getName());
WriteMetadataCase writeMetadataCase = (WriteMetadataCase) instruction.getInstructionChoice();
Assert.assertArrayEquals("Wrong metadata", new byte[]{0, 0, 0, 0, 0, 0, 0, 2},
writeMetadataCase.getWriteMetadata().getMetadata());
Assert.assertArrayEquals("Wrong metadata mask", new byte[]{0, 0, 0, 0, 0, 0, 0, 3},
writeMetadataCase.getWriteMetadata().getMetadataMask());
instruction = flowMod.get(0).getInstruction().get(2);
Assert.assertEquals("Wrong type", "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common"
+ ".instruction.rev130731.instruction.grouping.instruction.choice.WriteActionsCase", instruction.getInstructionChoice().getImplementedInterface().getName());
WriteActionsCase writeActionsCase = (WriteActionsCase) instruction.getInstructionChoice();
Assert.assertEquals("Wrong actions size", 0, writeActionsCase.getWriteActions().getAction().size());
instruction = flowMod.get(0).getInstruction().get(3);
Assert.assertEquals("Wrong type", "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common"
+ ".instruction.rev130731.instruction.grouping.instruction.choice.ApplyActionsCase", instruction.getInstructionChoice().getImplementedInterface().getName());
ApplyActionsCase applyActionsCase = (ApplyActionsCase) instruction.getInstructionChoice();
Assert.assertEquals("Wrong actions size", 0, applyActionsCase.getApplyActions().getAction().size());
instruction = flowMod.get(0).getInstruction().get(4);
Assert.assertEquals("Wrong type", "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common"
+ ".instruction.rev130731.instruction.grouping.instruction.choice.ClearActionsCase", instruction.getInstructionChoice().getImplementedInterface().getName());
instruction = flowMod.get(0).getInstruction().get(5);
Assert.assertEquals("Wrong type", "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common"
+ ".instruction.rev130731.instruction.grouping.instruction.choice.MeterCase", instruction.getInstructionChoice().getImplementedInterface().getName());
MeterCase meterCase = (MeterCase) instruction.getInstructionChoice();
Assert.assertEquals("Wrong meter id", 5, meterCase.getMeter().getMeterId().intValue());
}
@Test
public void testCloneAndAugmentFlowWithSetVlanId() {
MockFlow mockFlow = new MockFlow();
Action action1 = createAction(
new SetVlanIdActionCaseBuilder().setSetVlanIdAction(
new SetVlanIdActionBuilder().setVlanId(new VlanId(10)).build())
.build(),
0);
mockFlow.setMatch(new MatchBuilder().setEthernetMatch(createEthernetMatch()).build());
mockFlow.setInstructions(toApplyInstruction(Collections.singletonList(action1)));
VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(OFConstants.OFP_VERSION_1_3);
data.setDatapathId(BigInteger.ONE);
List<FlowModInputBuilder> flowModInputBuilders = convert(mockFlow, data);
Assert.assertEquals(2, flowModInputBuilders.size());
}
private List<FlowModInputBuilder> convert(Flow flow, VersionDatapathIdConvertorData data) {
Optional<List<FlowModInputBuilder>> flowModOptional = convertorManager.convert(flow, data);
Assert.assertTrue("Flow convertor not found", flowModOptional.isPresent());
return flowModOptional.get();
}
private static Action createAction(final org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action actionCase,
final int order) {
Action action = new ActionBuilder().setOrder(order).setAction(actionCase).build();
return action;
}
private static EthernetMatch createEthernetMatch() {
EthernetMatchBuilder ethernetMatchBuilder = new EthernetMatchBuilder();
ethernetMatchBuilder.setEthernetType(new EthernetTypeBuilder().setType(new EtherType(33024L)).build());
return ethernetMatchBuilder.build();
}
private static Instructions toApplyInstruction(
final List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> actions) {
return new InstructionsBuilder()
.setInstruction(
Collections.singletonList(
new InstructionBuilder()
.setOrder(0)
.setInstruction(
new ApplyActionsCaseBuilder()
.setApplyActions((new ApplyActionsBuilder()).setAction(actions).build())
.build()
).build())
).build();
}
private static class MockFlow implements AddFlowInput {
private Instructions instructions;
private Match match;
public void setInstructions(final Instructions instructions) {
this.instructions = instructions;
}
public void setMatch(final Match match) {
this.match = match;
}
@Override
public FlowRef getFlowRef() {
return null;
}
@Override
public <E extends Augmentation<AddFlowInput>> E getAugmentation(final Class<E> augmentationType) {
return null;
}
@Override
public FlowTableRef getFlowTable() {
return null;
}
@Override
public Match getMatch() {
return match;
}
@Override
public Instructions getInstructions() {
return instructions;
}
@Override
public String getContainerName() {
return null;
}
@Override
public FlowCookie getCookieMask() {
return null;
}
@Override
public Long getBufferId() {
return null;
}
@Override
public BigInteger getOutPort() {
return null;
}
@Override
public Long getOutGroup() {
return null;
}
@Override
public org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowModFlags getFlags() {
return null;
}
@Override
public String getFlowName() {
return null;
}
@Override
public Boolean isInstallHw() {
return null;
}
@Override
public Boolean isBarrier() {
return null;
}
@Override
public Boolean isStrict() {
return null;
}
@Override
public Integer getPriority() {
return null;
}
@Override
public Integer getIdleTimeout() {
return null;
}
@Override
public Integer getHardTimeout() {
return null;
}
@Override
public FlowCookie getCookie() {
return null;
}
@Override
public Short getTableId() {
return null;
}
@Override
public NodeRef getNode() {
return null;
}
@Override
public Uri getTransactionUri() {
return null;
}
@Override
public Class<? extends DataContainer> getImplementedInterface() {
return Flow.class;
}
}
}