yang change to make remove deprecated leaf-elements
[netvirt.git] / vpnservice / neutronvpn / neutronvpn-impl / src / main / java / org / opendaylight / netvirt / neutronvpn / NeutronvpnManager.java
index a7fb5d95051105a22f6cd378b256a1c5fb23348e..b5ac341b7d93fb5c4592745b33b42cced847bf39 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+ * Copyright © 2015, 2017 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,
@@ -7,25 +7,27 @@
  */
 package org.opendaylight.netvirt.neutronvpn;
 
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.EventListener;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.Callable;
+import java.util.Objects;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
-
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
-import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
 import org.opendaylight.netvirt.elanmanager.api.IElanService;
 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
@@ -44,14 +46,12 @@ import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev14081
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.config.rev160806.NeutronvpnConfig;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutput;
@@ -74,22 +74,17 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev15060
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.L3vpnInstance;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterAssociatedToVpn;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterAssociatedToVpnBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterDisassociatedFromVpn;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterDisassociatedFromVpnBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterInterfacesMap;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.SubnetAddedToVpnBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.SubnetDeletedFromVpnBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.SubnetUpdatedInVpnBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.createl3vpn.input.L3vpn;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstances;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstancesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfaces;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesKey;
@@ -114,6 +109,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension;
 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.Subnet;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
@@ -125,10 +121,6 @@ import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.SettableFuture;
-
 public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, EventListener {
     private static final Logger LOG = LoggerFactory.getLogger(NeutronvpnManager.class);
     private final DataBroker dataBroker;
@@ -136,35 +128,20 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
     private final NotificationPublishService notificationPublishService;
     private final VpnRpcService vpnRpcService;
     private final NeutronFloatingToFixedIpMappingChangeListener floatingIpMapListener;
-    private final NeutronvpnConfig neutronvpnConfig;
-    private final IMdsalApiManager mdsalUtil;
     private final IElanService elanService;
-    Boolean isExternalVpn;
+    private final NeutronvpnConfig neutronvpnConfig;
 
-    /**
-     * @param dataBroker DataBroker reference
-     * @param mdsalManager MDSAL Util API access
-     * @param notiPublishService notificationPublishService
-     * @param vpnNatMgr VPN NAT manager service
-     * @param vpnRpcSrv VPN RPC service
-     * @param elanService ELAN service
-     * @param neutronFloatingToFixedIpMappingChangeListener FIP to FixedIP listener
-     * @param neutronvpnConfig Neutronvpn configuration service
-     */
     public NeutronvpnManager(
-            final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
-            final NotificationPublishService notiPublishService, final NeutronvpnNatManager vpnNatMgr,
-            final VpnRpcService vpnRpcSrv, final IElanService elanService,
+            final DataBroker dataBroker, final NotificationPublishService notiPublishService,
+            final NeutronvpnNatManager vpnNatMgr, final VpnRpcService vpnRpcSrv, final IElanService elanService,
             final NeutronFloatingToFixedIpMappingChangeListener neutronFloatingToFixedIpMappingChangeListener,
             final NeutronvpnConfig neutronvpnConfig) {
         this.dataBroker = dataBroker;
-        mdsalUtil = mdsalManager;
         nvpnNatManager = vpnNatMgr;
         notificationPublishService = notiPublishService;
         vpnRpcService = vpnRpcSrv;
         this.elanService = elanService;
         floatingIpMapListener = neutronFloatingToFixedIpMappingChangeListener;
-        LOG.info("neutronvpnConfig: {}", neutronvpnConfig);
         this.neutronvpnConfig = neutronvpnConfig;
     }
 
@@ -177,59 +154,34 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         return neutronvpnConfig;
     }
 
-    protected void updateSubnetNodeWithFixedIps(Uuid subnetId, Uuid routerId,
-                                                Uuid routerInterfaceName, String fixedIp,
-                                                String routerIntfMacAddress) {
-        Subnetmap subnetmap = null;
-        SubnetmapBuilder builder = null;
-        InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).
-                child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
+    // TODO Clean up the exception handling
+    @SuppressWarnings("checkstyle:IllegalCatch")
+    protected void createSubnetmapNode(Uuid subnetId, String subnetIp, Uuid tenantId, Uuid networkId) {
         try {
+            InstanceIdentifier<Subnetmap> subnetMapIdentifier = NeutronvpnUtils.buildSubnetMapIdentifier(subnetId);
             synchronized (subnetId.getValue().intern()) {
-                Optional<Subnetmap> sn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
+                Optional<Subnetmap> sn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                        subnetMapIdentifier);
+                SubnetmapBuilder subnetmapBuilder = null;
                 if (sn.isPresent()) {
-                    builder = new SubnetmapBuilder(sn.get());
-                    LOG.debug("WithRouterFixedIPs: Updating existing subnetmap node for subnet ID {}", subnetId.getValue());
-                } else {
-                    builder = new SubnetmapBuilder().setKey(new SubnetmapKey(subnetId)).setId(subnetId);
-                    LOG.debug("WithRouterFixedIPs: creating new subnetmap node for subnet ID {}", subnetId.getValue());
-                }
-                if (routerId != null) {
-                    builder.setRouterId(routerId);
-                } else {
-                    builder.setRouterId(null);
-                }
-                if (routerInterfaceName != null) {
-                    builder.setRouterInterfaceName(routerInterfaceName);
-                } else {
-                    builder.setRouterInterfaceName(null);
-                }
-                if (routerIntfMacAddress != null) {
-                    builder.setRouterIntfMacAddress(routerIntfMacAddress);
-                } else {
-                    builder.setRouterIntfMacAddress(null);
-                }
-                if (fixedIp != null) {
-                    List<String> fixedIps = builder.getRouterInterfaceFixedIps();
-                    if (fixedIps == null) {
-                        fixedIps = new ArrayList<>();
-                    }
-                    fixedIps.add(fixedIp);
-                    builder.setRouterInterfaceFixedIps(fixedIps);
+                    LOG.error("subnetmap node for subnet ID {} already exists, returning", subnetId.getValue());
+                    return;
                 } else {
-                    builder.setRouterInterfaceFixedIps(null);
+                    subnetmapBuilder = new SubnetmapBuilder().setKey(new SubnetmapKey(subnetId)).setId(subnetId)
+                            .setSubnetIp(subnetIp).setTenantId(tenantId).setNetworkId(networkId);
+                    LOG.debug("Adding a new subnet node in Subnetmaps DS for subnet {}", subnetId.getValue());
                 }
-                subnetmap = builder.build();
-                LOG.debug("WithRouterFixedIPs Creating/Updating subnetMap node for Router FixedIps: {} ", subnetId.getValue());
-                MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
+                SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                        subnetMapIdentifier, subnetmapBuilder.build());
             }
         } catch (Exception e) {
-            LOG.error("WithRouterFixedIPs: Updation of subnetMap for Router FixedIps failed for node: {}", subnetId.getValue());
+            LOG.error("Creating subnetmap node failed for subnet {}", subnetId.getValue());
         }
     }
 
-    protected Subnetmap updateSubnetNode(Uuid subnetId, String subnetIp, Uuid tenantId, Uuid networkId, Uuid routerId,
-                                         Uuid vpnId) {
+    // TODO Clean up the exception handling
+    @SuppressWarnings("checkstyle:IllegalCatch")
+    private Subnetmap updateSubnetNode(Uuid subnetId, Uuid routerId, Uuid vpnId) {
         Subnetmap subnetmap = null;
         SubnetmapBuilder builder = null;
         InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
@@ -242,29 +194,19 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                     builder = new SubnetmapBuilder(sn.get());
                     LOG.debug("updating existing subnetmap node for subnet ID {}", subnetId.getValue());
                 } else {
-                    builder = new SubnetmapBuilder().setKey(new SubnetmapKey(subnetId)).setId(subnetId);
-                    LOG.debug("creating new subnetmap node for subnet ID {}", subnetId.getValue());
-                }
-
-                if (subnetIp != null) {
-                    builder.setSubnetIp(subnetIp);
+                    LOG.error("subnetmap node for subnet {} does not exist, returning", subnetId.getValue());
+                    return null;
                 }
                 if (routerId != null) {
                     builder.setRouterId(routerId);
                 }
-                if (networkId != null) {
-                    builder.setNetworkId(networkId);
-                }
                 if (vpnId != null) {
                     builder.setVpnId(vpnId);
                 }
-                if (tenantId != null) {
-                    builder.setTenantId(tenantId);
-                }
 
                 subnetmap = builder.build();
                 LOG.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue());
-                MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
+                SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
             }
         } catch (Exception e) {
             LOG.error("Updation of subnetMap failed for node: {}", subnetId.getValue());
@@ -272,44 +214,53 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         return subnetmap;
     }
 
-    protected Subnetmap removeFromSubnetNode(Uuid subnetId, Uuid networkId, Uuid routerId, Uuid vpnId, Uuid portId) {
+    // TODO Clean up the exception handling
+    @SuppressWarnings("checkstyle:IllegalCatch")
+    protected void updateSubnetNodeWithFixedIps(Uuid subnetId, Uuid routerId,
+                                                Uuid routerInterfaceName, String fixedIp,
+                                                String routerIntfMacAddress) {
         Subnetmap subnetmap = null;
-        InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
-                .child(Subnetmap.class, new SubnetmapKey(subnetId))
-                .build();
+        SubnetmapBuilder builder = null;
+        InstanceIdentifier<Subnetmap> id =
+            InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
         try {
             synchronized (subnetId.getValue().intern()) {
                 Optional<Subnetmap> sn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
                 if (sn.isPresent()) {
-                    SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
-                    if (routerId != null) {
-                        builder.setRouterId(null);
-                    }
-                    if (networkId != null) {
-                        builder.setNetworkId(null);
-                    }
-                    if (vpnId != null) {
-                        builder.setVpnId(null);
-                    }
-                    if (portId != null && builder.getPortList() != null) {
-                        List<Uuid> portList = builder.getPortList();
-                        portList.remove(portId);
-                        builder.setPortList(portList);
+                    builder = new SubnetmapBuilder(sn.get());
+                    LOG.debug("WithRouterFixedIPs: Updating existing subnetmap node for subnet ID {}",
+                        subnetId.getValue());
+                } else {
+                    builder = new SubnetmapBuilder().setKey(new SubnetmapKey(subnetId)).setId(subnetId);
+                    LOG.debug("WithRouterFixedIPs: creating new subnetmap node for subnet ID {}",
+                        subnetId.getValue());
+                }
+                builder.setRouterId(routerId);
+                builder.setRouterInterfaceName(routerInterfaceName);
+                builder.setRouterIntfMacAddress(routerIntfMacAddress);
+                if (fixedIp != null) {
+                    List<String> fixedIps = builder.getRouterInterfaceFixedIps();
+                    if (fixedIps == null) {
+                        fixedIps = new ArrayList<>();
                     }
-
-                    subnetmap = builder.build();
-                    LOG.debug("Removing from existing subnetmap node: {} ", subnetId.getValue());
-                    MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
+                    fixedIps.add(fixedIp);
+                    builder.setRouterInterfaceFixedIps(fixedIps);
                 } else {
-                    LOG.warn("removing from non-existing subnetmap node: {} ", subnetId.getValue());
+                    builder.setRouterInterfaceFixedIps(null);
                 }
+                subnetmap = builder.build();
+                LOG.debug("WithRouterFixedIPs Creating/Updating subnetMap node for Router FixedIps: {} ",
+                    subnetId.getValue());
+                SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
             }
         } catch (Exception e) {
-            LOG.error("Removal from subnetmap failed for node: {}", subnetId.getValue());
+            LOG.error("WithRouterFixedIPs: Updation of subnetMap for Router FixedIps failed for node: {}",
+                subnetId.getValue());
         }
-        return subnetmap;
     }
 
+    // TODO Clean up the exception handling
+    @SuppressWarnings("checkstyle:IllegalCatch")
     protected Subnetmap updateSubnetmapNodeWithPorts(Uuid subnetId, Uuid portId, Uuid directPortId) {
         Subnetmap subnetmap = null;
         InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
@@ -322,7 +273,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                     if (null != portId) {
                         List<Uuid> portList = builder.getPortList();
                         if (null == portList) {
-                            portList = new ArrayList<Uuid>();
+                            portList = new ArrayList<>();
                         }
                         portList.add(portId);
                         builder.setPortList(portList);
@@ -332,7 +283,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                     if (null != directPortId) {
                         List<Uuid> directPortList = builder.getDirectPortList();
                         if (null == directPortList) {
-                            directPortList = new ArrayList<Uuid>();
+                            directPortList = new ArrayList<>();
                         }
                         directPortList.add(directPortId);
                         builder.setDirectPortList(directPortList);
@@ -340,7 +291,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                                 directPortId.getValue());
                     }
                     subnetmap = builder.build();
-                    MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
+                    SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
+                            subnetmap);
                 } else {
                     LOG.error("Trying to update non-existing subnetmap node {} ", subnetId.getValue());
                 }
@@ -352,6 +304,49 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         return subnetmap;
     }
 
+    // TODO Clean up the exception handling
+    @SuppressWarnings("checkstyle:IllegalCatch")
+    protected Subnetmap removeFromSubnetNode(Uuid subnetId, Uuid networkId, Uuid routerId, Uuid vpnId, Uuid portId) {
+        Subnetmap subnetmap = null;
+        InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
+                .child(Subnetmap.class, new SubnetmapKey(subnetId))
+                .build();
+        try {
+            synchronized (subnetId.getValue().intern()) {
+                Optional<Subnetmap> sn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
+                if (sn.isPresent()) {
+                    SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
+                    if (routerId != null) {
+                        builder.setRouterId(null);
+                    }
+                    if (networkId != null) {
+                        builder.setNetworkId(null);
+                    }
+                    if (vpnId != null) {
+                        builder.setVpnId(null);
+                    }
+                    if (portId != null && builder.getPortList() != null) {
+                        List<Uuid> portList = builder.getPortList();
+                        portList.remove(portId);
+                        builder.setPortList(portList);
+                    }
+
+                    subnetmap = builder.build();
+                    LOG.debug("Removing from existing subnetmap node: {} ", subnetId.getValue());
+                    SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
+                            subnetmap);
+                } else {
+                    LOG.warn("removing from non-existing subnetmap node: {} ", subnetId.getValue());
+                }
+            }
+        } catch (Exception e) {
+            LOG.error("Removal from subnetmap failed for node: {}", subnetId.getValue());
+        }
+        return subnetmap;
+    }
+
+    // TODO Clean up the exception handling
+    @SuppressWarnings("checkstyle:IllegalCatch")
     protected Subnetmap removePortsFromSubnetmapNode(Uuid subnetId, Uuid portId, Uuid directPortId) {
         Subnetmap subnetmap = null;
         InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
@@ -376,7 +371,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                                 .getValue(), subnetId.getValue());
                     }
                     subnetmap = builder.build();
-                    MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
+                    SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
+                            subnetmap);
                 } else {
                     LOG.error("Trying to remove port from non-existing subnetmap node {}", subnetId.getValue());
                 }
@@ -388,26 +384,31 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         return subnetmap;
     }
 
+    // TODO Clean up the exception handling
+    @SuppressWarnings("checkstyle:IllegalCatch")
     protected void deleteSubnetMapNode(Uuid subnetId) {
         InstanceIdentifier<Subnetmap> subnetMapIdentifier =
                 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,new SubnetmapKey(subnetId)).build();
         LOG.debug("removing subnetMap node: {} ", subnetId.getValue());
         try {
             synchronized (subnetId.getValue().intern()) {
-                MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
+                SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                        subnetMapIdentifier);
             }
         } catch (Exception e) {
             LOG.error("Delete subnetMap node failed for subnet : {} ", subnetId.getValue());
         }
     }
 
-    private void updateVpnInstanceNode(String vpnName, List<String> rd, List<String> irt, List<String> ert) {
-
+    // TODO Clean up the exception handling
+    @SuppressWarnings("checkstyle:IllegalCatch")
+    private void updateVpnInstanceNode(String vpnName, List<String> rd, List<String> irt, List<String> ert,
+                                       VpnInstance.Type type, long l3vni) {
         VpnInstanceBuilder builder = null;
         List<VpnTarget> vpnTargetList = new ArrayList<>();
         boolean isLockAcquired = false;
-        InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class).child
-                (VpnInstance.class, new VpnInstanceKey(vpnName)).build();
+        InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
+            .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
         try {
             Optional<VpnInstance> optionalVpn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
                     vpnIdentifier);
@@ -416,7 +417,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 builder = new VpnInstanceBuilder(optionalVpn.get());
                 LOG.debug("updating existing vpninstance node");
             } else {
-                builder = new VpnInstanceBuilder().setKey(new VpnInstanceKey(vpnName)).setVpnInstanceName(vpnName);
+                builder = new VpnInstanceBuilder().setKey(new VpnInstanceKey(vpnName)).setVpnInstanceName(vpnName)
+                        .setType(type).setL3vni(l3vni);
             }
             if (irt != null && !irt.isEmpty()) {
                 if (ert != null && !ert.isEmpty()) {
@@ -454,7 +456,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             Ipv4FamilyBuilder ipv4vpnBuilder = new Ipv4FamilyBuilder().setVpnTargets(vpnTargets);
 
             if (rd != null && !rd.isEmpty()) {
-                ipv4vpnBuilder.setRouteDistinguisher(rd.get(0));
+                ipv4vpnBuilder.setRouteDistinguisher(rd);
             }
 
             VpnInstance newVpn = builder.setIpv4Family(ipv4vpnBuilder.build()).build();
@@ -470,6 +472,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         }
     }
 
+    // TODO Clean up the exception handling
+    @SuppressWarnings("checkstyle:IllegalCatch")
     private void deleteVpnMapsNode(Uuid vpnid) {
         boolean isLockAcquired = false;
         InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
@@ -488,6 +492,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         }
     }
 
+    // TODO Clean up the exception handling
+    @SuppressWarnings("checkstyle:IllegalCatch")
     private void updateVpnMaps(Uuid vpnId, String name, Uuid router, Uuid tenantId, List<Uuid> networks) {
         VpnMapBuilder builder;
         boolean isLockAcquired = false;
@@ -534,6 +540,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         }
     }
 
+    // TODO Clean up the exception handling
+    @SuppressWarnings("checkstyle:IllegalCatch")
     private void clearFromVpnMaps(Uuid vpnId, Uuid routerId, List<Uuid> networkIds) {
         boolean isLockAcquired = false;
         InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
@@ -593,6 +601,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         LOG.debug("Clear from VPNMaps DS successful for VPN {} ", vpnId.getValue());
     }
 
+    // TODO Clean up the exception handling
+    @SuppressWarnings("checkstyle:IllegalCatch")
     private void deleteVpnInstance(Uuid vpnId) {
         boolean isLockAcquired = false;
         InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
@@ -616,7 +626,6 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                                       WriteTransaction wrtConfigTxn) {
         String infName = port.getUuid().getValue();
         List<Adjacency> adjList = new ArrayList<>();
-        List<FixedIps> ips = port.getFixedIps();
         Boolean isRouterInterface = false;
         if (port.getDeviceOwner() != null) {
             isRouterInterface = port.getDeviceOwner().equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF);
@@ -626,24 +635,26 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         if (routerId != null) {
             rtr = NeutronvpnUtils.getNeutronRouter(dataBroker, routerId);
         }
+        List<FixedIps> ips = port.getFixedIps();
         // create adjacency list
         for (FixedIps ip : ips) {
             // create vm adjacency
             String ipValue = String.valueOf(ip.getIpAddress().getValue());
             String ipPrefix = (ip.getIpAddress().getIpv4Address() != null) ? ipValue + "/32" : ipValue + "/128";
             Adjacency vmAdj = new AdjacencyBuilder().setKey(new AdjacencyKey(ipPrefix)).setIpAddress(ipPrefix)
-                    .setMacAddress(port.getMacAddress().getValue()).setPrimaryAdjacency(true).build();
+                    .setMacAddress(port.getMacAddress().getValue()).setPrimaryAdjacency(true)
+                    .setSubnetId(ip.getSubnetId()).build();
             adjList.add(vmAdj);
             // create extra route adjacency
             if (rtr != null && rtr.getRoutes() != null) {
                 List<Routes> routeList = rtr.getRoutes();
-                List<Adjacency> erAdjList = addAdjacencyforExtraRoute(vpnId, routeList);
+                List<Adjacency> erAdjList = getAdjacencyforExtraRoute(vpnId, routeList, ipValue);
                 if (erAdjList != null && !erAdjList.isEmpty()) {
                     adjList.addAll(erAdjList);
                 }
             }
             NeutronvpnUtils.createVpnPortFixedIpToPort(dataBroker, vpnId.getValue(), ipValue, infName, port
-                            .getMacAddress().getValue(), isRouterInterface, true, false);
+                            .getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
         }
         // create vpn-interface on this neutron port
         Adjacencies adjs = new AdjacenciesBuilder().setAdjacency(adjList).build();
@@ -653,6 +664,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         }
     }
 
+    // TODO Clean up the exception handling
+    @SuppressWarnings("checkstyle:IllegalCatch")
     protected void deleteVpnInterface(Uuid vpnId, Uuid routerId, Port port, WriteTransaction wrtConfigTxn) {
         Boolean wrtConfigTxnPresent = true;
         if (wrtConfigTxn == null) {
@@ -668,7 +681,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             List<FixedIps> ips = port.getFixedIps();
             for (FixedIps ip : ips) {
                 String ipValue = String.valueOf(ip.getIpAddress().getValue());
-                NeutronvpnUtils.removeVpnPortFixedIpToPort(dataBroker, vpnId.getValue(), ipValue);
+                NeutronvpnUtils.removeVpnPortFixedIpToPort(dataBroker, vpnId.getValue(),
+                        ipValue, wrtConfigTxn);
             }
         } catch (Exception ex) {
             LOG.error("Deletion of vpninterface {} failed due to {}", infName, ex);
@@ -681,14 +695,19 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         }
     }
 
-    protected void updateVpnInterface(Uuid vpnId, Uuid oldVpnId, Port port, boolean  isBeingAssociated) {
+    // TODO Clean up the exception handling
+    @SuppressWarnings("checkstyle:IllegalCatch")
+    protected void updateVpnInterface(Uuid vpnId, Uuid oldVpnId, Port port, boolean isBeingAssociated,
+                                      boolean isSubnetIp) {
         if (vpnId == null || port == null) {
             return;
         }
         boolean isLockAcquired = false;
         String infName = port.getUuid().getValue();
         InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
+
         try {
+            WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
             isLockAcquired = NeutronvpnUtils.lock(infName);
             Optional<VpnInterface> optionalVpnInterface = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
                     .CONFIGURATION, vpnIfIdentifier);
@@ -697,40 +716,41 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                         .setVpnInstanceName(vpnId.getValue());
                 LOG.debug("Updating vpn interface {}", infName);
                 if (!isBeingAssociated) {
-                    List<Adjacency> adjacencyList = vpnIfBuilder.getAugmentation(Adjacencies.class).getAdjacency();
+                    Adjacencies adjs = vpnIfBuilder.getAugmentation(Adjacencies.class);
+                    List<Adjacency> adjacencyList = (adjs != null) ? adjs.getAdjacency() : new ArrayList<>();
                     Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
                     while (adjacencyIter.hasNext()) {
                         Adjacency adjacency = adjacencyIter.next();
                         String mipToQuery = adjacency.getIpAddress().split("/")[0];
-                        InstanceIdentifier<VpnPortipToPort> id = NeutronvpnUtils.buildVpnPortipToPortIdentifier
-                                (oldVpnId.getValue(), mipToQuery);
-                        Optional<VpnPortipToPort> optionalVpnPort = NeutronvpnUtils.read(dataBroker,
-                                LogicalDatastoreType
-                                .OPERATIONAL, id);
-                        if (!optionalVpnPort.isPresent() || optionalVpnPort.get().isLearnt()) {
-                            LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {} " +
-                                    "from VPN " + "{}", infName, vpnId, oldVpnId);
+                        InstanceIdentifier<LearntVpnVipToPort> id =
+                            NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
+                        Optional<LearntVpnVipToPort> optionalVpnVipToPort =
+                            NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
+                        if (optionalVpnVipToPort.isPresent()) {
+                            LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {} "
+                                + "from VPN " + "{}", infName, vpnId, oldVpnId);
                             adjacencyIter.remove();
-                            NeutronvpnUtils.removeVpnPortFixedIpToPort(dataBroker, oldVpnId.getValue(), mipToQuery);
-                            LOG.trace("Entry for fixedIP {} for port {} on VPN removed from " +
-                                    "VpnPortFixedIPToPortData", mipToQuery, infName, vpnId.getValue());
+                            NeutronvpnUtils.removeLearntVpnVipToPort(dataBroker, oldVpnId.getValue(), mipToQuery);
+                            LOG.trace("Entry for fixedIP {} for port {} on VPN removed from "
+                                + "VpnPortFixedIPToPortData", mipToQuery, infName, vpnId.getValue());
                         }
                     }
                     Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(adjacencyList).build();
                     vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
                 }
-                MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIfBuilder
-                        .build());
-
                 List<FixedIps> ips = port.getFixedIps();
                 for (FixedIps ip : ips) {
                     String ipValue = String.valueOf(ip.getIpAddress().getValue());
                     if (oldVpnId != null) {
-                        NeutronvpnUtils.removeVpnPortFixedIpToPort(dataBroker, oldVpnId.getValue(), ipValue);
+                        NeutronvpnUtils.removeVpnPortFixedIpToPort(dataBroker, oldVpnId.getValue(),
+                                ipValue, writeConfigTxn);
                     }
                     NeutronvpnUtils.createVpnPortFixedIpToPort(dataBroker, vpnId.getValue(), ipValue, infName, port
-                            .getMacAddress().getValue(), false, true, false);
+                            .getMacAddress().getValue(), isSubnetIp, writeConfigTxn);
                 }
+                writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIfBuilder
+                        .build());
+                writeConfigTxn.submit();
             } else {
                 LOG.error("VPN Interface {} not found", infName);
             }
@@ -747,7 +767,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                                     List<String> ert, Uuid router, List<Uuid> networks) {
 
         // Update VPN Instance node
-        updateVpnInstanceNode(vpn.getValue(), rd, irt, ert);
+        updateVpnInstanceNode(vpn.getValue(), rd, irt, ert, VpnInstance.Type.L3, 0 /*l3vni*/);
 
         // Update local vpn-subnet DS
         updateVpnMaps(vpn, name, router, tenant, networks);
@@ -762,8 +782,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 // preserved upon reboot.
                 // For a non-reboot case #associateRouterToInternalVPN already takes care of adding to
                 // RouterInterfacesMap via #createVPNInterface call.
-                LOG.info("Associating router to Internal VPN skipped for VPN {} due to router {} already associated " +
-                        "to external VPN {}", vpn.getValue(), router.getValue(), existingVpn.getValue());
+                LOG.info("Associating router to Internal VPN skipped for VPN {} due to router {} already associated "
+                    + "to external VPN {}", vpn.getValue(), router.getValue(), existingVpn.getValue());
                 return;
             }
             associateRouterToInternalVpn(vpn, router);
@@ -772,7 +792,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
 
     /**
      * Performs the creation of a Neutron L3VPN, associating the new VPN to the
-     * specified Neutron Networks and Routers
+     * specified Neutron Networks and Routers.
      *
      * @param vpn Uuid of the VPN tp be created
      * @param name Representative name of the new VPN
@@ -782,13 +802,15 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
      * @param ert A list of Export Route Targets
      * @param router UUID of the neutron router the VPN may be associated to
      * @param networks UUID of the neutron network the VPN may be associated to
+     * @param type Type of the VPN Instance
+     * @param l3vni L3VNI for the VPN Instance using VxLAN as the underlay
      * @throws Exception if association of L3VPN failed
      */
-    public void createL3Vpn(Uuid vpn, String name, Uuid tenant, List<String> rd, List<String> irt, List<String> ert,
-                            Uuid router, List<Uuid> networks) throws Exception {
+    public void createVpn(Uuid vpn, String name, Uuid tenant, List<String> rd, List<String> irt, List<String> ert,
+                            Uuid router, List<Uuid> networks, VpnInstance.Type type, long l3vni) throws Exception {
 
         // Update VPN Instance node
-        updateVpnInstanceNode(vpn.getValue(), rd, irt, ert);
+        updateVpnInstanceNode(vpn.getValue(), rd, irt, ert, type, l3vni);
 
         // Please note that router and networks will be filled into VPNMaps
         // by subsequent calls here to associateRouterToVpn and
@@ -801,7 +823,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         if (networks != null) {
             List<String> failStrings = associateNetworksToVpn(vpn, networks);
             if (failStrings != null &&  !failStrings.isEmpty()) {
-                LOG.error("L3VPN {} association to networks failed with error message {}. ",
+                LOG.error("VPN {} association to networks failed with error message {}. ",
                         vpn.getValue(), failStrings.get(0));
                 throw new Exception(failStrings.get(0));
             }
@@ -809,12 +831,11 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
     }
 
     /**
-     * It handles the invocations to the createL3VPN RPC method
-     *
-     * @see org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService#createL3VPN
-     * (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNInput)
+     * It handles the invocations to the createVPN RPC method.
      */
     @Override
+    // TODO Clean up the exception handling
+    @SuppressWarnings("checkstyle:IllegalCatch")
     public Future<RpcResult<CreateL3VPNOutput>> createL3VPN(CreateL3VPNInput input) {
 
         CreateL3VPNOutputBuilder opBuilder = new CreateL3VPNOutputBuilder();
@@ -827,6 +848,15 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         for (L3vpn vpn : vpns) {
             RpcError error = null;
             String msg;
+            if (NeutronvpnUtils.doesVpnExist(dataBroker, vpn.getId())) {
+                msg = String.format("Creation of L3VPN failed for VPN %s due to VPN with the same ID already present",
+                                vpn.getId().getValue());
+                LOG.warn(msg);
+                error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
+                errorList.add(error);
+                warningcount++;
+                continue;
+            }
             if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
                 msg = String.format("Creation of L3VPN failed for VPN %s due to absence of RD/iRT/eRT input",
                         vpn.getId().getValue());
@@ -836,8 +866,14 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 warningcount++;
                 continue;
             }
+            VpnInstance.Type vpnInstanceType = VpnInstance.Type.L3;
+            long l3vni = 0;
+            if (vpn.getL3vni() != null) {
+                l3vni = vpn.getL3vni();
+            }
+
             if (vpn.getRouteDistinguisher().size() > 1) {
-                msg = String.format("Creation of L3VPN failed for VPN %s due to multiple RD input %s",
+                msg = String.format("Creation of VPN failed for VPN %s due to multiple RD input %s",
                         vpn.getId().getValue(), vpn.getRouteDistinguisher());
                 LOG.warn(msg);
                 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
@@ -845,6 +881,17 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 warningcount++;
                 continue;
             }
+            List<String> existingRDs = NeutronvpnUtils.getExistingRDs(dataBroker);
+            if (existingRDs.contains(vpn.getRouteDistinguisher().get(0))) {
+                msg = String.format("Creation of L3VPN failed for VPN %s as another VPN with the same RD %s "
+                    + "is already configured",
+                    vpn.getId().getValue(), vpn.getRouteDistinguisher().get(0));
+                LOG.warn(msg);
+                error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
+                errorList.add(error);
+                warningcount++;
+                continue;
+            }
             if (vpn.getRouterId() != null) {
                 if (NeutronvpnUtils.getNeutronRouter(dataBroker, vpn.getRouterId()) == null) {
                     msg = String.format("Creation of L3VPN failed for VPN %s due to router not found %s",
@@ -893,10 +940,11 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 }
             }
             try {
-                createL3Vpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), vpn.getRouteDistinguisher(),
-                        vpn.getImportRT(), vpn.getExportRT(), vpn.getRouterId(), vpn.getNetworkIds());
+                createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), vpn.getRouteDistinguisher(),
+                        vpn.getImportRT(), vpn.getExportRT(), vpn.getRouterId(), vpn.getNetworkIds(),
+                        vpnInstanceType, l3vni);
             } catch (Exception ex) {
-                msg = String.format("Creation of L3VPN failed for VPN %s", vpn.getId().getValue());
+                msg = String.format("Creation of VPN failed for VPN %s", vpn.getId().getValue());
                 LOG.error(msg, ex);
                 error = RpcResultBuilder.newError(ErrorType.APPLICATION, msg, ex.getMessage());
                 errorList.add(error);
@@ -906,7 +954,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         // if at least one succeeds; result is success
         // if none succeeds; result is failure
         if (failurecount + warningcount == vpns.size()) {
-            result.set(RpcResultBuilder.<CreateL3VPNOutput> failed().withRpcErrors(errorList).build());
+            result.set(RpcResultBuilder.<CreateL3VPNOutput>failed().withRpcErrors(errorList).build());
         } else {
             List<String> errorResponseList = new ArrayList<>();
             if (!errorList.isEmpty()) {
@@ -919,18 +967,17 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 errorResponseList.add("Operation successful with no errors");
             }
             opBuilder.setResponse(errorResponseList);
-            result.set(RpcResultBuilder.<CreateL3VPNOutput> success().withResult(opBuilder.build()).build());
+            result.set(RpcResultBuilder.<CreateL3VPNOutput>success().withResult(opBuilder.build()).build());
         }
         return result;
     }
 
     /**
-     * It handles the invocations to the neutronvpn:getL3VPN RPC method
-     *
-     * @see org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService#getL3VPN
-     * (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInput)
+     * It handles the invocations to the neutronvpn:getL3VPN RPC method.
      */
     @Override
+    // TODO Clean up the exception handling
+    @SuppressWarnings("checkstyle:IllegalCatch")
     public Future<RpcResult<GetL3VPNOutput>> getL3VPN(GetL3VPNInput input) {
 
         GetL3VPNOutputBuilder opBuilder = new GetL3VPNOutputBuilder();
@@ -943,32 +990,31 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 // get all vpns
                 InstanceIdentifier<VpnInstances> vpnsIdentifier = InstanceIdentifier.builder(VpnInstances.class)
                         .build();
-                Optional<VpnInstances> optionalVpns = NeutronvpnUtils.read(dataBroker,
-                        LogicalDatastoreType.CONFIGURATION,
-                        vpnsIdentifier);
-                if (optionalVpns.isPresent() && optionalVpns.get().getVpnInstance() != null) {
+                Optional<VpnInstances> optionalVpns = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
+                        .CONFIGURATION, vpnsIdentifier);
+                if (optionalVpns.isPresent() && !optionalVpns.get().getVpnInstance().isEmpty()) {
                     for (VpnInstance vpn : optionalVpns.get().getVpnInstance()) {
-                        // eliminating internal VPNs from getL3VPN output
+                        // eliminating implicitly created (router and VLAN provider external network specific) VPNs
+                        // from getL3VPN output
                         if (vpn.getIpv4Family().getRouteDistinguisher() != null) {
                             vpns.add(vpn);
                         }
                     }
                 } else {
                     // No VPN present
-                    result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withWarning(ErrorType.PROTOCOL, "", "No VPN " +
-                            "is present").build());
+                    result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
                     return result;
                 }
             } else {
                 String name = inputVpnId.getValue();
                 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
-                        .child(VpnInstance.class,
-                                new VpnInstanceKey(name))
-                        .build();
+                        .child(VpnInstance.class, new VpnInstanceKey(name)).build();
                 // read VpnInstance Info
                 Optional<VpnInstance> optionalVpn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
                         vpnIdentifier);
-                if (optionalVpn.isPresent()) {
+                // eliminating implicitly created (router or VLAN provider external network specific) VPN from
+                // getL3VPN output
+                if (optionalVpn.isPresent() && optionalVpn.get().getIpv4Family().getRouteDistinguisher() != null) {
                     vpns.add(optionalVpn.get());
                 } else {
                     String message = String.format("GetL3VPN failed because VPN %s is not present", name);
@@ -981,11 +1027,9 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             for (VpnInstance vpnInstance : vpns) {
                 Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
                 // create VpnMaps id
-                InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap
-                        .class, new VpnMapKey(vpnId)).build();
                 L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
 
-                List<String> rd = Arrays.asList(vpnInstance.getIpv4Family().getRouteDistinguisher().split(","));
+                List<String> rd = vpnInstance.getIpv4Family().getRouteDistinguisher();
                 List<VpnTarget> vpnTargetList = vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget();
 
                 List<String> ertList = new ArrayList<>();
@@ -1005,6 +1049,11 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 }
 
                 l3vpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
+                if (vpnInstance.getL3vni() != null) {
+                    l3vpn.setL3vni(vpnInstance.getL3vni());
+                }
+                InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap
+                        .class, new VpnMapKey(vpnId)).build();
                 Optional<VpnMap> optionalVpnMap = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
                         vpnMapIdentifier);
                 if (optionalVpnMap.isPresent()) {
@@ -1016,23 +1065,22 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             }
 
             opBuilder.setL3vpnInstances(l3vpnList);
-            result.set(RpcResultBuilder.<GetL3VPNOutput> success().withResult(opBuilder.build()).build());
+            result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
 
         } catch (Exception ex) {
-            String message = String.format("GetL3VPN failed due to %s", ex.getMessage());
+            String message = String.format("GetVPN failed due to %s", ex.getMessage());
             LOG.error(message, ex);
-            result.set(RpcResultBuilder.<GetL3VPNOutput> failed().withError(ErrorType.APPLICATION, message).build());
+            result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withError(ErrorType.APPLICATION, message).build());
         }
         return result;
     }
 
     /**
-     * It handles the invocations to the neutronvpn:deleteL3VPN RPC method
-     *
-     * @see org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService#deleteL3VPN
-     * (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNInput)
+     * It handles the invocations to the neutronvpn:deleteL3VPN RPC method.
      */
     @Override
+    // TODO Clean up the exception handling
+    @SuppressWarnings("checkstyle:IllegalCatch")
     public Future<RpcResult<DeleteL3VPNOutput>> deleteL3VPN(DeleteL3VPNInput input) {
 
         DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder();
@@ -1047,12 +1095,12 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             String msg;
             try {
                 InstanceIdentifier<VpnInstance> vpnIdentifier =
-                        InstanceIdentifier.builder(VpnInstances.class).child(VpnInstance.class, new VpnInstanceKey
-                                (vpn.getValue())).build();
+                        InstanceIdentifier.builder(VpnInstances.class)
+                            .child(VpnInstance.class, new VpnInstanceKey(vpn.getValue())).build();
                 Optional<VpnInstance> optionalVpn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
                         .CONFIGURATION, vpnIdentifier);
                 if (optionalVpn.isPresent()) {
-                    removeL3Vpn(vpn);
+                    removeVpn(vpn);
                 } else {
                     msg = String.format("VPN with vpnid: %s does not exist", vpn.getValue());
                     LOG.warn(msg);
@@ -1071,7 +1119,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         // if at least one succeeds; result is success
         // if none succeeds; result is failure
         if (failurecount + warningcount == vpns.size()) {
-            result.set(RpcResultBuilder.<DeleteL3VPNOutput> failed().withRpcErrors(errorList).build());
+            result.set(RpcResultBuilder.<DeleteL3VPNOutput>failed().withRpcErrors(errorList).build());
         } else {
             List<String> errorResponseList = new ArrayList<>();
             if (!errorList.isEmpty()) {
@@ -1084,37 +1132,35 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 errorResponseList.add("Operation successful with no errors");
             }
             opBuilder.setResponse(errorResponseList);
-            result.set(RpcResultBuilder.<DeleteL3VPNOutput> success().withResult(opBuilder.build()).build());
+            result.set(RpcResultBuilder.<DeleteL3VPNOutput>success().withResult(opBuilder.build()).build());
         }
         return result;
     }
 
+    public void createVpnInstanceForSubnet(Uuid subnetId) {
+        LOG.debug("Creating/Updating L3 internalVPN for subnetID {} ", subnetId);
+        createL3InternalVpn(subnetId, subnetId.getValue(), null, null, null, null, null, null);
+    }
+
+    public void removeVpnInstanceForSubnet(Uuid subnetId) {
+        LOG.debug("Removing vpn-instance for subnetID {} ", subnetId);
+        removeVpn(subnetId);
+    }
+
     protected void addSubnetToVpn(final Uuid vpnId, Uuid subnet) {
         LOG.debug("Adding subnet {} to vpn {}", subnet.getValue(), vpnId.getValue());
-        Subnetmap sn = updateSubnetNode(subnet, null, null, null, null, vpnId);
-        final Uuid routerId = NeutronvpnUtils.getVpnMap(dataBroker, vpnId).getRouterId();
-        // send subnet added to vpn notification
-        isExternalVpn = vpnId.equals(routerId) ? false : true;
-        String elanInstanceName = sn.getNetworkId().getValue();
-        InstanceIdentifier<ElanInstance> elanIdentifierId = InstanceIdentifier.builder(ElanInstances.class)
-                .child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
-        try {
-            Optional<ElanInstance> elanInstance = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
-                    .CONFIGURATION, elanIdentifierId);
-            if (elanInstance.isPresent()) {
-                long elanTag = elanInstance.get().getElanTag();
-                checkAndPublishSubnetAddNotification(subnet, sn.getSubnetIp(), vpnId.getValue(), isExternalVpn,
-                        elanTag);
-                LOG.debug("Subnet added to VPN notification sent for subnet {} on VPN {}", subnet.getValue(),
-                        vpnId.getValue());
-            } else {
-                LOG.error("Subnet added to VPN notification failed for subnet {}  on VPN {} because of failure in " +
-                        "reading ELANInstance {}", subnet.getValue(), vpnId.getValue(), elanInstanceName);
-            }
-        } catch (Exception e) {
-            LOG.error("Subnet added to VPN notification failed for subnet {} on VPN {}", subnet.getValue(), vpnId
-                    .getValue(), e);
+        Subnetmap sn = updateSubnetNode(subnet, null, vpnId);
+        if (sn == null) {
+            LOG.error("subnetmap is null, cannot add subnet {} to VPN {}", subnet.getValue(), vpnId.getValue());
+            return;
+        }
+        VpnMap vpnMap = NeutronvpnUtils.getVpnMap(dataBroker, vpnId);
+        if (vpnMap == null) {
+            LOG.error("No vpnMap for vpnId {}, cannot add subnet {} to VPN", vpnId.getValue(), subnet.getValue());
+            return;
         }
+
+        final Uuid routerId = NeutronvpnUtils.getVpnMap(dataBroker, vpnId).getRouterId();
         // Check if there are ports on this subnet and add corresponding
         // vpn-interfaces
         List<Uuid> portList = sn.getPortList();
@@ -1122,17 +1168,13 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             for (final Uuid portId : sn.getPortList()) {
                 LOG.debug("adding vpn-interface for port {}", portId.getValue());
                 final DataStoreJobCoordinator portDataStoreCoordinator = DataStoreJobCoordinator.getInstance();
-                portDataStoreCoordinator.enqueueJob("PORT-" + portId.getValue(), new
-                        Callable<List<ListenableFuture<Void>>>() {
-                    @Override
-                    public List<ListenableFuture<Void>> call() throws Exception {
-                        WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
-                        List<ListenableFuture<Void>> futures = new ArrayList<>();
-                        createVpnInterface(vpnId, routerId, NeutronvpnUtils.getNeutronPort(dataBroker, portId),
-                                wrtConfigTxn);
-                        futures.add(wrtConfigTxn.submit());
-                        return futures;
-                    }
+                portDataStoreCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
+                    WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
+                    List<ListenableFuture<Void>> futures = new ArrayList<>();
+                    createVpnInterface(vpnId, routerId, NeutronvpnUtils.getNeutronPort(dataBroker, portId),
+                            wrtConfigTxn);
+                    futures.add(wrtConfigTxn.submit());
+                    return futures;
                 });
             }
         }
@@ -1142,8 +1184,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         LOG.debug("Updating VPN {} for subnet {}", vpnId.getValue(), subnet.getValue());
         // Read the subnet first to see if its already associated to a VPN
         Uuid oldVpnId = null;
-        InstanceIdentifier<Subnetmap> snId = InstanceIdentifier.builder(Subnetmaps.class).
-                child(Subnetmap.class, new SubnetmapKey(subnet)).build();
+        InstanceIdentifier<Subnetmap> snId = InstanceIdentifier.builder(Subnetmaps.class)
+            .child(Subnetmap.class, new SubnetmapKey(subnet)).build();
         Subnetmap sn = null;
         Optional<Subnetmap> optSn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, snId);
         if (optSn.isPresent()) {
@@ -1151,43 +1193,30 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             oldVpnId = sn.getVpnId();
             List<String> ips = sn.getRouterInterfaceFixedIps();
             for (String ipValue : ips) {
-                if (oldVpnId != null) {
-                    NeutronvpnUtils.removeVpnPortFixedIpToPort(dataBroker, oldVpnId.getValue(), ipValue);
+                // Update the association of router-interface to external vpn
+                String portName =
+                    NeutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(dataBroker, oldVpnId.getValue(), ipValue);
+                if (portName != null) {
+                    updateVpnInterface(vpnId, oldVpnId,
+                        NeutronvpnUtils.getNeutronPort(dataBroker, new Uuid(portName)),
+                        isBeingAssociated, true);
                 }
-                NeutronvpnUtils.createVpnPortFixedIpToPort(dataBroker, vpnId.getValue(), ipValue, sn
-                        .getRouterInterfaceName().getValue(), sn.getRouterIntfMacAddress(), true, true, false);
             }
         }
-        sn = updateSubnetNode(subnet, null, null, null, null, vpnId);
-        // send vpn updated for subnet notification
-        String elanInstanceName = sn.getNetworkId().getValue();
-        InstanceIdentifier<ElanInstance> elanIdentifierId = InstanceIdentifier.builder(ElanInstances.class)
-                .child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
-        try {
-            Optional<ElanInstance> elanInstance = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
-                    .CONFIGURATION, elanIdentifierId);
-            if (elanInstance.isPresent()) {
-                long elanTag = elanInstance.get().getElanTag();
-                checkAndPublishSubnetUpdNotification(subnet, sn.getSubnetIp(), vpnId.getValue(), isBeingAssociated,
-                        elanTag);
-                LOG.debug("VPN updated for subnet notification sent for subnet {} on VPN {}", subnet.getValue(),
-                        vpnId.getValue());
-            } else {
-                LOG.error("VPN updated for subnet notification failed for subnet {} on VPN {} because of failure " +
-                        "in reading ELANInstance {}", subnet.getValue(), vpnId.getValue(), elanInstanceName);
-            }
-        } catch (Exception e) {
-            LOG.error("VPN updated for subnet notification failed for subnet {} on VPN {}", subnet.getValue(),
-                    vpnId.getValue(), e);
+        sn = updateSubnetNode(subnet, null, vpnId);
+        if (sn == null) {
+            LOG.error("subnetmap is null, cannot update VPN {} for subnet {}", vpnId.getValue(), subnet.getValue());
+            return;
         }
         // Check for ports on this subnet and update association of
         // corresponding vpn-interfaces to external vpn
         List<Uuid> portList = sn.getPortList();
         if (portList != null) {
             for (Uuid port : sn.getPortList()) {
-                LOG.debug("Updating vpn-interface for port {}", port.getValue());
+                LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
+                    port.getValue(), isBeingAssociated);
                 updateVpnInterface(vpnId, oldVpnId, NeutronvpnUtils.getNeutronPort(dataBroker, port),
-                        isBeingAssociated);
+                        isBeingAssociated, false);
             }
         }
     }
@@ -1202,8 +1231,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
             Optional<RouterInterfaces> optRouterInterfaces = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
                     .CONFIGURATION, routerInterfacesId);
-            Interfaces routerInterface = new InterfacesBuilder().setKey(new InterfacesKey(interfaceName)).setInterfaceId
-                    (interfaceName).build();
+            Interfaces routerInterface = new InterfacesBuilder().setKey(new InterfacesKey(interfaceName))
+                .setInterfaceId(interfaceName).build();
             if (optRouterInterfaces.isPresent()) {
                 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, routerInterfacesId.child(Interfaces
                         .class, new InterfacesKey(interfaceName)), routerInterface);
@@ -1222,8 +1251,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
             Optional<RouterInterfaces> optRouterInterfaces = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
                     .CONFIGURATION, routerInterfacesId);
-            Interfaces routerInterface = new InterfacesBuilder().setKey(new InterfacesKey(interfaceName)).setInterfaceId
-                    (interfaceName).build();
+            Interfaces routerInterface = new InterfacesBuilder().setKey(new InterfacesKey(interfaceName))
+                .setInterfaceId(interfaceName).build();
             if (optRouterInterfaces.isPresent()) {
                 RouterInterfaces routerInterfaces = optRouterInterfaces.get();
                 List<Interfaces> interfaces = routerInterfaces.getInterfaces();
@@ -1250,11 +1279,11 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
      */
     public void addInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
                                   HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
-        for ( Routes route : interVpnLinkRoutes ) {
+        for (Routes route : interVpnLinkRoutes) {
             String nexthop = String.valueOf(route.getNexthop().getValue());
             String destination = String.valueOf(route.getDestination().getValue());
             InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
-            if ( isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink) ) {
+            if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
                 AddStaticRouteInput rpcInput =
                         new AddStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
                                 .setVpnInstanceName(vpnName.getValue())
@@ -1263,7 +1292,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 RpcResult<AddStaticRouteOutput> rpcResult;
                 try {
                     rpcResult = labelOuputFtr.get();
-                    if ( rpcResult.isSuccessful() ) {
+                    if (rpcResult.isSuccessful()) {
                         LOG.debug("Label generated for destination {} is: {}",
                                 destination, rpcResult.getResult().getLabel());
                     } else {
@@ -1276,7 +1305,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             } else {
                 // Any other case is a fault.
                 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
-                        String.valueOf(route.getDestination().getValue()), nexthop );
+                        String.valueOf(route.getDestination().getValue()), nexthop);
                 continue;
             }
         }
@@ -1292,11 +1321,11 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
      */
     public void removeInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
                                      HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
-        for ( Routes route : interVpnLinkRoutes ) {
+        for (Routes route : interVpnLinkRoutes) {
             String nexthop = String.valueOf(route.getNexthop().getValue());
             String destination = String.valueOf(route.getDestination().getValue());
             InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
-            if ( isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink) ) {
+            if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
                 RemoveStaticRouteInput rpcInput =
                         new RemoveStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
                                 .setVpnInstanceName(vpnName.getValue())
@@ -1305,7 +1334,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             } else {
                 // Any other case is a fault.
                 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
-                        String.valueOf(route.getDestination().getValue()), nexthop );
+                        String.valueOf(route.getDestination().getValue()), nexthop);
                 continue;
             }
         }
@@ -1318,13 +1347,13 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
     private boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid, InterVpnLink interVpnLink) {
         return
                 interVpnLink != null
-                        && (   (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
+                        && ((interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
                         && interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nexthop))
-                        || (interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(thisVpnUuid )
-                        && interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(nexthop)) );
+                        || (interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
+                        && interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(nexthop)));
     }
 
-    protected List<Adjacency> addAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
+    protected List<Adjacency> getAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList, String fixedIp) {
         List<Adjacency> adjList = new ArrayList<>();
         Map<String, List<String>> adjMap = new HashMap<>();
         for (Routes route : routeList) {
@@ -1333,72 +1362,70 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             } else {
                 String nextHop = String.valueOf(route.getNexthop().getValue());
                 String destination = String.valueOf(route.getDestination().getValue());
-                String infName = NeutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(dataBroker, vpnId.getValue(),
-                        nextHop);
-                if (infName == null) {
-                    LOG.error("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} " +
-                            "with nexthop {}", destination, vpnId.getValue(), nextHop);
-                    // Proceed to process the next extra-route
+                if (!nextHop.equals(fixedIp)) {
+                    LOG.trace("FixedIP {} is not extra route nexthop for destination {}", fixedIp, destination);
                     continue;
                 }
-                LOG.trace("Adding extra route for destination {} onto vpn {} with nexthop {} and infName {}", destination,
-                        vpnId.getValue(), nextHop, infName);
-                List<String> hops = adjMap.get(destination);
-                if (hops == null){
-                    hops = new ArrayList<>();
-                    adjMap.put(destination, hops);
-                }
-                if (! hops.contains(nextHop)) {
+                LOG.trace("Adding extra route for destination {} onto vpn {} with nexthop {} ", destination,
+                        vpnId.getValue(), nextHop);
+                List<String> hops = adjMap.computeIfAbsent(destination, k -> new ArrayList<>());
+                if (!hops.contains(nextHop)) {
                     hops.add(nextHop);
                 }
             }
         }
 
         for (String destination : adjMap.keySet()) {
-            Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination).setNextHopIpList(adjMap.get
-                    (destination)).setKey(new AdjacencyKey(destination)).build();
+            Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
+                .setNextHopIpList(adjMap.get(destination)).setKey(new AdjacencyKey(destination)).build();
             adjList.add(erAdj);
         }
+        return  adjList;
+    }
 
-        for (Adjacency adj : adjList) {
-            for(String nextHop : adj.getNextHopIpList()) {
+    // TODO Clean up the exception handling
+    @SuppressWarnings("checkstyle:IllegalCatch")
+    protected void updateVpnInterfaceWithExtraRouteAdjacency(Uuid vpnId, List<Routes> routeList) {
+        for (Routes route : routeList) {
+            if (route == null || route.getNexthop() == null || route.getDestination() == null) {
+                LOG.error("Incorrect input received for extra route. {}", route);
+            } else {
+                String nextHop = String.valueOf(route.getNexthop().getValue());
+                String destination = String.valueOf(route.getDestination().getValue());
                 String infName = NeutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(dataBroker, vpnId.getValue(),
                         nextHop);
                 if (infName != null) {
-                    InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(VpnInterfaces.class)
-                            .child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
+                    LOG.trace("Updating extra route for destination {} onto vpn {} with nexthop {} and infName {}",
+                        destination, vpnId.getValue(), nextHop, infName);
                     boolean isLockAcquired = false;
                     try {
-                        Optional<VpnInterface> optionalVpnInterface =
-                                NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
-                        if (optionalVpnInterface.isPresent()) {
-                            Adjacency newAdj = new AdjacencyBuilder(adj).setNextHopIpList(Arrays.asList(nextHop))
-                                    .build();
-                            Adjacencies erAdjs = new AdjacenciesBuilder().setAdjacency(Arrays.asList(newAdj)).build();
-                            VpnInterface vpnIf = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(infName))
-                                    .addAugmentation(Adjacencies.class, erAdjs).build();
-                            isLockAcquired = NeutronvpnUtils.lock(infName);
-                            MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIf);
-                        } else {
-                            LOG.error("VM adjacency for interface {} not present; cannot add extra route adjacency",
-                                    infName);
-                        }
+                        InstanceIdentifier<VpnInterface> identifier = InstanceIdentifier.builder(VpnInterfaces.class)
+                                .child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
+                        InstanceIdentifier<Adjacency> path = identifier.augmentation(Adjacencies.class)
+                            .child(Adjacency.class, new AdjacencyKey(destination));
+                        Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
+                            .setNextHopIpList(Collections.singletonList(nextHop)).setKey(new AdjacencyKey(destination))
+                            .build();
+                        isLockAcquired = NeutronvpnUtils.lock(infName);
+                        MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, path, erAdj);
                     } catch (Exception e) {
-                        LOG.error("exception in adding extra route with destination: {}, next hop: {}", adj
-                                .getIpAddress(), nextHop, e);
+                        LOG.error("exception in adding extra route with destination: {}, next hop: {}",
+                            destination, nextHop, e);
                     } finally {
                         if (isLockAcquired) {
                             NeutronvpnUtils.unlock(infName);
                         }
                     }
                 } else {
-                    LOG.warn("Could not find suitable Interface for {}", nextHop);
+                    LOG.debug("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} "
+                        + "with nexthop {}", destination, vpnId.getValue(), nextHop);
                 }
             }
         }
-        return adjList;
     }
 
+    // TODO Clean up the exception handling
+    @SuppressWarnings("checkstyle:IllegalCatch")
     protected void removeAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
         for (Routes route : routeList) {
             if (route != null && route.getNexthop() != null && route.getDestination() != null) {
@@ -1408,9 +1435,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 String infName = NeutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(dataBroker, vpnId.getValue(),
                         nextHop);
                 if (infName == null) {
-                    LOG.error("Unable to find VPN NextHop interface to remove extra-route destination {} on VPN {} " +
-                                    "with nexthop {}",
-                            destination, vpnId.getValue(), nextHop);
+                    LOG.error("Unable to find VPN NextHop interface to remove extra-route destination {} on VPN {} "
+                            + "with nexthop {}", destination, vpnId.getValue(), nextHop);
                     // Proceed to remove the next extra-route
                     continue;
                 }
@@ -1452,7 +1478,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                                 .setNextHopIpList(nextHopList)
                                 .setKey(new AdjacencyKey(destination))
                                 .build();
-                        Adjacencies erAdjs = new AdjacenciesBuilder().setAdjacency(Arrays.asList(newAdj)).build();
+                        Adjacencies erAdjs =
+                                new AdjacenciesBuilder().setAdjacency(Collections.singletonList(newAdj)).build();
                         VpnInterface vpnIf = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(infName))
                                 .addAugmentation(Adjacencies.class, erAdjs).build();
                         MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIf);
@@ -1474,10 +1501,10 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         }
     }
 
-    protected void removeL3Vpn(Uuid id) {
+    protected void removeVpn(Uuid id) {
         // read VPNMaps
         VpnMap vpnMap = NeutronvpnUtils.getVpnMap(dataBroker, id);
-        Uuid router = vpnMap.getRouterId();
+        Uuid router = (vpnMap != null) ? vpnMap.getRouterId() : null;
         // dissociate router
         if (router != null) {
             dissociateRouterFromVpn(id, router);
@@ -1495,30 +1522,15 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
 
     protected void removeSubnetFromVpn(final Uuid vpnId, Uuid subnet) {
         LOG.debug("Removing subnet {} from vpn {}", subnet.getValue(), vpnId.getValue());
-        final Uuid routerId = NeutronvpnUtils.getVpnMap(dataBroker, vpnId).getRouterId();
-        Subnetmap sn = NeutronvpnUtils.getSubnetmap(dataBroker, subnet);
-        // send subnet removed from vpn notification
-        isExternalVpn = vpnId.equals(routerId) ? false : true;
-        String elanInstanceName = sn.getNetworkId().getValue();
-        InstanceIdentifier<ElanInstance> elanIdentifierId = InstanceIdentifier.builder(ElanInstances.class)
-                .child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
-        try {
-            Optional<ElanInstance> elanInstance = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
-                    .CONFIGURATION, elanIdentifierId);
-            if (elanInstance.isPresent()) {
-                long elanTag = elanInstance.get().getElanTag();
-                checkAndPublishSubnetDelNotification(subnet, sn.getSubnetIp(), vpnId.getValue(), isExternalVpn,
-                        elanTag);
-                LOG.debug("Subnet removed from VPN notification sent for subnet {} on VPN {}", subnet.getValue(),
-                        vpnId.getValue());
-            } else {
-                LOG.error("Subnet removed from VPN notification failed for subnet {} on VPN {} because of failure " +
-                        "in reading ELANInstance {}", subnet.getValue(), vpnId.getValue(), elanInstanceName);
-            }
-        } catch (Exception e) {
-            LOG.error("Subnet removed from VPN notification failed for subnet {} on VPN {}", subnet.getValue(),
-                    vpnId.getValue(), e);
+        VpnMap vpnMap = NeutronvpnUtils.getVpnMap(dataBroker, vpnId);
+        if (vpnMap == null) {
+            LOG.error("No vpnMap for vpnId {}, cannot remove subnet {} from VPN",
+                    vpnId.getValue(), subnet.getValue());
+            return;
         }
+
+        final Uuid routerId = vpnMap.getRouterId();
+        Subnetmap sn = NeutronvpnUtils.getSubnetmap(dataBroker, subnet);
         if (sn != null) {
             // Check if there are ports on this subnet; remove corresponding vpn-interfaces
             List<Uuid> portList = sn.getPortList();
@@ -1529,8 +1541,13 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                     portDataStoreCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
                         WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
                         List<ListenableFuture<Void>> futures = new ArrayList<>();
-                        deleteVpnInterface(vpnId, routerId, NeutronvpnUtils.getNeutronPort(dataBroker, portId),
-                                wrtConfigTxn);
+                        Port port = NeutronvpnUtils.getNeutronPort(dataBroker, portId);
+                        if (port != null) {
+                            deleteVpnInterface(vpnId, routerId, port, wrtConfigTxn);
+                        } else {
+                            LOG.error("Cannot proceed with deleteVpnInterface for port {} in subnet {} since port is "
+                                + "absent in Neutron config DS", portId.getValue(), subnet.getValue());
+                        }
                         futures.add(wrtConfigTxn.submit());
                         return futures;
                     });
@@ -1543,6 +1560,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         }
     }
 
+    // TODO Clean up the exception handling
+    @SuppressWarnings("checkstyle:IllegalCatch")
     protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
         updateVpnMaps(vpnId, null, routerId, null, null);
         LOG.debug("Updating association of subnets to external vpn {}", vpnId.getValue());
@@ -1570,6 +1589,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         }
     }
 
+    // TODO Clean up the exception handling
+    @SuppressWarnings("checkstyle:IllegalCatch")
     protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
 
         List<Uuid> routerSubnets = NeutronvpnUtils.getNeutronRouterSubnetIds(dataBroker, routerId);
@@ -1597,6 +1618,14 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             // process corresponding subnets for VPN
             for (Uuid nw : networks) {
                 Network network = NeutronvpnUtils.getNeutronNetwork(dataBroker, nw);
+                NetworkProviderExtension providerExtension = network.getAugmentation(NetworkProviderExtension.class);
+                if (providerExtension.getSegments() != null && providerExtension.getSegments().size() > 1) {
+                    LOG.error("MultiSegmented networks not supported in VPN. Failed to associate network {} on vpn {}",
+                            nw.getValue(), vpn.getValue());
+                    failedNwList.add(String.format("Failed to associate network %s on vpn %s as it is multisegmented.",
+                            nw.getValue(), vpn.getValue()));
+                    continue;
+                }
                 Uuid vpnId = NeutronvpnUtils.getVpnForNetwork(dataBroker, nw);
                 if (network == null) {
                     failedNwList.add(String.format("network %s not found", nw.getValue()));
@@ -1614,8 +1643,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                                 addSubnetToVpn(vpn, subnet);
                                 passedNwList.add(nw);
                             } else {
-                                failedNwList.add(String.format("subnet %s already added as router interface bound to " +
-                                        "internal/external VPN %s", subnet.getValue (), subnetVpnId.getValue()));
+                                failedNwList.add(String.format("subnet %s already added as router interface bound to "
+                                    + "internal/external VPN %s", subnet.getValue(), subnetVpnId.getValue()));
                             }
                         }
                     }
@@ -1654,8 +1683,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                             failedNwList.add(String.format("input network %s not associated to any vpn yet", nw
                                     .getValue()));
                         } else {
-                            failedNwList.add(String.format("input network %s associated to a another vpn %s instead " +
-                                    "of the one given as input", nw.getValue(), vpnId.getValue()));
+                            failedNwList.add(String.format("input network %s associated to a another vpn %s instead "
+                                + "of the one given as input", nw.getValue(), vpnId.getValue()));
                         }
                     }
                     if (NeutronvpnUtils.getIsExternal(network)) {
@@ -1669,12 +1698,11 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
     }
 
     /**
-     * It handles the invocations to the neutronvpn:associateNetworks RPC method
-     *
-     * @see org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService#associateNetworks
-     * (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksInput)
+     * It handles the invocations to the neutronvpn:associateNetworks RPC method.
      */
     @Override
+    // TODO Clean up the exception handling
+    @SuppressWarnings("checkstyle:IllegalCatch")
     public Future<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
 
         AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
@@ -1702,15 +1730,15 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 String errorResponse = String.format("ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: %s",
                         message);
                 opBuilder.setResponse(errorResponse);
-                result.set(RpcResultBuilder.<AssociateNetworksOutput> success().withResult(opBuilder.build()).build());
+                result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
             } else {
-                result.set(RpcResultBuilder.<AssociateNetworksOutput> success().build());
+                result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
             }
         } catch (Exception ex) {
             String message = String.format("associate Networks to vpn %s failed due to %s",
                     input.getVpnId().getValue(), ex.getMessage());
             LOG.error(message, ex);
-            result.set(RpcResultBuilder.<AssociateNetworksOutput> failed().withError(ErrorType.APPLICATION, message)
+            result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION, message)
                     .build());
         }
         LOG.debug("associateNetworks returns..");
@@ -1718,12 +1746,11 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
     }
 
     /**
-     * It handles the invocations to the neutronvpn:associateRouter RPC method
-     *
-     * @see org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService#associateRouter
-     * (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterInput)
+     * It handles the invocations to the neutronvpn:associateRouter RPC method.
      */
     @Override
+    // TODO Clean up the exception handling
+    @SuppressWarnings("checkstyle:IllegalCatch")
     public Future<RpcResult<Void>> associateRouter(AssociateRouterInput input) {
 
         SettableFuture<RpcResult<Void>> result = SettableFuture.create();
@@ -1741,8 +1768,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                         returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
                                 .append(vpnMap.getRouterId().getValue());
                     } else if (extVpnId != null) {
-                        returnMsg.append("router ").append(routerId.getValue()).append(" already associated to " +
-                                "another VPN ").append(extVpnId.getValue());
+                        returnMsg.append("router ").append(routerId.getValue()).append(" already associated to "
+                            + "another VPN ").append(extVpnId.getValue());
                     } else {
                         associateRouterToVpn(vpnId, routerId);
                     }
@@ -1756,28 +1783,28 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 String message = String.format("associate router to vpn %s failed due to %s", routerId.getValue(),
                         returnMsg);
                 LOG.error(message);
-                result.set(RpcResultBuilder.<Void> failed().withWarning(ErrorType.PROTOCOL, "invalid-value", message)
+                result.set(RpcResultBuilder.<Void>failed().withWarning(ErrorType.PROTOCOL, "invalid-value", message)
                         .build());
             } else {
-                result.set(RpcResultBuilder.<Void> success().build());
+                result.set(RpcResultBuilder.<Void>success().build());
             }
         } catch (Exception ex) {
             String message = String.format("associate router %s to vpn %s failed due to %s", routerId.getValue(),
                     vpnId.getValue(), ex.getMessage());
             LOG.error(message, ex);
-            result.set(RpcResultBuilder.<Void> failed().withError(ErrorType.APPLICATION, message).build());
+            result.set(RpcResultBuilder.<Void>failed().withError(ErrorType.APPLICATION, message).build());
         }
         LOG.debug("associateRouter returns..");
         return result;
     }
 
-    /** It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method
-     *
-     * @see org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService#getFixedIPsForNeutronPort
-     * (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortInput)
+    /** It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
      */
     @Override
-    public Future<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(GetFixedIPsForNeutronPortInput input) {
+    // TODO Clean up the exception handling
+    @SuppressWarnings("checkstyle:IllegalCatch")
+    public Future<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(
+        GetFixedIPsForNeutronPortInput input) {
         GetFixedIPsForNeutronPortOutputBuilder opBuilder = new GetFixedIPsForNeutronPortOutputBuilder();
         SettableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> result = SettableFuture.create();
         Uuid portId = input.getPortId();
@@ -1796,32 +1823,30 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             if (returnMsg.length() != 0) {
                 String message = String.format("Retrieval of FixedIPList for neutron port failed due to %s", returnMsg);
                 LOG.error(message);
-                result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput> failed()
+                result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed()
                         .withWarning(ErrorType.PROTOCOL, "invalid-value", message).build());
             } else {
                 opBuilder.setFixedIPs(fixedIPList);
-                result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput> success().withResult(opBuilder.build())
+                result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().withResult(opBuilder.build())
                         .build());
-                result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput> success().build());
+                result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().build());
             }
         } catch (Exception ex) {
             String message = String.format("Retrieval of FixedIPList for neutron port %s failed due to %s",
                     portId.getValue(), ex.getMessage());
             LOG.error(message, ex);
-            result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput> failed()
+            result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed()
                     .withError(ErrorType.APPLICATION, message).build());
         }
         return result;
     }
 
     /**
-     * It handles the invocations to the neutronvpn:dissociateNetworks RPC method
-     *
-     * @see org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn
-     * .rev150602.NeutronvpnService#dissociateNetworks(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt
-     * .neutronvpn.rev150602.DissociateNetworksInput)
+     * It handles the invocations to the neutronvpn:dissociateNetworks RPC method.
      */
     @Override
+    // TODO Clean up the exception handling
+    @SuppressWarnings("checkstyle:IllegalCatch")
     public Future<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
 
         DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
@@ -1850,15 +1875,15 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 String errorResponse = String.format("ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: "
                         + message);
                 opBuilder.setResponse(errorResponse);
-                result.set(RpcResultBuilder.<DissociateNetworksOutput> success().withResult(opBuilder.build()).build());
+                result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
             } else {
-                result.set(RpcResultBuilder.<DissociateNetworksOutput> success().build());
+                result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
             }
         } catch (Exception ex) {
             String message = String.format("dissociate Networks to vpn %s failed due to %s",
                     input.getVpnId().getValue(), ex.getMessage());
             LOG.error(message, ex);
-            result.set(RpcResultBuilder.<DissociateNetworksOutput> failed().withError(ErrorType.APPLICATION, message)
+            result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION, message)
                     .build());
         }
         LOG.debug("dissociateNetworks returns..");
@@ -1867,12 +1892,10 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
 
     /**
      * It handles the invocations to the neutronvpn:dissociateRouter RPC method.
-     *
-     * @see org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn
-     * .rev150602.NeutronvpnService#dissociateRouter(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn
-     * .rev150602.DissociateRouterInput)
      */
     @Override
+    // TODO Clean up the exception handling
+    @SuppressWarnings("checkstyle:IllegalCatch")
     public Future<RpcResult<Void>> dissociateRouter(DissociateRouterInput input) {
 
         SettableFuture<RpcResult<Void>> result = SettableFuture.create();
@@ -1891,12 +1914,12 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                             dissociateRouterFromVpn(vpnId, routerId);
                         } else {
                             if (routerVpnId == null) {
-                                returnMsg.append("input router ").append(routerId.getValue()).append(" not associated" +
-                                        " to any vpn yet");
+                                returnMsg.append("input router ").append(routerId.getValue())
+                                    .append(" not associated to any vpn yet");
                             } else {
-                                returnMsg.append("input router ").append(routerId.getValue()).append(" associated to " +
-                                        "vpn ").append(routerVpnId.getValue()).append("instead of the vpn given as " +
-                                        "input");
+                                returnMsg.append("input router ").append(routerId.getValue())
+                                    .append(" associated to vpn ")
+                                    .append(routerVpnId.getValue()).append("instead of the vpn given as input");
                             }
                         }
                     } else {
@@ -1912,16 +1935,16 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 LOG.error(message);
                 String errorResponse = String.format("ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: "
                         + message);
-                result.set(RpcResultBuilder.<Void> failed().withWarning(ErrorType.PROTOCOL, "invalid-value", message)
+                result.set(RpcResultBuilder.<Void>failed().withWarning(ErrorType.PROTOCOL, "invalid-value", message)
                         .build());
             } else {
-                result.set(RpcResultBuilder.<Void> success().build());
+                result.set(RpcResultBuilder.<Void>success().build());
             }
         } catch (Exception ex) {
             String message = String.format("disssociate router %s to vpn %s failed due to %s", routerId.getValue(),
                     vpnId.getValue(), ex.getMessage());
             LOG.error(message, ex);
-            result.set(RpcResultBuilder.<Void> failed().withError(ErrorType.APPLICATION, message).build());
+            result.set(RpcResultBuilder.<Void>failed().withError(ErrorType.APPLICATION, message).build());
         }
         LOG.debug("dissociateRouter returns..");
 
@@ -1950,7 +1973,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         deleteVpnInstance(routerId);
     }
 
-    protected Subnet getNeutronSubnet(Uuid subnetId){
+    protected Subnet getNeutronSubnet(Uuid subnetId) {
         return NeutronvpnUtils.getNeutronSubnet(dataBroker, subnetId);
     }
 
@@ -1975,36 +1998,30 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         return NeutronvpnUtils.getNeutronPort(dataBroker, portId);
     }
 
-    protected List<Uuid> getSubnetsforVpn(Uuid vpnid) {
-        List<Uuid> subnets = new ArrayList<>();
-        // read subnetmaps
-        InstanceIdentifier<Subnetmaps> subnetmapsid = InstanceIdentifier.builder(Subnetmaps.class).build();
-        Optional<Subnetmaps> subnetmaps = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
-                subnetmapsid);
-        if (subnetmaps.isPresent() && subnetmaps.get().getSubnetmap() != null) {
-            List<Subnetmap> subnetMapList = subnetmaps.get().getSubnetmap();
-            for (Subnetmap subnetMap : subnetMapList) {
-                if (subnetMap.getVpnId() != null && subnetMap.getVpnId().equals(vpnid)) {
-                    subnets.add(subnetMap.getId());
-                }
-            }
-        }
-        return subnets;
+    protected Uuid getNetworkForSubnet(Uuid subnetId) {
+        return NeutronvpnUtils.getNetworkForSubnet(dataBroker, subnetId);
+    }
+
+    protected List<Uuid> getNetworksForVpn(Uuid vpnId) {
+        return NeutronvpnUtils.getNetworksforVpn(dataBroker, vpnId);
     }
 
     /**
-     * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command
+     * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command.
      *
      * @return a List of String to be printed on screen
      */
+    // TODO Clean up the exception handling and the console output
+    @SuppressWarnings({"checkstyle:IllegalCatch", "checkstyle:RegexpSinglelineJava"})
     public List<String> showNeutronPortsCLI() {
         List<String> result = new ArrayList<>();
-        result.add(String.format(" %-36s  %-19s  %-13s  %-20s ", "Port ID", "Mac Address", "Prefix Length", "IP " +
-                "Address"));
+        result.add(String.format(" %-36s  %-19s  %-13s  %-20s ", "Port ID", "Mac Address", "Prefix Length",
+            "IP Address"));
         result.add("-------------------------------------------------------------------------------------------");
         InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
         try {
-            Optional<Ports> ports = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, portidentifier);
+            Optional<Ports> ports =
+                NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, portidentifier);
             if (ports.isPresent() && ports.get().getPort() != null) {
                 for (Port port : ports.get().getPort()) {
                     List<FixedIps> fixedIPs = port.getFixedIps();
@@ -2042,11 +2059,12 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
     }
 
     /**
-     * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command
+     * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command.
      *
      * @param vpnuuid Uuid of the VPN whose config must be shown
      * @return formatted output list
      */
+    @SuppressWarnings("checkstyle:RegexpSinglelineJava")
     public List<String> showVpnConfigCLI(Uuid vpnuuid) {
         List<String> result = new ArrayList<>();
         if (vpnuuid == null) {
@@ -2069,20 +2087,21 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 result.add("");
                 result.add("------------------------------------------------------------------------------------");
                 result.add("");
-                List<L3vpnInstances> VpnList = rpcResult.getResult().getL3vpnInstances();
-                for (L3vpnInstance Vpn : VpnList) {
-                    String tenantId = Vpn.getTenantId() != null ? Vpn.getTenantId().getValue()
+                List<L3vpnInstances> vpnList = rpcResult.getResult().getL3vpnInstances();
+                for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn
+                            .rev150602.VpnInstance vpn : vpnList) {
+                    String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
                             : "\"                 " + "                  \"";
-                    result.add(String.format(" %-37s %-37s %-7s ", Vpn.getId().getValue(), tenantId,
-                            Vpn.getRouteDistinguisher()));
+                    result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
+                            vpn.getRouteDistinguisher()));
                     result.add("");
-                    result.add(String.format(" %-80s ", Vpn.getImportRT()));
+                    result.add(String.format(" %-80s ", vpn.getImportRT()));
                     result.add("");
-                    result.add(String.format(" %-80s ", Vpn.getExportRT()));
+                    result.add(String.format(" %-80s ", vpn.getExportRT()));
                     result.add("");
 
-                    Uuid vpnid = Vpn.getId();
-                    List<Uuid> subnetList = getSubnetsforVpn(vpnid);
+                    Uuid vpnid = vpn.getId();
+                    List<Uuid> subnetList = NeutronvpnUtils.getSubnetsforVpn(dataBroker, vpnid);
                     if (!subnetList.isEmpty()) {
                         for (Uuid subnetuuid : subnetList) {
                             result.add(String.format(" %-76s ", subnetuuid.getValue()));
@@ -2096,10 +2115,10 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 }
             } else {
                 String errortag = rpcResult.getErrors().iterator().next().getTag();
-                if (errortag == "") {
+                if (Objects.equals(errortag, "")) {
                     System.out.println("");
                     System.out.println("No VPN has been configured yet");
-                } else if (errortag == "invalid-value") {
+                } else if (Objects.equals(errortag, "invalid-value")) {
                     System.out.println("");
                     System.out.println("VPN " + vpnuuid.getValue() + " is not present");
                 } else {
@@ -2126,40 +2145,43 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             return;
         }
 
+        WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
         for (String elanInterface : extElanInterfaces) {
-            createExternalVpnInterface(extNetId, elanInterface);
+            createExternalVpnInterface(extNetId, elanInterface, wrtConfigTxn);
         }
+        wrtConfigTxn.submit();
     }
 
+    // TODO Clean up the exception handling
+    @SuppressWarnings("checkstyle:IllegalCatch")
     protected void removeExternalVpnInterfaces(Uuid extNetId) {
         Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
         if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
             LOG.trace("No external ports attached for external network {}", extNetId);
             return;
         }
+        try {
 
-        for (String elanInterface : extElanInterfaces) {
-            boolean isLockAcquired = false;
-            InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
-                    .buildVpnInterfaceIdentifier(elanInterface);
-            try {
-                isLockAcquired = NeutronvpnUtils.lock(elanInterface);
-                LOG.debug("removing vpn interface {}, vpnIfIdentifier", elanInterface, vpnIfIdentifier);
-                MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
-            } catch (Exception ex) {
-                LOG.error("Removal of vpninterface {} failed due to {}", elanInterface, ex);
-            } finally {
-                if (isLockAcquired) {
-                    NeutronvpnUtils.unlock(elanInterface);
-                }
+            WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
+            for (String elanInterface : extElanInterfaces) {
+                InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
+                        .buildVpnInterfaceIdentifier(elanInterface);
+                LOG.info("Removing vpn interface {}", elanInterface);
+                wrtConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
             }
+            wrtConfigTxn.submit();
+
+        } catch (Exception ex) {
+            LOG.error("Removal of vpninterfaces {} failed due to {}", extElanInterfaces, ex);
         }
     }
 
-    private void createExternalVpnInterface(Uuid vpnId, String infName) {
-        writeVpnInterfaceToDs(vpnId, infName, null, false /* not a router iface */, null);
+    private void createExternalVpnInterface(Uuid vpnId, String infName, WriteTransaction wrtConfigTxn) {
+        writeVpnInterfaceToDs(vpnId, infName, null, false /* not a router iface */, wrtConfigTxn);
     }
 
+    // TODO Clean up the exception handling
+    @SuppressWarnings("checkstyle:IllegalCatch")
     private void writeVpnInterfaceToDs(Uuid vpnId, String infName, Adjacencies adjacencies,
             Boolean isRouterInterface, WriteTransaction wrtConfigTxn) {
         if (vpnId == null || infName == null) {
@@ -2200,51 +2222,6 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         return help.toString();
     }
 
-    private void checkAndPublishSubnetAddNotification(Uuid subnetId, String subnetIp, String vpnName,
-                                                      Boolean isExternalvpn, Long elanTag) throws InterruptedException {
-        SubnetAddedToVpnBuilder builder = new SubnetAddedToVpnBuilder();
-
-        LOG.info("publish notification called");
-
-        builder.setSubnetId(subnetId);
-        builder.setSubnetIp(subnetIp);
-        builder.setVpnName(vpnName);
-        builder.setExternalVpn(isExternalvpn);
-        builder.setElanTag(elanTag);
-
-        notificationPublishService.putNotification(builder.build());
-    }
-
-    private void checkAndPublishSubnetDelNotification(Uuid subnetId, String subnetIp, String vpnName,
-                                                      Boolean isExternalvpn, Long elanTag) throws InterruptedException {
-        SubnetDeletedFromVpnBuilder builder = new SubnetDeletedFromVpnBuilder();
-
-        LOG.info("publish notification called");
-
-        builder.setSubnetId(subnetId);
-        builder.setSubnetIp(subnetIp);
-        builder.setVpnName(vpnName);
-        builder.setExternalVpn(isExternalvpn);
-        builder.setElanTag(elanTag);
-
-        notificationPublishService.putNotification(builder.build());
-    }
-
-    private void checkAndPublishSubnetUpdNotification(Uuid subnetId, String subnetIp, String vpnName,
-                                                      Boolean isExternalvpn, Long elanTag) throws InterruptedException {
-        SubnetUpdatedInVpnBuilder builder = new SubnetUpdatedInVpnBuilder();
-
-        LOG.info("publish notification called");
-
-        builder.setSubnetId(subnetId);
-        builder.setSubnetIp(subnetIp);
-        builder.setVpnName(vpnName);
-        builder.setExternalVpn(isExternalvpn);
-        builder.setElanTag(elanTag);
-
-        notificationPublishService.putNotification(builder.build());
-    }
-
     private void checkAndPublishRouterAssociatedtoVpnNotification(Uuid routerId, Uuid vpnId) throws
             InterruptedException {
         RouterAssociatedToVpn routerAssociatedToVpn = new RouterAssociatedToVpnBuilder().setRouterId(routerId)
@@ -2255,8 +2232,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
 
     private void checkAndPublishRouterDisassociatedFromVpnNotification(Uuid routerId, Uuid vpnId) throws
             InterruptedException {
-        RouterDisassociatedFromVpn routerDisassociatedFromVpn = new RouterDisassociatedFromVpnBuilder().setRouterId
-                (routerId).setVpnId(vpnId).build();
+        RouterDisassociatedFromVpn routerDisassociatedFromVpn =
+            new RouterDisassociatedFromVpnBuilder().setRouterId(routerId).setVpnId(vpnId).build();
         LOG.info("publishing notification upon disassociation of router from VPN");
         notificationPublishService.putNotification(routerDisassociatedFromVpn);
     }