Add MatchDeserializerInjector 02/49302/15
authorTomas Slusny <tomas.slusny@pantheon.tech>
Tue, 13 Dec 2016 10:00:48 +0000 (11:00 +0100)
committerTomas Slusny <tomas.slusny@pantheon.tech>
Wed, 15 Feb 2017 15:13:41 +0000 (16:13 +0100)
Add injector where all match and match entry deserializers will be
registered and call it from general DeserializerInjector.
Add MatchEntryDeserializer and MatchDeserializer to be able to actually
create match entry deserializers and deserialize match body.
Add new method to MatchExtensionHelper that can inject extension
augmentations one by one.

See also: bug 7140

Change-Id: Id15419539792cb4a21a5862be2dd423be34ab117
Signed-off-by: Tomas Slusny <tomas.slusny@pantheon.tech>
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/protocol/deserialization/MatchEntryDeserializer.java [new file with mode: 0644]
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/protocol/deserialization/MatchEntryDeserializerRegistry.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/MatchDeserializerInjector.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/key/MessageCodeMatchKey.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/match/AbstractMatchEntryDeserializer.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/match/MatchDeserializer.java [new file with mode: 0644]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/match/AbstractMatchEntryDeserializerTest.java [new file with mode: 0644]
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/extension/MatchExtensionHelper.java

diff --git a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/protocol/deserialization/MatchEntryDeserializer.java b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/protocol/deserialization/MatchEntryDeserializer.java
new file mode 100644 (file)
index 0000000..2d25279
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * 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 io.netty.buffer.ByteBuf;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+
+public interface MatchEntryDeserializer {
+
+    /**
+     * Transforms byte match entry message into POJO/DTO (of type E).
+     *
+     * @param message message as bytes in ByteBuf
+     * @param builder match builder
+     */
+    void deserializeEntry(ByteBuf message, MatchBuilder builder);
+
+}
diff --git a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/protocol/deserialization/MatchEntryDeserializerRegistry.java b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/protocol/deserialization/MatchEntryDeserializerRegistry.java
new file mode 100644 (file)
index 0000000..9dbddfb
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * 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 org.opendaylight.openflowjava.protocol.api.keys.MatchEntryDeserializerKey;
+
+public interface MatchEntryDeserializerRegistry {
+
+    /**
+     * Registers match entry deserializer.
+     *
+     * @param key          used for deserializer lookup
+     * @param deserializer deserializer instance
+     */
+    void registerEntryDeserializer(MatchEntryDeserializerKey key, MatchEntryDeserializer deserializer);
+
+    /**
+     * Unregisters match entry deserializer
+     *
+     * @param key used for deserializer lookup
+     * @return true if deserializer was removed, false if no deserializer was found under specified key
+     */
+    boolean unregisterEntryDeserializer(MatchEntryDeserializerKey key);
+
+}
index 9ec85acb6f1bb422e08b51fb8b70b7669afb748b..41ea422156af47bfb5c4b9378ac23010c12f1c05 100644 (file)
@@ -21,6 +21,7 @@ public class DeserializerInjector {
      */
     public static void injectDeserializers(final DeserializerExtensionProvider provider) {
         // Inject new deserializers here
+        MatchDeserializerInjector.injectDeserializers(provider);
         MessageDeserializerInjector.injectDeserializers(provider);
     }
 }
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/MatchDeserializerInjector.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/MatchDeserializerInjector.java
new file mode 100644 (file)
index 0000000..0c40d09
--- /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.impl.protocol.deserialization;
+
+import com.google.common.annotations.VisibleForTesting;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerExtensionProvider;
+import org.opendaylight.openflowjava.protocol.api.keys.MatchEntryDeserializerKey;
+import org.opendaylight.openflowjava.protocol.api.keys.MessageCodeKey;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.openflowplugin.impl.protocol.deserialization.key.MessageCodeMatchKey;
+import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.MatchDeserializer;
+import org.opendaylight.openflowplugin.api.openflow.protocol.deserialization.MatchEntryDeserializer;
+import org.opendaylight.openflowplugin.api.openflow.protocol.deserialization.MatchEntryDeserializerRegistry;
+import org.opendaylight.openflowplugin.extension.api.path.MatchPath;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.Match;
+
+/**
+ * Util class for injecting new match entry deserializers into OpenflowJava
+ */
+public class MatchDeserializerInjector {
+
+    /**
+     * Injects deserializers into provided {@link org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerExtensionProvider}
+     * @param provider OpenflowJava deserializer extension provider
+     */
+    public static void injectDeserializers(final DeserializerExtensionProvider provider) {
+        for (MatchPath path : MatchPath.values()) {
+            final MatchDeserializer deserializer = new MatchDeserializer(path);
+            provider.registerDeserializer(
+                    new MessageCodeMatchKey(
+                        EncodeConstants.OF13_VERSION_ID,
+                        EncodeConstants.EMPTY_LENGTH,
+                        Match.class,
+                        path),
+                    deserializer);
+
+            // Inject new match entry serializers here using injector created by createInjector method
+            final Function<Integer, Function<Long, Function<Integer, Consumer<MatchEntryDeserializer>>>> injector =
+                createInjector(deserializer, EncodeConstants.OF13_VERSION_ID);
+        }
+    }
+
+    /**
+     * Create injector that will inject new serializers into {@link org.opendaylight.openflowplugin.api.openflow.protocol.deserialization.MatchEntryDeserializerRegistry}
+     * @param registry Match entry deserializer registry
+     * @param version Openflow version
+     * @return injector
+     */
+    @VisibleForTesting
+    static Function<Integer, Function<Long, Function<Integer, Consumer<MatchEntryDeserializer>>>> createInjector(
+            final MatchEntryDeserializerRegistry registry,
+            final short version
+            ) {
+        return oxmClass -> expId -> oxmField -> deserializer -> {
+            final MatchEntryDeserializerKey key = new MatchEntryDeserializerKey(version, oxmClass, oxmField);
+            key.setExperimenterId(expId);
+            registry.registerEntryDeserializer(key, deserializer);
+        };
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/key/MessageCodeMatchKey.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/key/MessageCodeMatchKey.java
new file mode 100644 (file)
index 0000000..5df9e4b
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2017 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.key;
+
+import java.util.Objects;
+
+import org.opendaylight.openflowjava.protocol.api.keys.MessageCodeKey;
+import org.opendaylight.openflowplugin.extension.api.path.MatchPath;
+
+public class MessageCodeMatchKey extends MessageCodeKey {
+
+    private MatchPath matchPath;
+
+    /**
+     * 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 matchPath match extension path
+     */
+    public MessageCodeMatchKey(short version, int value, Class<?> clazz, MatchPath matchPath) {
+        super(version, value, clazz);
+        this.matchPath = matchPath;
+    }
+
+    public MatchPath getMatchPath() {
+        return this.matchPath;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        return prime * super.hashCode() + (Objects.isNull(matchPath) ? 0 : matchPath.ordinal());
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (!(obj instanceof MessageCodeMatchKey)) {
+            return false;
+        }
+        MessageCodeMatchKey other = (MessageCodeMatchKey) obj;
+        if (matchPath == null) {
+            if (other.matchPath != null) {
+                return false;
+            }
+        } else if (!matchPath.equals(other.matchPath)) {
+            return false;
+        }
+        return super.equals(obj);
+    }
+
+    @Override
+    public String toString() {
+        return super.toString() + " matchPath: " + matchPath.name();
+    }
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/match/AbstractMatchEntryDeserializer.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/match/AbstractMatchEntryDeserializer.java
new file mode 100644 (file)
index 0000000..6230cba
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * 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.match;
+
+import io.netty.buffer.ByteBuf;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.openflowjava.protocol.impl.deserialization.match.OxmDeserializerHelper;
+import org.opendaylight.openflowjava.util.ByteBufUtils;
+import org.opendaylight.openflowplugin.api.openflow.protocol.deserialization.MatchEntryDeserializer;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.IpConversionUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+
+public abstract class AbstractMatchEntryDeserializer implements MatchEntryDeserializer {
+
+    /**
+     * Processes match entry header and returns if it have mask, or not
+     * @param in input buffer
+     * @return true if match entry has mask, false otherwise
+     */
+    protected static boolean processHeader(ByteBuf in) {
+        in.skipBytes(EncodeConstants.SIZE_OF_SHORT_IN_BYTES); // skip oxm_class
+        boolean hasMask = (in.readUnsignedByte() & 1) != 0;
+        in.skipBytes(EncodeConstants.SIZE_OF_BYTE_IN_BYTES); // skip match entry length
+        return hasMask;
+    }
+
+    /**
+     * Read Ipv4Prefix from message
+     * @param message buffered message
+     * @param hasMask determines if prefix has mask or not
+     * @return IPv4 prefix
+     */
+    protected static Ipv4Prefix readPrefix(ByteBuf message, boolean hasMask) {
+        final Ipv4Address address = ByteBufUtils.readIetfIpv4Address(message);
+        int mask = 32;
+
+        if (hasMask) {
+            mask = IpConversionUtil.countBits(
+                    OxmDeserializerHelper.convertMask(message, EncodeConstants.GROUPS_IN_IPV4_ADDRESS));
+        }
+
+        return IpConversionUtil.createPrefix(address, mask);
+    }
+
+    /**
+     * Throw error on malformed match builder input
+     * @param builder match builder
+     * @param propertyName name of property that already containsData
+     */
+    protected static void throwErrorOnMalformed(MatchBuilder builder, String propertyName) {
+        throw new IllegalArgumentException("Match: " + builder.toString() + " is malformed, "
+                + builder + "#" + propertyName + " contains invalid data.");
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/match/MatchDeserializer.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/match/MatchDeserializer.java
new file mode 100644 (file)
index 0000000..9d8d113
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * 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.match;
+
+import io.netty.buffer.ByteBuf;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistry;
+import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistryInjector;
+import org.opendaylight.openflowjava.protocol.api.extensibility.HeaderDeserializer;
+import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
+import org.opendaylight.openflowjava.protocol.api.keys.MatchEntryDeserializerKey;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.openflowplugin.api.openflow.protocol.deserialization.MatchEntryDeserializer;
+import org.opendaylight.openflowplugin.api.openflow.protocol.deserialization.MatchEntryDeserializerRegistry;
+import org.opendaylight.openflowplugin.extension.api.path.MatchPath;
+import org.opendaylight.openflowplugin.openflow.md.core.extension.MatchExtensionHelper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MatchDeserializer implements OFDeserializer<Match>, HeaderDeserializer<Match>,
+        MatchEntryDeserializerRegistry, MatchEntryDeserializer, DeserializerRegistryInjector {
+
+    private static final Logger LOG = LoggerFactory.getLogger(MatchDeserializer.class);
+    private final Map<MatchEntryDeserializerKey, MatchEntryDeserializer> entryRegistry = new HashMap<>();
+    private final MatchPath matchPath;
+    private DeserializerRegistry registry;
+
+    public MatchDeserializer(final MatchPath matchPath) {
+        this.matchPath = matchPath;
+    }
+
+    @Override
+    public Match deserialize(ByteBuf inBuffer) {
+        if (inBuffer.readableBytes() <= 0) return null;
+
+        final MatchBuilder builder = new MatchBuilder();
+
+        // OFP do not have any method to differentiate between OXM and standard match, so we do not care about type
+        final int type = inBuffer.readUnsignedShort();
+        final int length = inBuffer.readUnsignedShort();
+
+        final int startIndex = inBuffer.readerIndex();
+        final int entriesLength = length - 2 * EncodeConstants.SIZE_OF_SHORT_IN_BYTES;
+
+        while ((inBuffer.readerIndex() - startIndex) < entriesLength) {
+            deserializeEntry(inBuffer, builder);
+        }
+
+        int paddingRemainder = length % EncodeConstants.PADDING;
+
+        if (paddingRemainder != 0) {
+            inBuffer.skipBytes(EncodeConstants.PADDING - paddingRemainder);
+        }
+
+        return builder.build();
+    }
+
+    @Override
+    public Match deserializeHeader(ByteBuf inBuffer) {
+        final MatchBuilder builder = new MatchBuilder();
+        deserializeEntry(inBuffer, builder);
+        return builder.build();
+    }
+
+    @Override
+    public void deserializeEntry(ByteBuf inBuffer, MatchBuilder builder) {
+        if (inBuffer.readableBytes() <= 0) return;
+        int oxmClass = inBuffer.getUnsignedShort(inBuffer.readerIndex());
+        int oxmField = inBuffer.getUnsignedByte(inBuffer.readerIndex()
+                + EncodeConstants.SIZE_OF_SHORT_IN_BYTES) >>> 1;
+
+        final MatchEntryDeserializerKey key = new MatchEntryDeserializerKey(
+                EncodeConstants.OF13_VERSION_ID,oxmClass, oxmField);
+
+        if (oxmClass == EncodeConstants.EXPERIMENTER_VALUE) {
+            long expId = inBuffer.getUnsignedInt(inBuffer.readerIndex()
+                    + EncodeConstants.SIZE_OF_SHORT_IN_BYTES
+                    + 2 * EncodeConstants.SIZE_OF_BYTE_IN_BYTES);
+
+            key.setExperimenterId(expId);
+        }
+
+        final MatchEntryDeserializer entryDeserializer = entryRegistry.get(key);
+
+        if (Objects.nonNull(entryDeserializer)) {
+            entryDeserializer.deserializeEntry(inBuffer, builder);
+        } else {
+            final OFDeserializer<MatchEntry> deserializer = registry.getDeserializer(key);
+            MatchExtensionHelper.injectExtension(EncodeConstants.OF13_VERSION_ID,
+                    deserializer.deserialize(inBuffer), builder, matchPath);
+        }
+    }
+
+    @Override
+    public void registerEntryDeserializer(MatchEntryDeserializerKey key, MatchEntryDeserializer deserializer) {
+        if (Objects.isNull(key) || Objects.isNull(deserializer)) {
+            throw new IllegalArgumentException("MatchEntryDeserializerKey or Deserializer is null");
+        }
+
+        final MatchEntryDeserializer desInRegistry = entryRegistry.put(key, deserializer);
+
+        if (desInRegistry != null) {
+            LOG.debug("Deserializer for key {} overwritten. Old deserializer: {}, new deserializer: {}", key,
+                    desInRegistry.getClass().getName(), deserializer.getClass().getName());
+        }
+    }
+
+    @Override
+    public boolean unregisterEntryDeserializer(MatchEntryDeserializerKey key) {
+        if (Objects.isNull(key)) {
+            throw new IllegalArgumentException("MatchEntryDeserializerKey is null");
+        }
+
+        return Objects.nonNull(entryRegistry.remove(key));
+    }
+
+    @Override
+    public void injectDeserializerRegistry(DeserializerRegistry deserializerRegistry) {
+        registry = deserializerRegistry;
+    }
+
+}
diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/match/AbstractMatchEntryDeserializerTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/match/AbstractMatchEntryDeserializerTest.java
new file mode 100644 (file)
index 0000000..d09bc6e
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * 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.match;
+
+import io.netty.buffer.ByteBuf;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.openflowplugin.api.openflow.protocol.deserialization.MatchEntryDeserializer;
+import org.opendaylight.openflowplugin.extension.api.path.MatchPath;
+import org.opendaylight.openflowplugin.impl.protocol.deserialization.AbstractDeserializerTest;
+import org.opendaylight.openflowplugin.impl.protocol.deserialization.key.MessageCodeMatchKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.Match;
+
+public abstract class AbstractMatchEntryDeserializerTest extends AbstractDeserializerTest {
+
+    private MatchEntryDeserializer deserializer;
+
+    @Override
+    protected void init() {
+        deserializer = getRegistry().getDeserializer(new MessageCodeMatchKey(EncodeConstants.OF13_VERSION_ID,
+                    EncodeConstants.EMPTY_LENGTH,
+                    Match.class,
+                    MatchPath.FLOWSSTATISTICSUPDATE_FLOWANDSTATISTICSMAPLIST_MATCH));
+    }
+
+    protected Match deserialize(ByteBuf inBuffer) {
+        final MatchBuilder builder = new MatchBuilder();
+        deserializer.deserializeEntry(inBuffer, builder);
+        return builder.build();
+    }
+
+    protected void writeHeader(ByteBuf inBuffer, boolean hasMask) {
+        inBuffer.writeShort(getOxmClassCode());
+
+        int fieldAndMask = getOxmFieldCode() << 1;
+        int length = getValueLength();
+
+        if (hasMask) {
+            fieldAndMask |= 1;
+            length *= 2;
+        }
+
+        inBuffer.writeByte(fieldAndMask);
+        inBuffer.writeByte(length);
+    }
+
+    protected abstract int getOxmClassCode();
+    protected abstract int getOxmFieldCode();
+    protected abstract int getValueLength();
+
+}
index de3879b2dbf6358389be94e27a5c4074a052343c..6574f9d42eb3d3626bd79ff0abdbac113a5570ed 100644 (file)
@@ -10,6 +10,9 @@ package org.opendaylight.openflowplugin.openflow.md.core.extension;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+
 import org.opendaylight.openflowjava.protocol.api.keys.MatchEntrySerializerKey;
 import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
 import org.opendaylight.openflowplugin.extension.api.AugmentTuple;
@@ -17,6 +20,7 @@ import org.opendaylight.openflowplugin.extension.api.ConvertorFromOFJava;
 import org.opendaylight.openflowplugin.extension.api.ExtensionAugment;
 import org.opendaylight.openflowplugin.extension.api.path.MatchPath;
 import org.opendaylight.openflowplugin.openflow.md.core.session.OFSessionUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.MatchField;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.OxmClassBase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntry;
@@ -50,6 +54,72 @@ public final class MatchExtensionHelper {
         throw new IllegalAccessError("singleton enforcement");
     }
 
+
+    /**
+     * @param matchEntry match entry
+     * @param ofVersion openflow version
+     * @param matchPath match path
+     */
+    public static <T> void injectExtension(
+            final short ofVersion,
+            final MatchEntry matchEntry,
+            final T matchBuilder,
+            final MatchPath matchPath) {
+
+        final ExtensionListBuilder extBuilder = processExtension(matchEntry, ofVersion, matchPath);
+
+        if (Objects.isNull(extBuilder)) {
+            LOG.warn("Convertor for {} for version {} with match path {} not found.",
+                    matchEntry.toString(),
+                    ofVersion,
+                    matchPath.name());
+        }
+
+
+        switch (matchPath) {
+            case FLOWSSTATISTICSUPDATE_FLOWANDSTATISTICSMAPLIST_MATCH: {
+                final MatchBuilder augMatchBuilder = MatchBuilder.class.cast(matchBuilder);
+
+                final GeneralAugMatchNotifUpdateFlowStatsBuilder builder = Optional
+                    .ofNullable(augMatchBuilder.getAugmentation(GeneralAugMatchNotifUpdateFlowStats.class))
+                    .map(aug -> new GeneralAugMatchNotifUpdateFlowStatsBuilder(aug))
+                    .orElse(new GeneralAugMatchNotifUpdateFlowStatsBuilder().setExtensionList(new ArrayList<>()));
+
+                builder.getExtensionList().add(extBuilder.build());
+                break;
+            }
+            case PACKETRECEIVED_MATCH: {
+                final org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.packet.received
+                    .MatchBuilder augMatchBuilder = org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.packet.received
+                            .MatchBuilder.class.cast(matchBuilder);
+
+                final GeneralAugMatchNotifPacketInBuilder builder = Optional
+                    .ofNullable(augMatchBuilder.getAugmentation(GeneralAugMatchNotifPacketIn.class))
+                    .map(aug -> new GeneralAugMatchNotifPacketInBuilder(aug))
+                    .orElse(new GeneralAugMatchNotifPacketInBuilder().setExtensionList(new ArrayList<>()));
+
+                builder.getExtensionList().add(extBuilder.build());
+                break;
+            }
+            case SWITCHFLOWREMOVED_MATCH: {
+                final org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.mod.removed
+                    .MatchBuilder augMatchBuilder = org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.mod.removed
+                        .MatchBuilder.class.cast(matchBuilder);
+
+
+                final GeneralAugMatchNotifSwitchFlowRemovedBuilder builder = Optional
+                    .ofNullable(augMatchBuilder.getAugmentation(GeneralAugMatchNotifSwitchFlowRemoved.class))
+                    .map(aug -> new GeneralAugMatchNotifSwitchFlowRemovedBuilder(aug))
+                    .orElse(new GeneralAugMatchNotifSwitchFlowRemovedBuilder().setExtensionList(new ArrayList<>()));
+
+                builder.getExtensionList().add(extBuilder.build());
+                break;
+            }
+            default:
+                LOG.warn("Match path {} not supported.", matchPath.name());
+        }
+    }
+
     /**
      * @param matchEntries match entries
      * @param ofVersion openflow version
@@ -64,7 +134,7 @@ public final class MatchExtensionHelper {
         List<ExtensionList> extensionsList = new ArrayList<>();
 
         for (MatchEntry matchEntry : matchEntries) {
-            ExtensionListBuilder extensionListBld = processExtension(matchEntry, ofVersion, matchPath);
+            ExtensionListBuilder extensionListBld = processExtension(matchEntry, ofVersion.getVersion(), matchPath);
             if (extensionListBld == null) {
                 continue;
             }
@@ -116,12 +186,12 @@ public final class MatchExtensionHelper {
      * @param matchEntry
      * @return
      */
-    private static ExtensionListBuilder processExtension(MatchEntry matchEntry, OpenflowVersion ofVersion, MatchPath matchPath) {
+    private static ExtensionListBuilder processExtension(MatchEntry matchEntry, short ofVersion, MatchPath matchPath) {
         ExtensionListBuilder extListBld = null;
 
         /** TODO: EXTENSION PROPOSAL (match, OFJava to MD-SAL) */
         MatchEntrySerializerKey<? extends OxmClassBase, ? extends MatchField> key = new MatchEntrySerializerKey<>(
-                ofVersion.getVersion(), matchEntry.getOxmClass(), matchEntry.getOxmMatchField());
+                ofVersion, matchEntry.getOxmClass(), matchEntry.getOxmMatchField());
         if (null != OFSessionUtil.getExtensionConvertorProvider()) {
             ConvertorFromOFJava<MatchEntry, MatchPath> convertor = OFSessionUtil.getExtensionConvertorProvider().getConverter(key);
             if (convertor != null) {