1*5245Sroot /* tcp_timer.c 4.6 81/12/12 */ 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 235069Swnj /* 245069Swnj * Fast timeout routine for processing delayed acks 255069Swnj */ 265069Swnj tcp_fasttimo() 275069Swnj { 285069Swnj 295089Swnj COUNT(TCP_FASTTIMO); 305069Swnj } 315069Swnj 325069Swnj /* 335069Swnj * Tcp protocol timeout routine called every 500 ms. 345069Swnj * Updates the timers in all active tcb's and 355069Swnj * causes finite state machine actions if timers expire. 365069Swnj */ 375069Swnj tcp_slowtimo() 385069Swnj { 395069Swnj register struct inpcb *ip; 405069Swnj register struct tcpcb *tp; 415069Swnj int s = splnet(); 425069Swnj register int i; 435089Swnj COUNT(TCP_SLOWTIMO); 445069Swnj 455069Swnj /* 465069Swnj * Search through tcb's and update active timers. 475069Swnj */ 48*5245Sroot ip = tcb.inp_next; 49*5245Sroot if (ip == 0) { 50*5245Sroot splx(s); 51*5245Sroot return; 52*5245Sroot } 53*5245Sroot for (; ip != &tcb; ip = ip->inp_next) { 545069Swnj tp = intotcpcb(ip); 555075Swnj for (i = 0; i < TCPT_NTIMERS; i++) { 565089Swnj if (tp->t_timer[i] && --tp->t_timer[i] == 0) 575069Swnj (void) tcp_usrreq(tp->t_inpcb->inp_socket, 585069Swnj PRU_SLOWTIMO, (struct mbuf *)0, 595069Swnj (caddr_t)i); 605069Swnj } 615165Swnj tp->t_idle++; 625165Swnj if (tp->t_rtt) 635165Swnj tp->t_rtt++; 645069Swnj } 655075Swnj tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */ 665069Swnj splx(s); 675069Swnj } 685069Swnj 695069Swnj /* 705075Swnj * Cancel all timers for TCP tp. 715069Swnj */ 725089Swnj tcp_canceltimers(tp) 735069Swnj struct tcpcb *tp; 745069Swnj { 755069Swnj register int i; 765069Swnj 775089Swnj COUNT(TCP_CANCELTIMERS); 78*5245Sroot printf("tcp_canceltimers %x\n", tp); 795075Swnj for (i = 0; i < TCPT_NTIMERS; i++) 805075Swnj tp->t_timer[i] = 0; 815069Swnj } 825069Swnj 835069Swnj /* 845165Swnj * TCP timer processing. 855069Swnj */ 865075Swnj tcp_timers(tp, timer) 875069Swnj register struct tcpcb *tp; 885075Swnj int timer; 895069Swnj { 905069Swnj 915069Swnj COUNT(TCP_TIMERS); 92*5245Sroot printf("tcp_timers %x %d\n", tp, timer); 935089Swnj switch (timer) { 945069Swnj 955165Swnj /* 965165Swnj * 2 MSL timeout in shutdown went off. Delete connection 975165Swnj * control block. 985165Swnj */ 995075Swnj case TCPT_2MSL: 1005075Swnj tcp_close(tp); 1015075Swnj return; 1025069Swnj 1035165Swnj /* 1045165Swnj * Retransmission timer went off. Message has not 1055165Swnj * been acked within retransmit interval. Back off 1065165Swnj * to a longer retransmit interval and retransmit all 1075165Swnj * unacknowledged messages in the window. 1085165Swnj */ 1095075Swnj case TCPT_REXMT: 1105165Swnj tp->t_rxtshift++; 1115165Swnj TCPT_RANGESET(tp->t_timer[TCPT_REXMT], 1125165Swnj ((int)(2 * tp->t_srtt)) << tp->t_rxtshift, 1135165Swnj TCPTV_MIN, TCPTV_MAX); 114*5245Sroot printf("rexmt timer now %d\n", tp->t_timer[TCPT_REXMT]); 1155165Swnj tp->snd_nxt = tp->snd_una; 1165165Swnj /* this only transmits one segment! */ 1175165Swnj (void) tcp_output(tp); 1185075Swnj return; 1195069Swnj 1205165Swnj /* 1215165Swnj * Persistance timer into zero window. 1225165Swnj * Force a byte to be output, if possible. 1235165Swnj */ 1245075Swnj case TCPT_PERSIST: 1255165Swnj tp->t_force = 1; 1265165Swnj (void) tcp_output(tp); 1275165Swnj tp->t_force = 0; 1285165Swnj TCPT_RANGESET(tp->t_timer[TCPT_PERSIST], 1295165Swnj 2 * tp->t_srtt, TCPTV_PERSMIN, TCPTV_MAX); 130*5245Sroot printf("persist timer now %d\n", tp->t_timer[TCPT_PERSIST]); 1315089Swnj return; 1325069Swnj 1335165Swnj /* 1345165Swnj * Keep-alive timer went off; send something 1355165Swnj * or drop connection if idle for too long. 1365165Swnj */ 1375075Swnj case TCPT_KEEP: 1385165Swnj if (tp->t_state < TCPS_ESTABLISHED || 1395165Swnj tp->t_idle >= TCPTV_MAXIDLE) { 140*5245Sroot printf("drop because of keep alive\n"); 1415165Swnj tcp_drop(tp, ETIMEDOUT); 1425165Swnj return; 1435165Swnj } 144*5245Sroot printf("send keep alive\n"); 1455165Swnj tcp_respond(tp->t_template, tp->rcv_nxt, tp->snd_una-1, 0); 1465165Swnj tp->t_timer[TCPT_KEEP] = TCPTV_KEEP; 1475075Swnj return; 1485069Swnj } 1495069Swnj } 150