Search in sources :

Example 6 with PiPipelineInterpreter

use of org.onosproject.net.pi.model.PiPipelineInterpreter 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();
}
Also used : PiTableId(org.onosproject.net.pi.model.PiTableId) PiOptionalFieldMatch(org.onosproject.net.pi.runtime.PiOptionalFieldMatch) PiUtils.getInterpreterOrNull(org.onosproject.net.pi.impl.PiUtils.getInterpreterOrNull) PiPipeconf(org.onosproject.net.pi.model.PiPipeconf) ImmutableByteSequence(org.onlab.util.ImmutableByteSequence) LoggerFactory(org.slf4j.LoggerFactory) PiActionParam(org.onosproject.net.pi.runtime.PiActionParam) PiActionParamModel(org.onosproject.net.pi.model.PiActionParamModel) PiPipelineModel(org.onosproject.net.pi.model.PiPipelineModel) PiMatchKey(org.onosproject.net.pi.runtime.PiMatchKey) PiUtils.translateTableId(org.onosproject.net.pi.impl.PiUtils.translateTableId) ImmutableByteSequence.prefixOnes(org.onlab.util.ImmutableByteSequence.prefixOnes) TrafficSelector(org.onosproject.net.flow.TrafficSelector) PiInstruction(org.onosproject.net.flow.instructions.PiInstruction) PiTableModel(org.onosproject.net.pi.model.PiTableModel) PiCriterion(org.onosproject.net.flow.criteria.PiCriterion) Map(java.util.Map) PiTranslationException(org.onosproject.net.pi.service.PiTranslationException) PiExactFieldMatch(org.onosproject.net.pi.runtime.PiExactFieldMatch) PiFieldMatch(org.onosproject.net.pi.runtime.PiFieldMatch) Criterion(org.onosproject.net.flow.criteria.Criterion) TrafficTreatment(org.onosproject.net.flow.TrafficTreatment) PiTableAction(org.onosproject.net.pi.runtime.PiTableAction) PiPipelineInterpreter(org.onosproject.net.pi.model.PiPipelineInterpreter) Logger(org.slf4j.Logger) Device(org.onosproject.net.Device) PiActionModel(org.onosproject.net.pi.model.PiActionModel) Instruction(org.onosproject.net.flow.instructions.Instruction) PiMatchFieldModel(org.onosproject.net.pi.model.PiMatchFieldModel) Collection(java.util.Collection) PiRangeFieldMatch(org.onosproject.net.pi.runtime.PiRangeFieldMatch) Set(java.util.Set) PiMatchFieldId(org.onosproject.net.pi.model.PiMatchFieldId) Maps(com.google.common.collect.Maps) Sets(com.google.common.collect.Sets) PiMatchType(org.onosproject.net.pi.model.PiMatchType) String.format(java.lang.String.format) PiTernaryFieldMatch(org.onosproject.net.pi.runtime.PiTernaryFieldMatch) ByteSequenceTrimException(org.onlab.util.ImmutableByteSequence.ByteSequenceTrimException) PROTOCOL_INDEPENDENT(org.onosproject.net.flow.criteria.Criterion.Type.PROTOCOL_INDEPENDENT) PiAction(org.onosproject.net.pi.runtime.PiAction) PiTableEntry(org.onosproject.net.pi.runtime.PiTableEntry) CriterionTranslatorHelper.translateCriterion(org.onosproject.net.pi.impl.CriterionTranslatorHelper.translateCriterion) FlowRule(org.onosproject.net.flow.FlowRule) StringJoiner(java.util.StringJoiner) PiTableType(org.onosproject.net.pi.model.PiTableType) PiLpmFieldMatch(org.onosproject.net.pi.runtime.PiLpmFieldMatch) PiActionSet(org.onosproject.net.pi.runtime.PiActionSet) PiCriterion(org.onosproject.net.flow.criteria.PiCriterion) PiTranslationException(org.onosproject.net.pi.service.PiTranslationException) PiCriterion(org.onosproject.net.flow.criteria.PiCriterion) Criterion(org.onosproject.net.flow.criteria.Criterion) CriterionTranslatorHelper.translateCriterion(org.onosproject.net.pi.impl.CriterionTranslatorHelper.translateCriterion) PiMatchFieldId(org.onosproject.net.pi.model.PiMatchFieldId) PiFieldMatch(org.onosproject.net.pi.runtime.PiFieldMatch) PiMatchFieldModel(org.onosproject.net.pi.model.PiMatchFieldModel) Map(java.util.Map) StringJoiner(java.util.StringJoiner)

Example 7 with PiPipelineInterpreter

use of org.onosproject.net.pi.model.PiPipelineInterpreter in project onos by opennetworkinglab.

the class P4RuntimeDriverUtils method getInterpreter.

/**
 * Returns an instance of the interpreter implementation for this device,
 * null if an interpreter cannot be retrieved.
 *
 * @param handler driver handler
 * @return interpreter or null
 */
static PiPipelineInterpreter getInterpreter(DriverHandler handler) {
    final DeviceId deviceId = handler.data().deviceId();
    final Device device = handler.get(DeviceService.class).getDevice(deviceId);
    if (device == null) {
        log.warn("Unable to find device {}, cannot get interpreter", deviceId);
        return null;
    }
    if (!device.is(PiPipelineInterpreter.class)) {
        log.warn("Unable to get interpreter for {}, missing behaviour", deviceId);
        return null;
    }
    return device.as(PiPipelineInterpreter.class);
}
Also used : DeviceId(org.onosproject.net.DeviceId) Device(org.onosproject.net.Device) DeviceService(org.onosproject.net.device.DeviceService) PiPipelineInterpreter(org.onosproject.net.pi.model.PiPipelineInterpreter)

Aggregations

PiPipelineInterpreter (org.onosproject.net.pi.model.PiPipelineInterpreter)7 Device (org.onosproject.net.Device)5 Sets (com.google.common.collect.Sets)3 String.format (java.lang.String.format)3 Set (java.util.Set)3 PiUtils.getInterpreterOrNull (org.onosproject.net.pi.impl.PiUtils.getInterpreterOrNull)3 PiPipeconf (org.onosproject.net.pi.model.PiPipeconf)3 PiPipelineModel (org.onosproject.net.pi.model.PiPipelineModel)3 PiTableId (org.onosproject.net.pi.model.PiTableId)3 PiAction (org.onosproject.net.pi.runtime.PiAction)3 PiTranslationException (org.onosproject.net.pi.service.PiTranslationException)3 Maps (com.google.common.collect.Maps)2 Collection (java.util.Collection)2 Map (java.util.Map)2 StringJoiner (java.util.StringJoiner)2 ImmutableByteSequence (org.onlab.util.ImmutableByteSequence)2 ByteSequenceTrimException (org.onlab.util.ImmutableByteSequence.ByteSequenceTrimException)2 ImmutableByteSequence.prefixOnes (org.onlab.util.ImmutableByteSequence.prefixOnes)2 DeviceId (org.onosproject.net.DeviceId)2 FlowRule (org.onosproject.net.flow.FlowRule)2