Add bundle messages serializers 25/47725/5
authorAndrej Leitner <andrej.leitner@pantheon.tech>
Tue, 25 Oct 2016 12:28:45 +0000 (14:28 +0200)
committerAndrej Leitner <andrej.leitner@pantheon.tech>
Fri, 4 Nov 2016 08:33:24 +0000 (09:33 +0100)
 - 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 <andrej.leitner@pantheon.tech>
openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/MessageFactoryInitializer.java
openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/experimenter/AbstractBundleMessageFactory.java [new file with mode: 0644]
openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/experimenter/BundleAddMessageFactory.java [new file with mode: 0644]
openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/experimenter/BundleControlFactory.java [new file with mode: 0644]
openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/factories/FlowModInputMessageFactory.java
openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/factories/GroupModInputMessageFactory.java
openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/factories/PortModInputMessageFactory.java
openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/serialization/experimenter/AbstractBundleMessageFactoryTest.java [new file with mode: 0644]
openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/serialization/experimenter/BundleAddMessageFactoryTest.java [new file with mode: 0644]
openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/serialization/experimenter/BundleControlFactoryTest.java [new file with mode: 0644]
openflowjava-util/src/main/java/org/opendaylight/openflowjava/util/ExperimenterSerializerKeyFactory.java

index 23551bb7530ba438c199b2e214b270758ef7991e..08b9bc542e2b99a19c8ede76ce9ed7b6437fea6a 100644 (file)
@@ -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 (file)
index 0000000..3fc2896
--- /dev/null
@@ -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<T extends DataContainer> implements OFSerializer<T>,
+        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<BundleProperty> 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<BundleExperimenterPropertyData> 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 (file)
index 0000000..9ceec4d
--- /dev/null
@@ -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<BundleAddMessage> {
+
+    @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<BundleProperty> bundleProperties = input.getBundleProperty();
+        if (bundleProperties != null && !bundleProperties.isEmpty()) {
+            outBuffer.writeZero(paddingNeeded(msgLength));
+            writeBundleProperties(input.getBundleProperty(), outBuffer);
+        }
+    }
+
+    private <T extends DataContainer> void serializeInnerMessage(final Message innerMessage, final ByteBuf outBuffer,
+                                                                 final Class<T> clazz) {
+        OFSerializer<T> 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 (file)
index 0000000..069f34f
--- /dev/null
@@ -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<BundleControl> {
+
+    @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);
+        }
+    }
+
+}
index 79f831bad952e0fe8f9b4bed6c124a94e8c8c6ce..62fab01423f16ba25ea58d26642e754210be0c39 100644 (file)
@@ -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<FlowModInput>, SerializerRegistryInjector {
+public class FlowModInputMessageFactory implements OFSerializer<FlowMod>, SerializerRegistryInjector {
     private static final byte MESSAGE_TYPE = 14;
     private static final byte PADDING_IN_FLOW_MOD_MESSAGE = 2;
     private static final TypeKeyMaker<Instruction> INSTRUCTION_KEY_MAKER =
@@ -37,14 +37,14 @@ public class FlowModInputMessageFactory implements OFSerializer<FlowModInput>, 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());
index 93e4c741c052e948500d55f0f9e918562cc919a6..95a3b7db47ee620f33718d0f8960e666ef66c0ed 100644 (file)
@@ -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<GroupModInput>, SerializerRegistryInjector {
+public class GroupModInputMessageFactory implements OFSerializer<GroupMod>, 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());
index 595a216c296edb8ad4a0bfbca76dd239dfcd8b68..ded3af6d259b4a794f4cb96bfc8385dc7a75e3e6 100644 (file)
@@ -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<PortModInput> {
+public class PortModInputMessageFactory implements OFSerializer<PortMod> {
     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 (file)
index 0000000..3de4997
--- /dev/null
@@ -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<BundleProperty> 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<? extends DataContainer> 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 (file)
index 0000000..9e66251
--- /dev/null
@@ -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<BundleAddMessage> factory;
+    @Mock
+    SerializerRegistry registry;
+    @Mock
+    OFSerializer<PortMod> portModSerializer;
+    @Mock
+    OFSerializer<BundleExperimenterPropertyData> 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 (file)
index 0000000..180d915
--- /dev/null
@@ -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<BundleControl> factory;
+    @Mock
+    SerializerRegistry registry;
+    @Mock
+    OFSerializer<BundleExperimenterPropertyData> 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
index 613cd804aef4ef069b6b47478f19aeacf9c61a32..24e78debc76c5e1c837ab68c2a6554f1f60cdb3a 100755 (executable)
@@ -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<? extends ExperimenterMeterBandSubType> 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<BundleExperimenterPropertyData> createBundlePropertySerializerKey(
+            short msgVersion, long experimenterId, long type) {
+        return new ExperimenterIdTypeSerializerKey<>(msgVersion, experimenterId, type, BundleExperimenterPropertyData.class);
+    }
 }
\ No newline at end of file