} destroy; /**< Destroy arguments. */
struct {
uint32_t rule;
- enum rte_flow_action_type action;
+ struct rte_flow_action action;
} query; /**< Query arguments. */
struct {
uint32_t *group;
.next = NEXT(NEXT_ENTRY(QUERY_ACTION),
NEXT_ENTRY(RULE_ID),
NEXT_ENTRY(PORT_ID)),
- .args = ARGS(ARGS_ENTRY(struct buffer, args.query.action),
+ .args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
ARGS_ENTRY(struct buffer, args.query.rule),
ARGS_ENTRY(struct buffer, port)),
.call = parse_query,
break;
case QUERY:
port_flow_query(in->port, in->args.query.rule,
- in->args.query.action);
+ &in->args.query.action);
break;
case LIST:
port_flow_list(in->port, in->args.list.group_n,
MK_FLOW_ACTION(FLAG, 0),
MK_FLOW_ACTION(QUEUE, sizeof(struct rte_flow_action_queue)),
MK_FLOW_ACTION(DROP, 0),
- MK_FLOW_ACTION(COUNT, 0),
+ MK_FLOW_ACTION(COUNT, sizeof(struct rte_flow_action_count)),
MK_FLOW_ACTION(RSS, sizeof(struct rte_flow_action_rss)),
MK_FLOW_ACTION(PF, 0),
MK_FLOW_ACTION(VF, sizeof(struct rte_flow_action_vf)),
/** Query a flow rule. */
int
port_flow_query(portid_t port_id, uint32_t rule,
- enum rte_flow_action_type action)
+ const struct rte_flow_action *action)
{
struct rte_flow_error error;
struct rte_port *port;
printf("Flow rule #%u not found\n", rule);
return -ENOENT;
}
- if ((unsigned int)action >= RTE_DIM(flow_action) ||
- !flow_action[action].name)
+ if ((unsigned int)action->type >= RTE_DIM(flow_action) ||
+ !flow_action[action->type].name)
name = "unknown";
else
- name = flow_action[action].name;
- switch (action) {
+ name = flow_action[action->type].name;
+ switch (action->type) {
case RTE_FLOW_ACTION_TYPE_COUNT:
break;
default:
- printf("Cannot query action type %d (%s)\n", action, name);
+ printf("Cannot query action type %d (%s)\n",
+ action->type, name);
return -ENOTSUP;
}
/* Poisoning to make sure PMDs update it in case of error. */
memset(&query, 0, sizeof(query));
if (rte_flow_query(port_id, pf->flow, action, &query, &error))
return port_flow_complain(&error);
- switch (action) {
+ switch (action->type) {
case RTE_FLOW_ACTION_TYPE_COUNT:
printf("%s:\n"
" hits_set: %u\n"
break;
default:
printf("Cannot display result for action type %d (%s)\n",
- action, name);
+ action->type, name);
break;
}
return 0;
int port_flow_destroy(portid_t port_id, uint32_t n, const uint32_t *rule);
int port_flow_flush(portid_t port_id);
int port_flow_query(portid_t port_id, uint32_t rule,
- enum rte_flow_action_type action);
+ const struct rte_flow_action *action);
void port_flow_list(portid_t port_id, uint32_t n, const uint32_t *group);
int port_flow_isolate(portid_t port_id, int set);
.. table:: Mark, count then redirect
- +-------+--------+-----------+-------+
- | Index | Action | Field | Value |
- +=======+========+===========+=======+
- | 0 | MARK | ``mark`` | 0x2a |
- +-------+--------+-----------+-------+
- | 1 | COUNT |
- +-------+--------+-----------+-------+
- | 2 | QUEUE | ``queue`` | 10 |
- +-------+--------+-----------+-------+
- | 3 | END |
- +-------+----------------------------+
+ +-------+--------+------------+-------+
+ | Index | Action | Field | Value |
+ +=======+========+============+=======+
+ | 0 | MARK | ``mark`` | 0x2a |
+ +-------+--------+------------+-------+
+ | 1 | COUNT | ``shared`` | 0 |
+ | | +------------+-------+
+ | | | ``id`` | 0 |
+ +-------+--------+------------+-------+
+ | 2 | QUEUE | ``queue`` | 10 |
+ +-------+--------+------------+-------+
+ | 3 | END |
+ +-------+-----------------------------+
|
Action: ``COUNT``
^^^^^^^^^^^^^^^^^
-Enables counters for this rule.
+Adds a counter action to a matched flow.
+
+If more than one count action is specified in a single flow rule, then each
+action must specify a unique id.
-These counters can be retrieved and reset through ``rte_flow_query()``, see
+Counters can be retrieved and reset through ``rte_flow_query()``, see
``struct rte_flow_query_count``.
-- Counters can be retrieved with ``rte_flow_query()``.
-- No configurable properties.
+The shared flag indicates whether the counter is unique to the flow rule the
+action is specified with, or whether it is a shared counter.
+
+For a count action with the shared flag set, then then a global device
+namespace is assumed for the counter id, so that any matched flow rules using
+a count action with the same counter id on the same port will contribute to
+that counter.
+
+For ports within the same switch domain then the counter id namespace extends
+to all ports within that switch domain.
.. _table_rte_flow_action_count:
.. table:: COUNT
- +---------------+
- | Field |
- +===============+
- | no properties |
- +---------------+
+ +------------+---------------------+
+ | Field | Value |
+ +============+=====================+
+ | ``shared`` | shared counter flag |
+ +------------+---------------------+
+ | ``id`` | counter id |
+ +------------+---------------------+
Query structure to retrieve and reset flow rule counters:
int
rte_flow_query(uint16_t port_id,
struct rte_flow *flow,
- enum rte_flow_action_type action,
+ const struct rte_flow_action *action,
void *data,
struct rte_flow_error *error);
- ``port_id``: port identifier of Ethernet device.
- ``flow``: flow rule handle to query.
-- ``action``: action type to query.
+- ``action``: action to query, this must match prototype from flow rule.
- ``data``: pointer to storage for the associated query data type.
- ``error``: perform verbose error reporting if not NULL. PMDs initialize
this structure in case of error only.
* PORT_ID pattern item and actions were added to match and target DPDK
port IDs at a higher level than PHY_PORT.
+* ethdev: change flow APIs regarding count action:
+ * ``rte_flow_create()`` API count action now requires the ``struct rte_flow_action_count``.
+ * ``rte_flow_query()`` API parameter changed from action type to action structure.
+
ABI Changes
-----------
static int
bond_flow_query_count(struct rte_eth_dev *dev, struct rte_flow *flow,
+ const struct rte_flow_action *action,
struct rte_flow_query_count *count,
struct rte_flow_error *err)
{
rte_memcpy(&slave_count, count, sizeof(slave_count));
for (i = 0; i < internals->slave_count; i++) {
ret = rte_flow_query(internals->slaves[i].port_id,
- flow->flows[i], RTE_FLOW_ACTION_TYPE_COUNT,
+ flow->flows[i], action,
&slave_count, err);
if (unlikely(ret != 0)) {
RTE_BOND_LOG(ERR, "Failed to query flow on"
static int
bond_flow_query(struct rte_eth_dev *dev, struct rte_flow *flow,
- enum rte_flow_action_type type, void *arg,
+ const struct rte_flow_action *action, void *arg,
struct rte_flow_error *err)
{
- switch (type) {
+ switch (action->type) {
case RTE_FLOW_ACTION_TYPE_COUNT:
- return bond_flow_query_count(dev, flow, arg, err);
+ return bond_flow_query_count(dev, flow, action, arg, err);
default:
return rte_flow_error_set(err, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ACTION, arg,
static int
fs_flow_query(struct rte_eth_dev *dev,
struct rte_flow *flow,
- enum rte_flow_action_type type,
+ const struct rte_flow_action *action,
void *arg,
struct rte_flow_error *error)
{
if (sdev != NULL) {
int ret = rte_flow_query(PORT_ID(sdev),
flow->flows[SUB_ID(sdev)],
- type, arg, error);
+ action, arg, error);
if ((ret = fs_err(sdev, ret))) {
fs_unlock(dev, 0);
void mlx5_flow_list_flush(struct rte_eth_dev *dev, struct mlx5_flows *list);
int mlx5_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error);
int mlx5_flow_query(struct rte_eth_dev *dev, struct rte_flow *flow,
- enum rte_flow_action_type action, void *data,
+ const struct rte_flow_action *action, void *data,
struct rte_flow_error *error);
int mlx5_flow_isolate(struct rte_eth_dev *dev, int enable,
struct rte_flow_error *error);
int
mlx5_flow_query(struct rte_eth_dev *dev __rte_unused,
struct rte_flow *flow,
- enum rte_flow_action_type action __rte_unused,
+ const struct rte_flow_action *action __rte_unused,
void *data,
struct rte_flow_error *error)
{
int
rte_flow_query(uint16_t port_id,
struct rte_flow *flow,
- enum rte_flow_action_type action,
+ const struct rte_flow_action *action,
void *data,
struct rte_flow_error *error)
{
* These counters can be retrieved and reset through rte_flow_query(),
* see struct rte_flow_query_count.
*
- * No associated configuration structure.
+ * See struct rte_flow_action_count.
*/
RTE_FLOW_ACTION_TYPE_COUNT,
uint16_t index; /**< Queue index to use. */
};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this structure may change without prior notice
+ *
+ * RTE_FLOW_ACTION_TYPE_COUNT
+ *
+ * Adds a counter action to a matched flow.
+ *
+ * If more than one count action is specified in a single flow rule, then each
+ * action must specify a unique id.
+ *
+ * Counters can be retrieved and reset through ``rte_flow_query()``, see
+ * ``struct rte_flow_query_count``.
+ *
+ * The shared flag indicates whether the counter is unique to the flow rule the
+ * action is specified with, or whether it is a shared counter.
+ *
+ * For a count action with the shared flag set, then then a global device
+ * namespace is assumed for the counter id, so that any matched flow rules using
+ * a count action with the same counter id on the same port will contribute to
+ * that counter.
+ *
+ * For ports within the same switch domain then the counter id namespace extends
+ * to all ports within that switch domain.
+ */
+struct rte_flow_action_count {
+ uint32_t shared:1; /**< Share counter ID with other flow rules. */
+ uint32_t reserved:31; /**< Reserved, must be zero. */
+ uint32_t id; /**< Counter ID. */
+};
+
/**
* RTE_FLOW_ACTION_TYPE_COUNT (query)
*
* @param flow
* Flow rule handle to query.
* @param action
- * Action type to query.
+ * Action definition as defined in original flow rule.
* @param[in, out] data
* Pointer to storage for the associated query data type.
* @param[out] error
int
rte_flow_query(uint16_t port_id,
struct rte_flow *flow,
- enum rte_flow_action_type action,
+ const struct rte_flow_action *action,
void *data,
struct rte_flow_error *error);
int (*query)
(struct rte_eth_dev *,
struct rte_flow *,
- enum rte_flow_action_type,
+ const struct rte_flow_action *,
void *,
struct rte_flow_error *);
/** See rte_flow_isolate(). */