Bug 3244 - SFC Improvements for distributed classifier, robustness
[groupbasedpolicy.git] / renderers / ofoverlay / src / main / java / org / opendaylight / groupbasedpolicy / renderer / ofoverlay / node / SwitchManager.java
index 0f11cab8459c98327c8475d0846e074d48f27d47..3ec0a16aa0eedf3615730a1adfbee6e7a573ee19 100644 (file)
@@ -22,18 +22,25 @@ import java.util.concurrent.CopyOnWriteArrayList;
 
 import javax.annotation.Nullable;
 
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.node.SwitchListener;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayConfig.EncapsulationFormat;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayNodeConfig;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.nodes.node.ExternalInterfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.nodes.node.Tunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.nodes.node.TunnelBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
 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.params.xml.ns.yang.overlay.rev150105.TunnelTypeBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.TunnelTypeVxlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.TunnelTypeVxlanGpe;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -41,8 +48,10 @@ import org.slf4j.LoggerFactory;
 import com.google.common.base.Function;
 import com.google.common.base.Objects;
 import com.google.common.base.Predicate;
+import com.google.common.collect.Collections2;
 import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Maps;
 
 /**
@@ -53,7 +62,7 @@ public class SwitchManager implements AutoCloseable {
 
     private static final Logger LOG = LoggerFactory.getLogger(SwitchManager.class);
 
-    protected Map<NodeId, SwitchState> switches = new HashMap<>();
+    protected static Map<NodeId, SwitchState> switches = new HashMap<>();
     protected List<SwitchListener> listeners = new CopyOnWriteArrayList<>();
 
     private final FlowCapableNodeListener nodeListener;
@@ -76,6 +85,28 @@ public class SwitchManager implements AutoCloseable {
         LOG.debug("Initialized OFOverlay switch manager");
     }
 
+    // When first endpoint is attached to switch, it can be ready
+    public static void activatingSwitch(NodeId nodeId) {
+        SwitchState state = switches.get(nodeId);
+        if (state == null) {
+            state = new SwitchState(nodeId);
+            switches.put(nodeId, state);
+        }
+        state.setHasEndpoints(true);
+        state.updateStatus();
+    }
+
+    // When last endpoint is removed from switch, it is no longer ready
+    public static void deactivatingSwitch(NodeId nodeId) {
+        SwitchState state = switches.get(nodeId);
+        if (state == null) {
+            LOG.error("No SwitchState for {} in deactivatingSwitch. This should not happen.",nodeId);
+            return;
+        }
+        state.setHasEndpoints(false);;
+        state.updateStatus();
+    }
+
     /**
      * Get the collection of switches that are in the "ready" state. Note
      * that the collection is immutable.
@@ -107,21 +138,47 @@ public class SwitchManager implements AutoCloseable {
         SwitchState state = switches.get(nodeId);
         if (state == null)
             return Collections.emptySet();
-        return state.externalPorts;
+        return ImmutableSet.copyOf(state.externalPorts);
     }
 
-    public synchronized NodeConnectorId getTunnelPort(NodeId nodeId) {
+    public synchronized Collection<NodeConnectorId> getTunnelPorts(NodeId nodeId) {
+        Collection<NodeConnectorId> ncIds = new HashSet<>();
         SwitchState state = switches.get(nodeId);
-        if (state == null)
+        if (state == null ) {
+            return Collections.emptySet();
+        }
+        ncIds = Collections2.transform(state.tunnelBuilderByType.values(),new Function<TunnelBuilder, NodeConnectorId>() {
+
+            @Override
+            public NodeConnectorId apply(TunnelBuilder input) {
+                return input.getNodeConnectorId();
+            }
+        });
+
+        return ncIds;
+    }
+    public synchronized NodeConnectorId getTunnelPort(NodeId nodeId, Class<? extends TunnelTypeBase> tunnelType) {
+        SwitchState state = switches.get(nodeId);
+        if (state == null) {
             return null;
-        return state.tunnelPort;
+        }
+        TunnelBuilder tunnel = state.tunnelBuilderByType.get(tunnelType);
+        if (tunnel == null) {
+            return null;
+        }
+        return tunnel.getNodeConnectorId();
     }
 
-    public synchronized IpAddress getTunnelIP(NodeId nodeId) {
+    public synchronized IpAddress getTunnelIP(NodeId nodeId, Class<? extends TunnelTypeBase> tunnelType) {
         SwitchState state = switches.get(nodeId);
-        if (state == null || state.nodeConfig == null)
+        if (state == null) {
             return null;
-        return state.nodeConfig.getTunnelIp();
+        }
+        TunnelBuilder tunnel = state.tunnelBuilderByType.get(tunnelType);
+        if (tunnel == null) {
+            return null;
+        }
+        return tunnel.getIp();
     }
 
     /**
@@ -227,8 +284,19 @@ public class SwitchManager implements AutoCloseable {
         private FlowCapableNode fcNode;
         private OfOverlayNodeConfig nodeConfig;
         private Map<InstanceIdentifier<NodeConnector>, FlowCapableNodeConnector> fcncByNcIid = Maps.newHashMap();
+        private boolean hasEndpoints=false;
 
-        NodeConnectorId tunnelPort;
+
+        public boolean isHasEndpoints() {
+            return hasEndpoints;
+        }
+
+
+        public void setHasEndpoints(boolean hasEndpoints) {
+            this.hasEndpoints = hasEndpoints;
+        }
+
+        Map<Class<? extends TunnelTypeBase>, TunnelBuilder> tunnelBuilderByType = new HashMap<>();
         Set<NodeConnectorId> externalPorts = new HashSet<>();
 
         SwitchStatus status;
@@ -244,14 +312,37 @@ public class SwitchManager implements AutoCloseable {
         public SwitchState(NodeId node, NodeConnectorId tunnelPort, Set<NodeConnectorId> externalPorts,
                 OfOverlayNodeConfig nodeConfig) {
             this.nodeId = node;
-            this.tunnelPort = tunnelPort;
-            this.externalPorts = externalPorts;
             this.nodeConfig = nodeConfig;
+            update();
+            this.externalPorts = externalPorts;
         }
 
         private void update() {
-            HashSet<NodeConnectorId> externalPorts = new HashSet<>();
-            NodeConnectorId tunnelPort = null;
+            tunnelBuilderByType = new HashMap<>();
+            externalPorts = new HashSet<>();
+            if (nodeConfig != null && nodeConfig.getExternalInterfaces() != null) {
+                for (ExternalInterfaces nc : nodeConfig.getExternalInterfaces()) {
+                    externalPorts.add(nc.getNodeConnectorId());
+                }
+            }
+            if (nodeConfig != null && nodeConfig.getTunnel() != null) {
+                for (Tunnel tunnel : nodeConfig.getTunnel()) {
+                    TunnelBuilder tunnelBuilder = tunnelBuilderByType.get(tunnel.getTunnelType());
+                    if (tunnelBuilder == null) {
+                        tunnelBuilder = new TunnelBuilder();
+                        tunnelBuilderByType.put(tunnel.getTunnelType(), tunnelBuilder);
+                    }
+                    if (tunnel.getIp() != null) {
+                        tunnelBuilder.setIp(tunnel.getIp());
+                    }
+                    if (tunnel.getNodeConnectorId() != null) {
+                        tunnelBuilder.setNodeConnectorId(tunnel.getNodeConnectorId());
+                    }
+                    if (tunnel.getPort() != null) {
+                        tunnelBuilder.setPort(tunnel.getPort());
+                    }
+                }
+            }
             for (Entry<InstanceIdentifier<NodeConnector>, FlowCapableNodeConnector> fcncByNcIidEntry : fcncByNcIid.entrySet()) {
                 FlowCapableNodeConnector fcnc = fcncByNcIidEntry.getValue();
                 if (fcnc.getName() == null) {
@@ -259,26 +350,28 @@ public class SwitchManager implements AutoCloseable {
                 }
                 InstanceIdentifier<NodeConnector> ncIid = fcncByNcIidEntry.getKey();
                 NodeConnectorId ncId = ncIid.firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId();
-                if (fcnc.getName().matches(".*(vxlan|tun).*")) {
-                    tunnelPort = ncId;
-                }
-                if (nodeConfig != null && nodeConfig.getExternalInterfaces() != null) {
-                    for (String pattern : nodeConfig.getExternalInterfaces()) {
-                        if (fcnc.getName().matches(pattern)) {
-                            externalPorts.add(ncId);
-                            break;
-                        }
+                if (fcnc.getName().matches(".*(vxlan-).*")) {
+                    TunnelBuilder tunnelBuilder = tunnelBuilderByType.get(TunnelTypeVxlan.class);
+                    if (tunnelBuilder == null) {
+                        tunnelBuilder = new TunnelBuilder().setTunnelType(TunnelTypeVxlan.class);
+                        tunnelBuilderByType.put(TunnelTypeVxlan.class, tunnelBuilder);
+                    }
+                    tunnelBuilder.setNodeConnectorId(ncId);
+                } else if (fcnc.getName().matches(".*(vxlangpe-).*")) {
+                    TunnelBuilder tunnelBuilder = tunnelBuilderByType.get(TunnelTypeVxlanGpe.class);
+                    if (tunnelBuilder == null) {
+                        tunnelBuilder = new TunnelBuilder().setTunnelType(TunnelTypeVxlanGpe.class);
+                        tunnelBuilderByType.put(TunnelTypeVxlanGpe.class, tunnelBuilder);
                     }
+                    tunnelBuilder.setNodeConnectorId(ncId);
                 }
             }
-            this.tunnelPort = tunnelPort;
-            this.externalPorts = Collections.unmodifiableSet(externalPorts);
         }
 
         private void updateStatus() {
-            boolean tunnelPortWithIpExists = tunnelPortWithIpExists();
+            boolean tunnelWithIpAndNcExists = tunnelWithIpAndNcExists();
             if (fcNode != null) {
-                if (tunnelPortWithIpExists) {
+                if (tunnelWithIpAndNcExists && isHasEndpoints()) {
                     setStatus(SwitchStatus.READY);
                 } else {
                     setStatus(SwitchStatus.PREPARING);
@@ -296,15 +389,21 @@ public class SwitchManager implements AutoCloseable {
             this.status = newStatus;
         }
 
-        private boolean tunnelPortWithIpExists() {
-            boolean tunnelPortWithIpExists = false;
-            if (tunnelPort != null && nodeConfig != null && nodeConfig.getTunnelIp() != null) {
-                tunnelPortWithIpExists = true;
+        private boolean tunnelWithIpAndNcExists() {
+            if (tunnelBuilderByType.isEmpty()) {
+                LOG.trace("No tunnel on switch {}", nodeId.getValue());
+                return false;
+            }
+            LOG.trace("Iterating over tunnel till tunnel with IP and node-connector is not found.");
+            for (TunnelBuilder tb : tunnelBuilderByType.values()) {
+                if (tb.getIp() != null && tb.getNodeConnectorId() != null) {
+                    LOG.trace("Tunnel {} found.",tb.toString());
+                    return true;
+                } else {
+                    LOG.trace("Tunnel is not complete for node: {}", nodeId.getValue());
+                }
             }
-            LOG.trace("Status of tunnel on switch {} - tunnelPort: {} tunnelIp: {}", nodeId.getValue(),
-                    tunnelPort == null ? null : tunnelPort.getValue(),
-                    nodeConfig == null ? null : nodeConfig.getTunnelIp());
-            return tunnelPortWithIpExists;
+            return false;
         }
 
         public boolean isConfigurationEmpty() {
@@ -359,4 +458,6 @@ public class SwitchManager implements AutoCloseable {
         READY
     }
 
+
+
 }