use of org.onosproject.net.group.GroupBucket in project onos by opennetworkinglab.
the class Ofdpa2GroupHandler method prepareL3UnicastGroup.
private GroupInfo prepareL3UnicastGroup(NextObjective nextObj, NextGroup next) {
ImmutableList.Builder<GroupInfo> groupInfoBuilder = ImmutableList.builder();
TrafficTreatment treatment = nextObj.next().iterator().next();
VlanId assignedVlan = readVlanFromSelector(nextObj.meta());
if (assignedVlan == null) {
log.warn("VLAN ID required by next obj is missing. Abort.");
return null;
}
List<GroupInfo> l2GroupInfos = prepareL2InterfaceGroup(nextObj, assignedVlan);
GroupDescription l2InterfaceGroupDesc = l2GroupInfos.get(0).innerMostGroupDesc();
GroupKey l2groupkey = l2InterfaceGroupDesc.appCookie();
TrafficTreatment.Builder outerTtb = DefaultTrafficTreatment.builder();
VlanId vlanid = null;
MacAddress srcMac;
MacAddress dstMac;
for (Instruction ins : treatment.allInstructions()) {
if (ins.type() == Instruction.Type.L2MODIFICATION) {
L2ModificationInstruction l2ins = (L2ModificationInstruction) ins;
switch(l2ins.subtype()) {
case ETH_DST:
dstMac = ((L2ModificationInstruction.ModEtherInstruction) l2ins).mac();
outerTtb.setEthDst(dstMac);
break;
case ETH_SRC:
srcMac = ((L2ModificationInstruction.ModEtherInstruction) l2ins).mac();
outerTtb.setEthSrc(srcMac);
break;
case VLAN_ID:
vlanid = ((L2ModificationInstruction.ModVlanIdInstruction) l2ins).vlanId();
outerTtb.setVlanId(vlanid);
break;
default:
break;
}
} else {
log.debug("Driver does not handle this type of TrafficTreatment" + " instruction in l2l3chain: {} - {}", ins.type(), ins);
}
}
GroupId l2groupId = new GroupId(l2InterfaceGroupDesc.givenGroupId());
outerTtb.group(l2groupId);
// we need the top level group's key to point the flow to it
List<Deque<GroupKey>> gkeys = appKryo.deserialize(next.data());
GroupKey l3groupkey = gkeys.get(0).peekFirst();
GroupId grpId = groupService.getGroup(deviceId, l3groupkey).id();
int l3groupId = grpId.id();
// create the l3unicast group description to wait for the
// l2 interface group to be processed
GroupBucket l3UnicastGroupBucket = DefaultGroupBucket.createIndirectGroupBucket(outerTtb.build());
GroupDescription l3UnicastGroupDescription = new DefaultGroupDescription(deviceId, GroupDescription.Type.INDIRECT, new GroupBuckets(Collections.singletonList(l3UnicastGroupBucket)), l3groupkey, l3groupId, nextObj.appId());
// store l2groupkey with the groupChainElem for the outer-group that depends on it
GroupChainElem gce = new GroupChainElem(l3UnicastGroupDescription, 1, false, deviceId);
updatePendingGroups(l2groupkey, gce);
log.debug("Trying L3-Interface: device:{} gid:{} gkey:{} nextid:{}", deviceId, Integer.toHexString(l3groupId), l3groupkey, nextObj.id());
groupInfoBuilder.add(new GroupInfo(l2InterfaceGroupDesc, l3UnicastGroupDescription));
return groupInfoBuilder.build().iterator().next();
}
use of org.onosproject.net.group.GroupBucket in project onos by opennetworkinglab.
the class Ofdpa2GroupHandler method createEcmpHashBucketChains.
/**
* Creates group chains for all buckets in a hashed group, and stores the
* GroupInfos and GroupKeys for all the groups in the lists passed in, which
* should be empty.
* <p>
* Does not create the top level ECMP group. Does not actually send the
* groups to the groupService.
*
* @param nextObj the Next Objective with buckets that need to be converted
* to group chains
* @param allGroupKeys a list to store groupKey for each bucket-group-chain
* @param unsentGroups a list to store GroupInfo for each bucket-group-chain
*/
protected void createEcmpHashBucketChains(NextObjective nextObj, List<Deque<GroupKey>> allGroupKeys, List<GroupInfo> unsentGroups) {
// break up hashed next objective to multiple groups
Collection<TrafficTreatment> buckets = nextObj.next();
for (TrafficTreatment bucket : buckets) {
// figure out how many labels are pushed in each bucket
int labelsPushed = 0;
MplsLabel innermostLabel = null;
for (Instruction ins : bucket.allInstructions()) {
if (ins.type() == Instruction.Type.L2MODIFICATION) {
L2ModificationInstruction l2ins = (L2ModificationInstruction) ins;
if (l2ins.subtype() == L2ModificationInstruction.L2SubType.MPLS_PUSH) {
labelsPushed++;
}
if (l2ins.subtype() == L2ModificationInstruction.L2SubType.MPLS_LABEL) {
if (innermostLabel == null) {
innermostLabel = ((L2ModificationInstruction.ModMplsLabelInstruction) l2ins).label();
}
}
}
}
Deque<GroupKey> gKeyChain = new ArrayDeque<>();
// here we only deal with 0 and 1 label push
if (labelsPushed == 0) {
GroupInfo noLabelGroupInfo;
TrafficSelector metaSelector = nextObj.meta();
if (metaSelector != null) {
if (isNotMplsBos(metaSelector)) {
noLabelGroupInfo = createL2L3Chain(bucket, nextObj.id(), nextObj.appId(), true, nextObj.meta());
} else {
noLabelGroupInfo = createL2L3Chain(bucket, nextObj.id(), nextObj.appId(), false, nextObj.meta());
}
} else {
noLabelGroupInfo = createL2L3Chain(bucket, nextObj.id(), nextObj.appId(), false, nextObj.meta());
}
if (noLabelGroupInfo == null) {
log.error("Could not process nextObj={} in dev:{}", nextObj.id(), deviceId);
return;
}
gKeyChain.addFirst(noLabelGroupInfo.innerMostGroupDesc().appCookie());
gKeyChain.addFirst(noLabelGroupInfo.nextGroupDesc().appCookie());
// we can't send the inner group description yet, as we have to
// create the dependent ECMP group first. So we store..
unsentGroups.add(noLabelGroupInfo);
} else if (labelsPushed == 1) {
GroupInfo onelabelGroupInfo = createL2L3Chain(bucket, nextObj.id(), nextObj.appId(), true, nextObj.meta());
if (onelabelGroupInfo == null) {
log.error("Could not process nextObj={} in dev:{}", nextObj.id(), deviceId);
return;
}
// we need to add another group to this chain - the L3VPN group
TrafficTreatment.Builder l3vpnTtb = DefaultTrafficTreatment.builder();
if (requireVlanPopBeforeMplsPush()) {
l3vpnTtb.popVlan();
}
l3vpnTtb.pushMpls().setMpls(innermostLabel).group(new GroupId(onelabelGroupInfo.nextGroupDesc().givenGroupId()));
if (supportCopyTtl()) {
l3vpnTtb.copyTtlOut();
}
if (supportSetMplsBos()) {
l3vpnTtb.setMplsBos(true);
}
if (requireVlanPopBeforeMplsPush()) {
l3vpnTtb.pushVlan().setVlanId(VlanId.vlanId(VlanId.RESERVED));
}
GroupBucket l3vpnGrpBkt = DefaultGroupBucket.createIndirectGroupBucket(l3vpnTtb.build());
int l3vpnIndex = getNextAvailableIndex();
int l3vpnGroupId = MPLS_L3VPN_SUBTYPE | (SUBTYPE_MASK & l3vpnIndex);
GroupKey l3vpnGroupKey = new DefaultGroupKey(appKryo.serialize(l3vpnIndex));
GroupDescription l3vpnGroupDesc = new DefaultGroupDescription(deviceId, GroupDescription.Type.INDIRECT, new GroupBuckets(Collections.singletonList(l3vpnGrpBkt)), l3vpnGroupKey, l3vpnGroupId, nextObj.appId());
GroupChainElem l3vpnGce = new GroupChainElem(l3vpnGroupDesc, 1, false, deviceId);
updatePendingGroups(onelabelGroupInfo.nextGroupDesc().appCookie(), l3vpnGce);
gKeyChain.addFirst(onelabelGroupInfo.innerMostGroupDesc().appCookie());
gKeyChain.addFirst(onelabelGroupInfo.nextGroupDesc().appCookie());
gKeyChain.addFirst(l3vpnGroupKey);
// now we can replace the outerGrpDesc with the one we just created
onelabelGroupInfo.nextGroupDesc(l3vpnGroupDesc);
// we can't send the innermost group yet, as we have to create
// the dependent ECMP group first. So we store ...
unsentGroups.add(onelabelGroupInfo);
log.debug("Trying L3VPN: device:{} gid:{} group key:{} nextId:{}", deviceId, Integer.toHexString(l3vpnGroupId), l3vpnGroupKey, nextObj.id());
} else {
log.warn("Driver currently does not handle more than 1 MPLS " + "labels. Not processing nextObjective {}", nextObj.id());
return;
}
// all groups in this chain
allGroupKeys.add(gKeyChain);
}
}
use of org.onosproject.net.group.GroupBucket in project onos by opennetworkinglab.
the class Ofdpa2GroupHandler method addBucketToL2HashGroup.
private void addBucketToL2HashGroup(NextObjective nextObjective, List<Deque<GroupKey>> allActiveKeys) {
// storage for all group keys in the chain of groups created
List<Deque<GroupKey>> allGroupKeys = new ArrayList<>();
List<GroupInfo> unsentGroups = new ArrayList<>();
List<GroupBucket> newBuckets;
// Prepare the l2 unfiltered groups
createL2HashBuckets(nextObjective, allGroupKeys, unsentGroups);
// now we can create the buckets to add to the outermost L2 hash group
newBuckets = generateNextGroupBuckets(unsentGroups, SELECT);
// retrieve the original l2 load balance group
Group l2hashGroup = retrieveTopLevelGroup(allActiveKeys, deviceId, groupService, nextObjective.id());
if (l2hashGroup == null) {
fail(nextObjective, ObjectiveError.GROUPMISSING);
return;
}
GroupKey l2hashGroupKey = l2hashGroup.appCookie();
int l2hashGroupId = l2hashGroup.id().id();
GroupDescription l2hashGroupDesc = new DefaultGroupDescription(deviceId, SELECT, new GroupBuckets(newBuckets), l2hashGroupKey, l2hashGroupId, nextObjective.appId());
GroupChainElem l2hashGce = new GroupChainElem(l2hashGroupDesc, unsentGroups.size(), true, deviceId);
// update new bucket-chains
List<Deque<GroupKey>> addedKeys = new ArrayList<>();
for (Deque<GroupKey> newBucketChain : allGroupKeys) {
newBucketChain.addFirst(l2hashGroupKey);
addedKeys.add(newBucketChain);
}
updatePendingNextObjective(l2hashGroupKey, new OfdpaNextGroup(addedKeys, nextObjective));
log.debug("Adding to L2HASH: device:{} gid:{} group key:{} nextId:{}", deviceId, Integer.toHexString(l2hashGroupId), l2hashGroupKey, nextObjective.id());
unsentGroups.forEach(groupInfo -> {
// send the innermost group
log.debug("Sending innermost group {} in group chain on device {} ", Integer.toHexString(groupInfo.innerMostGroupDesc().givenGroupId()), deviceId);
updatePendingGroups(groupInfo.nextGroupDesc().appCookie(), l2hashGce);
groupService.addGroup(groupInfo.innerMostGroupDesc());
});
}
use of org.onosproject.net.group.GroupBucket in project onos by opennetworkinglab.
the class Ofdpa2GroupHandler method prepareL2InterfaceGroup.
private List<GroupInfo> prepareL2InterfaceGroup(NextObjective nextObj, VlanId assignedVlan) {
ImmutableList.Builder<GroupInfo> groupInfoBuilder = ImmutableList.builder();
// break up broadcast next objective to multiple groups
Collection<TrafficTreatment> buckets = nextObj.nextTreatments().stream().filter(nt -> nt.type() == NextTreatment.Type.TREATMENT).map(nt -> ((DefaultNextTreatment) nt).treatment()).collect(Collectors.toSet());
// Each treatment is converted to an L2 interface group
for (TrafficTreatment treatment : buckets) {
TrafficTreatment.Builder newTreatment = DefaultTrafficTreatment.builder();
PortNumber portNum = null;
VlanId egressVlan = null;
// ensure that the only allowed treatments are pop-vlan and output
for (Instruction ins : treatment.allInstructions()) {
if (ins.type() == Instruction.Type.L2MODIFICATION) {
L2ModificationInstruction l2ins = (L2ModificationInstruction) ins;
switch(l2ins.subtype()) {
case VLAN_POP:
newTreatment.add(l2ins);
break;
case VLAN_ID:
egressVlan = ((L2ModificationInstruction.ModVlanIdInstruction) l2ins).vlanId();
break;
default:
log.debug("action {} not permitted for broadcast nextObj", l2ins.subtype());
break;
}
} else if (ins.type() == Instruction.Type.OUTPUT) {
portNum = ((Instructions.OutputInstruction) ins).port();
newTreatment.add(ins);
} else {
log.debug("TrafficTreatment of type {} not permitted in " + " broadcast nextObjective", ins.type());
}
}
if (portNum == null) {
log.debug("Can't find output port for the bucket {}.", treatment);
continue;
}
// assemble info for l2 interface group
VlanId l2InterfaceGroupVlan = (egressVlan != null && !assignedVlan.equals(egressVlan)) ? egressVlan : assignedVlan;
int l2gk = l2InterfaceGroupKey(deviceId, l2InterfaceGroupVlan, portNum.toLong());
final GroupKey l2InterfaceGroupKey = new DefaultGroupKey(appKryo.serialize(l2gk));
int l2InterfaceGroupId = L2_INTERFACE_TYPE | ((l2InterfaceGroupVlan.toShort() & THREE_NIBBLE_MASK) << PORT_LEN) | ((int) portNum.toLong() & FOUR_NIBBLE_MASK);
GroupBucket l2InterfaceGroupBucket = DefaultGroupBucket.createIndirectGroupBucket(newTreatment.build());
GroupDescription l2InterfaceGroupDescription = new DefaultGroupDescription(deviceId, GroupDescription.Type.INDIRECT, new GroupBuckets(Collections.singletonList(l2InterfaceGroupBucket)), l2InterfaceGroupKey, l2InterfaceGroupId, nextObj.appId());
log.debug("Trying L2-Interface: device:{} gid:{} gkey:{} nextid:{}", deviceId, Integer.toHexString(l2InterfaceGroupId), l2InterfaceGroupKey, nextObj.id());
groupInfoBuilder.add(new GroupInfo(l2InterfaceGroupDescription, l2InterfaceGroupDescription));
}
return groupInfoBuilder.build();
}
use of org.onosproject.net.group.GroupBucket in project onos by opennetworkinglab.
the class Ofdpa2GroupHandler method addBucketToL2FloodGroup.
private void addBucketToL2FloodGroup(NextObjective nextObj, List<Deque<GroupKey>> allActiveKeys, List<GroupInfo> groupInfos, VlanId assignedVlan) {
Group l2FloodGroup = retrieveTopLevelGroup(allActiveKeys, deviceId, groupService, nextObj.id());
if (l2FloodGroup == null) {
log.warn("Can't find L2 flood group while adding bucket to it. NextObj = {}", nextObj);
fail(nextObj, ObjectiveError.GROUPMISSING);
return;
}
GroupKey l2floodGroupKey = l2FloodGroup.appCookie();
int l2floodGroupId = l2FloodGroup.id().id();
List<GroupBucket> newBuckets = generateNextGroupBuckets(groupInfos, ALL);
GroupDescription l2FloodGroupDescription = new DefaultGroupDescription(deviceId, ALL, new GroupBuckets(newBuckets), l2floodGroupKey, l2floodGroupId, nextObj.appId());
GroupChainElem l2FloodGroupChainElement = new GroupChainElem(l2FloodGroupDescription, groupInfos.size(), true, deviceId);
// ensure assignedVlan applies to the chosen group
VlanId floodGroupVlan = extractVlanIdFromGroupId(l2floodGroupId);
if (!floodGroupVlan.equals(assignedVlan)) {
log.warn("VLAN ID {} does not match Flood group {} to which bucket is " + "being added, for next:{} in dev:{}. Abort.", assignedVlan, Integer.toHexString(l2floodGroupId), nextObj.id(), deviceId);
fail(nextObj, ObjectiveError.BADPARAMS);
return;
}
List<Deque<GroupKey>> addedKeys = new ArrayList<>();
groupInfos.forEach(groupInfo -> {
// update original NextGroup with new bucket-chain
Deque<GroupKey> newBucketChain = new ArrayDeque<>();
newBucketChain.addFirst(groupInfo.nextGroupDesc().appCookie());
newBucketChain.addFirst(l2floodGroupKey);
addedKeys.add(newBucketChain);
log.debug("Adding to L2FLOOD: device:{} gid:{} group key:{} nextId:{}", deviceId, Integer.toHexString(l2floodGroupId), l2floodGroupKey, nextObj.id());
// send the innermost group
log.debug("Sending innermost group {} in group chain on device {} ", Integer.toHexString(groupInfo.innerMostGroupDesc().givenGroupId()), deviceId);
updatePendingGroups(groupInfo.nextGroupDesc().appCookie(), l2FloodGroupChainElement);
DeviceId innerMostGroupDevice = groupInfo.innerMostGroupDesc().deviceId();
GroupKey innerMostGroupKey = groupInfo.innerMostGroupDesc().appCookie();
Group existsL2IGroup = groupService.getGroup(innerMostGroupDevice, innerMostGroupKey);
if (existsL2IGroup != null) {
// group already exist
processPendingAddGroupsOrNextObjs(innerMostGroupKey, true);
} else {
groupService.addGroup(groupInfo.innerMostGroupDesc());
}
});
updatePendingNextObjective(l2floodGroupKey, new OfdpaNextGroup(addedKeys, nextObj));
}
Aggregations