git.openpandora.org
/
pandora-kernel.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
tcp: preserve ACK clocking in TSO
[pandora-kernel.git]
/
net
/
ipv4
/
tcp_output.c
diff --git
a/net/ipv4/tcp_output.c
b/net/ipv4/tcp_output.c
index
63170e2
..
5c1807c
100644
(file)
--- a/
net/ipv4/tcp_output.c
+++ b/
net/ipv4/tcp_output.c
@@
-1093,6
+1093,13
@@
static void __pskb_trim_head(struct sk_buff *skb, int len)
{
int i, k, eat;
{
int i, k, eat;
+ eat = min_t(int, len, skb_headlen(skb));
+ if (eat) {
+ __skb_pull(skb, eat);
+ len -= eat;
+ if (!len)
+ return;
+ }
eat = len;
k = 0;
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
eat = len;
k = 0;
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
@@
-1124,11
+1131,7
@@
int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
if (skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
return -ENOMEM;
if (skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
return -ENOMEM;
- /* If len == headlen, we avoid __skb_pull to preserve alignment. */
- if (unlikely(len < skb_headlen(skb)))
- __skb_pull(skb, len);
- else
- __pskb_trim_head(skb, len - skb_headlen(skb));
+ __pskb_trim_head(skb, len);
TCP_SKB_CB(skb)->seq += len;
skb->ip_summed = CHECKSUM_PARTIAL;
TCP_SKB_CB(skb)->seq += len;
skb->ip_summed = CHECKSUM_PARTIAL;
@@
-1138,11
+1141,9
@@
int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
sk_mem_uncharge(sk, len);
sock_set_flag(sk, SOCK_QUEUE_SHRUNK);
sk_mem_uncharge(sk, len);
sock_set_flag(sk, SOCK_QUEUE_SHRUNK);
- /* Any change of skb->len requires recalculation of tso
- * factor and mss.
- */
+ /* Any change of skb->len requires recalculation of tso factor. */
if (tcp_skb_pcount(skb) > 1)
if (tcp_skb_pcount(skb) > 1)
- tcp_set_skb_tso_segs(sk, skb, tcp_
current_mss(sk
));
+ tcp_set_skb_tso_segs(sk, skb, tcp_
skb_mss(skb
));
return 0;
}
return 0;
}
@@
-1316,21
+1317,21
@@
static void tcp_cwnd_validate(struct sock *sk)
* when we would be allowed to send the split-due-to-Nagle skb fully.
*/
static unsigned int tcp_mss_split_point(const struct sock *sk, const struct sk_buff *skb,
* when we would be allowed to send the split-due-to-Nagle skb fully.
*/
static unsigned int tcp_mss_split_point(const struct sock *sk, const struct sk_buff *skb,
- unsigned int mss_now, unsigned int
cwnd
)
+ unsigned int mss_now, unsigned int
max_segs
)
{
const struct tcp_sock *tp = tcp_sk(sk);
{
const struct tcp_sock *tp = tcp_sk(sk);
- u32 needed, window,
cwnd
_len;
+ u32 needed, window,
max
_len;
window = tcp_wnd_end(tp) - TCP_SKB_CB(skb)->seq;
window = tcp_wnd_end(tp) - TCP_SKB_CB(skb)->seq;
-
cwnd_len = mss_now * cwnd
;
+
max_len = mss_now * max_segs
;
- if (likely(
cwnd
_len <= window && skb != tcp_write_queue_tail(sk)))
- return
cwnd
_len;
+ if (likely(
max
_len <= window && skb != tcp_write_queue_tail(sk)))
+ return
max
_len;
needed = min(skb->len, window);
needed = min(skb->len, window);
- if (
cwnd
_len <= needed)
- return
cwnd
_len;
+ if (
max
_len <= needed)
+ return
max
_len;
return needed - needed % mss_now;
}
return needed - needed % mss_now;
}
@@
-1558,7
+1559,8
@@
static int tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb)
limit = min(send_win, cong_win);
/* If a full-sized TSO skb can be sent, do it. */
limit = min(send_win, cong_win);
/* If a full-sized TSO skb can be sent, do it. */
- if (limit >= sk->sk_gso_max_size)
+ if (limit >= min_t(unsigned int, sk->sk_gso_max_size,
+ sk->sk_gso_max_segs * tp->mss_cache))
goto send_now;
/* Middle in queue won't get any more data, full sendable already? */
goto send_now;
/* Middle in queue won't get any more data, full sendable already? */
@@
-1585,8
+1587,11
@@
static int tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb)
goto send_now;
}
goto send_now;
}
- /* Ok, it looks like it is advisable to defer. */
- tp->tso_deferred = 1 | (jiffies << 1);
+ /* Ok, it looks like it is advisable to defer.
+ * Do not rearm the timer if already set to not break TCP ACK clocking.
+ */
+ if (!tp->tso_deferred)
+ tp->tso_deferred = 1 | (jiffies << 1);
return 1;
return 1;
@@
-1784,7
+1789,9
@@
static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
limit = mss_now;
if (tso_segs > 1 && !tcp_urg_mode(tp))
limit = tcp_mss_split_point(sk, skb, mss_now,
limit = mss_now;
if (tso_segs > 1 && !tcp_urg_mode(tp))
limit = tcp_mss_split_point(sk, skb, mss_now,
- cwnd_quota);
+ min_t(unsigned int,
+ cwnd_quota,
+ sk->sk_gso_max_segs));
if (skb->len > limit &&
unlikely(tso_fragment(sk, skb, limit, mss_now, gfp)))
if (skb->len > limit &&
unlikely(tso_fragment(sk, skb, limit, mss_now, gfp)))
@@
-2059,7
+2066,7
@@
static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *to,
/* Punt if not enough space exists in the first SKB for
* the data in the second
*/
/* Punt if not enough space exists in the first SKB for
* the data in the second
*/
- if (skb->len > skb_
t
ailroom(to))
+ if (skb->len > skb_
av
ailroom(to))
break;
if (after(TCP_SKB_CB(skb)->end_seq, tcp_wnd_end(tp)))
break;
if (after(TCP_SKB_CB(skb)->end_seq, tcp_wnd_end(tp)))