static int mlx5i_create_flow_steering(struct mlx5e_priv *priv) { struct ttc_params ttc_params = {}; int tt, err; priv->fs.ns = mlx5_get_flow_namespace(priv->mdev, MLX5_FLOW_NAMESPACE_KERNEL); if (!priv->fs.ns) return -EINVAL; err = mlx5e_arfs_create_tables(priv); if (err) { netdev_err(priv->netdev, "Failed to create arfs tables, err=%d\n", err); priv->netdev->hw_features &= ~NETIF_F_NTUPLE; } mlx5e_set_ttc_basic_params(priv, &ttc_params); mlx5e_set_inner_ttc_ft_params(&ttc_params); for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) ttc_params.indir_tirn[tt] = priv->inner_indir_tir[tt].tirn; err = mlx5e_create_inner_ttc_table(priv, &ttc_params, &priv->fs.inner_ttc); if (err) { netdev_err(priv->netdev, "Failed to create inner ttc table, err=%d\n", err); goto err_destroy_arfs_tables; } mlx5e_set_ttc_ft_params(&ttc_params); for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) ttc_params.indir_tirn[tt] = priv->indir_tir[tt].tirn; err = mlx5e_create_ttc_table(priv, &ttc_params, &priv->fs.ttc); if (err) { netdev_err(priv->netdev, "Failed to create ttc table, err=%d\n", err); goto err_destroy_inner_ttc_table; } return 0; err_destroy_inner_ttc_table: mlx5e_destroy_inner_ttc_table(priv, &priv->fs.inner_ttc); err_destroy_arfs_tables: mlx5e_arfs_destroy_tables(priv); return err; }
static int mlx5i_create_flow_steering(struct mlx5e_priv *priv) { int err; priv->fs.ns = mlx5_get_flow_namespace(priv->mdev, MLX5_FLOW_NAMESPACE_KERNEL); if (!priv->fs.ns) return -EINVAL; err = mlx5e_arfs_create_tables(priv); if (err) { netdev_err(priv->netdev, "Failed to create arfs tables, err=%d\n", err); priv->netdev->hw_features &= ~NETIF_F_NTUPLE; } err = mlx5e_create_inner_ttc_table(priv); if (err) { netdev_err(priv->netdev, "Failed to create inner ttc table, err=%d\n", err); goto err_destroy_arfs_tables; } err = mlx5e_create_ttc_table(priv); if (err) { netdev_err(priv->netdev, "Failed to create ttc table, err=%d\n", err); goto err_destroy_inner_ttc_table; } return 0; err_destroy_inner_ttc_table: mlx5e_destroy_inner_ttc_table(priv); err_destroy_arfs_tables: mlx5e_arfs_destroy_tables(priv); return err; }
static int mlx5_esw_create_fdb_table(struct mlx5_core_dev *dev, int nvports) { int max_fdb_size = 1 << MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size); struct mlx5_eswitch *esw = &dev->priv.eswitch; struct mlx5_flow_group *mc_promisc_grp; struct mlx5_flow_namespace *root_ns; struct mlx5_flow_group *promisc_grp; struct mlx5_flow_group *addr_grp; struct mlx5_flow_table *fdb; void *match_criteria; int table_size; u32 *grp_in; u8 *dmac; int err; max_fdb_size -= 2; /* FW reserve */ table_size = MLX5_MAX_UC_PER_VPORT(dev); table_size += MLX5_MAX_MC_PER_VPORT(dev); table_size *= nvports; table_size += 1; /* TODO: reserve 1 as a FW W/A for modify Rule */ table_size += 4; /* 2 Promisc groups reserve 1 per each */ table_size = min(table_size, max_fdb_size - 2); esw_debug(dev, "Create FDB talbe size(%d) max_size(%d)\n", table_size, max_fdb_size - 2); /* TODO: Don't allow vports to get more than they deserve */ root_ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_FDB); if (!root_ns) { esw_warn(dev, "Failed to get FDB flow namespace\n"); return -ENOMEM; } fdb = mlx5_create_flow_table(root_ns, 0, "eswitch-fdb", table_size); if (IS_ERR_OR_NULL(fdb)) { esw_warn(dev, "Failed to create FDB flow table err(%ld)\n", PTR_ERR(fdb)); return PTR_ERR(fdb); } grp_in = kzalloc(MLX5_ST_SZ_BYTES(create_flow_group_in), GFP_KERNEL); if (!grp_in) { esw_warn(dev, "Failed to alloc group inbox\n"); err = -ENOMEM; goto err_fdb; } MLX5_SET(create_flow_group_in, grp_in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS); match_criteria = MLX5_ADDR_OF(create_flow_group_in, grp_in, match_criteria); dmac = MLX5_ADDR_OF(fte_match_param, match_criteria, outer_headers.dmac_47_16); /* MC/UC ADDR Group */ MLX5_SET(create_flow_group_in, grp_in, start_flow_index, 0); MLX5_SET(create_flow_group_in, grp_in, end_flow_index, table_size - 5); memset(dmac, 0xff, ETH_ALEN); addr_grp = mlx5_create_flow_group(fdb, grp_in); if (IS_ERR_OR_NULL(addr_grp)) { esw_warn(dev, "Failed to create uc/mc addr group err(%ld)\n", PTR_ERR(addr_grp)); err = PTR_ERR(addr_grp); goto err_fdb; } /* MC promisc Group */ MLX5_SET(create_flow_group_in, grp_in, start_flow_index, table_size - 4); MLX5_SET(create_flow_group_in, grp_in, end_flow_index, table_size - 3); memset(dmac, 0, ETH_ALEN); dmac[0] = 0x01; mc_promisc_grp = mlx5_create_flow_group(fdb, grp_in); if (IS_ERR_OR_NULL(mc_promisc_grp)) { esw_warn(dev, "Failed to create FDB MC promisc group err(%ld)\n", PTR_ERR(mc_promisc_grp)); err = PTR_ERR(mc_promisc_grp); goto err_addr_grp; } /* Promisc Group */ MLX5_SET(create_flow_group_in, grp_in, match_criteria_enable, 0); MLX5_SET(create_flow_group_in, grp_in, start_flow_index, table_size - 2); MLX5_SET(create_flow_group_in, grp_in, end_flow_index, table_size - 1); memset(dmac, 0, ETH_ALEN); promisc_grp = mlx5_create_flow_group(fdb, grp_in); if (IS_ERR_OR_NULL(promisc_grp)) { esw_warn(dev, "Failed to create FDB promisc group err(%ld)\n", PTR_ERR(promisc_grp)); err = PTR_ERR(promisc_grp); goto err_mc_promisc_grp; } kfree(grp_in); esw->fdb_table.fdb = fdb; esw->fdb_table.addr_grp = addr_grp; esw->fdb_table.mc_promisc_grp = mc_promisc_grp; esw->fdb_table.promisc_grp = promisc_grp; return 0; err_mc_promisc_grp: mlx5_destroy_flow_group(mc_promisc_grp); err_addr_grp: mlx5_destroy_flow_group(addr_grp); err_fdb: mlx5_destroy_flow_table(fdb); kfree(grp_in); return err; }