.. | .. |
---|
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) |
---|