Bulk merge of l2gw changes
[netvirt.git] / elanmanager / impl / src / main / java / org / opendaylight / netvirt / elan / internal / ElanInterfaceManager.java
index 2b76fc1a2aaabde2c3102437bb65621c27c162fc..e76b4f763c9b877672f7da401dc3318ed6fe69fb 100644 (file)
@@ -8,44 +8,34 @@
 package org.opendaylight.netvirt.elan.internal;
 
 import static java.util.Collections.emptyList;
-import static org.opendaylight.controller.md.sal.binding.api.WriteTransaction.CREATE_MISSING_PARENTS;
-import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
-import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
 import static org.opendaylight.infrautils.utils.concurrent.LoggingFutures.addErrorLogging;
+import static org.opendaylight.mdsal.binding.util.Datastore.CONFIGURATION;
+import static org.opendaylight.mdsal.binding.util.Datastore.OPERATIONAL;
 import static org.opendaylight.netvirt.elan.utils.ElanUtils.isVxlanNetworkOrVxlanSegment;
 
-import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.FluentFuture;
 import com.google.common.util.concurrent.ListenableFuture;
 import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.Queue;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.locks.ReentrantLock;
-import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 import org.apache.commons.lang3.StringUtils;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
-import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
-import org.opendaylight.genius.infra.Datastore.Configuration;
-import org.opendaylight.genius.infra.Datastore.Operational;
-import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
-import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
-import org.opendaylight.genius.infra.TransactionAdapter;
-import org.opendaylight.genius.infra.TypedReadWriteTransaction;
-import org.opendaylight.genius.infra.TypedWriteTransaction;
 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
 import org.opendaylight.genius.itm.globals.ITMConstants;
@@ -71,8 +61,17 @@ import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId;
 import org.opendaylight.genius.utils.JvmGlobalLocks;
 import org.opendaylight.genius.utils.ServiceIndex;
 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
+import org.opendaylight.infrautils.utils.concurrent.Executors;
 import org.opendaylight.infrautils.utils.concurrent.LoggingFutures;
 import org.opendaylight.infrautils.utils.concurrent.NamedSimpleReentrantLock.Acquired;
+import org.opendaylight.mdsal.binding.api.DataBroker;
+import org.opendaylight.mdsal.binding.util.Datastore.Configuration;
+import org.opendaylight.mdsal.binding.util.Datastore.Operational;
+import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunner;
+import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunnerImpl;
+import org.opendaylight.mdsal.binding.util.TypedReadWriteTransaction;
+import org.opendaylight.mdsal.binding.util.TypedWriteTransaction;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
 import org.opendaylight.netvirt.elan.cache.ElanInstanceCache;
 import org.opendaylight.netvirt.elan.cache.ElanInterfaceCache;
 import org.opendaylight.netvirt.elan.l2gw.utils.ElanL2GatewayMulticastUtils;
@@ -90,20 +89,28 @@ import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronUtils;
 import org.opendaylight.netvirt.neutronvpn.interfaces.INeutronVpnManager;
 import org.opendaylight.serviceutils.srm.RecoverableListener;
 import org.opendaylight.serviceutils.srm.ServiceRecoveryRegistry;
+import org.opendaylight.serviceutils.tools.listener.AbstractAsyncDataTreeChangeListener;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
 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;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
 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;
@@ -112,9 +119,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.Elan
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanForwardingTables;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInterfaces;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMac;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMacBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMacKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesListKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfaces;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfacesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfacesKey;
@@ -124,6 +130,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.elan._interface.StaticMacEntries;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.elan._interface.StaticMacEntriesKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.state.Elan;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.state.ElanBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.state.ElanKey;
@@ -135,6 +142,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev14
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.Uint32;
+import org.opendaylight.yangtools.yang.common.Uint64;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -145,9 +154,10 @@ import org.slf4j.LoggerFactory;
  * @see org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface
  */
 @Singleton
-public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanInterface, ElanInterfaceManager>
+public class ElanInterfaceManager extends AbstractAsyncDataTreeChangeListener<ElanInterface>
         implements RecoverableListener {
     private static final Logger LOG = LoggerFactory.getLogger(ElanInterfaceManager.class);
+    private static final Logger EVENT_LOGGER = LoggerFactory.getLogger("NetvirtEventLogger");
     public static final long WAIT_TIME_FOR_SYNC_INSTALL = Long.getLong("wait.time.sync.install", 300L);
     private static final boolean SH_FLAG_SET = true;
     private static final boolean SH_FLAG_UNSET = false;
@@ -167,6 +177,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,8 +193,11 @@ 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);
+        super(dataBroker, LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(ElanInterfaces.class)
+                .child(ElanInterface.class),
+                Executors.newListeningSingleThreadExecutor("ElanInterfaceManager", LOG));
         this.broker = dataBroker;
         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
         this.idManager = managerService;
@@ -199,29 +213,38 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         this.elanL2GatewayMulticastUtils = elanL2GatewayMulticastUtils;
         this.elanInstanceCache = elanInstanceCache;
         this.elanInterfaceCache = elanInterfaceCache;
+        this.elanGroupCache = elanGroupCache;
         serviceRecoveryRegistry.addRecoverableListener(elanServiceRecoveryHandler.buildServiceRegistryKey(), this);
     }
 
-    @Override
-    @PostConstruct
     public void init() {
-        registerListener();
+        LOG.info("{} registered", getClass().getSimpleName());
     }
 
     @Override
     public void registerListener() {
-        registerListener(LogicalDatastoreType.CONFIGURATION, broker);
+        super.register();
+        LOG.info("Registering ElanInterfaceManager");
     }
 
     @Override
-    protected InstanceIdentifier<ElanInterface> getWildCardPath() {
-        return InstanceIdentifier.create(ElanInterfaces.class).child(ElanInterface.class);
+    public void deregisterListener() {
+        super.close();
+        LOG.info("Deregistering ElanInterfaceManager");
     }
 
     @Override
-    protected void remove(InstanceIdentifier<ElanInterface> identifier, ElanInterface del) {
+    @PreDestroy
+    public void close() {
+        super.close();
+        Executors.shutdownAndAwaitTermination(getExecutorService());
+    }
+
+    @Override
+    public void remove(InstanceIdentifier<ElanInterface> identifier, ElanInterface del) {
         String interfaceName = del.getName();
         String elanInstanceName = del.getElanInstanceName();
+        EVENT_LOGGER.debug("ELAN-Interface, REMOVE {} Instance {}", interfaceName, elanInstanceName);
         Queue<ElanInterface> elanInterfaces = unProcessedElanInterfaces.get(elanInstanceName);
         if (elanInterfaces != null && elanInterfaces.contains(del)) {
             elanInterfaces.remove(del);
@@ -229,7 +252,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
                 unProcessedElanInterfaces.remove(elanInstanceName);
             }
         }
-        ElanInstance elanInfo = elanInstanceCache.get(elanInstanceName).orNull();
+        ElanInstance elanInfo = elanInstanceCache.get(elanInstanceName).orElse(null);
         /*
          * Handling in case the elan instance is deleted.If the Elan instance is
          * deleted, there is no need to explicitly delete the elan interfaces
@@ -251,17 +274,17 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
 
     private static class RemoveElanInterfaceHolder {
         boolean isLastElanInterface = false;
-        boolean isLastInterfaceOnDpn = false;
-        BigInteger dpId = null;
+        Uint64 dpId = null;
     }
 
     @SuppressWarnings("checkstyle:ForbidCertainMethod")
-    public List<ListenableFuture<Void>> removeElanInterface(ElanInstance elanInfo, String interfaceName,
+    public List<ListenableFuture<?>> removeElanInterface(ElanInstance elanInfo, String interfaceName,
             InterfaceInfo interfaceInfo) {
         String elanName = elanInfo.getElanInstanceName();
-        long elanTag = elanInfo.getElanTag();
+        EVENT_LOGGER.debug("ELAN-InterfaceState, REMOVE {} Instance {}", interfaceName, elanName);
+        Uint32 elanTag = elanInfo.getElanTag();
         // We use two transaction so we don't suffer on multiple shards (interfaces and flows)
-        List<ListenableFuture<Void>> futures = new ArrayList<>();
+        List<ListenableFuture<?>> futures = new ArrayList<>();
         RemoveElanInterfaceHolder holder = new RemoveElanInterfaceHolder();
         futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, interfaceTx -> {
             Elan elanState = removeElanStateForInterface(elanInfo, interfaceName, interfaceTx);
@@ -284,12 +307,13 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
                     if (dpnInterfaces == null || dpnInterfaces.getInterfaces() == null
                         || dpnInterfaces.getInterfaces().isEmpty()) {
                         // No more Elan Interfaces in this DPN
+                        EVENT_LOGGER.debug("ELAN-Flows, REMOVE {} Instance {}", interfaceName, elanName);
                         LOG.debug("deleting the elan: {} present on dpId: {}", elanInfo.getElanInstanceName(),
                             holder.dpId);
                         if (!elanUtils.isOpenstackVniSemanticsEnforced()) {
-                            removeDefaultTermFlow(holder.dpId, elanInfo.getElanTag());
+                            removeDefaultTermFlow(holder.dpId, elanInfo.getElanTag().toJava());
                         }
-                        removeUnknownDmacFlow(holder.dpId, elanInfo, flowTx, elanInfo.getElanTag());
+                        removeUnknownDmacFlow(holder.dpId, elanInfo, flowTx, elanInfo.getElanTag().toJava());
                         removeEtreeUnknownDmacFlow(holder.dpId, elanInfo, flowTx);
                         removeElanBroadcastGroup(elanInfo, interfaceInfo, flowTx);
                         removeLocalBroadcastGroup(elanInfo, interfaceInfo, flowTx);
@@ -301,7 +325,6 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
                             }
                             unsetExternalTunnelTable(holder.dpId, elanInfo, flowTx);
                         }
-                        holder.isLastInterfaceOnDpn = true;
                     } else {
                         setupLocalBroadcastGroups(elanInfo, dpnInterfaces, interfaceInfo, flowTx);
                     }
@@ -310,11 +333,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,
@@ -323,12 +341,12 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         return futures;
     }
 
-    private void removeEtreeUnknownDmacFlow(BigInteger dpId, ElanInstance elanInfo,
+    private void removeEtreeUnknownDmacFlow(Uint64 dpId, ElanInstance elanInfo,
             TypedReadWriteTransaction<Configuration> deleteFlowGroupTx)
             throws ExecutionException, InterruptedException {
-        EtreeLeafTagName etreeLeafTag = elanEtreeUtils.getEtreeLeafTagByElanTag(elanInfo.getElanTag());
+        EtreeLeafTagName etreeLeafTag = elanEtreeUtils.getEtreeLeafTagByElanTag(elanInfo.getElanTag().toJava());
         if (etreeLeafTag != null) {
-            long leafTag = etreeLeafTag.getEtreeLeafTag().getValue();
+            long leafTag = etreeLeafTag.getEtreeLeafTag().getValue().toJava();
             removeUnknownDmacFlow(dpId, elanInfo, deleteFlowGroupTx, leafTag);
         }
     }
@@ -345,8 +363,8 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
             throws ExecutionException, InterruptedException {
         EtreeInstance etreeInstance = elanInfo.augmentation(EtreeInstance.class);
         if (etreeInstance != null) {
-            BigInteger dpnId = interfaceInfo.getDpId();
-            long groupId = ElanUtils.getEtreeLeafLocalBCGId(etreeInstance.getEtreeLeafTagVal().getValue());
+            Uint64 dpnId = interfaceInfo.getDpId();
+            long groupId = ElanUtils.getEtreeLeafLocalBCGId(etreeInstance.getEtreeLeafTagVal().getValue().toJava());
             LOG.trace("deleted the localBroadCast Group:{}", groupId);
             mdsalManager.removeGroup(deleteFlowGroupTx, dpnId, groupId);
         }
@@ -357,8 +375,8 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
             throws ExecutionException, InterruptedException {
         EtreeInstance etreeInstance = elanInfo.augmentation(EtreeInstance.class);
         if (etreeInstance != null) {
-            long etreeTag = etreeInstance.getEtreeLeafTagVal().getValue();
-            BigInteger dpnId = interfaceInfo.getDpId();
+            long etreeTag = etreeInstance.getEtreeLeafTagVal().getValue().toJava();
+            Uint64 dpnId = interfaceInfo.getDpId();
             long groupId = ElanUtils.getEtreeLeafRemoteBCGId(etreeTag);
             LOG.trace("deleting the remoteBroadCast group:{}", groupId);
             mdsalManager.removeGroup(deleteFlowGroupTx, dpnId, groupId);
@@ -372,8 +390,12 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         if (elanState == null) {
             return elanState;
         }
-        List<String> elanInterfaces = elanState.getElanInterfaces();
-        boolean isRemoved = elanInterfaces != null && elanInterfaces.remove(interfaceName);
+        List<String> existingElanInterfaces = elanState.getElanInterfaces();
+        List<String> elanInterfaces = new ArrayList<>();
+        if (existingElanInterfaces != null) {
+            elanInterfaces.addAll(existingElanInterfaces);
+        }
+        boolean isRemoved = elanInterfaces.remove(interfaceName);
         if (!isRemoved) {
             return elanState;
         }
@@ -392,20 +414,22 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
     }
 
     private void deleteElanInterfaceFromConfigDS(String interfaceName, TypedReadWriteTransaction<Configuration> tx)
-            throws ReadFailedException {
+            throws ExecutionException, InterruptedException {
         // removing the ElanInterface from the config data_store if interface is
         // not present in Interface config DS
-        if (interfaceManager.getInterfaceInfoFromConfigDataStore(TransactionAdapter.toReadWriteTransaction(tx),
-            interfaceName) == null
-                && elanInterfaceCache.get(interfaceName).isPresent()) {
+        InstanceIdentifier<ElanInterface> elanInterfaceId = ElanUtils
+                .getElanInterfaceConfigurationDataPathId(interfaceName);
+        FluentFuture<Optional<ElanInterface>> interfaceOptional = tx.read(elanInterfaceId);
+        if (!interfaceOptional.get().isPresent() && elanInterfaceCache.get(interfaceName).isPresent()) {
             tx.delete(ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName));
         }
     }
 
-    List<ListenableFuture<Void>> removeEntriesForElanInterface(ElanInstance elanInfo, InterfaceInfo
+    List<ListenableFuture<?>> removeEntriesForElanInterface(ElanInstance elanInfo, InterfaceInfo
             interfaceInfo, String interfaceName, boolean isLastElanInterface) {
         String elanName = elanInfo.getElanInstanceName();
-        List<ListenableFuture<Void>> futures = new ArrayList<>();
+        EVENT_LOGGER.debug("ELAN-InterfaceEntries, REMOVE {} Instance {}", interfaceName, elanName);
+        List<ListenableFuture<?>> futures = new ArrayList<>();
         futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, flowTx -> {
             futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, interfaceTx -> {
                 InstanceIdentifier<ElanInterfaceMac> elanInterfaceId = ElanUtils
@@ -414,10 +438,11 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
                 LOG.debug("Removing the Interface:{} from elan:{}", interfaceName, elanName);
                 if (interfaceInfo != null) {
                     if (existingElanInterfaceMac.isPresent()) {
-                        List<MacEntry> existingMacEntries = existingElanInterfaceMac.get().getMacEntry();
+                        Map<MacEntryKey, MacEntry> existingMacEntries =
+                            existingElanInterfaceMac.get().nonnullMacEntry();
                         if (existingMacEntries != null) {
                             List<PhysAddress> macAddresses = new ArrayList<>();
-                            for (MacEntry macEntry : existingMacEntries) {
+                            for (MacEntry macEntry : existingMacEntries.values()) {
                                 PhysAddress macAddress = macEntry.getMacAddress();
                                 LOG.debug("removing the  mac-entry:{} present on elanInterface:{}",
                                         macAddress.getValue(), interfaceName);
@@ -426,6 +451,8 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
                                 if (!isLastElanInterface && macEntryOptional.isPresent()) {
                                     interfaceTx.delete(ElanUtils.getMacEntryOperationalDataPath(elanName, macAddress));
                                 }
+                                EVENT_LOGGER.debug("ELAN-MacFlows, REMOVE {} Instance {} Mac {}",
+                                        interfaceName, elanName, macAddress);
                                 elanUtils.deleteMacFlows(elanInfo, interfaceInfo, macEntry, flowTx);
                                 macAddresses.add(macAddress);
                             }
@@ -442,9 +469,9 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
                 } else if (existingElanInterfaceMac.isPresent()) {
                     // Interface does not exist in ConfigDS, so lets remove everything
                     // about that interface related to Elan
-                    List<MacEntry> macEntries = existingElanInterfaceMac.get().getMacEntry();
+                    Map<MacEntryKey, MacEntry> macEntries = existingElanInterfaceMac.get().nonnullMacEntry();
                     if (macEntries != null) {
-                        for (MacEntry macEntry : macEntries) {
+                        for (MacEntry macEntry : macEntries.values()) {
                             PhysAddress macAddress = macEntry.getMacAddress();
                             if (elanUtils.getMacEntryForElanInstance(elanName, macAddress).isPresent()) {
                                 interfaceTx.delete(ElanUtils.getMacEntryOperationalDataPath(elanName, macAddress));
@@ -462,8 +489,8 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         return futures;
     }
 
-    private DpnInterfaces removeElanDpnInterfaceFromOperationalDataStore(String elanName, BigInteger dpId,
-                                                                         String interfaceName, long elanTag,
+    private DpnInterfaces removeElanDpnInterfaceFromOperationalDataStore(String elanName, Uint64 dpId,
+                                                                         String interfaceName, Uint32 elanTag,
                                                                          TypedReadWriteTransaction<Operational> tx)
             throws ExecutionException, InterruptedException {
         // FIXME: pass in and use ElanInstanceKey instead?
@@ -472,7 +499,10 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         try {
             DpnInterfaces dpnInterfaces = elanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId);
             if (dpnInterfaces != null) {
-                List<String> interfaceLists = dpnInterfaces.getInterfaces();
+                List<String> interfaceLists = null;
+                if (dpnInterfaces.getInterfaces() != null) {
+                    interfaceLists = new ArrayList<>(dpnInterfaces.getInterfaces());
+                }
                 if (interfaceLists != null) {
                     interfaceLists.remove(interfaceName);
                 }
@@ -490,20 +520,20 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         }
     }
 
-    private void deleteAllRemoteMacsInADpn(String elanName, BigInteger dpId, long elanTag) {
+    private void deleteAllRemoteMacsInADpn(String elanName, Uint64 dpId, Uint32 elanTag) {
         List<DpnInterfaces> dpnInterfaces = elanUtils.getInvolvedDpnsInElan(elanName);
         addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, confTx -> {
             for (DpnInterfaces dpnInterface : dpnInterfaces) {
-                BigInteger currentDpId = dpnInterface.getDpId();
+                Uint64 currentDpId = dpnInterface.getDpId();
                 if (!currentDpId.equals(dpId) && dpnInterface.getInterfaces() != null) {
                     for (String elanInterface : dpnInterface.getInterfaces()) {
                         ElanInterfaceMac macs = elanUtils.getElanInterfaceMacByInterfaceName(elanInterface);
                         if (macs == null || macs.getMacEntry() == null) {
                             continue;
                         }
-                        for (MacEntry mac : macs.getMacEntry()) {
-                            removeTheMacFlowInTheDPN(dpId, elanTag, currentDpId, mac, confTx);
-                            removeEtreeMacFlowInTheDPN(dpId, elanTag, currentDpId, mac, confTx);
+                        for (MacEntry mac : new ArrayList<MacEntry>(macs.nonnullMacEntry().values())) {
+                            removeTheMacFlowInTheDPN(dpId, elanTag, mac, confTx);
+                            removeEtreeMacFlowInTheDPN(dpId, elanTag, mac, confTx);
                         }
                     }
                 }
@@ -511,21 +541,20 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         }), LOG, "Error deleting remote MACs in DPN {}", dpId);
     }
 
-    private void removeEtreeMacFlowInTheDPN(BigInteger dpId, long elanTag, BigInteger currentDpId, MacEntry mac,
+    private void removeEtreeMacFlowInTheDPN(Uint64 dpId, Uint32 elanTag, MacEntry mac,
             TypedReadWriteTransaction<Configuration> confTx) throws ExecutionException, InterruptedException {
-        EtreeLeafTagName etreeLeafTag = elanEtreeUtils.getEtreeLeafTagByElanTag(elanTag);
+        EtreeLeafTagName etreeLeafTag = elanEtreeUtils.getEtreeLeafTagByElanTag(elanTag.longValue());
         if (etreeLeafTag != null) {
-            removeTheMacFlowInTheDPN(dpId, etreeLeafTag.getEtreeLeafTag().getValue(), currentDpId, mac, confTx);
+            removeTheMacFlowInTheDPN(dpId, etreeLeafTag.getEtreeLeafTag().getValue(), mac, confTx);
         }
     }
 
-    private void removeTheMacFlowInTheDPN(BigInteger dpId, long elanTag, BigInteger currentDpId, MacEntry mac,
+    private void removeTheMacFlowInTheDPN(Uint64 dpId, Uint32 elanTag, MacEntry mac,
             TypedReadWriteTransaction<Configuration> confTx) throws ExecutionException, InterruptedException {
         mdsalManager
                 .removeFlow(confTx, dpId,
                         MDSALUtil.buildFlow(NwConstants.ELAN_DMAC_TABLE,
-                                ElanUtils.getKnownDynamicmacFlowRef(NwConstants.ELAN_DMAC_TABLE, dpId, currentDpId,
-                                        mac.getMacAddress().getValue(), elanTag)));
+                                ElanUtils.getKnownDynamicmacFlowRef(elanTag, mac.getMacAddress().getValue())));
     }
 
     /*
@@ -547,14 +576,17 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
     * */
     @SuppressWarnings("checkstyle:ForbidCertainMethod")
     @Override
-    protected void update(InstanceIdentifier<ElanInterface> identifier, ElanInterface original, ElanInterface update) {
+    public void update(InstanceIdentifier<ElanInterface> identifier, ElanInterface original, ElanInterface update) {
         // updating the static-Mac Entries for the existing elanInterface
         String elanName = update.getElanInstanceName();
         String interfaceName = update.getName();
         LOG.info("Update static mac entries for elan interface {} in elan instance {}", interfaceName, elanName);
+        EVENT_LOGGER.debug("ELAN-Interface, UPDATE {} Instance {}", original.getName(), elanName);
 
-        List<StaticMacEntries> originalStaticMacEntries = original.getStaticMacEntries();
-        List<StaticMacEntries> updatedStaticMacEntries = update.getStaticMacEntries();
+        List<StaticMacEntries> originalStaticMacEntries = new ArrayList<StaticMacEntries>(original
+                .nonnullStaticMacEntries().values());
+        List<StaticMacEntries> updatedStaticMacEntries = new ArrayList<StaticMacEntries>(update
+                .nonnullStaticMacEntries().values());
         List<StaticMacEntries> deletedEntries = ElanUtils.diffOf(originalStaticMacEntries, updatedStaticMacEntries);
         List<StaticMacEntries> updatedEntries = ElanUtils.diffOf(updatedStaticMacEntries, originalStaticMacEntries);
 
@@ -586,17 +618,18 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
     }
 
     @Override
-    protected void add(InstanceIdentifier<ElanInterface> identifier, ElanInterface elanInterfaceAdded) {
+    public void add(InstanceIdentifier<ElanInterface> identifier, ElanInterface elanInterfaceAdded) {
         LOG.info("Init for ELAN interface Add {}", elanInterfaceAdded);
         addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, operTx -> {
             String elanInstanceName = elanInterfaceAdded.getElanInstanceName();
             String interfaceName = elanInterfaceAdded.getName();
+            EVENT_LOGGER.debug("ELAN-Interface, ADD {} Instance {}", interfaceName, elanInstanceName);
             InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
             if (interfaceInfo == null) {
                 LOG.info("Interface {} is removed from Interface Oper DS due to port down ", interfaceName);
                 return;
             }
-            ElanInstance elanInstance = elanInstanceCache.get(elanInstanceName).orNull();
+            ElanInstance elanInstance = elanInstanceCache.get(elanInstanceName).orElse(null);
 
             if (elanInstance == null) {
                 // Add the ElanInstance in the Configuration data-store
@@ -608,11 +641,11 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
                             elanInterfaceAdded.getDescription()).build(), elanInterfaces, confTx, operTx)).get();
             }
 
-            Long elanTag = elanInstance.getElanTag();
+            Uint32 elanTag = elanInstance.getElanTag();
             // If elan tag is not updated, then put the elan interface into
             // unprocessed entry map and entry. Let entries
             // in this map get processed during ELAN update DCN.
-            if (elanTag == null || elanTag == 0L) {
+            if (elanTag == null || elanTag.longValue() == 0L) {
                 ConcurrentLinkedQueue<ElanInterface> elanInterfaces = unProcessedElanInterfaces.get(elanInstanceName);
                 if (elanInterfaces == null) {
                     elanInterfaces = new ConcurrentLinkedQueue<>();
@@ -620,6 +653,8 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
                 if (!elanInterfaces.contains(elanInterfaceAdded)) {
                     elanInterfaces.add(elanInterfaceAdded);
                 }
+                LOG.error("ELAN tag for instance {} is not created. Adding it to unprocessed list."
+                        + " Recreate the network if this message is seen multiple times", elanInstanceName);
                 unProcessedElanInterfaces.put(elanInstanceName, elanInterfaces);
                 return;
             }
@@ -629,9 +664,9 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         }), LOG, "Error processing added ELAN interface");
     }
 
-    List<ListenableFuture<Void>> handleunprocessedElanInterfaces(ElanInstance elanInstance) {
+    List<ListenableFuture<?>> handleunprocessedElanInterfaces(ElanInstance elanInstance) {
         LOG.trace("Handling unprocessed elan interfaces for elan instance {}", elanInstance.getElanInstanceName());
-        List<ListenableFuture<Void>> futures = new ArrayList<>();
+        List<ListenableFuture<?>> futures = new ArrayList<>();
         Queue<ElanInterface> elanInterfaces = unProcessedElanInterfaces.get(elanInstance.getElanInstanceName());
         if (elanInterfaces == null || elanInterfaces.isEmpty()) {
             return futures;
@@ -653,33 +688,38 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
                 .getElanDpnInterfacesList(elanInstance.getElanInstanceName());
         List<DpnInterfaces> dpnInterfaceLists = null;
         if (elanDpnInterfacesList != null) {
-            dpnInterfaceLists = elanDpnInterfacesList.getDpnInterfaces();
+            dpnInterfaceLists = new ArrayList<DpnInterfaces>(elanDpnInterfacesList.nonnullDpnInterfaces().values());
         }
-        if (dpnInterfaceLists == null) {
-            dpnInterfaceLists = new ArrayList<>();
+        if (dpnInterfaceLists != null && !dpnInterfaceLists.isEmpty()) {
+            Uint64 dstDpId = interfaceInfo.getDpId();
+            processRemoteDmacFlowForInterface(dstDpId, elanInstance, dpnInterfaceLists, writeFlowGroupTx);
         }
+    }
+
+    private void processRemoteDmacFlowForInterface(Uint64 dstDpId, ElanInstance elanInstance,
+             List<DpnInterfaces> dpnInterfaceLists, TypedWriteTransaction<Configuration> writeFlowGroupTx) {
         for (DpnInterfaces dpnInterfaces : dpnInterfaceLists) {
-            BigInteger dstDpId = interfaceInfo.getDpId();
             if (Objects.equals(dpnInterfaces.getDpId(), dstDpId)) {
                 continue;
             }
             List<String> remoteElanInterfaces = dpnInterfaces.getInterfaces();
+            if (remoteElanInterfaces == null || remoteElanInterfaces.isEmpty()) {
+                continue;
+            }
             for (String remoteIf : remoteElanInterfaces) {
                 ElanInterfaceMac elanIfMac = elanUtils.getElanInterfaceMacByInterfaceName(remoteIf);
                 InterfaceInfo remoteInterface = interfaceManager.getInterfaceInfo(remoteIf);
                 if (elanIfMac == null || remoteInterface == null) {
                     continue;
                 }
-                List<MacEntry> remoteMacEntries = elanIfMac.getMacEntry();
-                if (remoteMacEntries != null) {
-                    for (MacEntry macEntry : remoteMacEntries) {
-                        String macAddress = macEntry.getMacAddress().getValue();
-                        LOG.info("Programming remote dmac {} on the newly added DPN {} for elan {}", macAddress,
-                                dstDpId, elanInstance.getElanInstanceName());
-                        elanUtils.setupRemoteDmacFlow(dstDpId, remoteInterface.getDpId(),
-                                remoteInterface.getInterfaceTag(), elanInstance.getElanTag(), macAddress,
-                                elanInstance.getElanInstanceName(), writeFlowGroupTx, remoteIf, elanInstance);
-                    }
+                Map<MacEntryKey, MacEntry> remoteMacEntries = elanIfMac.nonnullMacEntry();
+                for (MacEntry macEntry : remoteMacEntries.values()) {
+                    String macAddress = macEntry.getMacAddress().getValue();
+                    LOG.info("Programming remote dmac {} on the newly added DPN {} for elan {}", macAddress,
+                            dstDpId, elanInstance.getElanInstanceName());
+                    elanUtils.setupRemoteDmacFlow(dstDpId, remoteInterface.getDpId(),
+                            remoteInterface.getInterfaceTag(), elanInstance.getElanTag(), macAddress,
+                            elanInstance.getElanInstanceName(), writeFlowGroupTx, remoteIf, elanInstance);
                 }
             }
         }
@@ -688,11 +728,11 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
     private static class AddElanInterfaceHolder {
         private DpnInterfaces dpnInterfaces = null;
         private boolean isFirstInterfaceInDpn = false;
-        private BigInteger dpId;
+        private Uint64 dpId;
     }
 
     @SuppressWarnings("checkstyle:ForbidCertainMethod")
-    List<ListenableFuture<Void>> addElanInterface(ElanInterface elanInterface,
+    List<ListenableFuture<?>> addElanInterface(ElanInterface elanInterface,
             InterfaceInfo interfaceInfo, ElanInstance elanInstance) {
         Preconditions.checkNotNull(elanInstance, "elanInstance cannot be null");
         Preconditions.checkNotNull(interfaceInfo, "interfaceInfo cannot be null");
@@ -701,8 +741,9 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         String interfaceName = elanInterface.getName();
         String elanInstanceName = elanInterface.getElanInstanceName();
         LOG.trace("Adding elan interface: interface name {} , instance name {}", interfaceName, elanInstanceName);
+        EVENT_LOGGER.debug("ELAN-InterfaceState, ADD {} Instance {}", interfaceName, elanInstanceName);
 
-        List<ListenableFuture<Void>> futures = new ArrayList<>();
+        List<ListenableFuture<?>> futures = new ArrayList<>();
         AddElanInterfaceHolder holder = new AddElanInterfaceHolder();
         futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, operTx -> {
             Elan elanInfo = ElanUtils.getElanByName(broker, elanInstanceName);
@@ -781,8 +822,6 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
             // terminating service table flow entry
             // call bindservice of interfacemanager to create ingress table flow
             // enty.
-            // Add interface to the ElanInterfaceForwardingEntires Container
-            createElanInterfaceTablesList(interfaceName, operTx);
         }));
         futures.forEach(ElanUtils::waitForTransactionToComplete);
         futures.add(
@@ -798,41 +837,39 @@ 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.mergeParentStructurePut(ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName,
+                        holder.dpId), holder.dpnInterfaces);
+            }));
+        } 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;
     }
 
     @SuppressWarnings("checkstyle:ForbidCertainMethod")
-    List<ListenableFuture<Void>> setupEntriesForElanInterface(ElanInstance elanInstance,
+    List<ListenableFuture<?>> setupEntriesForElanInterface(ElanInstance elanInstance,
             ElanInterface elanInterface, InterfaceInfo interfaceInfo, boolean isFirstInterfaceInDpn) {
         String elanInstanceName = elanInstance.getElanInstanceName();
         String interfaceName = elanInterface.getName();
-        List<ListenableFuture<Void>> futures = new ArrayList<>();
-        BigInteger dpId = interfaceInfo.getDpId();
+        List<ListenableFuture<?>> futures = new ArrayList<>();
+        Uint64 dpId = interfaceInfo.getDpId();
         boolean isInterfaceOperational = isOperational(interfaceInfo);
         futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, confTx -> {
             futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, operTx -> {
                 installEntriesForElanInterface(elanInstance, elanInterface, interfaceInfo,
                     isFirstInterfaceInDpn, confTx);
-
-                List<StaticMacEntries> staticMacEntriesList = elanInterface.getStaticMacEntries();
+                Map<StaticMacEntriesKey, StaticMacEntries> staticMacEntriesMap =
+                    elanInterface.nonnullStaticMacEntries();
                 List<PhysAddress> staticMacAddresses = Lists.newArrayList();
-
-                if (ElanUtils.isNotEmpty(staticMacEntriesList)) {
-                    for (StaticMacEntries staticMacEntry : staticMacEntriesList) {
+                if (ElanUtils.isNotEmpty(staticMacEntriesMap.values())) {
+                    for (StaticMacEntries staticMacEntry : staticMacEntriesMap.values()) {
                         InstanceIdentifier<MacEntry> macId = getMacEntryOperationalDataPath(elanInstanceName,
                             staticMacEntry.getMacAddress());
                         Optional<MacEntry> existingMacEntry = ElanUtils.read(broker,
@@ -854,6 +891,8 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
                                 "programming smac and dmacs for {} on source and other DPNs for elan {} and interface"
                                     + " {}",
                                 macAddress, elanInstanceName, interfaceName);
+                            EVENT_LOGGER.debug("ELAN-MacFlows, ADD {} Instance {} Mac {}",
+                                    interfaceName, elanInstanceName, macAddress);
                             elanUtils.setupMacFlows(elanInstance, interfaceInfo, ElanConstants.STATIC_MAC_TIMEOUT,
                                 staticMacEntry.getMacAddress().getValue(), true, confTx);
                         }
@@ -862,7 +901,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
                     if (isInterfaceOperational) {
                         // Add MAC in TOR's remote MACs via OVSDB. Outside of the loop
                         // on purpose.
-                        for (StaticMacEntries staticMacEntry : staticMacEntriesList) {
+                        for (StaticMacEntries staticMacEntry : staticMacEntriesMap.values()) {
                             staticMacAddresses.add(staticMacEntry.getMacAddress());
                         }
                         elanL2GatewayUtils.scheduleAddDpnMacInExtDevices(elanInstance.getElanInstanceName(), dpId,
@@ -900,7 +939,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         MacEntry macEntry = new MacEntryBuilder().setMacAddress(physAddress).setInterface(interfaceName)
                 .withKey(new MacEntryKey(physAddress)).build();
         elanForwardingEntriesHandler.deleteElanInterfaceForwardingEntries(
-                elanInstanceCache.get(elanInstanceName).orNull(), interfaceInfo, macEntry);
+                elanInstanceCache.get(elanInstanceName).orElse(null), interfaceInfo, macEntry);
     }
 
     private boolean checkIfFirstInterface(String elanInterface, String elanInstanceName,
@@ -937,9 +976,11 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
             InterfaceInfo interfaceInfo, boolean isFirstInterfaceInDpn, TypedWriteTransaction<Configuration> confTx) {
         if (!isOperational(interfaceInfo)) {
             LOG.warn("Interface {} is not operational", elanInterface.getName());
+            EVENT_LOGGER.debug("ELAN-InterfaceEntries, ADD {} Instance {} Interface Status {}, returning",
+                    elanInterface.getName(), elanInstance.getElanInstanceName(), interfaceInfo.getOpState());
             return;
         }
-        BigInteger dpId = interfaceInfo.getDpId();
+        Uint64 dpId = interfaceInfo.getDpId();
         if (!elanUtils.isOpenstackVniSemanticsEnforced()) {
             elanUtils.setupTermDmacFlows(interfaceInfo, mdsalManager, confTx);
         }
@@ -973,22 +1014,18 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         if (!isOperational(interfaceInfo)) {
             LOG.warn("Entries for interface on dpn {} not installed since interface {} is not operational",
                     dpnInterfaces.getDpId(), interfaceInfo.getInterfaceName());
+            EVENT_LOGGER.debug("ELAN-1stInterfaceEntries, ADD {} Instance {} Interface Status {}, returning",
+                    interfaceInfo.getInterfaceName(), elanInfo.getElanInstanceName(), interfaceInfo.getOpState());
             return;
         }
+        EVENT_LOGGER.debug("ELAN-1stInterfaceEntries, ADD {} Instance {}",
+                interfaceInfo.getInterfaceName(), elanInfo.getElanInstanceName());
         // LocalBroadcast Group creation with elan-Interfaces
         LOG.info("Installing entries for interface {} on dpn {}", interfaceInfo.getInterfaceName(),
                 dpnInterfaces.getDpId());
         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,23 +1034,55 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         }
     }
 
+    public InstanceIdentifier<Group> getGroupIid(ElanInstance elanInfo, Uint64 dpnId) {
+        long remoteBcGroupId = ElanUtils.getElanRemoteBCGId(elanInfo.getElanTag().toJava());
+        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();
         Flow flow = MDSALUtil.buildFlowNew(NwConstants.ELAN_FILTER_EQUALS_TABLE,
-                getFlowRef(NwConstants.ELAN_FILTER_EQUALS_TABLE, ifTag, "group"), 9, elanInfo.getElanInstanceName(), 0,
-                0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)),
+                getFlowRef(NwConstants.ELAN_FILTER_EQUALS_TABLE, ifTag, "group"), 11, elanInfo.getElanInstanceName(),
+                0, 0, Uint64.valueOf(ElanConstants.COOKIE_ELAN_FILTER_EQUALS.toJava().add(BigInteger.valueOf(ifTag))),
                 ElanUtils.getTunnelIdMatchForFilterEqualsLPortTag(ifTag),
                 elanUtils.getInstructionsInPortForOutGroup(interfaceInfo.getInterfaceName()));
 
         mdsalManager.addFlow(writeFlowGroupTx, interfaceInfo.getDpId(), flow);
         LOG.trace("Filter equals table(55) flow entry created on dpn: {} for interface port: {}",
                 interfaceInfo.getDpId(), interfaceInfo.getPortName());
+        Map<InstructionKey, Instruction> customInstructionsMap = new HashMap<InstructionKey, Instruction>();
+        int instructionKey = 0;
+        for (Instruction instructionObj : MDSALUtil.buildInstructionsDrop()) {
+            customInstructionsMap.put(new InstructionKey(++instructionKey), instructionObj);
+        }
 
         Flow flowEntry = MDSALUtil.buildFlowNew(NwConstants.ELAN_FILTER_EQUALS_TABLE,
-                getFlowRef(NwConstants.ELAN_FILTER_EQUALS_TABLE, ifTag, "drop"), 10, elanInfo.getElanInstanceName(), 0,
-                0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)),
-                getMatchesForFilterEqualsLPortTag(ifTag), MDSALUtil.buildInstructionsDrop());
+                getFlowRef(NwConstants.ELAN_FILTER_EQUALS_TABLE, ifTag, "drop"), 12, elanInfo.getElanInstanceName(), 0,
+                0, Uint64.valueOf(ElanConstants.COOKIE_ELAN_FILTER_EQUALS.toJava().add(BigInteger.valueOf(ifTag))),
+                getMatchesForFilterEqualsLPortTag(ifTag), customInstructionsMap);
 
         mdsalManager.addFlow(writeFlowGroupTx, interfaceInfo.getDpId(), flowEntry);
         LOG.trace("Filter equals table(55) drop flow entry created on dpn: {} for interface port: {}",
@@ -1028,91 +1097,15 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
 
         mdsalManager.removeFlow(flowTx, interfaceInfo.getDpId(), flow);
 
-        Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.ELAN_FILTER_EQUALS_TABLE,
-            getFlowRef(NwConstants.ELAN_FILTER_EQUALS_TABLE, ifTag, "drop"), 10, elanInfo.getElanInstanceName(), 0,
-            0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)),
-            getMatchesForFilterEqualsLPortTag(ifTag), MDSALUtil.buildInstructionsDrop());
+        Flow flowEntity = MDSALUtil.buildFlow(NwConstants.ELAN_FILTER_EQUALS_TABLE,
+            getFlowRef(NwConstants.ELAN_FILTER_EQUALS_TABLE, ifTag, "drop"));
 
         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) {
+    private static List<MatchInfo> buildMatchesForVni(Uint64 vni) {
         List<MatchInfo> mkMatches = new ArrayList<>();
-        MatchInfo match = new MatchTunnelId(BigInteger.valueOf(vni));
+        MatchInfo match = new MatchTunnelId(vni);
         mkMatches.add(match);
         return mkMatches;
     }
@@ -1139,10 +1132,10 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
      *            elanTag to be written in metadata when flow is selected
      * @return the instructions ready to be installed in a flow
      */
-    private static List<InstructionInfo> getInstructionsIntOrExtTunnelTable(Long elanTag) {
+    private static List<InstructionInfo> getInstructionsIntOrExtTunnelTable(Uint32 elanTag) {
         List<InstructionInfo> mkInstructions = new ArrayList<>();
-        mkInstructions.add(new InstructionWriteMetadata(ElanHelper.getElanMetadataLabel(elanTag), ElanHelper
-                .getElanMetadataMask()));
+        mkInstructions.add(new InstructionWriteMetadata(ElanHelper.getElanMetadataLabel(elanTag.longValue()),
+                ElanHelper.getElanMetadataMask()));
         /* applicable for EXTERNAL_TUNNEL_TABLE only
         * TODO: We should point to SMAC or DMAC depending on a configuration property to enable mac learning
         */
@@ -1151,19 +1144,19 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
     }
 
     // Install DMAC entry on dst DPN
-    public List<ListenableFuture<Void>> installDMacAddressTables(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
-            BigInteger dstDpId) {
+    public List<ListenableFuture<?>> installDMacAddressTables(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
+            Uint64 dstDpId) {
         String interfaceName = interfaceInfo.getInterfaceName();
         ElanInterfaceMac elanInterfaceMac = elanUtils.getElanInterfaceMacByInterfaceName(interfaceName);
         if (elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
-            List<MacEntry> macEntries = elanInterfaceMac.getMacEntry();
+            Map<MacEntryKey, MacEntry> macEntries = elanInterfaceMac.nonnullMacEntry();
             return Collections.singletonList(ElanUtils.waitForTransactionToComplete(
                 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
-                    for (MacEntry macEntry : macEntries) {
+                    for (MacEntry macEntry : macEntries.values()) {
                         String macAddress = macEntry.getMacAddress().getValue();
                         LOG.info("Installing remote dmac for mac address {} and interface {}", macAddress,
                             interfaceName);
-                        try (Acquired lock = ElanUtils.lockElanMacDPN(elanInfo.getElanTag(), macAddress,
+                        try (Acquired lock = ElanUtils.lockElanMacDPN(elanInfo.getElanTag().toJava(), macAddress,
                             interfaceInfo.getDpId())) {
                             LOG.info("Acquired lock for mac : {}, proceeding with remote dmac install operation",
                                 macAddress);
@@ -1185,6 +1178,11 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
 
     private void setupLocalBroadcastGroups(ElanInstance elanInfo, DpnInterfaces newDpnInterface,
             InterfaceInfo interfaceInfo, TypedWriteTransaction<Configuration> confTx) {
+        if (!isOperational(interfaceInfo)) {
+            EVENT_LOGGER.debug("ELAN-LBG, ADD {} Instance {} Interface Status {}, returning",
+                    interfaceInfo.getInterfaceName(), elanInfo.getElanInstanceName(), interfaceInfo.getOpState());
+            return;
+        }
         setupStandardLocalBroadcastGroups(elanInfo, newDpnInterface, interfaceInfo, confTx);
         setupLeavesLocalBroadcastGroups(elanInfo, newDpnInterface, interfaceInfo, confTx);
     }
@@ -1193,7 +1191,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
             InterfaceInfo interfaceInfo, TypedWriteTransaction<Configuration> confTx) {
         List<Bucket> listBucket = new ArrayList<>();
         int bucketId = 0;
-        long groupId = ElanUtils.getElanLocalBCGId(elanInfo.getElanTag());
+        long groupId = ElanUtils.getElanLocalBCGId(elanInfo.getElanTag().toJava());
 
         List<String> interfaces = new ArrayList<>();
         if (newDpnInterface != null && newDpnInterface.getInterfaces() != null) {
@@ -1252,7 +1250,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
                 createDropBucket(listBucket);
             }
 
-            long etreeLeafTag = etreeInstance.getEtreeLeafTagVal().getValue();
+            long etreeLeafTag = etreeInstance.getEtreeLeafTagVal().getValue().toJava();
             long groupId = ElanUtils.getEtreeLeafLocalBCGId(etreeLeafTag);
             Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
                     MDSALUtil.buildBucketLists(listBucket));
@@ -1275,8 +1273,8 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
     public void removeLocalBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
             TypedReadWriteTransaction<Configuration> deleteFlowGroupTx)
             throws ExecutionException, InterruptedException {
-        BigInteger dpnId = interfaceInfo.getDpId();
-        long groupId = ElanUtils.getElanLocalBCGId(elanInfo.getElanTag());
+        Uint64 dpnId = interfaceInfo.getDpId();
+        long groupId = ElanUtils.getElanLocalBCGId(elanInfo.getElanTag().toJava());
         LOG.trace("deleted the localBroadCast Group:{}", groupId);
         mdsalManager.removeGroup(deleteFlowGroupTx, dpnId, groupId);
     }
@@ -1284,8 +1282,8 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
     public void removeElanBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
             TypedReadWriteTransaction<Configuration> deleteFlowGroupTx)
             throws ExecutionException, InterruptedException {
-        BigInteger dpnId = interfaceInfo.getDpId();
-        long groupId = ElanUtils.getElanRemoteBCGId(elanInfo.getElanTag());
+        Uint64 dpnId = interfaceInfo.getDpId();
+        long groupId = ElanUtils.getElanRemoteBCGId(elanInfo.getElanTag().toJava());
         LOG.trace("deleting the remoteBroadCast group:{}", groupId);
         mdsalManager.removeGroup(deleteFlowGroupTx, dpnId, groupId);
     }
@@ -1296,16 +1294,16 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
      * elanTag that will be used later in the ELANs pipeline.
      * @param dpnId the dpn id
      */
-    private void setExternalTunnelTable(BigInteger dpnId, ElanInstance elanInfo,
+    private void setExternalTunnelTable(Uint64 dpnId, ElanInstance elanInfo,
             TypedWriteTransaction<Configuration> confTx) {
-        long elanTag = elanInfo.getElanTag();
+        Uint32 elanTag = elanInfo.getElanTag();
         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpnId, NwConstants.EXTERNAL_TUNNEL_TABLE,
-                getFlowRef(NwConstants.EXTERNAL_TUNNEL_TABLE, elanTag), 5, // prio
+                getFlowRef(NwConstants.EXTERNAL_TUNNEL_TABLE, elanTag.longValue()), 5, // prio
                 elanInfo.getElanInstanceName(), // flowName
                 0, // idleTimeout
                 0, // hardTimeout
-                ITMConstants.COOKIE_ITM_EXTERNAL.add(BigInteger.valueOf(elanTag)),
-                buildMatchesForVni(ElanUtils.getVxlanSegmentationId(elanInfo)),
+                Uint64.valueOf(ITMConstants.COOKIE_ITM_EXTERNAL.toJava().add(BigInteger.valueOf(elanTag.longValue()))),
+                buildMatchesForVni(Uint64.valueOf(ElanUtils.getVxlanSegmentationId(elanInfo).longValue())),
                 getInstructionsIntOrExtTunnelTable(elanTag));
 
         mdsalManager.addFlow(confTx, flowEntity);
@@ -1318,14 +1316,14 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
      *
      * @param dpnId DPN whose Ext Tunnel table is going to be modified
      */
-    private void unsetExternalTunnelTable(BigInteger dpnId, ElanInstance elanInfo,
+    private void unsetExternalTunnelTable(Uint64 dpnId, ElanInstance elanInfo,
             TypedReadWriteTransaction<Configuration> confTx) throws ExecutionException, InterruptedException {
         // TODO: Use DataStoreJobCoordinator in order to avoid that removing the
         // last ElanInstance plus
         // adding a new one does (almost at the same time) are executed in that
         // exact order
 
-        String flowId = getFlowRef(NwConstants.EXTERNAL_TUNNEL_TABLE, elanInfo.getElanTag());
+        String flowId = getFlowRef(NwConstants.EXTERNAL_TUNNEL_TABLE, elanInfo.getElanTag().toJava());
         FlowEntity flowEntity = new FlowEntityBuilder()
             .setDpnId(dpnId)
             .setTableId(NwConstants.EXTERNAL_TUNNEL_TABLE)
@@ -1334,67 +1332,69 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         mdsalManager.removeFlow(confTx, flowEntity);
     }
 
-    public void setupTerminateServiceTable(ElanInstance elanInfo, BigInteger dpId,
+    public void setupTerminateServiceTable(ElanInstance elanInfo, Uint64 dpId,
             TypedWriteTransaction<Configuration> writeFlowGroupTx) {
         setupTerminateServiceTable(elanInfo, dpId, elanInfo.getElanTag(), writeFlowGroupTx);
         setupEtreeTerminateServiceTable(elanInfo, dpId, writeFlowGroupTx);
     }
 
-    public void setupTerminateServiceTable(ElanInstance elanInfo, BigInteger dpId, long elanTag,
+    public void setupTerminateServiceTable(ElanInstance elanInfo, Uint64 dpId, Uint32 elanTag,
             TypedWriteTransaction<Configuration> writeFlowGroupTx) {
         List<? extends MatchInfoBase> listMatchInfoBase;
         List<InstructionInfo> instructionInfos;
-        long serviceId;
+        Uint32 serviceId;
         if (!elanUtils.isOpenstackVniSemanticsEnforced()) {
             serviceId = elanTag;
-            listMatchInfoBase = ElanUtils.getTunnelMatchesForServiceId((int) elanTag);
-            instructionInfos = getInstructionsForOutGroup(ElanUtils.getElanLocalBCGId(elanTag));
+            listMatchInfoBase = ElanUtils.getTunnelMatchesForServiceId(elanTag);
+            instructionInfos = getInstructionsForOutGroup(ElanUtils.getElanLocalBCGId(elanTag.longValue()));
         } else {
             serviceId = ElanUtils.getVxlanSegmentationId(elanInfo);
-            listMatchInfoBase = buildMatchesForVni(serviceId);
+            listMatchInfoBase = buildMatchesForVni(Uint64.valueOf(serviceId));
             instructionInfos = getInstructionsIntOrExtTunnelTable(elanTag);
         }
         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INTERNAL_TUNNEL_TABLE,
-                getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE, serviceId), 5, String.format("%s:%d", "ITM Flow Entry ",
-                elanTag), 0, 0, ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(elanTag)), listMatchInfoBase,
-                instructionInfos);
+                getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE, serviceId.longValue()), 5,
+                String.format("%s:%s", "ITM Flow Entry ", elanTag.toString()), 0, 0,
+                Uint64.valueOf(ITMConstants.COOKIE_ITM.toJava().add(BigInteger.valueOf(elanTag.longValue()))),
+                listMatchInfoBase, instructionInfos);
         mdsalManager.addFlow(writeFlowGroupTx, flowEntity);
         LOG.info("Installed internal tunnel table (36) flow entry on dpn: {} for elan: {}, tag: {}", dpId,
                 elanInfo.getElanInstanceName(), elanTag);
     }
 
-    private void setupEtreeTerminateServiceTable(ElanInstance elanInfo, BigInteger dpId,
+    private void setupEtreeTerminateServiceTable(ElanInstance elanInfo, Uint64 dpId,
             TypedWriteTransaction<Configuration> writeFlowGroupTx) {
         EtreeInstance etreeInstance = elanInfo.augmentation(EtreeInstance.class);
         if (etreeInstance != null) {
-            setupTerminateServiceTable(elanInfo, dpId, etreeInstance.getEtreeLeafTagVal().getValue(), writeFlowGroupTx);
+            setupTerminateServiceTable(elanInfo, dpId,
+                etreeInstance.getEtreeLeafTagVal().getValue(), writeFlowGroupTx);
         }
     }
 
-    public void setupUnknownDMacTable(ElanInstance elanInfo, BigInteger dpId,
+    public void setupUnknownDMacTable(ElanInstance elanInfo, Uint64 dpId,
             TypedWriteTransaction<Configuration> writeFlowGroupTx) {
-        long elanTag = elanInfo.getElanTag();
+        long elanTag = elanInfo.getElanTag().toJava();
         installLocalUnknownFlow(elanInfo, dpId, elanTag, writeFlowGroupTx);
         installRemoteUnknownFlow(elanInfo, dpId, elanTag, writeFlowGroupTx);
         setupEtreeUnknownDMacTable(elanInfo, dpId, elanTag, writeFlowGroupTx);
     }
 
-    private void setupEtreeUnknownDMacTable(ElanInstance elanInfo, BigInteger dpId, long elanTag,
+    private void setupEtreeUnknownDMacTable(ElanInstance elanInfo, Uint64 dpId, long elanTag,
             TypedWriteTransaction<Configuration> writeFlowGroupTx) {
         EtreeLeafTagName etreeLeafTag = elanEtreeUtils.getEtreeLeafTagByElanTag(elanTag);
         if (etreeLeafTag != null) {
-            long leafTag = etreeLeafTag.getEtreeLeafTag().getValue();
+            long leafTag = etreeLeafTag.getEtreeLeafTag().getValue().toJava();
             installRemoteUnknownFlow(elanInfo, dpId, leafTag, writeFlowGroupTx);
             installLocalUnknownFlow(elanInfo, dpId, leafTag, writeFlowGroupTx);
         }
     }
 
-    private void installLocalUnknownFlow(ElanInstance elanInfo, BigInteger dpId, long elanTag,
+    private void installLocalUnknownFlow(ElanInstance elanInfo, Uint64 dpId, long elanTag,
             TypedWriteTransaction<Configuration> writeFlowGroupTx) {
         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.ELAN_UNKNOWN_DMAC_TABLE,
                 getUnknownDmacFlowRef(NwConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag,/* SH flag */false),
                 5, elanInfo.getElanInstanceName(), 0, 0,
-                ElanConstants.COOKIE_ELAN_UNKNOWN_DMAC.add(BigInteger.valueOf(elanTag)),
+                Uint64.valueOf(ElanConstants.COOKIE_ELAN_UNKNOWN_DMAC.toJava().add(BigInteger.valueOf(elanTag))),
                 getMatchesForElanTag(elanTag, /* SH flag */false),
                 getInstructionsForOutGroup(ElanUtils.getElanRemoteBCGId(elanTag)));
 
@@ -1403,7 +1403,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
                 dpId, elanInfo.getElanInstanceName(), elanTag);
     }
 
-    private void installRemoteUnknownFlow(ElanInstance elanInfo, BigInteger dpId, long elanTag,
+    private void installRemoteUnknownFlow(ElanInstance elanInfo, Uint64 dpId, long elanTag,
             TypedWriteTransaction<Configuration> writeFlowGroupTx) {
         // only if ELAN can connect to external network, perform the following
 
@@ -1411,7 +1411,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
             FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.ELAN_UNKNOWN_DMAC_TABLE,
                     getUnknownDmacFlowRef(NwConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag,/* SH flag */true),
                     5, elanInfo.getElanInstanceName(), 0, 0,
-                    ElanConstants.COOKIE_ELAN_UNKNOWN_DMAC.add(BigInteger.valueOf(elanTag)),
+                    Uint64.valueOf(ElanConstants.COOKIE_ELAN_UNKNOWN_DMAC.toJava().add(BigInteger.valueOf(elanTag))),
                     getMatchesForElanTag(elanTag, /* SH flag */true),
                     getInstructionsForOutGroup(ElanUtils.getElanLocalBCGId(elanTag)));
             mdsalManager.addFlow(writeFlowGroupTx, flowEntity);
@@ -1421,7 +1421,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
     }
 
 
-    private void removeUnknownDmacFlow(BigInteger dpId, ElanInstance elanInfo,
+    private void removeUnknownDmacFlow(Uint64 dpId, ElanInstance elanInfo,
             TypedReadWriteTransaction<Configuration> deleteFlowGroupTx, long elanTag)
             throws ExecutionException, InterruptedException {
         Flow flow = new FlowBuilder().setId(new FlowId(getUnknownDmacFlowRef(NwConstants.ELAN_UNKNOWN_DMAC_TABLE,
@@ -1436,14 +1436,14 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         }
     }
 
-    private void removeDefaultTermFlow(BigInteger dpId, long elanTag) {
+    private void removeDefaultTermFlow(Uint64 dpId, long elanTag) {
         elanUtils.removeTerminatingServiceAction(dpId, (int) elanTag);
     }
 
     private void bindService(ElanInstance elanInfo, ElanInterface elanInterface, int lportTag,
             TypedWriteTransaction<Configuration> tx) {
         if (isStandardElanService(elanInterface)) {
-            bindElanService(elanInfo.getElanTag(), elanInfo.getElanInstanceName(),
+            bindElanService(elanInfo.getElanTag().toJava(), elanInfo.getElanInstanceName(),
                     elanInterface.getName(), lportTag, tx);
         } else { // Etree service
             bindEtreeService(elanInfo, elanInterface, lportTag, tx);
@@ -1475,7 +1475,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         Optional<BoundServices> existingElanService = ElanUtils.read(broker, LogicalDatastoreType.CONFIGURATION,
                 bindServiceId);
         if (!existingElanService.isPresent()) {
-            tx.put(bindServiceId, serviceInfo, CREATE_MISSING_PARENTS);
+            tx.mergeParentStructurePut(bindServiceId, serviceInfo);
             LOG.trace("Done binding elan service for elan: {} for interface: {}", elanInstanceName, interfaceName);
         }
     }
@@ -1483,7 +1483,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
     private void bindEtreeService(ElanInstance elanInfo, ElanInterface elanInterface, int lportTag,
             TypedWriteTransaction<Configuration> tx) {
         if (elanInterface.augmentation(EtreeInterface.class).getEtreeInterfaceType() == EtreeInterfaceType.Root) {
-            bindElanService(elanInfo.getElanTag(), elanInfo.getElanInstanceName(), elanInterface.getName(),
+            bindElanService(elanInfo.getElanTag().toJava(), elanInfo.getElanInstanceName(), elanInterface.getName(),
                     lportTag, tx);
         } else {
             EtreeInstance etreeInstance = elanInfo.augmentation(EtreeInstance.class);
@@ -1491,7 +1491,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
                 LOG.error("EtreeInterface {} is associated with a non EtreeInstance: {}",
                         elanInterface.getName(), elanInfo.getElanInstanceName());
             } else {
-                bindElanService(etreeInstance.getEtreeLeafTagVal().getValue(), elanInfo.getElanInstanceName(),
+                bindElanService(etreeInstance.getEtreeLeafTagVal().getValue().toJava(), elanInfo.getElanInstanceName(),
                         elanInterface.getName(), lportTag, tx);
             }
         }
@@ -1527,18 +1527,18 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         List<Action> listAction = new ArrayList<>();
         int actionKey = 0;
         listAction.add(
-            new ActionSetFieldTunnelId(BigInteger.valueOf(interfaceInfo.getInterfaceTag())).buildAction(actionKey));
+            new ActionSetFieldTunnelId(Uint64.valueOf(interfaceInfo.getInterfaceTag())).buildAction(actionKey));
         actionKey++;
         listAction.add(new ActionNxResubmit(NwConstants.ELAN_FILTER_EQUALS_TABLE).buildAction(actionKey));
         return listAction;
     }
 
-    private static DpnInterfaces updateElanDpnInterfacesList(String elanInstanceName, BigInteger dpId,
+    private static DpnInterfaces updateElanDpnInterfacesList(String elanInstanceName, Uint64 dpId,
             List<String> interfaceNames, TypedWriteTransaction<Operational> tx) {
         DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId).setInterfaces(interfaceNames)
                 .withKey(new DpnInterfacesKey(dpId)).build();
-        tx.put(ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId), dpnInterface,
-                CREATE_MISSING_PARENTS);
+        tx.mergeParentStructurePut(ElanUtils
+                .getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId), dpnInterface);
         LOG.trace("Updated operational dpn interfaces for elan: {} with interfaces: {}", elanInstanceName,
                 interfaceNames);
         return dpnInterface;
@@ -1552,7 +1552,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
      * @param dpId
      *            the dp id
      */
-    private static void deleteElanDpnInterface(String elanInstanceName, BigInteger dpId,
+    private static void deleteElanDpnInterface(String elanInstanceName, Uint64 dpId,
             TypedReadWriteTransaction<Operational> tx) throws ExecutionException, InterruptedException {
         InstanceIdentifier<DpnInterfaces> dpnInterfacesId = ElanUtils
                 .getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId);
@@ -1563,34 +1563,14 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
     }
 
     private static DpnInterfaces createElanInterfacesList(String elanInstanceName, String interfaceName,
-            BigInteger dpId, TypedWriteTransaction<Operational> tx) {
+            Uint64 dpId, TypedWriteTransaction<Operational> tx) {
         List<String> interfaceNames = new ArrayList<>();
         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;
     }
 
-    private static void createElanInterfaceTablesList(String interfaceName, TypedReadWriteTransaction<Operational> tx)
-            throws ExecutionException, InterruptedException {
-        InstanceIdentifier<ElanInterfaceMac> elanInterfaceMacTables = ElanUtils
-                .getElanInterfaceMacEntriesOperationalDataPath(interfaceName);
-        Optional<ElanInterfaceMac> interfaceMacTables = tx.read(elanInterfaceMacTables).get();
-        // Adding new Elan Interface Port to the operational DataStore without
-        // Static-Mac Entries..
-        if (!interfaceMacTables.isPresent()) {
-            ElanInterfaceMac elanInterfaceMacTable = new ElanInterfaceMacBuilder().setElanInterface(interfaceName)
-                    .withKey(new ElanInterfaceMacKey(interfaceName)).build();
-            tx.put(ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName), elanInterfaceMacTable,
-                    CREATE_MISSING_PARENTS);
-            LOG.trace("Created interface MAC table for interface: {}", interfaceName);
-        }
-    }
-
     private static void createElanStateList(String elanInstanceName, String interfaceName,
             TypedReadWriteTransaction<Operational> tx) throws ExecutionException, InterruptedException {
         InstanceIdentifier<Elan> elanInstance = ElanUtils.getElanInstanceOperationalDataPath(elanInstanceName);
@@ -1598,14 +1578,16 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         // Adding new Elan Interface Port to the operational DataStore without
         // Static-Mac Entries..
         if (elanInterfaceLists.isPresent()) {
-            List<String> interfaceLists = elanInterfaceLists.get().getElanInterfaces();
-            if (interfaceLists == null) {
-                interfaceLists = new ArrayList<>();
-            }
+            List<String> interfaceLists = new ArrayList<>();
             interfaceLists.add(interfaceName);
+            List<String> existingInterfaceLists = elanInterfaceLists.get().getElanInterfaces();
+            if (existingInterfaceLists != null && !existingInterfaceLists.isEmpty()) {
+                existingInterfaceLists.forEach(iface -> interfaceLists.add(iface));
+            }
+
             Elan elanState = new ElanBuilder().setName(elanInstanceName).setElanInterfaces(interfaceLists)
                     .withKey(new ElanKey(elanInstanceName)).build();
-            tx.put(ElanUtils.getElanInstanceOperationalDataPath(elanInstanceName), elanState, CREATE_MISSING_PARENTS);
+            tx.mergeParentStructurePut(ElanUtils.getElanInstanceOperationalDataPath(elanInstanceName), elanState);
             LOG.trace("Updated operational elan state for elan: {} with interfaces: {}", elanInstanceName,
                     interfaceLists);
         }
@@ -1616,18 +1598,19 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
     }
 
     @SuppressWarnings("checkstyle:IllegalCatch")
-    public void handleInternalTunnelStateEvent(BigInteger srcDpId, BigInteger dstDpId) {
+    public void handleInternalTunnelStateEvent(Uint64 srcDpId, Uint64 dstDpId) {
         ElanDpnInterfaces dpnInterfaceLists = elanUtils.getElanDpnInterfacesList();
         LOG.trace("processing tunnel state event for srcDpId {} dstDpId {}"
                 + " and dpnInterfaceList {}", srcDpId, dstDpId, dpnInterfaceLists);
         if (dpnInterfaceLists == null) {
             return;
         }
-        List<ElanDpnInterfacesList> elanDpnIf = dpnInterfaceLists.nonnullElanDpnInterfacesList();
-        for (ElanDpnInterfacesList elanDpns : elanDpnIf) {
+        Map<ElanDpnInterfacesListKey, ElanDpnInterfacesList> elanDpnIf = dpnInterfaceLists
+                .nonnullElanDpnInterfacesList();
+        for (ElanDpnInterfacesList elanDpns : elanDpnIf.values()) {
             int cnt = 0;
             String elanName = elanDpns.getElanInstanceName();
-            ElanInstance elanInfo = elanInstanceCache.get(elanName).orNull();
+            ElanInstance elanInfo = elanInstanceCache.get(elanName).orElse(null);
             if (elanInfo == null) {
                 LOG.warn("ELAN Info is null for elanName {} that does exist in elanDpnInterfaceList, "
                         + "skipping this ELAN for tunnel handling", elanName);
@@ -1637,13 +1620,13 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
                 LOG.debug("Ignoring internal tunnel state event for Flat/Vlan elan {}", elanName);
                 continue;
             }
-            List<DpnInterfaces> dpnInterfaces = elanDpns.getDpnInterfaces();
+            Map<DpnInterfacesKey, DpnInterfaces> dpnInterfaces = elanDpns.nonnullDpnInterfaces();
             if (dpnInterfaces == null) {
                 continue;
             }
             DpnInterfaces dstDpnIf = null;
-            for (DpnInterfaces dpnIf : dpnInterfaces) {
-                BigInteger dpnIfDpId = dpnIf.getDpId();
+            for (DpnInterfaces dpnIf : dpnInterfaces.values()) {
+                Uint64 dpnIfDpId = dpnIf.getDpId();
                 if (Objects.equals(dpnIfDpId, srcDpId)) {
                     cnt++;
                 } else if (Objects.equals(dpnIfDpId, dstDpId)) {
@@ -1697,13 +1680,13 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         }
         // dpId/externalNodeId will be available either in source or destination
         // based on the tunnel end point
-        BigInteger dpId = null;
+        Uint64 dpId = null;
         NodeId externalNodeId = null;
         if (StringUtils.isNumeric(externalTunnel.getSourceDevice())) {
-            dpId = new BigInteger(externalTunnel.getSourceDevice());
+            dpId = Uint64.valueOf(externalTunnel.getSourceDevice());
             externalNodeId = new NodeId(externalTunnel.getDestinationDevice());
         } else if (StringUtils.isNumeric(externalTunnel.getDestinationDevice())) {
-            dpId = new BigInteger(externalTunnel.getDestinationDevice());
+            dpId = Uint64.valueOf(externalTunnel.getDestinationDevice());
             externalNodeId = new NodeId(externalTunnel.getSourceDevice());
         }
         if (dpId == null || externalNodeId == null) {
@@ -1715,10 +1698,11 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         if (dpnInterfaceLists == null) {
             return;
         }
-        List<ElanDpnInterfacesList> elanDpnIf = dpnInterfaceLists.nonnullElanDpnInterfacesList();
-        for (ElanDpnInterfacesList elanDpns : elanDpnIf) {
+        Map<ElanDpnInterfacesListKey, ElanDpnInterfacesList> elanDpnIf
+                = dpnInterfaceLists.nonnullElanDpnInterfacesList();
+        for (ElanDpnInterfacesList elanDpns : elanDpnIf.values()) {
             String elanName = elanDpns.getElanInstanceName();
-            ElanInstance elanInfo = elanInstanceCache.get(elanName).orNull();
+            ElanInstance elanInfo = elanInstanceCache.get(elanName).orElse(null);
 
             DpnInterfaces dpnInterfaces = elanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId);
             if (elanInfo == null || dpnInterfaces == null || dpnInterfaces.getInterfaces() == null
@@ -1727,7 +1711,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
             }
             LOG.debug("Elan instance:{} is present in Dpn:{} ", elanName, dpId);
 
-            final BigInteger finalDpId = dpId;
+            final Uint64 finalDpId = dpId;
             LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
                 confTx -> elanL2GatewayMulticastUtils.setupElanBroadcastGroups(elanInfo, finalDpId, confTx)), LOG,
                 "Error setting up ELAN BGs");
@@ -1756,7 +1740,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
      * @param externalNodeId
      *            the external node id
      */
-    private void installDpnMacsInL2gwDevice(String elanName, Set<String> lstElanInterfaceNames, BigInteger dpnId,
+    private void installDpnMacsInL2gwDevice(String elanName, Set<String> lstElanInterfaceNames, Uint64 dpnId,
             NodeId externalNodeId) {
         L2GatewayDevice elanL2GwDevice = ElanL2GwCacheUtils.getL2GatewayDeviceFromCache(elanName,
                 externalNodeId.getValue());
@@ -1779,6 +1763,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
                 dpnTepIp);
         LOG.debug("phyLocAlreadyExists = {} for locator [{}] in remote mcast entry for elan [{}], nodeId [{}]",
                 phyLocAlreadyExists, dpnTepIp.stringValue(), elanName, externalNodeId.getValue());
+        /*
         List<PhysAddress> staticMacs = elanL2GatewayUtils.getElanDpnMacsFromInterfaces(lstElanInterfaceNames);
 
         if (phyLocAlreadyExists) {
@@ -1787,6 +1772,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         }
         elanL2GatewayMulticastUtils.scheduleMcastMacUpdateJob(elanName, elanL2GwDevice);
         elanL2GatewayUtils.scheduleAddDpnMacsInExtDevice(elanName, dpnId, staticMacs, elanL2GwDevice);
+        */
     }
 
     /**
@@ -1825,17 +1811,12 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         // Matching metadata
         mkMatches.add(
                 new MatchMetadata(MetaDataUtil.getLportTagMetaData(lportTag), MetaDataUtil.METADATA_MASK_LPORT_TAG));
-        mkMatches.add(new MatchTunnelId(BigInteger.valueOf(lportTag)));
+        mkMatches.add(new MatchTunnelId(Uint64.valueOf(lportTag)));
         return mkMatches;
     }
 
-    @Override
-    protected ElanInterfaceManager getDataTreeChangeListener() {
-        return this;
-    }
-
     public void handleExternalInterfaceEvent(ElanInstance elanInstance, DpnInterfaces dpnInterfaces,
-                                             BigInteger dpId) {
+                                             Uint64 dpId) {
         LOG.debug("setting up remote BC group for elan {}", elanInstance.getPhysicalNetworkName());
         addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
             confTx -> elanL2GatewayMulticastUtils.setupStandardElanBroadcastGroups(elanInstance, dpnInterfaces, dpId,