net/mlx5_core: Add utilities to find next and prev flow-tables
authorMaor Gottlieb <maorg@mellanox.com>
Mon, 11 Jan 2016 08:25:58 +0000 (10:25 +0200)
committerDavid S. Miller <davem@davemloft.net>
Mon, 11 Jan 2016 22:48:52 +0000 (17:48 -0500)
Add two utility functions for find next and prev flow table.
Find next flow table function gets priority and return the
first flow table of the next priority in the tree.
Find prev flow table return the last flow table of
the previous priority in the tree.

These utility functions are used for chaining flow table from different
priorities.

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>
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c

index 7d24bbba58ba670fd75c3814ea7986bd669b6a59..c5a96e6abe0da590921a6aa612e66a17393ded3c 100644 (file)
@@ -443,6 +443,73 @@ static struct mlx5_flow_table *alloc_flow_table(int level, int max_fte,
        return ft;
 }
 
+/* If reverse is false, then we search for the first flow table in the
+ * root sub-tree from start(closest from right), else we search for the
+ * last flow table in the root sub-tree till start(closest from left).
+ */
+static struct mlx5_flow_table *find_closest_ft_recursive(struct fs_node  *root,
+                                                        struct list_head *start,
+                                                        bool reverse)
+{
+#define list_advance_entry(pos, reverse)               \
+       ((reverse) ? list_prev_entry(pos, list) : list_next_entry(pos, list))
+
+#define list_for_each_advance_continue(pos, head, reverse)     \
+       for (pos = list_advance_entry(pos, reverse);            \
+            &pos->list != (head);                              \
+            pos = list_advance_entry(pos, reverse))
+
+       struct fs_node *iter = list_entry(start, struct fs_node, list);
+       struct mlx5_flow_table *ft = NULL;
+
+       if (!root)
+               return NULL;
+
+       list_for_each_advance_continue(iter, &root->children, reverse) {
+               if (iter->type == FS_TYPE_FLOW_TABLE) {
+                       fs_get_obj(ft, iter);
+                       return ft;
+               }
+               ft = find_closest_ft_recursive(iter, &iter->children, reverse);
+               if (ft)
+                       return ft;
+       }
+
+       return ft;
+}
+
+/* If reverse if false then return the first flow table in next priority of
+ * prio in the tree, else return the last flow table in the previous priority
+ * of prio in the tree.
+ */
+static struct mlx5_flow_table *find_closest_ft(struct fs_prio *prio, bool reverse)
+{
+       struct mlx5_flow_table *ft = NULL;
+       struct fs_node *curr_node;
+       struct fs_node *parent;
+
+       parent = prio->node.parent;
+       curr_node = &prio->node;
+       while (!ft && parent) {
+               ft = find_closest_ft_recursive(parent, &curr_node->list, reverse);
+               curr_node = parent;
+               parent = curr_node->parent;
+       }
+       return ft;
+}
+
+/* Assuming all the tree is locked by mutex chain lock */
+static struct mlx5_flow_table *find_next_chained_ft(struct fs_prio *prio)
+{
+       return find_closest_ft(prio, false);
+}
+
+/* Assuming all the tree is locked by mutex chain lock */
+static struct mlx5_flow_table *find_prev_chained_ft(struct fs_prio *prio)
+{
+       return find_closest_ft(prio, true);
+}
+
 struct mlx5_flow_table *mlx5_create_flow_table(struct mlx5_flow_namespace *ns,
                                               int prio,
                                               int max_fte)