Skip to content

Commit 59104f0

Browse files
Eric Dumazetdavem330
authored andcommitted
ip: take care of last fragment in ip_append_data
While investigating a bit, I found ip_fragment() slow path was taken because ip_append_data() provides following layout for a send(MTU + N*(MTU - 20)) syscall : - one skb with 1500 (mtu) bytes - N fragments of 1480 (mtu-20) bytes (before adding IP header) last fragment gets 17 bytes of trail data because of following bit: if (datalen == length + fraggap) alloclen += rt->dst.trailer_len; Then esp4 adds 16 bytes of data (while trailer_len is 17... hmm... another bug ?) In ip_fragment(), we notice last fragment is too big (1496 + 20) > mtu, so we take slow path, building another skb chain. In order to avoid taking slow path, we should correct ip_append_data() to make sure last fragment has real trail space, under mtu... Signed-off-by: Eric Dumazet <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent a02cec2 commit 59104f0

File tree

1 file changed

+6
-3
lines changed

1 file changed

+6
-3
lines changed

net/ipv4/ip_output.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -926,16 +926,19 @@ int ip_append_data(struct sock *sk,
926926
!(rt->dst.dev->features&NETIF_F_SG))
927927
alloclen = mtu;
928928
else
929-
alloclen = datalen + fragheaderlen;
929+
alloclen = fraglen;
930930

931931
/* The last fragment gets additional space at tail.
932932
* Note, with MSG_MORE we overallocate on fragments,
933933
* because we have no idea what fragment will be
934934
* the last.
935935
*/
936-
if (datalen == length + fraggap)
936+
if (datalen == length + fraggap) {
937937
alloclen += rt->dst.trailer_len;
938-
938+
/* make sure mtu is not reached */
939+
if (datalen > mtu - fragheaderlen - rt->dst.trailer_len)
940+
datalen -= ALIGN(rt->dst.trailer_len, 8);
941+
}
939942
if (transhdrlen) {
940943
skb = sock_alloc_send_skb(sk,
941944
alloclen + hh_len + 15,

0 commit comments

Comments
 (0)