Fix for VM deletion issue 34/73634/15
authoreswanit <swati.udhavrao.niture@ericsson.com>
Wed, 11 Jul 2018 06:14:47 +0000 (11:44 +0530)
committerSam Hague <shague@redhat.com>
Sat, 14 Jul 2018 20:14:47 +0000 (20:14 +0000)
Route path entry is getting removed from
FIB table after VM deletion->

If multiple VMs are present in the same CSS and
an extra-route is configured with nexthop being
both such VMs, then if one of the VM is removed,
the entire route-path representing that CSS nexthop
is getting removed from FIB.

Consequence -> If further deletion of VM takes place,
then it won't update the flows and groups.

Fix -> This is fixed by checking if extra-route is present
behind at least one VM, then do not remove or update fib entry
for route-path representing that CSS nexthop, just update
vpntoextraroute and prefixtointerface DS.

Change-Id: I885fd307db4b571e4fa11a1626e3b2a95bf25c89
Signed-off-by: eswanit <swati.udhavrao.niture@ericsson.com>
vpnmanager/api/src/main/java/org/opendaylight/netvirt/vpnmanager/api/IVpnManager.java
vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnInterfaceManager.java
vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnManagerImpl.java
vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnRpcServiceImpl.java
vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnUtil.java
vpnmanager/impl/src/test/java/org/opendaylight/netvirt/vpnmanager/intervpnlink/InterVpnLinkLocatorTest.java

index ecf55501dd9a369b5d109c95460e5dd409e3c42f..83413493c66342a72153e60f25374d434539a30b 100644 (file)
@@ -16,6 +16,7 @@ import java.util.Set;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 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;
@@ -41,17 +42,19 @@ public interface IVpnManager {
 
     @Deprecated
     void delExtraRoute(String vpnName, String destination, String nextHop, String rd, String routerID,
-            String intfName, WriteTransaction writeConfigTxn);
+            String intfName, WriteTransaction writeConfigTxn, WriteTransaction writeOperTx);
 
     void delExtraRoute(String vpnName, String destination, String nextHop, String rd, String routerID,
-        String intfName, TypedWriteTransaction<Configuration> confTx);
+        String intfName, TypedWriteTransaction<Configuration> confTx, TypedWriteTransaction<Operational> operTx);
 
     @Deprecated
-    void removePrefixFromBGP(String primaryRd, String rd, String vpnName, String prefix, String nextHop,
-            String tunnelIp, BigInteger dpnId, WriteTransaction writeConfigTxn);
+    void removePrefixFromBGP(String vpnName, String primaryRd, String extraRouteRd, String vpnInterfaceName,
+        String prefix, String nextHop, String nextHopTunnelIp, BigInteger dpnId, WriteTransaction writeConfigTxn,
+        WriteTransaction writeOperTx);
 
-    void removePrefixFromBGP(String primaryRd, String rd, String vpnName, String prefix, String nextHop,
-        String tunnelIp, BigInteger dpnId, TypedWriteTransaction<Configuration> confTx);
+    void removePrefixFromBGP(String vpnName, String primaryRd, String extraRouteRd, String vpnInterfaceName,
+        String prefix, String nextHop, String nextHopTunnelIp, BigInteger dpnId,
+        TypedWriteTransaction<Configuration> confTx, TypedWriteTransaction<Operational> operTx);
 
     boolean isVPNConfigured();
 
index a55cd950f510d92d735c9ab1cc089f0c58e95bdc..a017a3599adb7e6c150a316d0072b5f46ad9fdf7 100755 (executable)
@@ -636,7 +636,8 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
     // TODO Clean up the exception handling
     @SuppressWarnings("checkstyle:IllegalCatch")
     private void withdrawAdjacenciesForVpnFromBgp(final InstanceIdentifier<VpnInterfaceOpDataEntry> identifier,
-                        String vpnName, String interfaceName, WriteTransaction writeConfigTxn) {
+                        String vpnName, String interfaceName, WriteTransaction writeConfigTxn,
+                        WriteTransaction writeOperTx) {
         //Read NextHops
         InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
         String rd = vpnUtil.getVpnRd(interfaceName);
@@ -683,7 +684,8 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                             String allocatedRd = nextHop.getVrfId();
                             for (String nh : nextHop.getNextHopIpList()) {
                                 deleteExtraRouteFromCurrentAndImportingVpns(
-                                    vpnName, nextHop.getIpAddress(), nh, allocatedRd, interfaceName, writeConfigTxn);
+                                    vpnName, nextHop.getIpAddress(), nh, allocatedRd, interfaceName, writeConfigTxn,
+                                    writeOperTx);
                             }
                         }
                     } catch (Exception e) {
@@ -1321,7 +1323,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
         } else {
             // Interface is retained in the DPN, but its Link Down.
             // Only withdraw the prefixes for this interface from BGP
-            withdrawAdjacenciesForVpnFromBgp(identifier, vpnName, interfaceName, writeConfigTxn);
+            withdrawAdjacenciesForVpnFromBgp(identifier, vpnName, interfaceName, writeConfigTxn, writeOperTxn);
         }
     }
 
@@ -1366,10 +1368,10 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                                 //this is an internal vpn - the rd is assigned to the vpn instance name;
                                 //remove from FIB directly
                                 nhList.forEach(removeAdjacencyFromInternalVpn(nextHop, vpnName,
-                                        interfaceName, dpnId, writeConfigTxn));
+                                        interfaceName, dpnId, writeConfigTxn, writeOperTxn));
                             } else {
                                 removeAdjacencyFromBgpvpn(nextHop, nhList, vpnName, primaryRd, dpnId, rd,
-                                        interfaceName, writeConfigTxn);
+                                        interfaceName, writeConfigTxn, writeOperTxn);
                             }
                         } else {
                             LOG.error("removeAdjacenciesFromVpn: nextHop empty for ip {} rd {} adjacencyType {}"
@@ -1407,12 +1409,26 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
         }
     }
 
-    private Consumer<String> removeAdjacencyFromInternalVpn(Adjacency nextHop, String vpnName,
-                                                                   String interfaceName, BigInteger dpnId,
-                                                                   WriteTransaction writeConfigTxn) {
+    private Consumer<String> removeAdjacencyFromInternalVpn(Adjacency nextHop, String vpnName, String interfaceName,
+                                                            BigInteger dpnId, WriteTransaction writeConfigTxn,
+                                                            WriteTransaction writeOperTx) {
         return (nh) -> {
-            fibManager.removeOrUpdateFibEntry(vpnName, nextHop.getIpAddress(), nh,
-                    writeConfigTxn);
+            String primaryRd = vpnUtil.getVpnRd(vpnName);
+            String prefix = nextHop.getIpAddress();
+            String vpnNamePrefixKey = VpnUtil.getVpnNamePrefixKey(vpnName, prefix);
+            LOG.info("remove adjacencies for nexthop {} vpnName {} interfaceName {} dpnId {}",
+                    nextHop, vpnName, interfaceName, dpnId);
+            synchronized (vpnNamePrefixKey.intern()) {
+                if (vpnUtil.removeOrUpdateDSForExtraRoute(vpnName, primaryRd, dpnId.toString(), interfaceName,
+                        prefix, nextHop.getNextHopIpList().get(0), nh, writeOperTx)) {
+                    //If extra-route is present behind at least one VM, then do not remove or update
+                    //fib entry for route-path representing that CSS nexthop, just update vpntoextraroute and
+                    //prefixtointerface DS
+                    return;
+                }
+                fibManager.removeOrUpdateFibEntry(vpnName, nextHop.getIpAddress(), nh,
+                        writeConfigTxn);
+            }
             LOG.info("removeAdjacenciesFromVpn: removed/updated FIB with rd {} prefix {}"
                             + " nexthop {} for interface {} on dpn {} for internal vpn {}",
                     vpnName, nextHop.getIpAddress(), nh, interfaceName, dpnId, vpnName);
@@ -1421,13 +1437,13 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
 
     private void removeAdjacencyFromBgpvpn(Adjacency nextHop, List<String> nhList, String vpnName, String primaryRd,
                                            BigInteger dpnId, String rd, String interfaceName,
-                                           WriteTransaction writeConfigTxn) {
+                                           WriteTransaction writeConfigTxn, WriteTransaction writeOperTx) {
         List<VpnInstanceOpDataEntry> vpnsToImportRoute =
                 vpnUtil.getVpnsImportingMyRoute(vpnName);
         nhList.forEach((nh) -> {
             //IRT: remove routes from other vpns importing it
-            vpnManager.removePrefixFromBGP(primaryRd, rd, vpnName, nextHop.getIpAddress(),
-                    nextHop.getNextHopIpList().get(0), nh, dpnId, writeConfigTxn);
+            vpnManager.removePrefixFromBGP(vpnName, primaryRd, rd, interfaceName, nextHop.getIpAddress(),
+                    nextHop.getNextHopIpList().get(0), nh, dpnId, writeConfigTxn, writeOperTx);
             for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
                 String vpnRd = vpn.getVrfId();
                 if (vpnRd != null) {
@@ -1849,7 +1865,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                                     for (String nh : adj.getNextHopIpList()) {
                                         deleteExtraRouteFromCurrentAndImportingVpns(
                                                 currVpnIntf.getVpnInstanceName(), adj.getIpAddress(), nh, rd,
-                                                currVpnIntf.getName(), writeConfigTxn);
+                                                currVpnIntf.getName(), writeConfigTxn, writeOperTxn);
                                     }
                                 } else if (adj.isPhysNetworkFunc()) {
                                     LOG.info("delAdjFromVpnInterface: deleting PNF adjacency prefix {} subnet {}",
@@ -1876,13 +1892,14 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
     }
 
     private void deleteExtraRouteFromCurrentAndImportingVpns(String vpnName, String destination, String nextHop,
-        String rd, String intfName, WriteTransaction writeConfigTxn) {
-        vpnManager.delExtraRoute(vpnName, destination, nextHop, rd, vpnName, intfName, writeConfigTxn);
+        String rd, String intfName, WriteTransaction writeConfigTxn, WriteTransaction writeOperTx) {
+        vpnManager.delExtraRoute(vpnName, destination, nextHop, rd, vpnName, intfName, writeConfigTxn, writeOperTx);
         List<VpnInstanceOpDataEntry> vpnsToImportRoute = vpnUtil.getVpnsImportingMyRoute(vpnName);
         for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
             String vpnRd = vpn.getVrfId();
             if (vpnRd != null) {
-                vpnManager.delExtraRoute(vpnName, destination, nextHop, vpnRd, vpnName, intfName, writeConfigTxn);
+                vpnManager.delExtraRoute(vpnName, destination, nextHop, vpnRd, vpnName, intfName, writeConfigTxn,
+                        writeOperTx);
             }
         }
     }
index 61bee964cf633958e2c6b1b5743064c1bc50317c..43e55e2897cd5adc9bca3d051545c114e46d5b9b 100644 (file)
@@ -30,6 +30,7 @@ import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
 import org.opendaylight.genius.datastoreutils.listeners.DataTreeEventCallbackRegistrar;
 import org.opendaylight.genius.infra.Datastore.Configuration;
+import org.opendaylight.genius.infra.Datastore.Operational;
 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
 import org.opendaylight.genius.infra.TransactionAdapter;
@@ -38,7 +39,6 @@ import org.opendaylight.genius.infra.TypedReadWriteTransaction;
 import org.opendaylight.genius.infra.TypedWriteTransaction;
 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
 import org.opendaylight.genius.mdsalutil.FlowEntity;
-import org.opendaylight.genius.mdsalutil.MDSALUtil;
 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
 import org.opendaylight.genius.mdsalutil.NwConstants;
 import org.opendaylight.genius.mdsalutil.UpgradeState;
@@ -77,7 +77,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.SubnetsAssociatedToRouteTargets;
 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.prefix.to._interface.vpn.ids.Prefixes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnets.associated.to.route.targets.RouteTarget;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnets.associated.to.route.targets.RouteTargetKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnets.associated.to.route.targets.route.target.AssociatedSubnet;
@@ -273,18 +272,24 @@ public class VpnManagerImpl implements IVpnManager {
 
     @Override
     public void delExtraRoute(String vpnName, String destination, String nextHop, String rd, String routerID,
-        String intfName, TypedWriteTransaction<Configuration> confTx) {
+        String intfName, TypedWriteTransaction<Configuration> confTx, TypedWriteTransaction<Operational> operTx) {
         delExtraRoute(vpnName, destination, nextHop, rd, routerID, intfName,
-            TransactionAdapter.toWriteTransaction(confTx));
+            TransactionAdapter.toWriteTransaction(confTx), TransactionAdapter.toWriteTransaction(operTx));
     }
 
     @Override
     public void delExtraRoute(String vpnName, String destination, String nextHop, String rd, String routerID,
-            String intfName, WriteTransaction writeConfigTxn) {
+            String intfName, WriteTransaction writeConfigTxn, WriteTransaction writeOperTx) {
         if (writeConfigTxn == null) {
-            ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx ->
-                delExtraRoute(vpnName, destination, nextHop, rd, routerID, intfName, tx)),
-                    LOG, "Error deleting extra route");
+            ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+                delExtraRoute(vpnName, destination, nextHop, rd, routerID, intfName, tx, writeOperTx);
+            }), LOG, "Error deleting extra route");
+            return;
+        }
+        if (writeOperTx == null) {
+            ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+                delExtraRoute(vpnName, destination, nextHop, rd, routerID, intfName, writeConfigTxn, tx);
+            }), LOG, "Error deleting extra route");
             return;
         }
         BigInteger dpnId = null;
@@ -301,7 +306,8 @@ public class VpnManagerImpl implements IVpnManager {
         }
         if (rd != null) {
             String primaryRd = vpnUtil.getVpnRd(vpnName);
-            removePrefixFromBGP(primaryRd, rd, vpnName, destination, nextHop, tunnelIp, dpnId, writeConfigTxn);
+            removePrefixFromBGP(vpnName, primaryRd, rd, intfName, destination, nextHop, tunnelIp, dpnId,
+                    writeConfigTxn, writeOperTx);
             LOG.info("delExtraRoute: Removed extra route {} from interface {} for rd {}", destination, intfName, rd);
         } else {
             // add FIB route directly
@@ -312,61 +318,37 @@ public class VpnManagerImpl implements IVpnManager {
     }
 
     @Override
-    public void removePrefixFromBGP(String primaryRd, String rd, String vpnName, String prefix, String nextHop,
-        String tunnelIp, BigInteger dpnId, TypedWriteTransaction<Configuration> confTx) {
-        removePrefixFromBGP(primaryRd, rd, vpnName, prefix, nextHop, tunnelIp, dpnId,
-            TransactionAdapter.toWriteTransaction(confTx));
+    public void removePrefixFromBGP(String vpnName, String primaryRd, String extraRouteRd, String vpnInterfaceName,
+                                    String prefix, String nextHop, String nextHopTunnelIp, BigInteger dpnId,
+                                    TypedWriteTransaction<Configuration> confTx,
+                                    TypedWriteTransaction<Operational> operTx) {
+        removePrefixFromBGP(vpnName, primaryRd, extraRouteRd, vpnInterfaceName, prefix, nextHop, nextHopTunnelIp,
+                dpnId, TransactionAdapter.toWriteTransaction(confTx), TransactionAdapter.toWriteTransaction(operTx));
     }
 
     // TODO Clean up the exception handling
     @Override
     @SuppressWarnings("checkstyle:IllegalCatch")
-    public void removePrefixFromBGP(String primaryRd, String rd, String vpnName, String prefix, String nextHop,
-                                     String tunnelIp, BigInteger dpnId, WriteTransaction writeConfigTxn) {
+    public void removePrefixFromBGP(String vpnName, String primaryRd, String extraRouteRd, String vpnInterfaceName,
+        String prefix, String nextHop, String nextHopTunnelIp, BigInteger dpnId, WriteTransaction writeConfigTxn,
+        WriteTransaction writeOperTx) {
         try {
-            LOG.info("removePrefixFromBGP: VPN WITHDRAW: Removing Fib Entry rd {} prefix {} nexthop {}", rd, prefix,
-                    nextHop);
             String vpnNamePrefixKey = VpnUtil.getVpnNamePrefixKey(vpnName, prefix);
             synchronized (vpnNamePrefixKey.intern()) {
-                Optional<Routes> optVpnExtraRoutes = VpnExtraRouteHelper
-                        .getVpnExtraroutes(dataBroker, vpnName, rd, prefix);
-                if (optVpnExtraRoutes.isPresent()) {
-                    List<String> nhList = optVpnExtraRoutes.get().getNexthopIpList();
-                    if (nhList != null && nhList.size() > 1) {
-                        // If nhList is more than 1, just update vpntoextraroute and prefixtointerface DS
-                        // For other cases, remove the corresponding tep ip from fibentry and withdraw prefix
-                        nhList.remove(nextHop);
-                        vpnUtil.syncWrite(LogicalDatastoreType.OPERATIONAL,
-                                VpnExtraRouteHelper.getVpnToExtrarouteVrfIdIdentifier(vpnName, rd, prefix),
-                                VpnUtil.getVpnToExtraroute(prefix, nhList));
-                        MDSALUtil.syncDelete(dataBroker,
-                                LogicalDatastoreType.CONFIGURATION, VpnExtraRouteHelper.getUsedRdsIdentifier(
-                                vpnUtil.getVpnId(vpnName), prefix, nextHop));
-                        LOG.debug("removePrefixFromBGP: Removed vpn-to-extraroute with rd {} prefix {} nexthop {}",
-                                rd, prefix, nextHop);
-                        fibManager.refreshVrfEntry(primaryRd, prefix);
-                        long vpnId = vpnUtil.getVpnId(vpnName);
-                        Optional<Prefixes> prefixToInterface = vpnUtil.getPrefixToInterface(vpnId, nextHop);
-                        if (prefixToInterface.isPresent()) {
-                            writeConfigTxn.delete(LogicalDatastoreType.OPERATIONAL,
-                                    VpnUtil.getAdjacencyIdentifier(prefixToInterface.get().getVpnInterfaceName(),
-                                            prefix));
-                        }
-                        LOG.info("VPN WITHDRAW: removePrefixFromBGP: Removed Fib Entry rd {} prefix {} nexthop {}",
-                                rd, prefix, tunnelIp);
-                        return;
-                    }
+                if (vpnUtil.removeOrUpdateDSForExtraRoute(vpnName, primaryRd, extraRouteRd, vpnInterfaceName, prefix,
+                        nextHop, nextHopTunnelIp, writeOperTx)) {
+                    return;
                 }
-                fibManager.removeOrUpdateFibEntry(primaryRd, prefix, tunnelIp, writeConfigTxn);
-                if (VpnUtil.isEligibleForBgp(primaryRd, vpnName, dpnId, null /*networkName*/)) {
+                fibManager.removeOrUpdateFibEntry(primaryRd, prefix, nextHopTunnelIp, writeConfigTxn);
+                if (VpnUtil.isEligibleForBgp(extraRouteRd, vpnName, dpnId, null /*networkName*/)) {
                     // TODO: Might be needed to include nextHop here
-                    bgpManager.withdrawPrefix(rd, prefix);
+                    bgpManager.withdrawPrefix(extraRouteRd, prefix);
                 }
             }
-            LOG.info("removePrefixFromBGP: VPN WITHDRAW: Removed Fib Entry rd {} prefix {} nexthop {}", rd, prefix,
-                    nextHop);
+            LOG.info("removePrefixFromBGP: VPN WITHDRAW: Removed Fib Entry rd {} prefix {} nexthop {}", extraRouteRd,
+                    prefix, nextHop);
         } catch (RuntimeException e) {
-            LOG.error("removePrefixFromBGP: Delete prefix {} rd {} nextHop {} failed", prefix, rd, nextHop);
+            LOG.error("removePrefixFromBGP: Delete prefix {} rd {} nextHop {} failed", prefix, extraRouteRd, nextHop);
         }
     }
 
index b4ccf01c727747d98793369c9d92d9d01c1672af..f645acbf8075af8c06327aece46a30cf71979c61 100644 (file)
@@ -244,7 +244,8 @@ public class VpnRpcServiceImpl implements VpnRpcService {
             bgpManager.withdrawPrefix(vpnRd, destination);
         } else {
             vpnManager.delExtraRoute(vpnInstanceName, destination,
-                    nexthop, vpnRd, null /* routerId */, null /* intfName */, (WriteTransaction) null);
+                    nexthop, vpnRd, null /* routerId */, null /* intfName */, (WriteTransaction) null,
+                    (WriteTransaction) null);
         }
         result.set(RpcResultBuilder.success(new RemoveStaticRouteOutputBuilder().build()).build());
 
index ba49a0b9fae51cadf6068fbf5f89b2cc14bec2a7..debf06b3bff423eca02119cc79094a6e751e4425 100644 (file)
@@ -46,6 +46,7 @@ import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFaile
 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
 import org.opendaylight.genius.infra.Datastore;
 import org.opendaylight.genius.infra.Datastore.Configuration;
+import org.opendaylight.genius.infra.Datastore.Operational;
 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
 import org.opendaylight.genius.infra.TypedReadTransaction;
@@ -73,6 +74,7 @@ import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
 import org.opendaylight.netvirt.elanmanager.api.ElanHelper;
 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
+import org.opendaylight.netvirt.fibmanager.api.IFibManager;
 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
 import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice;
 import org.opendaylight.netvirt.neutronvpn.interfaces.INeutronVpnManager;
@@ -247,6 +249,7 @@ public final class VpnUtil {
 
     private final DataBroker dataBroker;
     private final IdManagerService idManager;
+    private final IFibManager fibManager;
     private final IBgpManager bgpManager;
     private final LockManagerService lockManager;
     private final INeutronVpnManager neutronVpnService;
@@ -280,12 +283,13 @@ public final class VpnUtil {
         }
     }
 
-    public VpnUtil(DataBroker dataBroker, IdManagerService idManager, IBgpManager bgpManager,
-                   LockManagerService lockManager, INeutronVpnManager neutronVpnService,
-                   IMdsalApiManager mdsalManager, JobCoordinator jobCoordinator,
-                   IInterfaceManager interfaceManager, OdlInterfaceRpcService ifmRpcService) {
+    public VpnUtil(DataBroker dataBroker, IdManagerService idManager, IFibManager fibManager,
+                   IBgpManager bgpManager, LockManagerService lockManager, INeutronVpnManager neutronVpnService,
+                   IMdsalApiManager mdsalManager, JobCoordinator jobCoordinator, IInterfaceManager interfaceManager,
+                   OdlInterfaceRpcService ifmRpcService) {
         this.dataBroker = dataBroker;
         this.idManager = idManager;
+        this.fibManager = fibManager;
         this.bgpManager = bgpManager;
         this.lockManager = lockManager;
         this.neutronVpnService = neutronVpnService;
@@ -643,6 +647,39 @@ public final class VpnUtil {
         });
     }
 
+    public boolean removeOrUpdateDSForExtraRoute(String vpnName, String primaryRd, String extraRouteRd,
+                                                 String vpnInterfaceName, String prefix, String nextHop,
+                                                 String nextHopTunnelIp, WriteTransaction operTx) {
+        LOG.info("removeOrUpdateDSForExtraRoute: VPN WITHDRAW: Removing Fib Entry rd {} prefix {} nexthop {}",
+                extraRouteRd, prefix, nextHop);
+        boolean areNextHopsClearedForRd = false;
+        Optional<Routes> optVpnExtraRoutes = VpnExtraRouteHelper
+                .getVpnExtraroutes(dataBroker, vpnName, extraRouteRd, prefix);
+        if (optVpnExtraRoutes.isPresent()) {
+            List<String> nhList = optVpnExtraRoutes.get().getNexthopIpList();
+            if (nhList != null && nhList.size() > 1) {
+                // If nhList is more than 1, just update vpntoextraroute and prefixtointerface DS
+                // For other cases, remove the corresponding tep ip from fibentry and withdraw prefix
+                nhList.remove(nextHop);
+                syncWrite(LogicalDatastoreType.OPERATIONAL,
+                        VpnExtraRouteHelper.getVpnToExtrarouteVrfIdIdentifier(vpnName, extraRouteRd, prefix),
+                        VpnUtil.getVpnToExtraroute(prefix, nhList));
+                MDSALUtil.syncDelete(dataBroker,
+                        LogicalDatastoreType.CONFIGURATION, VpnExtraRouteHelper.getUsedRdsIdentifier(getVpnId(vpnName),
+                                prefix, nextHop));
+                LOG.debug("removeOrUpdateDSForExtraRoute: Removed vpn-to-extraroute with rd {} prefix {} nexthop {}",
+                        extraRouteRd, prefix, nextHop);
+                fibManager.refreshVrfEntry(primaryRd, prefix);
+                operTx.delete(LogicalDatastoreType.OPERATIONAL, VpnUtil
+                        .getVpnInterfaceOpDataEntryAdjacencyIdentifier(vpnInterfaceName, vpnName, prefix));
+                LOG.info("VPN WITHDRAW: removeOrUpdateDSForExtraRoute: Removed Fib Entry rd {} prefix {} nexthop {}",
+                        extraRouteRd, prefix, nextHopTunnelIp);
+                areNextHopsClearedForRd = true;
+            }
+        }
+        return areNextHopsClearedForRd;
+    }
+
     static org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance
         getVpnInstanceToVpnId(String vpnName, long vpnId, String rd) {
         return new VpnInstanceBuilder().setVpnId(vpnId).setVpnInstanceName(vpnName).setVrfId(rd).build();
@@ -815,14 +852,14 @@ public final class VpnUtil {
     }
 
     static void removePrefixToInterfaceForVpnId(long vpnId,
-                                                       @Nonnull TypedWriteTransaction<Datastore.Operational> operTx) {
+                                                       @Nonnull TypedWriteTransaction<Operational> operTx) {
         // Clean up PrefixToInterface Operational DS
         operTx.delete(InstanceIdentifier.builder(
                     PrefixToInterface.class).child(VpnIds.class, new VpnIdsKey(vpnId)).build());
     }
 
     static void removeVpnExtraRouteForVpn(String vpnName,
-                                                    @Nonnull TypedWriteTransaction<Datastore.Operational> operTx) {
+                                                    @Nonnull TypedWriteTransaction<Operational> operTx) {
         // Clean up VPNExtraRoutes Operational DS
         operTx.delete(InstanceIdentifier.builder(VpnToExtraroutes.class).child(Vpn.class, new VpnKey(vpnName)).build());
     }
@@ -830,7 +867,7 @@ public final class VpnUtil {
     // TODO Clean up the exception handling
     @SuppressWarnings("checkstyle:IllegalCatch")
     static void removeVpnOpInstance(String vpnName,
-                                                    @Nonnull TypedWriteTransaction<Datastore.Operational> operTx) {
+                                                    @Nonnull TypedWriteTransaction<Operational> operTx) {
         // Clean up VPNInstanceOpDataEntry
         operTx.delete(getVpnInstanceOpDataIdentifier(vpnName));
     }
@@ -846,15 +883,14 @@ public final class VpnUtil {
     }
 
     static void removeL3nexthopForVpnId(long vpnId,
-                                               @Nonnull TypedWriteTransaction<Datastore.Operational> operTx) {
+                                               @Nonnull TypedWriteTransaction<Operational> operTx) {
         // Clean up L3NextHop Operational DS
         operTx.delete(InstanceIdentifier.builder(L3nexthop.class).child(
                                     VpnNexthops.class, new VpnNexthopsKey(vpnId)).build());
     }
 
-    void scheduleVpnInterfaceForRemoval(String interfaceName, BigInteger dpnId,
-                                                      String vpnInstanceName,
-                                                      TypedWriteTransaction<Datastore.Operational> writeOperTxn) {
+    void scheduleVpnInterfaceForRemoval(String interfaceName, BigInteger dpnId, String vpnInstanceName,
+                                        TypedWriteTransaction<Operational> writeOperTxn) {
         InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId =
                 getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnInstanceName);
         VpnInterfaceOpDataEntry interfaceToUpdate =
@@ -869,7 +905,7 @@ public final class VpnUtil {
     }
 
     void createLearntVpnVipToPort(String vpnName, String fixedIp, String
-            portName, String macAddress, TypedWriteTransaction<Datastore.Operational> writeOperTxn) {
+            portName, String macAddress, TypedWriteTransaction<Operational> writeOperTxn) {
         synchronized ((vpnName + fixedIp).intern()) {
             InstanceIdentifier<LearntVpnVipToPort> id = buildLearntVpnVipToPortIdentifier(vpnName, fixedIp);
             LearntVpnVipToPortBuilder builder =
@@ -894,7 +930,7 @@ public final class VpnUtil {
     }
 
     void removeLearntVpnVipToPort(String vpnName, String fixedIp,
-                                                   TypedWriteTransaction<Datastore.Operational> writeOperTxn) {
+                                                   TypedWriteTransaction<Operational> writeOperTxn) {
         synchronized ((vpnName + fixedIp).intern()) {
             InstanceIdentifier<LearntVpnVipToPort> id = buildLearntVpnVipToPortIdentifier(vpnName, fixedIp);
             if (writeOperTxn != null) {
@@ -923,7 +959,7 @@ public final class VpnUtil {
 
     public void createLearntVpnVipToPortEvent(String vpnName, String srcIp, String destIP, String portName,
                                               String macAddress, LearntVpnVipToPortEventAction action,
-                                              TypedWriteTransaction<Datastore.Operational> writeOperTxn) {
+                                              TypedWriteTransaction<Operational> writeOperTxn) {
         String eventId = MicroTimestamp.INSTANCE.get();
 
         InstanceIdentifier<LearntVpnVipToPortEvent> id = buildLearntVpnVipToPortEventIdentifier(eventId);
@@ -946,7 +982,7 @@ public final class VpnUtil {
         return id;
     }
 
-    void removeLearntVpnVipToPortEvent(String eventId, TypedWriteTransaction<Datastore.Operational> writeOperTxn) {
+    void removeLearntVpnVipToPortEvent(String eventId, TypedWriteTransaction<Operational> writeOperTxn) {
         InstanceIdentifier<LearntVpnVipToPortEvent> id = buildLearntVpnVipToPortEventIdentifier(eventId);
         if (writeOperTxn != null) {
             writeOperTxn.delete(id);
@@ -1389,6 +1425,13 @@ public final class VpnUtil {
                 .augmentation(Adjacencies.class).child(Adjacency.class, new AdjacencyKey(ipAddress)).build();
     }
 
+    static InstanceIdentifier<Adjacency> getVpnInterfaceOpDataEntryAdjacencyIdentifier(String intfName, String vpnName,
+                String ipAddress) {
+        return InstanceIdentifier.builder(VpnInterfaceOpData.class)
+                .child(VpnInterfaceOpDataEntry.class, new VpnInterfaceOpDataEntryKey(intfName, vpnName))
+                .augmentation(AdjacenciesOp.class).child(Adjacency.class, new AdjacencyKey(ipAddress)).build();
+    }
+
     public static List<String> getIpsListFromExternalIps(List<ExternalIps> externalIps) {
         if (externalIps == null) {
             return Collections.emptyList();
index 96500752e9e316a3b765a2b2d3099aac24f71e46..e5abda8dd2a5c8fa1a4c49c0afcf54cc4919fc4e 100644 (file)
@@ -29,6 +29,7 @@ import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
+import org.opendaylight.netvirt.fibmanager.api.IFibManager;
 import org.opendaylight.netvirt.neutronvpn.interfaces.INeutronVpnManager;
 import org.opendaylight.netvirt.vpnmanager.VpnOperDsUtils;
 import org.opendaylight.netvirt.vpnmanager.VpnUtil;
@@ -67,6 +68,8 @@ public class InterVpnLinkLocatorTest extends ConstantSchemaAbstractDataBrokerTes
     @Mock
     IdManagerService idManager;
     @Mock
+    IFibManager fibManager;
+    @Mock
     IBgpManager bgpManager;
     @Mock
     LockManagerService lockManager;
@@ -86,8 +89,8 @@ public class InterVpnLinkLocatorTest extends ConstantSchemaAbstractDataBrokerTes
 
         dataBroker = getDataBroker();
 
-        vpnUtil = new VpnUtil(dataBroker, idManager, bgpManager, lockManager, neutronVpnService, mdsalManager,
-                jobCoordinator, interfaceManager, ifmRpcService);
+        vpnUtil = new VpnUtil(dataBroker, idManager, fibManager, bgpManager, lockManager, neutronVpnService,
+                mdsalManager, jobCoordinator, interfaceManager, ifmRpcService);
 
         // Creating both empty containers: InterVpnLinks and InterVpnLinkStates
         WriteTransaction writeTx = dataBroker.newWriteOnlyTransaction();