Bug 8023: Making ELAN to use StateTunnelList listener 37/54237/7
authorPeriyasamy Palanisamy <periyasamy.palanisamy@ericsson.com>
Tue, 28 Mar 2017 07:18:06 +0000 (12:48 +0530)
committerSam Hague <shague@redhat.com>
Sat, 8 Apr 2017 16:40:01 +0000 (16:40 +0000)
* Currently ELAN uses Interface state DCN for tunnel events to program
remote DMAC and BC group when VxLAN tunnel is created later. So making it
to use listen StateTunnelList
* This change would be useful when ITM supports multiple VxLAN tunnels and
avoid race conditions

Change-Id: Idce3dd3a548b95feadf43fbe2c1311c3fafdb70a
Signed-off-by: Periyasamy Palanisamy <periyasamy.palanisamy@ericsson.com>
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanInterfaceStateChangeListener.java
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanTunnelInterfaceStateListener.java [new file with mode: 0644]
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/utils/ElanUtils.java
vpnservice/elanmanager/elanmanager-impl/src/main/resources/org/opendaylight/blueprint/elanmanager.xml

index 0fe5e03468382060eaa1137509459e322ff43d91..205ab9d073229572f8c784a1d0e64ca0993807c9 100644 (file)
@@ -9,22 +9,17 @@ package org.opendaylight.netvirt.elan.internal;
 
 
 import java.math.BigInteger;
-import java.util.Collections;
-import java.util.List;
+
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
-import org.opendaylight.netvirt.elan.ElanException;
 import org.opendaylight.netvirt.elan.utils.ElanConstants;
 import org.opendaylight.netvirt.elan.utils.ElanUtils;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.Tunnel;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelList;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnel;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
@@ -80,32 +75,6 @@ public class ElanInterfaceStateChangeListener
     @Override
     protected void update(InstanceIdentifier<Interface> identifier, Interface original, Interface update) {
         LOG.trace("Operation Interface update event - Old: {}, New: {}", original, update);
-        String interfaceName = update.getName();
-        if (update.getType() == null) {
-            LOG.trace("Interface type for interface {} is null", interfaceName);
-            return;
-        }
-        if (update.getType().equals(Tunnel.class)) {
-            DataStoreJobCoordinator.getInstance().enqueueJob(interfaceName, () -> {
-                if (!original.getOperStatus().equals(Interface.OperStatus.Unknown)
-                        && !update.getOperStatus().equals(Interface.OperStatus.Unknown)) {
-                    if (update.getOperStatus().equals(Interface.OperStatus.Up)) {
-                        InternalTunnel internalTunnel = getTunnelState(interfaceName);
-                        if (internalTunnel != null) {
-                            try {
-                                LOG.debug("ITM Tunnel Update event between source DPN {} and destination DPN {} ",
-                                    internalTunnel.getSourceDPN(), internalTunnel.getDestinationDPN());
-                                elanInterfaceManager.handleInternalTunnelStateEvent(internalTunnel.getSourceDPN(),
-                                        internalTunnel.getDestinationDPN());
-                            } catch (ElanException e) {
-                                LOG.error("Failed to update interface: " + identifier.toString(), e);
-                            }
-                        }
-                    }
-                }
-                return Collections.emptyList();
-            }, ElanConstants.JOB_MAX_RETRIES);
-        }
     }
 
     @Override
@@ -114,25 +83,6 @@ public class ElanInterfaceStateChangeListener
         String interfaceName =  intrf.getName();
         ElanInterface elanInterface = ElanUtils.getElanInterfaceByElanInterfaceName(broker, interfaceName);
         if (elanInterface == null) {
-            if (intrf.getType() != null && intrf.getType().equals(Tunnel.class)) {
-                DataStoreJobCoordinator.getInstance().enqueueJob(interfaceName,
-                    () -> {
-                        if (intrf.getOperStatus().equals(Interface.OperStatus.Up)) {
-                            InternalTunnel internalTunnel = getTunnelState(interfaceName);
-                            if (internalTunnel != null) {
-                                try {
-                                    LOG.debug("ITM Tunnel Add event between source DPN {} and destination DPN {} ",
-                                        internalTunnel.getSourceDPN(), internalTunnel.getDestinationDPN());
-                                    elanInterfaceManager.handleInternalTunnelStateEvent(internalTunnel.getSourceDPN(),
-                                            internalTunnel.getDestinationDPN());
-                                } catch (ElanException e) {
-                                    LOG.error("Failed to add interface: " + identifier.toString(), e);
-                                }
-                            }
-                        }
-                        return Collections.emptyList();
-                    }, ElanConstants.JOB_MAX_RETRIES);
-            }
             return;
         }
         InstanceIdentifier<ElanInterface> elanInterfaceId = ElanUtils
@@ -145,21 +95,6 @@ public class ElanInterfaceStateChangeListener
 
     }
 
-    public  InternalTunnel getTunnelState(String interfaceName) {
-        InternalTunnel internalTunnel = null;
-        TunnelList tunnelList = ElanUtils.buildInternalTunnel(broker);
-        if (tunnelList != null && tunnelList.getInternalTunnel() != null) {
-            List<InternalTunnel> internalTunnels = tunnelList.getInternalTunnel();
-            for (InternalTunnel tunnel : internalTunnels) {
-                if (tunnel.getTunnelInterfaceName().equalsIgnoreCase(interfaceName)) {
-                    internalTunnel = tunnel;
-                    break;
-                }
-            }
-        }
-        return internalTunnel;
-    }
-
     @Override
     protected InstanceIdentifier<Interface> getWildCardPath() {
         return InstanceIdentifier.create(InterfacesState.class).child(Interface.class);
diff --git a/vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanTunnelInterfaceStateListener.java b/vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanTunnelInterfaceStateListener.java
new file mode 100644 (file)
index 0000000..119affd
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. 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.netvirt.elan.internal;
+
+import java.math.BigInteger;
+import java.util.Collections;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
+import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.netvirt.elan.ElanException;
+import org.opendaylight.netvirt.elan.utils.ElanConstants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeInternal;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelOperStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelsState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ElanTunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBase<StateTunnelList,
+    ElanTunnelInterfaceStateListener> implements AutoCloseable {
+    private static final Logger LOG = LoggerFactory.getLogger(ElanTunnelInterfaceStateListener.class);
+    private final DataBroker dataBroker;
+    private final ElanInterfaceManager elanInterfaceManager;
+
+    public ElanTunnelInterfaceStateListener(final DataBroker dataBroker,
+            final ElanInterfaceManager elanInterfaceManager) {
+        super(StateTunnelList.class, ElanTunnelInterfaceStateListener.class);
+        this.dataBroker = dataBroker;
+        this.elanInterfaceManager = elanInterfaceManager;
+    }
+
+    @Override
+    public void init() {
+        registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
+    }
+
+    @Override
+    protected InstanceIdentifier<StateTunnelList> getWildCardPath() {
+        return InstanceIdentifier.create(TunnelsState.class).child(StateTunnelList.class);
+    }
+
+    @Override
+    protected void remove(InstanceIdentifier<StateTunnelList> key, StateTunnelList delete) {
+    }
+
+    @Override
+    protected void update(InstanceIdentifier<StateTunnelList> key, StateTunnelList original,
+            StateTunnelList update) {
+    }
+
+    @Override
+    protected void add(InstanceIdentifier<StateTunnelList> key, StateTunnelList add) {
+        LOG.info("processing add state for StateTunnelList {}", add);
+        if (!isInternalTunnel(add)) {
+            LOG.trace("tunnel {} is not a internal vxlan tunnel", add);
+            return;
+        }
+        TunnelOperStatus tunOpStatus = add.getOperState();
+        if (tunOpStatus != TunnelOperStatus.Down && tunOpStatus != TunnelOperStatus.Up) {
+            LOG.trace("Returning because unsupported tunnelOperStatus {}", tunOpStatus);
+            return;
+        }
+        DataStoreJobCoordinator.getInstance().enqueueJob(add.getTunnelInterfaceName(), () -> {
+            BigInteger srcDpId = new BigInteger(add.getSrcInfo().getTepDeviceId());
+            BigInteger dstDpId = new BigInteger(add.getDstInfo().getTepDeviceId());
+            try {
+                LOG.info("Handling tunnel state event for srcDpId {} and dstDpId {} ",
+                        srcDpId, dstDpId);
+                elanInterfaceManager.handleInternalTunnelStateEvent(srcDpId, dstDpId);
+            } catch (ElanException e) {
+                LOG.error("Failed handle tunnel state event between srcDpId {} and dstDpId {} ",
+                        srcDpId, dstDpId, e);
+            }
+            return Collections.emptyList();
+        }, ElanConstants.JOB_MAX_RETRIES);
+    }
+
+    @Override
+    protected ElanTunnelInterfaceStateListener getDataTreeChangeListener() {
+        return this;
+    }
+
+    private boolean isInternalTunnel(StateTunnelList stateTunnelList) {
+        return stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeInternal.class;
+    }
+
+}
index 90690e6aa6a664677ff8355ad7806b3236a5ad16..e309da86a1f5ca2bd6cd980891a46bb4c35e4232 100755 (executable)
@@ -92,7 +92,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.ser
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.ExternalTunnelList;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelList;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnel;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnelKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.CreateTerminatingServiceActionsInput;
@@ -1570,17 +1569,6 @@ public class ElanUtils {
         itmRpcService.createTerminatingServiceActions(input);
     }
 
-    public static TunnelList buildInternalTunnel(DataBroker broker) {
-        InstanceIdentifier<TunnelList> tunnelListInstanceIdentifier = InstanceIdentifier.builder(TunnelList.class)
-                .build();
-        Optional<TunnelList> tunnelList = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION,
-                tunnelListInstanceIdentifier);
-        if (tunnelList.isPresent()) {
-            return tunnelList.get();
-        }
-        return null;
-    }
-
     /**
      * Gets the external tunnel.
      *
index cf7236dd14682c4805314023f6a8c51c393aa569..c4dff66411690622684a554fa74fae70950c6435 100644 (file)
     <argument ref="elanInterfaceManager" />
   </bean>
 
+  <bean id="elanTunnelInterfaceStateListener"
+    class="org.opendaylight.netvirt.elan.internal.ElanTunnelInterfaceStateListener"
+    init-method="init" destroy-method="close">
+    <argument ref="dataBroker" />
+    <argument ref="elanInterfaceManager" />
+  </bean>
+
   <bean id="elanInterfaceStateClusterListener"
     class="org.opendaylight.netvirt.elan.internal.ElanInterfaceStateClusteredListener"
     init-method="init" destroy-method="close">