From ce4d2f2c0077fff015c3cde8c144fe543b915cba Mon Sep 17 00:00:00 2001 From: Andrej Leitner Date: Tue, 25 Oct 2016 14:28:45 +0200 Subject: [PATCH] Add bundle messages serializers - created and registered serializers for ONF_ET_BUNDLE_CONTROL and ONF_ET_BUNDLE_ADD_MESSAGE messages - updated Flow/Group/PortMod facories to use more general objects - registered additional serializers for inner messages - added tests Reference: ONF approved extension #230 Resolves: Bug 6806 Change-Id: I1e98332eed24e18f17157e9a16ac8d246c72af2c Signed-off-by: Andrej Leitner --- .../MessageFactoryInitializer.java | 16 +++ .../AbstractBundleMessageFactory.java | 80 +++++++++++++ .../experimenter/BundleAddMessageFactory.java | 55 +++++++++ .../experimenter/BundleControlFactory.java | 29 +++++ .../factories/FlowModInputMessageFactory.java | 14 +-- .../GroupModInputMessageFactory.java | 13 +-- .../factories/PortModInputMessageFactory.java | 9 +- .../AbstractBundleMessageFactoryTest.java | 82 ++++++++++++++ .../BundleAddMessageFactoryTest.java | 105 ++++++++++++++++++ .../BundleControlFactoryTest.java | 97 ++++++++++++++++ .../ExperimenterSerializerKeyFactory.java | 12 ++ 11 files changed, 494 insertions(+), 18 deletions(-) create mode 100644 openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/experimenter/AbstractBundleMessageFactory.java create mode 100644 openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/experimenter/BundleAddMessageFactory.java create mode 100644 openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/experimenter/BundleControlFactory.java create mode 100644 openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/serialization/experimenter/AbstractBundleMessageFactoryTest.java create mode 100644 openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/serialization/experimenter/BundleAddMessageFactoryTest.java create mode 100644 openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/serialization/experimenter/BundleControlFactoryTest.java diff --git a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/MessageFactoryInitializer.java b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/MessageFactoryInitializer.java index 23551bb7..08b9bc54 100644 --- a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/MessageFactoryInitializer.java +++ b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/MessageFactoryInitializer.java @@ -9,6 +9,8 @@ package org.opendaylight.openflowjava.protocol.impl.serialization; import org.opendaylight.openflowjava.protocol.api.extensibility.SerializerRegistry; import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants; +import org.opendaylight.openflowjava.protocol.impl.serialization.experimenter.BundleAddMessageFactory; +import org.opendaylight.openflowjava.protocol.impl.serialization.experimenter.BundleControlFactory; import org.opendaylight.openflowjava.protocol.impl.serialization.factories.BarrierInputMessageFactory; import org.opendaylight.openflowjava.protocol.impl.serialization.factories.EchoInputMessageFactory; import org.opendaylight.openflowjava.protocol.impl.serialization.factories.EchoReplyInputMessageFactory; @@ -37,6 +39,9 @@ import org.opendaylight.openflowjava.protocol.impl.serialization.factories.SetCo import org.opendaylight.openflowjava.protocol.impl.serialization.factories.TableModInputMessageFactory; import org.opendaylight.openflowjava.protocol.impl.serialization.factories.VendorInputMessageFactory; import org.opendaylight.openflowjava.protocol.impl.util.CommonMessageRegistryHelper; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.experimenter.input.experimenter.data.of.choice.bundle.add.message.message.FlowModCase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.experimenter.input.experimenter.data.of.choice.bundle.add.message.message.GroupModCase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.experimenter.input.experimenter.data.of.choice.bundle.add.message.message.PortModCase; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoReplyInput; @@ -111,5 +116,16 @@ public final class MessageFactoryInitializer { registryHelper.registerSerializer(SetAsyncInput.class, new SetAsyncInputMessageFactory()); registryHelper.registerSerializer(SetConfigInput.class, new SetConfigMessageFactory()); registryHelper.registerSerializer(TableModInput.class, new TableModInputMessageFactory()); + + // register ONF approved experimenter serializers + registryHelper.registerExperimenterSerializer(EncodeConstants.ONF_EXPERIMENTER_ID, + EncodeConstants.ONF_ET_BUNDLE_CONTROL, new BundleControlFactory()); + registryHelper.registerExperimenterSerializer(EncodeConstants.ONF_EXPERIMENTER_ID, + EncodeConstants.ONF_ET_BUNDLE_ADD_MESSAGE, new BundleAddMessageFactory()); + + // register serializers for inner messages of BundleAddMessage + registryHelper.registerSerializer(FlowModCase.class, new FlowModInputMessageFactory()); + registryHelper.registerSerializer(GroupModCase.class, new GroupModInputMessageFactory()); + registryHelper.registerSerializer(PortModCase.class, new PortModInputMessageFactory()); } } diff --git a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/experimenter/AbstractBundleMessageFactory.java b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/experimenter/AbstractBundleMessageFactory.java new file mode 100644 index 00000000..3fc2896a --- /dev/null +++ b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/experimenter/AbstractBundleMessageFactory.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2016 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.openflowjava.protocol.impl.serialization.experimenter; + +import io.netty.buffer.ByteBuf; +import java.util.List; +import org.opendaylight.openflowjava.protocol.api.extensibility.OFSerializer; +import org.opendaylight.openflowjava.protocol.api.extensibility.SerializerRegistry; +import org.opendaylight.openflowjava.protocol.api.extensibility.SerializerRegistryInjector; +import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants; +import org.opendaylight.openflowjava.util.ByteBufUtils; +import org.opendaylight.openflowjava.util.ExperimenterSerializerKeyFactory; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.BundleFlags; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.BundlePropertyType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.bundle.properties.BundleProperty; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.bundle.properties.bundle.property.bundle.property.entry.BundleExperimenterProperty; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.bundle.properties.bundle.property.bundle.property.entry.bundle.experimenter.property.BundleExperimenterPropertyData; +import org.opendaylight.yangtools.yang.binding.DataContainer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Abstract class for common stuff of bundle messages. + */ +public abstract class AbstractBundleMessageFactory implements OFSerializer, + SerializerRegistryInjector { + + private static final Logger LOG = LoggerFactory.getLogger(AbstractBundleMessageFactory.class); + protected SerializerRegistry serializerRegistry; + + @Override + public void serialize(T input, ByteBuf outBuffer) { + // to be extended + } + + @Override + public void injectSerializerRegistry(SerializerRegistry serializerRegistry) { + this.serializerRegistry = serializerRegistry; + } + + protected static void writeBundleFlags(final BundleFlags bundleFlags, final ByteBuf outBuffer) { + int flagsBitMap = ByteBufUtils.fillBitMask(0, bundleFlags.isAtomic(), bundleFlags.isOrdered()); + outBuffer.writeShort(flagsBitMap); + } + + protected void writeBundleProperties(final List properties, final ByteBuf outBuffer) { + for (BundleProperty property : properties) { + BundlePropertyType type = property.getType(); + if (type != null && type.equals(BundlePropertyType.ONFETBPTEXPERIMENTER)) { + int startIndex = outBuffer.writerIndex(); + outBuffer.writeShort(type.getIntValue()); + int lengthIndex = outBuffer.writerIndex(); + outBuffer.writeShort(EncodeConstants.EMPTY_LENGTH); + writeBundleExperimenterProperty(property, outBuffer); + outBuffer.setShort(lengthIndex, outBuffer.writerIndex() - startIndex); + } else { + LOG.warn("lTrying to serialize unknown bundle property (type: {}), skipping", type.getIntValue() ); + } + } + } + + protected void writeBundleExperimenterProperty(final BundleProperty bundleProperty, final ByteBuf outBuffer) { + BundleExperimenterProperty property = (BundleExperimenterProperty) bundleProperty.getBundlePropertyEntry(); + int experimenterId = property.getExperimenter().getValue().intValue(); + int expType = property.getExpType().intValue(); + outBuffer.writeInt(experimenterId); + outBuffer.writeInt(expType); + OFSerializer serializer = serializerRegistry.getSerializer( + ExperimenterSerializerKeyFactory.createBundlePropertySerializerKey(EncodeConstants.OF13_VERSION_ID, + experimenterId, expType)); + serializer.serialize(property.getBundleExperimenterPropertyData(), outBuffer); + } + +} diff --git a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/experimenter/BundleAddMessageFactory.java b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/experimenter/BundleAddMessageFactory.java new file mode 100644 index 00000000..9ceec4de --- /dev/null +++ b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/experimenter/BundleAddMessageFactory.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2016 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.openflowjava.protocol.impl.serialization.experimenter; + +import io.netty.buffer.ByteBuf; +import java.util.List; +import org.opendaylight.openflowjava.protocol.api.extensibility.OFSerializer; +import org.opendaylight.openflowjava.protocol.api.keys.MessageTypeKey; +import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.bundle.properties.BundleProperty; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.experimenter.input.experimenter.data.of.choice.BundleAddMessage; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.experimenter.input.experimenter.data.of.choice.bundle.add.message.Message; +import org.opendaylight.yangtools.yang.binding.DataContainer; + +/** + * Translates BundleAddMessage messages (OpenFlow v1.3 extension #230). + */ +public class BundleAddMessageFactory extends AbstractBundleMessageFactory { + + @Override + public void serialize(BundleAddMessage input, ByteBuf outBuffer) { + outBuffer.writeInt(input.getBundleId().getValue().intValue()); + outBuffer.writeZero(2); + writeBundleFlags(input.getFlags(), outBuffer); + + int msgStart = outBuffer.writerIndex(); + serializeInnerMessage(input.getMessage(), outBuffer, input.getMessage().getImplementedInterface()); + int msgLength = outBuffer.writerIndex() - msgStart; + + List bundleProperties = input.getBundleProperty(); + if (bundleProperties != null && !bundleProperties.isEmpty()) { + outBuffer.writeZero(paddingNeeded(msgLength)); + writeBundleProperties(input.getBundleProperty(), outBuffer); + } + } + + private void serializeInnerMessage(final Message innerMessage, final ByteBuf outBuffer, + final Class clazz) { + OFSerializer serializer = serializerRegistry.getSerializer( + new MessageTypeKey<>(EncodeConstants.OF13_VERSION_ID, clazz)); + serializer.serialize((T)innerMessage, outBuffer); + } + + private static int paddingNeeded(final int length) { + int paddingRemainder = length % EncodeConstants.PADDING; + return (paddingRemainder != 0) ? (EncodeConstants.PADDING - paddingRemainder) : 0; + } + +} diff --git a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/experimenter/BundleControlFactory.java b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/experimenter/BundleControlFactory.java new file mode 100644 index 00000000..069f34fe --- /dev/null +++ b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/experimenter/BundleControlFactory.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2016 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.openflowjava.protocol.impl.serialization.experimenter; + +import io.netty.buffer.ByteBuf; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.experimenter.input.experimenter.data.of.choice.BundleControl; + +/** + * Translates BundleControl messages (OpenFlow v1.3 extension #230). + */ +public class BundleControlFactory extends AbstractBundleMessageFactory { + + @Override + public void serialize(BundleControl input, ByteBuf outBuffer) { + outBuffer.writeInt(input.getBundleId().getValue().intValue()); + outBuffer.writeShort(input.getType().getIntValue()); + writeBundleFlags(input.getFlags(), outBuffer); + if (input.getBundleProperty() != null) { + writeBundleProperties(input.getBundleProperty(), outBuffer); + } + } + +} diff --git a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/factories/FlowModInputMessageFactory.java b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/factories/FlowModInputMessageFactory.java index 79f831ba..62fab014 100644 --- a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/factories/FlowModInputMessageFactory.java +++ b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/factories/FlowModInputMessageFactory.java @@ -9,7 +9,6 @@ package org.opendaylight.openflowjava.protocol.impl.serialization.factories; import io.netty.buffer.ByteBuf; - import org.opendaylight.openflowjava.protocol.api.extensibility.OFSerializer; import org.opendaylight.openflowjava.protocol.api.extensibility.SerializerRegistry; import org.opendaylight.openflowjava.protocol.api.extensibility.SerializerRegistryInjector; @@ -22,14 +21,15 @@ import org.opendaylight.openflowjava.util.ByteBufUtils; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instructions.grouping.Instruction; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowModFlags; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.grouping.Match; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowModInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowMod; /** - * Translates FlowMod messages + * Translates FlowMod messages. + * OF protocol versions: 1.3. * @author timotej.kubas * @author michal.polkorab */ -public class FlowModInputMessageFactory implements OFSerializer, SerializerRegistryInjector { +public class FlowModInputMessageFactory implements OFSerializer, SerializerRegistryInjector { private static final byte MESSAGE_TYPE = 14; private static final byte PADDING_IN_FLOW_MOD_MESSAGE = 2; private static final TypeKeyMaker INSTRUCTION_KEY_MAKER = @@ -37,14 +37,14 @@ public class FlowModInputMessageFactory implements OFSerializer, S private SerializerRegistry registry; @Override - public void serialize(final FlowModInput message, final ByteBuf outBuffer) { + public void serialize(final FlowMod message, final ByteBuf outBuffer) { ByteBufUtils.writeOFHeader(MESSAGE_TYPE, message, outBuffer, EncodeConstants.EMPTY_LENGTH); outBuffer.writeLong(message.getCookie().longValue()); outBuffer.writeLong(message.getCookieMask().longValue()); outBuffer.writeByte(message.getTableId().getValue().byteValue()); outBuffer.writeByte(message.getCommand().getIntValue()); - outBuffer.writeShort(message.getIdleTimeout().intValue()); - outBuffer.writeShort(message.getHardTimeout().intValue()); + outBuffer.writeShort(message.getIdleTimeout()); + outBuffer.writeShort(message.getHardTimeout()); outBuffer.writeShort(message.getPriority()); outBuffer.writeInt(message.getBufferId().intValue()); outBuffer.writeInt(message.getOutPort().getValue().intValue()); diff --git a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/factories/GroupModInputMessageFactory.java b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/factories/GroupModInputMessageFactory.java index 93e4c741..95a3b7db 100644 --- a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/factories/GroupModInputMessageFactory.java +++ b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/factories/GroupModInputMessageFactory.java @@ -9,32 +9,31 @@ package org.opendaylight.openflowjava.protocol.impl.serialization.factories; import io.netty.buffer.ByteBuf; - import java.util.List; - import org.opendaylight.openflowjava.protocol.api.extensibility.OFSerializer; import org.opendaylight.openflowjava.protocol.api.extensibility.SerializerRegistry; import org.opendaylight.openflowjava.protocol.api.extensibility.SerializerRegistryInjector; import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants; -import org.opendaylight.openflowjava.protocol.impl.util.TypeKeyMakerFactory; import org.opendaylight.openflowjava.protocol.impl.util.ListSerializer; +import org.opendaylight.openflowjava.protocol.impl.util.TypeKeyMakerFactory; import org.opendaylight.openflowjava.util.ByteBufUtils; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GroupModInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GroupMod; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.buckets.grouping.BucketsList; /** - * Translates GroupMod messages + * Translates GroupMod messages. + * OF protocol versions: 1.3. * @author timotej.kubas * @author michal.polkorab */ -public class GroupModInputMessageFactory implements OFSerializer, SerializerRegistryInjector { +public class GroupModInputMessageFactory implements OFSerializer, SerializerRegistryInjector { private static final byte MESSAGE_TYPE = 15; private static final byte PADDING_IN_GROUP_MOD_MESSAGE = 1; private static final byte PADDING_IN_BUCKET = 4; private SerializerRegistry registry; @Override - public void serialize(GroupModInput message, ByteBuf outBuffer) { + public void serialize(GroupMod message, ByteBuf outBuffer) { ByteBufUtils.writeOFHeader(MESSAGE_TYPE, message, outBuffer, EncodeConstants.EMPTY_LENGTH); outBuffer.writeShort(message.getCommand().getIntValue()); outBuffer.writeByte(message.getType().getIntValue()); diff --git a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/factories/PortModInputMessageFactory.java b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/factories/PortModInputMessageFactory.java index 595a216c..ded3af6d 100644 --- a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/factories/PortModInputMessageFactory.java +++ b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/factories/PortModInputMessageFactory.java @@ -17,21 +17,22 @@ import org.opendaylight.openflowjava.util.ByteBufUtils; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.IetfYangUtil; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortConfig; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortFeatures; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortModInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortMod; /** - * Translates PortMod messages + * Translates PortMod messages. + * OF protocol versions: 1.3. * @author timotej.kubas * @author michal.polkorab */ -public class PortModInputMessageFactory implements OFSerializer { +public class PortModInputMessageFactory implements OFSerializer { private static final byte MESSAGE_TYPE = 16; private static final byte PADDING_IN_PORT_MOD_MESSAGE_01 = 4; private static final byte PADDING_IN_PORT_MOD_MESSAGE_02 = 2; private static final byte PADDING_IN_PORT_MOD_MESSAGE_03 = 4; @Override - public void serialize(final PortModInput message, final ByteBuf outBuffer) { + public void serialize(final PortMod message, final ByteBuf outBuffer) { ByteBufUtils.writeOFHeader(MESSAGE_TYPE, message, outBuffer, EncodeConstants.EMPTY_LENGTH); outBuffer.writeInt(message.getPortNo().getValue().intValue()); outBuffer.writeZero(PADDING_IN_PORT_MOD_MESSAGE_01); diff --git a/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/serialization/experimenter/AbstractBundleMessageFactoryTest.java b/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/serialization/experimenter/AbstractBundleMessageFactoryTest.java new file mode 100644 index 00000000..3de49975 --- /dev/null +++ b/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/serialization/experimenter/AbstractBundleMessageFactoryTest.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2016 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.openflowjava.protocol.impl.serialization.experimenter; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.UnpooledByteBufAllocator; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import org.junit.Assert; +import org.junit.Test; +import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.BundleFlags; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.BundlePropertyType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.bundle.properties.BundleProperty; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.bundle.properties.BundlePropertyBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.bundle.properties.bundle.property.bundle.property.entry.BundleExperimenterPropertyBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.bundle.properties.bundle.property.bundle.property.entry.bundle.experimenter.property.BundleExperimenterPropertyData; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.experimenter.input.experimenter.data.of.choice.bundle.add.message.message.PortModCase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.experimenter.input.experimenter.data.of.choice.bundle.add.message.message.PortModCaseBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ExperimenterId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortConfig; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortFeatures; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortNumber; +import org.opendaylight.yangtools.yang.binding.DataContainer; + +/** + * Test for {@link org.opendaylight.openflowjava.protocol.impl.serialization.experimenter.AbstractBundleMessageFactory} + * and util methods. + */ +public class AbstractBundleMessageFactoryTest { + + @Test + public void writeBundleFlags() throws Exception { + ByteBuf out = UnpooledByteBufAllocator.DEFAULT.buffer(); + AbstractBundleMessageFactory.writeBundleFlags(new BundleFlags(true, true), out); + Assert.assertEquals("Wrong flags", 3, out.readUnsignedShort()); + } + + public static List createListWithBundleExperimenterProperty(BundleExperimenterPropertyData data) { + BundlePropertyBuilder propertyBuilder = new BundlePropertyBuilder(); + propertyBuilder.setType(BundlePropertyType.ONFETBPTEXPERIMENTER); + BundleExperimenterPropertyBuilder experimenterPropertyBuilder = new BundleExperimenterPropertyBuilder(); + experimenterPropertyBuilder.setExperimenter(new ExperimenterId(1L)); + experimenterPropertyBuilder.setExpType(2L); + + experimenterPropertyBuilder.setBundleExperimenterPropertyData(data); + propertyBuilder.setBundlePropertyEntry(experimenterPropertyBuilder.build()); + return new ArrayList<>(Collections.singleton(propertyBuilder.build())); + } + + public static BundleExperimenterPropertyData createBundleExperimenterPropertyData() { + return new BundleExperimenterPropertyData() { + @Override + public Class getImplementedInterface() { + return null; + } + }; + } + + public static PortModCase createPortModCase() { + PortModCaseBuilder caseBuilder = new PortModCaseBuilder(); + caseBuilder.setVersion((short) EncodeConstants.OF13_VERSION_ID); + caseBuilder.setXid(3L); + caseBuilder.setPortNo(new PortNumber(9L)); + caseBuilder.setHwAddress(new MacAddress("08:00:27:00:B0:EB")); + caseBuilder.setConfig(new PortConfig(true, false, true, false)); + caseBuilder.setMask(new PortConfig(false, true, false, true)); + caseBuilder.setAdvertise(new PortFeatures(true, false, false, false, + false, false, false, true, + false, false, false, false, + false, false, false, false)); + return caseBuilder.build(); + } +} \ No newline at end of file diff --git a/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/serialization/experimenter/BundleAddMessageFactoryTest.java b/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/serialization/experimenter/BundleAddMessageFactoryTest.java new file mode 100644 index 00000000..9e662519 --- /dev/null +++ b/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/serialization/experimenter/BundleAddMessageFactoryTest.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2016 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.openflowjava.protocol.impl.serialization.experimenter; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.UnpooledByteBufAllocator; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Matchers; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.runners.MockitoJUnitRunner; +import org.opendaylight.openflowjava.protocol.api.extensibility.OFSerializer; +import org.opendaylight.openflowjava.protocol.api.extensibility.SerializerRegistry; +import org.opendaylight.openflowjava.protocol.api.extensibility.SerializerRegistryInjector; +import org.opendaylight.openflowjava.protocol.api.keys.MessageTypeKey; +import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants; +import org.opendaylight.openflowjava.protocol.impl.serialization.SerializerRegistryImpl; +import org.opendaylight.openflowjava.util.ExperimenterSerializerKeyFactory; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.BundleFlags; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.BundleId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.bundle.properties.bundle.property.bundle.property.entry.bundle.experimenter.property.BundleExperimenterPropertyData; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.experimenter.input.experimenter.data.of.choice.BundleAddMessage; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.experimenter.input.experimenter.data.of.choice.BundleAddMessageBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.experimenter.input.experimenter.data.of.choice.bundle.add.message.Message; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortMod; + +/** + * Test for {@link org.opendaylight.openflowjava.protocol.impl.serialization.experimenter.BundleAddMessageFactory}. + */ +@RunWith(MockitoJUnitRunner.class) +public class BundleAddMessageFactoryTest { + + private OFSerializer factory; + @Mock + SerializerRegistry registry; + @Mock + OFSerializer portModSerializer; + @Mock + OFSerializer propertySerializer; + + @Before + public void setUp() { + SerializerRegistry registry = new SerializerRegistryImpl(); + registry.init(); + factory = registry.getSerializer(ExperimenterSerializerKeyFactory.createExperimenterMessageSerializerKey( + EncodeConstants.OF13_VERSION_ID, EncodeConstants.ONF_EXPERIMENTER_ID, + EncodeConstants.ONF_ET_BUNDLE_ADD_MESSAGE)); + } + + @Test + public void testSerializeWithoutProperties() { + BundleAddMessageBuilder builder = new BundleAddMessageBuilder(); + builder.setBundleId(new BundleId(1L)); + builder.setFlags(new BundleFlags(true, false)); + + Message innerMessage = AbstractBundleMessageFactoryTest.createPortModCase(); + builder.setMessage(innerMessage); + + ByteBuf out = UnpooledByteBufAllocator.DEFAULT.buffer(); + Mockito.when(registry.getSerializer(Matchers.any(MessageTypeKey.class))).thenReturn(portModSerializer); + ((SerializerRegistryInjector) factory).injectSerializerRegistry(registry); + factory.serialize(builder.build(), out); + + Assert.assertEquals("Wrong bundle ID", 1L, out.readUnsignedInt()); + long padding = out.readUnsignedShort(); + Assert.assertEquals("Wrong flags", 1, out.readUnsignedShort()); + Mockito.verify(portModSerializer, Mockito.times(1)).serialize((PortMod)innerMessage, out); + } + + @Test + public void testSerializeWithExperimenterProperty() { + BundleAddMessageBuilder builder = new BundleAddMessageBuilder(); + builder.setBundleId(new BundleId(2L)); + builder.setFlags(new BundleFlags(true, false)); + + Message innerMessage = AbstractBundleMessageFactoryTest.createPortModCase(); + builder.setMessage(innerMessage); + + BundleExperimenterPropertyData data = AbstractBundleMessageFactoryTest.createBundleExperimenterPropertyData(); + builder.setBundleProperty(AbstractBundleMessageFactoryTest.createListWithBundleExperimenterProperty(data)); + + ByteBuf out = UnpooledByteBufAllocator.DEFAULT.buffer(); + Mockito.when(registry.getSerializer(Matchers.any(MessageTypeKey.class))) + .thenReturn(portModSerializer) + .thenReturn(propertySerializer); + ((SerializerRegistryInjector) factory).injectSerializerRegistry(registry); + factory.serialize(builder.build(), out); + + Assert.assertEquals("Wrong bundle ID", 2L, out.readUnsignedInt()); + long padding = out.readUnsignedShort(); + Assert.assertEquals("Wrong flags", 1, out.readUnsignedShort()); + Mockito.verify(portModSerializer, Mockito.times(1)).serialize((PortMod)innerMessage, out); + Mockito.verify(propertySerializer, Mockito.times(1)).serialize(data, out); + } + +} \ No newline at end of file diff --git a/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/serialization/experimenter/BundleControlFactoryTest.java b/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/serialization/experimenter/BundleControlFactoryTest.java new file mode 100644 index 00000000..180d915a --- /dev/null +++ b/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/serialization/experimenter/BundleControlFactoryTest.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2016 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.openflowjava.protocol.impl.serialization.experimenter; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.UnpooledByteBufAllocator; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Matchers; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.runners.MockitoJUnitRunner; +import org.opendaylight.openflowjava.protocol.api.extensibility.OFSerializer; +import org.opendaylight.openflowjava.protocol.api.extensibility.SerializerRegistry; +import org.opendaylight.openflowjava.protocol.api.extensibility.SerializerRegistryInjector; +import org.opendaylight.openflowjava.protocol.api.keys.MessageTypeKey; +import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants; +import org.opendaylight.openflowjava.protocol.impl.serialization.SerializerRegistryImpl; +import org.opendaylight.openflowjava.util.ExperimenterSerializerKeyFactory; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.BundleControlType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.BundleFlags; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.BundleId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.BundlePropertyType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.bundle.properties.bundle.property.bundle.property.entry.bundle.experimenter.property.BundleExperimenterPropertyData; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.experimenter.input.experimenter.data.of.choice.BundleControl; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.experimenter.input.experimenter.data.of.choice.BundleControlBuilder; + +/** + * Test for {@link org.opendaylight.openflowjava.protocol.impl.serialization.experimenter.BundleControlFactory}. + */ +@RunWith(MockitoJUnitRunner.class) +public class BundleControlFactoryTest { + + private OFSerializer factory; + @Mock + SerializerRegistry registry; + @Mock + OFSerializer serializer; + + @Before + public void setUp() throws Exception { + SerializerRegistry registry = new SerializerRegistryImpl(); + registry.init(); + factory = registry.getSerializer(ExperimenterSerializerKeyFactory.createExperimenterMessageSerializerKey( + EncodeConstants.OF13_VERSION_ID, EncodeConstants.ONF_EXPERIMENTER_ID, EncodeConstants.ONF_ET_BUNDLE_CONTROL)); + } + + @Test + public void testSerializeWithoutProperties() { + BundleControlBuilder builder = new BundleControlBuilder(); + builder.setBundleId(new BundleId(1L)); + builder.setType(BundleControlType.ONFBCTOPENREQUEST); + builder.setFlags(new BundleFlags(true, true)); + + ByteBuf out = UnpooledByteBufAllocator.DEFAULT.buffer(); + factory.serialize(builder.build(), out); + + Assert.assertEquals("Wrong bundle ID", 1L, out.readUnsignedInt()); + Assert.assertEquals("Wrong type", BundleControlType.ONFBCTOPENREQUEST.getIntValue(), out.readUnsignedShort()); + Assert.assertEquals("Wrong flags", 3, out.readUnsignedShort()); + Assert.assertTrue("Unexpected data", out.readableBytes() == 0); + } + + @Test + public void testSerializeWithExperimenterProperty() { + BundleControlBuilder builder = new BundleControlBuilder(); + builder.setBundleId(new BundleId(3L)); + builder.setType(BundleControlType.ONFBCTCOMMITREQUEST); + builder.setFlags(new BundleFlags(false, true)); + + BundleExperimenterPropertyData data = AbstractBundleMessageFactoryTest.createBundleExperimenterPropertyData(); + builder.setBundleProperty(AbstractBundleMessageFactoryTest.createListWithBundleExperimenterProperty(data)); + + ByteBuf out = UnpooledByteBufAllocator.DEFAULT.buffer(); + Mockito.when(registry.getSerializer(Matchers.any(MessageTypeKey.class))).thenReturn(serializer); + ((SerializerRegistryInjector) factory).injectSerializerRegistry(registry); + factory.serialize(builder.build(), out); + + Assert.assertEquals("Wrong bundle ID", 3L, out.readUnsignedInt()); + Assert.assertEquals("Wrong type", BundleControlType.ONFBCTCOMMITREQUEST.getIntValue(), out.readUnsignedShort()); + Assert.assertEquals("Wrong flags", 2, out.readUnsignedShort()); + Assert.assertEquals("Wrong property type", BundlePropertyType.ONFETBPTEXPERIMENTER.getIntValue(), out.readUnsignedShort()); + int length = out.readUnsignedShort(); + Assert.assertEquals("Wrong experimenter ID", 1, out.readUnsignedInt()); + Assert.assertEquals("Wrong experimenter type", 2, out.readUnsignedInt()); + Mockito.verify(serializer, Mockito.times(1)).serialize(data, out); + } + +} \ No newline at end of file diff --git a/openflowjava-util/src/main/java/org/opendaylight/openflowjava/util/ExperimenterSerializerKeyFactory.java b/openflowjava-util/src/main/java/org/opendaylight/openflowjava/util/ExperimenterSerializerKeyFactory.java index 613cd804..24e78deb 100755 --- a/openflowjava-util/src/main/java/org/opendaylight/openflowjava/util/ExperimenterSerializerKeyFactory.java +++ b/openflowjava-util/src/main/java/org/opendaylight/openflowjava/util/ExperimenterSerializerKeyFactory.java @@ -11,6 +11,7 @@ package org.opendaylight.openflowjava.util; import org.opendaylight.openflowjava.protocol.api.keys.ExperimenterIdMeterSubTypeSerializerKey; import org.opendaylight.openflowjava.protocol.api.keys.ExperimenterIdSerializerKey; import org.opendaylight.openflowjava.protocol.api.keys.ExperimenterIdTypeSerializerKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.bundle.properties.bundle.property.bundle.property.entry.bundle.experimenter.property.BundleExperimenterPropertyData; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ExperimenterMeterBandSubType; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.experimenter.core.ExperimenterDataOfChoice; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.meter.band.header.meter.band.MeterBandExperimenterCase; @@ -67,4 +68,15 @@ public abstract class ExperimenterSerializerKeyFactory { short msgVersion, long experimenterId, Class meterSubType) { return new ExperimenterIdMeterSubTypeSerializerKey<>(msgVersion, experimenterId, MeterBandExperimenterCase.class, meterSubType); } + + /** + * @param msgVersion openflow wire version + * @param experimenterId experimenter ID + * @param type experimenter type according to vendor implementation + * @return key instance + */ + public static ExperimenterIdSerializerKey createBundlePropertySerializerKey( + short msgVersion, long experimenterId, long type) { + return new ExperimenterIdTypeSerializerKey<>(msgVersion, experimenterId, type, BundleExperimenterPropertyData.class); + } } \ No newline at end of file -- 2.36.6