Commit 78a9199b authored by Mohamad Haj Yahia's avatar Mohamad Haj Yahia Committed by David S. Miller

net/mlx5: E-Switch, Add promiscuous and allmulti FDB flowtable groups

Add promiscuous and allmulti steering groups in FDB table.
Besides the full match L2 steering rules group, we added
two more groups to catch the "miss" rules traffic:
* Allmulti group: One rule that forwards any mcast traffic coming from
either uplink or VFs/PF vports
* Promisc group: One rule that forwards all unmatched traffic coming
from uplink.

Needed for downstream privileged VF promisc and allmulti support.
Signed-off-by: default avatarMohamad Haj Yahia <mohamad@mellanox.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 586cfa7f
...@@ -323,15 +323,17 @@ static void del_l2_table_entry(struct mlx5_core_dev *dev, u32 index) ...@@ -323,15 +323,17 @@ static void del_l2_table_entry(struct mlx5_core_dev *dev, u32 index)
/* E-Switch FDB */ /* E-Switch FDB */
static struct mlx5_flow_rule * static struct mlx5_flow_rule *
esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u8 mac[ETH_ALEN], u32 vport) __esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u32 vport,
u8 mac_c[ETH_ALEN], u8 mac_v[ETH_ALEN])
{ {
int match_header = MLX5_MATCH_OUTER_HEADERS; int match_header = (is_zero_ether_addr(mac_c) ? 0 :
struct mlx5_flow_destination dest; MLX5_MATCH_OUTER_HEADERS);
struct mlx5_flow_rule *flow_rule = NULL; struct mlx5_flow_rule *flow_rule = NULL;
struct mlx5_flow_destination dest;
u8 *dmac_v = NULL;
u8 *dmac_c = NULL;
u32 *match_v; u32 *match_v;
u32 *match_c; u32 *match_c;
u8 *dmac_v;
u8 *dmac_c;
match_v = kzalloc(MLX5_ST_SZ_BYTES(fte_match_param), GFP_KERNEL); match_v = kzalloc(MLX5_ST_SZ_BYTES(fte_match_param), GFP_KERNEL);
match_c = kzalloc(MLX5_ST_SZ_BYTES(fte_match_param), GFP_KERNEL); match_c = kzalloc(MLX5_ST_SZ_BYTES(fte_match_param), GFP_KERNEL);
...@@ -339,14 +341,16 @@ esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u8 mac[ETH_ALEN], u32 vport) ...@@ -339,14 +341,16 @@ esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u8 mac[ETH_ALEN], u32 vport)
pr_warn("FDB: Failed to alloc match parameters\n"); pr_warn("FDB: Failed to alloc match parameters\n");
goto out; goto out;
} }
dmac_v = MLX5_ADDR_OF(fte_match_param, match_v, dmac_v = MLX5_ADDR_OF(fte_match_param, match_v,
outer_headers.dmac_47_16); outer_headers.dmac_47_16);
dmac_c = MLX5_ADDR_OF(fte_match_param, match_c, dmac_c = MLX5_ADDR_OF(fte_match_param, match_c,
outer_headers.dmac_47_16); outer_headers.dmac_47_16);
ether_addr_copy(dmac_v, mac); if (match_header == MLX5_MATCH_OUTER_HEADERS) {
/* Match criteria mask */ ether_addr_copy(dmac_v, mac_v);
memset(dmac_c, 0xff, 6); ether_addr_copy(dmac_c, mac_c);
}
dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT; dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
dest.vport_num = vport; dest.vport_num = vport;
...@@ -373,6 +377,15 @@ esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u8 mac[ETH_ALEN], u32 vport) ...@@ -373,6 +377,15 @@ esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u8 mac[ETH_ALEN], u32 vport)
return flow_rule; return flow_rule;
} }
static struct mlx5_flow_rule *
esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u8 mac[ETH_ALEN], u32 vport)
{
u8 mac_c[ETH_ALEN];
eth_broadcast_addr(mac_c);
return __esw_fdb_set_vport_rule(esw, vport, mac_c, mac);
}
static int esw_create_fdb_table(struct mlx5_eswitch *esw, int nvports) static int esw_create_fdb_table(struct mlx5_eswitch *esw, int nvports)
{ {
int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
...@@ -407,28 +420,74 @@ static int esw_create_fdb_table(struct mlx5_eswitch *esw, int nvports) ...@@ -407,28 +420,74 @@ static int esw_create_fdb_table(struct mlx5_eswitch *esw, int nvports)
esw_warn(dev, "Failed to create FDB Table err %d\n", err); esw_warn(dev, "Failed to create FDB Table err %d\n", err);
goto out; goto out;
} }
esw->fdb_table.fdb = fdb;
/* Addresses group : Full match unicast/multicast addresses */
MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable, MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
MLX5_MATCH_OUTER_HEADERS); MLX5_MATCH_OUTER_HEADERS);
match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria); match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria);
dmac = MLX5_ADDR_OF(fte_match_param, match_criteria, outer_headers.dmac_47_16); dmac = MLX5_ADDR_OF(fte_match_param, match_criteria, outer_headers.dmac_47_16);
MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0); MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 1); /* Preserve 2 entries for allmulti and promisc rules*/
MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 3);
eth_broadcast_addr(dmac); eth_broadcast_addr(dmac);
g = mlx5_create_flow_group(fdb, flow_group_in); g = mlx5_create_flow_group(fdb, flow_group_in);
if (IS_ERR_OR_NULL(g)) { if (IS_ERR_OR_NULL(g)) {
err = PTR_ERR(g); err = PTR_ERR(g);
esw_warn(dev, "Failed to create flow group err(%d)\n", err); esw_warn(dev, "Failed to create flow group err(%d)\n", err);
goto out; goto out;
} }
esw->fdb_table.addr_grp = g; esw->fdb_table.addr_grp = g;
esw->fdb_table.fdb = fdb;
/* Allmulti group : One rule that forwards any mcast traffic */
MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
MLX5_MATCH_OUTER_HEADERS);
MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, table_size - 2);
MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 2);
eth_zero_addr(dmac);
dmac[0] = 0x01;
g = mlx5_create_flow_group(fdb, flow_group_in);
if (IS_ERR_OR_NULL(g)) {
err = PTR_ERR(g);
esw_warn(dev, "Failed to create allmulti flow group err(%d)\n", err);
goto out;
}
esw->fdb_table.allmulti_grp = g;
/* Promiscuous group :
* One rule that forward all unmatched traffic from previous groups
*/
eth_zero_addr(dmac);
MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
MLX5_MATCH_MISC_PARAMETERS);
MLX5_SET_TO_ONES(fte_match_param, match_criteria, misc_parameters.source_port);
MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, table_size - 1);
MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 1);
g = mlx5_create_flow_group(fdb, flow_group_in);
if (IS_ERR_OR_NULL(g)) {
err = PTR_ERR(g);
esw_warn(dev, "Failed to create promisc flow group err(%d)\n", err);
goto out;
}
esw->fdb_table.promisc_grp = g;
out: out:
if (err) {
if (!IS_ERR_OR_NULL(esw->fdb_table.allmulti_grp)) {
mlx5_destroy_flow_group(esw->fdb_table.allmulti_grp);
esw->fdb_table.allmulti_grp = NULL;
}
if (!IS_ERR_OR_NULL(esw->fdb_table.addr_grp)) {
mlx5_destroy_flow_group(esw->fdb_table.addr_grp);
esw->fdb_table.addr_grp = NULL;
}
if (!IS_ERR_OR_NULL(esw->fdb_table.fdb)) {
mlx5_destroy_flow_table(esw->fdb_table.fdb);
esw->fdb_table.fdb = NULL;
}
}
kfree(flow_group_in); kfree(flow_group_in);
if (err && !IS_ERR_OR_NULL(fdb))
mlx5_destroy_flow_table(fdb);
return err; return err;
} }
...@@ -438,10 +497,14 @@ static void esw_destroy_fdb_table(struct mlx5_eswitch *esw) ...@@ -438,10 +497,14 @@ static void esw_destroy_fdb_table(struct mlx5_eswitch *esw)
return; return;
esw_debug(esw->dev, "Destroy FDB Table\n"); esw_debug(esw->dev, "Destroy FDB Table\n");
mlx5_destroy_flow_group(esw->fdb_table.promisc_grp);
mlx5_destroy_flow_group(esw->fdb_table.allmulti_grp);
mlx5_destroy_flow_group(esw->fdb_table.addr_grp); mlx5_destroy_flow_group(esw->fdb_table.addr_grp);
mlx5_destroy_flow_table(esw->fdb_table.fdb); mlx5_destroy_flow_table(esw->fdb_table.fdb);
esw->fdb_table.fdb = NULL; esw->fdb_table.fdb = NULL;
esw->fdb_table.addr_grp = NULL; esw->fdb_table.addr_grp = NULL;
esw->fdb_table.allmulti_grp = NULL;
esw->fdb_table.promisc_grp = NULL;
} }
/* E-Switch vport UC/MC lists management */ /* E-Switch vport UC/MC lists management */
......
...@@ -132,6 +132,8 @@ struct mlx5_l2_table { ...@@ -132,6 +132,8 @@ struct mlx5_l2_table {
struct mlx5_eswitch_fdb { struct mlx5_eswitch_fdb {
void *fdb; void *fdb;
struct mlx5_flow_group *addr_grp; struct mlx5_flow_group *addr_grp;
struct mlx5_flow_group *allmulti_grp;
struct mlx5_flow_group *promisc_grp;
}; };
struct mlx5_eswitch { struct mlx5_eswitch {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment