use of org.openkilda.model.PathSegment in project open-kilda by telstra.
the class PersistenceDummyEntityFactory method makeFlowPathPair.
private void makeFlowPathPair(Flow flow, FlowEndpoint source, FlowEndpoint dest, List<IslDirectionalReference> forwardPathHint, List<String> tags) {
long flowEffectiveId = idProvider.provideFlowEffectiveId();
makeFlowCookie(flow.getFlowId(), flowEffectiveId);
List<IslDirectionalReference> reversePathHint = forwardPathHint.stream().map(IslDirectionalReference::makeOpposite).collect(Collectors.toList());
// inline
Collections.reverse(reversePathHint);
PathId forwardPathId = idProvider.providePathId(flow.getFlowId(), Stream.concat(tags.stream(), Stream.of("forward")));
List<PathSegment> forwardSegments = makePathSegments(forwardPathId, source.getSwitchId(), dest.getSwitchId(), forwardPathHint);
flow.setForwardPath(makePath(flow, source, dest, forwardPathId, forwardSegments, new FlowSegmentCookie(FlowPathDirection.FORWARD, flowEffectiveId)));
PathId reversePathId = idProvider.providePathId(flow.getFlowId(), Stream.concat(tags.stream(), Stream.of("reverse")));
List<PathSegment> reverseSegments = makePathSegments(reversePathId, dest.getSwitchId(), source.getSwitchId(), reversePathHint);
flow.setReversePath(makePath(flow, dest, source, reversePathId, reverseSegments, new FlowSegmentCookie(FlowPathDirection.REVERSE, flowEffectiveId)));
}
use of org.openkilda.model.PathSegment in project open-kilda by telstra.
the class RerouteService method updateFlowPathsStateForFlow.
private boolean updateFlowPathsStateForFlow(SwitchId switchId, int port, List<FlowPath> paths) {
boolean rerouteRequired = false;
for (FlowPath fp : paths) {
boolean failedFlowPath = false;
for (PathSegment pathSegment : fp.getSegments()) {
if (pathSegment.getSrcPort() == port && switchId.equals(pathSegment.getSrcSwitchId()) || (pathSegment.getDestPort() == port && switchId.equals(pathSegment.getDestSwitchId()))) {
pathSegment.setFailed(true);
try {
pathSegmentRepository.updateFailedStatus(fp, pathSegment, true);
failedFlowPath = true;
rerouteRequired = true;
} catch (EntityNotFoundException e) {
log.warn("Path segment not found for flow {} and path {}. Skipping path segment status update.", fp.getFlow().getFlowId(), fp.getPathId(), e);
}
break;
}
}
if (failedFlowPath) {
updateFlowPathStatus(fp, FlowPathStatus.INACTIVE);
}
}
return rerouteRequired;
}
use of org.openkilda.model.PathSegment in project open-kilda by telstra.
the class RerouteService method rerouteInactiveFlows.
/**
* Handles reroute on ISL up events.
*
* @param sender transport sender
* @param correlationId correlation id to pass through
* @param command origin command
*/
@TimedExecution("reroute_inactive_flows")
public void rerouteInactiveFlows(MessageSender sender, String correlationId, RerouteInactiveFlows command) {
PathNode pathNode = command.getPathNode();
int port = pathNode.getPortNo();
SwitchId switchId = pathNode.getSwitchId();
Map<String, FlowThrottlingData> flowsForReroute = transactionManager.doInTransaction(() -> {
Map<String, FlowThrottlingData> forReroute = new HashMap<>();
Map<Flow, Set<PathId>> flowsForRerouting = getInactiveFlowsForRerouting();
for (Entry<Flow, Set<PathId>> entry : flowsForRerouting.entrySet()) {
Flow flow = entry.getKey();
Set<IslEndpoint> allAffectedIslEndpoints = new HashSet<>();
for (FlowPath flowPath : flow.getPaths()) {
Set<IslEndpoint> affectedIslEndpoints = new HashSet<>();
PathSegment firstSegment = null;
int failedSegmentsCount = 0;
for (PathSegment pathSegment : flowPath.getSegments()) {
if (firstSegment == null) {
firstSegment = pathSegment;
}
if (pathSegment.isFailed()) {
affectedIslEndpoints.add(new IslEndpoint(pathSegment.getSrcSwitchId(), pathSegment.getSrcPort()));
affectedIslEndpoints.add(new IslEndpoint(pathSegment.getDestSwitchId(), pathSegment.getDestPort()));
if (pathSegment.containsNode(switchId, port)) {
pathSegment.setFailed(false);
pathSegmentRepository.updateFailedStatus(flowPath, pathSegment, false);
} else {
failedSegmentsCount++;
}
}
}
if (flowPath.getStatus().equals(FlowPathStatus.INACTIVE) && failedSegmentsCount == 0) {
updateFlowPathStatus(flowPath, FlowPathStatus.ACTIVE);
// force reroute of failed path only (required due to inaccurate path/segment state management)
if (affectedIslEndpoints.isEmpty() && firstSegment != null) {
affectedIslEndpoints.add(new IslEndpoint(firstSegment.getSrcSwitchId(), firstSegment.getSrcPort()));
}
}
allAffectedIslEndpoints.addAll(affectedIslEndpoints);
}
FlowStatus flowStatus = flow.computeFlowStatus();
String flowStatusInfo = null;
if (!FlowStatus.UP.equals(flowStatus)) {
flowStatusInfo = command.getReason();
}
flowRepository.updateStatusSafe(flow, flowStatus, flowStatusInfo);
if (flow.isPinned()) {
log.info("Skipping reroute command for pinned flow {}", flow.getFlowId());
} else if (flow.getYFlow() != null) {
YFlow yFlow = flow.getYFlow();
log.info("Create reroute command (attempt to restore inactive flows) request for {} " + "(affected ISL endpoints: {})", yFlow.getYFlowId(), allAffectedIslEndpoints);
FlowThrottlingData flowThrottlingData = getFlowThrottlingDataBuilder(yFlow).correlationId(correlationId).affectedIsl(allAffectedIslEndpoints).force(false).effectivelyDown(true).reason(command.getReason()).build();
sender.emitRerouteCommand(yFlow.getYFlowId(), flowThrottlingData);
} else {
log.info("Create reroute command (attempt to restore inactive flows) request for {} (affected ISL " + "endpoints: {})", flow.getFlowId(), allAffectedIslEndpoints);
FlowThrottlingData flowThrottlingData = getFlowThrottlingDataBuilder(flow).correlationId(correlationId).affectedIsl(allAffectedIslEndpoints).force(false).effectivelyDown(true).reason(command.getReason()).build();
forReroute.put(flow.getFlowId(), flowThrottlingData);
}
}
return forReroute;
});
for (Entry<String, FlowThrottlingData> entry : flowsForReroute.entrySet()) {
log.info("Produce reroute (attempt to restore inactive flows) request for {} (affected ISL endpoints: {})", entry.getKey(), entry.getValue().getAffectedIsl());
sender.emitRerouteCommand(entry.getKey(), entry.getValue());
}
}
use of org.openkilda.model.PathSegment in project open-kilda by telstra.
the class BaseResourceAllocationAction method allocatePathPair.
@SneakyThrows
protected GetPathsResult allocatePathPair(Flow flow, PathId newForwardPathId, PathId newReversePathId, boolean forceToIgnoreBandwidth, List<PathId> pathsToReuseBandwidth, FlowPathPair oldPaths, boolean allowOldPaths, String sharedBandwidthGroupId, Predicate<GetPathsResult> whetherCreatePathSegments) throws RecoverableException, UnroutableFlowException, ResourceAllocationException {
// Lazy initialisable map with reused bandwidth...
Supplier<Map<IslEndpoints, Long>> reuseBandwidthPerIsl = Suppliers.memoize(() -> {
Map<IslEndpoints, Long> result = new HashMap<>();
if (pathsToReuseBandwidth != null && !pathsToReuseBandwidth.isEmpty()) {
pathsToReuseBandwidth.stream().map(pathId -> flow.getPath(pathId).orElse(flowPathRepository.findById(pathId).orElse(null))).filter(Objects::nonNull).flatMap(path -> path.getSegments().stream()).forEach(segment -> {
IslEndpoints isl = new IslEndpoints(segment.getSrcSwitchId().toString(), segment.getSrcPort(), segment.getDestSwitchId().toString(), segment.getDestPort());
result.put(isl, result.getOrDefault(isl, 0L) + segment.getBandwidth());
});
}
return result;
});
RetryPolicy<GetPathsResult> pathAllocationRetryPolicy = new RetryPolicy<GetPathsResult>().handle(RecoverableException.class).handle(ResourceAllocationException.class).handle(UnroutableFlowException.class).handle(PersistenceException.class).onRetry(e -> log.warn("Failure in path allocation. Retrying #{}...", e.getAttemptCount(), e.getLastFailure())).onRetriesExceeded(e -> log.warn("Failure in path allocation. No more retries", e.getFailure())).withMaxRetries(pathAllocationRetriesLimit);
if (pathAllocationRetryDelay > 0) {
pathAllocationRetryPolicy.withDelay(Duration.ofMillis(pathAllocationRetryDelay));
}
try {
return Failsafe.with(pathAllocationRetryPolicy).get(() -> {
GetPathsResult potentialPath;
if (forceToIgnoreBandwidth) {
boolean originalIgnoreBandwidth = flow.isIgnoreBandwidth();
flow.setIgnoreBandwidth(true);
potentialPath = pathComputer.getPath(flow);
flow.setIgnoreBandwidth(originalIgnoreBandwidth);
} else {
potentialPath = pathComputer.getPath(flow, pathsToReuseBandwidth);
}
boolean newPathFound = isNotSamePath(potentialPath, oldPaths);
if (allowOldPaths || newPathFound) {
if (!newPathFound) {
log.debug("Found the same path for flow {}. Proceed with recreating it", flow.getFlowId());
}
if (whetherCreatePathSegments.test(potentialPath)) {
boolean ignoreBandwidth = forceToIgnoreBandwidth || flow.isIgnoreBandwidth();
List<PathSegment> forwardSegments = flowPathBuilder.buildPathSegments(newForwardPathId, potentialPath.getForward(), flow.getBandwidth(), ignoreBandwidth, sharedBandwidthGroupId);
List<PathSegment> reverseSegments = flowPathBuilder.buildPathSegments(newReversePathId, potentialPath.getReverse(), flow.getBandwidth(), ignoreBandwidth, sharedBandwidthGroupId);
transactionManager.doInTransaction(() -> {
createPathSegments(forwardSegments, reuseBandwidthPerIsl);
createPathSegments(reverseSegments, reuseBandwidthPerIsl);
});
}
return potentialPath;
}
return null;
});
} catch (FailsafeException ex) {
throw ex.getCause();
}
}
use of org.openkilda.model.PathSegment in project open-kilda by telstra.
the class YFlowSwitchFlowEntriesBuilder method getFlowEntries.
/**
* Construct a set of {@link FlowEntry} that corresponds to the builder's y-flow.
*/
public Map<SwitchId, Collection<FlowEntry>> getFlowEntries() {
MultiValuedMap<SwitchId, FlowEntry> flowEntries = new ArrayListValuedHashMap<>();
yFlow.getSubFlows().forEach(subFlow -> {
Flow flow = subFlow.getFlow();
SwitchFlowEntriesBuilder builder = new SwitchFlowEntriesBuilder(flow);
int forwardTransitEncId = getEncapsulationId(flow.getEncapsulationType(), flow.getForwardPathId()).orElseThrow(IllegalStateException::new);
int reverseTransitEncId = getEncapsulationId(flow.getEncapsulationType(), flow.getReversePathId()).orElseThrow(IllegalStateException::new);
Integer protectedForwardTransitEncId = getEncapsulationId(flow.getEncapsulationType(), flow.getProtectedForwardPathId()).orElse(null);
Integer protectedReverseTransitEncId = getEncapsulationId(flow.getEncapsulationType(), flow.getProtectedReversePathId()).orElse(null);
builder.getSwitchFlowEntries(forwardTransitEncId, reverseTransitEncId, protectedForwardTransitEncId, protectedReverseTransitEncId).forEach(entries -> flowEntries.putAll(entries.getSwitchId(), entries.getFlowEntries()));
FlowPath forwardPath = flow.getForwardPath();
PathSegment firstSegment = forwardPath.getSegments().get(0);
FlowSegmentCookie forwardCookie = forwardPath.getCookie().toBuilder().yFlow(true).build();
boolean isVxlan = flow.getEncapsulationType() == VXLAN;
flowEntries.put(forwardPath.getSrcSwitchId(), builder.getFlowEntry(forwardCookie.getValue(), flow.getSrcPort(), flow.getSrcVlan(), null, firstSegment.getSrcPort(), isVxlan ? null : forwardTransitEncId, isVxlan ? forwardTransitEncId : null, yFlow.getSharedEndpointMeterId().getValue()));
if (!yFlow.getYPoint().equals(flow.getSrcSwitchId())) {
FlowPath reversePath = flow.getReversePath();
FlowSegmentCookie reverseCookie = reversePath.getCookie().toBuilder().yFlow(true).build();
List<PathSegment> reverseSegments = reversePath.getSegments();
for (int i = 0; i < reverseSegments.size() - 1; i++) {
PathSegment nsegment = reverseSegments.get(i);
PathSegment n1segment = reverseSegments.get(i + 1);
if (nsegment.getDestSwitchId().equals(yFlow.getYPoint())) {
flowEntries.put(yFlow.getYPoint(), builder.getFlowEntry(reverseCookie.getValue(), n1segment.getSrcPort(), isVxlan ? null : reverseTransitEncId, isVxlan ? reverseTransitEncId : null, nsegment.getDestPort(), null, null, yFlow.getMeterId().getValue()));
}
}
}
if (yFlow.isAllocateProtectedPath() && yFlow.getProtectedPathYPoint() != null && !yFlow.getProtectedPathYPoint().equals(flow.getSrcSwitchId())) {
FlowPath reversePath = flow.getProtectedReversePath();
FlowSegmentCookie reverseCookie = reversePath.getCookie().toBuilder().yFlow(true).build();
List<PathSegment> reverseSegments = reversePath.getSegments();
for (int i = 0; i < reverseSegments.size() - 1; i++) {
PathSegment nsegment = reverseSegments.get(i);
PathSegment n1segment = reverseSegments.get(i + 1);
if (nsegment.getDestSwitchId().equals(yFlow.getProtectedPathYPoint())) {
flowEntries.put(yFlow.getProtectedPathYPoint(), builder.getFlowEntry(reverseCookie.getValue(), n1segment.getSrcPort(), isVxlan ? null : reverseTransitEncId, isVxlan ? reverseTransitEncId : null, nsegment.getDestPort(), null, null, yFlow.getProtectedPathMeterId().getValue()));
}
}
}
});
return flowEntries.asMap();
}
Aggregations