Search in sources :

Example 1 with PiCounterId

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

use of org.onosproject.net.pi.model.PiCounterId in project up4 by omec-project.

the class Up4NorthComponent method readCountersAndTranslate.

/**
 * Read the all p4 counter cell requested by the message, and translate them to p4runtime
 * entities for crafting a p4runtime read response.
 *
 * @param message a p4runtime CounterEntry message from a read request
 * @return the requested counter cells' contents, as a list of p4runtime entities
 * @throws StatusException if the counter index is out of range
 */
private List<P4RuntimeOuterClass.Entity> readCountersAndTranslate(P4RuntimeOuterClass.CounterEntry message) throws StatusException {
    ArrayList<PiCounterCell> responseCells = new ArrayList<>();
    Integer index = null;
    // FYI a counter read message with no index corresponds to a wildcard read of all indices
    if (message.hasIndex()) {
        index = (int) message.getIndex().getIndex();
    }
    String counterName = null;
    PiCounterId piCounterId = null;
    int counterId = message.getCounterId();
    // FYI a counterId of 0 corresponds to a wildcard read of all counters
    if (counterId != 0) {
        try {
            counterName = PipeconfHelper.getP4InfoBrowser(pipeconf).counters().getById(message.getCounterId()).getPreamble().getName();
            piCounterId = PiCounterId.of(counterName);
        } catch (P4InfoBrowser.NotFoundException e) {
            log.warn("Unable to find UP4 counter with ID {}", counterId);
            throw INVALID_ARGUMENT.withDescription("Invalid UP4 counter identifier.").asException();
        }
    }
    // cell was requested.
    if (counterName != null && index != null) {
        // A single counter cell was requested
        UpfCounter ctrValues;
        try {
            ctrValues = up4Service.readCounter(index);
        } catch (UpfProgrammableException e) {
            throw INVALID_ARGUMENT.withDescription(e.getMessage()).asException();
        }
        long pkts;
        long bytes;
        if (piCounterId.equals(PRE_QOS_PIPE_PRE_QOS_COUNTER)) {
            pkts = ctrValues.getIngressPkts();
            bytes = ctrValues.getIngressBytes();
        } else if (piCounterId.equals(POST_QOS_PIPE_POST_QOS_COUNTER)) {
            pkts = ctrValues.getEgressPkts();
            bytes = ctrValues.getEgressBytes();
        } else {
            log.warn("Received read request for unknown counter {}", piCounterId);
            throw INVALID_ARGUMENT.withDescription("Invalid UP4 counter identifier.").asException();
        }
        responseCells.add(new PiCounterCell(PiCounterCellId.ofIndirect(piCounterId, index), pkts, bytes));
    } else {
        // All cells were requested, either for a specific counter or all counters
        // FIXME: only read the counter that was requested, instead of both ingress and egress unconditionally
        Collection<UpfCounter> allStats;
        try {
            allStats = up4Service.readCounters(-1);
        } catch (UpfProgrammableException e) {
            throw io.grpc.Status.UNKNOWN.withDescription(e.getMessage()).asException();
        }
        for (UpfCounter stat : allStats) {
            if (piCounterId == null || piCounterId.equals(PRE_QOS_PIPE_PRE_QOS_COUNTER)) {
                // If all counters were requested, or just the ingress one
                responseCells.add(new PiCounterCell(PiCounterCellId.ofIndirect(PRE_QOS_PIPE_PRE_QOS_COUNTER, stat.getCellId()), stat.getIngressPkts(), stat.getIngressBytes()));
            }
            if (piCounterId == null || piCounterId.equals(POST_QOS_PIPE_POST_QOS_COUNTER)) {
                // If all counters were requested, or just the egress one
                responseCells.add(new PiCounterCell(PiCounterCellId.ofIndirect(POST_QOS_PIPE_POST_QOS_COUNTER, stat.getCellId()), stat.getEgressPkts(), stat.getEgressBytes()));
            }
        }
    }
    List<P4RuntimeOuterClass.Entity> responseEntities = new ArrayList<>();
    for (PiCounterCell cell : responseCells) {
        try {
            responseEntities.add(Codecs.CODECS.entity().encode(cell, null, pipeconf));
            log.trace("Encoded response to counter read request for counter {} and index {}", cell.cellId().counterId(), cell.cellId().index());
        } catch (CodecException e) {
            log.error("Unable to encode counter cell into a p4runtime entity: {}", e.getMessage());
            throw io.grpc.Status.INTERNAL.withDescription("Unable to encode counter cell into a p4runtime entity.").asException();
        }
    }
    log.debug("Encoded response to counter read request for {} cells", responseEntities.size());
    return responseEntities;
}
Also used : UpfEntity(org.onosproject.net.behaviour.upf.UpfEntity) PiEntity(org.onosproject.net.pi.runtime.PiEntity) ArrayList(java.util.ArrayList) ByteString(com.google.protobuf.ByteString) HexString(org.onlab.util.HexString) UpfCounter(org.onosproject.net.behaviour.upf.UpfCounter) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) UpfProgrammableException(org.onosproject.net.behaviour.upf.UpfProgrammableException) PiCounterCell(org.onosproject.net.pi.runtime.PiCounterCell) CodecException(org.onosproject.p4runtime.ctl.codec.CodecException) PiCounterId(org.onosproject.net.pi.model.PiCounterId) P4InfoBrowser(org.onosproject.p4runtime.ctl.utils.P4InfoBrowser)

Aggregations

PiCounterId (org.onosproject.net.pi.model.PiCounterId)2 ImmutableMap (com.google.common.collect.ImmutableMap)1 HashingInputStream (com.google.common.hash.HashingInputStream)1 ByteString (com.google.protobuf.ByteString)1 IOException (java.io.IOException)1 ArrayList (java.util.ArrayList)1 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)1 HexString (org.onlab.util.HexString)1 UpfCounter (org.onosproject.net.behaviour.upf.UpfCounter)1 UpfEntity (org.onosproject.net.behaviour.upf.UpfEntity)1 UpfProgrammableException (org.onosproject.net.behaviour.upf.UpfProgrammableException)1 PiActionId (org.onosproject.net.pi.model.PiActionId)1 PiActionModel (org.onosproject.net.pi.model.PiActionModel)1 PiActionProfileId (org.onosproject.net.pi.model.PiActionProfileId)1 PiActionProfileModel (org.onosproject.net.pi.model.PiActionProfileModel)1 PiCounterModel (org.onosproject.net.pi.model.PiCounterModel)1 PiMatchFieldId (org.onosproject.net.pi.model.PiMatchFieldId)1 PiMatchFieldModel (org.onosproject.net.pi.model.PiMatchFieldModel)1 PiMeterId (org.onosproject.net.pi.model.PiMeterId)1 PiMeterModel (org.onosproject.net.pi.model.PiMeterModel)1