1*8404Swnj /* tcp_timer.c 4.26 82/10/09 */ 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" 9*8404Swnj #include "../netinet/in.h" 106353Ssam #include "../net/route.h" 11*8404Swnj #include "../netinet/in_pcb.h" 12*8404Swnj #include "../netinet/in_systm.h" 135069Swnj #include "../net/if.h" 14*8404Swnj #include "../netinet/ip.h" 15*8404Swnj #include "../netinet/ip_var.h" 16*8404Swnj #include "../netinet/tcp.h" 17*8404Swnj #include "../netinet/tcp_fsm.h" 18*8404Swnj #include "../netinet/tcp_seq.h" 19*8404Swnj #include "../netinet/tcp_timer.h" 20*8404Swnj #include "../netinet/tcp_var.h" 21*8404Swnj #include "../netinet/tcpip.h" 227302Ssam #include <errno.h> 235069Swnj 245442Swnj int tcpnodelack = 0; 255069Swnj /* 265069Swnj * Fast timeout routine for processing delayed acks 275069Swnj */ 285069Swnj tcp_fasttimo() 295069Swnj { 305284Sroot register struct inpcb *inp; 315284Sroot register struct tcpcb *tp; 325284Sroot int s = splnet(); 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; 575069Swnj 585069Swnj /* 595069Swnj * Search through tcb's and update active timers. 605069Swnj */ 615245Sroot ip = tcb.inp_next; 625245Sroot if (ip == 0) { 635245Sroot splx(s); 645245Sroot return; 655245Sroot } 666212Swnj while (ip != &tcb) { 675069Swnj tp = intotcpcb(ip); 685260Swnj if (tp == 0) 695260Swnj continue; 706212Swnj ipnxt = ip->inp_next; 715075Swnj for (i = 0; i < TCPT_NTIMERS; i++) { 726212Swnj if (tp->t_timer[i] && --tp->t_timer[i] == 0) { 735069Swnj (void) tcp_usrreq(tp->t_inpcb->inp_socket, 745069Swnj PRU_SLOWTIMO, (struct mbuf *)0, 755069Swnj (caddr_t)i); 766212Swnj if (ipnxt->inp_prev != ip) 776212Swnj goto tpgone; 786212Swnj } 795069Swnj } 805165Swnj tp->t_idle++; 815165Swnj if (tp->t_rtt) 825165Swnj tp->t_rtt++; 836212Swnj tpgone: 846212Swnj ip = ipnxt; 855069Swnj } 865075Swnj tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */ 875069Swnj splx(s); 885069Swnj } 895069Swnj 905069Swnj /* 915075Swnj * Cancel all timers for TCP tp. 925069Swnj */ 935089Swnj tcp_canceltimers(tp) 945069Swnj struct tcpcb *tp; 955069Swnj { 965069Swnj register int i; 975069Swnj 985075Swnj for (i = 0; i < TCPT_NTIMERS; i++) 995075Swnj tp->t_timer[i] = 0; 1005069Swnj } 1015069Swnj 1026474Sroot float tcp_backoff[TCP_MAXRXTSHIFT] = 1036474Sroot { 1.0, 1.2, 1.4, 1.7, 2.0, 3.0, 5.0, 8.0, 16.0, 32.0 }; 1046474Sroot int tcprexmtprint = 0; 1056474Sroot int tcpexprexmtbackoff = 0; 1065069Swnj /* 1075165Swnj * TCP timer processing. 1085069Swnj */ 1095075Swnj tcp_timers(tp, timer) 1105069Swnj register struct tcpcb *tp; 1115075Swnj int timer; 1125069Swnj { 1135069Swnj 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); 1386474Sroot if (tcpexprexmtbackoff) { 1396474Sroot TCPT_RANGESET(tp->t_timer[TCPT_REXMT], 1406474Sroot tp->t_timer[TCPT_REXMT] << tp->t_rxtshift, 1416474Sroot TCPTV_MIN, TCPTV_MAX); 1426474Sroot } else { 1436474Sroot TCPT_RANGESET(tp->t_timer[TCPT_REXMT], 1446474Sroot tp->t_timer[TCPT_REXMT] * 1456474Sroot tcp_backoff[tp->t_rxtshift - 1], 1466474Sroot TCPTV_MIN, TCPTV_MAX); 1476474Sroot } 1485952Swnj if (tcprexmtprint) 1495952Swnj printf("rexmt set to %d\n", tp->t_timer[TCPT_REXMT]); 1505165Swnj tp->snd_nxt = tp->snd_una; 1515165Swnj /* this only transmits one segment! */ 1525165Swnj (void) tcp_output(tp); 1535075Swnj return; 1545069Swnj 1555165Swnj /* 1565165Swnj * Persistance timer into zero window. 1575165Swnj * Force a byte to be output, if possible. 1585165Swnj */ 1595075Swnj case TCPT_PERSIST: 1607156Swnj tcp_setpersist(tp); 1615165Swnj tp->t_force = 1; 1625165Swnj (void) tcp_output(tp); 1635165Swnj tp->t_force = 0; 1645089Swnj return; 1655069Swnj 1665165Swnj /* 1675165Swnj * Keep-alive timer went off; send something 1685165Swnj * or drop connection if idle for too long. 1695165Swnj */ 1705075Swnj case TCPT_KEEP: 1716304Sroot if (tp->t_state < TCPS_ESTABLISHED) 1726304Sroot goto dropit; 1736267Sroot if (tp->t_inpcb->inp_socket->so_options & SO_KEEPALIVE) { 1746304Sroot if (tp->t_idle >= TCPTV_MAXIDLE) 1756304Sroot goto dropit; 1766267Sroot /* 1776267Sroot * Saying tp->rcv_nxt-1 lies about what 1786267Sroot * we have received, and by the protocol spec 1796267Sroot * requires the correspondent TCP to respond. 1806267Sroot * Saying tp->snd_una-1 causes the transmitted 1816267Sroot * byte to lie outside the receive window; this 1826267Sroot * is important because we don't necessarily 1836267Sroot * have a byte in the window to send (consider 1846267Sroot * a one-way stream!) 1856267Sroot */ 1865392Swnj tcp_respond(tp, 1876267Sroot tp->t_template, tp->rcv_nxt-1, tp->snd_una-1, 0); 1886267Sroot } else 1896212Swnj tp->t_idle = 0; 1905165Swnj tp->t_timer[TCPT_KEEP] = TCPTV_KEEP; 1915075Swnj return; 1926304Sroot dropit: 1936304Sroot tcp_drop(tp, ETIMEDOUT); 1946304Sroot return; 1955069Swnj } 1965069Swnj } 197