use of org.opendaylight.netvirt.vpnmanager.api.intervpnlink.InterVpnLinkDataComposite in project netvirt by opendaylight.
the class VrfEntryListener method createFibEntries.
private void createFibEntries(final InstanceIdentifier<VrfEntry> vrfEntryIid, final VrfEntry vrfEntry) {
final VrfTablesKey vrfTableKey = vrfEntryIid.firstKeyOf(VrfTables.class);
List<SubTransaction> txnObjects = new ArrayList<>();
final VpnInstanceOpDataEntry vpnInstance = fibUtil.getVpnInstance(vrfTableKey.getRouteDistinguisher());
Preconditions.checkNotNull(vpnInstance, "Vpn Instance not available " + vrfTableKey.getRouteDistinguisher());
Preconditions.checkNotNull(vpnInstance.getVpnId(), "Vpn Instance with rd " + vpnInstance.getVrfId() + " has null vpnId!");
final Collection<VpnToDpnList> vpnToDpnList;
if (vrfEntry.getParentVpnRd() != null && FibHelper.isControllerManagedNonSelfImportedRoute(RouteOrigin.value(vrfEntry.getOrigin()))) {
// This block MUST BE HIT only for PNF (Physical Network Function) FIB Entries.
VpnInstanceOpDataEntry parentVpnInstance = fibUtil.getVpnInstance(vrfEntry.getParentVpnRd());
vpnToDpnList = parentVpnInstance != null ? parentVpnInstance.getVpnToDpnList() : vpnInstance.getVpnToDpnList();
LOG.info("createFibEntries: Processing creation of PNF FIB entry with rd {} prefix {}", vrfEntry.getParentVpnRd(), vrfEntry.getDestPrefix());
} else {
vpnToDpnList = vpnInstance.getVpnToDpnList();
}
final Long vpnId = vpnInstance.getVpnId();
final String rd = vrfTableKey.getRouteDistinguisher();
SubnetRoute subnetRoute = vrfEntry.getAugmentation(SubnetRoute.class);
if (subnetRoute != null) {
final long elanTag = subnetRoute.getElantag();
LOG.trace("SUBNETROUTE: createFibEntries: SubnetRoute augmented vrfentry found for rd {} prefix {}" + " with elantag {}", rd, vrfEntry.getDestPrefix(), elanTag);
if (vpnToDpnList != null) {
jobCoordinator.enqueueJob(FibUtil.getJobKeyForRdPrefix(rd, vrfEntry.getDestPrefix()), () -> {
WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
for (final VpnToDpnList curDpn : vpnToDpnList) {
if (curDpn.getDpnState() == VpnToDpnList.DpnState.Active) {
installSubnetRouteInFib(curDpn.getDpnId(), elanTag, rd, vpnId, vrfEntry, tx);
installSubnetBroadcastAddrDropRule(curDpn.getDpnId(), rd, vpnId.longValue(), vrfEntry, NwConstants.ADD_FLOW, tx);
}
}
List<ListenableFuture<Void>> futures = new ArrayList<>();
futures.add(tx.submit());
return futures;
});
}
return;
}
final List<BigInteger> localDpnIdList = createLocalFibEntry(vpnInstance.getVpnId(), rd, vrfEntry);
if (!localDpnIdList.isEmpty() && vpnToDpnList != null) {
jobCoordinator.enqueueJob(FibUtil.getJobKeyForRdPrefix(rd, vrfEntry.getDestPrefix()), () -> {
WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
synchronized (vpnInstance.getVpnInstanceName().intern()) {
for (VpnToDpnList vpnDpn : vpnToDpnList) {
if (!localDpnIdList.contains(vpnDpn.getDpnId())) {
if (vpnDpn.getDpnState() == VpnToDpnList.DpnState.Active) {
try {
if (RouteOrigin.BGP.getValue().equals(vrfEntry.getOrigin())) {
bgpRouteVrfEntryHandler.createRemoteFibEntry(vpnDpn.getDpnId(), vpnId, vrfTableKey.getRouteDistinguisher(), vrfEntry, tx, txnObjects);
} else {
createRemoteFibEntry(vpnDpn.getDpnId(), vpnInstance.getVpnId(), vrfTableKey.getRouteDistinguisher(), vrfEntry, tx);
}
} catch (NullPointerException e) {
LOG.error("Failed to get create remote fib flows for prefix {} ", vrfEntry.getDestPrefix(), e);
}
}
}
}
}
List<ListenableFuture<Void>> futures = new ArrayList<>();
futures.add(tx.submit());
return futures;
}, MAX_RETRIES);
}
Optional<String> optVpnUuid = fibUtil.getVpnNameFromRd(rd);
if (optVpnUuid.isPresent()) {
String vpnUuid = optVpnUuid.get();
InterVpnLinkDataComposite interVpnLink = interVpnLinkCache.getInterVpnLinkByVpnId(vpnUuid).orNull();
if (interVpnLink != null) {
LOG.debug("InterVpnLink {} found in Cache linking Vpn {}", interVpnLink.getInterVpnLinkName(), vpnUuid);
FibUtil.getFirstNextHopAddress(vrfEntry).ifPresent(routeNexthop -> {
if (interVpnLink.isIpAddrTheOtherVpnEndpoint(routeNexthop, vpnUuid)) {
// This is an static route that points to the other endpoint of an InterVpnLink
// In that case, we should add another entry in FIB table pointing to LPortDispatcher table.
installIVpnLinkSwitchingFlows(interVpnLink, vpnUuid, vrfEntry, vpnId);
installInterVpnRouteInLFib(interVpnLink, vpnUuid, vrfEntry);
}
});
}
}
}
use of org.opendaylight.netvirt.vpnmanager.api.intervpnlink.InterVpnLinkDataComposite in project netvirt by opendaylight.
the class VrfEntryListener method deleteFibEntries.
private void deleteFibEntries(final InstanceIdentifier<VrfEntry> identifier, final VrfEntry vrfEntry) {
final VrfTablesKey vrfTableKey = identifier.firstKeyOf(VrfTables.class);
final String rd = vrfTableKey.getRouteDistinguisher();
final VpnInstanceOpDataEntry vpnInstance = fibUtil.getVpnInstance(vrfTableKey.getRouteDistinguisher());
if (vpnInstance == null) {
LOG.error("VPN Instance for rd {} is not available from VPN Op Instance Datastore", rd);
return;
}
final Collection<VpnToDpnList> vpnToDpnList;
if (vrfEntry.getParentVpnRd() != null && FibHelper.isControllerManagedNonSelfImportedRoute(RouteOrigin.value(vrfEntry.getOrigin()))) {
// This block MUST BE HIT only for PNF (Physical Network Function) FIB Entries.
VpnInstanceOpDataEntry parentVpnInstance = fibUtil.getVpnInstance(vrfEntry.getParentVpnRd());
vpnToDpnList = parentVpnInstance != null ? parentVpnInstance.getVpnToDpnList() : vpnInstance.getVpnToDpnList();
LOG.info("deleteFibEntries: Processing deletion of PNF FIB entry with rd {} prefix {}", vrfEntry.getParentVpnRd(), vrfEntry.getDestPrefix());
} else {
vpnToDpnList = vpnInstance.getVpnToDpnList();
}
SubnetRoute subnetRoute = vrfEntry.getAugmentation(SubnetRoute.class);
final java.util.Optional<Long> optionalLabel = FibUtil.getLabelFromRoutePaths(vrfEntry);
List<String> nextHopAddressList = FibHelper.getNextHopListFromRoutePaths(vrfEntry);
String vpnName = fibUtil.getVpnNameFromId(vpnInstance.getVpnId());
if (subnetRoute != null) {
long elanTag = subnetRoute.getElantag();
LOG.trace("SUBNETROUTE: deleteFibEntries: SubnetRoute augmented vrfentry found for rd {} prefix {}" + " with elantag {}", rd, vrfEntry.getDestPrefix(), elanTag);
if (vpnToDpnList != null) {
jobCoordinator.enqueueJob(FibUtil.getJobKeyForRdPrefix(rd, vrfEntry.getDestPrefix()), () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
for (final VpnToDpnList curDpn : vpnToDpnList) {
baseVrfEntryHandler.makeConnectedRoute(curDpn.getDpnId(), vpnInstance.getVpnId(), vrfEntry, vrfTableKey.getRouteDistinguisher(), null, NwConstants.DEL_FLOW, tx, null);
if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.SELF_IMPORTED) {
optionalLabel.ifPresent(label -> makeLFibTableEntry(curDpn.getDpnId(), label, null, DEFAULT_FIB_FLOW_PRIORITY, NwConstants.DEL_FLOW, tx));
}
installSubnetBroadcastAddrDropRule(curDpn.getDpnId(), rd, vpnInstance.getVpnId(), vrfEntry, NwConstants.DEL_FLOW, tx);
}
})));
}
optionalLabel.ifPresent(label -> {
synchronized (label.toString().intern()) {
LabelRouteInfo lri = getLabelRouteInfo(label);
if (isPrefixAndNextHopPresentInLri(vrfEntry.getDestPrefix(), nextHopAddressList, lri)) {
Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataEntryOptional = fibUtil.getVpnInstanceOpData(rd);
String vpnInstanceName = "";
if (vpnInstanceOpDataEntryOptional.isPresent()) {
vpnInstanceName = vpnInstanceOpDataEntryOptional.get().getVpnInstanceName();
}
boolean lriRemoved = this.deleteLabelRouteInfo(lri, vpnInstanceName, null);
if (lriRemoved) {
String parentRd = lri.getParentVpnRd();
fibUtil.releaseId(FibConstants.VPN_IDPOOL_NAME, FibUtil.getNextHopLabelKey(parentRd, vrfEntry.getDestPrefix()));
LOG.trace("SUBNETROUTE: deleteFibEntries: Released subnetroute label {} for rd {} prefix {}" + " as labelRouteInfo cleared", label, rd, vrfEntry.getDestPrefix());
}
} else {
fibUtil.releaseId(FibConstants.VPN_IDPOOL_NAME, FibUtil.getNextHopLabelKey(rd, vrfEntry.getDestPrefix()));
LOG.trace("SUBNETROUTE: deleteFibEntries: Released subnetroute label {} for rd {} prefix {}", label, rd, vrfEntry.getDestPrefix());
}
}
});
return;
}
final List<BigInteger> localDpnIdList = deleteLocalFibEntry(vpnInstance.getVpnId(), vrfTableKey.getRouteDistinguisher(), vrfEntry);
if (vpnToDpnList != null) {
List<String> usedRds = VpnExtraRouteHelper.getUsedRds(dataBroker, vpnInstance.getVpnId(), vrfEntry.getDestPrefix());
String jobKey;
Optional<Routes> extraRouteOptional;
// Is this fib route an extra route? If yes, get the nexthop which would be an adjacency in the vpn
if (usedRds != null && !usedRds.isEmpty()) {
jobKey = FibUtil.getJobKeyForRdPrefix(usedRds.get(0), vrfEntry.getDestPrefix());
if (usedRds.size() > 1) {
LOG.error("The extra route prefix is still present in some DPNs");
return;
} else {
// The first rd is retrieved from usedrds as Only 1 rd would be present as extra route prefix
// is not present in any other DPN
extraRouteOptional = VpnExtraRouteHelper.getVpnExtraroutes(dataBroker, vpnName, usedRds.get(0), vrfEntry.getDestPrefix());
}
} else {
jobKey = FibUtil.getJobKeyForRdPrefix(rd, vrfEntry.getDestPrefix());
extraRouteOptional = Optional.absent();
}
jobCoordinator.enqueueJob(jobKey, () -> {
WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
if (localDpnIdList.size() <= 0) {
for (VpnToDpnList curDpn : vpnToDpnList) {
baseVrfEntryHandler.deleteRemoteRoute(BigInteger.ZERO, curDpn.getDpnId(), vpnInstance.getVpnId(), vrfTableKey, vrfEntry, extraRouteOptional, tx);
}
} else {
for (BigInteger localDpnId : localDpnIdList) {
for (VpnToDpnList curDpn : vpnToDpnList) {
if (!curDpn.getDpnId().equals(localDpnId)) {
baseVrfEntryHandler.deleteRemoteRoute(localDpnId, curDpn.getDpnId(), vpnInstance.getVpnId(), vrfTableKey, vrfEntry, extraRouteOptional, tx);
}
}
}
}
List<ListenableFuture<Void>> futures = new ArrayList<>();
futures.add(tx.submit());
return futures;
}, MAX_RETRIES);
}
// The flow/group entry has been deleted from config DS; need to clean up associated operational
// DS entries in VPN Op DS, VpnInstanceOpData and PrefixToInterface to complete deletion
cleanUpOpDataForFib(vpnInstance.getVpnId(), vrfTableKey.getRouteDistinguisher(), vrfEntry);
// Remove all fib entries configured due to interVpnLink, when nexthop is the opposite endPoint
// of the interVpnLink.
Optional<String> optVpnUuid = fibUtil.getVpnNameFromRd(rd);
if (optVpnUuid.isPresent()) {
String vpnUuid = optVpnUuid.get();
FibUtil.getFirstNextHopAddress(vrfEntry).ifPresent(routeNexthop -> {
Optional<InterVpnLinkDataComposite> optInterVpnLink = interVpnLinkCache.getInterVpnLinkByVpnId(vpnUuid);
if (optInterVpnLink.isPresent()) {
InterVpnLinkDataComposite interVpnLink = optInterVpnLink.get();
if (interVpnLink.isIpAddrTheOtherVpnEndpoint(routeNexthop, vpnUuid)) {
// This is route that points to the other endpoint of an InterVpnLink
// In that case, we should look for the FIB table pointing to
// LPortDispatcher table and remove it.
removeInterVPNLinkRouteFlows(interVpnLink, vpnUuid, vrfEntry);
}
}
});
}
}
use of org.opendaylight.netvirt.vpnmanager.api.intervpnlink.InterVpnLinkDataComposite in project netvirt by opendaylight.
the class IVpnLinkServiceImpl method leakRouteIfNeeded.
@Override
public void leakRouteIfNeeded(String vpnName, String prefix, List<String> nextHopList, int label, RouteOrigin origin, int addOrRemove) {
Optional<InterVpnLinkDataComposite> optIVpnLink = interVpnLinkCache.getInterVpnLinkByVpnId(vpnName);
if (!optIVpnLink.isPresent()) {
LOG.debug("Vpn {} not involved in any InterVpnLink", vpnName);
return;
}
InterVpnLinkDataComposite ivpnLink = optIVpnLink.get();
if (addOrRemove == NwConstants.ADD_FLOW && !ivpnLink.isActive()) {
// Note: for the removal case it is not necessary that ivpnlink is ACTIVE
LOG.debug("Route to {} in VPN {} cannot be leaked because InterVpnLink {} is not ACTIVE", prefix, vpnName, ivpnLink.getInterVpnLinkName());
return;
}
switch(origin) {
case BGP:
if (!ivpnLink.isBgpRoutesLeaking()) {
LOG.debug("BGP route to {} not leaked because bgp-routes-leaking is disabled", prefix);
return;
}
leakRoute(vpnName, prefix, nextHopList, label, addOrRemove);
break;
case STATIC:
/* NOTE: There are 2 types of static routes depending on the next hop:
+ static route when next hop is a VM, the DC-GW or a DPNIP
+ static route when next hop is an Inter-VPN Link
Only the 1st type should be considered since the 2nd has a special treatment */
if (!ivpnLink.isStaticRoutesLeaking()) {
LOG.debug("Static route to {} not leaked because static-routes-leaking is disabled", prefix);
return;
}
leakRoute(vpnName, prefix, nextHopList, label, addOrRemove);
break;
case CONNECTED:
if (!ivpnLink.isConnectedRoutesLeaking()) {
LOG.debug("Connected route to {} not leaked because connected-routes-leaking is disabled", prefix);
return;
}
leakRoute(vpnName, prefix, nextHopList, label, addOrRemove);
break;
default:
LOG.warn("origin {} not considered in Route-leaking", origin.getValue());
}
}
use of org.opendaylight.netvirt.vpnmanager.api.intervpnlink.InterVpnLinkDataComposite in project netvirt by opendaylight.
the class IVpnLinkServiceImpl method leakExtraRoutesToVpnEndpoint.
/*
* Checks if there are static routes in Vpn1 whose nexthop is Vpn2's endpoint.
* Those routes must be leaked to Vpn1.
*
* @param vpnLink
* @param vpn1Uuid
* @param vpn2Uuid
*/
private void leakExtraRoutesToVpnEndpoint(InterVpnLinkDataComposite vpnLink, String vpn1Uuid, String vpn2Uuid) {
String vpn1Rd = VpnUtil.getVpnRd(dataBroker, vpn1Uuid);
String vpn2Endpoint = vpnLink.getOtherEndpointIpAddr(vpn2Uuid);
List<VrfEntry> allVpnVrfEntries = VpnUtil.getAllVrfEntries(dataBroker, vpn1Rd);
for (VrfEntry vrfEntry : allVpnVrfEntries) {
vrfEntry.getRoutePaths().stream().filter(routePath -> routePath.getNexthopAddress().equals(vpn2Endpoint)).forEach(routePath -> {
// Vpn1 has a route pointing to Vpn2's endpoint. Forcing the leaking of the route will update
// the BGP accordingly
long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, VpnUtil.getNextHopLabelKey(vpn1Rd, vrfEntry.getDestPrefix()));
if (label == VpnConstants.INVALID_LABEL) {
LOG.error("Unable to fetch label from Id Manager. Bailing out of leaking extra routes for " + "InterVpnLink {} rd {} prefix {}", vpnLink.getInterVpnLinkName(), vpn1Rd, vrfEntry.getDestPrefix());
} else {
leakRoute(vpnLink, vpn2Uuid, vpn1Uuid, vrfEntry.getDestPrefix(), label, RouteOrigin.value(vrfEntry.getOrigin()));
}
});
}
}
use of org.opendaylight.netvirt.vpnmanager.api.intervpnlink.InterVpnLinkDataComposite in project netvirt by opendaylight.
the class InterVpnLinkCacheImpl method removeInterVpnLinkStateFromCache.
@Override
public void removeInterVpnLinkStateFromCache(InterVpnLinkState interVpnLinkState) {
Optional<InterVpnLinkDataComposite> optIVpnLinkComposite = getInterVpnLinkByName(interVpnLinkState.getInterVpnLinkName());
if (optIVpnLinkComposite.isPresent()) {
InterVpnLinkDataComposite interVpnLinkComposite = optIVpnLinkComposite.get();
removeFromEndpointIpAddressCache(interVpnLinkComposite);
removeFromVpnUuidCache(interVpnLinkComposite);
removeFromInterVpnLinkNameCache(interVpnLinkComposite);
}
}
Aggregations