use of org.onosproject.net.PortNumber in project onos by opennetworkinglab.
the class OfdpaPipelineTraceable method apply.
@Override
public PipelineTraceableOutput apply(PipelineTraceableInput input) {
PipelineTraceableOutput.Builder outputBuilder = PipelineTraceableOutput.builder();
log.debug("Current packet {} - applying flow tables", input.ingressPacket());
List<FlowEntry> outputFlows = new ArrayList<>();
List<Instruction> deferredInstructions = new ArrayList<>();
PipelineTraceableHitChain currentHitChain = PipelineTraceableHitChain.emptyHitChain();
TrafficSelector currentPacket = DefaultTrafficSelector.builder(input.ingressPacket().packet()).build();
// Init step - find out the first table
int initialTableId = -1;
FlowEntry nextTableIdEntry = findNextTableIdEntry(initialTableId, input.flows());
if (nextTableIdEntry == null) {
currentHitChain.setEgressPacket(new PipelineTraceablePacket(currentPacket));
currentHitChain.dropped();
return outputBuilder.appendToLog("No flow rules for device " + deviceId + ". Aborting").noFlows().addHitChain(currentHitChain).build();
}
// Iterates over the flow tables until the end of the pipeline
TableId tableId = nextTableIdEntry.table();
FlowEntry flowEntry;
boolean lastTable = false;
while (!lastTable) {
log.debug("Searching a Flow Entry on table {} for packet {}", tableId, currentPacket);
// Gets the rule that matches the incoming packet
flowEntry = matchHighestPriority(currentPacket, tableId, input.flows());
log.debug("Found Flow Entry {}", flowEntry);
// If the flow entry on a table is null and we are on hardware we treat as table miss, with few exceptions
if (flowEntry == null && isHardwareSwitch()) {
log.debug("Ofdpa Hw setup, no flow rule means table miss");
if (((IndexTableId) tableId).id() == MPLS_L3_TYPE_TABLE) {
// Apparently a miss but Table 27 on OFDPA is a fixed table
currentPacket = handleOfdpa27FixedTable(input.ingressPacket().packet(), currentPacket);
// The nextTable should be ACL
tableId = IndexTableId.of(ACL_TABLE - 1);
}
// Finding next table to go In case of miss
nextTableIdEntry = findNextTableIdEntry(((IndexTableId) tableId).id(), input.flows());
log.debug("Next table id entry {}", nextTableIdEntry);
// (another possibility is max tableId)
if (nextTableIdEntry == null && currentHitChain.hitChain().size() == 0) {
currentHitChain.setEgressPacket(new PipelineTraceablePacket(currentPacket));
currentHitChain.dropped();
return outputBuilder.appendToLog("No flow rules for device " + deviceId + ". Aborting").noFlows().addHitChain(currentHitChain).build();
} else if (nextTableIdEntry == null) {
// Means that no more flow rules are present
lastTable = true;
} else if (((IndexTableId) tableId).id() == TMAC_TABLE) {
// If the table is 20 OFDPA skips to table 50
log.debug("A miss on Table 20 on OFDPA means that we skip directly to table 50");
tableId = IndexTableId.of(BRIDGING_TABLE);
} else if (((IndexTableId) tableId).id() == MULTICAST_ROUTING_TABLE) {
// If the table is 40 OFDPA skips to table 60
log.debug("A miss on Table 40 on OFDPA means that we skip directly to table 60");
tableId = IndexTableId.of(ACL_TABLE);
} else {
tableId = nextTableIdEntry.table();
}
} else if (flowEntry == null) {
currentHitChain.setEgressPacket(new PipelineTraceablePacket(currentPacket));
currentHitChain.dropped();
return outputBuilder.appendToLog("Packet has no match on table " + tableId + " in device " + deviceId + ". Dropping").noFlows().addHitChain(currentHitChain).build();
} else {
// If the table has a transition
if (flowEntry.treatment().tableTransition() != null) {
// Updates the next table we transitions to
tableId = IndexTableId.of(flowEntry.treatment().tableTransition().tableId());
log.debug("Flow Entry has transition to table Id {}", tableId);
currentHitChain.addDataPlaneEntity(new DataPlaneEntity(flowEntry));
} else {
// Table has no transition so it means that it's an output rule if on the last table
log.debug("Flow Entry has no transition to table, treating as last rule {}", flowEntry);
currentHitChain.addDataPlaneEntity(new DataPlaneEntity(flowEntry));
outputFlows.add(flowEntry);
lastTable = true;
}
// Updates the packet according to the immediate actions of this flow rule.
currentPacket = updatePacket(currentPacket, flowEntry.treatment().immediate()).build();
// Saves the deferred rules for later maintaining the order
deferredInstructions.addAll(flowEntry.treatment().deferred());
// If the flow requires to clear deferred actions we do so for all the ones we encountered.
if (flowEntry.treatment().clearedDeferred()) {
deferredInstructions.clear();
}
// On table 10 OFDPA needs two rules to apply the vlan if none and then to transition to the next table.
if (shouldMatchSecondVlanFlow(flowEntry)) {
// Let's get the packet vlanId instruction
VlanIdCriterion packetVlanIdCriterion = (VlanIdCriterion) currentPacket.getCriterion(Criterion.Type.VLAN_VID);
// Let's get the flow entry vlan mod instructions
ModVlanIdInstruction entryModVlanIdInstruction = (ModVlanIdInstruction) flowEntry.treatment().immediate().stream().filter(instruction -> instruction instanceof ModVlanIdInstruction).findFirst().orElse(null);
// is a flow rule that matches on same criteria and with updated vlanId
if (entryModVlanIdInstruction != null) {
FlowEntry secondVlanFlow = getSecondFlowEntryOnTable10(currentPacket, packetVlanIdCriterion, entryModVlanIdInstruction, input.flows());
// We found the flow that we expected
if (secondVlanFlow != null) {
currentHitChain.addDataPlaneEntity(new DataPlaneEntity(secondVlanFlow));
} else {
currentHitChain.setEgressPacket(new PipelineTraceablePacket(currentPacket));
currentHitChain.dropped();
return outputBuilder.appendToLog("Missing forwarding rule for tagged" + " packet on " + deviceId).noFlows().addHitChain(currentHitChain).build();
}
}
}
}
}
// Creating a modifiable builder for the egress packet
TrafficSelector.Builder egressPacket = DefaultTrafficSelector.builder(currentPacket);
log.debug("Current packet {} - applying output flows", currentPacket);
// Handling output flows which basically means handling output to controller.
// OVS and OFDPA have both immediate -> OUTPUT:CONTROLLER. Theoretically there is no
// need to reflect the updates performed on the packets and on the chain.
List<PortNumber> outputPorts = new ArrayList<>();
handleOutputFlows(currentPacket, outputFlows, egressPacket, outputPorts, currentHitChain, outputBuilder, input.ingressPacket().packet());
// Immediate instructions
log.debug("Current packet {} - applying immediate instructions", currentPacket);
// Handling immediate instructions which basically means handling output to controller.
// OVS has immediate -> group -> OUTPUT:CONTROLLER.
List<DataPlaneEntity> entries = ImmutableList.copyOf(currentHitChain.hitChain());
// Go to the next step - using a copy of the egress packet and of the hit chain
PipelineTraceableHitChain newHitChain = PipelineTraceableHitChain.emptyHitChain();
currentHitChain.hitChain().forEach(newHitChain::addDataPlaneEntity);
TrafficSelector.Builder newEgressPacket = DefaultTrafficSelector.builder(egressPacket.build());
for (DataPlaneEntity entry : entries) {
flowEntry = entry.getFlowEntry();
if (flowEntry != null) {
getGroupsFromInstructions(input.groups(), flowEntry.treatment().immediate(), newEgressPacket, outputPorts, newHitChain, outputBuilder, input, false);
}
}
// Deferred instructions
log.debug("Current packet {} - applying deferred instructions", egressPacket.build());
// egress packet and of the hit chain. This is the last step.
if (deferredInstructions.size() > 0) {
handleDeferredActions(egressPacket.build(), input.groups(), deferredInstructions, outputPorts, currentHitChain, outputBuilder, input);
}
// Let's store the partial hit chain and set a message
if (outputPorts.isEmpty()) {
currentHitChain.setEgressPacket(new PipelineTraceablePacket(egressPacket.build()));
currentHitChain.dropped();
outputBuilder.appendToLog("Packet has no output in device " + deviceId + ". Dropping").dropped().addHitChain(currentHitChain);
}
// Done!
return outputBuilder.build();
}
use of org.onosproject.net.PortNumber in project onos by opennetworkinglab.
the class FujitsuT100DeviceDescription method parseT100OchPort.
private static PortDescription parseT100OchPort(HierarchicalConfiguration cfg, long count) {
PortNumber portNumber = PortNumber.portNumber(count);
HierarchicalConfiguration otuConfig = cfg.configurationAt("otu");
boolean enabled = "up".equals(otuConfig.getString("administrative-state"));
OduSignalType signalType = "OTU4".equals(otuConfig.getString("rate")) ? OduSignalType.ODU4 : null;
// Unsure how to retrieve, outside knowledge it is tunable.
boolean isTunable = true;
OchSignal lambda = new OchSignal(GridType.DWDM, ChannelSpacing.CHL_50GHZ, 0, 4);
DefaultAnnotations annotations = DefaultAnnotations.builder().set(AnnotationKeys.PORT_NAME, cfg.getString("name")).build();
return ochPortDescription(portNumber, enabled, signalType, isTunable, lambda, annotations);
}
use of org.onosproject.net.PortNumber in project onos by opennetworkinglab.
the class ResourcesCommand method doExecute.
@Override
protected void doExecute() {
resourceService = get(ResourceQueryService.class);
if (typeStrings != null) {
typesToPrint = new HashSet<>(Arrays.asList(typeStrings));
} else {
typesToPrint = Collections.emptySet();
}
if (deviceIdStr != null && portNumberStr != null) {
DeviceId deviceId = deviceId(deviceIdStr);
PortNumber portNumber = PortNumber.fromString(portNumberStr);
printResource(Resources.discrete(deviceId, portNumber).resource(), 0);
} else if (deviceIdStr != null) {
DeviceId deviceId = deviceId(deviceIdStr);
printResource(Resources.discrete(deviceId).resource(), 0);
} else {
printResource(Resource.ROOT, 0);
}
}
use of org.onosproject.net.PortNumber in project onos by opennetworkinglab.
the class LinkCollectionCompiler method manageSpIntent.
/**
* Manages the Intents with a single ingress point (p2p, sp2mp)
* creating properly the selector builder and the treatment builder.
*
* @param selectorBuilder the selector builder to update
* @param treatmentBuilder the treatment builder to update
* @param intent the intent to compile
* @param deviceId the current device
* @param outPorts the output ports of this device
*/
private void manageSpIntent(TrafficSelector.Builder selectorBuilder, TrafficTreatment.Builder treatmentBuilder, LinkCollectionIntent intent, DeviceId deviceId, Set<PortNumber> outPorts) {
/*
* Sanity check.
*/
if (intent.filteredIngressPoints().size() != 1) {
throw new IntentCompilationException(WRONG_INGRESS);
}
/*
* For the p2p and sp2mp the transition initial state
* to final state is performed at the egress.
*/
Optional<FilteredConnectPoint> filteredIngressPoint = intent.filteredIngressPoints().stream().findFirst();
/*
* We build the final selector, adding the selector
* of the FIP to the Intent selector and potentially
* overriding its matches.
*/
filteredIngressPoint.get().trafficSelector().criteria().forEach(selectorBuilder::add);
/*
* In this scenario, potentially we can have several output
* ports. First we have to insert in the treatment the actions
* for the core.
*/
List<FilteredConnectPoint> egressPoints = Lists.newArrayList();
for (PortNumber outPort : outPorts) {
Optional<FilteredConnectPoint> filteredEgressPoint = getFilteredConnectPointFromIntent(deviceId, outPort, intent);
if (!filteredEgressPoint.isPresent()) {
treatmentBuilder.setOutput(outPort);
} else {
egressPoints.add(filteredEgressPoint.get());
}
}
/*
* The idea is to order the egress points. Before we deal
* with the egress points which looks like similar to the ingress
* point then the others.
*/
TrafficSelector prevState = filteredIngressPoint.get().trafficSelector();
if (optimizeTreatments()) {
egressPoints = orderedEgressPoints(prevState, egressPoints);
}
/*
* Then we deal with the egress points.
*/
generateEgressActions(treatmentBuilder, egressPoints, prevState, intent);
}
use of org.onosproject.net.PortNumber in project onos by opennetworkinglab.
the class LinkCollectionCompiler method manageOutputPorts.
/**
* Helper method which handles the proper generation of the ouput actions.
*
* @param outPorts the output ports
* @param deviceId the current device
* @param intent the intent to compile
* @param outLabels the output labels
* @param type the encapsulation type
* @param preCondition the previous state
* @param treatmentBuilder the builder to update with the ouput actions
*/
private void manageOutputPorts(Set<PortNumber> outPorts, DeviceId deviceId, LinkCollectionIntent intent, Map<ConnectPoint, Identifier<?>> outLabels, EncapsulationType type, TrafficSelector.Builder preCondition, TrafficTreatment.Builder treatmentBuilder) {
/*
* We need to order the actions. First the actions
* related to the not-egress points. At the same time we collect
* also the egress points.
*/
List<FilteredConnectPoint> egressPoints = Lists.newArrayList();
for (PortNumber outPort : outPorts) {
Optional<FilteredConnectPoint> filteredEgressPoint = getFilteredConnectPointFromIntent(deviceId, outPort, intent);
if (!filteredEgressPoint.isPresent()) {
/*
* We build a temporary selector for the encapsulation.
*/
TrafficSelector.Builder encapBuilder = DefaultTrafficSelector.builder();
/*
* We retrieve the associated label to the output port.
*/
ConnectPoint cp = new ConnectPoint(deviceId, outPort);
Identifier<?> outLabel = outLabels.get(cp);
/*
* If there are not labels, we cannot handle.
*/
if (outLabel == null) {
throw new IntentCompilationException(String.format(NO_LABELS, cp));
}
/*
* In the core we match using encapsulation.
*/
updateSelectorFromEncapsulation(encapBuilder, type, outLabel);
/*
* We generate the transition.
*/
TrafficTreatment forwardingTreatment = forwardingTreatment(preCondition.build(), encapBuilder.build(), getEthType(intent.selector()));
/*
* We add the instruction necessary to the transition.
*/
forwardingTreatment.allInstructions().stream().filter(inst -> inst.type() != Instruction.Type.NOACTION).forEach(treatmentBuilder::add);
/*
* Finally we set the output action.
*/
treatmentBuilder.setOutput(outPort);
/*
* The encapsulation modifies the packet. If we are optimizing
* we have to update the state.
*/
if (optimizeTreatments()) {
preCondition = encapBuilder;
}
} else {
egressPoints.add(filteredEgressPoint.get());
}
}
/*
* The idea is to order the egress points. Before we deal
* with the egress points which looks like similar to the
* selector derived from the previous state then the
* the others.
*/
TrafficSelector prevState = preCondition.build();
if (optimizeTreatments()) {
egressPoints = orderedEgressPoints(prevState, egressPoints);
}
/*
* In this case, we have to transit to the final
* state.
*/
generateEgressActions(treatmentBuilder, egressPoints, prevState, intent);
}
Aggregations