aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaor Gottlieb <maorg@mellanox.com>2016-01-11 03:26:01 -0500
committerDavid S. Miller <davem@davemloft.net>2016-01-11 17:48:53 -0500
commitf90edfd279f35a5c62003eeee107f03f3b1544bc (patch)
tree191c3058f94487a13817bac4ae56c1fbb605cb28
parent34a40e689393a6b13673ab395a9a4d063d249fe9 (diff)
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>
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c7
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_core.c104
3 files changed, 104 insertions, 10 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
index 2b5562553f2d..a9894d2e8e26 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
@@ -58,7 +58,8 @@ int mlx5_cmd_update_root_ft(struct mlx5_core_dev *dev,
58 58
59int mlx5_cmd_create_flow_table(struct mlx5_core_dev *dev, 59int mlx5_cmd_create_flow_table(struct mlx5_core_dev *dev,
60 enum fs_flow_table_type type, unsigned int level, 60 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)
62{ 63{
63 u32 out[MLX5_ST_SZ_DW(create_flow_table_out)]; 64 u32 out[MLX5_ST_SZ_DW(create_flow_table_out)];
64 u32 in[MLX5_ST_SZ_DW(create_flow_table_in)]; 65 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,
69 MLX5_SET(create_flow_table_in, in, opcode, 70 MLX5_SET(create_flow_table_in, in, opcode,
70 MLX5_CMD_OP_CREATE_FLOW_TABLE); 71 MLX5_CMD_OP_CREATE_FLOW_TABLE);
71 72
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 }
72 MLX5_SET(create_flow_table_in, in, table_type, type); 77 MLX5_SET(create_flow_table_in, in, table_type, type);
73 MLX5_SET(create_flow_table_in, in, level, level); 78 MLX5_SET(create_flow_table_in, in, level, level);
74 MLX5_SET(create_flow_table_in, in, log_size, log_size); 79 MLX5_SET(create_flow_table_in, in, log_size, log_size);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h
index 1ae9b685c783..9814d4784803 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h
@@ -35,7 +35,8 @@
35 35
36int mlx5_cmd_create_flow_table(struct mlx5_core_dev *dev, 36int mlx5_cmd_create_flow_table(struct mlx5_core_dev *dev,
37 enum fs_flow_table_type type, unsigned int level, 37 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);
39 40
40int mlx5_cmd_destroy_flow_table(struct mlx5_core_dev *dev, 41int mlx5_cmd_destroy_flow_table(struct mlx5_core_dev *dev,
41 struct mlx5_flow_table *ft); 42 struct mlx5_flow_table *ft);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
index 64bdb54041d1..c6f864d1ad1a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
@@ -510,6 +510,48 @@ static struct mlx5_flow_table *find_prev_chained_ft(struct fs_prio *prio)
510 return find_closest_ft(prio, true); 510 return find_closest_ft(prio, true);
511} 511}
512 512
513static 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 */
539static 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
513static int update_root_ft_create(struct mlx5_flow_table *ft, struct fs_prio 555static int update_root_ft_create(struct mlx5_flow_table *ft, struct fs_prio
514 *prio) 556 *prio)
515{ 557{
@@ -533,10 +575,30 @@ static int update_root_ft_create(struct mlx5_flow_table *ft, struct fs_prio
533 return err; 575 return err;
534} 576}
535 577
578static 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
536struct mlx5_flow_table *mlx5_create_flow_table(struct mlx5_flow_namespace *ns, 597struct mlx5_flow_table *mlx5_create_flow_table(struct mlx5_flow_namespace *ns,
537 int prio, 598 int prio,
538 int max_fte) 599 int max_fte)
539{ 600{
601 struct mlx5_flow_table *next_ft = NULL;
540 struct mlx5_flow_table *ft; 602 struct mlx5_flow_table *ft;
541 int err; 603 int err;
542 int log_table_sz; 604 int log_table_sz;
@@ -570,17 +632,15 @@ struct mlx5_flow_table *mlx5_create_flow_table(struct mlx5_flow_namespace *ns,
570 632
571 tree_init_node(&ft->node, 1, del_flow_table); 633 tree_init_node(&ft->node, 1, del_flow_table);
572 log_table_sz = ilog2(ft->max_fte); 634 log_table_sz = ilog2(ft->max_fte);
635 next_ft = find_next_chained_ft(fs_prio);
573 err = mlx5_cmd_create_flow_table(root->dev, ft->type, ft->level, 636 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);
575 if (err) 638 if (err)
576 goto free_ft; 639 goto free_ft;
577 640
578 if (MLX5_CAP_FLOWTABLE(root->dev, 641 err = connect_flow_table(root->dev, ft, fs_prio);
579 flow_table_properties_nic_receive.modify_root)) { 642 if (err)
580 err = update_root_ft_create(ft, fs_prio); 643 goto destroy_ft;
581 if (err)
582 goto destroy_ft;
583 }
584 lock_ref_node(&fs_prio->node); 644 lock_ref_node(&fs_prio->node);
585 tree_add_node(&ft->node, &fs_prio->node); 645 tree_add_node(&ft->node, &fs_prio->node);
586 list_add_tail(&ft->node.list, &fs_prio->node.children); 646 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)
967 return 0; 1027 return 0;
968} 1028}
969 1029
1030/* Connect flow table from previous priority to
1031 * the next flow table.
1032 */
1033static 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
970int mlx5_destroy_flow_table(struct mlx5_flow_table *ft) 1058int mlx5_destroy_flow_table(struct mlx5_flow_table *ft)
971{ 1059{
972 struct mlx5_flow_root_namespace *root = find_root(&ft->node); 1060 struct mlx5_flow_root_namespace *root = find_root(&ft->node);
973 int err = 0; 1061 int err = 0;
974 1062
975 mutex_lock(&root->chain_lock); 1063 mutex_lock(&root->chain_lock);
976 err = update_root_ft_destroy(ft); 1064 err = disconnect_flow_table(ft);
977 if (err) { 1065 if (err) {
978 mutex_unlock(&root->chain_lock); 1066 mutex_unlock(&root->chain_lock);
979 return err; 1067 return err;