Skip to content

Commit f478be7

Browse files
matanb10Saeed Mahameed
authored andcommitted
net/mlx5: Add hash table for flow groups in flow table
When adding a flow table entry (fte) to a flow table (ft), we first need to find its flow group (fg). Currently, this is done by traversing a linear list of all flow groups in the flow table. Furthermore, since multiple flow groups which correspond to the same fte mask may exist in the same ft, we can't just stop at the first match. Converting the linear list to rhltable in order to speed things up. The last four patches increases the steering rules update rate by a factor of more than 7 (for insertion of 50K steering rules). Signed-off-by: Matan Barak <[email protected]> Reviewed-by: Maor Gottlieb <[email protected]> Signed-off-by: Saeed Mahameed <[email protected]>
1 parent b7917e7 commit f478be7

File tree

2 files changed

+152
-37
lines changed

2 files changed

+152
-37
lines changed

drivers/net/ethernet/mellanox/mlx5/core/fs_core.c

Lines changed: 150 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,15 @@ static const struct rhashtable_params rhash_fte = {
158158
.min_size = 1,
159159
};
160160

161+
static const struct rhashtable_params rhash_fg = {
162+
.key_len = FIELD_SIZEOF(struct mlx5_flow_group, mask),
163+
.key_offset = offsetof(struct mlx5_flow_group, mask),
164+
.head_offset = offsetof(struct mlx5_flow_group, hash),
165+
.automatic_shrinking = true,
166+
.min_size = 1,
167+
168+
};
169+
161170
static void del_rule(struct fs_node *node);
162171
static void del_flow_table(struct fs_node *node);
163172
static void del_flow_group(struct fs_node *node);
@@ -318,12 +327,22 @@ static bool check_valid_mask(u8 match_criteria_enable, const u32 *match_criteria
318327
return check_last_reserved(match_criteria);
319328
}
320329

321-
static bool compare_match_criteria(u8 match_criteria_enable1,
322-
u8 match_criteria_enable2,
323-
void *mask1, void *mask2)
330+
static bool check_valid_spec(const struct mlx5_flow_spec *spec)
324331
{
325-
return match_criteria_enable1 == match_criteria_enable2 &&
326-
!memcmp(mask1, mask2, MLX5_ST_SZ_BYTES(fte_match_param));
332+
int i;
333+
334+
if (!check_valid_mask(spec->match_criteria_enable, spec->match_criteria)) {
335+
pr_warn("mlx5_core: Match criteria given mismatches match_criteria_enable\n");
336+
return false;
337+
}
338+
339+
for (i = 0; i < MLX5_ST_SZ_DW_MATCH_PARAM; i++)
340+
if (spec->match_value[i] & ~spec->match_criteria[i]) {
341+
pr_warn("mlx5_core: match_value differs from match_criteria\n");
342+
return false;
343+
}
344+
345+
return check_last_reserved(spec->match_value);
327346
}
328347

329348
static struct mlx5_flow_root_namespace *find_root(struct fs_node *node)
@@ -365,6 +384,7 @@ static void del_flow_table(struct fs_node *node)
365384
if (err)
366385
mlx5_core_warn(dev, "flow steering can't destroy ft\n");
367386
ida_destroy(&ft->fte_allocator);
387+
rhltable_destroy(&ft->fgs_hash);
368388
fs_get_obj(prio, ft->node.parent);
369389
prio->num_ft--;
370390
}
@@ -454,6 +474,7 @@ static void del_flow_group(struct fs_node *node)
454474
struct mlx5_flow_group *fg;
455475
struct mlx5_flow_table *ft;
456476
struct mlx5_core_dev *dev;
477+
int err;
457478

458479
fs_get_obj(fg, node);
459480
fs_get_obj(ft, fg->node.parent);
@@ -463,6 +484,10 @@ static void del_flow_group(struct fs_node *node)
463484
ft->autogroup.num_groups--;
464485

465486
rhashtable_destroy(&fg->ftes_hash);
487+
err = rhltable_remove(&ft->fgs_hash,
488+
&fg->hash,
489+
rhash_fg);
490+
WARN_ON(err);
466491
if (mlx5_cmd_destroy_flow_group(dev, ft, fg->id))
467492
mlx5_core_warn(dev, "flow steering can't destroy fg %d of ft %d\n",
468493
fg->id, ft->id);
@@ -525,10 +550,17 @@ static struct mlx5_flow_table *alloc_flow_table(int level, u16 vport, int max_ft
525550
u32 flags)
526551
{
527552
struct mlx5_flow_table *ft;
553+
int ret;
528554

529555
ft = kzalloc(sizeof(*ft), GFP_KERNEL);
530556
if (!ft)
531-
return NULL;
557+
return ERR_PTR(-ENOMEM);
558+
559+
ret = rhltable_init(&ft->fgs_hash, &rhash_fg);
560+
if (ret) {
561+
kfree(ft);
562+
return ERR_PTR(ret);
563+
}
532564

533565
ft->level = level;
534566
ft->node.type = FS_TYPE_FLOW_TABLE;
@@ -829,8 +861,8 @@ static struct mlx5_flow_table *__mlx5_create_flow_table(struct mlx5_flow_namespa
829861
ft_attr->max_fte ? roundup_pow_of_two(ft_attr->max_fte) : 0,
830862
root->table_type,
831863
op_mod, ft_attr->flags);
832-
if (!ft) {
833-
err = -ENOMEM;
864+
if (IS_ERR(ft)) {
865+
err = PTR_ERR(ft);
834866
goto unlock_root;
835867
}
836868

@@ -942,10 +974,14 @@ static struct mlx5_flow_group *create_flow_group_common(struct mlx5_flow_table *
942974
if (IS_ERR(fg))
943975
return fg;
944976

945-
err = mlx5_cmd_create_flow_group(dev, ft, fg_in, &fg->id);
977+
err = rhltable_insert(&ft->fgs_hash, &fg->hash, rhash_fg);
946978
if (err)
947979
goto err_free_fg;
948980

981+
err = mlx5_cmd_create_flow_group(dev, ft, fg_in, &fg->id);
982+
if (err)
983+
goto err_remove_fg;
984+
949985
if (ft->autogroup.active)
950986
ft->autogroup.num_groups++;
951987
/* Add node to tree */
@@ -956,6 +992,10 @@ static struct mlx5_flow_group *create_flow_group_common(struct mlx5_flow_table *
956992

957993
return fg;
958994

995+
err_remove_fg:
996+
WARN_ON(rhltable_remove(&ft->fgs_hash,
997+
&fg->hash,
998+
rhash_fg));
959999
err_free_fg:
9601000
rhashtable_destroy(&fg->ftes_hash);
9611001
kfree(fg);
@@ -1291,18 +1331,13 @@ static struct mlx5_flow_handle *add_rule_fg(struct mlx5_flow_group *fg,
12911331
u32 *match_value,
12921332
struct mlx5_flow_act *flow_act,
12931333
struct mlx5_flow_destination *dest,
1294-
int dest_num)
1334+
int dest_num,
1335+
struct fs_fte *fte)
12951336
{
1296-
u32 masked_val[sizeof(fg->mask.match_criteria)];
12971337
struct mlx5_flow_handle *handle;
12981338
struct mlx5_flow_table *ft;
1299-
struct fs_fte *fte;
13001339
int i;
13011340

1302-
nested_lock_ref_node(&fg->node, FS_MUTEX_PARENT);
1303-
for (i = 0; i < sizeof(masked_val); i++)
1304-
masked_val[i] = match_value[i] & fg->mask.match_criteria[i];
1305-
fte = rhashtable_lookup_fast(&fg->ftes_hash, masked_val, rhash_fte);
13061341
if (fte) {
13071342
int old_action;
13081343
int ret;
@@ -1324,23 +1359,20 @@ static struct mlx5_flow_handle *add_rule_fg(struct mlx5_flow_group *fg,
13241359
} else {
13251360
goto add_rules;
13261361
}
1327-
unlock_ref_node(&fte->node);
13281362
}
13291363
fs_get_obj(ft, fg->node.parent);
13301364

13311365
fte = create_fte(fg, match_value, flow_act);
1332-
if (IS_ERR(fte)) {
1333-
handle = (void *)fte;
1334-
goto unlock_fg;
1335-
}
1366+
if (IS_ERR(fte))
1367+
return (void *)fte;
13361368
tree_init_node(&fte->node, 0, del_fte);
13371369
nested_lock_ref_node(&fte->node, FS_MUTEX_CHILD);
13381370
handle = add_rule_fte(fte, fg, dest, dest_num, false);
13391371
if (IS_ERR(handle)) {
13401372
unlock_ref_node(&fte->node);
13411373
destroy_fte(fte, fg);
13421374
kfree(fte);
1343-
goto unlock_fg;
1375+
return handle;
13441376
}
13451377

13461378
tree_add_node(&fte->node, &fg->node);
@@ -1353,8 +1385,6 @@ static struct mlx5_flow_handle *add_rule_fg(struct mlx5_flow_group *fg,
13531385
}
13541386
unlock_fte:
13551387
unlock_ref_node(&fte->node);
1356-
unlock_fg:
1357-
unlock_ref_node(&fg->node);
13581388
return handle;
13591389
}
13601390

@@ -1402,6 +1432,96 @@ static bool dest_is_valid(struct mlx5_flow_destination *dest,
14021432
return true;
14031433
}
14041434

1435+
static struct mlx5_flow_handle *
1436+
try_add_to_existing_fg(struct mlx5_flow_table *ft,
1437+
struct mlx5_flow_spec *spec,
1438+
struct mlx5_flow_act *flow_act,
1439+
struct mlx5_flow_destination *dest,
1440+
int dest_num)
1441+
{
1442+
struct mlx5_flow_group *g;
1443+
struct mlx5_flow_handle *rule = ERR_PTR(-ENOENT);
1444+
struct rhlist_head *tmp, *list;
1445+
struct match_list {
1446+
struct list_head list;
1447+
struct mlx5_flow_group *g;
1448+
} match_list, *iter;
1449+
LIST_HEAD(match_head);
1450+
1451+
rcu_read_lock();
1452+
/* Collect all fgs which has a matching match_criteria */
1453+
list = rhltable_lookup(&ft->fgs_hash, spec, rhash_fg);
1454+
rhl_for_each_entry_rcu(g, tmp, list, hash) {
1455+
struct match_list *curr_match;
1456+
1457+
if (likely(list_empty(&match_head))) {
1458+
match_list.g = g;
1459+
list_add_tail(&match_list.list, &match_head);
1460+
continue;
1461+
}
1462+
curr_match = kmalloc(sizeof(*curr_match), GFP_ATOMIC);
1463+
1464+
if (!curr_match) {
1465+
rcu_read_unlock();
1466+
rule = ERR_PTR(-ENOMEM);
1467+
goto free_list;
1468+
}
1469+
curr_match->g = g;
1470+
list_add_tail(&curr_match->list, &match_head);
1471+
}
1472+
rcu_read_unlock();
1473+
1474+
/* Try to find a fg that already contains a matching fte */
1475+
list_for_each_entry(iter, &match_head, list) {
1476+
struct fs_fte *fte;
1477+
1478+
g = iter->g;
1479+
nested_lock_ref_node(&g->node, FS_MUTEX_PARENT);
1480+
fte = rhashtable_lookup_fast(&g->ftes_hash, spec->match_value,
1481+
rhash_fte);
1482+
if (fte) {
1483+
rule = add_rule_fg(g, spec->match_value,
1484+
flow_act, dest, dest_num, fte);
1485+
unlock_ref_node(&g->node);
1486+
goto free_list;
1487+
}
1488+
unlock_ref_node(&g->node);
1489+
}
1490+
1491+
/* No group with matching fte found. Try to add a new fte to any
1492+
* matching fg.
1493+
*/
1494+
list_for_each_entry(iter, &match_head, list) {
1495+
g = iter->g;
1496+
1497+
nested_lock_ref_node(&g->node, FS_MUTEX_PARENT);
1498+
rule = add_rule_fg(g, spec->match_value,
1499+
flow_act, dest, dest_num, NULL);
1500+
if (!IS_ERR(rule) || PTR_ERR(rule) != -ENOSPC) {
1501+
unlock_ref_node(&g->node);
1502+
goto free_list;
1503+
}
1504+
unlock_ref_node(&g->node);
1505+
}
1506+
1507+
free_list:
1508+
if (!list_empty(&match_head)) {
1509+
struct match_list *match_tmp;
1510+
1511+
/* The most common case is having one FG. Since we want to
1512+
* optimize this case, we save the first on the stack.
1513+
* Therefore, no need to free it.
1514+
*/
1515+
list_del(&list_first_entry(&match_head, typeof(*iter), list)->list);
1516+
list_for_each_entry_safe(iter, match_tmp, &match_head, list) {
1517+
list_del(&iter->list);
1518+
kfree(iter);
1519+
}
1520+
}
1521+
1522+
return rule;
1523+
}
1524+
14051525
static struct mlx5_flow_handle *
14061526
_mlx5_add_flow_rules(struct mlx5_flow_table *ft,
14071527
struct mlx5_flow_spec *spec,
@@ -1414,8 +1534,7 @@ _mlx5_add_flow_rules(struct mlx5_flow_table *ft,
14141534
struct mlx5_flow_handle *rule;
14151535
int i;
14161536

1417-
if (!check_valid_mask(spec->match_criteria_enable,
1418-
spec->match_criteria))
1537+
if (!check_valid_spec(spec))
14191538
return ERR_PTR(-EINVAL);
14201539

14211540
for (i = 0; i < dest_num; i++) {
@@ -1424,16 +1543,9 @@ _mlx5_add_flow_rules(struct mlx5_flow_table *ft,
14241543
}
14251544

14261545
nested_lock_ref_node(&ft->node, FS_MUTEX_GRANDPARENT);
1427-
fs_for_each_fg(g, ft)
1428-
if (compare_match_criteria(g->mask.match_criteria_enable,
1429-
spec->match_criteria_enable,
1430-
g->mask.match_criteria,
1431-
spec->match_criteria)) {
1432-
rule = add_rule_fg(g, spec->match_value,
1433-
flow_act, dest, dest_num);
1434-
if (!IS_ERR(rule) || PTR_ERR(rule) != -ENOSPC)
1435-
goto unlock;
1436-
}
1546+
rule = try_add_to_existing_fg(ft, spec, flow_act, dest, dest_num);
1547+
if (!IS_ERR(rule))
1548+
goto unlock;
14371549

14381550
g = create_autogroup(ft, spec->match_criteria_enable,
14391551
spec->match_criteria);
@@ -1442,7 +1554,8 @@ _mlx5_add_flow_rules(struct mlx5_flow_table *ft,
14421554
goto unlock;
14431555
}
14441556

1445-
rule = add_rule_fg(g, spec->match_value, flow_act, dest, dest_num);
1557+
rule = add_rule_fg(g, spec->match_value, flow_act, dest,
1558+
dest_num, NULL);
14461559
if (IS_ERR(rule)) {
14471560
/* Remove assumes refcount > 0 and autogroup creates a group
14481561
* with a refcount = 0.

drivers/net/ethernet/mellanox/mlx5/core/fs_core.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ struct mlx5_flow_table {
120120
struct list_head fwd_rules;
121121
u32 flags;
122122
struct ida fte_allocator;
123+
struct rhltable fgs_hash;
123124
};
124125

125126
struct mlx5_fc_cache {
@@ -200,6 +201,7 @@ struct mlx5_flow_group {
200201
u32 max_ftes;
201202
u32 id;
202203
struct rhashtable ftes_hash;
204+
struct rhlist_head hash;
203205
};
204206

205207
struct mlx5_flow_root_namespace {

0 commit comments

Comments
 (0)