org.onosproject.net.pi.model.PiPipelineInterpreter Java Examples

The following examples show how to use org.onosproject.net.pi.model.PiPipelineInterpreter. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: PiUtils.java    From onos with Apache License 2.0 6 votes vote down vote up
static PiTableId translateTableId(TableId tableId, PiPipelineInterpreter interpreter)
        throws PiTranslationException {
    switch (tableId.type()) {
        case PIPELINE_INDEPENDENT:
            return (PiTableId) tableId;
        case INDEX:
            IndexTableId indexId = (IndexTableId) tableId;
            if (interpreter == null) {
                throw new PiTranslationException(format(
                        "Unable to map table ID '%d' from index to PI: missing interpreter", indexId.id()));
            } else if (!interpreter.mapFlowRuleTableId(indexId.id()).isPresent()) {
                throw new PiTranslationException(format(
                        "Unable to map table ID '%d' from index to PI: missing ID in interpreter", indexId.id()));
            } else {
                return interpreter.mapFlowRuleTableId(indexId.id()).get();
            }
        default:
            throw new PiTranslationException(format(
                    "Unrecognized table ID type %s", tableId.type().name()));
    }
}
 
Example #2
Source File: P4RuntimeTableStatisticsDiscovery.java    From onos with Apache License 2.0 6 votes vote down vote up
@Override
public List<TableStatisticsEntry> getTableStatistics() {
    if (!setupBehaviour("getTableStatistics()")) {
        return Collections.emptyList();
    }
    FlowRuleService flowService = handler().get(FlowRuleService.class);
    PiPipelineInterpreter interpreter = getInterpreter(handler());
    PiPipelineModel model = pipeconf.pipelineModel();
    List<TableStatisticsEntry> tableStatsList;

    List<FlowEntry> rules = newArrayList(flowService.getFlowEntries(deviceId));
    Map<PiTableId, Integer> piTableFlowCount = piFlowRuleCounting(model, interpreter, rules);
    Map<PiTableId, Long> piTableMatchCount = piMatchedCounting(model, interpreter, rules);
    tableStatsList = generatePiFlowTableStatistics(piTableFlowCount, piTableMatchCount, model, deviceId);

    return tableStatsList;
}
 
Example #3
Source File: P4RuntimeTableStatisticsDiscovery.java    From onos with Apache License 2.0 6 votes vote down vote up
/**
 * Returns the number of added flows in each table.
 *
 * @param model pipeline model
 * @param interpreter pipeline interpreter
 * @param rules flow rules in this device
 * @return hashmap containing matched packet counting for each table
 */
private Map<PiTableId, Integer> piFlowRuleCounting(PiPipelineModel model, PiPipelineInterpreter interpreter,
                                                   List<FlowEntry> rules) {
    Map<PiTableId, Integer> piTableFlowCount = new HashMap<>();
    for (PiTableModel tableModel : model.tables()) {
        piTableFlowCount.put(tableModel.id(), 0);
    }
    for (FlowEntry f : rules) {
        if (f.state() == FlowEntry.FlowEntryState.ADDED) {
            PiTableId piTableId = getPiTableId(f, interpreter);
            if (piTableId != null) {
                piTableFlowCount.put(piTableId, piTableFlowCount.get(piTableId) + 1);
            }
        }
    }
    return piTableFlowCount;
}
 
Example #4
Source File: P4RuntimeTableStatisticsDiscovery.java    From onos with Apache License 2.0 6 votes vote down vote up
/**
 * Returns the number of matched packets for each table.
 *
 * @param model pipeline model
 * @param interpreter pipeline interpreter
 * @param rules flow rules in this device
 * @return hashmap containing flow rule counting for each table
 */
private Map<PiTableId, Long> piMatchedCounting(PiPipelineModel model, PiPipelineInterpreter interpreter,
                                               List<FlowEntry> rules) {
    Map<PiTableId, Long> piTableMatchCount = new HashMap<>();
    for (PiTableModel tableModel : model.tables()) {
        piTableMatchCount.put(tableModel.id(), (long) 0);
    }
    for (FlowEntry f : rules) {
        if (f.state() == FlowEntry.FlowEntryState.ADDED) {
            PiTableId piTableId = getPiTableId(f, interpreter);
            if (piTableId != null) {
                piTableMatchCount.put(piTableId, piTableMatchCount.get(piTableId) + f.packets());
            }
        }
    }
    return piTableMatchCount;
}
 
Example #5
Source File: PiUtils.java    From onos with Apache License 2.0 6 votes vote down vote up
static PiPipelineInterpreter getInterpreterOrNull(Device device, PiPipeconf pipeconf) {
    if (device != null) {
        return device.is(PiPipelineInterpreter.class) ? device.as(PiPipelineInterpreter.class) : null;
    } else {
        // The case of device == null should be admitted only during unit testing.
        // In any other case, the interpreter should be constructed using the device.as() method to make sure that
        // behaviour's handler/data attributes are correctly populated.
        // FIXME: modify test class PiFlowRuleTranslatorTest to avoid passing null device
        // I.e. we need to create a device object that supports is/as method for obtaining the interpreter.
        log.warn("getInterpreterOrNull() called with device == null, is this a unit test?");
        try {
            return (PiPipelineInterpreter) pipeconf.implementation(PiPipelineInterpreter.class)
                    .orElse(null)
                    .newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            throw new IllegalArgumentException(format("Unable to instantiate interpreter of pipeconf %s",
                                                      pipeconf.id()));
        }
    }
}
 
Example #6
Source File: P4RuntimePacketProgrammable.java    From onos with Apache License 2.0 6 votes vote down vote up
@Override
public void emit(OutboundPacket packet) {

    if (!this.setupBehaviour("emit()")) {
        return;
    }

    final PiPipelineInterpreter interpreter = getInterpreter(handler());
    if (interpreter == null) {
        // Error logged by getInterpreter().
        return;
    }

    if (log.isTraceEnabled()) {
        logPacketOut(packet);
    }

    try {
        interpreter.mapOutboundPacket(packet).forEach(
                op -> client.packetOut(p4DeviceId, op, pipeconf));
    } catch (PiPipelineInterpreter.PiInterpreterException e) {
        log.error("Unable to translate outbound packet for {} with pipeconf {}: {}",
                  deviceId, pipeconf.id(), e.getMessage());
    }
}
 
Example #7
Source File: AbstractObjectiveTranslator.java    From onos with Apache License 2.0 6 votes vote down vote up
TrafficTreatment mapTreatmentToPiIfNeeded(TrafficTreatment treatment, PiTableId tableId)
        throws FabricPipelinerException {
    if (isTreatmentPi(treatment)) {
        return treatment;
    }
    final PiAction piAction;
    try {
        piAction = interpreter.mapTreatment(treatment, tableId);
    } catch (PiPipelineInterpreter.PiInterpreterException ex) {
        throw new FabricPipelinerException(
                format("Unable to map treatment for table '%s': %s",
                       tableId, ex.getMessage()),
                ObjectiveError.UNSUPPORTED);
    }
    return DefaultTrafficTreatment.builder()
            .piTableAction(piAction)
            .build();
}
 
Example #8
Source File: PipeconfLoader.java    From onos with Apache License 2.0 6 votes vote down vote up
private static PiPipeconf buildBasicPipeconf() {
    final URL jsonUrl = PipeconfLoader.class.getResource(BASIC_JSON_PATH);
    final URL p4InfoUrl = PipeconfLoader.class.getResource(BASIC_P4INFO);

    return DefaultPiPipeconf.builder()
            .withId(BASIC_PIPECONF_ID)
            .withPipelineModel(parseP4Info(p4InfoUrl))
            .addBehaviour(PiPipelineInterpreter.class, BasicInterpreterImpl.class)
            .addBehaviour(Pipeliner.class, BasicPipelinerImpl.class)
            .addBehaviour(PortStatisticsDiscovery.class, PortStatisticsDiscoveryImpl.class)
            .addExtension(P4_INFO_TEXT, p4InfoUrl)
            .addExtension(BMV2_JSON, jsonUrl)
            // Put here other target-specific extensions,
            // e.g. Tofino's bin and context.json.
            .build();
}
 
Example #9
Source File: PipeconfLoader.java    From onos with Apache License 2.0 6 votes vote down vote up
private static PiPipeconf buildIntPipeconf() {
    final URL jsonUrl = PipeconfLoader.class.getResource(INT_JSON_PATH);
    final URL p4InfoUrl = PipeconfLoader.class.getResource(INT_P4INFO);

    // INT behavior is controlled using pipeline-specific flow rule,
    // not using flow objectives, so we just borrow pipeliner to basic pipeconf.
    return DefaultPiPipeconf.builder()
            .withId(INT_PIPECONF_ID)
            .withPipelineModel(parseP4Info(p4InfoUrl))
            .addBehaviour(PiPipelineInterpreter.class, BasicInterpreterImpl.class)
            .addBehaviour(Pipeliner.class, BasicPipelinerImpl.class)
            .addBehaviour(PortStatisticsDiscovery.class, PortStatisticsDiscoveryImpl.class)
            .addBehaviour(IntProgrammable.class, IntProgrammableImpl.class)
            .addExtension(P4_INFO_TEXT, p4InfoUrl)
            .addExtension(BMV2_JSON, jsonUrl)
            .build();
}
 
Example #10
Source File: FabricPipeconfManager.java    From onos with Apache License 2.0 5 votes vote down vote up
static PiPipeconf build(
        DefaultPiPipeconf.Builder pipeconfBuilder,
        String profileName, URL p4InfoUrl, URL cpuPortUrl) {
    checkNotNull(pipeconfBuilder,
                 "pipeconfBuilder cannot be null");
    checkArgument(profileName != null && !profileName.isEmpty(),
                  "profileName cannot be null or empty");
    checkNotNull(p4InfoUrl,
                 "p4InfoUrl cannot be null (check if file exists)");
    checkNotNull(cpuPortUrl,
                 "cpuPortUrl cannot be null (check if file exists)");

    pipeconfBuilder
            .withPipelineModel(parseP4Info(p4InfoUrl))
            .addBehaviour(PiPipelineInterpreter.class, FabricInterpreter.class)
            .addBehaviour(Pipeliner.class, FabricPipeliner.class)
            .addExtension(PiPipeconf.ExtensionType.P4_INFO_TEXT, p4InfoUrl)
            .addExtension(PiPipeconf.ExtensionType.CPU_PORT_TXT, cpuPortUrl);

    // Add IntProgrammable behaviour for INT-enabled profiles.
    if (profileName.endsWith(INT_PROFILE_SUFFIX) ||
            profileName.endsWith(FULL_PROFILE_SUFFIX)) {
        pipeconfBuilder.addBehaviour(IntProgrammable.class, FabricIntProgrammable.class);
    }
    // Add BngProgrammable behavior for BNG-enabled pipelines.
    if (profileName.endsWith(BNG_PROFILE_SUFFIX)) {
        pipeconfBuilder.addBehaviour(BngProgrammable.class, FabricBngProgrammable.class);
    }
    return pipeconfBuilder.build();
}
 
Example #11
Source File: PiFlowRuleTranslatorImpl.java    From onos with Apache License 2.0 5 votes vote down vote up
/**
 * Builds a PI action out of the given treatment, optionally using the given
 * interpreter.
 */
private static PiTableAction buildAction(TrafficTreatment treatment, PiPipelineInterpreter interpreter,
                                         PiTableId tableId)
        throws PiTranslationException {

    PiTableAction piTableAction = null;

    // If treatment has only one instruction of type PiInstruction, use that.
    for (Instruction inst : treatment.allInstructions()) {
        if (inst.type() == Instruction.Type.PROTOCOL_INDEPENDENT) {
            if (treatment.allInstructions().size() == 1) {
                piTableAction = ((PiInstruction) inst).action();
            } else {
                throw new PiTranslationException(format(
                        "Unable to translate treatment, found multiple instructions " +
                                "of which one is protocol-independent: %s", treatment));
            }
        }
    }

    if (piTableAction == null && interpreter != null) {
        // No PiInstruction, use interpreter to build action.
        try {
            piTableAction = interpreter.mapTreatment(treatment, tableId);
        } catch (PiPipelineInterpreter.PiInterpreterException e) {
            throw new PiTranslationException(
                    "Interpreter was unable to translate treatment. " + e.getMessage());
        }
    }

    return piTableAction;
}
 
Example #12
Source File: PiReplicationGroupTranslatorImpl.java    From onos with Apache License 2.0 5 votes vote down vote up
private static PortNumber logicalToPipelineSpecific(
        PortNumber logicalPort, Device device)
        throws PiTranslationException {
    if (!device.is(PiPipelineInterpreter.class)) {
        throw new PiTranslationException(
                "missing interpreter, cannot map logical port " + logicalPort.toString());
    }
    final PiPipelineInterpreter interpreter = device.as(PiPipelineInterpreter.class);
    Optional<Integer> mappedPort = interpreter.mapLogicalPortNumber(logicalPort);
    if (!mappedPort.isPresent()) {
        throw new PiTranslationException(
                "interpreter cannot map logical port " + logicalPort.toString());
    }
    return PortNumber.portNumber(mappedPort.get());
}
 
Example #13
Source File: PipeconfFactory.java    From onos with Apache License 2.0 5 votes vote down vote up
private PiPipeconf buildPipeconf() throws P4InfoParserException {

        final PiPipelineModel pipelineModel = P4InfoParser.parse(P4INFO_URL);

        return DefaultPiPipeconf.builder()
                .withId(PIPECONF_ID)
                .withPipelineModel(pipelineModel)
                .addBehaviour(PiPipelineInterpreter.class, PipelineInterpreterImpl.class)
                .addBehaviour(PortStatisticsDiscovery.class, PortStatisticsDiscoveryImpl.class)
                // Since mytunnel.p4 defines only 1 table, we re-use the existing single-table pipeliner.
                .addBehaviour(Pipeliner.class, DefaultSingleTablePipeline.class)
                .addExtension(P4_INFO_TEXT, P4INFO_URL)
                .addExtension(BMV2_JSON, BMV2_JSON_URL)
                .build();
    }
 
Example #14
Source File: PipeconfLoader.java    From ngsdn-tutorial with Apache License 2.0 5 votes vote down vote up
private PiPipeconf buildPipeconf() throws P4InfoParserException {

        final URL p4InfoUrl = PipeconfLoader.class.getResource(P4INFO_PATH);
        final URL bmv2JsonUrlUrl = PipeconfLoader.class.getResource(BMV2_JSON_PATH);
        final PiPipelineModel pipelineModel = P4InfoParser.parse(p4InfoUrl);

        return DefaultPiPipeconf.builder()
                .withId(PIPECONF_ID)
                .withPipelineModel(pipelineModel)
                .addBehaviour(PiPipelineInterpreter.class, InterpreterImpl.class)
                .addBehaviour(Pipeliner.class, PipelinerImpl.class)
                .addExtension(P4_INFO_TEXT, p4InfoUrl)
                .addExtension(BMV2_JSON, bmv2JsonUrlUrl)
                .build();
    }
 
Example #15
Source File: P4RuntimeDriverUtils.java    From onos with Apache License 2.0 5 votes vote down vote up
/**
 * Returns an instance of the interpreter implementation for this device,
 * null if an interpreter cannot be retrieved.
 *
 * @param handler driver handler
 * @return interpreter or null
 */
static PiPipelineInterpreter getInterpreter(DriverHandler handler) {
    final DeviceId deviceId = handler.data().deviceId();
    final Device device = handler.get(DeviceService.class).getDevice(deviceId);
    if (device == null) {
        log.warn("Unable to find device {}, cannot get interpreter", deviceId);
        return null;
    }
    if (!device.is(PiPipelineInterpreter.class)) {
        log.warn("Unable to get interpreter for {}, missing behaviour",
                 deviceId);
        return null;
    }
    return device.as(PiPipelineInterpreter.class);
}
 
Example #16
Source File: PipeconfLoader.java    From onos-p4-tutorial with Apache License 2.0 5 votes vote down vote up
private PiPipeconf buildPipeconf() throws P4InfoParserException {

        final URL p4InfoUrl = PipeconfLoader.class.getResource(P4INFO_PATH);
        final URL bmv2JsonUrlUrl = PipeconfLoader.class.getResource(BMV2_JSON_PATH);
        final PiPipelineModel pipelineModel = P4InfoParser.parse(p4InfoUrl);

        return DefaultPiPipeconf.builder()
                .withId(PIPECONF_ID)
                .withPipelineModel(pipelineModel)
                .addBehaviour(PiPipelineInterpreter.class, InterpreterImpl.class)
                .addBehaviour(Pipeliner.class, PipelinerImpl.class)
                .addExtension(P4_INFO_TEXT, p4InfoUrl)
                .addExtension(BMV2_JSON, bmv2JsonUrlUrl)
                .build();
    }
 
Example #17
Source File: PipeconfLoader.java    From onos-p4-tutorial with Apache License 2.0 5 votes vote down vote up
private PiPipeconf buildPipeconf() throws P4InfoParserException {

        final URL p4InfoUrl = PipeconfLoader.class.getResource(P4INFO_PATH);
        final URL bmv2JsonUrlUrl = PipeconfLoader.class.getResource(BMV2_JSON_PATH);
        final PiPipelineModel pipelineModel = P4InfoParser.parse(p4InfoUrl);

        return DefaultPiPipeconf.builder()
                .withId(PIPECONF_ID)
                .withPipelineModel(pipelineModel)
                .addBehaviour(PiPipelineInterpreter.class, InterpreterImpl.class)
                .addBehaviour(Pipeliner.class, PipelinerImpl.class)
                .addExtension(P4_INFO_TEXT, p4InfoUrl)
                .addExtension(BMV2_JSON, bmv2JsonUrlUrl)
                .build();
    }
 
Example #18
Source File: PiFlowRuleTranslatorImpl.java    From onos with Apache License 2.0 4 votes vote down vote up
/**
 * 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);
    }
    // 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((double) rule.timeout());
        } else {
            log.debug("Flow rule is temporary, but table '{}' doesn't support " +
                              "aging, translating to permanent.", tableModel.id());
        }

    }

    return tableEntryBuilder.build();
}
 
Example #19
Source File: PiFlowRuleTranslatorImpl.java    From onos with Apache License 2.0 3 votes vote down vote up
/**
 * Returns a PI action equivalent to the given treatment, optionally using
 * the given interpreter. This method also checks that the produced PI table
 * action is suitable for the given table ID and pipeline model. If
 * suitable, the returned action instance will have parameters well-sized,
 * according to the table model.
 *
 * @param treatment     traffic treatment
 * @param interpreter   interpreter
 * @param tableId       PI table ID
 * @param pipelineModel pipeline model
 * @return PI table action
 * @throws PiTranslationException if the treatment cannot be translated or
 *                                if the PI action is not suitable for the
 *                                given pipeline model
 */
static PiTableAction translateTreatment(TrafficTreatment treatment, PiPipelineInterpreter interpreter,
                                        PiTableId tableId, PiPipelineModel pipelineModel)
        throws PiTranslationException {
    PiTableModel tableModel = getTableModel(tableId, pipelineModel);
    return typeCheckAction(buildAction(treatment, interpreter, tableId), tableModel);
}
 
Example #20
Source File: P4RuntimeTableStatisticsDiscovery.java    From onos with Apache License 2.0 2 votes vote down vote up
/**
 * Returns the PiTableId of the pipeline independent table that contains the flow rule. If null is returned, it
 * means that the given flow rule's table ID is index table ID without a mapping with a pipeline independent table
 * ID.
 *
 * @param flowEntry flow rule
 * @param interpreter pipeline interpreter
 * @return PiTableId of the table containing input FlowEntry or null
 */
private PiTableId getPiTableId(FlowEntry flowEntry, PiPipelineInterpreter interpreter) {
    return flowEntry.table().type() == TableId.Type.PIPELINE_INDEPENDENT ?  (PiTableId) flowEntry.table() :
            interpreter.mapFlowRuleTableId(((IndexTableId) flowEntry.table()).id()).orElse(null);
}