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();
}
}
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);
});
}
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);
}
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);
}
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());
}
Aggregations