diff options
author | Willem de Bruijn <willemb@google.com> | 2016-11-02 11:02:17 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-11-03 15:41:11 -0400 |
commit | 0cc0aa614b4c24b21b2492c0a1753035ee8c6edb (patch) | |
tree | 848076fe75ed2503f9ef9b479cefb2317ea18682 /net | |
parent | 70ecc24841326396a827deb55c3fefac582a729d (diff) | |
download | linux-stable-0cc0aa614b4c24b21b2492c0a1753035ee8c6edb.tar.gz linux-stable-0cc0aa614b4c24b21b2492c0a1753035ee8c6edb.tar.bz2 linux-stable-0cc0aa614b4c24b21b2492c0a1753035ee8c6edb.zip |
ipv6: add IPV6_RECVFRAGSIZE cmsg
When reading a datagram or raw packet that arrived fragmented, expose
the maximum fragment size if recorded to allow applications to
estimate receive path MTU.
At this point, the field is only recorded when ipv6 connection
tracking is enabled. A follow-up patch will record this field also
in the ipv6 input path.
Tested using the test for IP_RECVFRAGSIZE plus
ip netns exec to ip addr add dev veth1 fc07::1/64
ip netns exec from ip addr add dev veth0 fc07::2/64
ip netns exec to ./recv_cmsg_recvfragsize -6 -u -p 6000 &
ip netns exec from nc -q 1 -u fc07::1 6000 < payload
Both with and without enabling connection tracking
ip6tables -A INPUT -m state --state NEW -p udp -j LOG
Signed-off-by: Willem de Bruijn <willemb@google.com>
Acked-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv6/datagram.c | 5 | ||||
-rw-r--r-- | net/ipv6/ipv6_sockglue.c | 8 |
2 files changed, 13 insertions, 0 deletions
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 37874e2f30ed..620c79a0130a 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c @@ -715,6 +715,11 @@ void ip6_datagram_recv_specific_ctl(struct sock *sk, struct msghdr *msg, put_cmsg(msg, SOL_IPV6, IPV6_ORIGDSTADDR, sizeof(sin6), &sin6); } } + if (np->rxopt.bits.recvfragsize && opt->frag_max_size) { + int val = opt->frag_max_size; + + put_cmsg(msg, SOL_IPV6, IPV6_RECVFRAGSIZE, sizeof(val), &val); + } } void ip6_datagram_recv_ctl(struct sock *sk, struct msghdr *msg, diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 636ec56f5f50..6c126780fcf2 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -868,6 +868,10 @@ pref_skip_coa: np->autoflowlabel = valbool; retv = 0; break; + case IPV6_RECVFRAGSIZE: + np->rxopt.bits.recvfragsize = valbool; + retv = 0; + break; } release_sock(sk); @@ -1310,6 +1314,10 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, val = np->autoflowlabel; break; + case IPV6_RECVFRAGSIZE: + val = np->rxopt.bits.recvfragsize; + break; + default: return -ENOPROTOOPT; } |