--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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);
+ };
+ }
+
+}
public static void injectDeserializers(final DeserializerExtensionProvider provider) {
// Inject new deserializers here
MatchDeserializerInjector.injectDeserializers(provider);
+ ActionDeserializerInjector.injectDeserializers(provider);
MessageDeserializerInjector.injectDeserializers(provider);
}
}
--- /dev/null
+/*
+ * 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);
+ }
+
+}
--- /dev/null
+/*
+ * 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);
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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();
+
+}