|
|
1.1 ! root 1: /* tcp_output.c 6.1 83/07/29 */ ! 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 "../h/errno.h" ! 10: ! 11: #include "../net/route.h" ! 12: ! 13: #include "../netinet/in.h" ! 14: #include "../netinet/in_pcb.h" ! 15: #include "../netinet/in_systm.h" ! 16: #include "../netinet/ip.h" ! 17: #include "../netinet/ip_var.h" ! 18: #include "../netinet/tcp.h" ! 19: #define TCPOUTFLAGS ! 20: #include "../netinet/tcp_fsm.h" ! 21: #include "../netinet/tcp_seq.h" ! 22: #include "../netinet/tcp_timer.h" ! 23: #include "../netinet/tcp_var.h" ! 24: #include "../netinet/tcpip.h" ! 25: #include "../netinet/tcp_debug.h" ! 26: ! 27: /* ! 28: * Initial options. ! 29: */ ! 30: u_char tcp_initopt[4] = { TCPOPT_MAXSEG, 4, 0x0, 0x0, }; ! 31: ! 32: /* ! 33: * Tcp output routine: figure out what should be sent and send it. ! 34: */ ! 35: tcp_output(tp) ! 36: register struct tcpcb *tp; ! 37: { ! 38: register struct socket *so = tp->t_inpcb->inp_socket; ! 39: register int len; ! 40: struct mbuf *m0; ! 41: int off, flags, win, error; ! 42: register struct mbuf *m; ! 43: register struct tcpiphdr *ti; ! 44: u_char *opt; ! 45: unsigned optlen = 0; ! 46: int sendalot; ! 47: ! 48: /* ! 49: * Determine length of data that should be transmitted, ! 50: * and flags that will be used. ! 51: * If there is some data or critical controls (SYN, RST) ! 52: * to send, then transmit; otherwise, investigate further. ! 53: */ ! 54: again: ! 55: sendalot = 0; ! 56: off = tp->snd_nxt - tp->snd_una; ! 57: len = MIN(so->so_snd.sb_cc, tp->snd_wnd+tp->t_force) - off; ! 58: if (len < 0) ! 59: return (0); /* ??? */ /* past FIN */ ! 60: if (len > tp->t_maxseg) { ! 61: len = tp->t_maxseg; ! 62: sendalot = 1; ! 63: } ! 64: ! 65: flags = tcp_outflags[tp->t_state]; ! 66: if (tp->snd_nxt + len < tp->snd_una + so->so_snd.sb_cc) ! 67: flags &= ~TH_FIN; ! 68: if (flags & (TH_SYN|TH_RST|TH_FIN)) ! 69: goto send; ! 70: if (SEQ_GT(tp->snd_up, tp->snd_una)) ! 71: goto send; ! 72: ! 73: /* ! 74: * Sender silly window avoidance. If can send all data, ! 75: * a maximum segment, at least 1/4 of window do it, ! 76: * or are forced, do it; otherwise don't bother. ! 77: */ ! 78: if (len) { ! 79: if (len == tp->t_maxseg || off+len >= so->so_snd.sb_cc) ! 80: goto send; ! 81: if (len * 4 >= tp->snd_wnd) /* a lot */ ! 82: goto send; ! 83: if (tp->t_force) ! 84: goto send; ! 85: } ! 86: ! 87: /* ! 88: * Send if we owe peer an ACK. ! 89: */ ! 90: if (tp->t_flags&TF_ACKNOW) ! 91: goto send; ! 92: ! 93: ! 94: /* ! 95: * Calculate available window in i, and also amount ! 96: * of window known to peer (as advertised window less ! 97: * next expected input.) If this is 35% or more of the ! 98: * maximum possible window, then want to send a segment to peer. ! 99: */ ! 100: win = sbspace(&so->so_rcv); ! 101: if (win > 0 && ! 102: ((100*(win-(tp->rcv_adv-tp->rcv_nxt))/so->so_rcv.sb_hiwat) >= 35)) ! 103: goto send; ! 104: ! 105: /* ! 106: * TCP window updates are not reliable, rather a polling protocol ! 107: * using ``persist'' packets is used to insure receipt of window ! 108: * updates. The three ``states'' for the output side are: ! 109: * idle not doing retransmits or persists ! 110: * persisting to move a zero window ! 111: * (re)transmitting and thereby not persisting ! 112: * ! 113: * tp->t_timer[TCPT_PERSIST] ! 114: * is set when we are in persist state. ! 115: * tp->t_force ! 116: * is set when we are called to send a persist packet. ! 117: * tp->t_timer[TCPT_REXMT] ! 118: * is set when we are retransmitting ! 119: * The output side is idle when both timers are zero. ! 120: * ! 121: * If send window is closed, there is data to transmit, and no ! 122: * retransmit or persist is pending, then go to persist state, ! 123: * arranging to force out a byte to get more current window information ! 124: * if nothing happens soon. ! 125: */ ! 126: if (tp->snd_wnd == 0 && so->so_snd.sb_cc && ! 127: tp->t_timer[TCPT_REXMT] == 0 && tp->t_timer[TCPT_PERSIST] == 0) { ! 128: tp->t_rxtshift = 0; ! 129: tcp_setpersist(tp); ! 130: } ! 131: ! 132: /* ! 133: * No reason to send a segment, just return. ! 134: */ ! 135: return (0); ! 136: ! 137: send: ! 138: /* ! 139: * Grab a header mbuf, attaching a copy of data to ! 140: * be transmitted, and initialize the header from ! 141: * the template for sends on this connection. ! 142: */ ! 143: MGET(m, M_DONTWAIT, MT_HEADER); ! 144: if (m == NULL) ! 145: return (ENOBUFS); ! 146: m->m_off = MMAXOFF - sizeof (struct tcpiphdr); ! 147: m->m_len = sizeof (struct tcpiphdr); ! 148: if (len) { ! 149: m->m_next = m_copy(so->so_snd.sb_mb, off, len); ! 150: if (m->m_next == 0) ! 151: len = 0; ! 152: } ! 153: ti = mtod(m, struct tcpiphdr *); ! 154: if (tp->t_template == 0) ! 155: panic("tcp_output"); ! 156: bcopy((caddr_t)tp->t_template, (caddr_t)ti, sizeof (struct tcpiphdr)); ! 157: ! 158: /* ! 159: * Fill in fields, remembering maximum advertised ! 160: * window for use in delaying messages about window sizes. ! 161: */ ! 162: ti->ti_seq = tp->snd_nxt; ! 163: ti->ti_ack = tp->rcv_nxt; ! 164: ti->ti_seq = htonl(ti->ti_seq); ! 165: ti->ti_ack = htonl(ti->ti_ack); ! 166: /* ! 167: * Before ESTABLISHED, force sending of initial options ! 168: * unless TCP set to not do any options. ! 169: */ ! 170: if (tp->t_state < TCPS_ESTABLISHED) { ! 171: if (tp->t_flags&TF_NOOPT) ! 172: goto noopt; ! 173: opt = tcp_initopt; ! 174: optlen = sizeof (tcp_initopt); ! 175: *(u_short *)(opt + 2) = MIN(so->so_rcv.sb_hiwat / 2, 1024); ! 176: *(u_short *)(opt + 2) = htons(*(u_short *)(opt + 2)); ! 177: } else { ! 178: if (tp->t_tcpopt == 0) ! 179: goto noopt; ! 180: opt = mtod(tp->t_tcpopt, u_char *); ! 181: optlen = tp->t_tcpopt->m_len; ! 182: } ! 183: if (opt) { ! 184: m0 = m->m_next; ! 185: m->m_next = m_get(M_DONTWAIT, MT_DATA); ! 186: if (m->m_next == 0) { ! 187: (void) m_free(m); ! 188: m_freem(m0); ! 189: return (ENOBUFS); ! 190: } ! 191: m->m_next->m_next = m0; ! 192: m0 = m->m_next; ! 193: m0->m_len = optlen; ! 194: bcopy((caddr_t)opt, mtod(m0, caddr_t), optlen); ! 195: opt = (u_char *)(mtod(m0, caddr_t) + optlen); ! 196: while (m0->m_len & 0x3) { ! 197: *opt++ = TCPOPT_EOL; ! 198: m0->m_len++; ! 199: } ! 200: optlen = m0->m_len; ! 201: ti->ti_off = (sizeof (struct tcphdr) + optlen) >> 2; ! 202: } ! 203: noopt: ! 204: ti->ti_flags = flags; ! 205: win = sbspace(&so->so_rcv); ! 206: if (win < so->so_rcv.sb_hiwat / 4) /* avoid silly window */ ! 207: win = 0; ! 208: if (win > 0) ! 209: ti->ti_win = htons((u_short)win); ! 210: if (SEQ_GT(tp->snd_up, tp->snd_nxt)) { ! 211: ti->ti_urp = tp->snd_up - tp->snd_nxt; ! 212: ti->ti_urp = htons(ti->ti_urp); ! 213: ti->ti_flags |= TH_URG; ! 214: } else ! 215: /* ! 216: * If no urgent pointer to send, then we pull ! 217: * the urgent pointer to the left edge of the send window ! 218: * so that it doesn't drift into the send window on sequence ! 219: * number wraparound. ! 220: */ ! 221: tp->snd_up = tp->snd_una; /* drag it along */ ! 222: /* ! 223: * If anything to send and we can send it all, set PUSH. ! 224: * (This will keep happy those implementations which only ! 225: * give data to the user when a buffer fills or a PUSH comes in.) ! 226: */ ! 227: if (len && off+len == so->so_snd.sb_cc) ! 228: ti->ti_flags |= TH_PUSH; ! 229: ! 230: /* ! 231: * Put TCP length in extended header, and then ! 232: * checksum extended header and data. ! 233: */ ! 234: if (len + optlen) { ! 235: ti->ti_len = sizeof (struct tcphdr) + optlen + len; ! 236: ti->ti_len = htons((u_short)ti->ti_len); ! 237: } ! 238: ti->ti_sum = in_cksum(m, sizeof (struct tcpiphdr) + (int)optlen + len); ! 239: ! 240: /* ! 241: * In transmit state, time the transmission and arrange for ! 242: * the retransmit. In persist state, reset persist time for ! 243: * next persist. ! 244: */ ! 245: if (tp->t_force == 0) { ! 246: /* ! 247: * Advance snd_nxt over sequence space of this segment. ! 248: */ ! 249: if (flags & (TH_SYN|TH_FIN)) ! 250: tp->snd_nxt++; ! 251: tp->snd_nxt += len; ! 252: if (SEQ_GT(tp->snd_nxt, tp->snd_max)) ! 253: tp->snd_max = tp->snd_nxt; ! 254: ! 255: /* ! 256: * Time this transmission if not a retransmission and ! 257: * not currently timing anything. ! 258: */ ! 259: if (SEQ_GT(tp->snd_nxt, tp->snd_max) && tp->t_rtt == 0) { ! 260: tp->t_rtt = 1; ! 261: tp->t_rtseq = tp->snd_nxt - len; ! 262: } ! 263: ! 264: /* ! 265: * Set retransmit timer if not currently set. ! 266: * Initial value for retransmit timer to tcp_beta*tp->t_srtt. ! 267: * Initialize shift counter which is used for exponential ! 268: * backoff of retransmit time. ! 269: */ ! 270: if (tp->t_timer[TCPT_REXMT] == 0 && ! 271: tp->snd_nxt != tp->snd_una) { ! 272: TCPT_RANGESET(tp->t_timer[TCPT_REXMT], ! 273: tcp_beta * tp->t_srtt, TCPTV_MIN, TCPTV_MAX); ! 274: tp->t_rtt = 0; ! 275: tp->t_rxtshift = 0; ! 276: } ! 277: tp->t_timer[TCPT_PERSIST] = 0; ! 278: } else { ! 279: if (SEQ_GT(tp->snd_una+1, tp->snd_max)) ! 280: tp->snd_max = tp->snd_una+1; ! 281: } ! 282: ! 283: /* ! 284: * Trace. ! 285: */ ! 286: if (so->so_options & SO_DEBUG) ! 287: tcp_trace(TA_OUTPUT, tp->t_state, tp, ti, 0); ! 288: ! 289: /* ! 290: * Fill in IP length and desired time to live and ! 291: * send to IP level. ! 292: */ ! 293: ((struct ip *)ti)->ip_len = sizeof (struct tcpiphdr) + optlen + len; ! 294: ((struct ip *)ti)->ip_ttl = TCP_TTL; ! 295: if (so->so_options & SO_DONTROUTE) ! 296: error = ! 297: ip_output(m, tp->t_ipopt, (struct route *)0, IP_ROUTETOIF); ! 298: else ! 299: error = ip_output(m, tp->t_ipopt, &tp->t_inpcb->inp_route, 0); ! 300: if (error) ! 301: return (error); ! 302: ! 303: /* ! 304: * Data sent (as far as we can tell). ! 305: * If this advertises a larger window than any other segment, ! 306: * then remember the size of the advertised window. ! 307: * Drop send for purpose of ACK requirements. ! 308: */ ! 309: if (win > 0 && SEQ_GT(tp->rcv_nxt+win, tp->rcv_adv)) ! 310: tp->rcv_adv = tp->rcv_nxt + win; ! 311: tp->t_flags &= ~(TF_ACKNOW|TF_DELACK); ! 312: if (sendalot && tp->t_force == 0) ! 313: goto again; ! 314: return (0); ! 315: } ! 316: ! 317: tcp_setpersist(tp) ! 318: register struct tcpcb *tp; ! 319: { ! 320: ! 321: if (tp->t_timer[TCPT_REXMT]) ! 322: panic("tcp_output REXMT"); ! 323: /* ! 324: * Start/restart persistance timer. ! 325: */ ! 326: TCPT_RANGESET(tp->t_timer[TCPT_PERSIST], ! 327: ((int)(tcp_beta * tp->t_srtt)) << tp->t_rxtshift, ! 328: TCPTV_PERSMIN, TCPTV_MAX); ! 329: tp->t_rxtshift++; ! 330: if (tp->t_rxtshift >= TCP_MAXRXTSHIFT) ! 331: tp->t_rxtshift = 0; ! 332: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.