diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h index 062a823d311c..708ff7cb8806 100644 --- a/include/net/ip6_fib.h +++ b/include/net/ip6_fib.h @@ -21,6 +21,7 @@ #include #include #include +#include #ifdef CONFIG_IPV6_MULTIPLE_TABLES #define FIB6_TABLE_HASHSZ 256 @@ -109,6 +110,7 @@ struct rt6_info { u32 rt6i_metric; struct inet6_dev *rt6i_idev; + struct inet_peer *rt6i_peer; #ifdef CONFIG_XFRM u32 rt6i_flow_cache_genid; diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index 278312c95f96..23fed28db4bb 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h @@ -56,6 +56,9 @@ static inline unsigned int rt6_flags2srcprefs(int flags) return (flags >> 3) & 7; } +extern void rt6_bind_peer(struct rt6_info *rt, + int create); + extern void ip6_route_input(struct sk_buff *skb); extern struct dst_entry * ip6_route_output(struct net *net, diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c index 1c1335b0d401..f95b89f3916d 100644 --- a/net/ipv4/inetpeer.c +++ b/net/ipv4/inetpeer.c @@ -532,6 +532,7 @@ static int compute_total(void) { return v4_peers.total + v6_peers.total; } +EXPORT_SYMBOL_GPL(inet_getpeer); /* Called with local BH disabled. */ static void peer_check_expire(unsigned long dummy) @@ -577,3 +578,4 @@ void inet_putpeer(struct inet_peer *p) local_bh_enable(); } +EXPORT_SYMBOL_GPL(inet_putpeer); diff --git a/net/ipv6/route.c b/net/ipv6/route.c index a0c4ad109c63..026caef0326c 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -188,11 +188,29 @@ static void ip6_dst_destroy(struct dst_entry *dst) { struct rt6_info *rt = (struct rt6_info *)dst; struct inet6_dev *idev = rt->rt6i_idev; + struct inet_peer *peer = rt->rt6i_peer; if (idev != NULL) { rt->rt6i_idev = NULL; in6_dev_put(idev); } + if (peer) { + BUG_ON(!(rt->rt6i_flags & RTF_CACHE)); + rt->rt6i_peer = NULL; + inet_putpeer(peer); + } +} + +void rt6_bind_peer(struct rt6_info *rt, int create) +{ + struct inet_peer *peer; + + if (WARN_ON(!(rt->rt6i_flags & RTF_CACHE))) + return; + + peer = inet_getpeer_v6(&rt->rt6i_dst.addr, create); + if (peer && cmpxchg(&rt->rt6i_peer, NULL, peer) != NULL) + inet_putpeer(peer); } static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,