Allow any hello mesage and extend hello support for v1.4, v1.5 87/26087/18
authorAndrej Leitner <andrej.leitner@pantheon.tech>
Tue, 4 Oct 2016 15:38:03 +0000 (17:38 +0200)
committerAndrej Leitner <andrej.leitner@pantheon.tech>
Wed, 2 Nov 2016 10:24:22 +0000 (11:24 +0100)
 - accept any (also unsupported version) hello message for handshake and negotiation
 - added version assignable factory
 - made HelloFactory version assignable
 - register deserializers for hello message of v1.4, v 1.5
 - update logging
 - update tests

Resolves: Bug 6805, Bug 4255

Change-Id: I228108908ecfb2c3a7f8afa866790b7c193f046c
Signed-off-by: Andrej Leitner <andrej.leitner@pantheon.tech>
20 files changed:
openflow-protocol-api/src/main/java/org/opendaylight/openflowjava/protocol/api/keys/MessageCodeKey.java
openflow-protocol-api/src/main/java/org/opendaylight/openflowjava/protocol/api/util/EncodeConstants.java
openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/DelegatingInboundHandler.java
openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/OFDecoder.java
openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/OFEncoder.java
openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/OFFrameDecoder.java
openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/OFVersionDetector.java
openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/TcpChannelInitializer.java
openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/connection/ChannelOutboundQueue.java
openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/connection/ConnectionAdapterImpl.java
openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/deserialization/MessageDeserializerInitializer.java
openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/deserialization/TypeToClassMapInitializer.java
openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/deserialization/factories/HelloMessageFactory.java
openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/util/SimpleDeserializerRegistryHelper.java
openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/util/VersionAssignableFactory.java [new file with mode: 0644]
openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/core/OFVersionDetectorTest.java
openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/deserialization/TypeToClassMapInitializerTest.java
openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/deserialization/factories/HelloMessageFactoryTest.java
openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/util/BufferHelper.java
openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/util/DefaultDeserializerFactoryTest.java [new file with mode: 0644]

index 6597c19ac56974c13169d1279eab0b7a7c9346a1..566b3623cd4c8570a252a9f7848bdfbf0f551db3 100644 (file)
@@ -28,6 +28,14 @@ public class MessageCodeKey {
         this.clazz = clazz;
     }
 
+    public int getMsgType() {
+        return this.msgType;
+    }
+
+    public Class<?> getClazz() {
+        return this.clazz;
+    }
+
     @Override
     public int hashCode() {
         final int prime = 31;
index 82a09282cb54688350370df6adb3647602b80ff7..dad7b76f1b4c128443a99e6b9fcffc8922f6334a 100644 (file)
@@ -9,7 +9,7 @@
 package org.opendaylight.openflowjava.protocol.api.util;
 
 /**
- * Stores common constants
+ * Stores common constants.
  * @author michal.polkorab
  */
 public abstract class EncodeConstants {
@@ -20,6 +20,14 @@ public abstract class EncodeConstants {
     public static final byte OF10_VERSION_ID = 0x01;
     /** OpenFlow v1.3 wire protocol number */
     public static final byte OF13_VERSION_ID = 0x04;
+    /** OpenFlow v1.4 wire protocol number */
+    public static final byte OF14_VERSION_ID = 0x05;
+    /** OpenFlow v1.5 wire protocol number */
+    public static final byte OF15_VERSION_ID = 0x06;
+    /** OpenFlow Hello message type value */
+    public static final byte OF_HELLO_MESSAGE_TYPE_VALUE = 0;
+    /** OpenFlow PacketIn message type value */
+    public static final byte OF_PACKETIN_MESSAGE_TYPE_VALUE = 10;
     /** Index of length in Openflow header */
     public static final int OFHEADER_LENGTH_INDEX = 2;
     /** Size of Openflow header */
@@ -52,10 +60,9 @@ public abstract class EncodeConstants {
     /** Common experimenter value */
     public static final int EXPERIMENTER_VALUE = 0xFFFF;
 
-
     /** OF v1.0 maximal port name length */
     public static final byte MAX_PORT_NAME_LENGTH = 16;
-    /** OF v1.3 lenght of experimenter_ids - see Multipart TableFeatures (properties) message */
+    /** OF v1.3 length of experimenter_ids - see Multipart TableFeatures (properties) message */
     public static final byte EXPERIMENTER_IDS_LENGTH = 8;
 
     private EncodeConstants() {
index a0efc90073852965c07ec63ea3b771853f533120..b0fee5c3bbe81a467855f4e38a088ca1d57381ac 100644 (file)
@@ -8,9 +8,9 @@
 
 package org.opendaylight.openflowjava.protocol.impl.core;
 
+import com.google.common.base.Preconditions;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.ChannelInboundHandlerAdapter;
-
 import org.opendaylight.openflowjava.protocol.impl.core.connection.ConnectionAdapterImpl;
 import org.opendaylight.openflowjava.protocol.impl.core.connection.MessageConsumer;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.DisconnectEventBuilder;
@@ -18,8 +18,6 @@ import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Preconditions;
-
 /**
  * Holds reference to {@link ConnectionAdapterImpl} and passes messages for further processing.
  * Also informs on switch disconnection.
@@ -28,12 +26,11 @@ import com.google.common.base.Preconditions;
 public class DelegatingInboundHandler extends ChannelInboundHandlerAdapter {
 
     private static final Logger LOG = LoggerFactory.getLogger(DelegatingInboundHandler.class);
-
     private final MessageConsumer consumer;
     private boolean inactiveMessageSent = false;
 
     /**
-     * Constructs class + creates and sets MessageConsumer
+     * Constructs class + creates and sets MessageConsumer.
      * @param connectionAdapter reference for adapter communicating with upper layers outside library
      */
     public DelegatingInboundHandler(final MessageConsumer connectionAdapter) {
index ec1f43d329e1efa23ea0171607fcaf63642a4319..90d0ab0227dffe084be247402b0caccf8bf55e2e 100644 (file)
@@ -10,9 +10,7 @@ package org.opendaylight.openflowjava.protocol.impl.core;
 
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.handler.codec.MessageToMessageDecoder;
-
 import java.util.List;
-
 import org.opendaylight.openflowjava.protocol.impl.deserialization.DeserializationFactory;
 import org.opendaylight.openflowjava.statistics.CounterEventTypes;
 import org.opendaylight.openflowjava.statistics.StatisticsCounters;
@@ -22,7 +20,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * Transforms OpenFlow Protocol messages to POJOs
+ * Transforms OpenFlow Protocol messages to POJOs.
  * @author michal.polkorab
  */
 public class OFDecoder extends MessageToMessageDecoder<VersionMessageWrapper> {
@@ -33,18 +31,14 @@ public class OFDecoder extends MessageToMessageDecoder<VersionMessageWrapper> {
     // TODO: make this final?
     private DeserializationFactory deserializationFactory;
 
-    /**
-     * Constructor of class
-     */
     public OFDecoder() {
-        LOG.trace("Creating OF 1.3 Decoder");
-       // TODO: pass as argument
+        LOG.trace("Creating OFDecoder");
+           // TODO: pass as argument
         statisticsCounter = StatisticsCounters.getInstance();
     }
 
     @Override
-    protected void decode(ChannelHandlerContext ctx, VersionMessageWrapper msg,
-            List<Object> out) throws Exception {
+    protected void decode(ChannelHandlerContext ctx, VersionMessageWrapper msg, List<Object> out) throws Exception {
         statisticsCounter.incrementCounter(CounterEventTypes.US_RECEIVED_IN_OFJAVA);
         if (LOG.isDebugEnabled()) {
             LOG.debug("VersionMessageWrapper received");
index 4c54732bda6ed0b91274dc56858d921bae13620e..2f356693773803aac9b87628f77588f19c0299e8 100644 (file)
@@ -21,7 +21,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * Transforms OpenFlow Protocol messages to POJOs
+ * Transforms OpenFlow Protocol messages to POJOs.
  * @author michal.polkorab
  * @author timotej.kubas
  */
@@ -34,7 +34,7 @@ public class OFEncoder extends MessageToByteEncoder<MessageListenerWrapper> {
     /** Constructor of class */
     public OFEncoder() {
         statisticsCounters = StatisticsCounters.getInstance();
-        LOG.trace("Creating OF13Encoder");
+        LOG.trace("Creating OFEncoder");
     }
 
     @Override
index 735070fa0c0017684b6d37c95207446d5b3a2d06..a9c5ecd252325af820af76a7fbd413223fe9e830 100644 (file)
@@ -12,9 +12,7 @@ package org.opendaylight.openflowjava.protocol.impl.core;
 import io.netty.buffer.ByteBuf;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.handler.codec.ByteToMessageDecoder;
-
 import java.util.List;
-
 import org.opendaylight.openflowjava.protocol.impl.core.connection.ConnectionFacade;
 import org.opendaylight.openflowjava.util.ByteBufUtils;
 import org.slf4j.Logger;
@@ -26,7 +24,7 @@ import org.slf4j.LoggerFactory;
  */
 public class OFFrameDecoder extends ByteToMessageDecoder {
 
-    /** Length of OpenFlow 1.3 header */
+    /** Length of OpenFlow header */
     public static final byte LENGTH_OF_HEADER = 8;
     private static final byte LENGTH_INDEX_IN_HEADER = 2;
     private static final Logger LOG = LoggerFactory.getLogger(OFFrameDecoder.class);
@@ -36,7 +34,7 @@ public class OFFrameDecoder extends ByteToMessageDecoder {
     /**
      * Constructor of class.
      * @param connectionFacade  ConnectionFacade that will be notified
-     * with ConnectionReadyNotification after TLS has been successfully set up.
+     *                          with ConnectionReadyNotification after TLS has been successfully set up.
      * @param tlsPresent true is TLS is required, false otherwise
      */
     public OFFrameDecoder(ConnectionFacade connectionFacade, boolean tlsPresent) {
index b635ef2567610076a3b982db2dfb688ed387f209..8e23566af1fef8bf5fda007668787aff26c58f97 100644 (file)
@@ -11,6 +11,8 @@ package org.opendaylight.openflowjava.protocol.impl.core;
 import io.netty.buffer.ByteBuf;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.handler.codec.ByteToMessageDecoder;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
 import org.opendaylight.openflowjava.statistics.CounterEventTypes;
@@ -19,23 +21,20 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * Detects version of used OpenFlow Protocol and discards unsupported version messages
+ * Detects version of used OpenFlow Protocol and discards unsupported version messages.
  * @author michal.polkorab
  */
 public class OFVersionDetector extends ByteToMessageDecoder {
 
-    /** Version number of OpenFlow 1.0 protocol */
-    private static final byte OF10_VERSION_ID = EncodeConstants.OF10_VERSION_ID;
-    /** Version number of OpenFlow 1.3 protocol */
-    private static final byte OF13_VERSION_ID = EncodeConstants.OF13_VERSION_ID;
-    private static final short OF_PACKETIN = 10;
     private static final Logger LOG = LoggerFactory.getLogger(OFVersionDetector.class);
+    /** IDs of accepted OpenFlow protocol versions */
+    private static final List<Byte> OF_VERSIONS = new ArrayList<>(Arrays.asList(
+            EncodeConstants.OF10_VERSION_ID,
+            EncodeConstants.OF13_VERSION_ID
+    ));
     private final StatisticsCounters statisticsCounters;
     private volatile boolean filterPacketIns;
 
-    /**
-     * Constructor of class.
-     */
     public OFVersionDetector() {
         LOG.trace("Creating OFVersionDetector");
         statisticsCounters = StatisticsCounters.getInstance();
@@ -54,9 +53,10 @@ public class OFVersionDetector extends ByteToMessageDecoder {
         }
 
         final byte version = in.readByte();
-        if (version == OF13_VERSION_ID || version == OF10_VERSION_ID) {
+        final short messageType = in.getUnsignedByte(in.readerIndex());
+        if (messageType == EncodeConstants.OF_HELLO_MESSAGE_TYPE_VALUE || OF_VERSIONS.contains(version)) {
             LOG.debug("detected version: {}", version);
-            if (!filterPacketIns || OF_PACKETIN != in.getUnsignedByte(in.readerIndex())) {
+            if (!filterPacketIns || EncodeConstants.OF_PACKETIN_MESSAGE_TYPE_VALUE != messageType) {
                 ByteBuf messageBuffer = in.slice();
                 out.add(new VersionMessageWrapper(version, messageBuffer));
                 messageBuffer.retain();
@@ -69,4 +69,5 @@ public class OFVersionDetector extends ByteToMessageDecoder {
         }
         in.skipBytes(in.readableBytes());
     }
+
 }
index 376978d1c4e392eb9069fb50ba50422c7c1b807d..9540eeede476daf713912e1ead7a2f0834faad65 100644 (file)
@@ -26,26 +26,24 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * Initializes TCP / TLS channel
+ * Initializes TCP / TLS channel.
  * @author michal.polkorab
  */
 public class TcpChannelInitializer extends ProtocolChannelInitializer<SocketChannel> {
 
-    private static final Logger LOG = LoggerFactory
-            .getLogger(TcpChannelInitializer.class);
+    private static final Logger LOG = LoggerFactory.getLogger(TcpChannelInitializer.class);
     private final DefaultChannelGroup allChannels;
     private final ConnectionAdapterFactory connectionAdapterFactory;
 
     /**
-     * default ctor
+     * Default constructor.
      */
     public TcpChannelInitializer() {
         this( new DefaultChannelGroup("netty-receiver", null), new ConnectionAdapterFactoryImpl() );
     }
 
     /**
-     * Testing Constructor
-     *
+     * Testing constructor.
      */
     protected TcpChannelInitializer( final DefaultChannelGroup channelGroup, final ConnectionAdapterFactory connAdaptorFactory ) {
        allChannels = channelGroup ;
@@ -72,10 +70,11 @@ public class TcpChannelInitializer extends ProtocolChannelInitializer<SocketChan
         ConnectionFacade connectionFacade = null;
         connectionFacade = connectionAdapterFactory.createConnectionFacade(ch, null, useBarrier());
         try {
-            LOG.debug("calling plugin: {}", getSwitchConnectionHandler());
+            LOG.debug("Calling OF plugin: {}", getSwitchConnectionHandler());
             getSwitchConnectionHandler().onSwitchConnected(connectionFacade);
             connectionFacade.checkListeners();
-            ch.pipeline().addLast(PipelineHandlers.IDLE_HANDLER.name(), new IdleHandler(getSwitchIdleTimeout(), TimeUnit.MILLISECONDS));
+            ch.pipeline().addLast(PipelineHandlers.IDLE_HANDLER.name(),
+                    new IdleHandler(getSwitchIdleTimeout(), TimeUnit.MILLISECONDS));
             boolean tlsPresent = false;
 
             // If this channel is configured to support SSL it will only support SSL
@@ -112,7 +111,8 @@ public class TcpChannelInitializer extends ProtocolChannelInitializer<SocketChan
             final OFEncoder ofEncoder = new OFEncoder();
             ofEncoder.setSerializationFactory(getSerializationFactory());
             ch.pipeline().addLast(PipelineHandlers.OF_ENCODER.name(), ofEncoder);
-            ch.pipeline().addLast(PipelineHandlers.DELEGATING_INBOUND_HANDLER.name(), new DelegatingInboundHandler(connectionFacade));
+            ch.pipeline().addLast(PipelineHandlers.DELEGATING_INBOUND_HANDLER.name(),
+                    new DelegatingInboundHandler(connectionFacade));
             if (!tlsPresent) {
                 connectionFacade.fireConnectionReadyNotification();
             }
index a3ce3d5ef1012d1630df682f23341caad1e96c4e..5845dff85ae683f18bf3282df11243576414339d 100644 (file)
@@ -145,7 +145,7 @@ final class ChannelOutboundQueue extends ChannelInboundHandlerAdapter {
      */
     private void conditionalFlush() {
         if (queue.isEmpty()) {
-            LOG.trace("Queue is empty, not flush needed");
+            LOG.trace("Queue is empty, flush not needed");
             return;
         }
         if (!channel.isWritable()) {
index 7c10be16208c60cc6234336a2bffaa489703bd93..8d9c87466a337039f15719754a57ccbf392118c4 100644 (file)
@@ -36,7 +36,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * Handles messages (notifications + rpcs) and connections
+ * Handles messages (notifications + rpcs) and connections.
  * @author mirehak
  * @author michal.polkorab
  */
@@ -53,11 +53,10 @@ public class ConnectionAdapterImpl extends AbstractConnectionAdapterStatistics i
     private final boolean useBarrier;
 
     /**
-     * default ctor
-     *
+     * Default constructor.
      * @param channel the channel to be set - used for communication
      * @param address client address (used only in case of UDP communication,
-     *            as there is no need to store address over tcp (stable channel))
+     *                as there is no need to store address over tcp (stable channel))
      * @param useBarrier value is configurable by configSubsytem
      */
     public ConnectionAdapterImpl(final Channel channel, final InetSocketAddress address, final boolean useBarrier) {
@@ -84,7 +83,7 @@ public class ConnectionAdapterImpl extends AbstractConnectionAdapterStatistics i
     @Override
     public void consumeDeviceMessage(final DataObject message) {
         LOG.debug("ConsumeIntern msg on {}", channel);
-        if (disconnectOccured ) {
+        if (disconnectOccured) {
             return;
         }
         if (message instanceof Notification) {
@@ -96,7 +95,7 @@ public class ConnectionAdapterImpl extends AbstractConnectionAdapterStatistics i
                 disconnectOccured = true;
             } else if (message instanceof SwitchIdleEvent) {
                 systemListener.onSwitchIdleEvent((SwitchIdleEvent) message);
-                // OpenFlow messages
+            // OpenFlow messages
             } else if (message instanceof EchoRequestMessage) {
                 if (outputManager != null) {
                     outputManager.onEchoRequest((EchoRequestMessage) message);
@@ -116,7 +115,7 @@ public class ConnectionAdapterImpl extends AbstractConnectionAdapterStatistics i
             } else if (message instanceof FlowRemovedMessage) {
                 messageListener.onFlowRemovedMessage((FlowRemovedMessage) message);
             } else if (message instanceof HelloMessage) {
-                LOG.info("Hello received / branch");
+                LOG.info("Hello received");
                 messageListener.onHelloMessage((HelloMessage) message);
             } else if (message instanceof MultipartReplyMessage) {
                 if (outputManager != null) {
@@ -131,15 +130,15 @@ public class ConnectionAdapterImpl extends AbstractConnectionAdapterStatistics i
                 LOG.warn("message listening not supported for type: {}", message.getClass());
             }
         } else if (message instanceof OfHeader) {
-            LOG.debug("OFheader msg received");
+            LOG.debug("OF header msg received");
 
             if (outputManager == null || !outputManager.onMessage((OfHeader) message)) {
                 final RpcResponseKey key = createRpcResponseKey((OfHeader) message);
                 final ResponseExpectedRpcListener<?> listener = findRpcResponse(key);
                 if (listener != null) {
-                    LOG.debug("corresponding rpcFuture found");
+                    LOG.debug("Corresponding rpcFuture found");
                     listener.completed((OfHeader)message);
-                    LOG.debug("after setting rpcFuture");
+                    LOG.debug("After setting rpcFuture");
                     responseCache.invalidate(key);
                 } else {
                     LOG.warn("received unexpected rpc response: {}", key);
@@ -150,10 +149,6 @@ public class ConnectionAdapterImpl extends AbstractConnectionAdapterStatistics i
         }
     }
 
-    /**
-     * @param message
-     * @return
-     */
     private static RpcResponseKey createRpcResponseKey(final OfHeader message) {
         return new RpcResponseKey(message.getXid(), message.getImplementedInterface().getName());
     }
index 0e6720247913a774eb5e1c26936645663e19c077..3fd8508fe11098a1c3db5c072575f458580bef2b 100644 (file)
@@ -55,8 +55,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.RoleRequestOutput;
 
 /**
+ * Util class for init registration of deserializers.
  * @author michal.polkorab
- *
  */
 public final class MessageDeserializerInitializer {
 
@@ -65,15 +65,14 @@ public final class MessageDeserializerInitializer {
     }
 
     /**
-     * Registers message deserializers
-     *
-     * @param registry
-     *            registry to be filled with deserializers
+     * Registers message deserializers.
+     * @param registry registry to be filled with deserializers
      */
-    public static void registerMessageDeserializers(DeserializerRegistry registry) {
+    public static void registerMessageDeserializers(final DeserializerRegistry registry) {
+        SimpleDeserializerRegistryHelper helper;
+
         // register OF v1.0 message deserializers
-        SimpleDeserializerRegistryHelper helper = new SimpleDeserializerRegistryHelper(EncodeConstants.OF10_VERSION_ID,
-                registry);
+        helper = new SimpleDeserializerRegistryHelper(EncodeConstants.OF10_VERSION_ID, registry);
         helper.registerDeserializer(0, null, HelloMessage.class, new OF10HelloMessageFactory());
         helper.registerDeserializer(1, null, ErrorMessage.class, new OF10ErrorMessageFactory());
         helper.registerDeserializer(2, null, EchoRequestMessage.class, new OF10EchoRequestMessageFactory());
@@ -88,7 +87,7 @@ public final class MessageDeserializerInitializer {
         helper.registerDeserializer(19, null, BarrierOutput.class, new OF10BarrierReplyMessageFactory());
         helper.registerDeserializer(21, null, GetQueueConfigOutput.class, new OF10QueueGetConfigReplyMessageFactory());
 
-        // register Of v1.3 message deserializers
+        // register OF v1.3 message deserializers
         helper = new SimpleDeserializerRegistryHelper(EncodeConstants.OF13_VERSION_ID, registry);
         helper.registerDeserializer(0, null, HelloMessage.class, new HelloMessageFactory());
         helper.registerDeserializer(1, null, ErrorMessage.class, new ErrorMessageFactory());
@@ -105,5 +104,13 @@ public final class MessageDeserializerInitializer {
         helper.registerDeserializer(23, null, GetQueueConfigOutput.class, new QueueGetConfigReplyMessageFactory());
         helper.registerDeserializer(25, null, RoleRequestOutput.class, new RoleReplyMessageFactory());
         helper.registerDeserializer(27, null, GetAsyncOutput.class, new GetAsyncReplyMessageFactory());
+
+        // register OF v1.4 message deserializers
+        helper = new SimpleDeserializerRegistryHelper(EncodeConstants.OF14_VERSION_ID, registry);
+        helper.registerDeserializer(0, null, HelloMessage.class, new HelloMessageFactory());
+
+        // register OF v1.5 message deserializers
+        helper = new SimpleDeserializerRegistryHelper(EncodeConstants.OF15_VERSION_ID, registry);
+        helper.registerDeserializer(0, null, HelloMessage.class, new HelloMessageFactory());
     }
 }
index 97ae5364ae01d7ecc418e609601aa2e8b5526e8f..0d603cd21860cf9bd845f265eb0d6004864b06b9 100644 (file)
@@ -43,9 +43,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.TableModInput;
 
 /**
+ * Util class for init OF message type to class mapping.
  * @author michal.polkorab
  * @author giuseppex.petralia@intel.com
- *
  */
 public final class TypeToClassMapInitializer {
 
@@ -54,13 +54,14 @@ public final class TypeToClassMapInitializer {
     }
 
     /**
-     * Initializes type to class map
-     *
-     * @param messageClassMap
+     * Initializes standard types mapping.
+     * @param messageClassMap type to class map
      */
-    public static void initializeTypeToClassMap(Map<TypeToClassKey, Class<?>> messageClassMap) {
+    public static void initializeTypeToClassMap(final Map<TypeToClassKey, Class<?>> messageClassMap) {
+        TypeToClassInitHelper helper;
+
         // init OF v1.0 mapping
-        TypeToClassInitHelper helper = new TypeToClassInitHelper(EncodeConstants.OF10_VERSION_ID, messageClassMap);
+        helper = new TypeToClassInitHelper(EncodeConstants.OF10_VERSION_ID, messageClassMap);
         helper.registerTypeToClass((short) 0, HelloMessage.class);
         helper.registerTypeToClass((short) 1, ErrorMessage.class);
         helper.registerTypeToClass((short) 2, EchoRequestMessage.class);
@@ -74,6 +75,7 @@ public final class TypeToClassMapInitializer {
         helper.registerTypeToClass((short) 17, MultipartReplyMessage.class);
         helper.registerTypeToClass((short) 19, BarrierOutput.class);
         helper.registerTypeToClass((short) 21, GetQueueConfigOutput.class);
+
         // init OF v1.3 mapping
         helper = new TypeToClassInitHelper(EncodeConstants.OF13_VERSION_ID, messageClassMap);
         helper.registerTypeToClass((short) 0, HelloMessage.class);
@@ -91,17 +93,25 @@ public final class TypeToClassMapInitializer {
         helper.registerTypeToClass((short) 23, GetQueueConfigOutput.class);
         helper.registerTypeToClass((short) 25, RoleRequestOutput.class);
         helper.registerTypeToClass((short) 27, GetAsyncOutput.class);
+
+        // init OF v1.4 mapping
+        helper = new TypeToClassInitHelper(EncodeConstants.OF14_VERSION_ID, messageClassMap);
+        helper.registerTypeToClass((short) 0, HelloMessage.class);
+
+        // init OF v1.5 mapping
+        helper = new TypeToClassInitHelper(EncodeConstants.OF15_VERSION_ID, messageClassMap);
+        helper.registerTypeToClass((short) 0, HelloMessage.class);
     }
 
     /**
-     * Initializes type to class map to associate OF code to Java Class for
-     * messages for additional deserializers.
-     *
-     * @param messageClassMap
+     * Initializes additional types mapping.
+     * @param messageClassMap type to class map
      */
-    public static void initializeAdditionalTypeToClassMap(Map<TypeToClassKey, Class<?>> messageClassMap) {
+    public static void initializeAdditionalTypeToClassMap(final Map<TypeToClassKey, Class<?>> messageClassMap) {
+        TypeToClassInitHelper helper;
+
         // init OF v1.0 mapping
-        TypeToClassInitHelper helper = new TypeToClassInitHelper(EncodeConstants.OF10_VERSION_ID, messageClassMap);
+        helper = new TypeToClassInitHelper(EncodeConstants.OF10_VERSION_ID, messageClassMap);
         helper.registerTypeToClass((short) 5, GetFeaturesInput.class);
         helper.registerTypeToClass((short) 7, GetConfigInput.class);
         helper.registerTypeToClass((short) 9, SetConfigInput.class);
@@ -111,6 +121,7 @@ public final class TypeToClassMapInitializer {
         helper.registerTypeToClass((short) 16, MultipartRequestInput.class);
         helper.registerTypeToClass((short) 18, BarrierInput.class);
         helper.registerTypeToClass((short) 20, GetQueueConfigInput.class);
+
         // init OF v1.3 mapping
         helper = new TypeToClassInitHelper(EncodeConstants.OF13_VERSION_ID, messageClassMap);
         helper.registerTypeToClass((short) 5, GetFeaturesInput.class);
index ca0a79c8d2271809a4674da4363188ba030a181c..50cf33c1c3a2a11ef102b738b256890d8e387ed3 100644 (file)
@@ -9,12 +9,11 @@
 package org.opendaylight.openflowjava.protocol.impl.deserialization.factories;
 
 import io.netty.buffer.ByteBuf;
-
 import java.util.ArrayList;
 import java.util.List;
-
 import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
 import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.openflowjava.protocol.impl.util.VersionAssignableFactory;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.HelloElementType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloMessage;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloMessageBuilder;
@@ -22,17 +21,19 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.hello.ElementsBuilder;
 
 /**
- * Translates Hello messages
+ * Translates Hello messages.
+ * OF protocol versions: 1.3, 1.4, 1.5.
  * @author michal.polkorab
  * @author timotej.kubas
  */
-public class HelloMessageFactory implements OFDeserializer<HelloMessage> {
+public class HelloMessageFactory extends VersionAssignableFactory implements OFDeserializer<HelloMessage> {
 
     private static final byte HELLO_ELEMENT_HEADER_SIZE = 4;
+
     @Override
     public HelloMessage deserialize(ByteBuf rawMessage) {
         HelloMessageBuilder builder = new HelloMessageBuilder();
-        builder.setVersion((short) EncodeConstants.OF13_VERSION_ID);
+        builder.setVersion(getVersion());
         builder.setXid(rawMessage.readUnsignedInt());
         if (rawMessage.readableBytes() > 0) {
             builder.setElements(readElement(rawMessage));
@@ -70,7 +71,7 @@ public class HelloMessageFactory implements OFDeserializer<HelloMessage> {
         for (int i = 0; i < input.length; i++) {
             int mask = input[i];
             for (int j = 0; j < Integer.SIZE; j++) {
-                    versionBitmapList.add((mask & (1<<j)) != 0);
+                    versionBitmapList.add((mask & (1 << j)) != 0);
             }
         }
         return versionBitmapList;
index 38d05d2cbc65c82c676b0fa6bf1a2f0d26ecb3ba..9e2fc83bbbcf517e628819ebb67da55c2c4877b9 100644 (file)
@@ -12,8 +12,8 @@ import org.opendaylight.openflowjava.protocol.api.extensibility.OFGeneralDeseria
 import org.opendaylight.openflowjava.protocol.api.keys.MessageCodeKey;
 
 /**
+ * Helper class for deserializer registration assigning particular version if necessary.
  * @author michal.polkorab
- *
  */
 public class SimpleDeserializerRegistryHelper {
 
@@ -24,21 +24,24 @@ public class SimpleDeserializerRegistryHelper {
      * @param version wire protocol version
      * @param deserializerRegistry registry to be filled with message deserializers
      */
-    public SimpleDeserializerRegistryHelper(short version, DeserializerRegistry deserializerRegistry) {
+    public SimpleDeserializerRegistryHelper(final short version, final DeserializerRegistry deserializerRegistry) {
         this.version = version;
         this.registry = deserializerRegistry;
     }
 
     /**
+     * Register deserializer in registry. If deserializer supports more protocol versions assign actual one.
      * @param code code / value to distinguish between deserializers
      * @param experimenterID TODO
-     * @param deserializedObjectClass class of object that will be deserialized
-     *  by given deserializer
+     * @param deserializedObjectClass class of object that will be deserialized by given deserializer
      * @param deserializer deserializer instance
      */
-    public void registerDeserializer(int code,
-            Long experimenterID, Class<?> deserializedObjectClass, OFGeneralDeserializer deserializer) {
-        registry.registerDeserializer(new MessageCodeKey(version, code,
-                deserializedObjectClass), deserializer);
+    public void registerDeserializer(final int code, final Long experimenterID, final Class<?> deserializedObjectClass,
+                                     final OFGeneralDeserializer deserializer) {
+        registry.registerDeserializer(new MessageCodeKey(version, code, deserializedObjectClass), deserializer);
+
+        if (deserializer instanceof VersionAssignableFactory) {
+            ((VersionAssignableFactory) deserializer).assignVersion(version);
+        }
     }
 }
diff --git a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/util/VersionAssignableFactory.java b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/util/VersionAssignableFactory.java
new file mode 100644 (file)
index 0000000..d10f8fa
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * 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.util;
+
+import javax.annotation.Nonnull;
+
+/**
+ * Abstract factory class to support OF protocol version assigning and reading.
+ */
+public abstract class VersionAssignableFactory {
+    private Short version;
+
+    /**
+     * @param version OpenFlow protocol version
+     */
+    public void assignVersion(@Nonnull final Short version) {
+        if (this.version == null) {
+            this.version = version;
+        } else {
+            throw new IllegalStateException("Version already assigned: " + this.version);
+        }
+    }
+
+    /**
+     * @return OpenFlow protocol version
+     */
+    protected Short getVersion() {
+        return this.version;
+    }
+}
\ No newline at end of file
index 8cf3f75f527ad5e3e857e2e8963816a085358f20..7b3d814a59b0f458e1b42e8198993b7b6bd3a690 100644 (file)
@@ -8,14 +8,13 @@
 
 package org.opendaylight.openflowjava.protocol.impl.core;
 
+import static org.junit.Assert.assertEquals;
+
 import io.netty.buffer.ByteBuf;
 import io.netty.channel.ChannelHandlerContext;
-
 import java.util.ArrayList;
 import java.util.List;
-
 import org.junit.Assert;
-import static org.junit.Assert.assertEquals;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -24,8 +23,7 @@ import org.mockito.runners.MockitoJUnitRunner;
 import org.opendaylight.openflowjava.util.ByteBufUtils;
 
 /**
- *
- * @author michal.polkorab
+ * Test for {@link org.opendaylight.openflowjava.protocol.impl.core.OFVersionDetector}.
  */
 @RunWith(MockitoJUnitRunner.class)
 public class OFVersionDetectorTest {
@@ -36,74 +34,40 @@ public class OFVersionDetectorTest {
     private OFVersionDetector detector;
     private List<Object> list = new ArrayList<>();
 
-    /**
-     * Sets up test environment
-     */
     @Before
     public void setUp() {
         list.clear();
         detector = new OFVersionDetector();
     }
 
-    /**
-     * Test of decode
-     * {@link OFVersionDetector#decode(io.netty.channel.ChannelHandlerContext, io.netty.buffer.ByteBuf, java.util.List)
-     * }
-     *
-     * @throws Exception
-     */
     @Test
-    public void testDecode13ProtocolMessage() throws Exception {
-        detector.decode(channelHandlerContext,
-                ByteBufUtils.hexStringToByteBuf("04 00 00 08 00 00 00 01"),
-                list);
-
-        Assert.assertEquals(7, ((VersionMessageWrapper) list.get(0))
-                .getMessageBuffer().readableBytes());
+    public void testDecode13ProtocolMessage() {
+        detector.decode(channelHandlerContext, ByteBufUtils.hexStringToByteBuf("04 00 00 08 00 00 00 01"), list);
+        Assert.assertEquals(7, ((VersionMessageWrapper) list.get(0)).getMessageBuffer().readableBytes());
     }
 
-    /**
-     * Test of decode
-     * {@link OFVersionDetector#decode(io.netty.channel.ChannelHandlerContext, io.netty.buffer.ByteBuf, java.util.List)
-     * }
-     * @throws Exception
-     */
     @Test
-    public void testDecode10ProtocolMessage() throws Exception {
-        detector.decode(channelHandlerContext,
-                ByteBufUtils.hexStringToByteBuf("01 00 00 08 00 00 00 01"),
-                list);
-
-        Assert.assertEquals(7, ((VersionMessageWrapper) list.get(0))
-                .getMessageBuffer().readableBytes());
+    public void testDecode10ProtocolMessage() {
+        detector.decode(channelHandlerContext, ByteBufUtils.hexStringToByteBuf("01 00 00 08 00 00 00 01"), list);
+        Assert.assertEquals(7, ((VersionMessageWrapper) list.get(0)).getMessageBuffer().readableBytes());
     }
 
-    /**
-     * Test of decode
-     * {@link OFVersionDetector#decode(io.netty.channel.ChannelHandlerContext, io.netty.buffer.ByteBuf, java.util.List)
-     * }
-     * @throws Exception
-     */
     @Test
-    public void testDecodeEmptyProtocolMessage() throws Exception {
+    public void testDecodeEmptyProtocolMessage() {
         ByteBuf byteBuffer = ByteBufUtils.hexStringToByteBuf("01 00 00 08 00 00 00 01").skipBytes(8);
         detector.decode(channelHandlerContext, byteBuffer, list);
-
-        assertEquals( 0, byteBuffer.refCnt() ) ;
+        assertEquals(0, byteBuffer.refCnt());
     }
 
-    /**
-     * Test of decode
-     * {@link OFVersionDetector#decode(io.netty.channel.ChannelHandlerContext, io.netty.buffer.ByteBuf, java.util.List)
-     * }
-     *
-     * @throws Exception
-     */
     @Test
-    public void testDecodeNotSupportedVersionProtocolMessage() throws Exception {
-        detector.decode(channelHandlerContext, ByteBufUtils.hexStringToByteBuf("02 00 00 08 00 00 00 01"), list);
-
+    public void testDecodeNotSupportedVersionProtocolMessage() {
+        detector.decode(channelHandlerContext, ByteBufUtils.hexStringToByteBuf("02 01 00 08 00 00 00 01"), list);
         Assert.assertEquals("List is not empty", 0, list.size());
     }
 
+    @Test
+    public void testDecodeHelloProtocolMessage() {
+        detector.decode(channelHandlerContext, ByteBufUtils.hexStringToByteBuf("05 00 00 08 00 00 00 01"), list);
+        Assert.assertEquals(7, ((VersionMessageWrapper) list.get(0)).getMessageBuffer().readableBytes());
+    }
 }
index cef8daa7dd68f794535dc827aa1e90b1ce2ec3fc..622b33ce6b50dd1ee571085cb51b896e4d934c5f 100644 (file)
@@ -47,21 +47,19 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.TableModInput;
 
 /**
+ * Test for {@link org.opendaylight.openflowjava.protocol.impl.deserialization.TypeToClassMapInitializer}.
  * @author michal.polkorab
  * @author giuseppex.petralia@intel.com
- *
  */
 public class TypeToClassMapInitializerTest {
 
     private Map<TypeToClassKey, Class<?>> messageClassMap;
 
-    /**
-     * Tests correct map initialization
-     */
     @Test
     public void test() {
         messageClassMap = new HashMap<>();
         TypeToClassMapInitializer.initializeTypeToClassMap(messageClassMap);
+
         short version = EncodeConstants.OF10_VERSION_ID;
         assertEquals("Wrong class", HelloMessage.class, messageClassMap.get(new TypeToClassKey(version, 0)));
         assertEquals("Wrong class", ErrorMessage.class, messageClassMap.get(new TypeToClassKey(version, 1)));
@@ -76,6 +74,7 @@ public class TypeToClassMapInitializerTest {
         assertEquals("Wrong class", MultipartReplyMessage.class, messageClassMap.get(new TypeToClassKey(version, 17)));
         assertEquals("Wrong class", BarrierOutput.class, messageClassMap.get(new TypeToClassKey(version, 19)));
         assertEquals("Wrong class", GetQueueConfigOutput.class, messageClassMap.get(new TypeToClassKey(version, 21)));
+
         version = EncodeConstants.OF13_VERSION_ID;
         assertEquals("Wrong class", HelloMessage.class, messageClassMap.get(new TypeToClassKey(version, 0)));
         assertEquals("Wrong class", ErrorMessage.class, messageClassMap.get(new TypeToClassKey(version, 1)));
@@ -92,12 +91,19 @@ public class TypeToClassMapInitializerTest {
         assertEquals("Wrong class", GetQueueConfigOutput.class, messageClassMap.get(new TypeToClassKey(version, 23)));
         assertEquals("Wrong class", RoleRequestOutput.class, messageClassMap.get(new TypeToClassKey(version, 25)));
         assertEquals("Wrong class", GetAsyncOutput.class, messageClassMap.get(new TypeToClassKey(version, 27)));
+
+        version = EncodeConstants.OF14_VERSION_ID;
+        assertEquals("Wrong class", HelloMessage.class, messageClassMap.get(new TypeToClassKey(version, 0)));
+
+        version = EncodeConstants.OF15_VERSION_ID;
+        assertEquals("Wrong class", HelloMessage.class, messageClassMap.get(new TypeToClassKey(version, 0)));
     }
 
     @Test
     public void testAdditionalTypes() {
         messageClassMap = new HashMap<>();
         TypeToClassMapInitializer.initializeAdditionalTypeToClassMap(messageClassMap);
+
         short version = EncodeConstants.OF10_VERSION_ID;
         assertEquals("Wrong class", GetFeaturesInput.class, messageClassMap.get(new TypeToClassKey(version, 5)));
         assertEquals("Wrong class", GetConfigInput.class, messageClassMap.get(new TypeToClassKey(version, 7)));
index 7dab76e20f82af392448a9a234ad5f7cb3b8a8e9..d4ec69d4460fe675387a0ddf724197129451f5be 100644 (file)
@@ -9,46 +9,54 @@
 package org.opendaylight.openflowjava.protocol.impl.deserialization.factories;
 
 import io.netty.buffer.ByteBuf;
-
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
-
 import org.junit.Assert;
-import org.junit.Before;
 import org.junit.Test;
-import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistry;
-import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
 import org.opendaylight.openflowjava.protocol.api.keys.MessageCodeKey;
-import org.opendaylight.openflowjava.protocol.impl.deserialization.DeserializerRegistryImpl;
-import org.opendaylight.openflowjava.protocol.impl.util.BufferHelper;
 import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.openflowjava.protocol.impl.util.BufferHelper;
+import org.opendaylight.openflowjava.protocol.impl.util.DefaultDeserializerFactoryTest;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.HelloElementType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloMessage;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.hello.Elements;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.hello.ElementsBuilder;
 
 /**
+ * Test for {@link org.opendaylight.openflowjava.protocol.impl.deserialization.factories.HelloMessageFactory}.
  * @author michal.polkorab
  * @author timotej.kubas
  * @author madamjak
  */
-public class HelloMessageFactoryTest {
+public class HelloMessageFactoryTest extends DefaultDeserializerFactoryTest<HelloMessage> {
 
-    private OFDeserializer<HelloMessage> helloFactory;
+    /**
+     * Initializes deserializer registry and lookups OF13 deserializer.
+     */
+    public HelloMessageFactoryTest() {
+        super(new MessageCodeKey(EncodeConstants.OF13_VERSION_ID, 0, HelloMessage.class));
+    }
 
     /**
-     * Initializes deserializer registry and lookups correct deserializer
+     * Testing {@link HelloMessageFactory} for correct header version.
      */
-    @Before
-    public void startUp() {
-        DeserializerRegistry registry = new DeserializerRegistryImpl();
-        registry.init();
-        helloFactory = registry.getDeserializer(
-                new MessageCodeKey(EncodeConstants.OF13_VERSION_ID, 0, HelloMessage.class));
+    @Test
+    public void testVersion() {
+        List<Byte> versions = new ArrayList<>(Arrays.asList(
+                EncodeConstants.OF13_VERSION_ID,
+                EncodeConstants.OF14_VERSION_ID,
+                EncodeConstants.OF15_VERSION_ID
+        ));
+        ByteBuf bb = BufferHelper.buildBuffer("00 01 " // type
+                                            + "00 08 " // length
+                                            + "00 00 00 11" // bitmap 1
+        );
+        testHeaderVersions(versions, bb);
     }
 
     /**
-     * Testing {@link HelloMessageFactory} for correct length without padding
+     * Testing {@link HelloMessageFactory} for correct length without padding.
      */
     @Test
     public void testWithoutPadding() {
@@ -56,15 +64,14 @@ public class HelloMessageFactoryTest {
                                             + "00 08 " // length
                                             + "00 00 00 11" // bitmap 1
                                             );
-        HelloMessage builtByFactory = BufferHelper.deserialize(helloFactory, bb);
-        BufferHelper.checkHeaderV13(builtByFactory);
+        HelloMessage builtByFactory = BufferHelper.deserialize(factory, bb);
         List<Elements> element = createElement(4,HelloElementType.VERSIONBITMAP.getIntValue());
         Assert.assertEquals("Wrong type", element.get(0).getType(), builtByFactory.getElements().get(0).getType());
         Assert.assertEquals("Wrong versionBitmap", element.get(0).getVersionBitmap(), builtByFactory.getElements().get(0).getVersionBitmap());
     }
 
     /**
-     * Testing {@link HelloMessageFactory} for correct length with padding
+     * Testing {@link HelloMessageFactory} for correct length with padding.
      */
     @Test
     public void testWithPadding() {
@@ -74,15 +81,14 @@ public class HelloMessageFactoryTest {
                                             + "00 00 00 00 " // bitmap 2
                                             + "00 00 00 00"  // padding
                                             );
-        HelloMessage builtByFactory = BufferHelper.deserialize(helloFactory, bb);
-        BufferHelper.checkHeaderV13(builtByFactory);
+        HelloMessage builtByFactory = BufferHelper.deserialize(factory, bb);
         List<Elements> element = createElement(8,HelloElementType.VERSIONBITMAP.getIntValue());
         Assert.assertEquals("Wrong type", element.get(0).getType(), builtByFactory.getElements().get(0).getType());
         Assert.assertEquals("Wrong versionBitmap", element.get(0).getVersionBitmap(), builtByFactory.getElements().get(0).getVersionBitmap());
     }
 
     /**
-     * Testing {@link HelloMessageFactory} if incorrect version is set
+     * Testing {@link HelloMessageFactory} if incorrect version is set.
      */
     @Test
     public void testBadType(){
@@ -92,8 +98,7 @@ public class HelloMessageFactoryTest {
                                             + "00 00 00 00 " // bitmap 2
                                             + "00 00 00 00"  // padding
                                             );
-        HelloMessage builtByFactory = BufferHelper.deserialize(helloFactory, bb);
-        BufferHelper.checkHeaderV13(builtByFactory);
+        HelloMessage builtByFactory = BufferHelper.deserialize(factory, bb);
         Assert.assertEquals("Wrong - no element has been expected", 0, builtByFactory.getElements().size());
     }
 
index dcdbec18f86051706a456de058bd3373d9fde549..29d0da2f94707468a1b5246a3c1d0b415bcb83d5 100644 (file)
@@ -19,6 +19,7 @@ import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
 import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
 import org.opendaylight.openflowjava.util.ByteBufUtils;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 
 /**
@@ -107,7 +108,12 @@ public abstract class BufferHelper {
         checkHeader(ofHeader, (short) EncodeConstants.OF10_VERSION_ID);
     }
 
-    private static void checkHeader(OfHeader ofHeader, Short version) {
+    /**
+     * Check version and xid of OFP header.
+     * @param ofHeader OpenFlow protocol header
+     * @param version OpenFlow protocol version
+     */
+    public static void checkHeader(OfHeader ofHeader, Short version) {
         Assert.assertEquals("Wrong version", version, ofHeader.getVersion());
         Assert.assertEquals("Wrong Xid", DEFAULT_XID, ofHeader.getXid());
     }
@@ -134,7 +140,7 @@ public abstract class BufferHelper {
      * @param bb data input buffer
      * @return message decoded pojo
      */
-    public static <E extends DataObject> E deserialize(OFDeserializer<E> decoder, ByteBuf bb) {
+    public static <E extends DataContainer> E deserialize(OFDeserializer<E> decoder, ByteBuf bb) {
         return decoder.deserialize(bb);
     }
 
diff --git a/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/util/DefaultDeserializerFactoryTest.java b/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/util/DefaultDeserializerFactoryTest.java
new file mode 100644 (file)
index 0000000..2d424cd
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 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.util;
+
+import io.netty.buffer.ByteBuf;
+import java.util.List;
+import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistry;
+import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
+import org.opendaylight.openflowjava.protocol.api.keys.MessageCodeKey;
+import org.opendaylight.openflowjava.protocol.impl.deserialization.DeserializerRegistryImpl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+
+/**
+ * Super class for common stuff of deserialization factories tests.
+ */
+public abstract class DefaultDeserializerFactoryTest<T extends DataContainer> {
+
+    private DeserializerRegistry registry;
+    protected OFDeserializer<T> factory;
+    private MessageCodeKey messageCodeKey;
+
+    public DefaultDeserializerFactoryTest(final MessageCodeKey key) {
+        this.registry = new DeserializerRegistryImpl();
+        this.registry.init();
+        this.messageCodeKey = key;
+        this.factory = registry.getDeserializer(key);
+    }
+
+    /**
+     * Test correct version after deserialization for all supported OF versions.
+     * @param versions supported OF versions
+     * @param buffer byte buffer to deserialze
+     */
+    protected void testHeaderVersions(final List<Byte> versions, final ByteBuf buffer) {
+        for (short version : versions) {
+            ByteBuf bb = buffer.copy();
+            OFDeserializer<T> factory = registry.getDeserializer(
+                    new MessageCodeKey(version, messageCodeKey.getMsgType(), messageCodeKey.getClazz()));
+            T builtByFactory = BufferHelper.deserialize(factory, bb);
+            BufferHelper.checkHeader((OfHeader) builtByFactory, version);
+        }
+    }
+}