1 /* tcp_output.c 4.21 81/12/02 */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../h/mbuf.h" 6 #include "../h/protosw.h" 7 #include "../h/socket.h" 8 #include "../h/socketvar.h" 9 #include "../net/in.h" 10 #include "../net/in_pcb.h" 11 #include "../net/in_systm.h" 12 #include "../net/ip.h" 13 #include "../net/ip_var.h" 14 #include "../net/tcp.h" 15 #define TCPOUTFLAGS 16 #include "../net/tcp_fsm.h" 17 #include "../net/tcp_seq.h" 18 #include "../net/tcp_timer.h" 19 #include "../net/tcp_var.h" 20 #include "../net/tcpip.h" 21 #include "../errno.h" 22 23 /* 24 * Tcp output routine: figure out what should be sent 25 * and, if nothing, send a null segment anyways if force is nonzero 26 * (e.g. to be sure to send an ACK). 27 * 28 * This routine can be called only after SYNs have been exchanged. 29 */ 30 tcp_output(tp) 31 register struct tcpcb *tp; 32 { 33 register struct socket *so = tp->t_inpcb->inp_socket; 34 register int len; 35 struct mbuf *m0; 36 int off, flags; 37 register struct mbuf *m; 38 register struct tcpiphdr *ti; 39 int win; 40 41 COUNT(TCP_OUTPUT); 42 43 /* 44 * Determine length of data that can be transmitted, 45 * and flags that will be used. 46 * If there is some data or critical controls (SYN, RST) 47 * to send, then transmit; otherwise, investigate further. 48 */ 49 off = tp->snd_nxt - tp->snd_una; 50 len = MIN(so->so_snd.sb_cc, tp->snd_wnd+tp->t_force) - off; 51 if (len > tp->t_maxseg) 52 len = tp->t_maxseg; 53 flags = tcp_outflags[tp->t_state]; 54 if (len < so->so_snd.sb_cc) 55 flags &= ~TH_FIN; 56 if (len || (flags & (TH_SYN|TH_RST))) 57 goto send; 58 59 /* 60 * See if we owe peer an ACK or have a unacked FIN to send. 61 */ 62 if (tp->t_flags & TF_ACKNOW) 63 goto send; 64 if ((so->so_state & SS_CANTSENDMORE) && 65 TCPS_OURFINNOTACKED(tp->t_state)) 66 goto send; 67 68 /* 69 * Calculate available window in i, and also amount 70 * of window known to peer (as advertised window less 71 * next expected input.) If this is 35% or more of the 72 * maximum possible window, then want to send a segment to peer. 73 */ 74 win = sbspace(&so->so_rcv); 75 if (win > 0 && 76 ((100*(win-(tp->rcv_adv-tp->rcv_nxt))/so->so_rcv.sb_hiwat) >= 35)) 77 goto send; 78 79 /* 80 * No reason to send a segment, just return. 81 */ 82 return (0); 83 84 send: 85 /* 86 * Grab a header mbuf, attaching a copy of data to 87 * be transmitted, and initialize the header from 88 * the template for sends on this connection. 89 */ 90 MGET(m, 0); 91 if (m == 0) 92 return (0); 93 m->m_off = MMAXOFF - sizeof(struct tcpiphdr); 94 m->m_len = sizeof (struct tcpiphdr); 95 if (len) { 96 m->m_next = m_copy(so->so_snd.sb_mb, off, len); 97 if (m->m_next == 0) 98 len = 0; 99 } 100 ti = mtod(m, struct tcpiphdr *); 101 if (tp->t_template == 0) 102 panic("tcp_output"); 103 bcopy((caddr_t)tp->t_template, (caddr_t)ti, sizeof (struct tcpiphdr)); 104 105 /* 106 * Fill in fields, remembering maximum advertised 107 * window for use in delaying messages about window sizes. 108 */ 109 ti->ti_seq = htonl(tp->snd_nxt); 110 ti->ti_ack = htonl(tp->rcv_nxt); 111 if (tp->t_tcpopt) { 112 m0 = m->m_next; 113 m->m_next = m_get(0); 114 if (m->m_next == 0) { 115 (void) m_free(m); 116 m_freem(m); 117 return (0); 118 } 119 m->m_next->m_next = m0; 120 m->m_off = MMINOFF; 121 m->m_len = tp->t_tcpopt->m_len; 122 bcopy(mtod(tp->t_tcpopt, caddr_t), mtod(m, caddr_t), 123 (unsigned)tp->t_tcpopt->m_len); 124 ti->ti_off = (sizeof (struct tcphdr)+tp->t_tcpopt->m_len) >> 2; 125 } 126 ti->ti_flags = flags; 127 win = sbspace(&so->so_rcv); 128 if (win > 0) 129 ti->ti_win = htons((u_short)win); 130 if (SEQ_GT(tp->snd_up, tp->snd_nxt)) { 131 ti->ti_urp = htons((u_short)(tp->snd_up - tp->snd_nxt)); 132 ti->ti_flags |= TH_URG; 133 } else 134 /* 135 * If no urgent pointer to send, then we pull 136 * the urgent pointer to the left edge of the send window 137 * so that it doesn't drift into the send window on sequence 138 * number wraparound. 139 */ 140 tp->snd_up = tp->snd_una; /* drag it along */ 141 /* PUSH */ 142 143 /* 144 * Put TCP length in extended header, and then 145 * checksum extended header and data. 146 */ 147 if (len) 148 ti->ti_len = htons((u_short)(len + sizeof (struct tcphdr))); 149 ti->ti_sum = in_cksum(m, sizeof (struct tcpiphdr) + len); 150 151 /* 152 * Advance snd_nxt over sequence space of this segment 153 */ 154 if (flags & (TH_SYN|TH_FIN)) 155 len++; 156 tp->snd_nxt += len; 157 158 /* 159 * If this transmission closes the window, 160 * start persistance timer at 2 round trip 161 * times but at least TCPTV_PERSMIN ticks. 162 */ 163 if (tp->snd_una + tp->snd_wnd >= tp->snd_nxt && 164 tp->t_timer[TCPT_PERSIST] == 0) { 165 tp->t_timer[TCPT_PERSIST] = 2 * tp->t_srtt; 166 if (tp->t_timer[TCPT_PERSIST] < TCPTV_PERSMIN) 167 tp->t_timer[TCPT_PERSIST] = TCPTV_PERSMIN; 168 if (tp->t_timer[TCPT_PERSIST] > TCPTV_MAX) 169 tp->t_timer[TCPT_PERSIST] = TCPTV_MAX; 170 } 171 172 /* 173 * Time this transmission if not a retransmission and 174 * not currently timing anything. 175 */ 176 if (SEQ_GT(tp->snd_nxt, tp->snd_max) && tp->t_rtt == 0) { 177 tp->t_rtt = 1; 178 tp->t_rtseq = tp->snd_nxt - len; 179 } 180 181 /* 182 * Set retransmit timer if not currently set. 183 * Initial value for retransmit timer to tcp_beta*tp->t_srtt, 184 * with a minimum of TCPTV_MIN and a max of TCPTV_MAX. 185 * Initialize shift counter which is used for exponential 186 * backoff of retransmit time. 187 */ 188 if (tp->t_timer[TCPT_REXMT] == 0) { 189 tp->t_timer[TCPT_REXMT] = tcp_beta * tp->t_srtt; 190 if (tp->t_timer[TCPT_REXMT] < TCPTV_MIN) 191 tp->t_timer[TCPT_REXMT] = TCPTV_MIN; 192 if (tp->t_timer[TCPT_REXMT] > TCPTV_MAX) 193 tp->t_timer[TCPT_REXMT] = TCPTV_MAX; 194 tp->t_rxtshift = 0; 195 } 196 197 /* 198 * Fill in IP length and desired time to live and 199 * send to IP level. 200 */ 201 ((struct ip *)ti)->ip_len = len + sizeof (struct tcpiphdr); 202 ((struct ip *)ti)->ip_ttl = TCP_TTL; 203 if (ip_output(m, tp->t_ipopt) == 0) 204 return (0); 205 206 /* 207 * Data sent (as far as we can tell). 208 * If this advertises a larger window than any other segment, 209 * then record its sequence to be used in suppressing messages. 210 * Drop send for purpose of ACK requirements. 211 */ 212 if (win > 0 && SEQ_GT(tp->rcv_nxt+win, tp->rcv_adv)) 213 tp->rcv_adv = tp->rcv_nxt + win; 214 tp->t_flags &= ~(TF_ACKNOW|TF_DELACK); 215 tp->snd_max = tp->snd_nxt; 216 return (1); 217 } 218