Search in sources :

Example 11 with PiFieldMatch

use of org.onosproject.net.pi.runtime.PiFieldMatch 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 12 with PiFieldMatch

use of org.onosproject.net.pi.runtime.PiFieldMatch in project onos by opennetworkinglab.

the class FieldMatchCodec method encode.

@Override
public P4RuntimeOuterClass.FieldMatch encode(PiFieldMatch piFieldMatch, P4InfoOuterClass.Preamble tablePreamble, PiPipeconf pipeconf, P4InfoBrowser browser) throws CodecException, P4InfoBrowser.NotFoundException {
    P4RuntimeOuterClass.FieldMatch.Builder messageBuilder = P4RuntimeOuterClass.FieldMatch.newBuilder();
    // FIXME: check how field names for stacked headers are constructed in P4Runtime.
    String fieldName = piFieldMatch.fieldId().id();
    P4InfoOuterClass.MatchField matchFieldInfo = browser.matchFields(tablePreamble.getId()).getByName(fieldName);
    String entityName = format("field match '%s' of table '%s'", matchFieldInfo.getName(), tablePreamble.getName());
    int fieldId = matchFieldInfo.getId();
    int fieldBitwidth = matchFieldInfo.getBitwidth();
    boolean isSdnString = browser.isTypeString(matchFieldInfo.getTypeName());
    messageBuilder.setFieldId(fieldId);
    switch(piFieldMatch.type()) {
        case EXACT:
            PiExactFieldMatch fieldMatch = (PiExactFieldMatch) piFieldMatch;
            ByteString exactValue;
            if (isSdnString) {
                exactValue = ByteString.copyFrom(fieldMatch.value().asReadOnlyBuffer());
            } else {
                exactValue = ByteString.copyFrom(fieldMatch.value().canonical().asReadOnlyBuffer());
                assertSize(VALUE_OF_PREFIX + entityName, exactValue, fieldBitwidth);
            }
            return messageBuilder.setExact(P4RuntimeOuterClass.FieldMatch.Exact.newBuilder().setValue(exactValue).build()).build();
        case TERNARY:
            PiTernaryFieldMatch ternaryMatch = (PiTernaryFieldMatch) piFieldMatch;
            ByteString ternaryValue = ByteString.copyFrom(ternaryMatch.value().canonical().asReadOnlyBuffer());
            ByteString ternaryMask = ByteString.copyFrom(ternaryMatch.mask().canonical().asReadOnlyBuffer());
            if (isSdnString) {
                sdnStringUnsupported(entityName, piFieldMatch.type());
            }
            assertSize(VALUE_OF_PREFIX + entityName, ternaryValue, fieldBitwidth);
            assertSize(MASK_OF_PREFIX + entityName, ternaryMask, fieldBitwidth);
            return messageBuilder.setTernary(P4RuntimeOuterClass.FieldMatch.Ternary.newBuilder().setValue(ternaryValue).setMask(ternaryMask).build()).build();
        case LPM:
            PiLpmFieldMatch lpmMatch = (PiLpmFieldMatch) piFieldMatch;
            ByteString lpmValue = ByteString.copyFrom(lpmMatch.value().canonical().asReadOnlyBuffer());
            int lpmPrefixLen = lpmMatch.prefixLength();
            if (isSdnString) {
                sdnStringUnsupported(entityName, piFieldMatch.type());
            }
            assertSize(VALUE_OF_PREFIX + entityName, lpmValue, fieldBitwidth);
            assertPrefixLen(entityName, lpmPrefixLen, fieldBitwidth);
            return messageBuilder.setLpm(P4RuntimeOuterClass.FieldMatch.LPM.newBuilder().setValue(lpmValue).setPrefixLen(lpmPrefixLen).build()).build();
        case RANGE:
            PiRangeFieldMatch rangeMatch = (PiRangeFieldMatch) piFieldMatch;
            ByteString rangeHighValue = ByteString.copyFrom(rangeMatch.highValue().canonical().asReadOnlyBuffer());
            ByteString rangeLowValue = ByteString.copyFrom(rangeMatch.lowValue().canonical().asReadOnlyBuffer());
            if (isSdnString) {
                sdnStringUnsupported(entityName, piFieldMatch.type());
            }
            assertSize(HIGH_RANGE_VALUE_OF_PREFIX + entityName, rangeHighValue, fieldBitwidth);
            assertSize(LOW_RANGE_VALUE_OF_PREFIX + entityName, rangeLowValue, fieldBitwidth);
            return messageBuilder.setRange(P4RuntimeOuterClass.FieldMatch.Range.newBuilder().setHigh(rangeHighValue).setLow(rangeLowValue).build()).build();
        case OPTIONAL:
            PiOptionalFieldMatch optionalMatch = (PiOptionalFieldMatch) piFieldMatch;
            ByteString optionalValue;
            if (isSdnString) {
                optionalValue = ByteString.copyFrom(optionalMatch.value().asReadOnlyBuffer());
            } else {
                optionalValue = ByteString.copyFrom(optionalMatch.value().canonical().asReadOnlyBuffer());
                assertSize(VALUE_OF_PREFIX + entityName, optionalValue, fieldBitwidth);
            }
            return messageBuilder.setOptional(P4RuntimeOuterClass.FieldMatch.Optional.newBuilder().setValue(optionalValue).build()).build();
        default:
            throw new CodecException(format("Building of match type %s not implemented", piFieldMatch.type()));
    }
}
Also used : PiOptionalFieldMatch(org.onosproject.net.pi.runtime.PiOptionalFieldMatch) PiRangeFieldMatch(org.onosproject.net.pi.runtime.PiRangeFieldMatch) PiTernaryFieldMatch(org.onosproject.net.pi.runtime.PiTernaryFieldMatch) PiExactFieldMatch(org.onosproject.net.pi.runtime.PiExactFieldMatch) PiLpmFieldMatch(org.onosproject.net.pi.runtime.PiLpmFieldMatch) PiFieldMatch(org.onosproject.net.pi.runtime.PiFieldMatch) ByteString(com.google.protobuf.ByteString) PiRangeFieldMatch(org.onosproject.net.pi.runtime.PiRangeFieldMatch) ByteString(com.google.protobuf.ByteString) PiTernaryFieldMatch(org.onosproject.net.pi.runtime.PiTernaryFieldMatch) PiLpmFieldMatch(org.onosproject.net.pi.runtime.PiLpmFieldMatch) P4InfoOuterClass(p4.config.v1.P4InfoOuterClass) PiOptionalFieldMatch(org.onosproject.net.pi.runtime.PiOptionalFieldMatch) PiExactFieldMatch(org.onosproject.net.pi.runtime.PiExactFieldMatch)

Example 13 with PiFieldMatch

use of org.onosproject.net.pi.runtime.PiFieldMatch in project onos by opennetworkinglab.

the class FieldMatchCodec method decode.

@Override
public PiFieldMatch decode(P4RuntimeOuterClass.FieldMatch message, P4InfoOuterClass.Preamble tablePreamble, PiPipeconf pipeconf, P4InfoBrowser browser) throws CodecException, P4InfoBrowser.NotFoundException {
    final P4InfoOuterClass.MatchField matchField = browser.matchFields(tablePreamble.getId()).getById(message.getFieldId());
    final int fieldBitwidth = matchField.getBitwidth();
    final PiMatchFieldId headerFieldId = PiMatchFieldId.of(matchField.getName());
    final boolean isSdnString = browser.isTypeString(matchField.getTypeName());
    final P4RuntimeOuterClass.FieldMatch.FieldMatchTypeCase typeCase = message.getFieldMatchTypeCase();
    try {
        switch(typeCase) {
            case EXACT:
                P4RuntimeOuterClass.FieldMatch.Exact exactFieldMatch = message.getExact();
                final ImmutableByteSequence exactValue;
                if (isSdnString) {
                    exactValue = copyFrom(new String(exactFieldMatch.getValue().toByteArray()));
                } else {
                    exactValue = copyAndFit(exactFieldMatch.getValue().asReadOnlyByteBuffer(), fieldBitwidth);
                }
                return new PiExactFieldMatch(headerFieldId, exactValue);
            case TERNARY:
                P4RuntimeOuterClass.FieldMatch.Ternary ternaryFieldMatch = message.getTernary();
                ImmutableByteSequence ternaryValue = copyAndFit(ternaryFieldMatch.getValue().asReadOnlyByteBuffer(), fieldBitwidth);
                ImmutableByteSequence ternaryMask = copyAndFit(ternaryFieldMatch.getMask().asReadOnlyByteBuffer(), fieldBitwidth);
                return new PiTernaryFieldMatch(headerFieldId, ternaryValue, ternaryMask);
            case LPM:
                P4RuntimeOuterClass.FieldMatch.LPM lpmFieldMatch = message.getLpm();
                ImmutableByteSequence lpmValue = copyAndFit(lpmFieldMatch.getValue().asReadOnlyByteBuffer(), fieldBitwidth);
                int lpmPrefixLen = lpmFieldMatch.getPrefixLen();
                return new PiLpmFieldMatch(headerFieldId, lpmValue, lpmPrefixLen);
            case RANGE:
                P4RuntimeOuterClass.FieldMatch.Range rangeFieldMatch = message.getRange();
                ImmutableByteSequence rangeHighValue = copyAndFit(rangeFieldMatch.getHigh().asReadOnlyByteBuffer(), fieldBitwidth);
                ImmutableByteSequence rangeLowValue = copyAndFit(rangeFieldMatch.getLow().asReadOnlyByteBuffer(), fieldBitwidth);
                return new PiRangeFieldMatch(headerFieldId, rangeLowValue, rangeHighValue);
            case OPTIONAL:
                P4RuntimeOuterClass.FieldMatch.Optional optionalFieldMatch = message.getOptional();
                final ImmutableByteSequence optionalValue;
                if (isSdnString) {
                    optionalValue = copyFrom(new String(optionalFieldMatch.getValue().toByteArray()));
                } else {
                    optionalValue = copyAndFit(optionalFieldMatch.getValue().asReadOnlyByteBuffer(), fieldBitwidth);
                }
                return new PiOptionalFieldMatch(headerFieldId, optionalValue);
            default:
                throw new CodecException(format("Decoding of field match type '%s' not implemented", typeCase.name()));
        }
    } catch (ImmutableByteSequence.ByteSequenceTrimException e) {
        throw new CodecException(e.getMessage());
    }
}
Also used : PiOptionalFieldMatch(org.onosproject.net.pi.runtime.PiOptionalFieldMatch) PiRangeFieldMatch(org.onosproject.net.pi.runtime.PiRangeFieldMatch) PiTernaryFieldMatch(org.onosproject.net.pi.runtime.PiTernaryFieldMatch) PiExactFieldMatch(org.onosproject.net.pi.runtime.PiExactFieldMatch) PiLpmFieldMatch(org.onosproject.net.pi.runtime.PiLpmFieldMatch) PiFieldMatch(org.onosproject.net.pi.runtime.PiFieldMatch) PiRangeFieldMatch(org.onosproject.net.pi.runtime.PiRangeFieldMatch) ByteString(com.google.protobuf.ByteString) PiTernaryFieldMatch(org.onosproject.net.pi.runtime.PiTernaryFieldMatch) PiLpmFieldMatch(org.onosproject.net.pi.runtime.PiLpmFieldMatch) P4InfoOuterClass(p4.config.v1.P4InfoOuterClass) PiOptionalFieldMatch(org.onosproject.net.pi.runtime.PiOptionalFieldMatch) PiMatchFieldId(org.onosproject.net.pi.model.PiMatchFieldId) PiExactFieldMatch(org.onosproject.net.pi.runtime.PiExactFieldMatch) ImmutableByteSequence(org.onlab.util.ImmutableByteSequence)

Example 14 with PiFieldMatch

use of org.onosproject.net.pi.runtime.PiFieldMatch in project up4 by omec-project.

the class Up4TranslatorUtil method getFieldPrefix.

static Ip4Prefix getFieldPrefix(PiTableEntry entry, PiMatchFieldId fieldId) {
    Optional<PiFieldMatch> optField = entry.matchKey().fieldMatch(fieldId);
    if (optField.isEmpty()) {
        return null;
    }
    PiLpmFieldMatch field = (PiLpmFieldMatch) optField.get();
    Ip4Address address = Ip4Address.valueOf(field.value().asArray());
    return Ip4Prefix.valueOf(address, field.prefixLength());
}
Also used : Ip4Address(org.onlab.packet.Ip4Address) PiFieldMatch(org.onosproject.net.pi.runtime.PiFieldMatch) PiLpmFieldMatch(org.onosproject.net.pi.runtime.PiLpmFieldMatch)

Example 15 with PiFieldMatch

use of org.onosproject.net.pi.runtime.PiFieldMatch in project up4 by omec-project.

the class Up4TranslatorUtil method getFieldRangeShort.

static Range<Short> getFieldRangeShort(PiTableEntry entry, PiMatchFieldId fieldId) {
    Optional<PiFieldMatch> optField = entry.matchKey().fieldMatch(fieldId);
    if (optField.isEmpty()) {
        return null;
    }
    PiRangeFieldMatch field = (PiRangeFieldMatch) optField.get();
    return Range.closed(byteSeqToShort(field.lowValue()), byteSeqToShort(field.highValue()));
}
Also used : PiRangeFieldMatch(org.onosproject.net.pi.runtime.PiRangeFieldMatch) PiFieldMatch(org.onosproject.net.pi.runtime.PiFieldMatch)

Aggregations

PiFieldMatch (org.onosproject.net.pi.runtime.PiFieldMatch)15 PiLpmFieldMatch (org.onosproject.net.pi.runtime.PiLpmFieldMatch)8 PiRangeFieldMatch (org.onosproject.net.pi.runtime.PiRangeFieldMatch)8 Test (org.junit.Test)6 PiExactFieldMatch (org.onosproject.net.pi.runtime.PiExactFieldMatch)6 PiOptionalFieldMatch (org.onosproject.net.pi.runtime.PiOptionalFieldMatch)6 PiTernaryFieldMatch (org.onosproject.net.pi.runtime.PiTernaryFieldMatch)6 ImmutableByteSequence (org.onlab.util.ImmutableByteSequence)3 Criterion (org.onosproject.net.flow.criteria.Criterion)3 PiCriterion (org.onosproject.net.flow.criteria.PiCriterion)3 PiMatchFieldId (org.onosproject.net.pi.model.PiMatchFieldId)3 Maps (com.google.common.collect.Maps)2 Sets (com.google.common.collect.Sets)2 ByteString (com.google.protobuf.ByteString)2 String.format (java.lang.String.format)2 Collection (java.util.Collection)2 Map (java.util.Map)2 Set (java.util.Set)2 StringJoiner (java.util.StringJoiner)2 Ip4Address (org.onlab.packet.Ip4Address)2