Search in sources :

Example 6 with PiTranslationException

use of org.onosproject.net.pi.service.PiTranslationException in project onos by opennetworkinglab.

the class P4RuntimeReplicationGroupProgrammable method processGroupOp.

private void processGroupOp(Group pdGroup, GroupOperation.Type opType) {
    final PiPreEntry preEntry;
    try {
        preEntry = translator.translate(pdGroup, pipeconf);
    } catch (PiTranslationException e) {
        log.warn("Unable to translate replication group, aborting {} operation: {} [{}]", opType, e.getMessage(), pdGroup);
        return;
    }
    final PiPreEntryHandle handle = (PiPreEntryHandle) preEntry.handle(deviceId);
    final PiPreEntry entryOnDevice = mirror.get(handle) == null ? null : mirror.get(handle).entry();
    final Lock lock = STRIPED_LOCKS.get(handle);
    lock.lock();
    try {
        processPreEntry(handle, preEntry, entryOnDevice, pdGroup, opType);
    } finally {
        lock.unlock();
    }
}
Also used : PiPreEntryHandle(org.onosproject.net.pi.runtime.PiPreEntryHandle) PiPreEntry(org.onosproject.net.pi.runtime.PiPreEntry) PiTranslationException(org.onosproject.net.pi.service.PiTranslationException) Lock(java.util.concurrent.locks.Lock)

Example 7 with PiTranslationException

use of org.onosproject.net.pi.service.PiTranslationException in project onos by opennetworkinglab.

the class PiReplicationGroupTranslatorImpl method translate.

/**
 * Returns a PI PRE entry equivalent to the given group, for the given
 * pipeconf and device.
 * <p>
 * The passed group is expected to have type {@link GroupDescription.Type#ALL}
 * or {@link GroupDescription.Type#CLONE}.
 *
 * @param group    group
 * @param pipeconf pipeconf
 * @param device   device
 * @return PI PRE entry
 * @throws PiTranslationException if the group cannot be translated
 */
static PiPreEntry translate(Group group, PiPipeconf pipeconf, Device device) throws PiTranslationException {
    checkNotNull(group);
    final List<OutputInstruction> outInstructions = Lists.newArrayList();
    int truncateMaxLen = PiCloneSessionEntry.DO_NOT_TRUNCATE;
    for (GroupBucket bucket : group.buckets().buckets()) {
        int numInstructionsInBucket = bucket.treatment().allInstructions().size();
        List<OutputInstruction> outputs = getInstructions(bucket, Instruction.Type.OUTPUT, OutputInstruction.class);
        List<TruncateInstruction> truncates = getInstructions(bucket, Instruction.Type.TRUNCATE, TruncateInstruction.class);
        if (outputs.size() != 1) {
            throw new PiTranslationException("support only groups with just one OUTPUT instruction per bucket");
        }
        outInstructions.add(outputs.get(0));
        if (truncates.size() != 0) {
            if (group.type() != GroupDescription.Type.CLONE) {
                throw new PiTranslationException("only CLONE group support truncate instruction");
            }
            if (truncates.size() != 1) {
                throw new PiTranslationException("support only groups with just one TRUNCATE instruction per bucket");
            }
            int truncateInstMaxLen = truncates.get(0).maxLen();
            if (truncateMaxLen != PiCloneSessionEntry.DO_NOT_TRUNCATE && truncateMaxLen != truncateInstMaxLen) {
                throw new PiTranslationException("all TRUNCATE instruction must be the same in a CLONE group");
            }
            truncateMaxLen = truncateInstMaxLen;
        } else if (truncateMaxLen != PiCloneSessionEntry.DO_NOT_TRUNCATE) {
            // No truncate instruction found in this bucket, but previous bucket contains one.
            throw new PiTranslationException("all TRUNCATE instruction must be the same in a CLONE group");
        }
        if (numInstructionsInBucket != outputs.size() + truncates.size()) {
            throw new PiTranslationException("bucket contains unsupported instruction(s)");
        }
    }
    switch(group.type()) {
        case ALL:
            return PiMulticastGroupEntry.builder().withGroupId(group.id().id()).addReplicas(getReplicas(outInstructions, device)).build();
        case CLONE:
            return PiCloneSessionEntry.builder().withSessionId(group.id().id()).addReplicas(getReplicas(outInstructions, device)).withMaxPacketLengthBytes(truncateMaxLen).build();
        default:
            throw new PiTranslationException(format("group type %s not supported", group.type()));
    }
}
Also used : OutputInstruction(org.onosproject.net.flow.instructions.Instructions.OutputInstruction) TruncateInstruction(org.onosproject.net.flow.instructions.Instructions.TruncateInstruction) GroupBucket(org.onosproject.net.group.GroupBucket) PiTranslationException(org.onosproject.net.pi.service.PiTranslationException)

Example 8 with PiTranslationException

use of org.onosproject.net.pi.service.PiTranslationException in project onos by opennetworkinglab.

the class PiFlowRuleTranslatorImpl method typeCheckFieldMatch.

private static PiFieldMatch typeCheckFieldMatch(PiFieldMatch fieldMatch, PiMatchFieldModel fieldModel) throws PiTranslationException {
    // Check parameter type and size
    if (!fieldModel.matchType().equals(fieldMatch.type())) {
        throw new PiTranslationException(format("Wrong match type for field '%s', expected %s, but found %s", fieldMatch.fieldId(), fieldModel.matchType().name(), fieldMatch.type().name()));
    }
    // Check if the arbitrary bit width is supported
    if (!fieldModel.hasBitWidth() && !fieldModel.matchType().equals(PiMatchType.EXACT) && !fieldModel.matchType().equals(PiMatchType.OPTIONAL)) {
        throw new PiTranslationException(format("Arbitrary bit width for field '%s' and match type %s is not supported", fieldMatch.fieldId(), fieldModel.matchType().name()));
    }
    int modelBitWidth = fieldModel.bitWidth();
    try {
        switch(fieldModel.matchType()) {
            case EXACT:
                PiExactFieldMatch exactField = (PiExactFieldMatch) fieldMatch;
                return new PiExactFieldMatch(fieldMatch.fieldId(), fieldModel.hasBitWidth() ? exactField.value().fit(modelBitWidth) : exactField.value());
            case TERNARY:
                PiTernaryFieldMatch ternField = (PiTernaryFieldMatch) fieldMatch;
                ImmutableByteSequence ternMask = ternField.mask().fit(modelBitWidth);
                ImmutableByteSequence ternValue = ternField.value().fit(modelBitWidth).bitwiseAnd(ternMask);
                return new PiTernaryFieldMatch(fieldMatch.fieldId(), ternValue, ternMask);
            case LPM:
                PiLpmFieldMatch lpmfield = (PiLpmFieldMatch) fieldMatch;
                if (lpmfield.prefixLength() > modelBitWidth) {
                    throw new PiTranslationException(format("Invalid prefix length for LPM field '%s', found %d but field has bit-width %d", fieldMatch.fieldId(), lpmfield.prefixLength(), modelBitWidth));
                }
                ImmutableByteSequence lpmValue = lpmfield.value().fit(modelBitWidth);
                ImmutableByteSequence lpmMask = prefixOnes(lpmValue.size(), lpmfield.prefixLength());
                lpmValue = lpmValue.bitwiseAnd(lpmMask);
                return new PiLpmFieldMatch(fieldMatch.fieldId(), lpmValue, lpmfield.prefixLength());
            case RANGE:
                return new PiRangeFieldMatch(fieldMatch.fieldId(), ((PiRangeFieldMatch) fieldMatch).lowValue().fit(modelBitWidth), ((PiRangeFieldMatch) fieldMatch).highValue().fit(modelBitWidth));
            case OPTIONAL:
                PiOptionalFieldMatch optionalField = (PiOptionalFieldMatch) fieldMatch;
                return new PiOptionalFieldMatch(fieldMatch.fieldId(), fieldModel.hasBitWidth() ? optionalField.value().fit(modelBitWidth) : optionalField.value());
            default:
                // Should never be here.
                throw new IllegalArgumentException("Unrecognized match type " + fieldModel.matchType().name());
        }
    } catch (ByteSequenceTrimException e) {
        throw new PiTranslationException(format("Size mismatch for field %s: %s", fieldMatch.fieldId(), e.getMessage()));
    }
}
Also used : PiRangeFieldMatch(org.onosproject.net.pi.runtime.PiRangeFieldMatch) PiOptionalFieldMatch(org.onosproject.net.pi.runtime.PiOptionalFieldMatch) PiExactFieldMatch(org.onosproject.net.pi.runtime.PiExactFieldMatch) PiTernaryFieldMatch(org.onosproject.net.pi.runtime.PiTernaryFieldMatch) PiTranslationException(org.onosproject.net.pi.service.PiTranslationException) ByteSequenceTrimException(org.onlab.util.ImmutableByteSequence.ByteSequenceTrimException) ImmutableByteSequence(org.onlab.util.ImmutableByteSequence) PiLpmFieldMatch(org.onosproject.net.pi.runtime.PiLpmFieldMatch)

Example 9 with PiTranslationException

use of org.onosproject.net.pi.service.PiTranslationException 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 10 with PiTranslationException

use of org.onosproject.net.pi.service.PiTranslationException in project onos by opennetworkinglab.

the class P4RuntimeActionGroupProgrammable method processPdGroup.

private void processPdGroup(Group pdGroup, GroupOperation.Type opType) {
    // Translate.
    final PiActionProfileGroup piGroup;
    try {
        piGroup = groupTranslator.translate(pdGroup, pipeconf);
    } catch (PiTranslationException e) {
        log.warn("Unable to translate group, aborting {} operation: {} [{}]", opType, e.getMessage(), pdGroup);
        return;
    }
    final Operation operation = opType.equals(GroupOperation.Type.DELETE) ? Operation.REMOVE : Operation.APPLY;
    final PiActionProfileGroupHandle handle = piGroup.handle(deviceId);
    // Update translation store.
    if (operation.equals(Operation.APPLY)) {
        groupTranslator.learn(handle, new PiTranslatedEntity<>(pdGroup, piGroup, handle));
    } else {
        groupTranslator.forget(handle);
    }
    // Submit write and forget about it.
    asyncWritePiGroup(piGroup, handle, operation);
}
Also used : PiActionProfileGroupHandle(org.onosproject.net.pi.runtime.PiActionProfileGroupHandle) GroupOperation(org.onosproject.net.group.GroupOperation) PiTranslationException(org.onosproject.net.pi.service.PiTranslationException) PiActionProfileGroup(org.onosproject.net.pi.runtime.PiActionProfileGroup)

Aggregations

PiTranslationException (org.onosproject.net.pi.service.PiTranslationException)12 ByteSequenceTrimException (org.onlab.util.ImmutableByteSequence.ByteSequenceTrimException)5 ImmutableByteSequence (org.onlab.util.ImmutableByteSequence)4 PiExactFieldMatch (org.onosproject.net.pi.runtime.PiExactFieldMatch)4 PiLpmFieldMatch (org.onosproject.net.pi.runtime.PiLpmFieldMatch)4 PiOptionalFieldMatch (org.onosproject.net.pi.runtime.PiOptionalFieldMatch)4 PiTernaryFieldMatch (org.onosproject.net.pi.runtime.PiTernaryFieldMatch)4 Sets (com.google.common.collect.Sets)3 String.format (java.lang.String.format)3 Set (java.util.Set)3 Device (org.onosproject.net.Device)3 FlowRule (org.onosproject.net.flow.FlowRule)3 PiUtils.getInterpreterOrNull (org.onosproject.net.pi.impl.PiUtils.getInterpreterOrNull)3 PiActionModel (org.onosproject.net.pi.model.PiActionModel)3 PiActionParamModel (org.onosproject.net.pi.model.PiActionParamModel)3 PiPipeconf (org.onosproject.net.pi.model.PiPipeconf)3 PiPipelineInterpreter (org.onosproject.net.pi.model.PiPipelineInterpreter)3 PiAction (org.onosproject.net.pi.runtime.PiAction)3 Maps (com.google.common.collect.Maps)2 Collection (java.util.Collection)2