diff options
author | Aviv Heller <avivh@mellanox.com> | 2016-05-09 05:57:05 -0400 |
---|---|---|
committer | Leon Romanovsky <leon@kernel.org> | 2016-08-18 11:49:56 -0400 |
commit | aaff1bea16bb7f259a263c3ae4633d092e2da799 (patch) | |
tree | 6c4f82ed6a6abac3f8c95eaf020dbca0ebee5b66 | |
parent | edb31b1686751f605eb02a6dcf5ef29c5d485a8e (diff) |
net/mlx5: LAG demux flow table support
Add interfaces to allow the creation and destruction of a
LAG demux flow table.
It is a special flow table used during LAG for redirecting
non user-mode packets from PF0 to PF1 root ft, if a packet was
received on phys port two.
Signed-off-by: Aviv Heller <avivh@mellanox.com>
Reviewed-by: Maor Gottlieb <maorg@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Signed-off-by: Leon Romanovsky <leon@kernel.org>
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c | 56 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 31 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/fs_core.h | 6 | ||||
-rw-r--r-- | include/linux/mlx5/fs.h | 3 |
5 files changed, 75 insertions, 22 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c index 7aaefa9aaf1c..7a0415e6d339 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c | |||
@@ -58,6 +58,7 @@ int mlx5_cmd_update_root_ft(struct mlx5_core_dev *dev, | |||
58 | 58 | ||
59 | int mlx5_cmd_create_flow_table(struct mlx5_core_dev *dev, | 59 | int mlx5_cmd_create_flow_table(struct mlx5_core_dev *dev, |
60 | u16 vport, | 60 | u16 vport, |
61 | enum fs_flow_table_op_mod op_mod, | ||
61 | enum fs_flow_table_type type, unsigned int level, | 62 | enum fs_flow_table_type type, unsigned int level, |
62 | unsigned int log_size, struct mlx5_flow_table | 63 | unsigned int log_size, struct mlx5_flow_table |
63 | *next_ft, unsigned int *table_id) | 64 | *next_ft, unsigned int *table_id) |
@@ -69,10 +70,6 @@ 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 | ||
72 | if (next_ft) { | ||
73 | MLX5_SET(create_flow_table_in, in, table_miss_mode, 1); | ||
74 | MLX5_SET(create_flow_table_in, in, table_miss_id, next_ft->id); | ||
75 | } | ||
76 | MLX5_SET(create_flow_table_in, in, table_type, type); | 73 | MLX5_SET(create_flow_table_in, in, table_type, type); |
77 | MLX5_SET(create_flow_table_in, in, level, level); | 74 | MLX5_SET(create_flow_table_in, in, level, level); |
78 | MLX5_SET(create_flow_table_in, in, log_size, log_size); | 75 | MLX5_SET(create_flow_table_in, in, log_size, log_size); |
@@ -81,6 +78,22 @@ int mlx5_cmd_create_flow_table(struct mlx5_core_dev *dev, | |||
81 | MLX5_SET(create_flow_table_in, in, other_vport, 1); | 78 | MLX5_SET(create_flow_table_in, in, other_vport, 1); |
82 | } | 79 | } |
83 | 80 | ||
81 | switch (op_mod) { | ||
82 | case FS_FT_OP_MOD_NORMAL: | ||
83 | if (next_ft) { | ||
84 | MLX5_SET(create_flow_table_in, in, table_miss_mode, 1); | ||
85 | MLX5_SET(create_flow_table_in, in, table_miss_id, next_ft->id); | ||
86 | } | ||
87 | break; | ||
88 | |||
89 | case FS_FT_OP_MOD_LAG_DEMUX: | ||
90 | MLX5_SET(create_flow_table_in, in, op_mod, 0x1); | ||
91 | if (next_ft) | ||
92 | MLX5_SET(create_flow_table_in, in, lag_master_next_table_id, | ||
93 | next_ft->id); | ||
94 | break; | ||
95 | } | ||
96 | |||
84 | err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); | 97 | err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); |
85 | if (!err) | 98 | if (!err) |
86 | *table_id = MLX5_GET(create_flow_table_out, out, | 99 | *table_id = MLX5_GET(create_flow_table_out, out, |
@@ -117,17 +130,32 @@ int mlx5_cmd_modify_flow_table(struct mlx5_core_dev *dev, | |||
117 | MLX5_CMD_OP_MODIFY_FLOW_TABLE); | 130 | MLX5_CMD_OP_MODIFY_FLOW_TABLE); |
118 | MLX5_SET(modify_flow_table_in, in, table_type, ft->type); | 131 | MLX5_SET(modify_flow_table_in, in, table_type, ft->type); |
119 | MLX5_SET(modify_flow_table_in, in, table_id, ft->id); | 132 | MLX5_SET(modify_flow_table_in, in, table_id, ft->id); |
120 | if (ft->vport) { | 133 | |
121 | MLX5_SET(modify_flow_table_in, in, vport_number, ft->vport); | 134 | if (ft->op_mod == FS_FT_OP_MOD_LAG_DEMUX) { |
122 | MLX5_SET(modify_flow_table_in, in, other_vport, 1); | 135 | MLX5_SET(modify_flow_table_in, in, modify_field_select, |
123 | } | 136 | MLX5_MODIFY_FLOW_TABLE_LAG_NEXT_TABLE_ID); |
124 | MLX5_SET(modify_flow_table_in, in, modify_field_select, | 137 | if (next_ft) { |
125 | MLX5_MODIFY_FLOW_TABLE_MISS_TABLE_ID); | 138 | MLX5_SET(modify_flow_table_in, in, |
126 | if (next_ft) { | 139 | lag_master_next_table_id, next_ft->id); |
127 | MLX5_SET(modify_flow_table_in, in, table_miss_mode, 1); | 140 | } else { |
128 | MLX5_SET(modify_flow_table_in, in, table_miss_id, next_ft->id); | 141 | MLX5_SET(modify_flow_table_in, in, |
142 | lag_master_next_table_id, 0); | ||
143 | } | ||
129 | } else { | 144 | } else { |
130 | MLX5_SET(modify_flow_table_in, in, table_miss_mode, 0); | 145 | if (ft->vport) { |
146 | MLX5_SET(modify_flow_table_in, in, vport_number, | ||
147 | ft->vport); | ||
148 | MLX5_SET(modify_flow_table_in, in, other_vport, 1); | ||
149 | } | ||
150 | MLX5_SET(modify_flow_table_in, in, modify_field_select, | ||
151 | MLX5_MODIFY_FLOW_TABLE_MISS_TABLE_ID); | ||
152 | if (next_ft) { | ||
153 | MLX5_SET(modify_flow_table_in, in, table_miss_mode, 1); | ||
154 | MLX5_SET(modify_flow_table_in, in, table_miss_id, | ||
155 | next_ft->id); | ||
156 | } else { | ||
157 | MLX5_SET(modify_flow_table_in, in, table_miss_mode, 0); | ||
158 | } | ||
131 | } | 159 | } |
132 | 160 | ||
133 | return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); | 161 | return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); |
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h index ac52fdfb5096..c5bc4686c832 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h | |||
@@ -35,6 +35,7 @@ | |||
35 | 35 | ||
36 | int mlx5_cmd_create_flow_table(struct mlx5_core_dev *dev, | 36 | int mlx5_cmd_create_flow_table(struct mlx5_core_dev *dev, |
37 | u16 vport, | 37 | u16 vport, |
38 | enum fs_flow_table_op_mod op_mod, | ||
38 | enum fs_flow_table_type type, unsigned int level, | 39 | enum fs_flow_table_type type, unsigned int level, |
39 | unsigned int log_size, struct mlx5_flow_table | 40 | unsigned int log_size, struct mlx5_flow_table |
40 | *next_ft, unsigned int *table_id); | 41 | *next_ft, unsigned int *table_id); |
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c index 243efc5a8bd1..eabd73482c86 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | |||
@@ -477,7 +477,8 @@ static struct mlx5_flow_group *alloc_flow_group(u32 *create_fg_in) | |||
477 | } | 477 | } |
478 | 478 | ||
479 | static struct mlx5_flow_table *alloc_flow_table(int level, u16 vport, int max_fte, | 479 | static struct mlx5_flow_table *alloc_flow_table(int level, u16 vport, int max_fte, |
480 | enum fs_flow_table_type table_type) | 480 | enum fs_flow_table_type table_type, |
481 | enum fs_flow_table_op_mod op_mod) | ||
481 | { | 482 | { |
482 | struct mlx5_flow_table *ft; | 483 | struct mlx5_flow_table *ft; |
483 | 484 | ||
@@ -487,6 +488,7 @@ static struct mlx5_flow_table *alloc_flow_table(int level, u16 vport, int max_ft | |||
487 | 488 | ||
488 | ft->level = level; | 489 | ft->level = level; |
489 | ft->node.type = FS_TYPE_FLOW_TABLE; | 490 | ft->node.type = FS_TYPE_FLOW_TABLE; |
491 | ft->op_mod = op_mod; | ||
490 | ft->type = table_type; | 492 | ft->type = table_type; |
491 | ft->vport = vport; | 493 | ft->vport = vport; |
492 | ft->max_fte = max_fte; | 494 | ft->max_fte = max_fte; |
@@ -724,6 +726,7 @@ static void list_add_flow_table(struct mlx5_flow_table *ft, | |||
724 | } | 726 | } |
725 | 727 | ||
726 | static struct mlx5_flow_table *__mlx5_create_flow_table(struct mlx5_flow_namespace *ns, | 728 | static struct mlx5_flow_table *__mlx5_create_flow_table(struct mlx5_flow_namespace *ns, |
729 | enum fs_flow_table_op_mod op_mod, | ||
727 | u16 vport, int prio, | 730 | u16 vport, int prio, |
728 | int max_fte, u32 level) | 731 | int max_fte, u32 level) |
729 | { | 732 | { |
@@ -756,18 +759,19 @@ static struct mlx5_flow_table *__mlx5_create_flow_table(struct mlx5_flow_namespa | |||
756 | level += fs_prio->start_level; | 759 | level += fs_prio->start_level; |
757 | ft = alloc_flow_table(level, | 760 | ft = alloc_flow_table(level, |
758 | vport, | 761 | vport, |
759 | roundup_pow_of_two(max_fte), | 762 | max_fte ? roundup_pow_of_two(max_fte) : 0, |
760 | root->table_type); | 763 | root->table_type, |
764 | op_mod); | ||
761 | if (!ft) { | 765 | if (!ft) { |
762 | err = -ENOMEM; | 766 | err = -ENOMEM; |
763 | goto unlock_root; | 767 | goto unlock_root; |
764 | } | 768 | } |
765 | 769 | ||
766 | tree_init_node(&ft->node, 1, del_flow_table); | 770 | tree_init_node(&ft->node, 1, del_flow_table); |
767 | log_table_sz = ilog2(ft->max_fte); | 771 | log_table_sz = ft->max_fte ? ilog2(ft->max_fte) : 0; |
768 | next_ft = find_next_chained_ft(fs_prio); | 772 | next_ft = find_next_chained_ft(fs_prio); |
769 | err = mlx5_cmd_create_flow_table(root->dev, ft->vport, ft->type, ft->level, | 773 | err = mlx5_cmd_create_flow_table(root->dev, ft->vport, ft->op_mod, ft->type, |
770 | log_table_sz, next_ft, &ft->id); | 774 | ft->level, log_table_sz, next_ft, &ft->id); |
771 | if (err) | 775 | if (err) |
772 | goto free_ft; | 776 | goto free_ft; |
773 | 777 | ||
@@ -794,16 +798,27 @@ struct mlx5_flow_table *mlx5_create_flow_table(struct mlx5_flow_namespace *ns, | |||
794 | int prio, int max_fte, | 798 | int prio, int max_fte, |
795 | u32 level) | 799 | u32 level) |
796 | { | 800 | { |
797 | return __mlx5_create_flow_table(ns, 0, prio, max_fte, level); | 801 | return __mlx5_create_flow_table(ns, FS_FT_OP_MOD_NORMAL, 0, prio, |
802 | max_fte, level); | ||
798 | } | 803 | } |
799 | 804 | ||
800 | struct mlx5_flow_table *mlx5_create_vport_flow_table(struct mlx5_flow_namespace *ns, | 805 | struct mlx5_flow_table *mlx5_create_vport_flow_table(struct mlx5_flow_namespace *ns, |
801 | int prio, int max_fte, | 806 | int prio, int max_fte, |
802 | u32 level, u16 vport) | 807 | u32 level, u16 vport) |
803 | { | 808 | { |
804 | return __mlx5_create_flow_table(ns, vport, prio, max_fte, level); | 809 | return __mlx5_create_flow_table(ns, FS_FT_OP_MOD_NORMAL, vport, prio, |
810 | max_fte, level); | ||
805 | } | 811 | } |
806 | 812 | ||
813 | struct mlx5_flow_table *mlx5_create_lag_demux_flow_table( | ||
814 | struct mlx5_flow_namespace *ns, | ||
815 | int prio, u32 level) | ||
816 | { | ||
817 | return __mlx5_create_flow_table(ns, FS_FT_OP_MOD_LAG_DEMUX, 0, prio, 0, | ||
818 | level); | ||
819 | } | ||
820 | EXPORT_SYMBOL(mlx5_create_lag_demux_flow_table); | ||
821 | |||
807 | struct mlx5_flow_table *mlx5_create_auto_grouped_flow_table(struct mlx5_flow_namespace *ns, | 822 | struct mlx5_flow_table *mlx5_create_auto_grouped_flow_table(struct mlx5_flow_namespace *ns, |
808 | int prio, | 823 | int prio, |
809 | int num_flow_table_entries, | 824 | int num_flow_table_entries, |
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h index 9cffb6aeb4e9..23e46e35413f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h | |||
@@ -51,6 +51,11 @@ enum fs_flow_table_type { | |||
51 | FS_FT_FDB = 0X4, | 51 | FS_FT_FDB = 0X4, |
52 | }; | 52 | }; |
53 | 53 | ||
54 | enum fs_flow_table_op_mod { | ||
55 | FS_FT_OP_MOD_NORMAL, | ||
56 | FS_FT_OP_MOD_LAG_DEMUX, | ||
57 | }; | ||
58 | |||
54 | enum fs_fte_status { | 59 | enum fs_fte_status { |
55 | FS_FTE_STATUS_EXISTING = 1UL << 0, | 60 | FS_FTE_STATUS_EXISTING = 1UL << 0, |
56 | }; | 61 | }; |
@@ -93,6 +98,7 @@ struct mlx5_flow_table { | |||
93 | unsigned int max_fte; | 98 | unsigned int max_fte; |
94 | unsigned int level; | 99 | unsigned int level; |
95 | enum fs_flow_table_type type; | 100 | enum fs_flow_table_type type; |
101 | enum fs_flow_table_op_mod op_mod; | ||
96 | struct { | 102 | struct { |
97 | bool active; | 103 | bool active; |
98 | unsigned int required_groups; | 104 | unsigned int required_groups; |
diff --git a/include/linux/mlx5/fs.h b/include/linux/mlx5/fs.h index e036d6030867..7edfe0b8f1ec 100644 --- a/include/linux/mlx5/fs.h +++ b/include/linux/mlx5/fs.h | |||
@@ -106,6 +106,9 @@ mlx5_create_vport_flow_table(struct mlx5_flow_namespace *ns, | |||
106 | int prio, | 106 | int prio, |
107 | int num_flow_table_entries, | 107 | int num_flow_table_entries, |
108 | u32 level, u16 vport); | 108 | u32 level, u16 vport); |
109 | struct mlx5_flow_table *mlx5_create_lag_demux_flow_table( | ||
110 | struct mlx5_flow_namespace *ns, | ||
111 | int prio, u32 level); | ||
109 | int mlx5_destroy_flow_table(struct mlx5_flow_table *ft); | 112 | int mlx5_destroy_flow_table(struct mlx5_flow_table *ft); |
110 | 113 | ||
111 | /* inbox should be set with the following values: | 114 | /* inbox should be set with the following values: |