use of org.onosproject.net.behaviour.NextGroup in project onos by opennetworkinglab.
the class CentecV350Pipeline method processSpecific.
private Collection<FlowRule> processSpecific(ForwardingObjective fwd) {
log.debug("Processing specific forwarding objective");
TrafficSelector selector = fwd.selector();
EthTypeCriterion ethType = (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE);
if (ethType == null || ethType.ethType().toShort() != Ethernet.TYPE_IPV4) {
fail(fwd, ObjectiveError.UNSUPPORTED);
return Collections.emptySet();
}
// Must have metadata as key.
TrafficSelector filteredSelector = DefaultTrafficSelector.builder().matchEthType(Ethernet.TYPE_IPV4).matchMetadata(DEFAULT_METADATA).matchIPDst(((IPCriterion) selector.getCriterion(Criterion.Type.IPV4_DST)).ip()).build();
TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder();
if (fwd.nextId() != null) {
NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId());
GroupKey key = appKryo.deserialize(next.data());
Group group = groupService.getGroup(deviceId, key);
if (group == null) {
log.warn("The group left!");
fail(fwd, ObjectiveError.GROUPMISSING);
return Collections.emptySet();
}
tb.group(group.id());
}
FlowRule.Builder ruleBuilder = DefaultFlowRule.builder().fromApp(fwd.appId()).withPriority(ROUTE_TABLE_PRIORITY).forDevice(deviceId).withSelector(filteredSelector).withTreatment(tb.build());
if (fwd.permanent()) {
ruleBuilder.makePermanent();
} else {
ruleBuilder.makeTemporary(fwd.timeout());
}
ruleBuilder.forTable(ROUTE_TABLE);
return Collections.singletonList(ruleBuilder.build());
}
use of org.onosproject.net.behaviour.NextGroup in project onos by opennetworkinglab.
the class DefaultSingleTablePipeline method next.
@Override
public void next(NextObjective nextObjective) {
switch(nextObjective.op()) {
case ADD:
// Check next objective
TrafficTreatment treatment = getTreatment(nextObjective);
if (treatment == null) {
// unsupported next objective
nextObjective.context().ifPresent(context -> context.onError(nextObjective, ObjectiveError.UNSUPPORTED));
return;
}
// We insert the value in the cache
pendingAddNext.put(nextObjective.id(), nextObjective);
// Then in the store, this will unblock the queued fwd obj
flowObjectiveStore.putNextGroup(nextObjective.id(), new SingleGroup(treatment));
break;
case REMOVE:
NextGroup next = flowObjectiveStore.removeNextGroup(nextObjective.id());
if (next == null) {
nextObjective.context().ifPresent(context -> context.onError(nextObjective, ObjectiveError.GROUPMISSING));
return;
}
break;
default:
log.warn("Unsupported operation {}", nextObjective.op());
}
nextObjective.context().ifPresent(context -> context.onSuccess(nextObjective));
}
use of org.onosproject.net.behaviour.NextGroup in project onos by opennetworkinglab.
the class SoftRouterPipeline method processVersatile.
/**
* SoftRouter has a single versatile table - the filter table.
* This table can be used to filter entries that reach the next table (FIB table).
* It can also be used to punt packets to the controller and/or bypass
* the FIB table to forward out of a port.
*
* @param fwd The forwarding objective of type versatile
* @return A collection of flow rules meant to be delivered to the flowrule
* subsystem. May return empty collection in case of failures.
*/
private Collection<FlowRule> processVersatile(ForwardingObjective fwd) {
log.debug("Received versatile fwd: to next:{}", fwd.nextId());
Collection<FlowRule> flowrules = new ArrayList<>();
if (fwd.nextId() == null && fwd.treatment() == null) {
log.error("Forwarding objective {} from {} must contain " + "nextId or Treatment", fwd.selector(), fwd.appId());
return Collections.emptySet();
}
int tableId = FILTER_TABLE;
// so that it only takes effect if the packet misses the FIB rules
if (fwd.treatment() != null && containsPunt(fwd.treatment()) && fwd.selector() != null && matchesIp(fwd.selector()) && !matchesControlTraffic(fwd.selector())) {
tableId = FIB_TABLE;
}
TrafficTreatment.Builder ttBuilder = DefaultTrafficTreatment.builder();
if (fwd.treatment() != null) {
fwd.treatment().immediate().forEach(ins -> ttBuilder.add(ins));
}
// convert nextId to flow actions
if (fwd.nextId() != null) {
// only acceptable value is output to port
NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId());
if (next == null) {
log.error("next-id {} does not exist in store", fwd.nextId());
return Collections.emptySet();
}
TrafficTreatment nt = appKryo.deserialize(next.data());
if (nt == null) {
log.error("Error in deserializing next-id {}", fwd.nextId());
return Collections.emptySet();
}
for (Instruction ins : nt.allInstructions()) {
if (ins instanceof OutputInstruction) {
ttBuilder.add(ins);
}
}
}
FlowRule rule = DefaultFlowRule.builder().withSelector(fwd.selector()).withTreatment(ttBuilder.build()).forTable(tableId).makePermanent().forDevice(deviceId).fromApp(fwd.appId()).withPriority(fwd.priority()).build();
flowrules.add(rule);
return flowrules;
}
use of org.onosproject.net.behaviour.NextGroup in project onos by opennetworkinglab.
the class SpringOpenTTPDell method processSpecific.
@Override
protected // ETH_DST match condition while pushing IP table flow rules
Collection<FlowRule> processSpecific(ForwardingObjective fwd) {
log.debug("Processing specific");
TrafficSelector selector = fwd.selector();
EthTypeCriterion ethType = (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE);
if ((ethType == null) || (ethType.ethType().toShort() != Ethernet.TYPE_IPV4) && (ethType.ethType().toShort() != Ethernet.MPLS_UNICAST)) {
log.debug("processSpecific: Unsupported " + "forwarding objective criteraia");
fail(fwd, ObjectiveError.UNSUPPORTED);
return Collections.emptySet();
}
TrafficSelector.Builder filteredSelectorBuilder = DefaultTrafficSelector.builder();
int forTableId = -1;
if (ethType.ethType().toShort() == Ethernet.TYPE_IPV4) {
if (deviceTMac == null) {
log.debug("processSpecific: ETH_DST filtering " + "objective is not set which is required " + "before sending a IPv4 forwarding objective");
// TODO: Map the error to more appropriate error code.
fail(fwd, ObjectiveError.DEVICEMISSING);
return Collections.emptySet();
}
filteredSelectorBuilder = filteredSelectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchEthDst(deviceTMac).matchIPDst(((IPCriterion) selector.getCriterion(Criterion.Type.IPV4_DST)).ip());
forTableId = ipv4UnicastTableId;
log.debug("processing IPv4 specific forwarding objective");
} else {
filteredSelectorBuilder = filteredSelectorBuilder.matchEthType(Ethernet.MPLS_UNICAST).matchMplsLabel(((MplsCriterion) selector.getCriterion(Criterion.Type.MPLS_LABEL)).label());
if (selector.getCriterion(Criterion.Type.MPLS_BOS) != null) {
filteredSelectorBuilder.matchMplsBos(((MplsBosCriterion) selector.getCriterion(Criterion.Type.MPLS_BOS)).mplsBos());
}
forTableId = mplsTableId;
log.debug("processing MPLS specific forwarding objective");
}
TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
if (fwd.treatment() != null) {
for (Instruction i : fwd.treatment().allInstructions()) {
treatmentBuilder.add(i);
}
}
if (fwd.nextId() != null) {
NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId());
if (next != null) {
SpringOpenGroup soGroup = appKryo.deserialize(next.data());
if (soGroup.dummy()) {
log.debug("Adding {} flow-actions for fwd. obj. {} -> next:{} " + "in dev: {}", soGroup.treatment().allInstructions().size(), fwd.id(), fwd.nextId(), deviceId);
for (Instruction ins : soGroup.treatment().allInstructions()) {
treatmentBuilder.add(ins);
}
} else {
Group group = groupService.getGroup(deviceId, soGroup.key());
if (group == null) {
log.warn("The group left!");
fail(fwd, ObjectiveError.GROUPMISSING);
return Collections.emptySet();
}
treatmentBuilder.group(group.id());
log.debug("Adding OUTGROUP action to group:{} for fwd. obj. {} " + "for next:{} in dev: {}", group.id(), fwd.id(), fwd.nextId(), deviceId);
}
} else {
log.warn("processSpecific: No associated next objective object");
fail(fwd, ObjectiveError.GROUPMISSING);
return Collections.emptySet();
}
}
TrafficSelector filteredSelector = filteredSelectorBuilder.build();
TrafficTreatment treatment = treatmentBuilder.transition(aclTableId).build();
FlowRule.Builder ruleBuilder = DefaultFlowRule.builder().fromApp(fwd.appId()).withPriority(fwd.priority()).forDevice(deviceId).withSelector(filteredSelector).withTreatment(treatment);
if (fwd.permanent()) {
ruleBuilder.makePermanent();
} else {
ruleBuilder.makeTemporary(fwd.timeout());
}
ruleBuilder.forTable(forTableId);
return Collections.singletonList(ruleBuilder.build());
}
use of org.onosproject.net.behaviour.NextGroup in project onos by opennetworkinglab.
the class Ofdpa2GroupHandler method removeBucket.
/**
* Removes top-level buckets from a group that represents the given next objective.
*
* @param chainsToRemove a list of group bucket chains to remove
* @param nextObjective the next objective that contains information for the
* buckets to be removed from the group
*/
protected void removeBucket(List<Deque<GroupKey>> chainsToRemove, NextObjective nextObjective) {
List<GroupBucket> bucketsToRemove = Lists.newArrayList();
// first group key is the one we want to modify
GroupKey modGroupKey = chainsToRemove.get(0).peekFirst();
Group modGroup = groupService.getGroup(deviceId, modGroupKey);
if (modGroup == null) {
log.warn("removeBucket(): Attempt to modify non-existent group {} for device {}", modGroupKey, deviceId);
return;
}
for (Deque<GroupKey> foundChain : chainsToRemove) {
// second group key is the one we wish to remove the reference to
if (foundChain.size() < 2) {
// additional check to make sure second group key exists in
// the chain.
log.warn("Can't find second group key from chain {}", foundChain);
continue;
}
GroupKey pointedGroupKey = foundChain.stream().collect(Collectors.toList()).get(1);
Group pointedGroup = groupService.getGroup(deviceId, pointedGroupKey);
if (pointedGroup == null) {
continue;
}
GroupBucket bucket;
if (nextObjective.type() == NextObjective.Type.HASHED) {
bucket = DefaultGroupBucket.createSelectGroupBucket(DefaultTrafficTreatment.builder().group(pointedGroup.id()).build());
} else {
bucket = DefaultGroupBucket.createAllGroupBucket(DefaultTrafficTreatment.builder().group(pointedGroup.id()).build());
}
bucketsToRemove.add(bucket);
}
GroupBuckets removeBuckets = new GroupBuckets(bucketsToRemove);
// for debug log
List<String> pointedGroupIds;
pointedGroupIds = bucketsToRemove.stream().map(GroupBucket::treatment).map(TrafficTreatment::allInstructions).flatMap(List::stream).filter(inst -> inst instanceof Instructions.GroupInstruction).map(inst -> (Instructions.GroupInstruction) inst).map(Instructions.GroupInstruction::groupId).map(GroupId::id).map(Integer::toHexString).map(id -> HEX_PREFIX + id).collect(Collectors.toList());
log.debug("Removing buckets from group id 0x{} pointing to group id(s) {} " + "for next id {} in device {}", Integer.toHexString(modGroup.id().id()), pointedGroupIds, nextObjective.id(), deviceId);
addPendingUpdateNextObjective(modGroupKey, nextObjective);
groupService.removeBucketsFromGroup(deviceId, modGroupKey, removeBuckets, modGroupKey, nextObjective.appId());
// potentially stale copy of allActiveKeys
synchronized (flowObjectiveStore) {
// get a fresh copy of what the store holds
NextGroup next = flowObjectiveStore.getNextGroup(nextObjective.id());
List<Deque<GroupKey>> allActiveKeys = appKryo.deserialize(next.data());
allActiveKeys = Lists.newArrayList(allActiveKeys);
// Note that since we got a new object, and ArrayDeque does not implement
// Object.equals(), we have to check the deque elems one by one
allActiveKeys.removeIf(active -> chainsToRemove.stream().anyMatch(remove -> Arrays.equals(remove.toArray(new GroupKey[0]), active.toArray(new GroupKey[0]))));
// top level group which still exists.
if (allActiveKeys.isEmpty()) {
ArrayDeque<GroupKey> top = new ArrayDeque<>();
top.add(modGroupKey);
allActiveKeys.add(top);
}
flowObjectiveStore.putNextGroup(nextObjective.id(), new OfdpaNextGroup(allActiveKeys, nextObjective));
}
}
Aggregations