Annotation of cci/sys/netinet/tcp_output.c, revision 1.1.1.2

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

unix.superglobalmegacorp.com

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