use of org.onosproject.net.flow.instructions.L2ModificationInstruction in project onos by opennetworkinglab.
the class Ofdpa2GroupHandler method processSimpleNextObjective.
/**
* As per the OFDPA 2.0 TTP, packets are sent out of ports by using
* a chain of groups. The simple Next Objective passed in by the application
* is broken up into a group chain. The following chains can be created
* depending on the parameters in the Next Objective.
* 1. L2 Interface group (no chaining)
* 2. L3 Unicast group -> L2 Interface group
* 3. MPLS Interface group -> L2 Interface group
* 4. MPLS Swap group -> MPLS Interface group -> L2 Interface group
* 5. PW initiation group chain
*
* @param nextObj the nextObjective of type SIMPLE
*/
private void processSimpleNextObjective(NextObjective nextObj) {
TrafficTreatment treatment = nextObj.next().iterator().next();
// determine if plain L2 or L3->L2 or MPLS Swap -> MPLS Interface -> L2
boolean plainL2 = true;
boolean mplsSwap = false;
MplsLabel mplsLabel = null;
for (Instruction ins : treatment.allInstructions()) {
if (ins.type() == Instruction.Type.L2MODIFICATION) {
L2ModificationInstruction l2ins = (L2ModificationInstruction) ins;
if (l2ins.subtype() == L2ModificationInstruction.L2SubType.ETH_DST || l2ins.subtype() == L2ModificationInstruction.L2SubType.ETH_SRC) {
plainL2 = false;
}
// a MPLS Swap group before the MPLS Interface Group
if (l2ins.subtype() == L2ModificationInstruction.L2SubType.MPLS_LABEL) {
mplsSwap = true;
mplsLabel = ((L2ModificationInstruction.ModMplsLabelInstruction) l2ins).label();
}
}
}
if (plainL2) {
createL2InterfaceGroup(nextObj);
return;
}
// In order to understand if it is a pseudowire related
// next objective we look for the tunnel id in the meta.
boolean isPw = false;
if (nextObj.meta() != null) {
TunnelIdCriterion tunnelIdCriterion = (TunnelIdCriterion) nextObj.meta().getCriterion(TUNNEL_ID);
if (tunnelIdCriterion != null) {
isPw = true;
}
}
if (mplsSwap && !isPw) {
log.debug("Creating a MPLS Swap -> MPLS Interface -> L2 Interface group chain.");
// break up simple next objective to GroupChain objects
GroupInfo groupInfo = createL2L3Chain(treatment, nextObj.id(), nextObj.appId(), true, nextObj.meta());
if (groupInfo == null) {
log.error("Could not process nextObj={} in dev:{}", nextObj.id(), deviceId);
fail(nextObj, ObjectiveError.BADPARAMS);
return;
}
Deque<GroupKey> gkeyChain = new ArrayDeque<>();
// l2 interface
gkeyChain.addFirst(groupInfo.innerMostGroupDesc().appCookie());
// mpls interface
gkeyChain.addFirst(groupInfo.nextGroupDesc().appCookie());
// creating the mpls swap group and adding it to the chain
int nextGid = groupInfo.nextGroupDesc().givenGroupId();
int index = getNextAvailableIndex();
GroupDescription swapGroupDescription = createMplsSwap(nextGid, OfdpaMplsGroupSubType.MPLS_SWAP_LABEL, index, mplsLabel, nextObj.appId());
// ensure swap group is added after L2L3 chain
GroupKey swapGroupKey = swapGroupDescription.appCookie();
GroupChainElem swapChainElem = new GroupChainElem(swapGroupDescription, 1, false, deviceId);
updatePendingGroups(groupInfo.nextGroupDesc().appCookie(), swapChainElem);
gkeyChain.addFirst(swapGroupKey);
// ensure nextObjective waits on the outermost groupKey
List<Deque<GroupKey>> allGroupKeys = Lists.newArrayList();
allGroupKeys.add(gkeyChain);
OfdpaNextGroup ofdpaGrp = new OfdpaNextGroup(allGroupKeys, nextObj);
updatePendingNextObjective(swapGroupKey, ofdpaGrp);
// now we are ready to send the l2 groupDescription (inner), as all the stores
// that will get async replies have been updated. By waiting to update
// the stores, we prevent nasty race conditions.
groupService.addGroup(groupInfo.innerMostGroupDesc());
} else if (!isPw) {
boolean isMpls = false;
if (nextObj.meta() != null) {
isMpls = isNotMplsBos(nextObj.meta());
}
log.debug("Creating a {} -> L2 Interface group chain.", (isMpls) ? "MPLS Interface" : "L3 Unicast");
// break up simple next objective to GroupChain objects
GroupInfo groupInfo = createL2L3Chain(treatment, nextObj.id(), nextObj.appId(), isMpls, nextObj.meta());
if (groupInfo == null) {
log.error("Could not process nextObj={} in dev:{}", nextObj.id(), deviceId);
fail(nextObj, ObjectiveError.BADPARAMS);
return;
}
// create object for local and distributed storage
Deque<GroupKey> gkeyChain = new ArrayDeque<>();
gkeyChain.addFirst(groupInfo.innerMostGroupDesc().appCookie());
gkeyChain.addFirst(groupInfo.nextGroupDesc().appCookie());
List<Deque<GroupKey>> allGroupKeys = Lists.newArrayList();
allGroupKeys.add(gkeyChain);
OfdpaNextGroup ofdpaGrp = new OfdpaNextGroup(allGroupKeys, nextObj);
// store l3groupkey with the ofdpaNextGroup for the nextObjective that depends on it
updatePendingNextObjective(groupInfo.nextGroupDesc().appCookie(), ofdpaGrp);
// now we are ready to send the l2 groupDescription (inner), as all the stores
// that will get async replies have been updated. By waiting to update
// the stores, we prevent nasty race conditions.
groupService.addGroup(groupInfo.innerMostGroupDesc());
} else {
// We handle the pseudo wire with a different a procedure.
// This procedure is meant to handle both initiation and
// termination of the pseudo wire.
processPwNextObjective(nextObj);
}
}
use of org.onosproject.net.flow.instructions.L2ModificationInstruction in project onos by opennetworkinglab.
the class HPPipelineV3500 method tableIdForForwardingObjective.
@Override
protected int tableIdForForwardingObjective(TrafficSelector selector, TrafficTreatment treatment) {
boolean hardwareProcess = true;
log.debug("HP V3500 Driver - Evaluating the ForwardingObjective for proper TableID");
// Check criteria supported in hardware
for (Criterion criterion : selector.criteria()) {
if (!this.hardwareCriteria.contains(criterion.type())) {
log.warn("HP V3500 Driver - criterion {} only supported in SOFTWARE", criterion.type());
hardwareProcess = false;
break;
}
// HP3500 supports hardware match on ETH_TYPE only with value TYPE_IPV4
if (criterion.type() == Criterion.Type.ETH_TYPE) {
if (((EthTypeCriterion) criterion).ethType().toShort() != Ethernet.TYPE_IPV4) {
log.warn("HP V3500 Driver - only ETH_TYPE == IPv4 (0x0800) is supported in hardware");
hardwareProcess = false;
break;
}
}
// HP3500 supports IN_PORT criterion in hardware only if associated with ETH_TYPE criterion
if (criterion.type() == Criterion.Type.IN_PORT) {
hardwareProcess = false;
for (Criterion requiredCriterion : selector.criteria()) {
if (requiredCriterion.type() == Criterion.Type.ETH_TYPE) {
hardwareProcess = true;
}
}
if (!hardwareProcess) {
log.warn("HP V3500 Driver - IN_PORT criterion without ETH_TYPE is not supported in hardware");
break;
}
}
}
// Check if a CLEAR action is included
if (treatment.clearedDeferred()) {
log.warn("HP V3500 Driver - CLEAR action only supported in SOFTWARE");
hardwareProcess = false;
}
// If criteria can be processed in hardware, then check treatment
if (hardwareProcess) {
for (Instruction instruction : treatment.allInstructions()) {
// Check if the instruction type is contained in the hardware instruction
if (!this.hardwareInstructions.contains(instruction.type())) {
log.warn("HP V3500 Driver - instruction {} only supported in SOFTWARE", instruction.type());
hardwareProcess = false;
break;
}
/**
* If output is CONTROLLER_PORT the flow entry could be installed in hardware
* but is anyway processed in software because openflow header has to be added
*/
if (instruction.type() == Instruction.Type.OUTPUT) {
if (((Instructions.OutputInstruction) instruction).port() == PortNumber.CONTROLLER) {
log.warn("HP V3500 Driver - Forwarding to CONTROLLER only supported in software");
hardwareProcess = false;
break;
}
}
/**
* Only L2MODIFICATION supported in hardware is MODIFY VLAN_PRIORITY.
* Check if the specific L2MODIFICATION.subtype is supported in hardware
*/
if (instruction.type() == Instruction.Type.L2MODIFICATION) {
if (!this.hardwareInstructionsL2mod.contains(((L2ModificationInstruction) instruction).subtype())) {
log.warn("HP V3500 Driver - L2MODIFICATION.subtype {} only supported in SOFTWARE", ((L2ModificationInstruction) instruction).subtype());
hardwareProcess = false;
break;
}
}
}
}
if (hardwareProcess) {
log.warn("HP V3500 Driver - This flow rule is supported in HARDWARE");
return HP_HARDWARE_TABLE;
} else {
// TODO: create a specific flow in table 100 to redirect selected traffic on table 200
log.warn("HP V3500 Driver - This flow rule is only supported in SOFTWARE");
return HP_SOFTWARE_TABLE;
}
}
use of org.onosproject.net.flow.instructions.L2ModificationInstruction in project onos by opennetworkinglab.
the class HPPipelineV3500 method checkUnSupportedFeatures.
// Return TRUE if ForwardingObjective fwd includes unsupported features
@Override
protected boolean checkUnSupportedFeatures(TrafficSelector selector, TrafficTreatment treatment) {
boolean unsupportedFeatures = false;
for (Criterion criterion : selector.criteria()) {
if (this.unsupportedCriteria.contains(criterion.type())) {
log.warn("HP V3500 Driver - unsupported criteria {}", criterion.type());
unsupportedFeatures = true;
}
}
for (Instruction instruction : treatment.allInstructions()) {
if (this.unsupportedInstructions.contains(instruction.type())) {
log.warn("HP V3500 Driver - unsupported instruction {}", instruction.type());
unsupportedFeatures = true;
}
if (instruction.type() == Instruction.Type.L2MODIFICATION) {
if (this.unsupportedL2mod.contains(((L2ModificationInstruction) instruction).subtype())) {
log.warn("HP V3500 Driver - unsupported L2MODIFICATION instruction {}", ((L2ModificationInstruction) instruction).subtype());
unsupportedFeatures = true;
}
}
if (instruction.type() == Instruction.Type.L3MODIFICATION) {
if (this.unsupportedL3mod.contains(((L3ModificationInstruction) instruction).subtype())) {
log.warn("HP V3500 Driver - unsupported L3MODIFICATION instruction {}", ((L3ModificationInstruction) instruction).subtype());
unsupportedFeatures = true;
}
}
}
return unsupportedFeatures;
}
use of org.onosproject.net.flow.instructions.L2ModificationInstruction in project trellis-control by opennetworkinglab.
the class MockFlowObjectiveService method forward.
@Override
public void forward(DeviceId deviceId, ForwardingObjective forwardingObjective) {
TrafficSelector selector = forwardingObjective.selector();
TrafficTreatment treatment = nextTable.get(forwardingObjective.nextId());
MacAddress macAddress = ((EthCriterion) selector.getCriterion(Criterion.Type.ETH_DST)).mac();
VlanId vlanId = ((VlanIdCriterion) selector.getCriterion(Criterion.Type.VLAN_VID)).vlanId();
boolean popVlan = treatment.allInstructions().stream().filter(instruction -> instruction.type().equals(Instruction.Type.L2MODIFICATION)).anyMatch(instruction -> ((L2ModificationInstruction) instruction).subtype().equals(L2ModificationInstruction.L2SubType.VLAN_POP));
PortNumber portNumber = treatment.allInstructions().stream().filter(instruction -> instruction.type().equals(Instruction.Type.OUTPUT)).map(instruction -> ((Instructions.OutputInstruction) instruction).port()).findFirst().orElse(null);
if (portNumber == null) {
throw new IllegalArgumentException();
}
Objective.Operation op = forwardingObjective.op();
MockBridgingTableKey btKey = new MockBridgingTableKey(deviceId, macAddress, vlanId);
MockBridgingTableValue btValue = new MockBridgingTableValue(popVlan, portNumber);
if (op.equals(Objective.Operation.ADD)) {
bridgingTable.put(btKey, btValue);
forwardingObjective.context().ifPresent(context -> context.onSuccess(forwardingObjective));
} else if (op.equals(Objective.Operation.REMOVE)) {
bridgingTable.remove(btKey, btValue);
forwardingObjective.context().ifPresent(context -> context.onSuccess(forwardingObjective));
} else {
forwardingObjective.context().ifPresent(context -> context.onError(forwardingObjective, ObjectiveError.UNKNOWN));
throw new IllegalArgumentException();
}
}
use of org.onosproject.net.flow.instructions.L2ModificationInstruction in project onos by opennetworkinglab.
the class CorsaPipelineV3 method processNextTreatment.
@Override
protected CorsaTrafficTreatment processNextTreatment(TrafficTreatment treatment) {
TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder();
treatment.immediate().stream().filter(i -> {
switch(i.type()) {
case L2MODIFICATION:
L2ModificationInstruction l2i = (L2ModificationInstruction) i;
return l2i instanceof L2ModificationInstruction.ModVlanIdInstruction || l2i instanceof L2ModificationInstruction.ModEtherInstruction;
case OUTPUT:
return true;
default:
return false;
}
}).forEach(i -> tb.add(i));
TrafficTreatment t = tb.build();
boolean isPresentModVlanId = false;
boolean isPresentModEthSrc = false;
boolean isPresentModEthDst = false;
boolean isPresentOutpuPort = false;
for (Instruction instruction : t.immediate()) {
switch(instruction.type()) {
case L2MODIFICATION:
L2ModificationInstruction l2i = (L2ModificationInstruction) instruction;
if (l2i instanceof L2ModificationInstruction.ModVlanIdInstruction) {
isPresentModVlanId = true;
}
if (l2i instanceof L2ModificationInstruction.ModEtherInstruction) {
L2ModificationInstruction.L2SubType subType = l2i.subtype();
if (subType.equals(L2ModificationInstruction.L2SubType.ETH_SRC)) {
isPresentModEthSrc = true;
} else if (subType.equals(L2ModificationInstruction.L2SubType.ETH_DST)) {
isPresentModEthDst = true;
}
}
break;
case OUTPUT:
isPresentOutpuPort = true;
break;
default:
}
}
CorsaTrafficTreatmentType type = CorsaTrafficTreatmentType.ACTIONS;
/**
* This represents the allowed group for CorsaPipelinev3
*/
if (isPresentModVlanId && isPresentModEthSrc && isPresentModEthDst && isPresentOutpuPort) {
type = CorsaTrafficTreatmentType.GROUP;
}
CorsaTrafficTreatment corsaTreatment = new CorsaTrafficTreatment(type, t);
return corsaTreatment;
}
Aggregations