use of org.onosproject.net.flow.criteria.PiCriterion in project fabric-tna by stratum.
the class FabricUpfTranslator method buildApplicationCriterion.
public PiCriterion buildApplicationCriterion(UpfApplication appFilter) {
PiCriterion.Builder matchBuilder = PiCriterion.builder();
matchBuilder.matchExact(HDR_SLICE_ID, SliceId.of(appFilter.sliceId()).id());
if (appFilter.ip4Prefix().isPresent()) {
Ip4Prefix ip4Prefix = appFilter.ip4Prefix().get();
matchBuilder.matchLpm(HDR_APP_IPV4_ADDR, ip4Prefix.address().toOctets(), ip4Prefix.prefixLength());
}
if (appFilter.l4PortRange().isPresent()) {
Range<Short> l4PortRange = appFilter.l4PortRange().get();
matchBuilder.matchRange(HDR_APP_L4_PORT, l4PortRange.lowerEndpoint(), l4PortRange.upperEndpoint());
}
if (appFilter.ipProto().isPresent()) {
byte ipProto = appFilter.ipProto().get();
matchBuilder.matchTernary(HDR_APP_IP_PROTO, ipProto, 0xF);
}
return matchBuilder.build();
}
use of org.onosproject.net.flow.criteria.PiCriterion in project fabric-tna by stratum.
the class FabricUpfTranslator method upfApplicationToFabricEntry.
public FlowRule upfApplicationToFabricEntry(UpfApplication appFilter, DeviceId deviceId, ApplicationId appId) throws UpfProgrammableException {
PiCriterion match = buildApplicationCriterion(appFilter);
PiAction action = PiAction.builder().withId(FABRIC_INGRESS_UPF_SET_APP_ID).withParameter(new PiActionParam(APP_ID, appFilter.appId())).build();
return DefaultFlowRule.builder().forDevice(deviceId).fromApp(appId).makePermanent().forTable(FABRIC_INGRESS_UPF_APPLICATIONS).withSelector(DefaultTrafficSelector.builder().matchPi(match).build()).withTreatment(DefaultTrafficTreatment.builder().piTableAction(action).build()).withPriority(appFilter.priority()).build();
}
use of org.onosproject.net.flow.criteria.PiCriterion in project fabric-tna by stratum.
the class StatisticManager method buildFlowRules.
// Prepare flow rules for both ingress and egress
protected List<FlowRule> buildFlowRules(StatisticKey key) {
// All possible ports in current topology
List<Port> ports = StreamSupport.stream(deviceService.getAvailableDevices().spliterator(), true).map(Device::id).map(deviceService::getPorts).flatMap(List<Port>::stream).collect(Collectors.toList());
// Prepare ingress and egress flow rule per port
List<FlowRule> flowRules = Lists.newArrayList();
ports.stream().forEach(port -> {
DeviceId deviceId = (DeviceId) port.element().id();
PortNumber portNumber = port.number();
log.debug("Processing flow rule for {}/{}", deviceId, portNumber);
// Prepare PiCriterion
PiCriterion ingressPiCriterion = PiCriterion.builder().matchExact(P4InfoConstants.HDR_IG_PORT, portNumber.toLong()).build();
PiCriterion egressPiCriterion = PiCriterion.builder().matchExact(P4InfoConstants.HDR_STATS_FLOW_ID, key.id()).matchExact(P4InfoConstants.HDR_EG_PORT, portNumber.toLong()).build();
// Prepare PiTableAction
PiTableAction ingressPiTableAction = PiAction.builder().withId(P4InfoConstants.FABRIC_INGRESS_STATS_COUNT).withParameter(new PiActionParam(P4InfoConstants.FLOW_ID, key.id())).build();
PiTableAction egressPiTableAction = PiAction.builder().withId(P4InfoConstants.FABRIC_EGRESS_STATS_COUNT).build();
// Prepare FlowRule
FlowRule ingressFlowRule = DefaultFlowRule.builder().forDevice(deviceId).forTable(PiTableId.of(FABRIC_INGRESS_STATS_FLOWS.id())).fromApp(appId).withPriority(key.id()).withSelector(DefaultTrafficSelector.builder(key.selector()).matchPi(ingressPiCriterion).build()).withTreatment(DefaultTrafficTreatment.builder().piTableAction(ingressPiTableAction).build()).makePermanent().build();
FlowRule egressFlowRule = DefaultFlowRule.builder().forDevice(deviceId).forTable(PiTableId.of(FABRIC_EGRESS_STATS_FLOWS.id())).fromApp(appId).withPriority(key.id()).withSelector(DefaultTrafficSelector.builder().matchPi(egressPiCriterion).build()).withTreatment(DefaultTrafficTreatment.builder().piTableAction(egressPiTableAction).build()).makePermanent().build();
flowRules.add(ingressFlowRule);
flowRules.add(egressFlowRule);
});
log.debug("Total {} flow rules", flowRules.size());
return flowRules;
}
use of org.onosproject.net.flow.criteria.PiCriterion in project fabric-tna by stratum.
the class FilteringObjectiveTranslator method ingressPortVlanRule.
private void ingressPortVlanRule(FilteringObjective obj, PortCriterion inPortCriterion, VlanIdCriterion outerVlanCriterion, VlanIdCriterion innerVlanCriterion, ObjectiveTranslation.Builder resultBuilder) throws FabricPipelinerException {
final boolean outerVlanValid = outerVlanCriterion != null && !outerVlanCriterion.vlanId().equals(VlanId.NONE);
final boolean innerVlanValid = innerVlanCriterion != null && !innerVlanCriterion.vlanId().equals(VlanId.NONE);
if (innerVlanValid && !capabilities.supportDoubleVlanTerm()) {
throw new FabricPipelinerException("Found 2 VLAN IDs, but the pipeline does not support double VLAN termination", ObjectiveError.UNSUPPORTED);
}
final PiCriterion piCriterion = PiCriterion.builder().matchExact(P4InfoConstants.HDR_VLAN_IS_VALID, outerVlanValid ? ONE : ZERO).build();
final TrafficSelector.Builder selector = DefaultTrafficSelector.builder().add(inPortCriterion).add(piCriterion);
if (outerVlanValid) {
selector.add(outerVlanCriterion);
}
if (innerVlanValid) {
selector.add(innerVlanCriterion);
}
final TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
if (obj.type().equals(FilteringObjective.Type.DENY)) {
treatmentBuilder.piTableAction(DENY);
} else {
// FIXME SDFAB-52 to complete the work on metadata
Byte portType = portType(obj);
if (portType == null) {
throw new FabricPipelinerException(format("Unsupported port_type configuration: metadata=%s", obj.meta()), ObjectiveError.BADPARAMS);
}
try {
treatmentBuilder.piTableAction(mapFilteringTreatment(obj.meta(), P4InfoConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN, portType));
} catch (PiInterpreterException ex) {
throw new FabricPipelinerException(format("Unable to map treatment for table '%s': %s", P4InfoConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN, ex.getMessage()), ObjectiveError.UNSUPPORTED);
}
// the EgressDscpRewriter table.
if (portType == PORT_TYPE_EDGE) {
// We need to make sure that traffic exiting an edge port doesn't
// carry the SD-Fabric DSCP field.
resultBuilder.addFlowRule(buildEgressDscpRewriter(obj, inPortCriterion, true));
} else if (portType == PORT_TYPE_INFRA) {
// We need to make sure that traffic exiting an infra port carry
// SD-Fabric DSCP field.
resultBuilder.addFlowRule(buildEgressDscpRewriter(obj, inPortCriterion, false));
resultBuilder.addFlowRule(buildTrustDscpEntry(obj, inPortCriterion));
}
}
resultBuilder.addFlowRule(flowRule(obj, P4InfoConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN, selector.build(), treatmentBuilder.build()));
}
use of org.onosproject.net.flow.criteria.PiCriterion in project onos by opennetworkinglab.
the class PiFlowRuleTranslatorImpl method translateFieldMatches.
/**
* Builds a collection of PI field matches out of the given selector,
* optionally using the given interpreter. The field matches returned are
* guaranteed to be compatible for the given table model.
*/
private static Collection<PiFieldMatch> translateFieldMatches(PiPipelineInterpreter interpreter, TrafficSelector selector, PiTableModel tableModel) throws PiTranslationException {
Map<PiMatchFieldId, PiFieldMatch> fieldMatches = Maps.newHashMap();
// If present, find a PiCriterion and get its field matches as a map. Otherwise, use an empty map.
Map<PiMatchFieldId, PiFieldMatch> piCriterionFields = selector.criteria().stream().filter(c -> c.type().equals(PROTOCOL_INDEPENDENT)).map(c -> (PiCriterion) c).findFirst().map(PiCriterion::fieldMatches).map(c -> {
Map<PiMatchFieldId, PiFieldMatch> fieldMap = Maps.newHashMap();
c.forEach(fieldMatch -> fieldMap.put(fieldMatch.fieldId(), fieldMatch));
return fieldMap;
}).orElse(Maps.newHashMap());
Set<Criterion> translatedCriteria = Sets.newHashSet();
Set<Criterion> ignoredCriteria = Sets.newHashSet();
Set<PiMatchFieldId> usedPiCriterionFields = Sets.newHashSet();
Set<PiMatchFieldId> ignoredPiCriterionFields = Sets.newHashSet();
Map<PiMatchFieldId, Criterion> criterionMap = Maps.newHashMap();
if (interpreter != null) {
// NOTE: if two criterion types map to the same match field ID, and
// those two criterion types are present in the selector, this won't
// work. This is unlikely to happen since those cases should be
// mutually exclusive:
// e.g. ICMPV6_TYPE -> metadata.my_normalized_icmp_type
// ICMPV4_TYPE -> metadata.my_normalized_icmp_type
// A packet can be either ICMPv6 or ICMPv4 but not both.
selector.criteria().stream().map(Criterion::type).filter(t -> t != PROTOCOL_INDEPENDENT).forEach(t -> {
PiMatchFieldId mfid = interpreter.mapCriterionType(t).orElse(null);
if (mfid != null) {
if (criterionMap.containsKey(mfid)) {
log.warn("Detected criterion mapping " + "conflict for PiMatchFieldId {}", mfid);
}
criterionMap.put(mfid, selector.getCriterion(t));
}
});
}
for (PiMatchFieldModel fieldModel : tableModel.matchFields()) {
PiMatchFieldId fieldId = fieldModel.id();
int bitWidth = fieldModel.bitWidth();
Criterion criterion = criterionMap.get(fieldId);
if (!piCriterionFields.containsKey(fieldId) && criterion == null) {
// Can ignore if match is ternary-like, as it means "don't care".
switch(fieldModel.matchType()) {
case TERNARY:
case LPM:
case RANGE:
case OPTIONAL:
// Skip field.
break;
default:
throw new PiTranslationException(format("No value found for required match field '%s'", fieldId));
}
// Next field.
continue;
}
PiFieldMatch fieldMatch = null;
// TODO: we currently do not support fields with arbitrary bit width
if (criterion != null && fieldModel.hasBitWidth()) {
// Criterion mapping is possible for this field id.
try {
fieldMatch = translateCriterion(criterion, fieldId, fieldModel.matchType(), bitWidth);
translatedCriteria.add(criterion);
} catch (PiTranslationException ex) {
// Ignore exception if the same field was found in PiCriterion.
if (piCriterionFields.containsKey(fieldId)) {
ignoredCriteria.add(criterion);
} else {
throw ex;
}
}
}
if (piCriterionFields.containsKey(fieldId)) {
// Field was found in PiCriterion.
if (fieldMatch != null) {
// Throw exception only if we are trying to match on different values of the same field...
if (!fieldMatch.equals(piCriterionFields.get(fieldId))) {
throw new PiTranslationException(format("Duplicate match field '%s': instance translated from criterion '%s' is different to " + "what found in PiCriterion.", fieldId, criterion.type()));
}
ignoredPiCriterionFields.add(fieldId);
} else {
fieldMatch = piCriterionFields.get(fieldId);
fieldMatch = typeCheckFieldMatch(fieldMatch, fieldModel);
usedPiCriterionFields.add(fieldId);
}
}
fieldMatches.put(fieldId, fieldMatch);
}
// Check if all criteria have been translated.
StringJoiner skippedCriteriaJoiner = new StringJoiner(", ");
selector.criteria().stream().filter(c -> !c.type().equals(PROTOCOL_INDEPENDENT)).filter(c -> !translatedCriteria.contains(c) && !ignoredCriteria.contains(c)).forEach(c -> skippedCriteriaJoiner.add(c.type().name()));
if (skippedCriteriaJoiner.length() > 0) {
throw new PiTranslationException(format("The following criteria cannot be translated for table '%s': %s", tableModel.id(), skippedCriteriaJoiner.toString()));
}
// Check if all fields found in PiCriterion have been used.
StringJoiner skippedPiFieldsJoiner = new StringJoiner(", ");
piCriterionFields.keySet().stream().filter(k -> !usedPiCriterionFields.contains(k) && !ignoredPiCriterionFields.contains(k)).forEach(k -> skippedPiFieldsJoiner.add(k.id()));
if (skippedPiFieldsJoiner.length() > 0) {
throw new PiTranslationException(format("The following PiCriterion field matches are not supported in table '%s': %s", tableModel.id(), skippedPiFieldsJoiner.toString()));
}
return fieldMatches.values();
}
Aggregations