From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <antonin@barefootnetworks.com>
Received: from mail-pl0-f66.google.com (mail-pl0-f66.google.com
 [209.85.160.66]) by dpdk.org (Postfix) with ESMTP id 16F2D1B59B
 for <dev@dpdk.org>; Sat, 16 Jun 2018 01:25:41 +0200 (CEST)
Received: by mail-pl0-f66.google.com with SMTP id 30-v6so6076391pld.13
 for <dev@dpdk.org>; Fri, 15 Jun 2018 16:25:40 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=barefootnetworks.com; s=google;
 h=from:message-id:mime-version:subject:date:in-reply-to:cc:to
 :references; bh=MFoAfKAJXTy4+oSNpZJf1xxrKrZLnpiPO0JDHY6oobc=;
 b=fRbLohKxW5xncB73qoiFMgbHKX1D3id/rpj1oUNUr39k7yaT5r23UNEYE4vbSC2Ide
 Z0us9sDNvTGPadhgQ52C0zYtgkeHThoIOCWz6iqq2G2yNGv+Bs9BisVdnPYmo2NrRAGR
 xLqfLTR94NAH7oKdFGuPewtbpNNy852NmauXw=
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=1e100.net; s=20161025;
 h=x-gm-message-state:from:message-id:mime-version:subject:date
 :in-reply-to:cc:to:references;
 bh=MFoAfKAJXTy4+oSNpZJf1xxrKrZLnpiPO0JDHY6oobc=;
 b=TyqRfAwD/+hWxK3kI4lP1iHgKmTn6WqE5E2zraCxe6t/tnqhLcU2NqvslY4Ul4wYyd
 SAxJmx3uImdPDZiIlF48OYDSE0Zgx0ngx9mKNcb+PYKe3Nud8P3gXM4apkKlWkwJwCqI
 PwW35jSjMV/VQTSFxUMvVFuP0XI2l81i3SjKjNBwtfcUoWgEKVG6f9UcTsZTULUzIMh9
 xi0naMM9NLtD2is7F5qi9I35MQMo20BXrpfn728pRqVAYSRqvurM1nnhCpssSrRzjiUT
 nmbr/Hy43+89Uw86HWm3SlsGXGuTmuGZynwhPG6Pz/G7yjI7AL3gQlX1e+ttXV/hwokP
 s3uA==
X-Gm-Message-State: APt69E0Q/yaluUcNUiK2GGtCqjHcPD61tB48RiyDrCNivnMYDUY8LZBT
 C7u9S71fYpKyNy/gT9ewmy6qVw==
X-Google-Smtp-Source: ADUXVKKxpYil5CH7cXmTYEMOr21NFwME2F20yNXDkedWCgEFiqz0h+/7Z3uFM+oOkTEmNa7atDeeug==
X-Received: by 2002:a17:902:bd95:: with SMTP id
 q21-v6mr4161338pls.237.1529105139962; 
 Fri, 15 Jun 2018 16:25:39 -0700 (PDT)
Received: from [10.10.41.68] ([38.77.204.66])
 by smtp.gmail.com with ESMTPSA id t192-v6sm13292357pgc.74.2018.06.15.16.25.38
 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
 Fri, 15 Jun 2018 16:25:39 -0700 (PDT)
From: antonin@barefootnetworks.com
Message-Id: <767DDC46-5501-4147-9004-0AB38C34C17B@barefootnetworks.com>
Mime-Version: 1.0 (Mac OS X Mail 11.3 \(3445.6.18\))
Date: Fri, 15 Jun 2018 16:25:38 -0700
In-Reply-To: <1524072121-237519-1-git-send-email-cristian.dumitrescu@intel.com>
Cc: "dev@dpdk.org" <dev@dpdk.org>,
 "Daly, Dan" <dan.daly@intel.com>
To: "Dumitrescu, Cristian" <cristian.dumitrescu@intel.com>
References: <1524072121-237519-1-git-send-email-cristian.dumitrescu@intel.com>
X-Mailer: Apple Mail (2.3445.6.18)
Content-Type: text/plain;
	charset=utf-8
Content-Transfer-Encoding: quoted-printable
X-Content-Filtered-By: Mailman/MimeDel 2.1.15
Subject: Re: [dpdk-dev] [RFC] P4 enablement in DPDK
X-BeenThere: dev@dpdk.org
X-Mailman-Version: 2.1.15
Precedence: list
List-Id: DPDK patches and discussions <dev.dpdk.org>
List-Unsubscribe: <https://dpdk.org/ml/options/dev>,
 <mailto:dev-request@dpdk.org?subject=unsubscribe>
List-Archive: <http://dpdk.org/ml/archives/dev/>
List-Post: <mailto:dev@dpdk.org>
List-Help: <mailto:dev-request@dpdk.org?subject=help>
List-Subscribe: <https://dpdk.org/ml/listinfo/dev>,
 <mailto:dev-request@dpdk.org?subject=subscribe>
X-List-Received-Date: Fri, 15 Jun 2018 23:25:41 -0000

Hi,

I want to express support for this proposal and adding P4 capabilities =
in DPDK. For example, I personally see a lot of demand for a =
production-quality P4-programmable software switch.

A few comments on this:

1) I see a lot of similarities between the proposed PDEV table runtime =
API and the existing PI C API: =
https://github.com/p4lang/PI/tree/master/include/PI =
<https://github.com/p4lang/PI/tree/master/include/PI>. I wonder if there =
would be value in trying to re-use them - at least partially - for this.
PI is very much aligned on P4 and strictly Program Independent. That =
does not seem to be completely the case for the PDEV table runtime API =
(dscp table, TTL, =E2=80=A6) and I=E2=80=99m not familiar enough with =
DPDK to understand the rationale for this, but I don=E2=80=99t see why =
DPDK couldn=E2=80=99t have its own extensions to the PI API.

2) For the sake of avoiding fragmentation of the community, I would =
strongly recommend making sure that there is an available P4Runtime =
(https://p4.org/p4-spec/docs/P4Runtime-v1.0.0.pdf =
<https://p4.org/p4-spec/docs/P4Runtime-v1.0.0.pdf>) implementation for =
DPDK. That would require a mapping from P4Runtime messages to PDEV API =
calls. The advantage of trying to align PDEV with PI (first bullet =
point) is that there is already a mapping from P4Runtime messages to PI =
API calls.
The burden of supporting P4Runtime can probably be reduced by leveraging =
the Stratum project (https://stratumproject.org/ =
<https://stratumproject.org/>), which unfortunately is not open-source =
yet.

3) It seems that the notion of =E2=80=9Caction profile=E2=80=9D here is =
more general than in P4, or more precisely than in the P4_16 PSA =
architecture (Portable Switch Architecture). Since this term has a =
strong connotation in the P4 world, maybe another term should be used =
instead if possible.

4) I recommend looking into the notion of =E2=80=9Carchitecture=E2=80=9D =
in P4_16 and trying to decide if you want to a) have generic support for =
all P4 architectures (at least for the CPU implementation), b) support =
the PSA architecture specifically (which is the primary / only =
architecture used as part of Stratum) or c) define your own architecture =
specifically for targets that are going to support P4 through DPDK =
drivers (which may limit your impact).

 5) Conceptually the APIs can be split into 2 parts: a) the table =
runtime APIs, which are generally pretty-straightforward and b) pipeline =
query & configuration APIs. Both P4Runtime (SetForwardingPipelineConfig) =
& PI (pi_device_update_[start|end]) include mechanisms to re-configure =
the data-plane, by providing the compiler output to the target.
For b), I strongly recommend looking into what we have done with =
P4Runtime. SetForwardingPipelineConfig provides the target with a P4Info =
message (which is target-agnostic and describes the interface of each =
runtime-controllable P4 object; in a way I believe it is similar to your =
table_create PDEV API) and a target-specific opaque =E2=80=9Cblob=E2=80=9D=
. For reconfigurable SW & HW the =E2=80=9Cblob=E2=80=9D is essentially a =
description of the pipeline: it can be some text file, binary register =
values, an object file, etc=E2=80=A6
The case of fixed-function devices is usually trickier. We actually do =
not have a pipeline discovery mechanism in P4Runtime & PI. In P4Runtime, =
we just assume that the control-plane is aware of the pipeline and has =
access to a P4Info message for it. We still require the P4Runtime client =
to call SetForwardingPipelineConfig with the =E2=80=9Cright" P4Info =
message (we expect the target to return an error if the P4Info is not =
the right one) and a potentially empty =E2=80=9Cblob=E2=80=9D.
I think the take-away is that there isn=E2=80=99t a unified pipeline =
creation mechanism across programmable targets, i.e. it is difficult to =
break down pipeline creation into a sequence of universal sub-API calls, =
such as =E2=80=9Ccreate_table=E2=80=9D, =E2=80=9Ccreate_parser=E2=80=9D, =
etc=E2=80=A6 However it would make perfect sense IMO to design and =
implement such an API in the context of a specific DPDK SW switch. The =
P4 compiler backend would then be in-charge of generating the =
appropriate sequence of API calls.

Overall I=E2=80=99m very excited to see some work being done in this =
area. I believe a lot of people will be able to help, especially with =
compiler backend development. To summarize my 5 bullet points above, I =
would say that there are 2 import areas of investigation as far as I can =
tell:
1) what should be the compiler backend output for the DPDK CPU SW target =
(sequence of API calls)? For non-programmable devices, having the =
=E2=80=9Cright=E2=80=9D P4Info is usually enough. Existing =
P4-programmable hardware already comes with its own compiler backend =
(Barefoot Tofino ASIC, Xilinx FPGAs).
2) can we try to avoid fragmentation and re-use existing code with =
P4Runtime / PI / Stratum?

Thanks,

Antonin

> On Apr 18, 2018, at 10:22 AM, Dumitrescu, Cristian =
<cristian.dumitrescu@intel.com> wrote:
>=20
> P4 is a language for programming the data plane of network devices =
[1]. The P4
> language is developed by p4.org which is joining ONF and Linux =
Foundation [2].
>=20
> This API provides a way to program P4 capable devices through DPDK. =
The purpose
> of this API is to enable P4 compilers [3] to generate high performance =
DPDK code
> out of P4 programs.
>=20
> The main advantage of this approach is that P4 enablement of network =
devices can
> be done through DPDK in a unified way:
>=20
>   1. This API serves as the interface between the P4 compiler =
front-end (target
>      independent) and the P4 compiler backe-ends (target specific).
>=20
>   2. Device vendors develop their device drivers as part of DPDK by
>      implementing this API. The device driver is agostic of being =
called by the
>      P4 front-end. The device driver serves as the P4 compiler taget =
specific
>      back-end.
>=20
>   3. The P4 compiler front-end is target independent. The amount of C =
code it
>      generates is minimized by calling this API directly for every P4 =
feature
>      as opposed to vendor-specific free-style C code generation.
>=20
> This API introduces a pipeline device (PDEV) by using a similar =
approach to the
> existing ethdev and eventdev DPDK device-like APIs implemented by the =
DPDK Poll
> Mode Drivers (PMDs). Main features:
>=20
>   1. Discovery of built-in pipeline devices and their capabilities.
>=20
>   2. Creation of new pipelines out of input ports, output ports, =
tables and
>      actions.
>=20
>   3. Registration of packet protocol header and meta-data fields.
>=20
>   4. Action definition for input ports, output ports and tables.
>=20
>   5. Pipeline run-time API for table population, statistics read, etc.
>=20
> This API targets P4 capable devices such as NICs, FPGAs, NPUs, ASICs, =
etc, as
> well as CPUs. Let=E2=80=99s remember that the first P in P4 stands for =
Programmable, and
> the CPUs are arguably the most programmable devices. The =
implementation for the
> CPU SW target is expected to use the DPDK Packet Framework libraries =
such as
> librte_pipeline, librte_port, librte_table with some expected but =
moderate API
> and implementation adjustments.
>=20
> Links:
>=20
>   [1] P4-16 language specification:
>       https://p4lang.github.io/p4-spec/docs/P4-16-v1.0.0-spec.pdf
>=20
>   [2] p4.org to join ONF and LF: =
https://p4.org/p4/onward-and-upward.html
>=20
>   [3] p4c: https://github.com/p4lang/p4c
>=20
> Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
> ---
> lib/librte_pipeline/rte_pdev.h        | 1654 =
+++++++++++++++++++++++++++++++++
> lib/librte_pipeline/rte_pdev_driver.h |  283 ++++++
> 2 files changed, 1937 insertions(+)
> create mode 100644 lib/librte_pipeline/rte_pdev.h
> create mode 100644 lib/librte_pipeline/rte_pdev_driver.h
>=20
> diff --git a/lib/librte_pipeline/rte_pdev.h =
b/lib/librte_pipeline/rte_pdev.h
> new file mode 100644
> index 0000000..7095197
> --- /dev/null
> +++ b/lib/librte_pipeline/rte_pdev.h
> @@ -0,0 +1,1654 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2018 Intel Corporation
> + */
> +
> +#ifndef __INCLUDE_RTE_PDEV_H__
> +#define __INCLUDE_RTE_PDEV_H__
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/**
> + * @file
> + * RTE Pipeline Device (PDEV)
> + *
> + * @warning
> + * @b EXPERIMENTAL: this API may change without prior notice
> + */
> +
> +#include <stdint.h>
> +
> +#include <rte_common.h>
> +#include <rte_dev.h>
> +#include <rte_ether.h>
> +
> +/** PDEV device handle data type. */
> +struct rte_pdev;
> +
> +/**
> + * PDEV Capability API
> + */
> +
> +/** PDEV capabilities. */
> +struct rte_pdev_capabilities {
> +       /** Number of built-in pipelines.
> +        * @see rte_pdev_next_get()
> +        */
> +       uint32_t n_pipelines_builtin;
> +
> +       /** Non-zero when new pipelines can be created, zero =
otherwise.
> +        * @see rte_pdev_create()
> +        */
> +       int create;
> +};
> +
> +/**
> + * PDEV capabilities get
> + *
> + * @param[in] dev
> + *   Current device.
> + * @param[out] cap
> + *   PDEV capabilities. Must be non-NULL.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_capabilities_get(struct rte_device *dev,
> +       struct rte_pdev_capabilities *cap);
> +
> +/**
> + * PDEV Discovery API
> + *
> + */
> +
> +/**
> + * PDEV get next
> + *
> + * This API is used to discover pre-existent pipelines on given =
device. This is
> + * typically the case for built-in HW pipelines.
> + *
> + * @param[in] dev
> + *   Current device.
> + * @param[in] pdev
> + *   Handle to current PDEV on *dev*. Set to NULL during the first =
invocation
> + *   for *dev* device.
> + * @return
> + *   When non-NULL, handle to next PDEV, otherwise no more PDEV.
> + *
> + * @see struct rte_pdev_capabilities::n_pipelines_builtin
> + */
> +struct rte_pdev *
> +rte_pdev_next_get(struct rte_device *dev, struct rte_pdev *pdev);
> +
> +/**
> + * PDEV Create API
> + */
> +
> +/** PDEV statistics counter type. */
> +enum rte_pdev_stats_type {
> +       /** Number of packets. */
> +       RTE_PDEV_STATS_N_PKTS =3D 1 << 0,
> +
> +       /** Number of packet bytes. */
> +       RTE_PDEV_STATS_N_BYTES =3D 1 << 1,
> +};
> +
> +/** PDEV parameters. */
> +struct rte_pdev_params {
> +       /** PDEV name. */
> +       const char *name;
> +
> +       /** Statistics counters to be enabled.
> +        * @see enum rte_pdev_stats_type
> +        */
> +       uint64_t stats_mask;
> +};
> +
> +/**
> + * PDEV create
> + *
> + * This API is to be called to create new pipelines on given device. =
This is
> + * typically supported by reconfigurable HW devices and SW pipelines.
> + *
> + * @param[in] dev
> + *   Current device.
> + * @param[in] params
> + *   PDEV parameters. Must be non-NULL and valid.
> + * @return
> + *   When non-NULL, handle to created PDEV, otherwise error.
> + *
> + * @see struct rte_pdev_capabilities::create
> + */
> +struct rte_pdev *
> +rte_pdev_create(struct rte_device *dev,
> +       struct rte_pdev_params *params);
> +
> +/**
> + * PDEV free
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_free(struct rte_pdev *pdev);
> +
> +/**
> + * PDEV start
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_start(struct rte_pdev *pdev);
> +
> +/** PDEV input port types. */
> +enum rte_pdev_port_in_type {
> +       /** Builtin device. */
> +       RTE_PDEV_PORT_IN_BUILTIN =3D 0,
> +
> +       /** Ethernet device. */
> +       RTE_PDEV_PORT_IN_ETHDEV,
> +};
> +
> +/** PDEV input port parameters. */
> +struct rte_pdev_port_in_params {
> +       /** Type. */
> +       enum rte_pdev_port_in_type type;
> +
> +       /** Device specific parameters. */
> +       union {
> +               /** Builtin device. */
> +               struct {
> +                       /** Builtin device name. */
> +                       const char *name;
> +               } builtin;
> +
> +               /** Ethernet device. */
> +               struct {
> +                       /** Ethernet device name. */
> +                       const char *name;
> +
> +                       /** Reception side queue ID. */
> +                       uint32_t rx_queue_id;
> +
> +                       /** Burst size. */
> +                       uint32_t burst_size;
> +               } ethdev;
> +       } dev;
> +};
> +
> +/**
> + * PDEV input port create
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + * @params[in] port_id
> + *   PDEV input port ID. Must not be used by any existing *pdev* =
input port.
> + * @params[in] params
> + *   Input port parameters. Must be non-NULL and valid.
> + * @params[in] enable
> + *   When non-zero, the new input port is initially enabled, =
otherwise disabled.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_port_in_create(struct rte_pdev *pdev,
> +       uint32_t port_id,
> +       struct rte_pdev_port_in_params *params,
> +       int enable);
> +
> +/**
> + * PDEV input port connect to table
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + * @params[in] port_id
> + *   Input port ID.
> + * @params[in] table_id
> + *   Table ID.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_port_in_connect(struct rte_pdev *pdev,
> +       uint32_t port_id,
> +       uint32_t table_id);
> +
> +/** PDEV table match type. */
> +enum rte_pdev_table_match_type {
> +       /**  Wildcard match. */
> +       RTE_PDEV_TABLE_MATCH_WILDCARD =3D 0,
> +
> +       /** Exact match. */
> +       RTE_PDEV_TABLE_MATCH_EXACT,
> +
> +       /** Longest Prefix Match (LPM). */
> +       RTE_PDEV_TABLE_MATCH_LPM,
> +
> +       /** Index match. */
> +       RTE_PDEV_TABLE_MATCH_INDEX,
> +
> +       /** Stub match. No real match process: the default rule is =
always hit. */
> +       RTE_PDEV_TABLE_MATCH_STUB,
> +};
> +
> +/** PDEV table match parameters. */
> +struct rte_pdev_table_match_params {
> +       /** Packet field or packet meta-data field name at match =
offset 0. */
> +       const char *start;
> +
> +       /** Match size (in bits).
> +        *
> +        * For LPM match type, typical values are 32 bits to match a =
single IPv4
> +        * address and 128 bits to match a single IPv6 address, but =
other values
> +        * are possible, for example for Virtual Routing and =
Forwarding (VRF).
> +        *
> +        * For INDEX match type, the maximum allowed value is 32 bits.
> +        */
> +       uint32_t size;
> +
> +       /** Match mask (*size* bits are used and must be valid).
> +        *
> +        * For LPM match type, this parameter is ignored, as *size* =
implicitly
> +        * defines *mask* as *size* bits of 1.
> +        */
> +       uint8_t *mask;
> +};
> +
> +/** PDEV exact match table parameters. */
> +struct rte_pdev_table_exact_match_params {
> +       /** Number of hash table buckets. This parameter represents a =
hint that
> +        * the underlying implementation may ignore.
> +        */
> +       uint32_t n_buckets;
> +
> +       /** Hash table type. Non-zero for extendable bucket hash =
table, zero for
> +        * Least Recently Used (LRU) hash table.
> +        */
> +       int extendable_bucket;
> +};
> +
> +/** PDEV table parameters. */
> +struct rte_pdev_table_params {
> +       /** Match type. */
> +       enum rte_pdev_table_match_type match_type;
> +
> +       /** Match parameters. Ignored for STUB match type. */
> +       struct rte_pdev_table_match_params match;
> +
> +       /** Match type specific parameters. */
> +       RTE_STD_C11
> +       union {
> +               /** Exact match table specific parameters. */
> +               struct rte_pdev_table_exact_match_params exact;
> +       };
> +
> +       /** Maximum number of rules to be stored in the current table. =
*/
> +       uint32_t n_rules;
> +};
> +
> +/**
> + * PDEV table create
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + * @params[in] table_id
> + *   PDEV table ID. Must not be used by any existing *pdev* table.
> + * @params[in] params
> + *   Table parameters. Must be non-NULL and valid.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_table_create(struct rte_pdev *pdev,
> +       uint32_t table_id,
> +       struct rte_pdev_table_params *params);
> +
> +/** PDEV output port type. */
> +enum rte_pdev_port_out_type {
> +       /** Builtin device. */
> +       RTE_PDEV_PORT_OUT_BUILTIN =3D 0,
> +
> +       /** Ethernet device. */
> +       RTE_PDEV_PORT_OUT_ETHDEV,
> +
> +       /** Drop all packets device. */
> +       RTE_PDEV_PORT_OUT_DROP,
> +};
> +
> +/** PDEV output port parameters. */
> +struct rte_pdev_port_out_params {
> +       /** Type. */
> +       enum rte_pdev_port_out_type type;
> +
> +       /** Device specific parameters. */
> +       union {
> +               /** Builtin device. */
> +               struct {
> +                       /** Builtin device name. */
> +                       const char *name;
> +               } builtin;
> +
> +               /** Ethernet device. */
> +               struct {
> +                       /** Ethernet device name. */
> +                       const char *name;
> +
> +                       /** Transmission side queue ID. */
> +                       uint32_t tx_queue_id;
> +
> +                       /** Burst size. */
> +                       uint32_t burst_size;
> +               } ethdev;
> +       } dev;
> +};
> +
> +/**
> + * PDEV output port create
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + * @params[in] port_id
> + *   PDEV output port ID. Must not be used by any existing *pdev* =
output port.
> + * @params[in] params
> + *   Output port parameters. Must be non-NULL and valid.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_port_out_create(struct rte_pdev *pdev,
> +       uint32_t port_id,
> +       struct rte_pdev_port_out_params *params);
> +
> +/**
> + * PDEV meta-data definition API
> + */
> +
> +/**
> + * PDEV packet field registration.
> + *
> + * Create symbolic alias for a protocol header or header field in the =
input
> + * packet. This alias can then be used as part of assignment actions =
registered
> + * for PDEV input ports, tables or output ports, either as left hand =
side value
> + * or as one of the right hand side expression operands, as =
appropriate. The
> + * packet field registered with the name of "x" is used as "pkt.x".
> + *
> + * This alias is typically translated to its offset and size, which =
are then
> + * used during the execution of assignment actions to access the =
associated data
> + * bytes within the packet.
> + *
> + * The scope of the packet field aliases is the PDEV instance. The =
attributes
> + * such as offset or size cannot be changed after the alias =
registration. This
> + * approach assumes the input packet type is known in advance, as =
opposed to
> + * having each input packet parsed to detect its type. This is a =
reasonable
> + * assumption, given that NIC capabilities to filter each packet type =
to a
> + * different RX queue are quite common; the NIC is configured =
transparently to
> + * the PDEV, with each NIC RX queue mapped as different PDEV input =
port.
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + * @params[in] name
> + *   Symbolic alias for the input packet header or header field.
> + * @params[in] offset
> + *   Byte offset within the input packet. Offset 0 points to the =
first byte of
> + *   the packet.
> + * @params[in] size
> + *   Field size (in bytes).
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_pkt_field_register(struct rte_pdev *pdev,
> +       const char *name,
> +       uint32_t offset,
> +       uint32_t size);
> +
> +/**
> + * PDEV packet meta-data field registration.
> + *
> + * Reserve field into the packet meta-data and assign a symbolic =
alias to it.
> + * This alias can then be used as part of assignment actions =
registered for PDEV
> + * input ports, tables and output ports, either as left hand side =
value or as
> + * one of the right hand side expression operands, as appropriate. =
The packet
> + * meta-data field registered with the name of "x" is used as =
"meta.x".
> + *
> + * Each input packet has its own private memory area reserved to =
store its
> + * meta-data, which is valid for the lifetime of the packet within =
the PDEV.
> + * This alias is typically translated to its offset and size, which =
are then
> + * used during the execution of assignment actions to access the =
associated
> + * packet meta-data bytes.
> + *
> + * The scope of the packet meta-data field aliases is the PDEV =
instance,
> + * therefore the meta-data layout is commmon for all the PDEV input =
packets.
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + * @params[in] name
> + *   Symbolic alias for the packet meta-data field.
> + * @params[in] size
> + *   Field size (in bytes).
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_pkt_meta_field_register(struct rte_pdev *pdev,
> +       const char *name,
> +       uint32_t size);
> +
> +/**
> + * PDEV table rule data field registration.
> + *
> + * Reserve field into the table rule data and assign a symbolic alias =
to it.
> + * This alias can then be used as part of assignment actions =
registered for PDEV
> + * tables, either as left hand side value or as one of the right hand =
side
> + * expression operands, as appropriate. The table rule data field =
registered
> + * with the name of "x" is used as "table.x".
> + *
> + * This alias is typically translated to its offset and size, which =
are then
> + * used during the execution of assignment actions to access the =
associated
> + * table rule data bytes.
> + *
> + * The table rule data layout is common for all the rules of a given =
table that
> + * share the same action profile, therefore the scope of the table =
rule data
> + * field alias is its (table, action profile) pair.
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + * @params[in] table_id
> + *   PDEV table ID.
> + * @params[in] action_profile_id
> + *   Table action profile ID.
> + * @params[in] name
> + *   Symbolic alias for the table rule data field.
> + * @params[in] size
> + *   Field size (in bytes).
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_table_field_register(struct rte_pdev *pdev,
> +       uint32_t table_id,
> +       uint32_t action_profile_id,
> +       const char *name,
> +       uint32_t size);
> +
> +/**
> + * PDEV input port action API
> + */
> +enum rte_pdev_port_in_action_type {
> +       /** Assignment: lvalue =3D expression. */
> +       RTE_PDEV_PORT_IN_ACTION_ASSIGN =3D 0,
> +};
> +
> +/**
> + * RTE_PDEV_PORT_IN_ACTION_ASSIGN
> + */
> +struct rte_pdev_port_in_action_assign_config {
> +       /** Left hand side value for the assignment. Must be one of =
the
> +        * pre-registered packet meta-data field symbolic aliases. =
Packet field
> +        * and table rule data field symbolic aliases are not allowed.
> +        */
> +       const char *lvalue;
> +
> +       /** Expression with operands and operators. The operands must =
be
> +        * pre-registered packet or packet meta-data field symbolic =
aliases.
> +        * Table rule data field aliases are not allowed.
> +        */
> +       const char *expression;
> +};
> +
> +/**
> + * PDEV input port action profile create
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + * @params[in] profile_id
> + *   Input port action profile ID. Must not be used by any existing =
*pdev* input
> + *   port action profile.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_port_in_action_profile_create(struct rte_pdev *pdev,
> +       uint32_t profile_id);
> +
> +/**
> + * PDEV input port action profile action register
> + *
> + * The action registration order is important, as it determines the =
action
> + * execution order. The same action type can be registered several =
times for the
> + * same profile.
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + * @params[in] profile_id
> + *   Input port action profile ID.
> + * @params[in] action_type
> + *   Input port action type.
> + * @params[in] action_config
> + *   Input port action configuration. For input port action X, this =
parameter
> + *   needs to point to pre-allocated and valid instance of struct
> + *   rte_pdev_port_in_action_X_config.
> + *   Input port action configuration. For input port action X, this =
parameter
> + *   must point to valid instance of struct =
rte_pdev_port_in_action_X_config
> + *   when this structure is defined by the API or to NULL otherwise.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_port_in_action_profile_action_register(struct rte_pdev =
*pdev,
> +       uint32_t profile_id,
> +       enum rte_pdev_port_in_action_type action_type,
> +       void *action_config);
> +
> +/**
> + * PDEV input port action profile freeze
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + * @params[in] profile_id
> + *   Input port action profile ID.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_port_in_action_profile_freeze(struct rte_pdev *pdev,
> +       uint32_t profile_id);
> +
> +/**
> + * PDEV input port action profile register
> + *
> + * Zero or at most one action profile can be registered for each =
input port.
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + * @params[in] port_id
> + *   PDEV input port ID.
> + * @params[in] profile_id
> + *   Input port action profile ID.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_port_in_action_profile_register(struct rte_pdev *pdev,
> +       uint32_t port_id,
> +       uint32_t profile_id);
> +
> +/**
> + * PDEV table action API
> + *
> + * For some actions below (e.g. packet encapsulations, NAT, =
statistics, etc),
> + * the same effect can be obtained through a sequence of assignment =
actions, but
> + * usually this approach is significantly less performant than using =
specialized
> + * actions.
> + *
> + * Some of the actions below (e.g. metering, timestamp update, etc) =
require the
> + * definition of specialized actions.
> + */
> +enum rte_pdev_table_action_type {
> +       /** Assignment: lvalue =3D expression. */
> +       RTE_PDEV_TABLE_ACTION_ASSIGN =3D 0,
> +
> +       /** Load balancing. */
> +       RTE_PDEV_TABLE_ACTION_LB,
> +
> +       /** Traffic metering and policing. */
> +       RTE_PDEV_TABLE_ACTION_METER,
> +
> +       /** Packet encapsulation. */
> +       RTE_PDEV_TABLE_ACTION_ENCAP,
> +
> +       /** Network Address Translation (NAT). */
> +       RTE_PDEV_TABLE_ACTION_NAT,
> +
> +       /** Time to Leave (TTL) update. */
> +       RTE_PDEV_TABLE_ACTION_TTL,
> +
> +       /** Statistics per table rule. */
> +       RTE_PDEV_TABLE_ACTION_STATS,
> +
> +       /** Time stamp update. */
> +       RTE_PDEV_TABLE_ACTION_TIME,
> +};
> +
> +/**
> + * RTE_PDEV_TABLE_ACTION_ASSIGN
> + */
> +struct rte_pdev_table_action_assign_config {
> +       /** Left hand side value for the assignment. Must be one of =
the
> +        * pre-registered packet, packet meta-data or table field =
symbolic
> +        * aliases.
> +        */
> +       const char *lvalue;
> +
> +       /** Expression with operands and operators. The operands must =
be
> +        * pre-registered packet, packet meta-data or table field =
symbolic
> +        * aliases.
> +        */
> +       const char *expression;
> +};
> +
> +/**
> + * RTE_PDEV_TABLE_ACTION_LB
> + */
> +/** Load balance action configuration (per table action profile). */
> +struct rte_pdev_table_action_lb_config {
> +       /** Hash key parameters. */
> +       struct rte_pdev_table_match_params hash_key;
> +
> +       /** Hash function name. This parameter represents a hint that =
the
> +        * underlying implementation may ignore.
> +        */
> +       const char *hash_func;
> +
> +       /** Hash function seed value. This parameter represents a hint =
that the
> +        * underlying implementation may ignore.
> +        */
> +       uint64_t hash_seed;
> +
> +       /** Number of elements in the table storing the output values. =
*/
> +       uint32_t table_size;
> +
> +       /** Packet meta-data field name where the output value should =
be saved. */
> +       const char *out;
> +};
> +
> +/** Load balance action parameters (per table rule). */
> +struct rte_pdev_table_action_lb_params {
> +       /** Table defining the output values and their weights. Needs =
to be
> +        * pre-allocated with exactly *table_size* elements. The =
weights are set
> +        * in 1 / *table_size* increments. To assign a weight of N / =
*table_size*
> +        * to a given output value (0 <=3D N <=3D *table_size*), the =
same output
> +        * value needs to show up exactly N times in this table.
> +        */
> +       uint32_t *table;
> +};
> +
> +/**
> + * RTE_PDEV_TABLE_ACTION_MTR
> + */
> +/** Packet color. */
> +enum rte_pdev_meter_color {
> +       RTE_PDEV_METER_COLOR_GREEN =3D 0, /**< Green. */
> +       RTE_PDEV_METER_COLOR_YELLOW, /**< Yellow. */
> +       RTE_PDEV_METER_COLOR_RED, /**< Red. */
> +       RTE_PDEV_METER_COLORS /**< Number of colors. */
> +};
> +
> +/** Differentiated Services Code Point (DSCP) translation table =
entry. */
> +struct rte_pdev_dscp_table_entry {
> +       /** Traffic class ID. Has to be strictly less than *n_tc*. */
> +       uint32_t tc_id;
> +
> +       /** Packet input color. Used by the traffic metering algorithm =
in
> +        * color aware mode.
> +        */
> +       enum rte_pdev_meter_color color;
> +};
> +
> +/** DSCP translation table. */
> +struct rte_pdev_dscp_table {
> +       /** Array of DSCP table entries */
> +       struct rte_pdev_dscp_table_entry entry[64];
> +};
> +
> +/** Supported traffic metering algorithms. */
> +enum rte_pdev_meter_algorithm {
> +       /** Single Rate Three Color Marker (srTCM) - IETF RFC 2697. */
> +       RTE_PDEV_METER_SRTCM_RFC2697,
> +
> +       /** Two Rate Three Color Marker (trTCM) - IETF RFC 2698. */
> +       RTE_PDEV_METER_TRTCM_RFC2698,
> +
> +       /** Two Rate Three Color Marker (trTCM) - IETF RFC 4115. */
> +       RTE_PDEV_METER_TRTCM_RFC4115,
> +};
> +
> +/** Traffic metering profile (configuration template). */
> +struct rte_pdev_meter_profile {
> +       /** Traffic metering algorithm. */
> +       enum rte_pdev_meter_algorithm alg;
> +
> +       RTE_STD_C11
> +       union {
> +               /** Items only valid when *alg* is set to srTCM - RFC =
2697. */
> +               struct {
> +                       /** Committed Information Rate (CIR) =
(bytes/second). */
> +                       uint64_t cir;
> +
> +                       /** Committed Burst Size (CBS) (bytes). */
> +                       uint64_t cbs;
> +
> +                       /** Excess Burst Size (EBS) (bytes). */
> +                       uint64_t ebs;
> +               } srtcm_rfc2697;
> +
> +               /** Items only valid when *alg* is set to trTCM - RFC =
2698. */
> +               struct {
> +                       /** Committed Information Rate (CIR) =
(bytes/second). */
> +                       uint64_t cir;
> +
> +                       /** Peak Information Rate (PIR) =
(bytes/second). */
> +                       uint64_t pir;
> +
> +                       /** Committed Burst Size (CBS) (byes). */
> +                       uint64_t cbs;
> +
> +                       /** Peak Burst Size (PBS) (bytes). */
> +                       uint64_t pbs;
> +               } trtcm_rfc2698;
> +
> +               /** Items only valid when *alg* is set to trTCM - RFC =
4115. */
> +               struct {
> +                       /** Committed Information Rate (CIR) =
(bytes/second). */
> +                       uint64_t cir;
> +
> +                       /** Excess Information Rate (EIR) =
(bytes/second). */
> +                       uint64_t eir;
> +
> +                       /** Committed Burst Size (CBS) (byes). */
> +                       uint64_t cbs;
> +
> +                       /** Excess Burst Size (EBS) (bytes). */
> +                       uint64_t ebs;
> +               } trtcm_rfc4115;
> +       };
> +};
> +
> +/** Policer actions. */
> +enum rte_pdev_policer {
> +       /** Recolor the packet as green. */
> +       RTE_PDEV_POLICER_COLOR_GREEN =3D 0,
> +
> +       /** Recolor the packet as yellow. */
> +       RTE_PDEV_POLICER_COLOR_YELLOW,
> +
> +       /** Recolor the packet as red. */
> +       RTE_PDEV_POLICER_COLOR_RED,
> +
> +       /** Drop the packet. */
> +       RTE_PDEV_POLICER_DROP,
> +};
> +
> +/** Meter action configuration per traffic class. */
> +struct rte_pdev_table_action_mtr_tc_params {
> +       /** Meter profile ID. */
> +       uint32_t meter_profile_id;
> +
> +       /** Policer actions. */
> +       enum rte_pdev_policer policer[RTE_PDEV_METER_COLORS];
> +};
> +
> +/** Meter action statistics counters per traffic class. */
> +struct rte_pdev_table_action_mtr_tc_counters {
> +       /** Number of packets per color at the output of the traffic =
metering
> +        * and before the policer actions are executed. Only valid =
when
> +        * *n_packets_valid* is non-zero.
> +        */
> +       uint64_t n_packets[RTE_PDEV_METER_COLORS];
> +
> +       /** Number of packet bytes per color at the output of the =
traffic
> +        * metering and before the policer actions are executed. Only =
valid when
> +        * *n_bytes_valid* is non-zero.
> +        */
> +       uint64_t n_bytes[RTE_PDEV_METER_COLORS];
> +
> +       /** When non-zero, the *n_packets* field is valid. */
> +       int n_packets_valid;
> +
> +       /** When non-zero, the *n_bytes* field is valid. */
> +       int n_bytes_valid;
> +};
> +
> +/** Meter action configuration (per table action profile). */
> +struct rte_pdev_table_action_mtr_config {
> +       /** Packet field for IP header. */
> +       const char *ip;
> +
> +       /** IP protocol version. Non-zero for IPv4, zero for IPv6. */
> +       int ip_version;
> +
> +       /** DSCP translation table. */
> +       struct rte_pdev_dscp_table *dscp_table;
> +
> +       /** Number of traffic classes. Each traffic class has its own =
traffic
> +        * meter and policer instances.
> +        */
> +       uint32_t n_tc;
> +
> +       /** Meter algorithm. */
> +       enum rte_pdev_meter_algorithm alg;
> +
> +       /** When non-zero, the *n_packets* meter stats counter is =
enabled,
> +        * otherwise it is disabled.
> +        *
> +        * @see struct rte_pdev_table_action_mtr_tc_counters
> +        */
> +       int n_packets_enabled;
> +
> +       /** When non-zero, the *n_bytes* meter stats counter is =
enabled,
> +        * otherwise it is disabled.
> +        *
> +        * @see struct rte_pdev_table_action_mtr_tc_counters
> +        */
> +       int n_bytes_enabled;
> +};
> +
> +/** Meter action parameters (per table rule). */
> +struct rte_pdev_table_action_mtr_params {
> +       /** Traffic meter and policer parameters for all traffic =
classes. Array
> +        * of *n_tc* elements.
> +        */
> +       struct rte_pdev_table_action_mtr_tc_params *mtr;
> +};
> +
> +/** Meter action statistics counters (per table rule). */
> +struct rte_pdev_table_action_mtr_counters {
> +       /** Stats counters for all traffic classes. Array of *n_tc* =
elements. */
> +       struct rte_pdev_table_action_mtr_tc_counters *stats;
> +};
> +
> +/**
> + * RTE_PDEV_TABLE_ACTION_ENCAP
> + */
> +/** Supported packet encapsulation types. */
> +enum rte_pdev_encap_type {
> +       /** IP -> { Ether | IP } */
> +       RTE_PDEV_ENCAP_ETHER =3D 0,
> +
> +       /** IP -> { Ether | VLAN | IP } */
> +       RTE_PDEV_ENCAP_VLAN,
> +
> +       /** IP -> { Ether | S-VLAN | C-VLAN | IP } */
> +       RTE_PDEV_ENCAP_QINQ,
> +
> +       /** IP -> { Ether | MPLS | IP } */
> +       RTE_PDEV_ENCAP_MPLS,
> +
> +       /** IP -> { Ether | PPPoE | PPP | IP } */
> +       RTE_PDEV_ENCAP_PPPOE,
> +};
> +
> +/** Pre-computed Ethernet header fields for encapsulation action. */
> +struct rte_pdev_ether_hdr {
> +       struct ether_addr da; /**< Destination address. */
> +       struct ether_addr sa; /**< Source address. */
> +};
> +
> +/** Pre-computed VLAN header fields for encapsulation action. */
> +struct rte_pdev_vlan_hdr {
> +       uint8_t pcp; /**< Priority Code Point (PCP). */
> +       uint8_t dei; /**< Drop Eligibility Indicator (DEI). */
> +       uint16_t vid; /**< VLAN Identifier (VID). */
> +};
> +
> +/** Pre-computed MPLS header fields for encapsulation action. */
> +struct rte_pdev_mpls_hdr {
> +       uint32_t label; /**< Label. */
> +       uint8_t tc; /**< Traffic Class (TC). */
> +       uint8_t ttl; /**< Time to Live (TTL). */
> +};
> +
> +/** Pre-computed PPPoE header fields for encapsulation action. */
> +struct rte_pdev_pppoe_hdr {
> +       uint16_t session_id; /**< Session ID. */
> +};
> +
> +/** Ether encap parameters. */
> +struct rte_pdev_encap_ether_params {
> +       struct rte_pdev_ether_hdr ether; /**< Ethernet header. */
> +};
> +
> +/** VLAN encap parameters. */
> +struct rte_pdev_encap_vlan_params {
> +       struct rte_pdev_ether_hdr ether; /**< Ethernet header. */
> +       struct rte_pdev_vlan_hdr vlan; /**< VLAN header. */
> +};
> +
> +/** QinQ encap parameters. */
> +struct rte_pdev_encap_qinq_params {
> +       struct rte_pdev_ether_hdr ether; /**< Ethernet header. */
> +       struct rte_pdev_vlan_hdr svlan; /**< Service VLAN header. */
> +       struct rte_pdev_vlan_hdr cvlan; /**< Customer VLAN header. */
> +};
> +
> +/** Max number of MPLS labels per output packet for MPLS =
encapsulation. */
> +#ifndef RTE_PDEV_MPLS_LABELS_MAX
> +#define RTE_PDEV_MPLS_LABELS_MAX                            4
> +#endif
> +
> +/** MPLS encap parameters. */
> +struct rte_pdev_encap_mpls_params {
> +       /** Ethernet header. */
> +       struct rte_pdev_ether_hdr ether;
> +
> +       /** MPLS header. */
> +       struct rte_pdev_mpls_hdr mpls[RTE_PDEV_MPLS_LABELS_MAX];
> +
> +       /** Number of MPLS labels in MPLS header. */
> +       uint32_t mpls_count;
> +
> +       /** Non-zero for MPLS unicast, zero for MPLS multicast. */
> +       int unicast;
> +};
> +
> +/** PPPoE encap parameters. */
> +struct rte_pdev_encap_pppoe_params {
> +       struct rte_pdev_ether_hdr ether; /**< Ethernet header. */
> +       struct rte_pdev_pppoe_hdr pppoe; /**< PPPoE/PPP headers. */
> +};
> +
> +/** Encap action configuration (per table action profile). */
> +struct rte_pdev_table_action_encap_config {
> +       /** Packet field for IP header. */
> +       const char *ip;
> +
> +       /** IP protocol version. Non-zero for IPv4, zero for IPv6. */
> +       int ip_version;
> +
> +       /** Bit mask defining the set of packet encapsulations enabled =
for the
> +        * current table action profile. If bit (1 << N) is set in =
*encap_mask*,
> +        * then packet encapsulation N is enabled, otherwise it is =
disabled.
> +        *
> +        * @see enum rte_pdev_encap_type
> +        */
> +       uint64_t encap_mask;
> +};
> +
> +/** Encap action parameters (per table rule). */
> +struct rte_pdev_table_action_encap_params {
> +       /** Encapsulation type. */
> +       enum rte_pdev_encap_type type;
> +
> +       RTE_STD_C11
> +       union {
> +               /** Only valid when *type* is set to Ether. */
> +               struct rte_pdev_encap_ether_params ether;
> +
> +               /** Only valid when *type* is set to VLAN. */
> +               struct rte_pdev_encap_vlan_params vlan;
> +
> +               /** Only valid when *type* is set to QinQ. */
> +               struct rte_pdev_encap_qinq_params qinq;
> +
> +               /** Only valid when *type* is set to MPLS. */
> +               struct rte_pdev_encap_mpls_params mpls;
> +
> +               /** Only valid when *type* is set to PPPoE. */
> +               struct rte_pdev_encap_pppoe_params pppoe;
> +       };
> +};
> +
> +/**
> + * RTE_PDEV_TABLE_ACTION_NAT
> + */
> +/** NAT action configuration (per table action profile). */
> +struct rte_pdev_table_action_nat_config {
> +       /** Packet field for IP header. */
> +       const char *ip;
> +
> +       /** IP protocol version. Non-zero for IPv4, zero for IPv6. */
> +       int ip_version;
> +
> +       /** When non-zero, the IP source address and L4 protocol =
source port are
> +        * translated. When zero, the IP destination address and L4 =
protocol
> +        * destination port are translated.
> +        */
> +       int source_nat;
> +
> +       /** Layer 4 protocol, for example TCP (0x06) or UDP (0x11). =
The checksum
> +        * field is computed differently and placed at different =
header offset
> +        * by each layer 4 protocol.
> +        */
> +       uint8_t proto;
> +};
> +
> +/** NAT action parameters (per table rule). */
> +struct rte_pdev_table_action_nat_params {
> +       /** IP version for *addr*: non-zero for IPv4, zero for IPv6. =
*/
> +       int ip_version;
> +
> +       /** IP address. */
> +       union {
> +               /** IPv4 address; only valid when *ip_version* is =
IPv4. */
> +               uint32_t ipv4;
> +
> +               /** IPv6 address; only valid when *ip_version* is =
IPv6. */
> +               uint8_t ipv6[16];
> +       } addr;
> +
> +       /** Port. */
> +       uint16_t port;
> +};
> +
> +/**
> + * RTE_PDEV_TABLE_ACTION_TTL
> + */
> +/** TTL action configuration (per table action profile). */
> +struct rte_pdev_table_action_ttl_config {
> +       /** Packet field for IP header. */
> +       const char *ip;
> +
> +       /** IP protocol version. Non-zero for IPv4, zero for IPv6. */
> +       int ip_version;
> +
> +       /** Packet meta-data field to be set to *port_out_id* when the =
updated
> +        * IPv4 Time to Live (TTL) field or IPv6 Hop Limit (HL) field =
is zero.
> +        */
> +       const char *port_out;
> +
> +       /** Output port ID to be stored into *port_out* packet =
meta-data field
> +        * when the updated IPv4 TTL field or IPv6 HL field is zero.
> +        */
> +       uint32_t port_out_id;
> +
> +       /** When non-zero, the *n_packets* stats counter for TTL =
action is
> +        * enabled, otherwise disabled.
> +        *
> +        * @see struct rte_pdev_table_action_ttl_counters
> +        */
> +       int n_packets_enabled;
> +};
> +
> +/** TTL action parameters (per table rule). */
> +struct rte_pdev_table_action_ttl_params {
> +       /** When non-zero, decrement the IPv4 TTL field and update the =
checksum
> +        * field, or decrement the IPv6 HL field. When zero, the IPv4 =
TTL field
> +        * or the IPv6 HL field is not changed.
> +        */
> +       int decrement;
> +};
> +
> +/** TTL action statistics packets (per table rule). */
> +struct rte_pdev_table_action_ttl_counters {
> +       /** Number of IPv4 packets whose updated TTL field is zero or =
IPv6
> +        * packets whose updated HL field is zero.
> +        */
> +       uint64_t n_packets;
> +};
> +
> +/**
> + * RTE_PDEV_TABLE_ACTION_STATS
> + */
> +/** Stats action configuration (per table action profile). */
> +struct rte_pdev_table_action_stats_config {
> +       /** Packet field for IP header. */
> +       const char *ip;
> +
> +       /** IP protocol version. Non-zero for IPv4, zero for IPv6. */
> +       int ip_version;
> +
> +       /** When non-zero, the *n_packets* stats counter is enabled, =
otherwise
> +        * disabled.
> +        *
> +        * @see struct rte_pdev_table_action_stats_counters
> +        */
> +       int n_packets_enabled;
> +
> +       /** When non-zero, the *n_bytes* stats counter is enabled, =
otherwise
> +        * disabled.
> +        *
> +        * @see struct rte_pdev_table_action_stats_counters
> +        */
> +       int n_bytes_enabled;
> +};
> +
> +/** Stats action parameters (per table rule). */
> +struct rte_pdev_table_action_stats_params {
> +       /** Initial value for the *n_packets* stats counter. Typically =
set to 0.
> +        *
> +        * @see struct rte_pdev_table_action_stats_counters
> +        */
> +       uint64_t n_packets;
> +
> +       /** Initial value for the *n_bytes* stats counter. Typically =
set to 0.
> +        *
> +        * @see struct rte_pdev_table_action_stats_counters
> +        */
> +       uint64_t n_bytes;
> +};
> +
> +/** Stats action counters (per table rule). */
> +struct rte_pdev_table_action_stats_counters {
> +       /** Number of packets. Valid only when *n_packets_valid* is =
non-zero. */
> +       uint64_t n_packets;
> +
> +       /** Number of bytes. Valid only when *n_bytes_valid* is =
non-zero. */
> +       uint64_t n_bytes;
> +
> +       /** When non-zero, the *n_packets* field is valid, otherwise =
invalid. */
> +       int n_packets_valid;
> +
> +       /** When non-zero, the *n_bytes* field is valid, otherwise =
invalid. */
> +       int n_bytes_valid;
> +};
> +
> +/**
> + * RTE_PDEV_TABLE_ACTION_TIME
> + */
> +/** Timestamp action parameters (per table rule). */
> +struct rte_pdev_table_action_time_params {
> +       /** Initial timestamp value. Typically set to current time. */
> +       uint64_t time;
> +};
> +
> +/**
> + * PDEV table action profile create
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + * @params[in] profile_id
> + *   Table action profile ID. Must not be used by any existing *pdev* =
table
> + *   action profile.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_table_action_profile_create(struct rte_pdev *pdev,
> +       uint32_t profile_id);
> +
> +/**
> + * PDEV table action profile action register
> + *
> + * The action registration order is important, as it determines the =
action
> + * execution order. The same action type can be registered several =
times for the
> + * same profile.
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + * @params[in] profile_id
> + *   Table action profile ID.
> + * @params[in] action_type
> + *   Table action type.
> + * @params[in] action_config
> + *   Table action configuration. For table action X, this parameter =
must point
> + *   to valid instance of struct rte_pdev_table_action_X_config when =
this
> + *   structure is defined by the API or to NULL otherwise.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_table_action_profile_action_register(struct rte_pdev *pdev,
> +       uint32_t profile_id,
> +       enum rte_pdev_table_action_type action_type,
> +       void *action_config);
> +
> +/**
> + * PDEV table action profile freeze
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + * @params[in] profile_id
> + *   Table action profile ID.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_table_action_profile_freeze(struct rte_pdev *pdev,
> +       uint32_t profile_id);
> +
> +/**
> + * PDEV table action profile register
> + *
> + * Zero or several action profiles can be registered for each table.
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + * @params[in] table_id
> + *   PDEV table ID.
> + * @params[in] profile_id
> + *   Table action profile ID.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_table_action_profile_register(struct rte_pdev *pdev,
> +       uint32_t table_id,
> +       uint32_t profile_id);
> +
> +/**
> + * PDEV output port action API
> + */
> +enum rte_pdev_port_out_action_type {
> +       /** Assignment: lvalue =3D expression. */
> +       RTE_PDEV_PORT_OUT_ACTION_ASSIGN =3D 0,
> +};
> +
> +/**
> + * RTE_PDEV_PORT_OUT_ACTION_ASSIGN
> + */
> +struct rte_pdev_port_out_action_assign_config {
> +       /** Left hand side value for the assignment. Must be one of =
the
> +        * pre-registered packet field symbolic aliases. Packet =
meta-data field
> +        * and table rule data field aliases are not allowed.
> +        */
> +       const char *lvalue;
> +
> +       /** Expression with operands and operators. The operands must =
be
> +        * pre-registered packet or packet meta-data field symbolic =
aliases.
> +        * Table rule data field aliases are not allowed.
> +        */
> +       const char *expression;
> +};
> +
> +/**
> + * PDEV output port action profile create
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + * @params[in] profile_id
> + *   Output port action profile ID. Must not be used by any existing =
*pdev*
> + *   output port action profile.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_port_out_action_profile_create(struct rte_pdev *pdev,
> +       uint32_t profile_id);
> +
> +/**
> + * PDEV output port action profile action register
> + *
> + * The action registration order is important, as it determines the =
action
> + * execution order. The same action type can be registered several =
times for the
> + * same profile.
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + * @params[in] profile_id
> + *   Output port action profile ID.
> + * @params[in] action_type
> + *   Output port action type.
> + * @params[in] action_config
> + *   Output port action configuration. For output port action X, this =
parameter
> + *   must point to valid instance of struct =
rte_pdev_port_out_action_X_config
> + *   when this structure is defined by the API or to NULL otherwise.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_port_out_action_profile_action_register(struct rte_pdev =
*pdev,
> +       uint32_t profile_id,
> +       enum rte_pdev_port_out_action_type action_type,
> +       void *action_config);
> +
> +/**
> + * PDEV output port action profile freeze
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + * @params[in] profile_id
> + *   Output port action profile ID.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_port_out_action_profile_freeze(struct rte_pdev *pdev,
> +       uint32_t profile_id);
> +
> +/**
> + * PDEV output port action profile register
> + *
> + * Zero or at most one action profile can be registered for each =
output port.
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + * @params[in] port_id
> + *   PDEV output port ID.
> + * @params[in] profile_id
> + *   Output port action profile ID.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_port_out_action_profile_register(struct rte_pdev *pdev,
> +       uint32_t table_id,
> +       uint32_t profile_id);
> +
> +/**
> + * PDEV input port run-time API
> + */
> +
> +/**
> + * PDEV input port enable
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + * @params[in] port_id
> + *   PDEV input port ID.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_port_in_enable(struct rte_pdev *pdev,
> +       uint32_t port_id);
> +
> +/**
> + * PDEV input port disable
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + * @params[in] port_id
> + *   PDEV input port ID.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_port_in_disable(struct rte_pdev *pdev,
> +       uint32_t port_id);
> +
> +/** PDEV input port statistics counters. */
> +struct rte_pdev_port_in_stats {
> +       /** Number of packets read from this input port. */
> +       uint64_t n_packets;
> +
> +       /** Number of bytes associated with *n_packets*. */
> +       uint64_t n_bytes;
> +};
> +
> +/**
> + * PDEV input port statistics counters read
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + * @params[in] port_id
> + *   PDEV input port ID.
> + * @params[out] stats
> + *   When non-NULL, the statistics counters are read and saved here.
> + * @params[in] clear
> + *   When non-zero, the statistics counters are cleared after read, =
otherwise
> + *   they are not modified.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_port_in_stats_read(struct rte_pdev *pdev,
> +       uint32_t port_id,
> +       struct rte_pdev_port_in_stats *stats,
> +       int clear);
> +
> +/**
> + * PDEV table run-time API
> + */
> +
> +/**
> + * PDEV table rule add.
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + * @param[in] table_id
> + *   PDEV table ID.
> + * @param[in] match
> + *   Rule match. For any match type, the NULL value indicates the =
default rule.
> + * @param[in] match_mask
> + *   Rule match bit-mask. Ignored when *match* is set to NULL. =
Ignored when
> + *   *table_id* match type is not WILDCARD or LPM.
> + * @param[in] match_priority
> + *   Rule match priority. Ignored when *match* is set to NULL. =
Ignored when
> + *   *table_id* match type is not WILDCARD.
> + * @param[in] action_profile_id
> + *   Table action profile ID.
> + * @param[in] action_params
> + *   Array of action parameters. The number of elements must be equal =
to the
> + *   number of actions registered for the *action_profile_id* table =
action
> + *   profile. If X is the N-th action registered for =
*action_profile_id*, then
> + *   the N-th element of this array needs to be pointer to valid =
instance of
> + *   struct rte_pdev_table_action_X_params when defined by the API or =
to NULL
> + *   otherwise.
> + * @param[out] rule_handle
> + *   Rule handle.
> + * @return
> + *   Zero on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_table_rule_add(struct rte_pdev *pdev,
> +       uint32_t table_id,
> +       uint8_t *match,
> +       uint8_t *match_mask,
> +       uint32_t match_priority,
> +       uint32_t action_profile_id,
> +       void **action_params,
> +       void **rule_handle);
> +
> +/**
> + * PDEV table rule delete.
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + * @param[in] table_id
> + *   PDEV table ID.
> + * @param[in] match
> + *   Rule match. For any match type, the NULL value indicates the =
default rule.
> + * @param[in] match_mask
> + *   Rule match bit-mask. Ignored when *match* is set to NULL. =
Ignored when
> + *   *table_id* match type is not WILDCARD or LPM.
> +  * @return
> + *   Zero on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_table_rule_delete(struct rte_pdev *pdev,
> +       uint32_t table_id,
> +       uint8_t *match,
> +       uint8_t *match_mask);
> +
> +/**
> + * PDEV table DSCP table update.
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + * @param[in] table_id
> + *   PDEV table ID.
> + * @param[in] dscp_table
> + *   DSCP table. Must be pre-allocated and valid.
> + * @return
> + *   Zero on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_table_dscp_table_update(struct rte_pdev *pdev,
> +       uint32_t table_id,
> +       struct rte_pdev_dscp_table *dscp_table);
> +
> +/**
> + * PDEV table meter profile add.
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + * @param[in] table_id
> + *   PDEV table ID.
> + * @param[in] meter_profile_id
> + *   Meter profile ID. Must not be used by any existing *table_id* =
meter
> + *   profile.
> + * @param[in] profile
> + *   Meter profile parameters.
> + * @return
> + *   Zero on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_table_meter_profile_add(struct rte_pdev *pdev,
> +       uint32_t table_id,
> +       uint32_t meter_profile_id,
> +       struct rte_pdev_meter_profile *profile);
> +
> +/**
> + * PDEV table meter profile delete.
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + * @param[in] table_id
> + *   PDEV table ID.
> + * @param[in] meter_profile_id
> + *   Meter profile ID. Must be one of the existing *table_id* meter =
profiles.
> + * @return
> + *   Zero on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_table_meter_profile_delete(struct rte_pdev *pdev,
> +       uint32_t table_id,
> +       uint32_t meter_profile_id);
> +
> +/**
> + * PDEV table rule meter statistics counters read.
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + * @param[in] table_id
> + *   PDEV table ID.
> + * @param[in] rule_handle
> + *   Rule handle.
> + * @params[out] stats
> + *   When non-NULL, the statistics counters are read and saved here.
> + * @params[in] clear
> + *   When non-zero, the statistics counters are cleared after read, =
otherwise
> + *   they are not modified.
> + * @return
> + *   Zero on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_table_rule_meter_read(struct rte_pdev *pdev,
> +       uint32_t table_id,
> +       void *rule_handle,
> +       struct rte_pdev_table_action_mtr_counters *stats,
> +       int clear);
> +
> +/**
> + * PDEV table rule TTL statistics counters read.
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + * @param[in] table_id
> + *   PDEV table ID.
> + * @param[in] rule_handle
> + *   Rule handle.
> + * @params[out] stats
> + *   When non-NULL, the statistics counters are read and saved here.
> + * @params[in] clear
> + *   When non-zero, the statistics counters are cleared after read, =
otherwise
> + *   they are not modified.
> + * @return
> + *   Zero on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_table_rule_ttl_read(struct rte_pdev *pdev,
> +       uint32_t table_id,
> +       void *rule_handle,
> +       struct rte_pdev_table_action_ttl_counters *stats,
> +       int clear);
> +
> +/**
> + * PDEV table rule statistics counters read.
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + * @param[in] table_id
> + *   PDEV table ID.
> + * @param[in] rule_handle
> + *   Rule handle.
> + * @params[out] stats
> + *   When non-NULL, the statistics counters are read and saved here.
> + * @params[in] clear
> + *   When non-zero, the statistics counters are cleared after read, =
otherwise
> + *   they are not modified.
> + * @return
> + *   Zero on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_table_rule_stats_read(struct rte_pdev *pdev,
> +       uint32_t table_id,
> +       void *rule_handle,
> +       struct rte_pdev_table_action_stats_counters *stats,
> +       int clear);
> +
> +/**
> + * PDEV table rule timestamp read.
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + * @param[in] table_id
> + *   PDEV table ID.
> + * @param[in] rule_handle
> + *   Rule handle.
> + * @param[out] timestamp
> + *   Current timestamp value. Must be non-NULL.
> + * @return
> + *   Zero on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_table_rule_timestamp_read(struct rte_pdev *pdev,
> +       uint32_t table_id,
> +       void *rule_handle,
> +       uint64_t *timestamp);
> +
> +/** PDEV table statistics counters. */
> +struct rte_pdev_table_stats {
> +       /** Number of packets looked up in this table. */
> +       uint64_t n_packets;
> +
> +       /** Number of bytes associated with *n_packets*. */
> +       uint64_t n_bytes;
> +};
> +
> +/**
> + * PDEV table statistics counters read
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + * @params[in] table_id
> + *   PDEV table ID.
> + * @params[out] stats
> + *   When non-NULL, the statistics counters are read and saved here.
> + * @params[in] clear
> + *   When non-zero, the statistics counters are cleared after read, =
otherwise
> + *   they are not modified.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_table_stats_read(struct rte_pdev *pdev,
> +       uint32_t table_id,
> +       struct rte_pdev_table_stats *stats,
> +       int clear);
> +
> +/**
> + * PDEV output port run-time API
> + */
> +
> +/** PDEV output port statistics counters. */
> +struct rte_pdev_port_out_stats {
> +       /** Number of packets written to this output port. */
> +       uint64_t n_packets;
> +
> +       /** Number of bytes associated with *n_packets*. */
> +       uint64_t n_bytes;
> +};
> +
> +/**
> + * PDEV output port statistics counters read
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + * @params[in] port_id
> + *   PDEV output port ID.
> + * @params[out] stats
> + *   When non-NULL, the statistics counters are read and saved here.
> + * @params[in] clear
> + *   When non-zero, the statistics counters are cleared after read, =
otherwise
> + *   they are not modified.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_pdev_port_out_stats_read(struct rte_pdev *pdev,
> +       uint32_t port_id,
> +       struct rte_pdev_port_out_stats *stats,
> +       int clear);
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif
> diff --git a/lib/librte_pipeline/rte_pdev_driver.h =
b/lib/librte_pipeline/rte_pdev_driver.h
> new file mode 100644
> index 0000000..4b97784
> --- /dev/null
> +++ b/lib/librte_pipeline/rte_pdev_driver.h
> @@ -0,0 +1,283 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2018 Intel Corporation
> + */
> +
> +#ifndef __INCLUDE_RTE_PDEV_DRIVER_H__
> +#define __INCLUDE_RTE_PDEV_DRIVER_H__
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/**
> + * @file
> + * RTE Pipeline Device (PDEV) - Device Driver Interface
> + */
> +
> +#include <stdint.h>
> +
> +#include "rte_pdev.h"
> +
> +/** @internal PDEV create */
> +typedef struct rte_pdev * (*rte_pdev_create_t)(struct rte_device =
*dev,
> +       struct rte_pdev_params *params);
> +
> +/** @internal PDEV free */
> +typedef int (*rte_pdev_free_t)(struct rte_pdev *pdev);
> +
> +/** @internal PDEV start */
> +typedef int (*rte_pdev_start_t)(struct rte_pdev *pdev);
> +
> +/** @internal PDEV input port create */
> +typedef int (*rte_pdev_port_in_create_t)(struct rte_pdev *pdev,
> +       uint32_t port_id,
> +       struct rte_pdev_port_in_params *params,
> +       int enable);
> +
> +/** @internal PDEV input port connect */
> +typedef int (*rte_pdev_port_in_connect_t)(struct rte_pdev *pdev,
> +       uint32_t port_id,
> +       uint32_t table_id);
> +
> +/** @internal PDEV table create */
> +typedef int (*rte_pdev_table_create_t)(struct rte_pdev *pdev,
> +       uint32_t table_id,
> +       struct rte_pdev_table_params *params);
> +
> +/** @internal PDEV output port create */
> +typedef int (*rte_pdev_port_out_create_t)(struct rte_pdev *pdev,
> +       uint32_t port_id,
> +       struct rte_pdev_port_out_params *params);
> +
> +/** @internal PDEV packet field register */
> +typedef int (*rte_pdev_pkt_field_register_t)(struct rte_pdev *pdev,
> +       const char *name,
> +       uint32_t offset,
> +       uint32_t size);
> +
> +/** @internal PDEV packet meta-data field register */
> +typedef int (*rte_pdev_pkt_meta_field_register_t)(struct rte_pdev =
*pdev,
> +       const char *name,
> +       uint32_t size);
> +
> +/** @internal PDEV table rule data field register */
> +typedef int (*rte_pdev_table_field_register_t)(struct rte_pdev *pdev,
> +       uint32_t table_id,
> +       uint32_t action_profile_id,
> +       const char *name,
> +       uint32_t size);
> +
> +/** @internal PDEV input port action profile create */
> +typedef int (*rte_pdev_port_in_action_profile_create_t)(struct =
rte_pdev *pdev,
> +       uint32_t profile_id);
> +
> +/** @internal PDEV input port action profile action register */
> +typedef int =
(*rte_pdev_port_in_action_profile_action_register_t)(struct rte_pdev =
*pdev,
> +       uint32_t profile_id,
> +       enum rte_pdev_port_in_action_type action_type,
> +       void *action_config);
> +
> +/** @internal PDEV input port action profile freeze */
> +typedef int (*rte_pdev_port_in_action_profile_freeze_t)(struct =
rte_pdev *pdev,
> +       uint32_t profile_id);
> +
> +/** @internal PDEV input port action profile register */
> +typedef int (*rte_pdev_port_in_action_profile_register_t)(struct =
rte_pdev *pdev,
> +       uint32_t port_id,
> +       uint32_t profile_id);
> +
> +/** @internal PDEV table action profile create */
> +typedef int (*rte_pdev_table_action_profile_create_t)(struct rte_pdev =
*pdev,
> +       uint32_t profile_id);
> +
> +/** @internal PDEV table action profile action register */
> +typedef int (*rte_pdev_table_action_profile_action_register_t)(struct =
rte_pdev *pdev,
> +       uint32_t profile_id,
> +       enum rte_pdev_table_action_type action_type,
> +       void *action_config);
> +
> +/** @internal PDEV table action profile freeze */
> +typedef int (*rte_pdev_table_action_profile_freeze_t)(struct rte_pdev =
*pdev,
> +       uint32_t profile_id);
> +
> +/** @internal PDEV table action profile register */
> +typedef int (*rte_pdev_table_action_profile_register_t)(struct =
rte_pdev *pdev,
> +       uint32_t table_id,
> +       uint32_t profile_id);
> +
> +/** @internal PDEV output port action profile create */
> +typedef int (*rte_pdev_port_out_action_profile_create_t)(struct =
rte_pdev *pdev,
> +       uint32_t profile_id);
> +
> +/** @internal PDEV output port action profile action register */
> +typedef int =
(*rte_pdev_port_out_action_profile_action_register_t)(struct rte_pdev =
*pdev,
> +       uint32_t profile_id,
> +       enum rte_pdev_port_out_action_type action_type,
> +       void *action_config);
> +
> +/** @internal PDEV output port action profile freeze */
> +typedef int (*rte_pdev_port_out_action_profile_freeze_t)(struct =
rte_pdev *pdev,
> +       uint32_t profile_id);
> +
> +/** @internal PDEV output port action profile register */
> +typedef int (*rte_pdev_port_out_action_profile_register_t)(struct =
rte_pdev *pdev,
> +       uint32_t table_id,
> +       uint32_t profile_id);
> +
> +/** @internal PDEV input port enable */
> +typedef int (*rte_pdev_port_in_enable_t)(struct rte_pdev *pdev,
> +       uint32_t port_id);
> +
> +/** @internal PDEV input port disable */
> +typedef int (*rte_pdev_port_in_disable_t)(struct rte_pdev *pdev,
> +       uint32_t port_id);
> +
> +/** @internal PDEV input port stats read */
> +typedef int (*rte_pdev_port_in_stats_read_t)(struct rte_pdev *pdev,
> +       uint32_t port_id,
> +       struct rte_pdev_port_in_stats *stats,
> +       int clear);
> +
> +/** @internal PDEV table rule add */
> +typedef int (*rte_pdev_table_rule_add_t)(struct rte_pdev *pdev,
> +       uint32_t table_id,
> +       uint8_t *match,
> +       uint8_t *match_mask,
> +       uint32_t match_priority,
> +       uint32_t action_profile_id,
> +       void **action_params,
> +       void **rule_handle);
> +
> +/** @internal PDEV table rule delete */
> +typedef int (*rte_pdev_table_rule_delete_t)(struct rte_pdev *pdev,
> +       uint32_t table_id,
> +       uint8_t *match,
> +       uint8_t *match_mask);
> +
> +/** @internal PDEV table DSCP table update */
> +typedef int (*rte_pdev_table_dscp_table_update_t)(struct rte_pdev =
*pdev,
> +       uint32_t table_id,
> +       struct rte_pdev_dscp_table *dscp_table);
> +
> +/** @internal PDEV table meter profile add */
> +typedef int (*rte_pdev_table_meter_profile_add_t)(struct rte_pdev =
*pdev,
> +       uint32_t table_id,
> +       uint32_t meter_profile_id,
> +       struct rte_pdev_meter_profile *profile);
> +
> +/** @internal PDEV table meter profile delete */
> +typedef int (*rte_pdev_table_meter_profile_delete_t)(struct rte_pdev =
*pdev,
> +       uint32_t table_id,
> +       uint32_t meter_profile_id);
> +
> +/** @internal PDEV table rule meter stats read */
> +typedef int (*rte_pdev_table_rule_meter_read_t)(struct rte_pdev =
*pdev,
> +       uint32_t table_id,
> +       void *rule_handle,
> +       struct rte_pdev_table_action_mtr_counters *stats,
> +       int clear);
> +
> +/** @internal PDEV table rule TTL stats read */
> +typedef int (*rte_pdev_table_rule_ttl_read_t)(struct rte_pdev *pdev,
> +       uint32_t table_id,
> +       void *rule_handle,
> +       struct rte_pdev_table_action_ttl_counters *stats,
> +       int clear);
> +
> +/** @internal PDEV table rule stats read */
> +typedef int (*rte_pdev_table_rule_stats_read_t)(struct rte_pdev =
*pdev,
> +       uint32_t table_id,
> +       void *rule_handle,
> +       struct rte_pdev_table_action_stats_counters *stats,
> +       int clear);
> +
> +/** @internal PDEV table rule tiemstamp read */
> +typedef int (*rte_pdev_table_rule_timestamp_read_t)(struct rte_pdev =
*pdev,
> +       uint32_t table_id,
> +       void *rule_handle,
> +       uint64_t *timestamp);
> +
> +/** @internal PDEV table stats read */
> +typedef int (*rte_pdev_table_stats_read_t)(struct rte_pdev *pdev,
> +       uint32_t table_id,
> +       struct rte_pdev_table_stats *stats,
> +       int clear);
> +
> +/** @internal PDEV output port stats read */
> +typedef int (*rte_pdev_port_out_stats_read_t)(struct rte_pdev *pdev,
> +       uint32_t port_id,
> +       struct rte_pdev_port_out_stats *stats,
> +       int clear);
> +
> +/** PDEV ops */
> +struct rte_pdev_ops {
> +       /** PDEV create API */
> +       rte_pdev_create_t create;
> +       rte_pdev_free_t free;
> +       rte_pdev_start_t start;
> +       rte_pdev_port_in_create_t port_in_create;
> +       rte_pdev_port_in_connect_t port_in_connect;
> +       rte_pdev_table_create_t table_create;
> +       rte_pdev_port_out_create_t port_out_create;
> +
> +       /** PDEV meta-data API */
> +       rte_pdev_pkt_field_register_t pkt_field_register;
> +       rte_pdev_pkt_meta_field_register_t pkt_meta_field_register;
> +       rte_pdev_table_field_register_t table_field_register;
> +
> +       /** PDEV input port action API */
> +       rte_pdev_port_in_action_profile_create_t =
port_in_action_profile_create;
> +       rte_pdev_port_in_action_profile_action_register_t =
port_in_action_profile_action_register;
> +       rte_pdev_port_in_action_profile_freeze_t =
port_in_action_profile_freeze;
> +       rte_pdev_port_in_action_profile_register_t =
port_in_action_profile_register;
> +
> +       /** PDEV table action API */
> +       rte_pdev_table_action_profile_create_t =
table_action_profile_create;
> +       rte_pdev_table_action_profile_action_register_t =
table_action_profile_action_register;
> +       rte_pdev_table_action_profile_freeze_t =
table_action_profile_freeze;
> +       rte_pdev_table_action_profile_register_t =
table_action_profile_register;
> +
> +       /** PDEV output port action API */
> +       rte_pdev_port_out_action_profile_create_t =
port_out_action_profile_create;
> +       rte_pdev_port_out_action_profile_action_register_t =
port_out_action_profile_action_register;
> +       rte_pdev_port_out_action_profile_freeze_t =
port_out_action_profile_freeze;
> +       rte_pdev_port_out_action_profile_register_t =
port_out_action_profile_register;
> +
> +       /** PDEV input port run-time API */
> +       rte_pdev_port_in_enable_t port_in_enable;
> +       rte_pdev_port_in_disable_t port_in_disable;
> +       rte_pdev_port_in_stats_read_t port_in_stats_read;
> +
> +       /** PDEV table run-time API */
> +       rte_pdev_table_rule_add_t table_rule_add;
> +       rte_pdev_table_rule_delete_t table_rule_delete;
> +       rte_pdev_table_dscp_table_update_t table_dscp_table_update;
> +       rte_pdev_table_meter_profile_add_t table_meter_profile_add;
> +       rte_pdev_table_meter_profile_delete_t =
table_meter_profile_delete;
> +       rte_pdev_table_rule_meter_read_t table_rule_meter_read;
> +       rte_pdev_table_rule_ttl_read_t table_rule_ttl_read;
> +       rte_pdev_table_rule_stats_read_t table_rule_stats_read;
> +       rte_pdev_table_rule_timestamp_read_t =
table_rule_timestamp_read;
> +       rte_pdev_table_stats_read_t table_stats_read;
> +
> +       /** PDEV output port run-time API */
> +       rte_pdev_port_out_stats_read_t port_out_stats_read;
> +};
> +
> +/**
> + * Get PDEV ops
> + *
> + * @param[in] pdev
> + *   PDEV handle.
> + *
> + * @return
> + *   PDEV ops on success, NULL otherwise.
> + */
> +const struct rte_pdev_ops *
> +rte_pdev_ops_get(struct rte_pdev *pdev);
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif
> --
> 2.7.4
>=20