Add 'connected' argument to ip6_sk_dst_lookup_flow() and update the cache only if ip6_sk_dst_check() returns NULL and a socket is connected.
The function is used as before, the new behavior for UDP sockets in udpv6_sendmsg() will be enabled in the next patch. Signed-off-by: Alexey Kodanev <alexey.koda...@oracle.com> --- include/net/ipv6.h | 3 ++- net/ipv6/ip6_output.c | 15 ++++++++++++--- net/ipv6/ping.c | 2 +- net/ipv6/udp.c | 2 +- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 1dd31ca..769550a 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -978,7 +978,8 @@ int ip6_dst_lookup(struct net *net, struct sock *sk, struct dst_entry **dst, struct dst_entry *ip6_dst_lookup_flow(const struct sock *sk, struct flowi6 *fl6, const struct in6_addr *final_dst); struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6, - const struct in6_addr *final_dst); + const struct in6_addr *final_dst, + int connected); struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *orig_dst); diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index ed87ce5..cdcdf37 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -1122,23 +1122,32 @@ struct dst_entry *ip6_dst_lookup_flow(const struct sock *sk, struct flowi6 *fl6, * @sk: socket which provides the dst cache and route info * @fl6: flow to lookup * @final_dst: final destination address for ipsec lookup + * @connected: whether @sk is connected or not * * This function performs a route lookup on the given flow with the * possibility of using the cached route in the socket if it is valid. * It will take the socket dst lock when operating on the dst cache. * As a result, this function can only be used in process context. * + * In addition, for a connected socket, cache the dst in the socket + * if the current cache is not valid. + * * It returns a valid dst pointer on success, or a pointer encoded * error code. */ struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6, - const struct in6_addr *final_dst) + const struct in6_addr *final_dst, + int connected) { struct dst_entry *dst = sk_dst_check(sk, inet6_sk(sk)->dst_cookie); dst = ip6_sk_dst_check(sk, dst, fl6); - if (!dst) - dst = ip6_dst_lookup_flow(sk, fl6, final_dst); + if (dst) + return dst; + + dst = ip6_dst_lookup_flow(sk, fl6, final_dst); + if (connected && !IS_ERR(dst)) + ip6_dst_store_flow(sk, dst_clone(dst), fl6); return dst; } diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c index d12c55d..546f4a6 100644 --- a/net/ipv6/ping.c +++ b/net/ipv6/ping.c @@ -121,7 +121,7 @@ static int ping_v6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) ipc6.tclass = np->tclass; fl6.flowlabel = ip6_make_flowinfo(ipc6.tclass, fl6.flowlabel); - dst = ip6_sk_dst_lookup_flow(sk, &fl6, daddr); + dst = ip6_sk_dst_lookup_flow(sk, &fl6, daddr, 0); if (IS_ERR(dst)) return PTR_ERR(dst); rt = (struct rt6_info *) dst; diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 52e3ea0..e49dac4 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -1289,7 +1289,7 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) fl6.flowlabel = ip6_make_flowinfo(ipc6.tclass, fl6.flowlabel); - dst = ip6_sk_dst_lookup_flow(sk, &fl6, final_p); + dst = ip6_sk_dst_lookup_flow(sk, &fl6, final_p, 0); if (IS_ERR(dst)) { err = PTR_ERR(dst); dst = NULL; -- 1.8.3.1