/* * Copyright (c) 2016 Hewlett-Packard Enterprise 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.openflowjava.nx.codec.action; import java.math.BigInteger; import java.util.ArrayList; import java.util.List; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.opendaylight.openflowjava.nx.api.NiciraConstants; import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.actions.grouping.Action; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.actions.grouping.ActionBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ExperimenterId; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionLearn; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionLearnBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.FlowModSpec; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromFieldCase; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromFieldCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromValueCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModCopyFieldIntoFieldCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModCopyValueIntoFieldCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModOutputToPortCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.add.match.from.field._case.FlowModAddMatchFromField; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.add.match.from.field._case.FlowModAddMatchFromFieldBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.add.match.from.value._case.FlowModAddMatchFromValueBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.copy.field.into.field._case.FlowModCopyFieldIntoFieldBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.copy.value.into.field._case.FlowModCopyValueIntoFieldBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.output.to.port._case.FlowModOutputToPortBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.learn.grouping.NxActionLearnBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.learn.grouping.nx.action.learn.FlowMods; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.learn.grouping.nx.action.learn.FlowModsBuilder; public class LearnCodecTest { private LearnCodec learnCodec; private ByteBuf buffer; private Action action; private final byte LEARN_HEADER_LEN = 32; private final byte NXAST_LEARN_SUBTYPE = 16; private static final short SRC_MASK = 0x2000; private static final short DST_MASK = 0x1800; private static final short NUM_BITS_MASK = 0x07FF; @Before public void setUp() { learnCodec = new LearnCodec(); buffer = ByteBufAllocator.DEFAULT.buffer(); } @Test public void serializeTest() { action = createAction(); learnCodec.serialize(action, buffer); Assert.assertEquals(LEARN_HEADER_LEN+56, buffer.readableBytes()); Assert.assertEquals(EncodeConstants.EXPERIMENTER_VALUE, buffer.readUnsignedShort()); Assert.assertEquals(LEARN_HEADER_LEN+56, buffer.readUnsignedShort()); Assert.assertEquals(NiciraConstants.NX_VENDOR_ID.intValue(), buffer.readUnsignedInt()); Assert.assertEquals(NXAST_LEARN_SUBTYPE, buffer.readUnsignedShort()); Assert.assertEquals(1, buffer.readUnsignedShort()); Assert.assertEquals(2, buffer.readUnsignedShort()); Assert.assertEquals(3, buffer.readUnsignedShort()); Assert.assertEquals(4, buffer.readLong()); Assert.assertEquals(5, buffer.readUnsignedShort()); Assert.assertEquals(6, buffer.readUnsignedByte()); buffer.skipBytes(1); Assert.assertEquals(7, buffer.readUnsignedShort()); Assert.assertEquals(8, buffer.readUnsignedShort()); assertFlowMods(); } @Test public void deserializeTest() { createBufer(buffer); action = learnCodec.deserialize(buffer); ActionLearn result = (ActionLearn) action.getActionChoice(); Action act= createAction(); ActionLearn expResult = (ActionLearn)act.getActionChoice(); Assert.assertEquals(expResult, result); } private void assertFlowMods() { short header = buffer.readShort(); short src = (short) ((header & SRC_MASK) >> 13); short dst = (short) ((header & DST_MASK) >> 11); short len = (short) (header & NUM_BITS_MASK); Assert.assertEquals(0, src); Assert.assertEquals(0, dst); Assert.assertEquals(48, len); Assert.assertEquals(9, buffer.readUnsignedInt()); Assert.assertEquals(10, buffer.readUnsignedShort()); Assert.assertEquals(11, buffer.readUnsignedInt()); Assert.assertEquals(12, buffer.readUnsignedShort()); buffer.skipBytes(2); Assert.assertEquals(9, buffer.readUnsignedInt()); Assert.assertEquals(10, buffer.readUnsignedShort()); Assert.assertEquals(11, buffer.readUnsignedInt()); Assert.assertEquals(12, buffer.readUnsignedShort()); buffer.skipBytes(2); Assert.assertEquals(9, buffer.readUnsignedShort()); Assert.assertEquals(10, buffer.readUnsignedInt()); Assert.assertEquals(11, buffer.readUnsignedShort()); buffer.skipBytes(2); Assert.assertEquals(9, buffer.readUnsignedShort()); Assert.assertEquals(10, buffer.readUnsignedInt()); Assert.assertEquals(11, buffer.readUnsignedShort()); buffer.skipBytes(2); Assert.assertEquals(9, buffer.readUnsignedInt()); Assert.assertEquals(10, buffer.readUnsignedShort()); Assert.assertEquals(0, buffer.readableBytes()); } private Action createAction() { ExperimenterId experimenterId = new ExperimenterId(NiciraConstants.NX_VENDOR_ID); ActionBuilder actionBuilder = new ActionBuilder(); actionBuilder.setExperimenterId(experimenterId); ActionLearnBuilder actionLearnBuilder = new ActionLearnBuilder(); NxActionLearnBuilder nxActionLearnBuilder = new NxActionLearnBuilder(); nxActionLearnBuilder.setIdleTimeout(1); nxActionLearnBuilder.setHardTimeout(2); nxActionLearnBuilder.setPriority(3); nxActionLearnBuilder.setCookie(BigInteger.valueOf(4)); nxActionLearnBuilder.setFlags(5); nxActionLearnBuilder.setTableId((short)6); nxActionLearnBuilder.setFinIdleTimeout(7); nxActionLearnBuilder.setFinHardTimeout(8); nxActionLearnBuilder.setFlowMods(createFlowMods()); actionLearnBuilder.setNxActionLearn(nxActionLearnBuilder.build()); actionBuilder.setActionChoice(actionLearnBuilder.build()); return actionBuilder.build(); } private List<FlowMods> createFlowMods() { List<FlowMods> flowMods = new ArrayList<FlowMods>(); //length = 14 FlowModsBuilder flowMod = new FlowModsBuilder(); FlowModAddMatchFromFieldBuilder spec = new FlowModAddMatchFromFieldBuilder(); spec.setFlowModNumBits(48); spec.setSrcField((long)9); spec.setSrcOfs(10); spec.setDstField((long) 11); spec.setDstOfs(12); FlowModAddMatchFromFieldCaseBuilder caseBuilder = new FlowModAddMatchFromFieldCaseBuilder(); caseBuilder.setFlowModAddMatchFromField(spec.build()); flowMod.setFlowModSpec(caseBuilder.build()); flowMods.add(flowMod.build()); //length = 14 FlowModsBuilder flowMod2 = new FlowModsBuilder(); FlowModCopyFieldIntoFieldBuilder spec2 = new FlowModCopyFieldIntoFieldBuilder(); spec2.setFlowModNumBits(48); spec2.setSrcField((long)9); spec2.setSrcOfs(10); spec2.setDstField((long) 11); spec2.setDstOfs(12); FlowModCopyFieldIntoFieldCaseBuilder caseBuilder2 = new FlowModCopyFieldIntoFieldCaseBuilder(); caseBuilder2.setFlowModCopyFieldIntoField(spec2.build()); flowMod2.setFlowModSpec(caseBuilder2.build()); flowMods.add(flowMod2.build()); //length = 10 FlowModsBuilder flowMod3 = new FlowModsBuilder(); FlowModCopyValueIntoFieldBuilder spec3 = new FlowModCopyValueIntoFieldBuilder(); spec3.setFlowModNumBits(48); spec3.setValue(9); spec3.setDstField((long) 10); spec3.setDstOfs(11); FlowModCopyValueIntoFieldCaseBuilder caseBuilder3 = new FlowModCopyValueIntoFieldCaseBuilder(); caseBuilder3.setFlowModCopyValueIntoField(spec3.build()); flowMod3.setFlowModSpec(caseBuilder3.build()); flowMods.add(flowMod3.build()); //length = 10 FlowModsBuilder flowMod4 = new FlowModsBuilder(); FlowModAddMatchFromValueBuilder spec4 = new FlowModAddMatchFromValueBuilder(); spec4.setFlowModNumBits(48); spec4.setValue(9); spec4.setSrcField((long) 10); spec4.setSrcOfs(11); FlowModAddMatchFromValueCaseBuilder caseBuilder4 = new FlowModAddMatchFromValueCaseBuilder(); caseBuilder4.setFlowModAddMatchFromValue(spec4.build()); flowMod4.setFlowModSpec(caseBuilder4.build()); flowMods.add(flowMod4.build()); //length = 8 FlowModsBuilder flowMod5 = new FlowModsBuilder(); FlowModOutputToPortBuilder spec5 = new FlowModOutputToPortBuilder(); spec5.setFlowModNumBits(48); spec5.setSrcField((long) 9); spec5.setSrcOfs(10); FlowModOutputToPortCaseBuilder caseBuilder5 = new FlowModOutputToPortCaseBuilder(); caseBuilder5.setFlowModOutputToPort(spec5.build()); flowMod5.setFlowModSpec(caseBuilder5.build()); flowMods.add(flowMod5.build()); return flowMods; } private void createBufer(ByteBuf message) { message.writeShort(EncodeConstants.EXPERIMENTER_VALUE); message.writeShort(LEARN_HEADER_LEN + 56); message.writeInt(NiciraConstants.NX_VENDOR_ID.intValue()); message.writeShort(NXAST_LEARN_SUBTYPE); message.writeShort(1); message.writeShort(2); message.writeShort(3); message.writeLong(4); message.writeShort(5); message.writeByte(6); message.writeZero(1); message.writeShort(7); message.writeShort(8); toFlowModSpecHeader(message, 0, 0); message.writeInt(9); message.writeShort(10); message.writeInt(11); message.writeShort(12); toFlowModSpecHeader(message, 0, 1); message.writeInt(9); message.writeShort(10); message.writeInt(11); message.writeShort(12); toFlowModSpecHeader(message, 1, 1); message.writeShort(9); message.writeInt(10); message.writeShort(11); toFlowModSpecHeader(message, 1, 0); message.writeShort(9); message.writeInt(10); message.writeShort(11); toFlowModSpecHeader(message, 0, 2); message.writeInt(9); message.writeShort(10); } private void toFlowModSpecHeader(ByteBuf message, int src, int dst) { short b = 0; short bitNum = 48; b |= (src << 13); b |= (dst << 11); b |= bitNum; message.writeShort(b); } }