ipv6: Refactor find_rr_leaf
authorDavid Ahern <dsahern@gmail.com>
Tue, 9 Apr 2019 21:41:15 +0000 (14:41 -0700)
committerDavid S. Miller <davem@davemloft.net>
Thu, 11 Apr 2019 21:24:06 +0000 (14:24 -0700)
find_rr_leaf has 3 loops over fib_entries calling find_match. The loops
are very similar with differences in start point and whether the metric
is evaluated:
    1. start at rr_head, no extra loop compare, check fib metric
    2. start at leaf, compare rt against rr_head, check metric
    3. start at cont (potential saved point from earlier loops), no
       extra loop compare, no metric check

Create 1 loop that is called 3 different times. This will make a
later change with multipath nexthop objects much simpler.

Signed-off-by: David Ahern <dsahern@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv6/route.c

index 200bd5bb56bf8fc349881591e197ee33d0263be7..52aa48a8dbda9e414acba4022998469a1bf858a3 100644 (file)
@@ -668,58 +668,52 @@ out:
        return rc;
 }
 
-static struct fib6_info *find_rr_leaf(struct fib6_node *fn,
-                                    struct fib6_info *leaf,
-                                    struct fib6_info *rr_head,
-                                    u32 metric, int oif, int strict,
-                                    bool *do_rr)
+static void __find_rr_leaf(struct fib6_info *rt_start,
+                          struct fib6_info *nomatch, u32 metric,
+                          struct fib6_info **match, struct fib6_info **cont,
+                          int oif, int strict, bool *do_rr, int *mpri)
 {
-       struct fib6_info *rt, *match, *cont;
-       struct fib6_nh *nh;
-       int mpri = -1;
+       struct fib6_info *rt;
 
-       match = NULL;
-       cont = NULL;
-       for (rt = rr_head; rt; rt = rcu_dereference(rt->fib6_next)) {
-               if (rt->fib6_metric != metric) {
-                       cont = rt;
-                       break;
+       for (rt = rt_start;
+            rt && rt != nomatch;
+            rt = rcu_dereference(rt->fib6_next)) {
+               struct fib6_nh *nh;
+
+               if (cont && rt->fib6_metric != metric) {
+                       *cont = rt;
+                       return;
                }
 
                if (fib6_check_expired(rt))
                        continue;
 
                nh = &rt->fib6_nh;
-               if (find_match(nh, rt->fib6_flags, oif, strict, &mpri, do_rr))
-                       match = rt;
+               if (find_match(nh, rt->fib6_flags, oif, strict, mpri, do_rr))
+                       *match = rt;
        }
+}
 
-       for (rt = leaf; rt && rt != rr_head;
-            rt = rcu_dereference(rt->fib6_next)) {
-               if (rt->fib6_metric != metric) {
-                       cont = rt;
-                       break;
-               }
+static struct fib6_info *find_rr_leaf(struct fib6_node *fn,
+                                     struct fib6_info *leaf,
+                                     struct fib6_info *rr_head,
+                                     u32 metric, int oif, int strict,
+                                     bool *do_rr)
+{
+       struct fib6_info *match = NULL, *cont = NULL;
+       int mpri = -1;
 
-               if (fib6_check_expired(rt))
-                       continue;
+       __find_rr_leaf(rr_head, NULL, metric, &match, &cont,
+                      oif, strict, do_rr, &mpri);
 
-               nh = &rt->fib6_nh;
-               if (find_match(nh, rt->fib6_flags, oif, strict, &mpri, do_rr))
-                       match = rt;
-       }
+       __find_rr_leaf(leaf, rr_head, metric, &match, &cont,
+                      oif, strict, do_rr, &mpri);
 
        if (match || !cont)
                return match;
 
-       for (rt = cont; rt; rt = rcu_dereference(rt->fib6_next)) {
-               if (fib6_check_expired(rt))
-                       continue;
-
-               nh = &rt->fib6_nh;
-               if (find_match(nh, rt->fib6_flags, oif, strict, &mpri, do_rr))
-                       match = rt;
-       }
+       __find_rr_leaf(cont, NULL, metric, &match, NULL,
+                      oif, strict, do_rr, &mpri);
 
        return match;
 }