@@ -1408,6 +1408,23 @@ static inline int tcp_win_from_space(const struct sock *sk, int space)
space - (space>>tcp_adv_win_scale);
}
+/* Calculate the amount of buffer space which would allow for the advertisement
+ * of a window size of win, accounting for overhead.
+ *
+ * This is the inverse of tcp_win_from_space().
+ */
+static inline int tcp_space_from_win(const struct sock *sk, int win)
+{
+ int tcp_adv_win_scale = sock_net(sk)->ipv4.sysctl_tcp_adv_win_scale;
+
+ return tcp_adv_win_scale <= 0 ?
+ win<<(-tcp_adv_win_scale) :
+ /* Division by zero is avoided because the above expression is
+ * used when tcp_adv_win_scale == 0.
+ */
+ (win<<tcp_adv_win_scale) / ((1<<tcp_adv_win_scale) - 1);
+}
+
/* Note: caller must be prepared to deal with negative returns */
static inline int tcp_space(const struct sock *sk)
{
@@ -783,6 +783,9 @@ EXPORT_SYMBOL(sock_set_keepalive);
*/
static inline int sock_buf_size_to_available(struct sock *sk, int buf_size)
{
+ if (sk->sk_protocol == IPPROTO_TCP)
+ return tcp_win_from_space(sk, buf_size);
+
return buf_size / 2;
}
@@ -792,6 +795,9 @@ static inline int sock_buf_size_to_available(struct sock *sk, int buf_size)
*/
static inline int sock_available_to_buf_size(struct sock *sk, int available)
{
+ if (sk->sk_protocol == IPPROTO_TCP)
+ return tcp_space_from_win(sk, available);
+
return available * 2;
}
When setting SO_RCVBUF for TCP sockets, account for overhead in accord with sysctl_tcp_adv_win_scale. This makes the receive buffer overhead accounting for SO_RCVBUF consistent with how it is accounted elsewhere for TCP sockets. Signed-off-by: Heath Caldwell <hcaldwel@akamai.com> --- include/net/tcp.h | 17 +++++++++++++++++ net/core/sock.c | 6 ++++++ 2 files changed, 23 insertions(+)