Upgrade to the Neon base platform
[netvirt.git] / fibmanager / impl / src / main / java / org / opendaylight / netvirt / fibmanager / FibUtil.java
index 3633258e7bda8a47b4ac442be6b25dd286ea6e9f..92c274ee535dd3ca9a172647973726637503b271 100644 (file)
@@ -8,8 +8,10 @@
 
 package org.opendaylight.netvirt.fibmanager;
 
+import static java.util.Collections.emptyList;
 import static java.util.stream.Collectors.joining;
 import static java.util.stream.Collectors.toList;
+import static org.opendaylight.controller.md.sal.binding.api.WriteTransaction.CREATE_MISSING_PARENTS;
 
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
@@ -19,34 +21,54 @@ import java.net.InetAddress;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
+import org.opendaylight.genius.infra.Datastore.Configuration;
+import org.opendaylight.genius.infra.Datastore.Operational;
+import org.opendaylight.genius.infra.TypedReadTransaction;
+import org.opendaylight.genius.infra.TypedReadWriteTransaction;
+import org.opendaylight.genius.infra.TypedWriteTransaction;
+import org.opendaylight.genius.itm.api.IITMProvider;
 import org.opendaylight.genius.mdsalutil.BucketInfo;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
+import org.opendaylight.genius.mdsalutil.NWUtil;
 import org.opendaylight.genius.mdsalutil.NwConstants;
 import org.opendaylight.netvirt.elanmanager.api.IElanService;
 import org.opendaylight.netvirt.fibmanager.NexthopManager.AdjacencyResult;
 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
 import org.opendaylight.netvirt.vpnmanager.api.VpnExtraRouteHelper;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.Tunnel;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev170119.Tunnel;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
-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.flow.inventory.rev130819.FlowCapableNode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnEndpoints;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfoKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.LockManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.TimeUnits;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.TryLockInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.TryLockInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.TryLockOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.UnlockInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.UnlockInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.UnlockOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.BucketId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.Buckets;
@@ -64,6 +86,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.N
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.RouterInterface;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
@@ -90,12 +113,12 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIdsKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroutes.vpn.extra.routes.Routes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkAttributes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkAttributes.NetworkType;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
@@ -109,12 +132,15 @@ public class FibUtil {
     private final DataBroker dataBroker;
     private final IElanService elanManager;
     private final IdManagerService idManager;
+    private final IITMProvider iitmProvider;
 
     @Inject
-    public FibUtil(DataBroker dataBroker, IElanService elanManager, IdManagerService idManager) {
+    public FibUtil(DataBroker dataBroker, IElanService elanManager, IdManagerService idManager,
+           IITMProvider iitmProvider) {
         this.dataBroker = dataBroker;
         this.elanManager = elanManager;
         this.idManager = idManager;
+        this.iitmProvider = iitmProvider;
     }
 
     static InstanceIdentifier<Adjacency> getAdjacencyIdentifier(String vpnInterfaceName, String ipAddress) {
@@ -133,11 +159,11 @@ public class FibUtil {
     static InstanceIdentifier<Adjacency> getAdjacencyIdentifierOp(String vpnInterfaceName,
                                       String vpnName, String ipAddress) {
         LOG.debug("getAdjacencyIdentifierOp vpninterface {} vpn {} ip {}", vpnInterfaceName, vpnName, ipAddress);
-        return InstanceIdentifier.builder(getAdjListPathOp(vpnInterfaceName, vpnName)
+        return getAdjListPathOp(vpnInterfaceName, vpnName).builder()
                           .child(org.opendaylight.yang.gen.v1.urn.opendaylight
                           .netvirt.l3vpn.rev130911.adjacency.list.Adjacency.class,
                           new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list
-                              .AdjacencyKey(ipAddress))).build();
+                              .AdjacencyKey(ipAddress)).build();
     }
 
     static InstanceIdentifier<Adjacencies> getAdjListPath(String vpnInterfaceName) {
@@ -152,9 +178,9 @@ public class FibUtil {
     }
 
     static InstanceIdentifier<AdjacenciesOp> getAdjListPathOp(String vpnInterfaceName, String vpnName) {
-        return InstanceIdentifier.builder(getVpnInterfaceOpDataEntryIdentifier(vpnInterfaceName, vpnName)
+        return getVpnInterfaceOpDataEntryIdentifier(vpnInterfaceName, vpnName).builder()
             .augmentation(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911
-            .AdjacenciesOp.class)).build();
+            .AdjacenciesOp.class).build();
     }
 
     static InstanceIdentifier<Prefixes> getPrefixToInterfaceIdentifier(long vpnId, String ipPrefix) {
@@ -188,6 +214,12 @@ public class FibUtil {
         return MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
     }
 
+    static Optional<VpnInstanceOpDataEntry> getVpnInstanceOpData(TypedReadTransaction<Operational> operTx, String rd)
+        throws ExecutionException, InterruptedException {
+        return operTx.read(getVpnInstanceOpDataIdentifier(rd)).get();
+    }
+
+    @Nullable
     VpnInstanceOpDataEntry getVpnInstance(String rd) {
         InstanceIdentifier<VpnInstanceOpDataEntry> id =
                 InstanceIdentifier.create(VpnInstanceOpData.class)
@@ -201,12 +233,20 @@ public class FibUtil {
         return rd + FibConstants.SEPARATOR + prefix;
     }
 
+    @Nullable
     Prefixes getPrefixToInterface(Long vpnId, String ipPrefix) {
         Optional<Prefixes> localNextHopInfoData = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
             getPrefixToInterfaceIdentifier(vpnId, ipPrefix));
         return localNextHopInfoData.isPresent() ? localNextHopInfoData.get() : null;
     }
 
+    @Nullable
+    static Prefixes getPrefixToInterface(TypedReadTransaction<Operational> operTx, Long vpnId, String ipPrefix)
+            throws ExecutionException, InterruptedException {
+        return operTx.read(getPrefixToInterfaceIdentifier(vpnId, ipPrefix)).get().orNull();
+    }
+
+    @Nullable
     String getMacAddressFromPrefix(String ifName, String vpnName, String ipPrefix) {
         Optional<Adjacency> adjacencyData = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
                        getAdjacencyIdentifierOp(ifName, vpnName, ipPrefix));
@@ -216,8 +256,7 @@ public class FibUtil {
     void releaseId(String poolName, String idKey) {
         ReleaseIdInput idInput = new ReleaseIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
         try {
-            Future<RpcResult<Void>> result = idManager.releaseId(idInput);
-            RpcResult<Void> rpcResult = result.get();
+            RpcResult<ReleaseIdOutput> rpcResult = idManager.releaseId(idInput).get();
             if (!rpcResult.isSuccessful()) {
                 LOG.error("RPC Call to Get Unique Id for key {} returned with Errors {}", idKey, rpcResult.getErrors());
             }
@@ -253,6 +292,7 @@ public class FibUtil {
                 getVpnInstanceOpData(rd).toJavaUtil().map(VpnInstanceOpDataEntry::getVpnInstanceName));
     }
 
+    @Nullable
     public String getVpnNameFromId(long vpnId) {
         InstanceIdentifier<VpnIds> id = getVpnIdToVpnInstanceIdentifier(vpnId);
         return MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(
@@ -268,7 +308,7 @@ public class FibUtil {
     @SuppressWarnings("checkstyle:IllegalCatch")
     public void addOrUpdateFibEntry(String rd, String macAddress, String prefix, List<String> nextHopList,
             VrfEntry.EncapType encapType, long label, long l3vni, String gwMacAddress, String parentVpnRd,
-            RouteOrigin origin, WriteTransaction writeConfigTxn) {
+            RouteOrigin origin, TypedWriteTransaction<Configuration> writeConfigTxn) {
         if (rd == null || rd.isEmpty()) {
             LOG.error("Prefix {} not associated with vpn", prefix);
             return;
@@ -296,14 +336,14 @@ public class FibUtil {
     @SuppressWarnings("checkstyle:IllegalCatch")
     public void writeFibEntryToDs(InstanceIdentifier<VrfEntry> vrfEntryId, String prefix, List<String> nextHopList,
             long label, Long l3vni, VrfEntry.EncapType encapType, RouteOrigin origin, String macAddress,
-            String gatewayMacAddress, String parentVpnRd, WriteTransaction writeConfigTxn) {
+            String gatewayMacAddress, String parentVpnRd, TypedWriteTransaction<Configuration> writeConfigTxn) {
         VrfEntryBuilder vrfEntryBuilder = new VrfEntryBuilder().setDestPrefix(prefix).setOrigin(origin.getValue());
         if (parentVpnRd != null) {
             vrfEntryBuilder.setParentVpnRd(parentVpnRd);
         }
         buildVpnEncapSpecificInfo(vrfEntryBuilder, encapType, label, l3vni, macAddress, gatewayMacAddress, nextHopList);
         if (writeConfigTxn != null) {
-            writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntryBuilder.build(), true);
+            writeConfigTxn.merge(vrfEntryId, vrfEntryBuilder.build(), CREATE_MISSING_PARENTS);
         } else {
             MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntryBuilder.build());
         }
@@ -311,7 +351,7 @@ public class FibUtil {
 
     @SuppressWarnings("checkstyle:IllegalCatch")
     public void addFibEntryForRouterInterface(String rd, String prefix, RouterInterface routerInterface, long label,
-            WriteTransaction writeConfigTxn) {
+            TypedWriteTransaction<Configuration> writeConfigTxn) {
         if (rd == null || rd.isEmpty()) {
             LOG.error("Prefix {} not associated with vpn", prefix);
             return;
@@ -329,7 +369,7 @@ public class FibUtil {
                 .addAugmentation(RouterInterface.class, routerInterface).build();
 
             if (writeConfigTxn != null) {
-                writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry, true);
+                writeConfigTxn.merge(vrfEntryId, vrfEntry, CREATE_MISSING_PARENTS);
             } else {
                 MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry);
             }
@@ -360,7 +400,7 @@ public class FibUtil {
         builder.setRoutePaths(routePaths);
     }
 
-    public void removeFibEntry(String rd, String prefix, WriteTransaction writeConfigTxn) {
+    public void removeFibEntry(String rd, String prefix, TypedWriteTransaction<Configuration> writeConfigTxn) {
 
         if (rd == null || rd.isEmpty()) {
             LOG.error("Prefix {} not associated with vpn", prefix);
@@ -374,7 +414,7 @@ public class FibUtil {
                 .child(VrfTables.class, new VrfTablesKey(rd)).child(VrfEntry.class, new VrfEntryKey(prefix));
         InstanceIdentifier<VrfEntry> vrfEntryId = idBuilder.build();
         if (writeConfigTxn != null) {
-            writeConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, vrfEntryId);
+            writeConfigTxn.delete(vrfEntryId);
         } else {
             MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
         }
@@ -390,7 +430,7 @@ public class FibUtil {
      *                        If null or empty, then the whole VrfEntry is removed
      */
     public void removeOrUpdateFibEntry(String rd, String prefix, String nextHopToRemove,
-            WriteTransaction writeConfigTxn) {
+            TypedWriteTransaction<Configuration> writeConfigTxn) {
 
         LOG.debug("Removing fib entry with destination prefix {} from vrf table for rd {} nextHop {}", prefix, rd,
                 nextHopToRemove);
@@ -408,8 +448,8 @@ public class FibUtil {
             }
             java.util.Optional<RoutePaths> optRoutePath =
                     routePaths.stream()
-                              .filter(routePath -> routePath.getNexthopAddress().equals(
-                                    nextHopToRemove)).findFirst();
+                        .filter(
+                            routePath -> Objects.equals(routePath.getNexthopAddress(), nextHopToRemove)).findFirst();
             if (!optRoutePath.isPresent()) {
                 LOG.error("Unable to find a routePath that contains the given nextHop to remove {}", nextHopToRemove);
                 return;
@@ -418,7 +458,7 @@ public class FibUtil {
             if (routePaths.size() == 1) {
                 // Remove the whole entry
                 if (writeConfigTxn != null) {
-                    writeConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, vrfEntryId);
+                    writeConfigTxn.delete(vrfEntryId);
                 } else {
                     MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
                 }
@@ -452,7 +492,7 @@ public class FibUtil {
                 RoutePaths routePaths = FibHelper.buildRoutePath(nextHop, label);
                 if (writeConfigTxn != null) {
                     writeConfigTxn.put(LogicalDatastoreType.CONFIGURATION, routePathId, routePaths,
-                            WriteTransaction.CREATE_MISSING_PARENTS);
+                            CREATE_MISSING_PARENTS);
                 } else {
                     MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, routePathId, routePaths);
                 }
@@ -475,14 +515,29 @@ public class FibUtil {
         }
     }
 
-    public void removeVrfTable(String rd, WriteTransaction writeConfigTxn) {
+    public void addVrfTable(String rd, WriteTransaction writeConfigTxn) {
+        LOG.debug("Adding vrf table for rd {}", rd);
+        InstanceIdentifier.InstanceIdentifierBuilder<VrfTables> idBuilder =
+            InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
+        InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
+        VrfTablesBuilder vrfTablesBuilder = new VrfTablesBuilder().withKey(new VrfTablesKey(rd))
+            .setRouteDistinguisher(rd).setVrfEntry(new ArrayList<VrfEntry>());
+        if (writeConfigTxn != null) {
+            writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTablesBuilder.build());
+        } else {
+            MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                                 vrfTableId, vrfTablesBuilder.build());
+        }
+    }
+
+    public void removeVrfTable(String rd, TypedWriteTransaction<Configuration> writeConfigTxn) {
         LOG.debug("Removing vrf table for rd {}", rd);
         InstanceIdentifier.InstanceIdentifierBuilder<VrfTables> idBuilder =
             InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
         InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
 
         if (writeConfigTxn != null) {
-            writeConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, vrfTableId);
+            writeConfigTxn.delete(vrfTableId);
         } else {
             Optional<VrfTables> ifStateOptional = MDSALUtil.read(dataBroker,
                     LogicalDatastoreType.CONFIGURATION, vrfTableId);
@@ -514,11 +569,20 @@ public class FibUtil {
             return java.util.Optional.empty();
         }
         return routePaths.stream()
-                .filter(routePath -> routePath.getNexthopAddress().equals(nextHopIp))
+                .filter(routePath -> Objects.equals(routePath.getNexthopAddress(), nextHopIp))
                 .findFirst()
                 .map(RoutePaths::getLabel);
     }
 
+    @Nullable
+    public StateTunnelList getTunnelState(String interfaceName) throws ReadFailedException {
+        Optional<StateTunnelList> tunnelStateOptional = iitmProvider.getTunnelState(interfaceName);
+        if (tunnelStateOptional.isPresent()) {
+            return tunnelStateOptional.get();
+        }
+        return null;
+    }
+
     public static InstanceIdentifier<Interface> buildStateInterfaceId(String interfaceName) {
         InstanceIdentifier.InstanceIdentifierBuilder<Interface> idBuilder =
                 InstanceIdentifier.builder(InterfacesState.class)
@@ -531,6 +595,7 @@ public class FibUtil {
         return id;
     }
 
+    @Nullable
     public org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
         .state.Interface getInterfaceStateFromOperDS(String interfaceName) {
         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
@@ -547,6 +612,10 @@ public class FibUtil {
         return "FIB-" + vpnId.toString() + "-" + dpnId.toString() + "-" + prefix;
     }
 
+    public static String getCreateRemoteNextHopJobKey(Long vpnId, BigInteger dpnId, String prefix) {
+        return getCreateLocalNextHopJobKey(vpnId, dpnId, prefix);
+    }
+
     public static String getJobKeyForRdPrefix(String rd, String prefix) {
         return "FIB-" + rd + "-" + prefix;
     }
@@ -555,42 +624,35 @@ public class FibUtil {
         return "FIB-" + vpnId.toString() + "-" + dpnId.toString() ;
     }
 
-    public void updateUsedRdAndVpnToExtraRoute(WriteTransaction writeOperTxn, String tunnelIpRemoved, String primaryRd,
-            String prefix) {
-        Optional<VpnInstanceOpDataEntry> optVpnInstance = getVpnInstanceOpData(primaryRd);
+    public void updateUsedRdAndVpnToExtraRoute(TypedReadWriteTransaction<Configuration> confTx,
+            TypedReadWriteTransaction<Operational> operTx, String tunnelIpRemoved, String primaryRd, String prefix)
+            throws ExecutionException, InterruptedException {
+        Optional<VpnInstanceOpDataEntry> optVpnInstance = getVpnInstanceOpData(operTx, primaryRd);
         if (!optVpnInstance.isPresent()) {
             return;
         }
         VpnInstanceOpDataEntry vpnInstance = optVpnInstance.get();
         String vpnName = vpnInstance.getVpnInstanceName();
         long vpnId = vpnInstance.getVpnId();
-        List<String> usedRds = VpnExtraRouteHelper.getUsedRds(dataBroker, vpnId, prefix);
+        List<String> usedRds = VpnExtraRouteHelper.getUsedRds(confTx, vpnId, prefix);
         // To identify the rd to be removed, iterate through the allocated rds for the prefix and check
         // which rd is allocated for the particular OVS.
         for (String usedRd : usedRds) {
-            Optional<Routes> vpnExtraRoutes = VpnExtraRouteHelper
-                    .getVpnExtraroutes(dataBroker, vpnName, usedRd, prefix);
+            Optional<Routes> vpnExtraRoutes = VpnExtraRouteHelper.getVpnExtraroutes(operTx, vpnName, usedRd, prefix);
             if (vpnExtraRoutes.isPresent()) {
                 // Since all the nexthops under one OVS will be present under one rd, only 1 nexthop is read
                 // to identify the OVS
                 String nextHopRemoved = vpnExtraRoutes.get().getNexthopIpList().get(0);
-                Prefixes prefixToInterface = getPrefixToInterface(vpnId, getIpPrefix(nextHopRemoved));
+                Prefixes prefixToInterface = getPrefixToInterface(operTx, vpnId, getIpPrefix(nextHopRemoved));
                 if (prefixToInterface != null && tunnelIpRemoved
                         .equals(getEndpointIpAddressForDPN(prefixToInterface.getDpnId()))) {
-                    InstanceIdentifier<Adjacency> adjId = getAdjacencyIdentifier(
-                            prefixToInterface.getVpnInterfaceName(), prefix);
-                    Interface ifState = getInterfaceStateFromOperDS(prefixToInterface.getVpnInterfaceName());
-                    //Delete datastore only if extra route is deleted or VM interface is deleted/down
-                    if (!MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, adjId).isPresent()
-                            || ifState == null || ifState.getOperStatus() == OperStatus.Down) {
-                        writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL,
-                                getAdjacencyIdentifier(prefixToInterface.getVpnInterfaceName(), prefix));
-                        writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL,
-                                VpnExtraRouteHelper.getVpnToExtrarouteVrfIdIdentifier(vpnName, usedRd, prefix));
-                        writeOperTxn.delete(LogicalDatastoreType.CONFIGURATION,
-                                VpnExtraRouteHelper.getUsedRdsIdentifier(vpnId, prefix, nextHopRemoved));
-                        break;
-                    }
+                    LOG.info("updating data-stores for prefix {} with primaryRd {} for interface {} on vpn {} ",
+                            prefix, primaryRd, prefixToInterface.getVpnInterfaceName(), vpnName);
+                    operTx.delete(FibUtil.getAdjacencyIdentifierOp(prefixToInterface.getVpnInterfaceName(),
+                                    vpnName, prefix));
+                    operTx.delete(VpnExtraRouteHelper.getVpnToExtrarouteVrfIdIdentifier(vpnName, usedRd, prefix));
+                    confTx.delete(VpnExtraRouteHelper.getUsedRdsIdentifier(vpnId, prefix, nextHopRemoved));
+                    break;
                 }
             }
         }
@@ -605,7 +667,7 @@ public class FibUtil {
         if (tunnelInfo.isPresent()) {
             List<TunnelEndPoints> nexthopIpList = tunnelInfo.get().getTunnelEndPoints();
             if (nexthopIpList != null && !nexthopIpList.isEmpty()) {
-                nextHopIp = String.valueOf(nexthopIpList.get(0).getIpAddress().getValue());
+                nextHopIp = nexthopIpList.get(0).getIpAddress().stringValue();
             }
         }
         return nextHopIp;
@@ -614,7 +676,7 @@ public class FibUtil {
     public static String getIpPrefix(String prefix) {
         String[] prefixValues = prefix.split(FibConstants.PREFIX_SEPARATOR);
         if (prefixValues.length == 1) {
-            prefix = prefix + NwConstants.IPV4PREFIX;
+            return NWUtil.toIpPrefix(prefix);
         }
         return prefix;
     }
@@ -638,45 +700,39 @@ public class FibUtil {
         }
     }
 
-    public Subnetmap getSubnetMap(Uuid subnetId) {
-        InstanceIdentifier<Subnetmap> subnetmapId = InstanceIdentifier.builder(Subnetmaps.class)
-            .child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
-        return MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetmapId).orNull();
-    }
-
     public static String getGreLbGroupKey(List<String> availableDcGws) {
         Preconditions.checkNotNull(availableDcGws, "AvailableDcGws is null");
         return "gre-" + availableDcGws.stream().sorted().collect(joining(":"));
     }
 
     public static void updateLbGroupInfo(BigInteger dpnId, String destinationIp, String groupIdKey,
-            String groupId, WriteTransaction tx) {
+            String groupId, TypedWriteTransaction<Operational> tx) {
         InstanceIdentifier<DpnLbNexthops> id = getDpnLbNexthopsIdentifier(dpnId, destinationIp);
         DpnLbNexthops dpnToLbNextHop = buildDpnLbNextHops(dpnId, destinationIp, groupIdKey);
-        tx.merge(LogicalDatastoreType.OPERATIONAL, id, dpnToLbNextHop);
+        tx.merge(id, dpnToLbNextHop);
         InstanceIdentifier<Nexthops> nextHopsId = getNextHopsIdentifier(groupIdKey);
         Nexthops nextHopsToGroupId = buildNextHops(dpnId, groupIdKey, groupId);
-        tx.merge(LogicalDatastoreType.OPERATIONAL, nextHopsId, nextHopsToGroupId);
+        tx.merge(nextHopsId, nextHopsToGroupId);
     }
 
-    public static void removeDpnIdToNextHopInfo(String destinationIp, BigInteger dpnId, WriteTransaction tx) {
-        InstanceIdentifier<DpnLbNexthops> id = getDpnLbNexthopsIdentifier(dpnId, destinationIp);
-        tx.delete(LogicalDatastoreType.OPERATIONAL, id);
+    public static void removeDpnIdToNextHopInfo(String destinationIp, BigInteger dpnId,
+            TypedWriteTransaction<Operational> tx) {
+        tx.delete(getDpnLbNexthopsIdentifier(dpnId, destinationIp));
     }
 
     public static void removeOrUpdateNextHopInfo(BigInteger dpnId, String nextHopKey, String groupId,
-            Nexthops nexthops, WriteTransaction tx) {
+            Nexthops nexthops, TypedWriteTransaction<Operational> tx) {
         InstanceIdentifier<Nexthops> nextHopsId = getNextHopsIdentifier(nextHopKey);
-        List<String> targetDeviceIds = nexthops.getTargetDeviceId();
+        List<String> targetDeviceIds = new ArrayList<>(nullToEmpty(nexthops.getTargetDeviceId()));
         targetDeviceIds.remove(dpnId.toString());
         if (targetDeviceIds.isEmpty()) {
-            tx.delete(LogicalDatastoreType.OPERATIONAL, nextHopsId);
+            tx.delete(nextHopsId);
         } else {
-            Nexthops nextHopsToGroupId = new NexthopsBuilder().setKey(new NexthopsKey(nextHopKey))
+            Nexthops nextHopsToGroupId = new NexthopsBuilder().withKey(new NexthopsKey(nextHopKey))
                 .setNexthopKey(nextHopKey)
                 .setGroupId(groupId)
                 .setTargetDeviceId(targetDeviceIds).build();
-            tx.put(LogicalDatastoreType.OPERATIONAL, nextHopsId, nextHopsToGroupId);
+            tx.put(nextHopsId, nextHopsToGroupId);
         }
     }
 
@@ -693,7 +749,7 @@ public class FibUtil {
     }
 
     private static Nexthops buildNextHops(BigInteger dpnId, String groupIdKey, String groupId) {
-        return new NexthopsBuilder().setKey(new NexthopsKey(groupIdKey))
+        return new NexthopsBuilder().withKey(new NexthopsKey(groupIdKey))
                 .setNexthopKey(groupIdKey)
                 .setGroupId(groupId)
                 .setTargetDeviceId(Collections.singletonList(dpnId.toString())).build();
@@ -701,7 +757,7 @@ public class FibUtil {
 
     private static DpnLbNexthops buildDpnLbNextHops(BigInteger dpnId, String destinationIp,
             String groupIdKey) {
-        return new DpnLbNexthopsBuilder().setKey(new DpnLbNexthopsKey(destinationIp, dpnId))
+        return new DpnLbNexthopsBuilder().withKey(new DpnLbNexthopsKey(destinationIp, dpnId))
                 .setDstDeviceId(destinationIp).setSrcDpId(dpnId)
                 .setNexthopKey(Collections.singletonList(groupIdKey)).build();
     }
@@ -719,33 +775,15 @@ public class FibUtil {
         return MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
     }
 
-    boolean isVxlanNetworkAndInternalRouterVpn(Uuid subnetId, String
-            vpnInstanceName, String rd) {
-        if (rd.equals(vpnInstanceName)) {
-            Subnetmap subnetmap = getSubnetMap(subnetId);
-            if (subnetmap != null) {
-                return subnetmap.getNetworkType() == NetworkAttributes.NetworkType.VXLAN;
-            }
+    static boolean isVxlanNetwork(NetworkType networkType) {
+        if (networkType != null) {
+            return networkType == NetworkAttributes.NetworkType.VXLAN;
         }
         return false;
     }
 
-    java.util.Optional<Long> getVniForVxlanNetwork(Uuid subnetId) {
-        Subnetmap subnetmap = getSubnetMap(subnetId);
-        if (subnetmap != null && subnetmap.getNetworkType() == NetworkAttributes.NetworkType.VXLAN) {
-            return java.util.Optional.of(subnetmap.getSegmentationId());
-        }
-        return java.util.Optional.empty();
-    }
-
-    boolean enforceVxlanDatapathSemanticsforInternalRouterVpn(Uuid subnetId, long vpnId, String rd) {
-        return elanManager.isOpenStackVniSemanticsEnforced()
-                && isVxlanNetworkAndInternalRouterVpn(subnetId, getVpnNameFromId(vpnId), rd);
-    }
-
-    boolean enforceVxlanDatapathSemanticsforInternalRouterVpn(Uuid subnetId, String vpnName, String rd) {
-        return elanManager.isOpenStackVniSemanticsEnforced()
-                && isVxlanNetworkAndInternalRouterVpn(subnetId, vpnName, rd);
+    static boolean isBgpVpn(String vpnName, String rd) {
+        return vpnName != null && !vpnName.equals(rd);
     }
 
     static NodeRef buildNodeRef(BigInteger dpId) {
@@ -796,7 +834,7 @@ public class FibUtil {
 
     static Node buildDpnNode(BigInteger dpnId) {
         return new NodeBuilder().setId(new NodeId("openflow:" + dpnId))
-                .setKey(new NodeKey(new NodeId("openflow:" + dpnId))).build();
+                .withKey(new NodeKey(new NodeId("openflow:" + dpnId))).build();
     }
 
     public static String getBroadcastAddressFromCidr(String cidr) {
@@ -811,4 +849,62 @@ public class FibUtil {
         int broadcast = network | ~netmask;
         return InetAddresses.toAddrString(InetAddresses.fromInteger(broadcast));
     }
+
+    public static boolean lockCluster(LockManagerService lockManager, String lockName, long tryLockPeriod) {
+        TryLockInput input = new TryLockInputBuilder().setLockName(lockName).setTime(tryLockPeriod)
+                .setTimeUnit(TimeUnits.Milliseconds).build();
+        Future<RpcResult<TryLockOutput>> result = lockManager.tryLock(input);
+        boolean lockAcquired;
+        try {
+            if (result != null && result.get().isSuccessful()) {
+                LOG.debug("lockCluster: Acquired lock for {}", lockName);
+                lockAcquired = true;
+            } else {
+                LOG.error("lockCluster: Unable to getLock for {}", lockName);
+                lockAcquired = false;
+            }
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.error("lockCluster: Exception while trying to getLock for {}", lockName, e);
+            lockAcquired = false;
+        }
+
+        return lockAcquired;
+    }
+
+    public static void unlockCluster(LockManagerService lockManager, String lockName) {
+        UnlockInput input = new UnlockInputBuilder().setLockName(lockName).build();
+        Future<RpcResult<UnlockOutput>> result = lockManager.unlock(input);
+        try {
+            if (result != null && result.get().isSuccessful()) {
+                LOG.debug("unlockCluster: Unlocked {}", lockName);
+            } else {
+                LOG.error("unlockCluster: Unable to release lock for {}", lockName);
+            }
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.error("unlockCluster: Unable to unlock {}", lockName, e);
+        }
+    }
+
+    public boolean isInterfacePresentInDpn(String vpnName, BigInteger dpnId) {
+        InstanceIdentifier<VpnToDpnList> vpnToDpnListId = InstanceIdentifier.builder(VpnInstanceOpData.class)
+                .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(vpnName))
+                .child(VpnToDpnList.class, new VpnToDpnListKey(dpnId)).build();
+        try {
+            VpnToDpnList vpnToDpnList = SingleTransactionDataBroker.syncRead(dataBroker,
+                    LogicalDatastoreType.OPERATIONAL, vpnToDpnListId);
+            if (!(vpnToDpnList == null) && !(vpnToDpnList.getVpnInterfaces() == null)
+                    && !vpnToDpnList.getVpnInterfaces().isEmpty()) {
+                return true;
+            }
+        } catch (ReadFailedException e) {
+            LOG.warn("Failed to read interfaces with error {}", e.getMessage());
+        }
+        return false;
+    }
+
+    // TODO Replace this with mdsal's DataObjectUtils.nullToEmpty when upgrading to mdsal 3
+    @Nonnull
+    public static <T> List<T> nullToEmpty(final @Nullable List<T> input) {
+        return input != null ? input : emptyList();
+    }
 }