Search in sources :

Example 1 with PiMatchFieldModel

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

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

use of org.onosproject.net.pi.model.PiMatchFieldModel 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)

Example 4 with PiMatchFieldModel

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

the class P4InfoParserTest method testParse.

/**
 * Tests parse method.
 * @throws Exception if equality group objects dose not match as expected
 */
@Test
public void testParse() throws Exception {
    // Generate two PiPipelineModels from the same p4Info file
    PiPipelineModel model = P4InfoParser.parse(p4InfoUrl);
    PiPipelineModel sameAsModel = P4InfoParser.parse(p4InfoUrl);
    // Check equality
    new EqualsTester().addEqualityGroup(model, sameAsModel).testEquals();
    // Generate a P4Info object from the file
    final P4Info p4info;
    try {
        p4info = getP4InfoMessage(p4InfoUrl);
    } 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());
    PiTableId wcmpTableId = PiTableId.of(tableMsgs.get(1).getPreamble().getName());
    PiTableId wcmpTableOneShotId = PiTableId.of(tableMsgs.get(2).getPreamble().getName());
    // parse tables
    PiTableModel table0Model = model.table(table0Id).orElse(null);
    PiTableModel wcmpTableModel = model.table(wcmpTableId).orElse(null);
    PiTableModel wcmpTableOneShotModel = model.table(wcmpTableOneShotId).orElse(null);
    PiTableModel table0Model2 = sameAsModel.table(table0Id).orElse(null);
    PiTableModel wcmpTableModel2 = sameAsModel.table(wcmpTableId).orElse(null);
    new EqualsTester().addEqualityGroup(table0Model, table0Model2).addEqualityGroup(wcmpTableModel, wcmpTableModel2).testEquals();
    // Check existence
    assertThat("model parsed value is null", table0Model, notNullValue());
    assertThat("model parsed value is null", wcmpTableModel, notNullValue());
    assertThat("model parsed value is null", wcmpTableOneShotModel, notNullValue());
    assertThat("Incorrect size for table0 size", table0Model.maxSize(), is(equalTo(DEFAULT_MAX_TABLE_SIZE)));
    assertThat("Incorrect size for wcmp_table size", wcmpTableModel.maxSize(), is(equalTo(DEFAULT_MAX_TABLE_SIZE)));
    assertThat("Incorrect size for wcmp_table_one_shot size", wcmpTableOneShotModel.maxSize(), is(equalTo(DEFAULT_MAX_TABLE_SIZE)));
    // Check one-shot annotation
    assertThat("error parsing one-shot annotation", wcmpTableModel.oneShotOnly(), is(false));
    assertThat("error parsing one-shot annotation", wcmpTableOneShotModel.oneShotOnly(), is(true));
    // 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;
            default:
                Assert.fail();
                return;
        }
        piMatchFieldList.add(new P4MatchFieldModel(PiMatchFieldId.of(matchFieldIter.getName()), matchFieldIter.getBitwidth(), piMatchType));
    }
    // Check MatchFields size
    assertThat("Incorrect size for matchFields", table0Model.matchFields().size(), is(equalTo(9)));
    // Check if matchFields are in order
    assertThat("Incorrect order for matchFields", table0Model.matchFields(), IsIterableContainingInOrder.contains(piMatchFieldList.get(0), piMatchFieldList.get(1), piMatchFieldList.get(2), piMatchFieldList.get(3), piMatchFieldList.get(4), piMatchFieldList.get(5), piMatchFieldList.get(6), piMatchFieldList.get(7), piMatchFieldList.get(8)));
    assertThat("Incorrect size for matchFields", wcmpTableModel.matchFields().size(), is(equalTo(1)));
    // check if matchFields are in order
    matchFieldList = tableMsgs.get(1).getMatchFieldsList();
    assertThat("Incorrect order for matchFields", wcmpTableModel.matchFields(), IsIterableContainingInOrder.contains(new P4MatchFieldModel(PiMatchFieldId.of(matchFieldList.get(0).getName()), matchFieldList.get(0).getBitwidth(), PiMatchType.EXACT)));
    // check table0 actionsRefs
    List<ActionRef> actionRefList = tableMsgs.get(0).getActionRefsList();
    assertThat("Incorrect size for actionRefs", actionRefList.size(), is(equalTo(4)));
    // create action instances
    PiActionId actionId = PiActionId.of("set_egress_port");
    PiActionParamId piActionParamId = PiActionParamId.of("port");
    int bitWitdth = 9;
    PiActionParamModel actionParamModel = new P4ActionParamModel(piActionParamId, bitWitdth);
    ImmutableMap<PiActionParamId, PiActionParamModel> params = new ImmutableMap.Builder<PiActionParamId, PiActionParamModel>().put(piActionParamId, actionParamModel).build();
    PiActionModel setEgressPortAction = 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());
    actionId = PiActionId.of("NoAction");
    PiActionModel noAction = new P4ActionModel(actionId, new ImmutableMap.Builder<PiActionParamId, PiActionParamModel>().build());
    actionId = PiActionId.of("table0_control.set_next_hop_id");
    piActionParamId = PiActionParamId.of("next_hop_id");
    bitWitdth = 16;
    actionParamModel = new P4ActionParamModel(piActionParamId, bitWitdth);
    params = new ImmutableMap.Builder<PiActionParamId, PiActionParamModel>().put(piActionParamId, actionParamModel).build();
    PiActionModel setNextHopIdAction = new P4ActionModel(actionId, params);
    // check table0 actions
    assertThat("action dose not match", table0Model.actions(), IsIterableContainingInAnyOrder.containsInAnyOrder(setEgressPortAction, sendToCpuAction, setNextHopIdAction, dropAction));
    // check wcmp_table actions
    assertThat("actions dose not match", wcmpTableModel.actions(), IsIterableContainingInAnyOrder.containsInAnyOrder(setEgressPortAction, noAction));
    PiActionModel table0DefaultAction = table0Model.constDefaultAction().orElse(null);
    new EqualsTester().addEqualityGroup(table0DefaultAction, dropAction).testEquals();
    // Check existence
    assertThat("model parsed value is null", table0DefaultAction, notNullValue());
    // parse action profiles
    PiTableId tableId = PiTableId.of("wcmp_control.wcmp_table");
    ImmutableSet<PiTableId> tableIds = new ImmutableSet.Builder<PiTableId>().add(tableId).build();
    PiActionProfileId actionProfileId = PiActionProfileId.of("wcmp_control.wcmp_selector");
    PiActionProfileModel wcmpSelector3 = new P4ActionProfileModel(actionProfileId, tableIds, true, DEFAULT_MAX_ACTION_PROFILE_SIZE, DEFAULT_MAX_GROUP_SIZE);
    PiActionProfileModel wcmpSelector = model.actionProfiles(actionProfileId).orElse(null);
    PiActionProfileModel wcmpSelector2 = sameAsModel.actionProfiles(actionProfileId).orElse(null);
    new EqualsTester().addEqualityGroup(wcmpSelector, wcmpSelector2, wcmpSelector3).testEquals();
    // Check existence
    assertThat("model parsed value is null", wcmpSelector, notNullValue());
    assertThat("Incorrect value for actions profiles", model.actionProfiles(), containsInAnyOrder(wcmpSelector));
    // ActionProfiles size
    assertThat("Incorrect size for action profiles", model.actionProfiles().size(), is(equalTo(1)));
    // parse counters
    PiCounterModel ingressPortCounterModel = model.counter(PiCounterId.of("port_counters_ingress.ingress_port_counter")).orElse(null);
    PiCounterModel egressPortCounterModel = model.counter(PiCounterId.of("port_counters_egress.egress_port_counter")).orElse(null);
    PiCounterModel table0CounterModel = model.counter(PiCounterId.of("table0_control.table0_counter")).orElse(null);
    PiCounterModel wcmpTableCounterModel = model.counter(PiCounterId.of("wcmp_control.wcmp_table_counter")).orElse(null);
    PiCounterModel ingressPortCounterModel2 = sameAsModel.counter(PiCounterId.of("port_counters_ingress.ingress_port_counter")).orElse(null);
    PiCounterModel egressPortCounterModel2 = sameAsModel.counter(PiCounterId.of("port_counters_egress.egress_port_counter")).orElse(null);
    PiCounterModel table0CounterModel2 = sameAsModel.counter(PiCounterId.of("table0_control.table0_counter")).orElse(null);
    PiCounterModel wcmpTableCounterModel2 = sameAsModel.counter(PiCounterId.of("wcmp_control.wcmp_table_counter")).orElse(null);
    new EqualsTester().addEqualityGroup(ingressPortCounterModel, ingressPortCounterModel2).addEqualityGroup(egressPortCounterModel, egressPortCounterModel2).addEqualityGroup(table0CounterModel, table0CounterModel2).addEqualityGroup(wcmpTableCounterModel, wcmpTableCounterModel2).testEquals();
    assertThat("model parsed value is null", ingressPortCounterModel, notNullValue());
    assertThat("model parsed value is null", egressPortCounterModel, notNullValue());
    assertThat("model parsed value is null", table0CounterModel, notNullValue());
    assertThat("model parsed value is null", wcmpTableCounterModel, notNullValue());
    // Parse meters
    Collection<PiMeterModel> meterModel = model.meters();
    Collection<PiMeterModel> meterModel2 = sameAsModel.meters();
    assertThat("model parsed meter collection should be empty", meterModel.isEmpty(), is(true));
    assertThat("model parsed meter collection should be empty", meterModel2.isEmpty(), is(true));
    // parse packet operations
    PiPacketOperationModel packetInOperationalModel = model.packetOperationModel(PiPacketOperationType.PACKET_IN).orElse(null);
    PiPacketOperationModel packetOutOperationalModel = model.packetOperationModel(PiPacketOperationType.PACKET_OUT).orElse(null);
    PiPacketOperationModel packetInOperationalModel2 = sameAsModel.packetOperationModel(PiPacketOperationType.PACKET_IN).orElse(null);
    PiPacketOperationModel packetOutOperationalModel2 = sameAsModel.packetOperationModel(PiPacketOperationType.PACKET_OUT).orElse(null);
    new EqualsTester().addEqualityGroup(packetInOperationalModel, packetInOperationalModel2).addEqualityGroup(packetOutOperationalModel, packetOutOperationalModel2).testEquals();
    // Check existence
    assertThat("model parsed value is null", packetInOperationalModel, notNullValue());
    assertThat("model parsed value is null", packetOutOperationalModel, notNullValue());
}
Also used : PiTableModel(org.onosproject.net.pi.model.PiTableModel) PiActionId(org.onosproject.net.pi.model.PiActionId) PiActionParamId(org.onosproject.net.pi.model.PiActionParamId) PiCounterModel(org.onosproject.net.pi.model.PiCounterModel) ArrayList(java.util.ArrayList) PiPacketOperationModel(org.onosproject.net.pi.model.PiPacketOperationModel) 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) EqualsTester(com.google.common.testing.EqualsTester) PiMeterModel(org.onosproject.net.pi.model.PiMeterModel) PiActionParamModel(org.onosproject.net.pi.model.PiActionParamModel) PiActionProfileId(org.onosproject.net.pi.model.PiActionProfileId) IOException(java.io.IOException) ImmutableMap(com.google.common.collect.ImmutableMap) P4Info(p4.config.v1.P4InfoOuterClass.P4Info) PiActionProfileModel(org.onosproject.net.pi.model.PiActionProfileModel) PiMatchFieldModel(org.onosproject.net.pi.model.PiMatchFieldModel) Test(org.junit.Test)

Aggregations

PiActionModel (org.onosproject.net.pi.model.PiActionModel)4 PiMatchFieldModel (org.onosproject.net.pi.model.PiMatchFieldModel)4 PiTableId (org.onosproject.net.pi.model.PiTableId)4 PiTableModel (org.onosproject.net.pi.model.PiTableModel)4 ImmutableMap (com.google.common.collect.ImmutableMap)3 IOException (java.io.IOException)3 PiActionId (org.onosproject.net.pi.model.PiActionId)3 PiActionParamModel (org.onosproject.net.pi.model.PiActionParamModel)3 PiMatchType (org.onosproject.net.pi.model.PiMatchType)3 PiPipelineModel (org.onosproject.net.pi.model.PiPipelineModel)3 ActionRef (p4.config.v1.P4InfoOuterClass.ActionRef)3 MatchField (p4.config.v1.P4InfoOuterClass.MatchField)3 P4Info (p4.config.v1.P4InfoOuterClass.P4Info)3 Table (p4.config.v1.P4InfoOuterClass.Table)3 ArrayList (java.util.ArrayList)2 Test (org.junit.Test)2 PiActionProfileId (org.onosproject.net.pi.model.PiActionProfileId)2 PiActionProfileModel (org.onosproject.net.pi.model.PiActionProfileModel)2 PiCounterModel (org.onosproject.net.pi.model.PiCounterModel)2 PiMatchFieldId (org.onosproject.net.pi.model.PiMatchFieldId)2