aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/tcp_output.c51
1 files changed, 25 insertions, 26 deletions
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 9a9510acb14..9058e0a2510 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -1017,13 +1017,29 @@ static void tcp_cwnd_validate(struct sock *sk)
1017 } 1017 }
1018} 1018}
1019 1019
1020static unsigned int tcp_window_allows(struct tcp_sock *tp, struct sk_buff *skb, unsigned int mss_now, unsigned int cwnd) 1020/* Returns the portion of skb which can be sent right away without
1021 * introducing MSS oddities to segment boundaries. In rare cases where
1022 * mss_now != mss_cache, we will request caller to create a small skb
1023 * per input skb which could be mostly avoided here (if desired).
1024 */
1025static unsigned int tcp_mss_split_point(struct sock *sk, struct sk_buff *skb,
1026 unsigned int mss_now,
1027 unsigned int cwnd)
1021{ 1028{
1022 u32 window, cwnd_len; 1029 struct tcp_sock *tp = tcp_sk(sk);
1030 u32 needed, window, cwnd_len;
1023 1031
1024 window = (tp->snd_una + tp->snd_wnd - TCP_SKB_CB(skb)->seq); 1032 window = (tp->snd_una + tp->snd_wnd - TCP_SKB_CB(skb)->seq);
1025 cwnd_len = mss_now * cwnd; 1033 cwnd_len = mss_now * cwnd;
1026 return min(window, cwnd_len); 1034
1035 if (likely(cwnd_len <= window && skb != tcp_write_queue_tail(sk)))
1036 return cwnd_len;
1037
1038 if (skb == tcp_write_queue_tail(sk) && cwnd_len <= skb->len)
1039 return cwnd_len;
1040
1041 needed = min(skb->len, window);
1042 return needed - needed % mss_now;
1027} 1043}
1028 1044
1029/* Can at least one segment of SKB be sent right now, according to the 1045/* Can at least one segment of SKB be sent right now, according to the
@@ -1458,17 +1474,9 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle)
1458 } 1474 }
1459 1475
1460 limit = mss_now; 1476 limit = mss_now;
1461 if (tso_segs > 1) { 1477 if (tso_segs > 1)
1462 limit = tcp_window_allows(tp, skb, 1478 limit = tcp_mss_split_point(sk, skb, mss_now,
1463 mss_now, cwnd_quota); 1479 cwnd_quota);
1464
1465 if (skb->len < limit) {
1466 unsigned int trim = skb->len % mss_now;
1467
1468 if (trim)
1469 limit = skb->len - trim;
1470 }
1471 }
1472 1480
1473 if (skb->len > limit && 1481 if (skb->len > limit &&
1474 unlikely(tso_fragment(sk, skb, limit, mss_now))) 1482 unlikely(tso_fragment(sk, skb, limit, mss_now)))
@@ -1515,7 +1523,6 @@ void __tcp_push_pending_frames(struct sock *sk, unsigned int cur_mss,
1515 */ 1523 */
1516void tcp_push_one(struct sock *sk, unsigned int mss_now) 1524void tcp_push_one(struct sock *sk, unsigned int mss_now)
1517{ 1525{
1518 struct tcp_sock *tp = tcp_sk(sk);
1519 struct sk_buff *skb = tcp_send_head(sk); 1526 struct sk_buff *skb = tcp_send_head(sk);
1520 unsigned int tso_segs, cwnd_quota; 1527 unsigned int tso_segs, cwnd_quota;
1521 1528
@@ -1530,17 +1537,9 @@ void tcp_push_one(struct sock *sk, unsigned int mss_now)
1530 BUG_ON(!tso_segs); 1537 BUG_ON(!tso_segs);
1531 1538
1532 limit = mss_now; 1539 limit = mss_now;
1533 if (tso_segs > 1) { 1540 if (tso_segs > 1)
1534 limit = tcp_window_allows(tp, skb, 1541 limit = tcp_mss_split_point(sk, skb, mss_now,
1535 mss_now, cwnd_quota); 1542 cwnd_quota);
1536
1537 if (skb->len < limit) {
1538 unsigned int trim = skb->len % mss_now;
1539
1540 if (trim)
1541 limit = skb->len - trim;
1542 }
1543 }
1544 1543
1545 if (skb->len > limit && 1544 if (skb->len > limit &&
1546 unlikely(tso_fragment(sk, skb, limit, mss_now))) 1545 unlikely(tso_fragment(sk, skb, limit, mss_now)))