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:
parent
50d889b178
commit
901731b882
|
@ -236,6 +236,8 @@ struct ipv6_stub {
|
||||||
struct flowi6 *fl6, int oif,
|
struct flowi6 *fl6, int oif,
|
||||||
const struct sk_buff *skb,
|
const struct sk_buff *skb,
|
||||||
int strict);
|
int strict);
|
||||||
|
u32 (*ip6_mtu_from_fib6)(struct fib6_info *f6i, struct in6_addr *daddr,
|
||||||
|
struct in6_addr *saddr);
|
||||||
|
|
||||||
void (*udpv6_encap_enable)(void);
|
void (*udpv6_encap_enable)(void);
|
||||||
void (*ndisc_send_na)(struct net_device *dev, const struct in6_addr *daddr,
|
void (*ndisc_send_na)(struct net_device *dev, const struct in6_addr *daddr,
|
||||||
|
|
|
@ -412,6 +412,12 @@ static inline struct net_device *fib6_info_nh_dev(const struct fib6_info *f6i)
|
||||||
return f6i->fib6_nh.nh_dev;
|
return f6i->fib6_nh.nh_dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
struct lwtunnel_state *fib6_info_nh_lwt(const struct fib6_info *f6i)
|
||||||
|
{
|
||||||
|
return f6i->fib6_nh.nh_lwtstate;
|
||||||
|
}
|
||||||
|
|
||||||
void inet6_rt_notify(int event, struct fib6_info *rt, struct nl_info *info,
|
void inet6_rt_notify(int event, struct fib6_info *rt, struct nl_info *info,
|
||||||
unsigned int flags);
|
unsigned int flags);
|
||||||
|
|
||||||
|
|
|
@ -300,6 +300,9 @@ static inline unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst)
|
||||||
return mtu;
|
return mtu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 ip6_mtu_from_fib6(struct fib6_info *f6i, struct in6_addr *daddr,
|
||||||
|
struct in6_addr *saddr);
|
||||||
|
|
||||||
struct neighbour *ip6_neigh_lookup(const struct in6_addr *gw,
|
struct neighbour *ip6_neigh_lookup(const struct in6_addr *gw,
|
||||||
struct net_device *dev, struct sk_buff *skb,
|
struct net_device *dev, struct sk_buff *skb,
|
||||||
const void *daddr);
|
const void *daddr);
|
||||||
|
|
|
@ -161,12 +161,20 @@ eafnosupport_fib6_multipath_select(const struct net *net, struct fib6_info *f6i,
|
||||||
return f6i;
|
return f6i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u32
|
||||||
|
eafnosupport_ip6_mtu_from_fib6(struct fib6_info *f6i, struct in6_addr *daddr,
|
||||||
|
struct in6_addr *saddr)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
const struct ipv6_stub *ipv6_stub __read_mostly = &(struct ipv6_stub) {
|
const struct ipv6_stub *ipv6_stub __read_mostly = &(struct ipv6_stub) {
|
||||||
.ipv6_dst_lookup = eafnosupport_ipv6_dst_lookup,
|
.ipv6_dst_lookup = eafnosupport_ipv6_dst_lookup,
|
||||||
.fib6_get_table = eafnosupport_fib6_get_table,
|
.fib6_get_table = eafnosupport_fib6_get_table,
|
||||||
.fib6_table_lookup = eafnosupport_fib6_table_lookup,
|
.fib6_table_lookup = eafnosupport_fib6_table_lookup,
|
||||||
.fib6_lookup = eafnosupport_fib6_lookup,
|
.fib6_lookup = eafnosupport_fib6_lookup,
|
||||||
.fib6_multipath_select = eafnosupport_fib6_multipath_select,
|
.fib6_multipath_select = eafnosupport_fib6_multipath_select,
|
||||||
|
.ip6_mtu_from_fib6 = eafnosupport_ip6_mtu_from_fib6,
|
||||||
};
|
};
|
||||||
EXPORT_SYMBOL_GPL(ipv6_stub);
|
EXPORT_SYMBOL_GPL(ipv6_stub);
|
||||||
|
|
||||||
|
|
|
@ -894,6 +894,7 @@ static const struct ipv6_stub ipv6_stub_impl = {
|
||||||
.fib6_table_lookup = fib6_table_lookup,
|
.fib6_table_lookup = fib6_table_lookup,
|
||||||
.fib6_lookup = fib6_lookup,
|
.fib6_lookup = fib6_lookup,
|
||||||
.fib6_multipath_select = fib6_multipath_select,
|
.fib6_multipath_select = fib6_multipath_select,
|
||||||
|
.ip6_mtu_from_fib6 = ip6_mtu_from_fib6,
|
||||||
.udpv6_encap_enable = udpv6_encap_enable,
|
.udpv6_encap_enable = udpv6_encap_enable,
|
||||||
.ndisc_send_na = ndisc_send_na,
|
.ndisc_send_na = ndisc_send_na,
|
||||||
.nd_tbl = &nd_tbl,
|
.nd_tbl = &nd_tbl,
|
||||||
|
|
|
@ -2603,6 +2603,54 @@ out:
|
||||||
return mtu - lwtunnel_headroom(dst->lwtstate, mtu);
|
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 dst_entry *icmp6_dst_alloc(struct net_device *dev,
|
||||||
struct flowi6 *fl6)
|
struct flowi6 *fl6)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue