/*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",
(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,
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)
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",
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);
},
};
-/* *** 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;
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;
| ``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
~~~~~~~~~~~~~~
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
* 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.**
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
-----------
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
~~~~~~~~~~~~~~~~~~~~~~~~~
/* 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;
/* 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;
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;
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.
*
/* 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. */
};
(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,
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;
(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);
/* 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;
}
/* 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;
}
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. */
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;
}
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);
}
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
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.
*
.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,
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;
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.
*
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;
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);
{
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)
"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.");
{
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,
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;
}
{
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;
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;
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,
};
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;
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;
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,
} 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.");
{
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;
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;
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;
struct mtr_internals {
struct softnic_mtr_meter_profile_list meter_profiles;
+ struct softnic_mtr_meter_policy_list meter_policies;
struct softnic_mtr_list mtrs;
};
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;
/**
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
*/
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,
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)
{
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;
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)
/* Update dependencies */
mp->n_users++;
+ policy->n_users++;
return 0;
}
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);
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);
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);
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) {
/* 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,
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;
}
/* 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];
}
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];
}
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);
.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,
.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,
#include <rte_bitops.h>
#include <rte_mbuf.h>
#include <rte_mbuf_dyn.h>
+#include <rte_meter.h>
#ifdef __cplusplus
extern "C" {
* @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,
};
/**
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.
*/
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,
mtr_id, meter_profile_id, error);
}
-/** MTR object meter DSCP table update */
+/** MTR object meter policy update */
int
-rte_mtr_meter_dscp_table_update(uint16_t port_id,
+rte_mtr_meter_policy_update(uint16_t port_id,
uint32_t mtr_id,
- enum rte_color *dscp_table,
+ 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_dscp_table_update)(dev,
- mtr_id, dscp_table, error);
+ return RTE_MTR_FUNC(port_id, meter_policy_update)(dev,
+ mtr_id, meter_policy_id, error);
}
-/** MTR object policer action update */
+/** MTR object meter DSCP table update */
int
-rte_mtr_policer_actions_update(uint16_t port_id,
+rte_mtr_meter_dscp_table_update(uint16_t port_id,
uint32_t mtr_id,
- uint32_t action_mask,
- enum rte_mtr_policer_action *actions,
+ enum rte_color *dscp_table,
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);
+ return RTE_MTR_FUNC(port_id, meter_dscp_table_update)(dev,
+ mtr_id, dscp_table, error);
}
/** MTR object enabled stats update */
#include <rte_compat.h>
#include <rte_common.h>
#include <rte_meter.h>
+#include <rte_flow.h>
#ifdef __cplusplus
extern "C" {
};
/**
- * 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];
};
/**
*/
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;
};
/**
*/
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.
*/
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
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,
};
/**
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
*
struct rte_mtr_error *error);
/**
- * MTR object DSCP table update
+ * 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] dscp_table
- * 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”
- * populated table (i.e. table with all the 64 elements set to green color).
+ * @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
*/
__rte_experimental
int
-rte_mtr_meter_dscp_table_update(uint16_t port_id,
+rte_mtr_meter_policy_update(uint16_t port_id,
uint32_t mtr_id,
- enum rte_color *dscp_table,
+ uint32_t meter_policy_id,
struct rte_mtr_error *error);
/**
- * MTR object policer actions update
+ * MTR object DSCP table 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[in] dscp_table
+ * 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"
+ * 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.
* @return
*/
__rte_experimental
int
-rte_mtr_policer_actions_update(uint16_t port_id,
+rte_mtr_meter_dscp_table_update(uint16_t port_id,
uint32_t mtr_id,
- uint32_t action_mask,
- enum rte_mtr_policer_action *actions,
+ enum rte_color *dscp_table,
struct rte_mtr_error *error);
/**
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,
struct rte_mtr_error *error);
/**< @internal MTR object meter profile update */
-typedef int (*rte_mtr_meter_dscp_table_update_t)(struct rte_eth_dev *dev,
+typedef int (*rte_mtr_meter_policy_update_t)(struct rte_eth_dev *dev,
uint32_t mtr_id,
- enum rte_color *dscp_table,
+ uint32_t meter_policy_id,
struct rte_mtr_error *error);
-/**< @internal MTR object meter DSCP table update */
+/**< @internal MTR object meter policy update */
-typedef int (*rte_mtr_policer_actions_update_t)(struct rte_eth_dev *dev,
+typedef int (*rte_mtr_meter_dscp_table_update_t)(struct rte_eth_dev *dev,
uint32_t mtr_id,
- uint32_t action_mask,
- enum rte_mtr_policer_action *actions,
+ enum rte_color *dscp_table,
struct rte_mtr_error *error);
-/**< @internal MTR object policer action update*/
+/**< @internal MTR object meter DSCP table update */
typedef int (*rte_mtr_stats_update_t)(struct rte_eth_dev *dev,
uint32_t mtr_id,
/** 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;
};
/**
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;
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 {