Skip to content

Commit

Permalink
ipv6: add IPV6_RECVFRAGSIZE cmsg
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Willem de Bruijn authored and David S. Miller committed Nov 3, 2016
1 parent 70ecc24 commit 0cc0aa6
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 2 deletions.
5 changes: 3 additions & 2 deletions include/linux/ipv6.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,8 +229,9 @@ struct ipv6_pinfo {
rxflow:1,
rxtclass:1,
rxpmtu:1,
rxorigdstaddr:1;
/* 2 bits hole */
rxorigdstaddr:1,
recvfragsize:1;
/* 1 bits hole */
} bits;
__u16 all;
} rxopt;
Expand Down
1 change: 1 addition & 0 deletions include/uapi/linux/in6.h
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ struct in6_flowlabel_req {
#define IPV6_RECVORIGDSTADDR IPV6_ORIGDSTADDR
#define IPV6_TRANSPARENT 75
#define IPV6_UNICAST_IF 76
#define IPV6_RECVFRAGSIZE 77

/*
* Multicast Routing:
Expand Down
5 changes: 5 additions & 0 deletions net/ipv6/datagram.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
8 changes: 8 additions & 0 deletions net/ipv6/ipv6_sockglue.c
Original file line number Diff line number Diff line change
Expand Up @@ -868,6 +868,10 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
np->autoflowlabel = valbool;
retv = 0;
break;
case IPV6_RECVFRAGSIZE:
np->rxopt.bits.recvfragsize = valbool;
retv = 0;
break;
}

release_sock(sk);
Expand Down Expand Up @@ -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;
}
Expand Down

0 comments on commit 0cc0aa6

Please sign in to comment.