Search in sources :

Example 1 with FlowEncapsulationType

use of org.openkilda.model.FlowEncapsulationType in project open-kilda by telstra.

the class SwapFlowPathsAction method swapPrimaryPaths.

private void swapPrimaryPaths(FlowUpdateFsm stateMachine) {
    PathId newForward = stateMachine.getNewPrimaryForwardPath();
    PathId newReverse = stateMachine.getNewPrimaryReversePath();
    if (newForward != null && newReverse != null) {
        transactionManager.doInTransaction(() -> {
            Flow flow = getFlow(stateMachine.getFlowId());
            FlowPath oldForward = flow.getForwardPath();
            if (oldForward != null) {
                stateMachine.setOldPrimaryForwardPath(oldForward.getPathId());
                stateMachine.setOldPrimaryForwardPathStatus(oldForward.getStatus());
                oldForward.setStatus(FlowPathStatus.IN_PROGRESS);
            }
            FlowPath oldReverse = flow.getReversePath();
            if (oldReverse != null) {
                stateMachine.setOldPrimaryReversePath(oldReverse.getPathId());
                stateMachine.setOldPrimaryReversePathStatus(oldReverse.getStatus());
                oldReverse.setStatus(FlowPathStatus.IN_PROGRESS);
            }
            if (oldForward != null || oldReverse != null) {
                FlowEncapsulationType oldFlowEncapsulationType = stateMachine.getOriginalFlow().getFlowEncapsulationType();
                FlowResources oldResources = getResources(oldForward != null ? oldForward : oldReverse, oldReverse != null ? oldReverse : oldForward, oldFlowEncapsulationType);
                stateMachine.getOldResources().add(oldResources);
            }
            flow.setForwardPathId(newForward);
            flow.setReversePathId(newReverse);
            log.debug("Swapping the primary paths {}/{} with {}/{}", oldForward != null ? oldForward.getPathId() : null, oldReverse != null ? oldReverse.getPathId() : null, newForward, newReverse);
        });
        saveHistory(stateMachine, stateMachine.getFlowId(), newForward, newReverse);
    }
}
Also used : PathId(org.openkilda.model.PathId) FlowResources(org.openkilda.wfm.share.flow.resources.FlowResources) FlowEncapsulationType(org.openkilda.model.FlowEncapsulationType) FlowPath(org.openkilda.model.FlowPath) Flow(org.openkilda.model.Flow)

Example 2 with FlowEncapsulationType

use of org.openkilda.model.FlowEncapsulationType in project open-kilda by telstra.

the class RevertNewRulesAction method perform.

@Override
protected void perform(State from, State to, Event event, FlowRerouteContext context, FlowRerouteFsm stateMachine) {
    Flow flow = getFlow(stateMachine.getFlowId());
    log.debug("Abandoning all pending commands: {}", stateMachine.getPendingCommands());
    stateMachine.clearPendingAndRetriedAndFailedCommands();
    FlowEncapsulationType encapsulationType = stateMachine.getNewEncapsulationType() != null ? stateMachine.getNewEncapsulationType() : flow.getEncapsulationType();
    FlowCommandBuilder commandBuilder = commandBuilderFactory.getBuilder(encapsulationType);
    Collection<FlowSegmentRequestFactory> installCommands = new ArrayList<>();
    // Reinstall old ingress rules that may be overridden by new ingress.
    if (stateMachine.getOldPrimaryForwardPath() != null && stateMachine.getOldPrimaryReversePath() != null) {
        FlowPath oldForward = getFlowPath(flow, stateMachine.getOldPrimaryForwardPath());
        FlowPath oldReverse = getFlowPath(flow, stateMachine.getOldPrimaryReversePath());
        SpeakerRequestBuildContext installContext = buildBaseSpeakerContextForInstall(oldForward.getSrcSwitchId(), oldReverse.getSrcSwitchId());
        installCommands.addAll(commandBuilder.buildIngressOnly(stateMachine.getCommandContext(), flow, oldForward, oldReverse, installContext));
    }
    // need to clean previous requests
    stateMachine.getIngressCommands().clear();
    SpeakerInstallSegmentEmitter.INSTANCE.emitBatch(stateMachine.getCarrier(), installCommands, stateMachine.getIngressCommands());
    stateMachine.getIngressCommands().forEach((key, value) -> stateMachine.addPendingCommand(key, value.getSwitchId()));
    // Remove possible installed flow segments
    MirrorContext mirrorContext = MirrorContext.builder().removeFlowOperation(true).build();
    Collection<FlowSegmentRequestFactory> removeCommands = new ArrayList<>();
    if (stateMachine.getNewPrimaryForwardPath() != null && stateMachine.getNewPrimaryReversePath() != null) {
        FlowPath newForward = getFlowPath(flow, stateMachine.getNewPrimaryForwardPath());
        FlowPath newReverse = getFlowPath(flow, stateMachine.getNewPrimaryReversePath());
        SpeakerRequestBuildContext speakerContext = buildSpeakerContextForRemovalIngressOnly(newForward.getSrcSwitchId(), newReverse.getSrcSwitchId());
        removeCommands.addAll(commandBuilder.buildAll(stateMachine.getCommandContext(), flow, newForward, newReverse, speakerContext, mirrorContext));
    }
    if (stateMachine.getNewProtectedForwardPath() != null && stateMachine.getNewProtectedReversePath() != null) {
        FlowPath newForward = getFlowPath(flow, stateMachine.getNewProtectedForwardPath());
        FlowPath newReverse = getFlowPath(flow, stateMachine.getNewProtectedReversePath());
        removeCommands.addAll(commandBuilder.buildAllExceptIngress(stateMachine.getCommandContext(), flow, newForward, newReverse, mirrorContext));
    }
    stateMachine.getRemoveCommands().clear();
    SpeakerRemoveSegmentEmitter.INSTANCE.emitBatch(stateMachine.getCarrier(), removeCommands, stateMachine.getRemoveCommands());
    stateMachine.getRemoveCommands().forEach((key, value) -> stateMachine.addPendingCommand(key, value.getSwitchId()));
    if (stateMachine.getPendingCommands().isEmpty()) {
        stateMachine.saveActionToHistory("No need to remove new rules or re-install original ingress rule");
        stateMachine.fire(Event.RULES_REMOVED);
    } else {
        stateMachine.saveActionToHistory("Commands for removing new rules and re-installing original ingress rule have been sent");
    }
}
Also used : FlowSegmentRequestFactory(org.openkilda.floodlight.api.request.factory.FlowSegmentRequestFactory) MirrorContext(org.openkilda.wfm.share.model.MirrorContext) ArrayList(java.util.ArrayList) FlowCommandBuilder(org.openkilda.wfm.topology.flowhs.service.FlowCommandBuilder) FlowEncapsulationType(org.openkilda.model.FlowEncapsulationType) FlowPath(org.openkilda.model.FlowPath) SpeakerRequestBuildContext(org.openkilda.wfm.share.model.SpeakerRequestBuildContext) Flow(org.openkilda.model.Flow)

Example 3 with FlowEncapsulationType

use of org.openkilda.model.FlowEncapsulationType in project open-kilda by telstra.

the class RemoveOldRulesAction method perform.

@Override
protected void perform(State from, State to, Event event, FlowUpdateContext context, FlowUpdateFsm stateMachine) {
    FlowEncapsulationType oldEncapsulationType = stateMachine.getOriginalFlow().getFlowEncapsulationType();
    FlowCommandBuilder commandBuilder = commandBuilderFactory.getBuilder(oldEncapsulationType);
    Collection<FlowSegmentRequestFactory> factories = new ArrayList<>();
    Flow originalFlow = getOriginalFlowWithPaths(stateMachine, stateMachine.getOriginalFlow());
    MirrorContext mirrorContext = MirrorContext.builder().removeFlowOperation(true).build();
    if (stateMachine.getEndpointUpdate().isPartialUpdate()) {
        SpeakerRequestBuildContext speakerContext = getSpeakerRequestBuildContext(stateMachine, false);
        FlowPath forward = getFlowPath(stateMachine.getOldPrimaryForwardPath());
        FlowPath reverse = getFlowPath(stateMachine.getOldPrimaryReversePath());
        switch(stateMachine.getEndpointUpdate()) {
            case SOURCE:
                factories.addAll(buildCommandsForSourceUpdate(commandBuilder, stateMachine, originalFlow, forward, reverse, speakerContext, mirrorContext.toBuilder().removeGroup(false).build()));
                break;
            case DESTINATION:
                factories.addAll(buildCommandsForDestinationUpdate(commandBuilder, stateMachine, originalFlow, forward, reverse, speakerContext, mirrorContext.toBuilder().removeGroup(false).build()));
                break;
            case BOTH:
            default:
                switch(stateMachine.getFlowLoopOperation()) {
                    case DELETE:
                        factories.addAll(commandBuilder.buildIngressOnly(stateMachine.getCommandContext(), originalFlow, forward, reverse, speakerContext).stream().filter(f -> f instanceof IngressFlowLoopSegmentRequestFactory).collect(Collectors.toList()));
                        break;
                    case CREATE:
                        // No rules removing required
                        break;
                    case NONE:
                    default:
                        factories.addAll(commandBuilder.buildIngressOnly(stateMachine.getCommandContext(), originalFlow, forward, reverse, speakerContext, mirrorContext.toBuilder().removeGroup(false).build()));
                        break;
                }
                break;
        }
    } else {
        SpeakerRequestBuildContext speakerContext = getSpeakerRequestBuildContext(stateMachine, true);
        if (stateMachine.getOldPrimaryForwardPath() != null) {
            FlowPath oldForward = getFlowPath(stateMachine.getOldPrimaryForwardPath());
            if (stateMachine.getOldPrimaryReversePath() != null) {
                FlowPath oldReverse = getFlowPath(stateMachine.getOldPrimaryReversePath());
                factories.addAll(commandBuilder.buildAll(stateMachine.getCommandContext(), originalFlow, oldForward, oldReverse, speakerContext, mirrorContext));
            } else {
                factories.addAll(commandBuilder.buildAll(stateMachine.getCommandContext(), originalFlow, oldForward, speakerContext, mirrorContext));
            }
        } else if (stateMachine.getOldPrimaryReversePath() != null) {
            FlowPath oldReverse = getFlowPath(stateMachine.getOldPrimaryReversePath());
            // swap contexts
            speakerContext.setForward(speakerContext.getReverse());
            speakerContext.setReverse(PathContext.builder().build());
            factories.addAll(commandBuilder.buildAll(stateMachine.getCommandContext(), originalFlow, oldReverse, speakerContext, mirrorContext));
        }
        if (stateMachine.getOldProtectedForwardPath() != null) {
            FlowPath oldForward = getFlowPath(stateMachine.getOldProtectedForwardPath());
            if (stateMachine.getOldProtectedReversePath() != null) {
                FlowPath oldReverse = getFlowPath(stateMachine.getOldProtectedReversePath());
                factories.addAll(commandBuilder.buildAllExceptIngress(stateMachine.getCommandContext(), originalFlow, oldForward, oldReverse, mirrorContext));
            } else {
                factories.addAll(commandBuilder.buildAllExceptIngress(stateMachine.getCommandContext(), originalFlow, oldForward, mirrorContext));
            }
        } else if (stateMachine.getOldProtectedReversePath() != null) {
            FlowPath oldReverse = getFlowPath(stateMachine.getOldProtectedReversePath());
            factories.addAll(commandBuilder.buildAllExceptIngress(stateMachine.getCommandContext(), originalFlow, oldReverse, mirrorContext));
        }
    }
    stateMachine.clearPendingAndRetriedAndFailedCommands();
    if (factories.isEmpty()) {
        stateMachine.saveActionToHistory("No need to remove old rules");
        stateMachine.fire(Event.RULES_REMOVED);
    } else {
        SpeakerRemoveSegmentEmitter.INSTANCE.emitBatch(stateMachine.getCarrier(), factories, stateMachine.getRemoveCommands());
        stateMachine.getRemoveCommands().forEach((key, value) -> stateMachine.addPendingCommand(key, value.getSwitchId()));
        stateMachine.saveActionToHistory("Remove commands for old rules have been sent");
    }
}
Also used : FlowSegmentRequestFactory(org.openkilda.floodlight.api.request.factory.FlowSegmentRequestFactory) MirrorContext(org.openkilda.wfm.share.model.MirrorContext) IngressFlowLoopSegmentRequestFactory(org.openkilda.floodlight.api.request.factory.IngressFlowLoopSegmentRequestFactory) ArrayList(java.util.ArrayList) FlowCommandBuilder(org.openkilda.wfm.topology.flowhs.service.FlowCommandBuilder) FlowEncapsulationType(org.openkilda.model.FlowEncapsulationType) SpeakerRequestBuildContext(org.openkilda.wfm.share.model.SpeakerRequestBuildContext) FlowPath(org.openkilda.model.FlowPath) Flow(org.openkilda.model.Flow) RequestedFlow(org.openkilda.wfm.topology.flowhs.model.RequestedFlow)

Example 4 with FlowEncapsulationType

use of org.openkilda.model.FlowEncapsulationType in project open-kilda by telstra.

the class InMemoryPathComputer method getNPaths.

@Override
public List<Path> getNPaths(SwitchId srcSwitchId, SwitchId dstSwitchId, int count, FlowEncapsulationType flowEncapsulationType, PathComputationStrategy pathComputationStrategy, Duration maxLatency, Duration maxLatencyTier2) throws RecoverableException, UnroutableFlowException {
    final long maxLatencyNs = maxLatency != null ? maxLatency.toNanos() : 0;
    final long maxLatencyTier2Ns = maxLatencyTier2 != null ? maxLatencyTier2.toNanos() : 0;
    Flow flow = Flow.builder().flowId(// just any id, as not used.
    "").srcSwitch(Switch.builder().switchId(srcSwitchId).build()).destSwitch(Switch.builder().switchId(dstSwitchId).build()).ignoreBandwidth(false).encapsulationType(flowEncapsulationType).bandwidth(// to get ISLs with non zero available bandwidth
    1).maxLatency(maxLatencyNs).maxLatencyTier2(maxLatencyTier2Ns).build();
    AvailableNetwork availableNetwork = availableNetworkFactory.getAvailableNetwork(flow, Collections.emptyList());
    if (MAX_LATENCY.equals(pathComputationStrategy) && (flow.getMaxLatency() == null || flow.getMaxLatency() == 0)) {
        pathComputationStrategy = LATENCY;
    }
    List<List<Edge>> paths;
    switch(pathComputationStrategy) {
        case COST:
        case LATENCY:
        case COST_AND_AVAILABLE_BANDWIDTH:
            paths = pathFinder.findNPathsBetweenSwitches(availableNetwork, srcSwitchId, dstSwitchId, count, getWeightFunctionByStrategy(pathComputationStrategy));
            break;
        case MAX_LATENCY:
            paths = pathFinder.findNPathsBetweenSwitches(availableNetwork, srcSwitchId, dstSwitchId, count, getWeightFunctionByStrategy(pathComputationStrategy), maxLatencyNs, maxLatencyTier2Ns);
            break;
        default:
            throw new UnsupportedOperationException(String.format("Unsupported strategy type %s", pathComputationStrategy));
    }
    Comparator<Path> comparator;
    if (pathComputationStrategy == LATENCY || pathComputationStrategy == MAX_LATENCY) {
        comparator = Comparator.comparing(Path::getLatency).thenComparing(Comparator.comparing(Path::getMinAvailableBandwidth).reversed());
    } else {
        comparator = Comparator.comparing(Path::getMinAvailableBandwidth).reversed().thenComparing(Path::getLatency);
    }
    return paths.stream().map(edges -> convertToPath(srcSwitchId, dstSwitchId, edges)).sorted(comparator).limit(count).collect(Collectors.toList());
}
Also used : FlowPath(org.openkilda.model.FlowPath) Path(org.openkilda.pce.Path) MAX_LATENCY(org.openkilda.model.PathComputationStrategy.MAX_LATENCY) PathSegment(org.openkilda.model.PathSegment) FlowPath(org.openkilda.model.FlowPath) RecoverableException(org.openkilda.pce.exception.RecoverableException) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) UnroutableFlowException(org.openkilda.pce.exception.UnroutableFlowException) Edge(org.openkilda.pce.model.Edge) Flow(org.openkilda.model.Flow) AvailableNetworkFactory(org.openkilda.pce.AvailableNetworkFactory) Duration(java.time.Duration) PathComputerConfig(org.openkilda.pce.PathComputerConfig) LinkedList(java.util.LinkedList) PathId(org.openkilda.model.PathId) Path(org.openkilda.pce.Path) PathFinder(org.openkilda.pce.finder.PathFinder) FlowEncapsulationType(org.openkilda.model.FlowEncapsulationType) PathWeight(org.openkilda.pce.model.PathWeight) Switch(org.openkilda.model.Switch) PathComputationStrategy(org.openkilda.model.PathComputationStrategy) Collections.emptyList(java.util.Collections.emptyList) Collection(java.util.Collection) Set(java.util.Set) LATENCY(org.openkilda.model.PathComputationStrategy.LATENCY) Collectors(java.util.stream.Collectors) String.format(java.lang.String.format) WeightFunction(org.openkilda.pce.model.WeightFunction) Objects(java.util.Objects) Slf4j(lombok.extern.slf4j.Slf4j) List(java.util.List) SwitchId(org.openkilda.model.SwitchId) FindPathResult(org.openkilda.pce.model.FindPathResult) PathComputer(org.openkilda.pce.PathComputer) Optional(java.util.Optional) GetPathsResult(org.openkilda.pce.GetPathsResult) VisibleForTesting(com.google.common.annotations.VisibleForTesting) Comparator(java.util.Comparator) Collections(java.util.Collections) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) Collections.emptyList(java.util.Collections.emptyList) List(java.util.List) Flow(org.openkilda.model.Flow)

Example 5 with FlowEncapsulationType

use of org.openkilda.model.FlowEncapsulationType in project open-kilda by telstra.

the class CommandBuilderImpl method buildRemoveFlowWithoutMeterFromFlowEntry.

@VisibleForTesting
RemoveFlow buildRemoveFlowWithoutMeterFromFlowEntry(SwitchId switchId, FlowEntry entry) {
    Optional<FlowMatchField> entryMatch = Optional.ofNullable(entry.getMatch());
    Integer inPort = entryMatch.map(FlowMatchField::getInPort).map(Integer::valueOf).orElse(null);
    FlowEncapsulationType encapsulationType = FlowEncapsulationType.TRANSIT_VLAN;
    Integer encapsulationId = null;
    Integer vlan = entryMatch.map(FlowMatchField::getVlanVid).map(Integer::valueOf).orElse(null);
    if (vlan != null) {
        encapsulationId = vlan;
    } else {
        Integer tunnelId = entryMatch.map(FlowMatchField::getTunnelId).map(Integer::decode).orElse(null);
        if (tunnelId != null) {
            encapsulationId = tunnelId;
            encapsulationType = FlowEncapsulationType.VXLAN;
        }
    }
    Optional<FlowApplyActions> actions = Optional.ofNullable(entry.getInstructions()).map(FlowInstructions::getApplyActions);
    Integer outPort = actions.map(FlowApplyActions::getFlowOutput).filter(NumberUtils::isNumber).map(Integer::valueOf).orElse(null);
    SwitchId ingressSwitchId = entryMatch.map(FlowMatchField::getEthSrc).map(SwitchId::new).orElse(null);
    Long metadataValue = entryMatch.map(FlowMatchField::getMetadataValue).map(Long::decode).orElse(null);
    Long metadataMask = entryMatch.map(FlowMatchField::getMetadataMask).map(Long::decode).orElse(null);
    DeleteRulesCriteria criteria = new DeleteRulesCriteria(entry.getCookie(), inPort, encapsulationId, 0, outPort, encapsulationType, ingressSwitchId, metadataValue, metadataMask);
    return RemoveFlow.builder().transactionId(transactionIdGenerator.generate()).flowId("SWMANAGER_BATCH_REMOVE").cookie(entry.getCookie()).switchId(switchId).criteria(criteria).build();
}
Also used : FlowInstructions(org.openkilda.messaging.info.rule.FlowInstructions) FlowMatchField(org.openkilda.messaging.info.rule.FlowMatchField) DeleteRulesCriteria(org.openkilda.messaging.command.switches.DeleteRulesCriteria) FlowEncapsulationType(org.openkilda.model.FlowEncapsulationType) SwitchId(org.openkilda.model.SwitchId) FlowApplyActions(org.openkilda.messaging.info.rule.FlowApplyActions) NumberUtils(org.apache.commons.lang.math.NumberUtils) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Aggregations

FlowEncapsulationType (org.openkilda.model.FlowEncapsulationType)11 Flow (org.openkilda.model.Flow)7 FlowPath (org.openkilda.model.FlowPath)7 ArrayList (java.util.ArrayList)5 FlowSegmentRequestFactory (org.openkilda.floodlight.api.request.factory.FlowSegmentRequestFactory)4 SwitchId (org.openkilda.model.SwitchId)4 MirrorContext (org.openkilda.wfm.share.model.MirrorContext)4 SpeakerRequestBuildContext (org.openkilda.wfm.share.model.SpeakerRequestBuildContext)4 FlowCommandBuilder (org.openkilda.wfm.topology.flowhs.service.FlowCommandBuilder)4 Duration (java.time.Duration)3 List (java.util.List)3 Collectors (java.util.stream.Collectors)3 PathComputationStrategy (org.openkilda.model.PathComputationStrategy)3 PathId (org.openkilda.model.PathId)3 VisibleForTesting (com.google.common.annotations.VisibleForTesting)2 Objects (java.util.Objects)2 Optional (java.util.Optional)2 Slf4j (lombok.extern.slf4j.Slf4j)2 IngressFlowLoopSegmentRequestFactory (org.openkilda.floodlight.api.request.factory.IngressFlowLoopSegmentRequestFactory)2 DeleteRulesCriteria (org.openkilda.messaging.command.switches.DeleteRulesCriteria)2