1 /* tcp_output.c 4.35 82/03/20 */ 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 "../net/tcp_debug.h" 22 #include "../errno.h" 23 24 char *tcpstates[]; /* XXX */ 25 26 /* 27 * Initial options: indicate max segment length 1/2 of space 28 * allocated for receive; if TCPTRUEOOB is defined, indicate 29 * willingness to do true out-of-band. 30 */ 31 #ifndef TCPTRUEOOB 32 u_char tcp_initopt[4] = { TCPOPT_MAXSEG, 4, 0x0, 0x0, }; 33 #else 34 u_char tcp_initopt[6] = { TCPOPT_MAXSEG, 4, 0x0, 0x0, TCPOPT_WILLOOB, 2 }; 35 #endif 36 37 /* 38 * Tcp output routine: figure out what should be sent and send it. 39 */ 40 tcp_output(tp) 41 register struct tcpcb *tp; 42 { 43 register struct socket *so = tp->t_inpcb->inp_socket; 44 register int len; 45 struct mbuf *m0; 46 int off, flags, win; 47 register struct mbuf *m; 48 register struct tcpiphdr *ti; 49 u_char *opt; 50 unsigned optlen = 0; 51 52 COUNT(TCP_OUTPUT); 53 54 /* 55 * Determine length of data that should be transmitted, 56 * and flags that will be used. 57 * If there is some data or critical controls (SYN, RST) 58 * to send, then transmit; otherwise, investigate further. 59 */ 60 off = tp->snd_nxt - tp->snd_una; 61 len = MIN(so->so_snd.sb_cc, tp->snd_wnd+tp->t_force) - off; 62 if (len < 0) 63 return (0); /* past FIN */ 64 if (len > tp->t_maxseg) 65 len = tp->t_maxseg; 66 67 flags = tcp_outflags[tp->t_state]; 68 if (tp->snd_nxt + len < tp->snd_una + so->so_snd.sb_cc) 69 flags &= ~TH_FIN; 70 if (flags & (TH_SYN|TH_RST|TH_FIN)) 71 goto send; 72 if (SEQ_GT(tp->snd_up, tp->snd_una)) 73 goto send; 74 75 /* 76 * Sender silly window avoidance. If can send all data, 77 * a maximum segment, at least 1/4 of window do it, 78 * or are forced, do it; otherwise don't bother. 79 */ 80 if (len) { 81 if (len == tp->t_maxseg || off+len >= so->so_snd.sb_cc) 82 goto send; 83 if (len * 4 >= tp->snd_wnd) /* a lot */ 84 goto send; 85 if (tp->t_force) 86 goto send; 87 } 88 89 /* 90 * Send if we owe peer an ACK. 91 */ 92 if (tp->t_flags&TF_ACKNOW) 93 goto send; 94 95 #ifdef TCPTRUEOOB 96 /* 97 * Send if an out of band data or ack should be transmitted. 98 */ 99 if (tp->t_oobflags&(TCPOOB_OWEACK|TCPOOB_NEEDACK))) 100 goto send; 101 #endif 102 103 /* 104 * Calculate available window in i, and also amount 105 * of window known to peer (as advertised window less 106 * next expected input.) If this is 35% or more of the 107 * maximum possible window, then want to send a segment to peer. 108 */ 109 win = sbspace(&so->so_rcv); 110 if (win > 0 && 111 ((100*(win-(tp->rcv_adv-tp->rcv_nxt))/so->so_rcv.sb_hiwat) >= 35)) 112 goto send; 113 114 /* 115 * No reason to send a segment, just return. 116 */ 117 return (0); 118 119 send: 120 /* 121 * Grab a header mbuf, attaching a copy of data to 122 * be transmitted, and initialize the header from 123 * the template for sends on this connection. 124 */ 125 MGET(m, 0); 126 if (m == 0) 127 return (0); 128 m->m_off = MMAXOFF - sizeof (struct tcpiphdr); 129 m->m_len = sizeof (struct tcpiphdr); 130 if (len) { 131 m->m_next = m_copy(so->so_snd.sb_mb, off, len); 132 if (m->m_next == 0) 133 len = 0; 134 } 135 ti = mtod(m, struct tcpiphdr *); 136 if (tp->t_template == 0) 137 panic("tcp_output"); 138 bcopy((caddr_t)tp->t_template, (caddr_t)ti, sizeof (struct tcpiphdr)); 139 140 /* 141 * Fill in fields, remembering maximum advertised 142 * window for use in delaying messages about window sizes. 143 */ 144 ti->ti_seq = tp->snd_nxt; 145 ti->ti_ack = tp->rcv_nxt; 146 #if vax 147 ti->ti_seq = htonl(ti->ti_seq); 148 ti->ti_ack = htonl(ti->ti_ack); 149 #endif 150 /* 151 * Before ESTABLISHED, force sending of initial options 152 * unless TCP set to not do any options. 153 */ 154 if (tp->t_state < TCPS_ESTABLISHED) { 155 if (tp->t_flags&TF_NOOPT) 156 goto noopt; 157 opt = tcp_initopt; 158 optlen = sizeof (tcp_initopt); 159 *(u_short *)(opt + 2) = so->so_rcv.sb_hiwat / 2; 160 #if vax 161 *(u_short *)(opt + 2) = htons(*(u_short *)(opt + 2)); 162 #endif 163 } else { 164 if (tp->t_tcpopt == 0) 165 goto noopt; 166 opt = mtod(tp->t_tcpopt, u_char *); 167 optlen = tp->t_tcpopt->m_len; 168 } 169 #ifndef TCPTRUEOOB 170 if (opt) 171 #else 172 if (opt || (tp->t_oobflags&(TCPOOB_OWEACK|TCPOOB_NEEDACK))) 173 #endif 174 { 175 m0 = m->m_next; 176 m->m_next = m_get(M_DONTWAIT); 177 if (m->m_next == 0) { 178 (void) m_free(m); 179 m_freem(m0); 180 return (0); 181 } 182 m->m_next->m_next = m0; 183 m0 = m->m_next; 184 m0->m_off = MMINOFF; 185 m0->m_len = optlen; 186 bcopy((caddr_t)opt, mtod(m0, caddr_t), optlen); 187 opt = (u_char *)(mtod(m0, caddr_t) + optlen); 188 #ifdef TCPTRUEOOB 189 if (tp->t_oobflags&TCPOOB_OWEACK) { 190 printf("tp %x send OOBACK for %x\n", tp->t_iobseq); 191 *opt++ = TCPOPT_OOBACK; 192 *opt++ = 3; 193 *opt++ = tp->t_iobseq; 194 m0->m_len += 3; 195 tp->t_oobflags &= ~TCPOOB_OWEACK; 196 /* sender should rexmt oob to force ack repeat */ 197 } 198 if (tp->t_oobflags&TCPOOB_NEEDACK) { 199 printf("tp %x send OOBDATA seq %x data %x\n", tp->t_oobseq, tp->t_oobc); 200 *opt++ = TCPOPT_OOBDATA; 201 *opt++ = 8; 202 *opt++ = tp->t_oobseq; 203 *opt++ = tp->t_oobc; 204 *(tcp_seq *)opt = tp->t_oobmark - tp->snd_nxt; 205 #ifdef vax 206 *(tcp_seq *)opt = htonl((unsigned)*(tcp_seq *)opt); 207 #endif 208 m0->m_len += 8; 209 TCPT_RANGESET(tp->t_timer[TCPT_OOBREXMT], 210 tcp_beta * tp->t_srtt, TCPTV_MIN, TCPTV_MAX); 211 } 212 #endif 213 while (m0->m_len & 0x3) { 214 *opt++ = TCPOPT_EOL; 215 m0->m_len++; 216 } 217 optlen = m0->m_len; 218 ti->ti_off = (sizeof (struct tcphdr) + optlen) >> 2; 219 } 220 noopt: 221 ti->ti_flags = flags; 222 win = sbspace(&so->so_rcv); 223 if (win < so->so_rcv.sb_hiwat / 4) /* avoid silly window */ 224 win = 0; 225 if (win > 0) 226 #if vax 227 ti->ti_win = htons((u_short)win); 228 #else 229 ti->ti_win = win; 230 #endif 231 if (SEQ_GT(tp->snd_up, tp->snd_nxt)) { 232 ti->ti_urp = tp->snd_up - tp->snd_nxt; 233 #if vax 234 ti->ti_urp = htons(ti->ti_urp); 235 #endif 236 ti->ti_flags |= TH_URG; 237 } else 238 /* 239 * If no urgent pointer to send, then we pull 240 * the urgent pointer to the left edge of the send window 241 * so that it doesn't drift into the send window on sequence 242 * number wraparound. 243 */ 244 tp->snd_up = tp->snd_una; /* drag it along */ 245 /* PUSH */ 246 247 /* 248 * Put TCP length in extended header, and then 249 * checksum extended header and data. 250 */ 251 if (len + optlen) { 252 ti->ti_len = sizeof (struct tcphdr) + optlen + len; 253 #if vax 254 ti->ti_len = htons((u_short)ti->ti_len); 255 #endif 256 } 257 ti->ti_sum = in_cksum(m, sizeof (struct tcpiphdr) + (int)optlen + len); 258 259 /* 260 * Advance snd_nxt over sequence space of this segment 261 */ 262 if (flags & (TH_SYN|TH_FIN)) 263 tp->snd_nxt++; 264 tp->snd_nxt += len; 265 266 /* 267 * If this transmission closes the window, 268 * start persistance timer at 2 round trip times 269 * but at least TCPTV_PERSMIN ticks. 270 */ 271 if (TCPS_HAVERCVDSYN(tp->t_state) && 272 SEQ_GEQ(tp->snd_nxt, tp->snd_una+tp->snd_wnd) && 273 tp->t_timer[TCPT_PERSIST] == 0) 274 TCPT_RANGESET(tp->t_timer[TCPT_PERSIST], 275 2 * tp->t_srtt, TCPTV_PERSMIN, TCPTV_MAX); 276 277 /* 278 * Time this transmission if not a retransmission and 279 * not currently timing anything. 280 */ 281 if (SEQ_GT(tp->snd_nxt, tp->snd_max) && tp->t_rtt == 0) { 282 tp->t_rtt = 1; 283 tp->t_rtseq = tp->snd_nxt - len; 284 } 285 286 /* 287 * Set retransmit timer if not currently set. 288 * Initial value for retransmit timer to tcp_beta*tp->t_srtt. 289 * Initialize shift counter which is used for exponential 290 * backoff of retransmit time. 291 */ 292 if (tp->t_timer[TCPT_REXMT] == 0 && tp->snd_nxt != tp->snd_una) { 293 TCPT_RANGESET(tp->t_timer[TCPT_REXMT], 294 tcp_beta * tp->t_srtt, TCPTV_MIN, TCPTV_MAX); 295 tp->t_rtt = 0; 296 tp->t_rxtshift = 0; 297 } 298 299 /* 300 * Trace. 301 */ 302 if (tp->t_inpcb->inp_socket->so_options & SO_DEBUG) 303 tcp_trace(TA_OUTPUT, tp->t_state, tp, ti, 0); 304 305 /* 306 * Fill in IP length and desired time to live and 307 * send to IP level. 308 */ 309 ((struct ip *)ti)->ip_len = sizeof (struct tcpiphdr) + optlen + len; 310 ((struct ip *)ti)->ip_ttl = TCP_TTL; 311 if (ip_output(m, tp->t_ipopt, 0) == 0) 312 return (0); 313 314 /* 315 * Data sent (as far as we can tell). 316 * If this advertises a larger window than any other segment, 317 * then remember the size of the advertised window. 318 * Drop send for purpose of ACK requirements. 319 */ 320 if (win > 0 && SEQ_GT(tp->rcv_nxt+win, tp->rcv_adv)) 321 tp->rcv_adv = tp->rcv_nxt + win; 322 tp->t_flags &= ~(TF_ACKNOW|TF_DELACK); 323 if (SEQ_GT(tp->snd_nxt, tp->snd_max)) 324 tp->snd_max = tp->snd_nxt; 325 return (1); 326 } 327