diff options
author | Alexey Kodanev <alexey.kodanev@oracle.com> | 2018-04-03 15:00:08 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-04-04 11:31:57 -0400 |
commit | 96818159c3c08911330e84f86b3becf71aeeaac8 (patch) | |
tree | 4c194bd0926d5e954e596303d79b7277b301358f /net/ipv6/ip6_output.c | |
parent | 7d6850f7c618d8f13d7945dd0dcee98223be6459 (diff) | |
download | lwn-96818159c3c08911330e84f86b3becf71aeeaac8.tar.gz lwn-96818159c3c08911330e84f86b3becf71aeeaac8.zip |
ipv6: allow to cache dst for a connected sk in ip6_sk_dst_lookup_flow()
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>
Diffstat (limited to 'net/ipv6/ip6_output.c')
-rw-r--r-- | net/ipv6/ip6_output.c | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index e6eaa4dd9f60..66a768b7b8fb 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -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; } |