net/ipv6: Add helper to return path MTU based on fib result

Determine path MTU from a FIB lookup result. Logic is based on
ip6_dst_mtu_forward plus lookup of nexthop exception.

Add ip6_dst_mtu_forward to ipv6_stubs to handle access by core
bpf code.

Signed-off-by: David Ahern <dsahern@gmail.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
This commit is contained in:
David Ahern 2018-05-21 09:08:14 -07:00 committed by Daniel Borkmann
parent 50d889b178
commit 901731b882
6 changed files with 68 additions and 0 deletions

View file

@ -2603,6 +2603,54 @@ out:
return mtu - lwtunnel_headroom(dst->lwtstate, mtu);
}
/* MTU selection:
* 1. mtu on route is locked - use it
* 2. mtu from nexthop exception
* 3. mtu from egress device
*
* based on ip6_dst_mtu_forward and exception logic of
* rt6_find_cached_rt; called with rcu_read_lock
*/
u32 ip6_mtu_from_fib6(struct fib6_info *f6i, struct in6_addr *daddr,
struct in6_addr *saddr)
{
struct rt6_exception_bucket *bucket;
struct rt6_exception *rt6_ex;
struct in6_addr *src_key;
struct inet6_dev *idev;
u32 mtu = 0;
if (unlikely(fib6_metric_locked(f6i, RTAX_MTU))) {
mtu = f6i->fib6_pmtu;
if (mtu)
goto out;
}
src_key = NULL;
#ifdef CONFIG_IPV6_SUBTREES
if (f6i->fib6_src.plen)
src_key = saddr;
#endif
bucket = rcu_dereference(f6i->rt6i_exception_bucket);
rt6_ex = __rt6_find_exception_rcu(&bucket, daddr, src_key);
if (rt6_ex && !rt6_check_expired(rt6_ex->rt6i))
mtu = dst_metric_raw(&rt6_ex->rt6i->dst, RTAX_MTU);
if (likely(!mtu)) {
struct net_device *dev = fib6_info_nh_dev(f6i);
mtu = IPV6_MIN_MTU;
idev = __in6_dev_get(dev);
if (idev && idev->cnf.mtu6 > mtu)
mtu = idev->cnf.mtu6;
}
mtu = min_t(unsigned int, mtu, IP6_MAX_MTU);
out:
return mtu - lwtunnel_headroom(fib6_info_nh_lwt(f6i), mtu);
}
struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
struct flowi6 *fl6)
{