|
@@ -267,11 +267,31 @@ static bool TCP_ECN_rcv_ecn_echo(const struct tcp_sock *tp, const struct tcphdr
|
|
|
* 1. Tuning sk->sk_sndbuf, when connection enters established state.
|
|
|
*/
|
|
|
|
|
|
-static void tcp_fixup_sndbuf(struct sock *sk)
|
|
|
+static void tcp_sndbuf_expand(struct sock *sk)
|
|
|
{
|
|
|
- int sndmem = SKB_TRUESIZE(tcp_sk(sk)->rx_opt.mss_clamp + MAX_TCP_HEADER);
|
|
|
+ const struct tcp_sock *tp = tcp_sk(sk);
|
|
|
+ int sndmem, per_mss;
|
|
|
+ u32 nr_segs;
|
|
|
+
|
|
|
+ /* Worst case is non GSO/TSO : each frame consumes one skb
|
|
|
+ * and skb->head is kmalloced using power of two area of memory
|
|
|
+ */
|
|
|
+ per_mss = max_t(u32, tp->rx_opt.mss_clamp, tp->mss_cache) +
|
|
|
+ MAX_TCP_HEADER +
|
|
|
+ SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
|
|
|
+
|
|
|
+ per_mss = roundup_pow_of_two(per_mss) +
|
|
|
+ SKB_DATA_ALIGN(sizeof(struct sk_buff));
|
|
|
+
|
|
|
+ nr_segs = max_t(u32, TCP_INIT_CWND, tp->snd_cwnd);
|
|
|
+ nr_segs = max_t(u32, nr_segs, tp->reordering + 1);
|
|
|
+
|
|
|
+ /* Fast Recovery (RFC 5681 3.2) :
|
|
|
+ * Cubic needs 1.7 factor, rounded to 2 to include
|
|
|
+ * extra cushion (application might react slowly to POLLOUT)
|
|
|
+ */
|
|
|
+ sndmem = 2 * nr_segs * per_mss;
|
|
|
|
|
|
- sndmem *= TCP_INIT_CWND;
|
|
|
if (sk->sk_sndbuf < sndmem)
|
|
|
sk->sk_sndbuf = min(sndmem, sysctl_tcp_wmem[2]);
|
|
|
}
|
|
@@ -376,7 +396,7 @@ void tcp_init_buffer_space(struct sock *sk)
|
|
|
if (!(sk->sk_userlocks & SOCK_RCVBUF_LOCK))
|
|
|
tcp_fixup_rcvbuf(sk);
|
|
|
if (!(sk->sk_userlocks & SOCK_SNDBUF_LOCK))
|
|
|
- tcp_fixup_sndbuf(sk);
|
|
|
+ tcp_sndbuf_expand(sk);
|
|
|
|
|
|
tp->rcvq_space.space = tp->rcv_wnd;
|
|
|
tp->rcvq_space.time = tcp_time_stamp;
|
|
@@ -4723,15 +4743,7 @@ static void tcp_new_space(struct sock *sk)
|
|
|
struct tcp_sock *tp = tcp_sk(sk);
|
|
|
|
|
|
if (tcp_should_expand_sndbuf(sk)) {
|
|
|
- int sndmem = SKB_TRUESIZE(max_t(u32,
|
|
|
- tp->rx_opt.mss_clamp,
|
|
|
- tp->mss_cache) +
|
|
|
- MAX_TCP_HEADER);
|
|
|
- int demanded = max_t(unsigned int, tp->snd_cwnd,
|
|
|
- tp->reordering + 1);
|
|
|
- sndmem *= 2 * demanded;
|
|
|
- if (sndmem > sk->sk_sndbuf)
|
|
|
- sk->sk_sndbuf = min(sndmem, sysctl_tcp_wmem[2]);
|
|
|
+ tcp_sndbuf_expand(sk);
|
|
|
tp->snd_cwnd_stamp = tcp_time_stamp;
|
|
|
}
|
|
|
|