Merge "Bug 8535: Fix IPv6 OXMHeader Mask issue"
authorAnil Vishnoi <vishnoianil@gmail.com>
Thu, 25 May 2017 18:17:25 +0000 (18:17 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Thu, 25 May 2017 18:17:25 +0000 (18:17 +0000)
55 files changed:
applications/bulk-o-matic/src/main/java/org/opendaylight/openflowplugin/applications/bulk/o/matic/BulkOMaticUtils.java
applications/bulk-o-matic/src/main/java/org/opendaylight/openflowplugin/applications/bulk/o/matic/FlowCounter.java
applications/bulk-o-matic/src/main/java/org/opendaylight/openflowplugin/applications/bulk/o/matic/FlowCounterMBean.java
applications/bulk-o-matic/src/main/java/org/opendaylight/openflowplugin/applications/bulk/o/matic/FlowReader.java
applications/bulk-o-matic/src/main/java/org/opendaylight/openflowplugin/applications/bulk/o/matic/FlowWriterConcurrent.java
applications/bulk-o-matic/src/main/java/org/opendaylight/openflowplugin/applications/bulk/o/matic/FlowWriterDirectOFRpc.java
applications/bulk-o-matic/src/main/java/org/opendaylight/openflowplugin/applications/bulk/o/matic/FlowWriterSequential.java
applications/bulk-o-matic/src/main/java/org/opendaylight/openflowplugin/applications/bulk/o/matic/FlowWriterTxChain.java
applications/bulk-o-matic/src/main/java/org/opendaylight/openflowplugin/applications/bulk/o/matic/SalBulkFlowServiceImpl.java
applications/bulk-o-matic/src/main/java/org/opendaylight/openflowplugin/applications/bulk/o/matic/TableWriter.java [new file with mode: 0644]
applications/bulk-o-matic/src/main/yang/sal-bulk-flow.yang
applications/bulk-o-matic/src/test/java/org/opendaylight/openflowplugin/applications/bulk/o/matic/FlowWriterConcurrentTest.java
applications/bulk-o-matic/src/test/java/org/opendaylight/openflowplugin/applications/bulk/o/matic/FlowWriterSequentialTest.java
applications/bulk-o-matic/src/test/java/org/opendaylight/openflowplugin/applications/bulk/o/matic/FlowWriterTxChainTest.java
applications/bulk-o-matic/src/test/java/org/opendaylight/openflowplugin/applications/bulk/o/matic/SalBulkFlowServiceImplTest.java
applications/bulk-o-matic/src/test/java/org/opendaylight/openflowplugin/applications/bulk/o/matic/TableWriterTest.java [new file with mode: 0644]
applications/inventory-manager/src/main/java/org/opendaylight/openflowplugin/applications/inventory/manager/InventoryMapping.java
distribution/karaf/pom.xml
extension/openflowjava-extension-nicira/src/main/java/org/opendaylight/openflowjava/nx/NiciraMatchCodecs.java
extension/openflowjava-extension-nicira/src/main/java/org/opendaylight/openflowjava/nx/codec/action/ConntrackCodec.java
extension/openflowjava-extension-nicira/src/main/java/org/opendaylight/openflowjava/nx/codec/match/Ipv6DstCodec.java [new file with mode: 0644]
extension/openflowjava-extension-nicira/src/main/java/org/opendaylight/openflowjava/nx/codec/match/Ipv6SrcCodec.java [new file with mode: 0644]
extension/openflowjava-extension-nicira/src/test/java/org/opendaylight/openflowjava/nx/codec/action/ConntrackCodecTest.java
extension/openflowjava-extension-nicira/src/test/java/org/opendaylight/openflowjava/nx/codec/match/Ipv6DstCodecTest.java [new file with mode: 0644]
extension/openflowjava-extension-nicira/src/test/java/org/opendaylight/openflowjava/nx/codec/match/Ipv6SrcCodecTest.java [new file with mode: 0644]
extension/openflowplugin-extension-nicira/src/main/java/org/opendaylight/openflowplugin/extension/vendor/nicira/convertor/action/RegMoveConvertor.java
extension/openflowplugin-extension-nicira/src/main/yang/openflowplugin-extension-nicira-action.yang
model/model-flow-service/src/main/yang/flow-node-inventory.yang
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/OFPContext.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/connection/ConnectionContext.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/DeviceContext.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/lifecycle/ContextChain.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/lifecycle/ContextChainStateListener.java [new file with mode: 0644]
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/lifecycle/MastershipChangeListener.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/connection/ConnectionContextImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/connection/listener/HandshakeListenerImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/connection/listener/OpenflowProtocolListenerInitialImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/PortStatsMultipartWriter.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/DeviceContextImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/DeviceManagerImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/TransactionChainManager.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/initialization/AbstractDeviceInitializer.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/lifecycle/ContextChainHolderImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/lifecycle/ContextChainImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/lifecycle/LifecycleServiceImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/serialization/match/MatchSerializer.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsContextImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/translator/PortUpdateTranslator.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/connection/listener/HandshakeListenerImplTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/lifecycle/ContextChainImplTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/lifecycle/LifecycleServiceImplTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/translator/PortUpdateTranslatorTest.java
openflowplugin-it/pom.xml
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/util/PortTranslatorUtil.java
parent/pom.xml

index 8c80b15b03653c6d7c03a5e22f1d4d0e0ccaab3b..8a750d56e397007ad085a199084f7d2f28d29302 100644 (file)
@@ -32,6 +32,7 @@ public final class BulkOMaticUtils {
 
     public static final int DEFUALT_STATUS = FlowCounter.OperationStatus.INIT.status();
     public static final int DEFAULT_FLOW_COUNT = 0;
+    public static final int DEFAULT_TABLE_COUNT = 0;
     public static final long DEFAULT_COMPLETION_TIME = 0;
     public static final String DEFAULT_UNITS = "ns";
     public static final String DEVICE_TYPE_PREFIX = "openflow:";
index f0c42537b688642fdf560df52118edcb79363784..32716eaaada2ede3559c3c51450055852f8ac796 100644 (file)
@@ -78,4 +78,12 @@ public class FlowCounter implements FlowCounterMBean {
             return BulkOMaticUtils.DEFAULT_UNITS;
         }
     }
+
+    @Override
+    public long getTableCount() {
+        if (writer != null) {
+            return writer.getTableCount();
+        }
+        return BulkOMaticUtils.DEFAULT_TABLE_COUNT;
+    }
 }
index 7d5de72fcf23787ee1abe9ef0b5113453614e23f..b1ddb4a6fceb46bcd6109f6bf4643e2421b4d935 100644 (file)
@@ -9,14 +9,28 @@ package org.opendaylight.openflowplugin.applications.bulk.o.matic;
 
 public interface FlowCounterMBean {
 
-    public long getFlowCount();
+    default public long getFlowCount() {
+        return BulkOMaticUtils.DEFAULT_FLOW_COUNT;
+    }
 
-    public int getReadOpStatus();
+    default public int getReadOpStatus() {
+        return BulkOMaticUtils.DEFUALT_STATUS;
+    }
 
-    public int getWriteOpStatus();
+    default public int getWriteOpStatus() {
+        return BulkOMaticUtils.DEFUALT_STATUS;
+    }
 
-    public long getTaskCompletionTime();
+    default public long getTaskCompletionTime() {
+        return BulkOMaticUtils.DEFAULT_COMPLETION_TIME;
+    }
 
-    public String getUnits();
+    default public String getUnits() {
+        return BulkOMaticUtils.DEFAULT_UNITS;
+    }
+
+    default public long getTableCount() {
+        return BulkOMaticUtils.DEFAULT_TABLE_COUNT;
+    }
 }
 
index 3796081892a79f570c5f702ca56a7aae85f29986..70c3bbbeb58b877832daa0162ebcf5d9be4e344d 100644 (file)
@@ -8,6 +8,8 @@
 package org.opendaylight.openflowplugin.applications.bulk.o.matic;
 
 import com.google.common.base.Optional;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
@@ -26,9 +28,6 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
-
 public class FlowReader implements Runnable, FlowCounterMBean {
     private static final Logger LOG = LoggerFactory.getLogger(FlowReader.class);
     private final DataBroker dataBroker;
@@ -38,9 +37,8 @@ public class FlowReader implements Runnable, FlowCounterMBean {
     private final short startTableId;
     private final short endTableId;
     private final boolean isConfigDs;
-    private AtomicLong flowCount = new AtomicLong(0);
+    private AtomicLong flowCount = new AtomicLong();
     private AtomicInteger readOpStatus = new AtomicInteger(FlowCounter.OperationStatus.INIT.status());
-    private static final String UNITS = "ns";
 
     private FlowReader(final DataBroker dataBroker,
                       final Integer dpnCount,
@@ -135,19 +133,4 @@ public class FlowReader implements Runnable, FlowCounterMBean {
     public int getReadOpStatus() {
         return readOpStatus.get();
     }
-
-    @Override
-    public int getWriteOpStatus() {
-        return BulkOMaticUtils.DEFUALT_STATUS;
-    }
-
-    @Override
-    public long getTaskCompletionTime() {
-        return BulkOMaticUtils.DEFAULT_COMPLETION_TIME;
-    }
-
-    @Override
-    public String getUnits() {
-        return UNITS;
-    }
 }
\ No newline at end of file
index 96904bd8d6a460d6dadaefa1d587b49407dd89f2..65c014db380be0dd9ed17ddcde271a7a512186ae 100644 (file)
@@ -9,6 +9,9 @@ package org.opendaylight.openflowplugin.applications.bulk.o.matic;
 
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
@@ -18,10 +21,6 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
-
 public class FlowWriterConcurrent implements FlowCounterMBean {
     private static final Logger LOG = LoggerFactory.getLogger(FlowWriterConcurrent.class);
     public static final String USING_CONCURRENT_IMPLEMENTATION_OF_FLOW_WRITER = "Using Concurrent implementation of Flow Writer.";
@@ -29,9 +28,8 @@ public class FlowWriterConcurrent implements FlowCounterMBean {
     private final ExecutorService flowPusher;
     private long startTime;
     private AtomicInteger writeOpStatus = new AtomicInteger(FlowCounter.OperationStatus.INIT.status());
-    private AtomicInteger countDpnWriteCompletion = new AtomicInteger(0);
-    private AtomicLong taskCompletionTime = new AtomicLong(0);
-    private static final String UNITS = "ns";
+    private AtomicInteger countDpnWriteCompletion = new AtomicInteger();
+    private AtomicLong taskCompletionTime = new AtomicLong();
 
     public FlowWriterConcurrent(final DataBroker dataBroker, ExecutorService flowPusher) {
         this.dataBroker = dataBroker;
@@ -40,13 +38,14 @@ public class FlowWriterConcurrent implements FlowCounterMBean {
     }
 
     public void addFlows(Integer dpnCount, Integer flowsPerDPN, int batchSize,
-                         int sleepMillis, int sleepAfter, short startTableId, short endTableId) {
+                         int sleepMillis, int sleepAfter, short startTableId, short endTableId,
+                         boolean isCreateParents) {
         LOG.info(USING_CONCURRENT_IMPLEMENTATION_OF_FLOW_WRITER);
         countDpnWriteCompletion.set(dpnCount);
         startTime = System.nanoTime();
         for (int i = 1; i <= dpnCount; i++) {
             FlowHandlerTask task = new FlowHandlerTask(Integer.toString(i),
-                    flowsPerDPN, true, batchSize, sleepMillis, sleepAfter, startTableId, endTableId);
+                    flowsPerDPN, true, batchSize, sleepMillis, sleepAfter, startTableId, endTableId, isCreateParents);
             flowPusher.execute(task);
         }
     }
@@ -57,21 +56,11 @@ public class FlowWriterConcurrent implements FlowCounterMBean {
         countDpnWriteCompletion.set(dpnCount);
         for (int i = 1; i <= dpnCount; i++) {
             FlowHandlerTask task = new FlowHandlerTask(Integer.toString(i), flowsPerDPN, false, batchSize,
-                    0, 1, startTableId, endTableId);
+                    0, 1, startTableId, endTableId, false);
             flowPusher.execute(task);
         }
     }
 
-    @Override
-    public long getFlowCount() {
-        return BulkOMaticUtils.DEFAULT_FLOW_COUNT;
-    }
-
-    @Override
-    public int getReadOpStatus() {
-        return BulkOMaticUtils.DEFUALT_STATUS;
-    }
-
     @Override
     public int getWriteOpStatus() {
         return writeOpStatus.get();
@@ -82,11 +71,6 @@ public class FlowWriterConcurrent implements FlowCounterMBean {
         return taskCompletionTime.get();
     }
 
-    @Override
-    public String getUnits() {
-        return UNITS;
-    }
-
     private class FlowHandlerTask implements Runnable {
         private final String dpId;
         private final boolean add;
@@ -97,6 +81,7 @@ public class FlowWriterConcurrent implements FlowCounterMBean {
         private final short startTableId;
         private final short endTableId;
         private AtomicInteger remainingTxReturn = new AtomicInteger(0);
+        private final boolean isCreateParents;
 
         public FlowHandlerTask(final String dpId,
                                final int flowsPerDpn,
@@ -105,7 +90,8 @@ public class FlowWriterConcurrent implements FlowCounterMBean {
                                final int sleepMillis,
                                final int sleepAfter,
                                final short startTableId,
-                               final short endTableId){
+                               final short endTableId,
+                               final boolean isCreateParents){
             this.dpId = BulkOMaticUtils.DEVICE_TYPE_PREFIX + dpId;
             this.add = add;
             this.flowsPerDpn = flowsPerDpn;
@@ -114,6 +100,7 @@ public class FlowWriterConcurrent implements FlowCounterMBean {
             this.sleepAfter = sleepAfter;
             this.startTableId = startTableId;
             this.endTableId = endTableId;
+            this.isCreateParents = isCreateParents;
             remainingTxReturn.set(flowsPerDpn/batchSize);
         }
 
@@ -163,7 +150,7 @@ public class FlowWriterConcurrent implements FlowCounterMBean {
         private void addFlowToTx(WriteTransaction writeTransaction, String flowId, InstanceIdentifier<Flow> flowIid, Flow flow, Integer sourceIp, Short tableId){
             if (add) {
                 LOG.trace("Adding flow for flowId: {}, flowIid: {}", flowId, flowIid);
-                writeTransaction.put(LogicalDatastoreType.CONFIGURATION, flowIid, flow, true);
+                writeTransaction.put(LogicalDatastoreType.CONFIGURATION, flowIid, flow, isCreateParents);
             } else {
                 LOG.trace("Deleting flow for flowId: {}, flowIid: {}", flowId, flowIid);
                 writeTransaction.delete(LogicalDatastoreType.CONFIGURATION, flowIid);
index bfb764c07ac7b39d735699bf65ab4cf6ac9989f7..59d8409e56de777777b31604f05a7997502d3241 100644 (file)
@@ -8,6 +8,12 @@
 package org.opendaylight.openflowplugin.applications.bulk.o.matic;
 
 import com.google.common.base.Optional;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.TimeUnit;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
@@ -27,13 +33,6 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.TimeUnit;
-
 public class FlowWriterDirectOFRpc {
 
     private static final Logger LOG = LoggerFactory.getLogger(FlowWriterDirectOFRpc.class);
index 99436bec24e60dc96f78717cd5df5af4bbe821fc..c6c6b841a8762a785e87aed7708d0b30de32532c 100644 (file)
@@ -9,6 +9,9 @@ package org.opendaylight.openflowplugin.applications.bulk.o.matic;
 
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
@@ -18,10 +21,6 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
-
 public class FlowWriterSequential implements FlowCounterMBean {
     private static final Logger LOG = LoggerFactory.getLogger(FlowWriterSequential.class);
     private final DataBroker dataBroker;
@@ -29,9 +28,8 @@ public class FlowWriterSequential implements FlowCounterMBean {
     protected int dpnCount;
     private long startTime;
     private AtomicInteger writeOpStatus = new AtomicInteger(FlowCounter.OperationStatus.INIT.status());
-    private AtomicInteger countDpnWriteCompletion = new AtomicInteger(0);
-    private AtomicLong taskCompletionTime = new AtomicLong(0);
-    private static final String UNITS = "ns";
+    private AtomicInteger countDpnWriteCompletion = new AtomicInteger();
+    private AtomicLong taskCompletionTime = new AtomicLong();
 
     public FlowWriterSequential(final DataBroker dataBroker, ExecutorService flowPusher) {
         this.dataBroker = dataBroker;
@@ -40,14 +38,14 @@ public class FlowWriterSequential implements FlowCounterMBean {
     }
 
     public void addFlows(Integer dpnCount, Integer flowsPerDPN, int batchSize, int sleepMillis,
-                         short startTableId, short endTableId) {
+                         short startTableId, short endTableId, boolean isCreateParents) {
         LOG.info("Using Sequential implementation of Flow Writer.");
         this.dpnCount = dpnCount;
         countDpnWriteCompletion.set(dpnCount);
         startTime = System.nanoTime();
         for (int i = 1; i <= dpnCount; i++) {
             FlowHandlerTask task = new FlowHandlerTask(Integer.toString(i), flowsPerDPN, true, batchSize,
-                    sleepMillis, startTableId, endTableId);
+                    sleepMillis, startTableId, endTableId, isCreateParents);
             flowPusher.execute(task);
         }
     }
@@ -58,21 +56,11 @@ public class FlowWriterSequential implements FlowCounterMBean {
         countDpnWriteCompletion.set(dpnCount);
         for (int i = 1; i <= dpnCount; i++) {
             FlowHandlerTask task = new FlowHandlerTask(Integer.toString(i), flowsPerDPN, false, batchSize, 0,
-                    startTableId, endTableId);
+                    startTableId, endTableId, false);
             flowPusher.execute(task);
         }
     }
 
-    @Override
-    public long getFlowCount() {
-        return BulkOMaticUtils.DEFAULT_FLOW_COUNT;
-    }
-
-    @Override
-    public int getReadOpStatus() {
-        return BulkOMaticUtils.DEFUALT_STATUS;
-    }
-
     @Override
     public int getWriteOpStatus() {
         return writeOpStatus.get();
@@ -83,11 +71,6 @@ public class FlowWriterSequential implements FlowCounterMBean {
         return taskCompletionTime.get();
     }
 
-    @Override
-    public String getUnits() {
-        return UNITS;
-    }
-
     private class FlowHandlerTask implements Runnable {
         private final String dpId;
         private final int flowsPerDpn;
@@ -96,6 +79,7 @@ public class FlowWriterSequential implements FlowCounterMBean {
         private final int sleepMillis;
         private final short startTableId;
         private final short endTableId;
+        private final boolean isCreateParents;
 
         public FlowHandlerTask(final String dpId,
                                final int flowsPerDpn,
@@ -103,7 +87,8 @@ public class FlowWriterSequential implements FlowCounterMBean {
                                final int batchSize,
                                int sleepMillis,
                                final short startTableId,
-                               final short endTableId){
+                               final short endTableId,
+                               final boolean isCreateParents){
             this.dpId = BulkOMaticUtils.DEVICE_TYPE_PREFIX + dpId;
             this.add = add;
             this.flowsPerDpn = flowsPerDpn;
@@ -111,6 +96,7 @@ public class FlowWriterSequential implements FlowCounterMBean {
             this.sleepMillis = sleepMillis;
             this.startTableId = startTableId;
             this.endTableId = endTableId;
+            this.isCreateParents = isCreateParents;
         }
 
         @Override
@@ -151,7 +137,7 @@ public class FlowWriterSequential implements FlowCounterMBean {
                                  Flow flow) {
             if (add) {
                 LOG.trace("Adding flow for flowId: {}, flowIid: {}", flowId, flowIid);
-                writeTransaction.put(LogicalDatastoreType.CONFIGURATION, flowIid, flow, true);
+                writeTransaction.put(LogicalDatastoreType.CONFIGURATION, flowIid, flow, isCreateParents);
             } else {
                 LOG.trace("Deleting flow for flowId: {}, flowIid: {}", flowId, flowIid);
                 writeTransaction.delete(LogicalDatastoreType.CONFIGURATION, flowIid);
index 3bd424911e165c56d14b66eb04e81833bec9b06b..660b8d0797c9a7a1f2b27bb22d02c10557d9f225 100644 (file)
@@ -9,6 +9,9 @@ package org.opendaylight.openflowplugin.applications.bulk.o.matic;
 
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
 import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
@@ -22,19 +25,14 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
-
 public class FlowWriterTxChain implements FlowCounterMBean {
     private static final Logger LOG = LoggerFactory.getLogger(FlowWriterTxChain.class);
     private final DataBroker dataBroker;
     private final ExecutorService flowPusher;
     private long startTime;
     private AtomicInteger writeOpStatus = new AtomicInteger(FlowCounter.OperationStatus.INIT.status());
-    private AtomicInteger countDpnWriteCompletion = new AtomicInteger(0);
-    private AtomicLong taskCompletionTime = new AtomicLong(0);
-    private final String UNITS = "ns";
+    private AtomicInteger countDpnWriteCompletion = new AtomicInteger();
+    private AtomicLong taskCompletionTime = new AtomicLong();
 
     public FlowWriterTxChain(final DataBroker dataBroker, ExecutorService flowPusher){
         this.dataBroker = dataBroker;
@@ -43,13 +41,14 @@ public class FlowWriterTxChain implements FlowCounterMBean {
     }
 
     public void addFlows(Integer dpnCount, Integer flowsPerDPN, int batchSize,
-                         int sleepMillis, int sleepAfter, short startTableId, short endTableId) {
+                         int sleepMillis, int sleepAfter, short startTableId, short endTableId,
+                         boolean isCreateParents) {
         LOG.info("Using Transaction Chain Flow Writer Impl");
         countDpnWriteCompletion.set(dpnCount);
         startTime = System.nanoTime();
         for (int i = 1; i <= dpnCount; i++) {
             FlowHandlerTask task = new FlowHandlerTask(Integer.toString(i),
-                    flowsPerDPN, true, batchSize, sleepMillis, sleepAfter, startTableId, endTableId);
+                    flowsPerDPN, true, batchSize, sleepMillis, sleepAfter, startTableId, endTableId, isCreateParents);
             flowPusher.execute(task);
         }
     }
@@ -60,21 +59,11 @@ public class FlowWriterTxChain implements FlowCounterMBean {
         countDpnWriteCompletion.set(dpnCount);
         for (int i = 1; i <= dpnCount; i++) {
             FlowHandlerTask task = new FlowHandlerTask(Integer.toString(i), flowsPerDPN, false, batchSize,
-                    0, 1, startTableId, endTableId);
+                    0, 1, startTableId, endTableId, false);
             flowPusher.execute(task);
         }
     }
 
-    @Override
-    public long getFlowCount() {
-        return BulkOMaticUtils.DEFAULT_FLOW_COUNT;
-    }
-
-    @Override
-    public int getReadOpStatus() {
-        return BulkOMaticUtils.DEFUALT_STATUS;
-    }
-
     @Override
     public int getWriteOpStatus() {
         return writeOpStatus.get();
@@ -85,11 +74,6 @@ public class FlowWriterTxChain implements FlowCounterMBean {
         return taskCompletionTime.get();
     }
 
-    @Override
-    public String getUnits() {
-        return UNITS;
-    }
-
     private class FlowHandlerTask implements Runnable, TransactionChainListener {
         private final String dpId;
         private final boolean add;
@@ -99,6 +83,7 @@ public class FlowWriterTxChain implements FlowCounterMBean {
         private final int sleepMillis;
         private final short startTableId;
         private final short endTableId;
+        private final boolean isCreateParents;
         private AtomicInteger remainingTxReturn = new AtomicInteger(0);
 
         BindingTransactionChain txChain;
@@ -110,7 +95,8 @@ public class FlowWriterTxChain implements FlowCounterMBean {
                                final int sleepMillis,
                                final int sleepAfter,
                                final short startTableId,
-                               final short endTableId){
+                               final short endTableId,
+                               final boolean isCreateParents){
             this.dpId = BulkOMaticUtils.DEVICE_TYPE_PREFIX + dpId;
             this.add = add;
             this.flowsPerDpn = flowsPerDpn;
@@ -119,6 +105,7 @@ public class FlowWriterTxChain implements FlowCounterMBean {
             this.sleepAfter = sleepAfter;
             this.startTableId = startTableId;
             this.endTableId = endTableId;
+            this.isCreateParents = isCreateParents;
             remainingTxReturn.set(flowsPerDpn/batchSize);
         }
 
@@ -191,7 +178,7 @@ public class FlowWriterTxChain implements FlowCounterMBean {
         private void writeTxToDs(WriteTransaction writeTransaction, String flowId, InstanceIdentifier<Flow> flowIid, Flow flow, Integer sourceIp, Short tableId){
             if (add) {
                 LOG.trace("Adding flow for flowId: {}, flowIid: {}", flowId, flowIid);
-                writeTransaction.put(LogicalDatastoreType.CONFIGURATION, flowIid, flow, true);
+                writeTransaction.put(LogicalDatastoreType.CONFIGURATION, flowIid, flow, isCreateParents);
             } else {
                 LOG.trace("Deleting flow for flowId: {}, flowIid: {}", flowId, flowIid);
                 writeTransaction.delete(LogicalDatastoreType.CONFIGURATION, flowIid);
index 2ddfc89da39af52eae3b560cb05ce7cc28fadcb3..1a4dc4369ae6d6ab8c270d797455e09c35ae0d6f 100644 (file)
@@ -43,6 +43,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608
 import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.RemoveFlowsDsInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.RemoveFlowsRpcInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.SalBulkFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.TableTestInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.TableTestInput.Operation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.bulk.flow.ds.list.grouping.BulkFlowDsItem;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
@@ -244,7 +246,7 @@ public class SalBulkFlowServiceImpl implements SalBulkFlowService {
                 flowTester.addFlows(input.getDpnCount().intValue(), input.getFlowsPerDpn().intValue(),
                         input.getBatchSize().intValue(), input.getSleepFor().intValue(),
                         input.getSleepAfter().intValue(), input.getStartTableId().shortValue(),
-                        input.getEndTableId().shortValue());
+                        input.getEndTableId().shortValue(), input.isCreateParents());
             } else {
                 flowTester.deleteFlows(input.getDpnCount().intValue(), input.getFlowsPerDpn().intValue(),
                         input.getBatchSize().intValue(), input.getStartTableId().shortValue(),
@@ -259,7 +261,8 @@ public class SalBulkFlowServiceImpl implements SalBulkFlowService {
             if (input.isIsAdd()){
                 flowTester.addFlows(input.getDpnCount().intValue(), input.getFlowsPerDpn().intValue(),
                         input.getBatchSize().intValue(), input.getSleepFor().intValue(),
-                        input.getStartTableId().shortValue(), input.getEndTableId().shortValue());
+                        input.getStartTableId().shortValue(), input.getEndTableId().shortValue(),
+                        input.isCreateParents());
             } else {
                 flowTester.deleteFlows(input.getDpnCount().intValue(), input.getFlowsPerDpn().intValue(),
                         input.getBatchSize().intValue(), input.getStartTableId().shortValue(),
@@ -272,7 +275,7 @@ public class SalBulkFlowServiceImpl implements SalBulkFlowService {
                 flowTester.addFlows(input.getDpnCount().intValue(), input.getFlowsPerDpn().intValue(),
                         input.getBatchSize().intValue(), input.getSleepFor().intValue(),
                         input.getSleepAfter().intValue(), input.getStartTableId().shortValue(),
-                        input.getEndTableId().shortValue());
+                        input.getEndTableId().shortValue(), input.isCreateParents());
             } else {
                 flowTester.deleteFlows(input.getDpnCount().intValue(), input.getFlowsPerDpn().intValue(),
                         input.getBatchSize().intValue(), input.getStartTableId().shortValue(),
@@ -283,6 +286,27 @@ public class SalBulkFlowServiceImpl implements SalBulkFlowService {
         return Futures.immediateFuture(rpcResultBuilder.build());
     }
 
+    @Override
+    public Future<RpcResult<Void>> tableTest(final TableTestInput input) {
+        final TableWriter writer = new TableWriter(dataBroker, fjService);
+        flowCounterBeanImpl.setWriter(writer);
+        switch (input.getOperation()) {
+            case Add:
+                writer.addTables(input.getDpnCount().intValue(),
+                    input.getStartTableId().shortValue(), input.getEndTableId().shortValue());
+                break;
+            case Delete:
+                writer.deleteTables(input.getDpnCount().intValue(),
+                    input.getStartTableId().shortValue(), input.getEndTableId().shortValue());
+                break;
+            default:
+                RpcResultBuilder<Void> rpcResultBuilder = RpcResultBuilder.failed();
+                return Futures.immediateFuture(rpcResultBuilder.build());
+        }
+        RpcResultBuilder<Void> rpcResultBuilder = RpcResultBuilder.success();
+        return Futures.immediateFuture(rpcResultBuilder.build());
+    }
+
     @Override
     public Future<RpcResult<Void>> flowRpcAddMultiple(FlowRpcAddMultipleInput input) {
         FlowWriterDirectOFRpc flowTesterRPC = new FlowWriterDirectOFRpc(dataBroker, flowService, fjService);
diff --git a/applications/bulk-o-matic/src/main/java/org/opendaylight/openflowplugin/applications/bulk/o/matic/TableWriter.java b/applications/bulk-o-matic/src/main/java/org/opendaylight/openflowplugin/applications/bulk/o/matic/TableWriter.java
new file mode 100644 (file)
index 0000000..5bf5716
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2017 Ericsson Systems, Inc. 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.applications.bulk.o.matic;
+
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+import javax.annotation.Nullable;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TableWriter implements FlowCounterMBean {
+    private final Logger LOG = LoggerFactory.getLogger(TableWriter.class);
+
+    private final AtomicInteger writeOpStatus = new AtomicInteger(FlowCounter.OperationStatus.INIT.status());
+    private final AtomicLong taskCompletionTime = new AtomicLong(BulkOMaticUtils.DEFAULT_COMPLETION_TIME);
+    private final AtomicInteger successfulWrites = new AtomicInteger();
+    private final AtomicInteger failedWrites = new AtomicInteger();
+    private final DataBroker dataBroker;
+    private final ExecutorService tablePusher;
+
+    public TableWriter(final DataBroker dataBroker, final ExecutorService tablePusher) {
+        this.dataBroker = dataBroker;
+        this.tablePusher = tablePusher;
+    }
+
+    public void addTables(final int dpnCount, final short startTableId, final short endTableId) {
+        LOG.info("Starting to add tables: {} to {} on each of {}", startTableId, endTableId, dpnCount);
+        TableHandlerTask task = new TableHandlerTask(dpnCount, startTableId, endTableId, true);
+        tablePusher.execute(task);
+    }
+
+    public void deleteTables(int dpnCount, short startTableId, short endTableId) {
+        LOG.info("Starting to delete tables: {} to {} on each of {}", startTableId, endTableId, dpnCount);
+        TableHandlerTask task = new TableHandlerTask(dpnCount, startTableId, endTableId, false);
+        tablePusher.execute(task);
+    }
+
+    @Override
+    public int getWriteOpStatus() {
+        return writeOpStatus.get();
+    }
+
+    @Override
+    public long getTaskCompletionTime() {
+        return taskCompletionTime.get();
+    }
+
+    @Override
+    public long getTableCount() {
+        return successfulWrites.get();
+    }
+
+    private class TableHandlerTask implements Runnable {
+
+        private short startTableId;
+        private short endTableId;
+        private int dpnCount;
+        private boolean isAdd;
+
+        public TableHandlerTask(int dpnCount, short startTableId, short endTableId, boolean isAdd) {
+            this.dpnCount = dpnCount;
+            this.startTableId = startTableId;
+            this.endTableId = endTableId;
+            this.isAdd = isAdd;
+        }
+
+        @Override
+        public void run() {
+            writeOpStatus.set(FlowCounter.OperationStatus.IN_PROGRESS.status());
+            int totalTables = dpnCount * (endTableId - startTableId + 1);
+
+            for (int dpn = 1; dpn <= dpnCount; dpn++) {
+                String dpId = BulkOMaticUtils.DEVICE_TYPE_PREFIX + String.valueOf(dpn);
+                for (short tableId = startTableId; tableId <= endTableId; tableId++) {
+                    WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+                    Table table = new TableBuilder().setKey(new TableKey(tableId))
+                            .setId(tableId)
+                            .build();
+                    InstanceIdentifier<Table> tableIId = BulkOMaticUtils.getTableId(tableId, dpId);
+
+                    if (isAdd) {
+                        wtx.put(LogicalDatastoreType.CONFIGURATION, tableIId, table, true);
+                    } else {
+                        wtx.delete(LogicalDatastoreType.CONFIGURATION, tableIId);
+                    }
+
+                    CheckedFuture<Void, TransactionCommitFailedException> future = wtx.submit();
+
+                    Futures.addCallback(future, new FutureCallback<Void>() {
+                        @Override
+                        public void onSuccess(@Nullable Void v) {
+                            if (successfulWrites.incrementAndGet() == totalTables) {
+                                if (failedWrites.get() > 0) {
+                                    writeOpStatus.set(FlowCounter.OperationStatus.FAILURE.status());
+                                } else {
+                                    writeOpStatus.set(FlowCounter.OperationStatus.SUCCESS.status());
+                                }
+                            }
+                        }
+
+                        @Override
+                        public void onFailure(Throwable throwable) {
+                            LOG.error("Table addition Failed. Error: {}", throwable);
+                            if (failedWrites.incrementAndGet() == totalTables) {
+                                writeOpStatus.set(FlowCounter.OperationStatus.FAILURE.status());
+                            }
+                        }
+                    });
+                }
+            }
+        }
+    }
+}
index 965b335c4536c868e5c1b5efe77c3f26acf2973d..3eda3a0342bd1430af041fc255bb3b4b2a1ab37d 100644 (file)
@@ -73,68 +73,74 @@ module sal-bulk-flow {
     }
 
     rpc flow-test {
-       input {
-           leaf is-add {
-               type boolean;
-               mandatory true;
-               status current;
-               description "Add or delete";
-           }
-           leaf dpn-count {
-               type uint32;
-               mandatory true;
-               status current;
-               description "No of DPNs";
-           }
-           leaf flows-per-dpn {
-               type uint32;
-               mandatory true;
-               status current;
-               description "Flows to be pushed per DPN";
-           }
-           leaf start-table-id {
-               type uint32;
-               mandatory true;
-               status current;
-               description "Start adding flows from this table id";
-           }
-           leaf end-table-id {
-               type uint32;
-               mandatory true;
-               status current;
-               description "The last table to add flows to and then wrap around";
-           }
-           leaf batch-size {
-               type uint32;
-               mandatory true;
-               status current;
-               description "batch size";
-           }
-           leaf seq {
-               type boolean;
-               mandatory true;
-               status current;
-               description "Whether to use sequential or concurrent writer";
-           }
-           leaf tx-chain {
-               type boolean;
-               mandatory true;
-               status current;
-               description "Whether to use PingPong Broker or not. seq is ignored.";
-           }
-           leaf sleep-for {
-               type uint32;
-               mandatory true;
-               status current;
-               description "sleep for the given milliseconds";
-           }
-           leaf sleep-after {
-               type uint32;
-               mandatory true;
-               status current;
-               description "Sleep after the given number of iterations. Will be used in the concurrent case only";
-           }
-       }
+        input {
+            leaf create-parents {
+                type boolean;
+                mandatory true;
+                status current;
+                description "Create parents if doesn't exist";
+            }
+            leaf is-add {
+                type boolean;
+                mandatory true;
+                status current;
+                description "Add or delete";
+            }
+            leaf dpn-count {
+                type uint32;
+                mandatory true;
+                status current;
+                description "No of DPNs";
+            }
+            leaf flows-per-dpn {
+                type uint32;
+                mandatory true;
+                status current;
+                description "Flows to be pushed per DPN";
+            }
+            leaf start-table-id {
+                type uint32;
+                mandatory true;
+                status current;
+                description "Start adding flows from this table id";
+            }
+            leaf end-table-id {
+                type uint32;
+                mandatory true;
+                status current;
+                description "The last table to add flows to and then wrap around";
+            }
+            leaf batch-size {
+                type uint32;
+                mandatory true;
+                status current;
+                description "batch size";
+            }
+            leaf seq {
+                type boolean;
+                mandatory true;
+                status current;
+                description "Whether to use sequential or concurrent writer";
+            }
+            leaf tx-chain {
+                type boolean;
+                mandatory true;
+                status current;
+                description "Whether to use PingPong Broker or not. seq is ignored.";
+            }
+            leaf sleep-for {
+                type uint32;
+                mandatory true;
+                status current;
+                description "sleep for the given milliseconds";
+            }
+            leaf sleep-after {
+                type uint32;
+                mandatory true;
+                status current;
+                description "Sleep after the given number of iterations. Will be used in the concurrent case only";
+            }
+        }
     }
 
     rpc read-flow-test {
@@ -217,4 +223,38 @@ module sal-bulk-flow {
            }
        }
     }
+
+    rpc table-test {
+        input {
+            leaf operation {
+                type enumeration {
+                    enum add;
+                    enum delete;
+                }
+                status current;
+                description "Type of operation, add or delete";
+            }
+
+            leaf dpn-count {
+                type uint32;
+                mandatory true;
+                status current;
+                description "Total number of dpns to add these tables";
+            }
+
+            leaf start-table-id {
+                type uint32;
+                mandatory true;
+                status current;
+                description "Starting table id";
+            }
+
+            leaf end-table-id {
+                type uint32;
+                mandatory true;
+                status current;
+                description "Last table id";
+            }
+        }
+    }
 }
index 53a27b31c09f5d6e6330f61ed807b1b93f96c309..769f70d9fda38e47dd04f7ae5cf35781c4be0b18 100644 (file)
@@ -68,7 +68,7 @@ public class FlowWriterConcurrentTest {
     }
     @Test
     public void testAddFlows() throws Exception {
-        flowWriterConcurrent.addFlows(1, FLOWS_PER_DPN, 10, 10, 10, (short)0, (short)1);
+        flowWriterConcurrent.addFlows(1, FLOWS_PER_DPN, 10, 10, 10, (short)0, (short)1, true);
         Mockito.verify(wTx, Mockito.times(FLOWS_PER_DPN)).put(Matchers.<LogicalDatastoreType>any(), Matchers.<InstanceIdentifier<DataObject>>any(), Matchers.<DataObject>any(), Matchers.anyBoolean());
     }
 
index 5b570543556b9441434cefd7bbdffae948bfad1b..0aa5cee7966124ae41666b6333016cf13c372ee8 100644 (file)
@@ -65,7 +65,7 @@ public class FlowWriterSequentialTest {
     }
     @Test
     public void testAddFlows() throws Exception {
-        flowWriterSequential.addFlows(1, FLOWS_PER_DPN, 10, 10, (short)0, (short)1);
+        flowWriterSequential.addFlows(1, FLOWS_PER_DPN, 10, 10, (short)0, (short)1, true);
         Mockito.verify(wTx, Mockito.times(FLOWS_PER_DPN)).put(Matchers.<LogicalDatastoreType>any(), Matchers.<InstanceIdentifier<DataObject>>any(), Matchers.<DataObject>any(), Matchers.anyBoolean());
     }
 
index 9f3e239972117cd486be8ba4f9338b1e7677e980..e5b003b757bca04dd25974a660cf8528d4f20632 100644 (file)
@@ -72,7 +72,7 @@ public class FlowWriterTxChainTest {
     }
     @Test
     public void testAddFlows() throws Exception {
-        flowWriterTxChain.addFlows(1, FLOWS_PER_DPN, 10, 10, 10, (short)0, (short)1);
+        flowWriterTxChain.addFlows(1, FLOWS_PER_DPN, 10, 10, 10, (short)0, (short)1, true);
         Mockito.verify(wTx, Mockito.times(FLOWS_PER_DPN)).put(Matchers.<LogicalDatastoreType>any(), Matchers.<InstanceIdentifier<DataObject>>any(), Matchers.<DataObject>any(), Matchers.anyBoolean());
     }
 
index 2940240945c33e45e78b780b9816e85c14595a21..f8c564d1775a07656a036cfee0ce5e9f1606c574 100644 (file)
@@ -47,6 +47,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608
 import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.RemoveFlowsDsInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.RemoveFlowsRpcInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.RemoveFlowsRpcInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.TableTestInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.TableTestInput.Operation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.TableTestInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.bulk.flow.ds.list.grouping.BulkFlowDsItem;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.bulk.flow.ds.list.grouping.BulkFlowDsItemBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.bulk.flow.list.grouping.BulkFlowItem;
@@ -216,7 +219,8 @@ public class SalBulkFlowServiceImplTest {
                 .setSleepAfter(20L)
                 .setSleepFor(1L)
                 .setStartTableId(1L)
-                .setTxChain(true);
+                .setTxChain(true)
+                .setCreateParents(true);
 
         FlowTestInput flowTestInput = flowTestInputBuilder.build();
 
@@ -261,4 +265,22 @@ public class SalBulkFlowServiceImplTest {
 
         Assert.assertTrue(salBulkFlowService.flowRpcAddMultiple(flowRpcAddMultipleInput).get().isSuccessful());
     }
+
+    @Test
+    public void testTableTest() throws Exception {
+        final TableTestInputBuilder tableTestInputBuilder = new TableTestInputBuilder()
+                .setStartTableId(0L)
+                .setEndTableId(99L)
+                .setDpnCount(1L)
+                .setOperation(Operation.Add);
+
+        TableTestInput tableTestInput = tableTestInputBuilder.build();
+
+        Assert.assertTrue(salBulkFlowService.tableTest(tableTestInput).get().isSuccessful());
+
+        tableTestInputBuilder.setOperation(Operation.Delete);
+        tableTestInput = tableTestInputBuilder.build();
+
+        Assert.assertTrue(salBulkFlowService.tableTest(tableTestInput).get().isSuccessful());
+    }
 }
\ No newline at end of file
diff --git a/applications/bulk-o-matic/src/test/java/org/opendaylight/openflowplugin/applications/bulk/o/matic/TableWriterTest.java b/applications/bulk-o-matic/src/test/java/org/opendaylight/openflowplugin/applications/bulk/o/matic/TableWriterTest.java
new file mode 100644 (file)
index 0000000..775ecd0
--- /dev/null
@@ -0,0 +1,80 @@
+/**
+ * Copyright (c) 2017 Cisco Systems, Inc. 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.applications.bulk.o.matic;
+
+import static org.mockito.Mockito.doReturn;
+
+import com.google.common.util.concurrent.Futures;
+import java.util.concurrent.ExecutorService;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.mockito.stubbing.Answer;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Test for {@link FlowWriterSequential}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class TableWriterTest {
+    private static final Logger LOG = LoggerFactory.getLogger(TableWriterTest.class);
+
+    private static final int TABLES_PER_DPN = 100;
+    private static final int DPN_COUNT = 1;
+    private static final short START_TABLE_ID = 0;
+    private static final short END_TABLE_ID = 99;
+
+    @Mock
+    private DataBroker mockDataBroker;
+    @Mock
+    private ExecutorService mockTablePusher;
+    @Mock
+    private WriteTransaction wTx;
+
+    private TableWriter tableWriter;
+
+    @Before
+    public void setUp() throws Exception {
+
+        doReturn(wTx).when(mockDataBroker).newWriteOnlyTransaction();
+        Mockito.when(wTx.submit()).thenReturn(Futures.immediateCheckedFuture(null));
+
+        Mockito.doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                ((Runnable)invocation.getArguments()[0]).run();
+                return null;
+            }
+        }).when(mockTablePusher).execute(Matchers.<Runnable>any());
+
+        tableWriter = new TableWriter(mockDataBroker, mockTablePusher);
+    }
+    @Test
+    public void testAddTables() throws Exception {
+        tableWriter.addTables(DPN_COUNT, START_TABLE_ID, END_TABLE_ID);
+        Mockito.verify(wTx, Mockito.times(TABLES_PER_DPN)).put(Matchers.<LogicalDatastoreType>any(), Matchers.<InstanceIdentifier<DataObject>>any(), Matchers.<DataObject>any(), Matchers.anyBoolean());
+    }
+
+    @Test
+    public void testDeleteTables() throws Exception {
+        tableWriter.deleteTables(DPN_COUNT, START_TABLE_ID, END_TABLE_ID);
+        Mockito.verify(wTx, Mockito.times(TABLES_PER_DPN)).delete(Matchers.<LogicalDatastoreType>any(), Matchers.<InstanceIdentifier<DataObject>>any());
+    }
+}
\ No newline at end of file
index 441b0601c67f2c0628582ee7b436d0b20831fad6..e42d0da0d2937d3e1af63043bef44acb4e8b5896 100644 (file)
@@ -32,6 +32,7 @@ public class InventoryMapping {
         builder.setPortNumber(updated.getPortNumber());
         builder.setState(updated.getState());
         builder.setSupported(updated.getSupported());
+        builder.setReason(updated.getReason());
         return builder.build();
     }
 
index 39207b28b214691b2c54b636b2fa60963419096a..1b1b97afcd06f3247db5e1185ebea8c1baea0f2a 100644 (file)
@@ -11,9 +11,6 @@
   <artifactId>openflowplugin-karaf</artifactId>
   <version>0.5.0-SNAPSHOT</version>
   <packaging>pom</packaging>
-  <prerequisites>
-    <maven>3.0</maven>
-  </prerequisites>
 
   <properties>
     <openflowplugin.version>0.5.0-SNAPSHOT</openflowplugin.version>
index 27cd24f47f1d1d55d319aff0b4a5ee2c8cdd90bc..2272ed4996b3f82a45433d2aa72f0ea4d7834e45 100644 (file)
@@ -14,14 +14,21 @@ import org.opendaylight.openflowjava.nx.codec.match.ArpThaCodec;
 import org.opendaylight.openflowjava.nx.codec.match.ArpTpaCodec;
 import org.opendaylight.openflowjava.nx.codec.match.CtStateCodec;
 import org.opendaylight.openflowjava.nx.codec.match.CtZoneCodec;
+import org.opendaylight.openflowjava.nx.codec.match.EncapEthDstCodec;
+import org.opendaylight.openflowjava.nx.codec.match.EncapEthSrcCodec;
+import org.opendaylight.openflowjava.nx.codec.match.EncapEthTypeCodec;
 import org.opendaylight.openflowjava.nx.codec.match.EthDstCodec;
 import org.opendaylight.openflowjava.nx.codec.match.EthSrcCodec;
 import org.opendaylight.openflowjava.nx.codec.match.EthTypeCodec;
 import org.opendaylight.openflowjava.nx.codec.match.IcmpTypeCodec;
-import org.opendaylight.openflowjava.nx.codec.match.IpSrcCodec;
-import org.opendaylight.openflowjava.nx.codec.match.IpDstCodec;
 import org.opendaylight.openflowjava.nx.codec.match.InPortCodec;
+import org.opendaylight.openflowjava.nx.codec.match.IpDstCodec;
+import org.opendaylight.openflowjava.nx.codec.match.IpSrcCodec;
+import org.opendaylight.openflowjava.nx.codec.match.Ipv6DstCodec;
+import org.opendaylight.openflowjava.nx.codec.match.Ipv6SrcCodec;
 import org.opendaylight.openflowjava.nx.codec.match.MplsLabelCodec;
+import org.opendaylight.openflowjava.nx.codec.match.NshMdtypeCodec;
+import org.opendaylight.openflowjava.nx.codec.match.NshNpCodec;
 import org.opendaylight.openflowjava.nx.codec.match.Nshc1Codec;
 import org.opendaylight.openflowjava.nx.codec.match.Nshc2Codec;
 import org.opendaylight.openflowjava.nx.codec.match.Nshc3Codec;
@@ -38,15 +45,10 @@ import org.opendaylight.openflowjava.nx.codec.match.Reg6Codec;
 import org.opendaylight.openflowjava.nx.codec.match.Reg7Codec;
 import org.opendaylight.openflowjava.nx.codec.match.TcpDstCodec;
 import org.opendaylight.openflowjava.nx.codec.match.TcpSrcCodec;
+import org.opendaylight.openflowjava.nx.codec.match.TunGpeNpCodec;
 import org.opendaylight.openflowjava.nx.codec.match.TunIdCodec;
 import org.opendaylight.openflowjava.nx.codec.match.TunIpv4DstCodec;
 import org.opendaylight.openflowjava.nx.codec.match.TunIpv4SrcCodec;
-import org.opendaylight.openflowjava.nx.codec.match.EncapEthTypeCodec;
-import org.opendaylight.openflowjava.nx.codec.match.EncapEthSrcCodec;
-import org.opendaylight.openflowjava.nx.codec.match.EncapEthDstCodec;
-import org.opendaylight.openflowjava.nx.codec.match.NshMdtypeCodec;
-import org.opendaylight.openflowjava.nx.codec.match.NshNpCodec;
-import org.opendaylight.openflowjava.nx.codec.match.TunGpeNpCodec;
 import org.opendaylight.openflowjava.nx.codec.match.UdpDstCodec;
 import org.opendaylight.openflowjava.nx.codec.match.UdpSrcCodec;
 
@@ -98,5 +100,7 @@ public class NiciraMatchCodecs {
     public static final CtZoneCodec CT_ZONE_CODEC = new CtZoneCodec();
     public static final IpSrcCodec IP_SRC_CODEC = new IpSrcCodec();
     public static final IpDstCodec IP_DST_CODEC = new IpDstCodec();
+    public static final Ipv6SrcCodec IPV6_SRC_CODEC = new Ipv6SrcCodec();
+    public static final Ipv6DstCodec IPV6_DST_CODEC = new Ipv6DstCodec();
     public static final IcmpTypeCodec ICMP_TYPE_CODEC = new IcmpTypeCodec();
 }
index ea41785e72224ae834e3f30e46e72f3b7032c1ef..dbaf1c75188548f5972d9ea48d90d9ba8601f6a1 100644 (file)
@@ -67,7 +67,7 @@ public class ConntrackCodec extends AbstractActionCodec {
         outBuffer.writeShort(action.getNxActionConntrack().getConntrackZone().shortValue());
         outBuffer.writeByte(action.getNxActionConntrack().getRecircTable().byteValue());
         outBuffer.writeZero(5);
-        serializeCtAction(outBuffer,action, length);
+        serializeCtAction(outBuffer,action);
     }
 
     private int getActionLength(final ActionConntrack action) {
@@ -78,37 +78,46 @@ public class ConntrackCodec extends AbstractActionCodec {
         }
         for (CtActions ctActions : ctActionsList) {
             if (ctActions.getOfpactActions() instanceof NxActionNatCase) {
-                length += NX_NAT_LENGTH;
                 NxActionNatCase nxActionNatCase = (NxActionNatCase)ctActions.getOfpactActions();
                 NxActionNat natAction = nxActionNatCase.getNxActionNat();
-                short rangePresent = natAction.getRangePresent().shortValue();
-                if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MIN.getIntValue())) {
-                    length += INT_LENGTH;
+                int natLength = getNatActionLength(natAction);
+                int pad = 8 - (natLength % 8);
+                length += natLength + pad;
                 }
-                if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MAX.getIntValue())) {
-                    length += INT_LENGTH;
-                }
-                if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMIN.getIntValue())) {
-                    length += SHORT_LENGTH;
-                }
-                if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMAX.getIntValue())) {
-                    length += SHORT_LENGTH;
-                }
-            }
         }
         LOG.trace("ActionLength :conntrack: length {}",length);
         return length;
     }
 
-    private void serializeCtAction(final ByteBuf outBuffer, final ActionConntrack action, final int length) {
+    private int getNatActionLength(final NxActionNat natAction) {
+        int natLength = NX_NAT_LENGTH;
+        short rangePresent = natAction.getRangePresent().shortValue();
+        if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MIN.getIntValue())) {
+            natLength += INT_LENGTH;
+        }
+        if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MAX.getIntValue())) {
+            natLength += INT_LENGTH;
+        }
+        if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMIN.getIntValue())) {
+            natLength += SHORT_LENGTH;
+        }
+        if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMAX.getIntValue())) {
+            natLength += SHORT_LENGTH;
+        }
+        return natLength;
+
+    }
+
+    private void serializeCtAction(final ByteBuf outBuffer, final ActionConntrack action) {
         List<CtActions> ctActionsList = action.getNxActionConntrack().getCtActions();
         if (ctActionsList != null) {
             for (CtActions ctActions : ctActionsList) {
                 if (ctActions.getOfpactActions() instanceof NxActionNatCase){
                     NxActionNatCase nxActionNatCase = (NxActionNatCase)ctActions.getOfpactActions();
                     NxActionNat natAction = nxActionNatCase.getNxActionNat();
-                    int pad = length % 8;
-                    serializeHeader(length + pad, NXAST_NAT_SUBTYPE, outBuffer);
+                    int natLength = getNatActionLength(natAction);
+                    int pad = 8 - (natLength % 8);
+                    serializeHeader(natLength + pad, NXAST_NAT_SUBTYPE, outBuffer);
                     outBuffer.writeZero(2);
                     outBuffer.writeShort(natAction.getFlags().shortValue());
                     short rangePresent = natAction.getRangePresent().shortValue();
@@ -147,7 +156,7 @@ public class ConntrackCodec extends AbstractActionCodec {
         nxActionConntrackBuilder.setRecircTable(message.readUnsignedByte());
         message.skipBytes(5);
         if  (length > CT_LENGTH) {
-            dserializeCtAction(message,nxActionConntrackBuilder);
+            dserializeCtAction(message,nxActionConntrackBuilder, length - CT_LENGTH);
         }
         ActionBuilder actionBuilder = new ActionBuilder();
         actionBuilder.setExperimenterId(getExperimenterId());
@@ -157,35 +166,41 @@ public class ConntrackCodec extends AbstractActionCodec {
         return actionBuilder.build();
     }
 
-    private void dserializeCtAction(final ByteBuf message, final NxActionConntrackBuilder nxActionConntrackBuilder) {
-        deserializeCtHeader(message);
-
-        NxActionNatBuilder nxActionNatBuilder = new NxActionNatBuilder();
-        message.skipBytes(2);
-        nxActionNatBuilder.setFlags(message.readUnsignedShort());
-
-        int rangePresent = message.readUnsignedShort();
-        nxActionNatBuilder.setRangePresent(rangePresent);
-        if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MIN.getIntValue())) {
-            InetAddress address = InetAddresses.fromInteger((int)message.readUnsignedInt());
-            nxActionNatBuilder.setIpAddressMin(new IpAddress(address.getHostAddress().toCharArray()));
-        }
-        if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MAX.getIntValue())) {
-            InetAddress address = InetAddresses.fromInteger((int)message.readUnsignedInt());
-            nxActionNatBuilder.setIpAddressMax(new IpAddress(address.getHostAddress().toCharArray()));
-        }
-        if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMIN.getIntValue())) {
-            nxActionNatBuilder.setPortMin(message.readUnsignedShort());
-        }
-        if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMAX.getIntValue())) {
-            nxActionNatBuilder.setPortMax(message.readUnsignedShort());
-        }
-        NxActionNatCaseBuilder caseBuilder = new NxActionNatCaseBuilder();
-        caseBuilder.setNxActionNat(nxActionNatBuilder.build());
-        CtActionsBuilder ctActionsBuilder = new CtActionsBuilder();
-        ctActionsBuilder.setOfpactActions(caseBuilder.build());
+    private void dserializeCtAction(final ByteBuf message, final NxActionConntrackBuilder nxActionConntrackBuilder,
+            int ctActionsLength) {
         List<CtActions> ctActionsList = new ArrayList<>();
-        ctActionsList.add(ctActionsBuilder.build());
+        while (ctActionsLength > 0){
+            int startIndex = message.readerIndex();
+            int length = deserializeCtHeader(message);
+            ctActionsLength = ctActionsLength - length;
+            NxActionNatBuilder nxActionNatBuilder = new NxActionNatBuilder();
+            message.skipBytes(2);
+            nxActionNatBuilder.setFlags(message.readUnsignedShort());
+
+            int rangePresent = message.readUnsignedShort();
+            nxActionNatBuilder.setRangePresent(rangePresent);
+            if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MIN.getIntValue())) {
+                InetAddress address = InetAddresses.fromInteger((int)message.readUnsignedInt());
+                nxActionNatBuilder.setIpAddressMin(new IpAddress(address.getHostAddress().toCharArray()));
+            }
+            if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MAX.getIntValue())) {
+                InetAddress address = InetAddresses.fromInteger((int)message.readUnsignedInt());
+                nxActionNatBuilder.setIpAddressMax(new IpAddress(address.getHostAddress().toCharArray()));
+            }
+            if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMIN.getIntValue())) {
+                nxActionNatBuilder.setPortMin(message.readUnsignedShort());
+            }
+            if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMAX.getIntValue())) {
+                nxActionNatBuilder.setPortMax(message.readUnsignedShort());
+            }
+            NxActionNatCaseBuilder caseBuilder = new NxActionNatCaseBuilder();
+            caseBuilder.setNxActionNat(nxActionNatBuilder.build());
+            CtActionsBuilder ctActionsBuilder = new CtActionsBuilder();
+            ctActionsBuilder.setOfpactActions(caseBuilder.build());
+            ctActionsList.add(ctActionsBuilder.build());
+            int pad = length - (message.readerIndex() - startIndex);
+            message.skipBytes(pad);
+        }
         nxActionConntrackBuilder.setCtActions(ctActionsList);
     }
 
diff --git a/extension/openflowjava-extension-nicira/src/main/java/org/opendaylight/openflowjava/nx/codec/match/Ipv6DstCodec.java b/extension/openflowjava-extension-nicira/src/main/java/org/opendaylight/openflowjava/nx/codec/match/Ipv6DstCodec.java
new file mode 100644 (file)
index 0000000..b63ec3f
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2017 Red Hat, Inc. 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.match;
+
+import io.netty.buffer.ByteBuf;
+import org.opendaylight.openflowjava.protocol.api.keys.MatchEntryDeserializerKey;
+import org.opendaylight.openflowjava.protocol.api.keys.MatchEntrySerializerKey;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.openflowjava.protocol.api.util.OxmMatchConstants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.MatchField;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.Nxm1Class;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.OxmClassBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmOfIpDst;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.ofj.nxm.of.match.ip.dst.grouping.IpDstValuesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.oxm.container.match.entry.value.IpDstCaseValue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.oxm.container.match.entry.value.IpDstCaseValueBuilder;
+
+/**
+ * @author Sridhar Gaddam (sgaddam@redhat.com)
+ */
+public class Ipv6DstCodec extends AbstractMatchCodec {
+
+    private static final int VALUE_LENGTH = 16;
+    private static final int NXM_FIELD_CODE = 20;
+    public static final MatchEntrySerializerKey<Nxm1Class, NxmOfIpDst> SERIALIZER_KEY = new MatchEntrySerializerKey<>(
+            EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmOfIpDst.class);
+    public static final MatchEntryDeserializerKey DESERIALIZER_KEY = new MatchEntryDeserializerKey(
+            EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, NXM_FIELD_CODE);
+
+
+    @Override
+    public MatchEntry deserialize(ByteBuf message) {
+        MatchEntryBuilder matchEntriesBuilder = deserializeHeader(message);
+        IpDstCaseValueBuilder caseBuilder = new IpDstCaseValueBuilder();
+        caseBuilder.setIpDstValues(new IpDstValuesBuilder().setValue(message.readUnsignedInt()).build());
+        matchEntriesBuilder.setMatchEntryValue(caseBuilder.build());
+        return matchEntriesBuilder.build();
+    }
+
+    @Override
+    public void serialize(MatchEntry input, ByteBuf outBuffer) {
+        serializeHeader(input, outBuffer);
+        IpDstCaseValue ipDstCase = ((IpDstCaseValue) input.getMatchEntryValue());
+        outBuffer.writeInt(ipDstCase.getIpDstValues().getValue().intValue());
+    }
+
+    @Override
+    public int getNxmFieldCode() {
+        return NXM_FIELD_CODE;
+    }
+
+    @Override
+    public int getOxmClassCode() {
+        return OxmMatchConstants.NXM_1_CLASS;
+    }
+
+    @Override
+    public int getValueLength() {
+        return VALUE_LENGTH;
+    }
+
+    @Override
+    public Class<? extends MatchField> getNxmField() {
+        return NxmOfIpDst.class;
+    }
+
+    @Override
+    public Class<? extends OxmClassBase> getOxmClass() {
+        return Nxm1Class.class;
+    }
+
+}
diff --git a/extension/openflowjava-extension-nicira/src/main/java/org/opendaylight/openflowjava/nx/codec/match/Ipv6SrcCodec.java b/extension/openflowjava-extension-nicira/src/main/java/org/opendaylight/openflowjava/nx/codec/match/Ipv6SrcCodec.java
new file mode 100644 (file)
index 0000000..f221555
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2017 Red Hat, Inc. 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.match;
+
+import io.netty.buffer.ByteBuf;
+import org.opendaylight.openflowjava.protocol.api.keys.MatchEntryDeserializerKey;
+import org.opendaylight.openflowjava.protocol.api.keys.MatchEntrySerializerKey;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.openflowjava.protocol.api.util.OxmMatchConstants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.MatchField;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.Nxm1Class;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.OxmClassBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmOfIpSrc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.ofj.nxm.of.match.ip.src.grouping.IpSrcValuesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.oxm.container.match.entry.value.IpSrcCaseValue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.oxm.container.match.entry.value.IpSrcCaseValueBuilder;
+
+/**
+ * @author Sridhar Gaddam (sgaddam@redhat.com)
+ */
+public class Ipv6SrcCodec extends AbstractMatchCodec {
+
+    private static final int VALUE_LENGTH = 16;
+    private static final int NXM_FIELD_CODE = 19;
+    public static final MatchEntrySerializerKey<Nxm1Class, NxmOfIpSrc> SERIALIZER_KEY = new MatchEntrySerializerKey<>(
+            EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmOfIpSrc.class);
+    public static final MatchEntryDeserializerKey DESERIALIZER_KEY = new MatchEntryDeserializerKey(
+            EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, NXM_FIELD_CODE);
+
+
+    @Override
+    public MatchEntry deserialize(ByteBuf message) {
+        MatchEntryBuilder matchEntriesBuilder = deserializeHeader(message);
+        IpSrcCaseValueBuilder caseBuilder = new IpSrcCaseValueBuilder();
+        caseBuilder.setIpSrcValues(new IpSrcValuesBuilder().setValue(message.readUnsignedInt()).build());
+        matchEntriesBuilder.setMatchEntryValue(caseBuilder.build());
+        return matchEntriesBuilder.build();
+    }
+
+    @Override
+    public void serialize(MatchEntry input, ByteBuf outBuffer) {
+        serializeHeader(input, outBuffer);
+        IpSrcCaseValue ipSrcCase = ((IpSrcCaseValue) input.getMatchEntryValue());
+        outBuffer.writeInt(ipSrcCase.getIpSrcValues().getValue().intValue());
+    }
+
+    @Override
+    public int getNxmFieldCode() {
+        return NXM_FIELD_CODE;
+    }
+
+    @Override
+    public int getOxmClassCode() {
+        return OxmMatchConstants.NXM_1_CLASS;
+    }
+
+    @Override
+    public int getValueLength() {
+        return VALUE_LENGTH;
+    }
+
+    @Override
+    public Class<? extends MatchField> getNxmField() {
+        return NxmOfIpSrc.class;
+    }
+
+    @Override
+    public Class<? extends OxmClassBase> getOxmClass() {
+        return Nxm1Class.class;
+    }
+
+}
index 7c73d4a37306f644c442ca3beccfe39d1d420465..df699deb1d698ca794101242db8a87e5e25e32f7 100644 (file)
@@ -44,7 +44,8 @@ public class ConntrackCodecTest {
 
     private final int length = 24;
     private final byte nxastConntrackSubtype = 35;
-    private final int nxNatLength = 32;
+    private final int nxNatLengthAction1 = 32;
+    private final int nxNatLengthAction2 = 24;
     private final byte nxastNatSubtype = 36;
 
     @Before
@@ -58,9 +59,9 @@ public class ConntrackCodecTest {
         action = createAction();
         conntrackCodec.serialize(action, buffer);
 
-        Assert.assertEquals(56, buffer.readableBytes());
+        Assert.assertEquals(length + nxNatLengthAction1 + nxNatLengthAction2, buffer.readableBytes());
         Assert.assertEquals(EncodeConstants.EXPERIMENTER_VALUE, buffer.readUnsignedShort());
-        Assert.assertEquals(length + nxNatLength, buffer.readUnsignedShort());
+        Assert.assertEquals(length + nxNatLengthAction1 + nxNatLengthAction2, buffer.readUnsignedShort());
         Assert.assertEquals(NiciraConstants.NX_VENDOR_ID.intValue(), buffer.readUnsignedInt());
         Assert.assertEquals(nxastConntrackSubtype, buffer.readUnsignedShort());
         Assert.assertEquals(1, buffer.readUnsignedShort());
@@ -69,7 +70,7 @@ public class ConntrackCodecTest {
         Assert.assertEquals(4, buffer.readByte());
         buffer.skipBytes(5);
         Assert.assertEquals(EncodeConstants.EXPERIMENTER_VALUE, buffer.readUnsignedShort());
-        Assert.assertEquals(nxNatLength, buffer.readUnsignedShort());
+        Assert.assertEquals(nxNatLengthAction1, buffer.readUnsignedShort());
         Assert.assertEquals(NiciraConstants.NX_VENDOR_ID.intValue(), buffer.readUnsignedInt());
         Assert.assertEquals(nxastNatSubtype, buffer.readUnsignedShort());
         buffer.skipBytes(2);
@@ -80,6 +81,16 @@ public class ConntrackCodecTest {
         Assert.assertEquals(3000, buffer.readUnsignedShort());
         Assert.assertEquals(4000, buffer.readUnsignedShort());
         buffer.skipBytes(4);
+        Assert.assertEquals(EncodeConstants.EXPERIMENTER_VALUE, buffer.readUnsignedShort());
+        Assert.assertEquals(nxNatLengthAction2, buffer.readUnsignedShort());
+        Assert.assertEquals(NiciraConstants.NX_VENDOR_ID.intValue(), buffer.readUnsignedInt());
+        Assert.assertEquals(nxastNatSubtype, buffer.readUnsignedShort());
+        buffer.skipBytes(2);
+        Assert.assertEquals(5, buffer.readUnsignedShort());
+        Assert.assertEquals(0x21, buffer.readUnsignedShort());
+        Assert.assertEquals(3232235520L, buffer.readUnsignedInt());
+        Assert.assertEquals(4000, buffer.readUnsignedShort());
+        buffer.skipBytes(2);
     }
 
     @Test
@@ -119,7 +130,12 @@ public class ConntrackCodecTest {
         Assert.assertEquals("192.168.10.0", natAction.getIpAddressMax().getIpv4Address().getValue());
         Assert.assertEquals(3000, natAction.getPortMin().shortValue());
         Assert.assertEquals(4000, natAction.getPortMax().shortValue());
-
+        nxActionNatCase = (NxActionNatCase) ctActions.get(1).getOfpactActions();
+        natAction = nxActionNatCase.getNxActionNat();
+        Assert.assertEquals(5, natAction.getFlags().shortValue());
+        Assert.assertEquals(0x21, natAction.getRangePresent().intValue());
+        Assert.assertEquals("192.168.0.0", natAction.getIpAddressMin().getIpv4Address().getValue());
+        Assert.assertEquals(4000, natAction.getPortMax().shortValue());
     }
 
     @Test
@@ -156,6 +172,16 @@ public class ConntrackCodecTest {
         ctActionsBuilder.setOfpactActions(nxActionNatCaseBuilder.build());
         List<CtActions> ctActionsList = new  ArrayList<>();
         ctActionsList.add(ctActionsBuilder.build());
+        nxActionNatBuilder = new NxActionNatBuilder();
+        nxActionNatBuilder.setFlags(5);
+        nxActionNatBuilder.setRangePresent(0x21);
+        nxActionNatBuilder.setIpAddressMin(new IpAddress("192.168.0.0".toCharArray()));
+        nxActionNatBuilder.setPortMax(4000);
+        nxActionNatCaseBuilder = new NxActionNatCaseBuilder();
+        nxActionNatCaseBuilder.setNxActionNat(nxActionNatBuilder.build());
+        ctActionsBuilder = new CtActionsBuilder();
+        ctActionsBuilder.setOfpactActions(nxActionNatCaseBuilder.build());
+        ctActionsList.add(ctActionsBuilder.build());
         nxActionConntrackBuilder.setCtActions(ctActionsList);
 
         ExperimenterId experimenterId = new ExperimenterId(NiciraConstants.NX_VENDOR_ID);
@@ -188,7 +214,7 @@ public class ConntrackCodecTest {
 
     private void createBufer(ByteBuf message) {
         message.writeShort(EncodeConstants.EXPERIMENTER_VALUE);
-        message.writeShort(length + nxastNatSubtype);
+        message.writeShort(length + nxNatLengthAction1 + nxNatLengthAction2);
         message.writeInt(NiciraConstants.NX_VENDOR_ID.intValue());
         message.writeShort(nxastConntrackSubtype);
         //FLAG = 1
@@ -202,7 +228,7 @@ public class ConntrackCodecTest {
         //ADDS 5 empty bytes
         message.writeZero(5);
         message.writeShort(EncodeConstants.EXPERIMENTER_VALUE);
-        message.writeShort(nxNatLength);
+        message.writeShort(nxNatLengthAction1);
         message.writeInt(NiciraConstants.NX_VENDOR_ID.intValue());
         message.writeShort(nxastNatSubtype);
         message.writeZero(2);
@@ -218,6 +244,22 @@ public class ConntrackCodecTest {
         message.writeShort(3000);
         //PORT MAX
         message.writeShort(4000);
+        message.writeZero(4);
+
+        message.writeShort(EncodeConstants.EXPERIMENTER_VALUE);
+        message.writeShort(nxNatLengthAction2);
+        message.writeInt(NiciraConstants.NX_VENDOR_ID.intValue());
+        message.writeShort(nxastNatSubtype);
+        message.writeZero(2);
+        //NAT FLAG
+        message.writeShort(5);
+        //RANGE PRESENT
+        message.writeShort(0x21);
+        //IP ADDRESS MIN
+        message.writeBytes(IetfInetUtil.INSTANCE.ipv4AddressBytes(new Ipv4Address("192.168.0.0")));
+        //PORT MAX
+        message.writeShort(4000);
+        message.writeZero(2);
     }
 
     private void createBuferWIthoutCtAction(ByteBuf message) {
diff --git a/extension/openflowjava-extension-nicira/src/test/java/org/opendaylight/openflowjava/nx/codec/match/Ipv6DstCodecTest.java b/extension/openflowjava-extension-nicira/src/test/java/org/opendaylight/openflowjava/nx/codec/match/Ipv6DstCodecTest.java
new file mode 100644 (file)
index 0000000..610d197
--- /dev/null
@@ -0,0 +1,94 @@
+/**
+ * Copyright (c) 2017 Red Hat, Inc. 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.match;
+
+import static org.junit.Assert.assertEquals;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufAllocator;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.openflowjava.protocol.api.util.OxmMatchConstants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.Nxm1Class;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmOfIpDst;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.ofj.nxm.of.match.ip.dst.grouping.IpDstValuesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.oxm.container.match.entry.value.IpDstCaseValue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.oxm.container.match.entry.value.IpDstCaseValueBuilder;
+
+public class Ipv6DstCodecTest {
+
+    Ipv6DstCodec ipv6DstCodec;
+    ByteBuf buffer;
+    MatchEntry input;
+
+    private static final int VALUE_LENGTH = 16;
+    private static final int NXM_FIELD_CODE = 20;
+
+    @Before
+    public void setUp() {
+        ipv6DstCodec = new Ipv6DstCodec();
+        buffer = ByteBufAllocator.DEFAULT.buffer();
+    }
+
+    @Test
+    public void serializeTest() {
+        input = createMatchEntry();
+        ipv6DstCodec.serialize(input, buffer);
+
+        assertEquals(OxmMatchConstants.NXM_1_CLASS, buffer.readUnsignedShort());
+        short fieldMask = buffer.readUnsignedByte();
+        assertEquals(NXM_FIELD_CODE, fieldMask >> 1);
+        assertEquals(0, fieldMask & 1);
+        assertEquals(VALUE_LENGTH, buffer.readUnsignedByte());
+        assertEquals(1, buffer.readUnsignedInt());
+    }
+
+    @Test
+    public void deserializeTest() {
+        createBuffer(buffer);
+
+        input = ipv6DstCodec.deserialize(buffer);
+
+        IpDstCaseValue result = ((IpDstCaseValue) input.getMatchEntryValue());
+
+        assertEquals(Nxm1Class.class, input.getOxmClass());
+        assertEquals(NxmOfIpDst.class, input.getOxmMatchField());
+        assertEquals(false, input.isHasMask());
+        assertEquals(2, result.getIpDstValues().getValue().intValue());
+    }
+
+
+    private MatchEntry createMatchEntry() {
+        MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
+        IpDstCaseValueBuilder caseBuilder = new IpDstCaseValueBuilder();
+        IpDstValuesBuilder valuesBuilder = new IpDstValuesBuilder();
+
+        matchEntryBuilder.setOxmClass(Nxm1Class.class);
+        matchEntryBuilder.setOxmMatchField(NxmOfIpDst.class);
+        matchEntryBuilder.setHasMask(false);
+
+        valuesBuilder.setValue((long)1);
+
+        caseBuilder.setIpDstValues(valuesBuilder.build());
+        matchEntryBuilder.setMatchEntryValue(caseBuilder.build());
+        return matchEntryBuilder.build();
+    }
+
+    private void createBuffer(ByteBuf message) {
+        message.writeShort(OxmMatchConstants.NXM_1_CLASS);
+
+        int fieldMask = (NXM_FIELD_CODE << 1);
+        message.writeByte(fieldMask);
+        message.writeByte(VALUE_LENGTH);
+        message.writeInt(2);
+    }
+
+}
diff --git a/extension/openflowjava-extension-nicira/src/test/java/org/opendaylight/openflowjava/nx/codec/match/Ipv6SrcCodecTest.java b/extension/openflowjava-extension-nicira/src/test/java/org/opendaylight/openflowjava/nx/codec/match/Ipv6SrcCodecTest.java
new file mode 100644 (file)
index 0000000..0bcb24b
--- /dev/null
@@ -0,0 +1,93 @@
+/**
+ * Copyright (c) 2017 Red Hat, Inc. 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.match;
+
+import static org.junit.Assert.assertEquals;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufAllocator;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.openflowjava.protocol.api.util.OxmMatchConstants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.Nxm1Class;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmOfIpSrc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.ofj.nxm.of.match.ip.src.grouping.IpSrcValuesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.oxm.container.match.entry.value.IpSrcCaseValue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.oxm.container.match.entry.value.IpSrcCaseValueBuilder;
+
+public class Ipv6SrcCodecTest {
+
+    Ipv6SrcCodec ipv6SrcCodec;
+    ByteBuf buffer;
+    MatchEntry input;
+
+    private static final int VALUE_LENGTH = 16;
+    private static final int NXM_FIELD_CODE = 19;
+
+    @Before
+    public void setUp() {
+        ipv6SrcCodec = new Ipv6SrcCodec();
+        buffer = ByteBufAllocator.DEFAULT.buffer();
+    }
+
+    @Test
+    public void serializeTest() {
+        input = createMatchEntry();
+        ipv6SrcCodec.serialize(input, buffer);
+
+        assertEquals(OxmMatchConstants.NXM_1_CLASS, buffer.readUnsignedShort());
+        short fieldMask = buffer.readUnsignedByte();
+        assertEquals(NXM_FIELD_CODE, fieldMask >> 1);
+        assertEquals(0, fieldMask & 1);
+        assertEquals(VALUE_LENGTH, buffer.readUnsignedByte());
+        assertEquals(1, buffer.readUnsignedInt());
+    }
+
+    @Test
+    public void deserializeTest() {
+        createBuffer(buffer);
+
+        input = ipv6SrcCodec.deserialize(buffer);
+
+        IpSrcCaseValue result = ((IpSrcCaseValue) input.getMatchEntryValue());
+
+        assertEquals(Nxm1Class.class, input.getOxmClass());
+        assertEquals(NxmOfIpSrc.class, input.getOxmMatchField());
+        assertEquals(false, input.isHasMask());
+        assertEquals(2, result.getIpSrcValues().getValue().intValue());
+    }
+
+    private MatchEntry createMatchEntry() {
+        MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
+        IpSrcCaseValueBuilder caseBuilder = new IpSrcCaseValueBuilder();
+        IpSrcValuesBuilder valuesBuilder = new IpSrcValuesBuilder();
+
+        matchEntryBuilder.setOxmClass(Nxm1Class.class);
+        matchEntryBuilder.setOxmMatchField(NxmOfIpSrc.class);
+        matchEntryBuilder.setHasMask(false);
+
+        valuesBuilder.setValue((long)1);
+
+        caseBuilder.setIpSrcValues(valuesBuilder.build());
+        matchEntryBuilder.setMatchEntryValue(caseBuilder.build());
+        return matchEntryBuilder.build();
+    }
+
+    private void createBuffer(ByteBuf message) {
+        message.writeShort(OxmMatchConstants.NXM_1_CLASS);
+
+        int fieldMask = (NXM_FIELD_CODE << 1);
+        message.writeByte(fieldMask);
+        message.writeByte(VALUE_LENGTH);
+        message.writeInt(2);
+    }
+
+}
index 838271d15ba7e38b0e2b68d11a9da0c317dd22b1..7eb2d45177718df6a73ea9556c9839a2649d6fd0 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.openflowplugin.extension.vendor.nicira.convertor.action;
 
+import com.google.common.base.Preconditions;
 import org.opendaylight.openflowjava.nx.NiciraMatchCodecs;
 import org.opendaylight.openflowjava.nx.codec.match.NxmHeader;
 import org.opendaylight.openflowplugin.extension.api.ConvertorActionFromOFJava;
@@ -33,8 +34,18 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.ni
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxArpShaCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxArpThaCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxArpThaCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxOfInPortCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxOfInPortCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxEncapEthDstCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxEncapEthDstCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxEncapEthSrcCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxEncapEthSrcCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxIpv6DstCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxIpv6DstCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxIpv6SrcCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxIpv6SrcCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNshMdtypeCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNshMdtypeCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNshNpCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNshNpCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNshc1Case;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNshc1CaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNshc2Case;
@@ -47,18 +58,12 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.ni
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNsiCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNspCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNspCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxEncapEthSrcCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxEncapEthSrcCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxEncapEthDstCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxEncapEthDstCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNshMdtypeCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNshMdtypeCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNshNpCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNshNpCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxTunGpeNpCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxTunGpeNpCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxOfInPortCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxOfInPortCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxRegCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxRegCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxTunGpeNpCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxTunGpeNpCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxTunIdCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxTunIdCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxTunIpv4DstCase;
@@ -100,6 +105,18 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.ni
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxArpShaCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxArpThaCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxArpThaCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxEncapEthDstCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxEncapEthDstCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxEncapEthSrcCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxEncapEthSrcCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxIpv6DstCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxIpv6DstCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxIpv6SrcCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxIpv6SrcCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNshMdtypeCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNshMdtypeCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNshNpCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNshNpCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNshc1Case;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNshc1CaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNshc2Case;
@@ -112,19 +129,13 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.ni
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNsiCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNspCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNspCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxEncapEthSrcCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxEncapEthSrcCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxEncapEthDstCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxEncapEthDstCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNshMdtypeCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNshMdtypeCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNshNpCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNshNpCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxOfInPortCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxOfInPortCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxOfMplsLabelCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxTunGpeNpCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxTunGpeNpCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxRegCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxRegCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxTunGpeNpCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxTunGpeNpCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxTunIdCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxTunIdCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxTunIpv4DstCase;
@@ -147,10 +158,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.ni
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcOfIpDstCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcOfIpSrcCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcOfIpSrcCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxOfInPortCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxOfInPortCaseBuilder;
-
-import com.google.common.base.Preconditions;
 
 /**
  * @author msunal
@@ -257,6 +264,12 @@ public class RegMoveConvertor implements
         if (dstValue == NiciraMatchCodecs.IP_DST_CODEC.getHeaderWithoutHasMask().toLong()) {
             return new DstOfIpDstCaseBuilder().setOfIpDst(true).build();
         }
+        if (dstValue == NiciraMatchCodecs.IPV6_SRC_CODEC.getHeaderWithoutHasMask().toLong()) {
+            return new DstNxIpv6SrcCaseBuilder().setNxIpv6Src(true).build();
+        }
+        if (dstValue == NiciraMatchCodecs.IPV6_DST_CODEC.getHeaderWithoutHasMask().toLong()) {
+            return new DstNxIpv6DstCaseBuilder().setNxIpv6Dst(true).build();
+        }
         if (dstValue == NiciraMatchCodecs.ICMP_TYPE_CODEC.getHeaderWithoutHasMask().toLong()) {
             return new DstOfIcmpTypeCaseBuilder().setOfIcmpType(true).build();
         }
@@ -344,6 +357,12 @@ public class RegMoveConvertor implements
         if (srcValue == NiciraMatchCodecs.IP_SRC_CODEC.getHeaderWithoutHasMask().toLong()) {
             return new SrcOfIpSrcCaseBuilder().setOfIpSrc(true).build();
         }
+        if (srcValue == NiciraMatchCodecs.IPV6_SRC_CODEC.getHeaderWithoutHasMask().toLong()) {
+            return new SrcNxIpv6SrcCaseBuilder().setNxIpv6Src(true).build();
+        }
+        if (srcValue == NiciraMatchCodecs.IPV6_DST_CODEC.getHeaderWithoutHasMask().toLong()) {
+            return new SrcNxIpv6DstCaseBuilder().setNxIpv6Dst(true).build();
+        }
 
         throw new CodecPreconditionException("Missing codec for " + new NxmHeader(srcValue));
     }
@@ -485,6 +504,12 @@ public class RegMoveConvertor implements
         if (dstChoice instanceof DstOfIpDstCase) {
             return NiciraMatchCodecs.IP_DST_CODEC.getHeaderWithoutHasMask().toLong();
         }
+        if (dstChoice instanceof DstNxIpv6SrcCase) {
+            return NiciraMatchCodecs.IPV6_SRC_CODEC.getHeaderWithoutHasMask().toLong();
+        }
+        if (dstChoice instanceof DstNxIpv6DstCase) {
+            return NiciraMatchCodecs.IPV6_DST_CODEC.getHeaderWithoutHasMask().toLong();
+        }
         if (dstChoice instanceof DstOfIcmpTypeCase) {
             return NiciraMatchCodecs.ICMP_TYPE_CODEC.getHeaderWithoutHasMask().toLong();
         }
@@ -581,6 +606,12 @@ public class RegMoveConvertor implements
         if (srcChoice instanceof SrcOfIpDstCase) {
             return NiciraMatchCodecs.IP_DST_CODEC.getHeaderWithoutHasMask().toLong();
         }
+        if (srcChoice instanceof SrcNxIpv6SrcCase) {
+            return NiciraMatchCodecs.IPV6_SRC_CODEC.getHeaderWithoutHasMask().toLong();
+        }
+        if (srcChoice instanceof SrcNxIpv6DstCase) {
+            return NiciraMatchCodecs.IPV6_DST_CODEC.getHeaderWithoutHasMask().toLong();
+        }
         if (srcChoice instanceof SrcNxEncapEthSrcCase) {
             return  NiciraMatchCodecs.ENCAP_ETH_SRC_CODEC.getHeaderWithoutHasMask().toLong();
         }
index 7993262134cefd49921443e4ca050bde2ed52f0c..4a9def9c09882ee4850834cec020c72db489acf4 100644 (file)
@@ -145,6 +145,16 @@ module openflowplugin-extension-nicira-action {
             type empty;
         }
     }
+    grouping nxm-nx-ipv6-src-grouping {
+        leaf nx-ipv6-src {
+            type empty;
+        }
+    }
+    grouping nxm-nx-ipv6-dst-grouping {
+        leaf nx-ipv6-dst {
+            type empty;
+        }
+    }
     grouping nxm-of-icmp-type-grouping {
         leaf of-icmp-type {
             type empty;
@@ -241,6 +251,12 @@ module openflowplugin-extension-nicira-action {
             case dst-of-ip-dst-case {
                 uses nxm-of-ip-dst-grouping;
             }
+            case dst-nx-ipv6-src-case {
+                uses nxm-nx-ipv6-src-grouping;
+            }
+            case dst-nx-ipv6-dst-case {
+                uses nxm-nx-ipv6-dst-grouping;
+            }
             case dst-of-icmp-type-case {
                 uses nxm-of-icmp-type-grouping;
             }
@@ -330,6 +346,12 @@ module openflowplugin-extension-nicira-action {
             case src-of-ip-dst-case {
                 uses nxm-of-ip-dst-grouping;
             }
+            case src-nx-ipv6-src-case {
+                uses nxm-nx-ipv6-src-grouping;
+            }
+            case src-nx-ipv6-dst-case {
+                uses nxm-nx-ipv6-dst-grouping;
+            }
             case src-nx-encap-eth-src-case {
                 uses nxm-nx-encap-eth-src-grouping;
             }
index 813a8b225a025eb68bab1d0354626744507b99f3..d23aa28e0dfea967258b45449802289c027a1dbd 100644 (file)
@@ -240,6 +240,9 @@ module flow-node-inventory {
 
     grouping flow-node-connector {
         description "Wrapper of openflow port. TODO::simplify/rename";
+        leaf reason {
+            type port:port-reason;
+        }
         uses port:flow-capable-port;
     }
 
index 4752cf38bbfdb864c411b44b64a3df5461955f4c..43d6b5bdc234289c8c07e785e81e5e5ed651d438 100644 (file)
@@ -24,14 +24,6 @@ public interface OFPContext extends AutoCloseable, ClusterLifecycleSupervisor, C
 
     String MESSAGE = "Cannot stop abstract services, check implementation of cluster services";
 
-    /**
-     * Replace actual connection.
-     * @param connectionContext new connection
-     */
-    default void replaceConnection(final ConnectionContext connectionContext) {
-        //Nothing to do
-    }
-
     /**
      * Context state.
      */
@@ -53,20 +45,8 @@ public interface OFPContext extends AutoCloseable, ClusterLifecycleSupervisor, C
     /**
      * About to stop services in cluster not master anymore or going down.
      * @return Future most of services need time to be closed.
-     * @param connectionInterrupted true if clustering services stopping by device disconnect.
      */
-    default ListenableFuture<Void> stopClusterServices(boolean connectionInterrupted) {
-        return Futures.immediateFailedFuture(
-                new RejectedExecutionException(MESSAGE));
-    }
-
-    /**
-     * About to stop services in cluster not master anymore or going down.
-     * @return Future most of services need time to be closed.
-     */
-    default ListenableFuture<Void> stopClusterServices() {
-        return stopClusterServices(false);
-    }
+    ListenableFuture<Void> stopClusterServices();
 
     /**
      * Get cluster singleton service identifier.
index ff9e342e0c576229e2232cbf9fb3dbe88f6e6fb3..2c633542700c306bd326c48b87bb96a2cbd2a5d3 100644 (file)
@@ -8,6 +8,7 @@
 
 package org.opendaylight.openflowplugin.api.openflow.connection;
 
+import java.util.List;
 import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
 import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueue;
 import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueueHandlerRegistration;
@@ -15,6 +16,7 @@ import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceDisconnectedHandler;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage;
 
 /**
  * <p>
@@ -153,4 +155,13 @@ public interface ConnectionContext {
      * Should be called after nodeId and features are set in connection context.
      */
     void handshakeSuccessful();
+
+    /**
+     * Handle received port status message
+     * @param portStatusMessage port status message
+     */
+    void handlePortStatusMessage(PortStatusMessage portStatusMessage);
+
+    List<PortStatusMessage> retrieveAndClearPortStatusMessages();
+
 }
index f73eb9245264e5a54a2058688a3a0bc4aa80984d..b4fd0469b2437d162704e1dc685c83cc123e7f04 100644 (file)
@@ -18,7 +18,7 @@ import org.opendaylight.openflowplugin.api.openflow.OFPContext;
 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceReplyProcessor;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.MultiMsgCollector;
-import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleService;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.ContextChainStateListener;
 import org.opendaylight.openflowplugin.api.openflow.registry.ItemLifeCycleRegistry;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
@@ -45,7 +45,8 @@ public interface DeviceContext extends
         DeviceReplyProcessor,
         TxFacade,
         DeviceRegistry,
-        RequestContextStack {
+        RequestContextStack,
+        ContextChainStateListener {
 
     /**
      * Method close all auxiliary connections and primary connection.
@@ -132,8 +133,6 @@ public interface DeviceContext extends
 
     void setSwitchFeaturesMandatory(boolean switchFeaturesMandatory);
 
-    void putLifecycleServiceIntoTxChainManager(LifecycleService lifecycleService);
-
     boolean isSkipTableFeatures();
 
     /**
index ae453e050f58d7a52b9feee3742abc809e2adeb3..f876e677a93efe27c0aca097fa5626d94f8a3c20 100644 (file)
@@ -28,10 +28,9 @@ public interface ContextChain extends AutoCloseable {
 
     /**
      * Stop the working contexts, but not release them.
-     * @param connectionDropped true if stop the chain due to connection drop
      * @return Future
      */
-    ListenableFuture<Void> stopChain(boolean connectionDropped);
+    ListenableFuture<Void> stopChain();
 
     @Override
     void close();
diff --git a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/lifecycle/ContextChainStateListener.java b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/lifecycle/ContextChainStateListener.java
new file mode 100644 (file)
index 0000000..c9dfb39
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.api.openflow.lifecycle;
+
+/**
+ * Listens to changes about context chain state
+ */
+public interface ContextChainStateListener {
+
+    /**
+     * Event triggered on context chain state change
+     * @param state context chain state
+     */
+    void onStateAcquired(ContextChainState state);
+
+}
index 22475ab3836e0bc0400a4d2a3a5c2cec416f075e..aab1ce1705697ac815b8d9e5ace42c2b2647946c 100644 (file)
@@ -19,9 +19,20 @@ public interface MastershipChangeListener {
      * Event occurs if there was a try to acquire MASTER role.
      * But it was not possible to start this MASTER role on device.
      * @param deviceInfo for this device
-     * @param reason
+     * @param reason reason
+     * @param mandatory if it is mandatory connection will be dropped
      */
-    void onNotAbleToStartMastership(final DeviceInfo deviceInfo, @Nonnull final String reason);
+    void onNotAbleToStartMastership(final DeviceInfo deviceInfo, @Nonnull final String reason, final boolean mandatory);
+
+    /**
+     * Event occurs if there was a try to acquire MASTER role.
+     * But it was not possible to start this MASTER role on device.
+     * @param deviceInfo for this device
+     * @param reason reason
+     */
+    default void onNotAbleToStartMastershipMandatory(final DeviceInfo deviceInfo, @Nonnull final String reason) {
+        onNotAbleToStartMastership(deviceInfo, reason, true);
+    }
 
     /**
      * Changed to MASTER role on device.
index f68ec73839122308202f38fe7268b3b1834dea15..9b45e66a67802cea2e47e809b541e1a5527540be 100644 (file)
@@ -11,6 +11,9 @@ package org.opendaylight.openflowplugin.impl.connection;
 import com.google.common.base.Preconditions;
 import java.math.BigInteger;
 import java.net.InetSocketAddress;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 import java.util.Objects;
 import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
 import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
@@ -27,6 +30,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage;
 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -46,6 +50,7 @@ public class ConnectionContextImpl implements ConnectionContext {
     private OutboundQueueHandlerRegistration<OutboundQueueProvider> outboundQueueHandlerRegistration;
     private HandshakeContext handshakeContext;
     private DeviceInfo deviceInfo;
+    private List<PortStatusMessage> portStatusMessages = new ArrayList<>();
 
     /**
      * @param connectionAdapter
@@ -114,6 +119,7 @@ public class ConnectionContextImpl implements ConnectionContext {
         }
         connectionState = ConnectionContext.CONNECTION_STATE.RIP;
 
+        portStatusMessages.clear();
         unregisterOutboundQueue();
         closeHandshakeContext();
 
@@ -141,7 +147,6 @@ public class ConnectionContextImpl implements ConnectionContext {
 
     @Override
     public void onConnectionClosed() {
-
         connectionState = ConnectionContext.CONNECTION_STATE.RIP;
 
         if (null == nodeId){
@@ -163,6 +168,7 @@ public class ConnectionContextImpl implements ConnectionContext {
                 auxiliaryId,
                 getConnectionState());
 
+        portStatusMessages.clear();
         unregisterOutboundQueue();
         closeHandshakeContext();
         propagateDeviceDisconnectedEvent();
@@ -218,6 +224,24 @@ public class ConnectionContextImpl implements ConnectionContext {
         connectionState = CONNECTION_STATE.WORKING;
     }
 
+    @Override
+    public void handlePortStatusMessage(final PortStatusMessage portStatusMessage) {
+        if (Objects.isNull(deviceInfo)) {
+            LOG.debug("NOOP: Port-status message during handshake phase not supported: {}", portStatusMessage);
+            return;
+        }
+
+        LOG.debug("Handling alien port status message {} for node {}", portStatusMessage, nodeId);
+        portStatusMessages.add(portStatusMessage);
+    }
+
+    @Override
+    public List<PortStatusMessage> retrieveAndClearPortStatusMessages() {
+        final List<PortStatusMessage> immutablePortStatusMessages = Collections.unmodifiableList(portStatusMessages);
+        portStatusMessages.clear();
+        return immutablePortStatusMessages;
+    }
+
     @Override
     public DeviceInfo getDeviceInfo() {
         return this.deviceInfo;
index 696743f31a744ffa8f3a8576457affd239d35dfd..afac7ac95836b01fb6609b4683dd28cb1b665902 100644 (file)
@@ -69,18 +69,18 @@ public class HandshakeListenerImpl implements HandshakeListener {
             @Override
             public void onSuccess(@Nullable final RpcResult<BarrierOutput> result) {
                 if (LOG.isDebugEnabled()) {
-                    LOG.debug("succeeded by getting sweep barrier after post-handshake for device {}", connectionContext.getNodeId().getValue());
+                    LOG.debug("succeeded by getting sweep barrier after post-handshake for device {}", connectionContext.getDeviceInfo().getLOGValue());
                 }
                 try {
                     ConnectionStatus connectionStatusResult = deviceConnectedHandler.deviceConnected(connectionContext);
                     if (!ConnectionStatus.MAY_CONTINUE.equals(connectionStatusResult)) {
                         connectionContext.closeConnection(true);
                     }
-                    SessionStatistics.countEvent(connectionContext.getNodeId().toString(),
+                    SessionStatistics.countEvent(connectionContext.getDeviceInfo().getLOGValue(),
                             SessionStatistics.ConnectionStatus.CONNECTION_CREATED);
                 } catch (final Exception e) {
-                    LOG.error("ConnectionContext initial processing failed: ", e);
-                    SessionStatistics.countEvent(connectionContext.getNodeId().toString(),
+                    LOG.error("ConnectionContext initial processing failed for device {}", connectionContext.getDeviceInfo().getLOGValue(), e);
+                    SessionStatistics.countEvent(connectionContext.getDeviceInfo().getLOGValue(),
                             SessionStatistics.ConnectionStatus.CONNECTION_DISCONNECTED_BY_OFP);
                     connectionContext.closeConnection(true);
                 }
@@ -88,7 +88,7 @@ public class HandshakeListenerImpl implements HandshakeListener {
 
             @Override
             public void onFailure(final Throwable t) {
-                LOG.error("failed to get sweep barrier after post-handshake for device {}", connectionContext.getNodeId());
+                LOG.error("failed to get sweep barrier after post-handshake for device {}", connectionContext.getDeviceInfo().getLOGValue(), t);
                 connectionContext.closeConnection(false);
             }
         };
index ff8eb07bd4559cc63325c75cb7d56a9c038fb8d0..fb6cdcb0282033028ac05529287a3b2b4244edb7 100644 (file)
@@ -115,7 +115,7 @@ public class OpenflowProtocolListenerInitialImpl implements OpenflowProtocolList
 
     @Override
     public void onPortStatusMessage(final PortStatusMessage notification) {
-        LOG.debug("NOOP: Port-status message during handshake phase not supported: {}", notification);
+        connectionContext.handlePortStatusMessage(notification);
     }
 
     /**
index 8faf97fb9857622e964f69269fd4367dcd08775d..1fefc1fc3458eac66e659aefdc22aaf2e5cb6ea4 100644 (file)
@@ -8,6 +8,7 @@
 
 package org.opendaylight.openflowplugin.impl.datastore.multipart;
 
+import org.opendaylight.openflowplugin.api.OFConstants;
 import org.opendaylight.openflowplugin.api.openflow.device.TxFacade;
 import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
 import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
@@ -59,7 +60,7 @@ public class PortStatsMultipartWriter extends AbstractMultipartWriter<NodeConnec
                         .child(FlowCapableNodeConnectorStatistics.class),
                     new FlowCapableNodeConnectorStatisticsBuilder(stat)
                         .build(),
-                    withParents);
+                        OFConstants.OFP_VERSION_1_0 == features.getVersion() || withParents);
             });
     }
 
index e743e9ef037a3aa317316e0917f4ca467348a4f6..34a59a0b4a369de393f46eb03002007226b55de1 100644 (file)
@@ -8,7 +8,6 @@
 package org.opendaylight.openflowplugin.impl.device;
 
 import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Function;
 import com.google.common.base.Optional;
 import com.google.common.base.Verify;
 import com.google.common.util.concurrent.FutureCallback;
@@ -27,6 +26,7 @@ import java.util.Objects;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
@@ -35,12 +35,10 @@ import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
 import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
-import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueueHandlerRegistration;
 import org.opendaylight.openflowjava.protocol.api.keys.MessageTypeKey;
 import org.opendaylight.openflowplugin.api.ConnectionException;
 import org.opendaylight.openflowplugin.api.OFConstants;
 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
-import org.opendaylight.openflowplugin.api.openflow.connection.OutboundQueueProvider;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceManager;
@@ -52,7 +50,7 @@ import org.opendaylight.openflowplugin.api.openflow.device.Xid;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.ClusterInitializationPhaseHandler;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.MultiMsgCollector;
 import org.opendaylight.openflowplugin.api.openflow.lifecycle.ContextChainMastershipState;
-import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleService;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.ContextChainState;
 import org.opendaylight.openflowplugin.api.openflow.lifecycle.MastershipChangeListener;
 import org.opendaylight.openflowplugin.api.openflow.md.core.SwitchConnectionDistinguisher;
 import org.opendaylight.openflowplugin.api.openflow.md.core.TranslatorKey;
@@ -77,7 +75,6 @@ import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProviderFac
 import org.opendaylight.openflowplugin.impl.device.initialization.AbstractDeviceInitializer;
 import org.opendaylight.openflowplugin.impl.device.initialization.DeviceInitializerProvider;
 import org.opendaylight.openflowplugin.impl.device.listener.MultiMsgCollectorImpl;
-import org.opendaylight.openflowplugin.impl.device.listener.OpenflowProtocolListenerFullImpl;
 import org.opendaylight.openflowplugin.impl.registry.flow.DeviceFlowRegistryImpl;
 import org.opendaylight.openflowplugin.impl.registry.flow.FlowRegistryKeyFactory;
 import org.opendaylight.openflowplugin.impl.registry.group.DeviceGroupRegistryImpl;
@@ -137,6 +134,9 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
     // Timeout in seconds after what we will give up on propagating role
     private static final int SET_ROLE_TIMEOUT = 10;
 
+    // Timeout in milliseconds after what we will give up on initializing device
+    private static final int DEVICE_INIT_TIMEOUT = 9000;
+
     private static final int LOW_WATERMARK = 1000;
     private static final int HIGH_WATERMARK = 2000;
     private final MultipartWriterProvider writerProvider;
@@ -173,8 +173,7 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
     private final DeviceManager myManager;
     private final DeviceInitializerProvider deviceInitializerProvider;
     private final boolean useSingleLayerSerialization;
-    private OutboundQueueProvider outboundQueueProvider;
-    private boolean isInitialTransactionSubmitted;
+    private boolean hasState;
 
     DeviceContextImpl(
             @Nonnull final ConnectionContext primaryConnectionContext,
@@ -189,7 +188,6 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
             final DeviceInitializerProvider deviceInitializerProvider) {
 
         this.primaryConnectionContext = primaryConnectionContext;
-        this.outboundQueueProvider = (OutboundQueueProvider) primaryConnectionContext.getOutboundQueueProvider();
         this.deviceInfo = primaryConnectionContext.getDeviceInfo();
         this.hashedWheelTimer = hashedWheelTimer;
         this.deviceInitializerProvider = deviceInitializerProvider;
@@ -223,12 +221,7 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
 
     @Override
     public boolean initialSubmitTransaction() {
-        if (initialized) {
-            isInitialTransactionSubmitted = true;
-            return transactionChainManager.initialSubmitWriteTransaction();
-        }
-
-        return false;
+        return (initialized && transactionChainManager.initialSubmitWriteTransaction());
     }
 
     @Override
@@ -371,7 +364,7 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
     public void processPortStatusMessage(final PortStatusMessage portStatus) {
         messageSpy.spyMessage(portStatus.getImplementedInterface(), MessageSpy.STATISTIC_GROUP.FROM_SWITCH_PUBLISHED_SUCCESS);
 
-        if (isInitialTransactionSubmitted) {
+        if (initialized) {
             try {
                 writePortStatusMessage(portStatus);
                 submitTransaction();
@@ -379,6 +372,8 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
                 LOG.warn("Error processing port status message for port {} on device {}",
                         portStatus.getPortNo(), getDeviceInfo().getLOGValue(), e);
             }
+        } else if (!hasState) {
+            primaryConnectionContext.handlePortStatusMessage(portStatus);
         }
     }
 
@@ -587,77 +582,16 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
         this.switchFeaturesMandatory = switchFeaturesMandatory;
     }
 
-    @Override
-    public synchronized void replaceConnection(final ConnectionContext connectionContext) {
-
-        primaryConnectionContext = null;
-        deviceInfo = null;
-        packetInLimiter = null;
-
-        primaryConnectionContext = connectionContext;
-        deviceInfo = primaryConnectionContext.getDeviceInfo();
-
-        packetInLimiter = new PacketInRateLimiter(primaryConnectionContext.getConnectionAdapter(),
-                /*initial*/ LOW_WATERMARK, /*initial*/HIGH_WATERMARK, messageSpy, REJECTED_DRAIN_FACTOR);
-
-        primaryConnectionContext.setOutboundQueueProvider(outboundQueueProvider);
-
-        final OutboundQueueHandlerRegistration<OutboundQueueProvider> outboundQueueHandlerRegistration =
-                primaryConnectionContext.getConnectionAdapter().registerOutboundQueueHandler(
-                        outboundQueueProvider,
-                        myManager.getBarrierCountLimit(),
-                        myManager.getBarrierIntervalNanos());
-
-        primaryConnectionContext.setOutboundQueueHandleRegistration(outboundQueueHandlerRegistration);
-
-        final OpenflowProtocolListenerFullImpl messageListener = new OpenflowProtocolListenerFullImpl(
-                primaryConnectionContext.getConnectionAdapter(), this);
-
-        primaryConnectionContext.getConnectionAdapter().setMessageListener(messageListener);
-
-        LOG.info("ConnectionEvent: Connection on device:{}, NodeId:{} switched.",
-                primaryConnectionContext.getConnectionAdapter().getRemoteAddress(),
-                primaryConnectionContext.getDeviceInfo().getNodeId());
-
-    }
-
     @Override
     public CONTEXT_STATE getState() {
         return this.state;
     }
 
     @Override
-    public ListenableFuture<Void> stopClusterServices(boolean connectionInterrupted) {
-        final ListenableFuture<Void> deactivateTxManagerFuture = initialized
+    public ListenableFuture<Void> stopClusterServices() {
+        return initialized
                 ? transactionChainManager.deactivateTransactionManager()
                 : Futures.immediateFuture(null);
-
-        if (!connectionInterrupted) {
-            final ListenableFuture<Void> makeSlaveFuture
-                    = Futures.transform(makeDeviceSlave(), new Function<RpcResult<SetRoleOutput>, Void>() {
-                @Nullable
-                @Override
-                public Void apply(@Nullable RpcResult<SetRoleOutput> setRoleOutputRpcResult) {
-                    return null;
-                }
-            });
-
-            Futures.addCallback(makeSlaveFuture, new FutureCallback<Void>() {
-                @Override
-                public void onSuccess(@Nullable Void aVoid) {
-                    if (LOG.isDebugEnabled()) {
-                        LOG.debug("Role SLAVE was successfully propagated on device, node {}", deviceInfo.getLOGValue());
-                    }
-                }
-
-                @Override
-                public void onFailure(final Throwable throwable) {
-                    LOG.warn("Was not able to set role SLAVE to device on node {} ", deviceInfo.getLOGValue());
-                    LOG.trace("Error occurred on device role setting, probably connection loss: ", throwable);
-                }
-            });
-        }
-        return deactivateTxManagerFuture;
     }
 
     @Override
@@ -675,13 +609,6 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
         //NOOP
     }
 
-    @Override
-    public void putLifecycleServiceIntoTxChainManager(final LifecycleService lifecycleService){
-        if (initialized) {
-            this.transactionChainManager.setLifecycleService(lifecycleService);
-        }
-    }
-
     @Override
     public boolean canUseSingleLayerSerialization() {
         return useSingleLayerSerialization && getDeviceInfo().getVersion() >= OFConstants.OFP_VERSION_1_3;
@@ -707,19 +634,32 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
 
         LOG.info("Starting device context cluster services for node {}", deviceInfo.getLOGValue());
         lazyTransactionManagerInitialization();
-        this.transactionChainManager.activateTransactionManager();
+
+        try {
+            final List<PortStatusMessage> portStatusMessages = primaryConnectionContext
+                    .retrieveAndClearPortStatusMessages();
+
+            portStatusMessages.forEach(this::writePortStatusMessage);
+            submitTransaction();
+        } catch (final Exception ex) {
+            LOG.warn("Error processing port status messages from device {}", getDeviceInfo().getLOGValue(), ex);
+            return false;
+        }
 
         try {
             final java.util.Optional<AbstractDeviceInitializer> initializer = deviceInitializerProvider
                     .lookup(deviceInfo.getVersion());
 
             if (initializer.isPresent()) {
-                initializer.get().initialize(this, switchFeaturesMandatory, writerProvider, convertorExecutor);
+                initializer
+                        .get()
+                        .initialize(this, switchFeaturesMandatory, writerProvider, convertorExecutor)
+                        .get(DEVICE_INIT_TIMEOUT, TimeUnit.MILLISECONDS);
             } else {
                 throw new ExecutionException(new ConnectionException("Unsupported version " + deviceInfo.getVersion()));
             }
-        } catch (ExecutionException | InterruptedException e) {
-            LOG.warn("Device {} cannot be initialized: ", deviceInfo.getLOGValue(), e);
+        } catch (ExecutionException | InterruptedException | TimeoutException ex) {
+            LOG.warn("Device {} cannot be initialized: ", deviceInfo.getLOGValue(), ex);
             return false;
         }
 
@@ -743,6 +683,7 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
             this.deviceFlowRegistry = new DeviceFlowRegistryImpl(deviceInfo.getVersion(), dataBroker, deviceInfo.getNodeInstanceIdentifier());
             this.deviceGroupRegistry = new DeviceGroupRegistryImpl();
             this.deviceMeterRegistry = new DeviceMeterRegistryImpl();
+            this.transactionChainManager.activateTransactionManager();
             this.initialized = true;
         }
     }
@@ -792,6 +733,11 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
         return sendRoleChangeToDevice(OfpRole.BECOMESLAVE);
     }
 
+    @Override
+    public void onStateAcquired(final ContextChainState state) {
+        hasState = true;
+    }
+
     private class RpcResultFutureCallback implements FutureCallback<RpcResult<SetRoleOutput>> {
 
         private final MastershipChangeListener mastershipChangeListener;
@@ -813,7 +759,7 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
 
         @Override
         public void onFailure(final Throwable throwable) {
-            mastershipChangeListener.onNotAbleToStartMastership(
+            mastershipChangeListener.onNotAbleToStartMastershipMandatory(
                     deviceInfo,
                     "Was not able to set MASTER role on device");
         }
@@ -865,7 +811,8 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
             }
             mastershipChangeListener.onNotAbleToStartMastership(
                     deviceInfo,
-                    "Was not able to fill flow registry on device");
+                    "Was not able to fill flow registry on device",
+                    false);
         }
     }
 
index 94286671a219c90d951f61ab444a63d72f96882e..244069f2d9328a849de33b288b5afdafba329cbb 100644 (file)
@@ -304,7 +304,9 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
         if (LOG.isDebugEnabled()) {
             LOG.debug("Device context removed for node {}", deviceInfo.getLOGValue());
         }
-        this.updatePacketInRateLimiters();
+        if (deviceContexts.size() > 0) {
+            this.updatePacketInRateLimiters();
+        }
     }
 
     @Override
index 04b212f0856bad7b7b208a3f4c263c1c0838806e..e0f1027273e58fe6617d0739493061729514ade2 100644 (file)
@@ -21,7 +21,6 @@ import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
 import javax.annotation.concurrent.GuardedBy;
 import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
@@ -33,7 +32,6 @@ import org.opendaylight.controller.md.sal.common.api.data.TransactionChainClosed
 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
-import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleService;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
@@ -56,7 +54,6 @@ class TransactionChainManager implements TransactionChainListener, AutoCloseable
     private final Object txLock = new Object();
     private final DataBroker dataBroker;
     private final String nodeId;
-    private LifecycleService lifecycleService;
 
     @GuardedBy("txLock")
     private WriteTransaction wTx;
@@ -75,7 +72,7 @@ class TransactionChainManager implements TransactionChainListener, AutoCloseable
     TransactionChainManager(@Nonnull final DataBroker dataBroker,
                             @Nonnull final DeviceInfo deviceInfo) {
         this.dataBroker = dataBroker;
-        this.nodeId = deviceInfo.getNodeInstanceIdentifier().getKey().getId().getValue();
+        this.nodeId = deviceInfo.getLOGValue();
         this.lastSubmittedFuture = Futures.immediateFuture(null);
     }
 
@@ -86,10 +83,6 @@ class TransactionChainManager implements TransactionChainListener, AutoCloseable
         Optional.ofNullable(txChainFactoryTemp).ifPresent(TransactionChain::close);
     }
 
-    public void setLifecycleService(final LifecycleService lifecycleService) {
-        this.lifecycleService = lifecycleService;
-    }
-
     boolean initialSubmitWriteTransaction() {
         enableSubmit();
         return submitWriteTransaction();
@@ -102,12 +95,15 @@ class TransactionChainManager implements TransactionChainListener, AutoCloseable
      */
     void activateTransactionManager() {
         if (LOG.isDebugEnabled()) {
-            LOG.debug("activateTransactionManager for node {} transaction submit is set to {}", this.nodeId, submitIsEnabled);
+            LOG.debug("activateTransactionManager for node {} transaction submit is set to {}",
+                    this.nodeId, submitIsEnabled);
         }
         synchronized (txLock) {
             if (TransactionChainManagerStatus.SLEEPING == transactionChainManagerStatus) {
-                Preconditions.checkState(txChainFactory == null, "TxChainFactory survive last close.");
-                Preconditions.checkState(wTx == null, "We have some unexpected WriteTransaction.");
+                Preconditions.checkState(txChainFactory == null,
+                        "TxChainFactory survive last close.");
+                Preconditions.checkState(wTx == null,
+                        "We have some unexpected WriteTransaction.");
                 this.transactionChainManagerStatus = TransactionChainManagerStatus.WORKING;
                 this.submitIsEnabled = false;
                 this.initCommit = true;
@@ -131,7 +127,8 @@ class TransactionChainManager implements TransactionChainListener, AutoCloseable
             if (TransactionChainManagerStatus.WORKING == transactionChainManagerStatus) {
                 transactionChainManagerStatus = TransactionChainManagerStatus.SLEEPING;
                 future = txChainShuttingDown();
-                Preconditions.checkState(wTx == null, "We have some unexpected WriteTransaction.");
+                Preconditions.checkState(wTx == null,
+                        "We have some unexpected WriteTransaction.");
                 Futures.addCallback(future, new FutureCallback<Void>() {
                     @Override
                     public void onSuccess(final Void result) {
@@ -144,7 +141,7 @@ class TransactionChainManager implements TransactionChainListener, AutoCloseable
                     }
                 });
             } else {
-                // TODO : ignoring redundant deactivate invocation
+                // ignoring redundant deactivate invocation
                 future = Futures.immediateCheckedFuture(null);
             }
         }
@@ -171,7 +168,8 @@ class TransactionChainManager implements TransactionChainListener, AutoCloseable
                 return true;
             }
             Preconditions.checkState(TransactionChainManagerStatus.WORKING == transactionChainManagerStatus,
-                    "we have here Uncompleted Transaction for node {} and we are not MASTER", this.nodeId);
+                    "we have here Uncompleted Transaction for node {} and we are not MASTER",
+                    this.nodeId);
             final CheckedFuture<Void, TransactionCommitFailedException> submitFuture = wTx.submit();
             lastSubmittedFuture = submitFuture;
             wTx = null;
@@ -257,7 +255,6 @@ class TransactionChainManager implements TransactionChainListener, AutoCloseable
     }
 
     @GuardedBy("txLock")
-    @Nullable
     private void ensureTransaction() {
         if (wTx == null && TransactionChainManagerStatus.WORKING == transactionChainManagerStatus
             && txChainFactory != null) {
index 25a84ef0aca9febd6a44abb2b2602d5cd6830017..0380b47b77a78622ffa9d20d0deb596c12709b6a 100644 (file)
@@ -32,10 +32,10 @@ public abstract class AbstractDeviceInitializer {
      * @param deviceContext device context
      * @param multipartWriterProvider multipart writer provider
      */
-    public void initialize(@Nonnull final DeviceContext deviceContext,
-                           final boolean switchFeaturesMandatory,
-                           @Nullable final MultipartWriterProvider multipartWriterProvider,
-                           @Nullable final ConvertorExecutor convertorExecutor) throws ExecutionException,InterruptedException {
+    public Future<Void> initialize(@Nonnull final DeviceContext deviceContext,
+                                   final boolean switchFeaturesMandatory,
+                                   @Nullable final MultipartWriterProvider multipartWriterProvider,
+                                   @Nullable final ConvertorExecutor convertorExecutor) throws ExecutionException,InterruptedException {
         Preconditions.checkNotNull(deviceContext);
 
         // Write node to datastore
@@ -53,9 +53,8 @@ public abstract class AbstractDeviceInitializer {
             throw new ExecutionException(new ConnectionException("Failed to write node " + deviceContext.getDeviceInfo().getNodeId() + " to DS ", e));
         }
 
-        // Synchronously get information about device
-        initializeNodeInformation(deviceContext, switchFeaturesMandatory, multipartWriterProvider, convertorExecutor)
-            .get();
+        // Get information about device
+        return initializeNodeInformation(deviceContext, switchFeaturesMandatory, multipartWriterProvider, convertorExecutor);
     }
 
     protected abstract Future<Void> initializeNodeInformation(@Nonnull final DeviceContext deviceContext,
index 5e77567394ecca36e6a8fe8360c9307d224f5dc6..44c9565b8fce9f819bb0ca229d99a6f49a7b3786 100644 (file)
@@ -82,13 +82,13 @@ public class ContextChainHolderImpl implements ContextChainHolder {
     @Override
     public <T extends OFPManager> void addManager(final T manager) {
         if (Objects.isNull(deviceManager) && manager instanceof DeviceManager) {
-            LOG.debug("Device manager was set.");
+            LOG.trace("Context chain holder: Device manager OK.");
             deviceManager = (DeviceManager) manager;
         } else if (Objects.isNull(rpcManager) && manager instanceof RpcManager) {
-            LOG.debug("RPC manager was set.");
+            LOG.trace("Context chain holder: RPC manager OK.");
             rpcManager = (RpcManager) manager;
         } else if (Objects.isNull(statisticsManager) && manager instanceof StatisticsManager) {
-            LOG.debug("Statistics manager was set.");
+            LOG.trace("Context chain holder: Statistics manager OK.");
             statisticsManager = (StatisticsManager) manager;
         }
     }
@@ -196,11 +196,19 @@ public class ContextChainHolderImpl implements ContextChainHolder {
     }
 
     @Override
-    public void onNotAbleToStartMastership(final DeviceInfo deviceInfo, @Nonnull final String reason) {
+    public void onNotAbleToStartMastership(final DeviceInfo deviceInfo, @Nonnull final String reason, final boolean mandatory) {
         this.withoutRoleChains.remove(deviceInfo);
         LOG.warn("Not able to set MASTER role on device {}, reason: {}", deviceInfo.getLOGValue(), reason);
-        if (contextChainMap.containsKey(deviceInfo)) {
-            destroyContextChain(deviceInfo);
+        if (mandatory && contextChainMap.containsKey(deviceInfo)) {
+            LOG.warn("This mastering is mandatory, destroying context chain and closing connection.");
+            Futures.transform(contextChainMap.get(deviceInfo).stopChain(), new Function<Void, Object>() {
+                        @Nullable
+                        @Override
+                        public Object apply(@Nullable Void aVoid) {
+                            destroyContextChain(deviceInfo);
+                            return null;
+                        }
+                    });
         }
     }
 
@@ -289,22 +297,7 @@ public class ContextChainHolderImpl implements ContextChainHolder {
             this.withoutRoleChains.forEach((deviceInfo, contextChain) -> contextChain.makeDeviceSlave());
             timer.newTimeout(new RoleTimerTask(), this.checkRoleMaster, TimeUnit.MILLISECONDS);
         } else {
-            final Set<DeviceInfo> setOfClosedChains = new ConcurrentSet<>();
-            if (!this.contextChainMap.isEmpty()) {
-                this.contextChainMap.forEach((deviceInfo, contextChain) -> {
-                    if (!contextChain.hasState()) {
-                        LOG.warn("Context chain {} is long time without state. Closing.", deviceInfo);
-                        setOfClosedChains.add(deviceInfo);
-                        contextChain.close();
-                    }
-                });
-                setOfClosedChains.forEach(this.contextChainMap::remove);
-            }
-            if (this.contextChainMap.isEmpty()) {
-                this.stopTimerRole();
-            } else {
-                timer.newTimeout(new RoleTimerTask(), this.checkRoleMaster, TimeUnit.MILLISECONDS);
-            }
+            this.stopTimerRole();
         }
     }
 
@@ -317,7 +310,7 @@ public class ContextChainHolderImpl implements ContextChainHolder {
     public void close() throws Exception {
         this.contextChainMap.forEach((deviceInfo, contextChain) -> {
             if (contextChain.isMastered(ContextChainMastershipState.CHECK)) {
-                contextChain.stopChain(true);
+                contextChain.stopChain();
             }
             contextChain.close();
         });
@@ -328,13 +321,13 @@ public class ContextChainHolderImpl implements ContextChainHolder {
 
     @Override
     public void ownershipChanged(EntityOwnershipChange entityOwnershipChange) {
-        if (!entityOwnershipChange.hasOwner() && !entityOwnershipChange.isOwner() && entityOwnershipChange.wasOwner()) {
+        if (!entityOwnershipChange.hasOwner()) {
             final YangInstanceIdentifier yii = entityOwnershipChange.getEntity().getId();
             final YangInstanceIdentifier.NodeIdentifierWithPredicates niiwp =
                     (YangInstanceIdentifier.NodeIdentifierWithPredicates) yii.getLastPathArgument();
             String entityName =  niiwp.getKeyValues().values().iterator().next().toString();
             if (LOG.isDebugEnabled()) {
-                LOG.debug("Last master for entity : {}", entityName);
+                LOG.debug("Entity {} has no owner", entityName);
             }
 
             if (entityName != null ){
@@ -344,7 +337,7 @@ public class ContextChainHolderImpl implements ContextChainHolder {
                     if (entry.getKey().getNodeId().equals(nodeId)) {
                         inMap = entry.getKey();
                         break;
-                    }                    
+                    }
                 }
                 if (Objects.nonNull(inMap)) {
                     markToBeRemoved.add(inMap);
@@ -355,11 +348,12 @@ public class ContextChainHolderImpl implements ContextChainHolder {
                                 .removeDeviceFromOperationalDS(DeviceStateUtil.createNodeInstanceIdentifier(nodeId))
                                 .checkedGet(5L, TimeUnit.SECONDS);
                     } catch (TimeoutException | TransactionCommitFailedException e) {
-                        LOG.warn("Not able to remove device {} from DS", nodeId);
+                        LOG.info("Not able to remove device {} from DS. Probably removed by another cluster node.",
+                                nodeId);
                     }
                 }
-            }                
-        }        
+            }
+        }
     }
 
     private void sendNotificationNodeAdded(final DeviceInfo deviceInfo) {
index 873a33adbcf36163e73061059c5e00b0eb6d3797..6641176e16976f0983d78230d0b51bd1eb1274b6 100644 (file)
@@ -12,9 +12,9 @@ import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import io.netty.util.internal.ConcurrentSet;
 import java.util.ArrayList;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
@@ -25,6 +25,7 @@ import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
 import org.opendaylight.openflowplugin.api.openflow.lifecycle.ContextChain;
 import org.opendaylight.openflowplugin.api.openflow.lifecycle.ContextChainMastershipState;
 import org.opendaylight.openflowplugin.api.openflow.lifecycle.ContextChainState;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.ContextChainStateListener;
 import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleService;
 import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
 import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsContext;
@@ -46,18 +47,18 @@ public class ContextChainImpl implements ContextChain {
 
     private volatile ContextChainState contextChainState;
 
-    private boolean masterStateOnDevice;
-    private boolean initialGathering;
-    private boolean initialSubmitting;
-    private boolean registryFilling;
+    private AtomicBoolean masterStateOnDevice;
+    private AtomicBoolean initialGathering;
+    private AtomicBoolean initialSubmitting;
+    private AtomicBoolean registryFilling;
 
     ContextChainImpl(final ConnectionContext connectionContext) {
         this.primaryConnection = connectionContext;
         this.contextChainState = ContextChainState.UNDEFINED;
-        this.masterStateOnDevice = false;
-        this.initialGathering = false;
-        this.initialSubmitting = false;
-        this.registryFilling = false;
+        this.masterStateOnDevice = new AtomicBoolean(false);
+        this.initialGathering = new AtomicBoolean(false);
+        this.initialSubmitting = new AtomicBoolean(false);
+        this.registryFilling = new AtomicBoolean(false);
         this.deviceInfo = connectionContext.getDeviceInfo();
     }
 
@@ -74,6 +75,7 @@ public class ContextChainImpl implements ContextChain {
                 }
             }
         }
+
         contexts.add(context);
     }
 
@@ -83,13 +85,13 @@ public class ContextChainImpl implements ContextChain {
     }
 
     @Override
-    public ListenableFuture<Void> stopChain(boolean connectionDropped) {
+    public ListenableFuture<Void> stopChain() {
         //TODO: stopClusterServices change parameter
         final List<ListenableFuture<Void>> futureList = new ArrayList<>();
         futureList.add(statisticsContext.stopClusterServices());
         futureList.add(rpcContext.stopClusterServices());
-        futureList.add(deviceContext.stopClusterServices(connectionDropped));
-
+        futureList.add(deviceContext.stopClusterServices());
+        this.unMasterMe();
         return Futures.transform(Futures.successfulAsList(futureList), new Function<List<Void>, Void>() {
             @Nullable
             @Override
@@ -100,6 +102,13 @@ public class ContextChainImpl implements ContextChain {
         });
     }
 
+    private void unMasterMe() {
+        this.registryFilling.set(false);
+        this.initialSubmitting.set(false);
+        this.initialGathering.set(false);
+        this.masterStateOnDevice.set(false);
+    }
+
     @Override
     public void close() {
         this.auxiliaryConnections.forEach(connectionContext -> connectionContext.closeConnection(false));
@@ -114,14 +123,16 @@ public class ContextChainImpl implements ContextChain {
 
     @Override
     public void makeContextChainStateSlave() {
-        this.contextChainState = ContextChainState.WORKING_SLAVE;
+        this.unMasterMe();
+        changeState(ContextChainState.WORKING_SLAVE);
     }
 
     @Override
     public ListenableFuture<Void> connectionDropped() {
         if (this.contextChainState == ContextChainState.WORKING_MASTER) {
-            return this.stopChain(true);
+            return this.stopChain();
         }
+        this.unMasterMe();
         return Futures.immediateFuture(null);
     }
 
@@ -134,6 +145,7 @@ public class ContextChainImpl implements ContextChain {
 
     @Override
     public void makeDeviceSlave() {
+        this.unMasterMe();
         this.lifecycleService.makeDeviceSlave(this.deviceContext);
     }
 
@@ -142,31 +154,33 @@ public class ContextChainImpl implements ContextChain {
         switch (mastershipState) {
             case INITIAL_SUBMIT:
                 LOG.debug("Device {}, initial submit OK.", deviceInfo.getLOGValue());
-                this.initialSubmitting = true;
+                this.initialSubmitting.set(true);
                 break;
             case MASTER_ON_DEVICE:
                 LOG.debug("Device {}, master state OK.", deviceInfo.getLOGValue());
-                this.masterStateOnDevice = true;
+                this.masterStateOnDevice.set(true);
                 break;
             case INITIAL_GATHERING:
                 LOG.debug("Device {}, initial gathering OK.", deviceInfo.getLOGValue());
-                this.initialGathering = true;
+                this.initialGathering.set(true);
                 break;
+            //Flow registry fill is not mandatory to work as a master
             case INITIAL_FLOW_REGISTRY_FILL:
                 LOG.debug("Device {}, initial registry filling OK.", deviceInfo.getLOGValue());
-                this.registryFilling = true;
+                this.registryFilling.set(true);
             case CHECK:
             default:
         }
         final boolean result =
-                this.initialGathering &&
-                this.masterStateOnDevice &&
-                this.initialSubmitting &&
-                this.registryFilling;
+                this.initialGathering.get() &&
+                this.masterStateOnDevice.get() &&
+                this.initialSubmitting.get();
 
         if (result && mastershipState != ContextChainMastershipState.CHECK) {
-            LOG.info("Device {} is able to work as master.", deviceInfo.getLOGValue());
-            contextChainState = ContextChainState.WORKING_MASTER;
+            LOG.info("Device {} is able to work as master{}",
+                    deviceInfo.getLOGValue(),
+                    this.registryFilling.get() ? " WITHOUT flow registry !!!" : ".");
+            changeState(ContextChainState.WORKING_MASTER);
         }
         return result;
     }
@@ -198,4 +212,16 @@ public class ContextChainImpl implements ContextChain {
         this.auxiliaryConnections.remove(connectionContext);
         return true;
     }
+
+    private void changeState(final ContextChainState contextChainState) {
+        boolean propagate = this.contextChainState == ContextChainState.UNDEFINED;
+        this.contextChainState = contextChainState;
+
+        if (propagate) {
+            contexts.stream()
+                    .filter(ContextChainStateListener.class::isInstance)
+                    .map(ContextChainStateListener.class::cast)
+                    .forEach(listener -> listener.onStateAcquired(contextChainState));
+        }
+    }
 }
index 712addb98be23840691ea01a2425fb3ef0f1a447..9783cb251f83d778f29cc3b0e8a3f9e7b59dc143 100644 (file)
@@ -77,7 +77,7 @@ public class LifecycleServiceImpl implements LifecycleService {
 
         LOG.info("Starting clustering MASTER services for node {}", deviceInfo.getLOGValue());
         if (!clusterInitializationPhaseHandler.onContextInstantiateService(mastershipChangeListener)) {
-            mastershipChangeListener.onNotAbleToStartMastership(deviceInfo, "Cannot initialize device.");
+            mastershipChangeListener.onNotAbleToStartMastershipMandatory(deviceInfo, "Cannot initialize device.");
         }
     }
 
index 7b79a0d3999b9cb5105866d2a2e5e24b556a3587..fc82a5c42787ea4a8c7a93c5f21fc954c3889d1d 100644 (file)
@@ -10,8 +10,10 @@ package org.opendaylight.openflowplugin.impl.protocol.serialization.match;
 
 import io.netty.buffer.ByteBuf;
 import java.util.LinkedHashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Optional;
 import org.opendaylight.openflowjava.protocol.api.extensibility.HeaderSerializer;
 import org.opendaylight.openflowjava.protocol.api.extensibility.OFSerializer;
 import org.opendaylight.openflowjava.protocol.api.extensibility.SerializerRegistry;
@@ -28,6 +30,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev150225.oxm.container.match.entry.value.ExperimenterIdCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.ExperimenterClass;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.ExtensionKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.general.extension.list.grouping.ExtensionList;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -82,30 +86,43 @@ public class MatchSerializer implements OFSerializer<Match>, HeaderSerializer<Ma
         });
 
         // Serialize match extensions
-        ExtensionResolvers.getMatchExtensionResolver().getExtension(match).map(extensions -> {
-            extensions.getExtensionList().forEach(extension -> {
-                // TODO: Remove also extension converters
-                final MatchEntry entry = OFSessionUtil
-                    .getExtensionConvertorProvider()
-                    .<MatchEntry>getConverter(new ConverterExtensionKey<>(
-                        extension.getExtensionKey(),
-                        OFConstants.OFP_VERSION_1_3))
-                    .convert(extension.getExtension());
-
-                final MatchEntrySerializerKey<?, ?> key = new MatchEntrySerializerKey<>(
-                    EncodeConstants.OF13_VERSION_ID, entry.getOxmClass(), entry.getOxmMatchField());
-
-                // If entry is experimenter, set experimenter ID to key
-                if (entry.getOxmClass().equals(ExperimenterClass.class)) {
-                    key.setExperimenterId(ExperimenterIdCase.class.cast(entry.getMatchEntryValue())
-                        .getExperimenter().getExperimenter().getValue());
-                }
-
-                final OFSerializer<MatchEntry> entrySerializer = registry.getSerializer(key);
-                entrySerializer.serialize(entry, outBuffer);
-            });
-
-            return extensions;
+        ExtensionResolvers
+                .getMatchExtensionResolver()
+                .getExtension(match)
+                .flatMap(extensions -> Optional.ofNullable(extensions.getExtensionList()))
+                .ifPresent(extensionList -> serializeExtensionList(extensionList, outBuffer));
+    }
+
+    private void serializeExtensionList(final List<ExtensionList> extensionList, final ByteBuf outBuffer) {
+        // TODO: Remove also extension converters
+        extensionList.forEach(extension -> {
+            final ConverterExtensionKey<? extends ExtensionKey> converterExtensionKey =
+                    new ConverterExtensionKey<>(extension.getExtensionKey(), OFConstants.OFP_VERSION_1_3);
+
+            Optional.ofNullable(OFSessionUtil.getExtensionConvertorProvider())
+                    .flatMap(provider -> Optional.ofNullable(provider.<MatchEntry>getConverter(converterExtensionKey)))
+                    .map(matchEntryConvertorToOFJava -> {
+                        final MatchEntry entry = matchEntryConvertorToOFJava.convert(extension.getExtension());
+
+                        final MatchEntrySerializerKey<?, ?> key = new MatchEntrySerializerKey<>(
+                                EncodeConstants.OF13_VERSION_ID, entry.getOxmClass(), entry.getOxmMatchField());
+
+                        // If entry is experimenter, set experimenter ID to key
+                        if (entry.getOxmClass().equals(ExperimenterClass.class)) {
+                            key.setExperimenterId(ExperimenterIdCase.class.cast(entry.getMatchEntryValue())
+                                    .getExperimenter().getExperimenter().getValue());
+                        }
+
+                        final OFSerializer<MatchEntry> entrySerializer = registry.getSerializer(key);
+                        entrySerializer.serialize(entry, outBuffer);
+                        return entry;
+                    })
+                    .orElseGet(() -> {
+                        LOG.warn("Serializer for match entry {} for version {} not found.",
+                                extension.getExtension().getImplementedInterface(),
+                                OFConstants.OFP_VERSION_1_3);
+                        return null;
+                    });
         });
     }
 
index ca891edf078d43242e4080c003904987af5b7358..3793d72b03c371883458b9dea347081776bcac98 100644 (file)
@@ -281,29 +281,6 @@ class StatisticsContextImpl<T extends OfHeader> implements StatisticsContext {
         }
 
         if (!iterator.hasNext()) {
-            if (initial) {
-                Futures.addCallback(StatisticsGatheringUtils.gatherStatistics(
-                        statisticsGatheringService,
-                        getDeviceInfo(),
-                        MultipartType.OFPMPPORTDESC,
-                        deviceContext,
-                        deviceContext,
-                        false,
-                        convertorExecutor,
-                        statisticsWriterProvider), new FutureCallback<Boolean>() {
-                    @Override
-                    public void onSuccess(final Boolean result) {
-                        statChainFuture(iterator, resultFuture, false);
-                    }
-                    @Override
-                    public void onFailure(@Nonnull final Throwable t) {
-                        resultFuture.setException(t);
-                    }
-                });
-
-                return;
-            }
-
             resultFuture.set(Boolean.TRUE);
             LOG.debug("Stats collection successfully finished for node {}", getDeviceInfo().getLOGValue());
             return;
@@ -543,7 +520,7 @@ class StatisticsContextImpl<T extends OfHeader> implements StatisticsContext {
                         myManager.startScheduling(deviceInfo);
                     }
                 } else {
-                    mastershipChangeListener.onNotAbleToStartMastership(
+                    mastershipChangeListener.onNotAbleToStartMastershipMandatory(
                             deviceInfo,
                             "Initial transaction cannot be submitted."
                     );
@@ -552,7 +529,7 @@ class StatisticsContextImpl<T extends OfHeader> implements StatisticsContext {
 
             @Override
             public void onFailure(@Nonnull Throwable throwable) {
-                mastershipChangeListener.onNotAbleToStartMastership(
+                mastershipChangeListener.onNotAbleToStartMastershipMandatory(
                         deviceInfo,
                         "Initial gathering statistics unsuccessful."
                 );
index 61ef3344851a38b1fc5a5658003a26f699989064..7ac57810b14cc6e083d42da50bf2fd515d18f9c5 100644 (file)
@@ -14,13 +14,18 @@ import org.opendaylight.openflowplugin.api.openflow.device.MessageTranslator;
 import org.opendaylight.openflowplugin.openflow.md.util.PortTranslatorUtil;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortReason;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortNumberUni;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortGrouping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * @author tkubas
  */
 public class PortUpdateTranslator implements MessageTranslator<PortGrouping, FlowCapableNodeConnector> {
+    private static final Logger logger = LoggerFactory.getLogger(PortUpdateTranslator.class);
 
     @Override
     public FlowCapableNodeConnector translate(final PortGrouping input,
@@ -43,6 +48,13 @@ public class PortUpdateTranslator implements MessageTranslator<PortGrouping, Flo
             builder.setSupported(PortTranslatorUtil.translatePortFeatures(input.getSupportedFeatures()));
             builder.setQueue(Collections.<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.Queue>emptyList());
         }
+        if (input instanceof PortStatusMessage) {
+            if (((PortStatusMessage) input).getReason() != null) {
+                builder.setReason(PortReason.forValue(((PortStatusMessage) input).getReason().getIntValue()));
+            }else {
+                logger.debug("PortStatus Message has reason as null");
+            }
+        }
         builder.setCurrentSpeed(input.getCurrSpeed());
         builder.setHardwareAddress(input.getHwAddr());
         builder.setMaximumSpeed(input.getMaxSpeed());
index 4eab2e2f04c8082e9183d952cf567cdfd5ae7eef..d2ad7ff60767161f1b90f520baae1fe9b84480a1 100644 (file)
@@ -63,7 +63,6 @@ public class HandshakeListenerImplTest {
         connectionContextSpy = Mockito.spy(new ConnectionContextImpl(connectionAdapter));
         Mockito.when(connectionContextSpy.getConnectionAdapter()).thenReturn(connectionAdapter);
         Mockito.when(features.getDatapathId()).thenReturn(BigInteger.TEN);
-        Mockito.doNothing().when(connectionContextSpy).handshakeSuccessful();
         handshakeListener = new HandshakeListenerImpl(connectionContextSpy, deviceConnectedHandler);
         handshakeListener.setHandshakeContext(handshakeContext);
     }
index f3ffaf8ea3b866fe5efce189d4ef33bf4276bf7f..13019a48dc56b242b930748a5a1e3432daaa61e2 100644 (file)
@@ -45,7 +45,7 @@ public class ContextChainImplTest {
     public void setUp() throws Exception {
 
         Mockito.when(deviceContext.getDeviceInfo()).thenReturn(deviceInfo);
-        Mockito.when(deviceContext.stopClusterServices(Mockito.anyBoolean()))
+        Mockito.when(deviceContext.stopClusterServices())
                 .thenReturn(Futures.immediateFuture(null));
         Mockito.when(rpcContext.stopClusterServices()).thenReturn(Futures.immediateFuture(null));
         Mockito.when(statisticsContext.stopClusterServices()).thenReturn(Futures.immediateFuture(null));
@@ -62,8 +62,8 @@ public class ContextChainImplTest {
 
     @Test
     public void stopChain() throws Exception {
-        contextChain.stopChain(true);
-        Mockito.verify(deviceContext).stopClusterServices(Mockito.anyBoolean());
+        contextChain.stopChain();
+        Mockito.verify(deviceContext).stopClusterServices();
         Mockito.verify(rpcContext).stopClusterServices();
         Mockito.verify(statisticsContext).stopClusterServices();
     }
@@ -84,7 +84,7 @@ public class ContextChainImplTest {
         contextChain.isMastered(ContextChainMastershipState.MASTER_ON_DEVICE);
         contextChain.isMastered(ContextChainMastershipState.INITIAL_FLOW_REGISTRY_FILL);
         contextChain.connectionDropped();
-        Mockito.verify(deviceContext).stopClusterServices(Mockito.anyBoolean());
+        Mockito.verify(deviceContext).stopClusterServices();
         Mockito.verify(rpcContext).stopClusterServices();
         Mockito.verify(statisticsContext).stopClusterServices();
     }
index fb7f41521deeda3089c593cb3c6133aa338df00d..9a5413ee44e7b45cc23544dd1f6eaaa2bdf046b2 100644 (file)
@@ -88,7 +88,7 @@ public class LifecycleServiceImplTest {
         Mockito.when(deviceContext.onContextInstantiateService(Mockito.any()))
                 .thenReturn(false);
         lifecycleService.instantiateServiceInstance();
-        Mockito.verify(mastershipChangeListener).onNotAbleToStartMastership(Mockito.any(DeviceInfo.class), Mockito.anyString());
+        Mockito.verify(mastershipChangeListener).onNotAbleToStartMastershipMandatory(Mockito.any(DeviceInfo.class), Mockito.anyString());
     }
 
     @Test
index 2018e2c9945f3386a9fc0cb911c6f510a12e7a59..8133692c96c9f4d9edaa390ebc6b445a8b00cad2 100644 (file)
@@ -26,6 +26,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev13
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortConfigV10;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortFeatures;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortFeaturesV10;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortReason;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortState;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortStateV10;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessageBuilder;
@@ -121,6 +122,7 @@ public class PortUpdateTranslatorTest {
 
         return new PortStatusMessageBuilder()
                 .setPortNo(portNoValue)
+                .setReason(PortReason.OFPPRADD)
                 .setAdvertisedFeatures(portFeatures13)
                 .setAdvertisedFeaturesV10(portFeatures10)
                 .setConfig(portConfig13)
index 1b824f80c3361f6966e9c285dfa5fd69abb25094..15188ded72a332113907dab5de8eb2d5ce1b14a4 100644 (file)
             <groupId>org.ops4j.pax.exam</groupId>
             <artifactId>pax-exam</artifactId>
         </dependency>
-        <dependency>
-            <groupId>org.eclipse.tycho</groupId>
-            <artifactId>org.eclipse.osgi</artifactId>
-            <scope>test</scope>
-        </dependency>
         <dependency>
           <groupId>equinoxSDK381</groupId>
           <artifactId>org.eclipse.equinox.console</artifactId>
index 1a6a42755d1cafa9af25671150d14e12ece02318..8cdafd6adb2a8b32021576a8530ad7e8ae3625e6 100644 (file)
@@ -11,6 +11,7 @@ import java.math.BigInteger;
 import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorUpdated;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorUpdatedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortReason;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.flow.capable.port.State;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.flow.capable.port.StateBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRemoved;
@@ -24,8 +25,12 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev13
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortState;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortStateV10;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortGrouping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public abstract class PortTranslatorUtil {
+    private static final Logger logger = LoggerFactory.getLogger(PortTranslatorUtil.class);
     public static org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortFeatures translatePortFeatures(final PortFeatures apf) {
         org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortFeatures napf = null;
         if (apf != null) {
@@ -138,6 +143,13 @@ public abstract class PortTranslatorUtil {
             fcncub.setState(PortTranslatorUtil.translatePortState(port.getStateV10()));
             fcncub.setSupported(PortTranslatorUtil.translatePortFeatures(port.getSupportedFeaturesV10()));
         }
+        if (port instanceof PortStatusMessage) {
+            if (((PortStatusMessage) port).getReason() != null) {
+                fcncub.setReason(PortReason.forValue(((PortStatusMessage) port).getReason().getIntValue()));
+            }else {
+                logger.debug("PortStatus Message has reason as null");
+            }
+        }
         fcncub.setCurrentSpeed(port.getCurrSpeed());
         fcncub.setHardwareAddress(port.getHwAddr());
         fcncub.setMaximumSpeed(port.getMaxSpeed());
index 6a3456b0669b9b96002a07cf7e727ccf97001346..9d39d1b9fe1b65918af7a624066b2203fb1a35ef 100644 (file)
@@ -34,8 +34,8 @@
         <openflowjava.version>0.10.0-SNAPSHOT</openflowjava.version>
         <openflowplugin.version>0.5.0-SNAPSHOT</openflowplugin.version>
         <sal.api.version>0.13.0-SNAPSHOT</sal.api.version>
-        <jmxGeneratorPath>target/generated-sources/config</jmxGeneratorPath>
-        <salGeneratorPath>target/generated-sources/sal</salGeneratorPath>
+        <jmxGeneratorPath>${project.build.directory}/generated-sources/config</jmxGeneratorPath>
+        <salGeneratorPath>${project.build.directory}/generated-sources/sal</salGeneratorPath>
         <exi.nagasena.version>0000.0002.0053.0</exi.nagasena.version>
         <controller.distribution.version>0.6.0-SNAPSHOT</controller.distribution.version>