| From foo@baz Tue Mar 6 19:02:12 PST 2018 |
| From: Ilya Lesokhin <ilyal@mellanox.com> |
| Date: Mon, 12 Feb 2018 12:57:04 +0200 |
| Subject: tcp: Honor the eor bit in tcp_mtu_probe |
| |
| From: Ilya Lesokhin <ilyal@mellanox.com> |
| |
| |
| [ Upstream commit 808cf9e38cd7923036a99f459ccc8cf2955e47af ] |
| |
| Avoid SKB coalescing if eor bit is set in one of the relevant |
| SKBs. |
| |
| Fixes: c134ecb87817 ("tcp: Make use of MSG_EOR in tcp_sendmsg") |
| Signed-off-by: Ilya Lesokhin <ilyal@mellanox.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/ipv4/tcp_output.c | 25 +++++++++++++++++++++++++ |
| 1 file changed, 25 insertions(+) |
| |
| --- a/net/ipv4/tcp_output.c |
| +++ b/net/ipv4/tcp_output.c |
| @@ -1973,6 +1973,24 @@ static inline void tcp_mtu_check_reprobe |
| } |
| } |
| |
| +static bool tcp_can_coalesce_send_queue_head(struct sock *sk, int len) |
| +{ |
| + struct sk_buff *skb, *next; |
| + |
| + skb = tcp_send_head(sk); |
| + tcp_for_write_queue_from_safe(skb, next, sk) { |
| + if (len <= skb->len) |
| + break; |
| + |
| + if (unlikely(TCP_SKB_CB(skb)->eor)) |
| + return false; |
| + |
| + len -= skb->len; |
| + } |
| + |
| + return true; |
| +} |
| + |
| /* Create a new MTU probe if we are ready. |
| * MTU probe is regularly attempting to increase the path MTU by |
| * deliberately sending larger packets. This discovers routing |
| @@ -2045,6 +2063,9 @@ static int tcp_mtu_probe(struct sock *sk |
| return 0; |
| } |
| |
| + if (!tcp_can_coalesce_send_queue_head(sk, probe_size)) |
| + return -1; |
| + |
| /* We're allowed to probe. Build it now. */ |
| nskb = sk_stream_alloc_skb(sk, probe_size, GFP_ATOMIC, false); |
| if (!nskb) |
| @@ -2080,6 +2101,10 @@ static int tcp_mtu_probe(struct sock *sk |
| /* We've eaten all the data from this skb. |
| * Throw it away. */ |
| TCP_SKB_CB(nskb)->tcp_flags |= TCP_SKB_CB(skb)->tcp_flags; |
| + /* If this is the last SKB we copy and eor is set |
| + * we need to propagate it to the new skb. |
| + */ |
| + TCP_SKB_CB(nskb)->eor = TCP_SKB_CB(skb)->eor; |
| tcp_unlink_write_queue(skb, sk); |
| sk_wmem_free_skb(sk, skb); |
| } else { |