1*5691Swnj /* tcp_timer.c 4.14 82/02/03 */ 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 34*5691Swnj inp = tcb.inp_next; 35*5691Swnj if (inp) 36*5691Swnj 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 985069Swnj /* 995165Swnj * TCP timer processing. 1005069Swnj */ 1015075Swnj tcp_timers(tp, timer) 1025069Swnj register struct tcpcb *tp; 1035075Swnj int timer; 1045069Swnj { 1055069Swnj 1065069Swnj COUNT(TCP_TIMERS); 1075089Swnj switch (timer) { 1085069Swnj 1095165Swnj /* 1105165Swnj * 2 MSL timeout in shutdown went off. Delete connection 1115165Swnj * control block. 1125165Swnj */ 1135075Swnj case TCPT_2MSL: 1145075Swnj tcp_close(tp); 1155075Swnj return; 1165069Swnj 1175165Swnj /* 1185165Swnj * Retransmission timer went off. Message has not 1195165Swnj * been acked within retransmit interval. Back off 1205165Swnj * to a longer retransmit interval and retransmit all 1215165Swnj * unacknowledged messages in the window. 1225165Swnj */ 1235075Swnj case TCPT_REXMT: 1245165Swnj tp->t_rxtshift++; 125*5691Swnj if (tp->t_rxtshift > TCP_MAXRXTSHIFT) { 126*5691Swnj tcp_drop(tp, ETIMEDOUT); 127*5691Swnj return; 128*5691Swnj } 1295165Swnj TCPT_RANGESET(tp->t_timer[TCPT_REXMT], 1305284Sroot ((int)(2 * tp->t_srtt)), 1315165Swnj 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); 1355572Swnj /* printf("rexmt set to %d\n", tp->t_timer[TCPT_REXMT]); */ 1365165Swnj tp->snd_nxt = tp->snd_una; 1375165Swnj /* this only transmits one segment! */ 1385165Swnj (void) tcp_output(tp); 1395075Swnj return; 1405069Swnj 1415165Swnj /* 1425165Swnj * Persistance timer into zero window. 1435165Swnj * Force a byte to be output, if possible. 1445165Swnj */ 1455075Swnj case TCPT_PERSIST: 1465165Swnj tp->t_force = 1; 1475165Swnj (void) tcp_output(tp); 1485165Swnj tp->t_force = 0; 1495165Swnj TCPT_RANGESET(tp->t_timer[TCPT_PERSIST], 1505165Swnj 2 * tp->t_srtt, TCPTV_PERSMIN, TCPTV_MAX); 1515089Swnj return; 1525069Swnj 1535165Swnj /* 1545165Swnj * Keep-alive timer went off; send something 1555165Swnj * or drop connection if idle for too long. 1565165Swnj */ 1575075Swnj case TCPT_KEEP: 1585165Swnj if (tp->t_state < TCPS_ESTABLISHED || 1595165Swnj tp->t_idle >= TCPTV_MAXIDLE) { 1605165Swnj tcp_drop(tp, ETIMEDOUT); 1615165Swnj return; 1625165Swnj } 1635392Swnj if (tp->t_inpcb->inp_socket->so_options & SO_NOKEEPALIVE) 1645392Swnj tp->t_idle = 0; 1655392Swnj else 1665392Swnj tcp_respond(tp, 1675392Swnj tp->t_template, tp->rcv_nxt, tp->snd_una-1, 0); 1685165Swnj tp->t_timer[TCPT_KEEP] = TCPTV_KEEP; 1695075Swnj return; 1705442Swnj 1715442Swnj #ifdef TCPTRUEOOB 1725442Swnj /* 1735442Swnj * Out-of-band data retransmit timer. 1745442Swnj */ 1755442Swnj case TCPT_OOBREXMT: 1765442Swnj if (tp->t_flags & TF_NOOPT) 1775442Swnj return; 1785442Swnj (void) tcp_output(tp); 1795442Swnj TCPT_RANGESET(tp->t_timer[TCPT_OOBREXMT], 1805442Swnj 2 * tp->t_srtt, TCPTV_MIN, TCPTV_MAX); 1815442Swnj return; 1825442Swnj #endif 1835069Swnj } 1845069Swnj } 185