use of org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterface in project netvirt by opendaylight.
the class VpnInterfaceManager method handleVpnInstanceUpdateForVpnInterface.
private boolean handleVpnInstanceUpdateForVpnInterface(InstanceIdentifier<VpnInterface> identifier, VpnInterface original, VpnInterface update, List<ListenableFuture<?>> futures) {
boolean isVpnInstanceUpdate = false;
final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class);
final String interfaceName = key.getName();
List<String> oldVpnList = VpnUtil.getVpnListForVpnInterface(original);
List<String> oldVpnListCopy = new ArrayList<>();
oldVpnListCopy.addAll(oldVpnList);
List<String> newVpnList = VpnUtil.getVpnListForVpnInterface(update);
List<String> newVpnListCopy = new ArrayList<>();
newVpnListCopy.addAll(newVpnList);
oldVpnList.removeAll(newVpnList);
newVpnList.removeAll(oldVpnListCopy);
// This block will execute only on if there is a change in the VPN Instance.
if (!oldVpnList.isEmpty() || !newVpnList.isEmpty()) {
/*
* Internet BGP-VPN Instance update with single router:
* ====================================================
* In this case single VPN Interface will be part of maximum 2 VPN Instance only.
* 1st VPN Instance : router VPN or external BGP-VPN.
* 2nd VPN Instance : Internet BGP-VPN(router-gw update/delete) for public network access.
*
* VPN Instance UPDATE:
* oldVpnList = 0 and newVpnList = 1 (Internet BGP-VPN)
* oldVpnList = 1 and newVpnList = 0 (Internet BGP-VPN)
*
* External BGP-VPN Instance update with single router:
* ====================================================
* In this case single VPN interface will be part of maximum 1 VPN Instance only.
*
* Updated VPN Instance will be always either internal router VPN to
* external BGP-VPN or external BGP-VPN to internal router VPN swap.
*
* VPN Instance UPDATE:
* oldVpnList = 1 and newVpnList = 1 (router VPN to Ext-BGPVPN)
* oldVpnList = 1 and newVpnList = 1 (Ext-BGPVPN to router VPN)
*
* Dual Router VPN Instance Update:
* ================================
* In this case single VPN interface will be part of maximum 3 VPN Instance only.
*
* 1st VPN Instance : router VPN or external BGP-VPN-1.
* 2nd VPN Instance : router VPN or external BGP-VPN-2.
* 3rd VPN Instance : Internet BGP-VPN(router-gw update/delete) for public network access.
*
* Dual Router --> Associated with common external BGP-VPN Instance.
* 1st router and 2nd router are getting associated with single External BGP-VPN
* 1) add 1st router to external bgpvpn --> oldVpnList=1, newVpnList=1;
* 2) add 2nd router to the same external bgpvpn --> oldVpnList=1, newVpnList=0
* In this case, we need to call removeVpnInterfaceCall() followed by addVpnInterfaceCall()
*
*
*/
isVpnInstanceUpdate = true;
if (VpnUtil.isDualRouterVpnUpdate(oldVpnListCopy, newVpnListCopy)) {
if ((oldVpnListCopy.size() == 2 || oldVpnListCopy.size() == 3) && oldVpnList.size() == 1 && newVpnList.isEmpty()) {
// Identify the external BGP-VPN Instance and pass that value as newVpnList
List<String> externalBgpVpnList = new ArrayList<>();
for (String newVpnName : newVpnListCopy) {
String primaryRd = vpnUtil.getPrimaryRd(newVpnName);
VpnInstanceOpDataEntry vpnInstanceOpDataEntry = vpnUtil.getVpnInstanceOpData(primaryRd);
if (vpnInstanceOpDataEntry.getBgpvpnType() == VpnInstanceOpDataEntry.BgpvpnType.BGPVPN) {
externalBgpVpnList.add(newVpnName);
break;
}
}
// This call will execute removeVpnInterfaceCall() followed by addVpnInterfaceCall()
updateVpnInstanceChange(identifier, interfaceName, original, update, oldVpnList, externalBgpVpnList, oldVpnListCopy, futures);
} else if ((oldVpnListCopy.size() == 2 || oldVpnListCopy.size() == 3) && oldVpnList.isEmpty() && newVpnList.size() == 1) {
// Identify the router VPN Instance and pass that value as oldVpnList
List<String> routerVpnList = new ArrayList<>();
for (String newVpnName : newVpnListCopy) {
String primaryRd = vpnUtil.getPrimaryRd(newVpnName);
VpnInstanceOpDataEntry vpnInstanceOpDataEntry = vpnUtil.getVpnInstanceOpData(primaryRd);
if (vpnInstanceOpDataEntry.getBgpvpnType() == VpnInstanceOpDataEntry.BgpvpnType.BGPVPN) {
routerVpnList.add(newVpnName);
break;
}
}
// This call will execute removeVpnInterfaceCall() followed by addVpnInterfaceCall()
updateVpnInstanceChange(identifier, interfaceName, original, update, routerVpnList, newVpnList, oldVpnListCopy, futures);
} else {
// Handle remaining use cases.
updateVpnInstanceChange(identifier, interfaceName, original, update, oldVpnList, newVpnList, oldVpnListCopy, futures);
}
} else {
updateVpnInstanceChange(identifier, interfaceName, original, update, oldVpnList, newVpnList, oldVpnListCopy, futures);
}
}
return isVpnInstanceUpdate;
}
use of org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterface in project netvirt by opendaylight.
the class VpnInterfaceOpListener method postProcessVpnInterfaceRemoval.
private void postProcessVpnInterfaceRemoval(InstanceIdentifier<VpnInterfaceOpDataEntry> identifier, VpnInterfaceOpDataEntry del, @Nullable TypedReadWriteTransaction<Operational> operTx, @Nullable TypedReadTransaction<Configuration> confTx) throws InterruptedException {
if (confTx == null) {
txRunner.callWithNewReadOnlyTransactionAndClose(CONFIGURATION, tx -> postProcessVpnInterfaceRemoval(identifier, del, operTx, tx));
return;
}
if (operTx == null) {
LoggingFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, tx -> postProcessVpnInterfaceRemoval(identifier, del, tx, confTx)), LOG, "Error post-processing VPN interface removal");
return;
}
final VpnInterfaceOpDataEntryKey key = identifier.firstKeyOf(VpnInterfaceOpDataEntry.class);
String interfaceName = key.getName();
String vpnName = del.getVpnInstanceName();
try {
LOG.info("postProcessVpnInterfaceRemoval: interface name {} vpnName {} dpn {}", interfaceName, vpnName, del.getDpnId());
// decrement the vpn interface count in Vpn Instance Op Data
Optional<VpnInstance> vpnInstance = confTx.read(VpnOperDsUtils.getVpnInstanceToVpnIdIdentifier(vpnName)).get();
if (vpnInstance.isPresent()) {
String rd = vpnInstance.get().getVrfId();
VpnInstanceOpDataEntry vpnInstOp = vpnUtil.getVpnInstanceOpData(rd);
AdjacenciesOp adjs = del.augmentation(AdjacenciesOp.class);
Map<AdjacencyKey, Adjacency> adjMap = adjs != null ? adjs.getAdjacency() : null;
if (vpnInstOp != null && adjMap != null && adjMap.size() > 0) {
/*
* When a VPN Interface is removed by FibManager (aka VrfEntryListener and its cohorts),
* one adjacency or two adjacency (in case of dual-stack)
* for that VPN Interface will be hanging around along with that
* VPN Interface. That adjacency could be primary (or) non-primary.
* If its a primary adjacency, then a prefix-to-interface entry will be available for the
* same. If its a non-primary adjacency, then a prefix-to-interface entry will not be
* available for the same, instead we will have vpn-to-extraroutes filled in for them.
*
* Here we try to remove prefix-to-interface entry for pending adjacency in the deleted
* vpnInterface. More importantly, we also update the vpnInstanceOpData by removing this
* vpnInterface from it.
*/
List<Prefixes> prefixToInterface = new ArrayList<>();
for (Adjacency adjacency : adjs.getAdjacency().values()) {
List<Prefixes> prefixToInterfaceLocal = new ArrayList<>();
Optional<Prefixes> prefix = operTx.read(VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(), VpnUtil.getIpPrefix(adjacency.getIpAddress()))).get();
if (prefix.isPresent()) {
prefixToInterfaceLocal.add(prefix.get());
}
if (prefixToInterfaceLocal.isEmpty() && adjacency.getNextHopIpList() != null) {
for (String nh : adjacency.getNextHopIpList()) {
prefix = operTx.read(VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(), VpnUtil.getIpPrefix(nh))).get();
if (prefix.isPresent()) {
prefixToInterfaceLocal.add(prefix.get());
}
}
}
if (!prefixToInterfaceLocal.isEmpty()) {
prefixToInterface.addAll(prefixToInterfaceLocal);
}
}
/*
* In VPN Migration scenarios, there is a race condition where we use the new DPNID
* for the migrated VM instead of old DPNID because when we read prefix-to-interface to cleanup
* old DPNID, we actually get the new DPNID.
*
* More dangerously, we tend to alter the new prefix-to-interface which should be retained intac
* for the migration to succeed in L3VPN. As a workaround, here we are going to use the dpnId in
* the deleted vpnInterface itself instead of tinkering with the prefix-to-interface. Further we
* will tinker prefix-to-interface only when are damn sure if its value matches our
* deleted vpnInterface.
*
*/
for (Prefixes pref : prefixToInterface) {
if (VpnUtil.isMatchedPrefixToInterface(pref, del)) {
operTx.delete(VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(), pref.getIpAddress()));
}
}
}
if (del.getDpnId() != null) {
vpnFootprintService.updateVpnToDpnMapping(del.getDpnId(), del.getVpnInstanceName(), rd, interfaceName, null, /*ipAddressSourceValuePair*/
false);
}
LOG.info("postProcessVpnInterfaceRemoval: Removed vpn operational data and updated vpn footprint" + " for interface {} on dpn {} vpn {}", interfaceName, del.getDpnId(), vpnName);
} else {
LOG.error("postProcessVpnInterfaceRemoval: rd not retrievable as vpninstancetovpnid for vpn {}" + " is absent, trying rd as {}. interface {} dpn {}", vpnName, vpnName, interfaceName, del.getDpnId());
}
notifyTaskIfRequired(interfaceName);
} catch (InterruptedException | ExecutionException e) {
LOG.error("postProcessVpnInterfaceRemoval: Failed to read data store for interface {} vpn {}", interfaceName, vpnName);
}
}
use of org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterface in project netvirt by opendaylight.
the class VpnFootprintService method createOrUpdateVpnToDpnListForInterfaceName.
private void createOrUpdateVpnToDpnListForInterfaceName(Uint32 vpnId, String primaryRd, Uint64 dpnId, String intfName, String vpnName) {
AtomicBoolean newDpnOnVpn = new AtomicBoolean(false);
/* Starts synchronized block. This ensures only one reader/writer get access to vpn-dpn-list
* The future.get ensures that the write to the datastore is complete before leaving the synchronized block.
*/
// FIXME: separate this out somehow?
final ReentrantLock lock = JvmGlobalLocks.getLockForString(vpnName);
lock.lock();
try {
ListenableFuture<?> future = txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, tx -> {
InstanceIdentifier<VpnToDpnList> id = VpnHelper.getVpnToDpnListIdentifier(primaryRd, dpnId);
VpnInterfaces vpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
Optional<VpnToDpnList> dpnInVpn = tx.read(id).get();
if (dpnInVpn.isPresent()) {
VpnToDpnList vpnToDpnList = dpnInVpn.get();
List<VpnInterfaces> vpnInterfaces = new ArrayList<>(vpnToDpnList.nonnullVpnInterfaces().values());
vpnInterfaces.add(vpnInterface);
VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder(vpnToDpnList);
vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setVpnInterfaces(vpnInterfaces);
tx.mergeParentStructurePut(id, vpnToDpnListBuilder.build());
/*
* If earlier state was inactive, it is considered new DPN coming back to the
* same VPN
*/
if (vpnToDpnList.getDpnState() == VpnToDpnList.DpnState.Inactive) {
newDpnOnVpn.set(true);
}
LOG.debug("createOrUpdateVpnToDpnList: Updating vpn footprint for vpn {} vpnId {} interface {}" + " on dpn {}", vpnName, vpnId, intfName, dpnId);
} else {
List<VpnInterfaces> vpnInterfaces = new ArrayList<>();
vpnInterfaces.add(vpnInterface);
VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder().setDpnId(dpnId);
vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setVpnInterfaces(vpnInterfaces);
tx.mergeParentStructurePut(id, vpnToDpnListBuilder.build());
newDpnOnVpn.set(true);
LOG.debug("createOrUpdateVpnToDpnList: Creating vpn footprint for vpn {} vpnId {} interface {}" + " on dpn {}", vpnName, vpnId, intfName, dpnId);
}
});
future.get();
} catch (InterruptedException | ExecutionException e) {
LOG.error("createOrUpdateVpnToDpnList: Error adding to dpnToVpnList for vpn {} vpnId {} interface {}" + " dpn {}", vpnName, vpnId, intfName, dpnId, e);
throw new RuntimeException(e.getMessage(), e);
} finally {
lock.unlock();
}
LOG.info("createOrUpdateVpnToDpnList: Created/Updated vpn footprint for vpn {} vpnId {} interfacName{}" + " on dpn {}", vpnName, vpnId, intfName, dpnId);
/*
* Informing the FIB only after writeTxn is submitted successfully.
*/
if (newDpnOnVpn.get()) {
if (vpnUtil.isVlan(intfName)) {
if (!vpnUtil.shouldPopulateFibForVlan(vpnName, null, dpnId)) {
return;
}
}
fibManager.populateFibOnNewDpn(dpnId, vpnId, primaryRd, new DpnEnterExitVpnWorker(dpnId, vpnName, primaryRd, true));
LOG.info("createOrUpdateVpnToDpnList: Sent populateFib event for new dpn {} in VPN {} for interface {}", dpnId, vpnName, intfName);
}
}
use of org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterface in project netvirt by opendaylight.
the class InterfaceStateChangeListener method handleMipAdjRemoval.
private void handleMipAdjRemoval(VpnInterface cfgVpnInterface, String vpnName) {
String interfaceName = cfgVpnInterface.getName();
Adjacencies adjacencies = cfgVpnInterface.augmentation(Adjacencies.class);
if (adjacencies != null) {
Map<AdjacencyKey, Adjacency> adjacencyMap = adjacencies.nonnullAdjacency();
if (!adjacencyMap.isEmpty()) {
for (Adjacency adj : adjacencyMap.values()) {
if (adj.getAdjacencyType() != Adjacency.AdjacencyType.PrimaryAdjacency) {
String ipAddress = adj.getIpAddress();
String prefix = ipAddress.split("/")[0];
LearntVpnVipToPort vpnVipToPort = vpnUtil.getLearntVpnVipToPort(vpnName, prefix);
if (vpnVipToPort != null && vpnVipToPort.getPortName().equals(interfaceName)) {
vpnUtil.removeMipAdjacency(vpnName, interfaceName, ipAddress, null);
} else {
LOG.debug("IP {} could be extra-route or learnt-ip on different interface" + "than oper-vpn-interface {}", ipAddress, interfaceName);
}
}
}
}
}
}
use of org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterface in project netvirt by opendaylight.
the class SubnetRouteInterfaceStateChangeListener method add.
@Override
public void add(InstanceIdentifier<Interface> identifier, Interface intrf) {
LOG.trace("{} add: Received interface {} up event", LOGGING_PREFIX, intrf);
if (L2vlan.class.equals(intrf.getType())) {
LOG.trace("SubnetRouteInterfaceListener add: Received interface {} up event", intrf);
if (Interface.OperStatus.Up.equals(intrf.getOperStatus())) {
List<Uuid> subnetIdList = getSubnetId(intrf);
if (subnetIdList.isEmpty()) {
LOG.trace("SubnetRouteInterfaceListener add: Port {} doesn't exist in configDS", intrf.getName());
return;
}
for (Uuid subnetId : subnetIdList) {
jobCoordinator.enqueueJob("SUBNETROUTE-" + subnetId, () -> {
String interfaceName = intrf.getName();
Uint64 dpnId = Uint64.ZERO;
LOG.info("{} add: Received port UP event for interface {} subnetId {}", LOGGING_PREFIX, interfaceName, subnetId);
try {
dpnId = InterfaceUtils.getDpIdFromInterface(intrf);
} catch (NullPointerException e) {
LOG.error("{} add: Unable to obtain dpnId for interface {} in subnet {}," + " subnetroute inclusion for this interface failed", LOGGING_PREFIX, interfaceName, subnetId, e);
}
List<ListenableFuture<Void>> futures = new ArrayList<>();
try {
InstanceIdentifier<VpnInterface> id = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
Optional<VpnInterface> cfgVpnInterface = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
if (!cfgVpnInterface.isPresent()) {
return futures;
}
vpnSubnetRouteHandler.onInterfaceUp(dpnId, intrf.getName(), subnetId);
LOG.info("{} add: Processed interface {} up event", LOGGING_PREFIX, intrf.getName());
} catch (InterruptedException | ExecutionException e) {
LOG.error("add: Failed to read data store for interface {} dpn {}", interfaceName, dpnId);
}
return futures;
});
}
}
}
}
Aggregations