/* * Tcp protocol timeout routine called every 500 ms. * Updates timestamps used for TCP * causes finite state machine actions if timers expire. */ void tcp_slowtimo(void) { VNET_ITERATOR_DECL(vnet_iter); VNET_LIST_RLOCK_NOSLEEP(); VNET_FOREACH(vnet_iter) { CURVNET_SET(vnet_iter); (void) tcp_tw_2msl_scan(0); CURVNET_RESTORE(); } VNET_LIST_RUNLOCK_NOSLEEP(); }
/* * Tcp protocol timeout routine called every 500 ms. * Updates timestamps used for TCP * causes finite state machine actions if timers expire. */ void tcp_slowtimo(void) { VNET_ITERATOR_DECL(vnet_iter); VNET_LIST_RLOCK_NOSLEEP(); VNET_FOREACH(vnet_iter) { CURVNET_SET(vnet_iter); tcp_maxidle = tcp_keepcnt * tcp_keepintvl; INP_INFO_WLOCK(&V_tcbinfo); (void) tcp_tw_2msl_scan(0); INP_INFO_WUNLOCK(&V_tcbinfo); CURVNET_RESTORE(); } VNET_LIST_RUNLOCK_NOSLEEP(); }
/* * Move a TCP connection into TIME_WAIT state. * tcbinfo is locked. * inp is locked, and is unlocked before returning. */ void tcp_twstart(struct tcpcb *tp) { struct tcptw *tw; struct inpcb *inp = tp->t_inpcb; int acknow; struct socket *so; #ifdef INET6 //ScenSim-Port// int isipv6 = inp->inp_inc.inc_flags & INC_ISIPV6; #endif //ScenSim-Port// INP_INFO_WLOCK_ASSERT(&V_tcbinfo); /* tcp_tw_2msl_reset(). */ //ScenSim-Port// INP_WLOCK_ASSERT(inp); //ScenSim-Port// if (V_nolocaltimewait) { //ScenSim-Port// int error = 0; //ScenSim-Port//#ifdef INET6 //ScenSim-Port// if (isipv6) //ScenSim-Port// error = in6_localaddr(&inp->in6p_faddr); //ScenSim-Port//#endif //ScenSim-Port//#if defined(INET6) && defined(INET) //ScenSim-Port// else //ScenSim-Port//#endif //ScenSim-Port//#ifdef INET //ScenSim-Port// error = in_localip(inp->inp_faddr); //ScenSim-Port//#endif //ScenSim-Port// if (error) { //ScenSim-Port// tp = tcp_close(tp); //ScenSim-Port// if (tp != NULL) //ScenSim-Port// INP_WUNLOCK(inp); //ScenSim-Port// return; //ScenSim-Port// } //ScenSim-Port// } //ScenSim-Port// tw = uma_zalloc(V_tcptw_zone, M_NOWAIT); tw = (struct tcptw *)uma_zalloc(V_tcptw_zone, M_NOWAIT); //ScenSim-Port// if (tw == NULL) { tw = tcp_tw_2msl_scan(1); if (tw == NULL) { tp = tcp_close(tp); //ScenSim-Port// if (tp != NULL) //ScenSim-Port// INP_WUNLOCK(inp); return; } } tw->tw_inpcb = inp; /* * Recover last window size sent. */ //ScenSim-Port// KASSERT(SEQ_GEQ(tp->rcv_adv, tp->rcv_nxt), //ScenSim-Port// ("tcp_twstart negative window: tp %p rcv_nxt %u rcv_adv %u", tp, //ScenSim-Port// tp->rcv_nxt, tp->rcv_adv)); tw->last_win = (tp->rcv_adv - tp->rcv_nxt) >> tp->rcv_scale; /* * Set t_recent if timestamps are used on the connection. */ if ((tp->t_flags & (TF_REQ_TSTMP|TF_RCVD_TSTMP|TF_NOOPT)) == (TF_REQ_TSTMP|TF_RCVD_TSTMP)) { tw->t_recent = tp->ts_recent; tw->ts_offset = tp->ts_offset; } else { tw->t_recent = 0; tw->ts_offset = 0; } tw->snd_nxt = tp->snd_nxt; tw->rcv_nxt = tp->rcv_nxt; tw->iss = tp->iss; tw->irs = tp->irs; tw->t_starttime = tp->t_starttime; tw->tw_time = 0; /* XXX * If this code will * be used for fin-wait-2 state also, then we may need * a ts_recent from the last segment. */ acknow = tp->t_flags & TF_ACKNOW; /* * First, discard tcpcb state, which includes stopping its timers and * freeing it. tcp_discardcb() used to also release the inpcb, but * that work is now done in the caller. * * Note: soisdisconnected() call used to be made in tcp_discardcb(), * and might not be needed here any longer. */ tcp_discardcb(tp); so = inp->inp_socket; soisdisconnected(so); //ScenSim-Port// tw->tw_cred = crhold(so->so_cred); //ScenSim-Port// SOCK_LOCK(so); tw->tw_so_options = so->so_options; //ScenSim-Port// SOCK_UNLOCK(so); if (acknow) tcp_twrespond(tw, TH_ACK); inp->inp_ppcb = tw; inp->inp_flags |= INP_TIMEWAIT; tcp_tw_2msl_reset(tw, 0); /* * If the inpcb owns the sole reference to the socket, then we can * detach and free the socket as it is not needed in time wait. */ if (inp->inp_flags & INP_SOCKREF) { //ScenSim-Port// KASSERT(so->so_state & SS_PROTOREF, //ScenSim-Port// ("tcp_twstart: !SS_PROTOREF")); inp->inp_flags &= ~INP_SOCKREF; //ScenSim-Port// INP_WUNLOCK(inp); //ScenSim-Port// ACCEPT_LOCK(); //ScenSim-Port// SOCK_LOCK(so); so->so_state &= ~SS_PROTOREF; sofree(so); } else //ScenSim-Port// INP_WUNLOCK(inp); ; //ScenSim-Port// }