Adding BC group update job. 34/84034/11
authormanojna v <manojna.vijayakrishna@ericsson.com>
Wed, 28 Aug 2019 11:07:59 +0000 (16:37 +0530)
committerChetan Arakere Gowdru <chetan.arakere@altencalsoftlabs.com>
Wed, 18 Sep 2019 07:08:53 +0000 (07:08 +0000)
Instead of all cics writing bc group information into ds,
only Entity Owner cic will write this into the datastore.

Change-Id: Idb0b81446b2f9d545098a8034cf80b14f1a967fe
Signed-off-by: manojna v <manojna.vijayakrishna@ericsson.com>
elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/cache/ElanInstanceDpnsCache.java
elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanDpnInterfaceClusteredListener.java
elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanExtnTepListener.java
elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanGroupCache.java
elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanInterfaceManager.java
elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/l2gw/jobs/BcGroupUpdateJob.java [new file with mode: 0644]
elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/l2gw/utils/ElanRefUtil.java [new file with mode: 0644]
elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/utils/ElanUtils.java

index 9a537e979925d0136c093add75fb1743e810b127..ad0c6b98174a1c0d71efc9dc2a28152562345fc5 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.netvirt.elan.cache;
 
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
@@ -42,4 +43,9 @@ public class ElanInstanceDpnsCache {
         Set<DpnInterfaces> dpns = elanInstanceToDpnsCache.get(elanInstanceName);
         return dpns != null ? Collections.unmodifiableCollection(dpns) : Collections.emptyList();
     }
+
+    @NonNull
+    public Map<String, Set<DpnInterfaces>> getElanDpns() {
+        return elanInstanceToDpnsCache;
+    }
 }
index ed77f3cef55f8de82ca56f1188e96383749bd9e3..881602f09c54a54899c6329149f854ff792b8be1 100644 (file)
@@ -21,8 +21,10 @@ import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundConstants;
 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
 import org.opendaylight.netvirt.elan.cache.ElanInstanceCache;
 import org.opendaylight.netvirt.elan.cache.ElanInstanceDpnsCache;
+import org.opendaylight.netvirt.elan.l2gw.jobs.BcGroupUpdateJob;
 import org.opendaylight.netvirt.elan.l2gw.utils.ElanL2GatewayMulticastUtils;
 import org.opendaylight.netvirt.elan.l2gw.utils.ElanL2GatewayUtils;
+import org.opendaylight.netvirt.elan.l2gw.utils.ElanRefUtil;
 import org.opendaylight.netvirt.elan.utils.ElanClusterUtils;
 import org.opendaylight.netvirt.elanmanager.utils.ElanL2GwCacheUtils;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanDpnInterfaces;
@@ -47,6 +49,7 @@ public class ElanDpnInterfaceClusteredListener
     private final JobCoordinator jobCoordinator;
     private final ElanInstanceCache elanInstanceCache;
     private final ElanInstanceDpnsCache elanInstanceDpnsCache;
+    private final ElanRefUtil elanRefUtil;
 
     @Inject
     public ElanDpnInterfaceClusteredListener(DataBroker broker, EntityOwnershipUtils entityOwnershipUtils,
@@ -54,7 +57,8 @@ public class ElanDpnInterfaceClusteredListener
                                              ElanClusterUtils elanClusterUtils, JobCoordinator jobCoordinator,
                                              ElanL2GatewayMulticastUtils elanL2GatewayMulticastUtils,
                                              ElanInstanceCache elanInstanceCache,
-                                             ElanInstanceDpnsCache elanInstanceDpnsCache) {
+                                             ElanInstanceDpnsCache elanInstanceDpnsCache,
+                                             ElanRefUtil elanRefUtil) {
         this.broker = broker;
         this.entityOwnershipUtils = entityOwnershipUtils;
         this.elanL2GatewayUtils = elanL2GatewayUtils;
@@ -63,6 +67,7 @@ public class ElanDpnInterfaceClusteredListener
         this.jobCoordinator = jobCoordinator;
         this.elanInstanceCache = elanInstanceCache;
         this.elanInstanceDpnsCache = elanInstanceDpnsCache;
+        this.elanRefUtil = elanRefUtil;
     }
 
     @PostConstruct
@@ -110,6 +115,7 @@ public class ElanDpnInterfaceClusteredListener
 
                     // updating remote mcast mac on l2gw devices
                     elanL2GatewayMulticastUtils.updateRemoteMcastMacOnElanL2GwDevices(elanName);
+                    BcGroupUpdateJob.updateAllBcGroups(elanName, elanRefUtil, elanL2GatewayMulticastUtils, broker);
                 }
             } finally {
                 elanInstanceDpnsCache.remove(getElanName(identifier), dpnInterfaces);
@@ -125,7 +131,8 @@ public class ElanDpnInterfaceClusteredListener
         List<String> interfaces = dpnInterfaces.getInterfaces();
         if (interfaces != null && !interfaces.isEmpty()) {
             LOG.debug("dpninterfaces update fired new size {}", interfaces.size());
-            elanInstanceDpnsCache.remove(getElanName(identifier), dpnInterfaces);
+            elanInstanceDpnsCache.remove(getElanName(identifier), original);
+            elanInstanceDpnsCache.add(getElanName(identifier), dpnInterfaces);
             LOG.debug("dpninterfaces last dpn interface on this elan {} ", dpnInterfaces.key());
             // this is the last dpn interface on this elan
             handleUpdate(identifier, dpnInterfaces);
@@ -135,13 +142,13 @@ public class ElanDpnInterfaceClusteredListener
     @Override
     protected void add(InstanceIdentifier<DpnInterfaces> identifier, final DpnInterfaces dpnInterfaces) {
         final String elanName = getElanName(identifier);
-
         jobCoordinator.enqueueJob(elanName + ":l2gw", () -> {
             elanInstanceDpnsCache.add(getElanName(identifier), dpnInterfaces);
             if (entityOwnershipUtils.isEntityOwner(HwvtepSouthboundConstants.ELAN_ENTITY_TYPE,
                     HwvtepSouthboundConstants.ELAN_ENTITY_NAME)) {
                 ElanInstance elanInstance = elanInstanceCache.get(elanName).orNull();
                 if (elanInstance != null) {
+                    BcGroupUpdateJob.updateAllBcGroups(elanName, elanRefUtil, elanL2GatewayMulticastUtils, broker);
                     elanL2GatewayUtils.installElanL2gwDevicesLocalMacsInDpn(
                             dpnInterfaces.getDpId(), elanInstance, dpnInterfaces.getInterfaces().get(0));
 
index 6a60fd6fccc8fd94a869e7d48eb25df9181d5d01..af8fec506833520766ff86ce20d0cf7e24e08fad 100644 (file)
@@ -7,21 +7,19 @@
  */
 package org.opendaylight.netvirt.elan.internal;
 
-import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
-
-import java.util.Collections;
 import javax.annotation.PostConstruct;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 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.AsyncClusteredDataTreeChangeListenerBase;
 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
 import org.opendaylight.netvirt.elan.cache.ElanInstanceCache;
+import org.opendaylight.netvirt.elan.l2gw.jobs.BcGroupUpdateJob;
 import org.opendaylight.netvirt.elan.l2gw.utils.ElanL2GatewayMulticastUtils;
-import org.opendaylight.netvirt.elan.utils.ElanConstants;
+import org.opendaylight.netvirt.elan.l2gw.utils.ElanRefUtil;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
 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.instances.elan.instance.ExternalTeps;
@@ -30,7 +28,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 @Singleton
-public class ElanExtnTepListener extends AsyncDataTreeChangeListenerBase<ExternalTeps, ElanExtnTepListener> {
+public class ElanExtnTepListener extends AsyncClusteredDataTreeChangeListenerBase<ExternalTeps, ElanExtnTepListener> {
 
     private static final Logger LOG = LoggerFactory.getLogger(ElanExtnTepListener.class);
 
@@ -39,19 +37,20 @@ public class ElanExtnTepListener extends AsyncDataTreeChangeListenerBase<Externa
     private final ElanL2GatewayMulticastUtils elanL2GatewayMulticastUtils;
     private final JobCoordinator jobCoordinator;
     private final ElanInstanceCache elanInstanceCache;
+    private final ElanRefUtil elanRefUtil;
 
     @Inject
     public ElanExtnTepListener(DataBroker dataBroker, ElanL2GatewayMulticastUtils elanL2GatewayMulticastUtils,
-            JobCoordinator jobCoordinator, ElanInstanceCache elanInstanceCache) {
+            JobCoordinator jobCoordinator, ElanInstanceCache elanInstanceCache, ElanRefUtil elanRefUtil) {
         super(ExternalTeps.class, ElanExtnTepListener.class);
         this.broker = dataBroker;
         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
         this.elanL2GatewayMulticastUtils = elanL2GatewayMulticastUtils;
         this.jobCoordinator = jobCoordinator;
         this.elanInstanceCache = elanInstanceCache;
+        this.elanRefUtil = elanRefUtil;
     }
 
-    @Override
     @PostConstruct
     public void init() {
         registerListener(LogicalDatastoreType.OPERATIONAL, broker);
@@ -65,7 +64,7 @@ public class ElanExtnTepListener extends AsyncDataTreeChangeListenerBase<Externa
     @Override
     protected void add(InstanceIdentifier<ExternalTeps> instanceIdentifier, ExternalTeps tep) {
         LOG.trace("ExternalTeps add received {}", instanceIdentifier);
-        updateElanRemoteBroadCastGroup(instanceIdentifier);
+        updateBcGroupOfElan(instanceIdentifier, tep);
     }
 
     @Override
@@ -75,21 +74,12 @@ public class ElanExtnTepListener extends AsyncDataTreeChangeListenerBase<Externa
     @Override
     protected void remove(InstanceIdentifier<ExternalTeps> instanceIdentifier, ExternalTeps tep) {
         LOG.trace("ExternalTeps remove received {}", instanceIdentifier);
-        updateElanRemoteBroadCastGroup(instanceIdentifier);
+        updateBcGroupOfElan(instanceIdentifier, tep);
     }
 
-    @SuppressWarnings("checkstyle:IllegalCatch")
-    private void updateElanRemoteBroadCastGroup(final InstanceIdentifier<ExternalTeps> iid) {
-        String elanName = iid.firstKeyOf(ElanInstance.class).getElanInstanceName();
-        ElanInstance elanInfo = elanInstanceCache.get(elanName).orNull();
-        if (elanInfo == null) {
-            return;
-        }
-
-        jobCoordinator.enqueueJob(elanName,
-            () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
-                confTx -> elanL2GatewayMulticastUtils.updateRemoteBroadcastGroupForAllElanDpns(elanInfo, confTx))),
-            ElanConstants.JOB_MAX_RETRIES);
+    protected void updateBcGroupOfElan(InstanceIdentifier<ExternalTeps> instanceIdentifier, ExternalTeps tep) {
+        String elanName = instanceIdentifier.firstKeyOf(ElanInstance.class).getElanInstanceName();
+        BcGroupUpdateJob.updateAllBcGroups(elanName, elanRefUtil, elanL2GatewayMulticastUtils, broker);
     }
 
     @Override
index 061d8029681cf7d3f7688bc660536187c79c1077..0f63223db098a7829fa403928d130693f646d0a0 100644 (file)
@@ -15,6 +15,7 @@ import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.TimeUnit;
 
+import javax.annotation.PostConstruct;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
@@ -39,7 +40,6 @@ public class ElanGroupCache extends AsyncClusteredDataTreeChangeListenerBase<Gro
     private final Scheduler scheduler;
     private final Map<InstanceIdentifier<Group>, Group> groupsById = new ConcurrentHashMap<>();
     private final Map<InstanceIdentifier<Group>, Collection<Runnable>> waitingJobs = new ConcurrentHashMap<>();
-    private volatile boolean initialized = false;
 
     @Inject
     public ElanGroupCache(final DataBroker dataBroker, final Scheduler scheduler) {
@@ -48,11 +48,9 @@ public class ElanGroupCache extends AsyncClusteredDataTreeChangeListenerBase<Gro
         this.scheduler = scheduler;
     }
 
+    @PostConstruct
     public synchronized void init() {
-        if (!initialized) {
-            initialized = true;
-            this.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
-        }
+        this.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
     }
 
     @Override
index 2b76fc1a2aaabde2c3102437bb65621c27c162fc..f40fcb81ae8d6af8cc146be8235b2e917e7c88de 100644 (file)
@@ -94,6 +94,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.
 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.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
@@ -101,9 +102,14 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instru
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+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.netvirt.elan.etree.rev160614.EtreeInstance;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInterface;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInterface.EtreeInterfaceType;
@@ -167,6 +173,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
     private final JobCoordinator jobCoordinator;
     private final ElanInstanceCache elanInstanceCache;
     private final ElanInterfaceCache elanInterfaceCache;
+    private final ElanGroupCache elanGroupCache;
 
     private final Map<String, ConcurrentLinkedQueue<ElanInterface>>
         unProcessedElanInterfaces = new ConcurrentHashMap<>();
@@ -182,6 +189,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
                                 final ElanInstanceCache elanInstanceCache,
                                 final ElanInterfaceCache elanInterfaceCache,
                                 final ElanServiceRecoveryHandler elanServiceRecoveryHandler,
+                                ElanGroupCache elanGroupCache,
                                 final ServiceRecoveryRegistry serviceRecoveryRegistry) {
         super(ElanInterface.class, ElanInterfaceManager.class);
         this.broker = dataBroker;
@@ -199,6 +207,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         this.elanL2GatewayMulticastUtils = elanL2GatewayMulticastUtils;
         this.elanInstanceCache = elanInstanceCache;
         this.elanInterfaceCache = elanInterfaceCache;
+        this.elanGroupCache = elanGroupCache;
         serviceRecoveryRegistry.addRecoverableListener(elanServiceRecoveryHandler.buildServiceRegistryKey(), this);
     }
 
@@ -251,7 +260,6 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
 
     private static class RemoveElanInterfaceHolder {
         boolean isLastElanInterface = false;
-        boolean isLastInterfaceOnDpn = false;
         BigInteger dpId = null;
     }
 
@@ -301,7 +309,6 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
                             }
                             unsetExternalTunnelTable(holder.dpId, elanInfo, flowTx);
                         }
-                        holder.isLastInterfaceOnDpn = true;
                     } else {
                         setupLocalBroadcastGroups(elanInfo, dpnInterfaces, interfaceInfo, flowTx);
                     }
@@ -310,11 +317,6 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         }));
         futures.forEach(ElanUtils::waitForTransactionToComplete);
 
-        if (holder.isLastInterfaceOnDpn && holder.dpId != null && isVxlanNetworkOrVxlanSegment(elanInfo)) {
-            futures.add(
-                ElanUtils.waitForTransactionToComplete(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
-                    confTx -> setElanAndEtreeBCGrouponOtherDpns(elanInfo, holder.dpId, confTx))));
-        }
         InterfaceRemoveWorkerOnElanInterface removeInterfaceWorker = new InterfaceRemoveWorkerOnElanInterface(
                 interfaceName, elanInfo, interfaceInfo, this, holder.isLastElanInterface);
         jobCoordinator.enqueueJob(ElanUtils.getElanInterfaceJobKey(interfaceName), removeInterfaceWorker,
@@ -798,20 +800,19 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
                 handleExternalInterfaceEvent(elanInstance, holder.dpnInterfaces, holder.dpId);
             }
         }
-
-        if (holder.isFirstInterfaceInDpn && isVxlanNetworkOrVxlanSegment(elanInstance)) {
-            //update the remote-DPNs remoteBC group entry with Tunnels
-            LOG.trace("update remote bc group for elan {} on other DPNs for newly added dpn {}", elanInstance,
-                holder.dpId);
-            futures.add(
-                ElanUtils.waitForTransactionToComplete(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
-                    confTx -> setElanAndEtreeBCGrouponOtherDpns(elanInstance, holder.dpId, confTx))));
+        if (holder.isFirstInterfaceInDpn) {
+            // ELAN's 1st ElanInterface added to this DPN
+            LOG.debug("Adding dpn into operational dpn list {}", holder.dpId);
+            futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, operTx -> {
+                operTx.put(ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, holder.dpId),
+                        holder.dpnInterfaces, CREATE_MISSING_PARENTS);
+            }));
+        } else {
+            LOG.debug("Updated dpn into operational dpn list {}", holder.dpId);
         }
 
-        String jobKey = ElanUtils.getElanInterfaceJobKey(interfaceName);
-        InterfaceAddWorkerOnElanInterface addWorker = new InterfaceAddWorkerOnElanInterface(jobKey,
-                elanInterface, interfaceInfo, elanInstance, holder.isFirstInterfaceInDpn, this);
-        jobCoordinator.enqueueJob(jobKey, addWorker, ElanConstants.JOB_MAX_RETRIES);
+        scheduleElanInterfaceWorkerAfterRemoteBcGroup(elanInstance, interfaceInfo, holder.dpnInterfaces,
+                holder.isFirstInterfaceInDpn, elanInterface);
         return futures;
     }
 
@@ -981,14 +982,6 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         setupLocalBroadcastGroups(elanInfo, dpnInterfaces, interfaceInfo, confTx);
         if (isFirstInterfaceInDpn) {
             LOG.trace("waitTimeForSyncInstall is {}", WAIT_TIME_FOR_SYNC_INSTALL);
-            BigInteger dpId = interfaceInfo.getDpId();
-            // RemoteBroadcast Group creation
-            try {
-                Thread.sleep(WAIT_TIME_FOR_SYNC_INSTALL);
-            } catch (InterruptedException e1) {
-                LOG.warn("Error while waiting for local BC group for ELAN {} to install", elanInfo);
-            }
-            elanL2GatewayMulticastUtils.setupElanBroadcastGroups(elanInfo, dpnInterfaces, dpId, confTx);
             try {
                 Thread.sleep(WAIT_TIME_FOR_SYNC_INSTALL);
             } catch (InterruptedException e1) {
@@ -997,6 +990,33 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         }
     }
 
+    public InstanceIdentifier<Group> getGroupIid(ElanInstance elanInfo, BigInteger dpnId) {
+        long remoteBcGroupId = ElanUtils.getElanRemoteBCGId(elanInfo.getElanTag());
+        return InstanceIdentifier.builder(Nodes.class)
+                .child(Node.class, new NodeKey(new org.opendaylight.yang.gen.v1.urn.opendaylight
+                        .inventory.rev130819.NodeId("openflow:" + dpnId.toString())))
+                .augmentation(FlowCapableNode.class)
+                .child(Group.class, new GroupKey(new GroupId(remoteBcGroupId))).build();
+    }
+
+    public void scheduleElanInterfaceWorkerAfterRemoteBcGroup(ElanInstance elanInfo,
+                                                              InterfaceInfo interfaceInfo,
+                                                              DpnInterfaces dpnInterfaces,
+                                                              boolean isFirstInterfaceInDpn,
+                                                              ElanInterface elanInterface) {
+        if (!isOperational(interfaceInfo)) {
+            LOG.debug("Interface {} is not operational", elanInterface.getName());
+            return;
+        }
+        String elanInterfaceJobKey = ElanUtils.getElanInterfaceJobKey(interfaceInfo.getInterfaceName());
+        InterfaceAddWorkerOnElanInterface addWorker = new InterfaceAddWorkerOnElanInterface(elanInterfaceJobKey,
+                elanInterface, interfaceInfo, elanInfo, isFirstInterfaceInDpn, this);
+        InstanceIdentifier<Group> groupInstanceId = getGroupIid(elanInfo, dpnInterfaces.getDpId());
+        elanGroupCache.addJobToWaitList(groupInstanceId, () -> {
+            jobCoordinator.enqueueJob(elanInterfaceJobKey, addWorker, ElanConstants.JOB_MAX_RETRIES);
+        });
+    }
+
     public void setupFilterEqualsTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
             TypedWriteTransaction<Configuration> writeFlowGroupTx) {
         int ifTag = interfaceInfo.getInterfaceTag();
@@ -1036,80 +1056,6 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         mdsalManager.removeFlow(flowTx, interfaceInfo.getDpId(), flowEntity);
     }
 
-    private void setElanAndEtreeBCGrouponOtherDpns(ElanInstance elanInfo, BigInteger dpId,
-            TypedWriteTransaction<Configuration> confTx) {
-        int elanTag = elanInfo.getElanTag().intValue();
-        long groupId = ElanUtils.getElanRemoteBCGId(elanTag);
-        setBCGrouponOtherDpns(elanInfo, dpId, elanTag, groupId, confTx);
-        EtreeInstance etreeInstance = elanInfo.augmentation(EtreeInstance.class);
-        if (etreeInstance != null) {
-            int etreeLeafTag = etreeInstance.getEtreeLeafTagVal().getValue().intValue();
-            long etreeLeafGroupId = ElanUtils.getEtreeLeafRemoteBCGId(etreeLeafTag);
-            setBCGrouponOtherDpns(elanInfo, dpId, etreeLeafTag, etreeLeafGroupId, confTx);
-        }
-    }
-
-    @SuppressWarnings("checkstyle:IllegalCatch")
-    private void setBCGrouponOtherDpns(ElanInstance elanInfo, BigInteger dpId, int elanTag, long groupId,
-            TypedWriteTransaction<Configuration> confTx) {
-        int bucketId = 0;
-        ElanDpnInterfacesList elanDpns = elanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
-        if (elanDpns != null) {
-            List<DpnInterfaces> dpnInterfaces = elanDpns.nonnullDpnInterfaces();
-            for (DpnInterfaces dpnInterface : dpnInterfaces) {
-                List<Bucket> remoteListBucketInfo = new ArrayList<>();
-                if (elanUtils.isDpnPresent(dpnInterface.getDpId()) && !Objects.equals(dpnInterface.getDpId(), dpId)
-                        && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) {
-                    List<Action> listAction = new ArrayList<>();
-                    int actionKey = 0;
-                    listAction.add(new ActionGroup(ElanUtils.getElanLocalBCGId(elanTag)).buildAction(++actionKey));
-                    remoteListBucketInfo.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId,
-                            MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
-                    bucketId++;
-                    for (DpnInterfaces otherFes : dpnInterfaces) {
-                        if (elanUtils.isDpnPresent(otherFes.getDpId()) && !Objects.equals(otherFes.getDpId(),
-                            dpnInterface.getDpId()) && otherFes.getInterfaces() != null
-                            && !otherFes.getInterfaces().isEmpty()) {
-                            try {
-                                List<Action> remoteListActionInfo = elanItmUtils.getInternalTunnelItmEgressAction(
-                                        dpnInterface.getDpId(), otherFes.getDpId(),
-                                        elanUtils.isOpenstackVniSemanticsEnforced()
-                                                ? ElanUtils.getVxlanSegmentationId(elanInfo) : elanTag);
-                                if (!remoteListActionInfo.isEmpty()) {
-                                    remoteListBucketInfo.add(MDSALUtil.buildBucket(remoteListActionInfo, MDSALUtil
-                                            .GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
-                                    bucketId++;
-                                }
-                            } catch (Exception ex) {
-                                LOG.error("setElanBCGrouponOtherDpns failed due to Exception caught; "
-                                        + "Logical Group Interface not found between source Dpn - {}, "
-                                        + "destination Dpn - {} ", dpnInterface.getDpId(), otherFes.getDpId(), ex);
-                                return;
-                            }
-                        }
-                    }
-                    List<Bucket> elanL2GwDevicesBuckets = elanL2GatewayMulticastUtils
-                            .getRemoteBCGroupBucketsOfElanL2GwDevices(elanInfo, dpnInterface.getDpId(), bucketId);
-                    remoteListBucketInfo.addAll(elanL2GwDevicesBuckets);
-
-                    if (remoteListBucketInfo.isEmpty()) {
-                        LOG.debug("No ITM is present on Dpn - {} ", dpnInterface.getDpId());
-                        continue;
-                    }
-                    Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
-                            MDSALUtil.buildBucketLists(remoteListBucketInfo));
-                    LOG.trace("Installing remote bc group {} on dpnId {}", group, dpnInterface.getDpId());
-                    mdsalManager.addGroup(confTx, dpnInterface.getDpId(), group);
-                }
-            }
-            try {
-                Thread.sleep(WAIT_TIME_FOR_SYNC_INSTALL);
-            } catch (InterruptedException e1) {
-                LOG.warn("Error while waiting for remote BC group on other DPNs for ELAN {} to install", elanInfo);
-            }
-        }
-    }
-
     private static List<MatchInfo> buildMatchesForVni(Long vni) {
         List<MatchInfo> mkMatches = new ArrayList<>();
         MatchInfo match = new MatchTunnelId(BigInteger.valueOf(vni));
@@ -1568,10 +1514,6 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         interfaceNames.add(interfaceName);
         DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId).setInterfaces(interfaceNames)
                 .withKey(new DpnInterfacesKey(dpId)).build();
-        tx.put(ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId), dpnInterface,
-                CREATE_MISSING_PARENTS);
-        LOG.trace("Created operational dpn interfaces for elan: {} with interfaces: {}", elanInstanceName,
-                interfaceNames);
         return dpnInterface;
     }
 
diff --git a/elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/l2gw/jobs/BcGroupUpdateJob.java b/elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/l2gw/jobs/BcGroupUpdateJob.java
new file mode 100644 (file)
index 0000000..88a8078
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2019 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.l2gw.jobs;
+
+import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.ListenableFuture;
+
+import java.util.List;
+import java.util.concurrent.Callable;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
+import org.opendaylight.netvirt.elan.l2gw.utils.ElanL2GatewayMulticastUtils;
+import org.opendaylight.netvirt.elan.l2gw.utils.ElanRefUtil;
+import org.opendaylight.netvirt.elan.utils.ElanUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BcGroupUpdateJob implements Callable<List<ListenableFuture<Void>>> {
+
+    private static final Logger LOG = LoggerFactory.getLogger("HwvtepEventLogger");
+
+    private final String elanName;
+    private final ElanL2GatewayMulticastUtils elanL2GatewayMulticastUtils;
+    private final ElanRefUtil elanRefUtil;
+    private final ManagedNewTransactionRunner txRunner;
+    protected String jobKey;
+
+    public BcGroupUpdateJob(String elanName,
+                            ElanRefUtil elanRefUtil,
+                            ElanL2GatewayMulticastUtils elanL2GatewayMulticastUtils,
+                            DataBroker dataBroker) {
+        this.jobKey = ElanUtils.getBcGroupUpdateKey(elanName);
+        this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
+        this.elanName = elanName;
+        this.elanRefUtil = elanRefUtil;
+        this.elanL2GatewayMulticastUtils = elanL2GatewayMulticastUtils;
+    }
+
+    public void submit() {
+        elanRefUtil.getElanClusterUtils().runOnlyInOwnerNode(this.jobKey, "BC Group Update Job", this);
+    }
+
+    @Override
+    public List<ListenableFuture<Void>> call() throws Exception {
+        Optional<ElanInstance> elanInstanceOptional =  elanRefUtil.getElanInstanceCache().get(elanName);
+        if (elanInstanceOptional.isPresent()) {
+            return Lists.newArrayList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
+                confTx -> elanL2GatewayMulticastUtils.updateRemoteBroadcastGroupForAllElanDpns(
+                        elanInstanceOptional.get(), confTx)));
+        }
+        return null;
+    }
+
+    public static void updateAllBcGroups(String elanName,
+                                         ElanRefUtil elanRefUtil,
+                                         ElanL2GatewayMulticastUtils elanL2GatewayMulticastUtils,
+                                         DataBroker dataBroker) {
+        new BcGroupUpdateJob(elanName, elanRefUtil, elanL2GatewayMulticastUtils, dataBroker).submit();
+    }
+}
diff --git a/elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/l2gw/utils/ElanRefUtil.java b/elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/l2gw/utils/ElanRefUtil.java
new file mode 100644 (file)
index 0000000..17e874a
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2019 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.l2gw.utils;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
+import org.opendaylight.netvirt.elan.cache.ElanInstanceCache;
+import org.opendaylight.netvirt.elan.cache.ElanInstanceDpnsCache;
+import org.opendaylight.netvirt.elan.cache.ElanInterfaceCache;
+import org.opendaylight.netvirt.elan.utils.ElanClusterUtils;
+import org.opendaylight.netvirt.elan.utils.Scheduler;
+
+@Singleton
+public class ElanRefUtil {
+
+    private final DataBroker dataBroker;
+    private final ElanClusterUtils elanClusterUtils;
+    private final Scheduler scheduler;
+    private final JobCoordinator jobCoordinator;
+    private final ElanInstanceCache elanInstanceCache;
+    private final ElanInstanceDpnsCache elanInstanceDpnsCache;
+    private final ElanInterfaceCache elanInterfaceCache;
+
+    @Inject
+    public ElanRefUtil(DataBroker dataBroker,
+                       ElanClusterUtils elanClusterUtils,
+                       ElanInstanceCache elanInstanceCache,
+                       ElanInstanceDpnsCache elanInstanceDpnsCache,
+                       ElanInterfaceCache elanInterfaceCache,
+                       JobCoordinator jobCoordinator,
+                       Scheduler scheduler) {
+        this.dataBroker = dataBroker;
+        this.elanClusterUtils = elanClusterUtils;
+        this.elanInstanceCache = elanInstanceCache;
+        this.elanInstanceDpnsCache = elanInstanceDpnsCache;
+        this.elanInterfaceCache = elanInterfaceCache;
+        this.jobCoordinator = jobCoordinator;
+        this.scheduler = scheduler;
+    }
+
+    public DataBroker getDataBroker() {
+        return dataBroker;
+    }
+
+    public ElanClusterUtils getElanClusterUtils() {
+        return elanClusterUtils;
+    }
+
+    public ElanInstanceCache getElanInstanceCache() {
+        return elanInstanceCache;
+    }
+
+    public ElanInstanceDpnsCache getElanInstanceDpnsCache() {
+        return elanInstanceDpnsCache;
+    }
+
+    public ElanInterfaceCache getElanInterfaceCache() {
+        return elanInterfaceCache;
+    }
+
+    public JobCoordinator getJobCoordinator() {
+        return jobCoordinator;
+    }
+
+    public Scheduler getScheduler() {
+        return scheduler;
+    }
+}
\ No newline at end of file
index 6b24edebcde5cfbd3c73b7fb280f04130c7c83f6..c896d0cfb15304ca9884aec7a0f5d70ed43cb8f4 100755 (executable)
@@ -1646,4 +1646,8 @@ public class ElanUtils {
         return InstanceIdentifier.builder(Nodes.class).child(Node.class, new NodeKey(new NodeId("openflow:" + dpnId)))
                 .augmentation(FlowCapableNode.class).child(Group.class, new GroupKey(new GroupId(groupId))).build();
     }
+
+    public static String getBcGroupUpdateKey(String elanName) {
+        return "bc.group.update." + elanName;
+    }
 }