use of org.onosproject.net.group.GroupBucket in project onos by opennetworkinglab.
the class PiReplicationGroupTranslatorImpl method translate.
/**
* Returns a PI PRE entry equivalent to the given group, for the given
* pipeconf and device.
* <p>
* The passed group is expected to have type {@link GroupDescription.Type#ALL}
* or {@link GroupDescription.Type#CLONE}.
*
* @param group group
* @param pipeconf pipeconf
* @param device device
* @return PI PRE entry
* @throws PiTranslationException if the group cannot be translated
*/
static PiPreEntry translate(Group group, PiPipeconf pipeconf, Device device) throws PiTranslationException {
checkNotNull(group);
final List<OutputInstruction> outInstructions = Lists.newArrayList();
int truncateMaxLen = PiCloneSessionEntry.DO_NOT_TRUNCATE;
for (GroupBucket bucket : group.buckets().buckets()) {
int numInstructionsInBucket = bucket.treatment().allInstructions().size();
List<OutputInstruction> outputs = getInstructions(bucket, Instruction.Type.OUTPUT, OutputInstruction.class);
List<TruncateInstruction> truncates = getInstructions(bucket, Instruction.Type.TRUNCATE, TruncateInstruction.class);
if (outputs.size() != 1) {
throw new PiTranslationException("support only groups with just one OUTPUT instruction per bucket");
}
outInstructions.add(outputs.get(0));
if (truncates.size() != 0) {
if (group.type() != GroupDescription.Type.CLONE) {
throw new PiTranslationException("only CLONE group support truncate instruction");
}
if (truncates.size() != 1) {
throw new PiTranslationException("support only groups with just one TRUNCATE instruction per bucket");
}
int truncateInstMaxLen = truncates.get(0).maxLen();
if (truncateMaxLen != PiCloneSessionEntry.DO_NOT_TRUNCATE && truncateMaxLen != truncateInstMaxLen) {
throw new PiTranslationException("all TRUNCATE instruction must be the same in a CLONE group");
}
truncateMaxLen = truncateInstMaxLen;
} else if (truncateMaxLen != PiCloneSessionEntry.DO_NOT_TRUNCATE) {
// No truncate instruction found in this bucket, but previous bucket contains one.
throw new PiTranslationException("all TRUNCATE instruction must be the same in a CLONE group");
}
if (numInstructionsInBucket != outputs.size() + truncates.size()) {
throw new PiTranslationException("bucket contains unsupported instruction(s)");
}
}
switch(group.type()) {
case ALL:
return PiMulticastGroupEntry.builder().withGroupId(group.id().id()).addReplicas(getReplicas(outInstructions, device)).build();
case CLONE:
return PiCloneSessionEntry.builder().withSessionId(group.id().id()).addReplicas(getReplicas(outInstructions, device)).withMaxPacketLengthBytes(truncateMaxLen).build();
default:
throw new PiTranslationException(format("group type %s not supported", group.type()));
}
}
use of org.onosproject.net.group.GroupBucket in project onos by opennetworkinglab.
the class GroupManagerTest method createSouthboundGroupEntry.
private static Group createSouthboundGroupEntry(GroupId gId, List<PortNumber> ports, long referenceCount, DeviceId deviceId) {
List<PortNumber> outPorts = new ArrayList<>();
outPorts.addAll(ports);
List<GroupBucket> buckets = new ArrayList<>();
for (PortNumber portNumber : outPorts) {
TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
tBuilder.setOutput(portNumber).setEthDst(MacAddress.valueOf("00:00:00:00:00:02")).setEthSrc(MacAddress.valueOf("00:00:00:00:00:01")).pushMpls().setMpls(MplsLabel.mplsLabel(106));
buckets.add(DefaultGroupBucket.createSelectGroupBucket(tBuilder.build()));
}
GroupBuckets groupBuckets = new GroupBuckets(buckets);
StoredGroupEntry group = new DefaultGroup(gId, deviceId, Group.Type.SELECT, groupBuckets);
group.setReferenceCount(referenceCount);
return group;
}
use of org.onosproject.net.group.GroupBucket in project onos by opennetworkinglab.
the class ForwardingObjectiveTranslator method createCloneGroup.
private DefaultGroupDescription createCloneGroup(ApplicationId appId, int cloneSessionId, PortNumber outPort) {
final GroupKey groupKey = new DefaultGroupKey(FabricPipeliner.KRYO.serialize(cloneSessionId));
final List<GroupBucket> bucketList = ImmutableList.of(createCloneGroupBucket(DefaultTrafficTreatment.builder().setOutput(outPort).build()));
final DefaultGroupDescription cloneGroup = new DefaultGroupDescription(deviceId, GroupDescription.Type.CLONE, new GroupBuckets(bucketList), groupKey, cloneSessionId, appId);
return cloneGroup;
}
use of org.onosproject.net.group.GroupBucket in project onos by opennetworkinglab.
the class ForwardingObjectiveTranslatorTest method testAclArp.
/**
* Test versatile flag of forwarding objective with ARP match.
*/
@Test
public void testAclArp() {
TrafficTreatment treatment = DefaultTrafficTreatment.builder().punt().build();
// ARP
TrafficSelector selector = DefaultTrafficSelector.builder().matchEthType(Ethernet.TYPE_ARP).build();
ForwardingObjective fwd = DefaultForwardingObjective.builder().withSelector(selector).withPriority(PRIORITY).fromApp(APP_ID).makePermanent().withFlag(ForwardingObjective.Flag.VERSATILE).withTreatment(treatment).add();
ObjectiveTranslation result = translator.translate(fwd);
List<FlowRule> flowRulesInstalled = (List<FlowRule>) result.flowRules();
List<GroupDescription> groupsInstalled = (List<GroupDescription>) result.groups();
assertEquals(1, flowRulesInstalled.size());
assertEquals(1, groupsInstalled.size());
FlowRule actualFlowRule = flowRulesInstalled.get(0);
PiAction piAction = PiAction.builder().withId(FabricConstants.FABRIC_INGRESS_ACL_SET_CLONE_SESSION_ID).withParameter(new PiActionParam(FabricConstants.CLONE_ID, ForwardingObjectiveTranslator.CLONE_TO_CPU_ID)).build();
FlowRule expectedFlowRule = DefaultFlowRule.builder().forDevice(DEVICE_ID).forTable(FabricConstants.FABRIC_INGRESS_ACL_ACL).withPriority(PRIORITY).makePermanent().withSelector(selector).withTreatment(DefaultTrafficTreatment.builder().piTableAction(piAction).build()).fromApp(APP_ID).build();
GroupDescription actualCloneGroup = groupsInstalled.get(0);
TrafficTreatment cloneGroupTreatment = DefaultTrafficTreatment.builder().setOutput(PortNumber.CONTROLLER).build();
List<GroupBucket> cloneBuckets = ImmutableList.of(DefaultGroupBucket.createCloneGroupBucket(cloneGroupTreatment));
GroupBuckets cloneGroupBuckets = new GroupBuckets(cloneBuckets);
GroupKey cloneGroupKey = new DefaultGroupKey(FabricPipeliner.KRYO.serialize(ForwardingObjectiveTranslator.CLONE_TO_CPU_ID));
GroupDescription expectedCloneGroup = new DefaultGroupDescription(DEVICE_ID, GroupDescription.Type.CLONE, cloneGroupBuckets, cloneGroupKey, ForwardingObjectiveTranslator.CLONE_TO_CPU_ID, APP_ID);
assertTrue(expectedFlowRule.exactMatch(actualFlowRule));
assertTrue(expectedCloneGroup.equals(actualCloneGroup));
}
use of org.onosproject.net.group.GroupBucket in project onos by opennetworkinglab.
the class FabricPipeliner method handleVerify.
private ObjectiveError handleVerify(NextObjective nextObjective) {
Map<GroupBucket, FlowRule> bucketsToFlows = getBucketToFlowMapping(nextObjective);
if (bucketsToFlows.isEmpty() && !nextObjective.nextTreatments().isEmpty()) {
log.warn("VERIFY failed due to translation error, bucketsToFlows is empty");
return ObjectiveError.BADPARAMS;
}
if (log.isTraceEnabled()) {
log.trace("Mapping bucketsToFlows {} has been generated ", bucketsToFlows);
}
GroupKey groupKey = nextTranslator.getGroupKey(nextObjective);
if (groupKey == null) {
log.warn("VERIFY failed due to translation error, unable to determine group key");
return ObjectiveError.BADPARAMS;
}
Group groupFromStore = groupService.getGroup(deviceId, groupKey);
if (groupFromStore == null) {
log.warn("VERIFY failed due to missing group in the store");
return ObjectiveError.GROUPMISSING;
}
// Looking for duplicate buckets - remove them by using a set and comparing size after/before
Set<GroupBucket> bucketsFromStore = Sets.newHashSet(groupFromStore.buckets().buckets());
if (groupFromStore.buckets().buckets().size() > bucketsFromStore.size()) {
log.warn("Duplicated buckets detected in device:{}, nextId:{}, before-size" + ":{} after-size:{} .. correcting", deviceId, nextObjective.id(), groupFromStore.buckets().buckets().size(), bucketsFromStore.size());
final GroupBuckets bucketToSet = new GroupBuckets(Lists.newArrayList(bucketsFromStore));
groupService.setBucketsForGroup(deviceId, groupKey, bucketToSet, groupKey, nextObjective.appId());
// Forge temporary the group to avoid race condition with the store
groupFromStore = new DefaultGroup(groupFromStore.id(), deviceId, groupFromStore.type(), bucketToSet);
}
// Looking for buckets missing in the group but defined in the next
Map<GroupBucket, FlowRule> toAdd = Maps.newHashMap();
for (Map.Entry<GroupBucket, FlowRule> entry : bucketsToFlows.entrySet()) {
if (!groupFromStore.buckets().buckets().contains(entry.getKey())) {
toAdd.put(entry.getKey(), entry.getValue());
}
}
// Looking for buckets missing in the next but defined in the group
// FIXME SDFAB-250 we cannot remove associated egress flows
List<GroupBucket> toRemove = Lists.newArrayList();
groupFromStore.buckets().buckets().forEach(bucket -> {
if (!bucketsToFlows.containsKey(bucket)) {
toRemove.add(bucket);
}
});
if (!toAdd.isEmpty() || !toRemove.isEmpty()) {
log.warn("Mismatch detected in device:{}, nextId:{}, groupFromTranslation-size:{} " + "groupFromStore-size:{} toAdd-size:{} toRemove-size: {} .. correcting", deviceId, nextObjective.id(), bucketsToFlows.size(), groupFromStore.buckets().buckets().size(), toAdd.size(), toRemove.size());
}
if (!toAdd.isEmpty()) {
if (log.isTraceEnabled()) {
log.trace("Adding missing buckets {} and flows {}", toAdd.keySet(), toAdd.values());
}
final FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
final FlowRule dummyFlow = getDummyFlow(nextObjective);
toAdd.values().stream().filter(flowRule -> !flowRule.equals(dummyFlow)).forEach(ops::add);
final GroupBuckets bucketsToAdd = new GroupBuckets(Lists.newArrayList(toAdd.keySet()));
groupService.addBucketsToGroup(deviceId, groupKey, bucketsToAdd, groupKey, nextObjective.appId());
flowRuleService.apply(ops.build());
}
if (!toRemove.isEmpty()) {
if (log.isTraceEnabled()) {
log.trace("Removing stale buckets {}", toRemove);
}
final GroupBuckets bucketsToRemove = new GroupBuckets(toRemove);
groupService.removeBucketsFromGroup(deviceId, groupKey, bucketsToRemove, groupKey, nextObjective.appId());
}
return null;
}
Aggregations