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