use of org.openkilda.floodlight.api.request.factory.FlowSegmentRequestFactory in project open-kilda by telstra.
the class SpeakerFlowSegmentRequestBuilderTest method shouldCreateNonIngressCommandsWithTransitSwitch.
@Test
public void shouldCreateNonIngressCommandsWithTransitSwitch() {
Switch srcSwitch = Switch.builder().switchId(SWITCH_1).build();
Switch destSwitch = Switch.builder().switchId(SWITCH_3).build();
Flow flow = buildFlow(srcSwitch, 1, 101, destSwitch, 2, 102, 0);
setSegmentsWithTransitSwitches(Objects.requireNonNull(flow.getForwardPath()), Objects.requireNonNull(flow.getReversePath()));
List<FlowSegmentRequestFactory> commands = target.buildAllExceptIngress(COMMAND_CONTEXT, flow);
assertEquals(4, commands.size());
verifyForwardTransitRequest(flow, SWITCH_2, commands.get(0).makeInstallRequest(commandIdGenerator.generate()));
verifyForwardEgressRequest(flow, commands.get(1).makeInstallRequest(commandIdGenerator.generate()));
verifyReverseTransitRequest(flow, SWITCH_2, commands.get(2).makeInstallRequest(commandIdGenerator.generate()));
verifyReverseEgressRequest(flow, commands.get(3).makeInstallRequest(commandIdGenerator.generate()));
}
use of org.openkilda.floodlight.api.request.factory.FlowSegmentRequestFactory in project open-kilda by telstra.
the class SpeakerFlowSegmentRequestBuilderTest method commonIngressCommandTest.
private void commonIngressCommandTest(int bandwidth) {
Switch srcSwitch = Switch.builder().switchId(SWITCH_1).build();
Switch destSwitch = Switch.builder().switchId(SWITCH_2).build();
Flow flow = buildFlow(srcSwitch, 1, 101, destSwitch, 2, 102, bandwidth);
setSegmentsWithoutTransitSwitches(Objects.requireNonNull(flow.getForwardPath()), Objects.requireNonNull(flow.getReversePath()));
List<FlowSegmentRequestFactory> commands = target.buildIngressOnly(COMMAND_CONTEXT, flow, SpeakerRequestBuildContext.getEmpty());
assertEquals(2, commands.size());
verifyForwardIngressRequest(flow, commands.get(0).makeInstallRequest(commandIdGenerator.generate()));
verifyReverseIngressRequest(flow, commands.get(1).makeInstallRequest(commandIdGenerator.generate()));
}
use of org.openkilda.floodlight.api.request.factory.FlowSegmentRequestFactory in project open-kilda by telstra.
the class ValidateNonIngressRulesAction method perform.
@Override
protected void perform(State from, State to, Event event, FlowUpdateContext context, FlowUpdateFsm stateMachine) {
SpeakerFlowSegmentResponse response = context.getSpeakerFlowResponse();
UUID commandId = response.getCommandId();
FlowSegmentRequestFactory command = stateMachine.getNonIngressCommands().get(commandId);
if (!stateMachine.getPendingCommands().containsKey(commandId) || command == null) {
log.info("Received a response for unexpected command: {}", response);
return;
}
if (response.isSuccess()) {
stateMachine.removePendingCommand(commandId);
stateMachine.saveActionToHistory("Rule was validated", format("The non ingress rule has been validated successfully: switch %s, cookie %s", command.getSwitchId(), command.getCookie()));
} else {
FlowErrorResponse errorResponse = (FlowErrorResponse) response;
int attempt = stateMachine.doRetryForCommand(commandId);
if (attempt <= speakerCommandRetriesLimit && errorResponse.getErrorCode() != FlowErrorResponse.ErrorCode.MISSING_OF_FLOWS) {
stateMachine.saveErrorToHistory(RULE_VALIDATION_FAILED_ACTION, format("Failed to validate non ingress rule: commandId %s, switch %s, cookie %s. Error %s. " + "Retrying (attempt %d)", commandId, errorResponse.getSwitchId(), command.getCookie(), errorResponse, attempt));
stateMachine.getCarrier().sendSpeakerRequest(command.makeVerifyRequest(commandId));
} else if (stateMachine.isDoNotRevert()) {
stateMachine.removePendingCommand(commandId);
stateMachine.saveErrorToHistory(RULE_VALIDATION_FAILED_ACTION, format("Failed to validate non ingress rule: commandId %s, switch %s, cookie %s. Error %s. " + "Skipping validation attempts", commandId, errorResponse.getSwitchId(), command.getCookie(), errorResponse));
stateMachine.setNewFlowStatus(FlowStatus.DOWN);
stateMachine.setErrorReason(RULE_VALIDATION_FAILED_ACTION);
} else {
stateMachine.removePendingCommand(commandId);
stateMachine.saveErrorToHistory(RULE_VALIDATION_FAILED_ACTION, format("Failed to validate non ingress rule: commandId %s, switch %s, cookie %s. Error %s", commandId, errorResponse.getSwitchId(), command.getCookie(), errorResponse));
stateMachine.getFailedValidationResponses().put(commandId, response);
}
}
if (stateMachine.getPendingCommands().isEmpty()) {
if (stateMachine.getFailedValidationResponses().isEmpty()) {
log.debug("Non ingress rules have been validated for flow {}", stateMachine.getFlowId());
stateMachine.fire(Event.RULES_VALIDATED);
} else {
stateMachine.saveErrorToHistory(format("Found missing rules or received error response(s) on %d validation commands", stateMachine.getFailedValidationResponses().size()));
stateMachine.fire(Event.MISSING_RULE_FOUND);
}
}
}
use of org.openkilda.floodlight.api.request.factory.FlowSegmentRequestFactory in project open-kilda by telstra.
the class RevertNewRulesAction method perform.
@Override
protected void perform(State from, State to, Event event, FlowUpdateContext context, FlowUpdateFsm stateMachine) {
String flowId = stateMachine.getFlowId();
Flow flow = getFlow(flowId);
log.debug("Abandoning all pending commands: {}", stateMachine.getPendingCommands());
stateMachine.clearPendingAndRetriedAndFailedCommands();
FlowEncapsulationType encapsulationType = stateMachine.getTargetFlow().getFlowEncapsulationType();
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 speakerContext = buildBaseSpeakerContextForInstall(oldForward.getSrcSwitchId(), oldReverse.getSrcSwitchId());
installCommands.addAll(commandBuilder.buildIngressOnly(stateMachine.getCommandContext(), flow, oldForward, oldReverse, speakerContext));
}
// 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()));
CommandContext commandContext = stateMachine.getCommandContext();
// Remove possible installed segments
MirrorContext mirrorContext = MirrorContext.builder().removeFlowOperation(true).build();
Collection<FlowSegmentRequestFactory> revertCommands = new ArrayList<>();
if (stateMachine.getNewPrimaryForwardPath() != null && stateMachine.getNewPrimaryReversePath() != null) {
FlowPath newForward = getFlowPath(flow, stateMachine.getNewPrimaryForwardPath());
FlowPath newReverse = getFlowPath(flow, stateMachine.getNewPrimaryReversePath());
if (stateMachine.getEndpointUpdate().isPartialUpdate()) {
SpeakerRequestBuildContext speakerRequestBuildContext = getSpeakerRequestBuildContextForRemoval(stateMachine, false);
Flow oldFlow = RequestedFlowMapper.INSTANCE.toFlow(stateMachine.getOriginalFlow());
switch(stateMachine.getEndpointUpdate()) {
case SOURCE:
switch(stateMachine.getFlowLoopOperation()) {
case NONE:
revertCommands.addAll(commandBuilder.buildIngressOnlyOneDirection(commandContext, flow, newForward, newReverse, speakerRequestBuildContext.getForward(), mirrorContext));
revertCommands.addAll(commandBuilder.buildEgressOnlyOneDirection(commandContext, oldFlow, newReverse, newForward, mirrorContext));
break;
case CREATE:
revertCommands.addAll(commandBuilder.buildAll(commandContext, flow, newForward, newReverse, speakerRequestBuildContext).stream().filter(f -> f instanceof IngressFlowLoopSegmentRequestFactory || f instanceof TransitFlowLoopSegmentRequestFactory).collect(Collectors.toList()));
break;
case DELETE:
default:
// No need to revert rules
break;
}
break;
case DESTINATION:
switch(stateMachine.getFlowLoopOperation()) {
case NONE:
revertCommands.addAll(commandBuilder.buildIngressOnlyOneDirection(commandContext, flow, newReverse, newForward, speakerRequestBuildContext.getReverse(), mirrorContext));
revertCommands.addAll(commandBuilder.buildEgressOnlyOneDirection(commandContext, oldFlow, newForward, newReverse, mirrorContext));
break;
case CREATE:
revertCommands.addAll(commandBuilder.buildAll(commandContext, flow, newForward, newReverse, speakerRequestBuildContext).stream().filter(f -> f instanceof IngressFlowLoopSegmentRequestFactory || f instanceof TransitFlowLoopSegmentRequestFactory).collect(Collectors.toList()));
break;
case DELETE:
default:
// No need to revert rules
break;
}
break;
default:
revertCommands.addAll(commandBuilder.buildIngressOnly(commandContext, flow, newForward, newReverse, speakerRequestBuildContext, mirrorContext));
revertCommands.addAll(commandBuilder.buildEgressOnly(commandContext, oldFlow, newForward, newReverse, mirrorContext));
break;
}
} else {
revertCommands.addAll(commandBuilder.buildAll(stateMachine.getCommandContext(), flow, newForward, newReverse, getSpeakerRequestBuildContextForRemoval(stateMachine, true), mirrorContext));
}
}
if (stateMachine.getNewProtectedForwardPath() != null && stateMachine.getNewProtectedReversePath() != null) {
FlowPath newForward = getFlowPath(flow, stateMachine.getNewProtectedForwardPath());
FlowPath newReverse = getFlowPath(flow, stateMachine.getNewProtectedReversePath());
Flow oldFlow = RequestedFlowMapper.INSTANCE.toFlow(stateMachine.getOriginalFlow());
if (stateMachine.getEndpointUpdate().isPartialUpdate()) {
switch(stateMachine.getEndpointUpdate()) {
case SOURCE:
if (stateMachine.getFlowLoopOperation() == NONE) {
revertCommands.addAll(commandBuilder.buildEgressOnlyOneDirection(commandContext, oldFlow, newReverse, newForward, mirrorContext));
}
break;
case DESTINATION:
if (stateMachine.getFlowLoopOperation() == NONE) {
revertCommands.addAll(commandBuilder.buildEgressOnlyOneDirection(commandContext, oldFlow, newForward, newReverse, mirrorContext));
}
break;
default:
revertCommands.addAll(commandBuilder.buildEgressOnly(commandContext, oldFlow, newForward, newReverse, mirrorContext));
break;
}
} else {
revertCommands.addAll(commandBuilder.buildAllExceptIngress(stateMachine.getCommandContext(), flow, newForward, newReverse, mirrorContext));
}
}
stateMachine.getRemoveCommands().clear();
SpeakerRemoveSegmentEmitter.INSTANCE.emitBatch(stateMachine.getCarrier(), revertCommands, 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.floodlight.api.request.factory.FlowSegmentRequestFactory in project open-kilda by telstra.
the class RemoveOldRulesAction method perform.
@TimedExecution("fsm.remove_old_rules")
@Override
protected void perform(State from, State to, Event event, FlowRerouteContext context, FlowRerouteFsm stateMachine) {
FlowEncapsulationType encapsulationType = stateMachine.getOriginalEncapsulationType();
FlowCommandBuilder commandBuilder = commandBuilderFactory.getBuilder(encapsulationType);
Collection<FlowSegmentRequestFactory> factories = new ArrayList<>();
Flow originalFlow = getOriginalFlowWithPaths(stateMachine, stateMachine.getOriginalFlow());
SpeakerRequestBuildContext speakerContext = SpeakerRequestBuildContext.getEmpty();
MirrorContext mirrorContext = MirrorContext.builder().removeFlowOperation(true).build();
if (stateMachine.getOldPrimaryForwardPath() != null) {
FlowPath oldForward = getFlowPath(stateMachine.getOldPrimaryForwardPath());
speakerContext.setForward(buildPathContextForRemovalIngressOnly(oldForward.getSrcSwitchId()));
if (stateMachine.getOldPrimaryReversePath() != null) {
FlowPath oldReverse = getFlowPath(stateMachine.getOldPrimaryReversePath());
speakerContext.setReverse(buildPathContextForRemovalIngressOnly(oldReverse.getSrcSwitchId()));
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());
speakerContext.setForward(buildPathContextForRemovalIngressOnly(oldReverse.getSrcSwitchId()));
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 {
Map<UUID, FlowSegmentRequestFactory> requestsStorage = stateMachine.getRemoveCommands();
for (FlowSegmentRequestFactory factory : factories) {
FlowSegmentRequest request = factory.makeRemoveRequest(commandIdGenerator.generate());
// TODO ensure no conflicts
requestsStorage.put(request.getCommandId(), factory);
stateMachine.getCarrier().sendSpeakerRequest(request);
}
requestsStorage.forEach((key, value) -> stateMachine.addPendingCommand(key, value.getSwitchId()));
stateMachine.saveActionToHistory("Remove commands for old rules have been sent");
}
}
Aggregations