Search in sources :

Example 21 with GetPathsResult

use of org.openkilda.pce.GetPathsResult 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 22 with GetPathsResult

use of org.openkilda.pce.GetPathsResult in project open-kilda by telstra.

the class ResourcesAllocationAction method allocateMainPath.

private void allocateMainPath(FlowCreateFsm stateMachine) throws UnroutableFlowException, RecoverableException, ResourceAllocationException {
    GetPathsResult paths = pathComputer.getPath(getFlow(stateMachine.getFlowId()));
    stateMachine.setBackUpPrimaryPathComputationWayUsed(paths.isBackUpPathComputationWayUsed());
    log.debug("Creating the primary path {} for flow {}", paths, stateMachine.getFlowId());
    transactionManager.doInTransaction(() -> {
        Flow flow = getFlow(stateMachine.getFlowId());
        FlowResources flowResources = resourcesManager.allocateFlowResources(flow);
        final FlowSegmentCookieBuilder cookieBuilder = FlowSegmentCookie.builder().flowEffectiveId(flowResources.getUnmaskedCookie());
        updateSwitchRelatedFlowProperties(flow);
        FlowPath forward = flowPathBuilder.buildFlowPath(flow, flowResources.getForward(), paths.getForward(), cookieBuilder.direction(FlowPathDirection.FORWARD).build(), false, stateMachine.getSharedBandwidthGroupId());
        forward.setStatus(FlowPathStatus.IN_PROGRESS);
        flowPathRepository.add(forward);
        flow.setForwardPath(forward);
        FlowPath reverse = flowPathBuilder.buildFlowPath(flow, flowResources.getReverse(), paths.getReverse(), cookieBuilder.direction(FlowPathDirection.REVERSE).build(), false, stateMachine.getSharedBandwidthGroupId());
        reverse.setStatus(FlowPathStatus.IN_PROGRESS);
        flowPathRepository.add(reverse);
        flow.setReversePath(reverse);
        updateIslsForFlowPath(forward.getPathId());
        updateIslsForFlowPath(reverse.getPathId());
        stateMachine.setForwardPathId(forward.getPathId());
        stateMachine.setReversePathId(reverse.getPathId());
        log.debug("Allocated resources for the flow {}: {}", flow.getFlowId(), flowResources);
        stateMachine.getFlowResources().add(flowResources);
    });
}
Also used : FlowResources(org.openkilda.wfm.share.flow.resources.FlowResources) FlowSegmentCookieBuilder(org.openkilda.model.cookie.FlowSegmentCookie.FlowSegmentCookieBuilder) FlowPath(org.openkilda.model.FlowPath) GetPathsResult(org.openkilda.pce.GetPathsResult) Flow(org.openkilda.model.Flow) YSubFlow(org.openkilda.model.YSubFlow) RequestedFlow(org.openkilda.wfm.topology.flowhs.model.RequestedFlow) YFlow(org.openkilda.model.YFlow)

Example 23 with GetPathsResult

use of org.openkilda.pce.GetPathsResult in project open-kilda by telstra.

the class AllocatePrimaryResourcesAction method allocate.

@Override
protected void allocate(FlowUpdateFsm stateMachine) throws RecoverableException, UnroutableFlowException, ResourceAllocationException {
    String flowId = stateMachine.getFlowId();
    Set<String> flowIds = Sets.newHashSet(flowId);
    if (stateMachine.getBulkUpdateFlowIds() != null) {
        flowIds.addAll(stateMachine.getBulkUpdateFlowIds());
    }
    log.debug("Finding paths for flows {}", flowIds);
    List<PathId> pathIdsToReuse = new ArrayList<>(flowPathRepository.findActualPathIdsByFlowIds(flowIds));
    pathIdsToReuse.addAll(stateMachine.getRejectedPaths());
    Flow tmpFlow = getFlow(flowId);
    FlowPathPair oldPaths = new FlowPathPair(tmpFlow.getForwardPath(), tmpFlow.getReversePath());
    PathId newForwardPathId = resourcesManager.generatePathId(flowId);
    PathId newReversePathId = resourcesManager.generatePathId(flowId);
    log.debug("Finding a new primary path for flow {}", flowId);
    GetPathsResult allocatedPaths = allocatePathPair(tmpFlow, newForwardPathId, newReversePathId, false, pathIdsToReuse, oldPaths, true, stateMachine.getSharedBandwidthGroupId(), path -> true);
    if (allocatedPaths == null) {
        throw new ResourceAllocationException("Unable to allocate a path");
    }
    log.debug("New primary paths have been allocated: {}", allocatedPaths);
    stateMachine.setBackUpPrimaryPathComputationWayUsed(allocatedPaths.isBackUpPathComputationWayUsed());
    stateMachine.setNewPrimaryForwardPath(newForwardPathId);
    stateMachine.setNewPrimaryReversePath(newReversePathId);
    log.debug("Allocating resources for a new primary path of flow {}", flowId);
    FlowResources flowResources = allocateFlowResources(tmpFlow, newForwardPathId, newReversePathId);
    stateMachine.setNewPrimaryResources(flowResources);
    FlowPathPair createdPaths = createFlowPathPair(flowId, flowResources, allocatedPaths, false, stateMachine.getSharedBandwidthGroupId());
    log.debug("New primary path has been created: {}", createdPaths);
    setMirrorPointsToNewPath(oldPaths.getForwardPathId(), newForwardPathId);
    setMirrorPointsToNewPath(oldPaths.getReversePathId(), newReversePathId);
    saveAllocationActionWithDumpsToHistory(stateMachine, tmpFlow, "primary", createdPaths);
}
Also used : PathId(org.openkilda.model.PathId) FlowResources(org.openkilda.wfm.share.flow.resources.FlowResources) ArrayList(java.util.ArrayList) ResourceAllocationException(org.openkilda.wfm.share.flow.resources.ResourceAllocationException) Flow(org.openkilda.model.Flow) FlowPathPair(org.openkilda.wfm.topology.flow.model.FlowPathPair) GetPathsResult(org.openkilda.pce.GetPathsResult)

Example 24 with GetPathsResult

use of org.openkilda.pce.GetPathsResult in project open-kilda by telstra.

the class InMemoryPathComputerBaseTest method shouldFindOverLargeIslands.

/**
 * See how it works with a large network. It takes a while to create the network .. therefore @Ignore so that it
 * doesn't slow down unit tests.
 */
@Test
@Ignore
public void shouldFindOverLargeIslands() throws RecoverableException, UnroutableFlowException {
    createDiamond(IslStatus.ACTIVE, IslStatus.ACTIVE, 10, 20, "08:", 1);
    for (int i = 0; i < 50; i++) {
        createDiamond(IslStatus.ACTIVE, IslStatus.ACTIVE, 10, 20, "10:", 4 * i + 1);
        createDiamond(IslStatus.ACTIVE, IslStatus.ACTIVE, 10, 20, "11:", 4 * i + 1);
        createDiamond(IslStatus.ACTIVE, IslStatus.ACTIVE, 10, 20, "12:", 4 * i + 1);
        createDiamond(IslStatus.ACTIVE, IslStatus.ACTIVE, 10, 20, "13:", 4 * i + 1);
    }
    for (int i = 0; i < 49; i++) {
        String prev = format("%02X", 4 * i + 4);
        String next = format("%02X", 4 * i + 5);
        connectDiamonds(new SwitchId("10:" + prev), new SwitchId("10:" + next), IslStatus.ACTIVE, 20, 50);
        connectDiamonds(new SwitchId("11:" + prev), new SwitchId("11:" + next), IslStatus.ACTIVE, 20, 50);
        connectDiamonds(new SwitchId("12:" + prev), new SwitchId("12:" + next), IslStatus.ACTIVE, 20, 50);
        connectDiamonds(new SwitchId("13:" + prev), new SwitchId("13:" + next), IslStatus.ACTIVE, 20, 50);
    }
    connectDiamonds(new SwitchId("10:99"), new SwitchId("11:22"), IslStatus.ACTIVE, 20, 50);
    connectDiamonds(new SwitchId("11:99"), new SwitchId("12:22"), IslStatus.ACTIVE, 20, 50);
    connectDiamonds(new SwitchId("12:99"), new SwitchId("13:22"), IslStatus.ACTIVE, 20, 50);
    connectDiamonds(new SwitchId("13:99"), new SwitchId("10:22"), IslStatus.ACTIVE, 20, 50);
    Switch srcSwitch1 = getSwitchById("10:01");
    Switch destSwitch1 = getSwitchById("11:03");
    // THIS ONE SHOULD WORK
    Flow f1 = new TestFlowBuilder().srcSwitch(srcSwitch1).destSwitch(destSwitch1).bandwidth(0).ignoreBandwidth(false).build();
    PathComputer pathComputer = new InMemoryPathComputer(availableNetworkFactory, new BestWeightAndShortestPathFinder(200), config);
    GetPathsResult path = pathComputer.getPath(f1);
    assertNotNull(path);
    assertThat(path.getForward().getSegments(), Matchers.hasSize(278));
    Switch srcSwitch2 = getSwitchById("08:01");
    Switch destSwitch2 = getSwitchById("11:04");
    // THIS ONE SHOULD FAIL
    Flow f2 = new TestFlowBuilder().srcSwitch(srcSwitch2).destSwitch(destSwitch2).bandwidth(0).ignoreBandwidth(false).build();
    thrown.expect(UnroutableFlowException.class);
    pathComputer.getPath(f2);
}
Also used : PathComputer(org.openkilda.pce.PathComputer) Switch(org.openkilda.model.Switch) BestWeightAndShortestPathFinder(org.openkilda.pce.finder.BestWeightAndShortestPathFinder) SwitchId(org.openkilda.model.SwitchId) Flow(org.openkilda.model.Flow) GetPathsResult(org.openkilda.pce.GetPathsResult) Ignore(org.junit.Ignore) InMemoryGraphBasedTest(org.openkilda.persistence.inmemory.InMemoryGraphBasedTest) Test(org.junit.Test)

Example 25 with GetPathsResult

use of org.openkilda.pce.GetPathsResult in project open-kilda by telstra.

the class InMemoryPathComputerBaseTest method affinityPathShouldSplitAsCloseAsPossibleToDestination.

void affinityPathShouldSplitAsCloseAsPossibleToDestination(PathComputationStrategy pathComputationStrategy) throws Exception {
    createTestTopologyForAffinityTesting();
    Flow flow = Flow.builder().flowId("new-flow").affinityGroupId(TEST_FLOW_ID).bandwidth(10).srcSwitch(getSwitchById("00:0A")).destSwitch(getSwitchById("00:03")).encapsulationType(FlowEncapsulationType.TRANSIT_VLAN).pathComputationStrategy(pathComputationStrategy).build();
    PathComputer pathComputer = pathComputerFactory.getPathComputer();
    GetPathsResult affinityPath = pathComputer.getPath(flow);
    List<Segment> segments = affinityPath.getForward().getSegments();
    assertEquals(3, segments.size());
    assertEquals(new SwitchId("00:0A"), segments.get(0).getSrcSwitchId());
    assertEquals(new SwitchId("00:0B"), segments.get(1).getSrcSwitchId());
    assertEquals(new SwitchId("00:0C"), segments.get(2).getSrcSwitchId());
    assertEquals(new SwitchId("00:0B"), segments.get(0).getDestSwitchId());
    assertEquals(new SwitchId("00:0C"), segments.get(1).getDestSwitchId());
    assertEquals(new SwitchId("00:03"), segments.get(2).getDestSwitchId());
}
Also used : PathComputer(org.openkilda.pce.PathComputer) SwitchId(org.openkilda.model.SwitchId) Segment(org.openkilda.pce.Path.Segment) PathSegment(org.openkilda.model.PathSegment) Flow(org.openkilda.model.Flow) GetPathsResult(org.openkilda.pce.GetPathsResult)

Aggregations

Flow (org.openkilda.model.Flow)50 GetPathsResult (org.openkilda.pce.GetPathsResult)50 PathComputer (org.openkilda.pce.PathComputer)42 Test (org.junit.Test)40 SwitchId (org.openkilda.model.SwitchId)30 Switch (org.openkilda.model.Switch)22 FlowPath (org.openkilda.model.FlowPath)8 PathId (org.openkilda.model.PathId)8 FlowResources (org.openkilda.wfm.share.flow.resources.FlowResources)7 PathSegment (org.openkilda.model.PathSegment)5 BestWeightAndShortestPathFinder (org.openkilda.pce.finder.BestWeightAndShortestPathFinder)5 FlowPathPair (org.openkilda.wfm.topology.flow.model.FlowPathPair)5 ArrayList (java.util.ArrayList)4 Segment (org.openkilda.pce.Path.Segment)4 UnroutableFlowException (org.openkilda.pce.exception.UnroutableFlowException)4 ResourceAllocationException (org.openkilda.wfm.share.flow.resources.ResourceAllocationException)4 List (java.util.List)3 Predicate (java.util.function.Predicate)3 Slf4j (lombok.extern.slf4j.Slf4j)3 FlowSegmentRequest (org.openkilda.floodlight.api.request.FlowSegmentRequest)3