#include "mlx5_common_os.h"
#include "mlx5_utils.h"
#include "mlx5_rxtx.h"
+#include "mlx5_rx.h"
+#include "mlx5_tx.h"
#include "mlx5_autoconf.h"
#include "mlx5_mr.h"
#include "mlx5_flow.h"
goto error;
}
sh->fdb_domain = domain;
- sh->esw_drop_action = mlx5_glue->dr_create_flow_action_drop();
+ }
+ /*
+ * The drop action is just some dummy placeholder in rdma-core. It
+ * does not belong to domains and has no any attributes, and, can be
+ * shared by the entire device.
+ */
+ sh->dr_drop_action = mlx5_glue->dr_create_flow_action_drop();
+ if (!sh->dr_drop_action) {
+ DRV_LOG(ERR, "FDB mlx5dv_dr_create_flow_action_drop");
+ err = errno;
+ goto error;
}
#endif
if (!sh->tunnel_hub)
mlx5_glue->dr_destroy_domain(sh->fdb_domain);
sh->fdb_domain = NULL;
}
- if (sh->esw_drop_action) {
- mlx5_glue->destroy_flow_action(sh->esw_drop_action);
- sh->esw_drop_action = NULL;
+ if (sh->dr_drop_action) {
+ mlx5_glue->destroy_flow_action(sh->dr_drop_action);
+ sh->dr_drop_action = NULL;
}
if (sh->pop_vlan_action) {
mlx5_glue->destroy_flow_action(sh->pop_vlan_action);
mlx5_glue->dr_destroy_domain(sh->fdb_domain);
sh->fdb_domain = NULL;
}
- if (sh->esw_drop_action) {
- mlx5_glue->destroy_flow_action(sh->esw_drop_action);
- sh->esw_drop_action = NULL;
+ if (sh->dr_drop_action) {
+ mlx5_glue->destroy_flow_action(sh->dr_drop_action);
+ sh->dr_drop_action = NULL;
}
#endif
if (sh->pop_vlan_action) {
struct mlx5_switch_info *switch_info = &spawn->info;
unsigned int p, f;
uint16_t id;
- uint16_t repr_id = mlx5_representor_id_encode(switch_info);
+ uint16_t repr_id = mlx5_representor_id_encode(switch_info,
+ eth_da->type);
switch (eth_da->type) {
case RTE_ETH_REPRESENTOR_SF:
- if (switch_info->name_type != MLX5_PHYS_PORT_NAME_TYPE_PFSF) {
+ if (!(spawn->info.port_name == -1 &&
+ switch_info->name_type ==
+ MLX5_PHYS_PORT_NAME_TYPE_PFHPF) &&
+ switch_info->name_type != MLX5_PHYS_PORT_NAME_TYPE_PFSF) {
rte_errno = EBUSY;
return false;
}
if (spawn->pf_bond < 0) {
/* For non-LAG mode, allow and ignore pf. */
switch_info->pf_num = eth_da->ports[p];
- repr_id = mlx5_representor_id_encode(switch_info);
+ repr_id = mlx5_representor_id_encode(switch_info,
+ eth_da->type);
}
for (f = 0; f < eth_da->nb_representor_ports; ++f) {
id = MLX5_REPRESENTOR_ID
}
if (devx_port.comp_mask & MLX5DV_DEVX_PORT_VPORT) {
priv->vport_id = devx_port.vport_num;
- } else if (spawn->pf_bond >= 0) {
+ } else if (spawn->pf_bond >= 0 &&
+ (switch_info->representor || switch_info->master)) {
DRV_LOG(ERR, "can't deduce vport index for port %d"
" on bonding device %s",
spawn->phys_port,
priv->vport_id = switch_info->representor ?
switch_info->port_name + 1 : -1;
#endif
- priv->representor_id = mlx5_representor_id_encode(switch_info);
+ priv->representor_id = mlx5_representor_id_encode(switch_info,
+ eth_da->type);
/*
* Look for sibling devices in order to reuse their switch domain
* if any, otherwise allocate one.
"required for coalescing is %d bytes",
config->hca_attr.lro_min_mss_size);
}
-#if defined(HAVE_MLX5DV_DR) && defined(HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER)
+#if defined(HAVE_MLX5DV_DR) && \
+ (defined(HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER) || \
+ defined(HAVE_MLX5_DR_CREATE_ACTION_ASO))
if (config->hca_attr.qos.sup &&
config->hca_attr.qos.flow_meter_old &&
config->dv_flow_en) {
priv->mtr_color_reg);
}
}
+ if (config->hca_attr.qos.sup &&
+ config->hca_attr.qos.flow_meter_aso_sup) {
+ uint32_t log_obj_size =
+ rte_log2_u32(MLX5_ASO_MTRS_PER_POOL >> 1);
+ if (log_obj_size >=
+ config->hca_attr.qos.log_meter_aso_granularity &&
+ log_obj_size <=
+ config->hca_attr.qos.log_meter_aso_max_alloc)
+ sh->meter_aso_en = 1;
+ }
+ if (priv->mtr_en) {
+ err = mlx5_aso_flow_mtrs_mng_init(priv->sh);
+ if (err) {
+ err = -err;
+ goto error;
+ }
+ }
#endif
#ifdef HAVE_MLX5_DR_CREATE_ACTION_ASO
if (config->hca_attr.flow_hit_aso &&
DRV_LOG(DEBUG, "Flow Hit ASO is supported.");
}
#endif /* HAVE_MLX5_DR_CREATE_ACTION_ASO */
+#if defined(HAVE_MLX5_DR_CREATE_ACTION_ASO) && \
+ defined(HAVE_MLX5_DR_ACTION_ASO_CT)
+ if (config->hca_attr.ct_offload &&
+ priv->mtr_color_reg == REG_C_3) {
+ err = mlx5_flow_aso_ct_mng_init(sh);
+ if (err) {
+ err = -err;
+ goto error;
+ }
+ DRV_LOG(DEBUG, "CT ASO is supported.");
+ sh->ct_aso_en = 1;
+ }
+#endif /* HAVE_MLX5_DR_CREATE_ACTION_ASO && HAVE_MLX5_DR_ACTION_ASO_CT */
#if defined(HAVE_MLX5DV_DR) && defined(HAVE_MLX5_DR_CREATE_ACTION_FLOW_SAMPLE)
if (config->hca_attr.log_max_ft_sampler_num > 0 &&
config->dv_flow_en) {
*/
MLX5_ASSERT(spawn->ifindex);
priv->if_index = spawn->ifindex;
- if (priv->pf_bond >= 0 && priv->master) {
- /* Get bond interface info */
- err = mlx5_sysfs_bond_info(priv->if_index,
- &priv->bond_ifindex,
- priv->bond_name);
- if (err)
- DRV_LOG(ERR, "unable to get bond info: %s",
- strerror(rte_errno));
- else
- DRV_LOG(INFO, "PF device %u, bond device %u(%s)",
- priv->if_index, priv->bond_ifindex,
- priv->bond_name);
- }
eth_dev->data->dev_private = priv;
priv->dev_data = eth_dev->data;
eth_dev->data->mac_addrs = priv->mac;
* Netlink RDMA group socket handle.
* @param[in] owner
* Rerepsentor owner PF index.
+ * @param[out] bond_info
+ * Pointer to bonding information.
*
* @return
* negative value if no bonding device found, otherwise
static int
mlx5_device_bond_pci_match(const struct ibv_device *ibv_dev,
const struct rte_pci_addr *pci_dev,
- int nl_rdma, uint16_t owner)
+ int nl_rdma, uint16_t owner,
+ struct mlx5_bond_info *bond_info)
{
char ifname[IF_NAMESIZE + 1];
unsigned int ifindex;
unsigned int np, i;
- FILE *file = NULL;
+ FILE *bond_file = NULL, *file;
int pf = -1;
+ int ret;
/*
* Try to get master device name. If something goes
* wrong suppose the lack of kernel support and no
* bonding devices.
*/
+ memset(bond_info, 0, sizeof(*bond_info));
if (nl_rdma < 0)
return -1;
if (!strstr(ibv_dev->name, "bond"))
/* Try to read bonding slave names from sysfs. */
MKSTR(slaves,
"/sys/class/net/%s/master/bonding/slaves", ifname);
- file = fopen(slaves, "r");
- if (file)
+ bond_file = fopen(slaves, "r");
+ if (bond_file)
break;
}
- if (!file)
+ if (!bond_file)
return -1;
/* Use safe format to check maximal buffer length. */
MLX5_ASSERT(atol(RTE_STR(IF_NAMESIZE)) == IF_NAMESIZE);
- while (fscanf(file, "%" RTE_STR(IF_NAMESIZE) "s", ifname) == 1) {
+ while (fscanf(bond_file, "%" RTE_STR(IF_NAMESIZE) "s", ifname) == 1) {
char tmp_str[IF_NAMESIZE + 32];
struct rte_pci_addr pci_addr;
struct mlx5_switch_info info;
" for netdev \"%s\"", ifname);
continue;
}
- if (pci_dev->domain != pci_addr.domain ||
- pci_dev->bus != pci_addr.bus ||
- pci_dev->devid != pci_addr.devid ||
- pci_dev->function + owner != pci_addr.function)
- continue;
/* Slave interface PCI address match found. */
- fclose(file);
snprintf(tmp_str, sizeof(tmp_str),
"/sys/class/net/%s/phys_port_name", ifname);
file = fopen(tmp_str, "rb");
info.name_type = MLX5_PHYS_PORT_NAME_TYPE_NOTSET;
if (fscanf(file, "%32s", tmp_str) == 1)
mlx5_translate_port_name(tmp_str, &info);
- if (info.name_type == MLX5_PHYS_PORT_NAME_TYPE_LEGACY ||
- info.name_type == MLX5_PHYS_PORT_NAME_TYPE_UPLINK)
+ fclose(file);
+ /* Only process PF ports. */
+ if (info.name_type != MLX5_PHYS_PORT_NAME_TYPE_LEGACY &&
+ info.name_type != MLX5_PHYS_PORT_NAME_TYPE_UPLINK)
+ continue;
+ /* Check max bonding member. */
+ if (info.port_name >= MLX5_BOND_MAX_PORTS) {
+ DRV_LOG(WARNING, "bonding index out of range, "
+ "please increase MLX5_BOND_MAX_PORTS: %s",
+ tmp_str);
+ break;
+ }
+ /* Match PCI address. */
+ if (pci_dev->domain == pci_addr.domain &&
+ pci_dev->bus == pci_addr.bus &&
+ pci_dev->devid == pci_addr.devid &&
+ pci_dev->function + owner == pci_addr.function)
pf = info.port_name;
- break;
- }
- if (file)
+ /* Get ifindex. */
+ snprintf(tmp_str, sizeof(tmp_str),
+ "/sys/class/net/%s/ifindex", ifname);
+ file = fopen(tmp_str, "rb");
+ if (!file)
+ break;
+ ret = fscanf(file, "%u", &ifindex);
fclose(file);
+ if (ret != 1)
+ break;
+ /* Save bonding info. */
+ strncpy(bond_info->ports[info.port_name].ifname, ifname,
+ sizeof(bond_info->ports[0].ifname));
+ bond_info->ports[info.port_name].pci_addr = pci_addr;
+ bond_info->ports[info.port_name].ifindex = ifindex;
+ bond_info->n_port++;
+ }
+ if (pf >= 0) {
+ /* Get bond interface info */
+ ret = mlx5_sysfs_bond_info(ifindex, &bond_info->ifindex,
+ bond_info->ifname);
+ if (ret)
+ DRV_LOG(ERR, "unable to get bond info: %s",
+ strerror(rte_errno));
+ else
+ DRV_LOG(INFO, "PF device %u, bond device %u(%s)",
+ ifindex, bond_info->ifindex, bond_info->ifname);
+ }
return pf;
}
/**
- * DPDK callback to register a PCI device.
+ * Register a PCI device within bonding.
*
- * This function spawns Ethernet devices out of a given PCI device.
+ * This function spawns Ethernet devices out of a given PCI device and
+ * bonding owner PF index.
*
- * @param[in] pci_drv
- * PCI driver structure (mlx5_driver).
* @param[in] pci_dev
* PCI device information.
+ * @param[in] req_eth_da
+ * Requested ethdev device argument.
+ * @param[in] owner_id
+ * Requested owner PF port ID within bonding device, default to 0.
*
* @return
* 0 on success, a negative errno value otherwise and rte_errno is set.
*/
-int
-mlx5_os_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
- struct rte_pci_device *pci_dev)
+static int
+mlx5_os_pci_probe_pf(struct rte_pci_device *pci_dev,
+ struct rte_eth_devargs *req_eth_da,
+ uint16_t owner_id)
{
struct ibv_device **ibv_list;
/*
struct mlx5_dev_spawn_data *list = NULL;
struct mlx5_dev_config dev_config;
unsigned int dev_config_vf;
- struct rte_eth_devargs eth_da = { .type = RTE_ETH_REPRESENTOR_NONE };
+ struct rte_eth_devargs eth_da = *req_eth_da;
struct rte_pci_addr owner_pci = pci_dev->addr; /* Owner PF. */
+ struct mlx5_bond_info bond_info;
int ret = -1;
if (rte_eal_process_type() == RTE_PROC_PRIMARY)
strerror(rte_errno));
return -rte_errno;
}
- if (pci_dev->device.devargs) {
- /* Parse representor information from device argument. */
- if (pci_dev->device.devargs->cls_str)
- ret = rte_eth_devargs_parse
- (pci_dev->device.devargs->cls_str, ð_da);
- if (ret) {
- DRV_LOG(ERR, "failed to parse device arguments: %s",
- pci_dev->device.devargs->cls_str);
- return -rte_errno;
- }
- if (eth_da.type == RTE_ETH_REPRESENTOR_NONE) {
- /* Support legacy device argument */
- ret = rte_eth_devargs_parse
- (pci_dev->device.devargs->args, ð_da);
- if (ret) {
- DRV_LOG(ERR, "failed to parse device arguments: %s",
- pci_dev->device.devargs->args);
- return -rte_errno;
- }
- }
- }
errno = 0;
ibv_list = mlx5_glue->get_device_list(&ret);
if (!ibv_list) {
DRV_LOG(DEBUG, "checking device \"%s\"", ibv_list[ret]->name);
bd = mlx5_device_bond_pci_match
- (ibv_list[ret], &owner_pci, nl_rdma,
- eth_da.ports[0]);
+ (ibv_list[ret], &owner_pci, nl_rdma, owner_id,
+ &bond_info);
if (bd >= 0) {
/*
* Bonding device detected. Only one match is allowed,
}
/* Amend owner pci address if owner PF ID specified. */
if (eth_da.nb_representor_ports)
- owner_pci.function += eth_da.ports[0];
+ owner_pci.function += owner_id;
DRV_LOG(INFO, "PCI information matches for"
" slave %d bonding device \"%s\"",
bd, ibv_list[ret]->name);
MLX5_ASSERT(nd == 1);
MLX5_ASSERT(np);
for (i = 1; i <= np; ++i) {
+ list[ns].bond_info = &bond_info;
list[ns].max_port = np;
list[ns].phys_port = i;
list[ns].phys_dev = ibv_match[0];
*/
for (i = 0; i != nd; ++i) {
memset(&list[ns].info, 0, sizeof(list[ns].info));
+ list[ns].bond_info = NULL;
list[ns].max_port = 1;
list[ns].phys_port = 1;
list[ns].phys_dev = ibv_match[i];
return ret;
}
+/**
+ * DPDK callback to register a PCI device.
+ *
+ * This function spawns Ethernet devices out of a given PCI device.
+ *
+ * @param[in] pci_drv
+ * PCI driver structure (mlx5_driver).
+ * @param[in] pci_dev
+ * PCI device information.
+ *
+ * @return
+ * 0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+int
+mlx5_os_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
+ struct rte_pci_device *pci_dev)
+{
+ struct rte_eth_devargs eth_da = { .type = RTE_ETH_REPRESENTOR_NONE };
+ int ret = 0;
+ uint16_t p;
+
+ if (pci_dev->device.devargs) {
+ /* Parse representor information from device argument. */
+ if (pci_dev->device.devargs->cls_str)
+ ret = rte_eth_devargs_parse
+ (pci_dev->device.devargs->cls_str, ð_da);
+ if (ret) {
+ DRV_LOG(ERR, "failed to parse device arguments: %s",
+ pci_dev->device.devargs->cls_str);
+ return -rte_errno;
+ }
+ if (eth_da.type == RTE_ETH_REPRESENTOR_NONE) {
+ /* Support legacy device argument */
+ ret = rte_eth_devargs_parse
+ (pci_dev->device.devargs->args, ð_da);
+ if (ret) {
+ DRV_LOG(ERR, "failed to parse device arguments: %s",
+ pci_dev->device.devargs->args);
+ return -rte_errno;
+ }
+ }
+ }
+
+ if (eth_da.nb_ports > 0) {
+ /* Iterate all port if devargs pf is range: "pf[0-1]vf[...]". */
+ for (p = 0; p < eth_da.nb_ports; p++)
+ ret = mlx5_os_pci_probe_pf(pci_dev, ð_da,
+ eth_da.ports[p]);
+ } else {
+ ret = mlx5_os_pci_probe_pf(pci_dev, ð_da, 0);
+ }
+ return ret;
+}
+
static int
mlx5_config_doorbell_mapping_env(const struct mlx5_dev_config *config)
{