Search in sources :

Example 46 with PathSegment

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)));
}
Also used : PathId(org.openkilda.model.PathId) FlowSegmentCookie(org.openkilda.model.cookie.FlowSegmentCookie) PathSegment(org.openkilda.model.PathSegment)

Example 47 with PathSegment

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;
}
Also used : PathSegment(org.openkilda.model.PathSegment) EntityNotFoundException(org.openkilda.persistence.exceptions.EntityNotFoundException) FlowPath(org.openkilda.model.FlowPath)

Example 48 with PathSegment

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());
    }
}
Also used : YFlow(org.openkilda.model.YFlow) IslEndpoint(org.openkilda.model.IslEndpoint) HashSet(java.util.HashSet) Collectors.toSet(java.util.stream.Collectors.toSet) Set(java.util.Set) HashMap(java.util.HashMap) SwitchId(org.openkilda.model.SwitchId) PathSegment(org.openkilda.model.PathSegment) PathNode(org.openkilda.messaging.info.event.PathNode) IslEndpoint(org.openkilda.model.IslEndpoint) FlowStatus(org.openkilda.model.FlowStatus) Flow(org.openkilda.model.Flow) YFlow(org.openkilda.model.YFlow) FlowThrottlingData(org.openkilda.wfm.topology.reroute.model.FlowThrottlingData) FlowPath(org.openkilda.model.FlowPath) HashSet(java.util.HashSet) TimedExecution(org.openkilda.wfm.share.metrics.TimedExecution)

Example 49 with PathSegment

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();
    }
}
Also used : FlowPath(org.openkilda.model.FlowPath) HistoryMapper(org.openkilda.wfm.share.mappers.HistoryMapper) SneakyThrows(lombok.SneakyThrows) ResourceAllocationException(org.openkilda.wfm.share.flow.resources.ResourceAllocationException) FlowPathStatus(org.openkilda.model.FlowPathStatus) UnroutableFlowException(org.openkilda.pce.exception.UnroutableFlowException) FlowPathSwappingFsm(org.openkilda.wfm.topology.flowhs.fsm.common.FlowPathSwappingFsm) FailsafeException(net.jodah.failsafe.FailsafeException) Flow(org.openkilda.model.Flow) Duration(java.time.Duration) Map(java.util.Map) FlowPathPair(org.openkilda.wfm.topology.flow.model.FlowPathPair) DumpType(org.openkilda.wfm.share.history.model.FlowDumpData.DumpType) Path(org.openkilda.pce.Path) SwitchProperties(org.openkilda.model.SwitchProperties) IslEndpoints(org.openkilda.persistence.repositories.IslRepository.IslEndpoints) Predicate(java.util.function.Predicate) Collection(java.util.Collection) RetryPolicy(net.jodah.failsafe.RetryPolicy) PersistenceException(org.openkilda.persistence.exceptions.PersistenceException) FlowResources(org.openkilda.wfm.share.flow.resources.FlowResources) String.format(java.lang.String.format) Objects(java.util.Objects) SwitchPropertiesRepository(org.openkilda.persistence.repositories.SwitchPropertiesRepository) Slf4j(lombok.extern.slf4j.Slf4j) List(java.util.List) FlowDumpData(org.openkilda.wfm.share.history.model.FlowDumpData) PathComputer(org.openkilda.pce.PathComputer) Optional(java.util.Optional) ConstraintViolationException(org.openkilda.persistence.exceptions.ConstraintViolationException) SwitchRepository(org.openkilda.persistence.repositories.SwitchRepository) FlowSegmentCookieBuilder(org.openkilda.model.cookie.FlowSegmentCookie.FlowSegmentCookieBuilder) Message(org.openkilda.messaging.Message) PathSegment(org.openkilda.model.PathSegment) KildaConfigurationRepository(org.openkilda.persistence.repositories.KildaConfigurationRepository) HashMap(java.util.HashMap) Supplier(java.util.function.Supplier) RecoverableException(org.openkilda.pce.exception.RecoverableException) ArrayList(java.util.ArrayList) FlowPathDirection(org.openkilda.model.FlowPathDirection) PathSegmentRepository(org.openkilda.persistence.repositories.PathSegmentRepository) IslRepository(org.openkilda.persistence.repositories.IslRepository) Suppliers(com.google.common.base.Suppliers) FlowSegmentCookie(org.openkilda.model.cookie.FlowSegmentCookie) PersistenceManager(org.openkilda.persistence.PersistenceManager) PathId(org.openkilda.model.PathId) DetectConnectedDevices(org.openkilda.model.DetectConnectedDevices) FlowOperationsDashboardLogger(org.openkilda.wfm.share.logger.FlowOperationsDashboardLogger) ErrorType(org.openkilda.messaging.error.ErrorType) IslStatus(org.openkilda.model.IslStatus) Failsafe(net.jodah.failsafe.Failsafe) RepositoryFactory(org.openkilda.persistence.repositories.RepositoryFactory) FlowPathBuilder(org.openkilda.wfm.topology.flowhs.service.FlowPathBuilder) SwitchId(org.openkilda.model.SwitchId) FlowResourcesManager(org.openkilda.wfm.share.flow.resources.FlowResourcesManager) GetPathsResult(org.openkilda.pce.GetPathsResult) VisibleForTesting(com.google.common.annotations.VisibleForTesting) Isl(org.openkilda.model.Isl) LazyMap(org.apache.commons.collections4.map.LazyMap) HashMap(java.util.HashMap) FailsafeException(net.jodah.failsafe.FailsafeException) PathSegment(org.openkilda.model.PathSegment) GetPathsResult(org.openkilda.pce.GetPathsResult) IslEndpoints(org.openkilda.persistence.repositories.IslRepository.IslEndpoints) Objects(java.util.Objects) PersistenceException(org.openkilda.persistence.exceptions.PersistenceException) ResourceAllocationException(org.openkilda.wfm.share.flow.resources.ResourceAllocationException) Map(java.util.Map) HashMap(java.util.HashMap) LazyMap(org.apache.commons.collections4.map.LazyMap) SneakyThrows(lombok.SneakyThrows)

Example 50 with PathSegment

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();
}
Also used : FlowSegmentCookie(org.openkilda.model.cookie.FlowSegmentCookie) SwitchId(org.openkilda.model.SwitchId) PathSegment(org.openkilda.model.PathSegment) Flow(org.openkilda.model.Flow) YFlow(org.openkilda.model.YFlow) SwitchFlowEntriesBuilder(org.openkilda.wfm.topology.flowhs.fsm.validation.SwitchFlowEntriesBuilder) FlowPath(org.openkilda.model.FlowPath) FlowEntry(org.openkilda.messaging.info.rule.FlowEntry) ArrayListValuedHashMap(org.apache.commons.collections4.multimap.ArrayListValuedHashMap)

Aggregations

PathSegment (org.openkilda.model.PathSegment)73 FlowPath (org.openkilda.model.FlowPath)40 ArrayList (java.util.ArrayList)28 Flow (org.openkilda.model.Flow)26 PathId (org.openkilda.model.PathId)24 SwitchId (org.openkilda.model.SwitchId)18 FlowSegmentCookie (org.openkilda.model.cookie.FlowSegmentCookie)17 FlowEndpoint (org.openkilda.model.FlowEndpoint)12 Test (org.junit.Test)11 List (java.util.List)9 MeterId (org.openkilda.model.MeterId)9 Switch (org.openkilda.model.Switch)9 YFlow (org.openkilda.model.YFlow)8 PersistenceManager (org.openkilda.persistence.PersistenceManager)7 Optional (java.util.Optional)6 Slf4j (lombok.extern.slf4j.Slf4j)6 VisibleForTesting (com.google.common.annotations.VisibleForTesting)5 Set (java.util.Set)5 Collectors (java.util.stream.Collectors)5 PathInfoData (org.openkilda.messaging.info.event.PathInfoData)5