import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
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.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
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.VpnInstanceOpDataEntry.BgpvpnType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
LOG.debug("updating existing vpninstance node");
} else {
builder = new VpnInstanceBuilder().withKey(new VpnInstanceKey(vpnName)).setVpnInstanceName(vpnName)
- .setL2vpn(isL2Vpn).setL3vni(l3vni);
+ .setL2vpn(isL2Vpn).setL3vni(l3vni).setBgpvpnType(VpnInstance.BgpvpnType.InternalVPN);
}
if (irt != null && !irt.isEmpty()) {
if (ert != null && !ert.isEmpty()) {
VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
if (rd != null && !rd.isEmpty()) {
- builder.setRouteDistinguisher(rd).setVpnTargets(vpnTargets);
+ builder.setRouteDistinguisher(rd).setVpnTargets(vpnTargets).setBgpvpnType(VpnInstance.BgpvpnType.BGPVPN);
}
builder.setIpAddressFamilyConfigured(VpnInstance.IpAddressFamilyConfigured.forValue(ipVersion.choice));
}
}
if (ipVersion != IpVersionChoice.UNDEFINED) {
- LOG.debug("associateRouterToVpn: Updating vpnInstanceOpDataEntrywith ip address family {} for VPN {} ",
+ LOG.debug("associateRouterToVpn: Updating vpnInstance ip address family {} for VPN {} ",
ipVersion, vpnId);
neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
}
updateVpnForSubnet(vpnId, routerId, sn.getId(), false);
}
if (ipVersion != IpVersionChoice.UNDEFINED) {
- LOG.debug("dissociateRouterFromVpn; Updating vpnInstanceOpDataEntry with ip address family {} for VPN {} ",
+ LOG.debug("dissociateRouterFromVpn; Updating vpnInstance with ip address family {} for VPN {} ",
ipVersion, vpnId);
neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion,
false);
protected List<String> associateNetworksToVpn(@NonNull Uuid vpnId, @NonNull List<Uuid> networkList) {
List<String> failedNwList = new ArrayList<>();
HashSet<Uuid> passedNwList = new HashSet<>();
+ ConcurrentMap<Uuid, Network> extNwMap = new ConcurrentHashMap<>();
boolean isExternalNetwork = false;
if (networkList.isEmpty()) {
LOG.error("associateNetworksToVpn: Failed as given networks list is empty, VPN Id: {}", vpnId.getValue());
return failedNwList;
}
Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
+ boolean isIpFamilyUpdated = false;
for (Uuid nw : networkList) {
Network network = neutronvpnUtils.getNeutronNetwork(nw);
if (network == null) {
+ "another VPN %s", nw.getValue(), networkVpnId.getValue()));
continue;
}
- if (NeutronvpnUtils.getIsExternal(network) && !associateExtNetworkToVpn(vpnId, network)) {
- LOG.error("associateNetworksToVpn: Failed to associate Provider Network {} with VPN {}",
- nw.getValue(), vpnId.getValue());
- failedNwList.add(String.format("Failed to associate Provider Network %s with VPN %s",
- nw.getValue(), vpnId.getValue()));
- continue;
+ /* Handle association of external network(s) to Internet BGP-VPN use case outside of the
+ * networkList iteration
+ */
+ if (neutronvpnUtils.getIsExternal(network)) {
+ extNwMap.put(nw, network);
}
if (NeutronvpnUtils.getIsExternal(network)) {
isExternalNetwork = true;
ipVersion = ipVersion.addVersion(ipVers);
}
}
- if (ipVersion != IpVersionChoice.UNDEFINED) {
- LOG.debug("associateNetworksToVpn: Updating vpnInstanceOpDataEntry with ip address family {}"
+ //Update vpnInstance for IP address family
+ if (ipVersion != IpVersionChoice.UNDEFINED && !isIpFamilyUpdated) {
+ LOG.debug("associateNetworksToVpn: Updating vpnInstance with ip address family {}"
+ " for VPN {} ", ipVersion, vpnId);
neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
+ isIpFamilyUpdated = true;
}
for (Subnetmap subnetmap : subnetmapList) {
Uuid subnetId = subnetmap.getId();
}
}
passedNwList.add(nw);
+ //Handle association of external network(s) to Internet BGP-VPN Instance use case
+ if (!extNwMap.isEmpty() || extNwMap != null) {
+ for (Network extNw : extNwMap.values()) {
+ if (!associateExtNetworkToVpn(vpnId, extNw, vpnInstance.getBgpvpnType())) {
+ LOG.error("associateNetworksToVpn: Failed to associate Provider External Network {} with "
+ + "VPN {}", extNw, vpnId.getValue());
+ failedNwList.add(String.format("Failed to associate Provider External Network %s with "
+ + "VPN %s", extNw, vpnId.getValue()));
+ continue;
+ }
+ }
+ }
}
} catch (ExecutionException | InterruptedException e) {
LOG.error("associateNetworksToVpn: Failed to associate VPN {} with networks {}: ", vpnId.getValue(),
return failedNwList;
}
- private boolean associateExtNetworkToVpn(@NonNull Uuid vpnId, @NonNull Network extNet) {
+ private boolean associateExtNetworkToVpn(@NonNull Uuid vpnId, @NonNull Network extNet,
+ VpnInstance.BgpvpnType bgpVpnType) {
if (!addExternalNetworkToVpn(extNet, vpnId)) {
return false;
}
- VpnInstanceOpDataEntry vpnOpDataEntry = neutronvpnUtils.getVpnInstanceOpDataEntryFromVpnId(vpnId.getValue());
- if (vpnOpDataEntry == null) {
- LOG.error("associateExtNetworkToVpn: can not find VpnOpDataEntry for VPN {}", vpnId.getValue());
- return false;
- }
- if (!vpnOpDataEntry.getBgpvpnType().equals(BgpvpnType.BGPVPNInternet)) {
- LOG.info("associateExtNetworkToVpn: set type {} for VPN {}", BgpvpnType.BGPVPNInternet, vpnId.getValue());
- neutronvpnUtils.updateVpnInstanceOpWithType(BgpvpnType.BGPVPNInternet, vpnId);
+ if (!bgpVpnType.equals(VpnInstance.BgpvpnType.InternetBGPVPN)) {
+ LOG.info("associateExtNetworkToVpn: External network {} is associated to VPN {}."
+ + "Hence set vpnInstance type to {} from {} ", extNet.key().getUuid().getValue(),
+ vpnId.getValue(), VpnInstance.BgpvpnType.InternetBGPVPN.getName(),
+ VpnInstance.BgpvpnType.BGPVPN.getName());
+ neutronvpnUtils.updateVpnInstanceWithBgpVpnType(VpnInstance.BgpvpnType.InternetBGPVPN, vpnId);
}
//Update VpnMap with ext-nw is needed first before processing V6 internet default fallback flows
List<Uuid> extNwList = Collections.singletonList(extNet.key().getUuid());
protected List<String> dissociateNetworksFromVpn(@NonNull Uuid vpnId, @NonNull List<Uuid> networkList) {
List<String> failedNwList = new ArrayList<>();
HashSet<Uuid> passedNwList = new HashSet<>();
+ ConcurrentMap<Uuid, Network> extNwMap = new ConcurrentHashMap<>();
if (networkList.isEmpty()) {
LOG.error("dissociateNetworksFromVpn: Failed as networks list is empty");
failedNwList.add(String.format("Failed to disassociate networks from VPN %s as networks list is empty",
vpnId.getValue()));
continue;
}
- if (NeutronvpnUtils.getIsExternal(network)) {
- if (disassociateExtNetworkFromVpn(vpnId, network)) {
- passedNwList.add(nw);
- } else {
- LOG.error("dissociateNetworksFromVpn: Failed to withdraw Provider Network {} from VPN {}",
- nw.getValue(), vpnId.getValue());
- failedNwList.add(String.format("Failed to withdraw Provider Network %s from VPN %s", nw.getValue(),
- vpnId.getValue()));
- continue;
- }
+ /* Handle disassociation of external network(s) from Internet BGP-VPN use case outside of the
+ * networkList iteration
+ */
+ if (neutronvpnUtils.getIsExternal(network)) {
+ extNwMap.put(nw, network);
}
IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
for (Uuid subnet : networkSubnets) {
}
}
if (ipVersion != IpVersionChoice.UNDEFINED) {
- LOG.debug("dissociateNetworksFromVpn: Updating vpnInstanceOpDataEntryupdate with ip address family {}"
+ LOG.debug("dissociateNetworksFromVpn: Updating vpnInstance with ip address family {}"
+ " for VPN {}", ipVersion, vpnId);
neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, false);
}
}
+ //Handle disassociation of external network(s) from Internet BGP-VPN Instance use case
+ if (!extNwMap.isEmpty() || extNwMap != null) {
+ for (Network extNw : extNwMap.values()) {
+ if (disassociateExtNetworkFromVpn(vpnId, extNw)) {
+ passedNwList.add(extNw.getUuid());
+ } else {
+ LOG.error("dissociateNetworksFromVpn: Failed to withdraw External Provider Network {} from VPN {}",
+ extNw, vpnId.getValue());
+ failedNwList.add(String.format("Failed to withdraw External Provider Network %s from VPN %s",
+ extNw, vpnId.getValue()));
+ continue;
+ }
+ }
+ }
clearFromVpnMaps(vpnId, null, new ArrayList<>(passedNwList));
LOG.info("dissociateNetworksFromVpn: Network(s) {} disassociated from L3VPN {} successfully",
passedNwList, vpnId.getValue());
}
}
}
- //Set VPN Type is BGPVPNExternal from BGPVPNInternet
- LOG.info("disassociateExtNetworkFromVpn: set type {} for VPN {}",
- VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId.getValue());
- neutronvpnUtils.updateVpnInstanceOpWithType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId);
+ ///Set VPN Type is BGPVPN from InternetBGPVPN
+ LOG.info("disassociateExtNetworkFromVpn: Set BGP-VPN type with {} for VPN {} and update IPv6 address family. "
+ + "Since external network is disassociated from VPN {}",
+ VpnInstance.BgpvpnType.BGPVPN, extNet, vpnId.getValue());
+ neutronvpnUtils.updateVpnInstanceWithBgpVpnType(VpnInstance.BgpvpnType.BGPVPN, vpnId);
IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
for (Uuid snId : neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
package org.opendaylight.netvirt.neutronvpn;
import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
-import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableBiMap;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnListKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesList;
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.natservice.rev160111.ExtRouters;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalSubnets;
}
}
- public void updateVpnInstanceOpWithType(VpnInstanceOpDataEntry.BgpvpnType choice, @NonNull Uuid vpn) {
- String primaryRd = getVpnRd(vpn.getValue());
- if (primaryRd == null) {
- LOG.debug("updateVpnInstanceOpWithType: Update BgpvpnType {} for {}."
- + "Primary RD not found", choice, vpn.getValue());
- return;
- }
- InstanceIdentifier<VpnInstanceOpDataEntry> id = getVpnOpDataIdentifier(primaryRd);
-
- Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataEntryOptional =
- read(LogicalDatastoreType.OPERATIONAL, id);
- if (!vpnInstanceOpDataEntryOptional.isPresent()) {
- LOG.debug("updateVpnInstanceOpWithType: Update BgpvpnType {} for {}."
- + "VpnInstanceOpDataEntry not found", choice, vpn.getValue());
- return;
- }
- VpnInstanceOpDataEntry vpnInstanceOpDataEntry = vpnInstanceOpDataEntryOptional.get();
- if (vpnInstanceOpDataEntry.getBgpvpnType().equals(choice)) {
- LOG.debug("updateVpnInstanceOpWithType: Update BgpvpnType {} for {}."
- + "VpnInstanceOpDataEntry already set", choice, vpn.getValue());
- return;
- }
- VpnInstanceOpDataEntryBuilder builder = new VpnInstanceOpDataEntryBuilder(vpnInstanceOpDataEntry);
- builder.setBgpvpnType(choice);
- LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx -> {
- tx.merge(id, builder.build());
- LOG.debug("updateVpnInstanceOpWithType: sent merge to operDS BgpvpnType {} for {}", choice, vpn.getValue());
- }), LOG, "Error updating VPN instance op {} with type {}", vpn, choice);
+ public void updateVpnInstanceWithBgpVpnType(VpnInstance.BgpvpnType bgpvpnType, @NonNull Uuid vpnName) {
+ jobCoordinator.enqueueJob("VPN-" + vpnName.getValue(), () -> {
+ VpnInstance vpnInstance = getVpnInstance(dataBroker, vpnName);
+ if (vpnInstance == null) {
+ LOG.error("updateVpnInstanceWithBgpVpnType: Failed to Update VpnInstance {} with BGP-VPN type {}."
+ + "VpnInstance is does not exist in the CONFIG. Do nothing.", vpnName.getValue(), bgpvpnType);
+ return Collections.emptyList();
+ }
+ if (vpnInstance.isL2vpn()) {
+ LOG.error("updateVpnInstanceWithBgpVpnType: Failed to Update VpnInstance {} with BGP-VPN type {}."
+ + "VpnInstance is L2 instance. Do nothing.", vpnName.getValue(), bgpvpnType);
+ return Collections.emptyList();
+ }
+ VpnInstanceBuilder builder = new VpnInstanceBuilder(vpnInstance);
+ builder.setBgpvpnType(bgpvpnType);
+ InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
+ .child(VpnInstance.class, new VpnInstanceKey(vpnName.getValue())).build();
+ LOG.info("updateVpnInstanceWithBgpVpnType: Successfully updated the VpnInstance {} with BGP-VPN type {}",
+ vpnName.getValue(), bgpvpnType);
+ return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
+ CONFIGURATION, tx -> tx.merge(vpnIdentifier, builder.build())));
+ });
}
public static RouterIds getvpnInstanceRouterIds(Uuid routerId) {
}
leaf bgpvpn-type {
type enumeration {
- enum BGPVPNInternet {
+ enum InternetBGPVPN {
value "0";
- description "BGPVPN Internet";
+ description "Internet BGPVPN";
}
- enum BGPVPNExternal {
+ enum BGPVPN {
value "1";
- description "BGPVPN External";
+ description "BGPVPN";
}
- enum VPN {
+ enum InternalVPN {
value "2";
- description "Default VPN";
+ description "InternalVPN";
}
}
}
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import org.opendaylight.infrautils.utils.concurrent.Executors;
import org.opendaylight.infrautils.utils.concurrent.LoggingFutures;
import org.opendaylight.mdsal.binding.api.DataBroker;
+import org.opendaylight.mdsal.binding.api.WriteTransaction;
import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
import org.opendaylight.netvirt.fibmanager.api.IFibManager;
import org.opendaylight.serviceutils.tools.listener.AbstractAsyncDataTreeChangeListener;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.AddressFamily;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.ExternalTunnelList;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnel;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.DcGatewayIpList;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.dc.gateway.ip.list.DcGatewayIp;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.dc.gateway.ip.list.DcGatewayIpKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds;
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;
private final IdManagerService idManager;
private final VpnInterfaceManager vpnInterfaceManager;
private final IFibManager fibManager;
+ private final IBgpManager bgpManager;
private final VpnOpDataSyncer vpnOpDataNotifier;
private final IMdsalApiManager mdsalManager;
private final JobCoordinator jobCoordinator;
@Inject
public VpnInstanceListener(final DataBroker dataBroker, final IdManagerService idManager,
final VpnInterfaceManager vpnInterfaceManager, final IFibManager fibManager,
- final VpnOpDataSyncer vpnOpDataSyncer, final IMdsalApiManager mdsalManager,
+ final IBgpManager bgpManager, final VpnOpDataSyncer vpnOpDataSyncer, final IMdsalApiManager mdsalManager,
final JobCoordinator jobCoordinator, VpnUtil vpnUtil) {
super(dataBroker, LogicalDatastoreType.CONFIGURATION,
InstanceIdentifier.create(VpnInstances.class).child(VpnInstance.class),
this.idManager = idManager;
this.vpnInterfaceManager = vpnInterfaceManager;
this.fibManager = fibManager;
+ this.bgpManager = bgpManager;
this.vpnOpDataNotifier = vpnOpDataSyncer;
this.mdsalManager = mdsalManager;
this.jobCoordinator = jobCoordinator;
public void update(InstanceIdentifier<VpnInstance> identifier,
VpnInstance original, VpnInstance update) {
LOG.trace("VPN-UPDATE: update: VPN event key: {}, value: {}.", identifier, update);
- String vpnName = update.getVpnInstanceName();
- if (original != null && update != null
- && original.getRouteDistinguisher() != null
- && update.getRouteDistinguisher() != null
- && original.getRouteDistinguisher().size()
- != update.getRouteDistinguisher().size()) {
- LOG.debug("VPN-UPDATE: VpnInstance:{} updated with new RDs: {} from old RDs: {}", vpnName,
- update.getRouteDistinguisher(), original.getRouteDistinguisher());
- vpnUtil.updateVpnInstanceWithRdList(vpnName, update.getRouteDistinguisher());
+ if (Objects.equals(original, update)) {
+ return;
+ }
+ jobCoordinator.enqueueJob("VPN-" + original.getVpnInstanceName(),
+ new UpdateVpnInstanceWorker(dataBroker, identifier, original, update));
+ }
+
+ private class UpdateVpnInstanceWorker implements Callable<List<? extends ListenableFuture<?>>> {
+ private final Logger log = LoggerFactory.getLogger(VpnInstanceListener.UpdateVpnInstanceWorker.class);
+ VpnInstance original;
+ VpnInstance update;
+ InstanceIdentifier<VpnInstance> vpnIdentifier;
+ DataBroker broker;
+ String vpnName;
+
+ UpdateVpnInstanceWorker(DataBroker broker,
+ InstanceIdentifier<VpnInstance> identifier,
+ VpnInstance original,
+ VpnInstance update) {
+ this.broker = broker;
+ this.vpnIdentifier = identifier;
+ this.original = original;
+ this.update = update;
+ this.vpnName = update.getVpnInstanceName();
+ }
+
+ @Override
+ @SuppressWarnings("checkstyle:ForbidCertainMethod")
+ public List<ListenableFuture<Void>> call() {
+ WriteTransaction writeOperTxn = broker.newWriteOnlyTransaction();
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ String primaryRd = vpnUtil.getVpnRd(vpnName);
+ if (primaryRd == null) {
+ log.error("{}, failed to update VPN: PrimaryRD is null for vpnName {}", LOGGING_PREFIX_UPDATE, vpnName);
+ return futures;
+ }
+ updateVpnInstance(writeOperTxn, primaryRd);
+ try {
+ writeOperTxn.commit().get();
+ } catch (InterruptedException | ExecutionException e) {
+ log.error("{}, failed to update VPN: Exception in updating vpn {} rd {} ", LOGGING_PREFIX_UPDATE,
+ vpnName, update.getRouteDistinguisher(), e);
+ futures.add(Futures.immediateFailedFuture(e));
+ return futures;
+ }
+ ListenableFuture<List<Void>> listenableFuture = Futures.allAsList(futures);
+ boolean isIpAddressFamilyUpdated = false;
+ if (original.getIpAddressFamilyConfigured() == VpnInstance.IpAddressFamilyConfigured.Undefined
+ && update.getIpAddressFamilyConfigured() != original.getIpAddressFamilyConfigured()) {
+ isIpAddressFamilyUpdated = true;
+ }
+ Futures.addCallback(listenableFuture,
+ new PostVpnInstanceChangeWorker(update , isIpAddressFamilyUpdated, primaryRd),
+ MoreExecutors.directExecutor());
+ return futures;
+ }
+
+ private class PostVpnInstanceChangeWorker implements FutureCallback<List<Void>> {
+ private final Logger log = LoggerFactory.getLogger(PostVpnInstanceChangeWorker.class);
+ VpnInstance vpnInstance;
+ String vpnName;
+ boolean isIpAddressFamilyUpdated;
+ String primaryRd;
+
+ PostVpnInstanceChangeWorker(VpnInstance vpnInstance, boolean isIpAddressFamilyUpdated, String primaryRd) {
+ this.vpnInstance = vpnInstance;
+ this.vpnName = vpnInstance.getVpnInstanceName();
+ this.isIpAddressFamilyUpdated = isIpAddressFamilyUpdated;
+ this.primaryRd = primaryRd;
+ }
+
+ /**
+ * This implies that all the future instances have returned success. -- TODO: Confirm this
+ */
+ @Override
+ public void onSuccess(List<Void> voids) {
+ if (!VpnUtil.isBgpVpn(vpnName, primaryRd)) {
+ // plain router
+ notifyTask();
+ vpnInterfaceManager.vpnInstanceIsReady(vpnName);
+ return;
+ }
+ if (isIpAddressFamilyUpdated) {
+ //bgpvpn
+ notifyTask();
+ vpnInterfaceManager.vpnInstanceIsReady(vpnName);
+ }
+ }
+
+ /**
+ * This method is used to handle failure callbacks.
+ * If more retry needed, the retrycount is decremented and mainworker is executed again.
+ * After retries completed, rollbackworker is executed.
+ * If rollbackworker fails, this is a double-fault. Double fault is logged and ignored.
+ */
+
+ @Override
+ public void onFailure(Throwable throwable) {
+ log.error("{} onFailure: Job for vpnInstance: {} with rd {} failed with exception:", LOGGING_PREFIX_ADD,
+ vpnName, primaryRd, throwable);
+ vpnInterfaceManager.vpnInstanceFailed(vpnName);
+ }
+
+ private void notifyTask() {
+ vpnOpDataNotifier.notifyVpnOpDataReady(VpnOpDataSyncer.VpnOpDataType.vpnInstanceToId,
+ vpnInstance.getVpnInstanceName());
+ vpnOpDataNotifier.notifyVpnOpDataReady(VpnOpDataSyncer.VpnOpDataType.vpnOpData,
+ vpnInstance.getVpnInstanceName());
+ }
+ }
+
+ public void updateVpnInstance(WriteTransaction writeOperTxn, String primaryRd) {
+ log.trace("updateVpnInstance: VPN event key: {}, value: {}.", vpnIdentifier, update);
+ InstanceIdentifier<VrfTables> id = VpnUtil.buildVrfTableForPrimaryRd(primaryRd);
+ Optional<VrfTables> vrfTable;
+ try {
+ vrfTable = SingleTransactionDataBroker.syncReadOptional(dataBroker,
+ LogicalDatastoreType.CONFIGURATION, id);
+ } catch (ExecutionException | InterruptedException e) {
+ log.trace("updateVpnInstance: Exception while reading FIB VRF Table for VPN Instance {} with "
+ + "Primary RD {}.", vpnName, primaryRd);
+ return;
+ }
+ //TODO Later if FIB VRF table is available we need to callback the vpnInstanceOpData Update to proceed
+ if (!vrfTable.isPresent()) {
+ log.error("updateVpnInstance: FIB VRF table is not present for the VPN Instance {} "
+ + "with Primary RD {}. Unable to Proceed VpnInstanceOpData Update event {}",
+ vpnName, primaryRd, update);
+ return;
+ }
+ List<String> vpnInstanceUpdatedRdList = Collections.emptyList();
+ boolean isBgpVrfTableUpdateRequired = false;
+ boolean isVpnInstanceRdUpdated = false;
+ //Handle VpnInstance Address Family update
+ int originalIpAddrFamilyValue = original.getIpAddressFamilyConfigured().getIntValue();
+ int updateIpAddrFamilyValue = update.getIpAddressFamilyConfigured().getIntValue();
+ if (originalIpAddrFamilyValue != updateIpAddrFamilyValue) {
+ log.debug("updateVpnInstance: VpnInstance: {} updated with IP address family {} from IP address "
+ + "family {}", vpnName, update.getIpAddressFamilyConfigured().getName(),
+ original.getIpAddressFamilyConfigured().getName());
+ vpnUtil.setVpnInstanceOpDataWithAddressFamily(vpnName, update.getIpAddressFamilyConfigured(),
+ writeOperTxn);
+ }
+ //Update VpnInstanceOpData with BGPVPN to Internet BGPVPN and vice-versa
+ if (original.getBgpvpnType() != update.getBgpvpnType()) {
+ log.debug("updateVpnInstance: VpnInstance: {} updated with BGP-VPN type: {} from BGP-VPN type: {}",
+ vpnName, update.getBgpvpnType(), original.getBgpvpnType());
+ vpnUtil.updateVpnInstanceOpDataWithVpnType(vpnName, update.getBgpvpnType(), writeOperTxn);
+ }
+ //Handle BGP-VPN Instance RD Update
+ if ((update.getBgpvpnType() != VpnInstance.BgpvpnType.InternalVPN)) {
+ if (originalIpAddrFamilyValue < updateIpAddrFamilyValue) {
+ isBgpVrfTableUpdateRequired = true;
+ }
+ if (original.getRouteDistinguisher().size() != update.getRouteDistinguisher().size()) {
+ log.debug("updateVpnInstance: VpnInstance:{} updated with new RDs: {} from old RDs: {}", vpnName,
+ update.getRouteDistinguisher(), original.getRouteDistinguisher());
+ vpnUtil.updateVpnInstanceOpDataWithRdList(vpnName, update.getRouteDistinguisher(), writeOperTxn);
+ /* Update BGP Vrf entry for newly added RD. VPN Instance does not support for
+ * deleting the existing RDs
+ */
+ vpnInstanceUpdatedRdList = update.getRouteDistinguisher() != null
+ ? new ArrayList<>(update.getRouteDistinguisher()) : new ArrayList<>();
+ vpnInstanceUpdatedRdList.removeAll(original.getRouteDistinguisher());
+ isBgpVrfTableUpdateRequired = true;
+ isVpnInstanceRdUpdated = true;
+ }
+ }
+ //update Bgp VrfTable
+ if (isBgpVrfTableUpdateRequired) {
+ addBgpVrfTableForVpn(update, vpnName, vpnInstanceUpdatedRdList, isVpnInstanceRdUpdated);
+ }
}
- vpnInterfaceManager.updateVpnInterfacesForUnProcessAdjancencies(vpnName);
}
@Override
if (VpnUtil.isBgpVpn(vpnInstanceName, primaryRd)) {
List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn
.instance.op.data.entry.vpntargets.VpnTarget> opVpnTargetList = new ArrayList<>();
- builder.setBgpvpnType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal);
if (value.getL3vni() != null) {
builder.setL3vni(value.getL3vni());
}
List<String> rds = value.getRouteDistinguisher();
builder.setRd(rds);
- } else {
- builder.setBgpvpnType(VpnInstanceOpDataEntry.BgpvpnType.VPN);
}
+ // Get BGP-VPN type configured details from config vpn-instance
+ builder.setBgpvpnType(VpnInstanceOpDataEntry.BgpvpnType.forValue(value.getBgpvpnType().getIntValue()));
writeOperTxn.mergeParentStructureMerge(VpnUtil.getVpnInstanceOpDataIdentifier(primaryRd), builder.build());
LOG.info("{} addVpnInstance: VpnInstanceOpData populated successfully for vpn {} rd {}", LOGGING_PREFIX_ADD,
vpnInstanceName, primaryRd);
return VpnConstants.FLOWID_PREFIX + dpnId + NwConstants.FLOWID_SEPARATOR + tableId
+ NwConstants.FLOWID_SEPARATOR + vpnName + NwConstants.FLOWID_SEPARATOR + priority;
}
+
+ @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
+ justification = "https://github.com/spotbugs/spotbugs/issues/811")
+ private void addBgpVrfTableForVpn(VpnInstance vpnInstance, String vpnName, List<String> vpnInstanceUpdatedRdList,
+ boolean isVpnInstanceRdUpdated) {
+ String primaryRd = vpnUtil.getPrimaryRd(vpnName);
+ Collection<VpnTarget> vpnTargetCollection = (vpnInstance.getVpnTargets() != null)
+ ? vpnInstance.getVpnTargets().getVpnTarget().values() : null;
+ List<VpnTarget> vpnTargetList = new ArrayList<VpnTarget>(vpnTargetCollection != null ? vpnTargetCollection
+ : Collections.emptyList());
+ List<String> exportRTList = new ArrayList<>();
+ List<String> importRTList = new ArrayList<>();
+ if (!vpnTargetList.isEmpty()) {
+ for (VpnTarget vpnTarget : vpnTargetList) {
+ if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
+ exportRTList.add(vpnTarget.getVrfRTValue());
+ }
+ if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
+ importRTList.add(vpnTarget.getVrfRTValue());
+ }
+ if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
+ exportRTList.add(vpnTarget.getVrfRTValue());
+ importRTList.add(vpnTarget.getVrfRTValue());
+ }
+ }
+ }
+ synchronized (vpnName.intern()) {
+ List<String> rds = Collections.emptyList();
+ //Vpn Instance RD Update for ECMP use case
+ if (isVpnInstanceRdUpdated) {
+ rds = vpnInstanceUpdatedRdList;
+ } else {
+ rds = vpnInstance.getRouteDistinguisher() != null
+ ? new ArrayList<>(vpnInstance.getRouteDistinguisher()) : new ArrayList<>();
+ }
+ for (String rd : rds) {
+ List<String> irtList = rd.equals(primaryRd) ? importRTList : Collections.emptyList();
+ int ipAddrFamilyConfigured = vpnInstance.getIpAddressFamilyConfigured().getIntValue();
+ switch (ipAddrFamilyConfigured) {
+ case 10:
+ bgpManager.addVrf(rd, irtList, exportRTList, AddressFamily.IPV4);
+ bgpManager.addVrf(rd, irtList, exportRTList, AddressFamily.IPV6);
+ LOG.debug("addBgpVrfTableForVpn: ADD BGP VRF table for VPN {} with RD {}, ImportRTList {}, "
+ + "ExportRTList {} for IPv4andIPv6 AddressFamily ", vpnName, rd, irtList, exportRTList);
+ break;
+ case 6:
+ bgpManager.addVrf(rd, irtList, exportRTList, AddressFamily.IPV6);
+ LOG.debug("addBgpVrfTableForVpn: ADD BGP VRF table for VPN {} with RD {}, ImportRTList {}, "
+ + "ExportRTList {} for IPv6 AddressFamily ", vpnName, rd, irtList, exportRTList);
+ break;
+ case 4:
+ bgpManager.addVrf(rd, irtList, exportRTList, AddressFamily.IPV4);
+ LOG.debug("addBgpVrfTableForVpn: ADD BGP VRF table for VPN {} with RD {}, ImportRTList {}, "
+ + "ExportRTList {} for IPv4 AddressFamily ", vpnName, rd, irtList, exportRTList);
+ break;
+ default:
+ break;
+ }
+ //L2VPN Use case
+ if (vpnInstance.isL2vpn()) {
+ bgpManager.addVrf(rd, importRTList, exportRTList, AddressFamily.L2VPN);
+ LOG.debug("addBgpVrfTableForVpn: ADD BGP VRF table for VPN {} RD {}, ImportRTList {}, "
+ + "ExportRTList {} for L2VPN AddressFamily ", vpnName, rd, irtList, exportRTList);
+ }
+ }
+ }
+ }
}
for (Adjacency nextHop : nextHopsMap.values()) {
String rd = primaryRd;
String nexthopIpValue = nextHop.getIpAddress().split("/")[0];
- if (vpnInstanceOpData.getBgpvpnType() == VpnInstanceOpDataEntry.BgpvpnType.BGPVPNInternet
+ if (vpnInstanceOpData.getBgpvpnType() == VpnInstanceOpDataEntry.BgpvpnType.InternetBGPVPN
&& NWUtil.isIpv4Address(nexthopIpValue)) {
String prefix = nextHop.getIpAddress() == null ? "null" :
VpnUtil.getIpPrefix(nextHop.getIpAddress());
String primaryRd = vpnUtil.getPrimaryRd(newVpnName);
VpnInstanceOpDataEntry vpnInstanceOpDataEntry = vpnUtil.getVpnInstanceOpData(primaryRd);
if (vpnInstanceOpDataEntry.getBgpvpnType() == VpnInstanceOpDataEntry
- .BgpvpnType.BGPVPNExternal) {
+ .BgpvpnType.BGPVPN) {
externalBgpVpnList.add(newVpnName);
break;
}
String primaryRd = vpnUtil.getPrimaryRd(newVpnName);
VpnInstanceOpDataEntry vpnInstanceOpDataEntry = vpnUtil.getVpnInstanceOpData(primaryRd);
if (vpnInstanceOpDataEntry.getBgpvpnType() == VpnInstanceOpDataEntry
- .BgpvpnType.VPN) {
+ .BgpvpnType.BGPVPN) {
routerVpnList.add(newVpnName);
break;
}
boolean isBgpVpnInternet(String vpnName) {
String primaryRd = getVpnRd(vpnName);
if (primaryRd == null) {
- LOG.error("isBgpVpnInternet VPN {}."
- + "Primary RD not found", vpnName);
+ LOG.error("isBgpVpnInternet VPN {} Primary RD not found", vpnName);
return false;
}
InstanceIdentifier<VpnInstanceOpDataEntry> id = InstanceIdentifier.builder(VpnInstanceOpData.class)
+ "VpnInstanceOpDataEntry not found", vpnName);
return false;
}
- LOG.debug("isBgpVpnInternet VPN {}."
- + "Successfully VpnInstanceOpDataEntry.getBgpvpnType {}",
+ LOG.debug("isBgpVpnInternet VPN {} Successfully VpnInstanceOpDataEntry.getBgpvpnType {}",
vpnName, vpnInstanceOpDataEntryOptional.get().getBgpvpnType());
- if (vpnInstanceOpDataEntryOptional.get().getBgpvpnType() == VpnInstanceOpDataEntry
- .BgpvpnType.BGPVPNInternet) {
+ if (vpnInstanceOpDataEntryOptional.get().getBgpvpnType() == VpnInstanceOpDataEntry.BgpvpnType.InternetBGPVPN) {
return true;
}
return false;
// FIXME: is there some identifier we can use? LearntVpnVipToPortKey perhaps?
return JvmGlobalLocks.getLockForString(vpnName + fixedIp);
}
+
+ public static InstanceIdentifier<VrfTables> buildVrfTableForPrimaryRd(String primaryRd) {
+ InstanceIdentifier.InstanceIdentifierBuilder<VrfTables> idBuilder =
+ InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(primaryRd));
+ return idBuilder.build();
+ }
+
+ public void setVpnInstanceOpDataWithAddressFamily(String vpnName,
+ VpnInstance.IpAddressFamilyConfigured ipVersion,
+ WriteTransaction writeOperTxn) {
+ VpnInstanceOpDataEntry vpnInstanceOpDataEntry = getVpnInstanceOpDataEntryFromVpnName(vpnName);
+ if (vpnInstanceOpDataEntry == null) {
+ LOG.error("setVpnInstanceOpDataWithAddressFamily: Unable to set IP address family {} for the "
+ + "VPN {}. Since VpnInstanceOpData is not yet ready", ipVersion, vpnName);
+ return;
+ }
+ if (vpnInstanceOpDataEntry.getType() == VpnInstanceOpDataEntry.Type.L2) {
+ LOG.error("setVpnInstanceOpDataWithAddressFamily: Unable to set IP address family {} for the "
+ + "VPN {}. Since VPN type is L2 flavour. Do Nothing.", ipVersion, vpnName);
+ return;
+ }
+ synchronized (vpnName.intern()) {
+ VpnInstanceOpDataEntryBuilder builder = new VpnInstanceOpDataEntryBuilder()
+ .setVrfId(vpnInstanceOpDataEntry.getVrfId());
+ builder.setIpAddressFamilyConfigured(VpnInstanceOpDataEntry.IpAddressFamilyConfigured
+ .forValue(ipVersion.getIntValue()));
+ InstanceIdentifier<VpnInstanceOpDataEntry> id = InstanceIdentifier.builder(VpnInstanceOpData.class)
+ .child(VpnInstanceOpDataEntry.class,
+ new VpnInstanceOpDataEntryKey(vpnInstanceOpDataEntry.getVrfId())).build();
+ writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, id, builder.build());
+ LOG.info("setVpnInstanceOpDataWithAddressFamily: Successfully set vpnInstanceOpData with "
+ + "IP Address family {} for VpnInstance {}", ipVersion.getName(), vpnName);
+ }
+ }
+
+ public void updateVpnInstanceOpDataWithVpnType(String vpnName,
+ VpnInstance.BgpvpnType bgpvpnType,
+ WriteTransaction writeOperTxn) {
+ VpnInstanceOpDataEntry vpnInstanceOpDataEntry = getVpnInstanceOpDataEntryFromVpnName(vpnName);
+ if (vpnInstanceOpDataEntry == null) {
+ LOG.error("updateVpnInstanceOpDataWithVpnType: VpnInstance {} with BGPVPN Type {} update Failed."
+ + "Since vpnInstanceOpData is not yet ready.", vpnName, bgpvpnType);
+ return;
+ }
+ if (vpnInstanceOpDataEntry.getType() == VpnInstanceOpDataEntry.Type.L2) {
+ LOG.error("updateVpnInstanceOpDataWithVpnType: Unable to update the VpnInstance {} with BGPVPN Type {}."
+ + "Since VPN type is L2 flavour. Do Nothing.", vpnName, bgpvpnType);
+ return;
+ }
+ synchronized (vpnName.intern()) {
+ VpnInstanceOpDataEntryBuilder builder = new VpnInstanceOpDataEntryBuilder()
+ .setVrfId(vpnInstanceOpDataEntry.getVrfId());
+ builder.setBgpvpnType(VpnInstanceOpDataEntry.BgpvpnType.forValue(bgpvpnType.getIntValue()));
+ InstanceIdentifier<VpnInstanceOpDataEntry> id = InstanceIdentifier.builder(VpnInstanceOpData.class)
+ .child(VpnInstanceOpDataEntry.class,
+ new VpnInstanceOpDataEntryKey(vpnInstanceOpDataEntry.getVrfId())).build();
+ writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, id, builder.build());
+ LOG.info("updateVpnInstanceOpDataWithVpnType: Successfully updated vpn-instance-op-data with BGPVPN type "
+ + "{} for the Vpn {}", bgpvpnType, vpnName);
+ }
+ }
+
+ public VpnInstanceOpDataEntry getVpnInstanceOpDataEntryFromVpnName(String vpnName) {
+ String primaryRd = getVpnRd(vpnName);
+ if (primaryRd == null) {
+ LOG.error("getVpnInstanceOpDataEntryFromVpnName: Vpn Instance {} Primary RD not found", vpnName);
+ return null;
+ }
+ return getVpnInstanceOpData(primaryRd);
+ }
+
+ public void updateVpnInstanceOpDataWithRdList(String vpnName, List<String> updatedRdList,
+ WriteTransaction writeOperTxn) {
+ String primaryRd = getVpnRd(vpnName);
+ if (primaryRd == null) {
+ LOG.error("updateVpnInstanceOpDataWithRdList: Unable to get primary RD for the VPN {}. Skip to process "
+ + "the update RD list {} ", vpnName, updatedRdList);
+ return;
+ }
+ synchronized (vpnName.intern()) {
+ VpnInstanceOpDataEntryBuilder builder = new VpnInstanceOpDataEntryBuilder().setVrfId(primaryRd);
+ builder.setRd(updatedRdList);
+ InstanceIdentifier<VpnInstanceOpDataEntry> id = InstanceIdentifier.builder(VpnInstanceOpData.class)
+ .child(VpnInstanceOpDataEntry.class,
+ new VpnInstanceOpDataEntryKey(primaryRd)).build();
+ writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, id, builder.build());
+ LOG.info("updateVpnInstanceOpDataWithRdList: Successfully updated the VPN {} with list of RDs {}",
+ vpnName, updatedRdList);
+ }
+ }
}