Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f51ffde9 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'ipv6-udp-set-dst-cache-for-a-connected-sk-if-current-not-valid'



Alexey Kodanev says:

====================
ipv6: udp: set dst cache for a connected sk if current not valid

A new RTF_CACHE route can be created with the socket's dst cache
update between the below calls in udpv6_sendmsg(), when datagram
sending results to ICMPV6_PKT_TOOBIG error:

   dst = ip6_sk_dst_lookup_flow(...)
   ...
release_dst:
    if (dst) {
        if (connected) {
            ip6_dst_store(sk, dst)

Therefore, the new socket's dst cache reset to the old one on
"release_dst:".

The first three patches prepare the code to store dst cache
with ip6_sk_dst_lookup_flow():

  * the first patch adds ip6_sk_dst_store_flow() function with
    commonly used source and destiantion addresses checks using
    the flow information.

  * the second patch adds a new argument to ip6_sk_dst_lookup_flow()
    and ability to store dst in the socket's cache. Also, the two
    users of the function are updated without enabling the new
    behavior: pingv6_sendmsg() and udpv6_sendmsg().

  * the third patch makes 'connected' variable in udpv6_sendmsg()
    to be consistent with ip6_sk_dst_store_flow(), changes its type
    from int to bool.

The last patch contains the actual fix that removes sk dst cache
update in the end of udpv6_sendmsg(), and allows to do it in
ip6_sk_dst_lookup_flow().

v6: * use bool type for a new parameter in ip_sk_dst_lookup_flow()
    * add one more patch to convert 'connected' variable in
      udpv6_sendmsg() from int to bool type. If it shouldn't be
      here I will resend it when the net-next is opened.

v5: * relocate ip6_sk_dst_store_flow() to net/ipv6/route.c and
      rename ip6_dst_store_flow() to ip6_sk_dst_store_flow() as
      suggested by Martin

v4: * fix the error in the build of ip_dst_store_flow() reported by
      kbuild test robot due to missing checks for CONFIG_IPV6: add
      new function to ip6_output.c instead of ip6_route.h
    * add 'const' to struct flowi6 in ip6_dst_store_flow()
    * minor commit messages fixes

v3: * instead of moving ip6_dst_store() above udp_v6_send_skb(),
      update socket's dst cache inside ip6_sk_dst_lookup_flow()
      if the current one is invalid
    * the issue not reproduced in 4.1, but starting from 4.2. Add
      one more 'Fixes:' commit that creates new RTF_CACHE route.
      Though, it is also mentioned in the first one
====================

Acked-by: default avatarMartin KaFai Lau <kafai@fb.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 0d3ad854 4f858c56
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -214,6 +214,9 @@ static inline void ip6_dst_store(struct sock *sk, struct dst_entry *dst,
#endif
}

void ip6_sk_dst_store_flow(struct sock *sk, struct dst_entry *dst,
			   const struct flowi6 *fl6);

static inline bool ipv6_unicast_destination(const struct sk_buff *skb)
{
	struct rt6_info *rt = (struct rt6_info *) skb_dst(skb);
+2 −1
Original line number Diff line number Diff line
@@ -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);

+1 −8
Original line number Diff line number Diff line
@@ -106,14 +106,7 @@ int ip6_datagram_dst_update(struct sock *sk, bool fix_sk_saddr)
		}
	}

	ip6_dst_store(sk, dst,
		      ipv6_addr_equal(&fl6.daddr, &sk->sk_v6_daddr) ?
		      &sk->sk_v6_daddr : NULL,
#ifdef CONFIG_IPV6_SUBTREES
		      ipv6_addr_equal(&fl6.saddr, &np->saddr) ?
		      &np->saddr :
#endif
		      NULL);
	ip6_sk_dst_store_flow(sk, dst, &fl6);

out:
	fl6_sock_release(flowlabel);
+12 −3
Original line number Diff line number Diff line
@@ -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)
	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;
}
+1 −1
Original line number Diff line number Diff line
@@ -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;
Loading