Annotation of 42BSD/sys/netinet/tcp_output.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.