Merge "Neutron port listener updated to support allowed address pair with security...
authorSam Hague <shague@redhat.com>
Wed, 13 Jul 2016 15:38:50 +0000 (15:38 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Wed, 13 Jul 2016 15:38:50 +0000 (15:38 +0000)
32 files changed:
vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpExternalTunnelManager.java
vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpInterfaceEventListener.java
vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpProvider.java
vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpSubnetListener.java [new file with mode: 0644]
vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpUCastMacListener.java
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanDpnInterfaceClusteredListener.java
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanInstanceManager.java
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanInterfaceManager.java
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanInterfaceStateChangeListener.java
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanInterfaceStateClusteredListener.java
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanNodeListener.java
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanPacketInHandler.java
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanServiceProvider.java
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanSmacFlowEventListener.java
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/InterfaceAddWorkerOnElan.java [moved from vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanInterfaceAddWorker.java with 62% similarity]
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/InterfaceAddWorkerOnElanInterface.java [new file with mode: 0644]
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/InterfaceRemoveWorkerOnElan.java [moved from vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanInterfaceRemoveWorker.java with 56% similarity]
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/InterfaceRemoveWorkerOnElanInterface.java [new file with mode: 0644]
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/l2gw/jobs/LogicalSwitchAddedJob.java
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/statisitcs/ElanStatisticsImpl.java
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/utils/ElanClusterUtils.java
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/utils/ElanForwardingEntriesHandler.java [moved from vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanForwardingEntriesHandler.java with 59% similarity]
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/utils/ElanUtils.java
vpnservice/neutronvpn/neutronvpn-api/src/main/yang/neutronvpn.yang
vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronPortChangeListener.java
vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronSubnetChangeListener.java
vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnManager.java
vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnProvider.java
vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/l2gw/AddL2GwDevicesToTransportZoneJob.java [new file with mode: 0644]
vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/l2gw/L2GatewayProvider.java
vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/l2gw/L2GwTransportZoneListener.java [new file with mode: 0644]
vpnservice/neutronvpn/neutronvpn-impl/src/test/java/org/opendaylight/netvirt/neutronvpn/NeutronPortChangeListenerTest.java

index bcfbd96771e1c059490f1d6ef9e02fd4cde71444..d5f09965f55c3f779a9cef8af39533cc2f486472 100644 (file)
@@ -85,6 +85,7 @@ public class DhcpExternalTunnelManager {
 
     private ConcurrentMap<BigInteger, Set<Pair<IpAddress, String>>> designatedDpnsToTunnelIpElanNameCache = new ConcurrentHashMap<>();
     private ConcurrentMap<Pair<IpAddress, String>, Set<String>> tunnelIpElanNameToVmMacCache = new ConcurrentHashMap<>();
+    private ConcurrentMap<Pair<IpAddress, String>, Set<String>> availableVMCache = new ConcurrentHashMap<>();
     private ConcurrentMap<Pair<BigInteger, String>, Port> vniMacAddressToPortCache = new ConcurrentHashMap<>();
     private ItmRpcService itmRpcService;
     private EntityOwnershipService entityOwnershipService;
@@ -162,9 +163,7 @@ public class DhcpExternalTunnelManager {
     }
 
     public void unInstallDhcpFlowsForVms(String elanInstanceName, List<BigInteger> dpns, String vmMacAddress) {
-        for (BigInteger dpn : dpns) {
-            unInstallDhcpEntries(dpn, vmMacAddress, entityOwnershipService);
-        }
+        unInstallDhcpEntriesOnDpns(dpns, vmMacAddress);
         removeFromLocalCache(elanInstanceName, vmMacAddress);
     }
 
@@ -236,6 +235,20 @@ public class DhcpExternalTunnelManager {
         setOfExistingVmMacAddress.add(vmMacAddress);
         logger.trace("Updating tunnelIpElanNameToVmMacCache for tunnelIpElanName {} value {}", tunnelIpElanName, setOfExistingVmMacAddress);
         tunnelIpElanNameToVmMacCache.put(tunnelIpElanName, setOfExistingVmMacAddress);
+        updateExistingVMTunnelIPCache(tunnelIp, elanInstanceName, vmMacAddress);
+    }
+
+    public void updateExistingVMTunnelIPCache(IpAddress tunnelIp, String elanInstanceName, String vmMacAddress) {
+        Pair<IpAddress, String> tunnelIpElanName = new ImmutablePair<IpAddress, String>(tunnelIp, elanInstanceName);
+        Set<String> listExistingVmMacAddress;
+        listExistingVmMacAddress = availableVMCache.get(tunnelIpElanName);
+        if (null == listExistingVmMacAddress) {
+            listExistingVmMacAddress = new HashSet<String>();
+        }
+        listExistingVmMacAddress.add(vmMacAddress);
+        logger.trace("Updating availableVMCache for tunnelIpElanName {} value {}", tunnelIpElanName,
+                listExistingVmMacAddress);
+        availableVMCache.put(tunnelIpElanName, listExistingVmMacAddress);
     }
 
     public void handleDesignatedDpnDown(BigInteger dpnId, List<BigInteger> listOfDpns) {
@@ -688,15 +701,52 @@ public class DhcpExternalTunnelManager {
     public void unInstallDhcpFlowsForVms(String elanInstanceName, IpAddress tunnelIp, List<BigInteger> dpns) {
         Pair<IpAddress, String> tunnelIpElanNamePair = new ImmutablePair<>(tunnelIp, elanInstanceName);
         Set<String> vmMacs = tunnelIpElanNameToVmMacCache.get(tunnelIpElanNamePair);
-        logger.trace("In unInstallFlowsForVms elanInstanceName {}, tunnelIp {}, dpns {}, vmMacs {}", elanInstanceName, tunnelIp, dpns, vmMacs);
+        logger.trace("In unInstallFlowsForVms elanInstanceName {}, tunnelIp {}, dpns {}, vmMacs {}",
+                elanInstanceName, tunnelIp, dpns, vmMacs);
         if (vmMacs == null) {
             return;
         }
         for (String vmMacAddress : vmMacs) {
-            for (BigInteger dpn : dpns) {
-                unInstallDhcpEntries(dpn, vmMacAddress, entityOwnershipService);
-            }
+            unInstallDhcpEntriesOnDpns(dpns, vmMacAddress);
         }
         tunnelIpElanNameToVmMacCache.remove(tunnelIpElanNamePair);
     }
+
+    public void removeFromAvailableCache(Pair<IpAddress, String> tunnelIpElanName) {
+        availableVMCache.remove(tunnelIpElanName);
+    }
+
+    private void unInstallDhcpEntriesOnDpns(List<BigInteger> dpns, String vmMacAddress) {
+        for (BigInteger dpn : dpns) {
+            unInstallDhcpEntries(dpn, vmMacAddress, entityOwnershipService);
+        }
+    }
+
+    public IpAddress getTunnelIpBasedOnElan(String elanInstanceName, String vmMacAddress) {
+        if (logger.isTraceEnabled()) {
+            logger.trace("DhcpExternalTunnelManager getTunnelIpBasedOnElan elanInstanceName " + elanInstanceName);
+        }
+        IpAddress tunnelIp = null;
+        Set<Pair<IpAddress, String>> tunnelElanKeySet = availableVMCache.keySet();
+        Set<String> listExistingVmMacAddress;
+        for (Pair<IpAddress, String> pair : tunnelElanKeySet) {
+            if (logger.isTraceEnabled()) {
+                logger.trace("DhcpExternalTunnelManager getTunnelIpBasedOnElan left  " + pair.getLeft() + " right:" +
+                        pair.getRight());
+            }
+            if (pair.getRight().trim().equalsIgnoreCase(elanInstanceName.trim())) {
+                listExistingVmMacAddress = availableVMCache.get(pair);
+                if (listExistingVmMacAddress != null && !listExistingVmMacAddress.isEmpty() &&
+                        listExistingVmMacAddress.contains(vmMacAddress)) {
+                    tunnelIp = pair.getLeft();
+                    break;
+                }
+            }
+        }
+        if (logger.isTraceEnabled()) {
+            logger.trace("DhcpExternalTunnelManager getTunnelIpBasedOnElan returned tunnelIP " + tunnelIp);
+        }
+        return tunnelIp;
+    }
+
 }
index 05c1c5990f363670f23e355511bc6193d8366915..bcd4ea9c1ea453d1a475f30b18a8ccae569bd80a 100644 (file)
@@ -30,6 +30,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpserv
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710._interface.name.mac.addresses.InterfaceNameMacAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710._interface.name.mac.addresses.InterfaceNameMacAddressBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710._interface.name.mac.addresses.InterfaceNameMacAddressKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -185,8 +186,14 @@ public class DhcpInterfaceEventListener extends AbstractDataChangeListener<Inter
             }
         }
         if (!dpId.equals(DHCPMConstants.INVALID_DPID)) {
-            installDhcpEntries(interfaceName, dpId);
-            dhcpManager.updateInterfaceCache(interfaceName, new ImmutablePair<>(dpId, add.getPhysAddress().getValue()));
+            Port port = dhcpManager.getNeutronPort(interfaceName);
+            Subnet subnet = dhcpManager.getNeutronSubnet(port);
+            if (null != subnet && subnet.isEnableDhcp()) {
+                logger.info("DhcpInterfaceEventListener add isEnableDhcp" + subnet.isEnableDhcp());
+                installDhcpEntries(interfaceName, dpId);
+                dhcpManager.updateInterfaceCache(interfaceName, new ImmutablePair<>(dpId,
+                                                    add.getPhysAddress().getValue()));
+            }
         }
     }
 
index 5143eaeb6d7e411747797d0f489d19212d5a6ae0..c60c5e9edbbad5b635efef722e3fab6bf3e63f46 100644 (file)
@@ -45,6 +45,7 @@ public class DhcpProvider implements BindingAwareProvider, AutoCloseable {
     private DhcpDesignatedDpnListener dhcpDesignatedDpnListener;
     private DhcpL2GatewayConnectionListener dhcpL2GatewayConnectionListener;
     private boolean controllerDhcpEnabled = true;
+    private DhcpSubnetListener dhcpSubnetListener;
 
     @Override
     public void onSessionInitiated(ProviderContext session) {
@@ -63,7 +64,7 @@ public class DhcpProvider implements BindingAwareProvider, AutoCloseable {
             dhcpNodeListener = new NodeListener(dataBroker, dhcpManager, dhcpExternalTunnelManager);
             dhcpConfigListener = new DhcpConfigListener(dataBroker, dhcpManager);
             dhcpLogicalSwitchListener = new DhcpLogicalSwitchListener(dhcpExternalTunnelManager, dataBroker);
-            dhcpUCastMacListener = new DhcpUCastMacListener(dhcpExternalTunnelManager, dataBroker);
+            dhcpUCastMacListener = new DhcpUCastMacListener(dhcpManager,dhcpExternalTunnelManager, dataBroker);
             dhcpUCastMacListener.registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
             dhcpNeutronPortListener = new DhcpNeutronPortListener(dataBroker, dhcpExternalTunnelManager);
             dhcpNeutronPortListener.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
@@ -76,6 +77,8 @@ public class DhcpProvider implements BindingAwareProvider, AutoCloseable {
                 dhcpInterfaceEventListener = new DhcpInterfaceEventListener(dhcpManager, dataBroker, dhcpExternalTunnelManager);
                 dhcpInterfaceConfigListener = new DhcpInterfaceConfigListener(dataBroker, dhcpExternalTunnelManager);
             }
+            dhcpSubnetListener = new DhcpSubnetListener(dhcpManager,dhcpExternalTunnelManager,dataBroker);
+            dhcpSubnetListener.registerListener(LogicalDatastoreType.CONFIGURATION,dataBroker);
 
         } catch (Exception e) {
             LOG.error("Error initializing services {}", e);
diff --git a/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpSubnetListener.java b/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpSubnetListener.java
new file mode 100644 (file)
index 0000000..6c2769d
--- /dev/null
@@ -0,0 +1,276 @@
+/*
+ * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.netvirt.dhcpservice;
+
+import com.google.common.base.Optional;
+import org.opendaylight.controller.md.sal.binding.api.ClusteredDataChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.genius.datastoreutils.AsyncClusteredDataChangeListenerBase;
+import org.opendaylight.genius.mdsalutil.MDSALUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
+
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+import java.util.Iterator;
+import java.util.List;
+
+
+public class DhcpSubnetListener extends AsyncClusteredDataChangeListenerBase<Subnet, DhcpSubnetListener>
+        implements AutoCloseable {
+    private DataBroker dataBroker;
+    private DhcpManager dhcpManager;
+    private DhcpExternalTunnelManager dhcpExternalTunnelManager;
+    private static final Logger LOG = LoggerFactory.getLogger(DhcpSubnetListener.class);
+
+    public DhcpSubnetListener(final DhcpManager dhcpManager, final DhcpExternalTunnelManager
+            dhcpExternalTunnelManager, final DataBroker
+                                      broker) {
+        super(Subnet.class, DhcpSubnetListener.class);
+        this.dhcpManager = dhcpManager;
+        this.dataBroker = broker;
+        this.dhcpExternalTunnelManager = dhcpExternalTunnelManager;
+    }
+
+    @Override
+    protected void add(InstanceIdentifier<Subnet> identifier, Subnet add) {
+
+    }
+
+    @Override
+    protected void remove(InstanceIdentifier<Subnet> identifier, Subnet del) {
+
+    }
+
+    @Override
+    public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changeEvent) {
+        super.onDataChanged(changeEvent);
+    }
+
+    @Override
+    protected InstanceIdentifier<Subnet> getWildCardPath() {
+        return InstanceIdentifier.create(Neutron.class).child(Subnets.class).child(Subnet.class);
+    }
+
+    @Override
+    protected AsyncDataBroker.DataChangeScope getDataChangeScope() {
+        return AsyncDataBroker.DataChangeScope.SUBTREE;
+    }
+
+    @Override
+    protected ClusteredDataChangeListener getDataChangeListener() {
+        return DhcpSubnetListener.this;
+    }
+
+    @Override
+    protected void update(InstanceIdentifier<Subnet> identifier, Subnet original, Subnet update) {
+        if (LOG.isTraceEnabled()) {
+            LOG.trace("DhcpSubnetListener Update : Original dhcpstatus: " + original.isEnableDhcp() + ", " +
+                    "Updated dhcpstatus" + update.isEnableDhcp());
+        }
+
+        if (original.isEnableDhcp() != update.isEnableDhcp()) {
+            // write api to get port list
+            SubnetmapBuilder subnetmapBuilder = getSubnetMapBuilder(dataBroker, update.getUuid());
+            List<Uuid> portList = subnetmapBuilder.getPortList();
+            List<Uuid> directPortList = subnetmapBuilder.getDirectPortList();
+
+            if (update.isEnableDhcp()) {
+                if (null != portList) {
+                    //Install Entries for neutron ports
+                    installNeutronPortEntries(portList);
+                }
+                if (null != directPortList) {
+                    //install Entries for direct ports
+                    installDirectPortEntries(directPortList);
+                }
+            } else {
+                if (null != portList) {
+                    //UnInstall Entries for neutron ports
+                    uninstallNeutronPortEntries(portList);
+                }
+                if (null != directPortList) {
+                    //Uninstall Entries for direct ports
+                    uninstallDirectPortEntries(directPortList);
+                }
+            }
+        }
+    }
+
+    private void installNeutronPortEntries(List<Uuid> portList) {
+        if (LOG.isTraceEnabled()) {
+            LOG.trace("DhcpSubnetListener installNeutronPortEntries : portList: " + portList);
+        }
+        Uuid portIntf;
+        for (Iterator<Uuid> portIter = portList.iterator(); portIter.hasNext(); ) {
+            portIntf = portIter.next();
+            NodeConnectorId nodeConnectorId = getNodeConnectorIdForPortIntf(portIntf);
+            BigInteger dpId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId));
+            Port port = dhcpManager.getNeutronPort(portIntf.getValue());
+            String vmMacAddress = port.getMacAddress().getValue();
+            //check whether any changes have happened
+            if (LOG.isTraceEnabled()) {
+                LOG.trace("DhcpSubnetListener installNeutronPortEntries dpId: " + dpId + "vmMacAddress :" +
+                        vmMacAddress);
+            }
+            //install the entriesd
+            dhcpManager.installDhcpEntries(dpId, vmMacAddress);
+        }
+    }
+
+    private void uninstallNeutronPortEntries(List<Uuid> portList) {
+        if (LOG.isTraceEnabled()) {
+            LOG.trace("DhcpSubnetListener uninstallNeutronPortEntries : portList: " + portList);
+        }
+        Uuid portIntf;
+        for (Iterator<Uuid> portIter = portList.iterator(); portIter.hasNext(); ) {
+            portIntf = portIter.next();
+            NodeConnectorId nodeConnectorId = getNodeConnectorIdForPortIntf(portIntf);
+            BigInteger dpId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId));
+            Port port = dhcpManager.getNeutronPort(portIntf.getValue());
+            String vmMacAddress = port.getMacAddress().getValue();
+            //check whether any changes have happened
+            if (LOG.isTraceEnabled()) {
+                LOG.trace("DhcpSubnetListener uninstallNeutronPortEntries dpId: " + dpId + "vmMacAddress :" +
+                        vmMacAddress);
+            }
+            //install the entries
+            dhcpManager.unInstallDhcpEntries(dpId, vmMacAddress);
+        }
+    }
+
+    private void installDirectPortEntries(List<Uuid> directPortList) {
+        if (LOG.isTraceEnabled()) {
+            LOG.trace("DhcpSubnetListener installDirectPortEntries : directPortList: " + directPortList);
+        }
+        Uuid portIntf;
+        for (Iterator<Uuid> directPortIter = directPortList.iterator(); directPortIter.hasNext(); ) {
+            portIntf = directPortIter.next();
+            Port port = dhcpManager.getNeutronPort(portIntf.getValue());
+            String vmMacAddress = port.getMacAddress().getValue();
+            Uuid networkId = port.getNetworkId();
+            //install the entries on designated dpnId
+            List<BigInteger> listOfDpns = DhcpServiceUtils.getListOfDpns(dataBroker);
+            IpAddress tunnelIp = dhcpExternalTunnelManager.getTunnelIpBasedOnElan(networkId.getValue(), vmMacAddress);
+            if (null == tunnelIp) {
+                LOG.warn("DhcpSubnetListener installDirectPortEntries tunnelIP is null for  port {}", portIntf);
+                continue;
+            }
+            BigInteger designatedDpnId = dhcpExternalTunnelManager.readDesignatedSwitchesForExternalTunnel
+                    (tunnelIp, networkId.getValue());
+            if (LOG.isTraceEnabled()) {
+                LOG.trace("CR-DHCP DhcpSubnetListener update Install DIRECT vmMacAddress:" + vmMacAddress + "  " +
+                        " tunnelIp: " + tunnelIp + " designatedDpnId :" + designatedDpnId + " ListOf Dpn:" +
+                        listOfDpns.toString());
+            }
+            dhcpExternalTunnelManager.installDhcpFlowsForVms(tunnelIp, networkId.getValue(), listOfDpns,
+                    designatedDpnId, vmMacAddress);
+
+        }
+    }
+
+    private void uninstallDirectPortEntries(List<Uuid> directPortList) {
+        if (LOG.isTraceEnabled()) {
+            LOG.trace("DhcpSubnetListener uninstallDirectPortEntries : directPortList: " + directPortList);
+        }
+        Uuid portIntf;
+        for (Iterator<Uuid> directPortIter = directPortList.iterator(); directPortIter.hasNext(); ) {
+            portIntf = directPortIter.next();
+            Port port = dhcpManager.getNeutronPort(portIntf.getValue());
+            String vmMacAddress = port.getMacAddress().getValue();
+            Uuid networkId = port.getNetworkId();
+            List<BigInteger> listOfDpns = DhcpServiceUtils.getListOfDpns(dataBroker);
+            if (LOG.isTraceEnabled()) {
+                LOG.trace("DhcpSubnetListener uninstallDirectPortEntries  vmMacAddress:" + vmMacAddress + "  " +
+                        "networkId: " + networkId + " ListOf Dpn:" + listOfDpns.toString());
+            }
+            dhcpExternalTunnelManager.unInstallDhcpFlowsForVms(networkId.getValue(), listOfDpns, vmMacAddress);
+        }
+    }
+
+
+    private NodeConnectorId getNodeConnectorIdForPortIntf(Uuid interfaceName) {
+        if (LOG.isTraceEnabled()) {
+            LOG.trace("DhcpSubnetListener getNodeConnectorIdForPortIntf  interfaceName: " + interfaceName);
+        }
+        NodeConnectorId nodeConnectorId = null;
+        InstanceIdentifier.InstanceIdentifierBuilder<Interface> idBuilder =
+                InstanceIdentifier.builder(InterfacesState.class)
+                        .child(Interface.class,
+                                new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces
+                                        .rev140508.interfaces.state.InterfaceKey(interfaceName.getValue()));
+
+        InstanceIdentifier<Interface> ifStateId = idBuilder.build();
+
+        Optional<Interface> ifStateOptional = MDSALUtil.read(LogicalDatastoreType.OPERATIONAL, ifStateId, dataBroker);
+        Interface interfaceState = null;
+        if (ifStateOptional.isPresent()) {
+            interfaceState = ifStateOptional.get();
+        }
+        if (interfaceState != null) {
+            List<String> ofportIds = interfaceState.getLowerLayerIf();
+            nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
+        }
+        if (LOG.isTraceEnabled()) {
+            LOG.trace("DhcpSubnetListener getNodeConnectorIdForPortIntf returned nodeConnectorId :" + nodeConnectorId
+                    .getValue() +
+                    "for the interface :" + interfaceName);
+        }
+        return nodeConnectorId;
+    }
+
+    private SubnetmapBuilder getSubnetMapBuilder(DataBroker broker, Uuid subnetId){
+        SubnetmapBuilder builder = null ;
+        InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).
+                child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
+        try {
+            ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
+
+            Optional<Subnetmap> sn ;
+            try {
+                sn = tx.read(LogicalDatastoreType.CONFIGURATION, id).get();
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+
+            if (sn.isPresent()) {
+                builder = new SubnetmapBuilder(sn.get());
+            } else {
+                builder = new SubnetmapBuilder().setKey(new SubnetmapKey(subnetId)).setId(subnetId);
+            }
+        } catch (Exception e) {
+            LOG.error("Updation of subnetMap failed for node: {}", subnetId.getValue());
+        }
+        return builder;
+    }
+
+    @Override
+    public void close() throws Exception {
+
+    }
+}
index 7284cf0fbc376facbff4a46fc0043f978613a91f..d67649eb57e8b588fde24aa9c0851a5e6be0e6bf 100644 (file)
@@ -9,6 +9,9 @@ package org.opendaylight.netvirt.dhcpservice;
 
 import java.math.BigInteger;
 
+import com.google.common.base.Optional;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
 import org.opendaylight.controller.md.sal.binding.api.ClusteredDataChangeListener;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
@@ -28,6 +31,7 @@ import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
@@ -41,11 +45,13 @@ public class DhcpUCastMacListener extends AsyncClusteredDataChangeListenerBase<L
     private DataBroker broker;
     private ListenerRegistration<DataChangeListener> listenerRegistration;
     private DhcpExternalTunnelManager dhcpExternalTunnelManager;
+    private DhcpManager dhcpManager;
 
-    public DhcpUCastMacListener(DhcpExternalTunnelManager dhcpManager, DataBroker dataBroker) {
+    public DhcpUCastMacListener(DhcpManager dhcpManager,DhcpExternalTunnelManager dhcpExtTunnelMgr, DataBroker dataBroker) {
         super(LocalUcastMacs.class, DhcpUCastMacListener.class);
         this.broker = dataBroker;
-        this.dhcpExternalTunnelManager = dhcpManager;
+        this.dhcpExternalTunnelManager = dhcpExtTunnelMgr;
+        this.dhcpManager = dhcpManager;
     }
 
     @Override
@@ -71,6 +77,22 @@ public class DhcpUCastMacListener extends AsyncClusteredDataChangeListenerBase<L
     protected void remove(InstanceIdentifier<LocalUcastMacs> identifier,
             LocalUcastMacs del) {
         // Flow removal for table 18 is handled in Neutron Port delete.
+        //remove the new CR-DHCP
+        NodeId torNodeId = identifier.firstKeyOf(Node.class).getNodeId();
+        LogicalSwitches logicalSwitch = getLogicalSwitches(del);
+        if (null == logicalSwitch) {
+            logger.error("DhcpUCastMacListener remove :Logical Switch ref doesn't have data {}", logicalSwitch);
+            return;
+        }
+        String elanInstanceName = logicalSwitch.getHwvtepNodeName().getValue();
+        L2GatewayDevice device = ElanL2GwCacheUtils.getL2GatewayDeviceFromCache(elanInstanceName, torNodeId.getValue());
+        if (device == null) {
+            logger.error("Logical Switch Device with name {} is not present in L2GWCONN cache", elanInstanceName);
+            return;
+        }
+        IpAddress tunnelIp = device.getTunnelIp();
+        Pair<IpAddress, String> tunnelIpElanName = new ImmutablePair<IpAddress, String>(tunnelIp, elanInstanceName);
+        dhcpExternalTunnelManager.removeFromAvailableCache(tunnelIpElanName);
     }
 
     @Override
@@ -105,6 +127,13 @@ public class DhcpUCastMacListener extends AsyncClusteredDataChangeListenerBase<L
             return;
         }
         IpAddress tunnelIp = device.getTunnelIp();
+        Subnet subnet = dhcpManager.getNeutronSubnet(port);
+        if (null != subnet && !subnet.isEnableDhcp()) {
+            dhcpExternalTunnelManager.updateExistingVMTunnelIPCache(tunnelIp, elanInstanceName, macAddress);
+            logger.warn("DhcpUCastMacListener add: flag for the subnetId "+subnet.getUuid()+ " is False so Table 18 " +
+                    "entries are not added" );
+            return;
+        }
         BigInteger designatedDpnId = dhcpExternalTunnelManager.readDesignatedSwitchesForExternalTunnel(tunnelIp, elanInstanceName);
         if (designatedDpnId == null || designatedDpnId.equals(DHCPMConstants.INVALID_DPID)) {
             logger.trace("Unable to install flows for macAddress {}. TunnelIp {}, elanInstanceName {}, designatedDpn {} ", macAddress, tunnelIp, elanInstanceName, designatedDpnId);
@@ -122,4 +151,16 @@ public class DhcpUCastMacListener extends AsyncClusteredDataChangeListenerBase<L
     protected DataChangeScope getDataChangeScope() {
         return DataChangeScope.SUBTREE;
     }
-}
\ No newline at end of file
+
+    private LogicalSwitches getLogicalSwitches(LocalUcastMacs ucastMacs) {
+        LogicalSwitches logicalSwitch = null;
+        InstanceIdentifier<LogicalSwitches> logicalSwitchRef = (InstanceIdentifier<LogicalSwitches>)
+                                                                ucastMacs.getLogicalSwitchRef().getValue();
+        Optional<LogicalSwitches> logicalSwitchOptional = MDSALUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
+                logicalSwitchRef);
+        if (logicalSwitchOptional.isPresent()) {
+            logicalSwitch = logicalSwitchOptional.get();
+        }
+        return logicalSwitch;
+    }
+}
index 322b54450d8eff96e79451e1bb2a54798f86a7e6..4fa87cd29437cc99150aba85da9e38c0808aab07 100644 (file)
@@ -32,25 +32,36 @@ import com.google.common.collect.Lists;
 import com.google.common.util.concurrent.ListenableFuture;
 
 public class ElanDpnInterfaceClusteredListener
-        extends AsyncClusteredDataChangeListenerBase<DpnInterfaces, ElanDpnInterfaceClusteredListener>
-        implements AutoCloseable {
-    private DataBroker broker;
-    private ElanInterfaceManager elanInterfaceManager;
+    extends AsyncClusteredDataChangeListenerBase<DpnInterfaces, ElanDpnInterfaceClusteredListener>
+    implements AutoCloseable {
+    private ElanServiceProvider elanServiceProvider = null;
+    private static volatile ElanDpnInterfaceClusteredListener elanDpnInterfaceClusteredListener = null;
     private ListenerRegistration<DataChangeListener> listenerRegistration;
 
     private static final Logger LOG = LoggerFactory.getLogger(ElanDpnInterfaceClusteredListener.class);
 
-    public ElanDpnInterfaceClusteredListener(final DataBroker db, final ElanInterfaceManager ifManager) {
+
+    public ElanDpnInterfaceClusteredListener(ElanServiceProvider elanServiceProvider) {
         super(DpnInterfaces.class, ElanDpnInterfaceClusteredListener.class);
-        broker = db;
-        elanInterfaceManager = ifManager;
-        registerListener(db);
+        this.elanServiceProvider = elanServiceProvider;
+        registerListener(elanServiceProvider.getBroker());
     }
 
+    public static ElanDpnInterfaceClusteredListener getElanDpnInterfaceClusteredListener(
+        ElanServiceProvider elanServiceProvider) {
+        if (elanDpnInterfaceClusteredListener == null) {
+            synchronized (ElanDpnInterfaceClusteredListener.class) {
+                if (elanDpnInterfaceClusteredListener == null) {
+                    elanDpnInterfaceClusteredListener = new ElanDpnInterfaceClusteredListener(elanServiceProvider);
+                }
+            }
+        }
+        return elanDpnInterfaceClusteredListener;
+    }
     private void registerListener(final DataBroker db) {
         try {
-            listenerRegistration = broker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
-                    getWildCardPath(), ElanDpnInterfaceClusteredListener.this, AsyncDataBroker.DataChangeScope.BASE);
+            listenerRegistration = elanServiceProvider.getBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+                getWildCardPath(), ElanDpnInterfaceClusteredListener.this, AsyncDataBroker.DataChangeScope.BASE);
         } catch (final Exception e) {
             LOG.error("DpnInterfaces DataChange listener registration fail!", e);
         }
@@ -59,7 +70,7 @@ public class ElanDpnInterfaceClusteredListener
     @Override
     public InstanceIdentifier<DpnInterfaces> getWildCardPath() {
         return InstanceIdentifier.builder(ElanDpnInterfaces.class).child(ElanDpnInterfacesList.class)
-                .child(DpnInterfaces.class).build();
+            .child(DpnInterfaces.class).build();
     }
 
     @Override
@@ -76,17 +87,17 @@ public class ElanDpnInterfaceClusteredListener
         final String elanName = getElanName(id);
         if (ElanL2GwCacheUtils.getInvolvedL2GwDevices(elanName).isEmpty()) {
             LOG.debug("dpnInterface updation, no external l2 devices to update for elan {} with Dp Id:", elanName,
-                    dpnInterfaces.getDpId());
+                dpnInterfaces.getDpId());
             return;
         }
         ElanClusterUtils.runOnlyInLeaderNode(elanName, "updating mcast mac upon tunnel event",
-                new Callable<List<ListenableFuture<Void>>>() {
-                    @Override
-                    public List<ListenableFuture<Void>> call() throws Exception {
-                        return Lists.newArrayList(
-                                ElanL2GatewayMulticastUtils.updateRemoteMcastMacOnElanL2GwDevices(elanName));
-                    }
-                });
+            new Callable<List<ListenableFuture<Void>>>() {
+                @Override
+                public List<ListenableFuture<Void>> call() throws Exception {
+                    return Lists.newArrayList(
+                        ElanL2GatewayMulticastUtils.updateRemoteMcastMacOnElanL2GwDevices(elanName));
+                }
+            });
     }
 
     @Override
@@ -94,30 +105,30 @@ public class ElanDpnInterfaceClusteredListener
         // this is the last dpn interface on this elan
         final String elanName = getElanName(identifier);
         LOG.debug("Received ElanDpnInterface removed for for elan {} with Dp Id ", elanName,
-                dpnInterfaces.getDpId());
+            dpnInterfaces.getDpId());
 
         if (ElanL2GwCacheUtils.getInvolvedL2GwDevices(elanName).isEmpty()) {
             LOG.debug("dpnInterface removed, no external l2 devices to update for elan {} with Dp Id:", elanName,
-                    dpnInterfaces.getDpId());
+                dpnInterfaces.getDpId());
             return;
         }
         ElanClusterUtils.runOnlyInLeaderNode(elanName, "handling ElanDpnInterface removed",
-                new Callable<List<ListenableFuture<Void>>>() {
-                    @Override
-                    public List<ListenableFuture<Void>> call() throws Exception {
-                        // deleting Elan L2Gw Devices UcastLocalMacs From Dpn
-                        ElanL2GatewayUtils.deleteElanL2GwDevicesUcastLocalMacsFromDpn(elanName,
-                                dpnInterfaces.getDpId());
-                        // updating remote mcast mac on l2gw devices
-                        return Lists.newArrayList(
-                                ElanL2GatewayMulticastUtils.updateRemoteMcastMacOnElanL2GwDevices(elanName));
-                    }
-                });
+            new Callable<List<ListenableFuture<Void>>>() {
+                @Override
+                public List<ListenableFuture<Void>> call() throws Exception {
+                    // deleting Elan L2Gw Devices UcastLocalMacs From Dpn
+                    ElanL2GatewayUtils.deleteElanL2GwDevicesUcastLocalMacsFromDpn(elanName,
+                        dpnInterfaces.getDpId());
+                    // updating remote mcast mac on l2gw devices
+                    return Lists.newArrayList(
+                        ElanL2GatewayMulticastUtils.updateRemoteMcastMacOnElanL2GwDevices(elanName));
+                }
+            });
     }
 
     @Override
     protected void update(InstanceIdentifier<DpnInterfaces> identifier, DpnInterfaces original,
-            final DpnInterfaces dpnInterfaces) {
+                          final DpnInterfaces dpnInterfaces) {
         LOG.debug("dpninterfaces update fired new size {}", dpnInterfaces.getInterfaces().size());
         if (dpnInterfaces.getInterfaces().size() == 0) {
             LOG.debug("dpninterfaces last dpn interface on this elan {} ", dpnInterfaces.getKey());
@@ -130,7 +141,7 @@ public class ElanDpnInterfaceClusteredListener
     protected void add(InstanceIdentifier<DpnInterfaces> identifier, final DpnInterfaces dpnInterfaces) {
         if (dpnInterfaces.getInterfaces().size() == 1) {
             LOG.debug("dpninterfaces first dpn interface on this elan {} {} ", dpnInterfaces.getKey(),
-                    dpnInterfaces.getInterfaces().get(0));
+                dpnInterfaces.getInterfaces().get(0));
             // this is the first dpn interface on this elan
             handleUpdate(identifier, dpnInterfaces);
         }
@@ -143,4 +154,5 @@ public class ElanDpnInterfaceClusteredListener
     private String getElanName(InstanceIdentifier<DpnInterfaces> identifier) {
         return identifier.firstKeyOf(ElanDpnInterfacesList.class).getElanInstanceName();
     }
+
 }
index fed87200a1ed4a0015686c81630f705a315bcca1..e8fa7952c8c4b9a9bbc0677f38489eacbd073593 100644 (file)
@@ -5,19 +5,18 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
+
 package org.opendaylight.netvirt.elan.internal;
 
-import com.google.common.base.Optional;
+import java.util.ArrayList;
+import java.util.List;
 
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
 import org.opendaylight.netvirt.elan.utils.ElanConstants;
 import org.opendaylight.netvirt.elan.utils.ElanUtils;
 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
-import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
-import org.opendaylight.genius.mdsalutil.AbstractDataChangeListener;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanDpnInterfaces;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesList;
@@ -27,72 +26,33 @@ 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.ElanInstanceKey;
 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.state.Elan;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.List;
-
-public class ElanInstanceManager extends AbstractDataChangeListener<ElanInstance> implements AutoCloseable {
-    private DataBroker broker;
-    private static ElanInstanceManager elanInstanceManager = new ElanInstanceManager();
-    private ListenerRegistration<DataChangeListener> elanInstanceListenerRegistration;
-    private IdManagerService idManager;
-    private ElanInterfaceManager elanInterfaceManager;
-    private IInterfaceManager interfaceManager;
-
-    private static final Logger logger = LoggerFactory.getLogger(ElanInstanceManager.class);
-
-    private ElanInstanceManager() {
-        super(ElanInstance.class);
-
-    }
-
-    public static ElanInstanceManager getElanInstanceManager() {
-        return elanInstanceManager;
-    }
-
-    public void setIdManager(IdManagerService idManager) {
-        this.idManager = idManager;
-    }
-
-    public void setDataBroker(DataBroker broker) {
-        this.broker = broker;
-    }
-
-    public void setElanInterfaceManager(ElanInterfaceManager elanInterfaceManager) {
-        this.elanInterfaceManager = elanInterfaceManager;
-    }
+import com.google.common.base.Optional;
 
-    public void setInterfaceManager(IInterfaceManager interfaceManager) {
-        this.interfaceManager = interfaceManager;
-    }
+public class ElanInstanceManager extends AsyncDataTreeChangeListenerBase<ElanInstance,ElanInstanceManager> implements AutoCloseable {
 
+    private  ElanServiceProvider elanServiceProvider = null;
+    private static volatile ElanInstanceManager elanInstanceManager = null;
 
-    /**
-     * Starts listening for changes in elan.yang:elan-instance container
-     */
-    public void registerListener() {
-        try {
-            elanInstanceListenerRegistration = broker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
-                    getElanInstanceWildcardPath(), ElanInstanceManager.this, DataChangeScope.SUBTREE);
-        } catch (final Exception e) {
-            logger.error("ELAN Instance DataChange listener registration failed !", e);
-            throw new IllegalStateException("ELAN Instance registration Listener failed.", e);
-        }
-    }
+    private static final Logger logger = LoggerFactory.getLogger(ElanInstanceManager.class);
 
-    private InstanceIdentifier<?> getElanInstanceWildcardPath() {
-        return InstanceIdentifier.create(ElanInstances.class).child(ElanInstance.class);
+    private ElanInstanceManager(ElanServiceProvider elanServiceProvider) {
+        super(ElanInstance.class,ElanInstanceManager.class);
+        this.elanServiceProvider = elanServiceProvider;
     }
 
-    @Override
-    public void close() throws Exception {
-        if (elanInstanceListenerRegistration != null) {
-            elanInstanceListenerRegistration.close();
+    public static ElanInstanceManager getElanInstanceManager(ElanServiceProvider elanServiceProvider) {
+        if (elanInstanceManager == null) {
+            synchronized (ElanInstanceManager.class) {
+                if (elanInstanceManager == null) {
+                    elanInstanceManager = new ElanInstanceManager(elanServiceProvider);
+                }
+            }
         }
+        return elanInstanceManager;
     }
 
     @Override
@@ -103,22 +63,22 @@ public class ElanInstanceManager extends AbstractDataChangeListener<ElanInstance
         Elan existingElan = ElanUtils.getElanByName(elanName);
         long elanTag = deletedElan.getElanTag();
         //Cleaning up the existing Elan Instance
-        if(existingElan != null) {
+        if (existingElan != null) {
             List<String> elanInterfaces =  existingElan.getElanInterfaces();
-            if(elanInterfaces != null && !elanInterfaces.isEmpty()) {
+            if (elanInterfaces != null && !elanInterfaces.isEmpty()) {
                 for (String elanInterfaceName : elanInterfaces) {
                     InstanceIdentifier<ElanInterface> elanInterfaceId = ElanUtils.getElanInterfaceConfigurationDataPathId(elanInterfaceName);
-                    InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(elanInterfaceName);
-                    elanInterfaceManager.removeElanInterface(deletedElan, elanInterfaceName, interfaceInfo);
-                    ElanUtils.delete(broker, LogicalDatastoreType.CONFIGURATION, elanInterfaceId);
+                    InterfaceInfo interfaceInfo = elanServiceProvider.getInterfaceManager().getInterfaceInfo(elanInterfaceName);
+                    elanServiceProvider.getElanInterfaceManager().removeElanInterface(deletedElan, elanInterfaceName, interfaceInfo, false);
+                    ElanUtils.delete(elanServiceProvider.getBroker(), LogicalDatastoreType.CONFIGURATION, elanInterfaceId);
                 }
             }
-            ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName));
-            ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, getElanDpnOperationDataPath(elanName));
-            ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInfoEntriesOperationalDataPath(elanTag));
+            ElanUtils.delete(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName));
+            ElanUtils.delete(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, getElanDpnOperationDataPath(elanName));
+            ElanUtils.delete(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInfoEntriesOperationalDataPath(elanTag));
         }
         // Release tag
-        ElanUtils.releaseId(idManager, ElanConstants.ELAN_ID_POOL_NAME, elanName);
+        ElanUtils.releaseId( elanServiceProvider.getIdManager(), ElanConstants.ELAN_ID_POOL_NAME, elanName);
 
     }
 
@@ -129,24 +89,30 @@ public class ElanInstanceManager extends AbstractDataChangeListener<ElanInstance
             return;
         } else if (update.getElanTag() == null) {
             // update the elan-Instance with new properties
-            ElanUtils.updateOperationalDataStore(broker, idManager, update);
+            WriteTransaction tx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
+            ElanUtils.updateOperationalDataStore(elanServiceProvider.getBroker(), elanServiceProvider.getIdManager(),
+                update, new ArrayList<String>(), tx);
+            ElanUtils.waitForTransactionToComplete(tx);
             return;
         }
-        elanInterfaceManager.handleunprocessedElanInterfaces(update);
+        elanServiceProvider.getElanInterfaceManager().handleunprocessedElanInterfaces(update);
     }
 
     @Override
     protected void add(InstanceIdentifier<ElanInstance> identifier, ElanInstance elanInstanceAdded) {
         Elan elanInfo = ElanUtils.getElanByName(elanInstanceAdded.getElanInstanceName());
-        if(elanInfo == null) {
-            ElanUtils.updateOperationalDataStore(broker, idManager, elanInstanceAdded);
+        if (elanInfo == null) {
+            WriteTransaction tx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
+            ElanUtils.updateOperationalDataStore(elanServiceProvider.getBroker(), elanServiceProvider.getIdManager(), elanInstanceAdded,
+                new ArrayList<String>(), tx);
+            ElanUtils.waitForTransactionToComplete(tx);
         }
     }
 
     public ElanInstance getElanInstanceByName(String elanInstanceName) {
         InstanceIdentifier<ElanInstance> elanIdentifierId = getElanInstanceConfigurationDataPath(elanInstanceName);
-        Optional<ElanInstance> elanInstance = ElanUtils.read(broker, LogicalDatastoreType.CONFIGURATION, elanIdentifierId);
-        if(elanInstance.isPresent()) {
+        Optional<ElanInstance> elanInstance = ElanUtils.read(elanServiceProvider.getBroker(), LogicalDatastoreType.CONFIGURATION, elanIdentifierId);
+        if (elanInstance.isPresent()) {
             return elanInstance.get();
         }
         return null;
@@ -154,8 +120,8 @@ public class ElanInstanceManager extends AbstractDataChangeListener<ElanInstance
 
     public List<DpnInterfaces> getElanDPNByName(String elanInstanceName) {
         InstanceIdentifier<ElanDpnInterfacesList> elanIdentifier = getElanDpnOperationDataPath(elanInstanceName);
-        Optional<ElanDpnInterfacesList> elanInstance = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanIdentifier);
-        if(elanInstance.isPresent()) {
+        Optional<ElanDpnInterfacesList> elanInstance = ElanUtils.read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, elanIdentifier);
+        if (elanInstance.isPresent()) {
             ElanDpnInterfacesList elanDPNs =  elanInstance.get();
             return elanDPNs.getDpnInterfaces();
         }
@@ -169,4 +135,15 @@ public class ElanInstanceManager extends AbstractDataChangeListener<ElanInstance
     private InstanceIdentifier<ElanInstance> getElanInstanceConfigurationDataPath(String elanInstanceName) {
         return InstanceIdentifier.builder(ElanInstances.class).child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
     }
+
+    @Override
+    protected InstanceIdentifier<ElanInstance> getWildCardPath() {
+        return InstanceIdentifier.create(ElanInstances.class).child(ElanInstance.class);
+    }
+
+    @Override
+    protected ElanInstanceManager getDataTreeChangeListener() {
+        return this;
+    }
+
 }
index 54ce3fb316660c059295bae10616999c4b04dde4..e8824a112e89b67c7fcfc2bf84e1460f515e1847 100644 (file)
@@ -19,21 +19,16 @@ import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.ConcurrentMap;
 
 import org.apache.commons.lang3.StringUtils;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.netvirt.elan.utils.ElanConstants;
-import org.opendaylight.netvirt.elan.utils.ElanUtils;
-import org.opendaylight.netvirt.elan.l2gw.utils.ElanL2GatewayUtils;
 import org.opendaylight.netvirt.elanmanager.utils.ElanL2GwCacheUtils;
-import org.opendaylight.netvirt.neutronvpn.api.l2gw.L2GatewayDevice;
+import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.netvirt.elan.l2gw.utils.ElanL2GatewayUtils;
+import org.opendaylight.netvirt.elan.utils.ElanConstants;
+import org.opendaylight.netvirt.elan.utils.ElanUtils;
 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
-import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo.InterfaceType;
-import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
 import org.opendaylight.genius.itm.globals.ITMConstants;
-import org.opendaylight.genius.mdsalutil.AbstractDataChangeListener;
 import org.opendaylight.genius.mdsalutil.ActionInfo;
 import org.opendaylight.genius.mdsalutil.ActionType;
 import org.opendaylight.genius.mdsalutil.FlowEntity;
@@ -44,7 +39,8 @@ import org.opendaylight.genius.mdsalutil.MatchFieldType;
 import org.opendaylight.genius.mdsalutil.MatchInfo;
 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
 import org.opendaylight.genius.mdsalutil.NwConstants;
-import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
+//import org.opendaylight.genius.neutronvpn.api.l2gw.L2GatewayDevice;
+import org.opendaylight.netvirt.neutronvpn.api.l2gw.L2GatewayDevice;
 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;
@@ -55,6 +51,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instru
 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.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.netvirt.elan.rev150602.ElanDpnInterfaces;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanForwardingTables;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInterfaces;
@@ -76,12 +74,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntryBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntryKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
-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.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -95,189 +89,183 @@ import com.google.common.base.Preconditions;
  * @see org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface
  *
  */
-public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterface> implements AutoCloseable {
-
-    private static ElanInterfaceManager elanInterfaceManager = new ElanInterfaceManager();
-    private ListenerRegistration<DataChangeListener> elanInterfaceListenerRegistration;
-    private ListenerRegistration<DataChangeListener> itmInterfaceListenerRegistration;
-    private OdlInterfaceRpcService interfaceManagerRpcService;
-    private DataBroker broker;
-    private IMdsalApiManager mdsalManager;
-    private IInterfaceManager interfaceManager;
-    private IdManagerService idManager;
-
-    private ElanForwardingEntriesHandler elanForwardingEntriesHandler;
-    private Map<String, ConcurrentLinkedQueue<ElanInterface>> unProcessedElanInterfaces =
-            new ConcurrentHashMap<>();
-
-    private static final Logger logger = LoggerFactory.getLogger(ElanInterfaceManager.class);
-
-    public ElanInterfaceManager() {
-        super(ElanInterface.class);
-    }
+@SuppressWarnings( "deprecation" )
+public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanInterface,ElanInterfaceManager> implements AutoCloseable {
 
-    public static ElanInterfaceManager getElanInterfaceManager() {
-        return elanInterfaceManager;
-    }
-
-    public void setMdSalApiManager(IMdsalApiManager mdsalManager) {
-        this.mdsalManager = mdsalManager;
-    }
+    private ElanServiceProvider elanServiceProvider = null;
+    private static volatile ElanInterfaceManager elanInterfaceManager = null;
+    private static long waitTimeForSyncInstall;
 
-    public void setInterfaceManagerRpcService(OdlInterfaceRpcService ifManager) {
-        this.interfaceManagerRpcService = ifManager;
-    }
-
-    public void setElanForwardingEntriesHandler(ElanForwardingEntriesHandler elanForwardingEntriesHandler) {
-        this.elanForwardingEntriesHandler = elanForwardingEntriesHandler;
-    }
+    private Map<String, ConcurrentLinkedQueue<ElanInterface>> unProcessedElanInterfaces =
+        new ConcurrentHashMap<String, ConcurrentLinkedQueue<ElanInterface>> ();
 
-    public void setInterfaceManager(IInterfaceManager interfaceManager) {
-        this.interfaceManager = interfaceManager;
-    }
+    private static final Logger logger = LoggerFactory.getLogger(ElanInterfaceManager.class);
 
-    public void setDataBroker(DataBroker broker) {
-        this.broker = broker;
+    public ElanInterfaceManager(ElanServiceProvider elanServiceProvider) {
+        super(ElanInterface.class,ElanInterfaceManager.class);
+        this.elanServiceProvider = elanServiceProvider;
     }
 
-    @Override
-    public void close() throws Exception {
-        if (elanInterfaceListenerRegistration != null) {
-            try {
-                elanInterfaceListenerRegistration.close();
-            } catch (final Exception e) {
-                logger.error("Error when cleaning up DataChangeListener.", e);
+    public static ElanInterfaceManager getElanInterfaceManager(ElanServiceProvider elanServiceProvider) {
+        if (elanInterfaceManager == null) {
+            synchronized (ElanInterfaceManager.class) {
+                if (elanInterfaceManager == null) {
+                    elanInterfaceManager = new ElanInterfaceManager(elanServiceProvider);
+                    Long waitTime = Long.getLong("wait.time.sync.install");
+                    if (waitTime == null) {
+                        waitTime = 300L;
+                    }
+                    waitTimeForSyncInstall = waitTime;
+                }
             }
-            elanInterfaceListenerRegistration = null;
-        }
-    }
-
-    public void registerListener() {
-        try {
-            elanInterfaceListenerRegistration = broker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
-                    getElanInterfaceWildcardPath(), ElanInterfaceManager.this, DataChangeScope.SUBTREE);
-        } catch (final Exception e) {
-            logger.error("ELAN Interface DataChange listener registration failed !", e);
-            throw new IllegalStateException("ELAN Interface registration Listener failed.", e);
         }
+        return elanInterfaceManager;
     }
 
-    private InstanceIdentifier<?> getElanInterfaceWildcardPath() {
+    protected InstanceIdentifier<ElanInterface> getWildCardPath() {
         return InstanceIdentifier.create(ElanInterfaces.class).child(ElanInterface.class);
     }
 
-    public void setIdManager(IdManagerService idManager) {
-        this.idManager = idManager;
-    }
-
     @Override
     protected void remove(InstanceIdentifier<ElanInterface> identifier, ElanInterface del) {
         String interfaceName =  del.getName();
         ElanInstance elanInfo = ElanUtils.getElanInstanceByName(del.getElanInstanceName());
-        InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
+        /*
+         * Handling in case the elan instance is deleted.If the Elan instance is deleted, there is no need to explicitly delete the elan interfaces
+         */
+        if (elanInfo == null) {
+            return;
+        }
+        InterfaceInfo interfaceInfo = elanServiceProvider.getInterfaceManager().getInterfaceInfo(interfaceName);
         String elanInstanceName = elanInfo.getElanInstanceName();
         DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
-        ElanInterfaceRemoveWorker configWorker = new ElanInterfaceRemoveWorker(elanInstanceName, elanInfo, interfaceName, interfaceInfo, this);
+        InterfaceRemoveWorkerOnElan configWorker = new InterfaceRemoveWorkerOnElan(elanInstanceName, elanInfo, interfaceName, interfaceInfo, false, this);
         coordinator.enqueueJob(elanInstanceName, configWorker, ElanConstants.JOB_MAX_RETRIES);
     }
 
-    public void removeElanInterface(ElanInstance elanInfo, String interfaceName, InterfaceInfo interfaceInfo) {
+    public void removeElanInterface(ElanInstance elanInfo, String interfaceName, InterfaceInfo interfaceInfo, boolean isInterfaceStateRemoved) {
         String elanName = elanInfo.getElanInstanceName();
-        if (interfaceInfo == null) {
-            // Interface does not exist in ConfigDS, so lets remove everything about that interface related to Elan
-            ElanInterfaceMac elanInterfaceMac =  ElanUtils.getElanInterfaceMacByInterfaceName(interfaceName);
-            if(elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
-               List<MacEntry> macEntries = elanInterfaceMac.getMacEntry();
-                for(MacEntry macEntry : macEntries) {
-                    ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getMacEntryOperationalDataPath(elanName, macEntry.getMacAddress()));
+        boolean isLastElanInterface = false;
+        long elanTag = elanInfo.getElanTag();
+        WriteTransaction tx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
+        WriteTransaction deleteFlowGroupTx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
+        Elan elanState = removeElanStateForInterface(elanInfo, interfaceName, tx);
+        if (elanState == null) {
+            return;
+        }
+        List<String> elanInterfaces = elanState.getElanInterfaces();
+        if (elanInterfaces.size() == 0) {
+            isLastElanInterface = true;
+        }
+        if (interfaceInfo != null) {
+            BigInteger dpId = interfaceInfo.getDpId();
+            DpnInterfaces dpnInterfaces = removeElanDpnInterfaceFromOperationalDataStore(elanName, dpId, interfaceName, elanTag, tx);
+            /*
+             * If there are not elan ports, remove the unknown dmac, terminating service table
+             * flows, remote/local bc group
+             */
+            if (dpnInterfaces == null || dpnInterfaces.getInterfaces() == null || dpnInterfaces.getInterfaces().isEmpty()) {
+                // No more Elan Interfaces in this DPN
+                logger.debug("deleting the elan: {} present on dpId: {}", elanInfo.getElanInstanceName(), dpId);
+                removeDefaultTermFlow(dpId, elanInfo.getElanTag());
+                removeUnknownDmacFlow(dpId, elanInfo, deleteFlowGroupTx);
+                removeElanBroadcastGroup(elanInfo, interfaceInfo, deleteFlowGroupTx);
+                removeLocalBroadcastGroup(elanInfo, interfaceInfo, deleteFlowGroupTx);
+                if ( elanInfo.getVni() != null && elanInfo.getVni().longValue() != 0 ) {
+                    unsetExternalTunnelTable(dpId, elanInfo);
                 }
-            }
-            ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName));
-            Elan elanState = ElanUtils.getElanByName(elanName);
-            List<String> elanInterfaces = elanState.getElanInterfaces();
-            elanInterfaces.remove(interfaceName);
-            if(elanInterfaces.isEmpty()) {
-                ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName));
-                ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanMacTableOperationalDataPath(elanName));
-                ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInfoEntriesOperationalDataPath(elanInfo.getElanTag()));
             } else {
-                Elan updateElanState = new ElanBuilder().setElanInterfaces(elanInterfaces).setName(elanName).setKey(new ElanKey(elanName)).build();
-                MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName), updateElanState);
+                setupLocalBroadcastGroups(elanInfo, dpnInterfaces, interfaceInfo);
             }
+        }
+        ElanUtils.waitForTransactionToComplete(tx);
+        deleteFlowGroupTx.submit();
+        DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+        InterfaceRemoveWorkerOnElanInterface removeInterfaceWorker = new InterfaceRemoveWorkerOnElanInterface(interfaceName, elanInfo,
+            interfaceInfo, isInterfaceStateRemoved, this, isLastElanInterface);
+        coordinator.enqueueJob(interfaceName, removeInterfaceWorker, ElanConstants.JOB_MAX_RETRIES);
+    }
+
+    private Elan removeElanStateForInterface(ElanInstance elanInfo, String interfaceName, WriteTransaction tx) {
+        String elanName = elanInfo.getElanInstanceName();
+        Elan elanState = ElanUtils.getElanByName(elanName);
+        if(elanState == null) {
+            return elanState;
+        }
+        List<String> elanInterfaces = elanState.getElanInterfaces();
+        elanInterfaces.remove(interfaceName);
+        if(elanInterfaces.isEmpty()) {
+            tx.delete(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName));
+            tx.delete(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanMacTableOperationalDataPath(elanName));
+            tx.delete(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInfoEntriesOperationalDataPath(elanInfo.getElanTag()));
         } else {
-            removeElanInterface(elanInfo, interfaceInfo);
-            unbindService(elanInfo, interfaceName);
+            Elan updateElanState = new ElanBuilder().setElanInterfaces(elanInterfaces).setName(elanName).setKey(new ElanKey(elanName)).build();
+            tx.put(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName), updateElanState);
         }
+        return elanState;
     }
 
-    private void removeElanInterface(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
+    private void deleteElanInterfaceFromConfigDS(String interfaceName, WriteTransaction tx) {
+        //removing the ElanInterface from the config data_store if interface is not present in Interface config DS
+        if (elanServiceProvider.getInterfaceManager().getInterfaceInfoFromConfigDataStore(interfaceName) == null) {
+            tx.delete(LogicalDatastoreType.CONFIGURATION, ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName));
+        }
+    }
 
-        BigInteger dpId = interfaceInfo.getDpId();
+    void removeEntriesForElanInterface(ElanInstance elanInfo, InterfaceInfo interfaceInfo, String interfaceName, boolean isInterfaceStateRemoved, boolean isLastElanInterface) {
         String elanName = elanInfo.getElanInstanceName();
-        long elanTag = elanInfo.getElanTag();
-        String interfaceName = interfaceInfo.getInterfaceName();
-        Elan elanState = ElanUtils.getElanByName(elanName);
-        logger.debug("Removing the Interface:{} from elan:{}", interfaceName, elanName);
+        WriteTransaction tx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
+        WriteTransaction deleteFlowGroupTx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
         InstanceIdentifier<ElanInterfaceMac> elanInterfaceId = ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName);
-        Optional<ElanInterfaceMac> existingElanInterface = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanInterfaceId);
-        if(existingElanInterface.isPresent()) {
-            List<PhysAddress> macAddresses = new ArrayList<>();
-            List<MacEntry> existingMacEntries = existingElanInterface.get().getMacEntry();
-            List<MacEntry> macEntries = new ArrayList<>();
-            if (existingMacEntries != null && !existingMacEntries.isEmpty()) {
-                macEntries.addAll(existingMacEntries);
-            }
-            if(!macEntries.isEmpty()) {
-                for (MacEntry macEntry : macEntries) {
-                    logger.debug("removing the  mac-entry:{} present on elanInterface:{}", macEntry.getMacAddress().getValue(), interfaceName);
-                    elanForwardingEntriesHandler.deleteElanInterfaceForwardingEntries(elanInfo, interfaceInfo, macEntry);
-                    macAddresses.add(macEntry.getMacAddress());
+        logger.debug("Removing the Interface:{} from elan:{}", interfaceName, elanName);
+        if (interfaceInfo != null) {
+            Optional<ElanInterfaceMac> existingElanInterfaceMac = ElanUtils.read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, elanInterfaceId);
+            if(existingElanInterfaceMac.isPresent()) {
+                List<PhysAddress> macAddresses = new ArrayList<PhysAddress>();
+                List<MacEntry> existingMacEntries = existingElanInterfaceMac.get().getMacEntry();
+                List<MacEntry> macEntries = new ArrayList<>();
+                if (existingMacEntries != null && !existingMacEntries.isEmpty()) {
+                    macEntries.addAll(existingMacEntries);
                 }
+                if(!macEntries.isEmpty()) {
+                    for (MacEntry macEntry : macEntries) {
+                        logger.debug("removing the  mac-entry:{} present on elanInterface:{}", macEntry.getMacAddress().getValue(), interfaceName);
+                        if (!isLastElanInterface) {
+                            tx.delete(LogicalDatastoreType.OPERATIONAL, ElanUtils.getMacEntryOperationalDataPath(elanName, macEntry.getMacAddress()));
+                        }
+                        ElanUtils.deleteMacFlows(elanInfo, interfaceInfo, macEntry, deleteFlowGroupTx);
+                        macAddresses.add(macEntry.getMacAddress());
+                    }
 
-                // Removing all those MACs from External Devices belonging to this ELAN
-                if ( elanInfo.getVni() != null && elanInfo.getVni() != 0 ) {
-                    ElanL2GatewayUtils.removeMacsFromElanExternalDevices(elanInfo, macAddresses);
-                }
-            }
-        }
-        /*
-         *This condition check is mainly to get DPN-ID in pre-provision deletion scenario after stopping CSS
-         */
-        if(dpId.equals(ElanConstants.INVALID_DPN)) {
-            ElanDpnInterfacesList elanDpnInterfacesList = ElanUtils.getElanDpnInterfacesList(elanName);
-            if(elanDpnInterfacesList != null && !elanDpnInterfacesList.getDpnInterfaces().isEmpty()) {
-                List<DpnInterfaces> dpnIfList = elanDpnInterfacesList.getDpnInterfaces();
-                for (DpnInterfaces dpnInterface : dpnIfList) {
-                    DpnInterfaces dpnIfLists = ElanUtils.getElanInterfaceInfoByElanDpn(elanName, dpnInterface.getDpId());
-                    if (dpnIfLists.getInterfaces().contains(interfaceName)) {
-                        logger.debug("deleting the elanInterface from the ElanDpnInterface cache in pre-provision scenario of elan:{} dpn:{} interfaceName:{}", elanName, dpId, interfaceName);
-                        removeElanDpnInterfaceFromOperationalDataStore(elanName, dpId, interfaceName, elanTag);
-                        break;
+                    // Removing all those MACs from External Devices belonging to this ELAN
+                    if ( elanInfo.getVni() != null && elanInfo.getVni() != 0 ) {
+                        ElanL2GatewayUtils.removeMacsFromElanExternalDevices(elanInfo, macAddresses);
                     }
                 }
             }
+            removeDefaultTermFlow(interfaceInfo.getDpId(), interfaceInfo.getInterfaceTag());
+            removeFilterEqualsTable(elanInfo, interfaceInfo, deleteFlowGroupTx);
         } else {
-            removeElanDpnInterfaceFromOperationalDataStore(elanName, dpId, interfaceName, elanTag);
+            // Interface does not exist in ConfigDS, so lets remove everything about that interface related to Elan
+            ElanInterfaceMac elanInterfaceMac =  ElanUtils.getElanInterfaceMacByInterfaceName(interfaceName);
+            if(elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
+                List<MacEntry> macEntries = elanInterfaceMac.getMacEntry();
+                for(MacEntry macEntry : macEntries) {
+                    tx.delete(LogicalDatastoreType.OPERATIONAL, ElanUtils.getMacEntryOperationalDataPath(elanName, macEntry.getMacAddress()));
+                }
+            }
         }
-
-        removeStaticELanFlows(elanInfo, interfaceInfo);
-        ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, elanInterfaceId);
-        List<String> elanInterfaces = elanState.getElanInterfaces();
-        elanInterfaces.remove(interfaceName);
-
-        if(elanInterfaces.isEmpty()) {
-            ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName));
-            ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnOperationDataPath(elanName));
-            ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanMacTableOperationalDataPath(elanName));
-            ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInfoEntriesOperationalDataPath(elanInfo.getElanTag()));
-            //ElanUtils.delete(broker, LogicalDatastoreType.CONFIGURATION, ElanUtils.getElanInstanceConfigurationDataPath(elanName));
-        } else {
-            Elan updateElanState = new ElanBuilder().setElanInterfaces(elanInterfaces).setName(elanName).setKey(new ElanKey(elanName)).build();
-            MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName), updateElanState);
+        tx.delete(LogicalDatastoreType.OPERATIONAL, elanInterfaceId);
+        if(!isInterfaceStateRemoved) {
+            unbindService(elanInfo, interfaceName, tx);
         }
+        deleteElanInterfaceFromConfigDS(interfaceName, tx);
+        ElanUtils.waitForTransactionToComplete(tx);
+        deleteFlowGroupTx.submit();
     }
 
-    private void removeElanDpnInterfaceFromOperationalDataStore(String elanName, BigInteger dpId, String interfaceName, long elanTag) {
+    private DpnInterfaces removeElanDpnInterfaceFromOperationalDataStore(String elanName, BigInteger dpId, String interfaceName,
+                                                                         long elanTag, WriteTransaction tx) {
         DpnInterfaces dpnInterfaces =  ElanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId);
         if(dpnInterfaces != null) {
             List<String> interfaceLists = dpnInterfaces.getInterfaces();
@@ -285,11 +273,12 @@ public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterfa
 
             if (interfaceLists == null || interfaceLists.isEmpty()) {
                 deleteAllRemoteMacsInADpn(elanName, dpId, elanTag);
-                deleteElanDpnInterface(elanName, dpId);
+                deleteElanDpnInterface(elanName, dpId, tx);
             } else {
-                updateElanDpnInterfacesList(elanName, dpId, interfaceLists);
+                dpnInterfaces = updateElanDpnInterfacesList(elanName, dpId, interfaceLists, tx);
             }
         }
+        return dpnInterfaces;
     }
 
     private void deleteAllRemoteMacsInADpn(String elanName, BigInteger dpId, long elanTag) {
@@ -303,7 +292,7 @@ public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterfa
                         continue;
                     }
                     for (MacEntry mac : macs.getMacEntry())
-                        mdsalManager.removeFlow(dpId, MDSALUtil.buildFlow(ElanConstants.ELAN_DMAC_TABLE,
+                        elanServiceProvider.getMdsalManager().removeFlow(dpId, MDSALUtil.buildFlow(ElanConstants.ELAN_DMAC_TABLE,
                             ElanUtils.getKnownDynamicmacFlowRef(ElanConstants.ELAN_DMAC_TABLE, dpId, currentDpId, mac.getMacAddress().getValue(), elanTag)));
                 }
             }
@@ -315,7 +304,7 @@ public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterfa
         // updating the static-Mac Entries for the existing elanInterface
         String elanName = update.getElanInstanceName();
         String interfaceName = update.getName();
-        InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
+        InterfaceInfo interfaceInfo = elanServiceProvider.getInterfaceManager().getInterfaceInfo(interfaceName);
         List<PhysAddress> existingPhysAddress = original.getStaticMacEntries();
         List<PhysAddress> updatedPhysAddress = update.getStaticMacEntries();
         if(updatedPhysAddress != null && !updatedPhysAddress.isEmpty()) {
@@ -333,12 +322,14 @@ public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterfa
             if(updatedPhysAddress.size() > 0) {
                 for(PhysAddress physAddress: updatedPhysAddress) {
                     InstanceIdentifier<MacEntry> macId =  getMacEntryOperationalDataPath(elanName, physAddress);
-                    Optional<MacEntry> existingMacEntry = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, macId);
+                    Optional<MacEntry> existingMacEntry = ElanUtils.read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, macId);
+                    WriteTransaction tx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
                     if(existingMacEntry.isPresent()) {
-                        elanForwardingEntriesHandler.updateElanInterfaceForwardingTablesList(elanName, interfaceName, existingMacEntry.get().getInterface(), existingMacEntry.get());
+                        elanServiceProvider.getElanForwardingEntriesHandler().updateElanInterfaceForwardingTablesList(elanName, interfaceName, existingMacEntry.get().getInterface(), existingMacEntry.get(), tx);
                     } else {
-                        elanForwardingEntriesHandler.addElanInterfaceForwardingTableList(ElanUtils.getElanInstanceByName(elanName), interfaceName, physAddress);
+                        elanServiceProvider.getElanForwardingEntriesHandler().addElanInterfaceForwardingTableList(ElanUtils.getElanInstanceByName(elanName), interfaceName, physAddress, tx);
                     }
+                    ElanUtils.waitForTransactionToComplete(tx);
                 }
             }
         } else if(existingPhysAddress != null && !existingPhysAddress.isEmpty()) {
@@ -352,7 +343,7 @@ public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterfa
     protected void add(InstanceIdentifier<ElanInterface> identifier, ElanInterface elanInterfaceAdded) {
         String elanInstanceName = elanInterfaceAdded.getElanInstanceName();
         String interfaceName = elanInterfaceAdded.getName();
-        InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
+        InterfaceInfo interfaceInfo = elanServiceProvider.getInterfaceManager().getInterfaceInfo(interfaceName);
         if (interfaceInfo == null) {
             logger.warn("Interface {} is removed from Interface Oper DS due to port down ", interfaceName);
             return;
@@ -362,7 +353,11 @@ public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterfa
         if (elanInstance == null) {
             elanInstance = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName).setDescription(elanInterfaceAdded.getDescription()).build();
             //Add the ElanInstance in the Configuration data-store
-            ElanUtils.updateOperationalDataStore(broker, idManager, elanInstance);
+            WriteTransaction tx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
+            List<String> elanInterfaces = new ArrayList<String>();
+            elanInterfaces.add(interfaceName);
+            ElanUtils.updateOperationalDataStore(elanServiceProvider.getBroker(), elanServiceProvider.getIdManager(), elanInstance, elanInterfaces, tx);
+            ElanUtils.waitForTransactionToComplete(tx);
             elanInstance = ElanUtils.getElanInstanceByName(elanInstanceName);
         }
 
@@ -373,15 +368,15 @@ public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterfa
         if (elanTag == null) {
             ConcurrentLinkedQueue<ElanInterface> elanInterfaces = unProcessedElanInterfaces.get(elanInstanceName);
             if (elanInterfaces == null) {
-                elanInterfaces = new ConcurrentLinkedQueue<>();
+                elanInterfaces = new ConcurrentLinkedQueue<ElanInterface>();
             }
             elanInterfaces.add(elanInterfaceAdded);
             unProcessedElanInterfaces.put(elanInstanceName, elanInterfaces);
             return;
         }
         DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
-        ElanInterfaceAddWorker addWorker = new ElanInterfaceAddWorker(elanInstanceName, elanInterfaceAdded,
-                interfaceInfo, elanInstance, this);
+        InterfaceAddWorkerOnElan addWorker = new InterfaceAddWorkerOnElan(elanInstanceName, elanInterfaceAdded,
+            interfaceInfo, elanInstance, this);
         coordinator.enqueueJob(elanInstanceName, addWorker, ElanConstants.JOB_MAX_RETRIES);
     }
 
@@ -392,14 +387,20 @@ public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterfa
         }
         for (ElanInterface elanInterface: elanInterfaces) {
             String interfaceName = elanInterface.getName();
-            InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
+            InterfaceInfo interfaceInfo = elanServiceProvider.getInterfaceManager().getInterfaceInfo(interfaceName);
             addElanInterface(elanInterface, interfaceInfo, elanInstance);
         }
     }
 
-    void programRemoteDmacFlow(ElanInstance elanInstance, InterfaceInfo interfaceInfo){
+    void programRemoteDmacFlow(ElanInstance elanInstance, InterfaceInfo interfaceInfo, WriteTransaction writeFlowGroupTx){
         ElanDpnInterfacesList elanDpnInterfacesList =  ElanUtils.getElanDpnInterfacesList(elanInstance.getElanInstanceName());
-        List<DpnInterfaces> dpnInterfaceLists =  elanDpnInterfacesList.getDpnInterfaces();
+        List<DpnInterfaces> dpnInterfaceLists =  null;
+        if (elanDpnInterfacesList != null) {
+            dpnInterfaceLists = elanDpnInterfacesList.getDpnInterfaces();
+        }
+        if (dpnInterfaceLists == null) {
+            dpnInterfaceLists = new ArrayList<DpnInterfaces>();
+        }
         for(DpnInterfaces dpnInterfaces : dpnInterfaceLists){
             if(dpnInterfaces.getDpId().equals(interfaceInfo.getDpId())) {
                 continue;
@@ -407,7 +408,7 @@ public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterfa
             List<String> remoteElanInterfaces = dpnInterfaces.getInterfaces();
             for(String remoteIf : remoteElanInterfaces) {
                 ElanInterfaceMac elanIfMac = ElanUtils.getElanInterfaceMacByInterfaceName(remoteIf);
-                InterfaceInfo remoteInterface = interfaceManager.getInterfaceInfo(remoteIf);
+                InterfaceInfo remoteInterface = elanServiceProvider.getInterfaceManager().getInterfaceInfo(remoteIf);
                 if(elanIfMac == null) {
                     continue;
                 }
@@ -416,10 +417,10 @@ public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterfa
                     for (MacEntry macEntry : remoteMacEntries) {
                         PhysAddress physAddress = macEntry.getMacAddress();
                         ElanUtils.setupRemoteDmacFlow(interfaceInfo.getDpId(), remoteInterface.getDpId(),
-                                remoteInterface.getInterfaceTag(),
-                                elanInstance.getElanTag(),
-                                physAddress.getValue(),
-                                elanInstance.getElanInstanceName());
+                            remoteInterface.getInterfaceTag(),
+                            elanInstance.getElanTag(),
+                            physAddress.getValue(),
+                            elanInstance.getElanInstanceName(), writeFlowGroupTx);
                     }
                 }
             }
@@ -433,28 +434,28 @@ public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterfa
 
         String interfaceName = elanInterface.getName();
         String elanInstanceName = elanInterface.getElanInstanceName();
-        List<PhysAddress> staticMacAddresses = elanInterface.getStaticMacEntries();
 
         Elan elanInfo = ElanUtils.getElanByName(elanInstanceName);
-        if(elanInfo == null) {
-            ElanUtils.updateOperationalDataStore(broker, idManager, elanInstance);
+        WriteTransaction tx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
+        if (elanInfo == null) {
+            List<String> elanInterfaces = new ArrayList<String>();
+            elanInterfaces.add(interfaceName);
+            ElanUtils.updateOperationalDataStore(elanServiceProvider.getBroker(), elanServiceProvider.getIdManager(), elanInstance, elanInterfaces, tx);
+        } else {
+            createElanStateList(elanInstanceName, interfaceName, tx);
         }
-
+        boolean isFirstInterfaceInDpn = false;
         // Specific actions to the DPN where the ElanInterface has been added, for example, programming the
         // External tunnel table if needed or adding the ElanInterface to the DpnInterfaces in the operational DS.
         BigInteger dpId = ( interfaceInfo != null ) ? dpId = interfaceInfo.getDpId() : null;
-        if(dpId != null && !dpId.equals(ElanConstants.INVALID_DPN)) {
+        DpnInterfaces dpnInterfaces = null;
+        if (dpId != null && !dpId.equals(ElanConstants.INVALID_DPN)) {
             InstanceIdentifier<DpnInterfaces> elanDpnInterfaces = ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId);
-            Optional<DpnInterfaces> existingElanDpnInterfaces = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanDpnInterfaces);
+            Optional<DpnInterfaces> existingElanDpnInterfaces = ElanUtils.read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, elanDpnInterfaces);
             if (!existingElanDpnInterfaces.isPresent()) {
+                isFirstInterfaceInDpn = true;
                 // ELAN's 1st ElanInterface added to this DPN
-                createElanInterfacesList(elanInstanceName, interfaceName, dpId);
-                /*
-                 * Install remote DMAC flow.
-                 * This is required since this DPN is added later to the elan instance
-                 * and remote DMACs of other interfaces in this elan instance are not present in the current dpn.
-                 */
-                programRemoteDmacFlow(elanInstance, interfaceInfo);
+                dpnInterfaces = createElanInterfacesList(elanInstanceName, interfaceName, dpId, tx);
                 // The 1st ElanInterface in a DPN must program the Ext Tunnel table, but only if Elan has VNI
                 if ( elanInstance.getVni() != null && elanInstance.getVni().longValue() != 0 ) {
                     setExternalTunnelTable(dpId, elanInstance);
@@ -466,109 +467,159 @@ public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterfa
                 if (elanInterfaces.size() == 1) {//1st dpn interface
                     ElanL2GatewayUtils.installElanL2gwDevicesLocalMacsInDpn(dpId, elanInstance);
                 }
-                updateElanDpnInterfacesList(elanInstanceName, dpId, elanInterfaces);
+                dpnInterfaces = updateElanDpnInterfacesList(elanInstanceName, dpId, elanInterfaces, tx);
             }
         }
 
         // add code to install Local/Remote BC group, unknow DMAC entry, terminating service table flow entry
         // call bindservice of interfacemanager to create ingress table flow enty.
         //Add interface to the ElanInterfaceForwardingEntires Container
-        createElanInterfaceTablesList(interfaceName);
-        createElanStateList(elanInstanceName, interfaceName);
+        createElanInterfaceTablesList(interfaceName, tx);
         if (interfaceInfo != null) {
-            installFlowsAndGroups(elanInstance, interfaceInfo);
+            installEntriesForFirstInterfaceonDpn(elanInstance, interfaceInfo, dpnInterfaces, isFirstInterfaceInDpn, tx);
         }
-        // add the static mac addresses
+        ElanUtils.waitForTransactionToComplete(tx);
+
+        DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+        InterfaceAddWorkerOnElanInterface addWorker = new InterfaceAddWorkerOnElanInterface(interfaceName, elanInterface,
+            interfaceInfo, elanInstance, isFirstInterfaceInDpn, this);
+        coordinator.enqueueJob(interfaceName, addWorker, ElanConstants.JOB_MAX_RETRIES);
+    }
+
+    void setupEntriesForElanInterface(ElanInstance elanInstance, ElanInterface elanInterface,
+                                      InterfaceInfo interfaceInfo, boolean isFirstInterfaceInDpn) {
+        String elanInstanceName = elanInstance.getElanInstanceName();
+        String interfaceName = elanInterface.getName();
+        WriteTransaction tx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
+        BigInteger dpId = interfaceInfo.getDpId();
+        WriteTransaction writeFlowGroupTx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
+        installEntriesForElanInterface(elanInstance, interfaceInfo, isFirstInterfaceInDpn, tx, writeFlowGroupTx);
+        List<PhysAddress> staticMacAddresses = elanInterface.getStaticMacEntries();
         if (staticMacAddresses != null) {
             boolean isInterfaceOperational = isOperational(interfaceInfo);
             for (PhysAddress physAddress : staticMacAddresses) {
                 InstanceIdentifier<MacEntry> macId = getMacEntryOperationalDataPath(elanInstanceName, physAddress);
-                Optional<MacEntry> existingMacEntry = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, macId);
+                Optional<MacEntry> existingMacEntry = ElanUtils.read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, macId);
                 if (existingMacEntry.isPresent()) {
-                    elanForwardingEntriesHandler.updateElanInterfaceForwardingTablesList(elanInstanceName, interfaceName, existingMacEntry.get().getInterface(), existingMacEntry.get());
+                    elanServiceProvider.getElanForwardingEntriesHandler().updateElanInterfaceForwardingTablesList(elanInstanceName, interfaceName, existingMacEntry.get().getInterface(),
+                        existingMacEntry.get(), tx);
                 } else {
-                    elanForwardingEntriesHandler.addElanInterfaceForwardingTableList(elanInstance, interfaceName, physAddress);
+                    elanServiceProvider.getElanForwardingEntriesHandler().addElanInterfaceForwardingTableList(elanInstance, interfaceName, physAddress, tx);
                 }
 
                 if ( isInterfaceOperational ) {
                     // Setting SMAC, DMAC, UDMAC in this DPN and also in other DPNs
-                    ElanUtils.setupMacFlows(elanInstance, interfaceInfo, ElanConstants.STATIC_MAC_TIMEOUT, physAddress.getValue());
+                    ElanUtils.setupMacFlows(elanInstance, interfaceInfo, ElanConstants.STATIC_MAC_TIMEOUT, physAddress.getValue(), writeFlowGroupTx);
                 }
             }
 
-            if( isInterfaceOperational ) {
+            if ( isInterfaceOperational ) {
                 // Add MAC in TOR's remote MACs via OVSDB. Outside of the loop on purpose.
                 ElanL2GatewayUtils.scheduleAddDpnMacInExtDevices(elanInstance.getElanInstanceName(), dpId, staticMacAddresses);
             }
         }
+        ElanUtils.waitForTransactionToComplete(tx);
+        writeFlowGroupTx.submit();
     }
 
     protected void removeInterfaceStaticMacEntires(String elanInstanceName, String interfaceName, PhysAddress physAddress) {
-        InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
+        InterfaceInfo interfaceInfo = elanServiceProvider.getInterfaceManager().getInterfaceInfo(interfaceName);
         InstanceIdentifier<MacEntry> macId =  getMacEntryOperationalDataPath(elanInstanceName, physAddress);
-        Optional<MacEntry> existingMacEntry = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, macId);
+        Optional<MacEntry> existingMacEntry = ElanUtils.read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, macId);
 
-        if(!existingMacEntry.isPresent()) {
+        if (!existingMacEntry.isPresent()) {
             return;
         }
 
         MacEntry macEntry = new MacEntryBuilder().setMacAddress(physAddress).setInterface(interfaceName).setKey(new MacEntryKey(physAddress)).build();
-        elanForwardingEntriesHandler.deleteElanInterfaceForwardingEntries(ElanUtils.getElanInstanceByName(elanInstanceName), interfaceInfo, macEntry);
-        elanForwardingEntriesHandler.deleteElanInterfaceMacForwardingEntries(interfaceName, physAddress);
+        WriteTransaction tx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
+        elanServiceProvider.getElanForwardingEntriesHandler().deleteElanInterfaceForwardingEntries(ElanUtils.getElanInstanceByName(elanInstanceName), interfaceInfo, macEntry, tx);
+        elanServiceProvider.getElanForwardingEntriesHandler().deleteElanInterfaceMacForwardingEntries(interfaceName, physAddress, tx);
+        ElanUtils.waitForTransactionToComplete(tx);
     }
 
 
     private InstanceIdentifier<MacEntry> getMacEntryOperationalDataPath(String elanName, PhysAddress physAddress) {
         return InstanceIdentifier.builder(ElanForwardingTables.class).child(MacTable.class,
-                new MacTableKey(elanName)).child(MacEntry.class, new MacEntryKey(physAddress)).build();
+            new MacTableKey(elanName)).child(MacEntry.class, new MacEntryKey(physAddress)).build();
     }
 
-    public void installFlowsAndGroups(final ElanInstance elanInfo, final InterfaceInfo interfaceInfo) {
-        if (isOperational(interfaceInfo)) {
-
-            // LocalBroadcast Group creation with elan-Interfaces
-            setupElanBroadcastGroups(elanInfo, interfaceInfo.getDpId());
-
-            setupLocalBroadcastGroups(elanInfo, interfaceInfo);
+    private void installEntriesForElanInterface(ElanInstance elanInstance, InterfaceInfo interfaceInfo,
+                                                boolean isFirstInterfaceInDpn, WriteTransaction tx, WriteTransaction writeFlowGroupTx) {
+        if (!isOperational(interfaceInfo)) {
+            return;
+        }
+        BigInteger dpId = interfaceInfo.getDpId();
+        ElanUtils.setupTermDmacFlows(interfaceInfo, elanServiceProvider.getMdsalManager(), writeFlowGroupTx);
+        setupFilterEqualsTable(elanInstance, interfaceInfo, writeFlowGroupTx);
+        if (isFirstInterfaceInDpn) {
             //Terminating Service , UnknownDMAC Table.
-            setupTerminateServiceTable(elanInfo, interfaceInfo);
-            ElanUtils.setupTermDmacFlows(interfaceInfo, mdsalManager);
-            setupUnknownDMacTable(elanInfo, interfaceInfo);
-            setupFilterEqualsTable(elanInfo, interfaceInfo);
-            // bind the Elan service to the Interface
-            bindService(elanInfo, interfaceInfo.getInterfaceName());
-
+            setupTerminateServiceTable(elanInstance, dpId, writeFlowGroupTx);
+            setupUnknownDMacTable(elanInstance, dpId, writeFlowGroupTx);
             //update the remote-DPNs remoteBC group entry with Tunnels
-            setElanBCGrouponOtherDpns(elanInfo, interfaceInfo);
+            setElanBCGrouponOtherDpns(elanInstance, dpId, writeFlowGroupTx);
+            /*
+             * Install remote DMAC flow.
+             * This is required since this DPN is added later to the elan instance
+             * and remote DMACs of other interfaces in this elan instance are not present in the current dpn.
+             */
+            programRemoteDmacFlow(elanInstance, interfaceInfo, writeFlowGroupTx);
         }
+        // bind the Elan service to the Interface
+        bindService(elanInstance, interfaceInfo.getInterfaceName(), tx);
     }
 
-    public void setupFilterEqualsTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
+    public void installEntriesForFirstInterfaceonDpn(ElanInstance elanInfo, InterfaceInfo interfaceInfo, DpnInterfaces dpnInterfaces,
+                                                     boolean isFirstInterfaceInDpn, WriteTransaction tx) {
+        if (!isOperational(interfaceInfo)) {
+            return;
+        }
+        // LocalBroadcast Group creation with elan-Interfaces
+        setupLocalBroadcastGroups(elanInfo, dpnInterfaces, interfaceInfo);
+        if (isFirstInterfaceInDpn) {
+            logger.trace("waitTimeForSyncInstall is {}", waitTimeForSyncInstall);
+            BigInteger dpId = interfaceInfo.getDpId();
+            // RemoteBroadcast Group creation
+            try {
+                Thread.sleep(waitTimeForSyncInstall);
+            } catch (InterruptedException e1) {
+                logger.warn("Error while waiting for local BC group for ELAN {} to install", elanInfo);
+            }
+            setupElanBroadcastGroups(elanInfo, dpId);
+            try {
+                Thread.sleep(waitTimeForSyncInstall);
+            } catch (InterruptedException e1) {
+                logger.warn("Error while waiting for local BC group for ELAN {} to install", elanInfo);
+            }
+        }
+    }
+
+    public void setupFilterEqualsTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo, WriteTransaction writeFlowGroupTx) {
         int ifTag = interfaceInfo.getInterfaceTag();
         Flow flow = MDSALUtil.buildFlowNew(ElanConstants.ELAN_FILTER_EQUALS_TABLE, getFlowRef(ElanConstants.ELAN_FILTER_EQUALS_TABLE, ifTag),
-                9, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)), getTunnelIdMatchForFilterEqualsLPortTag(ifTag), ElanUtils.getInstructionsInPortForOutGroup(interfaceInfo.getInterfaceName()));
+            9, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)), getTunnelIdMatchForFilterEqualsLPortTag(ifTag), ElanUtils.getInstructionsInPortForOutGroup(interfaceInfo.getInterfaceName()));
 
-        mdsalManager.installFlow(interfaceInfo.getDpId(), flow);
+        elanServiceProvider.getMdsalManager().addFlowToTx(interfaceInfo.getDpId(), flow, writeFlowGroupTx);
 
         Flow flowEntry = MDSALUtil.buildFlowNew(ElanConstants.ELAN_FILTER_EQUALS_TABLE, getFlowRef(ElanConstants.ELAN_FILTER_EQUALS_TABLE, 1000+ifTag),
-                10, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)), getMatchesForFilterEqualsLPortTag(ifTag),
-                MDSALUtil.buildInstructionsDrop());
+            10, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)), getMatchesForFilterEqualsLPortTag(ifTag),
+            MDSALUtil.buildInstructionsDrop());
 
-        mdsalManager.installFlow(interfaceInfo.getDpId(), flowEntry);
+        elanServiceProvider.getMdsalManager().addFlowToTx(interfaceInfo.getDpId(), flowEntry, writeFlowGroupTx);
     }
 
-    public void removeFilterEqualsTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
+    public void removeFilterEqualsTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo, WriteTransaction deleteFlowGroupTx) {
         int ifTag = interfaceInfo.getInterfaceTag();
         Flow flow = MDSALUtil.buildFlowNew(ElanConstants.ELAN_FILTER_EQUALS_TABLE, getFlowRef(ElanConstants.ELAN_FILTER_EQUALS_TABLE, ifTag),
-                9, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)), getTunnelIdMatchForFilterEqualsLPortTag(ifTag), ElanUtils.getInstructionsInPortForOutGroup(interfaceInfo.getInterfaceName()));
+            9, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)), getTunnelIdMatchForFilterEqualsLPortTag(ifTag), ElanUtils.getInstructionsInPortForOutGroup(interfaceInfo.getInterfaceName()));
 
-        mdsalManager.removeFlow(interfaceInfo.getDpId(), flow);
+        elanServiceProvider.getMdsalManager().removeFlowToTx(interfaceInfo.getDpId(), flow, deleteFlowGroupTx);
 
         Flow flowEntity = MDSALUtil.buildFlowNew(ElanConstants.ELAN_FILTER_EQUALS_TABLE, getFlowRef(ElanConstants.ELAN_FILTER_EQUALS_TABLE, 1000+ifTag),
-                10, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)), getMatchesForFilterEqualsLPortTag(ifTag),
-                MDSALUtil.buildInstructionsDrop());
+            10, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)), getMatchesForFilterEqualsLPortTag(ifTag),
+            MDSALUtil.buildInstructionsDrop());
 
-        mdsalManager.removeFlow(interfaceInfo.getDpId(), flowEntity);
+        elanServiceProvider.getMdsalManager().removeFlowToTx(interfaceInfo.getDpId(), flowEntity, deleteFlowGroupTx);
     }
 
     private List<Bucket> getRemoteBCGroupBucketInfos(ElanInstance elanInfo,
@@ -576,20 +627,20 @@ public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterfa
         BigInteger dpnId = interfaceInfo.getDpId();
         int elanTag = elanInfo.getElanTag().intValue();
         int bucketId = bucketKeyStart;
-        List<Bucket> listBuckets = new ArrayList<>();
+        List<Bucket> listBuckets = new ArrayList<Bucket>();
         ElanDpnInterfacesList elanDpns = ElanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
-        if(elanDpns != null) {
+        if (elanDpns != null) {
             List<DpnInterfaces> dpnInterfaceses = elanDpns.getDpnInterfaces();
             for(DpnInterfaces dpnInterface : dpnInterfaceses) {
-               if(ElanUtils.isDpnPresent(dpnInterface.getDpId()) && dpnInterface.getDpId() != dpnId && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) {
-                   try {
-                       List<Action> listAction = ElanUtils.getInternalItmEgressAction(dpnId, dpnInterface.getDpId(), elanTag);
-                       listBuckets.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
-                       bucketId++;
-                   } catch (Exception ex) {
-                       logger.error( "Logical Group Interface not found between source Dpn - {}, destination Dpn - {} " ,dpnId, dpnInterface.getDpId() );
-                   }
-               }
+                if (ElanUtils.isDpnPresent(dpnInterface.getDpId()) && dpnInterface.getDpId() != dpnId && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) {
+                    try {
+                        List<Action> listAction = ElanUtils.getInternalItmEgressAction(dpnId, dpnInterface.getDpId(), elanTag);
+                        listBuckets.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
+                        bucketId++;
+                    } catch (Exception ex) {
+                        logger.error( "Logical Group Interface not found between source Dpn - {}, destination Dpn - {} " ,dpnId, dpnInterface.getDpId() );
+                    }
+                }
             }
             List<Bucket> elanL2GwDevicesBuckets = getRemoteBCGroupBucketsOfElanL2GwDevices(elanInfo, dpnId, bucketId);
             listBuckets.addAll(elanL2GwDevicesBuckets);
@@ -599,14 +650,17 @@ public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterfa
 
     private List<Bucket> getRemoteBCGroupBuckets(ElanInstance elanInfo, BigInteger dpnId, int bucketId) {
         int elanTag = elanInfo.getElanTag().intValue();
-        List<Bucket> listBucketInfo = new ArrayList<>();
+        List<Bucket> listBucketInfo = new ArrayList<Bucket>();
         ElanDpnInterfacesList elanDpns = ElanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
-        if(elanDpns != null) {
+        if (elanDpns != null) {
             List<DpnInterfaces> dpnInterfaceses = elanDpns.getDpnInterfaces();
             for(DpnInterfaces dpnInterface : dpnInterfaceses) {
-                if(ElanUtils.isDpnPresent(dpnInterface.getDpId()) && dpnInterface.getDpId() != dpnId && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) {
+                if (ElanUtils.isDpnPresent(dpnInterface.getDpId()) && dpnInterface.getDpId() != dpnId && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) {
                     try {
                         List<Action> listActionInfo = ElanUtils.getInternalItmEgressAction(dpnId, dpnInterface.getDpId(), elanTag);
+                        if (listActionInfo.isEmpty()) {
+                            continue;
+                        }
                         listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, 0, bucketId, 0xffffffffL, 0xffffffffL));
                         bucketId++;
                     } catch (Exception ex) {
@@ -622,33 +676,26 @@ public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterfa
     }
 
     private void setElanBCGrouponOtherDpns(ElanInstance elanInfo,
-                                           InterfaceInfo interfaceInfo) {
-        BigInteger dpnId = interfaceInfo.getDpId();
+                                           BigInteger dpId, WriteTransaction tx) {
         int elanTag = elanInfo.getElanTag().intValue();
         long groupId = ElanUtils.getElanRemoteBCGID(elanTag);
-        List<Bucket> listBucket = new ArrayList<>();
+        List<Bucket> listBucket = new ArrayList<Bucket>();
         int bucketId = 0;
         ElanDpnInterfacesList elanDpns = ElanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
-        if(elanDpns != null) {
+        if (elanDpns != null) {
             List<DpnInterfaces> dpnInterfaceses = elanDpns.getDpnInterfaces();
             for(DpnInterfaces dpnInterface : dpnInterfaceses) {
-              List<Bucket> remoteListBucketInfo = new ArrayList<>();
-                if(ElanUtils.isDpnPresent(dpnInterface.getDpId()) && !dpnInterface.getDpId().equals(dpnId) && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) {
-                    for(String ifName : dpnInterface.getInterfaces()) {
-                        // In case if there is a InterfacePort in the cache which is not in
-                        // operational state, skip processing it
-                        InterfaceInfo ifInfo = interfaceManager.getInterfaceInfoFromOperationalDataStore(ifName, interfaceInfo.getInterfaceType());
-                        if (!isOperational(ifInfo)) {
-                            continue;
-                        }
-
-                        listBucket.add(MDSALUtil.buildBucket(getInterfacePortActions(ifInfo), MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
-                        bucketId++;
-                    }
+                List<Bucket> remoteListBucketInfo = new ArrayList<Bucket>();
+                if (ElanUtils.isDpnPresent(dpnInterface.getDpId()) && !dpnInterface.getDpId().equals(dpId) && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) {
+                    List<Action> listAction = new ArrayList<Action>();
+                    int actionKey = 0;
+                    listAction.add((new ActionInfo(ActionType.group, new String[] {String.valueOf(ElanUtils.getElanLocalBCGID(elanTag))}, ++actionKey)).buildAction());
+                    listBucket.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
+                    bucketId++;
                     remoteListBucketInfo.addAll(listBucket);
                     for(DpnInterfaces otherFes : dpnInterfaceses) {
                         if (ElanUtils.isDpnPresent(otherFes.getDpId()) && otherFes.getDpId() != dpnInterface.getDpId()
-                                && otherFes.getInterfaces() != null && ! otherFes.getInterfaces().isEmpty()) {
+                            && otherFes.getInterfaces() != null && ! otherFes.getInterfaces().isEmpty()) {
                             try {
                                 List<Action> remoteListActionInfo = ElanUtils.getInternalItmEgressAction(dpnInterface.getDpId(), otherFes.getDpId(), elanTag);
                                 remoteListBucketInfo.add(MDSALUtil.buildBucket(remoteListActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT,MDSALUtil.WATCH_GROUP));
@@ -659,8 +706,8 @@ public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterfa
                             }
                         }
                     }
-                    List<Bucket> elanL2GwDevicesBuckets = getRemoteBCGroupBucketsOfElanL2GwDevices(elanInfo, dpnId,
-                            bucketId);
+                    List<Bucket> elanL2GwDevicesBuckets = getRemoteBCGroupBucketsOfElanL2GwDevices(elanInfo, dpId,
+                        bucketId);
                     remoteListBucketInfo.addAll(elanL2GwDevicesBuckets);
 
                     if (remoteListBucketInfo.size() == 0) {
@@ -668,7 +715,7 @@ public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterfa
                         continue;
                     }
                     Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(remoteListBucketInfo));
-                    mdsalManager.syncInstallGroup(dpnInterface.getDpId(), group, ElanConstants.DELAY_TIME_IN_MILLISECOND);
+                    elanServiceProvider.getMdsalManager().addGroupToTx(dpnInterface.getDpId(), group, tx);
                 }
             }
         }
@@ -682,44 +729,41 @@ public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterfa
     }
 
     private List<MatchInfo> getMatchesForElanTag(Long elanTag) {
-        List<MatchInfo> mkMatches = new ArrayList<>();
+        List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
         // Matching metadata
         mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
-                ElanUtils.getElanMetadataLabel(elanTag),
-                MetaDataUtil.METADATA_MASK_SERVICE }));
+            ElanUtils.getElanMetadataLabel(elanTag),
+            MetaDataUtil.METADATA_MASK_SERVICE }));
         return mkMatches;
     }
 
 
     private List<MatchInfo> buildMatchesForVni(Long vni) {
-        List<MatchInfo> mkMatches = new ArrayList<>();
+        List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
         MatchInfo match = new MatchInfo(MatchFieldType.tunnel_id,
-                                        new BigInteger[]{BigInteger.valueOf(vni)} );
+            new BigInteger[]{BigInteger.valueOf(vni)} );
         mkMatches.add(match);
         return mkMatches;
     }
 
     private List<Instruction> getInstructionsForOutGroup(
-            long groupId) {
-        List<Instruction> mkInstructions = new ArrayList<>();
-        List <Action> actions = new ArrayList<>();
+        long groupId) {
+        List<Instruction> mkInstructions = new ArrayList<Instruction>();
+        List <Action> actions = new ArrayList <Action> ();
         actions.add(new ActionInfo(ActionType.group, new String[]{Long.toString(groupId)}).buildAction());
         mkInstructions.add(MDSALUtil.getWriteActionsInstruction(actions, 0));
         return mkInstructions;
     }
 
     private List<MatchInfo> getMatchesForElanTag(long elanTag, boolean isSHFlagSet) {
-        List<MatchInfo> mkMatches = new ArrayList<>();
+        List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
         // Matching metadata
         mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
-                ElanUtils.getElanMetadataLabel(elanTag, isSHFlagSet),
-                MetaDataUtil.METADATA_MASK_SERVICE_SH_FLAG}));
+            ElanUtils.getElanMetadataLabel(elanTag, isSHFlagSet),
+            MetaDataUtil.METADATA_MASK_SERVICE_SH_FLAG}));
         return mkMatches;
     }
 
-
-
-
     /**
      * Builds the list of instructions to be installed in the External Tunnel table (38), which so far
      * consists in writing the elanTag in metadata and send packet to the new DHCP table
@@ -728,132 +772,66 @@ public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterfa
      * @return the instructions ready to be installed in a flow
      */
     private List<InstructionInfo> getInstructionsExtTunnelTable(Long elanTag) {
-        List<InstructionInfo> mkInstructions = new ArrayList<>();
+        List<InstructionInfo> mkInstructions = new ArrayList<InstructionInfo>();
         mkInstructions.add(new InstructionInfo(InstructionType.write_metadata,
-                                               new BigInteger[] {
-                                                       ElanUtils.getElanMetadataLabel(elanTag),
-                                                       ElanUtils.getElanMetadataMask()
-                                               } ) );
-        // TODO (eperefr) We should point to SMAC or DMAC depending on a configuration property to enable
+            new BigInteger[] {
+                ElanUtils.getElanMetadataLabel(elanTag),
+                ElanUtils.getElanMetadataMask()
+            } ) );
+        // TODO: We should point to SMAC or DMAC depending on a configuration property to enable
         // mac learning
         mkInstructions.add(new InstructionInfo(InstructionType.goto_table,
-                                               new long[] { ElanConstants.ELAN_DMAC_TABLE }));
+            new long[] { ElanConstants.ELAN_DMAC_TABLE }));
 
         return mkInstructions;
     }
 
-    public void removeFlowsAndGroups(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
-        removeStaticELanFlows(elanInfo, interfaceInfo);
-        unbindService(elanInfo, interfaceInfo.getInterfaceName());
-    }
-
-    public void installMacAddressTables(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
-
-        String interfaceName = interfaceInfo.getInterfaceName();
-        BigInteger currentDpn = interfaceInfo.getDpId();
-        ElanInterfaceMac elanInterfaceMac = ElanUtils.getElanInterfaceMacByInterfaceName(interfaceName);
-        if(elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
-            List<MacEntry> macEntries =  elanInterfaceMac.getMacEntry();
-            for(MacEntry macEntry : macEntries) {
-                PhysAddress physAddress = macEntry.getMacAddress();
-                ElanUtils.setupMacFlows(elanInfo,
-                                        interfaceInfo,
-                                        macEntry.isIsStaticAddress()
-                                          ? ElanConstants.STATIC_MAC_TIMEOUT
-                                          : elanInfo.getMacTimeout(), physAddress.getValue());
-            }
-            //Programming the remoteDMACFlows
-            ElanDpnInterfacesList elanDpnInterfacesList =  ElanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
-            List<DpnInterfaces> dpnInterfaceLists =  elanDpnInterfacesList.getDpnInterfaces();
-            for(DpnInterfaces dpnInterfaces : dpnInterfaceLists){
-                if(dpnInterfaces.getDpId().equals(interfaceInfo.getDpId())) {
-                    continue;
-                }
-                List<String> remoteElanInterfaces = dpnInterfaces.getInterfaces();
-                for(String remoteIf : remoteElanInterfaces) {
-                    ElanInterfaceMac elanIfMac = ElanUtils.getElanInterfaceMacByInterfaceName(remoteIf);
-                    InterfaceInfo remoteInterface = interfaceManager.getInterfaceInfo(remoteIf);
-                    if(elanIfMac == null) {
-                        continue;
-                    }
-                    List<MacEntry> remoteMacEntries = elanIfMac.getMacEntry();
-                    if(remoteMacEntries != null) {
-                        for (MacEntry macEntry : remoteMacEntries) {
-                            PhysAddress physAddress = macEntry.getMacAddress();
-                            ElanUtils.installDmacFlowsToInternalRemoteMac(currentDpn, remoteInterface.getDpId(),
-                                    remoteInterface.getInterfaceTag(),
-                                    elanInfo.getElanTag(),
-                                    physAddress.getValue(),
-                                    elanInfo.getElanInstanceName());
-                        }
-                    }
-                }
-            }
-        }
-    }
-
     // Install DMAC entry on dst DPN
     public void installDMacAddressTables(ElanInstance elanInfo, InterfaceInfo interfaceInfo, BigInteger dstDpId) {
         String interfaceName = interfaceInfo.getInterfaceName();
         ElanInterfaceMac elanInterfaceMac = ElanUtils.getElanInterfaceMacByInterfaceName(interfaceName);
-        if(elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
+        if (elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
+            WriteTransaction writeFlowTx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
             List<MacEntry> macEntries =  elanInterfaceMac.getMacEntry();
             for(MacEntry macEntry : macEntries) {
                 PhysAddress physAddress = macEntry.getMacAddress();
-                ElanUtils.setupDMacFlowonRemoteDpn(elanInfo, interfaceInfo, dstDpId, physAddress.getValue());
-            }
-        }
-    }
-
-    public void removeMacAddressTables(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
-        ElanInterfaceMac elanInterfaceMac = ElanUtils.getElanInterfaceMacByInterfaceName(interfaceInfo.getInterfaceName());
-        if(elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
-            List<MacEntry> macEntries =  elanInterfaceMac.getMacEntry();
-            for(MacEntry macEntry : macEntries) {
-                ElanUtils.deleteMacFlows(elanInfo, interfaceInfo, macEntry);
+                ElanUtils.setupDMacFlowonRemoteDpn(elanInfo, interfaceInfo, dstDpId, physAddress.getValue(), writeFlowTx);
             }
+            writeFlowTx.submit();
         }
     }
 
     public void setupElanBroadcastGroups(ElanInstance elanInfo, BigInteger dpnId) {
-        List<Bucket> listBucket = new ArrayList<>();
+        List<Bucket> listBucket = new ArrayList<Bucket>();
         int bucketId = 0;
-        long groupId = ElanUtils.getElanRemoteBCGID(elanInfo.getElanTag());
-
-        DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanInfo.getElanInstanceName(), dpnId);
-        for(String ifName : dpnInterfaces.getInterfaces()) {
-            // In case if there is a InterfacePort in the cache which is not in
-            // operational state, skip processing it
-            // FIXME: interfaceType to be obtained dynamically. It doesn't
-            // affect the functionality here as it is nowhere used.
-            InterfaceType interfaceType = InterfaceInfo.InterfaceType.VLAN_INTERFACE;
-            InterfaceInfo ifInfo = interfaceManager.getInterfaceInfoFromOperationalDataStore(ifName, interfaceType);
-            if (!isOperational(ifInfo)) {
-                continue;
-            }
-
-            listBucket.add(MDSALUtil.buildBucket(getInterfacePortActions(ifInfo), MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
-            bucketId++;
-        }
+        int actionKey = 0;
+        Long elanTag = elanInfo.getElanTag();
+        long groupId = ElanUtils.getElanRemoteBCGID(elanTag);
+        List<Action> listAction = new ArrayList<Action>();
+        listAction.add((new ActionInfo(ActionType.group, new String[] {String.valueOf(ElanUtils.getElanLocalBCGID(elanTag))}, ++actionKey)).buildAction());
+        listBucket.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
+        bucketId++;
         List<Bucket> listBucketInfoRemote = getRemoteBCGroupBuckets(elanInfo, dpnId, bucketId);
         listBucket.addAll(listBucketInfoRemote);
-
         Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(listBucket));
-        logger.trace("installing the remote BroadCast Group:{}", group);
-        mdsalManager.syncInstallGroup(dpnId, group, ElanConstants.DELAY_TIME_IN_MILLISECOND);
+        logger.trace("Installing the remote BroadCast Group:{}", group);
+        elanServiceProvider.getMdsalManager().syncInstallGroup(dpnId, group, ElanConstants.DELAY_TIME_IN_MILLISECOND);
     }
 
-    public void setupLocalBroadcastGroups(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
-        List<Bucket> listBucket = new ArrayList<>();
+    public void setupLocalBroadcastGroups(ElanInstance elanInfo, DpnInterfaces newDpnInterface, InterfaceInfo interfaceInfo) {
+        List<Bucket> listBucket = new ArrayList<Bucket>();
         int bucketId = 0;
         BigInteger dpnId = interfaceInfo.getDpId();
         long groupId = ElanUtils.getElanLocalBCGID(elanInfo.getElanTag());
 
-        DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanInfo.getElanInstanceName(), dpnId);
-        for(String ifName : dpnInterfaces.getInterfaces()) {
+        List<String> interfaces = new ArrayList<String>();
+        if (newDpnInterface != null) {
+            interfaces = newDpnInterface.getInterfaces();
+        }
+        for(String ifName : interfaces) {
             // In case if there is a InterfacePort in the cache which is not in
             // operational state, skip processing it
-            InterfaceInfo ifInfo = interfaceManager.getInterfaceInfoFromOperationalDataStore(ifName, interfaceInfo.getInterfaceType());
+            InterfaceInfo ifInfo = elanServiceProvider.getInterfaceManager().getInterfaceInfoFromOperationalDataStore(ifName, interfaceInfo.getInterfaceType());
             if (!isOperational(ifInfo)) {
                 continue;
             }
@@ -864,10 +842,10 @@ public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterfa
 
         Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(listBucket));
         logger.trace("installing the localBroadCast Group:{}", group);
-        mdsalManager.syncInstallGroup(dpnId, group, ElanConstants.DELAY_TIME_IN_MILLISECOND);
+        elanServiceProvider.getMdsalManager().syncInstallGroup(dpnId, group, ElanConstants.DELAY_TIME_IN_MILLISECOND);
     }
 
-    public void removeLocalBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
+    public void removeLocalBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo, WriteTransaction deleteFlowGroupTx) {
         BigInteger dpnId = interfaceInfo.getDpId();
         long groupId = ElanUtils.getElanLocalBCGID(elanInfo.getElanTag());
         List<Bucket> listBuckets = new ArrayList<>();
@@ -876,20 +854,24 @@ public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterfa
         //listBuckets.addAll(getRemoteBCGroupBucketInfos(elanInfo, 1, interfaceInfo));
         Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(listBuckets));
         logger.trace("deleted the localBroadCast Group:{}", group);
-        mdsalManager.syncRemoveGroup(dpnId, group);
+        elanServiceProvider.getMdsalManager().removeGroupToTx(dpnId, group, deleteFlowGroupTx);
     }
 
-    public void removeElanBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
+    public void removeElanBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo, WriteTransaction deleteFlowGroupTx) {
         int bucketId = 0;
+        int actionKey = 0;
+        Long elanTag = elanInfo.getElanTag();
         List<Bucket> listBuckets = new ArrayList<>();
-        listBuckets.add(getLocalBCGroupBucketInfo(interfaceInfo, bucketId));
+        List<Action> listAction = new ArrayList<Action>();
+        listAction.add((new ActionInfo(ActionType.group, new String[] {String.valueOf(ElanUtils.getElanLocalBCGID(elanTag))}, ++actionKey)).buildAction());
+        listBuckets.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
         bucketId++;
         listBuckets.addAll(getRemoteBCGroupBucketInfos(elanInfo, bucketId, interfaceInfo));
         BigInteger dpnId = interfaceInfo.getDpId();
         long groupId = ElanUtils.getElanRemoteBCGID(elanInfo.getElanTag());
         Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(listBuckets));
         logger.trace("deleting the remoteBroadCast group:{}", group);
-        mdsalManager.syncRemoveGroup(dpnId, group);
+        elanServiceProvider.getMdsalManager().removeGroupToTx(dpnId, group, deleteFlowGroupTx);
     }
 
     /**
@@ -905,17 +887,17 @@ public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterfa
     public void setExternalTunnelTable(BigInteger dpnId, ElanInstance elanInfo) {
         long elanTag = elanInfo.getElanTag();
         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpnId,
-                                                          NwConstants.EXTERNAL_TUNNEL_TABLE,
-                                                          getFlowRef(NwConstants.EXTERNAL_TUNNEL_TABLE, elanTag),
-                                                          5,  // prio
-                                                          elanInfo.getElanInstanceName(),  // flowName
-                                                          0,  // idleTimeout
-                                                          0,  // hardTimeout
-                                                          ITMConstants.COOKIE_ITM_EXTERNAL.add(BigInteger.valueOf(elanTag)),
-                                                          buildMatchesForVni(elanInfo.getVni()),
-                                                          getInstructionsExtTunnelTable(elanTag) );
-
-        mdsalManager.installFlow(flowEntity);
+            NwConstants.EXTERNAL_TUNNEL_TABLE,
+            getFlowRef(NwConstants.EXTERNAL_TUNNEL_TABLE, elanTag),
+            5,  // prio
+            elanInfo.getElanInstanceName(),  // flowName
+            0,  // idleTimeout
+            0,  // hardTimeout
+            ITMConstants.COOKIE_ITM_EXTERNAL.add(BigInteger.valueOf(elanTag)),
+            buildMatchesForVni(elanInfo.getVni()),
+            getInstructionsExtTunnelTable(elanTag) );
+
+        elanServiceProvider.getMdsalManager().installFlow(flowEntity);
     }
 
     /**
@@ -926,85 +908,58 @@ public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterfa
      * @param elanInfo holds the elanTag needed for selecting the flow to be removed
      */
     public void unsetExternalTunnelTable(BigInteger dpnId, ElanInstance elanInfo) {
-        // TODO (eperefr): Use DataStoreJobCoordinator in order to avoid that removing the last ElanInstance plus
+        // 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());
         FlowEntity flowEntity = new FlowEntity(dpnId);
         flowEntity.setTableId(NwConstants.EXTERNAL_TUNNEL_TABLE);
         flowEntity.setFlowId(flowId);
-        mdsalManager.removeFlow(flowEntity);
+        elanServiceProvider.getMdsalManager().removeFlow(flowEntity);
     }
 
-    public void setupTerminateServiceTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
+    public void setupTerminateServiceTable(ElanInstance elanInfo, BigInteger dpId, WriteTransaction writeFlowGroupTx) {
         long elanTag = elanInfo.getElanTag();
         Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE, getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE, elanTag),
-                5, String.format("%s:%d","ITM Flow Entry ",elanTag), 0,  0, ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(elanTag)), ElanUtils.getTunnelMatchesForServiceId((int)elanTag),
-                getInstructionsForOutGroup(ElanUtils.getElanLocalBCGID(elanTag)));
+            5, String.format("%s:%d","ITM Flow Entry ",elanTag), 0,  0, ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(elanTag)), ElanUtils.getTunnelMatchesForServiceId((int)elanTag),
+            getInstructionsForOutGroup(ElanUtils.getElanLocalBCGID(elanTag)));
 
-        mdsalManager.installFlow(interfaceInfo.getDpId(), flowEntity);
+        elanServiceProvider.getMdsalManager().addFlowToTx(dpId, flowEntity, writeFlowGroupTx);
     }
 
-    public void setupUnknownDMacTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
+    public void setupUnknownDMacTable(ElanInstance elanInfo, BigInteger dpId, WriteTransaction writeFlowGroupTx) {
         long elanTag = elanInfo.getElanTag();
         Flow flowEntity = MDSALUtil.buildFlowNew(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, getUnknownDmacFlowRef(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag, /*SH flag*/false),
-                5, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_UNKNOWN_DMAC.add(BigInteger.valueOf(elanTag)), getMatchesForElanTag(elanTag, /*SH flag*/false),
-                getInstructionsForOutGroup(ElanUtils.getElanRemoteBCGID(elanTag)));
+            5, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_UNKNOWN_DMAC.add(BigInteger.valueOf(elanTag)), getMatchesForElanTag(elanTag, /*SH flag*/false),
+            getInstructionsForOutGroup(ElanUtils.getElanRemoteBCGID(elanTag)));
 
-        mdsalManager.installFlow(interfaceInfo.getDpId(), flowEntity);
+        elanServiceProvider.getMdsalManager().addFlowToTx(dpId, flowEntity, writeFlowGroupTx);
 
         // only if vni is present in elanInfo, perform the following
         if (elanInfo.getVni() != null && elanInfo.getVni() != 0) {
-           Flow flowEntity2 = MDSALUtil.buildFlowNew(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, getUnknownDmacFlowRef(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag, /*SH flag*/true),
+            Flow flowEntity2 = MDSALUtil.buildFlowNew(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, getUnknownDmacFlowRef(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag, /*SH flag*/true),
                 5, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_UNKNOWN_DMAC.add(BigInteger.valueOf(elanTag)), getMatchesForElanTag(elanTag, /*SH flag*/true),
                 getInstructionsForOutGroup(ElanUtils.getElanLocalBCGID(elanTag)));
-           mdsalManager.installFlow(interfaceInfo.getDpId(), flowEntity2);
+            elanServiceProvider.getMdsalManager().addFlowToTx(dpId, flowEntity2, writeFlowGroupTx);
         }
 
     }
 
-
-    private void removeStaticELanFlows(final ElanInstance elanInfo, final InterfaceInfo interfaceInfo) {
-        BigInteger dpId = interfaceInfo.getDpId();
-        /*
-         * If there are not elan ports, remove the unknown smac and default dmac
-         * flows
-         */
-        DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanInfo.getElanInstanceName(), dpId);
-        if (dpnInterfaces == null || dpnInterfaces.getInterfaces() == null || dpnInterfaces.getInterfaces().isEmpty()) {
-            // No more Elan Interfaces in this DPN
-            logger.debug("deleting the elan: {} present on dpId: {}", elanInfo.getElanInstanceName(), dpId);
-            removeDefaultTermFlow(dpId, elanInfo.getElanTag());
-            removeDefaultTermFlow(dpId, interfaceInfo.getInterfaceTag());
-            removeUnknownDmacFlow(dpId, elanInfo);
-            removeElanBroadcastGroup(elanInfo, interfaceInfo);
-            removeLocalBroadcastGroup(elanInfo, interfaceInfo);
-            if ( elanInfo.getVni() != null && elanInfo.getVni().longValue() != 0 ) {
-                unsetExternalTunnelTable(dpId, elanInfo);
-            }
-            removeFilterEqualsTable(elanInfo, interfaceInfo);
-        } else {
-            setupElanBroadcastGroups(elanInfo, dpId);
-            setupLocalBroadcastGroups(elanInfo, interfaceInfo);
-            removeFilterEqualsTable(elanInfo, interfaceInfo);
-        }
-    }
-
-    private void removeUnknownDmacFlow(BigInteger dpId, ElanInstance elanInfo) {
-//        Flow flow = getUnknownDmacFlowEntity(dpId, elanInfo);
-//        mdsalManager.removeFlow(dpId, flow);
+    private void removeUnknownDmacFlow(BigInteger dpId, ElanInstance elanInfo, WriteTransaction deleteFlowGroupTx) {
+        //        Flow flow = getUnknownDmacFlowEntity(dpId, elanInfo);
+        //        mdsalManager.removeFlow(dpId, flow);
         Flow flow = new FlowBuilder().setId(new FlowId(getUnknownDmacFlowRef(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE,
-                                                                             elanInfo.getElanTag(), /*SH flag*/ false)))
-                                     .setTableId(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE)
-                                     .build();
-        mdsalManager.removeFlow(dpId, flow);
+            elanInfo.getElanTag(), /*SH flag*/ false)))
+            .setTableId(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE)
+            .build();
+        elanServiceProvider.getMdsalManager().removeFlowToTx(dpId, flow, deleteFlowGroupTx);
 
         if ( elanInfo.getVni() != null && elanInfo.getVni() > 0 ) {
-           Flow flow2 = new FlowBuilder().setId(new FlowId(getUnknownDmacFlowRef(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE,
-                                                                                elanInfo.getElanTag(), /*SH flag*/ true)))
-                                        .setTableId(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE)
-                                        .build();
-           mdsalManager.removeFlow(dpId, flow2);
+            Flow flow2 = new FlowBuilder().setId(new FlowId(getUnknownDmacFlowRef(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE,
+                elanInfo.getElanTag(), /*SH flag*/ true)))
+                .setTableId(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE)
+                .build();
+            elanServiceProvider.getMdsalManager().removeFlowToTx(dpId, flow2, deleteFlowGroupTx);
         }
 
 
@@ -1014,33 +969,25 @@ public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterfa
         ElanUtils.removeTerminatingServiceAction(dpId, (int) elanTag);
     }
 
-    private void bindService(ElanInstance elanInfo, String interfaceName) {
-       // interfaceManager.bindService(interfaceName, ElanUtils.getServiceInfo(elanInfo.getElanInstanceName(), elanInfo.getElanTag(), interfaceName));
+    private void bindService(ElanInstance elanInfo, String interfaceName, WriteTransaction tx) {
+        // interfaceManager.bindService(interfaceName, ElanUtils.getServiceInfo(elanInfo.getElanInstanceName(), elanInfo.getElanTag(), interfaceName));
 
         int priority = ElanConstants.ELAN_SERVICE_PRIORITY;
         int instructionKey = 0;
-        List<Instruction> instructions = new ArrayList<>();
+        List<Instruction> instructions = new ArrayList<Instruction>();
         instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(ElanUtils.getElanMetadataLabel(elanInfo.getElanTag()), MetaDataUtil.METADATA_MASK_SERVICE, ++instructionKey));
         instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(ElanConstants.ELAN_SMAC_TABLE, ++instructionKey));
         BoundServices
-                serviceInfo =
-                ElanUtils.getBoundServices(String.format("%s.%s.%s", "vpn",elanInfo.getElanInstanceName(), interfaceName),
-                        ElanConstants.ELAN_SERVICE_INDEX, priority,
-                        ElanConstants.COOKIE_ELAN_INGRESS_TABLE, instructions);
-        ElanUtils.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
-                ElanUtils.buildServiceId(interfaceName, ElanConstants.ELAN_SERVICE_INDEX), serviceInfo);
-    }
-
-    private void unbindService(ElanInstance elanInfo, String interfaceName) {
-        ElanUtils.delete(broker, LogicalDatastoreType.CONFIGURATION,
-                ElanUtils.buildServiceId(interfaceName,ElanConstants.ELAN_SERVICE_INDEX),
-                ElanUtils.DEFAULT_CALLBACK);
+            serviceInfo =
+            ElanUtils.getBoundServices(String.format("%s.%s.%s", "vpn",elanInfo.getElanInstanceName(), interfaceName),
+                ElanConstants.ELAN_SERVICE_INDEX, priority,
+                ElanConstants.COOKIE_ELAN_INGRESS_TABLE, instructions);
+        tx.put(LogicalDatastoreType.CONFIGURATION,
+            ElanUtils.buildServiceId(interfaceName, ElanConstants.ELAN_SERVICE_INDEX), serviceInfo, true);
     }
 
-    private void unbindService(ElanInstance elanInfo, String interfaceName, int vlanId) {
-        ElanUtils.delete(broker, LogicalDatastoreType.CONFIGURATION,
-                ElanUtils.buildServiceId(interfaceName,ElanConstants.ELAN_SERVICE_INDEX),
-                ElanUtils.DEFAULT_CALLBACK);
+    private void unbindService(ElanInstance elanInfo, String interfaceName, WriteTransaction tx) {
+        tx.delete(LogicalDatastoreType.CONFIGURATION, ElanUtils.buildServiceId(interfaceName,ElanConstants.ELAN_SERVICE_INDEX));
     }
 
     private String getFlowRef(long tableId, long elanTag) {
@@ -1052,20 +999,21 @@ public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterfa
     }
 
     private List<Action> getInterfacePortActions(InterfaceInfo interfaceInfo) {
-        List<Action> listAction = new ArrayList<>();
+        List<Action> listAction = new ArrayList<Action>();
         int actionKey = 0;
         listAction.add((new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[] {BigInteger.valueOf(interfaceInfo.getInterfaceTag())}, actionKey)).buildAction());
         actionKey++;
         listAction.add((new ActionInfo(ActionType.nx_resubmit,
-                new String[] {String.valueOf(ElanConstants.ELAN_FILTER_EQUALS_TABLE)}, actionKey)).buildAction());
+            new String[] {String.valueOf(ElanConstants.ELAN_FILTER_EQUALS_TABLE)}, actionKey)).buildAction());
         return listAction;
     }
 
-    private void updateElanDpnInterfacesList(String elanInstanceName, BigInteger dpId, List<String> interfaceNames) {
+    private DpnInterfaces updateElanDpnInterfacesList(String elanInstanceName, BigInteger dpId, List<String> interfaceNames, WriteTransaction tx) {
         DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId)
-                .setInterfaces(interfaceNames).setKey(new DpnInterfacesKey(dpId)).build();
-        MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId),
-                dpnInterface);
+            .setInterfaces(interfaceNames).setKey(new DpnInterfacesKey(dpId)).build();
+        tx.put(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId),
+            dpnInterface, true);
+        return dpnInterface;
     }
 
     /**
@@ -1076,44 +1024,44 @@ public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterfa
      * @param dpId
      *            the dp id
      */
-    private void deleteElanDpnInterface(String elanInstanceName, BigInteger dpId) {
-        MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL,
-                ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId));
+    private void deleteElanDpnInterface(String elanInstanceName, BigInteger dpId, WriteTransaction tx) {
+        tx.delete(LogicalDatastoreType.OPERATIONAL,
+            ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId));
     }
 
-    private List<String> createElanInterfacesList(String elanInstanceName, String interfaceName, BigInteger dpId) {
-        List<String> interfaceNames = new ArrayList<>();
+    private DpnInterfaces createElanInterfacesList(String elanInstanceName, String interfaceName, BigInteger dpId, WriteTransaction tx) {
+        List<String> interfaceNames = new ArrayList<String>();
         interfaceNames.add(interfaceName);
         DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId)
-                .setInterfaces(interfaceNames).setKey(new DpnInterfacesKey(dpId)).build();
-        MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId),
-                dpnInterface);
-        return interfaceNames;
+            .setInterfaces(interfaceNames).setKey(new DpnInterfacesKey(dpId)).build();
+        tx.put(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId),
+            dpnInterface, true);
+        return dpnInterface;
     }
 
-    private void createElanInterfaceTablesList(String interfaceName) {
+    private void createElanInterfaceTablesList(String interfaceName, WriteTransaction tx) {
         InstanceIdentifier<ElanInterfaceMac> elanInterfaceMacTables = ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName);
-        Optional<ElanInterfaceMac> interfaceMacTables = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanInterfaceMacTables);
+        Optional<ElanInterfaceMac> interfaceMacTables = ElanUtils.read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, elanInterfaceMacTables);
         // Adding new Elan Interface Port to the operational DataStore without Static-Mac Entries..
-        if(!interfaceMacTables.isPresent()) {
+        if (!interfaceMacTables.isPresent()) {
             ElanInterfaceMac elanInterfaceMacTable = new ElanInterfaceMacBuilder().setElanInterface(interfaceName).setKey(new ElanInterfaceMacKey(interfaceName)).build();
-            MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName),
-                    elanInterfaceMacTable);
+            tx.put(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName),
+                elanInterfaceMacTable, true);
         }
     }
 
-    private void createElanStateList(String elanInstanceName, String interfaceName) {
+    private void createElanStateList(String elanInstanceName, String interfaceName, WriteTransaction tx) {
         InstanceIdentifier<Elan> elanInstance = ElanUtils.getElanInstanceOperationalDataPath(elanInstanceName);
-        Optional<Elan> elanInterfaceLists = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanInstance);
+        Optional<Elan> elanInterfaceLists = ElanUtils.read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, elanInstance);
         // Adding new Elan Interface Port to the operational DataStore without Static-Mac Entries..
-        if(elanInterfaceLists.isPresent()) {
+        if (elanInterfaceLists.isPresent()) {
             List<String> interfaceLists = elanInterfaceLists.get().getElanInterfaces();
-            if(interfaceLists == null) {
+            if (interfaceLists == null) {
                 interfaceLists = new ArrayList<>();
             }
             interfaceLists.add(interfaceName);
             Elan elanState = new ElanBuilder().setName(elanInstanceName).setElanInterfaces(interfaceLists).setKey(new ElanKey(elanInstanceName)).build();
-            MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanInstanceName), elanState);
+            tx.put(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanInstanceName), elanState, true);
         }
     }
 
@@ -1124,53 +1072,9 @@ public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterfa
         return interfaceInfo.getAdminState() == InterfaceInfo.InterfaceAdminState.ENABLED;
     }
 
-    protected void updatedIfPrimaryAttributeChanged(ElanInterface elanInterface, boolean isUpdated) {
-        String interfaceName = elanInterface.getName();
-        InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
-        BigInteger dpId = interfaceInfo.getDpId();
-        InstanceIdentifier<ElanInterfaceMac> elanInterfaceId = ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName);
-        Optional<ElanInterfaceMac> existingElanInterface = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanInterfaceId);
-        ElanInstance elanInfo = ElanUtils.getElanInstanceByName(elanInterface.getElanInstanceName());
-
-        if(!existingElanInterface.isPresent()) {
-            return;
-        }
-
-        List<MacEntry> macEntries = existingElanInterface.get().getMacEntry();
-        if(macEntries != null && !macEntries.isEmpty()) {
-            for (MacEntry macEntry : macEntries) {
-                if(isUpdated) {
-                    ElanUtils.setupMacFlows(elanInfo, interfaceInfo, ElanConstants.STATIC_MAC_TIMEOUT, macEntry.getMacAddress().getValue());
-                } else {
-                    ElanUtils.deleteMacFlows(elanInfo, interfaceInfo, macEntry);
-                }
-            }
-        }
-
-        InstanceIdentifier<DpnInterfaces> dpnInterfaceId = ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInterface.getElanInstanceName(), interfaceInfo.getDpId());
-        Optional<DpnInterfaces> dpnInterfaces =  ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, dpnInterfaceId);
-        List<String> interfaceLists = dpnInterfaces.get().getInterfaces();
-
-        if(isUpdated) {
-            interfaceLists.add(elanInterface.getName());
-        } else {
-            interfaceLists.remove(elanInterface.getName());
-        }
-
-        DpnInterfaces  updateDpnInterfaces = new DpnInterfacesBuilder().setInterfaces(interfaceLists).setDpId(dpId).setKey(new DpnInterfacesKey(dpId)).build();
-        MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, dpnInterfaceId, updateDpnInterfaces);
-
-        if(isUpdated) {
-            installFlowsAndGroups(elanInfo, interfaceInfo);
-        } else {
-            removeStaticELanFlows(elanInfo, interfaceInfo);
-            unbindService(elanInfo, interfaceName);
-        }
-    }
-
     public void handleInternalTunnelStateEvent(BigInteger srcDpId, BigInteger dstDpId) {
         ElanDpnInterfaces dpnInterfaceLists =  ElanUtils.getElanDpnInterfacesList();
-        if(dpnInterfaceLists == null) {
+        if (dpnInterfaceLists == null) {
             return;
         }
         List<ElanDpnInterfacesList> elanDpnIf = dpnInterfaceLists.getElanDpnInterfacesList();
@@ -1178,27 +1082,27 @@ public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterfa
             int cnt = 0;
             String elanName = elanDpns.getElanInstanceName();
             List<DpnInterfaces> dpnInterfaces = elanDpns.getDpnInterfaces();
-            if(dpnInterfaces == null) {
-               continue;
+            if (dpnInterfaces == null) {
+                continue;
             }
             for (DpnInterfaces dpnIf : dpnInterfaces) {
-               if(dpnIf.getDpId().equals(srcDpId) || dpnIf.getDpId().equals(dstDpId)) {
-                   cnt++;
+                if (dpnIf.getDpId().equals(srcDpId) || dpnIf.getDpId().equals(dstDpId)) {
+                    cnt++;
                 }
             }
-            if(cnt == 2) {
+            if (cnt == 2) {
                 logger.debug("Elan instance:{} is present b/w srcDpn:{} and dstDpn:{}", elanName, srcDpId, dstDpId);
                 ElanInstance elanInfo = ElanUtils.getElanInstanceByName(elanName);
                 // update Remote BC Group
                 setupElanBroadcastGroups(elanInfo, srcDpId);
 
-                DpnInterfaces dpnInterface = ElanUtils.getElanInterfaceInfoByElanDpn(elanName, srcDpId);
+                DpnInterfaces dpnInterface = ElanUtils.getElanInterfaceInfoByElanDpn(elanName, dstDpId);
                 Set<String> interfaceLists = new HashSet<>();
                 interfaceLists.addAll(dpnInterface.getInterfaces());
                 for(String ifName : interfaceLists) {
-                    InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(ifName);
+                    InterfaceInfo interfaceInfo = elanServiceProvider.getInterfaceManager().getInterfaceInfo(ifName);
                     if (isOperational(interfaceInfo)) {
-                        elanInterfaceManager.installDMacAddressTables(elanInfo, interfaceInfo, dstDpId);
+                        installDMacAddressTables(elanInfo, interfaceInfo, srcDpId);
                     }
                 }
             }
@@ -1245,7 +1149,7 @@ public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterfa
 
             DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId);
             if (dpnInterfaces == null || dpnInterfaces.getInterfaces() == null
-                    || dpnInterfaces.getInterfaces().isEmpty()) {
+                || dpnInterfaces.getInterfaces().isEmpty()) {
                 continue;
             }
             logger.debug("Elan instance:{} is present in Dpn:{} ", elanName, dpId);
@@ -1255,7 +1159,7 @@ public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterfa
             ElanL2GatewayUtils.installL2gwDeviceMacsInDpn(dpId, externalNodeId, elanInfo);
             // Install dpn macs on external device
             ElanL2GatewayUtils.installDpnMacsInL2gwDevice(elanName, new HashSet<>(dpnInterfaces.getInterfaces()), dpId,
-                    externalNodeId);
+                externalNodeId);
         }
         logger.info("Handled ExternalTunnelStateEvent for {}", externalTunnel);
     }
@@ -1274,96 +1178,41 @@ public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterfa
             String srcDevice = externalTunnel.getDestinationDevice();
             String destDevice = externalTunnel.getSourceDevice();
             ExternalTunnel otherEndPointExtTunnel = ElanUtils.getExternalTunnel(srcDevice, destDevice,
-                    LogicalDatastoreType.CONFIGURATION);
+                LogicalDatastoreType.CONFIGURATION);
             if (logger.isTraceEnabled()) {
                 logger.trace("Validating external tunnel state: src tunnel {}, dest tunnel {}", externalTunnel,
-                        otherEndPointExtTunnel);
+                    otherEndPointExtTunnel);
             }
             if (otherEndPointExtTunnel != null) {
                 boolean otherEndPointInterfaceOperational = ElanUtils
-                        .isInterfaceOperational(otherEndPointExtTunnel.getTunnelInterfaceName(), broker);
+                    .isInterfaceOperational(otherEndPointExtTunnel.getTunnelInterfaceName(), elanServiceProvider.getBroker());
                 if (otherEndPointInterfaceOperational) {
                     return true;
                 } else {
                     logger.debug("Other end [{}] of the external tunnel is not yet UP for {}",
-                            otherEndPointExtTunnel.getTunnelInterfaceName(), externalTunnel);
+                        otherEndPointExtTunnel.getTunnelInterfaceName(), externalTunnel);
                 }
             }
         }
         return false;
     }
 
-    public void handleInterfaceUpdated(InterfaceInfo interfaceInfo, ElanInstance elanInstance, boolean isStateUp) {
-        BigInteger dpId = interfaceInfo.getDpId();
-        String elanName = elanInstance.getElanInstanceName();
-        String ifName = interfaceInfo.getInterfaceName();
-        logger.trace("Handling interface update event for interface with info {} , state {}", interfaceInfo, isStateUp);
-        if(isStateUp) {
-
-            DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId);
-            if(dpnInterfaces == null) {
-                createElanInterfacesList(elanName, interfaceInfo.getInterfaceName(), dpId);
-            } else {
-              List<String> dpnElanInterfaces = dpnInterfaces.getInterfaces();
-                dpnElanInterfaces.add(interfaceInfo.getInterfaceName());
-                DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId)
-                        .setInterfaces(dpnElanInterfaces).setKey(new DpnInterfacesKey(dpId)).build();
-                MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnInterfaceOperationalDataPath(elanName, interfaceInfo.getDpId()), dpnInterface);
-            }
-
-            logger.trace("ElanInterface Service is installed for interface:{}", ifName);
-            elanInterfaceManager.installFlowsAndGroups(elanInstance, interfaceInfo);
-            elanInterfaceManager.installMacAddressTables(elanInstance, interfaceInfo);
-
-            if (elanInstance.getVni() != null && elanInstance.getVni() != 0) {
-                List<PhysAddress> macAddresses = ElanUtils
-                        .getElanInterfaceMacAddresses(interfaceInfo.getInterfaceName());
-                if (macAddresses != null && !macAddresses.isEmpty()) {
-                    ElanL2GatewayUtils.scheduleAddDpnMacInExtDevices(elanInstance.getElanInstanceName(),
-                            dpId, macAddresses);
-                }
-            }
-        } else {
-
-            DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId);
-            if(dpnInterfaces != null) {
-                List<String> dpnElanInterfaces = dpnInterfaces.getInterfaces();
-                dpnElanInterfaces.remove(interfaceInfo.getInterfaceName());
-                DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId)
-                        .setInterfaces(dpnElanInterfaces).setKey(new DpnInterfacesKey(dpId)).build();
-                MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnInterfaceOperationalDataPath(elanName, interfaceInfo.getDpId()), dpnInterface);
-            }
-            logger.trace("ElanInterface Service is removed for the interface:{}", ifName);
-            elanInterfaceManager.removeMacAddressTables(elanInstance, interfaceInfo);
-            elanInterfaceManager.removeFlowsAndGroups(elanInstance, interfaceInfo);
-
-            // Removing MACs from External Devices belonging to this ELAN
-            if (elanInstance.getVni() != null && elanInstance.getVni() != 0) {
-                List<PhysAddress> macAddresses = ElanUtils
-                        .getElanInterfaceMacAddresses(interfaceInfo.getInterfaceName());
-                if (macAddresses != null && !macAddresses.isEmpty()) {
-                    ElanL2GatewayUtils.removeMacsFromElanExternalDevices(elanInstance, macAddresses);
-                }
-            }
-        }
-    }
-
     private List<MatchInfo> getMatchesForFilterEqualsLPortTag(int LportTag) {
-        List<MatchInfo> mkMatches = new ArrayList<>();
+        List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
         // Matching metadata
         mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
-                MetaDataUtil.getLportTagMetaData(LportTag),
-                MetaDataUtil.METADATA_MASK_LPORT_TAG }));
+            MetaDataUtil.getLportTagMetaData(LportTag),
+            MetaDataUtil.METADATA_MASK_LPORT_TAG }));
         mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(LportTag)}));
         return mkMatches;
     }
 
 
     private List<MatchInfo> getTunnelIdMatchForFilterEqualsLPortTag(int LportTag) {
-        List<MatchInfo> mkMatches = new ArrayList<>();
+        List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
         // Matching metadata
         mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {
-                BigInteger.valueOf(LportTag)}));
+            BigInteger.valueOf(LportTag)}));
         return mkMatches;
     }
 
@@ -1378,24 +1227,38 @@ public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterfa
     }
 
     public static List<Bucket> getRemoteBCGroupBucketsOfElanL2GwDevices(ElanInstance elanInfo, BigInteger dpnId,
-            int bucketId) {
-        List<Bucket> listBucketInfo = new ArrayList<>();
+                                                                        int bucketId) {
+        List<Bucket> listBucketInfo = new ArrayList<Bucket>();
         ConcurrentMap<String, L2GatewayDevice> map = ElanL2GwCacheUtils
-                .getInvolvedL2GwDevices(elanInfo.getElanInstanceName());
+            .getInvolvedL2GwDevices(elanInfo.getElanInstanceName());
         for (L2GatewayDevice device : map.values()) {
             String interfaceName = ElanL2GatewayUtils.getExternalTunnelInterfaceName(String.valueOf(dpnId),
-                    device.getHwvtepNodeId());
+                device.getHwvtepNodeId());
             if (interfaceName == null) {
                 continue;
             }
             List<Action> listActionInfo = ElanUtils.buildItmEgressActions(interfaceName, elanInfo.getVni());
             listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId,
-                    MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
+                MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
             bucketId++;
         }
         return listBucketInfo;
     }
 
+    public ElanServiceProvider getElanServiceProvider() {
+        return elanServiceProvider;
+    }
+
+    public void setElanServiceProvider(ElanServiceProvider elanServiceProvider) {
+        this.elanServiceProvider = elanServiceProvider;
+    }
+
+
+    @Override
+    protected ElanInterfaceManager getDataTreeChangeListener() {
+        return this;
+    }
+
 }
 
 
index 92bf8878077d6a550a055593111d7fe35cf35bc8..c966e7fef90af9e47a88d49899bad32ee3a1f1fc 100644 (file)
@@ -11,16 +11,12 @@ package org.opendaylight.netvirt.elan.internal;
 import java.math.BigInteger;
 import java.util.List;
 
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
+import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
 import org.opendaylight.netvirt.elan.utils.ElanConstants;
 import org.opendaylight.netvirt.elan.utils.ElanUtils;
-import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
-import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
-import org.opendaylight.genius.mdsalutil.AbstractDataChangeListener;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.Tunnel;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
@@ -30,41 +26,36 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelList;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnel;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class ElanInterfaceStateChangeListener extends AbstractDataChangeListener<Interface> implements AutoCloseable {
-    private DataBroker broker;
-    private IInterfaceManager interfaceManager;
-    private ElanInterfaceManager elanInterfaceManager;
-    private ListenerRegistration<DataChangeListener> listenerRegistration;
+public class ElanInterfaceStateChangeListener extends AsyncDataTreeChangeListenerBase<Interface,ElanInterfaceStateChangeListener> implements AutoCloseable {
+
+    private  ElanServiceProvider elanServiceProvider = null;
+    private static volatile ElanInterfaceStateChangeListener elanInterfaceStateChangeListener = null;
     private static final Logger logger = LoggerFactory.getLogger(ElanInterfaceStateChangeListener.class);
 
-    public ElanInterfaceStateChangeListener(final DataBroker db, final ElanInterfaceManager ifManager) {
-        super(Interface.class);
-        broker = db;
-        elanInterfaceManager = ifManager;
-        registerListener(db);
-    }
 
-    private void registerListener(final DataBroker db) {
-        try {
-            listenerRegistration = broker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
-                    getWildCardPath(), ElanInterfaceStateChangeListener.this, AsyncDataBroker.DataChangeScope.SUBTREE);
-        } catch (final Exception e) {
-            logger.error("Elan Interfaces DataChange listener registration fail!", e);
-            throw new IllegalStateException("ElanInterface registration Listener failed.", e);
-        }
-    }
+    private ElanInterfaceStateChangeListener(ElanServiceProvider elanServiceProvider) {
+        super(Interface.class, ElanInterfaceStateChangeListener.class);
+        this.elanServiceProvider = elanServiceProvider;
+        registerListener(LogicalDatastoreType.OPERATIONAL,this.elanServiceProvider.getBroker());
 
-    private InstanceIdentifier<Interface> getWildCardPath() {
-        return InstanceIdentifier.create(InterfacesState.class).child(Interface.class);
     }
 
-    public void setInterfaceManager(IInterfaceManager interfaceManager) {
-        this.interfaceManager = interfaceManager;
+    public static ElanInterfaceStateChangeListener getElanInterfaceStateChangeListener(
+        ElanServiceProvider elanServiceProvider) {
+        if (elanInterfaceStateChangeListener == null)
+            synchronized (ElanInterfaceStateChangeListener.class) {
+                if (elanInterfaceStateChangeListener == null)
+                {
+                    ElanInterfaceStateChangeListener elanInterfaceStateChangeListener = new ElanInterfaceStateChangeListener(elanServiceProvider);
+                    return elanInterfaceStateChangeListener;
+
+                }
+            }
+        return elanInterfaceStateChangeListener;
     }
 
     @Override
@@ -72,7 +63,7 @@ public class ElanInterfaceStateChangeListener extends AbstractDataChangeListener
         logger.trace("Received interface {} Down event", delIf);
         String interfaceName =  delIf.getName();
         ElanInterface elanInterface = ElanUtils.getElanInterfaceByElanInterfaceName(interfaceName);
-        if(elanInterface == null) {
+        if (elanInterface == null) {
             logger.debug("No Elan Interface is created for the interface:{} ", interfaceName);
             return;
         }
@@ -85,8 +76,8 @@ public class ElanInterfaceStateChangeListener extends AbstractDataChangeListener
         String elanInstanceName = elanInterface.getElanInstanceName();
         ElanInstance elanInstance = ElanUtils.getElanInstanceByName(elanInstanceName);
         DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
-        ElanInterfaceRemoveWorker removeWorker = new ElanInterfaceRemoveWorker(elanInstanceName, elanInstance, 
-                interfaceName, interfaceInfo, elanInterfaceManager);
+        InterfaceRemoveWorkerOnElan removeWorker = new InterfaceRemoveWorkerOnElan(elanInstanceName, elanInstance,
+            interfaceName, interfaceInfo, true, elanServiceProvider.getElanInterfaceManager());
         coordinator.enqueueJob(elanInstanceName, removeWorker, ElanConstants.JOB_MAX_RETRIES);
     }
 
@@ -98,11 +89,13 @@ public class ElanInterfaceStateChangeListener extends AbstractDataChangeListener
             logger.trace("Interface type for interface {} is null", interfaceName);
             return;
         }
-        if(update.getType().equals(Tunnel.class)) {
-            if (update.getOperStatus().equals(Interface.OperStatus.Up)) {
-                InternalTunnel internalTunnel = getTunnelState(interfaceName);
-                if (internalTunnel != null) {
-                    elanInterfaceManager.handleInternalTunnelStateEvent(internalTunnel.getSourceDPN(), internalTunnel.getDestinationDPN());
+        if (update.getType().equals(Tunnel.class)) {
+            if (!original.getOperStatus().equals(Interface.OperStatus.Unknown) && !update.getOperStatus().equals(Interface.OperStatus.Unknown)){
+                if (update.getOperStatus().equals(Interface.OperStatus.Up)) {
+                    InternalTunnel internalTunnel = getTunnelState(interfaceName);
+                    if (internalTunnel != null) {
+                        elanServiceProvider.getElanInterfaceManager().handleInternalTunnelStateEvent(internalTunnel.getSourceDPN(), internalTunnel.getDestinationDPN());
+                    }
                 }
             }
         }
@@ -113,20 +106,20 @@ public class ElanInterfaceStateChangeListener extends AbstractDataChangeListener
         logger.trace("Received interface {} up event", intrf);
         String interfaceName =  intrf.getName();
         ElanInterface elanInterface = ElanUtils.getElanInterfaceByElanInterfaceName(interfaceName);
-        if(elanInterface == null) {
+        if (elanInterface == null) {
             if (intrf.getType() != null && intrf.getType().equals(Tunnel.class)) {
-                if(intrf.getOperStatus().equals(Interface.OperStatus.Up)) {
+                if (intrf.getOperStatus().equals(Interface.OperStatus.Up)) {
                     InternalTunnel internalTunnel = getTunnelState(interfaceName);
                     if (internalTunnel != null) {
-                        elanInterfaceManager.handleInternalTunnelStateEvent(internalTunnel.getSourceDPN(),
-                                internalTunnel.getDestinationDPN());
+                        elanServiceProvider.getElanInterfaceManager().handleInternalTunnelStateEvent(internalTunnel.getSourceDPN(),
+                            internalTunnel.getDestinationDPN());
                     }
                 }
             }
             return;
         }
         InstanceIdentifier<ElanInterface> elanInterfaceId = ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName);
-        elanInterfaceManager.add(elanInterfaceId, elanInterface);
+        elanServiceProvider.getElanInterfaceManager().add(elanInterfaceId, elanInterface);
     }
 
     @Override
@@ -136,7 +129,7 @@ public class ElanInterfaceStateChangeListener extends AbstractDataChangeListener
 
     public  InternalTunnel getTunnelState(String interfaceName) {
         InternalTunnel internalTunnel = null;
-        TunnelList tunnelList = ElanUtils.buildInternalTunnel(broker);
+        TunnelList tunnelList = ElanUtils.buildInternalTunnel(elanServiceProvider.getBroker());
         if (tunnelList != null && tunnelList.getInternalTunnel() != null) {
             List<InternalTunnel> internalTunnels = tunnelList.getInternalTunnel();
             for (InternalTunnel tunnel : internalTunnels) {
@@ -148,4 +141,15 @@ public class ElanInterfaceStateChangeListener extends AbstractDataChangeListener
         }
         return internalTunnel;
     }
+    @Override
+    protected InstanceIdentifier<Interface> getWildCardPath() {
+        return InstanceIdentifier.create(InterfacesState.class).child(Interface.class);
+    }
+
+
+    @Override
+    protected ElanInterfaceStateChangeListener getDataTreeChangeListener() {
+        return this;
+    }
+
 }
index 0730151ce53ac6ac4847c79ce911272fcd34e597..1b30afad17972de63a3dfc877879d9939c1dedf0 100644 (file)
@@ -25,24 +25,44 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class ElanInterfaceStateClusteredListener extends
-        AsyncClusteredDataChangeListenerBase<Interface, ElanInterfaceStateClusteredListener> implements AutoCloseable {
-    private DataBroker broker;
-    private ElanInterfaceManager elanInterfaceManager;
+    AsyncClusteredDataChangeListenerBase<Interface, ElanInterfaceStateClusteredListener> implements AutoCloseable {
+    public  ElanServiceProvider getElanServiceProvider() {
+        return elanServiceProvider;
+    }
+    public void setElanServiceProvider(ElanServiceProvider elanServiceProvider) {
+        this.elanServiceProvider = elanServiceProvider;
+    }
+
+    private  ElanServiceProvider elanServiceProvider = null;
+    private static volatile ElanInterfaceStateClusteredListener elanInterfaceStateClusteredListener = null;
     private ListenerRegistration<DataChangeListener> listenerRegistration;
 
     private static final Logger logger = LoggerFactory.getLogger(ElanInterfaceStateClusteredListener.class);
 
-    public ElanInterfaceStateClusteredListener(final DataBroker db, final ElanInterfaceManager ifManager) {
+
+    public ElanInterfaceStateClusteredListener(ElanServiceProvider elanServiceProvider) {
         super(Interface.class, ElanInterfaceStateClusteredListener.class);
-        broker = db;
-        elanInterfaceManager = ifManager;
-        registerListener(db);
+        this.elanServiceProvider = elanServiceProvider;
+        registerListener(this.elanServiceProvider.getBroker());
+    }
+    public static ElanInterfaceStateClusteredListener getElanInterfaceStateClusteredListener(
+        ElanServiceProvider elanServiceProvider) {
+        if (elanInterfaceStateClusteredListener == null)
+            synchronized (ElanInterfaceStateClusteredListener.class) {
+                if (elanInterfaceStateClusteredListener == null)
+                {
+                    ElanInterfaceStateClusteredListener elanInterfaceStateClusteredListener = new ElanInterfaceStateClusteredListener(elanServiceProvider);
+                    return elanInterfaceStateClusteredListener;
+
+                }
+            }
+        return elanInterfaceStateClusteredListener;
     }
 
     private void registerListener(final DataBroker db) {
         try {
-            listenerRegistration = broker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
-                    getWildCardPath(), ElanInterfaceStateClusteredListener.this, AsyncDataBroker.DataChangeScope.BASE);
+            listenerRegistration = elanServiceProvider.getBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+                getWildCardPath(), ElanInterfaceStateClusteredListener.this, AsyncDataBroker.DataChangeScope.BASE);
         } catch (final Exception e) {
             logger.error("Elan Interfaces DataChange listener registration fail!", e);
             throw new IllegalStateException("ElanInterface registration Listener failed.", e);
@@ -94,10 +114,11 @@ public class ElanInterfaceStateClusteredListener extends
         ExternalTunnel externalTunnel = ElanUtils.getExternalTunnel(interfaceName, LogicalDatastoreType.CONFIGURATION);
         if (externalTunnel != null) {
             logger.debug("handling external tunnel update event for ext device dst {}  src {} ",
-                    externalTunnel.getDestinationDevice(), externalTunnel.getSourceDevice());
-            elanInterfaceManager.handleExternalTunnelStateEvent(externalTunnel, update);
+                externalTunnel.getDestinationDevice(), externalTunnel.getSourceDevice());
+            elanServiceProvider.getElanInterfaceManager().handleExternalTunnelStateEvent(externalTunnel, update);
         } else {
             logger.trace("External tunnel not found with interfaceName: {}", interfaceName);
         }
     }
+
 }
index 25c530be1143555500a3a4854fc134ad3d3372c8..8758cfca69978febfa9fdf642963c0d0847a8466 100644 (file)
@@ -30,22 +30,32 @@ import java.util.List;
 public class ElanNodeListener extends AbstractDataChangeListener<Node> {
 
     private static final Logger logger = LoggerFactory.getLogger(ElanNodeListener.class);
-
-    private IMdsalApiManager mdsalManager;
+    private static volatile ElanNodeListener elanNodeListener = null;
+    private ElanServiceProvider elanServiceProvider = null;
     private ListenerRegistration<DataChangeListener> listenerRegistration;
-    private final DataBroker broker;
+    public static ElanNodeListener getElanNodeListener(ElanServiceProvider elanServiceProvider) {
+        if (elanNodeListener == null)
+            synchronized (ElanNodeListener.class) {
+                if (elanNodeListener == null)
+                {
+                    ElanNodeListener elanNodeListener = new ElanNodeListener(elanServiceProvider);
+                    return elanNodeListener;
+
+                }
+            }
+        return elanNodeListener;
+    }
 
-    public ElanNodeListener(final DataBroker db, IMdsalApiManager mdsalManager) {
+    public ElanNodeListener(ElanServiceProvider elanServiceProvider) {
         super(Node.class);
-        broker = db;
-        this.mdsalManager = mdsalManager;
-        registerListener(db);
+        this.elanServiceProvider= elanServiceProvider;
+        registerListener(this.elanServiceProvider.getBroker());
     }
 
     private void registerListener(final DataBroker db) {
         try {
             listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
-                    getWildCardPath(), ElanNodeListener.this, AsyncDataBroker.DataChangeScope.SUBTREE);
+                getWildCardPath(), ElanNodeListener.this, AsyncDataBroker.DataChangeScope.SUBTREE);
         } catch (final Exception e) {
             logger.error("ElanNodeListener: DataChange listener registration fail!", e);
             throw new IllegalStateException("ElanNodeListener: registration Listener failed.", e);
@@ -71,7 +81,7 @@ public class ElanNodeListener extends AbstractDataChangeListener<Node> {
     protected void add(InstanceIdentifier<Node> identifier, Node add) {
         NodeId nodeId = add.getId();
         String[] node =  nodeId.getValue().split(":");
-        if(node.length < 2) {
+        if (node.length < 2) {
             logger.warn("Unexpected nodeId {}", nodeId.getValue());
             return;
         }
@@ -85,32 +95,34 @@ public class ElanNodeListener extends AbstractDataChangeListener<Node> {
     }
 
     private void setupTableMissSmacFlow(BigInteger dpId) {
-        List<MatchInfo> mkMatches = new ArrayList<>();
-        List<InstructionInfo> mkInstructions = new ArrayList<>();
-        List <ActionInfo> actionsInfos = new ArrayList<>();
+        List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
+        List<InstructionInfo> mkInstructions = new ArrayList<InstructionInfo>();
+        List <ActionInfo> actionsInfos = new ArrayList <ActionInfo> ();
         actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[] {}));
         mkInstructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
         mkInstructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { ElanConstants.ELAN_DMAC_TABLE }));
 
         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, ElanConstants.ELAN_SMAC_TABLE, getTableMissFlowRef(ElanConstants.ELAN_SMAC_TABLE),
-                0, "ELAN sMac Table Miss Flow", 0, 0, ElanConstants.COOKIE_ELAN_KNOWN_SMAC,
-                mkMatches, mkInstructions);
-        mdsalManager.installFlow(flowEntity);
+            0, "ELAN sMac Table Miss Flow", 0, 0, ElanConstants.COOKIE_ELAN_KNOWN_SMAC,
+            mkMatches, mkInstructions);
+        this.elanServiceProvider.getMdsalManager().installFlow(flowEntity);
     }
 
     private void setupTableMissDmacFlow(BigInteger dpId) {
-        List<MatchInfo> mkMatches = new ArrayList<>();
+        List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
 
-        List<InstructionInfo> mkInstructions = new ArrayList<>();
+        List<InstructionInfo> mkInstructions = new ArrayList<InstructionInfo>();
         mkInstructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { ElanConstants.ELAN_UNKNOWN_DMAC_TABLE }));
 
         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, ElanConstants.ELAN_DMAC_TABLE, getTableMissFlowRef(ElanConstants.ELAN_DMAC_TABLE),
-                0, "ELAN dMac Table Miss Flow", 0, 0, ElanConstants.COOKIE_ELAN_KNOWN_DMAC,
-                mkMatches, mkInstructions);
-        mdsalManager.installFlow(flowEntity);
+            0, "ELAN dMac Table Miss Flow", 0, 0, ElanConstants.COOKIE_ELAN_KNOWN_DMAC,
+            mkMatches, mkInstructions);
+        this.elanServiceProvider.getMdsalManager().installFlow(flowEntity);
     }
 
     private String getTableMissFlowRef(long tableId) {
         return new StringBuffer().append(tableId).toString();
     }
+
+
 }
index bdbe63169b4a16699df5f552a4e1ccc13e642d5e..24cf44ef6a315b391b909f407fa91568f5426d42 100755 (executable)
@@ -11,10 +11,11 @@ import java.math.BigInteger;
 
 import org.opendaylight.controller.liblldp.NetUtils;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.netvirt.elan.l2gw.utils.ElanL2GatewayUtils;
 import org.opendaylight.netvirt.elan.utils.ElanConstants;
 import org.opendaylight.netvirt.elan.utils.ElanUtils;
-import org.opendaylight.netvirt.elan.l2gw.utils.ElanL2GatewayUtils;
 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
@@ -43,24 +44,35 @@ import java.util.Arrays;
 @SuppressWarnings("deprecation")
 public class ElanPacketInHandler implements PacketProcessingListener {
 
-    private final DataBroker broker;
-    private IInterfaceManager interfaceManager;
 
+    private ElanServiceProvider elanServiceProvider = null;
+    private static volatile ElanPacketInHandler elanPacketInHandler = null;
     private static final Logger logger = LoggerFactory.getLogger(ElanPacketInHandler.class);
 
-    public ElanPacketInHandler(DataBroker dataBroker) {
-        broker = dataBroker;
+    public ElanPacketInHandler(ElanServiceProvider elanServiceProvider) {
+
+        this.elanServiceProvider = elanServiceProvider;
     }
+    public static ElanPacketInHandler getElanPacketInHandler(ElanServiceProvider elanServiceProvider) {
+        if (elanPacketInHandler == null) {
+            synchronized (ElanPacketInHandler.class) {
+                if (elanPacketInHandler == null)
+                {
+                    ElanPacketInHandler elanPacketInHandler = new ElanPacketInHandler(elanServiceProvider);
+                    return elanPacketInHandler;
 
-    public void setInterfaceManager(IInterfaceManager interfaceManager) {
-        this.interfaceManager = interfaceManager;
+                }
+            }
+        }
+        return elanPacketInHandler;
     }
 
+
     @Override
     public void onPacketReceived(PacketReceived notification) {
         Class<? extends PacketInReason>  pktInReason =  notification.getPacketInReason();
         short tableId = notification.getTableId().getValue();
-        if(pktInReason == NoMatch.class && tableId == ElanConstants.ELAN_SMAC_TABLE) {
+        if (pktInReason == NoMatch.class && tableId == ElanConstants.ELAN_SMAC_TABLE) {
             try {
                 byte[] data = notification.getPayload();
                 Ethernet res = new Ethernet();
@@ -88,7 +100,7 @@ public class ElanPacketInHandler implements PacketProcessingListener {
                 }
                 String elanName = elanTagName.getName();
                 MacEntry macEntry = ElanUtils.getInterfaceMacEntriesOperationalDataPath(interfaceName, physAddress);
-                if(macEntry != null && macEntry.getInterface() == interfaceName) {
+                if (macEntry != null && macEntry.getInterface() == interfaceName) {
                     BigInteger macTimeStamp = macEntry.getControllerLearnedForwardingEntryTimestamp();
                     if (System.currentTimeMillis() > macTimeStamp.longValue()+2000) {
                         /*
@@ -100,18 +112,18 @@ public class ElanPacketInHandler implements PacketProcessingListener {
                          * of cache is required so that the timestamp is updated).
                          */
                         InstanceIdentifier<MacEntry> macEntryId =  ElanUtils.getInterfaceMacEntriesIdentifierOperationalDataPath(interfaceName, physAddress);
-                        ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, macEntryId);
+                        ElanUtils.delete(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, macEntryId);
                     } else {
                         // Protection time running. Ignore packets for 2 seconds
                         return;
                     }
-                } else if(macEntry != null) {
+                } else if (macEntry != null) {
                     // MAC address has moved. Overwrite the mapping and replace MAC flows
                     long macTimeStamp = macEntry.getControllerLearnedForwardingEntryTimestamp().longValue();
                     if (System.currentTimeMillis() > macTimeStamp+1000) {
 
                         InstanceIdentifier<MacEntry> macEntryId =  ElanUtils.getInterfaceMacEntriesIdentifierOperationalDataPath(interfaceName, physAddress);
-                        ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, macEntryId);
+                        ElanUtils.delete(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, macEntryId);
                         tryAndRemoveInvalidMacEntry(elanName, macEntry);
                     } else {
                         // New FEs flood their packets on all interfaces. This can lead
@@ -123,15 +135,17 @@ public class ElanPacketInHandler implements PacketProcessingListener {
                 BigInteger timeStamp = new BigInteger(String.valueOf((long)System.currentTimeMillis()));
                 macEntry = new MacEntryBuilder().setInterface(interfaceName).setMacAddress(physAddress).setKey(new MacEntryKey(physAddress)).setControllerLearnedForwardingEntryTimestamp(timeStamp).setIsStaticAddress(false).build();
                 InstanceIdentifier<MacEntry> macEntryId = ElanUtils.getInterfaceMacEntriesIdentifierOperationalDataPath(interfaceName, physAddress);
-                MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, macEntryId, macEntry);
+                MDSALUtil.syncWrite(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, macEntryId, macEntry);
                 InstanceIdentifier<MacEntry> elanMacEntryId = ElanUtils.getMacEntryOperationalDataPath(elanName, physAddress);
-                MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, elanMacEntryId, macEntry);
+                MDSALUtil.syncWrite(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, elanMacEntryId, macEntry);
                 ElanInstance elanInstance = ElanUtils.getElanInstanceByName(elanName);
-                ElanUtils.setupMacFlows(elanInstance, interfaceManager.getInterfaceInfo(interfaceName), elanInstance.getMacTimeout(), macAddress);
+                WriteTransaction flowWritetx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
+                ElanUtils.setupMacFlows(elanInstance, elanServiceProvider.getInterfaceManager().getInterfaceInfo(interfaceName), elanInstance.getMacTimeout(), macAddress, flowWritetx);
+                flowWritetx.submit();
 
-                BigInteger dpId = interfaceManager.getDpnForInterface(interfaceName);
+                BigInteger dpId = elanServiceProvider.getInterfaceManager().getDpnForInterface(interfaceName);
                 ElanL2GatewayUtils.scheduleAddDpnMacInExtDevices(elanInstance.getElanInstanceName(), dpId,
-                        Arrays.asList(physAddress));
+                    Arrays.asList(physAddress));
             } catch (Exception e) {
                 logger.trace("Failed to decode packet: {}", e);
             }
@@ -149,18 +163,22 @@ public class ElanPacketInHandler implements PacketProcessingListener {
         ElanInstance elanInfo = ElanUtils.getElanInstanceByName(elanName);
         if (elanInfo == null) {
             logger.warn(String.format("MAC %s is been added (either statically or dynamically) for an invalid Elan %s. "
-                    + "Manual cleanup may be necessary", macEntry.getMacAddress(), elanName));
+                + "Manual cleanup may be necessary", macEntry.getMacAddress(), elanName));
             return;
         }
 
-        InterfaceInfo oldInterfaceLport = interfaceManager.getInterfaceInfo(macEntry.getInterface());
+        InterfaceInfo oldInterfaceLport = elanServiceProvider.getInterfaceManager().getInterfaceInfo(macEntry.getInterface());
         if (oldInterfaceLport == null) {
             logger.warn(String.format("MAC %s is been added (either statically or dynamically) on an invalid Logical Port %s. "
-                    + "Manual cleanup may be necessary", macEntry.getMacAddress(), macEntry.getInterface()));
+                + "Manual cleanup may be necessary", macEntry.getMacAddress(), macEntry.getInterface()));
             return;
         }
-        ElanUtils.deleteMacFlows(elanInfo, oldInterfaceLport, macEntry);
+        WriteTransaction flowDeletetx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
+        ElanUtils.deleteMacFlows(elanInfo, oldInterfaceLport, macEntry, flowDeletetx);
+        flowDeletetx.submit();
         ElanL2GatewayUtils.removeMacsFromElanExternalDevices(elanInfo, Arrays.asList(macEntry.getMacAddress()));
     }
 
+
+
 }
index 1d168f9a48f2d28ec07683ef0204c64dead24a87..4b23d07321c14945ae40e6d002a4992e4b03ffb4 100644 (file)
@@ -20,26 +20,21 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
 import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.netvirt.elan.utils.ElanForwardingEntriesHandler;
+import org.opendaylight.netvirt.elanmanager.api.IElanService;
+import org.opendaylight.netvirt.elanmanager.exceptions.MacNotFoundException;
+import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
 import org.opendaylight.netvirt.elan.l2gw.internal.ElanL2GatewayProvider;
+import org.opendaylight.netvirt.elan.statisitcs.ElanStatisticsImpl;
 import org.opendaylight.netvirt.elan.statusanddiag.ElanStatusMonitor;
 import org.opendaylight.netvirt.elan.utils.ElanClusterUtils;
 import org.opendaylight.netvirt.elan.utils.ElanConstants;
 import org.opendaylight.netvirt.elan.utils.ElanUtils;
-import org.opendaylight.netvirt.elan.statisitcs.ElanStatisticsImpl;
-import org.opendaylight.netvirt.elanmanager.api.IElanService;
-import org.opendaylight.netvirt.elanmanager.exceptions.MacNotFoundException;
-import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
 import org.opendaylight.genius.itm.api.IITMProvider;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
 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.flow.service.rev130819.SalFlowService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
 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;
@@ -52,6 +47,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan
 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.forwarding.entries.MacEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.statistics.rev150824.ElanStatisticsService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
@@ -67,6 +67,62 @@ public class ElanServiceProvider implements BindingAwareProvider, IElanService,
     private OdlInterfaceRpcService interfaceManagerRpcService;
     private ElanInstanceManager elanInstanceManager;
     private ElanForwardingEntriesHandler elanForwardingEntriesHandler;
+    public IdManagerService getIdManager() {
+        return idManager;
+    }
+
+    public ElanForwardingEntriesHandler getElanForwardingEntriesHandler() {
+        return elanForwardingEntriesHandler;
+    }
+
+    public ElanPacketInHandler getElanPacketInHandler() {
+        return elanPacketInHandler;
+    }
+
+    public ElanSmacFlowEventListener getElanSmacFlowEventListener() {
+        return elanSmacFlowEventListener;
+    }
+
+    public ElanInterfaceStateChangeListener getElanInterfaceStateChangeListener() {
+        return elanInterfaceStateChangeListener;
+    }
+
+    public ElanInterfaceStateClusteredListener getInfStateChangeClusteredListener() {
+        return infStateChangeClusteredListener;
+    }
+
+    public ElanDpnInterfaceClusteredListener getElanDpnInterfaceClusteredListener() {
+        return elanDpnInterfaceClusteredListener;
+    }
+
+    public ElanNodeListener getElanNodeListener() {
+        return elanNodeListener;
+    }
+
+    public NotificationService getNotificationService() {
+        return notificationService;
+    }
+
+    public RpcProviderRegistry getRpcProviderRegistry() {
+        return rpcProviderRegistry;
+    }
+
+    public ElanL2GatewayProvider getElanL2GatewayProvider() {
+        return elanL2GatewayProvider;
+    }
+
+    public static ElanStatusMonitor getElanstatusmonitor() {
+        return elanStatusMonitor;
+    }
+
+    public ElanItmEventListener getElanItmEventListener() {
+        return elanItmEventListener;
+    }
+
+    public static Logger getLogger() {
+        return logger;
+    }
+
     private ElanInterfaceManager elanInterfaceManager;
     private ElanPacketInHandler elanPacketInHandler;
     private ElanSmacFlowEventListener elanSmacFlowEventListener;
@@ -80,9 +136,8 @@ public class ElanServiceProvider implements BindingAwareProvider, IElanService,
     private ItmRpcService itmRpcService;
     private DataBroker broker;
     private ElanL2GatewayProvider elanL2GatewayProvider;
-
+    private ElanStatisticsService interfaceStatsService;
     private EntityOwnershipService entityOwnershipService;
-
     private static final ElanStatusMonitor elanStatusMonitor = ElanStatusMonitor.getInstance();
     static DataStoreJobCoordinator dataStoreJobCoordinator;
     private ElanOvsdbNodeListener elanOvsdbNodeListener;
@@ -93,6 +148,10 @@ public class ElanServiceProvider implements BindingAwareProvider, IElanService,
         dataStoreJobCoordinator = ds;
     }
 
+    public void setBroker(DataBroker broker) {
+        this.broker = broker;
+    }
+
     public static DataStoreJobCoordinator getDataStoreJobCoordinator() {
         if (dataStoreJobCoordinator == null) {
             dataStoreJobCoordinator = DataStoreJobCoordinator.getInstance();
@@ -119,61 +178,26 @@ public class ElanServiceProvider implements BindingAwareProvider, IElanService,
             getDataStoreJobCoordinator();
             broker = session.getSALService(DataBroker.class);
 
-            ElanUtils.setDataBroker(broker);
-            ElanUtils.setIfaceMgrRpcService(interfaceManagerRpcService);
-            ElanUtils.setItmRpcService(itmRpcService);
-            ElanUtils.setMdsalManager(mdsalManager);
-
-            elanForwardingEntriesHandler = new ElanForwardingEntriesHandler(broker);
-
-            elanInterfaceManager = ElanInterfaceManager.getElanInterfaceManager();
-            elanInterfaceManager.setInterfaceManager(interfaceManager);
-            elanInterfaceManager.setIdManager(idManager);
-            elanInterfaceManager.setMdSalApiManager(mdsalManager);
-            elanInterfaceManager.setDataBroker(broker);
-            elanInterfaceManager.setInterfaceManagerRpcService(interfaceManagerRpcService);
-            elanInterfaceManager.setElanForwardingEntriesHandler(elanForwardingEntriesHandler);
-
-            elanInstanceManager = ElanInstanceManager.getElanInstanceManager();
-            elanInstanceManager.setDataBroker(broker);
-            elanInstanceManager.setIdManager(idManager);
-            elanInstanceManager.setElanInterfaceManager(elanInterfaceManager);
-            elanInstanceManager.setInterfaceManager(interfaceManager);
-
-
-            elanNodeListener = new ElanNodeListener(broker, mdsalManager);
             elanOvsdbNodeListener = new ElanOvsdbNodeListener(broker, generateIntBridgeMac);
-
-            elanPacketInHandler = new ElanPacketInHandler(broker);
-            elanPacketInHandler.setInterfaceManager(interfaceManager);
-
-
-            elanSmacFlowEventListener = new ElanSmacFlowEventListener(broker);
-            elanSmacFlowEventListener.setMdSalApiManager(mdsalManager);
-            elanSmacFlowEventListener.setInterfaceManager(interfaceManager);
-            elanSmacFlowEventListener.setSalFlowService(session.getRpcService(SalFlowService.class));
-
-
+            ElanUtils.setElanServiceProvider(this);
+            elanForwardingEntriesHandler = ElanForwardingEntriesHandler.getElanForwardingEntriesHandler(this);
+            elanInterfaceManager = ElanInterfaceManager.getElanInterfaceManager(this);
+            elanInstanceManager = ElanInstanceManager.getElanInstanceManager(this);
+            elanNodeListener  = ElanNodeListener.getElanNodeListener(this);
+            elanPacketInHandler = ElanPacketInHandler.getElanPacketInHandler(this);
+            elanSmacFlowEventListener = ElanSmacFlowEventListener.getElanSmacFlowEventListener(this);
             // Initialize statistics rpc provider for elan
-            ElanStatisticsService interfaceStatsService = new ElanStatisticsImpl(broker, interfaceManager,
-                    mdsalManager);
+            interfaceStatsService = ElanStatisticsImpl.getElanStatisticsService(this);
             rpcProviderRegistry.addRpcImplementation(ElanStatisticsService.class, interfaceStatsService);
-
-            elanInterfaceStateChangeListener = new ElanInterfaceStateChangeListener(broker, elanInterfaceManager);
-            elanInterfaceStateChangeListener.setInterfaceManager(interfaceManager);
-
-            infStateChangeClusteredListener = new ElanInterfaceStateClusteredListener(broker, elanInterfaceManager);
-
-            elanDpnInterfaceClusteredListener = new ElanDpnInterfaceClusteredListener(broker, elanInterfaceManager);
-            ElanClusterUtils.setEntityOwnershipService(entityOwnershipService);
-            ElanClusterUtils.setDataStoreJobCoordinator(dataStoreJobCoordinator);
+            elanInterfaceStateChangeListener = ElanInterfaceStateChangeListener.getElanInterfaceStateChangeListener(this);
+            infStateChangeClusteredListener = ElanInterfaceStateClusteredListener.getElanInterfaceStateClusteredListener(this);
+            elanDpnInterfaceClusteredListener = ElanDpnInterfaceClusteredListener.getElanDpnInterfaceClusteredListener(this);
+            ElanClusterUtils.setElanServiceProvider(this);
             this.elanL2GatewayProvider = new ElanL2GatewayProvider(this);
-
-            elanInterfaceManager.registerListener();
-            elanInstanceManager.registerListener();
+            elanInterfaceManager.registerListener(LogicalDatastoreType.CONFIGURATION,broker);
+            elanInstanceManager.registerListener(LogicalDatastoreType.CONFIGURATION,broker);
             notificationService.registerNotificationListener(elanSmacFlowEventListener);
             notificationService.registerNotificationListener(elanPacketInHandler);
-
             elanStatusMonitor.reportStatus("OPERATIONAL");
         } catch (Exception e) {
             logger.error("Error initializing services", e);
@@ -181,6 +205,8 @@ public class ElanServiceProvider implements BindingAwareProvider, IElanService,
         }
     }
 
+
+
     public void setIdManager(IdManagerService idManager) {
         this.idManager = idManager;
     }
@@ -251,7 +277,7 @@ public class ElanServiceProvider implements BindingAwareProvider, IElanService,
 
     private void createIdPool() {
         CreateIdPoolInput createPool = new CreateIdPoolInputBuilder().setPoolName(ElanConstants.ELAN_ID_POOL_NAME)
-                .setLow(ElanConstants.ELAN_ID_LOW_VALUE).setHigh(ElanConstants.ELAN_ID_HIGH_VALUE).build();
+            .setLow(ElanConstants.ELAN_ID_LOW_VALUE).setHigh(ElanConstants.ELAN_ID_HIGH_VALUE).build();
         try {
             Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
             if ((result != null) && (result.get().isSuccessful())) {
@@ -272,29 +298,29 @@ public class ElanServiceProvider implements BindingAwareProvider, IElanService,
                 return true;
             } else {
                 ElanInstance updateElanInstance = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName)
-                        .setDescription(description).setMacTimeout(macTimeout)
-                        .setKey(new ElanInstanceKey(elanInstanceName)).build();
+                    .setDescription(description).setMacTimeout(macTimeout)
+                    .setKey(new ElanInstanceKey(elanInstanceName)).build();
                 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
-                        ElanUtils.getElanInstanceConfigurationDataPath(elanInstanceName), updateElanInstance);
+                    ElanUtils.getElanInstanceConfigurationDataPath(elanInstanceName), updateElanInstance);
                 logger.debug("Updating the Elan Instance {} with MAC TIME-OUT %l and Description %s ",
-                        updateElanInstance, macTimeout, description);
+                    updateElanInstance, macTimeout, description);
             }
         } else {
             ElanInstance elanInstance = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName)
-                    .setMacTimeout(macTimeout).setDescription(description).setKey(new ElanInstanceKey(elanInstanceName))
-                    .build();
+                .setMacTimeout(macTimeout).setDescription(description).setKey(new ElanInstanceKey(elanInstanceName))
+                .build();
             MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
-                    ElanUtils.getElanInstanceConfigurationDataPath(elanInstanceName), elanInstance);
+                ElanUtils.getElanInstanceConfigurationDataPath(elanInstanceName), elanInstance);
             logger.debug("Creating the new Elan Instance {}", elanInstance);
         }
         return isSuccess;
     }
 
     public static boolean compareWithExistingElanInstance(ElanInstance existingElanInstance, long macTimeOut,
-            String description) {
+                                                          String description) {
         boolean isEqual = false;
         if (existingElanInstance.getMacTimeout() == macTimeOut
-                && existingElanInstance.getDescription().equals(description)) {
+            && existingElanInstance.getDescription().equals(description)) {
             isEqual = true;
         }
         return isEqual;
@@ -315,29 +341,29 @@ public class ElanServiceProvider implements BindingAwareProvider, IElanService,
         }
         logger.debug("Deletion of the existing Elan Instance {}", existingElanInstance);
         ElanUtils.delete(broker, LogicalDatastoreType.CONFIGURATION,
-                ElanUtils.getElanInstanceConfigurationDataPath(elanInstanceName));
+            ElanUtils.getElanInstanceConfigurationDataPath(elanInstanceName));
         isSuccess = true;
         return isSuccess;
     }
 
     @Override
     public void addElanInterface(String elanInstanceName, String interfaceName, List<String> staticMacAddresses,
-            String description) {
+                                 String description) {
         ElanInstance existingElanInstance = elanInstanceManager.getElanInstanceByName(elanInstanceName);
         if (existingElanInstance != null) {
             ElanInterface elanInterface;
             if (staticMacAddresses == null) {
                 elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName)
-                        .setDescription(description).setName(interfaceName).setKey(new ElanInterfaceKey(interfaceName))
-                        .build();
+                    .setDescription(description).setName(interfaceName).setKey(new ElanInterfaceKey(interfaceName))
+                    .build();
             } else {
                 elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName)
-                        .setDescription(description).setName(interfaceName)
-                        .setStaticMacEntries(getPhysAddress(staticMacAddresses))
-                        .setKey(new ElanInterfaceKey(interfaceName)).build();
+                    .setDescription(description).setName(interfaceName)
+                    .setStaticMacEntries(getPhysAddress(staticMacAddresses))
+                    .setKey(new ElanInterfaceKey(interfaceName)).build();
             }
             MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
-                    ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName), elanInterface);
+                ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName), elanInterface);
             logger.debug("Creating the new ELan Interface {}", elanInterface);
         }
 
@@ -345,7 +371,7 @@ public class ElanServiceProvider implements BindingAwareProvider, IElanService,
 
     @Override
     public void updateElanInterface(String elanInstanceName, String interfaceName,
-            List<String> updatedStaticMacAddresses, String newDescription) {
+                                    List<String> updatedStaticMacAddresses, String newDescription) {
         ElanInterface existingElanInterface = ElanUtils.getElanInterfaceByElanInterfaceName(interfaceName);
         if (existingElanInterface == null) {
             return;
@@ -356,10 +382,10 @@ public class ElanServiceProvider implements BindingAwareProvider, IElanService,
         if (updatedPhysAddress.size() > 0) {
             logger.debug("updating the ElanInterface with new Mac Entries {}", updatedStaticMacAddresses);
             ElanInterface elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName)
-                    .setName(interfaceName).setDescription(newDescription).setStaticMacEntries(updatedPhysAddress)
-                    .setKey(new ElanInterfaceKey(interfaceName)).build();
+                .setName(interfaceName).setDescription(newDescription).setStaticMacEntries(updatedPhysAddress)
+                .setKey(new ElanInterfaceKey(interfaceName)).build();
             MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
-                    ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName), elanInterface);
+                ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName), elanInterface);
         }
     }
 
@@ -368,7 +394,7 @@ public class ElanServiceProvider implements BindingAwareProvider, IElanService,
         ElanInterface existingElanInterface = ElanUtils.getElanInterfaceByElanInterfaceName(interfaceName);
         if (existingElanInterface != null) {
             ElanUtils.delete(broker, LogicalDatastoreType.CONFIGURATION,
-                    ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName));
+                ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName));
             logger.debug("deleting the Elan Interface {}", existingElanInterface);
         }
     }
@@ -384,17 +410,17 @@ public class ElanServiceProvider implements BindingAwareProvider, IElanService,
             }
             existingMacAddress.add(updateStaticMacAddress);
             ElanInterface elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName)
-                    .setName(interfaceName).setStaticMacEntries(existingMacAddress)
-                    .setDescription(existingElanInterface.getDescription()).setKey(new ElanInterfaceKey(interfaceName))
-                    .build();
+                .setName(interfaceName).setStaticMacEntries(existingMacAddress)
+                .setDescription(existingElanInterface.getDescription()).setKey(new ElanInterfaceKey(interfaceName))
+                .build();
             MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
-                    ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName), elanInterface);
+                ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName), elanInterface);
         }
     }
 
     @Override
     public void deleteStaticMacAddress(String elanInstanceName, String interfaceName, String macAddress)
-            throws MacNotFoundException {
+        throws MacNotFoundException {
         ElanInterface existingElanInterface = ElanUtils.getElanInterfaceByElanInterfaceName(interfaceName);
         PhysAddress physAddress = new PhysAddress(macAddress);
         if (existingElanInterface == null) {
@@ -404,11 +430,11 @@ public class ElanServiceProvider implements BindingAwareProvider, IElanService,
         if (existingMacAddress.contains(physAddress)) {
             existingMacAddress.remove(physAddress);
             ElanInterface elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName)
-                    .setName(interfaceName).setStaticMacEntries(existingMacAddress)
-                    .setDescription(existingElanInterface.getDescription()).setKey(new ElanInterfaceKey(interfaceName))
-                    .build();
+                .setName(interfaceName).setStaticMacEntries(existingMacAddress)
+                .setDescription(existingElanInterface.getDescription()).setKey(new ElanInterfaceKey(interfaceName))
+                .build();
             MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
-                    ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName), elanInterface);
+                ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName), elanInterface);
         } else {
             throw new MacNotFoundException("Mac Not Found Exception");
         }
@@ -426,7 +452,7 @@ public class ElanServiceProvider implements BindingAwareProvider, IElanService,
             for (String elanInterface : elanInterfaces) {
                 ElanInterfaceMac elanInterfaceMac = ElanUtils.getElanInterfaceMacByInterfaceName(elanInterface);
                 if (elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null
-                        && elanInterfaceMac.getMacEntry().size() > 0) {
+                    && elanInterfaceMac.getMacEntry().size() > 0) {
                     macAddress.addAll(elanInterfaceMac.getMacEntry());
                 }
             }
@@ -476,7 +502,7 @@ public class ElanServiceProvider implements BindingAwareProvider, IElanService,
     }
 
     public List<PhysAddress> getUpdatedPhyAddress(List<PhysAddress> originalAddresses,
-            List<PhysAddress> updatePhyAddresses) {
+                                                  List<PhysAddress> updatePhyAddresses) {
         if (updatePhyAddresses != null && !updatePhyAddresses.isEmpty()) {
             List<PhysAddress> existingClonedPhyAddress = new ArrayList<>();
             if (originalAddresses != null && !originalAddresses.isEmpty()) {
@@ -497,9 +523,9 @@ public class ElanServiceProvider implements BindingAwareProvider, IElanService,
     public List<ElanInstance> getElanInstances() {
         List<ElanInstance> elanList = new ArrayList<>();
         InstanceIdentifier<ElanInstances> elanInstancesIdentifier = InstanceIdentifier.builder(ElanInstances.class)
-                .build();
+            .build();
         Optional<ElanInstances> elansOptional = ElanUtils.read(broker, LogicalDatastoreType.CONFIGURATION,
-                elanInstancesIdentifier);
+            elanInstancesIdentifier);
         if (elansOptional.isPresent()) {
             elanList.addAll(elansOptional.get().getElanInstance());
         }
@@ -510,9 +536,9 @@ public class ElanServiceProvider implements BindingAwareProvider, IElanService,
     public List<String> getElanInterfaces(String elanInstanceName) {
         List<String> elanInterfaces = new ArrayList<>();
         InstanceIdentifier<ElanInterfaces> elanInterfacesIdentifier = InstanceIdentifier.builder(ElanInterfaces.class)
-                .build();
+            .build();
         Optional<ElanInterfaces> elanInterfacesOptional = ElanUtils.read(broker, LogicalDatastoreType.CONFIGURATION,
-                elanInterfacesIdentifier);
+            elanInterfacesIdentifier);
         if (!elanInterfacesOptional.isPresent()) {
             return elanInterfaces;
         }
index 418e54e2234f9451cc4ee0c9085bb6412c9391f6..63701aa9818f456777d70539d39f1bd38209868c 100644 (file)
@@ -12,8 +12,8 @@ import java.math.BigInteger;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.netvirt.elan.utils.ElanUtils;
 import org.opendaylight.netvirt.elan.utils.ElanConstants;
+import org.opendaylight.netvirt.elan.utils.ElanUtils;
 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
@@ -41,31 +41,32 @@ import com.google.common.util.concurrent.ListenableFuture;
 
 @SuppressWarnings("deprecation")
 public class ElanSmacFlowEventListener implements SalFlowListener {
-    private final DataBroker broker;
-    private IInterfaceManager interfaceManager;
+
+    private  ElanServiceProvider elanServiceProvider = null;
+    private static volatile ElanSmacFlowEventListener elanSmacFlowEventListener = null;
     private static final Logger logger = LoggerFactory.getLogger(ElanSmacFlowEventListener.class);
 
-    public ElanSmacFlowEventListener(DataBroker dataBroker) {
-        broker = dataBroker;
+    public ElanSmacFlowEventListener(ElanServiceProvider elanServiceProvider) {
+        this.elanServiceProvider = elanServiceProvider;
     }
-    private SalFlowService salFlowService;
 
-    public SalFlowService getSalFlowService() {
-        return this.salFlowService;
+    public static ElanSmacFlowEventListener getElanSmacFlowEventListener(ElanServiceProvider elanServiceProvider) {
+        if (elanSmacFlowEventListener == null)
+            synchronized (ElanPacketInHandler.class) {
+                if (elanSmacFlowEventListener == null) {
+                    elanSmacFlowEventListener = new ElanSmacFlowEventListener(elanServiceProvider);
+                }
+            }
+        return elanSmacFlowEventListener;
     }
 
-    public void setSalFlowService(final SalFlowService salFlowService) {
-        this.salFlowService = salFlowService;
-    }
-    public void setInterfaceManager(IInterfaceManager interfaceManager) {
-        this.interfaceManager = interfaceManager;
-    }
 
     public void setMdSalApiManager(IMdsalApiManager mdsalManager) {
     }
     @Override
     public void onFlowAdded(FlowAdded arg0) {
         // TODO Auto-generated method stub
+
     }
 
     @Override
@@ -79,7 +80,7 @@ public class ElanSmacFlowEventListener implements SalFlowListener {
                 return;
             }
             final String srcMacAddress = flowRemoved.getMatch().getEthernetMatch()
-                    .getEthernetSource().getAddress().getValue().toUpperCase();
+                .getEthernetSource().getAddress().getValue().toUpperCase();
             int portTag = MetaDataUtil.getLportFromMetadata(metadata).intValue();
             if (portTag == 0) {
                 logger.debug(String.format("Flow removed event on SMAC flow entry. But having port Tag as 0 "));
@@ -97,49 +98,61 @@ public class ElanSmacFlowEventListener implements SalFlowListener {
                 return;
             }
             MacEntry macEntry = ElanUtils.getInterfaceMacEntriesOperationalDataPath(interfaceName, physAddress);
-            InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
-            if(macEntry != null && interfaceInfo != null) {
-                ElanUtils.deleteMacFlows(ElanUtils.getElanInstanceByName(elanTagInfo.getName()), interfaceInfo, macEntry);
+            InterfaceInfo interfaceInfo = elanServiceProvider.getInterfaceManager().getInterfaceInfo(interfaceName);
+            if (macEntry != null && interfaceInfo != null) {
+                WriteTransaction deleteFlowTx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
+                ElanUtils.deleteMacFlows(ElanUtils.getElanInstanceByName(elanTagInfo.getName()), interfaceInfo, macEntry, deleteFlowTx);
+                ListenableFuture<Void> result = deleteFlowTx.submit();
+                addCallBack(result, srcMacAddress);
             }
             InstanceIdentifier<MacEntry> macEntryIdForElanInterface =  ElanUtils.getInterfaceMacEntriesIdentifierOperationalDataPath(interfaceName, physAddress);
             InstanceIdentifier<MacEntry> macEntryIdForElanInstance  =  ElanUtils.getMacEntryOperationalDataPath(elanTagInfo.getName(), physAddress);
-            WriteTransaction tx = broker.newWriteOnlyTransaction();
+            WriteTransaction tx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
             tx.delete(LogicalDatastoreType.OPERATIONAL, macEntryIdForElanInterface);
             tx.delete(LogicalDatastoreType.OPERATIONAL, macEntryIdForElanInstance);
             ListenableFuture<Void> writeResult = tx.submit();
+            addCallBack(writeResult, srcMacAddress);
+        }
 
-            //WRITE Callback
-            Futures.addCallback(writeResult, new FutureCallback<Void>() {
-                @Override
-                public void onSuccess(Void noarg) {
-                    logger.debug("Successfully removed macEntry {} from Operational Datastore", srcMacAddress);
-                }
+    }
 
-                @Override
-                public void onFailure(Throwable error) {
-                    logger.debug("Error {} while removing macEntry {} from Operational Datastore", error, srcMacAddress);
-                }
-            });
-        }
+    private void addCallBack(ListenableFuture<Void> writeResult, String srcMacAddress) {
+        //WRITE Callback
+        Futures.addCallback(writeResult, new FutureCallback<Void>() {
+            @Override
+            public void onSuccess(Void noarg) {
+                logger.debug("Successfully removed macEntry {} from Operational Datastore", srcMacAddress);
+            }
+
+            @Override
+            public void onFailure(Throwable error) {
+                logger.debug("Error {} while removing macEntry {} from Operational Datastore", error, srcMacAddress);
+            }
+        });
     }
 
     @Override
     public void onFlowUpdated(FlowUpdated arg0) {
         // TODO Auto-generated method stub
+
     }
 
     @Override
     public void onNodeErrorNotification(NodeErrorNotification arg0) {
         // TODO Auto-generated method stub
+
     }
 
     @Override
     public void onNodeExperimenterErrorNotification(NodeExperimenterErrorNotification arg0) {
         // TODO Auto-generated method stub
+
     }
 
     @Override
     public void onSwitchFlowRemoved(SwitchFlowRemoved switchFlowRemoved) {
-        // TODO Auto-generated method stub
+
     }
+
+
 }
@@ -14,18 +14,21 @@ import java.util.concurrent.Callable;
 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.common.util.concurrent.ListenableFuture;
 
-public class ElanInterfaceAddWorker implements Callable<List<ListenableFuture<Void>>> {
+public class InterfaceAddWorkerOnElan implements Callable<List<ListenableFuture<Void>>> {
     private String key;
     private ElanInterface elanInterface;
     private ElanInstance elanInstance;
     private InterfaceInfo interfaceInfo;
     private ElanInterfaceManager dataChangeListener;
+    private static final Logger logger = LoggerFactory.getLogger(InterfaceAddWorkerOnElan.class);
 
-    public ElanInterfaceAddWorker(String key, ElanInterface elanInterface, InterfaceInfo interfaceInfo,
-            ElanInstance elanInstance, ElanInterfaceManager dataChangeListener) {
+    public InterfaceAddWorkerOnElan(String key, ElanInterface elanInterface, InterfaceInfo interfaceInfo,
+                                    ElanInstance elanInstance, ElanInterfaceManager dataChangeListener) {
         super();
         this.key = key;
         this.elanInterface = elanInterface;
@@ -36,18 +39,20 @@ public class ElanInterfaceAddWorker implements Callable<List<ListenableFuture<Vo
 
     @Override
     public String toString() {
-        return "ElanInterfaceAddWorker [key=" + key + ", elanInterface=" + elanInterface + ", elanInstance="
-                + elanInstance + ", interfaceInfo=" + interfaceInfo + "]";
+        return "InterfaceAddWorkerOnElan [key=" + key + ", elanInterface=" + elanInterface + ", elanInstance="
+            + elanInstance + ", interfaceInfo=" + interfaceInfo + "]";
     }
 
 
     @Override
     public List<ListenableFuture<Void>> call() throws Exception {
         List<ListenableFuture<Void>> futures = new ArrayList<>();
-        dataChangeListener.addElanInterface(elanInterface, interfaceInfo, elanInstance);
+        try {
+            dataChangeListener.addElanInterface(elanInterface, interfaceInfo, elanInstance);
+        } catch (Exception e) {
+            logger.error("Error while processing {} for {}, error {}", key, elanInterface, e);
+        }
         return futures;
     }
-    
-    
 
 }
diff --git a/vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/InterfaceAddWorkerOnElanInterface.java b/vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/InterfaceAddWorkerOnElanInterface.java
new file mode 100644 (file)
index 0000000..a39176a
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.netvirt.elan.internal;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+public class InterfaceAddWorkerOnElanInterface implements Callable<List<ListenableFuture<Void>>> {
+    private String key;
+    private ElanInterface elanInterface;
+    private ElanInstance elanInstance;
+    private InterfaceInfo interfaceInfo;
+    private ElanInterfaceManager dataChangeListener;
+    private boolean isFirstInterfaceInDpn;
+    private static final Logger logger = LoggerFactory.getLogger(InterfaceAddWorkerOnElanInterface.class);
+
+    public InterfaceAddWorkerOnElanInterface(String key, ElanInterface elanInterface, InterfaceInfo interfaceInfo,
+                                             ElanInstance elanInstance, boolean isFirstInterfaceInDpn, ElanInterfaceManager dataChangeListener) {
+        super();
+        this.key = key;
+        this.elanInterface = elanInterface;
+        this.interfaceInfo = interfaceInfo;
+        this.elanInstance = elanInstance;
+        this.dataChangeListener = dataChangeListener;
+        this.isFirstInterfaceInDpn = isFirstInterfaceInDpn;
+    }
+
+    @Override
+    public String toString() {
+        return "InterfaceAddWorkerOnElanInterface [key=" + key + ", elanInterface=" + elanInterface + ", elanInstance="
+            + elanInstance + ", interfaceInfo=" + interfaceInfo + "]";
+    }
+
+
+    @Override
+    public List<ListenableFuture<Void>> call() throws Exception {
+        List<ListenableFuture<Void>> futures = new ArrayList<>();
+        try {
+            dataChangeListener.setupEntriesForElanInterface(elanInstance, elanInterface, interfaceInfo, isFirstInterfaceInDpn);
+        } catch (Exception e) {
+            logger.error("Error while processing {} for {}, error {}", key, elanInterface, e);
+        }
+        return futures;
+    }
+
+}
@@ -13,37 +13,46 @@ import java.util.concurrent.Callable;
 
 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.common.util.concurrent.ListenableFuture;
 
-public class ElanInterfaceRemoveWorker implements Callable<List<ListenableFuture<Void>>> {
+public class InterfaceRemoveWorkerOnElan implements Callable<List<ListenableFuture<Void>>> {
     private String key;
     private ElanInstance elanInfo;
     private String interfaceName;
     private InterfaceInfo interfaceInfo;
+    private boolean isInterfaceStateRemoved;
     private ElanInterfaceManager dataChangeListener;
+    private static final Logger logger = LoggerFactory.getLogger(InterfaceRemoveWorkerOnElan.class);
 
-    public ElanInterfaceRemoveWorker(String key, ElanInstance elanInfo, String interfaceName,
-            InterfaceInfo interfaceInfo, ElanInterfaceManager dataChangeListener) {
+    public InterfaceRemoveWorkerOnElan(String key, ElanInstance elanInfo, String interfaceName,
+                                       InterfaceInfo interfaceInfo, boolean isInterfaceStateRemoved, ElanInterfaceManager dataChangeListener) {
         super();
         this.key = key;
         this.elanInfo = elanInfo;
         this.interfaceName = interfaceName;
         this.interfaceInfo = interfaceInfo;
+        this.isInterfaceStateRemoved = isInterfaceStateRemoved;
         this.dataChangeListener = dataChangeListener;
     }
 
     @Override
     public String toString() {
-        return "ElanInterfaceRemoveWorker [key=" + key + ", elanInfo=" + elanInfo +
-                ", interfaceName=" + interfaceName
-                + ", interfaceInfo=" + interfaceInfo + "]";
+        return "InterfaceRemoveWorkerOnElan [key=" + key + ", elanInfo=" + elanInfo +
+            ", interfaceName=" + interfaceName
+            + ", interfaceInfo=" + interfaceInfo + "]";
     }
 
     @Override
     public List<ListenableFuture<Void>> call() throws Exception {
         List<ListenableFuture<Void>> futures = new ArrayList<>();
-        dataChangeListener.removeElanInterface(elanInfo, interfaceName, interfaceInfo);
+        try {
+            dataChangeListener.removeElanInterface(elanInfo, interfaceName, interfaceInfo, isInterfaceStateRemoved);
+        } catch (Exception e) {
+            logger.error("Error while processing {} for {}, error {}", key, interfaceName, e);
+        }
         return futures;
     }
 
diff --git a/vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/InterfaceRemoveWorkerOnElanInterface.java b/vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/InterfaceRemoveWorkerOnElanInterface.java
new file mode 100644 (file)
index 0000000..00d284c
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.netvirt.elan.internal;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+public class InterfaceRemoveWorkerOnElanInterface implements Callable<List<ListenableFuture<Void>>> {
+    private String interfaceName;
+    private ElanInstance elanInfo;
+    private InterfaceInfo interfaceInfo;
+    private boolean isInterfaceStateRemoved;
+    private ElanInterfaceManager dataChangeListener;
+    private boolean isLastElanInterface;
+    private static final Logger logger = LoggerFactory.getLogger(InterfaceRemoveWorkerOnElanInterface.class);
+
+    public InterfaceRemoveWorkerOnElanInterface(String interfaceName, ElanInstance elanInfo,
+                                                InterfaceInfo interfaceInfo, boolean isInterfaceStateRemoved, ElanInterfaceManager dataChangeListener, boolean isLastElanInterface) {
+        this.interfaceName = interfaceName;
+        this.elanInfo = elanInfo;
+        this.interfaceInfo = interfaceInfo;
+        this.isInterfaceStateRemoved = isInterfaceStateRemoved;
+        this.dataChangeListener = dataChangeListener;
+        this.isLastElanInterface = isLastElanInterface;
+    }
+
+    @Override
+    public String toString() {
+        return "InterfaceRemoveWorkerOnElanInterface [key=" + interfaceName + ", elanInfo=" + elanInfo
+            + ", interfaceInfo=" + interfaceInfo + ", isInterfaceStateRemoved=" + isInterfaceStateRemoved + ", isLastElanInterface=" + isLastElanInterface + "]";
+    }
+
+    @Override
+    public List<ListenableFuture<Void>> call() throws Exception {
+        List<ListenableFuture<Void>> futures = new ArrayList<>();
+        try {
+            dataChangeListener.removeEntriesForElanInterface(elanInfo, interfaceInfo, interfaceName, isInterfaceStateRemoved, isLastElanInterface);
+        } catch (Exception e) {
+            logger.error("Error while processing {} for {}, error {}", interfaceName, elanInfo, e);
+        }
+        return futures;
+    }
+
+}
index df5e3b512db32449d71dd14e178433e1373240bd..73751067b63b968cf1bd212065621f60eda048f2 100644 (file)
@@ -44,7 +44,7 @@ public class LogicalSwitchAddedJob implements Callable<List<ListenableFuture<Voi
     private static final Logger LOG = LoggerFactory.getLogger(LogicalSwitchAddedJob.class);
 
     public LogicalSwitchAddedJob(String logicalSwitchName, Devices physicalDevice, L2GatewayDevice l2GatewayDevice,
-            Integer defaultVlanId) {
+                                 Integer defaultVlanId) {
         this.logicalSwitchName = logicalSwitchName;
         this.physicalDevice = physicalDevice;
         this.elanL2GwDevice = l2GatewayDevice;
@@ -70,24 +70,24 @@ public class LogicalSwitchAddedJob implements Callable<List<ListenableFuture<Voi
 
             LOG.info("creating vlan bindings for {} {}", logicalSwitchName, elanL2GwDevice.getHwvtepNodeId());
             futures.add(ElanL2GatewayUtils.updateVlanBindingsInL2GatewayDevice(
-                    new NodeId(elanL2GwDevice.getHwvtepNodeId()), logicalSwitchName, physicalDevice, defaultVlanId));
+                new NodeId(elanL2GwDevice.getHwvtepNodeId()), logicalSwitchName, physicalDevice, defaultVlanId));
             LOG.info("creating mast mac entries for {} {}", logicalSwitchName, elanL2GwDevice.getHwvtepNodeId());
             futures.add(ElanL2GatewayMulticastUtils.handleMcastForElanL2GwDeviceAdd(logicalSwitchName, elanL2GwDevice));
 
             List<IpAddress> expectedPhyLocatorIps = Lists.newArrayList();
-            HwvtepRemoteMcastMacListener list = new HwvtepRemoteMcastMacListener(ElanUtils.getDataBroker(),
-                    logicalSwitchName, elanL2GwDevice, expectedPhyLocatorIps,
-                    new Callable<List<ListenableFuture<Void>>>() {
-                        @Override
-                        public List<ListenableFuture<Void>> call() {
-                            LOG.info("adding remote ucast macs for {} {}", logicalSwitchName,
-                                    elanL2GwDevice.getHwvtepNodeId());
-                            List<ListenableFuture<Void>> futures = new ArrayList<>();
-                            futures.add(ElanL2GatewayUtils.installElanMacsInL2GatewayDevice(
-                                    logicalSwitchName, elanL2GwDevice));
-                            return futures;
-                        }
-                    });
+            HwvtepRemoteMcastMacListener list = new HwvtepRemoteMcastMacListener(ElanUtils.getElanServiceProvider().getBroker(),
+                logicalSwitchName, elanL2GwDevice, expectedPhyLocatorIps,
+                new Callable<List<ListenableFuture<Void>>>() {
+                    @Override
+                    public List<ListenableFuture<Void>> call() {
+                        LOG.info("adding remote ucast macs for {} {}", logicalSwitchName,
+                            elanL2GwDevice.getHwvtepNodeId());
+                        List<ListenableFuture<Void>> futures = new ArrayList<>();
+                        futures.add(ElanL2GatewayUtils.installElanMacsInL2GatewayDevice(
+                            logicalSwitchName, elanL2GwDevice));
+                        return futures;
+                    }
+                });
 
             return futures;
         } catch (Throwable e) {
index b141f830f84192255bcb9d3553820661693b6fe8..7bb8bdfb7b776f660402ec5abf68a0d0cd50c18b 100755 (executable)
@@ -10,6 +10,7 @@ package org.opendaylight.netvirt.elan.statisitcs;
 import com.google.common.util.concurrent.Futures;
 
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.netvirt.elan.internal.ElanServiceProvider;
 import org.opendaylight.netvirt.elan.utils.ElanConstants;
 import org.opendaylight.netvirt.elan.utils.ElanUtils;
 //import org.opendaylight.genius.ericsson.mdsalutil.statistics.StatValue;
@@ -43,21 +44,31 @@ import java.util.Set;
 import java.util.concurrent.Future;
 
 public class ElanStatisticsImpl implements ElanStatisticsService {
-    private DataBroker dataBroker;
-    private IInterfaceManager interfaceManager;
-    private IMdsalApiManager mdsalMgr;
+    private ElanServiceProvider elanServiceProvider;
     private static final Logger logger = LoggerFactory.getLogger(ElanStatisticsImpl.class);
+    private static volatile ElanStatisticsImpl elanStatisticsImpl;
 
-    public ElanStatisticsImpl(DataBroker dataBroker, IInterfaceManager interfaceManager,
-            IMdsalApiManager mdsalMgr) {
-        this.interfaceManager = interfaceManager;
-        this.dataBroker = dataBroker;
-        this.mdsalMgr = mdsalMgr;
+
+    private ElanStatisticsImpl(ElanServiceProvider elanServiceProvider) {
+        super();
+        this.elanServiceProvider = elanServiceProvider;
+
+
+    }
+
+    public static ElanStatisticsImpl getElanStatisticsService(ElanServiceProvider elanServiceProvider) {
+        if (elanStatisticsImpl == null)
+            synchronized (ElanStatisticsImpl.class) {
+                if (elanStatisticsImpl == null) {
+                    elanStatisticsImpl = new ElanStatisticsImpl(elanServiceProvider);
+                }
+            }
+        return elanStatisticsImpl;
     }
 
     @Override
     public Future<RpcResult<GetElanInterfaceStatisticsOutput>> getElanInterfaceStatistics(
-            GetElanInterfaceStatisticsInput input) {
+        GetElanInterfaceStatisticsInput input) {
         String interfaceName = input.getInterfaceName();
         logger.debug("getElanInterfaceStatistics is called for elan interface {}", interfaceName);
         RpcResultBuilder<GetElanInterfaceStatisticsOutput> rpcResultBuilder = null;
@@ -73,7 +84,7 @@ public class ElanStatisticsImpl implements ElanStatisticsService {
         String elanInstanceName = elanInterface.getElanInstanceName();
         ElanInstance elanInfo = ElanUtils.getElanInstanceByName(elanInstanceName);
         long elanTag = elanInfo.getElanTag();
-        InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
+        InterfaceInfo interfaceInfo = elanServiceProvider.getInterfaceManager().getInterfaceInfo(interfaceName);
         ServicesInfo serviceInfo = ElanUtils.getServiceInfo(elanInstanceName, elanTag, interfaceName);
         //FIXME [ELANBE] Get this API Later
         short tableId = 0;
@@ -88,8 +99,8 @@ public class ElanStatisticsImpl implements ElanStatisticsService {
             logger.debug("interface {} is down and returning with no statistics", interfaceName);
             rpcResultBuilder = RpcResultBuilder.success();
             return Futures.immediateFuture(rpcResultBuilder.withResult(new GetElanInterfaceStatisticsOutputBuilder().setStatResult(new StatResultBuilder()
-            .setStatResultCode(ResultCode.NotFound).setByteRxCount(0L).setByteTxCount(0L).setPacketRxCount(0L)
-            .setPacketTxCount(0L).build()).build()).build());
+                .setStatResultCode(ResultCode.NotFound).setByteRxCount(0L).setByteTxCount(0L).setPacketRxCount(0L)
+                .setPacketTxCount(0L).build()).build()).build());
         }
         rpcResultBuilder = RpcResultBuilder.success();
         return Futures.immediateFuture(rpcResultBuilder.withResult(queryforElanInterfaceStatistics(tableId, elanInstanceName, interfaceInfo)).build());
@@ -102,14 +113,14 @@ public class ElanStatisticsImpl implements ElanStatisticsService {
         if (tableId == IfmConstants.VLAN_INTERFACE_INGRESS_TABLE) {
             VlanInterfaceInfo vlanInterfaceInfo = (VlanInterfaceInfo)interfaceInfo;
             matches = InterfaceServiceUtil.getMatchInfoForVlanLPort(dpId, interfaceInfo.getPortNo(),
-                    InterfaceServiceUtil.getVlanId(interfaceName, dataBroker), vlanInterfaceInfo.isVlanTransparent());
+                InterfaceServiceUtil.getVlanId(interfaceName, elanServiceProvider.getBroker()), vlanInterfaceInfo.isVlanTransparent());
         } else {
             matches = InterfaceServiceUtil.getLPortDispatcherMatches(ElanConstants.ELAN_SERVICE_INDEX, interfaceInfo.getInterfaceTag());
         }
         long groupId = interfaceInfo.getGroupId();
         Set<Object> statRequestKeys = InterfaceServiceUtil.getStatRequestKeys(dpId, tableId, matches, String.format("%s.%s", elanInstanceName, interfaceName), groupId);
-       // StatisticsInfo statsInfo = new StatisticsInfo(statRequestKeys);
-//        org.opendaylight.genius.ericsson.mdsalutil.statistics.StatResult statResult = mdsalMgr.queryForStatistics(interfaceName, statsInfo);
+        // StatisticsInfo statsInfo = new StatisticsInfo(statRequestKeys);
+//        org.opendaylight.vpnservice.ericsson.mdsalutil.statistics.StatResult statResult = mdsalMgr.queryForStatistics(interfaceName, statsInfo);
 //        ResultCode resultCode = ResultCode.Success;
 //        if (!statResult.isComplete()) {
 //            resultCode = ResultCode.Incomplete;
@@ -124,7 +135,7 @@ public class ElanStatisticsImpl implements ElanStatisticsService {
     }
 
     private Future<RpcResult<GetElanInterfaceStatisticsOutput>> getFutureWithAppErrorMessage(
-            RpcResultBuilder<GetElanInterfaceStatisticsOutput> rpcResultBuilder, String message) {
+        RpcResultBuilder<GetElanInterfaceStatisticsOutput> rpcResultBuilder, String message) {
         rpcResultBuilder.withError(ErrorType.APPLICATION, message);
         return Futures.immediateFuture(rpcResultBuilder.build());
     }
index 115d52776600df96674ee9b4d2c1e0416b1a33d3..477f338616a6193521656de7ddb03ec2a66a7826 100644 (file)
@@ -15,6 +15,7 @@ import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
 import org.opendaylight.genius.utils.SystemPropertyReader;
 import org.opendaylight.genius.utils.clustering.ClusteringUtils;
 import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundConstants;
+import org.opendaylight.netvirt.elan.internal.ElanServiceProvider;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -24,16 +25,9 @@ import java.util.concurrent.Callable;
 public class ElanClusterUtils {
     private static final Logger logger = LoggerFactory.getLogger(ElanClusterUtils.class);
 
-    private static EntityOwnershipService eos;
-
-    static DataStoreJobCoordinator dataStoreJobCoordinator;
-
-    public static void setDataStoreJobCoordinator(DataStoreJobCoordinator ds) {
-        dataStoreJobCoordinator = ds;
-    }
-
-    public static void setEntityOwnershipService(EntityOwnershipService entityOwnershipService) {
-        eos = entityOwnershipService;
+    private  static ElanServiceProvider elanServiceProvider = null;
+    public static void setElanServiceProvider(ElanServiceProvider elanServiceProvider) {
+        ElanClusterUtils.elanServiceProvider = elanServiceProvider;
     }
 
     public static void runOnlyInLeaderNode(Runnable job) {
@@ -42,8 +36,8 @@ public class ElanClusterUtils {
 
     public static void runOnlyInLeaderNode(final Runnable job, final String jobDescription) {
         ListenableFuture<Boolean> checkEntityOwnerFuture = ClusteringUtils.checkNodeEntityOwner(
-                eos, HwvtepSouthboundConstants.ELAN_ENTITY_TYPE,
-                HwvtepSouthboundConstants.ELAN_ENTITY_NAME);
+            elanServiceProvider.getEntityOwnershipService(), HwvtepSouthboundConstants.ELAN_ENTITY_TYPE,
+            HwvtepSouthboundConstants.ELAN_ENTITY_NAME);
         Futures.addCallback(checkEntityOwnerFuture, new FutureCallback<Boolean>() {
             @Override
             public void onSuccess(Boolean isOwner) {
@@ -67,15 +61,15 @@ public class ElanClusterUtils {
     public static void runOnlyInLeaderNode(final String jobKey, final String jobDescription,
                                            final Callable<List<ListenableFuture<Void>>> dataStoreJob) {
         ListenableFuture<Boolean> checkEntityOwnerFuture = ClusteringUtils.checkNodeEntityOwner(
-                eos, HwvtepSouthboundConstants.ELAN_ENTITY_TYPE,
-                HwvtepSouthboundConstants.ELAN_ENTITY_NAME);
+            elanServiceProvider.getEntityOwnershipService(), HwvtepSouthboundConstants.ELAN_ENTITY_TYPE,
+            HwvtepSouthboundConstants.ELAN_ENTITY_NAME);
         Futures.addCallback(checkEntityOwnerFuture, new FutureCallback<Boolean>() {
             @Override
             public void onSuccess(Boolean isOwner) {
                 if (isOwner) {
                     logger.trace("scheduling job {} ", jobDescription);
-                    dataStoreJobCoordinator.enqueueJob(jobKey, dataStoreJob,
-                            SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
+                    elanServiceProvider.getDataStoreJobCoordinator().enqueueJob(jobKey, dataStoreJob,
+                        SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
                 } else {
                     logger.trace("job is not run as i m not cluster owner desc :{} ", jobDescription);
                 }
@@ -86,4 +80,5 @@ public class ElanClusterUtils {
             }
         });
     }
+
 }
@@ -5,17 +5,20 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.netvirt.elan.internal;
+
+package org.opendaylight.netvirt.elan.utils;
+
 
 
-import com.google.common.base.Optional;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
+import org.opendaylight.netvirt.elan.internal.ElanServiceProvider;
 import org.opendaylight.netvirt.elan.utils.ElanUtils;
 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
 import org.opendaylight.genius.mdsalutil.AbstractDataChangeListener;
-import org.opendaylight.genius.mdsalutil.MDSALUtil;
 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.netvirt.elan.rev150602.ElanInterfaces;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
@@ -28,116 +31,109 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.base.Optional;
+
 
-public class ElanForwardingEntriesHandler extends AbstractDataChangeListener<ElanInterface> implements AutoCloseable {
+public class ElanForwardingEntriesHandler {
 
     private static final Logger logger = LoggerFactory.getLogger(ElanForwardingEntriesHandler.class);
-    private DataBroker broker;
-    private ListenerRegistration<DataChangeListener> listenerRegistration;
+    private  ElanServiceProvider elanServiceProvider = null;
+    private static volatile ElanForwardingEntriesHandler elanForwardingEntriesHandler = null;
 
-    public ElanForwardingEntriesHandler(DataBroker db){
-        super(ElanInterface.class);
-        this.broker = db;
+    public  ElanServiceProvider getElanServiceProvider() {
+        return elanServiceProvider;
     }
-
-    private InstanceIdentifier<?> getWildCardPath() {
-        return InstanceIdentifier.create(ElanInterfaces.class).child(ElanInterface.class);
+    public void setElanServiceProvider(ElanServiceProvider elanServiceProvider) {
+        this.elanServiceProvider = elanServiceProvider;
     }
 
-    public void updateElanInterfaceForwardingTablesList(String elanInstanceName, String interfaceName, String existingInterfaceName, MacEntry mac) {
-        if(existingInterfaceName == interfaceName) {
+    public ElanForwardingEntriesHandler(ElanServiceProvider elanServiceProvider){
+        super();
+        this.elanServiceProvider = elanServiceProvider;
+    }
+    public static  ElanForwardingEntriesHandler getElanForwardingEntriesHandler(
+        ElanServiceProvider elanServiceProvider) {
+        if (elanForwardingEntriesHandler == null) {
+            synchronized (ElanForwardingEntriesHandler.class) {
+                if (elanForwardingEntriesHandler == null) {
+                    elanForwardingEntriesHandler = new ElanForwardingEntriesHandler(elanServiceProvider);
+                }
+            }
+        }
+        return elanForwardingEntriesHandler;
+    }
+    public void updateElanInterfaceForwardingTablesList(String elanInstanceName, String interfaceName, String existingInterfaceName, MacEntry mac, WriteTransaction tx) {
+        if (existingInterfaceName.equals(interfaceName)) {
             logger.error(String.format("Static MAC address %s has already been added for the same ElanInstance %s on the same Logical Interface Port %s."
-                    + " No operation will be done.", mac.getMacAddress().toString(), elanInstanceName, interfaceName));
+                + " No operation will be done.", mac.getMacAddress().toString(), elanInstanceName, interfaceName));
         } else {
             logger.warn(String.format("Static MAC address %s had already been added for ElanInstance %s on Logical Interface Port %s. "
-                    + "This would be considered as MAC movement scenario and old static mac will be removed and new static MAC will be added"
-                    + "for ElanInstance %s on Logical Interface Port %s", mac.getMacAddress().toString(), elanInstanceName, interfaceName, elanInstanceName, interfaceName));
+                + "This would be considered as MAC movement scenario and old static mac will be removed and new static MAC will be added"
+                + "for ElanInstance %s on Logical Interface Port %s", mac.getMacAddress().toString(), elanInstanceName, interfaceName, elanInstanceName, interfaceName));
             //Update the  ElanInterface Forwarding Container & ElanForwarding Container
-            deleteElanInterfaceForwardingTablesList(existingInterfaceName, mac);
-            createElanInterfaceForwardingTablesList(interfaceName, mac);
-            updateElanForwardingTablesList(elanInstanceName, interfaceName, mac);
+            deleteElanInterfaceForwardingTablesList(existingInterfaceName, mac, tx);
+            createElanInterfaceForwardingTablesList(interfaceName, mac, tx);
+            updateElanForwardingTablesList(elanInstanceName, interfaceName, mac, tx);
         }
 
     }
 
-    public void addElanInterfaceForwardingTableList(ElanInstance elanInstance, String interfaceName, PhysAddress physAddress) {
+    public void addElanInterfaceForwardingTableList(ElanInstance elanInstance, String interfaceName, PhysAddress physAddress, WriteTransaction tx) {
         MacEntry macEntry = new MacEntryBuilder().setIsStaticAddress(true).setMacAddress(physAddress).setInterface(interfaceName).setKey(new MacEntryKey(physAddress)).build();
-        createElanForwardingTablesList(elanInstance.getElanInstanceName(), macEntry);
-        createElanInterfaceForwardingTablesList(interfaceName, macEntry);
+        createElanForwardingTablesList(elanInstance.getElanInstanceName(), macEntry, tx);
+        createElanInterfaceForwardingTablesList(interfaceName, macEntry, tx);
     }
 
-    public void deleteElanInterfaceForwardingTablesList(String interfaceName, MacEntry mac) {
+    public void deleteElanInterfaceForwardingTablesList(String interfaceName, MacEntry mac, WriteTransaction tx) {
         InstanceIdentifier<MacEntry> existingMacEntryId = ElanUtils.getInterfaceMacEntriesIdentifierOperationalDataPath(interfaceName, mac.getMacAddress());
         MacEntry existingInterfaceMacEntry = ElanUtils.getInterfaceMacEntriesOperationalDataPathFromId(existingMacEntryId);
-        if(existingInterfaceMacEntry != null) {
-            ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, existingMacEntryId);
+        if (existingInterfaceMacEntry != null) {
+            tx.delete(LogicalDatastoreType.OPERATIONAL, existingMacEntryId);
         }
     }
 
-    public void createElanInterfaceForwardingTablesList(String interfaceName, MacEntry mac) {
+    public void createElanInterfaceForwardingTablesList(String interfaceName, MacEntry mac, WriteTransaction tx) {
         InstanceIdentifier<MacEntry> existingMacEntryId = ElanUtils.getInterfaceMacEntriesIdentifierOperationalDataPath(interfaceName, mac.getMacAddress());
         MacEntry existingInterfaceMacEntry = ElanUtils.getInterfaceMacEntriesOperationalDataPathFromId(existingMacEntryId);
-        if(existingInterfaceMacEntry == null) {
+        if (existingInterfaceMacEntry == null) {
             MacEntry macEntry = new MacEntryBuilder().setMacAddress(mac.getMacAddress()).setInterface(interfaceName).setIsStaticAddress(true).setKey(new MacEntryKey(mac.getMacAddress())).build();
-            MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, existingMacEntryId, macEntry);
+            tx.put(LogicalDatastoreType.OPERATIONAL, existingMacEntryId, macEntry);
 
         }
     }
 
-    public void updateElanForwardingTablesList(String elanName, String interfaceName, MacEntry mac) {
+    public void updateElanForwardingTablesList(String elanName, String interfaceName, MacEntry mac, WriteTransaction tx) {
         InstanceIdentifier<MacEntry> macEntryId =  ElanUtils.getMacEntryOperationalDataPath(elanName, mac.getMacAddress());
         MacEntry existingMacEntry = ElanUtils.getMacEntryFromElanMacId(macEntryId);
-        if(existingMacEntry != null) {
-            ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, macEntryId);
+        if (existingMacEntry != null) {
+            // Fix for TR HU71400.
+            // ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, macEntryId);
             MacEntry newMacEntry = new MacEntryBuilder().setInterface(interfaceName).setIsStaticAddress(true).setMacAddress(mac.getMacAddress()).setKey(new MacEntryKey(mac.getMacAddress())).build();
-            MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, macEntryId, newMacEntry);
+            tx.put(LogicalDatastoreType.OPERATIONAL, macEntryId, newMacEntry);
         }
     }
 
-    private void createElanForwardingTablesList(String elanName, MacEntry macEntry) {
+    private void createElanForwardingTablesList(String elanName, MacEntry macEntry, WriteTransaction tx) {
         InstanceIdentifier<MacEntry> macEntryId = ElanUtils.getMacEntryOperationalDataPath(elanName, macEntry.getMacAddress());
-        Optional<MacEntry> existingMacEntry = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, macEntryId);
-        if(!existingMacEntry.isPresent()) {
-            MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, macEntryId, macEntry);
+        Optional<MacEntry> existingMacEntry = ElanUtils.read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, macEntryId);
+        if (!existingMacEntry.isPresent()) {
+            tx.put(LogicalDatastoreType.OPERATIONAL, macEntryId, macEntry);
         }
     }
 
-    public void deleteElanInterfaceForwardingEntries(ElanInstance elanInfo, InterfaceInfo interfaceInfo, MacEntry macEntry) {
+    public void deleteElanInterfaceForwardingEntries(ElanInstance elanInfo, InterfaceInfo interfaceInfo, MacEntry macEntry, WriteTransaction tx) {
         InstanceIdentifier<MacEntry> macEntryId = ElanUtils.getMacEntryOperationalDataPath(elanInfo.getElanInstanceName(), macEntry.getMacAddress());
-        ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, macEntryId);
-        deleteElanInterfaceForwardingTablesList(interfaceInfo.getInterfaceName(), macEntry);
-        ElanUtils.deleteMacFlows(elanInfo, interfaceInfo, macEntry);
+        tx.delete(LogicalDatastoreType.OPERATIONAL, macEntryId);
+        deleteElanInterfaceForwardingTablesList(interfaceInfo.getInterfaceName(), macEntry, tx);
+        WriteTransaction deleteFlowtx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
+        ElanUtils.deleteMacFlows(elanInfo, interfaceInfo, macEntry, deleteFlowtx);
+        deleteFlowtx.submit();
     }
 
-    public void deleteElanInterfaceMacForwardingEntries(String interfaceName, PhysAddress physAddress) {
+    public void deleteElanInterfaceMacForwardingEntries(String interfaceName, PhysAddress physAddress, WriteTransaction tx) {
         InstanceIdentifier<MacEntry> macEntryId = ElanUtils.getInterfaceMacEntriesIdentifierOperationalDataPath(interfaceName, physAddress);
-        ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, macEntryId);
+        tx.delete(LogicalDatastoreType.OPERATIONAL, macEntryId);
     }
 
-    @Override
-    protected void remove(InstanceIdentifier<ElanInterface> identifier, ElanInterface del) {
 
-    }
-
-    @Override
-    protected void update(InstanceIdentifier<ElanInterface> identifier, ElanInterface original, ElanInterface update) {
-
-    }
-
-    @Override
-    protected void add(InstanceIdentifier<ElanInterface> identifier, ElanInterface add) {
-
-    }
-
-    @Override
-    public void close() throws Exception {
-        if (listenerRegistration != null) {
-            try {
-                listenerRegistration.close();
-            } catch (final Exception e) {
-                logger.error("Error when cleaning up Elan DataChangeListener.", e);
-            }
-            listenerRegistration = null;
-        }
-    }
 }
index e3cc31ddb961b8c6b8e61d5fa68ba6685607e137..ca5f7c436282f9f2caa57b4759b17d7273c6aa33 100644 (file)
@@ -35,6 +35,8 @@ import org.opendaylight.genius.mdsalutil.MatchInfo;
 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
 import org.opendaylight.genius.mdsalutil.NwConstants;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.netvirt.elan.internal.ElanServiceProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeIngress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus;
@@ -95,7 +97,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpc
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfo;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfoKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
@@ -131,16 +132,16 @@ import com.google.common.util.concurrent.ListenableFuture;
 
 public class ElanUtils {
 
-    private static OdlInterfaceRpcService interfaceMgrRpcService;
-
-    private static ItmRpcService itmRpcService;
-
-    private static IMdsalApiManager mdsalMgr;
-
-    private static DataBroker dataBroker;
-
+    private static  ElanServiceProvider elanServiceProvider ;
     private static final Logger logger = LoggerFactory.getLogger(ElanUtils.class);
 
+    public static void setElanServiceProvider(ElanServiceProvider serviceProvider) {
+        elanServiceProvider = serviceProvider;
+    }
+    public static ElanServiceProvider getElanServiceProvider() {
+        return elanServiceProvider;
+    }
+
     public static final FutureCallback<Void> DEFAULT_CALLBACK = new FutureCallback<Void>() {
         @Override
         public void onSuccess(Void result) {
@@ -162,44 +163,25 @@ public class ElanUtils {
      *            the id key
      * @return the integer
      */
-    public static Integer retrieveNewElanTag(IdManagerService idManager, String idKey) {
+    public static Long retrieveNewElanTag(IdManagerService idManager, String idKey) {
 
         AllocateIdInput getIdInput = new AllocateIdInputBuilder().setPoolName(ElanConstants.ELAN_ID_POOL_NAME)
-                .setIdKey(idKey).build();
+            .setIdKey(idKey).build();
 
         try {
             Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
             RpcResult<AllocateIdOutput> rpcResult = result.get();
             if (rpcResult.isSuccessful()) {
-                return rpcResult.getResult().getIdValue().intValue();
+                return rpcResult.getResult().getIdValue().longValue();
             } else {
                 logger.warn("RPC Call to Allocate Id returned with Errors {}", rpcResult.getErrors());
             }
         } catch (InterruptedException | ExecutionException e) {
             logger.warn("Exception when Allocating Id",e);
         }
-        return 0;
-    }
-
-    public static DataBroker getDataBroker() {
-        return dataBroker;
-    }
-
-    public final static void setIfaceMgrRpcService(OdlInterfaceRpcService rpcService) {
-        interfaceMgrRpcService = rpcService;
-    }
-
-    public final static void setItmRpcService(ItmRpcService itmService) {
-        itmRpcService = itmService;
+        return 0L;
     }
 
-    public final static void setDataBroker(DataBroker broker) {
-        dataBroker = broker;
-    }
-
-    public final static void setMdsalManager(IMdsalApiManager mdsalApiManager) {
-        mdsalMgr = mdsalApiManager;
-    }
 
     public static void releaseId(IdManagerService idManager, String poolName, String idKey) {
         ReleaseIdInput releaseIdInput = new ReleaseIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
@@ -207,8 +189,8 @@ public class ElanUtils {
     }
 
     public static <T extends DataObject> Optional<T> read(DataBroker broker, LogicalDatastoreType datastoreType,
-            InstanceIdentifier<T> path) {
-        ReadOnlyTransaction tx = (broker != null ) ? broker.newReadOnlyTransaction() : dataBroker.newReadOnlyTransaction();
+                                                          InstanceIdentifier<T> path) {
+        ReadOnlyTransaction tx = (broker != null ) ? broker.newReadOnlyTransaction() : elanServiceProvider.getBroker().newReadOnlyTransaction();
         Optional<T> result = Optional.absent();
         try {
             CheckedFuture<Optional<T>, ReadFailedException> checkedFuture = tx.read(datastoreType, path);
@@ -235,8 +217,8 @@ public class ElanUtils {
     //elan-instances config container
     public static ElanInstance getElanInstanceByName(String elanInstanceName) {
         InstanceIdentifier<ElanInstance> elanIdentifierId = getElanInstanceConfigurationDataPath(elanInstanceName);
-        Optional<ElanInstance> elanInstance = read(dataBroker, LogicalDatastoreType.CONFIGURATION, elanIdentifierId);
-        if(elanInstance.isPresent()) {
+        Optional<ElanInstance> elanInstance = read(elanServiceProvider.getBroker(), LogicalDatastoreType.CONFIGURATION, elanIdentifierId);
+        if (elanInstance.isPresent()) {
             return elanInstance.get();
         }
         return null;
@@ -249,8 +231,8 @@ public class ElanUtils {
     //elan-interfaces Config Container
     public static ElanInterface getElanInterfaceByElanInterfaceName(String elanInterfaceName) {
         InstanceIdentifier<ElanInterface> elanInterfaceId = getElanInterfaceConfigurationDataPathId(elanInterfaceName);
-        Optional<ElanInterface> existingElanInterface = read(dataBroker, LogicalDatastoreType.CONFIGURATION, elanInterfaceId);
-        if(existingElanInterface.isPresent()) {
+        Optional<ElanInterface> existingElanInterface = read(elanServiceProvider.getBroker(), LogicalDatastoreType.CONFIGURATION, elanInterfaceId);
+        if (existingElanInterface.isPresent()) {
             return existingElanInterface.get();
         }
         return null;
@@ -258,14 +240,14 @@ public class ElanUtils {
 
     public static InstanceIdentifier<ElanInterface> getElanInterfaceConfigurationDataPathId(String interfaceName) {
         return InstanceIdentifier.builder(ElanInterfaces.class).child(ElanInterface.class,
-                new ElanInterfaceKey(interfaceName)).build();
+            new ElanInterfaceKey(interfaceName)).build();
     }
 
     //elan-state Operational container
     public static Elan getElanByName(String elanInstanceName) {
         InstanceIdentifier<Elan> elanIdentifier = getElanInstanceOperationalDataPath(elanInstanceName);
-        Optional<Elan> elanInstance = read(dataBroker, LogicalDatastoreType.OPERATIONAL, elanIdentifier);
-        if(elanInstance.isPresent()) {
+        Optional<Elan> elanInstance = read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, elanIdentifier);
+        if (elanInstance.isPresent()) {
             return elanInstance.get();
         }
         return null;
@@ -278,16 +260,16 @@ public class ElanUtils {
     // grouping of forwarding-entries
     public static MacEntry getInterfaceMacEntriesOperationalDataPath(String interfaceName, PhysAddress physAddress) {
         InstanceIdentifier<MacEntry> existingMacEntryId = getInterfaceMacEntriesIdentifierOperationalDataPath(interfaceName, physAddress);
-        Optional<MacEntry> existingInterfaceMacEntry = read(dataBroker, LogicalDatastoreType.OPERATIONAL, existingMacEntryId);
-        if(existingInterfaceMacEntry.isPresent()) {
+        Optional<MacEntry> existingInterfaceMacEntry = read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, existingMacEntryId);
+        if (existingInterfaceMacEntry.isPresent()) {
             return existingInterfaceMacEntry.get();
         }
         return null;
     }
 
     public static MacEntry getInterfaceMacEntriesOperationalDataPathFromId(InstanceIdentifier identifier) {
-        Optional<MacEntry> existingInterfaceMacEntry = read(dataBroker, LogicalDatastoreType.OPERATIONAL, identifier);
-        if(existingInterfaceMacEntry.isPresent()) {
+        Optional<MacEntry> existingInterfaceMacEntry = read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, identifier);
+        if (existingInterfaceMacEntry.isPresent()) {
             return existingInterfaceMacEntry.get();
         }
         return null;
@@ -295,15 +277,15 @@ public class ElanUtils {
 
     public static InstanceIdentifier<MacEntry> getInterfaceMacEntriesIdentifierOperationalDataPath(String interfaceName, PhysAddress physAddress) {
         return InstanceIdentifier.builder(ElanInterfaceForwardingEntries.class).child(ElanInterfaceMac.class,
-                new ElanInterfaceMacKey(interfaceName)).child(MacEntry.class, new MacEntryKey(physAddress)).build();
+            new ElanInterfaceMacKey(interfaceName)).child(MacEntry.class, new MacEntryKey(physAddress)).build();
 
     }
 
     //elan-forwarding-tables Operational container
     public static MacEntry getMacTableByElanName(String elanName, PhysAddress physAddress) {
         InstanceIdentifier<MacEntry> macId =  getMacEntryOperationalDataPath(elanName, physAddress);
-        Optional<MacEntry> existingElanMacEntry = read(dataBroker, LogicalDatastoreType.OPERATIONAL, macId);
-        if(existingElanMacEntry.isPresent()) {
+        Optional<MacEntry> existingElanMacEntry = read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, macId);
+        if (existingElanMacEntry.isPresent()) {
             return existingElanMacEntry.get();
         }
         return null;
@@ -311,8 +293,8 @@ public class ElanUtils {
 
 
     public static MacEntry getMacEntryFromElanMacId(InstanceIdentifier identifier) {
-        Optional<MacEntry> existingInterfaceMacEntry = read(dataBroker, LogicalDatastoreType.OPERATIONAL, identifier);
-        if(existingInterfaceMacEntry.isPresent()) {
+        Optional<MacEntry> existingInterfaceMacEntry = read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, identifier);
+        if (existingInterfaceMacEntry.isPresent()) {
             return existingInterfaceMacEntry.get();
         }
         return null;
@@ -320,19 +302,19 @@ public class ElanUtils {
 
     public static InstanceIdentifier<MacEntry> getMacEntryOperationalDataPath(String elanName, PhysAddress physAddress) {
         return InstanceIdentifier.builder(ElanForwardingTables.class).child(MacTable.class,
-                new MacTableKey(elanName)).child(MacEntry.class, new MacEntryKey(physAddress)).build();
+            new MacTableKey(elanName)).child(MacEntry.class, new MacEntryKey(physAddress)).build();
     }
 
     public static InstanceIdentifier<MacTable> getElanMacTableOperationalDataPath(String elanName) {
         return InstanceIdentifier.builder(ElanForwardingTables.class).child(MacTable.class,
-                new MacTableKey(elanName)).build();
+            new MacTableKey(elanName)).build();
     }
 
     //elan-interface-forwarding-entries Operational container
     public static ElanInterfaceMac getElanInterfaceMacByInterfaceName(String interfaceName) {
         InstanceIdentifier<ElanInterfaceMac> elanInterfaceId = getElanInterfaceMacEntriesOperationalDataPath(interfaceName);
-        Optional<ElanInterfaceMac> existingElanInterface = read(dataBroker, LogicalDatastoreType.OPERATIONAL, elanInterfaceId);
-        if(existingElanInterface.isPresent()) {
+        Optional<ElanInterfaceMac> existingElanInterface = read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, elanInterfaceId);
+        if (existingElanInterface.isPresent()) {
             return existingElanInterface.get();
         }
         return null;
@@ -346,7 +328,7 @@ public class ElanUtils {
      * @return the elan interface mac addresses
      */
     public static List<PhysAddress> getElanInterfaceMacAddresses(String interfaceName) {
-        List<PhysAddress> macAddresses = new ArrayList<>();
+        List<PhysAddress> macAddresses = new ArrayList<PhysAddress>();
         ElanInterfaceMac elanInterfaceMac = ElanUtils.getElanInterfaceMacByInterfaceName(interfaceName);
         if (elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
             List<MacEntry> macEntries = elanInterfaceMac.getMacEntry();
@@ -359,7 +341,7 @@ public class ElanUtils {
 
     public static InstanceIdentifier<ElanInterfaceMac> getElanInterfaceMacEntriesOperationalDataPath(String interfaceName) {
         return InstanceIdentifier.builder(ElanInterfaceForwardingEntries.class).child(ElanInterfaceMac.class,
-                new ElanInterfaceMacKey(interfaceName)).build();
+            new ElanInterfaceMacKey(interfaceName)).build();
     }
 
     /**
@@ -370,12 +352,12 @@ public class ElanUtils {
      *          name of the Elan to which the interfaces must belong to
      * @param dpId
      *          Id of the DPN where the interfaces are located
-     * @return
+     * @return the elan interface Info
      */
     public static DpnInterfaces getElanInterfaceInfoByElanDpn(String elanInstanceName, BigInteger dpId) {
         InstanceIdentifier<DpnInterfaces> elanDpnInterfacesId =
-                getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId);
-        Optional<DpnInterfaces> elanDpnInterfaces = read(dataBroker, LogicalDatastoreType.OPERATIONAL, elanDpnInterfacesId);
+            getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId);
+        Optional<DpnInterfaces> elanDpnInterfaces = read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, elanDpnInterfacesId);
         if ( elanDpnInterfaces.isPresent() ) {
             return elanDpnInterfaces.get();
         }
@@ -391,20 +373,20 @@ public class ElanUtils {
      *          name of the Elan to which the interfaces must belong to
      * @param dpId
      *          Id of the DPN where the interfaces are located
-     * @return
+     * @return the elan dpn interface
      */
     public static InstanceIdentifier<DpnInterfaces> getElanDpnInterfaceOperationalDataPath(String elanInstanceName,
-            BigInteger dpId) {
+                                                                                           BigInteger dpId) {
         return InstanceIdentifier.builder(ElanDpnInterfaces.class)
-                .child(ElanDpnInterfacesList.class, new ElanDpnInterfacesListKey(elanInstanceName))
-                .child(DpnInterfaces.class, new DpnInterfacesKey(dpId)).build();
+            .child(ElanDpnInterfacesList.class, new ElanDpnInterfacesListKey(elanInstanceName))
+            .child(DpnInterfaces.class, new DpnInterfacesKey(dpId)).build();
     }
 
     //elan-tag-name-map Operational Container
     public static ElanTagName getElanInfoByElanTag(long elanTag) {
         InstanceIdentifier<ElanTagName> elanId = getElanInfoEntriesOperationalDataPath(elanTag);
-        Optional<ElanTagName> existingElanInfo = ElanUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, elanId);
-        if(existingElanInfo.isPresent()) {
+        Optional<ElanTagName> existingElanInfo = ElanUtils.read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, elanId);
+        if (existingElanInfo.isPresent()) {
             return existingElanInfo.get();
         }
         return null;
@@ -412,32 +394,32 @@ public class ElanUtils {
 
     public static InstanceIdentifier<ElanTagName> getElanInfoEntriesOperationalDataPath(long elanTag) {
         return InstanceIdentifier.builder(ElanTagNameMap.class).child(ElanTagName.class,
-                new ElanTagNameKey(elanTag)).build();
+            new ElanTagNameKey(elanTag)).build();
     }
 
     // interface-index-tag operational container
     public static Optional<IfIndexInterface> getInterfaceInfoByInterfaceTag(long interfaceTag) {
         InstanceIdentifier<IfIndexInterface> interfaceId = getInterfaceInfoEntriesOperationalDataPath(interfaceTag);
-        return ElanUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, interfaceId);
+        return ElanUtils.read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, interfaceId);
     }
 
     public static InstanceIdentifier<IfIndexInterface> getInterfaceInfoEntriesOperationalDataPath(long interfaceTag) {
         return InstanceIdentifier.builder(IfIndexesInterfaceMap.class).child(IfIndexInterface.class,
-                new IfIndexInterfaceKey((int) interfaceTag)).build();
+            new IfIndexInterfaceKey((int) interfaceTag)).build();
     }
 
 
 
     public static InstanceIdentifier<ElanDpnInterfacesList> getElanDpnOperationDataPath(String elanInstanceName) {
         return InstanceIdentifier.builder(ElanDpnInterfaces.class).child(ElanDpnInterfacesList.class,
-                new ElanDpnInterfacesListKey(elanInstanceName)).build();
+            new ElanDpnInterfacesListKey(elanInstanceName)).build();
     }
 
     public static  ElanDpnInterfacesList getElanDpnInterfacesList(String elanName) {
         InstanceIdentifier<ElanDpnInterfacesList> elanDpnInterfaceId = getElanDpnOperationDataPath(elanName);
         Optional<ElanDpnInterfacesList> existingElanDpnInterfaces =
-                ElanUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, elanDpnInterfaceId);
-        if(existingElanDpnInterfaces.isPresent()) {
+            ElanUtils.read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, elanDpnInterfaceId);
+        if (existingElanDpnInterfaces.isPresent()) {
             return existingElanDpnInterfaces.get();
         }
         return null;
@@ -453,10 +435,10 @@ public class ElanUtils {
      * @return list of dpIds
      */
     public static List<BigInteger> getParticipatingDPNsInElanInstance(String elanInstanceName) {
-        List<BigInteger> dpIds = new ArrayList<>();
+        List<BigInteger> dpIds = new ArrayList<BigInteger>();
         InstanceIdentifier<ElanDpnInterfacesList> elanDpnInterfaceId = getElanDpnOperationDataPath(elanInstanceName);
         Optional<ElanDpnInterfacesList> existingElanDpnInterfaces =
-                ElanUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, elanDpnInterfaceId);
+            ElanUtils.read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, elanDpnInterfaceId);
         if (!existingElanDpnInterfaces.isPresent()) {
             return dpIds;
         }
@@ -482,7 +464,7 @@ public class ElanUtils {
         boolean isDpIdPresent = false;
         InstanceIdentifier<ElanDpnInterfacesList> elanDpnInterfaceId = getElanDpnOperationDataPath(elanInstanceName);
         Optional<ElanDpnInterfacesList> existingElanDpnInterfaces =
-                ElanUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, elanDpnInterfaceId);
+            ElanUtils.read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, elanDpnInterfaceId);
         if (!existingElanDpnInterfaces.isPresent()) {
             return isDpIdPresent;
         }
@@ -498,10 +480,10 @@ public class ElanUtils {
 
     public static ElanDpnInterfaces getElanDpnInterfacesList() {
         InstanceIdentifier<ElanDpnInterfaces> elanDpnInterfaceId =
-                InstanceIdentifier.builder(ElanDpnInterfaces.class).build();
+            InstanceIdentifier.builder(ElanDpnInterfaces.class).build();
         Optional<ElanDpnInterfaces> existingElanDpnInterfaces =
-                ElanUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, elanDpnInterfaceId);
-        if(existingElanDpnInterfaces.isPresent()) {
+            ElanUtils.read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, elanDpnInterfaceId);
+        if (existingElanDpnInterfaces.isPresent()) {
             return existingElanDpnInterfaces.get();
         }
         return null;
@@ -509,10 +491,10 @@ public class ElanUtils {
 
     public static ElanForwardingTables getElanForwardingList() {
         InstanceIdentifier<ElanForwardingTables> elanForwardingTableId =
-                InstanceIdentifier.builder(ElanForwardingTables.class).build();
+            InstanceIdentifier.builder(ElanForwardingTables.class).build();
         Optional<ElanForwardingTables> existingElanForwardingList =
-                ElanUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, elanForwardingTableId);
-        if(existingElanForwardingList.isPresent()) {
+            ElanUtils.read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, elanForwardingTableId);
+        if (existingElanForwardingList.isPresent()) {
             return existingElanForwardingList.get();
         }
         return null;
@@ -528,7 +510,7 @@ public class ElanUtils {
     public static MacTable getElanMacTable(String elanName) {
         InstanceIdentifier<MacTable> elanMacTableId = getElanMacTableOperationalDataPath(elanName);
         Optional<MacTable> existingElanMacTable =
-                ElanUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, elanMacTableId);
+            ElanUtils.read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, elanMacTableId);
         if (existingElanMacTable.isPresent()) {
             return existingElanMacTable.get();
         }
@@ -572,21 +554,23 @@ public class ElanUtils {
      *            the mac timeout
      * @param macAddress
      *            the mac address
+     * @param writeFlowGroupTx
+     *            the flow group tx
      */
     public static void setupMacFlows(ElanInstance elanInfo, InterfaceInfo interfaceInfo, long macTimeout,
-            String macAddress) {
+                                     String macAddress, WriteTransaction writeFlowGroupTx) {
         synchronized (macAddress) {
             logger.info("Acquired lock for mac : " + macAddress + ". Proceeding with install operation.");
-            setupKnownSmacFlow(elanInfo, interfaceInfo, macTimeout, macAddress, mdsalMgr);
-            setupOrigDmacFlows(elanInfo, interfaceInfo, macAddress, mdsalMgr, dataBroker);
+            setupKnownSmacFlow(elanInfo, interfaceInfo, macTimeout, macAddress, elanServiceProvider.getMdsalManager(), writeFlowGroupTx);
+            setupOrigDmacFlows(elanInfo, interfaceInfo, macAddress, elanServiceProvider.getMdsalManager(), elanServiceProvider.getBroker(), writeFlowGroupTx);
         }
     }
 
     public static void setupDMacFlowonRemoteDpn(ElanInstance elanInfo, InterfaceInfo interfaceInfo, BigInteger dstDpId,
-            String macAddress) {
+                                                String macAddress, WriteTransaction writeFlowTx) {
         synchronized (macAddress) {
             logger.info("Acquired lock for mac : " + macAddress + "Proceeding with install operation.");
-            setupOrigDmacFlowsonRemoteDpn(elanInfo, interfaceInfo, dstDpId, macAddress);
+            setupOrigDmacFlowsonRemoteDpn(elanInfo, interfaceInfo, dstDpId, macAddress, writeFlowTx);
         }
     }
 
@@ -601,12 +585,12 @@ public class ElanUtils {
      * @param mdsalApiManager
      */
     private static void setupKnownSmacFlow(ElanInstance elanInfo, InterfaceInfo interfaceInfo, long macTimeout,
-            String macAddress, IMdsalApiManager mdsalApiManager) {
+                                           String macAddress, IMdsalApiManager mdsalApiManager, WriteTransaction writeFlowGroupTx) {
         FlowEntity flowEntity = buildKnownSmacFlow(elanInfo, interfaceInfo, macTimeout, macAddress);
-        mdsalApiManager.installFlow(flowEntity);
+        mdsalApiManager.addFlowToTx(flowEntity, writeFlowGroupTx);
         if (logger.isDebugEnabled()) {
             logger.debug("Known Smac flow entry created for elan Name:{}, logical Interface port:{} and mac address:{}",
-                         elanInfo.getElanInstanceName(), elanInfo.getDescription(), macAddress);
+                elanInfo.getElanInstanceName(), elanInfo.getDescription(), macAddress);
         }
     }
 
@@ -615,18 +599,18 @@ public class ElanUtils {
         int lportTag = interfaceInfo.getInterfaceTag();
         long elanTag = elanInfo.getElanTag();
         // Matching metadata and eth_src fields
-        List<MatchInfo> mkMatches = new ArrayList<>();
+        List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
         mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
-                ElanUtils.getElanMetadataLabel(elanInfo.getElanTag(), lportTag),
-                ElanUtils.getElanMetadataMask() }));
+            ElanUtils.getElanMetadataLabel(elanInfo.getElanTag(), lportTag),
+            ElanUtils.getElanMetadataMask() }));
         mkMatches.add(new MatchInfo(MatchFieldType.eth_src, new String[] { macAddress }));
-        List<InstructionInfo> mkInstructions = new ArrayList<>();
+        List<InstructionInfo> mkInstructions = new ArrayList<InstructionInfo>();
         mkInstructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { ElanConstants.ELAN_DMAC_TABLE }));
 
         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, ElanConstants.ELAN_SMAC_TABLE,
-                getKnownDynamicmacFlowRef(ElanConstants.ELAN_SMAC_TABLE, dpId, lportTag, macAddress, elanTag),
-                20, elanInfo.getDescription(), (int)macTimeout, 0, ElanConstants.COOKIE_ELAN_KNOWN_SMAC.add(BigInteger.valueOf(elanTag)),
-                mkMatches, mkInstructions);
+            getKnownDynamicmacFlowRef(ElanConstants.ELAN_SMAC_TABLE, dpId, lportTag, macAddress, elanTag),
+            20, elanInfo.getDescription(), (int)macTimeout, 0, ElanConstants.COOKIE_ELAN_KNOWN_SMAC.add(BigInteger.valueOf(elanTag)),
+            mkMatches, mkInstructions);
         flowEntity.setStrictFlag(true);
         flowEntity.setSendFlowRemFlag(macTimeout != 0); //If Mac timeout is 0, the flow wont be deleted automatically, so no need to get notified
         return flowEntity;
@@ -637,21 +621,25 @@ public class ElanUtils {
      * interface if the tunnel_id matches the interface's lportTag
      *
      * @param interfaceInfo
+     *            the interface info
      * @param mdsalApiManager
+     *            the mdsal API manager
+     * @param writeFlowGroupTx
+     *            the writeFLowGroup tx
      */
-    public static void setupTermDmacFlows(InterfaceInfo interfaceInfo, IMdsalApiManager mdsalApiManager) {
+    public static void setupTermDmacFlows(InterfaceInfo interfaceInfo, IMdsalApiManager mdsalApiManager, WriteTransaction writeFlowGroupTx) {
         BigInteger dpId = interfaceInfo.getDpId();
         int lportTag = interfaceInfo.getInterfaceTag();
         Flow flow = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
-                getIntTunnelTableFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE, lportTag), 5,
-                String.format("%s:%d","ITM Flow Entry ",lportTag), 0, 0,
-                ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(lportTag)),
-                getTunnelIdMatchForFilterEqualsLPortTag(lportTag),
-                getInstructionsInPortForOutGroup(interfaceInfo.getInterfaceName()));
-        mdsalApiManager.installFlow(dpId, flow);
+            getIntTunnelTableFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE, lportTag), 5,
+            String.format("%s:%d","ITM Flow Entry ",lportTag), 0, 0,
+            ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(lportTag)),
+            getTunnelIdMatchForFilterEqualsLPortTag(lportTag),
+            getInstructionsInPortForOutGroup(interfaceInfo.getInterfaceName()));
+        mdsalApiManager.addFlowToTx(dpId, flow, writeFlowGroupTx);
         if (logger.isDebugEnabled()) {
             logger.debug("Terminating service table flow entry created on dpn:{} for logical Interface port:{}",
-                         dpId, interfaceInfo.getPortName());
+                dpId, interfaceInfo.getPortName());
         }
     }
 
@@ -660,8 +648,10 @@ public class ElanUtils {
      * consisting in tableId + elanTag.
      *
      * @param tableId
+     *            table Id
      * @param elanTag
-     * @return
+     *            elan Tag
+     * @return the Internal tunnel
      */
     public static String getIntTunnelTableFlowRef(short tableId, int elanTag) {
         return new StringBuffer().append(tableId).append(elanTag).toString();
@@ -673,13 +663,13 @@ public class ElanUtils {
      *
      * @param lportTag
      *            lportTag that must be checked against the tunnel_id field
-     * @return
+     * @return the list of match Info
      */
     public static List<MatchInfo> getTunnelIdMatchForFilterEqualsLPortTag(int lportTag) {
-        List<MatchInfo> mkMatches = new ArrayList<>();
+        List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
         // Matching metadata
         mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {
-                BigInteger.valueOf(lportTag)}));
+            BigInteger.valueOf(lportTag)}));
         return mkMatches;
     }
 
@@ -689,10 +679,10 @@ public class ElanUtils {
      * @param ifName
      *          Name of the interface where the packet must be sent over. It can
      *          be a local interface or a tunnel interface (internal or external)
-     * @return
+     * @return the Instruction
      */
     public static List<Instruction> getInstructionsInPortForOutGroup(String ifName) {
-        List<Instruction> mkInstructions = new ArrayList<>();
+        List<Instruction> mkInstructions = new ArrayList<Instruction>();
         List<Action> actions = ElanUtils.getEgressActionsForInterface(ifName, /*tunnelKey*/ null );
 
         mkInstructions.add(MDSALUtil.buildApplyActionsInstruction(actions));
@@ -715,19 +705,19 @@ public class ElanUtils {
      * @return the egress actions for interface
      */
     public static List<Action> getEgressActionsForInterface(String ifName, Long tunnelKey) {
-        List<Action> listAction = new ArrayList<>();
+        List<Action> listAction = new ArrayList<Action>();
         try {
             GetEgressActionsForInterfaceInput getEgressActionInput =
-                    new GetEgressActionsForInterfaceInputBuilder().setIntfName(ifName).setTunnelKey(tunnelKey).build();
+                new GetEgressActionsForInterfaceInputBuilder().setIntfName(ifName).setTunnelKey(tunnelKey).build();
             Future<RpcResult<GetEgressActionsForInterfaceOutput>> result =
-                    interfaceMgrRpcService.getEgressActionsForInterface(getEgressActionInput);
+                elanServiceProvider.getInterfaceManagerRpcService().getEgressActionsForInterface(getEgressActionInput);
             RpcResult<GetEgressActionsForInterfaceOutput> rpcResult = result.get();
             if (!rpcResult.isSuccessful()) {
                 logger.warn("RPC Call to Get egress actions for interface {} returned with Errors {}",
-                            ifName, rpcResult.getErrors());
+                    ifName, rpcResult.getErrors());
             } else {
                 List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> actions =
-                        rpcResult.getResult().getAction();
+                    rpcResult.getResult().getAction();
                 listAction = actions;
             }
         } catch (InterruptedException | ExecutionException e) {
@@ -737,7 +727,7 @@ public class ElanUtils {
     }
 
     private static void setupOrigDmacFlows(ElanInstance elanInfo, InterfaceInfo interfaceInfo, String macAddress,
-            IMdsalApiManager mdsalApiManager, DataBroker broker) {
+                                           IMdsalApiManager mdsalApiManager, DataBroker broker, WriteTransaction writeFlowGroupTx) {
         BigInteger dpId = interfaceInfo.getDpId();
         String ifName = interfaceInfo.getInterfaceName();
         long ifTag = interfaceInfo.getInterfaceTag();
@@ -748,31 +738,31 @@ public class ElanUtils {
             for (DpnInterfaces elanDpn : elanDpns) {
                 if (elanDpn.getDpId().equals(dpId)) {
                     // On the local DPN set up a direct output flow
-                    setupLocalDmacFlow(elanTag, dpId, ifName, macAddress, elanInstanceName, mdsalApiManager, ifTag);
+                    setupLocalDmacFlow(elanTag, dpId, ifName, macAddress, elanInstanceName, mdsalApiManager, ifTag, writeFlowGroupTx);
                     logger.debug("Dmac flow entry created for elan Name:{}, logical port Name:{} and mac address:{} on dpn:{}",
-                                 elanInstanceName, interfaceInfo.getPortName(), macAddress, dpId);
+                        elanInstanceName, interfaceInfo.getPortName(), macAddress, dpId);
                 } else {
                     // Check for the Remote DPN present in Inventory Manager
                     if (isDpnPresent(elanDpn.getDpId())) {
                         // For remote DPNs a flow is needed to indicate that packets of this ELAN going to this MAC
                         // need to be forwarded through the appropiated ITM tunnel
                         setupRemoteDmacFlow(elanDpn.getDpId(),   // srcDpn (the remote DPN in this case)
-                                            dpId,                // dstDpn (the local DPN)
-                                            interfaceInfo.getInterfaceTag(), // lportTag of the local interface
-                                            elanTag,             // identifier of the Elan
-                                            macAddress,          // MAC to be programmed in remote DPN
-                                            elanInstanceName);
+                            dpId,                // dstDpn (the local DPN)
+                            interfaceInfo.getInterfaceTag(), // lportTag of the local interface
+                            elanTag,             // identifier of the Elan
+                            macAddress,          // MAC to be programmed in remote DPN
+                            elanInstanceName, writeFlowGroupTx);
                         logger.debug("Dmac flow entry created for elan Name:{}, logical port Name:{} and mac address:{} on dpn:{}",
-                                     elanInstanceName, interfaceInfo.getPortName(), macAddress, elanDpn.getDpId());
+                            elanInstanceName, interfaceInfo.getPortName(), macAddress, elanDpn.getDpId());
                     }
                 }
             }
 
-            // TODO (eperefr): Make sure that the same is performed against the ElanDevices.
+            // TODO: Make sure that the same is performed against the ElanDevices.
         }
     }
 
-    private static void setupOrigDmacFlowsonRemoteDpn(ElanInstance elanInfo, InterfaceInfo interfaceInfo, BigInteger dstDpId, String macAddress) {
+    private static void setupOrigDmacFlowsonRemoteDpn(ElanInstance elanInfo, InterfaceInfo interfaceInfo, BigInteger dstDpId, String macAddress, WriteTransaction writeFlowTx) {
         BigInteger dpId = interfaceInfo.getDpId();
         String elanInstanceName = elanInfo.getElanInstanceName();
         List<DpnInterfaces> remoteFEs = getInvolvedDpnsInElan(elanInstanceName);
@@ -780,7 +770,7 @@ public class ElanUtils {
             Long elanTag = elanInfo.getElanTag();
             if (remoteFE.getDpId().equals(dstDpId)) {
                 // Check for the Remote DPN present in Inventory Manager
-                setupRemoteDmacFlow(dstDpId, dpId, interfaceInfo.getInterfaceTag(), elanTag, macAddress, elanInstanceName);
+                setupRemoteDmacFlow(dstDpId, dpId, interfaceInfo.getInterfaceTag(), elanTag, macAddress, elanInstanceName, writeFlowTx);
                 if (logger.isDebugEnabled()) {
                     logger.debug("Dmac flow entry created for elan Name:{}, logical port Name:{} and mac address {} on dpn:{}", elanInstanceName, interfaceInfo.getPortName(), macAddress, remoteFE.getDpId());
                 }
@@ -792,7 +782,7 @@ public class ElanUtils {
 
     @SuppressWarnings("unchecked")
     public static List<DpnInterfaces> getInvolvedDpnsInElan(String elanName) {
-        List<DpnInterfaces> dpns = ElanInstanceManager.getElanInstanceManager().getElanDPNByName(elanName);
+        List<DpnInterfaces> dpns = ElanInstanceManager.getElanInstanceManager(elanServiceProvider).getElanDPNByName(elanName);
         if (dpns == null) {
             return Collections.emptyList();
         }
@@ -800,9 +790,9 @@ public class ElanUtils {
     }
 
     private static void setupLocalDmacFlow(long elanTag, BigInteger dpId, String ifName, String macAddress,
-                                           String displayName, IMdsalApiManager mdsalApiManager, long ifTag) {
+                                           String displayName, IMdsalApiManager mdsalApiManager, long ifTag, WriteTransaction writeFlowGroupTx) {
         Flow flowEntity = buildLocalDmacFlowEntry(elanTag, dpId, ifName, macAddress, displayName, ifTag);
-        mdsalApiManager.installFlow(dpId, flowEntity);
+        mdsalApiManager.addFlowToTx(dpId, flowEntity, writeFlowGroupTx);
 
     }
 
@@ -815,10 +805,10 @@ public class ElanUtils {
     }
 
     private static String getKnownDynamicmacFlowRef(short elanDmacTable, BigInteger dpId, String extDeviceNodeId,
-            String dstMacAddress, long elanTag, boolean shFlag) {
+                                                    String dstMacAddress, long elanTag, boolean shFlag) {
         return new StringBuffer().append(elanDmacTable).append(elanTag).append(dpId)
-                                 .append(extDeviceNodeId).append(dstMacAddress).append(shFlag)
-                                 .toString();
+            .append(extDeviceNodeId).append(dstMacAddress).append(shFlag)
+            .toString();
     }
 
     /**
@@ -842,26 +832,26 @@ public class ElanUtils {
      */
     public static Flow buildLocalDmacFlowEntry(long elanTag, BigInteger dpId, String ifName, String macAddress,
                                                String displayName, long ifTag) {
-        List<MatchInfo> mkMatches = new ArrayList<>();
+        List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
         mkMatches.add(new MatchInfo(MatchFieldType.metadata,
-                new BigInteger[] { ElanUtils.getElanMetadataLabel(elanTag), MetaDataUtil.METADATA_MASK_SERVICE }));
+            new BigInteger[] { ElanUtils.getElanMetadataLabel(elanTag), MetaDataUtil.METADATA_MASK_SERVICE }));
         mkMatches.add(new MatchInfo(MatchFieldType.eth_dst, new String[] { macAddress }));
 
-        List<Instruction> mkInstructions = new ArrayList<>();
+        List<Instruction> mkInstructions = new ArrayList<Instruction>();
         List<Action> actions = getEgressActionsForInterface(ifName, /* tunnelKey */ null);
         mkInstructions.add(MDSALUtil.buildApplyActionsInstruction(actions));
         Flow flow = MDSALUtil.buildFlowNew(ElanConstants.ELAN_DMAC_TABLE,
-                getKnownDynamicmacFlowRef(ElanConstants.ELAN_DMAC_TABLE, dpId, ifTag, macAddress, elanTag), 20,
-                displayName, 0, 0, ElanConstants.COOKIE_ELAN_KNOWN_DMAC.add(BigInteger.valueOf(elanTag)), mkMatches,
-                mkInstructions);
+            getKnownDynamicmacFlowRef(ElanConstants.ELAN_DMAC_TABLE, dpId, ifTag, macAddress, elanTag), 20,
+            displayName, 0, 0, ElanConstants.COOKIE_ELAN_KNOWN_DMAC.add(BigInteger.valueOf(elanTag)), mkMatches,
+            mkInstructions);
 
         return flow;
     }
 
     public static void setupRemoteDmacFlow(BigInteger srcDpId, BigInteger destDpId, int lportTag, long elanTag, String macAddress,
-                                           String displayName) {
+                                           String displayName, WriteTransaction writeFlowGroupTx) {
         Flow flowEntity = buildRemoteDmacFlowEntry(srcDpId, destDpId, lportTag, elanTag, macAddress, displayName);
-        mdsalMgr.installFlow(srcDpId, flowEntity);
+        elanServiceProvider.getMdsalManager().addFlowToTx(srcDpId, flowEntity, writeFlowGroupTx);
     }
 
     /**
@@ -875,22 +865,28 @@ public class ElanUtils {
      *    + output ITM internal tunnel interface with the other DPN
      *
      * @param srcDpId
+     *            the src Dpn Id
      * @param destDpId
+     *            dest Dp Id
      * @param lportTag
+     *            lport Tag
      * @param elanTag
+     *            elan Tag
      * @param macAddress
+     *            macAddress
      * @param displayName
-     * @return
+     *            display Name
+     * @return the flow remote Dmac
      */
     public static Flow buildRemoteDmacFlowEntry(BigInteger srcDpId, BigInteger destDpId, int lportTag, long elanTag,
-                                                 String macAddress, String displayName) {
-        List<MatchInfo> mkMatches = new ArrayList<>();
+                                                String macAddress, String displayName) {
+        List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
         mkMatches.add(new MatchInfo(MatchFieldType.metadata,
-                                    new BigInteger[]{ ElanUtils.getElanMetadataLabel(elanTag),
-                                                      MetaDataUtil.METADATA_MASK_SERVICE }));
+            new BigInteger[]{ ElanUtils.getElanMetadataLabel(elanTag),
+                MetaDataUtil.METADATA_MASK_SERVICE }));
         mkMatches.add(new MatchInfo(MatchFieldType.eth_dst, new String[] { macAddress }));
 
-        List<Instruction> mkInstructions = new ArrayList<>();
+        List<Instruction> mkInstructions = new ArrayList<Instruction>();
 
         //List of Action for the provided Source and Destination DPIDs
         try {
@@ -902,53 +898,66 @@ public class ElanUtils {
 
 
         Flow flow = MDSALUtil.buildFlowNew(ElanConstants.ELAN_DMAC_TABLE,
-                getKnownDynamicmacFlowRef(ElanConstants.ELAN_DMAC_TABLE, srcDpId, destDpId, macAddress, elanTag),
-                20,  /* prio */
-                displayName, 0,   /* idleTimeout */
-                0,   /* hardTimeout */
-                ElanConstants.COOKIE_ELAN_KNOWN_DMAC.add(BigInteger.valueOf(elanTag)), mkMatches, mkInstructions);
+            getKnownDynamicmacFlowRef(ElanConstants.ELAN_DMAC_TABLE, srcDpId, destDpId, macAddress, elanTag),
+            20,  /* prio */
+            displayName, 0,   /* idleTimeout */
+            0,   /* hardTimeout */
+            ElanConstants.COOKIE_ELAN_KNOWN_DMAC.add(BigInteger.valueOf(elanTag)), mkMatches, mkInstructions);
 
         return flow;
 
     }
 
-    public static void deleteMacFlows(ElanInstance elanInfo, InterfaceInfo interfaceInfo, MacEntry macEntry) {
+    public static void deleteMacFlows(ElanInstance elanInfo, InterfaceInfo interfaceInfo, MacEntry macEntry, WriteTransaction deleteFlowGroupTx) {
         if (elanInfo == null || interfaceInfo == null) {
             return;
         }
         String macAddress = macEntry.getMacAddress().getValue();
         synchronized (macAddress) {
             logger.info("Acquired lock for mac : " + macAddress + "Proceeding with remove operation.");
-            deleteMacFlows(elanInfo, interfaceInfo,  macAddress, /* alsoDeleteSMAC */ true);
+            deleteMacFlows(elanInfo, interfaceInfo,  macAddress, /* alsoDeleteSMAC */ true, deleteFlowGroupTx);
         }
     }
 
-    public static void deleteMacFlows(ElanInstance elanInfo, InterfaceInfo interfaceInfo, String macAddress, boolean deleteSmac) {
+    public static void deleteMacFlows(ElanInstance elanInfo, InterfaceInfo interfaceInfo, String macAddress, boolean deleteSmac, WriteTransaction deleteFlowGroupTx) {
         String elanInstanceName = elanInfo.getElanInstanceName();
-        long ifTag = interfaceInfo.getInterfaceTag();
         List<DpnInterfaces> remoteFEs = getInvolvedDpnsInElan(elanInstanceName);
         BigInteger srcdpId = interfaceInfo.getDpId();
+        boolean isFlowsRemovedInSrcDpn = false;
         for (DpnInterfaces dpnInterface: remoteFEs) {
             Long elanTag = elanInfo.getElanTag();
             BigInteger dstDpId = dpnInterface.getDpId();
             if (dstDpId.equals(srcdpId)) {
-                if(deleteSmac) {
-                    mdsalMgr.removeFlow(srcdpId, MDSALUtil.buildFlow(ElanConstants.ELAN_SMAC_TABLE,
-                            getKnownDynamicmacFlowRef(ElanConstants.ELAN_SMAC_TABLE, srcdpId, ifTag, macAddress, elanTag)));
-                }
-                mdsalMgr.removeFlow(srcdpId, MDSALUtil.buildFlow(ElanConstants.ELAN_DMAC_TABLE,
-                        getKnownDynamicmacFlowRef(ElanConstants.ELAN_DMAC_TABLE, srcdpId, ifTag, macAddress, elanTag)));
-                if (logger.isDebugEnabled()) {
-                    logger.debug("All the required flows deleted for elan:{}, logical Interface port:{} and mac address:{} on dpn:{}", elanInstanceName, interfaceInfo.getPortName(), macAddress, srcdpId);
-                }
+                isFlowsRemovedInSrcDpn = true;
+                deleteSmacAndDmacFlows(elanInfo, interfaceInfo, macAddress, deleteSmac, deleteFlowGroupTx);
             } else if (isDpnPresent(dstDpId)) {
-                mdsalMgr.removeFlow(dstDpId, MDSALUtil.buildFlow(ElanConstants.ELAN_DMAC_TABLE,
-                        getKnownDynamicmacFlowRef(ElanConstants.ELAN_DMAC_TABLE, dstDpId, srcdpId, macAddress, elanTag)));
+                elanServiceProvider.getMdsalManager().removeFlowToTx(dstDpId, MDSALUtil.buildFlow(ElanConstants.ELAN_DMAC_TABLE,
+                    getKnownDynamicmacFlowRef(ElanConstants.ELAN_DMAC_TABLE, dstDpId, srcdpId, macAddress, elanTag)), deleteFlowGroupTx);
                 if (logger.isDebugEnabled()) {
                     logger.debug("Dmac flow entry deleted for elan:{}, logical interface port:{} and mac address:{} on dpn:{}", elanInstanceName, interfaceInfo.getPortName(), macAddress, dstDpId);
                 }
             }
         }
+        if (!isFlowsRemovedInSrcDpn) {
+            deleteSmacAndDmacFlows(elanInfo, interfaceInfo, macAddress, deleteSmac, deleteFlowGroupTx);
+        }
+    }
+
+    private static void deleteSmacAndDmacFlows(ElanInstance elanInfo,InterfaceInfo interfaceInfo, String macAddress,
+                                               boolean deleteSmac, WriteTransaction deleteFlowGroupTx) {
+        String elanInstanceName = elanInfo.getElanInstanceName();
+        long ifTag = interfaceInfo.getInterfaceTag();
+        BigInteger srcdpId = interfaceInfo.getDpId();
+        Long elanTag = elanInfo.getElanTag();
+        if (deleteSmac) {
+            elanServiceProvider.getMdsalManager().removeFlowToTx(srcdpId, MDSALUtil.buildFlow(ElanConstants.ELAN_SMAC_TABLE,
+                getKnownDynamicmacFlowRef(ElanConstants.ELAN_SMAC_TABLE, srcdpId, ifTag, macAddress, elanTag)), deleteFlowGroupTx);
+        }
+        elanServiceProvider.getMdsalManager().removeFlowToTx(srcdpId, MDSALUtil.buildFlow(ElanConstants.ELAN_DMAC_TABLE,
+            getKnownDynamicmacFlowRef(ElanConstants.ELAN_DMAC_TABLE, srcdpId, ifTag, macAddress, elanTag)), deleteFlowGroupTx);
+        if (logger.isDebugEnabled()) {
+            logger.debug("All the required flows deleted for elan:{}, logical Interface port:{} and mac address:{} on dpn:{}", elanInstanceName, interfaceInfo.getPortName(), macAddress, srcdpId);
+        }
     }
 
     /**
@@ -961,37 +970,38 @@ public class ElanUtils {
      *            the id manager
      * @param elanInstanceAdded
      *            the elan instance added
+     * @param tx
+     *            transaction
      */
     public static void updateOperationalDataStore(DataBroker broker, IdManagerService idManager,
-            ElanInstance elanInstanceAdded) {
+                                                  ElanInstance elanInstanceAdded, List<String> elanInterfaces, WriteTransaction tx) {
         String elanInstanceName = elanInstanceAdded.getElanInstanceName();
-        long elanTag = ElanUtils.retrieveNewElanTag(idManager, elanInstanceName);
-        Elan elanInfo = new ElanBuilder().setName(elanInstanceName).setKey(new ElanKey(elanInstanceName)).build();
+        Long elanTag = elanInstanceAdded.getElanTag();
+        if (elanTag == null || elanTag == 0L) {
+            elanTag = ElanUtils.retrieveNewElanTag(idManager, elanInstanceName);
+        }
+        Elan elanInfo = new ElanBuilder().setName(elanInstanceName).setElanInterfaces(elanInterfaces).setKey(new ElanKey(elanInstanceName)).build();
 
         //Add the ElanState in the elan-state operational data-store
-        MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL,
-                ElanUtils.getElanInstanceOperationalDataPath(elanInstanceName), elanInfo);
+        tx.put(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanInstanceName), elanInfo, true);
 
         //Add the ElanMacTable in the elan-mac-table operational data-store
         MacTable elanMacTable = new MacTableBuilder().setKey(new MacTableKey(elanInstanceName)).build();
-        MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL,
-                ElanUtils.getElanMacTableOperationalDataPath(elanInstanceName), elanMacTable);
+        tx.put(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanMacTableOperationalDataPath(elanInstanceName), elanMacTable, true);
 
         ElanTagName elanTagName = new ElanTagNameBuilder().setElanTag(elanTag).setKey(new ElanTagNameKey(elanTag))
-                .setName(elanInstanceName).build();
+            .setName(elanInstanceName).build();
 
         //Add the ElanTag to ElanName in the elan-tag-name Operational data-store
-        MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL,
-                ElanUtils.getElanInfoEntriesOperationalDataPath(elanTag), elanTagName);
+        tx.put(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInfoEntriesOperationalDataPath(elanTag), elanTagName, true);
 
         // Updates the ElanInstance Config DS by setting the just adquired elanTag
         ElanInstance elanInstanceWithTag = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName)
-                .setDescription(elanInstanceAdded.getDescription())
-                .setMacTimeout(elanInstanceAdded.getMacTimeout() == null ?  ElanConstants.DEFAULT_MAC_TIME_OUT
-                        : elanInstanceAdded.getMacTimeout())
-                .setKey(elanInstanceAdded.getKey()).setElanTag(elanTag).build();
-        MDSALUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION,
-                getElanInstanceConfigurationDataPath(elanInstanceName), elanInstanceWithTag);
+            .setDescription(elanInstanceAdded.getDescription())
+            .setMacTimeout(elanInstanceAdded.getMacTimeout() == null ?  ElanConstants.DEFAULT_MAC_TIME_OUT
+                : elanInstanceAdded.getMacTimeout())
+            .setKey(elanInstanceAdded.getKey()).setElanTag(elanTag).build();
+        tx.merge(LogicalDatastoreType.CONFIGURATION, getElanInstanceConfigurationDataPath(elanInstanceName), elanInstanceWithTag, true);
     }
 
     public static boolean isDpnPresent(BigInteger dpnId) {
@@ -999,32 +1009,32 @@ public class ElanUtils {
         NodeId nodeId = new NodeId(dpn);
 
         InstanceIdentifier<Node> node = InstanceIdentifier.builder(Nodes.class).child(Node.class, new NodeKey(nodeId))
-                .build();
-        Optional<Node> nodePresent = read(dataBroker, LogicalDatastoreType.OPERATIONAL, node);
+            .build();
+        Optional<Node> nodePresent = read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, node);
         return (nodePresent.isPresent());
     }
 
     public static ServicesInfo getServiceInfo(String elanInstanceName, long elanTag, String interfaceName) {
         int priority = ElanConstants.ELAN_SERVICE_PRIORITY;
         int instructionKey = 0;
-        List<Instruction> instructions = new ArrayList<>();
+        List<Instruction> instructions = new ArrayList<Instruction>();
         instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(ElanUtils.getElanMetadataLabel(elanTag), MetaDataUtil.METADATA_MASK_SERVICE, ++instructionKey));
         instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(ElanConstants.ELAN_SMAC_TABLE, ++instructionKey));
 
         ServicesInfo serviceInfo = InterfaceServiceUtil.buildServiceInfo(String.format("%s.%s", elanInstanceName, interfaceName), ElanConstants.ELAN_SERVICE_INDEX,
-                priority, ElanConstants.COOKIE_ELAN_INGRESS_TABLE, instructions);
+            priority, ElanConstants.COOKIE_ELAN_INGRESS_TABLE, instructions);
         return serviceInfo;
     }
 
     public static <T extends DataObject> void delete(DataBroker broker, LogicalDatastoreType datastoreType,
-            InstanceIdentifier<T> path, FutureCallback<Void> callback) {
+                                                     InstanceIdentifier<T> path, FutureCallback<Void> callback) {
         WriteTransaction tx = broker.newWriteOnlyTransaction();
         tx.delete(datastoreType, path);
         Futures.addCallback(tx.submit(), callback);
     }
 
     public static <T extends DataObject> void syncWrite(DataBroker broker, LogicalDatastoreType datastoreType,
-            InstanceIdentifier<T> path, T data) {
+                                                        InstanceIdentifier<T> path, T data) {
         WriteTransaction tx = broker.newWriteOnlyTransaction();
         tx.put(datastoreType, path, data, true);
         CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
@@ -1038,17 +1048,16 @@ public class ElanUtils {
 
 
     public static BoundServices getBoundServices(String serviceName, short servicePriority, int flowPriority,
-            BigInteger cookie, List<Instruction> instructions) {
+                                                 BigInteger cookie, List<Instruction> instructions) {
         StypeOpenflowBuilder augBuilder = new StypeOpenflowBuilder().setFlowCookie(cookie).setFlowPriority(flowPriority).setInstruction(instructions);
         return new BoundServicesBuilder().setKey(new BoundServicesKey(servicePriority))
-                .setServiceName(serviceName).setServicePriority(servicePriority)
-                .setServiceType(ServiceTypeFlowBased.class).addAugmentation(StypeOpenflow.class, augBuilder.build()).build();
+            .setServiceName(serviceName).setServicePriority(servicePriority)
+            .setServiceType(ServiceTypeFlowBased.class).addAugmentation(StypeOpenflow.class, augBuilder.build()).build();
     }
 
     public static InstanceIdentifier<BoundServices> buildServiceId(String vpnInterfaceName, short serviceIndex) {
-        return InstanceIdentifier.builder(ServiceBindings.class).child(ServicesInfo.class,
-                new ServicesInfoKey(vpnInterfaceName, ServiceModeIngress.class))
-                .child(BoundServices.class, new BoundServicesKey(serviceIndex)).build();
+        return InstanceIdentifier.builder(ServiceBindings.class).child(ServicesInfo.class, new ServicesInfoKey(vpnInterfaceName, ServiceModeIngress.class))
+            .child(BoundServices.class, new BoundServicesKey(serviceIndex)).build();
     }
 
     /**
@@ -1066,10 +1075,10 @@ public class ElanUtils {
         List<Action> result = Collections.emptyList();
         if (tunnelIfaceName != null && !tunnelIfaceName.isEmpty()) {
             GetEgressActionsForInterfaceInput getEgressActInput = new GetEgressActionsForInterfaceInputBuilder()
-                    .setIntfName(tunnelIfaceName).setTunnelKey(tunnelKey).build();
+                .setIntfName(tunnelIfaceName).setTunnelKey(tunnelKey).build();
 
             Future<RpcResult<GetEgressActionsForInterfaceOutput>> egressActionsOutputFuture =
-                    interfaceMgrRpcService.getEgressActionsForInterface(getEgressActInput);
+                elanServiceProvider.getInterfaceManagerRpcService().getEgressActionsForInterface(getEgressActInput);
             try {
                 if (egressActionsOutputFuture.get().isSuccessful()) {
                     GetEgressActionsForInterfaceOutput egressActionsOutput = egressActionsOutputFuture.get().getResult();
@@ -1104,9 +1113,9 @@ public class ElanUtils {
         List<Action> result = Collections.emptyList();
 
         GetExternalTunnelInterfaceNameInput input = new GetExternalTunnelInterfaceNameInputBuilder()
-                .setDestinationNode(torNode.getValue()).setSourceNode(srcDpnId.toString()).setTunnelType(TunnelTypeVxlan.class).build();
+            .setDestinationNode(torNode.getValue()).setSourceNode(srcDpnId.toString()).setTunnelType(TunnelTypeVxlan.class).build();
         Future<RpcResult<GetExternalTunnelInterfaceNameOutput>> output =
-                itmRpcService.getExternalTunnelInterfaceName(input);
+            elanServiceProvider.getItmRpcService().getExternalTunnelInterfaceName(input);
         try {
             if (output.get().isSuccessful()) {
                 GetExternalTunnelInterfaceNameOutput tunnelInterfaceNameOutput = output.get().getResult();
@@ -1140,15 +1149,15 @@ public class ElanUtils {
      * @return the internal itm egress action
      */
     public static List<Action> getInternalItmEgressAction(BigInteger sourceDpnId, BigInteger destinationDpnId,
-            long serviceTag) {
+                                                          long serviceTag) {
         List<Action> result = Collections.emptyList();
 
         logger.debug("In getInternalItmEgressAction Action source {}, destination {}, elanTag {}",
-                     sourceDpnId, destinationDpnId, serviceTag);
+            sourceDpnId, destinationDpnId, serviceTag);
         Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
         GetTunnelInterfaceNameInput input = new GetTunnelInterfaceNameInputBuilder()
-                .setDestinationDpid(destinationDpnId).setSourceDpid(sourceDpnId).setTunnelType(tunType).build();
-        Future<RpcResult<GetTunnelInterfaceNameOutput>> output = itmRpcService.getTunnelInterfaceName(input);
+            .setDestinationDpid(destinationDpnId).setSourceDpid(sourceDpnId).setTunnelType(tunType).build();
+        Future<RpcResult<GetTunnelInterfaceNameOutput>> output = elanServiceProvider.getItmRpcService().getTunnelInterfaceName(input);
         try {
             if (output.get().isSuccessful()) {
                 GetTunnelInterfaceNameOutput tunnelInterfaceNameOutput = output.get().getResult();
@@ -1165,7 +1174,7 @@ public class ElanUtils {
     }
 
     public static List<MatchInfo> getTunnelMatchesForServiceId(int elanTag) {
-        List<MatchInfo> mkMatches = new ArrayList<>();
+        List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
         // Matching metadata
         mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[]{BigInteger.valueOf(elanTag)}));
 
@@ -1174,7 +1183,7 @@ public class ElanUtils {
 
     public static void removeTerminatingServiceAction(BigInteger destDpId, int serviceId) {
         RemoveTerminatingServiceActionsInput input = new RemoveTerminatingServiceActionsInputBuilder().setDpnId(destDpId).setServiceId(serviceId).build();
-        Future<RpcResult<Void>> futureObject = itmRpcService.removeTerminatingServiceActions(input);
+        Future<RpcResult<Void>> futureObject = elanServiceProvider.getItmRpcService().removeTerminatingServiceActions(input);
         try {
             RpcResult<Void> result = futureObject.get();
             if (result.isSuccessful()) {
@@ -1188,11 +1197,11 @@ public class ElanUtils {
     }
 
     public static void createTerminatingServiceActions(BigInteger destDpId, int serviceId, List<Action> actions) {
-        List<Instruction> mkInstructions = new ArrayList<>();
+        List<Instruction> mkInstructions = new ArrayList<Instruction>();
         mkInstructions.add(MDSALUtil.buildApplyActionsInstruction(actions));
         CreateTerminatingServiceActionsInput input = new CreateTerminatingServiceActionsInputBuilder().setDpnId(destDpId).setServiceId(serviceId).setInstruction(mkInstructions).build();
 
-        itmRpcService.createTerminatingServiceActions(input);
+        elanServiceProvider.getItmRpcService().createTerminatingServiceActions(input);
     }
 
     public static TunnelList buildInternalTunnel(DataBroker broker) {
@@ -1216,12 +1225,12 @@ public class ElanUtils {
      * @return the external tunnel
      */
     public static ExternalTunnel getExternalTunnel(String sourceDevice, String destinationDevice,
-            LogicalDatastoreType datastoreType) {
+                                                   LogicalDatastoreType datastoreType) {
         ExternalTunnel externalTunnel = null;
         Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class ;
         InstanceIdentifier<ExternalTunnel> iid = InstanceIdentifier.builder(ExternalTunnelList.class)
-                .child(ExternalTunnel.class, new ExternalTunnelKey(destinationDevice, sourceDevice, tunType)).build();
-        Optional<ExternalTunnel> tunnelList = read(dataBroker, datastoreType, iid);
+            .child(ExternalTunnel.class, new ExternalTunnelKey(destinationDevice, sourceDevice, tunType)).build();
+        Optional<ExternalTunnel> tunnelList = read(elanServiceProvider.getBroker(), datastoreType, iid);
         if (tunnelList.isPresent()) {
             externalTunnel = tunnelList.get();
         }
@@ -1252,12 +1261,14 @@ public class ElanUtils {
     /**
      * Gets the all external tunnels.
      *
+     * @param datastoreType
+     *              the data store type
      * @return the all external tunnels
      */
     public static List<ExternalTunnel> getAllExternalTunnels(LogicalDatastoreType datastoreType) {
         List<ExternalTunnel> result = null;
         InstanceIdentifier<ExternalTunnelList> iid = InstanceIdentifier.builder(ExternalTunnelList.class).build();
-        Optional<ExternalTunnelList> tunnelList = read(dataBroker, datastoreType, iid);
+        Optional<ExternalTunnelList> tunnelList = read(elanServiceProvider.getBroker(), datastoreType, iid);
         if (tunnelList.isPresent()) {
             result = tunnelList.get().getExternalTunnel();
         }
@@ -1287,9 +1298,9 @@ public class ElanUtils {
      *            the display name
      */
     public static void installDmacFlowsToInternalRemoteMac(BigInteger localDpId, BigInteger remoteDpId, long lportTag,
-            long elanTag, String macAddress, String displayName) {
+                                                           long elanTag, String macAddress, String displayName) {
         Flow flow = buildDmacFlowForInternalRemoteMac(localDpId, remoteDpId, lportTag, elanTag, macAddress, displayName);
-        mdsalMgr.installFlow(remoteDpId, flow);
+        elanServiceProvider.getMdsalManager().installFlow(remoteDpId, flow);
     }
 
     /**
@@ -1311,24 +1322,26 @@ public class ElanUtils {
      *            the mac address
      * @param displayName
      *            the display name
+     *
+     * @return the dmac flows
      */
     public static List<ListenableFuture<Void>> installDmacFlowsToExternalRemoteMac(BigInteger dpnId,
-            String extDeviceNodeId, Long elanTag, Long vni, String macAddress, String displayName) {
+                                                                                   String extDeviceNodeId, Long elanTag, Long vni, String macAddress, String displayName) {
         List<ListenableFuture<Void>> futures = new ArrayList<>();
         synchronized (macAddress) {
             Flow flow = buildDmacFlowForExternalRemoteMac(dpnId, extDeviceNodeId, elanTag, vni, macAddress, displayName);
-            futures.add(mdsalMgr.installFlow(dpnId, flow));
+            futures.add(elanServiceProvider.getMdsalManager().installFlow(dpnId, flow));
 
             Flow dropFlow = buildDmacFlowDropIfPacketComingFromTunnel(dpnId, extDeviceNodeId, elanTag, macAddress);
-            futures.add(mdsalMgr.installFlow(dpnId, dropFlow));
+            futures.add(elanServiceProvider.getMdsalManager().installFlow(dpnId, dropFlow));
         }
         return futures;
     }
 
     public static List<MatchInfo> buildMatchesForElanTagShFlagAndDstMac(long elanTag, boolean shFlag, String macAddr) {
-        List<MatchInfo> mkMatches = new ArrayList<>();
+        List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
         mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
-                ElanUtils.getElanMetadataLabel(elanTag, shFlag), MetaDataUtil.METADATA_MASK_SERVICE_SH_FLAG }));
+            ElanUtils.getElanMetadataLabel(elanTag, shFlag), MetaDataUtil.METADATA_MASK_SERVICE_SH_FLAG }));
         mkMatches.add(new MatchInfo(MatchFieldType.eth_dst, new String[] { macAddr }));
 
         return mkMatches;
@@ -1350,9 +1363,9 @@ public class ElanUtils {
      * @return the flow
      */
     public static Flow buildDmacFlowForExternalRemoteMac(BigInteger dpId, String extDeviceNodeId, long elanTag,
-            Long vni, String dstMacAddress, String displayName ) {
+                                                         Long vni, String dstMacAddress, String displayName ) {
         List<MatchInfo> mkMatches = buildMatchesForElanTagShFlagAndDstMac(elanTag, /*shFlag*/ false, dstMacAddress);
-        List<Instruction> mkInstructions = new ArrayList<>();
+        List<Instruction> mkInstructions = new ArrayList<Instruction>();
         try {
             List<Action> actions = getExternalItmEgressAction(dpId, new NodeId(extDeviceNodeId), vni);
             mkInstructions.add( MDSALUtil.buildApplyActionsInstruction(actions) );
@@ -1361,12 +1374,12 @@ public class ElanUtils {
         }
 
         Flow flow = MDSALUtil.buildFlowNew(ElanConstants.ELAN_DMAC_TABLE,
-                getKnownDynamicmacFlowRef(ElanConstants.ELAN_DMAC_TABLE, dpId, extDeviceNodeId, dstMacAddress, elanTag,
-                        false),
-                20,  /* prio */
-                displayName, 0,   /* idleTimeout */
-                0,   /* hardTimeout */
-                ElanConstants.COOKIE_ELAN_KNOWN_DMAC.add(BigInteger.valueOf(elanTag)), mkMatches, mkInstructions);
+            getKnownDynamicmacFlowRef(ElanConstants.ELAN_DMAC_TABLE, dpId, extDeviceNodeId, dstMacAddress, elanTag,
+                false),
+            20,  /* prio */
+            displayName, 0,   /* idleTimeout */
+            0,   /* hardTimeout */
+            ElanConstants.COOKIE_ELAN_KNOWN_DMAC.add(BigInteger.valueOf(elanTag)), mkMatches, mkInstructions);
 
         return flow;
     }
@@ -1383,22 +1396,22 @@ public class ElanUtils {
      * @return
      */
     private static Flow buildDmacFlowDropIfPacketComingFromTunnel(BigInteger dpnId, String extDeviceNodeId,
-            Long elanTag, String dstMacAddress) {
+                                                                  Long elanTag, String dstMacAddress) {
         List<MatchInfo> mkMatches = buildMatchesForElanTagShFlagAndDstMac(elanTag, /*shFlag*/ true, dstMacAddress);
         List<Instruction> mkInstructions = MDSALUtil.buildInstructionsDrop();
         String flowId = getKnownDynamicmacFlowRef(ElanConstants.ELAN_DMAC_TABLE, dpnId, extDeviceNodeId, dstMacAddress,
-                elanTag, true);
+            elanTag, true);
         Flow flow = MDSALUtil.buildFlowNew(ElanConstants.ELAN_DMAC_TABLE, flowId, 20,  /* prio */
-                "Drop", 0,   /* idleTimeout */
-                0,   /* hardTimeout */
-                ElanConstants.COOKIE_ELAN_KNOWN_DMAC.add(BigInteger.valueOf(elanTag)), mkMatches, mkInstructions);
+            "Drop", 0,   /* idleTimeout */
+            0,   /* hardTimeout */
+            ElanConstants.COOKIE_ELAN_KNOWN_DMAC.add(BigInteger.valueOf(elanTag)), mkMatches, mkInstructions);
 
         return flow;
     }
 
     private static String getDmacDropFlowId(Long elanTag, String dstMacAddress) {
         return new StringBuilder(ElanConstants.ELAN_DMAC_TABLE).append(elanTag).append(dstMacAddress).append("Drop")
-                .toString();
+            .toString();
     }
 
     /**
@@ -1422,10 +1435,10 @@ public class ElanUtils {
      * @return the flow
      */
     public static Flow buildDmacFlowForInternalRemoteMac(BigInteger localDpId, BigInteger remoteDpId, long lportTag,
-            long elanTag, String macAddress, String displayName) {
+                                                         long elanTag, String macAddress, String displayName) {
         List<MatchInfo> mkMatches = buildMatchesForElanTagShFlagAndDstMac(elanTag, /*shFlag*/ false, macAddress);
 
-        List<Instruction> mkInstructions = new ArrayList<>();
+        List<Instruction> mkInstructions = new ArrayList<Instruction>();
 
         try {
             //List of Action for the provided Source and Destination DPIDs
@@ -1433,15 +1446,15 @@ public class ElanUtils {
             mkInstructions.add( MDSALUtil.buildApplyActionsInstruction(actions) );
         } catch (Exception e) {
             logger.error("Could not get Egress Actions for localDpId={}  remoteDpId={}   lportTag={}",
-                         localDpId, remoteDpId, lportTag);
+                localDpId, remoteDpId, lportTag);
         }
 
         Flow flow = MDSALUtil.buildFlowNew(ElanConstants.ELAN_DMAC_TABLE,
-                getKnownDynamicmacFlowRef(ElanConstants.ELAN_DMAC_TABLE, localDpId, remoteDpId, macAddress, elanTag),
-                20,  /* prio */
-                displayName, 0,   /* idleTimeout */
-                0,   /* hardTimeout */
-                ElanConstants.COOKIE_ELAN_KNOWN_DMAC.add(BigInteger.valueOf(elanTag)), mkMatches, mkInstructions);
+            getKnownDynamicmacFlowRef(ElanConstants.ELAN_DMAC_TABLE, localDpId, remoteDpId, macAddress, elanTag),
+            20,  /* prio */
+            displayName, 0,   /* idleTimeout */
+            0,   /* hardTimeout */
+            ElanConstants.COOKIE_ELAN_KNOWN_DMAC.add(BigInteger.valueOf(elanTag)), mkMatches, mkInstructions);
 
         return flow;
 
@@ -1469,7 +1482,7 @@ public class ElanUtils {
      * @see org.opendaylight.genius.mdsalutil.MDSALUtil.MdsalOp
      */
     public static void setupDmacFlowsToExternalRemoteMac(BigInteger dpId, String extNodeId, Long elanTag, Long vni,
-            String macAddress, String elanInstanceName, MdsalOp addOrRemove) {
+                                                         String macAddress, String elanInstanceName, MdsalOp addOrRemove) {
         if ( addOrRemove == MdsalOp.CREATION_OP ) {
             ElanUtils.installDmacFlowsToExternalRemoteMac(dpId, extNodeId, elanTag, vni, macAddress, elanInstanceName);
         } else if ( addOrRemove == MdsalOp.REMOVAL_OP ) {
@@ -1488,24 +1501,25 @@ public class ElanUtils {
      *            the ext device node id
      * @param macToRemove
      *            the mac to remove
+     * @return dmac flow
      */
     public static List<ListenableFuture<Void>> deleteDmacFlowsToExternalMac(long elanTag, BigInteger dpId,
-            String extDeviceNodeId, String macToRemove ) {
+                                                                            String extDeviceNodeId, String macToRemove ) {
         List<ListenableFuture<Void>> futures = new ArrayList<>();
         synchronized (macToRemove) {
             // Removing the flows that sends the packet on an external tunnel
             String flowId = getKnownDynamicmacFlowRef(ElanConstants.ELAN_DMAC_TABLE, dpId, extDeviceNodeId,
-                    macToRemove, elanTag, false);
+                macToRemove, elanTag, false);
             Flow flowToRemove = new FlowBuilder().setId(new FlowId(flowId)).setTableId(ElanConstants.ELAN_DMAC_TABLE)
-                    .build();
-            futures.add(mdsalMgr.removeFlow(dpId, flowToRemove));
+                .build();
+            futures.add(elanServiceProvider.getMdsalManager().removeFlow(dpId, flowToRemove));
 
             // And now removing the drop flow
             flowId = getKnownDynamicmacFlowRef(ElanConstants.ELAN_DMAC_TABLE, dpId, extDeviceNodeId, macToRemove,
-                    elanTag, true);
+                elanTag, true);
             flowToRemove = new FlowBuilder().setId(new FlowId(flowId)).setTableId(ElanConstants.ELAN_DMAC_TABLE)
-                    .build();
-            futures.add(mdsalMgr.removeFlow(dpId, flowToRemove));
+                .build();
+            futures.add(elanServiceProvider.getMdsalManager().removeFlow(dpId, flowToRemove));
         }
         return futures;
     }
@@ -1519,8 +1533,8 @@ public class ElanUtils {
      */
     public static BigInteger getDpidFromInterface(String interfaceName) {
         BigInteger dpId = null;
-        Future<RpcResult<GetDpidFromInterfaceOutput>> output = interfaceMgrRpcService
-                .getDpidFromInterface(new GetDpidFromInterfaceInputBuilder().setIntfName(interfaceName).build());
+        Future<RpcResult<GetDpidFromInterfaceOutput>> output = elanServiceProvider.getInterfaceManagerRpcService()
+            .getDpidFromInterface(new GetDpidFromInterfaceInputBuilder().setIntfName(interfaceName).build());
         try {
             RpcResult<GetDpidFromInterfaceOutput> rpcResult = output.get();
             if (rpcResult.isSuccessful()) {
@@ -1562,11 +1576,11 @@ public class ElanUtils {
      * @return the interface state from oper ds
      */
     public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface getInterfaceStateFromOperDS(
-            String interfaceName, DataBroker dataBroker) {
+        String interfaceName, DataBroker dataBroker) {
         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId = createInterfaceStateInstanceIdentifier(
-                interfaceName);
+            interfaceName);
         Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateOptional = MDSALUtil
-                .read(dataBroker, LogicalDatastoreType.OPERATIONAL, ifStateId);
+            .read(dataBroker, LogicalDatastoreType.OPERATIONAL, ifStateId);
         if (ifStateOptional.isPresent()) {
             return ifStateOptional.get();
         }
@@ -1581,14 +1595,23 @@ public class ElanUtils {
      * @return the instance identifier
      */
     public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> createInterfaceStateInstanceIdentifier(
-            String interfaceName) {
+        String interfaceName) {
         InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> idBuilder = InstanceIdentifier
-                .builder(InterfacesState.class)
-                .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class,
-                        new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey(
-                                interfaceName));
+            .builder(InterfacesState.class)
+            .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class,
+                new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey(
+                    interfaceName));
         return idBuilder.build();
     }
 
+    public static void waitForTransactionToComplete(WriteTransaction tx) {
+        CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
+        try {
+            futures.get();
+        } catch (InterruptedException | ExecutionException e) {
+            logger.error("Error writing to datastore {}", e);
+        }
+    }
+
 }
 
index 9938a584bf44de9e3ab31dd68fb8ca4c5f376c22..cae7440937a39a6ef64a37dab3a1727d34940b7d 100644 (file)
@@ -46,6 +46,10 @@ module neutronvpn {
             leaf-list port-list {
               type yang:uuid;
             }
+
+            leaf-list direct-port-list{
+              type yang:uuid;
+            }
         }
     }
 
index 40f697c5c5a8f1aae33e2ff95c0708c4c04a9565..1ae7aed907f71537e2915f08c94db9e075a43d94 100644 (file)
@@ -66,19 +66,16 @@ public class NeutronPortChangeListener extends AbstractDataChangeListener<Port>
     private LockManagerService lockManager;
     private NotificationPublishService notificationPublishService;
     private NotificationService notificationService;
-    private NeutronFloatingToFixedIpMappingChangeListener floatingIpMapListener;
 
 
     public NeutronPortChangeListener(final DataBroker db, NeutronvpnManager nVpnMgr,NeutronvpnNatManager nVpnNatMgr,
-                                     NotificationPublishService notiPublishService, NotificationService notiService,
-                                     NeutronFloatingToFixedIpMappingChangeListener neutronFloatingToFixedIpMappingChangeListener) {
+                                     NotificationPublishService notiPublishService, NotificationService notiService) {
         super(Port.class);
         broker = db;
         nvpnManager = nVpnMgr;
         nvpnNatManager = nVpnNatMgr;
         notificationPublishService = notiPublishService;
         notificationService = notiService;
-        floatingIpMapListener = neutronFloatingToFixedIpMappingChangeListener;
         registerListener(db);
     }
 
@@ -251,6 +248,7 @@ public class NeutronPortChangeListener extends AbstractDataChangeListener<Port>
 
     private void handleNeutronPortCreated(Port port) {
         if (!NeutronUtils.isPortVnicTypeNormal(port)) {
+            nvpnManager.updateSubnetmapNodeWithPorts(port.getFixedIps().get(0).getSubnetId(), null, port.getUuid());
             LOG.info("Port {} is not a NORMAL VNIC Type port; OF Port interfaces are not created",
                     port.getUuid().getValue());
             return;
@@ -276,8 +274,14 @@ public class NeutronPortChangeListener extends AbstractDataChangeListener<Port>
     }
 
     private void handleNeutronPortDeleted(Port port) {
+        if (!NeutronUtils.isPortVnicTypeNormal(port)) {
+            nvpnManager.removePortsFromSubnetmapNode(port.getFixedIps().get(0).getSubnetId(), null, port.getUuid());
+            LOG.info("Port {} is not a NORMAL VNIC Type port; OF Port interfaces are not created",
+                    port.getUuid().getValue());
+            return;
+        }
         //dissociate fixedIP from floatingIP if associated
-        floatingIpMapListener.dissociatefixedIPFromFloatingIP(port.getUuid().getValue());
+        nvpnManager.dissociatefixedIPFromFloatingIP(port.getUuid().getValue());
         LOG.debug("Remove port from subnet");
         // remove port from local Subnets DS
         Uuid vpnId = removePortFromSubnets(port);
@@ -620,7 +624,7 @@ public class NeutronPortChangeListener extends AbstractDataChangeListener<Port>
         LOG.debug("fixedIp-name map for neutron port with fixedIp: {}, name: {} added to NeutronPortData DS",
                 ipValue, infName);
         subnetId = ip.getSubnetId();
-        subnetmap = nvpnManager.updateSubnetNode(subnetId, null, null, null, null, null, port.getUuid());
+        subnetmap = nvpnManager.updateSubnetmapNodeWithPorts(subnetId, port.getUuid(), null);
         if (subnetmap != null) {
             vpnId = subnetmap.getVpnId();
         }
@@ -654,7 +658,7 @@ public class NeutronPortChangeListener extends AbstractDataChangeListener<Port>
         MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, id);
         LOG.debug("fixedIp-name map for neutron port with fixedIp: {} deleted from NeutronPortData DS", ipValue);
         subnetId = ip.getSubnetId();
-        subnetmap = nvpnManager.removeFromSubnetNode(subnetId, null, null, null, port.getUuid());
+        subnetmap = nvpnManager.removePortsFromSubnetmapNode(subnetId, port.getUuid(), null);
         if (subnetmap != null) {
             vpnId = subnetmap.getVpnId();
         }
index 3ecd00b84e42604f1db0b88fc29a15d8e74920f4..b4f91644f5c77dff2ba93c1decf8acb5e7d7444a 100644 (file)
@@ -124,7 +124,7 @@ public class NeutronSubnetChangeListener extends AbstractDataChangeListener<Subn
     }
 
     private void handleNeutronSubnetCreated(Uuid subnetId, String subnetIp, Uuid networkId, Uuid tenantId) {
-        nvpnManager.updateSubnetNode(subnetId, subnetIp, tenantId, networkId, null, null, null);
+        nvpnManager.updateSubnetNode(subnetId, subnetIp, tenantId, networkId, null, null);
         if (networkId != null) {
             createSubnetToNetworkMapping(subnetId, networkId);
         }
@@ -149,7 +149,7 @@ public class NeutronSubnetChangeListener extends AbstractDataChangeListener<Subn
         if (networkId != null && !networkId.equals(oldNetworkId)) {
             createSubnetToNetworkMapping(subnetId, networkId);
         }
-        nvpnManager.updateSubnetNode(subnetId, null, tenantId, networkId, null, null, null);
+        nvpnManager.updateSubnetNode(subnetId, null, tenantId, networkId, null, null);
     }
 
     private void createSubnetToNetworkMapping(Uuid subnetId, Uuid networkId) {
index 2b0d5b605dee76b91dd6218245a56d5bb44e927a..075d6843b7e0a9df8268178306cb4084b3fa801c 100644 (file)
@@ -124,6 +124,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
     IMdsalApiManager mdsalUtil;
     private NotificationPublishService notificationPublishService;
     private NotificationService notificationService;
+    private NeutronFloatingToFixedIpMappingChangeListener floatingIpMapListener;
     Boolean isExternalVpn;
 
     /**
@@ -131,12 +132,14 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
      * @param mdsalManager - MDSAL Util API access
      */
     public NeutronvpnManager(final DataBroker db, IMdsalApiManager mdsalManager,NotificationPublishService notiPublishService,
-                             NotificationService notiService, NeutronvpnNatManager vpnNatMgr) {
+                             NotificationService notiService, NeutronvpnNatManager vpnNatMgr,
+                             NeutronFloatingToFixedIpMappingChangeListener neutronFloatingToFixedIpMappingChangeListener) {
         broker = db;
         mdsalUtil = mdsalManager;
         nvpnNatManager = vpnNatMgr;
         notificationPublishService = notiPublishService;
         notificationService = notiService;
+        floatingIpMapListener = neutronFloatingToFixedIpMappingChangeListener;
     }
 
     public void setLockManager(LockManagerService lockManager) {
@@ -149,7 +152,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
     }
 
     protected Subnetmap updateSubnetNode(Uuid subnetId, String subnetIp, Uuid tenantId, Uuid networkId, Uuid routerId,
-                                         Uuid vpnId, Uuid portId) {
+                                         Uuid vpnId) {
         Subnetmap subnetmap = null;
         SubnetmapBuilder builder = null;
         boolean isLockAcquired = false;
@@ -182,15 +185,6 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 builder.setTenantId(tenantId);
             }
 
-            if (portId != null) {
-                List<Uuid> portList = builder.getPortList();
-                if (portList == null) {
-                    portList = new ArrayList<>();
-                }
-                portList.add(portId);
-                builder.setPortList(portList);
-            }
-
             subnetmap = builder.build();
             isLockAcquired = NeutronvpnUtils.lock(lockManager, subnetId.getValue());
             logger.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue());
@@ -246,6 +240,92 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         return subnetmap;
     }
 
+    protected Subnetmap updateSubnetmapNodeWithPorts(Uuid subnetId, Uuid portId, Uuid directPortId) {
+        Subnetmap subnetmap = null;
+        boolean isLockAcquired = false;
+        InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
+                new SubnetmapKey(subnetId)).build();
+        try {
+            Optional<Subnetmap> sn = NeutronvpnUtils.read(broker, LogicalDatastoreType.CONFIGURATION, id);
+            if (sn.isPresent()) {
+                SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
+                if (null != portId) {
+                    List<Uuid> portList = builder.getPortList();
+                    if (null == portList) {
+                        portList = new ArrayList<Uuid>();
+                    }
+                    portList.add(portId);
+                    builder.setPortList(portList);
+                    logger.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
+                            portId.getValue());
+                }
+                if (null != directPortId) {
+                    List<Uuid> directPortList = builder.getDirectPortList();
+                    if (null == directPortList) {
+                        directPortList = new ArrayList<Uuid>();
+                    }
+                    directPortList.add(directPortId);
+                    builder.setDirectPortList(directPortList);
+                    logger.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
+                            directPortId.getValue());
+                }
+                subnetmap = builder.build();
+                isLockAcquired = NeutronvpnUtils.lock(lockManager, subnetId.getValue());
+                MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
+            } else {
+                logger.error("Trying to update non-existing subnetmap node {} ", subnetId.getValue());
+            }
+        } catch (Exception e) {
+            logger.error("Updating port list of a given subnetMap failed for node: {} with exception{}",
+                    subnetId.getValue(), e);
+        } finally {
+            if (isLockAcquired) {
+                NeutronvpnUtils.unlock(lockManager, subnetId.getValue());
+            }
+        }
+        return subnetmap;
+    }
+
+    protected Subnetmap removePortsFromSubnetmapNode(Uuid subnetId, Uuid portId, Uuid directPortId) {
+        Subnetmap subnetmap = null;
+        boolean isLockAcquired = false;
+        InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
+                new SubnetmapKey(subnetId)).build();
+        try {
+            Optional<Subnetmap> sn = NeutronvpnUtils.read(broker, LogicalDatastoreType.CONFIGURATION, id);
+            if (sn.isPresent()) {
+                SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
+                if (null != portId && null != builder.getPortList()) {
+                    List<Uuid> portList = builder.getPortList();
+                    portList.remove(portId);
+                    builder.setPortList(portList);
+                    logger.debug("Removing port {} from existing subnetmap node: {} ", portId.getValue(),
+                            subnetId.getValue());
+                }
+                if (null != directPortId && null != builder.getDirectPortList()) {
+                    List<Uuid> directPortList = builder.getDirectPortList();
+                    directPortList.remove(directPortId);
+                    builder.setDirectPortList(directPortList);
+                    logger.debug("Removing direct port {} from existing subnetmap node: {} ", directPortId.getValue(),
+                            subnetId.getValue());
+                }
+                subnetmap = builder.build();
+                isLockAcquired = NeutronvpnUtils.lock(lockManager, subnetId.getValue());
+                MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
+            } else {
+                logger.error("Trying to remove port from non-existing subnetmap node {}", subnetId.getValue());
+            }
+        } catch (Exception e) {
+            logger.error("Removing a port from port list of a subnetmap failed for node: {} with expection {}",
+                    subnetId.getValue(), e);
+        } finally {
+            if (isLockAcquired) {
+                NeutronvpnUtils.unlock(lockManager, subnetId.getValue());
+            }
+        }
+        return subnetmap;
+    }
+
     protected void deleteSubnetMapNode(Uuid subnetId) {
         boolean isLockAcquired = false;
         InstanceIdentifier<Subnetmap> subnetMapIdentifier = InstanceIdentifier.builder(Subnetmaps.class)
@@ -884,7 +964,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
 
     protected void addSubnetToVpn(Uuid vpnId, Uuid subnet) {
         logger.debug("Adding subnet {} to vpn {}", subnet.getValue(), vpnId.getValue());
-        Subnetmap sn = updateSubnetNode(subnet, null, null, null, null, vpnId, null);
+        Subnetmap sn = updateSubnetNode(subnet, null, null, null, null, vpnId);
         boolean isLockAcquired = false;
         String lockName = vpnId.getValue() + subnet.getValue();
         String elanInstanceName = sn.getNetworkId().getValue();
@@ -926,7 +1006,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
 
     protected void updateVpnForSubnet(Uuid vpnId, Uuid subnet, boolean isBeingAssociated) {
         logger.debug("Updating VPN {} for subnet {}", vpnId.getValue(), subnet.getValue());
-        Subnetmap sn = updateSubnetNode(subnet, null, null, null, null, vpnId, null);
+        Subnetmap sn = updateSubnetNode(subnet, null, null, null, null, vpnId);
         boolean isLockAcquired = false;
         String lockName = vpnId.getValue() + subnet.getValue();
         String elanInstanceName = sn.getNetworkId().getValue();
@@ -1157,6 +1237,10 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         }
     }
 
+    protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
+        floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);
+    }
+
     protected void associateRouterToInternalVpn(Uuid vpnId, Uuid routerId) {
         List<Uuid> routerSubnets = NeutronvpnUtils.getNeutronRouterSubnetIds(broker, routerId);
         logger.debug("Adding subnets to internal vpn {}", vpnId.getValue());
index 4352175361514499670d6e1b51a4fd0dc65ad254..7dadb5fc66d5205483ae1c8bf65261d6433df822 100644 (file)
@@ -81,17 +81,17 @@ public class NeutronvpnProvider implements BindingAwareProvider, INeutronVpnMana
         try {
             final DataBroker dbx = session.getSALService(DataBroker.class);
             nvNatManager = new NeutronvpnNatManager(dbx, mdsalManager);
+            floatingIpMapListener = new NeutronFloatingToFixedIpMappingChangeListener(dbx);
             nvManager = new NeutronvpnManager(dbx, mdsalManager,notificationPublishService,notificationService,
-                    nvNatManager);
+                    nvNatManager, floatingIpMapListener);
             final BindingAwareBroker.RpcRegistration<NeutronvpnService> rpcRegistration =
                     getRpcProviderRegistry().addRpcImplementation(NeutronvpnService.class, nvManager);
             bgpvpnListener = new NeutronBgpvpnChangeListener(dbx, nvManager);
             networkListener = new NeutronNetworkChangeListener(dbx, nvManager, nvNatManager);
             subnetListener = new NeutronSubnetChangeListener(dbx, nvManager);
             routerListener = new NeutronRouterChangeListener(dbx, nvManager, nvNatManager);
-            floatingIpMapListener = new NeutronFloatingToFixedIpMappingChangeListener(dbx);
             portListener = new NeutronPortChangeListener(dbx, nvManager, nvNatManager,
-                    notificationPublishService,notificationService, floatingIpMapListener);
+                    notificationPublishService,notificationService);
             portListener.setLockManager(lockManager);
             portListener.setLockManager(lockManager);
             nvManager.setLockManager(lockManager);
diff --git a/vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/l2gw/AddL2GwDevicesToTransportZoneJob.java b/vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/l2gw/AddL2GwDevicesToTransportZoneJob.java
new file mode 100644 (file)
index 0000000..2767cbe
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.netvirt.neutronvpn.l2gw;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentMap;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.netvirt.neutronvpn.api.l2gw.L2GatewayDevice;
+import org.opendaylight.netvirt.neutronvpn.api.l2gw.utils.L2GatewayCacheUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZone;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The Class AddL2GwDevicesToTransportZoneJob.
+ */
+public class AddL2GwDevicesToTransportZoneJob implements Callable<List<ListenableFuture<Void>>> {
+
+    /** The Constant LOG. */
+    private static final Logger LOG = LoggerFactory.getLogger(AddL2GwDevicesToTransportZoneJob.class);
+
+    /** The data broker. */
+    private DataBroker dataBroker;
+
+    /** The itm rpc service. */
+    private ItmRpcService itmRpcService;
+
+    /** The transport zone. */
+    private TransportZone transportZone;
+
+    /**
+     * Instantiates a new adds the l2 gw devices to transport zone job.
+     *
+     * @param dataBroker the data broker
+     * @param itmRpcService the itm rpc service
+     * @param transportZone the transport zone
+     */
+    public AddL2GwDevicesToTransportZoneJob(DataBroker dataBroker, ItmRpcService itmRpcService,
+            TransportZone transportZone) {
+        this.dataBroker = dataBroker;
+        this.itmRpcService = itmRpcService;
+        this.transportZone = transportZone;
+        LOG.debug("created AddL2GwDevicesToTransportZone Job for tZone {}", transportZone.getZoneName());
+    }
+
+    /**
+     * Gets the job key.
+     *
+     * @return the job key
+     */
+    public String getJobKey() {
+        return "L2GW" + this.transportZone.getZoneName();
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.util.concurrent.Callable#call()
+     */
+    @Override
+    public List<ListenableFuture<Void>> call() throws Exception {
+        LOG.debug("Running AddL2GwDevicesToTransportZone job for {}", this.transportZone.getZoneName());
+        try {
+            // When vxlan transport zone is added, add all l2gw devices to that
+            // transport zone. Doesn't matter if tz already has data or not.
+            ConcurrentMap<String, L2GatewayDevice> l2GwDevices = L2GatewayCacheUtils.getCache();
+            for (L2GatewayDevice l2gwDevice : l2GwDevices.values()) {
+                if (!l2gwDevice.getL2GatewayIds().isEmpty()) {
+                    LOG.debug("Adding l2gw device [{}] to transport zone [{}]", l2gwDevice.getDeviceName(),
+                            this.transportZone.getZoneName());
+                    L2GatewayUtils.createItmTunnels(itmRpcService, l2gwDevice.getHwvtepNodeId(),
+                            l2gwDevice.getDeviceName(), l2gwDevice.getTunnelIp());
+                }
+            }
+        } catch (Exception e) {
+            LOG.error("Failed during AddL2GwDevicesToTransportZone job ", e);
+        }
+        return Collections.emptyList();
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "AddL2GwDevicesToTransportZoneJob [transportZone=" + transportZone.getZoneName() + "]";
+    }
+}
index 8c888df4efd5f94988ac4ef85b4a34cf0c9c34e7..9a6ffd899ce9d7ed571dcb79f27722fc038dcdea 100644 (file)
@@ -9,9 +9,11 @@
 package org.opendaylight.netvirt.neutronvpn.l2gw;
 
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
 import org.opendaylight.netvirt.neutronvpn.api.l2gw.utils.L2GatewayCacheUtils;
-import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -19,16 +21,23 @@ public class L2GatewayProvider {
     private static final Logger LOG = LoggerFactory.getLogger(L2GatewayProvider.class);
 
     private L2GatewayListener l2GatewayListener;
+    private L2GwTransportZoneListener l2GwTZoneListener;
 
     public L2GatewayProvider(DataBroker broker, RpcProviderRegistry rpcRegistry,
             EntityOwnershipService entityOwnershipService) {
+        ItmRpcService itmRpcService = rpcRegistry.getRpcService(ItmRpcService.class);
+
         L2GatewayCacheUtils.createL2DeviceCache();
         l2GatewayListener = new L2GatewayListener(broker, rpcRegistry, entityOwnershipService);
+        l2GwTZoneListener = new L2GwTransportZoneListener(broker, itmRpcService);
+        l2GwTZoneListener.registerListener(LogicalDatastoreType.CONFIGURATION, broker);
+
         LOG.info("L2GatewayProvider Initialized");
     }
 
     public void close() throws Exception {
         l2GatewayListener.close();
+        l2GwTZoneListener.close();
         LOG.info("L2GatewayProvider Closed");
     }
 }
diff --git a/vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/l2gw/L2GwTransportZoneListener.java b/vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/l2gw/L2GwTransportZoneListener.java
new file mode 100644 (file)
index 0000000..7f51306
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.netvirt.neutronvpn.l2gw;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
+import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.TransportZones;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZone;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The listener class for ITM transport zone updates.
+ */
+public class L2GwTransportZoneListener extends AsyncDataTreeChangeListenerBase<TransportZone, L2GwTransportZoneListener>
+        implements AutoCloseable {
+
+    /** The Constant LOG. */
+    private static final Logger LOG = LoggerFactory.getLogger(L2GwTransportZoneListener.class);
+
+    /** The data broker. */
+    private DataBroker dataBroker;
+
+    /** The itm rpc service. */
+    private ItmRpcService itmRpcService;
+
+    /**
+     * Instantiates a new l2 gw transport zone listener.
+     *
+     * @param dataBroker the data broker
+     * @param itmRpcService the itm rpc service
+     */
+    public L2GwTransportZoneListener(DataBroker dataBroker, ItmRpcService itmRpcService) {
+        super(TransportZone.class, L2GwTransportZoneListener.class);
+
+        this.dataBroker = dataBroker;
+        this.itmRpcService = itmRpcService;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.opendaylight.vpnservice.datastoreutils.
+     * AsyncDataTreeChangeListenerBase#getWildCardPath()
+     */
+    @Override
+    protected InstanceIdentifier<TransportZone> getWildCardPath() {
+        return InstanceIdentifier.create(TransportZones.class).child(TransportZone.class);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.opendaylight.vpnservice.datastoreutils.
+     * AsyncDataTreeChangeListenerBase#remove(org.opendaylight.yangtools.yang.
+     * binding.InstanceIdentifier,
+     * org.opendaylight.yangtools.yang.binding.DataObject)
+     */
+    @Override
+    protected void remove(InstanceIdentifier<TransportZone> key, TransportZone dataObjectModification) {
+        // do nothing
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.opendaylight.vpnservice.datastoreutils.
+     * AsyncDataTreeChangeListenerBase#update(org.opendaylight.yangtools.yang.
+     * binding.InstanceIdentifier,
+     * org.opendaylight.yangtools.yang.binding.DataObject,
+     * org.opendaylight.yangtools.yang.binding.DataObject)
+     */
+    @Override
+    protected void update(InstanceIdentifier<TransportZone> key, TransportZone dataObjectModificationBefore,
+            TransportZone dataObjectModificationAfter) {
+        // do nothing
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.opendaylight.vpnservice.datastoreutils.
+     * AsyncDataTreeChangeListenerBase#add(org.opendaylight.yangtools.yang.
+     * binding.InstanceIdentifier,
+     * org.opendaylight.yangtools.yang.binding.DataObject)
+     */
+    @Override
+    protected void add(InstanceIdentifier<TransportZone> key, TransportZone tzNew) {
+        if (LOG.isTraceEnabled()) {
+            LOG.trace("Received Transport Zone Add Event: {}", tzNew);
+        }
+        if (tzNew.getTunnelType().equals(TunnelTypeVxlan.class)) {
+            DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+            AddL2GwDevicesToTransportZoneJob job =
+                    new AddL2GwDevicesToTransportZoneJob(dataBroker, itmRpcService, tzNew);
+            coordinator.enqueueJob(job.getJobKey(), job);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.opendaylight.vpnservice.datastoreutils.
+     * AsyncDataTreeChangeListenerBase#getDataTreeChangeListener()
+     */
+    @Override
+    protected L2GwTransportZoneListener getDataTreeChangeListener() {
+        return L2GwTransportZoneListener.this;
+    }
+}
index 306f2fe12bf2c36d5f5f713389528ea7cbe1a5e7..8ce5155e929dfbb6c451c7f01f43739ae3e32426 100644 (file)
@@ -76,7 +76,7 @@ public class NeutronPortChangeListenerTest {
             thenReturn(Futures.immediateCheckedFuture(Optional.of(mockNetwork)));
 
         neutronPortChangeListener = new NeutronPortChangeListener(dataBroker, nVpnMgr, nVpnNatMgr,
-                notiPublishService, notiService, floatingIpMapListener);
+                notiPublishService, notiService);
     }
 
     @Test