Add ActionDeserializerInjector 37/49737/21
authorTomas Slusny <tomas.slusny@pantheon.tech>
Thu, 22 Dec 2016 12:35:26 +0000 (13:35 +0100)
committerTomas Slusny <tomas.slusny@pantheon.tech>
Wed, 15 Feb 2017 15:13:41 +0000 (16:13 +0100)
Add injector where all action deserializers will be registered and call it
from general DeserializerInjector.
Add AbstractActionDeserializer that will define structure for all action
deserializers.
Add ActionUtil#readAction that will try to deserialize action or use
extensions.
Add MessageCodeExperimenterKey for registering action deserializers with
experimenters.

See also: bug 7140

Change-Id: I1a1eaec5c9aa128f2c2d5e2a31b37086f2a56734
Signed-off-by: Tomas Slusny <tomas.slusny@pantheon.tech>
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/protocol/deserialization/MessageCodeExperimenterKey.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/ActionDeserializerInjector.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/DeserializerInjector.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/action/AbstractActionDeserializer.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/util/ActionUtil.java [new file with mode: 0644]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/action/AbstractActionDeserializerTest.java [new file with mode: 0644]

diff --git a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/protocol/deserialization/MessageCodeExperimenterKey.java b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/protocol/deserialization/MessageCodeExperimenterKey.java
new file mode 100644 (file)
index 0000000..f1b4ad5
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * 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.openflowplugin.api.openflow.protocol.deserialization;
+
+import java.util.Objects;
+
+import org.opendaylight.openflowjava.protocol.api.keys.ExperimenterDeserializerKey;
+import org.opendaylight.openflowjava.protocol.api.keys.MessageCodeKey;
+
+public class MessageCodeExperimenterKey extends MessageCodeKey implements ExperimenterDeserializerKey {
+
+    private Long experimenterId;
+
+    /**
+     * Constructor
+     * @param version wire protocol version
+     * @param value used as distinguisher (read from binary data / buffer)
+     * @param clazz class of object that is going to be deserialized
+     * @param experimenterId experimenter id
+     */
+    public MessageCodeExperimenterKey(short version, int value, Class<?> clazz, Long experimenterId) {
+        super(version, value, clazz);
+        this.experimenterId = experimenterId;
+    }
+
+    public Long getExperimenterId() {
+        return experimenterId;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        return prime * super.hashCode() + (Objects.isNull(experimenterId) ? 0 : experimenterId.intValue());
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (!(obj instanceof MessageCodeExperimenterKey)) {
+            return false;
+        }
+        MessageCodeExperimenterKey other = (MessageCodeExperimenterKey) obj;
+
+        if (experimenterId == null) {
+            if (other.experimenterId != null) {
+                return false;
+            }
+        } else if (!experimenterId.equals(other.experimenterId)) {
+            return false;
+        }
+
+        return super.equals(obj);
+    }
+
+    @Override
+    public String toString() {
+        return super.toString() + " experimenterId: " + experimenterId;
+    }
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/ActionDeserializerInjector.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/ActionDeserializerInjector.java
new file mode 100644 (file)
index 0000000..133404f
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * 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.openflowplugin.impl.protocol.deserialization;
+
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerExtensionProvider;
+import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.openflowplugin.api.openflow.protocol.deserialization.MessageCodeExperimenterKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action;
+
+import com.google.common.annotations.VisibleForTesting;
+
+public class ActionDeserializerInjector {
+
+    /**
+     * Injects action deserializers into provided {@link org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerExtensionProvider}
+     * @param provider OpenflowJava deserializer extension provider
+     */
+    static void injectDeserializers(final DeserializerExtensionProvider provider) {
+        // Inject new message deserializers here using injector created by createInjector method
+        final Function<Byte, Consumer<OFDeserializer<Action>>> injector =
+                createInjector(provider, EncodeConstants.OF13_VERSION_ID);
+    }
+
+    /**
+     * Create injector that will inject new deserializers into #{@link org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerExtensionProvider}
+     * @param provider OpenflowJava deserializer extension provider
+     * @param version Openflow version
+     * @return injector
+     */
+    @VisibleForTesting
+    static Function<Byte, Consumer<OFDeserializer<Action>>> createInjector(
+            final DeserializerExtensionProvider provider,
+            final short version) {
+        return code -> deserializer -> {
+            provider.registerDeserializer(
+                    new MessageCodeExperimenterKey(version, code, Action.class, null),
+                    deserializer);
+        };
+    }
+
+}
index 41ea422156af47bfb5c4b9378ac23010c12f1c05..ca7692fb560157bb063201f2855c0a0969da4f74 100644 (file)
@@ -22,6 +22,7 @@ public class DeserializerInjector {
     public static void injectDeserializers(final DeserializerExtensionProvider provider) {
         // Inject new deserializers here
         MatchDeserializerInjector.injectDeserializers(provider);
+        ActionDeserializerInjector.injectDeserializers(provider);
         MessageDeserializerInjector.injectDeserializers(provider);
     }
 }
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/action/AbstractActionDeserializer.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/action/AbstractActionDeserializer.java
new file mode 100644 (file)
index 0000000..364be3d
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * 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.openflowplugin.impl.protocol.deserialization.action;
+
+import org.opendaylight.openflowjava.protocol.api.extensibility.HeaderDeserializer;
+import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action;
+
+import io.netty.buffer.ByteBuf;
+
+public abstract class AbstractActionDeserializer implements OFDeserializer<Action>, HeaderDeserializer<Action> {
+
+    /**
+     * Skip first few bytes of action message because they are irrelevant
+     * @param message Openflow buffered message
+     **/
+    protected static void processHeader(ByteBuf message) {
+        message.skipBytes(2 * EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/util/ActionUtil.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/util/ActionUtil.java
new file mode 100644 (file)
index 0000000..ae24d8b
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * 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.openflowplugin.impl.protocol.deserialization.util;
+
+import java.util.Objects;
+
+import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistry;
+import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
+import org.opendaylight.openflowjava.protocol.api.keys.ActionDeserializerKey;
+import org.opendaylight.openflowjava.protocol.api.keys.ExperimenterActionDeserializerKey;
+import org.opendaylight.openflowjava.protocol.api.keys.MessageCodeKey;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
+import org.opendaylight.openflowplugin.api.openflow.protocol.deserialization.MessageCodeExperimenterKey;
+import org.opendaylight.openflowplugin.extension.api.path.ActionPath;
+import org.opendaylight.openflowplugin.openflow.md.core.extension.ActionExtensionHelper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action;
+
+import io.netty.buffer.ByteBuf;
+
+/**
+ * Utility class for action deserialization
+ */
+public class ActionUtil {
+
+    /**
+     * Deserialize OpenFlow action, using extension converter if available
+     * TODO: Remove also extension converters
+     *
+     * @param version OpenFlow version
+     * @param message OpenFlow buffered message
+     * @param registry deserializer registry
+     * @param path Action path
+     */
+    public static Action readAction(short version, ByteBuf message, DeserializerRegistry registry,
+            ActionPath path) {
+        int type = message.getUnsignedShort(message.readerIndex());
+        Long expId = null;
+
+        if (type == EncodeConstants.EXPERIMENTER_VALUE) {
+            expId = message.getUnsignedInt(message.readerIndex()
+                    + 2 * EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
+        }
+
+        try {
+            final MessageCodeExperimenterKey key = new MessageCodeExperimenterKey(
+                version, type, Action.class, expId);
+
+            final OFDeserializer<Action> deserializer = registry.getDeserializer(key);
+
+            return deserializer.deserialize(message);
+        } catch (IllegalStateException e) {
+            final MessageCodeKey key = Objects.nonNull(expId)
+                ? new ExperimenterActionDeserializerKey(version, expId)
+                : new ActionDeserializerKey(version, type, expId);
+
+            final OFDeserializer<org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203
+                .actions.grouping.Action> deserializer = registry.getDeserializer(key);
+
+            return ActionExtensionHelper.processAlienAction(deserializer.deserialize(message),
+                    OpenflowVersion.get(version), path);
+        }
+    }
+
+}
diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/action/AbstractActionDeserializerTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/action/AbstractActionDeserializerTest.java
new file mode 100644 (file)
index 0000000..216fd04
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * 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.openflowplugin.impl.protocol.deserialization.action;
+
+import io.netty.buffer.ByteBuf;
+
+import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.openflowplugin.api.openflow.protocol.deserialization.MessageCodeExperimenterKey;
+import org.opendaylight.openflowplugin.impl.protocol.deserialization.AbstractDeserializerTest;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action;
+
+public abstract class AbstractActionDeserializerTest extends AbstractDeserializerTest {
+
+    private OFDeserializer<Action> deserializer;
+
+    @Override
+    protected void init() {
+        deserializer = getRegistry().getDeserializer(
+                new MessageCodeExperimenterKey(EncodeConstants.OF13_VERSION_ID, getType(), Action.class, null));
+    }
+
+    protected void writeHeader(ByteBuf message) {
+        message.writeShort(getType());
+        message.writeShort(getLength());
+    }
+
+    protected Action deserializeAction(ByteBuf message) {
+        return deserializer.deserialize(message);
+    }
+
+    protected abstract short getType();
+    protected abstract short getLength();
+
+}