aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaor Gottlieb <maorg@mellanox.com>2016-04-28 18:36:35 -0400
committerDavid S. Miller <davem@davemloft.net>2016-04-29 16:29:09 -0400
commitd63cd28608bb563d52e62990fa01c016e8dbdb75 (patch)
treed3b42d39a1a4129c127e09f928f27f04f06ba96b
parenta257b94a18f7eb60bbe9b5fd415d208ac71d49ea (diff)
net/mlx5: Add user chosen levels when allocating flow tables
Currently, consumers of the flow steering infrastructure can't choose their own flow table levels and are limited to one flow table per level. This just waste levels. Instead, we introduce here the possibility to use multiple flow tables in a level. The user is free to connect these flow tables, while following the rule (FTEs in FT of level x could only point to FTs of level y where y > x). In addition this patch switch the order of the create/destroy flow tables of the NIC(vlan and main). Signed-off-by: Maor Gottlieb <maorg@mellanox.com> Signed-off-by: Saeed Mahameed <saeedm@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/infiniband/hw/mlx5/main.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_fs.c30
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_tc.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eswitch.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_core.c66
-rw-r--r--include/linux/mlx5/fs.h6
6 files changed, 70 insertions, 40 deletions
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index 99eb1c1a3b7b..3ff663c35bac 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -1438,7 +1438,8 @@ static struct mlx5_ib_flow_prio *get_flow_table(struct mlx5_ib_dev *dev,
1438 if (!ft) { 1438 if (!ft) {
1439 ft = mlx5_create_auto_grouped_flow_table(ns, priority, 1439 ft = mlx5_create_auto_grouped_flow_table(ns, priority,
1440 num_entries, 1440 num_entries,
1441 num_groups); 1441 num_groups,
1442 0);
1442 1443
1443 if (!IS_ERR(ft)) { 1444 if (!IS_ERR(ft)) {
1444 prio->refcount = 0; 1445 prio->refcount = 0;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
index 4df49e660587..d61171ae0168 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
@@ -37,6 +37,11 @@
37#include <linux/mlx5/fs.h> 37#include <linux/mlx5/fs.h>
38#include "en.h" 38#include "en.h"
39 39
40enum {
41 MLX5E_VLAN_FT_LEVEL = 0,
42 MLX5E_MAIN_FT_LEVEL
43};
44
40#define MLX5_SET_CFG(p, f, v) MLX5_SET(create_flow_group_in, p, f, v) 45#define MLX5_SET_CFG(p, f, v) MLX5_SET(create_flow_group_in, p, f, v)
41 46
42enum { 47enum {
@@ -1041,7 +1046,8 @@ static int mlx5e_create_main_flow_table(struct mlx5e_priv *priv)
1041 int err; 1046 int err;
1042 1047
1043 ft->num_groups = 0; 1048 ft->num_groups = 0;
1044 ft->t = mlx5_create_flow_table(priv->fts.ns, 1, MLX5E_MAIN_TABLE_SIZE); 1049 ft->t = mlx5_create_flow_table(priv->fts.ns, 1, MLX5E_MAIN_TABLE_SIZE,
1050 MLX5E_MAIN_FT_LEVEL);
1045 1051
1046 if (IS_ERR(ft->t)) { 1052 if (IS_ERR(ft->t)) {
1047 err = PTR_ERR(ft->t); 1053 err = PTR_ERR(ft->t);
@@ -1150,7 +1156,8 @@ static int mlx5e_create_vlan_flow_table(struct mlx5e_priv *priv)
1150 int err; 1156 int err;
1151 1157
1152 ft->num_groups = 0; 1158 ft->num_groups = 0;
1153 ft->t = mlx5_create_flow_table(priv->fts.ns, 1, MLX5E_VLAN_TABLE_SIZE); 1159 ft->t = mlx5_create_flow_table(priv->fts.ns, 1, MLX5E_VLAN_TABLE_SIZE,
1160 MLX5E_VLAN_FT_LEVEL);
1154 1161
1155 if (IS_ERR(ft->t)) { 1162 if (IS_ERR(ft->t)) {
1156 err = PTR_ERR(ft->t); 1163 err = PTR_ERR(ft->t);
@@ -1167,11 +1174,16 @@ static int mlx5e_create_vlan_flow_table(struct mlx5e_priv *priv)
1167 if (err) 1174 if (err)
1168 goto err_free_g; 1175 goto err_free_g;
1169 1176
1177 err = mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_UNTAGGED, 0);
1178 if (err)
1179 goto err_destroy_vlan_flow_groups;
1180
1170 return 0; 1181 return 0;
1171 1182
1183err_destroy_vlan_flow_groups:
1184 mlx5e_destroy_groups(ft);
1172err_free_g: 1185err_free_g:
1173 kfree(ft->g); 1186 kfree(ft->g);
1174
1175err_destroy_vlan_flow_table: 1187err_destroy_vlan_flow_table:
1176 mlx5_destroy_flow_table(ft->t); 1188 mlx5_destroy_flow_table(ft->t);
1177 ft->t = NULL; 1189 ft->t = NULL;
@@ -1194,15 +1206,11 @@ int mlx5e_create_flow_tables(struct mlx5e_priv *priv)
1194 if (!priv->fts.ns) 1206 if (!priv->fts.ns)
1195 return -EINVAL; 1207 return -EINVAL;
1196 1208
1197 err = mlx5e_create_vlan_flow_table(priv);
1198 if (err)
1199 return err;
1200
1201 err = mlx5e_create_main_flow_table(priv); 1209 err = mlx5e_create_main_flow_table(priv);
1202 if (err) 1210 if (err)
1203 goto err_destroy_vlan_flow_table; 1211 return err;
1204 1212
1205 err = mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_UNTAGGED, 0); 1213 err = mlx5e_create_vlan_flow_table(priv);
1206 if (err) 1214 if (err)
1207 goto err_destroy_main_flow_table; 1215 goto err_destroy_main_flow_table;
1208 1216
@@ -1210,8 +1218,6 @@ int mlx5e_create_flow_tables(struct mlx5e_priv *priv)
1210 1218
1211err_destroy_main_flow_table: 1219err_destroy_main_flow_table:
1212 mlx5e_destroy_main_flow_table(priv); 1220 mlx5e_destroy_main_flow_table(priv);
1213err_destroy_vlan_flow_table:
1214 mlx5e_destroy_vlan_flow_table(priv);
1215 1221
1216 return err; 1222 return err;
1217} 1223}
@@ -1219,6 +1225,6 @@ err_destroy_vlan_flow_table:
1219void mlx5e_destroy_flow_tables(struct mlx5e_priv *priv) 1225void mlx5e_destroy_flow_tables(struct mlx5e_priv *priv)
1220{ 1226{
1221 mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_UNTAGGED, 0); 1227 mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_UNTAGGED, 0);
1222 mlx5e_destroy_main_flow_table(priv);
1223 mlx5e_destroy_vlan_flow_table(priv); 1228 mlx5e_destroy_vlan_flow_table(priv);
1229 mlx5e_destroy_main_flow_table(priv);
1224} 1230}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
index b3de09f13425..2137387c043d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
@@ -64,7 +64,8 @@ static struct mlx5_flow_rule *mlx5e_tc_add_flow(struct mlx5e_priv *priv,
64 priv->fts.tc.t = 64 priv->fts.tc.t =
65 mlx5_create_auto_grouped_flow_table(priv->fts.ns, 0, 65 mlx5_create_auto_grouped_flow_table(priv->fts.ns, 0,
66 MLX5E_TC_FLOW_TABLE_NUM_ENTRIES, 66 MLX5E_TC_FLOW_TABLE_NUM_ENTRIES,
67 MLX5E_TC_FLOW_TABLE_NUM_GROUPS); 67 MLX5E_TC_FLOW_TABLE_NUM_GROUPS,
68 0);
68 if (IS_ERR(priv->fts.tc.t)) { 69 if (IS_ERR(priv->fts.tc.t)) {
69 netdev_err(priv->netdev, 70 netdev_err(priv->netdev,
70 "Failed to create tc offload table\n"); 71 "Failed to create tc offload table\n");
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
index bc3d9f8a75c1..ff91bb5e1c43 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
@@ -401,7 +401,7 @@ static int esw_create_fdb_table(struct mlx5_eswitch *esw, int nvports)
401 memset(flow_group_in, 0, inlen); 401 memset(flow_group_in, 0, inlen);
402 402
403 table_size = BIT(MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size)); 403 table_size = BIT(MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size));
404 fdb = mlx5_create_flow_table(root_ns, 0, table_size); 404 fdb = mlx5_create_flow_table(root_ns, 0, table_size, 0);
405 if (IS_ERR_OR_NULL(fdb)) { 405 if (IS_ERR_OR_NULL(fdb)) {
406 err = PTR_ERR(fdb); 406 err = PTR_ERR(fdb);
407 esw_warn(dev, "Failed to create FDB Table err %d\n", err); 407 esw_warn(dev, "Failed to create FDB Table err %d\n", err);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
index cfb35c334cd1..ca55d7e30e5c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
@@ -225,19 +225,6 @@ static struct fs_prio *find_prio(struct mlx5_flow_namespace *ns,
225 return NULL; 225 return NULL;
226} 226}
227 227
228static unsigned int find_next_free_level(struct fs_prio *prio)
229{
230 if (!list_empty(&prio->node.children)) {
231 struct mlx5_flow_table *ft;
232
233 ft = list_last_entry(&prio->node.children,
234 struct mlx5_flow_table,
235 node.list);
236 return ft->level + 1;
237 }
238 return prio->start_level;
239}
240
241static bool masked_memcmp(void *mask, void *val1, void *val2, size_t size) 228static bool masked_memcmp(void *mask, void *val1, void *val2, size_t size)
242{ 229{
243 unsigned int i; 230 unsigned int i;
@@ -696,9 +683,23 @@ static int connect_flow_table(struct mlx5_core_dev *dev, struct mlx5_flow_table
696 return err; 683 return err;
697} 684}
698 685
686static void list_add_flow_table(struct mlx5_flow_table *ft,
687 struct fs_prio *prio)
688{
689 struct list_head *prev = &prio->node.children;
690 struct mlx5_flow_table *iter;
691
692 fs_for_each_ft(iter, prio) {
693 if (iter->level > ft->level)
694 break;
695 prev = &iter->node.list;
696 }
697 list_add(&ft->node.list, prev);
698}
699
699struct mlx5_flow_table *mlx5_create_flow_table(struct mlx5_flow_namespace *ns, 700struct mlx5_flow_table *mlx5_create_flow_table(struct mlx5_flow_namespace *ns,
700 int prio, 701 int prio, int max_fte,
701 int max_fte) 702 u32 level)
702{ 703{
703 struct mlx5_flow_table *next_ft = NULL; 704 struct mlx5_flow_table *next_ft = NULL;
704 struct mlx5_flow_table *ft; 705 struct mlx5_flow_table *ft;
@@ -719,12 +720,15 @@ struct mlx5_flow_table *mlx5_create_flow_table(struct mlx5_flow_namespace *ns,
719 err = -EINVAL; 720 err = -EINVAL;
720 goto unlock_root; 721 goto unlock_root;
721 } 722 }
722 if (fs_prio->num_ft == fs_prio->num_levels) { 723 if (level >= fs_prio->num_levels) {
723 err = -ENOSPC; 724 err = -ENOSPC;
724 goto unlock_root; 725 goto unlock_root;
725 } 726 }
726 727 /* The level is related to the
727 ft = alloc_flow_table(find_next_free_level(fs_prio), 728 * priority level range.
729 */
730 level += fs_prio->start_level;
731 ft = alloc_flow_table(level,
728 roundup_pow_of_two(max_fte), 732 roundup_pow_of_two(max_fte),
729 root->table_type); 733 root->table_type);
730 if (!ft) { 734 if (!ft) {
@@ -745,7 +749,7 @@ struct mlx5_flow_table *mlx5_create_flow_table(struct mlx5_flow_namespace *ns,
745 goto destroy_ft; 749 goto destroy_ft;
746 lock_ref_node(&fs_prio->node); 750 lock_ref_node(&fs_prio->node);
747 tree_add_node(&ft->node, &fs_prio->node); 751 tree_add_node(&ft->node, &fs_prio->node);
748 list_add_tail(&ft->node.list, &fs_prio->node.children); 752 list_add_flow_table(ft, fs_prio);
749 fs_prio->num_ft++; 753 fs_prio->num_ft++;
750 unlock_ref_node(&fs_prio->node); 754 unlock_ref_node(&fs_prio->node);
751 mutex_unlock(&root->chain_lock); 755 mutex_unlock(&root->chain_lock);
@@ -762,14 +766,15 @@ unlock_root:
762struct mlx5_flow_table *mlx5_create_auto_grouped_flow_table(struct mlx5_flow_namespace *ns, 766struct mlx5_flow_table *mlx5_create_auto_grouped_flow_table(struct mlx5_flow_namespace *ns,
763 int prio, 767 int prio,
764 int num_flow_table_entries, 768 int num_flow_table_entries,
765 int max_num_groups) 769 int max_num_groups,
770 u32 level)
766{ 771{
767 struct mlx5_flow_table *ft; 772 struct mlx5_flow_table *ft;
768 773
769 if (max_num_groups > num_flow_table_entries) 774 if (max_num_groups > num_flow_table_entries)
770 return ERR_PTR(-EINVAL); 775 return ERR_PTR(-EINVAL);
771 776
772 ft = mlx5_create_flow_table(ns, prio, num_flow_table_entries); 777 ft = mlx5_create_flow_table(ns, prio, num_flow_table_entries, level);
773 if (IS_ERR(ft)) 778 if (IS_ERR(ft))
774 return ft; 779 return ft;
775 780
@@ -1068,6 +1073,20 @@ unlock_fg:
1068 return rule; 1073 return rule;
1069} 1074}
1070 1075
1076static bool dest_is_valid(struct mlx5_flow_destination *dest,
1077 u32 action,
1078 struct mlx5_flow_table *ft)
1079{
1080 if (!(action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST))
1081 return true;
1082
1083 if (!dest || ((dest->type ==
1084 MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE) &&
1085 (dest->ft->level <= ft->level)))
1086 return false;
1087 return true;
1088}
1089
1071static struct mlx5_flow_rule * 1090static struct mlx5_flow_rule *
1072_mlx5_add_flow_rule(struct mlx5_flow_table *ft, 1091_mlx5_add_flow_rule(struct mlx5_flow_table *ft,
1073 u8 match_criteria_enable, 1092 u8 match_criteria_enable,
@@ -1080,7 +1099,7 @@ _mlx5_add_flow_rule(struct mlx5_flow_table *ft,
1080 struct mlx5_flow_group *g; 1099 struct mlx5_flow_group *g;
1081 struct mlx5_flow_rule *rule; 1100 struct mlx5_flow_rule *rule;
1082 1101
1083 if ((action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) && !dest) 1102 if (!dest_is_valid(dest, action, ft))
1084 return ERR_PTR(-EINVAL); 1103 return ERR_PTR(-EINVAL);
1085 1104
1086 nested_lock_ref_node(&ft->node, FS_MUTEX_GRANDPARENT); 1105 nested_lock_ref_node(&ft->node, FS_MUTEX_GRANDPARENT);
@@ -1517,6 +1536,7 @@ static void set_prio_attrs(struct mlx5_flow_root_namespace *root_ns)
1517 1536
1518#define ANCHOR_PRIO 0 1537#define ANCHOR_PRIO 0
1519#define ANCHOR_SIZE 1 1538#define ANCHOR_SIZE 1
1539#define ANCHOR_LEVEL 0
1520static int create_anchor_flow_table(struct mlx5_core_dev 1540static int create_anchor_flow_table(struct mlx5_core_dev
1521 *dev) 1541 *dev)
1522{ 1542{
@@ -1526,7 +1546,7 @@ static int create_anchor_flow_table(struct mlx5_core_dev
1526 ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_ANCHOR); 1546 ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_ANCHOR);
1527 if (!ns) 1547 if (!ns)
1528 return -EINVAL; 1548 return -EINVAL;
1529 ft = mlx5_create_flow_table(ns, ANCHOR_PRIO, ANCHOR_SIZE); 1549 ft = mlx5_create_flow_table(ns, ANCHOR_PRIO, ANCHOR_SIZE, ANCHOR_LEVEL);
1530 if (IS_ERR(ft)) { 1550 if (IS_ERR(ft)) {
1531 mlx5_core_err(dev, "Failed to create last anchor flow table"); 1551 mlx5_core_err(dev, "Failed to create last anchor flow table");
1532 return PTR_ERR(ft); 1552 return PTR_ERR(ft);
diff --git a/include/linux/mlx5/fs.h b/include/linux/mlx5/fs.h
index 28a5b662ab6a..165ff4f9cc6a 100644
--- a/include/linux/mlx5/fs.h
+++ b/include/linux/mlx5/fs.h
@@ -82,12 +82,14 @@ struct mlx5_flow_table *
82mlx5_create_auto_grouped_flow_table(struct mlx5_flow_namespace *ns, 82mlx5_create_auto_grouped_flow_table(struct mlx5_flow_namespace *ns,
83 int prio, 83 int prio,
84 int num_flow_table_entries, 84 int num_flow_table_entries,
85 int max_num_groups); 85 int max_num_groups,
86 u32 level);
86 87
87struct mlx5_flow_table * 88struct mlx5_flow_table *
88mlx5_create_flow_table(struct mlx5_flow_namespace *ns, 89mlx5_create_flow_table(struct mlx5_flow_namespace *ns,
89 int prio, 90 int prio,
90 int num_flow_table_entries); 91 int num_flow_table_entries,
92 u32 level);
91int mlx5_destroy_flow_table(struct mlx5_flow_table *ft); 93int mlx5_destroy_flow_table(struct mlx5_flow_table *ft);
92 94
93/* inbox should be set with the following values: 95/* inbox should be set with the following values: