1*5284Sroot /* tcp_timer.c 4.10 81/12/21 */ 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 23*5284Sroot int tcpdelack = 0; 245069Swnj /* 255069Swnj * Fast timeout routine for processing delayed acks 265069Swnj */ 275069Swnj tcp_fasttimo() 285069Swnj { 29*5284Sroot register struct inpcb *inp; 30*5284Sroot register struct tcpcb *tp; 31*5284Sroot int s = splnet(); 32*5284Sroot COUNT(TCP_FASTTIMO); 335069Swnj 34*5284Sroot for (inp = tcb.inp_next; inp != &tcb; inp = inp->inp_next) 35*5284Sroot if ((tp = (struct tcpcb *)inp->inp_ppcb) && 36*5284Sroot (tp->t_flags & TF_DELACK)) { 37*5284Sroot tp->t_flags &= ~TF_DELACK; 38*5284Sroot tp->t_flags |= TF_ACKNOW; 39*5284Sroot (void) tcp_output(tp); 40*5284Sroot } 41*5284Sroot splx(s); 425069Swnj } 435069Swnj 445069Swnj /* 455069Swnj * Tcp protocol timeout routine called every 500 ms. 465069Swnj * Updates the timers in all active tcb's and 475069Swnj * causes finite state machine actions if timers expire. 485069Swnj */ 495069Swnj tcp_slowtimo() 505069Swnj { 515069Swnj register struct inpcb *ip; 525069Swnj register struct tcpcb *tp; 535069Swnj int s = splnet(); 545069Swnj register int i; 555089Swnj COUNT(TCP_SLOWTIMO); 565069Swnj 575069Swnj /* 585069Swnj * Search through tcb's and update active timers. 595069Swnj */ 605245Sroot ip = tcb.inp_next; 615245Sroot if (ip == 0) { 625245Sroot splx(s); 635245Sroot return; 645245Sroot } 655245Sroot for (; ip != &tcb; ip = ip->inp_next) { 665069Swnj tp = intotcpcb(ip); 675260Swnj if (tp == 0) 685260Swnj continue; 695075Swnj for (i = 0; i < TCPT_NTIMERS; i++) { 705089Swnj if (tp->t_timer[i] && --tp->t_timer[i] == 0) 715069Swnj (void) tcp_usrreq(tp->t_inpcb->inp_socket, 725069Swnj PRU_SLOWTIMO, (struct mbuf *)0, 735069Swnj (caddr_t)i); 745069Swnj } 755165Swnj tp->t_idle++; 765165Swnj if (tp->t_rtt) 775165Swnj tp->t_rtt++; 785069Swnj } 795075Swnj tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */ 805069Swnj splx(s); 815069Swnj } 825069Swnj 835069Swnj /* 845075Swnj * Cancel all timers for TCP tp. 855069Swnj */ 865089Swnj tcp_canceltimers(tp) 875069Swnj struct tcpcb *tp; 885069Swnj { 895069Swnj register int i; 905069Swnj 915089Swnj COUNT(TCP_CANCELTIMERS); 925075Swnj for (i = 0; i < TCPT_NTIMERS; i++) 935075Swnj tp->t_timer[i] = 0; 945069Swnj } 955069Swnj 965069Swnj /* 975165Swnj * TCP timer processing. 985069Swnj */ 995075Swnj tcp_timers(tp, timer) 1005069Swnj register struct tcpcb *tp; 1015075Swnj int timer; 1025069Swnj { 1035069Swnj 1045069Swnj COUNT(TCP_TIMERS); 1055089Swnj switch (timer) { 1065069Swnj 1075165Swnj /* 1085165Swnj * 2 MSL timeout in shutdown went off. Delete connection 1095165Swnj * control block. 1105165Swnj */ 1115075Swnj case TCPT_2MSL: 1125075Swnj tcp_close(tp); 1135075Swnj return; 1145069Swnj 1155165Swnj /* 1165165Swnj * Retransmission timer went off. Message has not 1175165Swnj * been acked within retransmit interval. Back off 1185165Swnj * to a longer retransmit interval and retransmit all 1195165Swnj * unacknowledged messages in the window. 1205165Swnj */ 1215075Swnj case TCPT_REXMT: 1225165Swnj tp->t_rxtshift++; 1235165Swnj TCPT_RANGESET(tp->t_timer[TCPT_REXMT], 124*5284Sroot ((int)(2 * tp->t_srtt)), 1255165Swnj TCPTV_MIN, TCPTV_MAX); 126*5284Sroot TCPT_RANGESET(tp->t_timer[TCPT_REXMT], 127*5284Sroot tp->t_timer[TCPT_REXMT] << tp->t_rxtshift, 128*5284Sroot TCPTV_MIN, TCPTV_MAX); 129*5284Sroot if (tp->t_timer[TCPT_REXMT] > TCPTV_MAXIDLE / 2) { 130*5284Sroot tcp_drop(tp, ETIMEDOUT); 131*5284Sroot return; 132*5284Sroot } 1335276Swnj printf("rexmt set to %d\n", tp->t_timer[TCPT_REXMT]); 1345165Swnj tp->snd_nxt = tp->snd_una; 1355165Swnj /* this only transmits one segment! */ 1365165Swnj (void) tcp_output(tp); 1375075Swnj return; 1385069Swnj 1395165Swnj /* 1405165Swnj * Persistance timer into zero window. 1415165Swnj * Force a byte to be output, if possible. 1425165Swnj */ 1435075Swnj case TCPT_PERSIST: 1445165Swnj tp->t_force = 1; 1455165Swnj (void) tcp_output(tp); 1465165Swnj tp->t_force = 0; 1475165Swnj TCPT_RANGESET(tp->t_timer[TCPT_PERSIST], 1485165Swnj 2 * tp->t_srtt, TCPTV_PERSMIN, TCPTV_MAX); 1495089Swnj return; 1505069Swnj 1515165Swnj /* 1525165Swnj * Keep-alive timer went off; send something 1535165Swnj * or drop connection if idle for too long. 1545165Swnj */ 1555075Swnj case TCPT_KEEP: 1565165Swnj if (tp->t_state < TCPS_ESTABLISHED || 1575165Swnj tp->t_idle >= TCPTV_MAXIDLE) { 1585165Swnj tcp_drop(tp, ETIMEDOUT); 1595165Swnj return; 1605165Swnj } 1615165Swnj tcp_respond(tp->t_template, tp->rcv_nxt, tp->snd_una-1, 0); 1625165Swnj tp->t_timer[TCPT_KEEP] = TCPTV_KEEP; 1635075Swnj return; 1645069Swnj } 1655069Swnj } 166