[array] (@ref rte_table_array.h),
[stub] (@ref rte_table_stub.h)
* [pipeline] (@ref rte_pipeline.h)
+ [table_action] (@ref rte_table_action.h)
- **basic**:
[approx fraction] (@ref rte_approx.h),
# all source are stored in SRCS-y
#
SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) := rte_pipeline.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += rte_table_action.c
# install includes
-SYMLINK-$(CONFIG_RTE_LIBRTE_PIPELINE)-include += rte_pipeline.h
+SYMLINK-$(CONFIG_RTE_LIBRTE_PIPELINE)-include += rte_pipeline.h rte_table_action.h
include $(RTE_SDK)/mk/rte.lib.mk
# Copyright(c) 2017 Intel Corporation
version = 3
-sources = files('rte_pipeline.c')
-headers = files('rte_pipeline.h')
+allow_experimental_apis = true
+sources = files('rte_pipeline.c', 'rte_table_action.c')
+headers = files('rte_pipeline.h', 'rte_table_action.h')
deps += ['port', 'table']
rte_pipeline_ah_packet_drop;
} DPDK_2.2;
+
+EXPERIMENTAL {
+ global:
+
+ rte_table_action_apply;
+ rte_table_action_create;
+ rte_table_action_free;
+ rte_table_action_profile_action_register;
+ rte_table_action_profile_create;
+ rte_table_action_profile_free;
+ rte_table_action_profile_freeze;
+
+} DPDK_16.04;
--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2018 Intel Corporation
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <rte_malloc.h>
+
+#include <rte_common.h>
+#include <rte_malloc.h>
+
+#include "rte_table_action.h"
+
+/**
+ * RTE_TABLE_ACTION_FWD
+ */
+#define fwd_data rte_pipeline_table_entry
+
+static int
+fwd_apply(struct fwd_data *data,
+ struct rte_table_action_fwd_params *p)
+{
+ data->action = p->action;
+
+ if (p->action == RTE_PIPELINE_ACTION_PORT)
+ data->port_id = p->id;
+
+ if (p->action == RTE_PIPELINE_ACTION_TABLE)
+ data->table_id = p->id;
+
+ return 0;
+}
+
+/**
+ * Action profile
+ */
+static int
+action_valid(enum rte_table_action_type action)
+{
+ switch (action) {
+ case RTE_TABLE_ACTION_FWD:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+
+#define RTE_TABLE_ACTION_MAX 64
+
+struct ap_config {
+ uint64_t action_mask;
+ struct rte_table_action_common_config common;
+};
+
+static size_t
+action_cfg_size(enum rte_table_action_type action)
+{
+ switch (action) {
+ default:
+ return 0;
+ }
+}
+
+static void*
+action_cfg_get(struct ap_config *ap_config __rte_unused,
+ enum rte_table_action_type type)
+{
+ switch (type) {
+ default:
+ return NULL;
+ }
+}
+
+static void
+action_cfg_set(struct ap_config *ap_config,
+ enum rte_table_action_type type,
+ void *action_cfg)
+{
+ void *dst = action_cfg_get(ap_config, type);
+
+ if (dst)
+ memcpy(dst, action_cfg, action_cfg_size(type));
+
+ ap_config->action_mask |= 1LLU << type;
+}
+
+struct ap_data {
+ size_t offset[RTE_TABLE_ACTION_MAX];
+ size_t total_size;
+};
+
+static size_t
+action_data_size(enum rte_table_action_type action,
+ struct ap_config *ap_config __rte_unused)
+{
+ switch (action) {
+ case RTE_TABLE_ACTION_FWD:
+ return sizeof(struct fwd_data);
+
+ default:
+ return 0;
+ }
+}
+
+
+static void
+action_data_offset_set(struct ap_data *ap_data,
+ struct ap_config *ap_config)
+{
+ uint64_t action_mask = ap_config->action_mask;
+ size_t offset;
+ uint32_t action;
+
+ memset(ap_data->offset, 0, sizeof(ap_data->offset));
+
+ offset = 0;
+ for (action = 0; action < RTE_TABLE_ACTION_MAX; action++)
+ if (action_mask & (1LLU << action)) {
+ ap_data->offset[action] = offset;
+ offset += action_data_size((enum rte_table_action_type)action,
+ ap_config);
+ }
+
+ ap_data->total_size = offset;
+}
+
+struct rte_table_action_profile {
+ struct ap_config cfg;
+ struct ap_data data;
+ int frozen;
+};
+
+struct rte_table_action_profile *
+rte_table_action_profile_create(struct rte_table_action_common_config *common)
+{
+ struct rte_table_action_profile *ap;
+
+ /* Check input arguments */
+ if (common == NULL)
+ return NULL;
+
+ /* Memory allocation */
+ ap = calloc(1, sizeof(struct rte_table_action_profile));
+ if (ap == NULL)
+ return NULL;
+
+ /* Initialization */
+ memcpy(&ap->cfg.common, common, sizeof(*common));
+
+ return ap;
+}
+
+
+int
+rte_table_action_profile_action_register(struct rte_table_action_profile *profile,
+ enum rte_table_action_type type,
+ void *action_config)
+{
+ /* Check input arguments */
+ if ((profile == NULL) ||
+ profile->frozen ||
+ (action_valid(type) == 0) ||
+ (profile->cfg.action_mask & (1LLU << type)) ||
+ ((action_cfg_size(type) == 0) && action_config) ||
+ (action_cfg_size(type) && (action_config == NULL)))
+ return -EINVAL;
+
+ /* Action enable */
+ action_cfg_set(&profile->cfg, type, action_config);
+
+ return 0;
+}
+
+int
+rte_table_action_profile_freeze(struct rte_table_action_profile *profile)
+{
+ if (profile->frozen)
+ return -EBUSY;
+
+ profile->cfg.action_mask |= 1LLU << RTE_TABLE_ACTION_FWD;
+ action_data_offset_set(&profile->data, &profile->cfg);
+ profile->frozen = 1;
+
+ return 0;
+}
+
+int
+rte_table_action_profile_free(struct rte_table_action_profile *profile)
+{
+ if (profile == NULL)
+ return 0;
+
+ free(profile);
+ return 0;
+}
+
+struct rte_table_action {
+ struct ap_config cfg;
+ struct ap_data data;
+};
+
+struct rte_table_action *
+rte_table_action_create(struct rte_table_action_profile *profile,
+ uint32_t socket_id)
+{
+ struct rte_table_action *action;
+
+ /* Check input arguments */
+ if ((profile == NULL) ||
+ (profile->frozen == 0))
+ return NULL;
+
+ /* Memory allocation */
+ action = rte_zmalloc_socket(NULL,
+ sizeof(struct rte_table_action),
+ RTE_CACHE_LINE_SIZE,
+ socket_id);
+ if (action == NULL)
+ return NULL;
+
+ /* Initialization */
+ memcpy(&action->cfg, &profile->cfg, sizeof(profile->cfg));
+ memcpy(&action->data, &profile->data, sizeof(profile->data));
+
+ return action;
+}
+
+static __rte_always_inline void *
+action_data_get(void *data,
+ struct rte_table_action *action,
+ enum rte_table_action_type type)
+{
+ size_t offset = action->data.offset[type];
+ uint8_t *data_bytes = data;
+
+ return &data_bytes[offset];
+}
+
+int
+rte_table_action_apply(struct rte_table_action *action,
+ void *data,
+ enum rte_table_action_type type,
+ void *action_params)
+{
+ void *action_data;
+
+ /* Check input arguments */
+ if ((action == NULL) ||
+ (data == NULL) ||
+ (action_valid(type) == 0) ||
+ ((action->cfg.action_mask & (1LLU << type)) == 0) ||
+ (action_params == NULL))
+ return -EINVAL;
+
+ /* Data update */
+ action_data = action_data_get(data, action, type);
+
+ switch (type) {
+ case RTE_TABLE_ACTION_FWD:
+ return fwd_apply(action_data,
+ action_params);
+
+ default:
+ return -EINVAL;
+ }
+}
+
+int
+rte_table_action_free(struct rte_table_action *action)
+{
+ if (action == NULL)
+ return 0;
+
+ rte_free(action);
+
+ return 0;
+}
--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#ifndef __INCLUDE_RTE_TABLE_ACTION_H__
+#define __INCLUDE_RTE_TABLE_ACTION_H__
+
+/**
+ * @file
+ * RTE Pipeline Table Actions
+ *
+ * This API provides a common set of actions for pipeline tables to speed up
+ * application development.
+ *
+ * Each match-action rule added to a pipeline table has associated data that
+ * stores the action context. This data is input to the table action handler
+ * called for every input packet that hits the rule as part of the table lookup
+ * during the pipeline execution. The pipeline library allows the user to define
+ * his own table actions by providing customized table action handlers (table
+ * lookup) and complete freedom of setting the rules and their data (table rule
+ * add/delete). While the user can still follow this process, this API is
+ * intended to provide a quicker development alternative for a set of predefined
+ * actions.
+ *
+ * The typical steps to use this API are:
+ * - Define a table action profile. This is a configuration template that can
+ * potentially be shared by multiple tables from the same or different
+ * pipelines, with different tables from the same pipeline likely to use
+ * different action profiles. For every table using a given action profile,
+ * the profile defines the set of actions and the action configuration to be
+ * implemented for all the table rules. API functions:
+ * rte_table_action_profile_create(),
+ * rte_table_action_profile_action_register(),
+ * rte_table_action_profile_freeze().
+ *
+ * - Instantiate the table action profile to create table action objects. Each
+ * pipeline table has its own table action object. API functions:
+ * rte_table_action_create().
+ *
+ * - Use the table action object to generate the pipeline table action handlers
+ * (invoked by the pipeline table lookup operation). API functions:
+ * rte_table_action_table_params_get().
+ *
+ * - Use the table action object to generate the rule data (for the pipeline
+ * table rule add operation) based on given action parameters. API functions:
+ * rte_table_action_apply().
+ *
+ * - Use the table action object to read action data (e.g. stats counters) for
+ * any given rule. API functions: rte_table_action_XYZ_read().
+ *
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+#include <rte_compat.h>
+
+#include "rte_pipeline.h"
+
+/** Table actions. */
+enum rte_table_action_type {
+ /** Forward to next pipeline table, output port or drop. */
+ RTE_TABLE_ACTION_FWD = 0,
+};
+
+/** Common action configuration (per table action profile). */
+struct rte_table_action_common_config {
+ /** Input packet Internet Protocol (IP) version. Non-zero for IPv4, zero
+ * for IPv6.
+ */
+ int ip_version;
+
+ /** IP header offset within the input packet buffer. Offset 0 points to
+ * the first byte of the MBUF structure.
+ */
+ uint32_t ip_offset;
+};
+
+/**
+ * RTE_TABLE_ACTION_FWD
+ */
+/** Forward action parameters (per table rule). */
+struct rte_table_action_fwd_params {
+ /** Forward action. */
+ enum rte_pipeline_action action;
+
+ /** Pipeline table ID or output port ID. */
+ uint32_t id;
+};
+
+/**
+ * Table action profile.
+ */
+struct rte_table_action_profile;
+
+/**
+ * Table action profile create.
+ *
+ * @param[in] common
+ * Common action configuration.
+ * @return
+ * Table action profile handle on success, NULL otherwise.
+ */
+struct rte_table_action_profile * __rte_experimental
+rte_table_action_profile_create(struct rte_table_action_common_config *common);
+
+/**
+ * Table action profile free.
+ *
+ * @param[in] profile
+ * Table profile action handle (needs to be valid).
+ * @return
+ * Zero on success, non-zero error code otherwise.
+ */
+int __rte_experimental
+rte_table_action_profile_free(struct rte_table_action_profile *profile);
+
+/**
+ * Table action profile action register.
+ *
+ * @param[in] profile
+ * Table profile action handle (needs to be valid and not in frozen state).
+ * @param[in] type
+ * Specific table action to be registered for *profile*.
+ * @param[in] action_config
+ * Configuration for the *type* action.
+ * If struct rte_table_action_*type*_config is defined by the Table Action
+ * API, it needs to point to a valid instance of this structure, otherwise it
+ * needs to be set to NULL.
+ * @return
+ * Zero on success, non-zero error code otherwise.
+ */
+int __rte_experimental
+rte_table_action_profile_action_register(struct rte_table_action_profile *profile,
+ enum rte_table_action_type type,
+ void *action_config);
+
+/**
+ * Table action profile freeze.
+ *
+ * Once this function is called successfully, the given profile enters the
+ * frozen state with the following immediate effects: no more actions can be
+ * registered for this profile, so the profile can be instantiated to create
+ * table action objects.
+ *
+ * @param[in] profile
+ * Table profile action handle (needs to be valid and not in frozen state).
+ * @return
+ * Zero on success, non-zero error code otherwise.
+ *
+ * @see rte_table_action_create()
+ */
+int __rte_experimental
+rte_table_action_profile_freeze(struct rte_table_action_profile *profile);
+
+/**
+ * Table action.
+ */
+struct rte_table_action;
+
+/**
+ * Table action create.
+ *
+ * Instantiates the given table action profile to create a table action object.
+ *
+ * @param[in] profile
+ * Table profile action handle (needs to be valid and in frozen state).
+ * @param[in] socket_id
+ * CPU socket ID where the internal data structures required by the new table
+ * action object should be allocated.
+ * @return
+ * Handle to table action object on success, NULL on error.
+ *
+ * @see rte_table_action_create()
+ */
+struct rte_table_action * __rte_experimental
+rte_table_action_create(struct rte_table_action_profile *profile,
+ uint32_t socket_id);
+
+/**
+ * Table action free.
+ *
+ * @param[in] action
+ * Handle to table action object (needs to be valid).
+ * @return
+ * Zero on success, non-zero error code otherwise.
+ */
+int __rte_experimental
+rte_table_action_free(struct rte_table_action *action);
+
+/**
+ * Table action apply.
+ *
+ * @param[in] action
+ * Handle to table action object (needs to be valid).
+ * @param[in] data
+ * Data byte array (typically table rule data) to apply action *type* on.
+ * @param[in] type
+ * Specific table action previously registered for the table action profile of
+ * the *action* object.
+ * @param[in] action_params
+ * Parameters for the *type* action.
+ * If struct rte_table_action_*type*_params is defined by the Table Action
+ * API, it needs to point to a valid instance of this structure, otherwise it
+ * needs to be set to NULL.
+ * @return
+ * Zero on success, non-zero error code otherwise.
+ */
+int __rte_experimental
+rte_table_action_apply(struct rte_table_action *action,
+ void *data,
+ enum rte_table_action_type type,
+ void *action_params);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCLUDE_RTE_TABLE_ACTION_H__ */