When collapsing skbs during tcp_collapse_retrans and tcp_shift_skb_data, this patch is to avoid collapsing to a prev skb that has eor_info mark and the next_skb also has the tskey set (i.e. the prev skb will lose a eor marked tskey info).
Signed-off-by: Martin KaFai Lau <ka...@fb.com> Cc: Eric Dumazet <eduma...@google.com> Cc: Neal Cardwell <ncardw...@google.com> Cc: Soheil Hassas Yeganeh <soheil.k...@gmail.com> Cc: Willem de Bruijn <will...@google.com> Cc: Yuchung Cheng <ych...@google.com> --- include/net/tcp.h | 6 ++++++ net/ipv4/tcp_input.c | 3 +++ net/ipv4/tcp_output.c | 7 +++++-- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index f3c5dcb..56a287a 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -812,6 +812,12 @@ static inline int tcp_skb_mss(const struct sk_buff *skb) return TCP_SKB_CB(skb)->tcp_gso_size; } +static inline bool tcp_skb_can_collapse_eor(const struct sk_buff *skb, + const struct sk_buff *next_skb) +{ + return !(TCP_SKB_CB(skb)->eor_info && skb_shinfo(next_skb)->tskey); +} + /* Events passed to congestion control interface */ enum tcp_ca_event { CA_EVENT_TX_START, /* first transmit when no packets in flight */ diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 75e8336..e60922d 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -1368,6 +1368,9 @@ static struct sk_buff *tcp_shift_skb_data(struct sock *sk, struct sk_buff *skb, if ((TCP_SKB_CB(prev)->sacked & TCPCB_TAGBITS) != TCPCB_SACKED_ACKED) goto fallback; + if (!tcp_skb_can_collapse_eor(prev, skb)) + goto fallback; + in_sack = !after(start_seq, TCP_SKB_CB(skb)->seq) && !before(end_seq, TCP_SKB_CB(skb)->end_seq); diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index e71336c..1ae21f1 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -2512,7 +2512,8 @@ static void tcp_collapse_retrans(struct sock *sk, struct sk_buff *skb) } /* Check if coalescing SKBs is legal. */ -static bool tcp_can_collapse(const struct sock *sk, const struct sk_buff *skb) +static bool tcp_can_collapse(const struct sock *sk, const struct sk_buff *to, + const struct sk_buff *skb) { if (tcp_skb_pcount(skb) > 1) return false; @@ -2526,6 +2527,8 @@ static bool tcp_can_collapse(const struct sock *sk, const struct sk_buff *skb) /* Some heurestics for collapsing over SACK'd could be invented */ if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED) return false; + if (!tcp_skb_can_collapse_eor(to, skb)) + return false; return true; } @@ -2546,7 +2549,7 @@ static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *to, return; tcp_for_write_queue_from_safe(skb, tmp, sk) { - if (!tcp_can_collapse(sk, skb)) + if (!tcp_can_collapse(sk, to, skb)) break; space -= skb->len; -- 2.5.1