net/mlx5: check metadata registers availability
The metadata registers reg_c provide support for TAG and SET_TAG features. Although there are 8 registers are available on the current mlx5 devices, some of them can be reserved. The availability should be queried by iterative trial-and-error implemented by mlx5_flow_discover_mreg_c() routine. If reg_c is available, it can be regarded inclusively that the extensive metadata support is possible. E.g. metadata register copy action, supporting 16 modify header actions (instead of 8 by default) preserving register across different domains (FDB and NIC) and so on. Signed-off-by: Yongseok Koh <yskoh@mellanox.com> Signed-off-by: Viacheslav Ovsiienko <viacheslavo@mellanox.com> Acked-by: Matan Azrad <matan@mellanox.com>
This commit is contained in:
parent
e2bb15f761
commit
5e61bcdd24
@ -2341,6 +2341,17 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
|
||||
goto error;
|
||||
}
|
||||
priv->config.flow_prio = err;
|
||||
/* Query availibility of metadata reg_c's. */
|
||||
err = mlx5_flow_discover_mreg_c(eth_dev);
|
||||
if (err < 0) {
|
||||
err = -err;
|
||||
goto error;
|
||||
}
|
||||
if (!mlx5_flow_ext_mreg_supported(eth_dev)) {
|
||||
DRV_LOG(DEBUG,
|
||||
"port %u extensive metadata register is not supported",
|
||||
eth_dev->data->port_id);
|
||||
}
|
||||
return eth_dev;
|
||||
error:
|
||||
if (priv) {
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "mlx5_autoconf.h"
|
||||
#include "mlx5_defs.h"
|
||||
#include "mlx5_glue.h"
|
||||
#include "mlx5_prm.h"
|
||||
|
||||
enum {
|
||||
PCI_VENDOR_ID_MELLANOX = 0x15b3,
|
||||
@ -254,6 +255,8 @@ struct mlx5_dev_config {
|
||||
} mprq; /* Configurations for Multi-Packet RQ. */
|
||||
int mps; /* Multi-packet send supported mode. */
|
||||
unsigned int flow_prio; /* Number of flow priorities. */
|
||||
enum modify_reg flow_mreg_c[MLX5_MREG_C_NUM];
|
||||
/* Availibility of mreg_c's. */
|
||||
unsigned int tso_max_payload_sz; /* Maximum TCP payload for TSO. */
|
||||
unsigned int ind_table_max_size; /* Maximum indirection table size. */
|
||||
unsigned int max_dump_files_num; /* Maximum dump files per queue. */
|
||||
@ -563,6 +566,10 @@ struct mlx5_flow_tbl_resource {
|
||||
|
||||
#define MLX5_MAX_TABLES UINT16_MAX
|
||||
#define MLX5_HAIRPIN_TX_TABLE (UINT16_MAX - 1)
|
||||
/* Reserve the last two tables for metadata register copy. */
|
||||
#define MLX5_FLOW_MREG_ACT_TABLE_GROUP (MLX5_MAX_TABLES - 1)
|
||||
#define MLX5_FLOW_MREG_CP_TABLE_GROUP \
|
||||
(MLX5_FLOW_MREG_ACT_TABLE_GROUP - 1)
|
||||
#define MLX5_MAX_TABLES_FDB UINT16_MAX
|
||||
|
||||
#define MLX5_DBR_PAGE_SIZE 4096 /* Must be >= 512. */
|
||||
@ -788,7 +795,7 @@ int mlx5_set_link_up(struct rte_eth_dev *dev);
|
||||
int mlx5_is_removed(struct rte_eth_dev *dev);
|
||||
eth_tx_burst_t mlx5_select_tx_function(struct rte_eth_dev *dev);
|
||||
eth_rx_burst_t mlx5_select_rx_function(struct rte_eth_dev *dev);
|
||||
struct mlx5_priv *mlx5_port_to_eswitch_info(uint16_t port);
|
||||
struct mlx5_priv *mlx5_port_to_eswitch_info(uint16_t port, bool valid);
|
||||
struct mlx5_priv *mlx5_dev_to_eswitch_info(struct rte_eth_dev *dev);
|
||||
int mlx5_sysfs_switch_info(unsigned int ifindex,
|
||||
struct mlx5_switch_info *info);
|
||||
@ -868,6 +875,8 @@ int mlx5_traffic_restart(struct rte_eth_dev *dev);
|
||||
|
||||
/* mlx5_flow.c */
|
||||
|
||||
int mlx5_flow_discover_mreg_c(struct rte_eth_dev *eth_dev);
|
||||
bool mlx5_flow_ext_mreg_supported(struct rte_eth_dev *dev);
|
||||
int mlx5_flow_discover_priorities(struct rte_eth_dev *dev);
|
||||
void mlx5_flow_print(struct rte_flow *flow);
|
||||
int mlx5_flow_validate(struct rte_eth_dev *dev,
|
||||
|
@ -1793,6 +1793,10 @@ mlx5_is_removed(struct rte_eth_dev *dev)
|
||||
*
|
||||
* @param[in] port
|
||||
* Device port id.
|
||||
* @param[in] valid
|
||||
* Device port id is valid, skip check. This flag is useful
|
||||
* when trials are performed from probing and device is not
|
||||
* flagged as valid yet (in attaching process).
|
||||
* @param[out] es_domain_id
|
||||
* E-Switch domain id.
|
||||
* @param[out] es_port_id
|
||||
@ -1803,7 +1807,7 @@ mlx5_is_removed(struct rte_eth_dev *dev)
|
||||
* on success, NULL otherwise and rte_errno is set.
|
||||
*/
|
||||
struct mlx5_priv *
|
||||
mlx5_port_to_eswitch_info(uint16_t port)
|
||||
mlx5_port_to_eswitch_info(uint16_t port, bool valid)
|
||||
{
|
||||
struct rte_eth_dev *dev;
|
||||
struct mlx5_priv *priv;
|
||||
@ -1812,7 +1816,7 @@ mlx5_port_to_eswitch_info(uint16_t port)
|
||||
rte_errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
if (!rte_eth_dev_is_valid_port(port)) {
|
||||
if (!valid && !rte_eth_dev_is_valid_port(port)) {
|
||||
rte_errno = ENODEV;
|
||||
return NULL;
|
||||
}
|
||||
|
@ -372,6 +372,33 @@ static enum modify_reg flow_get_reg_id(struct rte_eth_dev *dev,
|
||||
NULL, "invalid feature name");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check extensive flow metadata register support.
|
||||
*
|
||||
* @param dev
|
||||
* Pointer to rte_eth_dev structure.
|
||||
*
|
||||
* @return
|
||||
* True if device supports extensive flow metadata register, otherwise false.
|
||||
*/
|
||||
bool
|
||||
mlx5_flow_ext_mreg_supported(struct rte_eth_dev *dev)
|
||||
{
|
||||
struct mlx5_priv *priv = dev->data->dev_private;
|
||||
struct mlx5_dev_config *config = &priv->config;
|
||||
|
||||
/*
|
||||
* Having available reg_c can be regarded inclusively as supporting
|
||||
* extensive flow metadata register, which could mean,
|
||||
* - metadata register copy action by modify header.
|
||||
* - 16 modify header actions is supported.
|
||||
* - reg_c's are preserved across different domain (FDB and NIC) on
|
||||
* packet loopback by flow lookup miss.
|
||||
*/
|
||||
return config->flow_mreg_c[2] != REG_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Discover the maximum number of priority available.
|
||||
*
|
||||
@ -4051,3 +4078,74 @@ mlx5_flow_group_to_table(const struct rte_flow_attr *attributes, bool external,
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Discover availability of metadata reg_c's.
|
||||
*
|
||||
* Iteratively use test flows to check availability.
|
||||
*
|
||||
* @param[in] dev
|
||||
* Pointer to the Ethernet device structure.
|
||||
*
|
||||
* @return
|
||||
* 0 on success, a negative errno value otherwise and rte_errno is set.
|
||||
*/
|
||||
int
|
||||
mlx5_flow_discover_mreg_c(struct rte_eth_dev *dev)
|
||||
{
|
||||
struct mlx5_priv *priv = dev->data->dev_private;
|
||||
struct mlx5_dev_config *config = &priv->config;
|
||||
enum modify_reg idx;
|
||||
int n = 0;
|
||||
|
||||
/* reg_c[0] and reg_c[1] are reserved. */
|
||||
config->flow_mreg_c[n++] = REG_C_0;
|
||||
config->flow_mreg_c[n++] = REG_C_1;
|
||||
/* Discover availability of other reg_c's. */
|
||||
for (idx = REG_C_2; idx <= REG_C_7; ++idx) {
|
||||
struct rte_flow_attr attr = {
|
||||
.group = MLX5_FLOW_MREG_CP_TABLE_GROUP,
|
||||
.priority = MLX5_FLOW_PRIO_RSVD,
|
||||
.ingress = 1,
|
||||
};
|
||||
struct rte_flow_item items[] = {
|
||||
[0] = {
|
||||
.type = RTE_FLOW_ITEM_TYPE_END,
|
||||
},
|
||||
};
|
||||
struct rte_flow_action actions[] = {
|
||||
[0] = {
|
||||
.type = MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG,
|
||||
.conf = &(struct mlx5_flow_action_copy_mreg){
|
||||
.src = REG_C_1,
|
||||
.dst = idx,
|
||||
},
|
||||
},
|
||||
[1] = {
|
||||
.type = RTE_FLOW_ACTION_TYPE_JUMP,
|
||||
.conf = &(struct rte_flow_action_jump){
|
||||
.group = MLX5_FLOW_MREG_ACT_TABLE_GROUP,
|
||||
},
|
||||
},
|
||||
[2] = {
|
||||
.type = RTE_FLOW_ACTION_TYPE_END,
|
||||
},
|
||||
};
|
||||
struct rte_flow *flow;
|
||||
struct rte_flow_error error;
|
||||
|
||||
if (!config->dv_flow_en)
|
||||
break;
|
||||
/* Create internal flow, validation skips copy action. */
|
||||
flow = flow_list_create(dev, NULL, &attr, items,
|
||||
actions, false, &error);
|
||||
if (!flow)
|
||||
continue;
|
||||
if (dev->data->dev_started || !flow_drv_apply(dev, flow, NULL))
|
||||
config->flow_mreg_c[n++] = idx;
|
||||
flow_list_destroy(dev, NULL, flow);
|
||||
}
|
||||
for (; n < MLX5_MREG_C_NUM; ++n)
|
||||
config->flow_mreg_c[n] = REG_NONE;
|
||||
return 0;
|
||||
}
|
||||
|
@ -27,19 +27,6 @@
|
||||
#include "mlx5.h"
|
||||
#include "mlx5_prm.h"
|
||||
|
||||
enum modify_reg {
|
||||
REG_A,
|
||||
REG_B,
|
||||
REG_C_0,
|
||||
REG_C_1,
|
||||
REG_C_2,
|
||||
REG_C_3,
|
||||
REG_C_4,
|
||||
REG_C_5,
|
||||
REG_C_6,
|
||||
REG_C_7,
|
||||
};
|
||||
|
||||
/* Private rte flow items. */
|
||||
enum mlx5_rte_flow_item_type {
|
||||
MLX5_RTE_FLOW_ITEM_TYPE_END = INT_MIN,
|
||||
|
@ -832,6 +832,7 @@ flow_dv_convert_action_modify_tcp_ack
|
||||
}
|
||||
|
||||
static enum mlx5_modification_field reg_to_field[] = {
|
||||
[REG_NONE] = MLX5_MODI_OUT_NONE,
|
||||
[REG_A] = MLX5_MODI_META_DATA_REG_A,
|
||||
[REG_B] = MLX5_MODI_META_DATA_REG_B,
|
||||
[REG_C_0] = MLX5_MODI_META_REG_C_0,
|
||||
@ -1040,7 +1041,7 @@ flow_dv_validate_item_port_id(struct rte_eth_dev *dev,
|
||||
return ret;
|
||||
if (!spec)
|
||||
return 0;
|
||||
esw_priv = mlx5_port_to_eswitch_info(spec->id);
|
||||
esw_priv = mlx5_port_to_eswitch_info(spec->id, false);
|
||||
if (!esw_priv)
|
||||
return rte_flow_error_set(error, rte_errno,
|
||||
RTE_FLOW_ERROR_TYPE_ITEM_SPEC, spec,
|
||||
@ -2697,7 +2698,7 @@ flow_dv_validate_action_port_id(struct rte_eth_dev *dev,
|
||||
"failed to obtain E-Switch info");
|
||||
port_id = action->conf;
|
||||
port = port_id->original ? dev->data->port_id : port_id->id;
|
||||
act_priv = mlx5_port_to_eswitch_info(port);
|
||||
act_priv = mlx5_port_to_eswitch_info(port, false);
|
||||
if (!act_priv)
|
||||
return rte_flow_error_set
|
||||
(error, rte_errno,
|
||||
@ -5119,7 +5120,7 @@ flow_dv_translate_item_port_id(struct rte_eth_dev *dev, void *matcher,
|
||||
|
||||
mask = pid_m ? pid_m->id : 0xffff;
|
||||
id = pid_v ? pid_v->id : dev->data->port_id;
|
||||
priv = mlx5_port_to_eswitch_info(id);
|
||||
priv = mlx5_port_to_eswitch_info(id, item == NULL);
|
||||
if (!priv)
|
||||
return -rte_errno;
|
||||
/* Translate to vport field or to metadata, depending on mode. */
|
||||
@ -5567,7 +5568,7 @@ flow_dv_translate_action_port_id(struct rte_eth_dev *dev,
|
||||
(const struct rte_flow_action_port_id *)action->conf;
|
||||
|
||||
port = conf->original ? dev->data->port_id : conf->id;
|
||||
priv = mlx5_port_to_eswitch_info(port);
|
||||
priv = mlx5_port_to_eswitch_info(port, false);
|
||||
if (!priv)
|
||||
return rte_flow_error_set(error, -rte_errno,
|
||||
RTE_FLOW_ERROR_TYPE_ACTION,
|
||||
|
@ -392,6 +392,7 @@ enum {
|
||||
|
||||
/* The field of packet to be modified. */
|
||||
enum mlx5_modification_field {
|
||||
MLX5_MODI_OUT_NONE = -1,
|
||||
MLX5_MODI_OUT_SMAC_47_16 = 1,
|
||||
MLX5_MODI_OUT_SMAC_15_0,
|
||||
MLX5_MODI_OUT_ETHERTYPE,
|
||||
@ -455,6 +456,23 @@ enum mlx5_modification_field {
|
||||
MLX5_MODI_IN_TCP_ACK_NUM = 0x5C,
|
||||
};
|
||||
|
||||
/* Total number of metadata reg_c's. */
|
||||
#define MLX5_MREG_C_NUM (MLX5_MODI_META_REG_C_7 - MLX5_MODI_META_REG_C_0 + 1)
|
||||
|
||||
enum modify_reg {
|
||||
REG_NONE = 0,
|
||||
REG_A,
|
||||
REG_B,
|
||||
REG_C_0,
|
||||
REG_C_1,
|
||||
REG_C_2,
|
||||
REG_C_3,
|
||||
REG_C_4,
|
||||
REG_C_5,
|
||||
REG_C_6,
|
||||
REG_C_7,
|
||||
};
|
||||
|
||||
/* Modification sub command. */
|
||||
struct mlx5_modification_cmd {
|
||||
union {
|
||||
|
Loading…
Reference in New Issue
Block a user