Commit 0cc0aa61 authored by Willem de Bruijn's avatar Willem de Bruijn Committed by David S. Miller

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: default avatarWillem de Bruijn <willemb@google.com>
Acked-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 70ecc248
...@@ -229,8 +229,9 @@ struct ipv6_pinfo { ...@@ -229,8 +229,9 @@ struct ipv6_pinfo {
rxflow:1, rxflow:1,
rxtclass:1, rxtclass:1,
rxpmtu:1, rxpmtu:1,
rxorigdstaddr:1; rxorigdstaddr:1,
/* 2 bits hole */ recvfragsize:1;
/* 1 bits hole */
} bits; } bits;
__u16 all; __u16 all;
} rxopt; } rxopt;
......
...@@ -283,6 +283,7 @@ struct in6_flowlabel_req { ...@@ -283,6 +283,7 @@ struct in6_flowlabel_req {
#define IPV6_RECVORIGDSTADDR IPV6_ORIGDSTADDR #define IPV6_RECVORIGDSTADDR IPV6_ORIGDSTADDR
#define IPV6_TRANSPARENT 75 #define IPV6_TRANSPARENT 75
#define IPV6_UNICAST_IF 76 #define IPV6_UNICAST_IF 76
#define IPV6_RECVFRAGSIZE 77
/* /*
* Multicast Routing: * Multicast Routing:
......
...@@ -715,6 +715,11 @@ void ip6_datagram_recv_specific_ctl(struct sock *sk, struct msghdr *msg, ...@@ -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); 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, void ip6_datagram_recv_ctl(struct sock *sk, struct msghdr *msg,
......
...@@ -868,6 +868,10 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, ...@@ -868,6 +868,10 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
np->autoflowlabel = valbool; np->autoflowlabel = valbool;
retv = 0; retv = 0;
break; break;
case IPV6_RECVFRAGSIZE:
np->rxopt.bits.recvfragsize = valbool;
retv = 0;
break;
} }
release_sock(sk); release_sock(sk);
...@@ -1310,6 +1314,10 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, ...@@ -1310,6 +1314,10 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
val = np->autoflowlabel; val = np->autoflowlabel;
break; break;
case IPV6_RECVFRAGSIZE:
val = np->rxopt.bits.recvfragsize;
break;
default: default:
return -ENOPROTOOPT; return -ENOPROTOOPT;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment