Merge "Declare a property for commons-lang version in poms and use it."
[controller.git] / opendaylight / protocol_plugins / openflow / src / main / java / org / opendaylight / controller / protocol_plugin / openflow / internal / DiscoveryService.java
index b3cfde9c146983b4ac44f115178d5af16da606a6..869d36d9cbf815142b430e093a72fb22aedfd439 100644 (file)
@@ -33,16 +33,11 @@ import org.opendaylight.controller.protocol_plugin.openflow.IInventoryProvider;
 import org.opendaylight.controller.protocol_plugin.openflow.IInventoryShimExternalListener;
 import org.opendaylight.controller.protocol_plugin.openflow.core.IController;
 import org.opendaylight.controller.protocol_plugin.openflow.core.ISwitch;
-import org.openflow.protocol.OFPhysicalPort;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.FrameworkUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
+import org.opendaylight.controller.sal.connection.IPluginOutConnectionService;
 import org.opendaylight.controller.sal.core.Config;
 import org.opendaylight.controller.sal.core.ConstructionException;
-import org.opendaylight.controller.sal.core.Edge;
 import org.opendaylight.controller.sal.core.ContainerFlow;
+import org.opendaylight.controller.sal.core.Edge;
 import org.opendaylight.controller.sal.core.IContainerListener;
 import org.opendaylight.controller.sal.core.Node;
 import org.opendaylight.controller.sal.core.NodeConnector;
@@ -60,6 +55,11 @@ import org.opendaylight.controller.sal.utils.HexEncode;
 import org.opendaylight.controller.sal.utils.NetUtils;
 import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
 import org.opendaylight.controller.sal.utils.NodeCreator;
+import org.openflow.protocol.OFPhysicalPort;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * The class describes neighbor discovery service for an OpenFlow network.
@@ -126,9 +126,11 @@ public class DiscoveryService implements IInventoryShimExternalListener, IDataPa
     private volatile Boolean shuttingDown = false;
 
     private LLDPTLV chassisIdTlv, portIdTlv, ttlTlv, customTlv;
+    private IPluginOutConnectionService connectionOutService;
 
     class DiscoveryTransmit implements Runnable {
         private final BlockingQueue<NodeConnector> transmitQ;
+        private int count = 0;
 
         DiscoveryTransmit(BlockingQueue<NodeConnector> transmitQ) {
             this.transmitQ = transmitQ;
@@ -142,6 +144,9 @@ public class DiscoveryService implements IInventoryShimExternalListener, IDataPa
                     RawPacket outPkt = createDiscoveryPacket(nodeConnector);
                     sendDiscoveryPacket(nodeConnector, outPkt);
                     nodeConnector = null;
+                    if ((++count & 0x7f) == 0) {
+                        Thread.sleep(10);
+                    }
                 } catch (InterruptedException e1) {
                     logger.warn("DiscoveryTransmit interupted", e1.getMessage());
                     if (shuttingDown) {
@@ -256,6 +261,11 @@ public class DiscoveryService implements IInventoryShimExternalListener, IDataPa
             return;
         }
 
+        if (!connectionOutService.isLocal(nodeConnector.getNode())) {
+            logger.debug("Discoery packets will not be sent to {} in a non-master controller", nodeConnector.toString());
+            return;
+        }
+
         if (outPkt == null) {
             logger.debug("Can not send discovery packet out since outPkt is null");
             return;
@@ -301,12 +311,18 @@ public class DiscoveryService implements IInventoryShimExternalListener, IDataPa
             return PacketResult.IGNORED;
         }
 
-        if (((Short) inPkt.getIncomingNodeConnector().getID()).equals(NodeConnector.SPECIALNODECONNECTORID)) {
+        NodeConnector nodeConnector = inPkt.getIncomingNodeConnector();
+        if (((Short) nodeConnector.getID()).equals(NodeConnector.SPECIALNODECONNECTORID)) {
             logger.trace("Ignoring ethernet packet received on special port: "
                     + inPkt.getIncomingNodeConnector().toString());
             return PacketResult.IGNORED;
         }
 
+        if (!connectionOutService.isLocal(nodeConnector.getNode())) {
+            logger.debug("Discoery packets will not be processed from {} in a non-master controller", nodeConnector.toString());
+            return PacketResult.IGNORED;
+        }
+
         Ethernet ethPkt = new Ethernet();
         try {
             ethPkt.deserialize(data, 0, data.length * NetUtils.NumBitsInAByte);
@@ -544,10 +560,11 @@ public class DiscoveryService implements IInventoryShimExternalListener, IDataPa
     private void addDiscovery(Node node) {
         Map<Long, ISwitch> switches = controller.getSwitches();
         ISwitch sw = switches.get(node.getID());
-        List<OFPhysicalPort> ports = sw.getEnabledPorts();
-        if (ports == null) {
+        if (sw == null) {
+            //switch could be removed by now, stop propagation
             return;
         }
+        List<OFPhysicalPort> ports = sw.getEnabledPorts();
         for (OFPhysicalPort port : ports) {
             NodeConnector nodeConnector = NodeConnectorCreator.createOFNodeConnector(port.getPortNumber(), node);
             if (!readyListHi.contains(nodeConnector)) {
@@ -564,6 +581,14 @@ public class DiscoveryService implements IInventoryShimExternalListener, IDataPa
         readyListHi.add(nodeConnector);
     }
 
+    private void removeNodeConnector(NodeConnector nodeConnector) {
+        readyListLo.remove(nodeConnector);
+        readyListHi.remove(nodeConnector);
+        stagingList.remove(nodeConnector);
+        holdTime.remove(nodeConnector);
+        elapsedTime.remove(nodeConnector);
+    }
+
     private Set<NodeConnector> getRemoveSet(Collection<NodeConnector> c, Node node) {
         Set<NodeConnector> removeSet = new HashSet<NodeConnector>();
         if (c == null) {
@@ -580,6 +605,29 @@ public class DiscoveryService implements IInventoryShimExternalListener, IDataPa
     private void removeDiscovery(Node node) {
         Set<NodeConnector> removeSet;
 
+        removeSet = getRemoveSet(edgeMap.keySet(), node);
+        NodeConnector peerConnector;
+        Edge edge1, edge2;
+        for (NodeConnector nodeConnector : removeSet) {
+            // get the peer for fast removal of the edge in reverse direction
+            peerConnector = null;
+            edge1 = edgeMap.get(nodeConnector);
+            if (edge1 != null) {
+                edge2 = edgeMap.get(edge1.getTailNodeConnector());
+                if ((edge2 != null) && node.equals(edge2.getTailNodeConnector().getNode())) {
+                    peerConnector = edge2.getHeadNodeConnector();
+                }
+            }
+
+            removeEdge(nodeConnector, false);
+            removeEdge(peerConnector, isEnabled(peerConnector));
+        }
+
+        removeSet = getRemoveSet(prodMap.keySet(), node);
+        for (NodeConnector nodeConnector : removeSet) {
+            removeProdEdge(nodeConnector);
+        }
+
         removeSet = getRemoveSet(readyListHi, node);
         readyListHi.removeAll(removeSet);
 
@@ -594,22 +642,14 @@ public class DiscoveryService implements IInventoryShimExternalListener, IDataPa
             holdTime.remove(nodeConnector);
         }
 
-        removeSet = getRemoveSet(edgeMap.keySet(), node);
-        for (NodeConnector nodeConnector : removeSet) {
-            removeEdge(nodeConnector, false);
-        }
-
-        removeSet = getRemoveSet(prodMap.keySet(), node);
+        removeSet = getRemoveSet(elapsedTime.keySet(), node);
         for (NodeConnector nodeConnector : removeSet) {
-            removeProdEdge(nodeConnector);
+            elapsedTime.remove(nodeConnector);
         }
     }
 
     private void removeDiscovery(NodeConnector nodeConnector) {
-        readyListHi.remove(nodeConnector);
-        readyListLo.remove(nodeConnector);
-        stagingList.remove(nodeConnector);
-        holdTime.remove(nodeConnector);
+        removeNodeConnector(nodeConnector);
         removeEdge(nodeConnector, false);
         removeProdEdge(nodeConnector);
     }
@@ -648,8 +688,10 @@ public class DiscoveryService implements IInventoryShimExternalListener, IDataPa
 
             for (NodeConnector nodeConnector : retrySet) {
                 // Allow one more retry
-                readyListLo.add(nodeConnector);
                 elapsedTime.remove(nodeConnector);
+                if (connectionOutService.isLocal(nodeConnector.getNode())) {
+                    transmitQ.add(nodeConnector);
+                }
             }
         }
     }
@@ -683,10 +725,12 @@ public class DiscoveryService implements IInventoryShimExternalListener, IDataPa
     private void doDiscovery() {
         if (++discoveryTimerTickCount <= discoveryBatchPauseTicks) {
             for (NodeConnector nodeConnector : getWorkingSet()) {
-                transmitQ.add(nodeConnector);
-                // Move to staging area after it's served
-                if (!stagingList.contains(nodeConnector)) {
-                    stagingList.add(nodeConnector);
+                if (connectionOutService.isLocal(nodeConnector.getNode())) {
+                    transmitQ.add(nodeConnector);
+                    // Move to staging area after it's served
+                    if (!stagingList.contains(nodeConnector)) {
+                        stagingList.add(nodeConnector);
+                    }
                 }
             }
         } else if (discoveryTimerTickCount >= discoveryBatchRestartTicks) {
@@ -776,6 +820,11 @@ public class DiscoveryService implements IInventoryShimExternalListener, IDataPa
         }
         elapsedTime.remove(src);
 
+        // fast discovery of the edge in reverse direction
+        if (!edgeMap.containsKey(dst) && !readyListHi.contains(dst) && !elapsedTime.keySet().contains(dst)) {
+            moveToReadyListHi(dst);
+        }
+
         // notify
         updateEdge(edge, UpdateType.ADDED, props);
         logger.trace("Add edge {}", edge);
@@ -842,18 +891,15 @@ public class DiscoveryService implements IInventoryShimExternalListener, IDataPa
      * Remove OpenFlow edge
      */
     private void removeEdge(NodeConnector nodeConnector, boolean stillEnabled) {
-        holdTime.remove(nodeConnector);
-        readyListLo.remove(nodeConnector);
-        readyListHi.remove(nodeConnector);
+        if (nodeConnector == null) {
+            return;
+        }
+
+        removeNodeConnector(nodeConnector);
 
         if (stillEnabled) {
             // keep discovering
-            if (!stagingList.contains(nodeConnector)) {
-                stagingList.add(nodeConnector);
-            }
-        } else {
-            // stop it
-            stagingList.remove(nodeConnector);
+            stagingList.add(nodeConnector);
         }
 
         Edge edge = null;
@@ -1211,7 +1257,15 @@ public class DiscoveryService implements IInventoryShimExternalListener, IDataPa
 
         if (val != null) {
             try {
-                int ticks = Integer.parseInt(val);
+                int ticks;
+                Set<NodeConnector> monitorSet = holdTime.keySet();
+                if (monitorSet != null) {
+                    for (NodeConnector nodeConnector : monitorSet) {
+                        holdTime.put(nodeConnector, 0);
+                    }
+                }
+
+                ticks = Integer.parseInt(val);
                 DiscoveryPeriod.INTERVAL.setTick(ticks);
                 discoveryBatchRestartTicks = getDiscoveryInterval();
                 discoveryBatchPauseTicks = getDiscoveryPauseInterval();
@@ -1393,6 +1447,16 @@ public class DiscoveryService implements IInventoryShimExternalListener, IDataPa
         }
     }
 
+    void setIPluginOutConnectionService(IPluginOutConnectionService s) {
+        connectionOutService = s;
+    }
+
+    void unsetIPluginOutConnectionService(IPluginOutConnectionService s) {
+        if (connectionOutService == s) {
+            connectionOutService = null;
+        }
+    }
+
     private void initDiscoveryPacket() {
         // Create LLDP ChassisID TLV
         chassisIdTlv = new LLDPTLV();
@@ -1619,7 +1683,7 @@ public class DiscoveryService implements IInventoryShimExternalListener, IDataPa
      */
     private int getDiscoveryBatchMaxPorts() {
         String val = System.getProperty("of.discoveryBatchMaxPorts");
-        int ports = 1024;
+        int ports = 512;
 
         if (val != null) {
             try {