1*5952Swnj /* tcp_timer.c 4.15 82/02/25 */ 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 { 535069Swnj register struct inpcb *ip; 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 } 675245Sroot for (; ip != &tcb; ip = ip->inp_next) { 685069Swnj tp = intotcpcb(ip); 695260Swnj if (tp == 0) 705260Swnj continue; 715075Swnj for (i = 0; i < TCPT_NTIMERS; i++) { 725089Swnj 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); 765069Swnj } 775165Swnj tp->t_idle++; 785165Swnj if (tp->t_rtt) 795165Swnj tp->t_rtt++; 805069Swnj } 815075Swnj tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */ 825069Swnj splx(s); 835069Swnj } 845069Swnj 855069Swnj /* 865075Swnj * Cancel all timers for TCP tp. 875069Swnj */ 885089Swnj tcp_canceltimers(tp) 895069Swnj struct tcpcb *tp; 905069Swnj { 915069Swnj register int i; 925069Swnj 935089Swnj COUNT(TCP_CANCELTIMERS); 945075Swnj for (i = 0; i < TCPT_NTIMERS; i++) 955075Swnj tp->t_timer[i] = 0; 965069Swnj } 975069Swnj 98*5952Swnj int tcprexmtprint; 995069Swnj /* 1005165Swnj * TCP timer processing. 1015069Swnj */ 1025075Swnj tcp_timers(tp, timer) 1035069Swnj register struct tcpcb *tp; 1045075Swnj int timer; 1055069Swnj { 1065069Swnj 1075069Swnj COUNT(TCP_TIMERS); 1085089Swnj switch (timer) { 1095069Swnj 1105165Swnj /* 1115165Swnj * 2 MSL timeout in shutdown went off. Delete connection 1125165Swnj * control block. 1135165Swnj */ 1145075Swnj case TCPT_2MSL: 1155075Swnj tcp_close(tp); 1165075Swnj return; 1175069Swnj 1185165Swnj /* 1195165Swnj * Retransmission timer went off. Message has not 1205165Swnj * been acked within retransmit interval. Back off 1215165Swnj * to a longer retransmit interval and retransmit all 1225165Swnj * unacknowledged messages in the window. 1235165Swnj */ 1245075Swnj case TCPT_REXMT: 1255165Swnj tp->t_rxtshift++; 1265691Swnj if (tp->t_rxtshift > TCP_MAXRXTSHIFT) { 1275691Swnj tcp_drop(tp, ETIMEDOUT); 1285691Swnj return; 1295691Swnj } 1305165Swnj TCPT_RANGESET(tp->t_timer[TCPT_REXMT], 131*5952Swnj (int)tp->t_srtt, TCPTV_MIN, TCPTV_MAX); 1325284Sroot TCPT_RANGESET(tp->t_timer[TCPT_REXMT], 1335284Sroot tp->t_timer[TCPT_REXMT] << tp->t_rxtshift, 1345284Sroot TCPTV_MIN, TCPTV_MAX); 135*5952Swnj if (tcprexmtprint) 136*5952Swnj printf("rexmt set to %d\n", tp->t_timer[TCPT_REXMT]); 1375165Swnj tp->snd_nxt = tp->snd_una; 1385165Swnj /* this only transmits one segment! */ 1395165Swnj (void) tcp_output(tp); 1405075Swnj return; 1415069Swnj 1425165Swnj /* 1435165Swnj * Persistance timer into zero window. 1445165Swnj * Force a byte to be output, if possible. 1455165Swnj */ 1465075Swnj case TCPT_PERSIST: 1475165Swnj tp->t_force = 1; 1485165Swnj (void) tcp_output(tp); 1495165Swnj tp->t_force = 0; 1505165Swnj TCPT_RANGESET(tp->t_timer[TCPT_PERSIST], 151*5952Swnj tcp_beta * tp->t_srtt, TCPTV_PERSMIN, TCPTV_MAX); 1525089Swnj return; 1535069Swnj 1545165Swnj /* 1555165Swnj * Keep-alive timer went off; send something 1565165Swnj * or drop connection if idle for too long. 1575165Swnj */ 1585075Swnj case TCPT_KEEP: 1595165Swnj if (tp->t_state < TCPS_ESTABLISHED || 1605165Swnj tp->t_idle >= TCPTV_MAXIDLE) { 1615165Swnj tcp_drop(tp, ETIMEDOUT); 1625165Swnj return; 1635165Swnj } 1645392Swnj if (tp->t_inpcb->inp_socket->so_options & SO_NOKEEPALIVE) 1655392Swnj tp->t_idle = 0; 1665392Swnj else 1675392Swnj tcp_respond(tp, 1685392Swnj tp->t_template, tp->rcv_nxt, tp->snd_una-1, 0); 1695165Swnj tp->t_timer[TCPT_KEEP] = TCPTV_KEEP; 1705075Swnj return; 1715442Swnj 1725442Swnj #ifdef TCPTRUEOOB 1735442Swnj /* 1745442Swnj * Out-of-band data retransmit timer. 1755442Swnj */ 1765442Swnj case TCPT_OOBREXMT: 1775442Swnj if (tp->t_flags & TF_NOOPT) 1785442Swnj return; 1795442Swnj (void) tcp_output(tp); 1805442Swnj TCPT_RANGESET(tp->t_timer[TCPT_OOBREXMT], 1815442Swnj 2 * tp->t_srtt, TCPTV_MIN, TCPTV_MAX); 1825442Swnj return; 1835442Swnj #endif 1845069Swnj } 1855069Swnj } 186