Adding learn action - Bug 6445 84/44084/1
authorSlava <slava.radune@hpe.com>
Thu, 28 Jul 2016 12:27:28 +0000 (15:27 +0300)
committerAlon Kochba <alonko@hpe.com>
Tue, 16 Aug 2016 16:25:27 +0000 (19:25 +0300)
Change-Id: Iab58e54230003dc8a5ea48bbc7a4d173c305cf8f
Signed-off-by: Slava <slava.radune@hpe.com>
(cherry picked from commit 122bf80)

extension/openflowjava-extension-nicira/src/main/java/org/opendaylight/openflowjava/nx/NiciraExtensionsRegistrator.java
extension/openflowjava-extension-nicira/src/main/java/org/opendaylight/openflowjava/nx/codec/action/LearnCodec.java [new file with mode: 0644]
extension/openflowjava-extension-nicira/src/main/java/org/opendaylight/openflowjava/nx/codec/action/LearnCodecUtil.java [new file with mode: 0644]
extension/openflowjava-extension-nicira/src/main/java/org/opendaylight/openflowjava/nx/codec/action/NiciraActionCodecs.java
extension/openflowjava-extension-nicira/src/main/yang/nicira-action.yang
extension/openflowjava-extension-nicira/src/test/java/org/opendaylight/openflowjava/nx/codec/action/LearnCodecTest.java [new file with mode: 0644]
extension/openflowjava-extension-nicira/src/test/java/org/opendaylight/openflowjava/nx/codec/action/TestsCodecStub.java [new file with mode: 0644]
extension/openflowplugin-extension-nicira/src/main/java/org/opendaylight/openflowplugin/extension/vendor/nicira/NiciraExtensionProvider.java
extension/openflowplugin-extension-nicira/src/main/java/org/opendaylight/openflowplugin/extension/vendor/nicira/convertor/action/LearnConvertor.java [new file with mode: 0644]
extension/openflowplugin-extension-nicira/src/main/java/org/opendaylight/openflowplugin/extension/vendor/nicira/convertor/action/LearnConvertorUtil.java [new file with mode: 0644]
extension/openflowplugin-extension-nicira/src/main/yang/openflowplugin-extension-nicira-action.yang

index ee74ca551fd1b25b42bb115c0a99047b9fc7606d..36ed7c23e4140acf04c278d323a932ad2d157a64 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.openflowjava.nx;
 
 import org.opendaylight.openflowjava.nx.api.NiciraExtensionCodecRegistrator;
 import org.opendaylight.openflowjava.nx.codec.action.ConntrackCodec;
+import org.opendaylight.openflowjava.nx.codec.action.LearnCodec;
 import org.opendaylight.openflowjava.nx.codec.action.MultipathCodec;
 import org.opendaylight.openflowjava.nx.codec.action.NiciraActionCodecs;
 import org.opendaylight.openflowjava.nx.codec.action.OutputRegCodec;
@@ -88,6 +89,8 @@ public class NiciraExtensionsRegistrator implements AutoCloseable {
 
         registrator.registerActionSerializer(ConntrackCodec.SERIALIZER_KEY, NiciraActionCodecs.CONNTRACK_CODEC);
         registrator.registerActionDeserializer(ConntrackCodec.DESERIALIZER_KEY, NiciraActionCodecs.CONNTRACK_CODEC);
+        registrator.registerActionSerializer(LearnCodec.SERIALIZER_KEY, NiciraActionCodecs.LEARN_CODEC);
+        registrator.registerActionDeserializer(LearnCodec.DESERIALIZER_KEY, NiciraActionCodecs.LEARN_CODEC);
         //Continue
 
 
@@ -185,6 +188,8 @@ public class NiciraExtensionsRegistrator implements AutoCloseable {
         registrator.unregisterActionSerializer(PopNshCodec.SERIALIZER_KEY);
         registrator.unregisterActionSerializer(ConntrackCodec.SERIALIZER_KEY);
         registrator.unregisterActionDeserializer(ConntrackCodec.DESERIALIZER_KEY);
+        registrator.unregisterActionSerializer(LearnCodec.SERIALIZER_KEY);
+        registrator.unregisterActionDeserializer(LearnCodec.DESERIALIZER_KEY);
         //CONTINUE
         registrator.unregisterMatchEntrySerializer(Reg0Codec.SERIALIZER_KEY);
         registrator.unregisterMatchEntryDeserializer(Reg0Codec.DESERIALIZER_KEY);
diff --git a/extension/openflowjava-extension-nicira/src/main/java/org/opendaylight/openflowjava/nx/codec/action/LearnCodec.java b/extension/openflowjava-extension-nicira/src/main/java/org/opendaylight/openflowjava/nx/codec/action/LearnCodec.java
new file mode 100644 (file)
index 0000000..b76bf61
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2016 Hewlett-Packard Enterprise 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.nx.codec.action;
+
+import io.netty.buffer.ByteBuf;
+
+import org.opendaylight.openflowjava.nx.api.NiciraActionDeserializerKey;
+import org.opendaylight.openflowjava.nx.api.NiciraActionSerializerKey;
+import org.opendaylight.openflowjava.nx.api.NiciraConstants;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.actions.grouping.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.actions.grouping.ActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ExperimenterId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionLearn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionLearnBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.learn.grouping.NxActionLearnBuilder;
+
+/**
+ * @author Slava Radune
+ */
+
+public class LearnCodec extends AbstractActionCodec {
+    public static final byte NXAST_LEARN_SUBTYPE = 16;
+    public static final NiciraActionSerializerKey SERIALIZER_KEY =
+            new NiciraActionSerializerKey(EncodeConstants.OF13_VERSION_ID, ActionLearn.class);
+    public static final NiciraActionDeserializerKey DESERIALIZER_KEY =
+            new NiciraActionDeserializerKey(EncodeConstants.OF13_VERSION_ID, NXAST_LEARN_SUBTYPE);
+    private static final int MUL_LENGTH = 8;
+
+    @Override
+    public void serialize(final Action input, final ByteBuf outBuffer) {
+        ActionLearn action = (ActionLearn) input.getActionChoice();
+        int length = LearnCodecUtil.calcLength(action);
+        int lengthMod = length % MUL_LENGTH;
+        if(lengthMod != 0){
+            lengthMod = MUL_LENGTH - lengthMod;
+        }
+        serializeHeader(length+lengthMod, NXAST_LEARN_SUBTYPE, outBuffer);
+
+        LearnCodecUtil.serializeLearnHeader(outBuffer, action);
+        LearnCodecUtil.serializeFlowMods(outBuffer, action);
+
+        //pad with zeros for the length to be multiplication by 8
+        if(lengthMod != 0){
+            outBuffer.writeZero(lengthMod);
+        }
+
+    }
+
+    @Override
+    public Action deserialize(final ByteBuf message) {
+        ActionBuilder actionBuilder = new ActionBuilder();
+        actionBuilder.setExperimenterId(new ExperimenterId(NiciraConstants.NX_VENDOR_ID));
+
+        short length = LearnCodecUtil.deserializeHeader(message);
+        ActionLearnBuilder actionLearnBuilder = new ActionLearnBuilder();
+
+        NxActionLearnBuilder nxActionLearnBuilder = new NxActionLearnBuilder();
+        LearnCodecUtil.deserializeLearnHeader(message, nxActionLearnBuilder);
+
+        length -= LearnCodecUtil.HEADER_LENGTH;
+
+        LearnCodecUtil.buildFlowModSpecs(nxActionLearnBuilder, message, length);
+
+        actionLearnBuilder.setNxActionLearn(nxActionLearnBuilder.build());
+
+        actionBuilder.setActionChoice(actionLearnBuilder.build());
+
+        return actionBuilder.build();
+    }
+
+}
diff --git a/extension/openflowjava-extension-nicira/src/main/java/org/opendaylight/openflowjava/nx/codec/action/LearnCodecUtil.java b/extension/openflowjava-extension-nicira/src/main/java/org/opendaylight/openflowjava/nx/codec/action/LearnCodecUtil.java
new file mode 100644 (file)
index 0000000..0a08c89
--- /dev/null
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2016 Hewlett-Packard Enterprise 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.nx.codec.action;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
+import io.netty.buffer.ByteBuf;
+
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionLearn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromFieldCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromFieldCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromValueCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromValueCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModCopyFieldIntoFieldCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModCopyFieldIntoFieldCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModCopyValueIntoFieldCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModCopyValueIntoFieldCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModOutputToPortCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModOutputToPortCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.add.match.from.field._case.FlowModAddMatchFromField;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.add.match.from.field._case.FlowModAddMatchFromFieldBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.add.match.from.value._case.FlowModAddMatchFromValue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.add.match.from.value._case.FlowModAddMatchFromValueBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.copy.field.into.field._case.FlowModCopyFieldIntoField;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.copy.field.into.field._case.FlowModCopyFieldIntoFieldBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.copy.value.into.field._case.FlowModCopyValueIntoField;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.copy.value.into.field._case.FlowModCopyValueIntoFieldBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.output.to.port._case.FlowModOutputToPort;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.output.to.port._case.FlowModOutputToPortBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.learn.grouping.NxActionLearnBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.learn.grouping.nx.action.learn.FlowMods;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.learn.grouping.nx.action.learn.FlowModsBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class LearnCodecUtil {
+
+    private static final Logger logger = LoggerFactory.getLogger(LearnCodecUtil.class);
+    public static final int HEADER_LENGTH = 32;
+    private static final short SRC_MASK = 0x2000;
+    private static final short DST_MASK = 0x1800;
+    private static final short NUM_BITS_MASK = 0x07FF;
+    private static final int SRC_POS = 13;
+    private static final int DST_POS = 11;
+    private static final int FROM_FIELD_LENGTH = 14;
+    private static final int FROM_VALUE_LENGTH = 10;
+    private static final int TO_PORT_LENGTH = 8;
+    private static final int EMPTY_FLOW_MOD_LENGTH = 2;
+    private static short length;
+
+
+    static short deserializeHeader(ByteBuf message) {
+        // size of experimenter type
+        message.skipBytes(EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
+        // size of length
+        short length = message.readShort();
+        // vendor id
+        message.skipBytes(EncodeConstants.SIZE_OF_INT_IN_BYTES);
+        // subtype
+        message.skipBytes(EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
+        return length;
+    }
+
+    /*
+     *                                 SERIALIZATION
+    */
+
+    static void serializeLearnHeader(final ByteBuf outBuffer, ActionLearn action) {
+        outBuffer.writeShort(action.getNxActionLearn().getIdleTimeout().shortValue());
+        outBuffer.writeShort(action.getNxActionLearn().getHardTimeout().shortValue());
+        outBuffer.writeShort(action.getNxActionLearn().getPriority().shortValue());
+        outBuffer.writeLong(action.getNxActionLearn().getCookie().longValue());
+        outBuffer.writeShort(action.getNxActionLearn().getFlags().shortValue());
+        outBuffer.writeByte(action.getNxActionLearn().getTableId().byteValue());
+        outBuffer.writeZero(1);
+        outBuffer.writeShort(action.getNxActionLearn().getFinIdleTimeout().shortValue());
+        outBuffer.writeShort(action.getNxActionLearn().getFinHardTimeout().shortValue());
+    }
+
+    static void serializeFlowMods(final ByteBuf outBuffer, ActionLearn action) {
+        if(action.getNxActionLearn().getFlowMods() != null){
+            for(FlowMods flowMod : action.getNxActionLearn().getFlowMods()){
+                if(flowMod.getFlowModSpec() instanceof FlowModAddMatchFromFieldCase){
+                    FlowModAddMatchFromField flowModSpecFromField = ((FlowModAddMatchFromFieldCase)flowMod.getFlowModSpec()).getFlowModAddMatchFromField();
+                    toFlowModSpecHeader(flowModSpecFromField, outBuffer);
+                    outBuffer.writeInt(flowModSpecFromField.getSrcField().intValue());
+                    outBuffer.writeShort(flowModSpecFromField.getSrcOfs().shortValue());
+                    outBuffer.writeInt(flowModSpecFromField.getDstField().intValue());
+                    outBuffer.writeShort(flowModSpecFromField.getDstOfs().shortValue());
+                }else if( flowMod.getFlowModSpec() instanceof FlowModAddMatchFromValueCase){
+                    FlowModAddMatchFromValue flowModSpec = ((FlowModAddMatchFromValueCase)flowMod.getFlowModSpec()).getFlowModAddMatchFromValue();
+                    toFlowModSpecHeader(flowModSpec, outBuffer);
+                    outBuffer.writeShort(flowModSpec.getValue().shortValue());
+                    outBuffer.writeInt(flowModSpec.getSrcField().intValue());
+                    outBuffer.writeShort(flowModSpec.getSrcOfs().shortValue());
+
+                }else if( flowMod.getFlowModSpec() instanceof FlowModCopyFieldIntoFieldCase){
+                    FlowModCopyFieldIntoField flowModSpec = ((FlowModCopyFieldIntoFieldCase)flowMod.getFlowModSpec()).getFlowModCopyFieldIntoField();
+                    toFlowModSpecHeader(flowModSpec, outBuffer);
+                    outBuffer.writeInt(flowModSpec.getSrcField().intValue());
+                    outBuffer.writeShort(flowModSpec.getSrcOfs().shortValue());
+                    outBuffer.writeInt(flowModSpec.getDstField().intValue());
+                    outBuffer.writeShort(flowModSpec.getDstOfs().shortValue());
+
+                }else if( flowMod.getFlowModSpec() instanceof FlowModCopyValueIntoFieldCase){
+                    FlowModCopyValueIntoField flowModSpec = ((FlowModCopyValueIntoFieldCase)flowMod.getFlowModSpec()).getFlowModCopyValueIntoField();
+                    toFlowModSpecHeader(flowModSpec, outBuffer);
+                    outBuffer.writeShort(flowModSpec.getValue().shortValue());
+                    outBuffer.writeInt(flowModSpec.getDstField().intValue());
+                    outBuffer.writeShort(flowModSpec.getDstOfs().shortValue());
+
+                }else if( flowMod.getFlowModSpec() instanceof FlowModOutputToPortCase){
+                    FlowModOutputToPort flowModSpec = ((FlowModOutputToPortCase)flowMod.getFlowModSpec()).getFlowModOutputToPort();
+                    toFlowModSpecHeader(flowModSpec, outBuffer);
+                    outBuffer.writeInt(flowModSpec.getSrcField().intValue());
+                    outBuffer.writeShort(flowModSpec.getSrcOfs().shortValue());
+                }
+            }
+        }
+    }
+
+    private static void toFlowModSpecHeader(FlowModOutputToPort flowModSpec, ByteBuf outBuffer) {
+        serializeFlowModSpecHeader(0,2,(short)(int)flowModSpec.getFlowModNumBits(), outBuffer);
+    }
+
+    private static void toFlowModSpecHeader(FlowModCopyValueIntoField flowModSpec, ByteBuf outBuffer) {
+        serializeFlowModSpecHeader(1,1,(short)(int)flowModSpec.getFlowModNumBits(), outBuffer);
+    }
+
+    private static void toFlowModSpecHeader(FlowModCopyFieldIntoField flowModSpec, ByteBuf outBuffer) {
+        serializeFlowModSpecHeader(0,1,(short)(int)flowModSpec.getFlowModNumBits(), outBuffer);
+    }
+
+    private static void toFlowModSpecHeader(FlowModAddMatchFromValue flowModSpec, ByteBuf outBuffer) {
+        serializeFlowModSpecHeader(1,0,(short)(int)flowModSpec.getFlowModNumBits(), outBuffer);
+    }
+
+    private static void toFlowModSpecHeader(FlowModAddMatchFromField flowModSpec, ByteBuf outBuffer) {
+        serializeFlowModSpecHeader(0,0,(short)(int)flowModSpec.getFlowModNumBits(), outBuffer);
+    }
+
+    private static void serializeFlowModSpecHeader(int src, int dst, short bitNum, ByteBuf outBuffer) {
+        short s = 0;
+        s |= (src << SRC_POS);
+        s |= (dst << DST_POS);
+        s |= bitNum;
+        outBuffer.writeShort(s);
+    }
+
+    static int calcLength(ActionLearn action) {
+        int length = HEADER_LENGTH;
+        if(action.getNxActionLearn().getFlowMods() == null){
+            return length;
+        }
+        for(FlowMods flowMod : action.getNxActionLearn().getFlowMods()){
+            if(flowMod.getFlowModSpec() instanceof FlowModAddMatchFromFieldCase){
+                length += FROM_FIELD_LENGTH;
+            } else if( flowMod.getFlowModSpec() instanceof FlowModAddMatchFromValueCase){
+                length += FROM_VALUE_LENGTH;
+            } else if( flowMod.getFlowModSpec() instanceof FlowModCopyFieldIntoFieldCase){
+                length += FROM_FIELD_LENGTH;
+            } else if( flowMod.getFlowModSpec() instanceof FlowModCopyValueIntoFieldCase){
+                length += FROM_VALUE_LENGTH;
+            } else if( flowMod.getFlowModSpec() instanceof FlowModOutputToPortCase){
+                length += TO_PORT_LENGTH;
+            }
+        }
+
+        return length;
+    }
+
+    /*
+     *                                 DESERIALIZATION
+    */
+
+    static void deserializeLearnHeader(final ByteBuf message, NxActionLearnBuilder nxActionLearnBuilder) {
+        nxActionLearnBuilder.setIdleTimeout(message.readUnsignedShort());
+        nxActionLearnBuilder.setHardTimeout(message.readUnsignedShort());
+        nxActionLearnBuilder.setPriority(message.readUnsignedShort());
+        nxActionLearnBuilder.setCookie(BigInteger.valueOf(message.readLong()));
+        nxActionLearnBuilder.setFlags(message.readUnsignedShort());
+        nxActionLearnBuilder.setTableId(message.readUnsignedByte());
+        message.skipBytes(1);
+        nxActionLearnBuilder.setFinIdleTimeout(message.readUnsignedShort());
+        nxActionLearnBuilder.setFinHardTimeout(message.readUnsignedShort());
+    }
+
+    static synchronized void buildFlowModSpecs(NxActionLearnBuilder nxActionLearnBuilder, ByteBuf message, short length) {
+        LearnCodecUtil.length = length;
+        List<FlowMods> flowModeList = new ArrayList<FlowMods>();
+
+        while(LearnCodecUtil.length > 0){
+            FlowMods flowMod = readFlowMod(message);
+
+            if(flowMod != null){
+                flowModeList.add(flowMod);
+            }else{
+                logger.trace("skipping padding bytes");
+            }
+        }
+
+        if(LearnCodecUtil.length != 0){
+            logger.error("Learn Codec read " + Math.abs(length) + " bytes more than needed from stream. Packet might be corrupted");
+        }
+        nxActionLearnBuilder.setFlowMods(flowModeList);
+    }
+
+    private static FlowMods readFlowMod(ByteBuf message) {
+        short header = message.readShort();
+        length -= EncodeConstants.SIZE_OF_SHORT_IN_BYTES;
+        if(header == 0){
+            return null;
+        }
+
+        short src = (short) ((header & SRC_MASK) >> SRC_POS);
+        short dst = (short) ((header & DST_MASK) >> DST_POS);
+        short numBits = (short) (header & NUM_BITS_MASK);
+
+        if(src == 0 && dst == 0 && numBits != 0){
+            return readFlowModAddMatchFromField(message, numBits);
+        } else if(src == 0 && dst == 0){
+            message.skipBytes(EMPTY_FLOW_MOD_LENGTH);
+            length -= EMPTY_FLOW_MOD_LENGTH;
+        } else if(src == 1 && dst == 0){
+            return readFlowModAddMatchFromValue(message, numBits);
+        } else if(src == 0 && dst == 1){
+            return readFlowModCopyFromField(message, numBits);
+        } else if(src == 1 && dst == 1){
+            return readFlowModCopyFromValue(message, numBits);
+        } else if(src == 0 && dst == 2){
+            return readFlowToPort(message, numBits);
+        }
+        return null;
+    }
+
+
+
+    private static FlowMods readFlowModAddMatchFromField(ByteBuf message, short numBits) {
+        FlowModAddMatchFromFieldBuilder builder = new FlowModAddMatchFromFieldBuilder();
+        builder.setSrcField((long) message.readInt());
+        builder.setSrcOfs((int) message.readShort());
+        builder.setDstField((long) message.readInt());
+        builder.setDstOfs((int) message.readShort());
+        builder.setFlowModNumBits((int) numBits);
+        length -= FROM_FIELD_LENGTH - EncodeConstants.SIZE_OF_SHORT_IN_BYTES;
+
+        FlowModsBuilder flowModsBuilder = new FlowModsBuilder();
+        FlowModAddMatchFromFieldCaseBuilder caseBuilder = new FlowModAddMatchFromFieldCaseBuilder();
+        caseBuilder.setFlowModAddMatchFromField(builder.build());
+        flowModsBuilder.setFlowModSpec(caseBuilder.build());
+        return flowModsBuilder.build();
+    }
+
+    private static FlowMods readFlowModAddMatchFromValue(ByteBuf message, short numBits) {
+        FlowModAddMatchFromValueBuilder builder = new FlowModAddMatchFromValueBuilder();
+        builder.setValue((int) message.readShort());
+        builder.setSrcField((long) message.readInt());
+        builder.setSrcOfs((int) message.readShort());
+        builder.setFlowModNumBits((int) numBits);
+        length -= FROM_VALUE_LENGTH - EncodeConstants.SIZE_OF_SHORT_IN_BYTES;
+
+        FlowModsBuilder flowModsBuilder = new FlowModsBuilder();
+        FlowModAddMatchFromValueCaseBuilder caseBuilder = new FlowModAddMatchFromValueCaseBuilder();
+        caseBuilder.setFlowModAddMatchFromValue(builder.build());
+        flowModsBuilder.setFlowModSpec(caseBuilder.build());
+        return flowModsBuilder.build();
+    }
+
+    private static FlowMods readFlowModCopyFromField(ByteBuf message, short numBits) {
+        FlowModCopyFieldIntoFieldBuilder builder = new FlowModCopyFieldIntoFieldBuilder();
+        builder.setSrcField((long) message.readInt());
+        builder.setSrcOfs((int) message.readShort());
+        builder.setDstField((long) message.readInt());
+        builder.setDstOfs((int) message.readShort());
+        builder.setFlowModNumBits((int) numBits);
+        length -= FROM_FIELD_LENGTH - EncodeConstants.SIZE_OF_SHORT_IN_BYTES;
+
+        FlowModsBuilder flowModsBuilder = new FlowModsBuilder();
+        FlowModCopyFieldIntoFieldCaseBuilder caseBuilder = new FlowModCopyFieldIntoFieldCaseBuilder();
+        caseBuilder.setFlowModCopyFieldIntoField(builder.build());
+        flowModsBuilder.setFlowModSpec(caseBuilder.build());
+        return flowModsBuilder.build();
+    }
+
+    private static FlowMods readFlowModCopyFromValue(ByteBuf message, short numBits) {
+        FlowModCopyValueIntoFieldBuilder builder = new FlowModCopyValueIntoFieldBuilder();
+        builder.setValue((int) message.readShort());
+        builder.setDstField((long) message.readInt());
+        builder.setDstOfs((int) message.readShort());
+        builder.setFlowModNumBits((int) numBits);
+        length -= FROM_VALUE_LENGTH - EncodeConstants.SIZE_OF_SHORT_IN_BYTES;
+
+        FlowModsBuilder flowModsBuilder = new FlowModsBuilder();
+        FlowModCopyValueIntoFieldCaseBuilder caseBuilder = new FlowModCopyValueIntoFieldCaseBuilder();
+        caseBuilder.setFlowModCopyValueIntoField(builder.build());
+        flowModsBuilder.setFlowModSpec(caseBuilder.build());
+        return flowModsBuilder.build();
+    }
+
+    private static FlowMods readFlowToPort(ByteBuf message, short numBits) {
+        FlowModOutputToPortBuilder builder = new FlowModOutputToPortBuilder();
+        builder.setSrcField((long) message.readInt());
+        builder.setSrcOfs((int) message.readShort());
+        builder.setFlowModNumBits((int) numBits);
+        length -= TO_PORT_LENGTH - EncodeConstants.SIZE_OF_SHORT_IN_BYTES;
+
+        FlowModsBuilder flowModsBuilder = new FlowModsBuilder();
+        FlowModOutputToPortCaseBuilder caseBuilder = new FlowModOutputToPortCaseBuilder();
+        caseBuilder.setFlowModOutputToPort(builder.build());
+        flowModsBuilder.setFlowModSpec(caseBuilder.build());
+        return flowModsBuilder.build();
+    }
+
+
+}
index a2e7133036027db6cce86f750ca5babafbf247b5..6e4cbed6621c6776aef07405fc69f67154990833 100644 (file)
@@ -23,4 +23,5 @@ public class NiciraActionCodecs {
     public static final PushNshCodec PUSH_NSH_CODEC = new PushNshCodec();
     public static final PopNshCodec POP_NSH_CODEC = new PopNshCodec();
     public static final ConntrackCodec CONNTRACK_CODEC = new ConntrackCodec();
+    public static final LearnCodec LEARN_CODEC = new LearnCodec();
 }
index c0677b9234da5b43a61faff348c07dcf7dd0bdfb..387f04271f3f070bcf40e4ecb37949283f74eefc 100644 (file)
@@ -39,6 +39,9 @@ module nicira-action {
     identity nxm-nx-conntrack {
         base ofaction:experimenter-action-sub-type;
     }
+    identity nxm-nx-learn {
+        base ofaction:experimenter-action-sub-type;
+    }
 
     grouping ofj-nx-action-reg-load-grouping {
         container nx-action-reg-load {
@@ -208,6 +211,168 @@ module nicira-action {
         }
     }
 
+    grouping flow-mod-spec {
+        description
+           "flow mod spec indicates the actions that should be performed to create a new flow which was learned from learn action.";
+        choice flow-mod-spec{
+            case flow-mod-add-match-from-field-case{
+                container flow-mod-add-match-from-field{
+                        leaf flow-mod-num-bits{
+                        type uint16;
+                    }
+
+                    leaf src-field{
+                        type uint32;
+                    }
+
+                    leaf src-ofs{
+                        type uint16;
+                    }
+
+                    leaf dst-field{
+                        type uint32;
+                    }
+
+                    leaf dst-ofs{
+                        type uint16;
+                    }
+                }
+            }
+            case flow-mod-add-match-from-field-case{
+                container flow-mod-add-match-from-field{
+                        leaf flow-mod-num-bits{
+                        type uint16;
+                    }
+
+                    leaf src-field{
+                        type uint32;
+                    }
+
+                    leaf src-ofs{
+                        type uint16;
+                    }
+
+                    leaf dst-field{
+                        type uint32;
+                    }
+
+                    leaf dst-ofs{
+                        type uint16;
+                    }
+                }
+            }
+            case flow-mod-add-match-from-value-case{
+                container flow-mod-add-match-from-value{
+                        leaf flow-mod-num-bits{
+                        type uint16;
+                    }
+
+                    leaf value{
+                        type uint16;
+                    }
+
+                    leaf src-field{
+                        type uint32;
+                    }
+
+                    leaf src-ofs{
+                        type uint16;
+                    }
+                }
+            }
+            case flow-mod-copy-field-into-field-case{
+                container flow-mod-copy-field-into-field{
+                        leaf flow-mod-num-bits{
+                        type uint16;
+                    }
+
+                    leaf src-field{
+                        type uint32;
+                    }
+
+                    leaf src-ofs{
+                        type uint16;
+                    }
+
+                    leaf dst-field{
+                        type uint32;
+                    }
+
+                    leaf dst-ofs{
+                        type uint16;
+                    }
+                }
+            }
+            case flow-mod-copy-value-into-field-case{
+                container flow-mod-copy-value-into-field{
+                        leaf flow-mod-num-bits{
+                        type uint16;
+                    }
+
+                    leaf value{
+                        type uint16;
+                    }
+
+                    leaf dst-field{
+                        type uint32;
+                    }
+
+                    leaf dst-ofs{
+                        type uint16;
+                    }
+                }
+            }
+            case flow-mod-output-to-port-case{
+                container flow-mod-output-to-port{
+                        leaf flow-mod-num-bits{
+                        type uint16;
+                    }
+
+                    leaf src-field{
+                        type uint32;
+                    }
+
+                    leaf src-ofs{
+                        type uint16;
+                    }
+                }
+            }
+        }
+    }
+
+    grouping ofj-nx-action-learn-grouping {
+        container nx-action-learn {
+            leaf idle-timeout {
+                type uint16;
+            }
+            leaf hard-timeout {
+                type uint16;
+            }
+            leaf priority {
+                type uint16;
+            }
+            leaf cookie {
+                type uint64;
+            }
+            leaf flags {
+                type uint16;
+            }
+            leaf table-id {
+                type uint8;
+            }
+            leaf fin-idle-timeout {
+                type uint16;
+            }
+            leaf fin-hard-timeout {
+                type uint16;
+            }
+
+            list flow-mods{
+                uses flow-mod-spec;
+            }
+        }
+    }
+
     augment "/ofaction:action-container/ofaction:action-choice" {
         ext:augment-identifier "ofj-aug-nx-action";
         case action-reg-load {
@@ -234,5 +399,8 @@ module nicira-action {
         case action-conntrack {
             uses ofj-nx-action-conntrack-grouping;
         }
+        case action-learn {
+            uses ofj-nx-action-learn-grouping;
+        }
     }
 }
diff --git a/extension/openflowjava-extension-nicira/src/test/java/org/opendaylight/openflowjava/nx/codec/action/LearnCodecTest.java b/extension/openflowjava-extension-nicira/src/test/java/org/opendaylight/openflowjava/nx/codec/action/LearnCodecTest.java
new file mode 100644 (file)
index 0000000..61343cb
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2016 Hewlett-Packard Enterprise 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.nx.codec.action;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufAllocator;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.openflowjava.nx.api.NiciraConstants;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.actions.grouping.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.actions.grouping.ActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ExperimenterId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionLearn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionLearnBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.FlowModSpec;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromFieldCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromFieldCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromValueCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModCopyFieldIntoFieldCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModCopyValueIntoFieldCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModOutputToPortCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.add.match.from.field._case.FlowModAddMatchFromField;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.add.match.from.field._case.FlowModAddMatchFromFieldBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.add.match.from.value._case.FlowModAddMatchFromValueBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.copy.field.into.field._case.FlowModCopyFieldIntoFieldBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.copy.value.into.field._case.FlowModCopyValueIntoFieldBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.output.to.port._case.FlowModOutputToPortBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.learn.grouping.NxActionLearnBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.learn.grouping.nx.action.learn.FlowMods;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.learn.grouping.nx.action.learn.FlowModsBuilder;
+
+public class LearnCodecTest {
+
+    private LearnCodec learnCodec;
+
+    private ByteBuf buffer;
+    private Action action;
+
+    private final byte LEARN_HEADER_LEN = 32;
+    private final byte NXAST_LEARN_SUBTYPE = 16;
+    private static final short SRC_MASK = 0x2000;
+    private static final short DST_MASK = 0x1800;
+    private static final short NUM_BITS_MASK = 0x07FF;
+
+    @Before
+    public void setUp() {
+        learnCodec = new LearnCodec();
+        buffer = ByteBufAllocator.DEFAULT.buffer();
+    }
+
+    @Test
+    public void serializeTest() {
+        action = createAction();
+        learnCodec.serialize(action, buffer);
+
+        Assert.assertEquals(LEARN_HEADER_LEN+56, buffer.readableBytes());
+        Assert.assertEquals(EncodeConstants.EXPERIMENTER_VALUE, buffer.readUnsignedShort());
+        Assert.assertEquals(LEARN_HEADER_LEN+56, buffer.readUnsignedShort());
+        Assert.assertEquals(NiciraConstants.NX_VENDOR_ID.intValue(), buffer.readUnsignedInt());
+        Assert.assertEquals(NXAST_LEARN_SUBTYPE, buffer.readUnsignedShort());
+        Assert.assertEquals(1, buffer.readUnsignedShort());
+        Assert.assertEquals(2, buffer.readUnsignedShort());
+        Assert.assertEquals(3, buffer.readUnsignedShort());
+        Assert.assertEquals(4, buffer.readLong());
+        Assert.assertEquals(5, buffer.readUnsignedShort());
+        Assert.assertEquals(6, buffer.readUnsignedByte());
+        buffer.skipBytes(1);
+        Assert.assertEquals(7, buffer.readUnsignedShort());
+        Assert.assertEquals(8, buffer.readUnsignedShort());
+        assertFlowMods();
+    }
+
+    @Test
+    public void deserializeTest() {
+        createBufer(buffer);
+        action = learnCodec.deserialize(buffer);
+
+        ActionLearn result = (ActionLearn) action.getActionChoice();
+        Action act= createAction();
+        ActionLearn expResult = (ActionLearn)act.getActionChoice();
+
+        Assert.assertEquals(expResult, result);
+    }
+
+    private void assertFlowMods() {
+        short header = buffer.readShort();
+        short src = (short) ((header & SRC_MASK) >> 13);
+        short dst = (short) ((header & DST_MASK) >> 11);
+        short len = (short) (header & NUM_BITS_MASK);
+
+        Assert.assertEquals(0, src);
+        Assert.assertEquals(0, dst);
+        Assert.assertEquals(48, len);
+        Assert.assertEquals(9, buffer.readUnsignedInt());
+        Assert.assertEquals(10, buffer.readUnsignedShort());
+        Assert.assertEquals(11, buffer.readUnsignedInt());
+        Assert.assertEquals(12, buffer.readUnsignedShort());
+        buffer.skipBytes(2);
+        Assert.assertEquals(9, buffer.readUnsignedInt());
+        Assert.assertEquals(10, buffer.readUnsignedShort());
+        Assert.assertEquals(11, buffer.readUnsignedInt());
+        Assert.assertEquals(12, buffer.readUnsignedShort());
+        buffer.skipBytes(2);
+        Assert.assertEquals(9, buffer.readUnsignedShort());
+        Assert.assertEquals(10, buffer.readUnsignedInt());
+        Assert.assertEquals(11, buffer.readUnsignedShort());
+        buffer.skipBytes(2);
+        Assert.assertEquals(9, buffer.readUnsignedShort());
+        Assert.assertEquals(10, buffer.readUnsignedInt());
+        Assert.assertEquals(11, buffer.readUnsignedShort());
+        buffer.skipBytes(2);
+        Assert.assertEquals(9, buffer.readUnsignedInt());
+        Assert.assertEquals(10, buffer.readUnsignedShort());
+        Assert.assertEquals(0, buffer.readableBytes());
+    }
+
+
+
+    private Action createAction() {
+        ExperimenterId experimenterId = new ExperimenterId(NiciraConstants.NX_VENDOR_ID);
+        ActionBuilder actionBuilder = new ActionBuilder();
+        actionBuilder.setExperimenterId(experimenterId);
+        ActionLearnBuilder actionLearnBuilder = new ActionLearnBuilder();
+
+        NxActionLearnBuilder nxActionLearnBuilder = new NxActionLearnBuilder();
+        nxActionLearnBuilder.setIdleTimeout(1);
+        nxActionLearnBuilder.setHardTimeout(2);
+        nxActionLearnBuilder.setPriority(3);
+        nxActionLearnBuilder.setCookie(BigInteger.valueOf(4));
+        nxActionLearnBuilder.setFlags(5);
+        nxActionLearnBuilder.setTableId((short)6);
+        nxActionLearnBuilder.setFinIdleTimeout(7);
+        nxActionLearnBuilder.setFinHardTimeout(8);
+        nxActionLearnBuilder.setFlowMods(createFlowMods());
+        actionLearnBuilder.setNxActionLearn(nxActionLearnBuilder.build());
+        actionBuilder.setActionChoice(actionLearnBuilder.build());
+
+        return actionBuilder.build();
+    }
+
+    private List<FlowMods> createFlowMods() {
+
+        List<FlowMods> flowMods = new ArrayList<FlowMods>();
+        //length = 14
+        FlowModsBuilder flowMod = new FlowModsBuilder();
+        FlowModAddMatchFromFieldBuilder spec = new FlowModAddMatchFromFieldBuilder();
+        spec.setFlowModNumBits(48);
+        spec.setSrcField((long)9);
+        spec.setSrcOfs(10);
+        spec.setDstField((long) 11);
+        spec.setDstOfs(12);
+        FlowModAddMatchFromFieldCaseBuilder caseBuilder = new FlowModAddMatchFromFieldCaseBuilder();
+        caseBuilder.setFlowModAddMatchFromField(spec.build());
+        flowMod.setFlowModSpec(caseBuilder.build());
+        flowMods.add(flowMod.build());
+
+        //length = 14
+        FlowModsBuilder flowMod2 = new FlowModsBuilder();
+        FlowModCopyFieldIntoFieldBuilder spec2 = new FlowModCopyFieldIntoFieldBuilder();
+        spec2.setFlowModNumBits(48);
+        spec2.setSrcField((long)9);
+        spec2.setSrcOfs(10);
+        spec2.setDstField((long) 11);
+        spec2.setDstOfs(12);
+        FlowModCopyFieldIntoFieldCaseBuilder caseBuilder2 = new FlowModCopyFieldIntoFieldCaseBuilder();
+        caseBuilder2.setFlowModCopyFieldIntoField(spec2.build());
+        flowMod2.setFlowModSpec(caseBuilder2.build());
+        flowMods.add(flowMod2.build());
+
+        //length = 10
+        FlowModsBuilder flowMod3 = new FlowModsBuilder();
+        FlowModCopyValueIntoFieldBuilder spec3 = new FlowModCopyValueIntoFieldBuilder();
+        spec3.setFlowModNumBits(48);
+        spec3.setValue(9);
+        spec3.setDstField((long) 10);
+        spec3.setDstOfs(11);
+        FlowModCopyValueIntoFieldCaseBuilder caseBuilder3 = new FlowModCopyValueIntoFieldCaseBuilder();
+        caseBuilder3.setFlowModCopyValueIntoField(spec3.build());
+        flowMod3.setFlowModSpec(caseBuilder3.build());
+        flowMods.add(flowMod3.build());
+
+        //length = 10
+        FlowModsBuilder flowMod4 = new FlowModsBuilder();
+        FlowModAddMatchFromValueBuilder spec4 = new FlowModAddMatchFromValueBuilder();
+        spec4.setFlowModNumBits(48);
+        spec4.setValue(9);
+        spec4.setSrcField((long) 10);
+        spec4.setSrcOfs(11);
+        FlowModAddMatchFromValueCaseBuilder caseBuilder4 = new FlowModAddMatchFromValueCaseBuilder();
+        caseBuilder4.setFlowModAddMatchFromValue(spec4.build());
+        flowMod4.setFlowModSpec(caseBuilder4.build());
+        flowMods.add(flowMod4.build());
+
+        //length = 8
+        FlowModsBuilder flowMod5 = new FlowModsBuilder();
+        FlowModOutputToPortBuilder spec5 = new FlowModOutputToPortBuilder();
+        spec5.setFlowModNumBits(48);
+        spec5.setSrcField((long) 9);
+        spec5.setSrcOfs(10);
+        FlowModOutputToPortCaseBuilder caseBuilder5 = new FlowModOutputToPortCaseBuilder();
+        caseBuilder5.setFlowModOutputToPort(spec5.build());
+        flowMod5.setFlowModSpec(caseBuilder5.build());
+        flowMods.add(flowMod5.build());
+
+        return flowMods;
+    }
+
+    private void createBufer(ByteBuf message) {
+        message.writeShort(EncodeConstants.EXPERIMENTER_VALUE);
+        message.writeShort(LEARN_HEADER_LEN + 56);
+        message.writeInt(NiciraConstants.NX_VENDOR_ID.intValue());
+        message.writeShort(NXAST_LEARN_SUBTYPE);
+
+        message.writeShort(1);
+        message.writeShort(2);
+        message.writeShort(3);
+        message.writeLong(4);
+        message.writeShort(5);
+        message.writeByte(6);
+        message.writeZero(1);
+        message.writeShort(7);
+        message.writeShort(8);
+
+        toFlowModSpecHeader(message, 0, 0);
+        message.writeInt(9);
+        message.writeShort(10);
+        message.writeInt(11);
+        message.writeShort(12);
+
+        toFlowModSpecHeader(message, 0, 1);
+        message.writeInt(9);
+        message.writeShort(10);
+        message.writeInt(11);
+        message.writeShort(12);
+
+        toFlowModSpecHeader(message, 1, 1);
+        message.writeShort(9);
+        message.writeInt(10);
+        message.writeShort(11);
+
+        toFlowModSpecHeader(message, 1, 0);
+        message.writeShort(9);
+        message.writeInt(10);
+        message.writeShort(11);
+
+        toFlowModSpecHeader(message, 0, 2);
+        message.writeInt(9);
+        message.writeShort(10);
+    }
+
+    private void toFlowModSpecHeader(ByteBuf message, int src, int dst) {
+        short b = 0;
+        short bitNum = 48;
+        b |= (src << 13);
+        b |= (dst << 11);
+        b |= bitNum;
+
+        message.writeShort(b);
+    }
+}
\ No newline at end of file
diff --git a/extension/openflowjava-extension-nicira/src/test/java/org/opendaylight/openflowjava/nx/codec/action/TestsCodecStub.java b/extension/openflowjava-extension-nicira/src/test/java/org/opendaylight/openflowjava/nx/codec/action/TestsCodecStub.java
new file mode 100644 (file)
index 0000000..fa5f3a0
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016 Hewlett-Packard Enterprise 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.nx.codec.action;
+
+import io.netty.buffer.ByteBuf;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.actions.grouping.Action;
+
+public class TestsCodecStub extends AbstractActionCodec {
+
+    @Override
+    public void serialize(Action input, ByteBuf outBuffer) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public Action deserialize(ByteBuf message) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+}
index f9a89ea926cd883915e543dd2e6637694b0ea192..b1fb354e050e248cea5b1d77a84a1c076b543e25 100644 (file)
@@ -8,14 +8,17 @@
 package org.opendaylight.openflowplugin.extension.vendor.nicira;
 
 import org.opendaylight.openflowjava.nx.codec.match.TunIpv4DstCodec;
-
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmNxTunIpv4DstKey;
 import org.opendaylight.openflowplugin.extension.vendor.nicira.convertor.match.TunIPv4DstConvertor;
+
 import com.google.common.base.Preconditions;
+
 import java.util.HashSet;
 import java.util.Set;
+
 import org.opendaylight.openflowjava.nx.api.NiciraUtil;
 import org.opendaylight.openflowjava.nx.codec.action.ConntrackCodec;
+import org.opendaylight.openflowjava.nx.codec.action.LearnCodec;
 import org.opendaylight.openflowjava.nx.codec.action.MultipathCodec;
 import org.opendaylight.openflowjava.nx.codec.action.OutputRegCodec;
 import org.opendaylight.openflowjava.nx.codec.action.RegLoadCodec;
@@ -68,6 +71,7 @@ import org.opendaylight.openflowplugin.extension.api.ExtensionConverterRegistrat
 import org.opendaylight.openflowplugin.extension.api.TypeVersionKey;
 import org.opendaylight.openflowplugin.extension.api.path.ActionPath;
 import org.opendaylight.openflowplugin.extension.vendor.nicira.convertor.action.ConntrackConvertor;
+import org.opendaylight.openflowplugin.extension.vendor.nicira.convertor.action.LearnConvertor;
 import org.opendaylight.openflowplugin.extension.vendor.nicira.convertor.action.MultipathConvertor;
 import org.opendaylight.openflowplugin.extension.vendor.nicira.convertor.action.OutputRegConvertor;
 import org.opendaylight.openflowplugin.extension.vendor.nicira.convertor.action.RegLoadConvertor;
@@ -107,6 +111,7 @@ import org.opendaylight.openflowplugin.extension.vendor.nicira.convertor.match.U
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.action.grouping.ActionChoice;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionConntrack;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionLearn;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionMultipath;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionOutputReg;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionRegLoad;
@@ -115,6 +120,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev1
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionPushNsh;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionPopNsh;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.add.flow.input.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionConntrackRpcAddFlowApplyActionsCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.add.flow.input.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionLearnRpcAddFlowApplyActionsCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.add.flow.input.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionMultipathRpcAddFlowApplyActionsCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.add.flow.input.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionOutputRegRpcAddFlowApplyActionsCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.add.flow.input.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionRegLoadRpcAddFlowApplyActionsCase;
@@ -123,6 +129,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.ni
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.add.flow.input.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionPushNshRpcAddFlowApplyActionsCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.add.flow.input.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionPopNshRpcAddFlowApplyActionsCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.add.flow.input.instructions.instruction.instruction.write.actions._case.write.actions.action.action.NxActionConntrackRpcAddFlowWriteActionsCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.add.flow.input.instructions.instruction.instruction.write.actions._case.write.actions.action.action.NxActionLearnRpcAddFlowWriteActionsCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.add.flow.input.instructions.instruction.instruction.write.actions._case.write.actions.action.action.NxActionMultipathRpcAddFlowWriteActionsCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.add.flow.input.instructions.instruction.instruction.write.actions._case.write.actions.action.action.NxActionOutputRegRpcAddFlowWriteActionsCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.add.flow.input.instructions.instruction.instruction.write.actions._case.write.actions.action.action.NxActionRegLoadRpcAddFlowWriteActionsCase;
@@ -131,6 +138,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.ni
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.add.flow.input.instructions.instruction.instruction.write.actions._case.write.actions.action.action.NxActionPushNshRpcAddFlowWriteActionsCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.add.flow.input.instructions.instruction.instruction.write.actions._case.write.actions.action.action.NxActionPopNshRpcAddFlowWriteActionsCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.add.group.input.buckets.bucket.action.action.NxActionConntrackRpcAddGroupCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.add.group.input.buckets.bucket.action.action.NxActionLearnRpcAddGroupCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.add.group.input.buckets.bucket.action.action.NxActionMultipathRpcAddGroupCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.add.group.input.buckets.bucket.action.action.NxActionOutputRegRpcAddGroupCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.add.group.input.buckets.bucket.action.action.NxActionRegLoadRpcAddGroupCase;
@@ -139,6 +147,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.ni
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.add.group.input.buckets.bucket.action.action.NxActionPushNshRpcAddGroupCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.add.group.input.buckets.bucket.action.action.NxActionPopNshRpcAddGroupCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.group.buckets.bucket.action.action.NxActionConntrackNodesNodeGroupBucketsBucketActionsCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.group.buckets.bucket.action.action.NxActionLearnNodesNodeGroupBucketsBucketActionsCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.group.buckets.bucket.action.action.NxActionMultipathNodesNodeGroupBucketsBucketActionsCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.group.buckets.bucket.action.action.NxActionOutputRegNodesNodeGroupBucketsBucketActionsCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.group.buckets.bucket.action.action.NxActionRegLoadNodesNodeGroupBucketsBucketActionsCase;
@@ -147,6 +156,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.ni
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.group.buckets.bucket.action.action.NxActionPushNshNodesNodeGroupBucketsBucketActionsCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.group.buckets.bucket.action.action.NxActionPopNshNodesNodeGroupBucketsBucketActionsCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionConntrackNodesNodeTableFlowApplyActionsCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionLearnNodesNodeTableFlowApplyActionsCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionMultipathNodesNodeTableFlowApplyActionsCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionOutputRegNodesNodeTableFlowApplyActionsCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionRegLoadNodesNodeTableFlowApplyActionsCase;
@@ -155,6 +165,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.ni
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionPushNshNodesNodeTableFlowApplyActionsCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionPopNshNodesNodeTableFlowApplyActionsCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.write.actions._case.write.actions.action.action.NxActionConntrackNodesNodeTableFlowWriteActionsCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.write.actions._case.write.actions.action.action.NxActionLearnNodesNodeTableFlowWriteActionsCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.write.actions._case.write.actions.action.action.NxActionMultipathNodesNodeTableFlowWriteActionsCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.write.actions._case.write.actions.action.action.NxActionOutputRegNodesNodeTableFlowWriteActionsCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.write.actions._case.write.actions.action.action.NxActionRegLoadNodesNodeTableFlowWriteActionsCase;
@@ -163,6 +174,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.ni
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.write.actions._case.write.actions.action.action.NxActionPushNshNodesNodeTableFlowWriteActionsCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.write.actions._case.write.actions.action.action.NxActionPopNshNodesNodeTableFlowWriteActionsCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.remove.group.input.buckets.bucket.action.action.NxActionConntrackRpcRemoveGroupCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.remove.group.input.buckets.bucket.action.action.NxActionLearnRpcRemoveGroupCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.remove.group.input.buckets.bucket.action.action.NxActionMultipathRpcRemoveGroupCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.remove.group.input.buckets.bucket.action.action.NxActionOutputRegRpcRemoveGroupCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.remove.group.input.buckets.bucket.action.action.NxActionRegLoadRpcRemoveGroupCase;
@@ -171,6 +183,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.ni
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.remove.group.input.buckets.bucket.action.action.NxActionPushNshRpcRemoveGroupCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.remove.group.input.buckets.bucket.action.action.NxActionPopNshRpcRemoveGroupCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.update.group.input.original.group.buckets.bucket.action.action.NxActionConntrackRpcUpdateGroupOriginalCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.update.group.input.original.group.buckets.bucket.action.action.NxActionLearnRpcUpdateGroupOriginalCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.update.group.input.original.group.buckets.bucket.action.action.NxActionMultipathRpcUpdateGroupOriginalCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.update.group.input.original.group.buckets.bucket.action.action.NxActionOutputRegRpcUpdateGroupOriginalCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.update.group.input.original.group.buckets.bucket.action.action.NxActionRegLoadRpcUpdateGroupOriginalCase;
@@ -179,6 +192,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.ni
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.update.group.input.original.group.buckets.bucket.action.action.NxActionPushNshRpcUpdateGroupOriginalCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.update.group.input.original.group.buckets.bucket.action.action.NxActionPopNshRpcUpdateGroupOriginalCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.update.group.input.updated.group.buckets.bucket.action.action.NxActionConntrackRpcUpdateGroupUpdatedCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.update.group.input.updated.group.buckets.bucket.action.action.NxActionLearnRpcUpdateGroupUpdatedCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.update.group.input.updated.group.buckets.bucket.action.action.NxActionMultipathRpcUpdateGroupUpdatedCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.update.group.input.updated.group.buckets.bucket.action.action.NxActionOutputRegRpcUpdateGroupUpdatedCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.update.group.input.updated.group.buckets.bucket.action.action.NxActionRegLoadRpcUpdateGroupUpdatedCase;
@@ -273,6 +287,7 @@ public class NiciraExtensionProvider implements AutoCloseable {
     private final static UdpSrcConvertor UDP_SRC_CONVERTOR = new UdpSrcConvertor();
     private final static UdpDstConvertor UDP_DST_CONVERTOR = new UdpDstConvertor();
     private final static ConntrackConvertor CONNTRACK_CONVERTOR = new ConntrackConvertor();
+    private final static LearnConvertor LEARN_CONVERTOR = new LearnConvertor();
     private final static CtStateConvertor CT_STATE_CONVERTOR = new CtStateConvertor();
     private final static CtZoneConvertor CT_ZONE_CONVERTOR = new CtZoneConvertor();
 
@@ -311,6 +326,7 @@ public class NiciraExtensionProvider implements AutoCloseable {
         registerAction13(NxActionPushNshNodesNodeTableFlowApplyActionsCase.class, PUSH_NSH_CONVERTOR);
         registerAction13(NxActionPopNshNodesNodeTableFlowApplyActionsCase.class, POP_NSH_CONVERTOR);
         registerAction13(NxActionConntrackNodesNodeTableFlowApplyActionsCase.class, CONNTRACK_CONVERTOR);
+        registerAction13(NxActionLearnNodesNodeTableFlowApplyActionsCase.class, LEARN_CONVERTOR);
 
         registerAction13(NxActionRegLoadNodesNodeTableFlowWriteActionsCase.class, REG_LOAD_CONVERTOR);
         registerAction13(NxActionRegMoveNodesNodeTableFlowWriteActionsCase.class, REG_MOVE_CONVERTOR);
@@ -320,6 +336,7 @@ public class NiciraExtensionProvider implements AutoCloseable {
         registerAction13(NxActionPushNshNodesNodeTableFlowWriteActionsCase.class, PUSH_NSH_CONVERTOR);
         registerAction13(NxActionPopNshNodesNodeTableFlowWriteActionsCase.class, POP_NSH_CONVERTOR);
         registerAction13(NxActionConntrackNodesNodeTableFlowWriteActionsCase.class, CONNTRACK_CONVERTOR);
+        registerAction13(NxActionLearnNodesNodeTableFlowWriteActionsCase.class, LEARN_CONVERTOR);
 
         registerAction13(NxActionRegLoadNodesNodeGroupBucketsBucketActionsCase.class, REG_LOAD_CONVERTOR);
         registerAction13(NxActionRegMoveNodesNodeGroupBucketsBucketActionsCase.class, REG_MOVE_CONVERTOR);
@@ -329,6 +346,7 @@ public class NiciraExtensionProvider implements AutoCloseable {
         registerAction13(NxActionPushNshNodesNodeGroupBucketsBucketActionsCase.class, PUSH_NSH_CONVERTOR);
         registerAction13(NxActionPopNshNodesNodeGroupBucketsBucketActionsCase.class, POP_NSH_CONVERTOR);
         registerAction13(NxActionConntrackNodesNodeGroupBucketsBucketActionsCase.class, CONNTRACK_CONVERTOR);
+        registerAction13(NxActionLearnNodesNodeGroupBucketsBucketActionsCase.class, LEARN_CONVERTOR);
 
         // src=rpc-addFlow
         registerAction13(NxActionRegLoadRpcAddFlowApplyActionsCase.class, REG_LOAD_CONVERTOR);
@@ -339,6 +357,7 @@ public class NiciraExtensionProvider implements AutoCloseable {
         registerAction13(NxActionPushNshRpcAddFlowApplyActionsCase.class, PUSH_NSH_CONVERTOR);
         registerAction13(NxActionPopNshRpcAddFlowApplyActionsCase.class, POP_NSH_CONVERTOR);
         registerAction13(NxActionConntrackRpcAddFlowApplyActionsCase.class, CONNTRACK_CONVERTOR);
+        registerAction13(NxActionLearnRpcAddFlowApplyActionsCase.class, LEARN_CONVERTOR);
 
         registerAction13(NxActionRegLoadRpcAddFlowWriteActionsCase.class, REG_LOAD_CONVERTOR);
         registerAction13(NxActionRegMoveRpcAddFlowWriteActionsCase.class, REG_MOVE_CONVERTOR);
@@ -348,6 +367,7 @@ public class NiciraExtensionProvider implements AutoCloseable {
         registerAction13(NxActionPushNshRpcAddFlowWriteActionsCase.class, PUSH_NSH_CONVERTOR);
         registerAction13(NxActionPopNshRpcAddFlowWriteActionsCase.class, POP_NSH_CONVERTOR);
         registerAction13(NxActionConntrackRpcAddFlowWriteActionsCase.class, CONNTRACK_CONVERTOR);
+        registerAction13(NxActionLearnRpcAddFlowWriteActionsCase.class, LEARN_CONVERTOR);
 
         registerAction13(NxActionRegLoadRpcAddGroupCase.class, REG_LOAD_CONVERTOR);
         registerAction13(NxActionRegLoadRpcRemoveGroupCase.class, REG_LOAD_CONVERTOR);
@@ -381,6 +401,10 @@ public class NiciraExtensionProvider implements AutoCloseable {
         registerAction13(NxActionConntrackRpcRemoveGroupCase.class, CONNTRACK_CONVERTOR);
         registerAction13(NxActionConntrackRpcUpdateGroupOriginalCase.class, CONNTRACK_CONVERTOR);
         registerAction13(NxActionConntrackRpcUpdateGroupUpdatedCase.class, CONNTRACK_CONVERTOR);
+        registerAction13(NxActionLearnRpcAddGroupCase.class, LEARN_CONVERTOR);
+        registerAction13(NxActionLearnRpcRemoveGroupCase.class, LEARN_CONVERTOR);
+        registerAction13(NxActionLearnRpcUpdateGroupOriginalCase.class, LEARN_CONVERTOR);
+        registerAction13(NxActionLearnRpcUpdateGroupUpdatedCase.class, LEARN_CONVERTOR);
 
 
         registerAction13(ActionRegLoad.class, REG_LOAD_CONVERTOR);
@@ -391,6 +415,7 @@ public class NiciraExtensionProvider implements AutoCloseable {
         registerAction13(ActionPushNsh.class, PUSH_NSH_CONVERTOR);
         registerAction13(ActionPopNsh.class, POP_NSH_CONVERTOR);
         registerAction13(ActionConntrack.class, CONNTRACK_CONVERTOR);
+        registerAction13(ActionLearn.class, LEARN_CONVERTOR);
 
         registrations.add(extensionConverterRegistrator.registerActionConvertor(NiciraUtil.createOfJavaKeyFrom(RegLoadCodec.SERIALIZER_KEY), REG_LOAD_CONVERTOR));
         registrations.add(extensionConverterRegistrator.registerActionConvertor(NiciraUtil.createOfJavaKeyFrom(RegMoveCodec.SERIALIZER_KEY), REG_MOVE_CONVERTOR));
@@ -400,6 +425,7 @@ public class NiciraExtensionProvider implements AutoCloseable {
         registrations.add(extensionConverterRegistrator.registerActionConvertor(NiciraUtil.createOfJavaKeyFrom(PushNshCodec.SERIALIZER_KEY), PUSH_NSH_CONVERTOR));
         registrations.add(extensionConverterRegistrator.registerActionConvertor(NiciraUtil.createOfJavaKeyFrom(PopNshCodec.SERIALIZER_KEY), POP_NSH_CONVERTOR));
         registrations.add(extensionConverterRegistrator.registerActionConvertor(NiciraUtil.createOfJavaKeyFrom(ConntrackCodec.SERIALIZER_KEY), CONNTRACK_CONVERTOR));
+        registrations.add(extensionConverterRegistrator.registerActionConvertor(NiciraUtil.createOfJavaKeyFrom(LearnCodec.SERIALIZER_KEY), LEARN_CONVERTOR));
 
         registrations.add(extensionConverterRegistrator.registerMatchConvertor(new ConverterExtensionKey<>(NxmNxReg0Key.class, EncodeConstants.OF13_VERSION_ID), REG_CONVERTOR));
         registrations.add(extensionConverterRegistrator.registerMatchConvertor(new ConverterExtensionKey<>(NxmNxReg1Key.class, EncodeConstants.OF13_VERSION_ID), REG_CONVERTOR));
diff --git a/extension/openflowplugin-extension-nicira/src/main/java/org/opendaylight/openflowplugin/extension/vendor/nicira/convertor/action/LearnConvertor.java b/extension/openflowplugin-extension-nicira/src/main/java/org/opendaylight/openflowplugin/extension/vendor/nicira/convertor/action/LearnConvertor.java
new file mode 100644 (file)
index 0000000..9bc8f21
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2016 Hewlett-Packard Enterprise 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.extension.vendor.nicira.convertor.action;
+
+import org.opendaylight.openflowplugin.extension.api.ConvertorActionFromOFJava;
+import org.opendaylight.openflowplugin.extension.api.ConvertorActionToOFJava;
+import org.opendaylight.openflowplugin.extension.api.path.ActionPath;
+import org.opendaylight.openflowplugin.extension.vendor.nicira.convertor.CodecPreconditionException;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.actions.grouping.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionLearn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionLearnBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.learn.grouping.NxActionLearn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.learn.grouping.NxActionLearnBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.NxActionLearnGrouping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flows.statistics.update.flow.and.statistics.map.list.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionLearnNotifFlowsStatisticsUpdateApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flows.statistics.update.flow.and.statistics.map.list.instructions.instruction.instruction.write.actions._case.write.actions.action.action.NxActionLearnNotifFlowsStatisticsUpdateWriteActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.group.desc.stats.updated.group.desc.stats.buckets.bucket.action.action.NxActionLearnNotifGroupDescStatsUpdatedCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.write.actions._case.write.actions.action.action.NxActionLearnNodesNodeTableFlowWriteActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.learn.grouping.NxLearn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.learn.grouping.NxLearnBuilder;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * @author Slava Radune
+ */
+
+public class LearnConvertor implements
+        ConvertorActionToOFJava<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action, Action>,
+        ConvertorActionFromOFJava<Action, ActionPath> {
+
+    @Override
+    public org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action convert(final Action input, final ActionPath path) {
+        NxActionLearn action = ((ActionLearn) input.getActionChoice()).getNxActionLearn();
+        NxLearnBuilder builder = new NxLearnBuilder();
+        LearnConvertorUtil.convertUp(action, builder);
+        return resolveAction(builder.build(), path);
+    }
+
+    private static org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action resolveAction(final NxLearn value, final ActionPath path) {
+        switch (path) {
+            case NODES_NODE_TABLE_FLOW_INSTRUCTIONS_INSTRUCTION_WRITEACTIONSCASE_WRITEACTIONS_ACTION_ACTION_EXTENSIONLIST_EXTENSION:
+                return new NxActionLearnNodesNodeTableFlowWriteActionsCaseBuilder().setNxLearn(value).build();
+            case FLOWSSTATISTICSUPDATE_FLOWANDSTATISTICSMAPLIST_INSTRUCTIONS_INSTRUCTION_INSTRUCTION_WRITEACTIONSCASE_WRITEACTIONS_ACTION_ACTION:
+                return new NxActionLearnNotifFlowsStatisticsUpdateWriteActionsCaseBuilder().setNxLearn(value).build();
+            case FLOWSSTATISTICSUPDATE_FLOWANDSTATISTICSMAPLIST_INSTRUCTIONS_INSTRUCTION_INSTRUCTION_APPLYACTIONSCASE_APPLYACTIONS_ACTION_ACTION:
+                return new NxActionLearnNotifFlowsStatisticsUpdateApplyActionsCaseBuilder().setNxLearn(value).build();
+            case GROUPDESCSTATSUPDATED_GROUPDESCSTATS_BUCKETS_BUCKET_ACTION:
+                return new NxActionLearnNotifGroupDescStatsUpdatedCaseBuilder().setNxLearn(value).build();
+            default:
+                throw new CodecPreconditionException(path);
+        }
+    }
+
+    @Override
+    public Action convert(final org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action nxActionArg) {
+        Preconditions.checkArgument(nxActionArg instanceof NxActionLearnGrouping);
+        NxActionLearnGrouping nxAction = (NxActionLearnGrouping) nxActionArg;
+
+        NxActionLearnBuilder nxActionLearnBuilder = new NxActionLearnBuilder();
+        LearnConvertorUtil.convertDown(nxAction, nxActionLearnBuilder);
+        ActionLearnBuilder actionLearnBuilder = new ActionLearnBuilder();
+        actionLearnBuilder.setNxActionLearn(nxActionLearnBuilder.build());
+        return ActionUtil.createAction(actionLearnBuilder.build());
+    }
+
+}
diff --git a/extension/openflowplugin-extension-nicira/src/main/java/org/opendaylight/openflowplugin/extension/vendor/nicira/convertor/action/LearnConvertorUtil.java b/extension/openflowplugin-extension-nicira/src/main/java/org/opendaylight/openflowplugin/extension/vendor/nicira/convertor/action/LearnConvertorUtil.java
new file mode 100644 (file)
index 0000000..088c0f8
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2016 Hewlett-Packard Enterprise 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.extension.vendor.nicira.convertor.action;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.learn.grouping.NxActionLearn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.learn.grouping.NxActionLearnBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.NxActionLearnGrouping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flow.mod.spec.FlowModSpec;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromFieldCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromFieldCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromValueCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromValueCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flow.mod.spec.flow.mod.spec.FlowModCopyFieldIntoFieldCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flow.mod.spec.flow.mod.spec.FlowModCopyFieldIntoFieldCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flow.mod.spec.flow.mod.spec.FlowModCopyValueIntoFieldCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flow.mod.spec.flow.mod.spec.FlowModCopyValueIntoFieldCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flow.mod.spec.flow.mod.spec.FlowModOutputToPortCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flow.mod.spec.flow.mod.spec.FlowModOutputToPortCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flow.mod.spec.flow.mod.spec.flow.mod.add.match.from.field._case.FlowModAddMatchFromField;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flow.mod.spec.flow.mod.spec.flow.mod.add.match.from.field._case.FlowModAddMatchFromFieldBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flow.mod.spec.flow.mod.spec.flow.mod.add.match.from.value._case.FlowModAddMatchFromValue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flow.mod.spec.flow.mod.spec.flow.mod.add.match.from.value._case.FlowModAddMatchFromValueBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flow.mod.spec.flow.mod.spec.flow.mod.copy.field.into.field._case.FlowModCopyFieldIntoField;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flow.mod.spec.flow.mod.spec.flow.mod.copy.field.into.field._case.FlowModCopyFieldIntoFieldBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flow.mod.spec.flow.mod.spec.flow.mod.copy.value.into.field._case.FlowModCopyValueIntoField;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flow.mod.spec.flow.mod.spec.flow.mod.copy.value.into.field._case.FlowModCopyValueIntoFieldBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flow.mod.spec.flow.mod.spec.flow.mod.output.to.port._case.FlowModOutputToPort;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flow.mod.spec.flow.mod.spec.flow.mod.output.to.port._case.FlowModOutputToPortBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.learn.grouping.NxLearn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.learn.grouping.NxLearnBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.learn.grouping.nx.learn.FlowMods;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.learn.grouping.nx.learn.FlowModsBuilder;
+
+public class LearnConvertorUtil {
+
+    /*
+     *                         CONVERT UP
+    */
+
+    static void convertUp(NxActionLearn action, NxLearnBuilder builder) {
+        builder.setFlags(action.getFlags());
+        builder.setCookie(action.getCookie());
+        builder.setFinHardTimeout(action.getFinHardTimeout());
+        builder.setFinIdleTimeout(action.getFinIdleTimeout());
+        builder.setHardTimeout(action.getHardTimeout());
+        builder.setIdleTimeout(action.getIdleTimeout());
+        builder.setPriority(action.getPriority());
+        builder.setTableId(action.getTableId());
+        builder.setFlowMods(getFlowMods(action));
+    }
+
+    private static List<FlowMods> getFlowMods(NxActionLearn action) {
+        if(action.getFlowMods() == null){
+            return null;
+        }
+
+        List<FlowMods> flowMods = new ArrayList<FlowMods>();
+        for(org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.learn.grouping.nx.action.learn.FlowMods flowMod : action.getFlowMods()){
+            FlowModsBuilder flowModBuilder = new FlowModsBuilder();
+            FlowModSpec flowModSpec = buildFlowModSpec(flowMod.getFlowModSpec());
+            flowModBuilder.setFlowModSpec(flowModSpec);
+            flowMods.add(flowModBuilder.build());
+        }
+        return flowMods;
+    }
+
+
+    private static FlowModSpec buildFlowModSpec(org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.FlowModSpec flowModSpec) {
+        if(flowModSpec instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromFieldCase){
+            org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.add.match.from.field._case.FlowModAddMatchFromField flowModAdd2 = 
+                    ((org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromFieldCase) flowModSpec).getFlowModAddMatchFromField(); 
+            FlowModAddMatchFromFieldBuilder flowModAdd = new FlowModAddMatchFromFieldBuilder();
+            flowModAdd.setDstField(flowModAdd2.getDstField());
+            flowModAdd.setSrcField(flowModAdd2.getSrcField());
+            flowModAdd.setDstOfs(flowModAdd2.getDstOfs());
+            flowModAdd.setSrcOfs(flowModAdd2.getSrcOfs());
+            flowModAdd.setFlowModNumBits(flowModAdd2.getFlowModNumBits());
+            FlowModAddMatchFromFieldCaseBuilder caseBuilder = new FlowModAddMatchFromFieldCaseBuilder();
+            caseBuilder.setFlowModAddMatchFromField(flowModAdd.build());
+            return caseBuilder.build();
+        } else if(flowModSpec instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromValueCase){
+            org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.add.match.from.value._case.FlowModAddMatchFromValue flowModAdd2 = 
+                    ((org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromValueCase) flowModSpec).getFlowModAddMatchFromValue(); 
+            FlowModAddMatchFromValueBuilder flowModAdd = new FlowModAddMatchFromValueBuilder();
+            flowModAdd.setValue(flowModAdd2.getValue());
+            flowModAdd.setSrcField(flowModAdd2.getSrcField());
+            flowModAdd.setSrcOfs(flowModAdd2.getSrcOfs());
+            flowModAdd.setFlowModNumBits(flowModAdd2.getFlowModNumBits());
+            FlowModAddMatchFromValueCaseBuilder caseBuilder = new FlowModAddMatchFromValueCaseBuilder();
+            caseBuilder.setFlowModAddMatchFromValue(flowModAdd.build());
+            return caseBuilder.build();
+        } else if(flowModSpec instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModCopyFieldIntoFieldCase){
+            org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.copy.field.into.field._case.FlowModCopyFieldIntoField flowModCopy2 = 
+                    ((org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModCopyFieldIntoFieldCase) flowModSpec).getFlowModCopyFieldIntoField(); 
+            FlowModCopyFieldIntoFieldBuilder flowModCopy = new FlowModCopyFieldIntoFieldBuilder();
+            flowModCopy.setDstField(flowModCopy2.getDstField());
+            flowModCopy.setDstOfs(flowModCopy2.getDstOfs());
+            flowModCopy.setSrcField(flowModCopy2.getSrcField());
+            flowModCopy.setSrcOfs(flowModCopy2.getSrcOfs());
+            flowModCopy.setFlowModNumBits(flowModCopy2.getFlowModNumBits());
+            FlowModCopyFieldIntoFieldCaseBuilder caseBuilder = new FlowModCopyFieldIntoFieldCaseBuilder();
+            caseBuilder.setFlowModCopyFieldIntoField(flowModCopy.build());
+            return caseBuilder.build();
+        } else if(flowModSpec instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModCopyValueIntoFieldCase){
+            org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.copy.value.into.field._case.FlowModCopyValueIntoField flowModCopy2 = 
+                    ((org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModCopyValueIntoFieldCase) flowModSpec).getFlowModCopyValueIntoField(); 
+            FlowModCopyValueIntoFieldBuilder flowModCopy = new FlowModCopyValueIntoFieldBuilder();
+            flowModCopy.setValue(flowModCopy2.getValue());
+            flowModCopy.setDstField(flowModCopy2.getDstField());
+            flowModCopy.setDstOfs(flowModCopy2.getDstOfs());
+            flowModCopy.setFlowModNumBits(flowModCopy2.getFlowModNumBits());
+            FlowModCopyValueIntoFieldCaseBuilder caseBuilder = new FlowModCopyValueIntoFieldCaseBuilder();
+            caseBuilder.setFlowModCopyValueIntoField(flowModCopy.build());
+            return caseBuilder.build();
+        } else if(flowModSpec instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModOutputToPortCase){
+            org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.output.to.port._case.FlowModOutputToPort flowModOut2 = 
+                    ((org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModOutputToPortCase) flowModSpec).getFlowModOutputToPort(); 
+            FlowModOutputToPortBuilder flowModOut = new FlowModOutputToPortBuilder();
+            flowModOut.setSrcField(flowModOut2.getSrcField());
+            flowModOut.setSrcOfs(flowModOut2.getSrcOfs());
+            flowModOut.setFlowModNumBits(flowModOut2.getFlowModNumBits());
+            FlowModOutputToPortCaseBuilder caseBuilder = new FlowModOutputToPortCaseBuilder();
+            caseBuilder.setFlowModOutputToPort(flowModOut.build());
+            return caseBuilder.build();
+        }
+        return null;
+    }
+
+    /*
+     *                                  CONVERT DOWN
+     */
+
+    static void convertDown(NxActionLearnGrouping nxAction, NxActionLearnBuilder nxActionLearnBuilder) {
+        nxActionLearnBuilder.setFlags(nxAction.getNxLearn().getFlags());
+        nxActionLearnBuilder.setCookie(nxAction.getNxLearn().getCookie());
+        nxActionLearnBuilder.setFinHardTimeout(nxAction.getNxLearn().getFinHardTimeout());
+        nxActionLearnBuilder.setFinIdleTimeout(nxAction.getNxLearn().getFinIdleTimeout());
+        nxActionLearnBuilder.setHardTimeout(nxAction.getNxLearn().getHardTimeout());
+        nxActionLearnBuilder.setIdleTimeout(nxAction.getNxLearn().getIdleTimeout());
+        nxActionLearnBuilder.setPriority(nxAction.getNxLearn().getPriority());
+        nxActionLearnBuilder.setTableId(nxAction.getNxLearn().getTableId());
+        nxActionLearnBuilder.setFlowMods(getFlowMods(nxAction.getNxLearn()));
+    }
+
+    private static List<org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.learn.grouping.nx.action.learn.FlowMods> getFlowMods(
+            NxLearn nxLearn) {
+        if(nxLearn.getFlowMods() == null){
+            return null;
+        }
+
+        List<org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.learn.grouping.nx.action.learn.FlowMods> flowMods = new ArrayList<>();
+        for(FlowMods flowMod : nxLearn.getFlowMods()){
+            org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.learn.grouping.nx.action.learn.FlowModsBuilder flowModBuilder = new org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.learn.grouping.nx.action.learn.FlowModsBuilder();
+            org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.FlowModSpec flowModSpec = buildFlowModSpec(flowMod.getFlowModSpec());
+            flowModBuilder.setFlowModSpec(flowModSpec);
+            flowMods.add(flowModBuilder.build());
+        }
+        return flowMods;
+    }
+
+    private static org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.FlowModSpec buildFlowModSpec(FlowModSpec flowModSpec) {
+        if(flowModSpec instanceof FlowModAddMatchFromFieldCase){
+            FlowModAddMatchFromField flowModAdd2 = ((FlowModAddMatchFromFieldCase) flowModSpec).getFlowModAddMatchFromField();
+            org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.add.match.from.field._case.FlowModAddMatchFromFieldBuilder 
+                flowModAdd = new org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.add.match.from.field._case.FlowModAddMatchFromFieldBuilder();
+            flowModAdd.setDstField(flowModAdd2.getDstField());
+            flowModAdd.setSrcField(flowModAdd2.getSrcField());
+            flowModAdd.setDstOfs(flowModAdd2.getDstOfs());
+            flowModAdd.setSrcOfs(flowModAdd2.getSrcOfs());
+            flowModAdd.setFlowModNumBits(flowModAdd2.getFlowModNumBits());
+            org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromFieldCaseBuilder 
+                caseBuilder = new org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromFieldCaseBuilder();
+            caseBuilder.setFlowModAddMatchFromField(flowModAdd.build());
+            return caseBuilder.build();
+        } else if(flowModSpec instanceof FlowModAddMatchFromValueCase){
+            FlowModAddMatchFromValue flowModAdd2 = ((FlowModAddMatchFromValueCase) flowModSpec).getFlowModAddMatchFromValue();
+            org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.add.match.from.value._case.FlowModAddMatchFromValueBuilder 
+                flowModAdd = new org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.add.match.from.value._case.FlowModAddMatchFromValueBuilder();
+            flowModAdd.setValue(flowModAdd2.getValue());
+            flowModAdd.setSrcField(flowModAdd2.getSrcField());
+            flowModAdd.setSrcOfs(flowModAdd2.getSrcOfs());
+            flowModAdd.setFlowModNumBits(flowModAdd2.getFlowModNumBits());
+            org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromValueCaseBuilder 
+                caseBuilder = new org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromValueCaseBuilder();
+            caseBuilder.setFlowModAddMatchFromValue(flowModAdd.build());
+            return caseBuilder.build();
+        } else if(flowModSpec instanceof FlowModCopyFieldIntoFieldCase){
+            FlowModCopyFieldIntoField flowModCopy2 = ((FlowModCopyFieldIntoFieldCase) flowModSpec).getFlowModCopyFieldIntoField();
+            org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.copy.field.into.field._case.FlowModCopyFieldIntoFieldBuilder 
+                flowModCopy = new org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.copy.field.into.field._case.FlowModCopyFieldIntoFieldBuilder();
+            flowModCopy.setDstField(flowModCopy2.getDstField());
+            flowModCopy.setDstOfs(flowModCopy2.getDstOfs());
+            flowModCopy.setSrcField(flowModCopy2.getSrcField());
+            flowModCopy.setSrcOfs(flowModCopy2.getSrcOfs());
+            flowModCopy.setFlowModNumBits(flowModCopy2.getFlowModNumBits());
+            org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModCopyFieldIntoFieldCaseBuilder 
+                caseBuilder = new org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModCopyFieldIntoFieldCaseBuilder();
+            caseBuilder.setFlowModCopyFieldIntoField(flowModCopy.build());
+            return caseBuilder.build();
+        } else if (flowModSpec instanceof FlowModCopyValueIntoFieldCase) {
+            FlowModCopyValueIntoField flowModCopy2 = ((FlowModCopyValueIntoFieldCase) flowModSpec).getFlowModCopyValueIntoField();
+            org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.copy.value.into.field._case.FlowModCopyValueIntoFieldBuilder 
+                flowModCopy = new org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.copy.value.into.field._case.FlowModCopyValueIntoFieldBuilder();
+            flowModCopy.setDstField(flowModCopy2.getDstField());
+            flowModCopy.setDstOfs(flowModCopy2.getDstOfs());
+            flowModCopy.setValue(flowModCopy2.getValue());
+            flowModCopy.setFlowModNumBits(flowModCopy2.getFlowModNumBits());
+            org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModCopyValueIntoFieldCaseBuilder 
+                caseBuilder = new org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModCopyValueIntoFieldCaseBuilder();
+            caseBuilder.setFlowModCopyValueIntoField(flowModCopy.build());
+            return caseBuilder.build();
+        } else if (flowModSpec instanceof FlowModOutputToPortCase) {
+            FlowModOutputToPort flowModOut2 = ((FlowModOutputToPortCase) flowModSpec).getFlowModOutputToPort();
+            org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.output.to.port._case.FlowModOutputToPortBuilder 
+                flowModOut = new org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.output.to.port._case.FlowModOutputToPortBuilder();
+            flowModOut.setSrcField(flowModOut2.getSrcField());
+            flowModOut.setSrcOfs(flowModOut2.getSrcOfs());
+            flowModOut.setFlowModNumBits(flowModOut2.getFlowModNumBits());
+            org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModOutputToPortCaseBuilder 
+                caseBuilder = new org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModOutputToPortCaseBuilder();
+            caseBuilder.setFlowModOutputToPort(flowModOut.build());
+            return caseBuilder.build();
+        }
+        return null;
+    }
+
+}
index 48f807bffea72aa987b4b94fee0944d82eef2569..c983e595288a6e9ae814aa9e3aa744baac5aeeee 100644 (file)
@@ -451,6 +451,147 @@ bits specified from the register.";
             }
         }
     }
+
+    grouping flow-mod-spec {
+        description
+           "flow mod spec indicates the actions that should be performed to create a new flow which was learned from learn action.";
+        choice flow-mod-spec{
+            case flow-mod-add-match-from-field-case{
+                container flow-mod-add-match-from-field{
+                        leaf flow-mod-num-bits{
+                        type uint16;
+                    }
+
+                    leaf src-field{
+                        type uint32;
+                    }
+
+                    leaf src-ofs{
+                        type uint16;
+                    }
+
+                    leaf dst-field{
+                        type uint32;
+                    }
+
+                    leaf dst-ofs{
+                        type uint16;
+                    }
+                }
+            }
+            case flow-mod-add-match-from-value-case{
+                container flow-mod-add-match-from-value{
+                        leaf flow-mod-num-bits{
+                        type uint16;
+                    }
+
+                    leaf value{
+                        type uint16;
+                    }
+
+                    leaf src-field{
+                        type uint32;
+                    }
+
+                    leaf src-ofs{
+                        type uint16;
+                    }
+                }
+            }
+            case flow-mod-copy-field-into-field-case{
+                container flow-mod-copy-field-into-field{
+                        leaf flow-mod-num-bits{
+                        type uint16;
+                    }
+
+                    leaf src-field{
+                        type uint32;
+                    }
+
+                    leaf src-ofs{
+                        type uint16;
+                    }
+
+                    leaf dst-field{
+                        type uint32;
+                    }
+
+                    leaf dst-ofs{
+                        type uint16;
+                    }
+                }
+            }
+            case flow-mod-copy-value-into-field-case{
+                container flow-mod-copy-value-into-field{
+                        leaf flow-mod-num-bits{
+                        type uint16;
+                    }
+
+                    leaf value{
+                        type uint16;
+                    }
+
+                    leaf dst-field{
+                        type uint32;
+                    }
+
+                    leaf dst-ofs{
+                        type uint16;
+                    }
+                }
+            }
+            case flow-mod-output-to-port-case{
+                container flow-mod-output-to-port{
+                        leaf flow-mod-num-bits{
+                        type uint16;
+                    }
+
+                    leaf src-field{
+                        type uint32;
+                    }
+
+                    leaf src-ofs{
+                        type uint16;
+                    }
+                }
+            }
+        }
+    }
+
+    grouping nx-action-learn-grouping {
+        container nx-learn {
+            leaf idle-timeout {
+                type uint16;
+            }
+            leaf hard-timeout {
+                type uint16;
+            }
+            leaf priority {
+                type uint16;
+            }
+            leaf cookie {
+                type uint64;
+            }
+            leaf flags {
+                type uint16;
+            }
+            leaf table-id {
+                type uint8;
+            }
+            leaf fin-idle-timeout {
+                type uint16;
+            }
+            leaf fin-hard-timeout {
+                type uint16;
+            }
+
+            list flow-mods{
+                uses flow-mod-spec;
+            }
+        }
+    }
+
+
     // ACTION augmentations
     // RPCS
     augment "/sal-flow:add-flow/sal-flow:input/sal-flow:instructions/sal-flow:instruction/sal-flow:instruction/sal-flow:write-actions-case/sal-flow:write-actions/sal-flow:action/sal-flow:action" {
@@ -488,11 +629,16 @@ bits specified from the register.";
             uses nx-action-pop-nsh-grouping;
         }
     }
-     augment "/sal-flow:add-flow/sal-flow:input/sal-flow:instructions/sal-flow:instruction/sal-flow:instruction/sal-flow:write-actions-case/sal-flow:write-actions/sal-flow:action/sal-flow:action" {
+    augment "/sal-flow:add-flow/sal-flow:input/sal-flow:instructions/sal-flow:instruction/sal-flow:instruction/sal-flow:write-actions-case/sal-flow:write-actions/sal-flow:action/sal-flow:action" {
         case nx-action-conntrack-rpc-add-flow-write-actions-case {
             uses nx-action-conntrack-grouping;
         }
     }
+    augment "/sal-flow:add-flow/sal-flow:input/sal-flow:instructions/sal-flow:instruction/sal-flow:instruction/sal-flow:write-actions-case/sal-flow:write-actions/sal-flow:action/sal-flow:action" {
+        case nx-action-learn-rpc-add-flow-write-actions-case {
+            uses nx-action-learn-grouping;
+        }
+    }
 
     augment "/sal-flow:add-flow/sal-flow:input/sal-flow:instructions/sal-flow:instruction/sal-flow:instruction/sal-flow:apply-actions-case/sal-flow:apply-actions/sal-flow:action/sal-flow:action" {
         case nx-action-reg-load-rpc-add-flow-apply-actions-case {
@@ -535,6 +681,11 @@ bits specified from the register.";
             uses nx-action-conntrack-grouping;
         }
     }
+    augment "/sal-flow:add-flow/sal-flow:input/sal-flow:instructions/sal-flow:instruction/sal-flow:instruction/sal-flow:apply-actions-case/sal-flow:apply-actions/sal-flow:action/sal-flow:action" {
+        case nx-action-learn-rpc-add-flow-apply-actions-case {
+            uses nx-action-learn-grouping;
+        }
+    }
 
     augment "/sal-flow:remove-flow/sal-flow:input/sal-flow:instructions/sal-flow:instruction/sal-flow:instruction/sal-flow:write-actions-case/sal-flow:write-actions/sal-flow:action/sal-flow:action" {
         case "nx-action-reg-load-rpc-remove-flow-write-actions-case" {
@@ -576,6 +727,11 @@ bits specified from the register.";
             uses nx-action-conntrack-grouping;
         }
     }
+    augment "/sal-flow:remove-flow/sal-flow:input/sal-flow:instructions/sal-flow:instruction/sal-flow:instruction/sal-flow:write-actions-case/sal-flow:write-actions/sal-flow:action/sal-flow:action" {
+        case nx-action-learn-rpc-remove-flow-write-actions-case {
+            uses nx-action-learn-grouping;
+        }
+    }
 
     augment "/sal-flow:remove-flow/sal-flow:input/sal-flow:instructions/sal-flow:instruction/sal-flow:instruction/sal-flow:apply-actions-case/sal-flow:apply-actions/sal-flow:action/sal-flow:action" {
         case "nx-action-reg-load-rpc-remove-flow-apply-actions-case" {
@@ -617,6 +773,11 @@ bits specified from the register.";
             uses nx-action-conntrack-grouping;
         }
     }
+    augment "/sal-flow:remove-flow/sal-flow:input/sal-flow:instructions/sal-flow:instruction/sal-flow:instruction/sal-flow:apply-actions-case/sal-flow:apply-actions/sal-flow:action/sal-flow:action" {
+        case nx-action-learn-rpc-remove-flow-apply-actions-case {
+            uses nx-action-learn-grouping;
+        }
+    }
 
     augment "/sal-flow:update-flow/sal-flow:input/sal-flow:original-flow/sal-flow:instructions/sal-flow:instruction/sal-flow:instruction/sal-flow:write-actions-case/sal-flow:write-actions/sal-flow:action/sal-flow:action" {
         case "nx-action-reg-load-rpc-update-flow-original-write-actions-case" {
@@ -658,6 +819,11 @@ bits specified from the register.";
             uses nx-action-conntrack-grouping;
         }
     }
+    augment "/sal-flow:update-flow/sal-flow:input/sal-flow:original-flow/sal-flow:instructions/sal-flow:instruction/sal-flow:instruction/sal-flow:write-actions-case/sal-flow:write-actions/sal-flow:action/sal-flow:action" {
+        case "nx-action-learn-rpc-update-flow-original-write-actions-case" {
+            uses nx-action-learn-grouping;
+        }
+    }
 
     augment "/sal-flow:update-flow/sal-flow:input/sal-flow:original-flow/sal-flow:instructions/sal-flow:instruction/sal-flow:instruction/sal-flow:apply-actions-case/sal-flow:apply-actions/sal-flow:action/sal-flow:action" {
         case "nx-action-reg-load-rpc-update-flow-original-apply-actions-case" {
@@ -699,6 +865,11 @@ bits specified from the register.";
             uses nx-action-conntrack-grouping;
         }
     }
+    augment "/sal-flow:update-flow/sal-flow:input/sal-flow:original-flow/sal-flow:instructions/sal-flow:instruction/sal-flow:instruction/sal-flow:apply-actions-case/sal-flow:apply-actions/sal-flow:action/sal-flow:action" {
+        case "nx-action-learn-rpc-update-flow-original-apply-actions-case" {
+            uses nx-action-learn-grouping;
+        }
+    }
 
     augment "/sal-flow:update-flow/sal-flow:input/sal-flow:updated-flow/sal-flow:instructions/sal-flow:instruction/sal-flow:instruction/sal-flow:write-actions-case/sal-flow:write-actions/sal-flow:action/sal-flow:action" {
         case "nx-action-reg-load-rpc-update-flow-updated-write-actions-case" {
@@ -735,11 +906,16 @@ bits specified from the register.";
             uses nx-action-pop-nsh-grouping;
         }
     }
-     augment "/sal-flow:update-flow/sal-flow:input/sal-flow:updated-flow/sal-flow:instructions/sal-flow:instruction/sal-flow:instruction/sal-flow:write-actions-case/sal-flow:write-actions/sal-flow:action/sal-flow:action" {
+    augment "/sal-flow:update-flow/sal-flow:input/sal-flow:updated-flow/sal-flow:instructions/sal-flow:instruction/sal-flow:instruction/sal-flow:write-actions-case/sal-flow:write-actions/sal-flow:action/sal-flow:action" {
         case "nx-action-conntrack-rpc-update-flow-updated-write-actions-case" {
             uses nx-action-conntrack-grouping;
         }
     }
+    augment "/sal-flow:update-flow/sal-flow:input/sal-flow:updated-flow/sal-flow:instructions/sal-flow:instruction/sal-flow:instruction/sal-flow:write-actions-case/sal-flow:write-actions/sal-flow:action/sal-flow:action" {
+        case "nx-action-learn-rpc-update-flow-updated-write-actions-case" {
+            uses nx-action-learn-grouping;
+        }
+    }
 
     augment "/sal-flow:update-flow/sal-flow:input/sal-flow:updated-flow/sal-flow:instructions/sal-flow:instruction/sal-flow:instruction/sal-flow:apply-actions-case/sal-flow:apply-actions/sal-flow:action/sal-flow:action" {
         case "nx-action-reg-load-rpc-update-flow-updated-apply-actions-case" {
@@ -781,6 +957,11 @@ bits specified from the register.";
             uses nx-action-conntrack-grouping;
         }
     }
+    augment "/sal-flow:update-flow/sal-flow:input/sal-flow:updated-flow/sal-flow:instructions/sal-flow:instruction/sal-flow:instruction/sal-flow:apply-actions-case/sal-flow:apply-actions/sal-flow:action/sal-flow:action" {
+        case "nx-action-learn-rpc-update-flow-updated-apply-actions-case" {
+            uses nx-action-learn-grouping;
+        }
+    }
 
     augment "/sal-group:add-group/sal-group:input/sal-group:buckets/sal-group:bucket/sal-group:action/sal-group:action" {
         case "nx-action-reg-load-rpc-add-group-case" {
@@ -822,6 +1003,11 @@ bits specified from the register.";
             uses nx-action-conntrack-grouping;
         }
     }
+    augment "/sal-group:add-group/sal-group:input/sal-group:buckets/sal-group:bucket/sal-group:action/sal-group:action" {
+        case "nx-action-learn-rpc-add-group-case" {
+            uses nx-action-learn-grouping;
+        }
+    }
 
     augment "/sal-group:remove-group/sal-group:input/sal-group:buckets/sal-group:bucket/sal-group:action/sal-group:action" {
         case "nx-action-reg-load-rpc-remove-group-case" {
@@ -863,6 +1049,11 @@ bits specified from the register.";
             uses nx-action-conntrack-grouping;
         }
     }
+    augment "/sal-group:remove-group/sal-group:input/sal-group:buckets/sal-group:bucket/sal-group:action/sal-group:action" {
+        case "nx-action-learn-rpc-remove-group-case" {
+            uses nx-action-learn-grouping;
+        }
+    }
 
     augment "/sal-group:update-group/sal-group:input/sal-group:original-group/sal-group:buckets/sal-group:bucket/sal-group:action/sal-group:action" {
         case "nx-action-reg-load-rpc-update-group-original-case" {
@@ -904,6 +1095,11 @@ bits specified from the register.";
             uses nx-action-conntrack-grouping;
         }
     }
+    augment "/sal-group:update-group/sal-group:input/sal-group:original-group/sal-group:buckets/sal-group:bucket/sal-group:action/sal-group:action" {
+        case "nx-action-learn-rpc-update-group-original-case" {
+            uses nx-action-learn-grouping;
+        }
+    }
 
     augment "/sal-group:update-group/sal-group:input/sal-group:updated-group/sal-group:buckets/sal-group:bucket/sal-group:action/sal-group:action" {
         case "nx-action-reg-load-rpc-update-group-updated-case" {
@@ -945,6 +1141,11 @@ bits specified from the register.";
             uses nx-action-conntrack-grouping;
         }
     }
+    augment "/sal-group:update-group/sal-group:input/sal-group:updated-group/sal-group:buckets/sal-group:bucket/sal-group:action/sal-group:action" {
+        case "nx-action-learn-rpc-update-group-updated-case" {
+            uses nx-action-learn-grouping;
+        }
+    }
 
     augment "/sal-packet:transmit-packet/sal-packet:input/sal-packet:action/sal-packet:action" {
         case "nx-action-reg-load-rpc-transmit-packet-case" {
@@ -986,6 +1187,11 @@ bits specified from the register.";
             uses nx-action-conntrack-grouping;
         }
     }
+    augment "/sal-packet:transmit-packet/sal-packet:input/sal-packet:action/sal-packet:action" {
+        case "nx-action-learn-rpc-transmit-packet-case" {
+            uses nx-action-learn-grouping;
+        }
+    }
 
     // DATA
     augment "/inv:nodes/inv:node/fni:table/fni:flow/fni:instructions/fni:instruction/fni:instruction/fni:write-actions-case/fni:write-actions/fni:action/fni:action" {
@@ -1028,6 +1234,11 @@ bits specified from the register.";
             uses nx-action-conntrack-grouping;
         }
     }
+    augment "/inv:nodes/inv:node/fni:table/fni:flow/fni:instructions/fni:instruction/fni:instruction/fni:write-actions-case/fni:write-actions/fni:action/fni:action" {
+        case "nx-action-learn-nodes-node-table-flow-write-actions-case" {
+            uses nx-action-learn-grouping;
+        }
+    }
 
     augment "/inv:nodes/inv:node/fni:table/fni:flow/fni:instructions/fni:instruction/fni:instruction/fni:apply-actions-case/fni:apply-actions/fni:action/fni:action" {
         case "nx-action-reg-load-nodes-node-table-flow-apply-actions-case" {
@@ -1069,6 +1280,11 @@ bits specified from the register.";
             uses nx-action-conntrack-grouping;
         }
     }
+    augment "/inv:nodes/inv:node/fni:table/fni:flow/fni:instructions/fni:instruction/fni:instruction/fni:apply-actions-case/fni:apply-actions/fni:action/fni:action" {
+        case "nx-action-learn-nodes-node-table-flow-apply-actions-case" {
+            uses nx-action-learn-grouping;
+        }
+    }
 
     augment "/inv:nodes/inv:node/fni:group/fni:buckets/fni:bucket/fni:action/fni:action" {
         case "nx-action-reg-load-nodes-node-group-buckets-bucket-actions-case" {
@@ -1110,6 +1326,11 @@ bits specified from the register.";
             uses nx-action-conntrack-grouping;
         }
     }
+    augment "/inv:nodes/inv:node/fni:group/fni:buckets/fni:bucket/fni:action/fni:action" {
+        case "nx-action-learn-nodes-node-group-buckets-bucket-actions-case" {
+            uses nx-action-learn-grouping;
+        }
+    }
 
     // NOTIFICATIONS
     augment "/odl-flow-stats:flows-statistics-update/odl-flow-stats:flow-and-statistics-map-list/odl-flow-stats:instructions/odl-flow-stats:instruction/odl-flow-stats:instruction/odl-flow-stats:write-actions-case/odl-flow-stats:write-actions/odl-flow-stats:action/odl-flow-stats:action" {
@@ -1152,6 +1373,11 @@ bits specified from the register.";
             uses nx-action-conntrack-grouping;
         }
     }
+    augment "/odl-flow-stats:flows-statistics-update/odl-flow-stats:flow-and-statistics-map-list/odl-flow-stats:instructions/odl-flow-stats:instruction/odl-flow-stats:instruction/odl-flow-stats:write-actions-case/odl-flow-stats:write-actions/odl-flow-stats:action/odl-flow-stats:action" {
+        case "nx-action-learn-notif-flows-statistics-update-write-actions-case" {
+            uses nx-action-learn-grouping;
+        }
+    }
 
     augment "/odl-flow-stats:flows-statistics-update/odl-flow-stats:flow-and-statistics-map-list/odl-flow-stats:instructions/odl-flow-stats:instruction/odl-flow-stats:instruction/odl-flow-stats:apply-actions-case/odl-flow-stats:apply-actions/odl-flow-stats:action/odl-flow-stats:action" {
         case "nx-action-reg-load-notif-flows-statistics-update-apply-actions-case" {
@@ -1193,6 +1419,11 @@ bits specified from the register.";
             uses nx-action-conntrack-grouping;
         }
     }
+    augment "/odl-flow-stats:flows-statistics-update/odl-flow-stats:flow-and-statistics-map-list/odl-flow-stats:instructions/odl-flow-stats:instruction/odl-flow-stats:instruction/odl-flow-stats:apply-actions-case/odl-flow-stats:apply-actions/odl-flow-stats:action/odl-flow-stats:action" {
+        case "nx-action-learn-notif-flows-statistics-update-apply-actions-case" {
+            uses nx-action-learn-grouping;
+        }
+    }
 
     augment "/odl-group-stats:group-desc-stats-updated/odl-group-stats:group-desc-stats/odl-group-stats:buckets/odl-group-stats:bucket/odl-group-stats:action/odl-group-stats:action" {
         case "nx-action-reg-load-notif-group-desc-stats-updated-case" {
@@ -1229,9 +1460,14 @@ bits specified from the register.";
             uses nx-action-pop-nsh-grouping;
         }
     }
-     augment "/odl-group-stats:group-desc-stats-updated/odl-group-stats:group-desc-stats/odl-group-stats:buckets/odl-group-stats:bucket/odl-group-stats:action/odl-group-stats:action" {
+    augment "/odl-group-stats:group-desc-stats-updated/odl-group-stats:group-desc-stats/odl-group-stats:buckets/odl-group-stats:bucket/odl-group-stats:action/odl-group-stats:action" {
         case "nx-action-conntrack-notif-group-desc-stats-updated-case" {
             uses nx-action-conntrack-grouping;
         }
     }
+    augment "/odl-group-stats:group-desc-stats-updated/odl-group-stats:group-desc-stats/odl-group-stats:buckets/odl-group-stats:bucket/odl-group-stats:action/odl-group-stats:action" {
+        case "nx-action-learn-notif-group-desc-stats-updated-case" {
+            uses nx-action-learn-grouping;
+        }
+    }
 }