use of org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction in project onos by opennetworkinglab.
the class InstructionJsonMatcher method matchModVlanIdInstruction.
/**
* Matches the contents of a mod vlan id instruction.
*
* @param instructionJson JSON instruction to match
* @param description Description object used for recording errors
* @return true if contents match, false otherwise
*/
private boolean matchModVlanIdInstruction(JsonNode instructionJson, Description description) {
ModVlanIdInstruction instructionToMatch = (ModVlanIdInstruction) instruction;
final String jsonSubtype = instructionJson.get("subtype").textValue();
if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
description.appendText("subtype was " + jsonSubtype);
return false;
}
final String jsonType = instructionJson.get("type").textValue();
if (!instructionToMatch.type().name().equals(jsonType)) {
description.appendText("type was " + jsonType);
return false;
}
final short jsonVlanId = instructionJson.get("vlanId").shortValue();
final short vlanId = instructionToMatch.vlanId().toShort();
if (jsonVlanId != vlanId) {
description.appendText("vlan id was " + jsonVlanId);
return false;
}
return true;
}
use of org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction 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.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction in project onos by opennetworkinglab.
the class FlowModBuilderVer10 method buildL2Modification.
private OFAction buildL2Modification(Instruction i) {
L2ModificationInstruction l2m = (L2ModificationInstruction) i;
ModEtherInstruction eth;
switch(l2m.subtype()) {
case ETH_DST:
eth = (ModEtherInstruction) l2m;
return factory().actions().setDlDst(MacAddress.of(eth.mac().toLong()));
case ETH_SRC:
eth = (ModEtherInstruction) l2m;
return factory().actions().setDlSrc(MacAddress.of(eth.mac().toLong()));
case VLAN_ID:
ModVlanIdInstruction vlanId = (ModVlanIdInstruction) l2m;
return factory().actions().setVlanVid(VlanVid.ofVlan(vlanId.vlanId().toShort()));
case VLAN_PCP:
ModVlanPcpInstruction vlanPcp = (ModVlanPcpInstruction) l2m;
return factory().actions().setVlanPcp(VlanPcp.of(vlanPcp.vlanPcp()));
case VLAN_POP:
return factory().actions().stripVlan();
case VLAN_PUSH:
return null;
default:
log.warn("Unimplemented action type {}.", l2m.subtype());
break;
}
return null;
}
use of org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction in project onos by opennetworkinglab.
the class InstructionJsonMatcher method matchesSafely.
@Override
public boolean matchesSafely(JsonNode jsonInstruction, Description description) {
// check type
final JsonNode jsonTypeNode = jsonInstruction.get("type");
final String jsonType = jsonTypeNode.textValue();
final String type = instruction.type().name();
if (!jsonType.equals(type)) {
description.appendText("type was " + type);
return false;
}
if (instruction instanceof ModMplsHeaderInstruction) {
return matchModMplsHeaderInstruction(jsonInstruction, description);
} else if (instruction instanceof OutputInstruction) {
return matchOutputInstruction(jsonInstruction, description);
} else if (instruction instanceof GroupInstruction) {
return matchGroupInstruction(jsonInstruction, description);
} else if (instruction instanceof MeterInstruction) {
return matchMeterInstruction(jsonInstruction, description);
} else if (instruction instanceof SetQueueInstruction) {
return matchSetQueueInstruction(jsonInstruction, description);
} else if (instruction instanceof ModOchSignalInstruction) {
return matchModOchSingalInstruction(jsonInstruction, description);
} else if (instruction instanceof ModEtherInstruction) {
return matchModEtherInstruction(jsonInstruction, description);
} else if (instruction instanceof ModVlanIdInstruction) {
return matchModVlanIdInstruction(jsonInstruction, description);
} else if (instruction instanceof ModVlanPcpInstruction) {
return matchModVlanPcpInstruction(jsonInstruction, description);
} else if (instruction instanceof ModIPInstruction) {
return matchModIpInstruction(jsonInstruction, description);
} else if (instruction instanceof ModIPv6FlowLabelInstruction) {
return matchModIPv6FlowLabelInstruction(jsonInstruction, description);
} else if (instruction instanceof ModMplsLabelInstruction) {
return matchModMplsLabelInstruction(jsonInstruction, description);
} else if (instruction instanceof ModOduSignalIdInstruction) {
return matchModOduSingalIdInstruction(jsonInstruction, description);
} else if (instruction instanceof PiInstruction) {
return matchPiInstruction(jsonInstruction, description);
} else if (instruction instanceof NoActionInstruction) {
return true;
}
return false;
}
use of org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction in project onos by opennetworkinglab.
the class LinkCollectionCompiler method updateBuilder.
/**
* Update the selector builder using a L2 instruction.
*
* @param builder the builder to update
* @param l2instruction the l2 instruction to use
*/
private void updateBuilder(TrafficSelector.Builder builder, L2ModificationInstruction l2instruction) {
switch(l2instruction.subtype()) {
case ETH_SRC:
case ETH_DST:
ModEtherInstruction ethInstr = (ModEtherInstruction) l2instruction;
switch(ethInstr.subtype()) {
case ETH_SRC:
builder.matchEthSrc(ethInstr.mac());
break;
case ETH_DST:
builder.matchEthDst(ethInstr.mac());
break;
default:
throw new IntentCompilationException(UNSUPPORTED_ETH_SUBTYPE);
}
break;
case VLAN_ID:
ModVlanIdInstruction vlanIdInstr = (ModVlanIdInstruction) l2instruction;
builder.matchVlanId(vlanIdInstr.vlanId());
break;
case VLAN_PUSH:
// FIXME
break;
case VLAN_POP:
// TODO how do we handle dropped label? remove the selector?
throw new IntentCompilationException(UNSUPPORTED_POP_ACTION);
case VLAN_PCP:
ModVlanPcpInstruction vlanPcpInstruction = (ModVlanPcpInstruction) l2instruction;
builder.matchVlanPcp(vlanPcpInstruction.vlanPcp());
break;
case MPLS_LABEL:
case MPLS_PUSH:
// FIXME
ModMplsLabelInstruction mplsInstr = (ModMplsLabelInstruction) l2instruction;
builder.matchMplsLabel(mplsInstr.label());
break;
case MPLS_POP:
// TODO how do we handle dropped label? remove the selector?
throw new IntentCompilationException(UNSUPPORTED_POP_ACTION);
case DEC_MPLS_TTL:
// no-op
break;
case MPLS_BOS:
ModMplsBosInstruction mplsBosInstr = (ModMplsBosInstruction) l2instruction;
builder.matchMplsBos(mplsBosInstr.mplsBos());
break;
case TUNNEL_ID:
ModTunnelIdInstruction tunInstr = (ModTunnelIdInstruction) l2instruction;
builder.matchTunnelId(tunInstr.tunnelId());
break;
default:
throw new IntentCompilationException(UNSUPPORTED_L2);
}
}
Aggregations