use of org.onosproject.net.group.GroupKey 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.group.GroupKey in project onos by opennetworkinglab.
the class Ofdpa2GroupHandler method createL2FloodGroup.
private void createL2FloodGroup(NextObjective nextObj, VlanId vlanId, List<GroupInfo> groupInfos) {
// assemble info for l2 flood group. Since there can be only one flood
// group for a vlan, its index is always the same - 0
Integer l2FloodGroupId = L2_FLOOD_TYPE | (vlanId.toShort() << 16);
final GroupKey l2FloodGroupKey = l2FloodGroupKey(vlanId, deviceId);
// collection of group buckets pointing to all the l2 interface groups
List<GroupBucket> l2floodBuckets = generateNextGroupBuckets(groupInfos, ALL);
// create the l2flood group-description to wait for all the
// l2interface groups to be processed
GroupDescription l2floodGroupDescription = new DefaultGroupDescription(deviceId, ALL, new GroupBuckets(l2floodBuckets), l2FloodGroupKey, l2FloodGroupId, nextObj.appId());
log.debug("Trying L2-Flood: device:{} gid:{} gkey:{} nextid:{}", deviceId, Integer.toHexString(l2FloodGroupId), l2FloodGroupKey, nextObj.id());
// Put all dependency information into allGroupKeys
List<Deque<GroupKey>> allGroupKeys = Lists.newArrayList();
groupInfos.forEach(groupInfo -> {
Deque<GroupKey> groupKeyChain = new ArrayDeque<>();
// In this case we should have L2 interface group only
groupKeyChain.addFirst(groupInfo.nextGroupDesc().appCookie());
groupKeyChain.addFirst(l2FloodGroupKey);
allGroupKeys.add(groupKeyChain);
});
// Point the next objective to this group
OfdpaNextGroup ofdpaGrp = new OfdpaNextGroup(allGroupKeys, nextObj);
updatePendingNextObjective(l2FloodGroupKey, ofdpaGrp);
GroupChainElem gce = new GroupChainElem(l2floodGroupDescription, groupInfos.size(), false, deviceId);
groupInfos.forEach(groupInfo -> {
// Point this group to the next group
updatePendingGroups(groupInfo.nextGroupDesc().appCookie(), gce);
// Start installing the inner-most group
groupService.addGroup(groupInfo.innerMostGroupDesc());
});
}
use of org.onosproject.net.group.GroupKey in project onos by opennetworkinglab.
the class SpringOpenTTP method removeGroup.
private void removeGroup(NextObjective nextObjective) {
log.debug("removeGroup in {}: for next objective id {}", deviceId, nextObjective.id());
final GroupKey key = new DefaultGroupKey(appKryo.serialize(nextObjective.id()));
groupService.removeGroup(deviceId, key, appId);
}
use of org.onosproject.net.group.GroupKey in project onos by opennetworkinglab.
the class SpringOpenTTP method processVersatile.
private Collection<FlowRule> processVersatile(ForwardingObjective fwd) {
log.debug("Processing versatile forwarding objective in dev:{}", deviceId);
TrafficSelector selector = fwd.selector();
EthTypeCriterion ethType = (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE);
if (ethType == null) {
log.error("Versatile forwarding objective must include ethType");
fail(fwd, ObjectiveError.UNKNOWN);
return Collections.emptySet();
}
if (fwd.treatment() == null && fwd.nextId() == null) {
log.error("VERSATILE forwarding objective needs next objective ID " + "or treatment.");
return Collections.emptySet();
}
// emulation of ACL table (for versatile fwd objective) requires
// overriding any previous instructions
TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
treatmentBuilder.wipeDeferred();
if (fwd.nextId() != null) {
NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId());
if (next != null) {
SpringOpenGroup soGroup = appKryo.deserialize(next.data());
if (soGroup.dummy) {
// need to convert to flow-actions
for (Instruction ins : soGroup.treatment.allInstructions()) {
treatmentBuilder.add(ins);
}
} else {
GroupKey key = soGroup.key;
Group group = groupService.getGroup(deviceId, key);
if (group == null) {
log.warn("The group left!");
fail(fwd, ObjectiveError.GROUPMISSING);
return Collections.emptySet();
}
treatmentBuilder.deferred().group(group.id());
log.debug("Adding OUTGROUP action");
}
}
}
if (fwd.treatment() != null) {
if (fwd.treatment().allInstructions().size() == 1 && fwd.treatment().allInstructions().get(0).type() == Instruction.Type.OUTPUT) {
OutputInstruction o = (OutputInstruction) fwd.treatment().allInstructions().get(0);
if (o.port() == PortNumber.CONTROLLER) {
treatmentBuilder.popVlan();
treatmentBuilder.punt();
} else {
treatmentBuilder.add(o);
}
} else {
for (Instruction ins : fwd.treatment().allInstructions()) {
treatmentBuilder.add(ins);
}
}
}
FlowRule.Builder ruleBuilder = DefaultFlowRule.builder().fromApp(fwd.appId()).withPriority(fwd.priority()).forDevice(deviceId).withSelector(fwd.selector()).withTreatment(treatmentBuilder.build());
if (fwd.permanent()) {
ruleBuilder.makePermanent();
} else {
ruleBuilder.makeTemporary(fwd.timeout());
}
ruleBuilder.forTable(aclTableId);
return Collections.singletonList(ruleBuilder.build());
}
use of org.onosproject.net.group.GroupKey in project onos by opennetworkinglab.
the class SpringOpenTTP method addGroup.
private void addGroup(NextObjective nextObjective) {
log.debug("addGroup with type{} for nextObjective id {}", nextObjective.type(), nextObjective.id());
List<GroupBucket> buckets;
switch(nextObjective.type()) {
case SIMPLE:
Collection<TrafficTreatment> treatments = nextObjective.next();
if (treatments.size() == 1) {
// Spring Open TTP converts simple nextObjective to flow-actions
// in a dummy group
TrafficTreatment treatment = nextObjective.next().iterator().next();
log.debug("Converting SIMPLE group for next objective id {} " + "to {} flow-actions in device:{}", nextObjective.id(), treatment.allInstructions().size(), deviceId);
flowObjectiveStore.putNextGroup(nextObjective.id(), new SpringOpenGroup(null, treatment));
}
break;
case HASHED:
// we convert MPLS ECMP groups to flow-actions for a single
// bucket(output port).
boolean mplsEcmp = false;
if (nextObjective.meta() != null) {
for (Criterion c : nextObjective.meta().criteria()) {
if (c.type() == Type.MPLS_LABEL) {
mplsEcmp = true;
}
}
}
if (mplsEcmp) {
// covert to flow-actions in a dummy group by choosing the first bucket
log.debug("Converting HASHED group for next objective id {} " + "to flow-actions in device:{}", nextObjective.id(), deviceId);
TrafficTreatment treatment = nextObjective.next().iterator().next();
flowObjectiveStore.putNextGroup(nextObjective.id(), new SpringOpenGroup(null, treatment));
} else {
// process as ECMP group
buckets = nextObjective.next().stream().map(DefaultGroupBucket::createSelectGroupBucket).collect(Collectors.toList());
if (!buckets.isEmpty()) {
final GroupKey key = new DefaultGroupKey(appKryo.serialize(nextObjective.id()));
GroupDescription groupDescription = new DefaultGroupDescription(deviceId, GroupDescription.Type.SELECT, new GroupBuckets(buckets), key, null, nextObjective.appId());
log.debug("Creating HASHED group for next objective id {}" + " in dev:{}", nextObjective.id(), deviceId);
pendingGroups.put(key, nextObjective);
groupService.addGroup(groupDescription);
verifyPendingGroupLater();
}
}
break;
case BROADCAST:
buckets = nextObjective.next().stream().map(DefaultGroupBucket::createAllGroupBucket).collect(Collectors.toList());
if (!buckets.isEmpty()) {
final GroupKey key = new DefaultGroupKey(appKryo.serialize(nextObjective.id()));
GroupDescription groupDescription = new DefaultGroupDescription(deviceId, GroupDescription.Type.ALL, new GroupBuckets(buckets), key, null, nextObjective.appId());
log.debug("Creating BROADCAST group for next objective id {} " + "in device {}", nextObjective.id(), deviceId);
pendingGroups.put(key, nextObjective);
groupService.addGroup(groupDescription);
verifyPendingGroupLater();
}
break;
case FAILOVER:
log.debug("FAILOVER next objectives not supported");
fail(nextObjective, ObjectiveError.UNSUPPORTED);
log.warn("Unsupported next objective type {}", nextObjective.type());
break;
default:
fail(nextObjective, ObjectiveError.UNKNOWN);
log.warn("Unknown next objective type {}", nextObjective.type());
}
}
Aggregations