1*6267Sroot /* tcp_timer.c 4.17 82/03/19 */ 25069Swnj 35069Swnj #include "../h/param.h" 45069Swnj #include "../h/systm.h" 55069Swnj #include "../h/mbuf.h" 65069Swnj #include "../h/socket.h" 75069Swnj #include "../h/socketvar.h" 85069Swnj #include "../h/protosw.h" 95089Swnj #include "../net/in.h" 105089Swnj #include "../net/in_pcb.h" 115089Swnj #include "../net/in_systm.h" 125069Swnj #include "../net/if.h" 135069Swnj #include "../net/ip.h" 145069Swnj #include "../net/ip_var.h" 155069Swnj #include "../net/tcp.h" 165069Swnj #include "../net/tcp_fsm.h" 175089Swnj #include "../net/tcp_seq.h" 185089Swnj #include "../net/tcp_timer.h" 195069Swnj #include "../net/tcp_var.h" 205089Swnj #include "../net/tcpip.h" 215112Swnj #include "../errno.h" 225069Swnj 235442Swnj int tcpnodelack = 0; 245069Swnj /* 255069Swnj * Fast timeout routine for processing delayed acks 265069Swnj */ 275069Swnj tcp_fasttimo() 285069Swnj { 295284Sroot register struct inpcb *inp; 305284Sroot register struct tcpcb *tp; 315284Sroot int s = splnet(); 325284Sroot COUNT(TCP_FASTTIMO); 335069Swnj 345691Swnj inp = tcb.inp_next; 355691Swnj if (inp) 365691Swnj for (; inp != &tcb; inp = inp->inp_next) 375284Sroot if ((tp = (struct tcpcb *)inp->inp_ppcb) && 385284Sroot (tp->t_flags & TF_DELACK)) { 395284Sroot tp->t_flags &= ~TF_DELACK; 405284Sroot tp->t_flags |= TF_ACKNOW; 415284Sroot (void) tcp_output(tp); 425284Sroot } 435284Sroot splx(s); 445069Swnj } 455069Swnj 465069Swnj /* 475069Swnj * Tcp protocol timeout routine called every 500 ms. 485069Swnj * Updates the timers in all active tcb's and 495069Swnj * causes finite state machine actions if timers expire. 505069Swnj */ 515069Swnj tcp_slowtimo() 525069Swnj { 536212Swnj register struct inpcb *ip, *ipnxt; 545069Swnj register struct tcpcb *tp; 555069Swnj int s = splnet(); 565069Swnj register int i; 575089Swnj COUNT(TCP_SLOWTIMO); 585069Swnj 595069Swnj /* 605069Swnj * Search through tcb's and update active timers. 615069Swnj */ 625245Sroot ip = tcb.inp_next; 635245Sroot if (ip == 0) { 645245Sroot splx(s); 655245Sroot return; 665245Sroot } 676212Swnj while (ip != &tcb) { 685069Swnj tp = intotcpcb(ip); 695260Swnj if (tp == 0) 705260Swnj continue; 716212Swnj ipnxt = ip->inp_next; 725075Swnj for (i = 0; i < TCPT_NTIMERS; i++) { 736212Swnj if (tp->t_timer[i] && --tp->t_timer[i] == 0) { 745069Swnj (void) tcp_usrreq(tp->t_inpcb->inp_socket, 755069Swnj PRU_SLOWTIMO, (struct mbuf *)0, 765069Swnj (caddr_t)i); 776212Swnj if (ipnxt->inp_prev != ip) 786212Swnj goto tpgone; 796212Swnj } 805069Swnj } 815165Swnj tp->t_idle++; 825165Swnj if (tp->t_rtt) 835165Swnj tp->t_rtt++; 846212Swnj tpgone: 856212Swnj ip = ipnxt; 865069Swnj } 875075Swnj tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */ 885069Swnj splx(s); 895069Swnj } 905069Swnj 915069Swnj /* 925075Swnj * Cancel all timers for TCP tp. 935069Swnj */ 945089Swnj tcp_canceltimers(tp) 955069Swnj struct tcpcb *tp; 965069Swnj { 975069Swnj register int i; 985069Swnj 995089Swnj COUNT(TCP_CANCELTIMERS); 1005075Swnj for (i = 0; i < TCPT_NTIMERS; i++) 1015075Swnj tp->t_timer[i] = 0; 1025069Swnj } 1035069Swnj 1045952Swnj int tcprexmtprint; 1055069Swnj /* 1065165Swnj * TCP timer processing. 1075069Swnj */ 1085075Swnj tcp_timers(tp, timer) 1095069Swnj register struct tcpcb *tp; 1105075Swnj int timer; 1115069Swnj { 1125069Swnj 1135069Swnj COUNT(TCP_TIMERS); 1145089Swnj switch (timer) { 1155069Swnj 1165165Swnj /* 1175165Swnj * 2 MSL timeout in shutdown went off. Delete connection 1185165Swnj * control block. 1195165Swnj */ 1205075Swnj case TCPT_2MSL: 1215075Swnj tcp_close(tp); 1225075Swnj return; 1235069Swnj 1245165Swnj /* 1255165Swnj * Retransmission timer went off. Message has not 1265165Swnj * been acked within retransmit interval. Back off 1275165Swnj * to a longer retransmit interval and retransmit all 1285165Swnj * unacknowledged messages in the window. 1295165Swnj */ 1305075Swnj case TCPT_REXMT: 1315165Swnj tp->t_rxtshift++; 1325691Swnj if (tp->t_rxtshift > TCP_MAXRXTSHIFT) { 1335691Swnj tcp_drop(tp, ETIMEDOUT); 1345691Swnj return; 1355691Swnj } 1365165Swnj TCPT_RANGESET(tp->t_timer[TCPT_REXMT], 1375952Swnj (int)tp->t_srtt, TCPTV_MIN, TCPTV_MAX); 1385284Sroot TCPT_RANGESET(tp->t_timer[TCPT_REXMT], 1395284Sroot tp->t_timer[TCPT_REXMT] << tp->t_rxtshift, 1405284Sroot TCPTV_MIN, TCPTV_MAX); 1415952Swnj if (tcprexmtprint) 1425952Swnj printf("rexmt set to %d\n", tp->t_timer[TCPT_REXMT]); 1435165Swnj tp->snd_nxt = tp->snd_una; 1445165Swnj /* this only transmits one segment! */ 1455165Swnj (void) tcp_output(tp); 1465075Swnj return; 1475069Swnj 1485165Swnj /* 1495165Swnj * Persistance timer into zero window. 1505165Swnj * Force a byte to be output, if possible. 1515165Swnj */ 1525075Swnj case TCPT_PERSIST: 1535165Swnj tp->t_force = 1; 1545165Swnj (void) tcp_output(tp); 1555165Swnj tp->t_force = 0; 1565165Swnj TCPT_RANGESET(tp->t_timer[TCPT_PERSIST], 1575952Swnj tcp_beta * tp->t_srtt, TCPTV_PERSMIN, TCPTV_MAX); 1585089Swnj return; 1595069Swnj 1605165Swnj /* 1615165Swnj * Keep-alive timer went off; send something 1625165Swnj * or drop connection if idle for too long. 1635165Swnj */ 1645075Swnj case TCPT_KEEP: 1655165Swnj if (tp->t_state < TCPS_ESTABLISHED || 1665165Swnj tp->t_idle >= TCPTV_MAXIDLE) { 1675165Swnj tcp_drop(tp, ETIMEDOUT); 1685165Swnj return; 1695165Swnj } 170*6267Sroot if (tp->t_inpcb->inp_socket->so_options & SO_KEEPALIVE) { 171*6267Sroot /* 172*6267Sroot * Saying tp->rcv_nxt-1 lies about what 173*6267Sroot * we have received, and by the protocol spec 174*6267Sroot * requires the correspondent TCP to respond. 175*6267Sroot * Saying tp->snd_una-1 causes the transmitted 176*6267Sroot * byte to lie outside the receive window; this 177*6267Sroot * is important because we don't necessarily 178*6267Sroot * have a byte in the window to send (consider 179*6267Sroot * a one-way stream!) 180*6267Sroot */ 1815392Swnj tcp_respond(tp, 182*6267Sroot tp->t_template, tp->rcv_nxt-1, tp->snd_una-1, 0); 183*6267Sroot } else 1846212Swnj tp->t_idle = 0; 1855165Swnj tp->t_timer[TCPT_KEEP] = TCPTV_KEEP; 1865075Swnj return; 1875442Swnj 1885442Swnj #ifdef TCPTRUEOOB 1895442Swnj /* 1905442Swnj * Out-of-band data retransmit timer. 1915442Swnj */ 1925442Swnj case TCPT_OOBREXMT: 1935442Swnj if (tp->t_flags & TF_NOOPT) 1945442Swnj return; 1955442Swnj (void) tcp_output(tp); 1965442Swnj TCPT_RANGESET(tp->t_timer[TCPT_OOBREXMT], 1975442Swnj 2 * tp->t_srtt, TCPTV_MIN, TCPTV_MAX); 1985442Swnj return; 1995442Swnj #endif 2005069Swnj } 2015069Swnj } 202