ipv6: Refactor __ip6_route_redirect
authorDavid Ahern <dsahern@gmail.com>
Tue, 9 Apr 2019 21:41:19 +0000 (14:41 -0700)
committerDavid S. Miller <davem@davemloft.net>
Thu, 11 Apr 2019 21:24:07 +0000 (14:24 -0700)
Move the nexthop evaluation of a fib entry to a helper that can be
leveraged for each fib6_nh in a multipath nexthop object.

In the move, 'continue' statements means the helper returns false
(loop should continue) and 'break' means return true (found the entry
of interest).

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

index 0e8becb..d555eda 100644 (file)
@@ -2407,6 +2407,35 @@ void ip6_sk_dst_store_flow(struct sock *sk, struct dst_entry *dst,
                      NULL);
 }
 
+static bool ip6_redirect_nh_match(struct fib6_info *f6i,
+                                 struct fib6_nh *nh,
+                                 struct flowi6 *fl6,
+                                 const struct in6_addr *gw,
+                                 struct rt6_info **ret)
+{
+       if (nh->fib_nh_flags & RTNH_F_DEAD || !nh->fib_nh_gw_family ||
+           fl6->flowi6_oif != nh->fib_nh_dev->ifindex)
+               return false;
+
+       /* rt_cache's gateway might be different from its 'parent'
+        * in the case of an ip redirect.
+        * So we keep searching in the exception table if the gateway
+        * is different.
+        */
+       if (!ipv6_addr_equal(gw, &nh->fib_nh_gw6)) {
+               struct rt6_info *rt_cache;
+
+               rt_cache = rt6_find_cached_rt(f6i, &fl6->daddr, &fl6->saddr);
+               if (rt_cache &&
+                   ipv6_addr_equal(gw, &rt_cache->rt6i_gateway)) {
+                       *ret = rt_cache;
+                       return true;
+               }
+               return false;
+       }
+       return true;
+}
+
 /* Handle redirects */
 struct ip6rd_flowi {
        struct flowi6 fl6;
@@ -2420,7 +2449,7 @@ static struct rt6_info *__ip6_route_redirect(struct net *net,
                                             int flags)
 {
        struct ip6rd_flowi *rdfl = (struct ip6rd_flowi *)fl6;
-       struct rt6_info *ret = NULL, *rt_cache;
+       struct rt6_info *ret = NULL;
        struct fib6_info *rt;
        struct fib6_node *fn;
 
@@ -2438,34 +2467,15 @@ static struct rt6_info *__ip6_route_redirect(struct net *net,
        fn = fib6_node_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
 restart:
        for_each_fib6_node_rt_rcu(fn) {
-               if (rt->fib6_nh.fib_nh_flags & RTNH_F_DEAD)
-                       continue;
                if (fib6_check_expired(rt))
                        continue;
                if (rt->fib6_flags & RTF_REJECT)
                        break;
-               if (!rt->fib6_nh.fib_nh_gw_family)
-                       continue;
                if (fl6->flowi6_oif != rt->fib6_nh.fib_nh_dev->ifindex)
                        continue;
-               /* rt_cache's gateway might be different from its 'parent'
-                * in the case of an ip redirect.
-                * So we keep searching in the exception table if the gateway
-                * is different.
-                */
-               if (!ipv6_addr_equal(&rdfl->gateway, &rt->fib6_nh.fib_nh_gw6)) {
-                       rt_cache = rt6_find_cached_rt(rt,
-                                                     &fl6->daddr,
-                                                     &fl6->saddr);
-                       if (rt_cache &&
-                           ipv6_addr_equal(&rdfl->gateway,
-                                           &rt_cache->rt6i_gateway)) {
-                               ret = rt_cache;
-                               break;
-                       }
-                       continue;
-               }
-               break;
+               if (ip6_redirect_nh_match(rt, &rt->fib6_nh, fl6,
+                                         &rdfl->gateway, &ret))
+                       goto out;
        }
 
        if (!rt)