use of org.onosproject.net.behaviour.NextGroup in project onos by opennetworkinglab.
the class Ofdpa2Pipeline method next.
@Override
public void next(NextObjective nextObjective) {
NextGroup nextGroup = flowObjectiveStore.getNextGroup(nextObjective.id());
switch(nextObjective.op()) {
case ADD:
if (nextGroup != null) {
log.warn("Cannot add next {} that already exists in device {}", nextObjective.id(), deviceId);
return;
}
log.debug("Processing NextObjective id {} in dev {} - add group", nextObjective.id(), deviceId);
groupHandler.addGroup(nextObjective);
break;
case ADD_TO_EXISTING:
if (nextGroup != null) {
log.debug("Processing NextObjective id {} in dev {} - add bucket", nextObjective.id(), deviceId);
groupHandler.addBucketToGroup(nextObjective, nextGroup);
} else {
// it is possible that group-chain has not been fully created yet
log.debug("Waiting to add bucket to group for next-id:{} in dev:{}", nextObjective.id(), deviceId);
// by design multiple pending bucket is allowed for the group
groupHandler.pendingBuckets.compute(nextObjective.id(), (nextId, pendBkts) -> {
if (pendBkts == null) {
pendBkts = Sets.newHashSet();
}
pendBkts.add(nextObjective);
return pendBkts;
});
}
break;
case REMOVE:
if (nextGroup == null) {
log.warn("Cannot remove next {} that does not exist in device {}", nextObjective.id(), deviceId);
return;
}
log.debug("Processing NextObjective id {} in dev {} - remove group", nextObjective.id(), deviceId);
groupHandler.removeGroup(nextObjective, nextGroup);
break;
case REMOVE_FROM_EXISTING:
if (nextGroup == null) {
log.warn("Cannot remove from next {} that does not exist in device {}", nextObjective.id(), deviceId);
return;
}
log.debug("Processing NextObjective id {} in dev {} - remove bucket", nextObjective.id(), deviceId);
groupHandler.removeBucketFromGroup(nextObjective, nextGroup);
break;
case MODIFY:
if (nextGroup == null) {
log.warn("Cannot modify next {} that does not exist in device {}", nextObjective.id(), deviceId);
return;
}
log.debug("Processing NextObjective id {} in dev {} group {} - modify bucket", nextObjective.id(), deviceId, nextGroup);
groupHandler.modifyBucketFromGroup(nextObjective, nextGroup);
break;
case VERIFY:
if (nextGroup == null) {
log.warn("Cannot verify next {} that does not exist in device {}", nextObjective.id(), deviceId);
return;
}
log.debug("Processing NextObjective id {} in dev {} - verify", nextObjective.id(), deviceId);
groupHandler.verifyGroup(nextObjective, nextGroup);
break;
default:
log.warn("Unsupported operation {}", nextObjective.op());
}
}
use of org.onosproject.net.behaviour.NextGroup in project onos by opennetworkinglab.
the class Ofdpa2Pipeline method processEthTypeSpecificInternal.
/**
* Internal implementation of processEthTypeSpecific.
* <p>
* Wildcarded IPv4_DST is not supported in OFDPA i12. Therefore, we break
* the rule into 0.0.0.0/1 and 128.0.0.0/1.
* The allowDefaultRoute must be set to false for OFDPA i12.
* </p>
*
* @param fwd the forwarding objective
* @param allowDefaultRoute allow wildcarded IPv4_DST or not
* @param mplsNextTable next MPLS table
* @return A collection of flow rules, or an empty set
*/
protected Collection<FlowRule> processEthTypeSpecificInternal(ForwardingObjective fwd, boolean allowDefaultRoute, int mplsNextTable) {
TrafficSelector selector = fwd.selector();
EthTypeCriterion ethType = (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE);
boolean emptyGroup = false;
int forTableId;
TrafficSelector.Builder filteredSelector = DefaultTrafficSelector.builder();
TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder();
TrafficSelector.Builder complementarySelector = DefaultTrafficSelector.builder();
if (ethType.ethType().toShort() == Ethernet.TYPE_IPV4) {
if (buildIpv4Selector(filteredSelector, complementarySelector, fwd, allowDefaultRoute) < 0) {
return Collections.emptyList();
}
// We need to set properly the next table
IpPrefix ipv4Dst = ((IPCriterion) selector.getCriterion(Criterion.Type.IPV4_DST)).ip();
if (ipv4Dst.isMulticast()) {
forTableId = MULTICAST_ROUTING_TABLE;
} else {
forTableId = UNICAST_ROUTING_TABLE;
}
// TODO decrementing IP ttl is done automatically for routing, this
// action is ignored or rejected in ofdpa as it is not fully implemented
// if (fwd.treatment() != null) {
// for (Instruction instr : fwd.treatment().allInstructions()) {
// if (instr instanceof L3ModificationInstruction &&
// ((L3ModificationInstruction) instr).subtype() == L3SubType.DEC_TTL) {
// tb.deferred().add(instr);
// }
// }
// }
} else if (ethType.ethType().toShort() == Ethernet.TYPE_IPV6) {
if (buildIpv6Selector(filteredSelector, fwd) < 0) {
return Collections.emptyList();
}
// We need to set the proper next table
IpPrefix ipv6Dst = ((IPCriterion) selector.getCriterion(Criterion.Type.IPV6_DST)).ip();
if (ipv6Dst.isMulticast()) {
forTableId = MULTICAST_ROUTING_TABLE;
} else {
forTableId = UNICAST_ROUTING_TABLE;
}
// TODO decrementing IP ttl is done automatically for routing, this
// action is ignored or rejected in ofdpa as it is not fully implemented
// if (fwd.treatment() != null) {
// for (Instruction instr : fwd.treatment().allInstructions()) {
// if (instr instanceof L3ModificationInstruction &&
// ((L3ModificationInstruction) instr).subtype() == L3SubType.DEC_TTL) {
// tb.deferred().add(instr);
// }
// }
// }
} else {
filteredSelector.matchEthType(Ethernet.MPLS_UNICAST).matchMplsLabel(((MplsCriterion) selector.getCriterion(Criterion.Type.MPLS_LABEL)).label());
MplsBosCriterion bos = (MplsBosCriterion) selector.getCriterion(MPLS_BOS);
if (bos != null && requireMplsBosMatch()) {
filteredSelector.matchMplsBos(bos.mplsBos());
}
forTableId = MPLS_TABLE_1;
log.debug("processing MPLS specific forwarding objective {} -> next:{}" + " in dev {}", fwd.id(), fwd.nextId(), deviceId);
if (fwd.treatment() != null) {
for (Instruction instr : fwd.treatment().allInstructions()) {
if (instr instanceof L2ModificationInstruction && ((L2ModificationInstruction) instr).subtype() == L2SubType.MPLS_POP) {
// setting the MPLS_TYPE so pop can happen down the pipeline
if (requireMplsPop()) {
if (mplsNextTable == MPLS_TYPE_TABLE && isNotMplsBos(selector)) {
tb.immediate().popMpls();
}
} else {
// Skip mpls pop action for mpls_unicast label
if (instr instanceof ModMplsHeaderInstruction && !((ModMplsHeaderInstruction) instr).ethernetType().equals(EtherType.MPLS_UNICAST.ethType())) {
tb.immediate().add(instr);
}
}
}
if (requireMplsTtlModification()) {
if (instr instanceof L3ModificationInstruction && ((L3ModificationInstruction) instr).subtype() == L3SubType.DEC_TTL) {
// FIXME Should modify the app to send the correct DEC_MPLS_TTL instruction
tb.immediate().decMplsTtl();
}
if (instr instanceof L3ModificationInstruction && ((L3ModificationInstruction) instr).subtype() == L3SubType.TTL_IN) {
tb.immediate().add(instr);
}
}
}
}
}
if (fwd.nextId() != null) {
NextGroup next = getGroupForNextObjective(fwd.nextId());
if (next != null) {
List<Deque<GroupKey>> gkeys = appKryo.deserialize(next.data());
// we only need the top level group's key to point the flow to it
Group group = groupService.getGroup(deviceId, gkeys.get(0).peekFirst());
if (group == null) {
log.warn("Group with key:{} for next-id:{} not found in dev:{}", gkeys.get(0).peekFirst(), fwd.nextId(), deviceId);
fail(fwd, ObjectiveError.GROUPMISSING);
return Collections.emptySet();
}
if (isNotMplsBos(selector) && group.type().equals(SELECT)) {
log.warn("SR CONTINUE case cannot be handled as MPLS ECMP " + "is not implemented in OF-DPA yet. Aborting flow {} -> next:{} " + "in this device {}", fwd.id(), fwd.nextId(), deviceId);
fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED);
return Collections.emptySet();
}
tb.deferred().group(group.id());
// retrying flows may be necessary due to bug CORD-554
if (gkeys.size() == 1 && gkeys.get(0).size() == 1) {
if (shouldRetry()) {
log.warn("Found empty group 0x{} in dev:{} .. will retry fwd:{}", Integer.toHexString(group.id().id()), deviceId, fwd.id());
emptyGroup = true;
}
}
} else {
log.warn("Cannot find group for nextId:{} in dev:{}. Aborting fwd:{}", fwd.nextId(), deviceId, fwd.id());
fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED);
return Collections.emptySet();
}
}
if (forTableId == MPLS_TABLE_1) {
if (mplsNextTable == MPLS_L3_TYPE_TABLE) {
Ofdpa3SetMplsType setMplsType = new Ofdpa3SetMplsType(Ofdpa3MplsType.L3_PHP);
// set mpls type as apply_action
tb.immediate().extension(setMplsType, deviceId);
}
tb.transition(mplsNextTable);
} else {
tb.transition(ACL_TABLE);
}
if (fwd.treatment() != null && fwd.treatment().clearedDeferred()) {
if (supportsUnicastBlackHole()) {
tb.wipeDeferred();
} else {
log.warn("Clear Deferred is not supported Unicast Routing Table on device {}", deviceId);
return Collections.emptySet();
}
}
FlowRule.Builder ruleBuilder = DefaultFlowRule.builder().fromApp(fwd.appId()).withPriority(fwd.priority()).forDevice(deviceId).withSelector(filteredSelector.build()).withTreatment(tb.build()).forTable(forTableId);
if (fwd.permanent()) {
ruleBuilder.makePermanent();
} else {
ruleBuilder.makeTemporary(fwd.timeout());
}
Collection<FlowRule> flowRuleCollection = new ArrayList<>();
flowRuleCollection.add(ruleBuilder.build());
if (!allowDefaultRoute) {
flowRuleCollection.add(defaultRoute(fwd, complementarySelector, forTableId, tb));
log.debug("Default rule 0.0.0.0/0 is being installed two rules");
}
if (emptyGroup) {
retryExecutorService.schedule(new RetryFlows(fwd, flowRuleCollection), RETRY_MS, TimeUnit.MILLISECONDS);
}
return flowRuleCollection;
}
use of org.onosproject.net.behaviour.NextGroup in project onos by opennetworkinglab.
the class Ofdpa3Pipeline method processInitPwVersatile.
/**
* Helper method to process the pw forwarding objectives.
*
* @param forwardingObjective the fw objective to process
* @return a singleton list of flow rule
*/
private Collection<FlowRule> processInitPwVersatile(ForwardingObjective forwardingObjective) {
// We retrieve the matching criteria for mpls l2 port.
TunnelIdCriterion tunnelIdCriterion = (TunnelIdCriterion) forwardingObjective.selector().getCriterion(TUNNEL_ID);
PortCriterion portCriterion = (PortCriterion) forwardingObjective.selector().getCriterion(IN_PORT);
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
int mplsLogicalPort;
long tunnelId;
// Mpls tunnel ids according to the OFDPA manual have to be
// in the range [2^17-1, 2^16].
tunnelId = MPLS_TUNNEL_ID_BASE | tunnelIdCriterion.tunnelId();
if (tunnelId > MPLS_TUNNEL_ID_MAX) {
log.error("Pw Versatile Forwarding Objective must include tunnel id < {}", MPLS_TUNNEL_ID_MAX);
fail(forwardingObjective, ObjectiveError.BADPARAMS);
return Collections.emptySet();
}
// Port has not been null.
if (portCriterion == null) {
log.error("Pw Versatile Forwarding Objective must include port");
fail(forwardingObjective, ObjectiveError.BADPARAMS);
return Collections.emptySet();
}
// 0x0000XXXX is UNI interface.
if (portCriterion.port().toLong() > MPLS_UNI_PORT_MAX) {
log.error("Pw Versatile Forwarding Objective invalid logical port {}", portCriterion.port().toLong());
fail(forwardingObjective, ObjectiveError.BADPARAMS);
return Collections.emptySet();
}
mplsLogicalPort = ((int) portCriterion.port().toLong());
if (forwardingObjective.nextId() == null) {
log.error("Pw Versatile Forwarding Objective must contain nextId ", forwardingObjective.nextId());
fail(forwardingObjective, ObjectiveError.BADPARAMS);
return Collections.emptySet();
}
// We don't expect a treatment.
if (forwardingObjective.treatment() != null && !forwardingObjective.treatment().equals(DefaultTrafficTreatment.emptyTreatment())) {
log.error("Pw Versatile Forwarding Objective cannot contain a treatment ", forwardingObjective.nextId());
fail(forwardingObjective, ObjectiveError.BADPARAMS);
return Collections.emptySet();
}
// We retrieve the l2 vpn group and point the mpls
// l2 port to this.
NextGroup next = getGroupForNextObjective(forwardingObjective.nextId());
if (next == null) {
log.warn("next-id:{} not found in dev:{}", forwardingObjective.nextId(), deviceId);
fail(forwardingObjective, ObjectiveError.GROUPMISSING);
return Collections.emptySet();
}
List<Deque<GroupKey>> gkeys = appKryo.deserialize(next.data());
Group group = groupService.getGroup(deviceId, gkeys.get(0).peekFirst());
if (group == null) {
log.warn("Group with key:{} for next-id:{} not found in dev:{}", gkeys.get(0).peekFirst(), forwardingObjective.nextId(), deviceId);
fail(forwardingObjective, ObjectiveError.GROUPMISSING);
return Collections.emptySet();
}
// We prepare the flow rule for the mpls l2 port table.
selector.matchTunnelId(tunnelId);
selector.extension(new Ofdpa3MatchMplsL2Port(mplsLogicalPort), deviceId);
// This should not be necessary but without we receive an error
treatment.extension(new Ofdpa3SetQosIndex(0), deviceId);
treatment.transition(MPLS_L2_PORT_PCP_TRUST_FLOW_TABLE);
treatment.deferred().group(group.id());
FlowRule.Builder ruleBuilder = DefaultFlowRule.builder().fromApp(forwardingObjective.appId()).withPriority(MPLS_L2_PORT_PRIORITY).forDevice(deviceId).withSelector(selector.build()).withTreatment(treatment.build()).makePermanent().forTable(MPLS_L2_PORT_FLOW_TABLE);
return Collections.singletonList(ruleBuilder.build());
}
use of org.onosproject.net.behaviour.NextGroup in project onos by opennetworkinglab.
the class OvsOfdpaPipeline method processEthTypeSpecific.
/*
* Open vSwitch emulation allows MPLS ECMP.
*
* (non-Javadoc)
* @see org.onosproject.driver.pipeline.OFDPA2Pipeline#processEthTypeSpecific
*/
@Override
protected Collection<FlowRule> processEthTypeSpecific(ForwardingObjective fwd) {
if (isDoubleTagged(fwd)) {
return processDoubleTaggedFwd(fwd);
}
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) && (ethType.ethType().toShort() != Ethernet.TYPE_IPV6)) {
log.warn("processSpecific: Unsupported forwarding objective criteria" + "ethType:{} in dev:{}", ethType, deviceId);
fail(fwd, ObjectiveError.UNSUPPORTED);
return Collections.emptySet();
}
boolean defaultRule = false;
int forTableId;
TrafficSelector.Builder filteredSelector = DefaultTrafficSelector.builder();
TrafficSelector.Builder complementarySelector = DefaultTrafficSelector.builder();
if (ethType.ethType().toShort() == Ethernet.TYPE_IPV4) {
IpPrefix ipv4Dst = ((IPCriterion) selector.getCriterion(Criterion.Type.IPV4_DST)).ip();
if (ipv4Dst.isMulticast()) {
if (ipv4Dst.prefixLength() != 32) {
log.warn("Multicast specific forwarding objective can only be /32");
fail(fwd, ObjectiveError.BADPARAMS);
return ImmutableSet.of();
}
VlanId assignedVlan = readVlanFromSelector(fwd.meta());
if (assignedVlan == null) {
log.warn("VLAN ID required by multicast specific fwd obj is missing. Abort.");
fail(fwd, ObjectiveError.BADPARAMS);
return ImmutableSet.of();
}
filteredSelector.matchVlanId(assignedVlan);
filteredSelector.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(ipv4Dst);
forTableId = MULTICAST_ROUTING_TABLE;
log.debug("processing IPv4 multicast specific forwarding objective {} -> next:{}" + " in dev:{}", fwd.id(), fwd.nextId(), deviceId);
} else {
if (ipv4Dst.prefixLength() == 0) {
// The entire IPV4_DST field is wildcarded intentionally
filteredSelector.matchEthType(Ethernet.TYPE_IPV4);
} else {
filteredSelector.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(ipv4Dst);
}
forTableId = UNICAST_ROUTING_TABLE;
log.debug("processing IPv4 unicast specific forwarding objective {} -> next:{}" + " in dev:{}", fwd.id(), fwd.nextId(), deviceId);
}
} else if (ethType.ethType().toShort() == Ethernet.TYPE_IPV6) {
IpPrefix ipv6Dst = ((IPCriterion) selector.getCriterion(Criterion.Type.IPV6_DST)).ip();
if (ipv6Dst.isMulticast()) {
if (ipv6Dst.prefixLength() != IpAddress.INET6_BIT_LENGTH) {
log.debug("Multicast specific IPv6 forwarding objective can only be /128");
fail(fwd, ObjectiveError.BADPARAMS);
return ImmutableSet.of();
}
VlanId assignedVlan = readVlanFromSelector(fwd.meta());
if (assignedVlan == null) {
log.debug("VLAN ID required by multicast specific fwd obj is missing. Abort.");
fail(fwd, ObjectiveError.BADPARAMS);
return ImmutableSet.of();
}
filteredSelector.matchVlanId(assignedVlan);
filteredSelector.matchEthType(Ethernet.TYPE_IPV6).matchIPv6Dst(ipv6Dst);
forTableId = MULTICAST_ROUTING_TABLE;
log.debug("processing IPv6 multicast specific forwarding objective {} -> next:{}" + " in dev:{}", fwd.id(), fwd.nextId(), deviceId);
} else {
if (buildIpv6Selector(filteredSelector, fwd) < 0) {
return Collections.emptyList();
}
forTableId = UNICAST_ROUTING_TABLE;
}
} else {
filteredSelector.matchEthType(Ethernet.MPLS_UNICAST).matchMplsLabel(((MplsCriterion) selector.getCriterion(Criterion.Type.MPLS_LABEL)).label());
MplsBosCriterion bos = (MplsBosCriterion) selector.getCriterion(Criterion.Type.MPLS_BOS);
if (bos != null) {
filteredSelector.matchMplsBos(bos.mplsBos());
}
forTableId = MPLS_TABLE_1;
log.debug("processing MPLS specific forwarding objective {} -> next:{}" + " in dev {}", fwd.id(), fwd.nextId(), deviceId);
}
TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder();
if (fwd.treatment() != null) {
for (Instruction i : fwd.treatment().allInstructions()) {
if (i instanceof L3ModificationInstruction) {
L3ModificationInstruction l3instr = (L3ModificationInstruction) i;
if (l3instr.subtype().equals(L3ModificationInstruction.L3SubType.TTL_IN) || l3instr.subtype().equals(L3ModificationInstruction.L3SubType.TTL_OUT)) {
continue;
}
}
/*
* NOTE: OF-DPA does not support immediate instruction in
* L3 unicast and MPLS table.
*/
tb.deferred().add(i);
}
}
if (fwd.nextId() != null) {
NextGroup next = getGroupForNextObjective(fwd.nextId());
if (next != null) {
List<Deque<GroupKey>> gkeys = appKryo.deserialize(next.data());
// we only need the top level group's key to point the flow to it
Group group = groupService.getGroup(deviceId, gkeys.get(0).peekFirst());
if (group == null) {
log.warn("Group with key:{} for next-id:{} not found in dev:{}", gkeys.get(0).peekFirst(), fwd.nextId(), deviceId);
fail(fwd, ObjectiveError.GROUPMISSING);
return Collections.emptySet();
}
tb.deferred().group(group.id());
}
}
tb.transition(ACL_TABLE);
FlowRule.Builder ruleBuilder = DefaultFlowRule.builder().fromApp(fwd.appId()).withPriority(fwd.priority()).forDevice(deviceId).withSelector(filteredSelector.build()).withTreatment(tb.build()).forTable(forTableId);
if (fwd.permanent()) {
ruleBuilder.makePermanent();
} else {
ruleBuilder.makeTemporary(fwd.timeout());
}
Collection<FlowRule> flowRuleCollection = new ArrayList<>();
flowRuleCollection.add(ruleBuilder.build());
if (defaultRule) {
flowRuleCollection.add(defaultRoute(fwd, complementarySelector, forTableId, tb));
log.debug("Default rule 0.0.0.0/0 is being installed two rules");
}
return flowRuleCollection;
}
use of org.onosproject.net.behaviour.NextGroup in project onos by opennetworkinglab.
the class AbstractHPPipeline method next.
@Override
public void next(NextObjective nextObjective) {
switch(nextObjective.op()) {
case ADD:
log.debug("HP driver: NextObjective ADDED");
// 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(nextObjective.next().iterator().next()));
break;
case REMOVE:
log.debug("HP driver: NextObjective REMOVED");
NextGroup next = flowObjectiveStore.removeNextGroup(nextObjective.id());
if (next == null) {
nextObjective.context().ifPresent(context -> context.onError(nextObjective, ObjectiveError.GROUPMISSING));
return;
}
break;
default:
log.debug("Unsupported operation {}", nextObjective.op());
}
nextObjective.context().ifPresent(context -> context.onSuccess(nextObjective));
}
Aggregations