Search in sources :

Example 1 with PiTableModel

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

the class PiFlowRuleTranslatorImpl method translate.

/**
 * Returns a PI table entry equivalent to the given flow rule, for the given
 * pipeconf and device.
 *
 * @param rule     flow rule
 * @param pipeconf pipeconf
 * @param device   device
 * @return PI table entry
 * @throws PiTranslationException if the flow rule cannot be translated
 */
static PiTableEntry translate(FlowRule rule, PiPipeconf pipeconf, Device device) throws PiTranslationException {
    PiPipelineModel pipelineModel = pipeconf.pipelineModel();
    // Retrieve interpreter, if any.
    final PiPipelineInterpreter interpreter = getInterpreterOrNull(device, pipeconf);
    // Get table model.
    final PiTableId piTableId = translateTableId(rule.table(), interpreter);
    final PiTableModel tableModel = getTableModel(piTableId, pipelineModel);
    // Translate selector.
    final PiMatchKey piMatchKey;
    final boolean needPriority;
    if (rule.selector().criteria().isEmpty()) {
        piMatchKey = PiMatchKey.EMPTY;
        needPriority = false;
    } else {
        final Collection<PiFieldMatch> fieldMatches = translateFieldMatches(interpreter, rule.selector(), tableModel);
        piMatchKey = PiMatchKey.builder().addFieldMatches(fieldMatches).build();
        // FIXME: P4Runtime limit
        // Need to ignore priority if no TCAM lookup match field
        needPriority = tableModel.matchFields().stream().anyMatch(match -> match.matchType() == PiMatchType.TERNARY || match.matchType() == PiMatchType.RANGE || match.matchType() == PiMatchType.OPTIONAL);
    }
    // Translate treatment.
    final PiTableAction piTableAction = translateTreatment(rule.treatment(), interpreter, piTableId, pipelineModel);
    // Build PI entry.
    final PiTableEntry.Builder tableEntryBuilder = PiTableEntry.builder();
    tableEntryBuilder.forTable(piTableId).withMatchKey(piMatchKey);
    if (piTableAction != null) {
        tableEntryBuilder.withAction(piTableAction);
    }
    if (needPriority) {
        // FIXME: move priority check to P4Runtime driver.
        final int newPriority;
        if (rule.priority() > MAX_PI_PRIORITY) {
            log.warn("Flow rule priority too big, setting translated priority to max value {}: {}", MAX_PI_PRIORITY, rule);
            newPriority = MAX_PI_PRIORITY;
        } else {
            newPriority = MIN_PI_PRIORITY + rule.priority();
        }
        tableEntryBuilder.withPriority(newPriority);
    }
    if (!rule.isPermanent()) {
        if (tableModel.supportsAging()) {
            tableEntryBuilder.withTimeout(rule.timeout());
        } else {
            log.debug("Flow rule is temporary, but table '{}' doesn't support " + "aging, translating to permanent.", tableModel.id());
        }
    }
    return tableEntryBuilder.build();
}
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) PiTableModel(org.onosproject.net.pi.model.PiTableModel) PiMatchKey(org.onosproject.net.pi.runtime.PiMatchKey) PiTableAction(org.onosproject.net.pi.runtime.PiTableAction) PiTableId(org.onosproject.net.pi.model.PiTableId) PiTableEntry(org.onosproject.net.pi.runtime.PiTableEntry) PiPipelineInterpreter(org.onosproject.net.pi.model.PiPipelineInterpreter) PiFieldMatch(org.onosproject.net.pi.runtime.PiFieldMatch) PiPipelineModel(org.onosproject.net.pi.model.PiPipelineModel)

Example 2 with PiTableModel

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

the class P4InfoParserTest method testParseP4RuntimeTranslationAndOptional.

/**
 * Tests parse method with P4Runtime translation fields and optional fields.
 * @throws Exception if equality group objects dose not match as expected
 */
@Test
public void testParseP4RuntimeTranslationAndOptional() throws Exception {
    PiPipelineModel model = P4InfoParser.parse(p4InfoUrl2);
    // Generate a P4Info object from the file
    final P4Info p4info;
    try {
        p4info = getP4InfoMessage(p4InfoUrl2);
    } catch (IOException e) {
        throw new P4InfoParserException("Unable to parse protobuf " + p4InfoUrl.toString(), e);
    }
    List<Table> tableMsgs = p4info.getTablesList();
    PiTableId table0Id = PiTableId.of(tableMsgs.get(0).getPreamble().getName());
    // parse tables
    PiTableModel table0Model = model.table(table0Id).orElse(null);
    // Check matchFields
    List<MatchField> matchFieldList = tableMsgs.get(0).getMatchFieldsList();
    List<PiMatchFieldModel> piMatchFieldList = new ArrayList<>();
    for (MatchField matchFieldIter : matchFieldList) {
        MatchField.MatchType matchType = matchFieldIter.getMatchType();
        PiMatchType piMatchType;
        switch(matchType) {
            case EXACT:
                piMatchType = PiMatchType.EXACT;
                break;
            case LPM:
                piMatchType = PiMatchType.LPM;
                break;
            case TERNARY:
                piMatchType = PiMatchType.TERNARY;
                break;
            case RANGE:
                piMatchType = PiMatchType.RANGE;
                break;
            case OPTIONAL:
                piMatchType = PiMatchType.OPTIONAL;
                break;
            default:
                Assert.fail();
                return;
        }
        if (matchFieldIter.getTypeName().getName().equals("mac_addr_t")) {
            piMatchFieldList.add(new P4MatchFieldModel(PiMatchFieldId.of(matchFieldIter.getName()), P4MatchFieldModel.BIT_WIDTH_UNDEFINED, piMatchType));
        } else {
            piMatchFieldList.add(new P4MatchFieldModel(PiMatchFieldId.of(matchFieldIter.getName()), matchFieldIter.getBitwidth(), piMatchType));
        }
    }
    assertThat("Incorrect order for matchFields", table0Model.matchFields(), IsIterableContainingInOrder.contains(piMatchFieldList.get(0), piMatchFieldList.get(1), piMatchFieldList.get(2), piMatchFieldList.get(3)));
    // check table0 actionsRefs
    List<ActionRef> actionRefList = tableMsgs.get(0).getActionRefsList();
    assertThat("Incorrect size for actionRefs", actionRefList.size(), is(equalTo(4)));
    // create action instances
    // Set egress with string as parameter
    PiActionId actionId = PiActionId.of("set_egress_port");
    PiActionParamId piActionParamId = PiActionParamId.of("port");
    PiActionParamModel actionParamModel = new P4ActionParamModel(piActionParamId, P4ActionParamModel.BIT_WIDTH_UNDEFINED);
    ImmutableMap<PiActionParamId, PiActionParamModel> params = new ImmutableMap.Builder<PiActionParamId, PiActionParamModel>().put(piActionParamId, actionParamModel).build();
    PiActionModel setEgressPortAction = new P4ActionModel(actionId, params);
    // Set egress with 32 bit as parameter
    actionId = PiActionId.of("set_egress_port2");
    piActionParamId = PiActionParamId.of("port");
    int bitWitdth = 32;
    actionParamModel = new P4ActionParamModel(piActionParamId, bitWitdth);
    params = new ImmutableMap.Builder<PiActionParamId, PiActionParamModel>().put(piActionParamId, actionParamModel).build();
    PiActionModel setEgressPortAction2 = new P4ActionModel(actionId, params);
    actionId = PiActionId.of("send_to_cpu");
    PiActionModel sendToCpuAction = new P4ActionModel(actionId, new ImmutableMap.Builder<PiActionParamId, PiActionParamModel>().build());
    actionId = PiActionId.of("drop");
    PiActionModel dropAction = new P4ActionModel(actionId, new ImmutableMap.Builder<PiActionParamId, PiActionParamModel>().build());
    // check table0 actions
    assertThat("action dose not match", table0Model.actions(), IsIterableContainingInAnyOrder.containsInAnyOrder(setEgressPortAction, setEgressPortAction2, sendToCpuAction, dropAction));
}
Also used : PiTableModel(org.onosproject.net.pi.model.PiTableModel) PiActionId(org.onosproject.net.pi.model.PiActionId) PiActionParamId(org.onosproject.net.pi.model.PiActionParamId) ArrayList(java.util.ArrayList) MatchField(p4.config.v1.P4InfoOuterClass.MatchField) PiTableId(org.onosproject.net.pi.model.PiTableId) ActionRef(p4.config.v1.P4InfoOuterClass.ActionRef) PiPipelineModel(org.onosproject.net.pi.model.PiPipelineModel) Table(p4.config.v1.P4InfoOuterClass.Table) PiMatchType(org.onosproject.net.pi.model.PiMatchType) PiActionModel(org.onosproject.net.pi.model.PiActionModel) PiActionParamModel(org.onosproject.net.pi.model.PiActionParamModel) IOException(java.io.IOException) ImmutableMap(com.google.common.collect.ImmutableMap) P4Info(p4.config.v1.P4InfoOuterClass.P4Info) PiMatchFieldModel(org.onosproject.net.pi.model.PiMatchFieldModel) Test(org.junit.Test)

Example 3 with PiTableModel

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

the class PiPipelineModelCodec method encode.

@Override
public ObjectNode encode(PiPipelineModel pipeline, CodecContext context) {
    ObjectNode result = context.mapper().createObjectNode();
    ArrayNode actions = result.putArray(ACTIONS);
    pipeline.tables().stream().flatMap(piTableModel -> piTableModel.actions().stream()).distinct().map(action -> context.encode(action, PiActionModel.class)).forEach(actions::add);
    ArrayNode tables = result.putArray(TABLES);
    pipeline.tables().stream().map(table -> context.encode(table, PiTableModel.class)).forEach(tables::add);
    return result;
}
Also used : ArrayNode(com.fasterxml.jackson.databind.node.ArrayNode) CodecContext(org.onosproject.codec.CodecContext) PiTableModel(org.onosproject.net.pi.model.PiTableModel) PiActionModel(org.onosproject.net.pi.model.PiActionModel) JsonCodec(org.onosproject.codec.JsonCodec) PiPipelineModel(org.onosproject.net.pi.model.PiPipelineModel) ObjectNode(com.fasterxml.jackson.databind.node.ObjectNode) ObjectNode(com.fasterxml.jackson.databind.node.ObjectNode) ArrayNode(com.fasterxml.jackson.databind.node.ArrayNode)

Example 4 with PiTableModel

use of org.onosproject.net.pi.model.PiTableModel 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 5 with PiTableModel

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

the class P4InfoParser method parse.

/**
 * Parse the given URL pointing to a P4Info file (in text format) to a PI pipeline model.
 *
 * @param p4InfoUrl URL to P4Info in text form
 * @return PI pipeline model
 * @throws P4InfoParserException if the P4Info file cannot be parsed (see message)
 */
public static PiPipelineModel parse(URL p4InfoUrl) throws P4InfoParserException {
    final P4Info p4info;
    try {
        p4info = getP4InfoMessage(p4InfoUrl);
    } catch (IOException e) {
        throw new P4InfoParserException("Unable to parse protobuf " + p4InfoUrl.toString(), e);
    }
    // Generate fingerprint of the pipeline by hashing p4info file
    final int fingerprint;
    try {
        HashingInputStream hin = new HashingInputStream(Hashing.crc32(), p4InfoUrl.openStream());
        // noinspection StatementWithEmptyBody
        while (hin.read() != -1) {
        // Do nothing. Reading all input stream to update hash.
        }
        fingerprint = hin.hash().asInt();
    } catch (IOException e) {
        throw new P4InfoParserException("Unable to generate fingerprint " + p4InfoUrl.toString(), e);
    }
    // Start by parsing and mapping instances to to their integer P4Info IDs.
    // Convenient to build the table model at the end.
    final String architecture = parseArchitecture(p4info);
    // Counters.
    final Map<Integer, PiCounterModel> counterMap = Maps.newHashMap();
    counterMap.putAll(parseCounters(p4info));
    counterMap.putAll(parseDirectCounters(p4info));
    // Meters.
    final Map<Integer, PiMeterModel> meterMap = Maps.newHashMap();
    meterMap.putAll(parseMeters(p4info));
    meterMap.putAll(parseDirectMeters(p4info));
    // Registers.
    final Map<Integer, PiRegisterModel> registerMap = Maps.newHashMap();
    registerMap.putAll(parseRegisters(p4info));
    // Action profiles.
    final Map<Integer, PiActionProfileModel> actProfileMap = parseActionProfiles(p4info);
    // Actions.
    final Map<Integer, PiActionModel> actionMap = parseActions(p4info);
    // Controller packet metadatas.
    final Map<PiPacketOperationType, PiPacketOperationModel> pktOpMap = parseCtrlPktMetadatas(p4info);
    // Finally, parse tables.
    final ImmutableMap.Builder<PiTableId, PiTableModel> tableImmMapBuilder = ImmutableMap.builder();
    for (Table tableMsg : p4info.getTablesList()) {
        final PiTableId tableId = PiTableId.of(tableMsg.getPreamble().getName());
        // Parse match fields.
        final ImmutableMap.Builder<PiMatchFieldId, PiMatchFieldModel> tableFieldMapBuilder = ImmutableMap.builder();
        for (MatchField fieldMsg : tableMsg.getMatchFieldsList()) {
            final PiMatchFieldId fieldId = PiMatchFieldId.of(fieldMsg.getName());
            tableFieldMapBuilder.put(fieldId, new P4MatchFieldModel(fieldId, isFieldString(p4info, fieldMsg.getTypeName().getName()) ? P4MatchFieldModel.BIT_WIDTH_UNDEFINED : fieldMsg.getBitwidth(), mapMatchFieldType(fieldMsg.getMatchType())));
        }
        // Retrieve action models by inter IDs.
        final ImmutableMap.Builder<PiActionId, PiActionModel> tableActionMapBuilder = ImmutableMap.builder();
        tableMsg.getActionRefsList().stream().map(ActionRef::getId).map(actionMap::get).forEach(actionModel -> tableActionMapBuilder.put(actionModel.id(), actionModel));
        // Retrieve direct meters by integer IDs.
        final ImmutableMap.Builder<PiMeterId, PiMeterModel> tableMeterMapBuilder = ImmutableMap.builder();
        tableMsg.getDirectResourceIdsList().stream().map(meterMap::get).filter(Objects::nonNull).forEach(meterModel -> tableMeterMapBuilder.put(meterModel.id(), meterModel));
        // Retrieve direct counters by integer IDs.
        final ImmutableMap.Builder<PiCounterId, PiCounterModel> tableCounterMapBuilder = ImmutableMap.builder();
        tableMsg.getDirectResourceIdsList().stream().map(counterMap::get).filter(Objects::nonNull).forEach(counterModel -> tableCounterMapBuilder.put(counterModel.id(), counterModel));
        // Check if table supports one-shot only
        boolean oneShotOnly = isAnnotationPresent(ONE_SHOT_ONLY_ANNOTATION, tableMsg.getPreamble());
        tableImmMapBuilder.put(tableId, new P4TableModel(PiTableId.of(tableMsg.getPreamble().getName()), tableMsg.getImplementationId() == 0 ? PiTableType.DIRECT : PiTableType.INDIRECT, actProfileMap.get(tableMsg.getImplementationId()), tableMsg.getSize(), tableCounterMapBuilder.build(), tableMeterMapBuilder.build(), !tableMsg.getIdleTimeoutBehavior().equals(Table.IdleTimeoutBehavior.NO_TIMEOUT), tableFieldMapBuilder.build(), tableActionMapBuilder.build(), actionMap.get(tableMsg.getConstDefaultActionId()), tableMsg.getIsConstTable(), oneShotOnly));
    }
    // Get a map with proper PI IDs for some of those maps we created at the beginning.
    ImmutableMap<PiCounterId, PiCounterModel> counterImmMap = ImmutableMap.copyOf(counterMap.values().stream().collect(Collectors.toMap(PiCounterModel::id, c -> c)));
    ImmutableMap<PiMeterId, PiMeterModel> meterImmMap = ImmutableMap.copyOf(meterMap.values().stream().collect(Collectors.toMap(PiMeterModel::id, m -> m)));
    ImmutableMap<PiRegisterId, PiRegisterModel> registerImmMap = ImmutableMap.copyOf(registerMap.values().stream().collect(Collectors.toMap(PiRegisterModel::id, r -> r)));
    ImmutableMap<PiActionProfileId, PiActionProfileModel> actProfileImmMap = ImmutableMap.copyOf(actProfileMap.values().stream().collect(Collectors.toMap(PiActionProfileModel::id, a -> a)));
    return new P4PipelineModel(tableImmMapBuilder.build(), counterImmMap, meterImmMap, registerImmMap, actProfileImmMap, ImmutableMap.copyOf(pktOpMap), architecture, fingerprint);
}
Also used : PiCounterModel(org.onosproject.net.pi.model.PiCounterModel) PiTableModel(org.onosproject.net.pi.model.PiTableModel) PiActionId(org.onosproject.net.pi.model.PiActionId) PiMeterId(org.onosproject.net.pi.model.PiMeterId) PiPacketOperationType(org.onosproject.net.pi.model.PiPacketOperationType) PiPacketOperationModel(org.onosproject.net.pi.model.PiPacketOperationModel) MatchField(p4.config.v1.P4InfoOuterClass.MatchField) PiTableId(org.onosproject.net.pi.model.PiTableId) PiMatchFieldId(org.onosproject.net.pi.model.PiMatchFieldId) ActionRef(p4.config.v1.P4InfoOuterClass.ActionRef) PiRegisterModel(org.onosproject.net.pi.model.PiRegisterModel) Table(p4.config.v1.P4InfoOuterClass.Table) PiActionModel(org.onosproject.net.pi.model.PiActionModel) PiMeterModel(org.onosproject.net.pi.model.PiMeterModel) PiActionProfileId(org.onosproject.net.pi.model.PiActionProfileId) IOException(java.io.IOException) ImmutableMap(com.google.common.collect.ImmutableMap) HashingInputStream(com.google.common.hash.HashingInputStream) P4Info(p4.config.v1.P4InfoOuterClass.P4Info) PiActionProfileModel(org.onosproject.net.pi.model.PiActionProfileModel) PiRegisterId(org.onosproject.net.pi.model.PiRegisterId) PiMatchFieldModel(org.onosproject.net.pi.model.PiMatchFieldModel) PiCounterId(org.onosproject.net.pi.model.PiCounterId)

Aggregations

PiActionModel (org.onosproject.net.pi.model.PiActionModel)6 PiTableModel (org.onosproject.net.pi.model.PiTableModel)6 PiMatchFieldModel (org.onosproject.net.pi.model.PiMatchFieldModel)5 PiPipelineModel (org.onosproject.net.pi.model.PiPipelineModel)5 PiTableId (org.onosproject.net.pi.model.PiTableId)5 PiActionParamModel (org.onosproject.net.pi.model.PiActionParamModel)4 PiMatchType (org.onosproject.net.pi.model.PiMatchType)4 ImmutableMap (com.google.common.collect.ImmutableMap)3 IOException (java.io.IOException)3 PiActionId (org.onosproject.net.pi.model.PiActionId)3 PiMatchFieldId (org.onosproject.net.pi.model.PiMatchFieldId)3 Maps (com.google.common.collect.Maps)2 Sets (com.google.common.collect.Sets)2 String.format (java.lang.String.format)2 ArrayList (java.util.ArrayList)2 Collection (java.util.Collection)2 Map (java.util.Map)2 Set (java.util.Set)2 StringJoiner (java.util.StringJoiner)2 Test (org.junit.Test)2