BGP-VPN Instance update with additional RD Support 83/75683/13
authorKarthikeyan Krishnan <karthikeyangceb007@gmail.com>
Mon, 3 Sep 2018 13:36:11 +0000 (19:06 +0530)
committerSam Hague <shague@redhat.com>
Sun, 7 Oct 2018 14:16:10 +0000 (14:16 +0000)
Issue:
======
For Extra route use cases, user can update the existing
BGP-VPN instance with additional RDs which are required
for extra/static routes.
Currently RD list update is not getting updated in
VPN Instance DS. As a result newly added RD is not
getting advertised to BGP.

Solution:
==========
This fix is addressing the existing BGP-VPN instance
is getting update with new RDs.Also if extra routes
are used this newly added RD will advertise this VRF
into external BGP Update.

Note: Removing the existing RD is not supported by NeutronVPN

Issue: NETVIRT-1416

Change-Id: Iedcdba88084934670c7ba7e8fcf66e0bd91f875b
Signed-off-by: Karthikeyan Krishnan <karthikeyangceb007@gmail.com>
vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnInstanceListener.java
vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnOpStatusListener.java
vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnUtil.java

index caafeb9b9258f968400c5280ff3aaf97265b43e4..a8b6ec33797aac6e0994a09e7511e1ee974ecfee 100644 (file)
@@ -157,8 +157,15 @@ public class VpnInstanceListener extends AsyncDataTreeChangeListenerBase<VpnInst
     @Override
     protected void update(InstanceIdentifier<VpnInstance> identifier,
         VpnInstance original, VpnInstance update) {
-        LOG.trace("VPN-UPDATE: update: VPN event key: {}, value: {}. Ignoring", identifier, update);
+        LOG.trace("VPN-UPDATE: update: VPN event key: {}, value: {}.", identifier, update);
         String vpnName = update.getVpnInstanceName();
+        if ((original.getIpv4Family() != null && update.getIpv4Family() != null)
+                && original.getIpv4Family().getRouteDistinguisher().size()
+                !=  update.getIpv4Family().getRouteDistinguisher().size()) {
+            LOG.debug("VPN-UPDATE: VpnInstance:{} updated with new RDs: {} from old RDs: {}", vpnName,
+                    update.getIpv4Family().getRouteDistinguisher(),  original.getIpv4Family().getRouteDistinguisher());
+            vpnUtil.updateVpnInstanceWithRdList(vpnName, update.getIpv4Family().getRouteDistinguisher());
+        }
         vpnInterfaceManager.updateVpnInterfacesForUnProcessAdjancencies(vpnName);
     }
 
index aa447b67ea50b8044f97465364f0b491a5b4d438..bacf5a9e033ae8091e96842088aff4f9a7919190 100644 (file)
@@ -204,7 +204,6 @@ public class VpnOpStatusListener extends AsyncDataTreeChangeListenerBase<VpnInst
             }, SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
         } else if (update.getVpnState() == VpnInstanceOpDataEntry.VpnState.Created) {
             final String vpnName = update.getVpnInstanceName();
-            final List<String> rds = update.getRd();
             String primaryRd = update.getVrfId();
             if (!VpnUtil.isBgpVpn(vpnName, primaryRd)) {
                 return;
@@ -241,6 +240,12 @@ public class VpnOpStatusListener extends AsyncDataTreeChangeListenerBase<VpnInst
                 return;
             }
             jobCoordinator.enqueueJob("VPN-" + update.getVpnInstanceName(), () -> {
+                //RD update case get only updated RD list
+                List<String> rds = update.getRd();
+                if (original.getRd().size() != update.getRd().size()) {
+                    List<String> oldRds = original.getRd();
+                    rds.removeAll(oldRds);
+                }
                 rds.parallelStream().forEach(rd -> {
                     try {
                         List<String> importRTList = rd.equals(primaryRd) ? irtList : Collections.emptyList();
@@ -260,6 +265,17 @@ public class VpnOpStatusListener extends AsyncDataTreeChangeListenerBase<VpnInst
                         } else if (original.isIpv6Configured() && !update.isIpv6Configured()) {
                             bgpManager.deleteVrf(rd, false, AddressFamily.IPV6);
                         }
+                        /* Update vrf entry with newly added RD list. VPN does not support for
+                         * deleting existing RDs
+                         */
+                        if (original.getRd().size() != update.getRd().size()) {
+                            if (update.isIpv4Configured()) {
+                                bgpManager.addVrf(rd, importRTList, ertList, AddressFamily.IPV4);
+                            }
+                            if (update.isIpv6Configured()) {
+                                bgpManager.addVrf(rd, importRTList, ertList, AddressFamily.IPV6);
+                            }
+                        }
                     } catch (Exception e) {
                         LOG.error("VpnOpStatusListener.update: Exception when updating VRF to BGP"
                                + " for vpn {} rd {}", vpnName, rd);
index c9efcb18d5a4e7af3059e817c5406591656e784f..6b95ee6020d6ca8eb280c56a014a22ac9403f9f4 100644 (file)
@@ -193,6 +193,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntryBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntryKey;
 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.VpnInstanceOpDataEntryBuilder;
 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.VpnTargets;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
@@ -2228,4 +2229,26 @@ public final class VpnUtil {
         return vpnInter.getVpnInstanceNames().stream()
                 .map(VpnInstanceNames::getVpnName).collect(Collectors.toList());
     }
+
+    public void updateVpnInstanceWithRdList(String vpnName, List<String> updatedRdList) {
+        String primaryRd = getVpnRd(vpnName);
+        if (primaryRd == null) {
+            LOG.warn("updateVpnInstanceWithRdList: Unable to retrieve primary RD for the VPN {}. Skip to process "
+                    + "the updated RD list {} ", vpnName, updatedRdList);
+            return;
+        }
+        jobCoordinator.enqueueJob("VPN-" + vpnName, () -> {
+            VpnInstanceOpDataEntryBuilder builder = new VpnInstanceOpDataEntryBuilder();
+            builder.setRd(updatedRdList);
+            return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
+                    OPERATIONAL, tx -> {
+                    InstanceIdentifier<VpnInstanceOpDataEntry> id = InstanceIdentifier
+                            .builder(VpnInstanceOpData.class).child(VpnInstanceOpDataEntry.class,
+                                    new VpnInstanceOpDataEntryKey(primaryRd)).build();
+                    tx.merge(id, builder.build(), false);
+                    LOG.debug("updateVpnInstanceWithRdList: Successfully updated the VPN {} with list of RDs {}",
+                            vpnName, updatedRdList);
+                }));
+        });
+    }
 }