Skip to content

Commit f90edfd

Browse files
Maor Gottliebdavem330
authored andcommitted
net/mlx5_core: Connect flow tables
Flow tables from different priorities should be chained together. When a packet arrives we search for a match in the by-pass flow tables (first we search for a match in priority 0 and if we don't find a match we move to the next priority). If we can't find a match in any of the bypass flow-tables, we continue searching in the flow-tables of the next priority, which are the kernel's flow tables. Setting the miss flow table in a new flow table to be the next one in the list is performed via create flow table API. If we want to change an existing flow table, for example in order to point from an existing flow table to the new next-in-list flow table, we use the modify flow table API. Signed-off-by: Maor Gottlieb <maorg@mellanox.com> Signed-off-by: Moni Shoua <monis@mellanox.com> Signed-off-by: Matan Barak <matanb@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 34a40e6 commit f90edfd

File tree

3 files changed

+104
-10
lines changed

3 files changed

+104
-10
lines changed

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ int mlx5_cmd_update_root_ft(struct mlx5_core_dev *dev,
5858

5959
int mlx5_cmd_create_flow_table(struct mlx5_core_dev *dev,
6060
enum fs_flow_table_type type, unsigned int level,
61-
unsigned int log_size, unsigned int *table_id)
61+
unsigned int log_size, struct mlx5_flow_table
62+
*next_ft, unsigned int *table_id)
6263
{
6364
u32 out[MLX5_ST_SZ_DW(create_flow_table_out)];
6465
u32 in[MLX5_ST_SZ_DW(create_flow_table_in)];
@@ -69,6 +70,10 @@ int mlx5_cmd_create_flow_table(struct mlx5_core_dev *dev,
6970
MLX5_SET(create_flow_table_in, in, opcode,
7071
MLX5_CMD_OP_CREATE_FLOW_TABLE);
7172

73+
if (next_ft) {
74+
MLX5_SET(create_flow_table_in, in, table_miss_mode, 1);
75+
MLX5_SET(create_flow_table_in, in, table_miss_id, next_ft->id);
76+
}
7277
MLX5_SET(create_flow_table_in, in, table_type, type);
7378
MLX5_SET(create_flow_table_in, in, level, level);
7479
MLX5_SET(create_flow_table_in, in, log_size, log_size);

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@
3535

3636
int mlx5_cmd_create_flow_table(struct mlx5_core_dev *dev,
3737
enum fs_flow_table_type type, unsigned int level,
38-
unsigned int log_size, unsigned int *table_id);
38+
unsigned int log_size, struct mlx5_flow_table
39+
*next_ft, unsigned int *table_id);
3940

4041
int mlx5_cmd_destroy_flow_table(struct mlx5_core_dev *dev,
4142
struct mlx5_flow_table *ft);

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

Lines changed: 96 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,48 @@ 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 connect_fts_in_prio(struct mlx5_core_dev *dev,
514+
struct fs_prio *prio,
515+
struct mlx5_flow_table *ft)
516+
{
517+
struct mlx5_flow_table *iter;
518+
int i = 0;
519+
int err;
520+
521+
fs_for_each_ft(iter, prio) {
522+
i++;
523+
err = mlx5_cmd_modify_flow_table(dev,
524+
iter,
525+
ft);
526+
if (err) {
527+
mlx5_core_warn(dev, "Failed to modify flow table %d\n",
528+
iter->id);
529+
/* The driver is out of sync with the FW */
530+
if (i > 1)
531+
WARN_ON(true);
532+
return err;
533+
}
534+
}
535+
return 0;
536+
}
537+
538+
/* Connect flow tables from previous priority of prio to ft */
539+
static int connect_prev_fts(struct mlx5_core_dev *dev,
540+
struct mlx5_flow_table *ft,
541+
struct fs_prio *prio)
542+
{
543+
struct mlx5_flow_table *prev_ft;
544+
545+
prev_ft = find_prev_chained_ft(prio);
546+
if (prev_ft) {
547+
struct fs_prio *prev_prio;
548+
549+
fs_get_obj(prev_prio, prev_ft->node.parent);
550+
return connect_fts_in_prio(dev, prev_prio, ft);
551+
}
552+
return 0;
553+
}
554+
513555
static int update_root_ft_create(struct mlx5_flow_table *ft, struct fs_prio
514556
*prio)
515557
{
@@ -533,10 +575,30 @@ static int update_root_ft_create(struct mlx5_flow_table *ft, struct fs_prio
533575
return err;
534576
}
535577

578+
static int connect_flow_table(struct mlx5_core_dev *dev, struct mlx5_flow_table *ft,
579+
struct fs_prio *prio)
580+
{
581+
int err = 0;
582+
583+
/* Connect_prev_fts and update_root_ft_create are mutually exclusive */
584+
585+
if (list_empty(&prio->node.children)) {
586+
err = connect_prev_fts(dev, ft, prio);
587+
if (err)
588+
return err;
589+
}
590+
591+
if (MLX5_CAP_FLOWTABLE(dev,
592+
flow_table_properties_nic_receive.modify_root))
593+
err = update_root_ft_create(ft, prio);
594+
return err;
595+
}
596+
536597
struct mlx5_flow_table *mlx5_create_flow_table(struct mlx5_flow_namespace *ns,
537598
int prio,
538599
int max_fte)
539600
{
601+
struct mlx5_flow_table *next_ft = NULL;
540602
struct mlx5_flow_table *ft;
541603
int err;
542604
int log_table_sz;
@@ -570,17 +632,15 @@ struct mlx5_flow_table *mlx5_create_flow_table(struct mlx5_flow_namespace *ns,
570632

571633
tree_init_node(&ft->node, 1, del_flow_table);
572634
log_table_sz = ilog2(ft->max_fte);
635+
next_ft = find_next_chained_ft(fs_prio);
573636
err = mlx5_cmd_create_flow_table(root->dev, ft->type, ft->level,
574-
log_table_sz, &ft->id);
637+
log_table_sz, next_ft, &ft->id);
575638
if (err)
576639
goto free_ft;
577640

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-
}
641+
err = connect_flow_table(root->dev, ft, fs_prio);
642+
if (err)
643+
goto destroy_ft;
584644
lock_ref_node(&fs_prio->node);
585645
tree_add_node(&ft->node, &fs_prio->node);
586646
list_add_tail(&ft->node.list, &fs_prio->node.children);
@@ -967,13 +1027,41 @@ static int update_root_ft_destroy(struct mlx5_flow_table *ft)
9671027
return 0;
9681028
}
9691029

1030+
/* Connect flow table from previous priority to
1031+
* the next flow table.
1032+
*/
1033+
static int disconnect_flow_table(struct mlx5_flow_table *ft)
1034+
{
1035+
struct mlx5_core_dev *dev = get_dev(&ft->node);
1036+
struct mlx5_flow_table *next_ft;
1037+
struct fs_prio *prio;
1038+
int err = 0;
1039+
1040+
err = update_root_ft_destroy(ft);
1041+
if (err)
1042+
return err;
1043+
1044+
fs_get_obj(prio, ft->node.parent);
1045+
if (!(list_first_entry(&prio->node.children,
1046+
struct mlx5_flow_table,
1047+
node.list) == ft))
1048+
return 0;
1049+
1050+
next_ft = find_next_chained_ft(prio);
1051+
err = connect_prev_fts(dev, next_ft, prio);
1052+
if (err)
1053+
mlx5_core_warn(dev, "Failed to disconnect flow table %d\n",
1054+
ft->id);
1055+
return err;
1056+
}
1057+
9701058
int mlx5_destroy_flow_table(struct mlx5_flow_table *ft)
9711059
{
9721060
struct mlx5_flow_root_namespace *root = find_root(&ft->node);
9731061
int err = 0;
9741062

9751063
mutex_lock(&root->chain_lock);
976-
err = update_root_ft_destroy(ft);
1064+
err = disconnect_flow_table(ft);
9771065
if (err) {
9781066
mutex_unlock(&root->chain_lock);
9791067
return err;

0 commit comments

Comments
 (0)