Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/tcp_input.c
Show First 20 Lines • Show All 206 Lines • ▼ Show 20 Lines | |||||
SYSCTL_INT(_net_inet_tcp, TCPCTL_RECVSPACE, recvspace, CTLFLAG_VNET | CTLFLAG_RW, | SYSCTL_INT(_net_inet_tcp, TCPCTL_RECVSPACE, recvspace, CTLFLAG_VNET | CTLFLAG_RW, | ||||
&VNET_NAME(tcp_recvspace), 0, "Initial receive socket buffer size"); | &VNET_NAME(tcp_recvspace), 0, "Initial receive socket buffer size"); | ||||
VNET_DEFINE(int, tcp_do_autorcvbuf) = 1; | VNET_DEFINE(int, tcp_do_autorcvbuf) = 1; | ||||
SYSCTL_INT(_net_inet_tcp, OID_AUTO, recvbuf_auto, CTLFLAG_VNET | CTLFLAG_RW, | SYSCTL_INT(_net_inet_tcp, OID_AUTO, recvbuf_auto, CTLFLAG_VNET | CTLFLAG_RW, | ||||
&VNET_NAME(tcp_do_autorcvbuf), 0, | &VNET_NAME(tcp_do_autorcvbuf), 0, | ||||
"Enable automatic receive buffer sizing"); | "Enable automatic receive buffer sizing"); | ||||
VNET_DEFINE(int, tcp_autorcvbuf_inc) = 16*1024; | |||||
SYSCTL_INT(_net_inet_tcp, OID_AUTO, recvbuf_inc, CTLFLAG_VNET | CTLFLAG_RW, | |||||
&VNET_NAME(tcp_autorcvbuf_inc), 0, | |||||
"Incrementor step size of automatic receive buffer"); | |||||
VNET_DEFINE(int, tcp_autorcvbuf_max) = 2*1024*1024; | VNET_DEFINE(int, tcp_autorcvbuf_max) = 2*1024*1024; | ||||
SYSCTL_INT(_net_inet_tcp, OID_AUTO, recvbuf_max, CTLFLAG_VNET | CTLFLAG_RW, | SYSCTL_INT(_net_inet_tcp, OID_AUTO, recvbuf_max, CTLFLAG_VNET | CTLFLAG_RW, | ||||
&VNET_NAME(tcp_autorcvbuf_max), 0, | &VNET_NAME(tcp_autorcvbuf_max), 0, | ||||
"Max size of automatic receive buffer"); | "Max size of automatic receive buffer"); | ||||
VNET_DEFINE(struct inpcbhead, tcb); | VNET_DEFINE(struct inpcbhead, tcb); | ||||
#define tcb6 tcb /* for KAME src sync over BSD*'s */ | #define tcb6 tcb /* for KAME src sync over BSD*'s */ | ||||
VNET_DEFINE(struct inpcbinfo, tcbinfo); | VNET_DEFINE(struct inpcbinfo, tcbinfo); | ||||
▲ Show 20 Lines • Show All 1,233 Lines • ▼ Show 20 Lines | |||||
* later. Setting the buffer size too big may only consume too | * later. Setting the buffer size too big may only consume too | ||||
* much kernel memory if the application doesn't read() from | * much kernel memory if the application doesn't read() from | ||||
* the socket or packet loss or reordering makes use of the | * the socket or packet loss or reordering makes use of the | ||||
* reassembly queue. | * reassembly queue. | ||||
* | * | ||||
* The criteria to step up the receive buffer one notch are: | * The criteria to step up the receive buffer one notch are: | ||||
* 1. Application has not set receive buffer size with | * 1. Application has not set receive buffer size with | ||||
* SO_RCVBUF. Setting SO_RCVBUF clears SB_AUTOSIZE. | * SO_RCVBUF. Setting SO_RCVBUF clears SB_AUTOSIZE. | ||||
* 2. the number of bytes received during the time it takes | * 2. the number of bytes received during 1/2 of an sRTT | ||||
* one timestamp to be reflected back to us (the RTT); | * is at least 3/8 of the current socket buffer size. | ||||
* 3. received bytes per RTT is within seven eighth of the | * 3. receive buffer size has not hit maximal automatic size; | ||||
* current socket buffer size; | |||||
* 4. receive buffer size has not hit maximal automatic size; | |||||
* | * | ||||
* This algorithm does one step per RTT at most and only if | * If all of the criteria are met we increaset the socket buffer | ||||
* by a 1/2 (bounded by the max). This allows us to keep ahead | |||||
* of slow-start but also makes it so our peer never gets limited | |||||
* by our rwnd which we then open up causing a burst. | |||||
* | |||||
* This algorithm does two steps per RTT at most and only if | |||||
* we receive a bulk stream w/o packet losses or reorderings. | * we receive a bulk stream w/o packet losses or reorderings. | ||||
* Shrinking the buffer during idle times is not necessary as | * Shrinking the buffer during idle times is not necessary as | ||||
* it doesn't consume any memory when idle. | * it doesn't consume any memory when idle. | ||||
* | * | ||||
* TODO: Only step up if the application is actually serving | * TODO: Only step up if the application is actually serving | ||||
* the buffer to better manage the socket buffer resources. | * the buffer to better manage the socket buffer resources. | ||||
*/ | */ | ||||
int | int | ||||
tcp_autorcvbuf(struct mbuf *m, struct tcphdr *th, struct socket *so, | tcp_autorcvbuf(struct mbuf *m, struct tcphdr *th, struct socket *so, | ||||
struct tcpcb *tp, int tlen) | struct tcpcb *tp, int tlen) | ||||
{ | { | ||||
int newsize = 0; | int newsize = 0; | ||||
if (V_tcp_do_autorcvbuf && (so->so_rcv.sb_flags & SB_AUTOSIZE) && | if (V_tcp_do_autorcvbuf && (so->so_rcv.sb_flags & SB_AUTOSIZE) && | ||||
tp->t_srtt != 0 && tp->rfbuf_ts != 0 && | tp->t_srtt != 0 && tp->rfbuf_ts != 0 && | ||||
TCP_TS_TO_TICKS(tcp_ts_getticks() - tp->rfbuf_ts) > | TCP_TS_TO_TICKS(tcp_ts_getticks() - tp->rfbuf_ts) > | ||||
(tp->t_srtt >> TCP_RTT_SHIFT)) { | ((tp->t_srtt >> TCP_RTT_SHIFT)/2)) { | ||||
if (tp->rfbuf_cnt > (so->so_rcv.sb_hiwat / 8 * 7) && | if (tp->rfbuf_cnt > ((so->so_rcv.sb_hiwat / 2)/ 4 * 3) && | ||||
so->so_rcv.sb_hiwat < V_tcp_autorcvbuf_max) { | so->so_rcv.sb_hiwat < V_tcp_autorcvbuf_max) { | ||||
newsize = min(so->so_rcv.sb_hiwat + | newsize = min((so->so_rcv.sb_hiwat + (so->so_rcv.sb_hiwat/2)), V_tcp_autorcvbuf_max); | ||||
V_tcp_autorcvbuf_inc, V_tcp_autorcvbuf_max); | |||||
} | } | ||||
TCP_PROBE6(receive__autoresize, NULL, tp, m, tp, th, newsize); | TCP_PROBE6(receive__autoresize, NULL, tp, m, tp, th, newsize); | ||||
/* Start over with next RTT. */ | /* Start over with next RTT. */ | ||||
tp->rfbuf_ts = 0; | tp->rfbuf_ts = 0; | ||||
tp->rfbuf_cnt = 0; | tp->rfbuf_cnt = 0; | ||||
} else { | } else { | ||||
tp->rfbuf_cnt += tlen; /* add up */ | tp->rfbuf_cnt += tlen; /* add up */ | ||||
▲ Show 20 Lines • Show All 2,316 Lines • Show Last 20 Lines |