]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/commitdiff
ipv6: allow to cache dst for a connected sk in ip6_sk_dst_lookup_flow()
authorAlexey Kodanev <alexey.kodanev@oracle.com>
Tue, 3 Apr 2018 12:00:08 +0000 (15:00 +0300)
committerDavid S. Miller <davem@davemloft.net>
Wed, 4 Apr 2018 15:31:57 +0000 (11:31 -0400)
Add 'connected' parameter 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.kodanev@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/ipv6.h
net/ipv6/ip6_output.c
net/ipv6/ping.c
net/ipv6/udp.c

index 9b6e7f51b1d46c1e2b5bdb2b9a2d3dc4904d778c..836f31af1369b9c6967073eed66ce5a062e4f9c2 100644 (file)
@@ -965,7 +965,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,
+                                        bool connected);
 struct dst_entry *ip6_blackhole_route(struct net *net,
                                      struct dst_entry *orig_dst);
 
index e6eaa4dd9f60bcfd088e5e44999aa53930ee6ad8..66a768b7b8fb796670bf69fc451264a72d153228 100644 (file)
@@ -1105,23 +1105,32 @@ EXPORT_SYMBOL_GPL(ip6_dst_lookup_flow);
  *     @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,
+                                        bool 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_sk_dst_store_flow(sk, dst_clone(dst), fl6);
 
        return dst;
 }
index d12c55dad7d141e632a6407a58eeeefe57c6b7c3..746eeae7f581e6918ddea6f9f5e8b855d58717e3 100644 (file)
@@ -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, false);
        if (IS_ERR(dst))
                return PTR_ERR(dst);
        rt = (struct rt6_info *) dst;
index 6861ed479469d347788362b868f7fdbc7f9becc2..fc13a1e2d789a6d6bbcd099e37c89a8d41ca4863 100644 (file)
@@ -1308,7 +1308,7 @@ do_udp_sendmsg:
 
        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, false);
        if (IS_ERR(dst)) {
                err = PTR_ERR(dst);
                dst = NULL;