diff options
-rw-r--r-- | include/linux/snmp.h | 1 | ||||
-rw-r--r-- | net/ipv4/proc.c | 1 | ||||
-rw-r--r-- | net/ipv4/tcp_input.c | 19 |
3 files changed, 20 insertions, 1 deletions
diff --git a/include/linux/snmp.h b/include/linux/snmp.h index 8ee8af4e6da9..2e68f5ba0389 100644 --- a/include/linux/snmp.h +++ b/include/linux/snmp.h | |||
@@ -233,6 +233,7 @@ enum | |||
233 | LINUX_MIB_TCPREQQFULLDOCOOKIES, /* TCPReqQFullDoCookies */ | 233 | LINUX_MIB_TCPREQQFULLDOCOOKIES, /* TCPReqQFullDoCookies */ |
234 | LINUX_MIB_TCPREQQFULLDROP, /* TCPReqQFullDrop */ | 234 | LINUX_MIB_TCPREQQFULLDROP, /* TCPReqQFullDrop */ |
235 | LINUX_MIB_TCPRETRANSFAIL, /* TCPRetransFail */ | 235 | LINUX_MIB_TCPRETRANSFAIL, /* TCPRetransFail */ |
236 | LINUX_MIB_TCPRCVCOALESCE, /* TCPRcvCoalesce */ | ||
236 | __LINUX_MIB_MAX | 237 | __LINUX_MIB_MAX |
237 | }; | 238 | }; |
238 | 239 | ||
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index 02d61079f08b..8af0d44e4e22 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c | |||
@@ -257,6 +257,7 @@ static const struct snmp_mib snmp4_net_list[] = { | |||
257 | SNMP_MIB_ITEM("TCPReqQFullDoCookies", LINUX_MIB_TCPREQQFULLDOCOOKIES), | 257 | SNMP_MIB_ITEM("TCPReqQFullDoCookies", LINUX_MIB_TCPREQQFULLDOCOOKIES), |
258 | SNMP_MIB_ITEM("TCPReqQFullDrop", LINUX_MIB_TCPREQQFULLDROP), | 258 | SNMP_MIB_ITEM("TCPReqQFullDrop", LINUX_MIB_TCPREQQFULLDROP), |
259 | SNMP_MIB_ITEM("TCPRetransFail", LINUX_MIB_TCPRETRANSFAIL), | 259 | SNMP_MIB_ITEM("TCPRetransFail", LINUX_MIB_TCPRETRANSFAIL), |
260 | SNMP_MIB_ITEM("TCPRcvCoalesce", LINUX_MIB_TCPRCVCOALESCE), | ||
260 | SNMP_MIB_SENTINEL | 261 | SNMP_MIB_SENTINEL |
261 | }; | 262 | }; |
262 | 263 | ||
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index fa7de12c4a52..e886e2f7fa8d 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -4484,7 +4484,24 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb) | |||
4484 | end_seq = TCP_SKB_CB(skb)->end_seq; | 4484 | end_seq = TCP_SKB_CB(skb)->end_seq; |
4485 | 4485 | ||
4486 | if (seq == TCP_SKB_CB(skb1)->end_seq) { | 4486 | if (seq == TCP_SKB_CB(skb1)->end_seq) { |
4487 | __skb_queue_after(&tp->out_of_order_queue, skb1, skb); | 4487 | /* Packets in ofo can stay in queue a long time. |
4488 | * Better try to coalesce them right now | ||
4489 | * to avoid future tcp_collapse_ofo_queue(), | ||
4490 | * probably the most expensive function in tcp stack. | ||
4491 | */ | ||
4492 | if (skb->len <= skb_tailroom(skb1) && !tcp_hdr(skb)->fin) { | ||
4493 | NET_INC_STATS_BH(sock_net(sk), | ||
4494 | LINUX_MIB_TCPRCVCOALESCE); | ||
4495 | BUG_ON(skb_copy_bits(skb, 0, | ||
4496 | skb_put(skb1, skb->len), | ||
4497 | skb->len)); | ||
4498 | TCP_SKB_CB(skb1)->end_seq = end_seq; | ||
4499 | TCP_SKB_CB(skb1)->ack_seq = TCP_SKB_CB(skb)->ack_seq; | ||
4500 | __kfree_skb(skb); | ||
4501 | skb = NULL; | ||
4502 | } else { | ||
4503 | __skb_queue_after(&tp->out_of_order_queue, skb1, skb); | ||
4504 | } | ||
4488 | 4505 | ||
4489 | if (!tp->rx_opt.num_sacks || | 4506 | if (!tp->rx_opt.num_sacks || |
4490 | tp->selective_acks[0].end_seq != seq) | 4507 | tp->selective_acks[0].end_seq != seq) |