Skip to content

Commit 2cc43b4

Browse files
Maor Gottliebdavem330
authored andcommitted
net/mlx5_core: Managing root flow table
The root Flow Table for each Flow Table Type is defined, by default, as the Flow Table with level 0. In order not to use an empty flow tables and introduce new hops, but still preserve space for flow-tables that have a priority greater(lower number) than the current flow table, we introduce this new set root flow table command. This command tells the HW to start matching packets from the assigned root flow table. This command is used when we create new flow table with level lower than the current lowest flow table or it is the first flow table. Signed-off-by: Maor Gottlieb <[email protected]> Signed-off-by: Moni Shoua <[email protected]> Signed-off-by: Matan Barak <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent fdb6896 commit 2cc43b4

5 files changed

Lines changed: 144 additions & 10 deletions

File tree

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,24 @@
3838
#include "fs_cmd.h"
3939
#include "mlx5_core.h"
4040

41+
int mlx5_cmd_update_root_ft(struct mlx5_core_dev *dev,
42+
struct mlx5_flow_table *ft)
43+
{
44+
u32 in[MLX5_ST_SZ_DW(set_flow_table_root_in)];
45+
u32 out[MLX5_ST_SZ_DW(set_flow_table_root_out)];
46+
47+
memset(in, 0, sizeof(in));
48+
49+
MLX5_SET(set_flow_table_root_in, in, opcode,
50+
MLX5_CMD_OP_SET_FLOW_TABLE_ROOT);
51+
MLX5_SET(set_flow_table_root_in, in, table_type, ft->type);
52+
MLX5_SET(set_flow_table_root_in, in, table_id, ft->id);
53+
54+
memset(out, 0, sizeof(out));
55+
return mlx5_cmd_exec_check_status(dev, in, sizeof(in), out,
56+
sizeof(out));
57+
}
58+
4159
int mlx5_cmd_create_flow_table(struct mlx5_core_dev *dev,
4260
enum fs_flow_table_type type, unsigned int level,
4361
unsigned int log_size, unsigned int *table_id)

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,6 @@ int mlx5_cmd_delete_fte(struct mlx5_core_dev *dev,
6262
struct mlx5_flow_table *ft,
6363
unsigned int index);
6464

65+
int mlx5_cmd_update_root_ft(struct mlx5_core_dev *dev,
66+
struct mlx5_flow_table *ft);
6567
#endif

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

Lines changed: 88 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,29 @@ static struct mlx5_flow_table *find_prev_chained_ft(struct fs_prio *prio)
510510
return find_closest_ft(prio, true);
511511
}
512512

513+
static int update_root_ft_create(struct mlx5_flow_table *ft, struct fs_prio
514+
*prio)
515+
{
516+
struct mlx5_flow_root_namespace *root = find_root(&prio->node);
517+
int min_level = INT_MAX;
518+
int err;
519+
520+
if (root->root_ft)
521+
min_level = root->root_ft->level;
522+
523+
if (ft->level >= min_level)
524+
return 0;
525+
526+
err = mlx5_cmd_update_root_ft(root->dev, ft);
527+
if (err)
528+
mlx5_core_warn(root->dev, "Update root flow table of id=%u failed\n",
529+
ft->id);
530+
else
531+
root->root_ft = ft;
532+
533+
return err;
534+
}
535+
513536
struct mlx5_flow_table *mlx5_create_flow_table(struct mlx5_flow_namespace *ns,
514537
int prio,
515538
int max_fte)
@@ -526,22 +549,23 @@ struct mlx5_flow_table *mlx5_create_flow_table(struct mlx5_flow_namespace *ns,
526549
return ERR_PTR(-ENODEV);
527550
}
528551

552+
mutex_lock(&root->chain_lock);
529553
fs_prio = find_prio(ns, prio);
530-
if (!fs_prio)
531-
return ERR_PTR(-EINVAL);
532-
533-
lock_ref_node(&fs_prio->node);
554+
if (!fs_prio) {
555+
err = -EINVAL;
556+
goto unlock_root;
557+
}
534558
if (fs_prio->num_ft == fs_prio->max_ft) {
535559
err = -ENOSPC;
536-
goto unlock_prio;
560+
goto unlock_root;
537561
}
538562

539563
ft = alloc_flow_table(find_next_free_level(fs_prio),
540564
roundup_pow_of_two(max_fte),
541565
root->table_type);
542566
if (!ft) {
543567
err = -ENOMEM;
544-
goto unlock_prio;
568+
goto unlock_root;
545569
}
546570

547571
tree_init_node(&ft->node, 1, del_flow_table);
@@ -551,15 +575,25 @@ struct mlx5_flow_table *mlx5_create_flow_table(struct mlx5_flow_namespace *ns,
551575
if (err)
552576
goto free_ft;
553577

578+
if (MLX5_CAP_FLOWTABLE(root->dev,
579+
flow_table_properties_nic_receive.modify_root)) {
580+
err = update_root_ft_create(ft, fs_prio);
581+
if (err)
582+
goto destroy_ft;
583+
}
584+
lock_ref_node(&fs_prio->node);
554585
tree_add_node(&ft->node, &fs_prio->node);
555586
list_add_tail(&ft->node.list, &fs_prio->node.children);
556587
fs_prio->num_ft++;
557588
unlock_ref_node(&fs_prio->node);
589+
mutex_unlock(&root->chain_lock);
558590
return ft;
591+
destroy_ft:
592+
mlx5_cmd_destroy_flow_table(root->dev, ft);
559593
free_ft:
560594
kfree(ft);
561-
unlock_prio:
562-
unlock_ref_node(&fs_prio->node);
595+
unlock_root:
596+
mutex_unlock(&root->chain_lock);
563597
return ERR_PTR(err);
564598
}
565599

@@ -899,13 +933,57 @@ void mlx5_del_flow_rule(struct mlx5_flow_rule *rule)
899933
tree_remove_node(&rule->node);
900934
}
901935

936+
/* Assuming prio->node.children(flow tables) is sorted by level */
937+
static struct mlx5_flow_table *find_next_ft(struct mlx5_flow_table *ft)
938+
{
939+
struct fs_prio *prio;
940+
941+
fs_get_obj(prio, ft->node.parent);
942+
943+
if (!list_is_last(&ft->node.list, &prio->node.children))
944+
return list_next_entry(ft, node.list);
945+
return find_next_chained_ft(prio);
946+
}
947+
948+
static int update_root_ft_destroy(struct mlx5_flow_table *ft)
949+
{
950+
struct mlx5_flow_root_namespace *root = find_root(&ft->node);
951+
struct mlx5_flow_table *new_root_ft = NULL;
952+
953+
if (root->root_ft != ft)
954+
return 0;
955+
956+
new_root_ft = find_next_ft(ft);
957+
if (new_root_ft) {
958+
int err = mlx5_cmd_update_root_ft(root->dev, new_root_ft);
959+
960+
if (err) {
961+
mlx5_core_warn(root->dev, "Update root flow table of id=%u failed\n",
962+
ft->id);
963+
return err;
964+
}
965+
root->root_ft = new_root_ft;
966+
}
967+
return 0;
968+
}
969+
902970
int mlx5_destroy_flow_table(struct mlx5_flow_table *ft)
903971
{
972+
struct mlx5_flow_root_namespace *root = find_root(&ft->node);
973+
int err = 0;
974+
975+
mutex_lock(&root->chain_lock);
976+
err = update_root_ft_destroy(ft);
977+
if (err) {
978+
mutex_unlock(&root->chain_lock);
979+
return err;
980+
}
904981
if (tree_remove_node(&ft->node))
905982
mlx5_core_warn(get_dev(&ft->node), "Flow table %d wasn't destroyed, refcount > 1\n",
906983
ft->id);
984+
mutex_unlock(&root->chain_lock);
907985

908-
return 0;
986+
return err;
909987
}
910988

911989
void mlx5_destroy_flow_group(struct mlx5_flow_group *fg)
@@ -1072,6 +1150,7 @@ static struct mlx5_flow_root_namespace *create_root_ns(struct mlx5_core_dev *dev
10721150

10731151
ns = &root_ns->ns;
10741152
fs_init_namespace(ns);
1153+
mutex_init(&root_ns->chain_lock);
10751154
tree_init_node(&ns->node, 1, NULL);
10761155
tree_add_node(&ns->node, NULL);
10771156

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,9 @@ struct mlx5_flow_root_namespace {
129129
struct mlx5_flow_namespace ns;
130130
enum fs_flow_table_type table_type;
131131
struct mlx5_core_dev *dev;
132+
struct mlx5_flow_table *root_ft;
133+
/* Should be held when chaining flow tables */
134+
struct mutex chain_lock;
132135
};
133136

134137
int mlx5_init_fs(struct mlx5_core_dev *dev);
@@ -148,6 +151,9 @@ void mlx5_cleanup_fs(struct mlx5_core_dev *dev);
148151
#define fs_for_each_prio(pos, ns) \
149152
fs_list_for_each_entry(pos, &(ns)->node.children)
150153

154+
#define fs_for_each_ft(pos, prio) \
155+
fs_list_for_each_entry(pos, &(prio)->node.children)
156+
151157
#define fs_for_each_fg(pos, ft) \
152158
fs_list_for_each_entry(pos, &(ft)->node.children)
153159

include/linux/mlx5/mlx5_ifc.h

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ enum {
185185
MLX5_CMD_OP_MODIFY_RQT = 0x917,
186186
MLX5_CMD_OP_DESTROY_RQT = 0x918,
187187
MLX5_CMD_OP_QUERY_RQT = 0x919,
188+
MLX5_CMD_OP_SET_FLOW_TABLE_ROOT = 0x92f,
188189
MLX5_CMD_OP_CREATE_FLOW_TABLE = 0x930,
189190
MLX5_CMD_OP_DESTROY_FLOW_TABLE = 0x931,
190191
MLX5_CMD_OP_QUERY_FLOW_TABLE = 0x932,
@@ -258,7 +259,8 @@ struct mlx5_ifc_flow_table_prop_layout_bits {
258259
u8 ft_support[0x1];
259260
u8 reserved_0[0x2];
260261
u8 flow_modify_en[0x1];
261-
u8 reserved_1[0x1c];
262+
u8 modify_root[0x1];
263+
u8 reserved_1[0x1b];
262264

263265
u8 reserved_2[0x2];
264266
u8 log_max_ft_size[0x6];
@@ -6946,4 +6948,31 @@ union mlx5_ifc_uplink_pci_interface_document_bits {
69466948
u8 reserved_0[0x20060];
69476949
};
69486950

6951+
struct mlx5_ifc_set_flow_table_root_out_bits {
6952+
u8 status[0x8];
6953+
u8 reserved_0[0x18];
6954+
6955+
u8 syndrome[0x20];
6956+
6957+
u8 reserved_1[0x40];
6958+
};
6959+
6960+
struct mlx5_ifc_set_flow_table_root_in_bits {
6961+
u8 opcode[0x10];
6962+
u8 reserved_0[0x10];
6963+
6964+
u8 reserved_1[0x10];
6965+
u8 op_mod[0x10];
6966+
6967+
u8 reserved_2[0x40];
6968+
6969+
u8 table_type[0x8];
6970+
u8 reserved_3[0x18];
6971+
6972+
u8 reserved_4[0x8];
6973+
u8 table_id[0x18];
6974+
6975+
u8 reserved_5[0x140];
6976+
};
6977+
69496978
#endif /* MLX5_IFC_H */

0 commit comments

Comments
 (0)