| .. | .. |
|---|
| 802 | 802 | struct fs_node *iter = list_entry(start, struct fs_node, list); |
|---|
| 803 | 803 | struct mlx5_flow_table *ft = NULL; |
|---|
| 804 | 804 | |
|---|
| 805 | | - if (!root || root->type == FS_TYPE_PRIO_CHAINS) |
|---|
| 805 | + if (!root) |
|---|
| 806 | 806 | return NULL; |
|---|
| 807 | 807 | |
|---|
| 808 | 808 | list_for_each_advance_continue(iter, &root->children, reverse) { |
|---|
| .. | .. |
|---|
| 818 | 818 | return ft; |
|---|
| 819 | 819 | } |
|---|
| 820 | 820 | |
|---|
| 821 | | -/* If reverse is false then return the first flow table in next priority of |
|---|
| 822 | | - * prio in the tree, else return the last flow table in the previous priority |
|---|
| 823 | | - * of prio in the tree. |
|---|
| 824 | | - */ |
|---|
| 825 | | -static struct mlx5_flow_table *find_closest_ft(struct fs_prio *prio, bool reverse) |
|---|
| 821 | +static struct fs_node *find_prio_chains_parent(struct fs_node *parent, |
|---|
| 822 | + struct fs_node **child) |
|---|
| 826 | 823 | { |
|---|
| 824 | + struct fs_node *node = NULL; |
|---|
| 825 | + |
|---|
| 826 | + while (parent && parent->type != FS_TYPE_PRIO_CHAINS) { |
|---|
| 827 | + node = parent; |
|---|
| 828 | + parent = parent->parent; |
|---|
| 829 | + } |
|---|
| 830 | + |
|---|
| 831 | + if (child) |
|---|
| 832 | + *child = node; |
|---|
| 833 | + |
|---|
| 834 | + return parent; |
|---|
| 835 | +} |
|---|
| 836 | + |
|---|
| 837 | +/* If reverse is false then return the first flow table next to the passed node |
|---|
| 838 | + * in the tree, else return the last flow table before the node in the tree. |
|---|
| 839 | + * If skip is true, skip the flow tables in the same prio_chains prio. |
|---|
| 840 | + */ |
|---|
| 841 | +static struct mlx5_flow_table *find_closest_ft(struct fs_node *node, bool reverse, |
|---|
| 842 | + bool skip) |
|---|
| 843 | +{ |
|---|
| 844 | + struct fs_node *prio_chains_parent = NULL; |
|---|
| 827 | 845 | struct mlx5_flow_table *ft = NULL; |
|---|
| 828 | 846 | struct fs_node *curr_node; |
|---|
| 829 | 847 | struct fs_node *parent; |
|---|
| 830 | 848 | |
|---|
| 831 | | - parent = prio->node.parent; |
|---|
| 832 | | - curr_node = &prio->node; |
|---|
| 849 | + if (skip) |
|---|
| 850 | + prio_chains_parent = find_prio_chains_parent(node, NULL); |
|---|
| 851 | + parent = node->parent; |
|---|
| 852 | + curr_node = node; |
|---|
| 833 | 853 | while (!ft && parent) { |
|---|
| 834 | | - ft = find_closest_ft_recursive(parent, &curr_node->list, reverse); |
|---|
| 854 | + if (parent != prio_chains_parent) |
|---|
| 855 | + ft = find_closest_ft_recursive(parent, &curr_node->list, |
|---|
| 856 | + reverse); |
|---|
| 835 | 857 | curr_node = parent; |
|---|
| 836 | 858 | parent = curr_node->parent; |
|---|
| 837 | 859 | } |
|---|
| .. | .. |
|---|
| 839 | 861 | } |
|---|
| 840 | 862 | |
|---|
| 841 | 863 | /* Assuming all the tree is locked by mutex chain lock */ |
|---|
| 842 | | -static struct mlx5_flow_table *find_next_chained_ft(struct fs_prio *prio) |
|---|
| 864 | +static struct mlx5_flow_table *find_next_chained_ft(struct fs_node *node) |
|---|
| 843 | 865 | { |
|---|
| 844 | | - return find_closest_ft(prio, false); |
|---|
| 866 | + return find_closest_ft(node, false, true); |
|---|
| 845 | 867 | } |
|---|
| 846 | 868 | |
|---|
| 847 | 869 | /* Assuming all the tree is locked by mutex chain lock */ |
|---|
| 848 | | -static struct mlx5_flow_table *find_prev_chained_ft(struct fs_prio *prio) |
|---|
| 870 | +static struct mlx5_flow_table *find_prev_chained_ft(struct fs_node *node) |
|---|
| 849 | 871 | { |
|---|
| 850 | | - return find_closest_ft(prio, true); |
|---|
| 872 | + return find_closest_ft(node, true, true); |
|---|
| 851 | 873 | } |
|---|
| 852 | 874 | |
|---|
| 853 | 875 | static struct mlx5_flow_table *find_next_fwd_ft(struct mlx5_flow_table *ft, |
|---|
| .. | .. |
|---|
| 859 | 881 | next_ns = flow_act->action & MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_NS; |
|---|
| 860 | 882 | fs_get_obj(prio, next_ns ? ft->ns->node.parent : ft->node.parent); |
|---|
| 861 | 883 | |
|---|
| 862 | | - return find_next_chained_ft(prio); |
|---|
| 884 | + return find_next_chained_ft(&prio->node); |
|---|
| 863 | 885 | } |
|---|
| 864 | 886 | |
|---|
| 865 | 887 | static int connect_fts_in_prio(struct mlx5_core_dev *dev, |
|---|
| .. | .. |
|---|
| 883 | 905 | return 0; |
|---|
| 884 | 906 | } |
|---|
| 885 | 907 | |
|---|
| 908 | +static struct mlx5_flow_table *find_closet_ft_prio_chains(struct fs_node *node, |
|---|
| 909 | + struct fs_node *parent, |
|---|
| 910 | + struct fs_node **child, |
|---|
| 911 | + bool reverse) |
|---|
| 912 | +{ |
|---|
| 913 | + struct mlx5_flow_table *ft; |
|---|
| 914 | + |
|---|
| 915 | + ft = find_closest_ft(node, reverse, false); |
|---|
| 916 | + |
|---|
| 917 | + if (ft && parent == find_prio_chains_parent(&ft->node, child)) |
|---|
| 918 | + return ft; |
|---|
| 919 | + |
|---|
| 920 | + return NULL; |
|---|
| 921 | +} |
|---|
| 922 | + |
|---|
| 886 | 923 | /* Connect flow tables from previous priority of prio to ft */ |
|---|
| 887 | 924 | static int connect_prev_fts(struct mlx5_core_dev *dev, |
|---|
| 888 | 925 | struct mlx5_flow_table *ft, |
|---|
| 889 | 926 | struct fs_prio *prio) |
|---|
| 890 | 927 | { |
|---|
| 928 | + struct fs_node *prio_parent, *parent = NULL, *child, *node; |
|---|
| 891 | 929 | struct mlx5_flow_table *prev_ft; |
|---|
| 930 | + int err = 0; |
|---|
| 892 | 931 | |
|---|
| 893 | | - prev_ft = find_prev_chained_ft(prio); |
|---|
| 894 | | - if (prev_ft) { |
|---|
| 932 | + prio_parent = find_prio_chains_parent(&prio->node, &child); |
|---|
| 933 | + |
|---|
| 934 | + /* return directly if not under the first sub ns of prio_chains prio */ |
|---|
| 935 | + if (prio_parent && !list_is_first(&child->list, &prio_parent->children)) |
|---|
| 936 | + return 0; |
|---|
| 937 | + |
|---|
| 938 | + prev_ft = find_prev_chained_ft(&prio->node); |
|---|
| 939 | + while (prev_ft) { |
|---|
| 895 | 940 | struct fs_prio *prev_prio; |
|---|
| 896 | 941 | |
|---|
| 897 | 942 | fs_get_obj(prev_prio, prev_ft->node.parent); |
|---|
| 898 | | - return connect_fts_in_prio(dev, prev_prio, ft); |
|---|
| 943 | + err = connect_fts_in_prio(dev, prev_prio, ft); |
|---|
| 944 | + if (err) |
|---|
| 945 | + break; |
|---|
| 946 | + |
|---|
| 947 | + if (!parent) { |
|---|
| 948 | + parent = find_prio_chains_parent(&prev_prio->node, &child); |
|---|
| 949 | + if (!parent) |
|---|
| 950 | + break; |
|---|
| 951 | + } |
|---|
| 952 | + |
|---|
| 953 | + node = child; |
|---|
| 954 | + prev_ft = find_closet_ft_prio_chains(node, parent, &child, true); |
|---|
| 899 | 955 | } |
|---|
| 900 | | - return 0; |
|---|
| 956 | + return err; |
|---|
| 901 | 957 | } |
|---|
| 902 | 958 | |
|---|
| 903 | 959 | static int update_root_ft_create(struct mlx5_flow_table *ft, struct fs_prio |
|---|
| .. | .. |
|---|
| 1036 | 1092 | if (err) |
|---|
| 1037 | 1093 | return err; |
|---|
| 1038 | 1094 | |
|---|
| 1039 | | - next_ft = first_ft ? first_ft : find_next_chained_ft(prio); |
|---|
| 1095 | + next_ft = first_ft ? first_ft : find_next_chained_ft(&prio->node); |
|---|
| 1040 | 1096 | err = connect_fwd_rules(dev, ft, next_ft); |
|---|
| 1041 | 1097 | if (err) |
|---|
| 1042 | 1098 | return err; |
|---|
| .. | .. |
|---|
| 1114 | 1170 | tree_init_node(&ft->node, del_hw_flow_table, del_sw_flow_table); |
|---|
| 1115 | 1171 | log_table_sz = ft->max_fte ? ilog2(ft->max_fte) : 0; |
|---|
| 1116 | 1172 | next_ft = unmanaged ? ft_attr->next_ft : |
|---|
| 1117 | | - find_next_chained_ft(fs_prio); |
|---|
| 1173 | + find_next_chained_ft(&fs_prio->node); |
|---|
| 1118 | 1174 | ft->def_miss_action = ns->def_miss_action; |
|---|
| 1119 | 1175 | ft->ns = ns; |
|---|
| 1120 | 1176 | err = root->cmds->create_flow_table(root, ft, log_table_sz, next_ft); |
|---|
| .. | .. |
|---|
| 2073 | 2129 | /* Assuming prio->node.children(flow tables) is sorted by level */ |
|---|
| 2074 | 2130 | static struct mlx5_flow_table *find_next_ft(struct mlx5_flow_table *ft) |
|---|
| 2075 | 2131 | { |
|---|
| 2132 | + struct fs_node *prio_parent, *child; |
|---|
| 2076 | 2133 | struct fs_prio *prio; |
|---|
| 2077 | 2134 | |
|---|
| 2078 | 2135 | fs_get_obj(prio, ft->node.parent); |
|---|
| 2079 | 2136 | |
|---|
| 2080 | 2137 | if (!list_is_last(&ft->node.list, &prio->node.children)) |
|---|
| 2081 | 2138 | return list_next_entry(ft, node.list); |
|---|
| 2082 | | - return find_next_chained_ft(prio); |
|---|
| 2139 | + |
|---|
| 2140 | + prio_parent = find_prio_chains_parent(&prio->node, &child); |
|---|
| 2141 | + |
|---|
| 2142 | + if (prio_parent && list_is_first(&child->list, &prio_parent->children)) |
|---|
| 2143 | + return find_closest_ft(&prio->node, false, false); |
|---|
| 2144 | + |
|---|
| 2145 | + return find_next_chained_ft(&prio->node); |
|---|
| 2083 | 2146 | } |
|---|
| 2084 | 2147 | |
|---|
| 2085 | 2148 | static int update_root_ft_destroy(struct mlx5_flow_table *ft) |
|---|