use of org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.replies.result.success._case.success.Paths in project netvirt by opendaylight.
the class NexthopManager method getBucketsForRemoteNexthop.
private List<BucketInfo> getBucketsForRemoteNexthop(Long vpnId, BigInteger dpnId, VrfEntry vrfEntry, String rd, List<Routes> vpnExtraRoutes) {
List<BucketInfo> listBucketInfo = new ArrayList<>();
Map<String, List<ActionInfo>> egressActionMap = new HashMap<>();
vpnExtraRoutes.forEach(vpnExtraRoute -> vpnExtraRoute.getNexthopIpList().forEach(nextHopIp -> {
String nextHopPrefixIp;
if (isIpv4Address(nextHopIp)) {
nextHopPrefixIp = nextHopIp + NwConstants.IPV4PREFIX;
} else {
nextHopPrefixIp = nextHopIp + NwConstants.IPV6PREFIX;
}
List<String> tepIpAddresses = fibUtil.getNextHopAddresses(rd, nextHopPrefixIp);
if (tepIpAddresses.isEmpty()) {
return;
}
// There would be only one nexthop address for a VM ip which would be the tep Ip
String tepIp = tepIpAddresses.get(0);
AdjacencyResult adjacencyResult = getRemoteNextHopPointer(dpnId, vpnId, vrfEntry.getDestPrefix(), tepIp);
if (adjacencyResult == null) {
return;
}
String egressInterface = adjacencyResult.getInterfaceName();
if (!FibUtil.isTunnelInterface(adjacencyResult)) {
return;
}
Class<? extends TunnelTypeBase> tunnelType = VpnExtraRouteHelper.getTunnelType(interfaceManager, egressInterface);
Interface ifState = fibUtil.getInterfaceStateFromOperDS(egressInterface);
if (ifState == null || ifState.getOperStatus() != OperStatus.Up) {
LOG.trace("Tunnel not up {}", egressInterface);
return;
}
if (!TunnelTypeVxlan.class.equals(tunnelType)) {
return;
}
Long label = FibUtil.getLabelFromRoutePaths(vrfEntry).get();
Prefixes prefixInfo = fibUtil.getPrefixToInterface(vpnId, nextHopPrefixIp);
BigInteger tunnelId;
if (fibUtil.enforceVxlanDatapathSemanticsforInternalRouterVpn(prefixInfo.getSubnetId(), vpnId, rd)) {
java.util.Optional<Long> optionalVni = fibUtil.getVniForVxlanNetwork(prefixInfo.getSubnetId());
if (!optionalVni.isPresent()) {
LOG.error("VNI not found for nexthop {} vrfEntry {} with subnetId {}", nextHopIp, vrfEntry, prefixInfo.getSubnetId());
return;
}
tunnelId = BigInteger.valueOf(optionalVni.get());
} else {
tunnelId = BigInteger.valueOf(label);
}
List<ActionInfo> actionInfos = new ArrayList<>();
actionInfos.add(new ActionSetFieldTunnelId(tunnelId));
String ifName = prefixInfo.getVpnInterfaceName();
String vpnName = fibUtil.getVpnNameFromId(vpnId);
if (vpnName == null) {
return;
}
String macAddress = fibUtil.getMacAddressFromPrefix(ifName, vpnName, nextHopPrefixIp);
actionInfos.add(new ActionSetFieldEthernetDestination(actionInfos.size(), new MacAddress(macAddress)));
List<ActionInfo> egressActions;
if (egressActionMap.containsKey(egressInterface)) {
egressActions = egressActionMap.get(egressInterface);
} else {
egressActions = getEgressActionsForInterface(egressInterface, actionInfos.size());
egressActionMap.put(egressInterface, egressActions);
}
if (egressActions.isEmpty()) {
LOG.error("Failed to retrieve egress action for prefix {} route-paths {}" + " interface {}." + " Aborting remote FIB entry creation.", vrfEntry.getDestPrefix(), vrfEntry.getRoutePaths(), egressInterface);
}
actionInfos.addAll(egressActions);
BucketInfo bucket = new BucketInfo(actionInfos);
bucket.setWeight(1);
listBucketInfo.add(bucket);
}));
LOG.trace("LOCAL: listbucket {}, rd {}, dpnId {}, routes {}", listBucketInfo, rd, dpnId, vpnExtraRoutes);
return listBucketInfo;
}
use of org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.replies.result.success._case.success.Paths 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());
}
use of org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.replies.result.success._case.success.Paths in project netvirt by opendaylight.
the class VrfEntryListener method installIVpnLinkSwitchingFlows.
/*
* Installs the flows in FIB table that, for a given route, do the switching from one VPN to the other.
*/
private void installIVpnLinkSwitchingFlows(final InterVpnLinkDataComposite interVpnLink, final String vpnUuid, final VrfEntry vrfEntry, long vpnTag) {
Preconditions.checkNotNull(interVpnLink, "InterVpnLink cannot be null");
Preconditions.checkArgument(vrfEntry.getRoutePaths() != null && vrfEntry.getRoutePaths().size() == 1);
String destination = vrfEntry.getDestPrefix();
String nextHop = vrfEntry.getRoutePaths().get(0).getNexthopAddress();
String interVpnLinkName = interVpnLink.getInterVpnLinkName();
// using as metadata the LPortTag associated to that vpn in the inter-vpn-link.
if (interVpnLink.getState().or(State.Error) != State.Active) {
LOG.warn("Route to {} with nexthop={} cannot be installed because the interVpnLink {} is not active", destination, nextHop, interVpnLinkName);
return;
}
Optional<Long> optOtherEndpointLportTag = interVpnLink.getOtherEndpointLportTagByVpnName(vpnUuid);
if (!optOtherEndpointLportTag.isPresent()) {
LOG.warn("Could not find suitable LportTag for the endpoint opposite to vpn {} in interVpnLink {}", vpnUuid, interVpnLinkName);
return;
}
List<BigInteger> targetDpns = interVpnLink.getEndpointDpnsByVpnName(vpnUuid);
if (targetDpns.isEmpty()) {
LOG.warn("Could not find DPNs for endpoint opposite to vpn {} in interVpnLink {}", vpnUuid, interVpnLinkName);
return;
}
String[] values = destination.split("/");
String destPrefixIpAddress = values[0];
int prefixLength = values.length == 1 ? 0 : Integer.parseInt(values[1]);
List<MatchInfo> matches = new ArrayList<>();
matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(vpnTag), MetaDataUtil.METADATA_MASK_VRFID));
matches.add(MatchEthernetType.IPV4);
if (prefixLength != 0) {
matches.add(new MatchIpv4Destination(destPrefixIpAddress, Integer.toString(prefixLength)));
}
List<Instruction> instructions = Arrays.asList(new InstructionWriteMetadata(MetaDataUtil.getMetaDataForLPortDispatcher(optOtherEndpointLportTag.get().intValue(), ServiceIndex.getIndex(NwConstants.L3VPN_SERVICE_NAME, NwConstants.L3VPN_SERVICE_INDEX)), MetaDataUtil.getMetaDataMaskForLPortDispatcher()).buildInstruction(0), new InstructionGotoTable(NwConstants.L3_INTERFACE_TABLE).buildInstruction(1));
int priority = DEFAULT_FIB_FLOW_PRIORITY + prefixLength;
String flowRef = getInterVpnFibFlowRef(interVpnLinkName, destination, nextHop);
Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_FIB_TABLE, flowRef, priority, flowRef, 0, 0, COOKIE_VM_FIB_TABLE, matches, instructions);
LOG.trace("Installing flow in FIB table for vpn {} interVpnLink {} nextHop {} key {}", vpnUuid, interVpnLink.getInterVpnLinkName(), nextHop, flowRef);
for (BigInteger dpId : targetDpns) {
LOG.debug("Installing flow: VrfEntry=[prefix={} route-paths={}] dpn {} for InterVpnLink {} in FIB", vrfEntry.getDestPrefix(), vrfEntry.getRoutePaths(), dpId, interVpnLink.getInterVpnLinkName());
mdsalManager.installFlow(dpId, flowEntity);
}
}
use of org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.replies.result.success._case.success.Paths in project openflowplugin by opendaylight.
the class StackedOutboundQueueNoBarrier method writeEntries.
@Override
int writeEntries(@Nonnull final Channel channel, final long now) {
// Local cache
StackedSegment segment = firstSegment;
int entries = 0;
while (channel.isWritable()) {
final OutboundQueueEntry entry = segment.getEntry(flushOffset);
if (!entry.isCommitted()) {
LOG.debug("Queue {} XID {} segment {} offset {} not committed yet", this, segment.getBaseXid() + flushOffset, segment, flushOffset);
break;
}
LOG.trace("Queue {} flushing entry at offset {}", this, flushOffset);
final OfHeader message = entry.takeMessage();
flushOffset++;
entries++;
if (message != null) {
manager.writeMessage(message, now);
} else {
entry.complete(null);
}
if (flushOffset >= StackedSegment.SEGMENT_SIZE) {
/*
* Slow path: purge the current segment unless it's the last one.
* If it is, we leave it for replacement when a new reservation
* is run on it.
* This costs us two slow paths, but hey, this should be very rare,
* so let's keep things simple.
*/
synchronized (unflushedSegments) {
LOG.debug("Flush offset {} unflushed segments {}", flushOffset, unflushedSegments.size());
// We may have raced ahead of reservation code and need to allocate a segment
ensureSegment(segment, flushOffset);
// Remove the segment, update the firstSegment and reset flushOffset
final StackedSegment oldSegment = unflushedSegments.remove(0);
oldSegment.completeAll();
uncompletedSegments.remove(oldSegment);
oldSegment.recycle();
// Reset the first segment and add it to the uncompleted list
segment = unflushedSegments.get(0);
uncompletedSegments.add(segment);
// Update the shutdown offset
if (shutdownOffset != null) {
shutdownOffset -= StackedSegment.SEGMENT_SIZE;
}
// Allow reservations back on the fast path by publishing the new first segment
firstSegment = segment;
flushOffset = 0;
LOG.debug("Queue {} flush moved to segment {}", this, segment);
}
}
}
return entries;
}
use of org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.replies.result.success._case.success.Paths in project openflowplugin by opendaylight.
the class AbstractStackedOutboundQueue method writeEntries.
/**
* Write some entries from the queue to the channel. Guaranteed to run
* in the corresponding EventLoop.
*
* @param channel Channel onto which we are writing
* @param now time stamp
* @return Number of entries written out
*/
int writeEntries(@Nonnull final Channel channel, final long now) {
// Local cache
StackedSegment segment = firstSegment;
int entries = 0;
while (channel.isWritable()) {
final OutboundQueueEntry entry = segment.getEntry(flushOffset);
if (!entry.isCommitted()) {
LOG.debug("Queue {} XID {} segment {} offset {} not committed yet", this, segment.getBaseXid() + flushOffset, segment, flushOffset);
break;
}
LOG.trace("Queue {} flushing entry at offset {}", this, flushOffset);
final OfHeader message = entry.takeMessage();
flushOffset++;
entries++;
if (message != null) {
manager.writeMessage(message, now);
} else {
entry.complete(null);
}
if (flushOffset >= StackedSegment.SEGMENT_SIZE) {
/*
* Slow path: purge the current segment unless it's the last one.
* If it is, we leave it for replacement when a new reservation
* is run on it.
*
* This costs us two slow paths, but hey, this should be very rare,
* so let's keep things simple.
*/
synchronized (unflushedSegments) {
LOG.debug("Flush offset {} unflushed segments {}", flushOffset, unflushedSegments.size());
// We may have raced ahead of reservation code and need to allocate a segment
ensureSegment(segment, flushOffset);
// Remove the segment, update the firstSegment and reset flushOffset
final StackedSegment oldSegment = unflushedSegments.remove(0);
if (oldSegment.isComplete()) {
uncompletedSegments.remove(oldSegment);
oldSegment.recycle();
}
// Reset the first segment and add it to the uncompleted list
segment = unflushedSegments.get(0);
uncompletedSegments.add(segment);
// Update the shutdown offset
if (shutdownOffset != null) {
shutdownOffset -= StackedSegment.SEGMENT_SIZE;
}
// Allow reservations back on the fast path by publishing the new first segment
firstSegment = segment;
flushOffset = 0;
LOG.debug("Queue {} flush moved to segment {}", this, segment);
}
}
}
return entries;
}
Aggregations