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 <[email protected]>
@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);
}
}, 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;
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();
} 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);
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;
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);
+ }));
+ });
+ }
}