ethdev: add pre-defined meter policy API
Currently, the flow meter policy does not support multiple actions per color; also the allowed action types per color are very limited. In addition, the policy cannot be pre-defined. Due to the growing in flow actions offload abilities there is a potential for the user to use variety of actions per color differently. This new meter policy API comes to allow this potential in the most ethdev common way using rte_flow action definition. A list of rte_flow actions will be provided by the user per color in order to create a meter policy. In addition, the API forces to pre-define the policy before the meters creation in order to allow sharing of single policy with multiple meters efficiently. meter_policy_id is added into struct rte_mtr_params. So that it can get the policy during the meters creation. Allow coloring the packet using a new rte_flow_action_color as could be done by the old policy API. Add two common policy template as macros in the head file. The next API function were added: - rte_mtr_meter_policy_add - rte_mtr_meter_policy_delete - rte_mtr_meter_policy_update - rte_mtr_meter_policy_validate The next struct was changed: - rte_mtr_params - rte_mtr_capabilities The next API was deleted: - rte_mtr_policer_actions_update To support this API the following app were changed: app/test-flow-perf: clean meter policer app/testpmd: clean meter policer To support this API the following drivers were changed: net/softnic: support meter policy API 1. Cleans meter rte_mtr_policer_action. 2. Supports policy API to get color action as policer action did. The color action will be mapped into rte_table_action_policer. net/mlx5: clean meter creation management Cleans and breaks part of the current meter management in order to allow better design with policy API. Signed-off-by: Li Zhang <lizh@nvidia.com> Signed-off-by: Haifei Luo <haifeil@nvidia.com> Signed-off-by: Jiawei Wang <jiaweiw@nvidia.com> Acked-by: Matan Azrad <matan@nvidia.com> Acked-by: Ray Kinsella <mdr@ashroe.eu> Acked-by: Ori Kam <orika@nvidia.com> Acked-by: Jasvinder Singh <jasvinder.singh@intel.com> Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com> Acked-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
This commit is contained in:
parent
fa1d598844
commit
5f0d54f372
@ -928,13 +928,6 @@ create_meter_rule(int port_id, uint32_t counter)
|
||||
|
||||
/*create meter*/
|
||||
params.meter_profile_id = default_prof_id;
|
||||
params.action[RTE_COLOR_GREEN] =
|
||||
MTR_POLICER_ACTION_COLOR_GREEN;
|
||||
params.action[RTE_COLOR_YELLOW] =
|
||||
MTR_POLICER_ACTION_COLOR_YELLOW;
|
||||
params.action[RTE_COLOR_RED] =
|
||||
MTR_POLICER_ACTION_DROP;
|
||||
|
||||
ret = rte_mtr_create(port_id, counter, ¶ms, 1, &error);
|
||||
if (ret != 0) {
|
||||
printf("Port %u create meter idx(%d) error(%d) message: %s\n",
|
||||
|
@ -17427,7 +17427,6 @@ cmdline_parse_ctx_t main_ctx[] = {
|
||||
(cmdline_parse_inst_t *)&cmd_del_port_meter,
|
||||
(cmdline_parse_inst_t *)&cmd_set_port_meter_profile,
|
||||
(cmdline_parse_inst_t *)&cmd_set_port_meter_dscp_table,
|
||||
(cmdline_parse_inst_t *)&cmd_set_port_meter_policer_action,
|
||||
(cmdline_parse_inst_t *)&cmd_set_port_meter_stats_mask,
|
||||
(cmdline_parse_inst_t *)&cmd_show_port_meter_stats,
|
||||
(cmdline_parse_inst_t *)&cmd_mcast_addr,
|
||||
|
@ -146,53 +146,6 @@ parse_meter_color_str(char *c_str, uint32_t *use_prev_meter_color,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
string_to_policer_action(char *s)
|
||||
{
|
||||
if ((strcmp(s, "G") == 0) || (strcmp(s, "g") == 0))
|
||||
return MTR_POLICER_ACTION_COLOR_GREEN;
|
||||
|
||||
if ((strcmp(s, "Y") == 0) || (strcmp(s, "y") == 0))
|
||||
return MTR_POLICER_ACTION_COLOR_YELLOW;
|
||||
|
||||
if ((strcmp(s, "R") == 0) || (strcmp(s, "r") == 0))
|
||||
return MTR_POLICER_ACTION_COLOR_RED;
|
||||
|
||||
if ((strcmp(s, "D") == 0) || (strcmp(s, "d") == 0))
|
||||
return MTR_POLICER_ACTION_DROP;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_policer_action_string(char *p_str, uint32_t action_mask,
|
||||
enum rte_mtr_policer_action actions[])
|
||||
{
|
||||
char *token;
|
||||
int count = __builtin_popcount(action_mask);
|
||||
int g_color = 0, y_color = 0, action, i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
token = strtok_r(p_str, PARSE_DELIMITER, &p_str);
|
||||
if (token == NULL)
|
||||
return -1;
|
||||
|
||||
action = string_to_policer_action(token);
|
||||
if (action == -1)
|
||||
return -1;
|
||||
|
||||
if (g_color == 0 && (action_mask & 0x1)) {
|
||||
actions[RTE_COLOR_GREEN] = action;
|
||||
g_color = 1;
|
||||
} else if (y_color == 0 && (action_mask & 0x2)) {
|
||||
actions[RTE_COLOR_YELLOW] = action;
|
||||
y_color = 1;
|
||||
} else
|
||||
actions[RTE_COLOR_RED] = action;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_multi_token_string(char *t_str, uint16_t *port_id,
|
||||
uint32_t *mtr_id, enum rte_color **dscp_table)
|
||||
@ -302,10 +255,6 @@ static void cmd_show_port_meter_cap_parsed(void *parsed_result,
|
||||
cap.color_aware_trtcm_rfc2698_supported);
|
||||
printf("cap.color_aware_trtcm_rfc4115_supported %" PRId32 "\n",
|
||||
cap.color_aware_trtcm_rfc4115_supported);
|
||||
printf("cap.policer_action_recolor_supported %" PRId32 "\n",
|
||||
cap.policer_action_recolor_supported);
|
||||
printf("cap.policer_action_drop_supported %" PRId32 "\n",
|
||||
cap.policer_action_drop_supported);
|
||||
printf("cap.srtcm_rfc2697_byte_mode_supported %" PRId32 "\n",
|
||||
cap.srtcm_rfc2697_byte_mode_supported);
|
||||
printf("cap.srtcm_rfc2697_packet_mode_supported %" PRId32 "\n",
|
||||
@ -842,12 +791,6 @@ static void cmd_create_port_meter_parsed(void *parsed_result,
|
||||
else
|
||||
params.meter_enable = 0;
|
||||
|
||||
params.action[RTE_COLOR_GREEN] =
|
||||
string_to_policer_action(res->g_action);
|
||||
params.action[RTE_COLOR_YELLOW] =
|
||||
string_to_policer_action(res->y_action);
|
||||
params.action[RTE_COLOR_RED] =
|
||||
string_to_policer_action(res->r_action);
|
||||
params.stats_mask = res->statistics_mask;
|
||||
|
||||
ret = rte_mtr_create(port_id, mtr_id, ¶ms, shared, &error);
|
||||
@ -1215,121 +1158,6 @@ cmdline_parse_inst_t cmd_set_port_meter_dscp_table = {
|
||||
},
|
||||
};
|
||||
|
||||
/* *** Set Port Meter Policer Action *** */
|
||||
struct cmd_set_port_meter_policer_action_result {
|
||||
cmdline_fixed_string_t set;
|
||||
cmdline_fixed_string_t port;
|
||||
cmdline_fixed_string_t meter;
|
||||
cmdline_fixed_string_t policer;
|
||||
cmdline_fixed_string_t action;
|
||||
uint16_t port_id;
|
||||
uint32_t mtr_id;
|
||||
uint32_t action_mask;
|
||||
cmdline_multi_string_t policer_action;
|
||||
};
|
||||
|
||||
cmdline_parse_token_string_t cmd_set_port_meter_policer_action_set =
|
||||
TOKEN_STRING_INITIALIZER(
|
||||
struct cmd_set_port_meter_policer_action_result, set, "set");
|
||||
cmdline_parse_token_string_t cmd_set_port_meter_policer_action_port =
|
||||
TOKEN_STRING_INITIALIZER(
|
||||
struct cmd_set_port_meter_policer_action_result, port, "port");
|
||||
cmdline_parse_token_string_t cmd_set_port_meter_policer_action_meter =
|
||||
TOKEN_STRING_INITIALIZER(
|
||||
struct cmd_set_port_meter_policer_action_result, meter,
|
||||
"meter");
|
||||
cmdline_parse_token_string_t cmd_set_port_meter_policer_action_policer =
|
||||
TOKEN_STRING_INITIALIZER(
|
||||
struct cmd_set_port_meter_policer_action_result, policer,
|
||||
"policer");
|
||||
cmdline_parse_token_string_t cmd_set_port_meter_policer_action_action =
|
||||
TOKEN_STRING_INITIALIZER(
|
||||
struct cmd_set_port_meter_policer_action_result, action,
|
||||
"action");
|
||||
cmdline_parse_token_num_t cmd_set_port_meter_policer_action_port_id =
|
||||
TOKEN_NUM_INITIALIZER(
|
||||
struct cmd_set_port_meter_policer_action_result, port_id,
|
||||
RTE_UINT16);
|
||||
cmdline_parse_token_num_t cmd_set_port_meter_policer_action_mtr_id =
|
||||
TOKEN_NUM_INITIALIZER(
|
||||
struct cmd_set_port_meter_policer_action_result, mtr_id,
|
||||
RTE_UINT32);
|
||||
cmdline_parse_token_num_t cmd_set_port_meter_policer_action_action_mask =
|
||||
TOKEN_NUM_INITIALIZER(
|
||||
struct cmd_set_port_meter_policer_action_result, action_mask,
|
||||
RTE_UINT32);
|
||||
cmdline_parse_token_string_t cmd_set_port_meter_policer_action_policer_action =
|
||||
TOKEN_STRING_INITIALIZER(
|
||||
struct cmd_set_port_meter_policer_action_result,
|
||||
policer_action, TOKEN_STRING_MULTI);
|
||||
|
||||
static void cmd_set_port_meter_policer_action_parsed(void *parsed_result,
|
||||
__rte_unused struct cmdline *cl,
|
||||
__rte_unused void *data)
|
||||
{
|
||||
struct cmd_set_port_meter_policer_action_result *res = parsed_result;
|
||||
enum rte_mtr_policer_action *actions;
|
||||
struct rte_mtr_error error;
|
||||
uint32_t mtr_id = res->mtr_id;
|
||||
uint32_t action_mask = res->action_mask;
|
||||
uint16_t port_id = res->port_id;
|
||||
char *p_str = res->policer_action;
|
||||
int ret;
|
||||
|
||||
if (port_id_is_invalid(port_id, ENABLED_WARN))
|
||||
return;
|
||||
|
||||
/* Check: action mask */
|
||||
if (action_mask == 0 || (action_mask & (~0x7UL))) {
|
||||
printf(" Policer action mask not correct (error)\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Allocate memory for policer actions */
|
||||
actions = (enum rte_mtr_policer_action *)malloc(RTE_COLORS *
|
||||
sizeof(enum rte_mtr_policer_action));
|
||||
if (actions == NULL) {
|
||||
printf("Memory for policer actions not allocated (error)\n");
|
||||
return;
|
||||
}
|
||||
/* Parse policer action string */
|
||||
ret = parse_policer_action_string(p_str, action_mask, actions);
|
||||
if (ret) {
|
||||
printf(" Policer action string parse error\n");
|
||||
free(actions);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = rte_mtr_policer_actions_update(port_id, mtr_id,
|
||||
action_mask, actions, &error);
|
||||
if (ret != 0) {
|
||||
free(actions);
|
||||
print_err_msg(&error);
|
||||
return;
|
||||
}
|
||||
|
||||
free(actions);
|
||||
}
|
||||
|
||||
cmdline_parse_inst_t cmd_set_port_meter_policer_action = {
|
||||
.f = cmd_set_port_meter_policer_action_parsed,
|
||||
.data = NULL,
|
||||
.help_str = "set port meter policer action <port_id> <mtr_id> "
|
||||
"<action_mask> <action0> [<action1> <action2>]",
|
||||
.tokens = {
|
||||
(void *)&cmd_set_port_meter_policer_action_set,
|
||||
(void *)&cmd_set_port_meter_policer_action_port,
|
||||
(void *)&cmd_set_port_meter_policer_action_meter,
|
||||
(void *)&cmd_set_port_meter_policer_action_policer,
|
||||
(void *)&cmd_set_port_meter_policer_action_action,
|
||||
(void *)&cmd_set_port_meter_policer_action_port_id,
|
||||
(void *)&cmd_set_port_meter_policer_action_mtr_id,
|
||||
(void *)&cmd_set_port_meter_policer_action_action_mask,
|
||||
(void *)&cmd_set_port_meter_policer_action_policer_action,
|
||||
NULL,
|
||||
},
|
||||
};
|
||||
|
||||
/* *** Set Port Meter Stats Mask *** */
|
||||
struct cmd_set_port_meter_stats_mask_result {
|
||||
cmdline_fixed_string_t set;
|
||||
|
@ -17,7 +17,6 @@ extern cmdline_parse_inst_t cmd_disable_port_meter;
|
||||
extern cmdline_parse_inst_t cmd_del_port_meter;
|
||||
extern cmdline_parse_inst_t cmd_set_port_meter_profile;
|
||||
extern cmdline_parse_inst_t cmd_set_port_meter_dscp_table;
|
||||
extern cmdline_parse_inst_t cmd_set_port_meter_policer_action;
|
||||
extern cmdline_parse_inst_t cmd_set_port_meter_stats_mask;
|
||||
extern cmdline_parse_inst_t cmd_show_port_meter_stats;
|
||||
|
||||
|
@ -2982,6 +2982,27 @@ The current conntrack context information could be queried via the
|
||||
| ``reserved`` | reserved bits |
|
||||
+----------------+-------------------------------------------------+
|
||||
|
||||
Action: ``METER_COLOR``
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Color the packet to reflect the meter color result.
|
||||
|
||||
The meter action must be configured before meter color action.
|
||||
Meter color action is set to a color to reflect the meter color result.
|
||||
Set the meter color in the mbuf to the selected color.
|
||||
The meter color action output color is the output color of the packet,
|
||||
which is set in the packet meta-data (i.e. struct ``rte_mbuf::sched::color``)
|
||||
|
||||
.. _table_rte_flow_action_meter_color:
|
||||
|
||||
.. table:: METER_COLOR
|
||||
|
||||
+-----------------+--------------+
|
||||
| Field | Value |
|
||||
+=================+==============+
|
||||
| ``meter_color`` | Packet color |
|
||||
+-----------------+--------------+
|
||||
|
||||
Negative types
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -56,18 +56,10 @@ The processing done for each input packet hitting an MTR object is:
|
||||
color blind mode, which is equivalent to considering all input packets
|
||||
initially colored as green.
|
||||
|
||||
* Policing: There is a separate policer action configured for each meter
|
||||
output color, which can:
|
||||
|
||||
* Drop the packet.
|
||||
|
||||
* Keep the same packet color: the policer output color matches the meter
|
||||
output color (essentially a no-op action).
|
||||
|
||||
* Recolor the packet: the policer output color is set to a different color
|
||||
than the meter output color. The policer output color is the output color
|
||||
of the packet, which is set in the packet meta-data (i.e. struct
|
||||
``rte_mbuf::sched::color``).
|
||||
* There is a meter policy API to manage pre-defined policies for meter.
|
||||
Any rte_flow action list can be configured per color for each policy.
|
||||
A meter object configured with a policy executes the actions per packet
|
||||
according to the packet color.
|
||||
|
||||
* Statistics: The set of counters maintained for each MTR object is
|
||||
configurable and subject to the implementation support. This set includes
|
||||
|
@ -88,11 +88,12 @@ New Features
|
||||
* Added new field ``queue_state`` to ``rte_eth_txq_info`` structure to
|
||||
provide indicated Tx queue state.
|
||||
|
||||
* **Added support for meter PPS profile.**
|
||||
* **Updated meter API.**
|
||||
|
||||
Added packet mode in the meter profile parameters data structures
|
||||
to support metering traffic by packet per second (PPS),
|
||||
in addition to the initial bytes per second (BPS) mode (value 0).
|
||||
* Added packet mode in the meter profile parameters data structures
|
||||
to support metering traffic by packet per second (PPS),
|
||||
in addition to the initial bytes per second (BPS) mode (value 0).
|
||||
* Added support of pre-defined meter policy via flow action list per color.
|
||||
|
||||
* **Added packet integrity match to flow rules.**
|
||||
|
||||
@ -308,6 +309,11 @@ API Changes
|
||||
The action ``RTE_FLOW_ACTION_TYPE_SHARED`` is deprecated and can be
|
||||
replaced with ``RTE_FLOW_ACTION_TYPE_INDIRECT``.
|
||||
|
||||
* ethdev: The experimental function ``rte_mtr_policer_actions_update()``,
|
||||
the enum ``rte_mtr_policer_action``, and the struct members
|
||||
``policer_action_recolor_supported`` and ``policer_action_drop_supported``
|
||||
have been removed.
|
||||
|
||||
|
||||
ABI Changes
|
||||
-----------
|
||||
|
@ -2831,24 +2831,6 @@ Set meter dscp table for the ethernet device::
|
||||
testpmd> set port meter dscp table (port_id) (mtr_id) [(dscp_tbl_entry0) \
|
||||
(dscp_tbl_entry1)...(dscp_tbl_entry63)]
|
||||
|
||||
set port meter policer action
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Set meter policer action for the ethernet device::
|
||||
|
||||
testpmd> set port meter policer action (port_id) (mtr_id) (action_mask) \
|
||||
(action0) [(action1) (action1)]
|
||||
|
||||
where:
|
||||
|
||||
* ``action_mask``: Bit mask indicating which policer actions need to be
|
||||
updated. One or more policer actions can be updated in a single function
|
||||
invocation. To update the policer action associated with color C, bit
|
||||
(1 << C) needs to be set in *action_mask* and element at position C
|
||||
in the *actions* array needs to be valid.
|
||||
* ``actionx``: Policer action for the color x,
|
||||
RTE_MTR_GREEN <= x < RTE_MTR_COLORS
|
||||
|
||||
set port meter stats mask
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -593,14 +593,6 @@ struct mlx5_dev_shared_port {
|
||||
/* Modify this value if enum rte_mtr_color changes. */
|
||||
#define RTE_MTR_DROPPED RTE_COLORS
|
||||
|
||||
/* Meter policer statistics */
|
||||
struct mlx5_flow_policer_stats {
|
||||
uint32_t pass_cnt;
|
||||
/**< Color counter for pass. */
|
||||
uint32_t drop_cnt;
|
||||
/**< Color counter for drop. */
|
||||
};
|
||||
|
||||
/* Meter table structure. */
|
||||
struct mlx5_meter_domain_info {
|
||||
struct mlx5_flow_tbl_resource *tbl;
|
||||
@ -639,24 +631,12 @@ struct mlx5_meter_domains_infos {
|
||||
|
||||
/* Meter parameter structure. */
|
||||
struct mlx5_flow_meter_info {
|
||||
uint32_t meter_id;
|
||||
/**< Meter id. */
|
||||
struct mlx5_flow_meter_profile *profile;
|
||||
/**< Meter profile parameters. */
|
||||
rte_spinlock_t sl; /**< Meter action spinlock. */
|
||||
/** Policer actions (per meter output color). */
|
||||
enum rte_mtr_policer_action action[RTE_COLORS];
|
||||
/** Set of stats counters to be enabled.
|
||||
* @see enum rte_mtr_stats_type
|
||||
*/
|
||||
uint32_t green_bytes:1;
|
||||
/** Set green bytes stats to be enabled. */
|
||||
uint32_t green_pkts:1;
|
||||
/** Set green packets stats to be enabled. */
|
||||
uint32_t red_bytes:1;
|
||||
/** Set red bytes stats to be enabled. */
|
||||
uint32_t red_pkts:1;
|
||||
/** Set red packets stats to be enabled. */
|
||||
uint32_t bytes_dropped:1;
|
||||
/** Set bytes dropped stats to be enabled. */
|
||||
uint32_t pkts_dropped:1;
|
||||
@ -691,8 +671,8 @@ struct mlx5_flow_meter_info {
|
||||
uint32_t transfer:1;
|
||||
struct mlx5_meter_domains_infos *mfts;
|
||||
/**< Flow table created for this meter. */
|
||||
struct mlx5_flow_policer_stats policer_stats;
|
||||
/**< Meter policer statistics. */
|
||||
uint32_t drop_cnt;
|
||||
/**< Color counter for drop. */
|
||||
uint32_t ref_cnt;
|
||||
/**< Use count. */
|
||||
struct mlx5_indexed_pool *flow_ipool;
|
||||
|
@ -6655,52 +6655,6 @@ mlx5_flow_destroy_mtr_tbls(struct rte_eth_dev *dev,
|
||||
return fops->destroy_mtr_tbls(dev, tbls);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare policer rules.
|
||||
*
|
||||
* @param[in] dev
|
||||
* Pointer to Ethernet device.
|
||||
* @param[in] fm
|
||||
* Pointer to flow meter structure.
|
||||
* @param[in] attr
|
||||
* Pointer to flow attributes.
|
||||
*
|
||||
* @return
|
||||
* 0 on success, -1 otherwise.
|
||||
*/
|
||||
int
|
||||
mlx5_flow_prepare_policer_rules(struct rte_eth_dev *dev,
|
||||
struct mlx5_flow_meter_info *fm,
|
||||
const struct rte_flow_attr *attr)
|
||||
{
|
||||
const struct mlx5_flow_driver_ops *fops;
|
||||
|
||||
fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
|
||||
return fops->prepare_policer_rules(dev, fm, attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy policer rules.
|
||||
*
|
||||
* @param[in] fm
|
||||
* Pointer to flow meter structure.
|
||||
* @param[in] attr
|
||||
* Pointer to flow attributes.
|
||||
*
|
||||
* @return
|
||||
* 0 on success, -1 otherwise.
|
||||
*/
|
||||
int
|
||||
mlx5_flow_destroy_policer_rules(struct rte_eth_dev *dev,
|
||||
struct mlx5_flow_meter_info *fm,
|
||||
const struct rte_flow_attr *attr)
|
||||
{
|
||||
const struct mlx5_flow_driver_ops *fops;
|
||||
|
||||
fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
|
||||
return fops->destroy_policer_rules(dev, fm, attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate the needed aso flow meter id.
|
||||
*
|
||||
|
@ -838,6 +838,8 @@ struct mlx5_legacy_flow_meter {
|
||||
/* Must be the first in struct. */
|
||||
TAILQ_ENTRY(mlx5_legacy_flow_meter) next;
|
||||
/**< Pointer to the next flow meter structure. */
|
||||
uint32_t meter_id;
|
||||
/**< Meter id. */
|
||||
uint32_t idx; /* Index to meter object. */
|
||||
};
|
||||
|
||||
@ -1096,14 +1098,6 @@ typedef struct mlx5_meter_domains_infos *(*mlx5_flow_create_mtr_tbls_t)
|
||||
(struct rte_eth_dev *dev);
|
||||
typedef int (*mlx5_flow_destroy_mtr_tbls_t)(struct rte_eth_dev *dev,
|
||||
struct mlx5_meter_domains_infos *tbls);
|
||||
typedef int (*mlx5_flow_create_policer_rules_t)
|
||||
(struct rte_eth_dev *dev,
|
||||
struct mlx5_flow_meter_info *fm,
|
||||
const struct rte_flow_attr *attr);
|
||||
typedef int (*mlx5_flow_destroy_policer_rules_t)
|
||||
(struct rte_eth_dev *dev,
|
||||
const struct mlx5_flow_meter_info *fm,
|
||||
const struct rte_flow_attr *attr);
|
||||
typedef uint32_t (*mlx5_flow_mtr_alloc_t)
|
||||
(struct rte_eth_dev *dev);
|
||||
typedef void (*mlx5_flow_mtr_free_t)(struct rte_eth_dev *dev,
|
||||
@ -1160,8 +1154,6 @@ struct mlx5_flow_driver_ops {
|
||||
mlx5_flow_query_t query;
|
||||
mlx5_flow_create_mtr_tbls_t create_mtr_tbls;
|
||||
mlx5_flow_destroy_mtr_tbls_t destroy_mtr_tbls;
|
||||
mlx5_flow_create_policer_rules_t prepare_policer_rules;
|
||||
mlx5_flow_destroy_policer_rules_t destroy_policer_rules;
|
||||
mlx5_flow_mtr_alloc_t create_meter;
|
||||
mlx5_flow_mtr_free_t free_meter;
|
||||
mlx5_flow_counter_alloc_t counter_alloc;
|
||||
@ -1391,12 +1383,6 @@ struct mlx5_meter_domains_infos *mlx5_flow_create_mtr_tbls
|
||||
(struct rte_eth_dev *dev);
|
||||
int mlx5_flow_destroy_mtr_tbls(struct rte_eth_dev *dev,
|
||||
struct mlx5_meter_domains_infos *tbl);
|
||||
int mlx5_flow_prepare_policer_rules(struct rte_eth_dev *dev,
|
||||
struct mlx5_flow_meter_info *fm,
|
||||
const struct rte_flow_attr *attr);
|
||||
int mlx5_flow_destroy_policer_rules(struct rte_eth_dev *dev,
|
||||
struct mlx5_flow_meter_info *fm,
|
||||
const struct rte_flow_attr *attr);
|
||||
int mlx5_flow_meter_flush(struct rte_eth_dev *dev,
|
||||
struct rte_mtr_error *error);
|
||||
int mlx5_flow_dv_discover_counter_offset_support(struct rte_eth_dev *dev);
|
||||
|
@ -808,8 +808,8 @@ mlx5_aso_meter_update_by_wqe(struct mlx5_dev_ctx_shared *sh,
|
||||
/* Waiting for wqe resource. */
|
||||
rte_delay_us_sleep(MLX5_ASO_WQE_CQE_RESPONSE_DELAY);
|
||||
} while (--poll_wqe_times);
|
||||
DRV_LOG(ERR, "Fail to send WQE for ASO meter %d",
|
||||
mtr->fm.meter_id);
|
||||
DRV_LOG(ERR, "Fail to send WQE for ASO meter offset %d",
|
||||
mtr->offset);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -844,7 +844,7 @@ mlx5_aso_mtr_wait(struct mlx5_dev_ctx_shared *sh,
|
||||
/* Waiting for CQE ready. */
|
||||
rte_delay_us_sleep(MLX5_ASO_WQE_CQE_RESPONSE_DELAY);
|
||||
} while (--poll_cqe_times);
|
||||
DRV_LOG(ERR, "Fail to poll CQE ready for ASO meter %d",
|
||||
mtr->fm.meter_id);
|
||||
DRV_LOG(ERR, "Fail to poll CQE ready for ASO meter offset %d",
|
||||
mtr->offset);
|
||||
return -1;
|
||||
}
|
||||
|
@ -185,31 +185,6 @@ flow_dv_attr_init(const struct rte_flow_item *item, union flow_dv_attr *attr,
|
||||
attr->valid = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert rte_mtr_color to mlx5 color.
|
||||
*
|
||||
* @param[in] rcol
|
||||
* rte_mtr_color.
|
||||
*
|
||||
* @return
|
||||
* mlx5 color.
|
||||
*/
|
||||
static int
|
||||
rte_col_2_mlx5_col(enum rte_color rcol)
|
||||
{
|
||||
switch (rcol) {
|
||||
case RTE_COLOR_GREEN:
|
||||
return MLX5_FLOW_COLOR_GREEN;
|
||||
case RTE_COLOR_YELLOW:
|
||||
return MLX5_FLOW_COLOR_YELLOW;
|
||||
case RTE_COLOR_RED:
|
||||
return MLX5_FLOW_COLOR_RED;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return MLX5_FLOW_COLOR_UNDEFINED;
|
||||
}
|
||||
|
||||
struct field_modify_info {
|
||||
uint32_t size; /* Size of field in protocol header, in bytes. */
|
||||
uint32_t offset; /* Offset of field in protocol header, in bytes. */
|
||||
@ -6026,12 +6001,10 @@ flow_dv_mtr_pool_create(struct rte_eth_dev *dev,
|
||||
mtrmng->n_valid++;
|
||||
for (i = 1; i < MLX5_ASO_MTRS_PER_POOL; ++i) {
|
||||
pool->mtrs[i].offset = i;
|
||||
pool->mtrs[i].fm.meter_id = UINT32_MAX;
|
||||
LIST_INSERT_HEAD(&mtrmng->meters,
|
||||
&pool->mtrs[i], next);
|
||||
}
|
||||
pool->mtrs[0].offset = 0;
|
||||
pool->mtrs[0].fm.meter_id = UINT32_MAX;
|
||||
*mtr_free = &pool->mtrs[0];
|
||||
return pool;
|
||||
}
|
||||
@ -6055,7 +6028,6 @@ flow_dv_aso_mtr_release_to_pool(struct rte_eth_dev *dev, uint32_t mtr_idx)
|
||||
rte_spinlock_lock(&mtrmng->mtrsl);
|
||||
memset(&aso_mtr->fm, 0, sizeof(struct mlx5_flow_meter_info));
|
||||
aso_mtr->state = ASO_METER_FREE;
|
||||
aso_mtr->fm.meter_id = UINT32_MAX;
|
||||
LIST_INSERT_HEAD(&mtrmng->meters, aso_mtr, next);
|
||||
rte_spinlock_unlock(&mtrmng->mtrsl);
|
||||
}
|
||||
@ -6095,8 +6067,8 @@ flow_dv_mtr_alloc(struct rte_eth_dev *dev)
|
||||
mtr_free->state = ASO_METER_WAIT;
|
||||
rte_spinlock_unlock(&mtrmng->mtrsl);
|
||||
pool = container_of(mtr_free,
|
||||
struct mlx5_aso_mtr_pool,
|
||||
mtrs[mtr_free->offset]);
|
||||
struct mlx5_aso_mtr_pool,
|
||||
mtrs[mtr_free->offset]);
|
||||
mtr_idx = MLX5_MAKE_MTR_IDX(pool->index, mtr_free->offset);
|
||||
if (!mtr_free->fm.meter_action) {
|
||||
#ifdef HAVE_MLX5_DR_CREATE_ACTION_ASO
|
||||
@ -13721,433 +13693,6 @@ flow_dv_create_mtr_tbl(struct rte_eth_dev *dev)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the meter table matchers.
|
||||
* Lock free, (mutex should be acquired by caller).
|
||||
*
|
||||
* @param[in] dev
|
||||
* Pointer to Ethernet device.
|
||||
* @param[in,out] dtb
|
||||
* Pointer to DV meter table.
|
||||
*
|
||||
* @return
|
||||
* Always 0.
|
||||
*/
|
||||
static int
|
||||
flow_dv_destroy_mtr_matchers(struct rte_eth_dev *dev,
|
||||
struct mlx5_meter_domain_info *dtb)
|
||||
{
|
||||
struct mlx5_priv *priv = dev->data->dev_private;
|
||||
struct mlx5_flow_tbl_data_entry *tbl;
|
||||
|
||||
if (!priv->config.dv_flow_en)
|
||||
return 0;
|
||||
if (dtb->drop_matcher) {
|
||||
tbl = container_of(dtb->drop_matcher->tbl, typeof(*tbl), tbl);
|
||||
mlx5_cache_unregister(&tbl->matchers,
|
||||
&dtb->drop_matcher->entry);
|
||||
dtb->drop_matcher = NULL;
|
||||
}
|
||||
if (dtb->color_matcher) {
|
||||
tbl = container_of(dtb->color_matcher->tbl, typeof(*tbl), tbl);
|
||||
mlx5_cache_unregister(&tbl->matchers,
|
||||
&dtb->color_matcher->entry);
|
||||
dtb->color_matcher = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the matchers for meter table.
|
||||
*
|
||||
* @param[in] dev
|
||||
* Pointer to Ethernet device.
|
||||
* @param[in] color_reg_c_idx
|
||||
* Reg C index for color match.
|
||||
* @param[in] mtr_id_reg_c_idx
|
||||
* Reg C index for meter_id match.
|
||||
* @param[in] mtr_id_mask
|
||||
* Mask for meter_id match criteria.
|
||||
* @param[in,out] dtb
|
||||
* Pointer to DV meter table.
|
||||
* @param[out] error
|
||||
* Perform verbose error reporting if not NULL.
|
||||
*
|
||||
* @return
|
||||
* 0 on success, a negative errno value otherwise and rte_errno is set.
|
||||
*/
|
||||
static int
|
||||
flow_dv_prepare_mtr_matchers(struct rte_eth_dev *dev,
|
||||
uint32_t color_reg_c_idx,
|
||||
uint32_t mtr_id_reg_c_idx,
|
||||
uint32_t mtr_id_mask,
|
||||
struct mlx5_meter_domain_info *dtb,
|
||||
struct rte_flow_error *error)
|
||||
{
|
||||
struct mlx5_priv *priv = dev->data->dev_private;
|
||||
struct mlx5_flow_tbl_data_entry *tbl_data;
|
||||
struct mlx5_cache_entry *entry;
|
||||
struct mlx5_flow_dv_matcher matcher = {
|
||||
.mask = {
|
||||
.size = sizeof(matcher.mask.buf) -
|
||||
MLX5_ST_SZ_BYTES(fte_match_set_misc4),
|
||||
},
|
||||
.tbl = dtb->tbl,
|
||||
};
|
||||
struct mlx5_flow_dv_match_params value = {
|
||||
.size = sizeof(value.buf) -
|
||||
MLX5_ST_SZ_BYTES(fte_match_set_misc4),
|
||||
};
|
||||
struct mlx5_flow_cb_ctx ctx = {
|
||||
.error = error,
|
||||
.data = &matcher,
|
||||
};
|
||||
uint32_t color_mask = (UINT32_C(1) << MLX5_MTR_COLOR_BITS) - 1;
|
||||
|
||||
tbl_data = container_of(dtb->tbl, struct mlx5_flow_tbl_data_entry, tbl);
|
||||
if (!dtb->drop_matcher) {
|
||||
/* Create matchers for Drop. */
|
||||
flow_dv_match_meta_reg(matcher.mask.buf, value.buf,
|
||||
mtr_id_reg_c_idx, 0, mtr_id_mask);
|
||||
matcher.priority = MLX5_REG_BITS * 2 - priv->max_mtr_bits;
|
||||
matcher.crc = rte_raw_cksum((const void *)matcher.mask.buf,
|
||||
matcher.mask.size);
|
||||
entry = mlx5_cache_register(&tbl_data->matchers, &ctx);
|
||||
if (!entry) {
|
||||
DRV_LOG(ERR, "Failed to register meter drop matcher.");
|
||||
return -1;
|
||||
}
|
||||
dtb->drop_matcher =
|
||||
container_of(entry, struct mlx5_flow_dv_matcher, entry);
|
||||
}
|
||||
if (!dtb->color_matcher) {
|
||||
/* Create matchers for Color + meter_id. */
|
||||
if (priv->mtr_reg_share) {
|
||||
flow_dv_match_meta_reg(matcher.mask.buf, value.buf,
|
||||
color_reg_c_idx, 0,
|
||||
(mtr_id_mask | color_mask));
|
||||
} else {
|
||||
flow_dv_match_meta_reg(matcher.mask.buf, value.buf,
|
||||
color_reg_c_idx, 0, color_mask);
|
||||
flow_dv_match_meta_reg(matcher.mask.buf, value.buf,
|
||||
mtr_id_reg_c_idx, 0, mtr_id_mask);
|
||||
}
|
||||
matcher.priority = MLX5_REG_BITS - priv->max_mtr_bits;
|
||||
matcher.crc = rte_raw_cksum((const void *)matcher.mask.buf,
|
||||
matcher.mask.size);
|
||||
entry = mlx5_cache_register(&tbl_data->matchers, &ctx);
|
||||
if (!entry) {
|
||||
DRV_LOG(ERR, "Failed to register meter color matcher.");
|
||||
return -1;
|
||||
}
|
||||
dtb->color_matcher =
|
||||
container_of(entry, struct mlx5_flow_dv_matcher, entry);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy domain policer rule.
|
||||
*
|
||||
* @param[in] dev
|
||||
* Pointer to Ethernet device.
|
||||
* @param[in] dt
|
||||
* Pointer to domain table.
|
||||
*/
|
||||
static void
|
||||
flow_dv_destroy_domain_policer_rule(struct rte_eth_dev *dev,
|
||||
struct mlx5_meter_domain_info *dt)
|
||||
{
|
||||
if (dt->drop_rule) {
|
||||
claim_zero(mlx5_flow_os_destroy_flow(dt->drop_rule));
|
||||
dt->drop_rule = NULL;
|
||||
}
|
||||
if (dt->green_rule) {
|
||||
claim_zero(mlx5_flow_os_destroy_flow(dt->green_rule));
|
||||
dt->green_rule = NULL;
|
||||
}
|
||||
flow_dv_destroy_mtr_matchers(dev, dt);
|
||||
if (dt->jump_actn) {
|
||||
claim_zero(mlx5_flow_os_destroy_flow_action(dt->jump_actn));
|
||||
dt->jump_actn = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy policer rules.
|
||||
*
|
||||
* @param[in] dev
|
||||
* Pointer to Ethernet device.
|
||||
* @param[in] fm
|
||||
* Pointer to flow meter structure.
|
||||
* @param[in] attr
|
||||
* Pointer to flow attributes.
|
||||
*
|
||||
* @return
|
||||
* Always 0.
|
||||
*/
|
||||
static int
|
||||
flow_dv_destroy_policer_rules(struct rte_eth_dev *dev,
|
||||
const struct mlx5_flow_meter_info *fm,
|
||||
const struct rte_flow_attr *attr)
|
||||
{
|
||||
struct mlx5_meter_domains_infos *mtb = fm ? fm->mfts : NULL;
|
||||
|
||||
if (!mtb)
|
||||
return 0;
|
||||
if (attr->egress)
|
||||
flow_dv_destroy_domain_policer_rule(dev, &mtb->egress);
|
||||
if (attr->ingress)
|
||||
flow_dv_destroy_domain_policer_rule(dev, &mtb->ingress);
|
||||
if (attr->transfer)
|
||||
flow_dv_destroy_domain_policer_rule(dev, &mtb->transfer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create specify domain meter policer rule.
|
||||
*
|
||||
* @param[in] dev
|
||||
* Pointer to Ethernet device.
|
||||
* @param[in] fm
|
||||
* Pointer to flow meter structure.
|
||||
* @param[in] mtr_idx
|
||||
* meter index.
|
||||
* @param[in] mtb
|
||||
* Pointer to DV meter table set.
|
||||
* @param[out] drop_rule
|
||||
* The address of pointer saving drop rule.
|
||||
* @param[out] color_rule
|
||||
* The address of pointer saving green rule.
|
||||
*
|
||||
* @return
|
||||
* 0 on success, -1 otherwise.
|
||||
*/
|
||||
static int
|
||||
flow_dv_create_policer_forward_rule(struct rte_eth_dev *dev,
|
||||
struct mlx5_flow_meter_info *fm,
|
||||
uint32_t mtr_idx,
|
||||
struct mlx5_meter_domain_info *dtb,
|
||||
void **drop_rule,
|
||||
void **green_rule)
|
||||
{
|
||||
struct mlx5_priv *priv = dev->data->dev_private;
|
||||
struct mlx5_flow_dv_match_params matcher = {
|
||||
.size = sizeof(matcher.buf) -
|
||||
MLX5_ST_SZ_BYTES(fte_match_set_misc4),
|
||||
};
|
||||
struct mlx5_flow_dv_match_params value = {
|
||||
.size = sizeof(value.buf) -
|
||||
MLX5_ST_SZ_BYTES(fte_match_set_misc4),
|
||||
};
|
||||
struct mlx5_meter_domains_infos *mtb = fm->mfts;
|
||||
struct rte_flow_error error;
|
||||
uint32_t color_reg_c = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR,
|
||||
0, &error);
|
||||
uint32_t mtr_id_reg_c = mlx5_flow_get_reg_id(dev, MLX5_MTR_ID,
|
||||
0, &error);
|
||||
uint8_t mtr_id_offset = priv->mtr_reg_share ? MLX5_MTR_COLOR_BITS : 0;
|
||||
uint32_t mtr_id_mask =
|
||||
((UINT32_C(1) << priv->max_mtr_bits) - 1) << mtr_id_offset;
|
||||
void *actions[METER_ACTIONS];
|
||||
int i;
|
||||
int ret = 0;
|
||||
|
||||
/* Create jump action. */
|
||||
if (!dtb->jump_actn)
|
||||
ret = mlx5_flow_os_create_flow_action_dest_flow_tbl
|
||||
(dtb->sfx_tbl->obj, &dtb->jump_actn);
|
||||
if (ret) {
|
||||
DRV_LOG(ERR, "Failed to create policer jump action.");
|
||||
goto error;
|
||||
}
|
||||
/* Prepare matchers. */
|
||||
if (!dtb->drop_matcher || !dtb->color_matcher) {
|
||||
ret = flow_dv_prepare_mtr_matchers(dev, color_reg_c,
|
||||
mtr_id_reg_c, mtr_id_mask,
|
||||
dtb, &error);
|
||||
if (ret) {
|
||||
DRV_LOG(ERR, "Failed to setup matchers for mtr table.");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
/* Create Drop flow, matching meter_id only. */
|
||||
i = 0;
|
||||
flow_dv_match_meta_reg(matcher.buf, value.buf, mtr_id_reg_c,
|
||||
(mtr_idx << mtr_id_offset), UINT32_MAX);
|
||||
if (mtb->drop_count)
|
||||
actions[i++] = mtb->drop_count;
|
||||
actions[i++] = priv->sh->dr_drop_action;
|
||||
ret = mlx5_flow_os_create_flow(dtb->drop_matcher->matcher_object,
|
||||
(void *)&value, i, actions, drop_rule);
|
||||
if (ret) {
|
||||
DRV_LOG(ERR, "Failed to create meter policer drop rule.");
|
||||
goto error;
|
||||
}
|
||||
/* Create flow matching Green color + meter_id. */
|
||||
i = 0;
|
||||
if (priv->mtr_reg_share) {
|
||||
flow_dv_match_meta_reg(matcher.buf, value.buf, color_reg_c,
|
||||
((mtr_idx << mtr_id_offset) |
|
||||
rte_col_2_mlx5_col(RTE_COLOR_GREEN)),
|
||||
UINT32_MAX);
|
||||
} else {
|
||||
flow_dv_match_meta_reg(matcher.buf, value.buf, color_reg_c,
|
||||
rte_col_2_mlx5_col(RTE_COLOR_GREEN),
|
||||
UINT32_MAX);
|
||||
flow_dv_match_meta_reg(matcher.buf, value.buf, mtr_id_reg_c,
|
||||
mtr_idx, UINT32_MAX);
|
||||
}
|
||||
if (mtb->green_count)
|
||||
actions[i++] = mtb->green_count;
|
||||
actions[i++] = dtb->jump_actn;
|
||||
ret = mlx5_flow_os_create_flow(dtb->color_matcher->matcher_object,
|
||||
(void *)&value, i, actions, green_rule);
|
||||
if (ret) {
|
||||
DRV_LOG(ERR, "Failed to create meter policer color rule.");
|
||||
goto error;
|
||||
}
|
||||
return 0;
|
||||
error:
|
||||
rte_errno = errno;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare policer rules for all domains.
|
||||
* If meter already initialized, this will replace all old rules with new ones.
|
||||
*
|
||||
* @param[in] dev
|
||||
* Pointer to Ethernet device.
|
||||
* @param[in] fm
|
||||
* Pointer to flow meter structure.
|
||||
* @param[in] attr
|
||||
* Pointer to flow attributes.
|
||||
*
|
||||
* @return
|
||||
* 0 on success, -1 otherwise.
|
||||
*/
|
||||
static int
|
||||
flow_dv_prepare_policer_rules(struct rte_eth_dev *dev,
|
||||
struct mlx5_flow_meter_info *fm,
|
||||
const struct rte_flow_attr *attr)
|
||||
{
|
||||
struct mlx5_priv *priv = dev->data->dev_private;
|
||||
struct mlx5_meter_domains_infos *mtb = fm->mfts;
|
||||
bool initialized = false;
|
||||
struct mlx5_flow_counter *cnt;
|
||||
void *egress_drop_rule = NULL;
|
||||
void *egress_green_rule = NULL;
|
||||
void *ingress_drop_rule = NULL;
|
||||
void *ingress_green_rule = NULL;
|
||||
void *transfer_drop_rule = NULL;
|
||||
void *transfer_green_rule = NULL;
|
||||
uint32_t mtr_idx;
|
||||
int ret;
|
||||
|
||||
/* Get the statistics counters for green/drop. */
|
||||
if (fm->policer_stats.pass_cnt) {
|
||||
cnt = flow_dv_counter_get_by_idx(dev,
|
||||
fm->policer_stats.pass_cnt,
|
||||
NULL);
|
||||
mtb->green_count = cnt->action;
|
||||
} else {
|
||||
mtb->green_count = NULL;
|
||||
}
|
||||
if (fm->policer_stats.drop_cnt) {
|
||||
cnt = flow_dv_counter_get_by_idx(dev,
|
||||
fm->policer_stats.drop_cnt,
|
||||
NULL);
|
||||
mtb->drop_count = cnt->action;
|
||||
} else {
|
||||
mtb->drop_count = NULL;
|
||||
}
|
||||
/**
|
||||
* If flow meter has been initialized, all policer rules
|
||||
* are created. So can get if meter initialized by checking
|
||||
* any policer rule.
|
||||
*/
|
||||
if (mtb->egress.drop_rule)
|
||||
initialized = true;
|
||||
if (priv->sh->meter_aso_en) {
|
||||
struct mlx5_aso_mtr *aso_mtr = NULL;
|
||||
struct mlx5_aso_mtr_pool *pool;
|
||||
|
||||
aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
|
||||
pool = container_of(aso_mtr, struct mlx5_aso_mtr_pool,
|
||||
mtrs[aso_mtr->offset]);
|
||||
mtr_idx = MLX5_MAKE_MTR_IDX(pool->index, aso_mtr->offset);
|
||||
} else {
|
||||
struct mlx5_legacy_flow_meter *legacy_fm;
|
||||
|
||||
legacy_fm = container_of(fm, struct mlx5_legacy_flow_meter, fm);
|
||||
mtr_idx = legacy_fm->idx;
|
||||
}
|
||||
if (attr->egress) {
|
||||
ret = flow_dv_create_policer_forward_rule(dev,
|
||||
fm, mtr_idx, &mtb->egress,
|
||||
&egress_drop_rule, &egress_green_rule);
|
||||
if (ret) {
|
||||
DRV_LOG(ERR, "Failed to create egress policer.");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
if (attr->ingress) {
|
||||
ret = flow_dv_create_policer_forward_rule(dev,
|
||||
fm, mtr_idx, &mtb->ingress,
|
||||
&ingress_drop_rule, &ingress_green_rule);
|
||||
if (ret) {
|
||||
DRV_LOG(ERR, "Failed to create ingress policer.");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
if (attr->transfer) {
|
||||
ret = flow_dv_create_policer_forward_rule(dev,
|
||||
fm, mtr_idx, &mtb->transfer,
|
||||
&transfer_drop_rule, &transfer_green_rule);
|
||||
if (ret) {
|
||||
DRV_LOG(ERR, "Failed to create transfer policer.");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
/* Replace old flows if existing. */
|
||||
if (mtb->egress.drop_rule)
|
||||
claim_zero(mlx5_flow_os_destroy_flow(mtb->egress.drop_rule));
|
||||
if (mtb->egress.green_rule)
|
||||
claim_zero(mlx5_flow_os_destroy_flow(mtb->egress.green_rule));
|
||||
if (mtb->ingress.drop_rule)
|
||||
claim_zero(mlx5_flow_os_destroy_flow(mtb->ingress.drop_rule));
|
||||
if (mtb->ingress.green_rule)
|
||||
claim_zero(mlx5_flow_os_destroy_flow(mtb->ingress.green_rule));
|
||||
if (mtb->transfer.drop_rule)
|
||||
claim_zero(mlx5_flow_os_destroy_flow(mtb->transfer.drop_rule));
|
||||
if (mtb->transfer.green_rule)
|
||||
claim_zero(mlx5_flow_os_destroy_flow(mtb->transfer.green_rule));
|
||||
mtb->egress.drop_rule = egress_drop_rule;
|
||||
mtb->egress.green_rule = egress_green_rule;
|
||||
mtb->ingress.drop_rule = ingress_drop_rule;
|
||||
mtb->ingress.green_rule = ingress_green_rule;
|
||||
mtb->transfer.drop_rule = transfer_drop_rule;
|
||||
mtb->transfer.green_rule = transfer_green_rule;
|
||||
return 0;
|
||||
error:
|
||||
if (egress_drop_rule)
|
||||
claim_zero(mlx5_flow_os_destroy_flow(egress_drop_rule));
|
||||
if (egress_green_rule)
|
||||
claim_zero(mlx5_flow_os_destroy_flow(egress_green_rule));
|
||||
if (ingress_drop_rule)
|
||||
claim_zero(mlx5_flow_os_destroy_flow(ingress_drop_rule));
|
||||
if (ingress_green_rule)
|
||||
claim_zero(mlx5_flow_os_destroy_flow(ingress_green_rule));
|
||||
if (transfer_drop_rule)
|
||||
claim_zero(mlx5_flow_os_destroy_flow(transfer_drop_rule));
|
||||
if (transfer_green_rule)
|
||||
claim_zero(mlx5_flow_os_destroy_flow(transfer_green_rule));
|
||||
if (!initialized)
|
||||
flow_dv_destroy_policer_rules(dev, fm, attr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the batch counter support in root table.
|
||||
*
|
||||
@ -14442,8 +13987,6 @@ const struct mlx5_flow_driver_ops mlx5_flow_dv_drv_ops = {
|
||||
.query = flow_dv_query,
|
||||
.create_mtr_tbls = flow_dv_create_mtr_tbl,
|
||||
.destroy_mtr_tbls = flow_dv_destroy_mtr_tbl,
|
||||
.prepare_policer_rules = flow_dv_prepare_policer_rules,
|
||||
.destroy_policer_rules = flow_dv_destroy_policer_rules,
|
||||
.create_meter = flow_dv_mtr_alloc,
|
||||
.free_meter = flow_dv_aso_mtr_release_to_pool,
|
||||
.counter_alloc = flow_dv_counter_allocate,
|
||||
|
@ -329,7 +329,6 @@ mlx5_flow_mtr_cap_get(struct rte_eth_dev *dev,
|
||||
cap->chaining_n_mtrs_per_flow_max = 1; /* Chaining is not supported. */
|
||||
cap->meter_srtcm_rfc2697_n_max = qattr->flow_meter_old ? cap->n_max : 0;
|
||||
cap->meter_rate_max = 1ULL << 40; /* 1 Tera tokens per sec. */
|
||||
cap->policer_action_drop_supported = 1;
|
||||
cap->stats_mask = RTE_MTR_STATS_N_BYTES_DROPPED |
|
||||
RTE_MTR_STATS_N_PKTS_DROPPED;
|
||||
return 0;
|
||||
@ -436,90 +435,6 @@ mlx5_flow_meter_profile_delete(struct rte_eth_dev *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert wrong color setting action to verbose error.
|
||||
*
|
||||
* @param[in] action
|
||||
* Policy color action.
|
||||
*
|
||||
* @return
|
||||
* Verbose meter color error type.
|
||||
*/
|
||||
static inline enum rte_mtr_error_type
|
||||
action2error(enum rte_mtr_policer_action action)
|
||||
{
|
||||
switch (action) {
|
||||
case MTR_POLICER_ACTION_COLOR_GREEN:
|
||||
return RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN;
|
||||
case MTR_POLICER_ACTION_COLOR_YELLOW:
|
||||
return RTE_MTR_ERROR_TYPE_POLICER_ACTION_YELLOW;
|
||||
case MTR_POLICER_ACTION_COLOR_RED:
|
||||
return RTE_MTR_ERROR_TYPE_POLICER_ACTION_RED;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return RTE_MTR_ERROR_TYPE_UNSPECIFIED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check meter validation.
|
||||
*
|
||||
* @param[in] priv
|
||||
* Pointer to mlx5 private data structure.
|
||||
* @param[in] meter_id
|
||||
* Meter id.
|
||||
* @param[in] params
|
||||
* Pointer to rte meter parameters.
|
||||
* @param[out] error
|
||||
* Pointer to rte meter error structure.
|
||||
*
|
||||
* @return
|
||||
* 0 on success, a negative errno value otherwise and rte_errno is set.
|
||||
*/
|
||||
static int
|
||||
mlx5_flow_meter_validate(struct mlx5_priv *priv, uint32_t meter_id,
|
||||
struct rte_mtr_params *params,
|
||||
struct rte_mtr_error *error)
|
||||
{
|
||||
/* Meter must use global drop action. */
|
||||
if (!priv->sh->dr_drop_action)
|
||||
return -rte_mtr_error_set(error, ENOTSUP,
|
||||
RTE_MTR_ERROR_TYPE_MTR_PARAMS,
|
||||
NULL,
|
||||
"No drop action ready for meter.");
|
||||
/* Meter params must not be NULL. */
|
||||
if (params == NULL)
|
||||
return -rte_mtr_error_set(error, EINVAL,
|
||||
RTE_MTR_ERROR_TYPE_MTR_PARAMS,
|
||||
NULL, "Meter object params null.");
|
||||
/* Previous meter color is not supported. */
|
||||
if (params->use_prev_mtr_color)
|
||||
return -rte_mtr_error_set(error, ENOTSUP,
|
||||
RTE_MTR_ERROR_TYPE_MTR_PARAMS,
|
||||
NULL,
|
||||
"Previous meter color "
|
||||
"not supported.");
|
||||
/* Validate policer settings. */
|
||||
if (params->action[RTE_COLOR_RED] != MTR_POLICER_ACTION_DROP)
|
||||
return -rte_mtr_error_set
|
||||
(error, ENOTSUP,
|
||||
action2error(params->action[RTE_COLOR_RED]),
|
||||
NULL,
|
||||
"Red color only supports drop action.");
|
||||
if (params->action[RTE_COLOR_GREEN] != MTR_POLICER_ACTION_COLOR_GREEN)
|
||||
return -rte_mtr_error_set
|
||||
(error, ENOTSUP,
|
||||
action2error(params->action[RTE_COLOR_GREEN]),
|
||||
NULL,
|
||||
"Green color only supports recolor green action.");
|
||||
/* Validate meter id. */
|
||||
if (mlx5_flow_meter_find(priv, meter_id, NULL))
|
||||
return -rte_mtr_error_set(error, EEXIST,
|
||||
RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
|
||||
"Meter object already exists.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify the flow meter action.
|
||||
*
|
||||
@ -629,167 +544,14 @@ static void
|
||||
mlx5_flow_meter_stats_enable_update(struct mlx5_flow_meter_info *fm,
|
||||
uint64_t stats_mask)
|
||||
{
|
||||
fm->green_bytes = (stats_mask & RTE_MTR_STATS_N_BYTES_GREEN) ? 1 : 0;
|
||||
fm->green_pkts = (stats_mask & RTE_MTR_STATS_N_PKTS_GREEN) ? 1 : 0;
|
||||
fm->red_bytes = (stats_mask & RTE_MTR_STATS_N_BYTES_RED) ? 1 : 0;
|
||||
fm->red_pkts = (stats_mask & RTE_MTR_STATS_N_PKTS_RED) ? 1 : 0;
|
||||
fm->bytes_dropped =
|
||||
(stats_mask & RTE_MTR_STATS_N_BYTES_DROPPED) ? 1 : 0;
|
||||
fm->pkts_dropped = (stats_mask & RTE_MTR_STATS_N_PKTS_DROPPED) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create meter rules.
|
||||
*
|
||||
* @param[in] dev
|
||||
* Pointer to Ethernet device.
|
||||
* @param[in] meter_id
|
||||
* Meter id.
|
||||
* @param[in] params
|
||||
* Pointer to rte meter parameters.
|
||||
* @param[in] shared
|
||||
* Meter shared with other flow or not.
|
||||
* @param[out] error
|
||||
* Pointer to rte meter error structure.
|
||||
*
|
||||
* @return
|
||||
* 0 on success, a negative errno value otherwise and rte_errno is set.
|
||||
*/
|
||||
static int
|
||||
mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,
|
||||
struct rte_mtr_params *params, int shared,
|
||||
struct rte_mtr_error *error)
|
||||
{
|
||||
struct mlx5_priv *priv = dev->data->dev_private;
|
||||
struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
|
||||
struct mlx5_flow_meter_profile *fmp;
|
||||
struct mlx5_legacy_flow_meter *legacy_fm;
|
||||
struct mlx5_flow_meter_info *fm;
|
||||
const struct rte_flow_attr attr = {
|
||||
.ingress = 1,
|
||||
.egress = 1,
|
||||
.transfer = priv->config.dv_esw_en ? 1 : 0,
|
||||
};
|
||||
struct mlx5_indexed_pool_config flow_ipool_cfg = {
|
||||
.size = 0,
|
||||
.trunk_size = 64,
|
||||
.need_lock = 1,
|
||||
.type = "mlx5_flow_mtr_flow_id_pool",
|
||||
};
|
||||
struct mlx5_aso_mtr *aso_mtr;
|
||||
union mlx5_l3t_data data;
|
||||
uint32_t mtr_idx;
|
||||
int ret;
|
||||
uint8_t mtr_id_bits;
|
||||
uint8_t mtr_reg_bits = priv->mtr_reg_share ?
|
||||
MLX5_MTR_IDLE_BITS_IN_COLOR_REG : MLX5_REG_BITS;
|
||||
|
||||
if (!priv->mtr_en)
|
||||
return -rte_mtr_error_set(error, ENOTSUP,
|
||||
RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
|
||||
"Meter is not supported");
|
||||
/* Validate the parameters. */
|
||||
ret = mlx5_flow_meter_validate(priv, meter_id, params, error);
|
||||
if (ret)
|
||||
return ret;
|
||||
/* Meter profile must exist. */
|
||||
fmp = mlx5_flow_meter_profile_find(priv, params->meter_profile_id);
|
||||
if (fmp == NULL)
|
||||
return -rte_mtr_error_set(error, ENOENT,
|
||||
RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
|
||||
NULL, "Meter profile id not valid.");
|
||||
/* Allocate the flow meter memory. */
|
||||
if (priv->sh->meter_aso_en) {
|
||||
mtr_idx = mlx5_flow_mtr_alloc(dev);
|
||||
if (!mtr_idx)
|
||||
return -rte_mtr_error_set(error, ENOMEM,
|
||||
RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
|
||||
"Memory alloc failed for meter.");
|
||||
aso_mtr = mlx5_aso_meter_by_idx(priv, mtr_idx);
|
||||
fm = &aso_mtr->fm;
|
||||
} else {
|
||||
legacy_fm = mlx5_ipool_zmalloc
|
||||
(priv->sh->ipool[MLX5_IPOOL_MTR], &mtr_idx);
|
||||
if (legacy_fm == NULL)
|
||||
return -rte_mtr_error_set(error, ENOMEM,
|
||||
RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
|
||||
"Memory alloc failed for meter.");
|
||||
legacy_fm->idx = mtr_idx;
|
||||
fm = &legacy_fm->fm;
|
||||
}
|
||||
mtr_id_bits = MLX5_REG_BITS - __builtin_clz(mtr_idx);
|
||||
if ((mtr_id_bits + priv->max_mtr_flow_bits) > mtr_reg_bits) {
|
||||
DRV_LOG(ERR, "Meter number exceeds max limit.");
|
||||
goto error;
|
||||
}
|
||||
if (mtr_id_bits > priv->max_mtr_bits)
|
||||
priv->max_mtr_bits = mtr_id_bits;
|
||||
/* Fill the flow meter parameters. */
|
||||
fm->meter_id = meter_id;
|
||||
fm->profile = fmp;
|
||||
memcpy(fm->action, params->action, sizeof(params->action));
|
||||
mlx5_flow_meter_stats_enable_update(fm, params->stats_mask);
|
||||
/* Alloc policer counters. */
|
||||
if (fm->green_bytes || fm->green_pkts) {
|
||||
fm->policer_stats.pass_cnt = mlx5_counter_alloc(dev);
|
||||
if (!fm->policer_stats.pass_cnt)
|
||||
goto error;
|
||||
}
|
||||
if (fm->red_bytes || fm->red_pkts ||
|
||||
fm->bytes_dropped || fm->pkts_dropped) {
|
||||
fm->policer_stats.drop_cnt = mlx5_counter_alloc(dev);
|
||||
if (!fm->policer_stats.drop_cnt)
|
||||
goto error;
|
||||
}
|
||||
fm->mfts = mlx5_flow_create_mtr_tbls(dev);
|
||||
if (!fm->mfts)
|
||||
goto error;
|
||||
ret = mlx5_flow_prepare_policer_rules(dev, fm, &attr);
|
||||
if (ret)
|
||||
goto error;
|
||||
/* Add to the flow meter list. */
|
||||
if (!priv->sh->meter_aso_en)
|
||||
TAILQ_INSERT_TAIL(fms, legacy_fm, next);
|
||||
fm->active_state = 1; /* Config meter starts as active. */
|
||||
fm->is_enable = 1;
|
||||
fm->shared = !!shared;
|
||||
__atomic_add_fetch(&fm->profile->ref_cnt, 1, __ATOMIC_RELAXED);
|
||||
fm->flow_ipool = mlx5_ipool_create(&flow_ipool_cfg);
|
||||
if (!fm->flow_ipool)
|
||||
goto error;
|
||||
rte_spinlock_init(&fm->sl);
|
||||
/* If ASO meter supported, allocate ASO flow meter. */
|
||||
if (priv->sh->meter_aso_en) {
|
||||
aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
|
||||
ret = mlx5_aso_meter_update_by_wqe(priv->sh, aso_mtr);
|
||||
if (ret)
|
||||
goto error;
|
||||
data.dword = mtr_idx;
|
||||
if (mlx5_l3t_set_entry(priv->mtr_idx_tbl, meter_id, &data))
|
||||
goto error;
|
||||
}
|
||||
return 0;
|
||||
error:
|
||||
mlx5_flow_destroy_policer_rules(dev, fm, &attr);
|
||||
mlx5_flow_destroy_mtr_tbls(dev, fm->mfts);
|
||||
/* Free policer counters. */
|
||||
if (fm->policer_stats.pass_cnt)
|
||||
mlx5_counter_free(dev, fm->policer_stats.pass_cnt);
|
||||
if (fm->policer_stats.drop_cnt)
|
||||
mlx5_counter_free(dev, fm->policer_stats.drop_cnt);
|
||||
if (priv->sh->meter_aso_en)
|
||||
mlx5_flow_mtr_free(dev, mtr_idx);
|
||||
else
|
||||
mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR], mtr_idx);
|
||||
return -rte_mtr_error_set(error, -ret,
|
||||
RTE_MTR_ERROR_TYPE_UNSPECIFIED,
|
||||
NULL, "Failed to create devx meter.");
|
||||
}
|
||||
|
||||
static int
|
||||
mlx5_flow_meter_params_flush(struct rte_eth_dev *dev,
|
||||
struct mlx5_flow_meter_info *fm,
|
||||
const struct rte_flow_attr *attr,
|
||||
uint32_t mtr_idx)
|
||||
{
|
||||
struct mlx5_priv *priv = dev->data->dev_private;
|
||||
@ -810,15 +572,12 @@ mlx5_flow_meter_params_flush(struct rte_eth_dev *dev,
|
||||
legacy_fm = container_of(fm, struct mlx5_legacy_flow_meter, fm);
|
||||
TAILQ_REMOVE(fms, legacy_fm, next);
|
||||
}
|
||||
/* Free policer counters. */
|
||||
if (fm->policer_stats.pass_cnt)
|
||||
mlx5_counter_free(dev, fm->policer_stats.pass_cnt);
|
||||
if (fm->policer_stats.drop_cnt)
|
||||
mlx5_counter_free(dev, fm->policer_stats.drop_cnt);
|
||||
/* Free drop counters. */
|
||||
if (fm->drop_cnt)
|
||||
mlx5_counter_free(dev, fm->drop_cnt);
|
||||
/* Free meter flow table. */
|
||||
if (fm->flow_ipool)
|
||||
mlx5_ipool_destroy(fm->flow_ipool);
|
||||
mlx5_flow_destroy_policer_rules(dev, fm, attr);
|
||||
mlx5_flow_destroy_mtr_tbls(dev, fm->mfts);
|
||||
if (priv->sh->meter_aso_en)
|
||||
mlx5_flow_mtr_free(dev, mtr_idx);
|
||||
@ -847,11 +606,6 @@ mlx5_flow_meter_destroy(struct rte_eth_dev *dev, uint32_t meter_id,
|
||||
{
|
||||
struct mlx5_priv *priv = dev->data->dev_private;
|
||||
struct mlx5_flow_meter_info *fm;
|
||||
const struct rte_flow_attr attr = {
|
||||
.ingress = 1,
|
||||
.egress = 1,
|
||||
.transfer = priv->config.dv_esw_en ? 1 : 0,
|
||||
};
|
||||
uint32_t mtr_idx = 0;
|
||||
|
||||
if (!priv->mtr_en)
|
||||
@ -876,7 +630,7 @@ mlx5_flow_meter_destroy(struct rte_eth_dev *dev, uint32_t meter_id,
|
||||
"Fail to delete ASO Meter in index table.");
|
||||
}
|
||||
/* Destroy the meter profile. */
|
||||
if (mlx5_flow_meter_params_flush(dev, fm, &attr, mtr_idx))
|
||||
if (mlx5_flow_meter_params_flush(dev, fm, mtr_idx))
|
||||
return -rte_mtr_error_set(error, EINVAL,
|
||||
RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
|
||||
NULL, "MTR object meter profile invalid.");
|
||||
@ -1102,13 +856,6 @@ mlx5_flow_meter_stats_update(struct rte_eth_dev *dev,
|
||||
{
|
||||
struct mlx5_priv *priv = dev->data->dev_private;
|
||||
struct mlx5_flow_meter_info *fm;
|
||||
const struct rte_flow_attr attr = {
|
||||
.ingress = 1,
|
||||
.egress = 1,
|
||||
.transfer = priv->config.dv_esw_en ? 1 : 0,
|
||||
};
|
||||
bool need_updated = false;
|
||||
struct mlx5_flow_policer_stats old_policer_stats;
|
||||
|
||||
if (!priv->mtr_en)
|
||||
return -rte_mtr_error_set(error, ENOTSUP,
|
||||
@ -1120,69 +867,6 @@ mlx5_flow_meter_stats_update(struct rte_eth_dev *dev,
|
||||
return -rte_mtr_error_set(error, ENOENT,
|
||||
RTE_MTR_ERROR_TYPE_MTR_ID,
|
||||
NULL, "Meter object id not valid.");
|
||||
old_policer_stats.pass_cnt = 0;
|
||||
old_policer_stats.drop_cnt = 0;
|
||||
if (!!((RTE_MTR_STATS_N_PKTS_GREEN |
|
||||
RTE_MTR_STATS_N_BYTES_GREEN) & stats_mask) !=
|
||||
!!fm->policer_stats.pass_cnt) {
|
||||
need_updated = true;
|
||||
if (fm->policer_stats.pass_cnt) {
|
||||
old_policer_stats.pass_cnt = fm->policer_stats.pass_cnt;
|
||||
fm->policer_stats.pass_cnt = 0;
|
||||
} else {
|
||||
fm->policer_stats.pass_cnt =
|
||||
mlx5_counter_alloc(dev);
|
||||
if (!fm->policer_stats.pass_cnt)
|
||||
return -rte_mtr_error_set(error, ENOMEM,
|
||||
RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
|
||||
"Counter alloc failed for meter.");
|
||||
}
|
||||
}
|
||||
if (!!((RTE_MTR_STATS_N_PKTS_RED | RTE_MTR_STATS_N_BYTES_RED |
|
||||
RTE_MTR_STATS_N_PKTS_DROPPED | RTE_MTR_STATS_N_BYTES_DROPPED) &
|
||||
stats_mask) !=
|
||||
!!fm->policer_stats.drop_cnt) {
|
||||
need_updated = true;
|
||||
if (fm->policer_stats.drop_cnt) {
|
||||
old_policer_stats.drop_cnt = fm->policer_stats.drop_cnt;
|
||||
fm->policer_stats.drop_cnt = 0;
|
||||
} else {
|
||||
fm->policer_stats.drop_cnt =
|
||||
mlx5_counter_alloc(dev);
|
||||
if (!fm->policer_stats.drop_cnt)
|
||||
return -rte_mtr_error_set(error, ENOMEM,
|
||||
RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
|
||||
"Counter alloc failed for meter.");
|
||||
}
|
||||
}
|
||||
if (need_updated) {
|
||||
if (mlx5_flow_prepare_policer_rules(dev, fm, &attr)) {
|
||||
if (fm->policer_stats.pass_cnt &&
|
||||
fm->policer_stats.pass_cnt !=
|
||||
old_policer_stats.pass_cnt)
|
||||
mlx5_counter_free(dev,
|
||||
fm->policer_stats.pass_cnt);
|
||||
fm->policer_stats.pass_cnt =
|
||||
old_policer_stats.pass_cnt;
|
||||
if (fm->policer_stats.drop_cnt &&
|
||||
fm->policer_stats.drop_cnt !=
|
||||
old_policer_stats.drop_cnt)
|
||||
mlx5_counter_free(dev,
|
||||
fm->policer_stats.drop_cnt);
|
||||
fm->policer_stats.pass_cnt =
|
||||
old_policer_stats.pass_cnt;
|
||||
return -rte_mtr_error_set(error, ENOTSUP,
|
||||
RTE_MTR_ERROR_TYPE_UNSPECIFIED,
|
||||
NULL, "Failed to create meter policer rules.");
|
||||
}
|
||||
/* Free old policer counters. */
|
||||
if (old_policer_stats.pass_cnt)
|
||||
mlx5_counter_free(dev,
|
||||
old_policer_stats.pass_cnt);
|
||||
if (old_policer_stats.drop_cnt)
|
||||
mlx5_counter_free(dev,
|
||||
old_policer_stats.drop_cnt);
|
||||
}
|
||||
mlx5_flow_meter_stats_enable_update(fm, stats_mask);
|
||||
return 0;
|
||||
}
|
||||
@ -1216,7 +900,6 @@ mlx5_flow_meter_stats_read(struct rte_eth_dev *dev,
|
||||
{
|
||||
struct mlx5_priv *priv = dev->data->dev_private;
|
||||
struct mlx5_flow_meter_info *fm;
|
||||
struct mlx5_flow_policer_stats *ps;
|
||||
uint64_t pkts;
|
||||
uint64_t bytes;
|
||||
int ret = 0;
|
||||
@ -1231,35 +914,14 @@ mlx5_flow_meter_stats_read(struct rte_eth_dev *dev,
|
||||
return -rte_mtr_error_set(error, ENOENT,
|
||||
RTE_MTR_ERROR_TYPE_MTR_ID,
|
||||
NULL, "Meter object id not valid.");
|
||||
ps = &fm->policer_stats;
|
||||
*stats_mask = 0;
|
||||
if (fm->green_bytes)
|
||||
*stats_mask |= RTE_MTR_STATS_N_BYTES_GREEN;
|
||||
if (fm->green_pkts)
|
||||
*stats_mask |= RTE_MTR_STATS_N_PKTS_GREEN;
|
||||
if (fm->red_bytes)
|
||||
*stats_mask |= RTE_MTR_STATS_N_BYTES_RED;
|
||||
if (fm->red_pkts)
|
||||
*stats_mask |= RTE_MTR_STATS_N_PKTS_RED;
|
||||
if (fm->bytes_dropped)
|
||||
*stats_mask |= RTE_MTR_STATS_N_BYTES_DROPPED;
|
||||
if (fm->pkts_dropped)
|
||||
*stats_mask |= RTE_MTR_STATS_N_PKTS_DROPPED;
|
||||
memset(stats, 0, sizeof(*stats));
|
||||
if (ps->pass_cnt) {
|
||||
ret = mlx5_counter_query(dev, ps->pass_cnt, clear, &pkts,
|
||||
&bytes);
|
||||
if (ret)
|
||||
goto error;
|
||||
/* If need to read the packets, set it. */
|
||||
if (fm->green_pkts)
|
||||
stats->n_pkts[RTE_COLOR_GREEN] = pkts;
|
||||
/* If need to read the bytes, set it. */
|
||||
if (fm->green_bytes)
|
||||
stats->n_bytes[RTE_COLOR_GREEN] = bytes;
|
||||
}
|
||||
if (ps->drop_cnt) {
|
||||
ret = mlx5_counter_query(dev, ps->drop_cnt, clear, &pkts,
|
||||
if (fm->drop_cnt) {
|
||||
ret = mlx5_counter_query(dev, fm->drop_cnt, clear, &pkts,
|
||||
&bytes);
|
||||
if (ret)
|
||||
goto error;
|
||||
@ -1273,20 +935,18 @@ mlx5_flow_meter_stats_read(struct rte_eth_dev *dev,
|
||||
return 0;
|
||||
error:
|
||||
return -rte_mtr_error_set(error, ret, RTE_MTR_ERROR_TYPE_STATS, NULL,
|
||||
"Failed to read policer counters.");
|
||||
"Failed to read meter drop counters.");
|
||||
}
|
||||
|
||||
static const struct rte_mtr_ops mlx5_flow_mtr_ops = {
|
||||
.capabilities_get = mlx5_flow_mtr_cap_get,
|
||||
.meter_profile_add = mlx5_flow_meter_profile_add,
|
||||
.meter_profile_delete = mlx5_flow_meter_profile_delete,
|
||||
.create = mlx5_flow_meter_create,
|
||||
.destroy = mlx5_flow_meter_destroy,
|
||||
.meter_enable = mlx5_flow_meter_enable,
|
||||
.meter_disable = mlx5_flow_meter_disable,
|
||||
.meter_profile_update = mlx5_flow_meter_profile_update,
|
||||
.meter_dscp_table_update = NULL,
|
||||
.policer_actions_update = NULL,
|
||||
.stats_update = mlx5_flow_meter_stats_update,
|
||||
.stats_read = mlx5_flow_meter_stats_read,
|
||||
};
|
||||
@ -1344,12 +1004,11 @@ mlx5_flow_meter_find(struct mlx5_priv *priv, uint32_t meter_id,
|
||||
aso_mtr = mlx5_aso_meter_by_idx(priv, data.dword);
|
||||
/* Remove reference taken by the mlx5_l3t_get_entry. */
|
||||
mlx5_l3t_clear_entry(priv->mtr_idx_tbl, meter_id);
|
||||
MLX5_ASSERT(meter_id == aso_mtr->fm.meter_id);
|
||||
rte_spinlock_unlock(&mtrmng->mtrsl);
|
||||
return &aso_mtr->fm;
|
||||
}
|
||||
TAILQ_FOREACH(legacy_fm, fms, next)
|
||||
if (meter_id == legacy_fm->fm.meter_id) {
|
||||
if (meter_id == legacy_fm->meter_id) {
|
||||
if (mtr_idx)
|
||||
*mtr_idx = legacy_fm->idx;
|
||||
return &legacy_fm->fm;
|
||||
@ -1517,11 +1176,6 @@ mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error)
|
||||
struct mlx5_legacy_flow_meter *legacy_fm;
|
||||
struct mlx5_flow_meter_info *fm;
|
||||
struct mlx5_aso_mtr_pool *mtr_pool;
|
||||
const struct rte_flow_attr attr = {
|
||||
.ingress = 1,
|
||||
.egress = 1,
|
||||
.transfer = priv->config.dv_esw_en ? 1 : 0,
|
||||
};
|
||||
void *tmp;
|
||||
uint32_t i, offset, mtr_idx;
|
||||
|
||||
@ -1533,9 +1187,8 @@ mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error)
|
||||
offset++) {
|
||||
fm = &mtr_pool->mtrs[offset].fm;
|
||||
mtr_idx = MLX5_MAKE_MTR_IDX(i, offset);
|
||||
if (fm->meter_id != UINT32_MAX &&
|
||||
mlx5_flow_meter_params_flush(dev,
|
||||
fm, &attr, mtr_idx))
|
||||
if (mlx5_flow_meter_params_flush(dev,
|
||||
fm, mtr_idx))
|
||||
return -rte_mtr_error_set
|
||||
(error, EINVAL,
|
||||
RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
|
||||
@ -1545,7 +1198,7 @@ mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error)
|
||||
} else {
|
||||
TAILQ_FOREACH_SAFE(legacy_fm, fms, next, tmp) {
|
||||
fm = &legacy_fm->fm;
|
||||
if (mlx5_flow_meter_params_flush(dev, fm, &attr, 0))
|
||||
if (mlx5_flow_meter_params_flush(dev, fm, 0))
|
||||
return -rte_mtr_error_set(error, EINVAL,
|
||||
RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
|
||||
NULL, "MTR object meter profile invalid.");
|
||||
|
@ -1166,6 +1166,7 @@ flow_rule_action_get(struct pmd_internals *softnic,
|
||||
{
|
||||
struct softnic_table_action_profile *profile;
|
||||
struct softnic_table_action_profile_params *params;
|
||||
struct softnic_mtr_meter_policy *policy;
|
||||
int n_jump_queue_rss_drop = 0;
|
||||
int n_count = 0;
|
||||
int n_mark = 0;
|
||||
@ -1621,15 +1622,25 @@ flow_rule_action_get(struct pmd_internals *softnic,
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Meter policy must exist */
|
||||
policy = softnic_mtr_meter_policy_find(softnic,
|
||||
m->params.meter_policy_id);
|
||||
if (policy == NULL) {
|
||||
rte_flow_error_set(error,
|
||||
EINVAL,
|
||||
RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
|
||||
NULL,
|
||||
"METER: fail to find meter policy");
|
||||
return -1;
|
||||
}
|
||||
/* RTE_TABLE_ACTION_METER */
|
||||
rule_action->mtr.mtr[0].meter_profile_id = meter_profile_id;
|
||||
rule_action->mtr.mtr[0].policer[RTE_COLOR_GREEN] =
|
||||
softnic_table_action_policer(m->params.action[RTE_COLOR_GREEN]);
|
||||
policy->policer[RTE_COLOR_GREEN];
|
||||
rule_action->mtr.mtr[0].policer[RTE_COLOR_YELLOW] =
|
||||
softnic_table_action_policer(m->params.action[RTE_COLOR_YELLOW]);
|
||||
policy->policer[RTE_COLOR_YELLOW];
|
||||
rule_action->mtr.mtr[0].policer[RTE_COLOR_RED] =
|
||||
softnic_table_action_policer(m->params.action[RTE_COLOR_RED]);
|
||||
policy->policer[RTE_COLOR_RED];
|
||||
rule_action->mtr.tc_mask = 1;
|
||||
rule_action->action_mask |= 1 << RTE_TABLE_ACTION_MTR;
|
||||
break;
|
||||
|
@ -83,6 +83,16 @@ struct softnic_mtr_meter_profile {
|
||||
|
||||
TAILQ_HEAD(softnic_mtr_meter_profile_list, softnic_mtr_meter_profile);
|
||||
|
||||
/* MTR meter policy */
|
||||
struct softnic_mtr_meter_policy {
|
||||
TAILQ_ENTRY(softnic_mtr_meter_policy) node;
|
||||
uint32_t meter_policy_id;
|
||||
enum rte_table_action_policer policer[RTE_COLORS];
|
||||
uint32_t n_users;
|
||||
};
|
||||
|
||||
TAILQ_HEAD(softnic_mtr_meter_policy_list, softnic_mtr_meter_policy);
|
||||
|
||||
/* MTR meter object */
|
||||
struct softnic_mtr {
|
||||
TAILQ_ENTRY(softnic_mtr) node;
|
||||
@ -95,6 +105,7 @@ TAILQ_HEAD(softnic_mtr_list, softnic_mtr);
|
||||
|
||||
struct mtr_internals {
|
||||
struct softnic_mtr_meter_profile_list meter_profiles;
|
||||
struct softnic_mtr_meter_policy_list meter_policies;
|
||||
struct softnic_mtr_list mtrs;
|
||||
};
|
||||
|
||||
@ -678,6 +689,10 @@ struct softnic_mtr_meter_profile *
|
||||
softnic_mtr_meter_profile_find(struct pmd_internals *p,
|
||||
uint32_t meter_profile_id);
|
||||
|
||||
struct softnic_mtr_meter_policy *
|
||||
softnic_mtr_meter_policy_find(struct pmd_internals *p,
|
||||
uint32_t meter_policy_id);
|
||||
|
||||
extern const struct rte_mtr_ops pmd_mtr_ops;
|
||||
|
||||
/**
|
||||
@ -841,9 +856,6 @@ softnic_table_action_profile_create(struct pmd_internals *p,
|
||||
const char *name,
|
||||
struct softnic_table_action_profile_params *params);
|
||||
|
||||
enum rte_table_action_policer
|
||||
softnic_table_action_policer(enum rte_mtr_policer_action action);
|
||||
|
||||
/**
|
||||
* Pipeline
|
||||
*/
|
||||
|
@ -65,27 +65,6 @@ softnic_mtr_meter_profile_find(struct pmd_internals *p,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
enum rte_table_action_policer
|
||||
softnic_table_action_policer(enum rte_mtr_policer_action action)
|
||||
{
|
||||
switch (action) {
|
||||
case MTR_POLICER_ACTION_COLOR_GREEN:
|
||||
return RTE_TABLE_ACTION_POLICER_COLOR_GREEN;
|
||||
|
||||
/* FALLTHROUGH */
|
||||
case MTR_POLICER_ACTION_COLOR_YELLOW:
|
||||
return RTE_TABLE_ACTION_POLICER_COLOR_YELLOW;
|
||||
|
||||
/* FALLTHROUGH */
|
||||
case MTR_POLICER_ACTION_COLOR_RED:
|
||||
return RTE_TABLE_ACTION_POLICER_COLOR_RED;
|
||||
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
return RTE_TABLE_ACTION_POLICER_DROP;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
meter_profile_check(struct rte_eth_dev *dev,
|
||||
uint32_t meter_profile_id,
|
||||
@ -208,6 +187,160 @@ pmd_mtr_meter_profile_delete(struct rte_eth_dev *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct softnic_mtr_meter_policy *
|
||||
softnic_mtr_meter_policy_find(struct pmd_internals *p,
|
||||
uint32_t meter_policy_id)
|
||||
{
|
||||
struct softnic_mtr_meter_policy_list *mpl = &p->mtr.meter_policies;
|
||||
struct softnic_mtr_meter_policy *mp;
|
||||
|
||||
TAILQ_FOREACH(mp, mpl, node)
|
||||
if (meter_policy_id == mp->meter_policy_id)
|
||||
return mp;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* MTR meter policy add */
|
||||
static int
|
||||
pmd_mtr_meter_policy_add(struct rte_eth_dev *dev,
|
||||
uint32_t meter_policy_id,
|
||||
struct rte_mtr_meter_policy_params *policy,
|
||||
struct rte_mtr_error *error)
|
||||
{
|
||||
struct pmd_internals *p = dev->data->dev_private;
|
||||
struct softnic_mtr_meter_policy_list *mpl = &p->mtr.meter_policies;
|
||||
struct softnic_mtr_meter_policy *mp;
|
||||
const struct rte_flow_action *act;
|
||||
const struct rte_flow_action_meter_color *recolor;
|
||||
uint32_t i;
|
||||
bool valid_act_found;
|
||||
|
||||
if (policy == NULL)
|
||||
return -rte_mtr_error_set(error,
|
||||
EINVAL,
|
||||
RTE_MTR_ERROR_TYPE_METER_POLICY,
|
||||
NULL,
|
||||
"Null meter policy invalid");
|
||||
|
||||
/* Meter policy must not exist. */
|
||||
mp = softnic_mtr_meter_policy_find(p, meter_policy_id);
|
||||
if (mp != NULL)
|
||||
return -rte_mtr_error_set(error,
|
||||
EINVAL,
|
||||
RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
|
||||
NULL,
|
||||
"Meter policy already exists");
|
||||
|
||||
for (i = 0; i < RTE_COLORS; i++) {
|
||||
if (policy->actions[i] == NULL)
|
||||
return -rte_mtr_error_set(error,
|
||||
EINVAL,
|
||||
RTE_MTR_ERROR_TYPE_METER_POLICY,
|
||||
NULL,
|
||||
"Null action list");
|
||||
for (act = policy->actions[i], valid_act_found = false;
|
||||
act->type != RTE_FLOW_ACTION_TYPE_END; act++) {
|
||||
if (act->type == RTE_FLOW_ACTION_TYPE_VOID)
|
||||
continue;
|
||||
/*
|
||||
* Support one (and one only) of
|
||||
* METER_COLOR or DROP action.
|
||||
*/
|
||||
if ((act->type != RTE_FLOW_ACTION_TYPE_METER_COLOR &&
|
||||
act->type != RTE_FLOW_ACTION_TYPE_DROP) ||
|
||||
valid_act_found)
|
||||
return -rte_mtr_error_set(error,
|
||||
EINVAL,
|
||||
RTE_MTR_ERROR_TYPE_METER_POLICY,
|
||||
NULL,
|
||||
"Action invalid");
|
||||
valid_act_found = true;
|
||||
}
|
||||
if (!valid_act_found)
|
||||
return -rte_mtr_error_set(error,
|
||||
EINVAL,
|
||||
RTE_MTR_ERROR_TYPE_METER_POLICY,
|
||||
NULL,
|
||||
"No valid action found");
|
||||
}
|
||||
|
||||
/* Memory allocation */
|
||||
mp = calloc(1, sizeof(struct softnic_mtr_meter_policy));
|
||||
if (mp == NULL)
|
||||
return -rte_mtr_error_set(error,
|
||||
ENOMEM,
|
||||
RTE_MTR_ERROR_TYPE_UNSPECIFIED,
|
||||
NULL,
|
||||
"Memory alloc failed");
|
||||
|
||||
/* Fill in */
|
||||
mp->meter_policy_id = meter_policy_id;
|
||||
for (i = 0; i < RTE_COLORS; i++) {
|
||||
mp->policer[i] = RTE_TABLE_ACTION_POLICER_DROP;
|
||||
act = policy->actions[i];
|
||||
if (!act)
|
||||
continue;
|
||||
if (act->type == RTE_FLOW_ACTION_TYPE_METER_COLOR) {
|
||||
recolor = act->conf;
|
||||
switch (recolor->color) {
|
||||
case RTE_COLOR_GREEN:
|
||||
mp->policer[i] =
|
||||
RTE_TABLE_ACTION_POLICER_COLOR_GREEN;
|
||||
break;
|
||||
case RTE_COLOR_YELLOW:
|
||||
mp->policer[i] =
|
||||
RTE_TABLE_ACTION_POLICER_COLOR_YELLOW;
|
||||
break;
|
||||
case RTE_COLOR_RED:
|
||||
mp->policer[i] =
|
||||
RTE_TABLE_ACTION_POLICER_COLOR_RED;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Add to list */
|
||||
TAILQ_INSERT_TAIL(mpl, mp, node);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* MTR meter policy delete */
|
||||
static int
|
||||
pmd_mtr_meter_policy_delete(struct rte_eth_dev *dev,
|
||||
uint32_t meter_policy_id,
|
||||
struct rte_mtr_error *error)
|
||||
{
|
||||
struct pmd_internals *p = dev->data->dev_private;
|
||||
struct softnic_mtr_meter_policy *mp;
|
||||
|
||||
/* Meter policy must exist */
|
||||
mp = softnic_mtr_meter_policy_find(p, meter_policy_id);
|
||||
if (mp == NULL)
|
||||
return -rte_mtr_error_set(error,
|
||||
EINVAL,
|
||||
RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
|
||||
NULL,
|
||||
"Meter policy id invalid");
|
||||
|
||||
/* Check unused */
|
||||
if (mp->n_users)
|
||||
return -rte_mtr_error_set(error,
|
||||
EBUSY,
|
||||
RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
|
||||
NULL,
|
||||
"Meter policy in use");
|
||||
|
||||
/* Remove from list */
|
||||
TAILQ_REMOVE(&p->mtr.meter_policies, mp, node);
|
||||
free(mp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct softnic_mtr *
|
||||
softnic_mtr_find(struct pmd_internals *p, uint32_t mtr_id)
|
||||
{
|
||||
@ -275,6 +408,7 @@ pmd_mtr_create(struct rte_eth_dev *dev,
|
||||
struct pmd_internals *p = dev->data->dev_private;
|
||||
struct softnic_mtr_list *ml = &p->mtr.mtrs;
|
||||
struct softnic_mtr_meter_profile *mp;
|
||||
struct softnic_mtr_meter_policy *policy;
|
||||
struct softnic_mtr *m;
|
||||
int status;
|
||||
|
||||
@ -292,6 +426,16 @@ pmd_mtr_create(struct rte_eth_dev *dev,
|
||||
NULL,
|
||||
"Meter profile id not valid");
|
||||
|
||||
/* Meter policy must exist */
|
||||
policy = softnic_mtr_meter_policy_find(p, params->meter_policy_id);
|
||||
if (policy == NULL) {
|
||||
return -rte_mtr_error_set(error,
|
||||
EINVAL,
|
||||
RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
|
||||
NULL,
|
||||
"Meter policy id invalid");
|
||||
}
|
||||
|
||||
/* Memory allocation */
|
||||
m = calloc(1, sizeof(struct softnic_mtr));
|
||||
if (m == NULL)
|
||||
@ -310,6 +454,7 @@ pmd_mtr_create(struct rte_eth_dev *dev,
|
||||
|
||||
/* Update dependencies */
|
||||
mp->n_users++;
|
||||
policy->n_users++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -324,6 +469,7 @@ pmd_mtr_destroy(struct rte_eth_dev *dev,
|
||||
struct softnic_mtr_list *ml = &p->mtr.mtrs;
|
||||
struct softnic_mtr_meter_profile *mp;
|
||||
struct softnic_mtr *m;
|
||||
struct softnic_mtr_meter_policy *policy;
|
||||
|
||||
/* MTR object must exist */
|
||||
m = softnic_mtr_find(p, mtr_id);
|
||||
@ -351,8 +497,18 @@ pmd_mtr_destroy(struct rte_eth_dev *dev,
|
||||
NULL,
|
||||
"MTR object meter profile invalid");
|
||||
|
||||
/* Meter policy must exist */
|
||||
policy = softnic_mtr_meter_policy_find(p, m->params.meter_policy_id);
|
||||
if (policy == NULL)
|
||||
return -rte_mtr_error_set(error,
|
||||
EINVAL,
|
||||
RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
|
||||
NULL,
|
||||
"MTR object meter policy invalid");
|
||||
|
||||
/* Update dependencies */
|
||||
mp->n_users--;
|
||||
policy->n_users--;
|
||||
|
||||
/* Remove from list */
|
||||
TAILQ_REMOVE(ml, m, node);
|
||||
@ -514,18 +670,18 @@ pmd_mtr_meter_dscp_table_update(struct rte_eth_dev *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* MTR object policer action update */
|
||||
/* MTR object policy update */
|
||||
static int
|
||||
pmd_mtr_policer_actions_update(struct rte_eth_dev *dev,
|
||||
pmd_mtr_meter_policy_update(struct rte_eth_dev *dev,
|
||||
uint32_t mtr_id,
|
||||
uint32_t action_mask,
|
||||
enum rte_mtr_policer_action *actions,
|
||||
uint32_t meter_policy_id,
|
||||
struct rte_mtr_error *error)
|
||||
{
|
||||
struct pmd_internals *p = dev->data->dev_private;
|
||||
struct softnic_mtr *m;
|
||||
uint32_t i;
|
||||
int status;
|
||||
struct softnic_mtr_meter_policy *mp_new, *mp_old;
|
||||
|
||||
/* MTR object id must be valid */
|
||||
m = softnic_mtr_find(p, mtr_id);
|
||||
@ -536,28 +692,17 @@ pmd_mtr_policer_actions_update(struct rte_eth_dev *dev,
|
||||
NULL,
|
||||
"MTR object id not valid");
|
||||
|
||||
/* Valid policer actions */
|
||||
if (actions == NULL)
|
||||
if (m->params.meter_policy_id == meter_policy_id)
|
||||
return 0;
|
||||
|
||||
/* Meter policy must exist */
|
||||
mp_new = softnic_mtr_meter_policy_find(p, meter_policy_id);
|
||||
if (mp_new == NULL)
|
||||
return -rte_mtr_error_set(error,
|
||||
EINVAL,
|
||||
RTE_MTR_ERROR_TYPE_UNSPECIFIED,
|
||||
RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
|
||||
NULL,
|
||||
"Invalid actions");
|
||||
|
||||
for (i = 0; i < RTE_COLORS; i++) {
|
||||
if (action_mask & (1 << i)) {
|
||||
if (actions[i] != MTR_POLICER_ACTION_COLOR_GREEN &&
|
||||
actions[i] != MTR_POLICER_ACTION_COLOR_YELLOW &&
|
||||
actions[i] != MTR_POLICER_ACTION_COLOR_RED &&
|
||||
actions[i] != MTR_POLICER_ACTION_DROP) {
|
||||
return -rte_mtr_error_set(error,
|
||||
EINVAL,
|
||||
RTE_MTR_ERROR_TYPE_UNSPECIFIED,
|
||||
NULL,
|
||||
" Invalid action value");
|
||||
}
|
||||
}
|
||||
}
|
||||
"Meter policy id invalid");
|
||||
|
||||
/* MTR object owner valid? */
|
||||
if (m->flow) {
|
||||
@ -569,9 +714,7 @@ pmd_mtr_policer_actions_update(struct rte_eth_dev *dev,
|
||||
|
||||
/* Set action */
|
||||
for (i = 0; i < RTE_COLORS; i++)
|
||||
if (action_mask & (1 << i))
|
||||
action.mtr.mtr[0].policer[i] =
|
||||
softnic_table_action_policer(actions[i]);
|
||||
action.mtr.mtr[0].policer[i] = mp_new->policer[i];
|
||||
|
||||
/* Re-add the rule */
|
||||
status = softnic_pipeline_table_rule_add(p,
|
||||
@ -595,10 +738,20 @@ pmd_mtr_policer_actions_update(struct rte_eth_dev *dev,
|
||||
1, NULL, 1);
|
||||
}
|
||||
|
||||
/* Meter: Update policer actions */
|
||||
for (i = 0; i < RTE_COLORS; i++)
|
||||
if (action_mask & (1 << i))
|
||||
m->params.action[i] = actions[i];
|
||||
mp_old = softnic_mtr_meter_policy_find(p, m->params.meter_policy_id);
|
||||
if (mp_old == NULL)
|
||||
return -rte_mtr_error_set(error,
|
||||
EINVAL,
|
||||
RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
|
||||
NULL,
|
||||
"Old meter policy id invalid");
|
||||
|
||||
/* Meter: Set meter profile */
|
||||
m->params.meter_policy_id = meter_policy_id;
|
||||
|
||||
/* Update dependencies*/
|
||||
mp_old->n_users--;
|
||||
mp_new->n_users++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -615,28 +768,40 @@ pmd_mtr_policer_actions_update(struct rte_eth_dev *dev,
|
||||
|
||||
/* MTR object stats read */
|
||||
static void
|
||||
mtr_stats_convert(struct softnic_mtr *m,
|
||||
mtr_stats_convert(struct pmd_internals *p,
|
||||
struct softnic_mtr *m,
|
||||
struct rte_table_action_mtr_counters_tc *in,
|
||||
struct rte_mtr_stats *out,
|
||||
uint64_t *out_mask)
|
||||
{
|
||||
struct softnic_mtr_meter_policy *mp;
|
||||
|
||||
memset(&out, 0, sizeof(out));
|
||||
*out_mask = 0;
|
||||
|
||||
/* Meter policy must exist */
|
||||
mp = softnic_mtr_meter_policy_find(p, m->params.meter_policy_id);
|
||||
if (mp == NULL)
|
||||
return;
|
||||
|
||||
if (in->n_packets_valid) {
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < RTE_COLORS; i++) {
|
||||
if (m->params.action[i] == MTR_POLICER_ACTION_COLOR_GREEN)
|
||||
if (mp->policer[i] ==
|
||||
RTE_TABLE_ACTION_POLICER_COLOR_GREEN)
|
||||
out->n_pkts[RTE_COLOR_GREEN] += in->n_packets[i];
|
||||
|
||||
if (m->params.action[i] == MTR_POLICER_ACTION_COLOR_YELLOW)
|
||||
if (mp->policer[i] ==
|
||||
RTE_TABLE_ACTION_POLICER_COLOR_YELLOW)
|
||||
out->n_pkts[RTE_COLOR_YELLOW] += in->n_packets[i];
|
||||
|
||||
if (m->params.action[i] == MTR_POLICER_ACTION_COLOR_RED)
|
||||
if (mp->policer[i] ==
|
||||
RTE_TABLE_ACTION_POLICER_COLOR_RED)
|
||||
out->n_pkts[RTE_COLOR_RED] += in->n_packets[i];
|
||||
|
||||
if (m->params.action[i] == MTR_POLICER_ACTION_DROP)
|
||||
if (mp->policer[i] ==
|
||||
RTE_TABLE_ACTION_POLICER_DROP)
|
||||
out->n_pkts_dropped += in->n_packets[i];
|
||||
}
|
||||
|
||||
@ -647,16 +812,20 @@ mtr_stats_convert(struct softnic_mtr *m,
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < RTE_COLORS; i++) {
|
||||
if (m->params.action[i] == MTR_POLICER_ACTION_COLOR_GREEN)
|
||||
if (mp->policer[i] ==
|
||||
RTE_TABLE_ACTION_POLICER_COLOR_GREEN)
|
||||
out->n_bytes[RTE_COLOR_GREEN] += in->n_bytes[i];
|
||||
|
||||
if (m->params.action[i] == MTR_POLICER_ACTION_COLOR_YELLOW)
|
||||
if (mp->policer[i] ==
|
||||
RTE_TABLE_ACTION_POLICER_COLOR_YELLOW)
|
||||
out->n_bytes[RTE_COLOR_YELLOW] += in->n_bytes[i];
|
||||
|
||||
if (m->params.action[i] == MTR_POLICER_ACTION_COLOR_RED)
|
||||
if (mp->policer[i] ==
|
||||
RTE_TABLE_ACTION_POLICER_COLOR_RED)
|
||||
out->n_bytes[RTE_COLOR_RED] += in->n_bytes[i];
|
||||
|
||||
if (m->params.action[i] == MTR_POLICER_ACTION_DROP)
|
||||
if (mp->policer[i] ==
|
||||
RTE_TABLE_ACTION_POLICER_DROP)
|
||||
out->n_bytes_dropped += in->n_bytes[i];
|
||||
}
|
||||
|
||||
@ -722,7 +891,8 @@ pmd_mtr_stats_read(struct rte_eth_dev *dev,
|
||||
struct rte_mtr_stats s;
|
||||
uint64_t s_mask = 0;
|
||||
|
||||
mtr_stats_convert(m,
|
||||
mtr_stats_convert(p,
|
||||
m,
|
||||
&counters.stats[0],
|
||||
&s,
|
||||
&s_mask);
|
||||
@ -743,6 +913,9 @@ const struct rte_mtr_ops pmd_mtr_ops = {
|
||||
.meter_profile_add = pmd_mtr_meter_profile_add,
|
||||
.meter_profile_delete = pmd_mtr_meter_profile_delete,
|
||||
|
||||
.meter_policy_add = pmd_mtr_meter_policy_add,
|
||||
.meter_policy_delete = pmd_mtr_meter_policy_delete,
|
||||
|
||||
.create = pmd_mtr_create,
|
||||
.destroy = pmd_mtr_destroy,
|
||||
.meter_enable = NULL,
|
||||
@ -750,7 +923,7 @@ const struct rte_mtr_ops pmd_mtr_ops = {
|
||||
|
||||
.meter_profile_update = pmd_mtr_meter_profile_update,
|
||||
.meter_dscp_table_update = pmd_mtr_meter_dscp_table_update,
|
||||
.policer_actions_update = pmd_mtr_policer_actions_update,
|
||||
.meter_policy_update = pmd_mtr_meter_policy_update,
|
||||
.stats_update = NULL,
|
||||
|
||||
.stats_read = pmd_mtr_stats_read,
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <rte_bitops.h>
|
||||
#include <rte_mbuf.h>
|
||||
#include <rte_mbuf_dyn.h>
|
||||
#include <rte_meter.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -2392,6 +2393,14 @@ enum rte_flow_action_type {
|
||||
* @see struct rte_flow_action_conntrack.
|
||||
*/
|
||||
RTE_FLOW_ACTION_TYPE_CONNTRACK,
|
||||
|
||||
/**
|
||||
* Color the packet to reflect the meter color result.
|
||||
* Set the meter color in the mbuf to the selected color.
|
||||
*
|
||||
* See struct rte_flow_action_meter_color.
|
||||
*/
|
||||
RTE_FLOW_ACTION_TYPE_METER_COLOR,
|
||||
};
|
||||
|
||||
/**
|
||||
@ -3138,6 +3147,19 @@ struct rte_flow_modify_conntrack {
|
||||
uint32_t reserved:30;
|
||||
};
|
||||
|
||||
/**
|
||||
* @warning
|
||||
* @b EXPERIMENTAL: this structure may change without prior notice
|
||||
*
|
||||
* RTE_FLOW_ACTION_TYPE_METER_COLOR
|
||||
*
|
||||
* The meter color should be set in the packet meta-data
|
||||
* (i.e. struct rte_mbuf::sched::color).
|
||||
*/
|
||||
struct rte_flow_action_meter_color {
|
||||
enum rte_color color; /**< Packet color. */
|
||||
};
|
||||
|
||||
/**
|
||||
* Field IDs for MODIFY_FIELD action.
|
||||
*/
|
||||
|
@ -91,6 +91,40 @@ rte_mtr_meter_profile_delete(uint16_t port_id,
|
||||
meter_profile_id, error);
|
||||
}
|
||||
|
||||
/* MTR meter policy validate */
|
||||
int
|
||||
rte_mtr_meter_policy_validate(uint16_t port_id,
|
||||
struct rte_mtr_meter_policy_params *policy,
|
||||
struct rte_mtr_error *error)
|
||||
{
|
||||
struct rte_eth_dev *dev = &rte_eth_devices[port_id];
|
||||
return RTE_MTR_FUNC(port_id, meter_policy_validate)(dev,
|
||||
policy, error);
|
||||
}
|
||||
|
||||
/* MTR meter policy add */
|
||||
int
|
||||
rte_mtr_meter_policy_add(uint16_t port_id,
|
||||
uint32_t policy_id,
|
||||
struct rte_mtr_meter_policy_params *policy,
|
||||
struct rte_mtr_error *error)
|
||||
{
|
||||
struct rte_eth_dev *dev = &rte_eth_devices[port_id];
|
||||
return RTE_MTR_FUNC(port_id, meter_policy_add)(dev,
|
||||
policy_id, policy, error);
|
||||
}
|
||||
|
||||
/** MTR meter policy delete */
|
||||
int
|
||||
rte_mtr_meter_policy_delete(uint16_t port_id,
|
||||
uint32_t policy_id,
|
||||
struct rte_mtr_error *error)
|
||||
{
|
||||
struct rte_eth_dev *dev = &rte_eth_devices[port_id];
|
||||
return RTE_MTR_FUNC(port_id, meter_policy_delete)(dev,
|
||||
policy_id, error);
|
||||
}
|
||||
|
||||
/** MTR object create */
|
||||
int
|
||||
rte_mtr_create(uint16_t port_id,
|
||||
@ -149,6 +183,18 @@ rte_mtr_meter_profile_update(uint16_t port_id,
|
||||
mtr_id, meter_profile_id, error);
|
||||
}
|
||||
|
||||
/** MTR object meter policy update */
|
||||
int
|
||||
rte_mtr_meter_policy_update(uint16_t port_id,
|
||||
uint32_t mtr_id,
|
||||
uint32_t meter_policy_id,
|
||||
struct rte_mtr_error *error)
|
||||
{
|
||||
struct rte_eth_dev *dev = &rte_eth_devices[port_id];
|
||||
return RTE_MTR_FUNC(port_id, meter_policy_update)(dev,
|
||||
mtr_id, meter_policy_id, error);
|
||||
}
|
||||
|
||||
/** MTR object meter DSCP table update */
|
||||
int
|
||||
rte_mtr_meter_dscp_table_update(uint16_t port_id,
|
||||
@ -161,19 +207,6 @@ rte_mtr_meter_dscp_table_update(uint16_t port_id,
|
||||
mtr_id, dscp_table, error);
|
||||
}
|
||||
|
||||
/** MTR object policer action update */
|
||||
int
|
||||
rte_mtr_policer_actions_update(uint16_t port_id,
|
||||
uint32_t mtr_id,
|
||||
uint32_t action_mask,
|
||||
enum rte_mtr_policer_action *actions,
|
||||
struct rte_mtr_error *error)
|
||||
{
|
||||
struct rte_eth_dev *dev = &rte_eth_devices[port_id];
|
||||
return RTE_MTR_FUNC(port_id, policer_actions_update)(dev,
|
||||
mtr_id, action_mask, actions, error);
|
||||
}
|
||||
|
||||
/** MTR object enabled stats update */
|
||||
int
|
||||
rte_mtr_stats_update(uint16_t port_id,
|
||||
|
@ -49,6 +49,7 @@
|
||||
#include <rte_compat.h>
|
||||
#include <rte_common.h>
|
||||
#include <rte_meter.h>
|
||||
#include <rte_flow.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -200,20 +201,16 @@ struct rte_mtr_meter_profile {
|
||||
};
|
||||
|
||||
/**
|
||||
* Policer actions
|
||||
* Meter policy
|
||||
*/
|
||||
enum rte_mtr_policer_action {
|
||||
/** Recolor the packet as green. */
|
||||
MTR_POLICER_ACTION_COLOR_GREEN = 0,
|
||||
|
||||
/** Recolor the packet as yellow. */
|
||||
MTR_POLICER_ACTION_COLOR_YELLOW,
|
||||
|
||||
/** Recolor the packet as red. */
|
||||
MTR_POLICER_ACTION_COLOR_RED,
|
||||
|
||||
/** Drop the packet. */
|
||||
MTR_POLICER_ACTION_DROP,
|
||||
struct rte_mtr_meter_policy_params {
|
||||
/**
|
||||
* Policy action list per color.
|
||||
* actions[i] potentially represents a chain of rte_flow actions
|
||||
* terminated by the END action, exactly as specified by the rte_flow
|
||||
* API for the flow definition, and not just a single action.
|
||||
*/
|
||||
const struct rte_flow_action *actions[RTE_COLORS];
|
||||
};
|
||||
|
||||
/**
|
||||
@ -257,13 +254,13 @@ struct rte_mtr_params {
|
||||
*/
|
||||
int meter_enable;
|
||||
|
||||
/** Policer actions (per meter output color). */
|
||||
enum rte_mtr_policer_action action[RTE_COLORS];
|
||||
|
||||
/** Set of stats counters to be enabled.
|
||||
* @see enum rte_mtr_stats_type
|
||||
*/
|
||||
uint64_t stats_mask;
|
||||
|
||||
/** Meter policy ID. */
|
||||
uint32_t meter_policy_id;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -349,6 +346,13 @@ struct rte_mtr_capabilities {
|
||||
*/
|
||||
uint64_t meter_rate_max;
|
||||
|
||||
/**
|
||||
* Maximum number of policy objects that can have.
|
||||
* The value of 0 is invalid. Policy must be supported for meter.
|
||||
* The maximum value is *n_max*.
|
||||
*/
|
||||
uint64_t meter_policy_n_max;
|
||||
|
||||
/**
|
||||
* When non-zero, it indicates that color aware mode is supported for
|
||||
* the srTCM RFC 2697 metering algorithm.
|
||||
@ -367,18 +371,6 @@ struct rte_mtr_capabilities {
|
||||
*/
|
||||
int color_aware_trtcm_rfc4115_supported;
|
||||
|
||||
/** When non-zero, it indicates that the policer packet recolor actions
|
||||
* are supported.
|
||||
* @see enum rte_mtr_policer_action
|
||||
*/
|
||||
int policer_action_recolor_supported;
|
||||
|
||||
/** When non-zero, it indicates that the policer packet drop action is
|
||||
* supported.
|
||||
* @see enum rte_mtr_policer_action
|
||||
*/
|
||||
int policer_action_drop_supported;
|
||||
|
||||
/**
|
||||
* srTCM rfc2697 byte mode supported.
|
||||
* When non-zero, it indicates that byte mode is supported for
|
||||
@ -447,6 +439,8 @@ enum rte_mtr_error_type {
|
||||
RTE_MTR_ERROR_TYPE_STATS_MASK,
|
||||
RTE_MTR_ERROR_TYPE_STATS,
|
||||
RTE_MTR_ERROR_TYPE_SHARED,
|
||||
RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
|
||||
RTE_MTR_ERROR_TYPE_METER_POLICY,
|
||||
};
|
||||
|
||||
/**
|
||||
@ -530,6 +524,144 @@ rte_mtr_meter_profile_delete(uint16_t port_id,
|
||||
uint32_t meter_profile_id,
|
||||
struct rte_mtr_error *error);
|
||||
|
||||
/**
|
||||
* Check whether a meter policy can be created on a given port.
|
||||
*
|
||||
* The meter policy is validated for correctness and
|
||||
* whether it could be accepted by the device given sufficient resources.
|
||||
* The policy is checked against the current capability information
|
||||
* meter_policy_n_max configuration.
|
||||
* The policy may also optionally be validated against existing
|
||||
* device policy resources.
|
||||
* This function has no effect on the target device.
|
||||
*
|
||||
* @param[in] port_id
|
||||
* The port identifier of the Ethernet device.
|
||||
* @param[in] policy
|
||||
* Associated action list per color.
|
||||
* list NULL is legal and means no special action.
|
||||
* (list terminated by the END action).
|
||||
* @param[out] error
|
||||
* Error details. Filled in only on error, when not NULL.
|
||||
* @return
|
||||
* 0 on success, non-zero error code otherwise.
|
||||
*/
|
||||
__rte_experimental
|
||||
int
|
||||
rte_mtr_meter_policy_validate(uint16_t port_id,
|
||||
struct rte_mtr_meter_policy_params *policy,
|
||||
struct rte_mtr_error *error);
|
||||
|
||||
/**
|
||||
* Meter policy add
|
||||
*
|
||||
* Create a new meter policy. The new policy
|
||||
* is used to create single or multiple MTR objects.
|
||||
* The same policy can be used to create multiple MTR objects.
|
||||
*
|
||||
* @param[in] port_id
|
||||
* The port identifier of the Ethernet device.
|
||||
* @param[in] policy_id
|
||||
* Policy identifier for the new meter policy.
|
||||
* @param[in] policy
|
||||
* Associated actions per color.
|
||||
* list NULL is legal and means no special action.
|
||||
* Non-NULL list must be terminated.
|
||||
* (list terminated by the END action).
|
||||
* @param[out] error
|
||||
* Error details. Filled in only on error, when not NULL.
|
||||
* @return
|
||||
* 0 on success, non-zero error code otherwise.
|
||||
*/
|
||||
__rte_experimental
|
||||
int
|
||||
rte_mtr_meter_policy_add(uint16_t port_id,
|
||||
uint32_t policy_id,
|
||||
struct rte_mtr_meter_policy_params *policy,
|
||||
struct rte_mtr_error *error);
|
||||
|
||||
/**
|
||||
* Define meter policy action list:
|
||||
* GREEN - GREEN, YELLOW - YELLOW, RED - RED
|
||||
*/
|
||||
#define rte_mtr_policy_pass_color(policy) \
|
||||
struct rte_mtr_meter_policy_params policy = \
|
||||
{ \
|
||||
.actions[RTE_COLOR_GREEN] = (struct rte_flow_action[]) { \
|
||||
{ \
|
||||
.type = RTE_FLOW_ACTION_TYPE_METER_COLOR, \
|
||||
.conf = &(struct rte_flow_action_meter_color) { \
|
||||
.color = RTE_COLOR_GREEN, \
|
||||
}, \
|
||||
}, \
|
||||
{ \
|
||||
.type = RTE_FLOW_ACTION_TYPE_END, \
|
||||
}, \
|
||||
}, \
|
||||
.actions[RTE_COLOR_YELLOW] = (struct rte_flow_action[]) { \
|
||||
{ \
|
||||
.type = RTE_FLOW_ACTION_TYPE_METER_COLOR, \
|
||||
.conf = &(struct rte_flow_action_meter_color) { \
|
||||
.color = RTE_COLOR_YELLOW, \
|
||||
}, \
|
||||
}, \
|
||||
{ \
|
||||
.type = RTE_FLOW_ACTION_TYPE_END, \
|
||||
}, \
|
||||
}, \
|
||||
.actions[RTE_COLOR_RED] = (struct rte_flow_action[]) { \
|
||||
{ \
|
||||
.type = RTE_FLOW_ACTION_TYPE_METER_COLOR, \
|
||||
.conf = &(struct rte_flow_action_meter_color) { \
|
||||
.color = RTE_COLOR_RED, \
|
||||
}, \
|
||||
}, \
|
||||
{ \
|
||||
.type = RTE_FLOW_ACTION_TYPE_END, \
|
||||
}, \
|
||||
}, \
|
||||
}
|
||||
|
||||
/**
|
||||
* Define meter policy action list:
|
||||
* GREEN - Do nothing, YELLOW - Do nothing, RED - DROP
|
||||
*/
|
||||
#define rte_mtr_policy_drop_red(policy) \
|
||||
struct rte_mtr_meter_policy_params policy = \
|
||||
{ \
|
||||
.actions[RTE_COLOR_GREEN] = NULL, \
|
||||
.actions[RTE_COLOR_YELLOW] = NULL, \
|
||||
.actions[RTE_COLOR_RED] = (struct rte_flow_action[]) { \
|
||||
{ \
|
||||
.type = RTE_FLOW_ACTION_TYPE_DROP, \
|
||||
}, \
|
||||
{ \
|
||||
.type = RTE_FLOW_ACTION_TYPE_END, \
|
||||
}, \
|
||||
}, \
|
||||
}
|
||||
|
||||
/**
|
||||
* Meter policy delete
|
||||
*
|
||||
* Delete an existing meter policy. This operation fails when there is
|
||||
* currently at least one user (i.e. MTR object) of this policy.
|
||||
*
|
||||
* @param[in] port_id
|
||||
* The port identifier of the Ethernet device.
|
||||
* @param[in] policy_id
|
||||
* Policy identifier.
|
||||
* @param[out] error
|
||||
* Error details. Filled in only on error, when not NULL.
|
||||
* @return
|
||||
* 0 on success, non-zero error code otherwise.
|
||||
*/
|
||||
__rte_experimental
|
||||
int
|
||||
rte_mtr_meter_policy_delete(uint16_t port_id,
|
||||
uint32_t policy_id,
|
||||
struct rte_mtr_error *error);
|
||||
|
||||
/**
|
||||
* MTR object create
|
||||
*
|
||||
@ -654,6 +786,27 @@ rte_mtr_meter_profile_update(uint16_t port_id,
|
||||
uint32_t meter_profile_id,
|
||||
struct rte_mtr_error *error);
|
||||
|
||||
/**
|
||||
* MTR object meter policy update
|
||||
*
|
||||
* @param[in] port_id
|
||||
* The port identifier of the Ethernet device.
|
||||
* @param[in] mtr_id
|
||||
* MTR object ID. Needs to be valid.
|
||||
* @param[in] meter_policy_id
|
||||
* Meter policy ID for the current MTR object. Needs to be valid.
|
||||
* @param[out] error
|
||||
* Error details. Filled in only on error, when not NULL.
|
||||
* @return
|
||||
* 0 on success, non-zero error code otherwise.
|
||||
*/
|
||||
__rte_experimental
|
||||
int
|
||||
rte_mtr_meter_policy_update(uint16_t port_id,
|
||||
uint32_t mtr_id,
|
||||
uint32_t meter_policy_id,
|
||||
struct rte_mtr_error *error);
|
||||
|
||||
/**
|
||||
* MTR object DSCP table update
|
||||
*
|
||||
@ -665,7 +818,7 @@ rte_mtr_meter_profile_update(uint16_t port_id,
|
||||
* When non-NULL: it points to a pre-allocated and pre-populated table with
|
||||
* exactly 64 elements providing the input color for each value of the
|
||||
* IPv4/IPv6 Differentiated Services Code Point (DSCP) input packet field.
|
||||
* When NULL: it is equivalent to setting this parameter to an “all-green”
|
||||
* When NULL: it is equivalent to setting this parameter to an "all-green"
|
||||
* populated table (i.e. table with all the 64 elements set to green color).
|
||||
* @param[out] error
|
||||
* Error details. Filled in only on error, when not NULL.
|
||||
@ -679,34 +832,6 @@ rte_mtr_meter_dscp_table_update(uint16_t port_id,
|
||||
enum rte_color *dscp_table,
|
||||
struct rte_mtr_error *error);
|
||||
|
||||
/**
|
||||
* MTR object policer actions update
|
||||
*
|
||||
* @param[in] port_id
|
||||
* The port identifier of the Ethernet device.
|
||||
* @param[in] mtr_id
|
||||
* MTR object ID. Needs to be valid.
|
||||
* @param[in] action_mask
|
||||
* Bit mask indicating which policer actions need to be updated. One or more
|
||||
* policer actions can be updated in a single function invocation. To update
|
||||
* the policer action associated with color C, bit (1 << C) needs to be set in
|
||||
* *action_mask* and element at position C in the *actions* array needs to be
|
||||
* valid.
|
||||
* @param[in] actions
|
||||
* Pre-allocated and pre-populated array of policer actions.
|
||||
* @param[out] error
|
||||
* Error details. Filled in only on error, when not NULL.
|
||||
* @return
|
||||
* 0 on success, non-zero error code otherwise.
|
||||
*/
|
||||
__rte_experimental
|
||||
int
|
||||
rte_mtr_policer_actions_update(uint16_t port_id,
|
||||
uint32_t mtr_id,
|
||||
uint32_t action_mask,
|
||||
enum rte_mtr_policer_action *actions,
|
||||
struct rte_mtr_error *error);
|
||||
|
||||
/**
|
||||
* MTR object enabled statistics counters update
|
||||
*
|
||||
|
@ -41,6 +41,22 @@ typedef int (*rte_mtr_meter_profile_delete_t)(struct rte_eth_dev *dev,
|
||||
struct rte_mtr_error *error);
|
||||
/**< @internal MTR meter profile delete */
|
||||
|
||||
typedef int (*rte_mtr_meter_policy_validate_t)(struct rte_eth_dev *dev,
|
||||
struct rte_mtr_meter_policy_params *policy,
|
||||
struct rte_mtr_error *error);
|
||||
/**< @internal MTR meter policy validate */
|
||||
|
||||
typedef int (*rte_mtr_meter_policy_add_t)(struct rte_eth_dev *dev,
|
||||
uint32_t policy_id,
|
||||
struct rte_mtr_meter_policy_params *policy,
|
||||
struct rte_mtr_error *error);
|
||||
/**< @internal MTR meter policy add */
|
||||
|
||||
typedef int (*rte_mtr_meter_policy_delete_t)(struct rte_eth_dev *dev,
|
||||
uint32_t policy_id,
|
||||
struct rte_mtr_error *error);
|
||||
/**< @internal MTR meter policy delete */
|
||||
|
||||
typedef int (*rte_mtr_create_t)(struct rte_eth_dev *dev,
|
||||
uint32_t mtr_id,
|
||||
struct rte_mtr_params *params,
|
||||
@ -69,19 +85,18 @@ typedef int (*rte_mtr_meter_profile_update_t)(struct rte_eth_dev *dev,
|
||||
struct rte_mtr_error *error);
|
||||
/**< @internal MTR object meter profile update */
|
||||
|
||||
typedef int (*rte_mtr_meter_policy_update_t)(struct rte_eth_dev *dev,
|
||||
uint32_t mtr_id,
|
||||
uint32_t meter_policy_id,
|
||||
struct rte_mtr_error *error);
|
||||
/**< @internal MTR object meter policy update */
|
||||
|
||||
typedef int (*rte_mtr_meter_dscp_table_update_t)(struct rte_eth_dev *dev,
|
||||
uint32_t mtr_id,
|
||||
enum rte_color *dscp_table,
|
||||
struct rte_mtr_error *error);
|
||||
/**< @internal MTR object meter DSCP table update */
|
||||
|
||||
typedef int (*rte_mtr_policer_actions_update_t)(struct rte_eth_dev *dev,
|
||||
uint32_t mtr_id,
|
||||
uint32_t action_mask,
|
||||
enum rte_mtr_policer_action *actions,
|
||||
struct rte_mtr_error *error);
|
||||
/**< @internal MTR object policer action update*/
|
||||
|
||||
typedef int (*rte_mtr_stats_update_t)(struct rte_eth_dev *dev,
|
||||
uint32_t mtr_id,
|
||||
uint64_t stats_mask,
|
||||
@ -124,14 +139,23 @@ struct rte_mtr_ops {
|
||||
/** MTR object meter DSCP table update */
|
||||
rte_mtr_meter_dscp_table_update_t meter_dscp_table_update;
|
||||
|
||||
/** MTR object policer action update */
|
||||
rte_mtr_policer_actions_update_t policer_actions_update;
|
||||
|
||||
/** MTR object enabled stats update */
|
||||
rte_mtr_stats_update_t stats_update;
|
||||
|
||||
/** MTR object stats read */
|
||||
rte_mtr_stats_read_t stats_read;
|
||||
|
||||
/** MTR meter policy validate */
|
||||
rte_mtr_meter_policy_validate_t meter_policy_validate;
|
||||
|
||||
/** MTR meter policy add */
|
||||
rte_mtr_meter_policy_add_t meter_policy_add;
|
||||
|
||||
/** MTR meter policy delete */
|
||||
rte_mtr_meter_policy_delete_t meter_policy_delete;
|
||||
|
||||
/** MTR object meter policy update */
|
||||
rte_mtr_meter_policy_update_t meter_policy_update;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -138,7 +138,6 @@ EXPERIMENTAL {
|
||||
rte_mtr_meter_profile_add;
|
||||
rte_mtr_meter_profile_delete;
|
||||
rte_mtr_meter_profile_update;
|
||||
rte_mtr_policer_actions_update;
|
||||
rte_mtr_stats_read;
|
||||
rte_mtr_stats_update;
|
||||
|
||||
@ -246,6 +245,10 @@ EXPERIMENTAL {
|
||||
rte_flow_action_handle_destroy;
|
||||
rte_flow_action_handle_update;
|
||||
rte_flow_action_handle_query;
|
||||
rte_mtr_meter_policy_add;
|
||||
rte_mtr_meter_policy_delete;
|
||||
rte_mtr_meter_policy_update;
|
||||
rte_mtr_meter_policy_validate;
|
||||
};
|
||||
|
||||
INTERNAL {
|
||||
|
Loading…
Reference in New Issue
Block a user