aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorDavid Ahern <dsahern@gmail.com>2019-04-09 17:41:19 -0400
committerDavid S. Miller <davem@davemloft.net>2019-04-11 17:24:07 -0400
commit0b34eb004347308ed0952ddb5b3898a71869ac3c (patch)
tree4c67f46492b695373ffde163f26ef2e3c7bb8594 /net/ipv6
parent0c59d00675874f9ee7a0371ad9d9b69386ea2d03 (diff)
ipv6: Refactor __ip6_route_redirect
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>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/route.c56
1 files changed, 33 insertions, 23 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 0e8becb1e455..d555edaaff13 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -2407,6 +2407,35 @@ void ip6_sk_dst_store_flow(struct sock *sk, struct dst_entry *dst,
2407 NULL); 2407 NULL);
2408} 2408}
2409 2409
2410static bool ip6_redirect_nh_match(struct fib6_info *f6i,
2411 struct fib6_nh *nh,
2412 struct flowi6 *fl6,
2413 const struct in6_addr *gw,
2414 struct rt6_info **ret)
2415{
2416 if (nh->fib_nh_flags & RTNH_F_DEAD || !nh->fib_nh_gw_family ||
2417 fl6->flowi6_oif != nh->fib_nh_dev->ifindex)
2418 return false;
2419
2420 /* rt_cache's gateway might be different from its 'parent'
2421 * in the case of an ip redirect.
2422 * So we keep searching in the exception table if the gateway
2423 * is different.
2424 */
2425 if (!ipv6_addr_equal(gw, &nh->fib_nh_gw6)) {
2426 struct rt6_info *rt_cache;
2427
2428 rt_cache = rt6_find_cached_rt(f6i, &fl6->daddr, &fl6->saddr);
2429 if (rt_cache &&
2430 ipv6_addr_equal(gw, &rt_cache->rt6i_gateway)) {
2431 *ret = rt_cache;
2432 return true;
2433 }
2434 return false;
2435 }
2436 return true;
2437}
2438
2410/* Handle redirects */ 2439/* Handle redirects */
2411struct ip6rd_flowi { 2440struct ip6rd_flowi {
2412 struct flowi6 fl6; 2441 struct flowi6 fl6;
@@ -2420,7 +2449,7 @@ static struct rt6_info *__ip6_route_redirect(struct net *net,
2420 int flags) 2449 int flags)
2421{ 2450{
2422 struct ip6rd_flowi *rdfl = (struct ip6rd_flowi *)fl6; 2451 struct ip6rd_flowi *rdfl = (struct ip6rd_flowi *)fl6;
2423 struct rt6_info *ret = NULL, *rt_cache; 2452 struct rt6_info *ret = NULL;
2424 struct fib6_info *rt; 2453 struct fib6_info *rt;
2425 struct fib6_node *fn; 2454 struct fib6_node *fn;
2426 2455
@@ -2438,34 +2467,15 @@ static struct rt6_info *__ip6_route_redirect(struct net *net,
2438 fn = fib6_node_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr); 2467 fn = fib6_node_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
2439restart: 2468restart:
2440 for_each_fib6_node_rt_rcu(fn) { 2469 for_each_fib6_node_rt_rcu(fn) {
2441 if (rt->fib6_nh.fib_nh_flags & RTNH_F_DEAD)
2442 continue;
2443 if (fib6_check_expired(rt)) 2470 if (fib6_check_expired(rt))
2444 continue; 2471 continue;
2445 if (rt->fib6_flags & RTF_REJECT) 2472 if (rt->fib6_flags & RTF_REJECT)
2446 break; 2473 break;
2447 if (!rt->fib6_nh.fib_nh_gw_family)
2448 continue;
2449 if (fl6->flowi6_oif != rt->fib6_nh.fib_nh_dev->ifindex) 2474 if (fl6->flowi6_oif != rt->fib6_nh.fib_nh_dev->ifindex)
2450 continue; 2475 continue;
2451 /* rt_cache's gateway might be different from its 'parent' 2476 if (ip6_redirect_nh_match(rt, &rt->fib6_nh, fl6,
2452 * in the case of an ip redirect. 2477 &rdfl->gateway, &ret))
2453 * So we keep searching in the exception table if the gateway 2478 goto out;
2454 * is different.
2455 */
2456 if (!ipv6_addr_equal(&rdfl->gateway, &rt->fib6_nh.fib_nh_gw6)) {
2457 rt_cache = rt6_find_cached_rt(rt,
2458 &fl6->daddr,
2459 &fl6->saddr);
2460 if (rt_cache &&
2461 ipv6_addr_equal(&rdfl->gateway,
2462 &rt_cache->rt6i_gateway)) {
2463 ret = rt_cache;
2464 break;
2465 }
2466 continue;
2467 }
2468 break;
2469 } 2479 }
2470 2480
2471 if (!rt) 2481 if (!rt)