ACTION_SET_TAG_DATA,
ACTION_SET_TAG_INDEX,
ACTION_SET_TAG_MASK,
+ ACTION_SET_META,
+ ACTION_SET_META_DATA,
+ ACTION_SET_META_MASK,
};
/** Maximum size for pattern in struct rte_flow_item_raw. */
ACTION_RAW_ENCAP,
ACTION_RAW_DECAP,
ACTION_SET_TAG,
+ ACTION_SET_META,
ZERO,
};
ZERO,
};
+static const enum index action_set_meta[] = {
+ ACTION_SET_META_DATA,
+ ACTION_SET_META_MASK,
+ ACTION_NEXT,
+ ZERO,
+};
+
static int parse_set_raw_encap_decap(struct context *, const struct token *,
const char *, unsigned int,
void *, unsigned int);
static int parse_vc_action_raw_decap_index(struct context *,
const struct token *, const char *,
unsigned int, void *, unsigned int);
+static int parse_vc_action_set_meta(struct context *ctx,
+ const struct token *token, const char *str,
+ unsigned int len, void *buf,
+ unsigned int size);
static int parse_destroy(struct context *, const struct token *,
const char *, unsigned int,
void *, unsigned int);
.name = "data",
.help = "metadata value",
.next = NEXT(item_meta, NEXT_ENTRY(UNSIGNED), item_param),
- .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_meta,
- data, "\xff\xff\xff\xff")),
+ .args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta,
+ data, "\xff\xff\xff\xff")),
},
[ITEM_GRE_KEY] = {
.name = "gre_key",
.name = "data",
.help = "tag value to match",
.next = NEXT(item_tag, NEXT_ENTRY(UNSIGNED), item_param),
- .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tag, data)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, data)),
},
[ITEM_TAG_INDEX] = {
.name = "index",
.name = "data",
.help = "tag value",
.next = NEXT(action_set_tag, NEXT_ENTRY(UNSIGNED)),
- .args = ARGS(ARGS_ENTRY_HTON
+ .args = ARGS(ARGS_ENTRY
(struct rte_flow_action_set_tag, data)),
.call = parse_vc_conf,
},
.name = "mask",
.help = "mask for tag value",
.next = NEXT(action_set_tag, NEXT_ENTRY(UNSIGNED)),
- .args = ARGS(ARGS_ENTRY_HTON
+ .args = ARGS(ARGS_ENTRY
(struct rte_flow_action_set_tag, mask)),
.call = parse_vc_conf,
},
+ [ACTION_SET_META] = {
+ .name = "set_meta",
+ .help = "set metadata",
+ .priv = PRIV_ACTION(SET_META,
+ sizeof(struct rte_flow_action_set_meta)),
+ .next = NEXT(action_set_meta),
+ .call = parse_vc_action_set_meta,
+ },
+ [ACTION_SET_META_DATA] = {
+ .name = "data",
+ .help = "metadata value",
+ .next = NEXT(action_set_meta, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY
+ (struct rte_flow_action_set_meta, data)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_SET_META_MASK] = {
+ .name = "mask",
+ .help = "mask for metadata value",
+ .next = NEXT(action_set_meta, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY
+ (struct rte_flow_action_set_meta, mask)),
+ .call = parse_vc_conf,
+ },
};
/** Remove and return last entry from argument stack. */
return ret;
}
+static int
+parse_vc_action_set_meta(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len, void *buf,
+ unsigned int size)
+{
+ int ret;
+
+ ret = parse_vc(ctx, token, str, len, buf, size);
+ if (ret < 0)
+ return ret;
+ ret = rte_flow_dynf_metadata_register();
+ if (ret < 0)
+ return -1;
+ return len;
+}
+
/** Parse tokens for destroy command. */
static int
parse_destroy(struct context *ctx, const struct token *token,
mb->vlan_tci, mb->vlan_tci_outer);
else if (ol_flags & PKT_RX_VLAN)
printf(" - VLAN tci=0x%x", mb->vlan_tci);
+ if (ol_flags & PKT_TX_METADATA)
+ printf(" - Tx metadata: 0x%x", mb->tx_metadata);
+ if (ol_flags & PKT_RX_DYNF_METADATA)
+ printf(" - Rx metadata: 0x%x",
+ *RTE_FLOW_DYNF_METADATA(mb));
if (mb->packet_type) {
rte_get_ptype_name(mb->packet_type, buf, sizeof(buf));
printf(" - hw ptype: %s", buf);
| | ``index`` | field is ignored |
+----------+-----------+---------------------------------------+
-ata matching item types
-~~~~~~~~~~~~~~~~~~~~~~~
+Item: ``META``
+^^^^^^^^^^^^^^^^^
+
+Matches 32 bit metadata item set.
+
+On egress, metadata can be set either by mbuf metadata field with
+PKT_TX_METADATA flag or ``SET_META`` action. On ingress, ``SET_META``
+action sets metadata for a packet and the metadata will be reported via
+``metadata`` dynamic field of ``rte_mbuf`` with PKT_RX_DYNF_METADATA flag.
+
+- Default ``mask`` matches the specified Rx metadata value.
+
+.. _table_rte_flow_item_meta:
+
+.. table:: META
+
+ +----------+----------+---------------------------------------+
+ | Field | Subfield | Value |
+ +==========+==========+=======================================+
+ | ``spec`` | ``data`` | 32 bit metadata value |
+ +----------+----------+---------------------------------------+
+ | ``last`` | ``data`` | upper range value |
+ +----------+----------+---------------------------------------+
+ | ``mask`` | ``data`` | bit-mask applies to "spec" and "last" |
+ +----------+----------+---------------------------------------+
+
+Data matching item types
+~~~~~~~~~~~~~~~~~~~~~~~~
Most of these are basically protocol header definitions with associated
bit-masks. They must be specified (stacked) from lowest to highest protocol
- ``proto_id``: PPP protocol identifier.
- Default ``mask`` matches proto_id only.
-
-.. _table_rte_flow_item_meta:
-
-.. table:: META
-
- +----------+----------+---------------------------------------+
- | Field | Subfield | Value |
- +==========+==========+=======================================+
- | ``spec`` | ``data`` | 32 bit metadata value |
- +----------+--------------------------------------------------+
- | ``last`` | ``data`` | upper range value |
- +----------+----------+---------------------------------------+
- | ``mask`` | ``data`` | bit-mask applies to "spec" and "last" |
- +----------+----------+---------------------------------------+
-
Item: ``NSH``
^^^^^^^^^^^^^
| ``index`` | index of tag to set |
+-----------+----------------------------+
+Action: ``SET_META``
+^^^^^^^^^^^^^^^^^^^^^^^
+
+Set metadata. Item ``META`` matches metadata.
+
+Metadata set by mbuf metadata field with PKT_TX_METADATA flag on egress will be
+overridden by this action. On ingress, the metadata will be carried by
+``metadata`` dynamic field of ``rte_mbuf`` which can be accessed by
+``RTE_FLOW_DYNF_METADATA()``. PKT_RX_DYNF_METADATA flag will be set along
+with the data.
+
+The mbuf dynamic field must be registered by calling
+``rte_flow_dynf_metadata_register()`` prior to use ``SET_META`` action.
+
+Altering partial bits is supported with ``mask``. For bits which have never been
+set, unpredictable value will be seen depending on driver implementation. For
+loopback/hairpin packet, metadata set on Rx/Tx may or may not be propagated to
+the other path depending on HW capability.
+
+.. _table_rte_flow_action_set_meta:
+
+.. table:: SET_META
+
+ +----------+----------------------------+
+ | Field | Value |
+ +==========+============================+
+ | ``data`` | 32 bit metadata value |
+ +----------+----------------------------+
+ | ``mask`` | bit-mask applies to "data" |
+ +----------+----------------------------+
+
Negative types
~~~~~~~~~~~~~~
SET_TAG action and TAG item have been added to support transient flow tag.
+* **Extended metadata support in rte_flow.**
+
+ Flow metadata is extended to both Rx and Tx.
+
+ * Tx metadata can also be set by SET_META action of rte_flow.
+ * Rx metadata is delivered to host via a dynamic field of ``rte_mbuf`` with
+ PKT_RX_DYNF_METADATA.
+
* **Updated the enic driver.**
* Added support for Geneve with options offload.
If the intent is to iterate over ports, ``RTE_ETH_FOREACH_*`` macros
are better port iterators.
+* ethdev: RTE_FLOW_ITEM_TYPE_META data endianness altered to host one.
+ Due to the new dynamic metadata field in mbuf is host-endian either, there
+ is the minor compatibility issue for applications in case of 32-bit values
+ supported.
+
* event: The function ``rte_event_eth_tx_adapter_enqueue`` takes an additional
input as ``flags``. Flag ``RTE_EVENT_ETH_TX_ADAPTER_ENQUEUE_SAME_DEST`` which
has been introduced in this release is used when used when all the packets
rte_eth_rx_hairpin_queue_setup;
rte_eth_tx_burst_mode_get;
rte_eth_tx_hairpin_queue_setup;
+ rte_flow_dynf_metadata_offs;
+ rte_flow_dynf_metadata_mask;
+ rte_flow_dynf_metadata_register;
};
#include <rte_errno.h>
#include <rte_branch_prediction.h>
#include <rte_string_fns.h>
+#include <rte_mbuf.h>
+#include <rte_mbuf_dyn.h>
#include "rte_ethdev.h"
#include "rte_flow_driver.h"
#include "rte_flow.h"
+/* Mbuf dynamic field name for metadata. */
+int rte_flow_dynf_metadata_offs = -1;
+
+/* Mbuf dynamic field flag bit number for metadata. */
+uint64_t rte_flow_dynf_metadata_mask;
+
/**
* Flow elements description tables.
*/
MK_FLOW_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)),
MK_FLOW_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)),
MK_FLOW_ACTION(SET_TAG, sizeof(struct rte_flow_action_set_tag)),
+ MK_FLOW_ACTION(SET_META, sizeof(struct rte_flow_action_set_meta)),
};
+int
+rte_flow_dynf_metadata_register(void)
+{
+ int offset;
+ int flag;
+
+ static const struct rte_mbuf_dynfield desc_offs = {
+ .name = RTE_MBUF_DYNFIELD_METADATA_NAME,
+ .size = sizeof(uint32_t),
+ .align = __alignof__(uint32_t),
+ };
+ static const struct rte_mbuf_dynflag desc_flag = {
+ .name = RTE_MBUF_DYNFLAG_METADATA_NAME,
+ };
+
+ offset = rte_mbuf_dynfield_register(&desc_offs);
+ if (offset < 0)
+ goto error;
+ flag = rte_mbuf_dynflag_register(&desc_flag);
+ if (flag < 0)
+ goto error;
+ rte_flow_dynf_metadata_offs = offset;
+ rte_flow_dynf_metadata_mask = (1ULL << flag);
+ return 0;
+
+error:
+ rte_flow_dynf_metadata_offs = -1;
+ rte_flow_dynf_metadata_mask = 0ULL;
+ return -rte_errno;
+}
+
static int
flow_err(uint16_t port_id, int ret, struct rte_flow_error *error)
{
#include <rte_byteorder.h>
#include <rte_esp.h>
#include <rte_higig.h>
+#include <rte_mbuf.h>
+#include <rte_mbuf_dyn.h>
#ifdef __cplusplus
extern "C" {
/**
* [META]
*
- * Matches a metadata value specified in mbuf metadata field.
+ * Matches a metadata value.
+ *
* See struct rte_flow_item_meta.
*/
RTE_FLOW_ITEM_TYPE_META,
#endif
/**
- * RTE_FLOW_ITEM_TYPE_META.
+ * RTE_FLOW_ITEM_TYPE_META
*
- * Matches a specified metadata value.
+ * Matches a specified metadata value. On egress, metadata can be set either by
+ * mbuf tx_metadata field with PKT_TX_METADATA flag or
+ * RTE_FLOW_ACTION_TYPE_SET_META. On ingress, RTE_FLOW_ACTION_TYPE_SET_META sets
+ * metadata for a packet and the metadata will be reported via mbuf metadata
+ * dynamic field with PKT_RX_DYNF_METADATA flag. The dynamic mbuf field must be
+ * registered in advance by rte_flow_dynf_metadata_register().
*/
struct rte_flow_item_meta {
- rte_be32_t data;
+ uint32_t data;
};
/** Default mask for RTE_FLOW_ITEM_TYPE_META. */
#ifndef __cplusplus
static const struct rte_flow_item_meta rte_flow_item_meta_mask = {
- .data = RTE_BE32(UINT32_MAX),
+ .data = UINT32_MAX,
};
#endif
* See struct rte_flow_action_set_tag.
*/
RTE_FLOW_ACTION_TYPE_SET_TAG,
+
+ /**
+ * Set metadata on ingress or egress path.
+ *
+ * See struct rte_flow_action_set_meta.
+ */
+ RTE_FLOW_ACTION_TYPE_SET_META,
};
/**
uint8_t index;
};
+/**
+ * @warning
+ * @b EXPERIMENTAL: this structure may change without prior notice
+ *
+ * RTE_FLOW_ACTION_TYPE_SET_META
+ *
+ * Set metadata. Metadata set by mbuf tx_metadata field with
+ * PKT_TX_METADATA flag on egress will be overridden by this action. On
+ * ingress, the metadata will be carried by mbuf metadata dynamic field
+ * with PKT_RX_DYNF_METADATA flag if set. The dynamic mbuf field must be
+ * registered in advance by rte_flow_dynf_metadata_register().
+ *
+ * Altering partial bits is supported with mask. For bits which have never
+ * been set, unpredictable value will be seen depending on driver
+ * implementation. For loopback/hairpin packet, metadata set on Rx/Tx may
+ * or may not be propagated to the other path depending on HW capability.
+ *
+ * RTE_FLOW_ITEM_TYPE_META matches metadata.
+ */
+struct rte_flow_action_set_meta {
+ uint32_t data;
+ uint32_t mask;
+};
+
+/* Mbuf dynamic field offset for metadata. */
+extern int rte_flow_dynf_metadata_offs;
+
+/* Mbuf dynamic field flag mask for metadata. */
+extern uint64_t rte_flow_dynf_metadata_mask;
+
+/* Mbuf dynamic field pointer for metadata. */
+#define RTE_FLOW_DYNF_METADATA(m) \
+ RTE_MBUF_DYNFIELD((m), rte_flow_dynf_metadata_offs, uint32_t *)
+
+/* Mbuf dynamic flag for metadata. */
+#define PKT_RX_DYNF_METADATA (rte_flow_dynf_metadata_mask)
+
+__rte_experimental
+static inline uint32_t
+rte_flow_dynf_metadata_get(struct rte_mbuf *m)
+{
+ return *RTE_FLOW_DYNF_METADATA(m);
+}
+
+__rte_experimental
+static inline void
+rte_flow_dynf_metadata_set(struct rte_mbuf *m, uint32_t v)
+{
+ *RTE_FLOW_DYNF_METADATA(m) = v;
+}
+
/*
* Definition of a single action.
*
RTE_FLOW_CONV_OP_ACTION_NAME_PTR,
};
+/**
+ * Check if mbuf dynamic field for metadata is registered.
+ *
+ * @return
+ * True if registered, false otherwise.
+ */
+__rte_experimental
+static inline int
+rte_flow_dynf_metadata_avail(void)
+{
+ return !!rte_flow_dynf_metadata_mask;
+}
+
+/**
+ * Register mbuf dynamic field and flag for metadata.
+ *
+ * This function must be called prior to use SET_META action in order to
+ * register the dynamic mbuf field. Otherwise, the data cannot be delivered to
+ * application.
+ *
+ * @return
+ * 0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+__rte_experimental
+int
+rte_flow_dynf_metadata_register(void);
+
/**
* Check whether a flow rule can be created on a given port.
*
__rte_experimental
void rte_mbuf_dyn_dump(FILE *out);
-/* Placeholder for dynamic fields and flags declarations. */
+/*
+ * Placeholder for dynamic fields and flags declarations.
+ * This is centralizing point to gather all field names
+ * and parameters together.
+ */
+
+/*
+ * The metadata dynamic field provides some extra packet information
+ * to interact with RTE Flow engine. The metadata in sent mbufs can be
+ * used to match on some Flows. The metadata in received mbufs can
+ * provide some feedback from the Flows. The metadata flag tells
+ * whether the field contains actual value to send, or received one.
+ */
+#define RTE_MBUF_DYNFIELD_METADATA_NAME "rte_flow_dynfield_metadata"
+#define RTE_MBUF_DYNFLAG_METADATA_NAME "rte_flow_dynflag_metadata"
#endif