Remove learnt and Adjacent entries for GW after deleting external subnet 12/72812/4
authorVinh Nguyen <vinh.nguyen@hcl.com>
Fri, 8 Jun 2018 22:47:16 +0000 (15:47 -0700)
committerSam Hague <shague@redhat.com>
Sat, 23 Jun 2018 01:02:46 +0000 (01:02 +0000)
Learnt and adjacent entries for external subnet GW
remain in DS after the external subnet is deleted.
This prevents installing new learnt/adjacent/Fib entries
for external GW when the external subnet is re-created.
Hence the fix.

JIRA: NETVIRT-1301
Change-Id: I3cce5e5d284563d359551173c569ef53d616388e
Signed-off-by: Vinh Nguyen <vinh.nguyen@hcl.com>
neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronExternalSubnetHandler.java
neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnNatManager.java

index 9de986ba18d7fda1f4cd2f3ee357f68a2ece97d4..b45b55754e695305cc738fe690164ca96b0d63f9 100644 (file)
@@ -54,7 +54,7 @@ public class NeutronExternalSubnetHandler implements AutoCloseable {
             LOG.info("Removed subnet {} part of external network {} will remove NAT external subnet",
                     subnetId.getValue(), networkId.getValue());
             nvpnManager.removeVpnInstanceForSubnet(subnetId);
-            nvpnNatManager.removeExternalSubnet(subnetId);
+            nvpnNatManager.removeExternalSubnet(networkId, subnetId);
         }
     }
 }
index 21a32ca1aa6fd9af24b5d193e9f4c367f905ed72..c1c766274586c02b2a8ffac22851254ed35c0d40 100644 (file)
@@ -9,7 +9,9 @@ package org.opendaylight.netvirt.neutronvpn;
 
 import com.google.common.base.Optional;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Objects;
 import java.util.Set;
@@ -21,9 +23,17 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
+import org.opendaylight.netvirt.elanmanager.api.IElanService;
 import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice;
 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
+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.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
+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.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.natservice.rev160111.ExternalNetworks;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalSubnets;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.FloatingIpInfo;
@@ -63,13 +73,15 @@ public class NeutronvpnNatManager implements AutoCloseable {
     private final DataBroker dataBroker;
     private final NeutronvpnUtils neutronvpnUtils;
     private final NeutronvpnManager nvpnManager;
+    private final IElanService elanService;
 
     @Inject
     public NeutronvpnNatManager(final DataBroker dataBroker, final NeutronvpnUtils neutronvpnUtils,
-                                  final NeutronvpnManager neutronvpnManager) {
+                                  final NeutronvpnManager neutronvpnManager, final IElanService elanService) {
         this.dataBroker = dataBroker;
         this.neutronvpnUtils = neutronvpnUtils;
         this.nvpnManager = neutronvpnManager;
+        this.elanService = elanService;
     }
 
     @Override
@@ -657,7 +669,8 @@ public class NeutronvpnNatManager implements AutoCloseable {
         }
     }
 
-    public void removeExternalSubnet(Uuid subnetId) {
+    public void removeExternalSubnet(Uuid networkId, Uuid subnetId) {
+        removeAdjacencyAndLearnedEntriesforExternalSubnet(networkId, subnetId);
         InstanceIdentifier<Subnets> subnetsIdentifier = InstanceIdentifier.builder(ExternalSubnets.class)
                 .child(Subnets.class, new SubnetsKey(subnetId)).build();
         try {
@@ -763,4 +776,53 @@ public class NeutronvpnNatManager implements AutoCloseable {
         externalIpsBuilder.setSubnetId(subnetId);
         externalIps.add(externalIpsBuilder.build());
     }
+
+    private void removeAdjacencyAndLearnedEntriesforExternalSubnet(Uuid extNetId, Uuid extSubnetId) {
+        Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
+        if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
+            LOG.error("No external ports attached to external network {}", extNetId.getValue());
+            return;
+        }
+
+        for (String infName : extElanInterfaces) {
+            InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
+                VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
+            InstanceIdentifier<Adjacencies> adjacenciesIdentifier = vpnIfIdentifier.augmentation(Adjacencies.class);
+            try {
+                // Looking for existing prefix in MDSAL database
+                Optional<Adjacencies> optionalAdjacencies = SingleTransactionDataBroker.syncReadOptional(dataBroker,
+                    LogicalDatastoreType.CONFIGURATION, adjacenciesIdentifier);
+                if (optionalAdjacencies.isPresent()) {
+                    List<Adjacency> adjacencies = optionalAdjacencies.get().getAdjacency();
+                    Iterator<Adjacency> adjacencyIter = adjacencies.iterator();
+                    while (adjacencyIter.hasNext()) {
+                        Adjacency adjacency = adjacencyIter.next();
+                        if (!adjacency.getSubnetId().equals(extSubnetId)) {
+                            continue;
+                        }
+                        InstanceIdentifier<Adjacency> adjacencyIdentifier =
+                            adjacenciesIdentifier.child(Adjacency.class, new AdjacencyKey(adjacency.getIpAddress()));
+                        SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                            adjacencyIdentifier);
+                        LOG.trace("Removed Adjacency for fixedIP {} for port {} on external subnet {} ",
+                            adjacency.getIpAddress(), infName, extSubnetId);
+                        String extNetVpnName = extNetId.getValue();
+                        String learnedSrcIp = adjacency.getIpAddress().split("/")[0];
+                        InstanceIdentifier<LearntVpnVipToPort> id =
+                            NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(extNetVpnName, learnedSrcIp);
+                        Optional<LearntVpnVipToPort> optionalLearntVpnVipToPort = SingleTransactionDataBroker
+                            .syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
+                        if (optionalLearntVpnVipToPort.isPresent()) {
+                            neutronvpnUtils.removeLearntVpnVipToPort(extNetVpnName, learnedSrcIp);
+                            LOG.trace("Removed Learnt Entry for fixedIP {} for port {}",
+                                adjacency.getIpAddress(), infName);
+                        }
+                    }
+                }
+            } catch (TransactionCommitFailedException | ReadFailedException e) {
+                LOG.error("exception in removeAdjacencyAndLearnedEntriesforExternalSubnet for interface {}",
+                    infName, e);
+            }
+        }
+    }
 }