Changeset View
Changeset View
Standalone View
Standalone View
head/sys/netinet/tcp_timewait.c
Show First 20 Lines • Show All 224 Lines • ▼ Show 20 Lines | |||||
* inp is locked, and is unlocked before returning. | * inp is locked, and is unlocked before returning. | ||||
*/ | */ | ||||
void | void | ||||
tcp_twstart(struct tcpcb *tp) | tcp_twstart(struct tcpcb *tp) | ||||
{ | { | ||||
struct tcptw twlocal, *tw; | struct tcptw twlocal, *tw; | ||||
struct inpcb *inp = tp->t_inpcb; | struct inpcb *inp = tp->t_inpcb; | ||||
struct socket *so; | struct socket *so; | ||||
uint32_t recwin; | |||||
bool acknow, local; | bool acknow, local; | ||||
#ifdef INET6 | #ifdef INET6 | ||||
bool isipv6 = inp->inp_inc.inc_flags & INC_ISIPV6; | bool isipv6 = inp->inp_inc.inc_flags & INC_ISIPV6; | ||||
#endif | #endif | ||||
INP_INFO_RLOCK_ASSERT(&V_tcbinfo); | INP_INFO_RLOCK_ASSERT(&V_tcbinfo); | ||||
INP_WLOCK_ASSERT(inp); | INP_WLOCK_ASSERT(inp); | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | #endif | ||||
* For !local case the tcptw will hold a reference on its inpcb | * For !local case the tcptw will hold a reference on its inpcb | ||||
* until tcp_twclose is called. | * until tcp_twclose is called. | ||||
*/ | */ | ||||
tw->tw_inpcb = inp; | tw->tw_inpcb = inp; | ||||
/* | /* | ||||
* Recover last window size sent. | * Recover last window size sent. | ||||
*/ | */ | ||||
if (SEQ_GT(tp->rcv_adv, tp->rcv_nxt)) | so = inp->inp_socket; | ||||
tw->last_win = (tp->rcv_adv - tp->rcv_nxt) >> tp->rcv_scale; | recwin = lmin(lmax(sbspace(&so->so_rcv), 0), | ||||
else | (long)TCP_MAXWIN << tp->rcv_scale); | ||||
tw->last_win = 0; | if (recwin < (so->so_rcv.sb_hiwat / 4) && | ||||
recwin < tp->t_maxseg) | |||||
recwin = 0; | |||||
if (SEQ_GT(tp->rcv_adv, tp->rcv_nxt) && | |||||
recwin < (tp->rcv_adv - tp->rcv_nxt)) | |||||
recwin = (tp->rcv_adv - tp->rcv_nxt); | |||||
tw->last_win = htons((u_short)(recwin >> tp->rcv_scale)); | |||||
/* | /* | ||||
* Set t_recent if timestamps are used on the connection. | * Set t_recent if timestamps are used on the connection. | ||||
*/ | */ | ||||
if ((tp->t_flags & (TF_REQ_TSTMP|TF_RCVD_TSTMP|TF_NOOPT)) == | if ((tp->t_flags & (TF_REQ_TSTMP|TF_RCVD_TSTMP|TF_NOOPT)) == | ||||
(TF_REQ_TSTMP|TF_RCVD_TSTMP)) { | (TF_REQ_TSTMP|TF_RCVD_TSTMP)) { | ||||
tw->t_recent = tp->ts_recent; | tw->t_recent = tp->ts_recent; | ||||
tw->ts_offset = tp->ts_offset; | tw->ts_offset = tp->ts_offset; | ||||
Show All 20 Lines | */ | ||||
* First, discard tcpcb state, which includes stopping its timers and | * First, discard tcpcb state, which includes stopping its timers and | ||||
* freeing it. tcp_discardcb() used to also release the inpcb, but | * freeing it. tcp_discardcb() used to also release the inpcb, but | ||||
* that work is now done in the caller. | * that work is now done in the caller. | ||||
* | * | ||||
* Note: soisdisconnected() call used to be made in tcp_discardcb(), | * Note: soisdisconnected() call used to be made in tcp_discardcb(), | ||||
* and might not be needed here any longer. | * and might not be needed here any longer. | ||||
*/ | */ | ||||
tcp_discardcb(tp); | tcp_discardcb(tp); | ||||
so = inp->inp_socket; | |||||
soisdisconnected(so); | soisdisconnected(so); | ||||
tw->tw_so_options = so->so_options; | tw->tw_so_options = so->so_options; | ||||
inp->inp_flags |= INP_TIMEWAIT; | inp->inp_flags |= INP_TIMEWAIT; | ||||
if (acknow) | if (acknow) | ||||
tcp_twrespond(tw, TH_ACK); | tcp_twrespond(tw, TH_ACK); | ||||
if (local) | if (local) | ||||
in_pcbdrop(inp); | in_pcbdrop(inp); | ||||
else { | else { | ||||
▲ Show 20 Lines • Show All 420 Lines • Show Last 20 Lines |