use of org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.l3vpn.lb.nexthops.Nexthops in project netvirt by opendaylight.
the class InterVpnLinkUtil method leakRoute.
/**
* Leaks a route from one VPN to another. By default, the origin for this leaked route is INTERVPN.
*
* @param broker dataBroker service reference
* @param bgpManager Used to advertise routes to the BGP Router
* @param interVpnLink Reference to the object that holds the info about the link between the 2 VPNs
* @param srcVpnUuid UUID of the VPN that has the route that is going to be leaked to the other VPN
* @param dstVpnUuid UUID of the VPN that is going to receive the route
* @param prefix Prefix of the route
* @param label Label of the route in the original VPN
*/
// TODO Clean up the exception handling
@SuppressWarnings("checkstyle:IllegalCatch")
public static void leakRoute(DataBroker broker, IBgpManager bgpManager, InterVpnLink interVpnLink, String srcVpnUuid, String dstVpnUuid, String prefix, Long label) {
Preconditions.checkNotNull(interVpnLink);
// The source VPN must participate in the InterVpnLink
Preconditions.checkArgument(interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(srcVpnUuid) || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(srcVpnUuid), "The source VPN {} does not participate in the interVpnLink {}", srcVpnUuid, interVpnLink.getName());
// The destination VPN must participate in the InterVpnLink
Preconditions.checkArgument(interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(dstVpnUuid) || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(dstVpnUuid), "The destination VPN {} does not participate in the interVpnLink {}", dstVpnUuid, interVpnLink.getName());
boolean destinationIs1stEndpoint = interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(dstVpnUuid);
String endpointIp = destinationIs1stEndpoint ? interVpnLink.getSecondEndpoint().getIpAddress().getValue() : interVpnLink.getFirstEndpoint().getIpAddress().getValue();
VrfEntry newVrfEntry = FibHelper.getVrfEntryBuilder(prefix, label, endpointIp, RouteOrigin.INTERVPN, null).build();
String dstVpnRd = VpnUtil.getVpnRd(broker, dstVpnUuid);
InstanceIdentifier<VrfEntry> newVrfEntryIid = InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(dstVpnRd)).child(VrfEntry.class, new VrfEntryKey(newVrfEntry.getDestPrefix())).build();
VpnUtil.asyncWrite(broker, LogicalDatastoreType.CONFIGURATION, newVrfEntryIid, newVrfEntry);
// Finally, route is advertised it to the DC-GW. But while in the FibEntries the nexthop is the other
// endpoint's IP, in the DC-GW the nexthop for those prefixes are the IPs of those DPNs where the target
// VPN has been instantiated
Optional<InterVpnLinkState> optVpnLinkState = getInterVpnLinkState(broker, interVpnLink.getName());
if (optVpnLinkState.isPresent()) {
InterVpnLinkState vpnLinkState = optVpnLinkState.get();
List<BigInteger> dpnIdList = destinationIs1stEndpoint ? vpnLinkState.getFirstEndpointState().getDpId() : vpnLinkState.getSecondEndpointState().getDpId();
List<String> nexthops = new ArrayList<>();
for (BigInteger dpnId : dpnIdList) {
nexthops.add(InterfaceUtils.getEndpointIpAddressForDPN(broker, dpnId));
}
try {
LOG.debug("Advertising route in VPN={} [prefix={} label={} nexthops={}] to DC-GW", dstVpnRd, newVrfEntry.getDestPrefix(), label.intValue(), nexthops);
bgpManager.advertisePrefix(dstVpnRd, null, /*macAddress*/
newVrfEntry.getDestPrefix(), nexthops, VrfEntry.EncapType.Mplsgre, label.intValue(), 0, /*l3vni*/
0, /*l2vni*/
null);
} catch (Exception ex) {
LOG.error("Could not advertise prefix {} with label {} to VPN rd={}", newVrfEntry.getDestPrefix(), label.intValue(), dstVpnRd, ex);
}
} else {
LOG.warn("Error when advertising leaked routes: Could not find State for InterVpnLink={}", interVpnLink.getName());
}
}
use of org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.l3vpn.lb.nexthops.Nexthops in project netvirt by opendaylight.
the class FibUtil method updateUsedRdAndVpnToExtraRoute.
public void updateUsedRdAndVpnToExtraRoute(WriteTransaction writeOperTxn, String tunnelIpRemoved, String primaryRd, String prefix) {
Optional<VpnInstanceOpDataEntry> optVpnInstance = getVpnInstanceOpData(primaryRd);
if (!optVpnInstance.isPresent()) {
return;
}
VpnInstanceOpDataEntry vpnInstance = optVpnInstance.get();
String vpnName = vpnInstance.getVpnInstanceName();
long vpnId = vpnInstance.getVpnId();
List<String> usedRds = VpnExtraRouteHelper.getUsedRds(dataBroker, vpnId, prefix);
// which rd is allocated for the particular OVS.
for (String usedRd : usedRds) {
Optional<Routes> vpnExtraRoutes = VpnExtraRouteHelper.getVpnExtraroutes(dataBroker, vpnName, usedRd, prefix);
if (vpnExtraRoutes.isPresent()) {
// Since all the nexthops under one OVS will be present under one rd, only 1 nexthop is read
// to identify the OVS
String nextHopRemoved = vpnExtraRoutes.get().getNexthopIpList().get(0);
Prefixes prefixToInterface = getPrefixToInterface(vpnId, getIpPrefix(nextHopRemoved));
if (prefixToInterface != null && tunnelIpRemoved.equals(getEndpointIpAddressForDPN(prefixToInterface.getDpnId()))) {
InstanceIdentifier<Adjacency> adjId = getAdjacencyIdentifier(prefixToInterface.getVpnInterfaceName(), prefix);
Interface ifState = getInterfaceStateFromOperDS(prefixToInterface.getVpnInterfaceName());
// Delete datastore only if extra route is deleted or VM interface is deleted/down
if (!MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, adjId).isPresent() || ifState == null || ifState.getOperStatus() == OperStatus.Down) {
writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, getAdjacencyIdentifier(prefixToInterface.getVpnInterfaceName(), prefix));
writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, VpnExtraRouteHelper.getVpnToExtrarouteVrfIdIdentifier(vpnName, usedRd, prefix));
writeOperTxn.delete(LogicalDatastoreType.CONFIGURATION, VpnExtraRouteHelper.getUsedRdsIdentifier(vpnId, prefix, nextHopRemoved));
break;
}
}
}
}
}
use of org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.l3vpn.lb.nexthops.Nexthops in project netvirt by opendaylight.
the class FibUtil method updateLbGroupInfo.
public static void updateLbGroupInfo(BigInteger dpnId, String destinationIp, String groupIdKey, String groupId, WriteTransaction tx) {
InstanceIdentifier<DpnLbNexthops> id = getDpnLbNexthopsIdentifier(dpnId, destinationIp);
DpnLbNexthops dpnToLbNextHop = buildDpnLbNextHops(dpnId, destinationIp, groupIdKey);
tx.merge(LogicalDatastoreType.OPERATIONAL, id, dpnToLbNextHop);
InstanceIdentifier<Nexthops> nextHopsId = getNextHopsIdentifier(groupIdKey);
Nexthops nextHopsToGroupId = buildNextHops(dpnId, groupIdKey, groupId);
tx.merge(LogicalDatastoreType.OPERATIONAL, nextHopsId, nextHopsToGroupId);
}
use of org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.l3vpn.lb.nexthops.Nexthops in project netvirt by opendaylight.
the class NexthopManager method updateDcGwLoadBalancingGroup.
/**
* This method is invoked when the tunnel status is updated.
* The bucket is directly removed/added based on the operational status of the tunnel.
*/
public void updateDcGwLoadBalancingGroup(List<String> availableDcGws, BigInteger dpnId, String destinationIp, boolean isTunnelUp) {
Preconditions.checkNotNull(availableDcGws, "There are no dc-gws present");
WriteTransaction configTx = dataBroker.newWriteOnlyTransaction();
// TODO : Place the logic to construct all possible DC-GW combination here.
int bucketId = availableDcGws.indexOf(destinationIp);
Optional<DpnLbNexthops> dpnLbNextHops = fibUtil.getDpnLbNexthops(dpnId, destinationIp);
if (!dpnLbNextHops.isPresent()) {
return;
}
List<String> nextHopKeys = dpnLbNextHops.get().getNexthopKey();
nextHopKeys.forEach(nextHopKey -> {
Optional<Nexthops> optionalNextHops = fibUtil.getNexthops(nextHopKey);
if (!optionalNextHops.isPresent()) {
return;
}
Nexthops nexthops = optionalNextHops.get();
final String groupId = nexthops.getGroupId();
final long groupIdValue = Long.parseLong(groupId);
if (isTunnelUp) {
Bucket bucket = buildBucketForDcGwLbGroup(destinationIp, dpnId, bucketId);
LOG.trace("Added bucket {} to group {} on dpn {}.", bucket, groupId, dpnId);
mdsalApiManager.addBucketToTx(dpnId, groupIdValue, bucket, configTx);
} else {
LOG.trace("Removed bucketId {} from group {} on dpn {}.", bucketId, groupId, dpnId);
mdsalApiManager.removeBucketToTx(dpnId, groupIdValue, bucketId, configTx);
}
});
configTx.submit();
return;
}
use of org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.l3vpn.lb.nexthops.Nexthops in project netvirt by opendaylight.
the class VrfEntryListener method update.
@Override
// originalRoutePath is a little dicey - safest to keep the checking even if not needed.
@SuppressFBWarnings("RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE")
protected void update(InstanceIdentifier<VrfEntry> identifier, VrfEntry original, VrfEntry update) {
Preconditions.checkNotNull(update, "VrfEntry should not be null or empty.");
final String rd = identifier.firstKeyOf(VrfTables.class).getRouteDistinguisher();
LOG.debug("UPDATE: Updating Fib Entries to rd {} prefix {} route-paths {} origin {} old-origin {}", rd, update.getDestPrefix(), update.getRoutePaths(), update.getOrigin(), original.getOrigin());
// Handle BGP Routes first
if (RouteOrigin.value(update.getOrigin()) == RouteOrigin.BGP) {
bgpRouteVrfEntryHandler.updateFlows(identifier, original, update, rd);
LOG.info("UPDATE: Updated BGP advertised Fib Entry with rd {} prefix {} route-paths {}", rd, update.getDestPrefix(), update.getRoutePaths());
return;
}
if (RouteOrigin.value(update.getOrigin()) == RouteOrigin.STATIC) {
List<RoutePaths> originalRoutePath = original.getRoutePaths();
List<RoutePaths> updateRoutePath = update.getRoutePaths();
LOG.info("UPDATE: Original route-path {} update route-path {} ", originalRoutePath, updateRoutePath);
// Updates need to be handled for extraroute even if original vrf entry route path is null or
// updated vrf entry route path is null. This can happen during tunnel events.
Optional<VpnInstanceOpDataEntry> optVpnInstance = fibUtil.getVpnInstanceOpData(rd);
List<String> usedRds = new ArrayList<>();
if (optVpnInstance.isPresent()) {
usedRds = VpnExtraRouteHelper.getUsedRds(dataBroker, optVpnInstance.get().getVpnId(), update.getDestPrefix());
}
// has nexthop , route needs to be created on remote Dpns
if (originalRoutePath == null || originalRoutePath.isEmpty() && updateRoutePath != null && !updateRoutePath.isEmpty() && usedRds.isEmpty()) {
// TODO(vivek): Though ugly, Not handling this code now, as each
// tep add event will invoke flow addition
LOG.trace("Original VRF entry NH is null for destprefix {}. And the prefix is not an extra route." + " This event is IGNORED here.", update.getDestPrefix());
return;
}
// has nexthop empty'ed out, route needs to be removed from remote Dpns
if (updateRoutePath == null || updateRoutePath.isEmpty() && originalRoutePath != null && !originalRoutePath.isEmpty() && usedRds.isEmpty()) {
LOG.trace("Original VRF entry had valid NH for destprefix {}. And the prefix is not an extra route." + "This event is IGNORED here.", update.getDestPrefix());
return;
}
// Update the used rds and vpntoextraroute containers only for the deleted nextHops.
List<String> nextHopsRemoved = FibHelper.getNextHopListFromRoutePaths(original);
nextHopsRemoved.removeAll(FibHelper.getNextHopListFromRoutePaths(update));
WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
nextHopsRemoved.parallelStream().forEach(nextHopRemoved -> fibUtil.updateUsedRdAndVpnToExtraRoute(writeOperTxn, nextHopRemoved, rd, update.getDestPrefix()));
CheckedFuture<Void, TransactionCommitFailedException> operFuture = writeOperTxn.submit();
try {
operFuture.get();
} catch (InterruptedException | ExecutionException e) {
LOG.error("Exception encountered while submitting operational future for update vrfentry {}", update, e);
}
createFibEntries(identifier, update);
LOG.info("UPDATE: Updated static Fib Entry with rd {} prefix {} route-paths {}", rd, update.getDestPrefix(), update.getRoutePaths());
return;
}
// Handle all other routes only on a cluster reboot
if (original.equals(update)) {
// Reboot use-case
createFibEntries(identifier, update);
LOG.info("UPDATE: Updated Non-static Fib Entry with rd {} prefix {} route-paths {}", rd, update.getDestPrefix(), update.getRoutePaths());
return;
}
LOG.info("UPDATE: Ignoring update for FIB entry with rd {} prefix {} route-origin {} route-paths {}", rd, update.getDestPrefix(), update.getOrigin(), update.getRoutePaths());
}
Aggregations