Annotation of 43BSDReno/sys/netiso/tp_subr.c, revision 1.1.1.1

1.1       root        1: /***********************************************************
                      2:                Copyright IBM Corporation 1987
                      3: 
                      4:                       All Rights Reserved
                      5: 
                      6: Permission to use, copy, modify, and distribute this software and its 
                      7: documentation for any purpose and without fee is hereby granted, 
                      8: provided that the above copyright notice appear in all copies and that
                      9: both that copyright notice and this permission notice appear in 
                     10: supporting documentation, and that the name of IBM not be
                     11: used in advertising or publicity pertaining to distribution of the
                     12: software without specific, written prior permission.  
                     13: 
                     14: IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
                     15: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
                     16: IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
                     17: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
                     18: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
                     19: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
                     20: SOFTWARE.
                     21: 
                     22: ******************************************************************/
                     23: 
                     24: /*
                     25:  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
                     26:  */
                     27: /* 
                     28:  * ARGO TP
                     29:  *
                     30:  * $Header: tp_subr.c,v 5.3 88/11/18 17:28:43 nhall Exp $
                     31:  * $Source: /usr/argo/sys/netiso/RCS/tp_subr.c,v $
                     32:  *     @(#)tp_subr.c   7.6 (Berkeley) 7/24/90
                     33:  *
                     34:  * The main work of data transfer is done here.
                     35:  * These routines are called from tp.trans.
                     36:  * They include the routines that check the validity of acks and Xacks,
                     37:  * (tp_goodack() and tp_goodXack() )
                     38:  * take packets from socket buffers and send them (tp_send()),
                     39:  * drop the data from the socket buffers (tp_sbdrop()),  
                     40:  * and put incoming packet data into socket buffers (tp_stash()).
                     41:  */
                     42: 
                     43: #ifndef lint
                     44: static char *rcsid = "$Header: tp_subr.c,v 5.3 88/11/18 17:28:43 nhall Exp $";
                     45: #endif lint
                     46: 
                     47: #include "param.h"
                     48: #include "mbuf.h"
                     49: #include "socket.h"
                     50: #include "socketvar.h"
                     51: #include "protosw.h"
                     52: #include "errno.h"
                     53: #include "types.h"
                     54: #include "time.h"
                     55: 
                     56: #include "tp_ip.h"
                     57: #include "iso.h"
                     58: #include "argo_debug.h"
                     59: #include "tp_timer.h"
                     60: #include "tp_param.h"
                     61: #include "tp_stat.h"
                     62: #include "tp_pcb.h"
                     63: #include "tp_tpdu.h"
                     64: #include "tp_trace.h"
                     65: #include "tp_meas.h"
                     66: #include "tp_seq.h"
                     67: 
                     68: int            tp_emit();
                     69: static void tp_sbdrop();
                     70: 
                     71: #define SMOOTH(newtype, alpha, old, new) \
                     72:        (newtype) (((new - old)>>alpha) + (old))
                     73: 
                     74: #define ABS(type, val) \
                     75:        (type) (((int)(val)<0)?-(val):(val))
                     76: 
                     77: #define TP_MAKE_RTC( Xreg, Xseq, Xeot, Xdata, Xlen, Xretval, Xtype) \
                     78: {      struct mbuf *xxn;\
                     79:        MGET(xxn, M_DONTWAIT, Xtype);\
                     80:        if( xxn == (struct mbuf *)0 ) {\
                     81:                printf("MAKE RTC FAILED: ENOBUFS\n");\
                     82:                return (int)Xretval;\
                     83:        }\
                     84:        xxn->m_act=MNULL;\
                     85:        Xreg = mtod(xxn, struct tp_rtc *);\
                     86:        if( Xreg == (struct tp_rtc *)0 ) {\
                     87:                return (int)Xretval;\
                     88:        }\
                     89:        Xreg->tprt_eot = Xeot;\
                     90:        Xreg->tprt_seq = Xseq;\
                     91:        Xreg->tprt_data = Xdata;\
                     92:        Xreg->tprt_octets = Xlen;\
                     93: }
                     94: 
                     95: 
                     96: /*
                     97:  * CALLED FROM:
                     98:  *     tp.trans, when an XAK arrives
                     99:  * FUNCTION and ARGUMENTS:
                    100:  *     Determines if the sequence number (seq) from the XAK 
                    101:  *     acks anything new.  If so, drop the appropriate tpdu
                    102:  *     from the XPD send queue.
                    103:  * RETURN VALUE:
                    104:  *     Returns 1 if it did this, 0 if the ack caused no action.
                    105:  */
                    106: int
                    107: tp_goodXack(tpcb, seq)
                    108:        struct tp_pcb   *tpcb;
                    109:        SeqNum                  seq; 
                    110: {
                    111: 
                    112:        IFTRACE(D_XPD)
                    113:                tptraceTPCB(TPPTgotXack, 
                    114:                        seq, tpcb->tp_Xuna, tpcb->tp_Xsndnxt, tpcb->tp_sndhiwat, 
                    115:                        tpcb->tp_snduna); 
                    116:        ENDTRACE
                    117: 
                    118:        if ( seq == tpcb->tp_Xuna ) {
                    119:                        tpcb->tp_Xuna = tpcb->tp_Xsndnxt;
                    120: 
                    121:                        /* DROP 1 packet from the Xsnd socket buf - just so happens
                    122:                         * that only one packet can be there at any time
                    123:                         * so drop the whole thing.  If you allow > 1 packet
                    124:                         * the socket buffer, then you'll have to keep
                    125:                         * track of how many characters went w/ each XPD tpdu, so this
                    126:                         * will get messier
                    127:                         */
                    128:                        IFDEBUG(D_XPD)
                    129:                                dump_mbuf(tpcb->tp_Xsnd.sb_mb,
                    130:                                        "tp_goodXack Xsnd before sbdrop");
                    131:                        ENDDEBUG
                    132: 
                    133:                        IFTRACE(D_XPD)
                    134:                                tptraceTPCB(TPPTmisc, 
                    135:                                        "goodXack: dropping cc ",
                    136:                                        (int)(tpcb->tp_Xsnd.sb_cc),
                    137:                                        0,0,0);
                    138:                        ENDTRACE
                    139:                        sbdrop( &tpcb->tp_Xsnd, (int)(tpcb->tp_Xsnd.sb_cc));
                    140:                        CONG_ACK(tpcb, seq);
                    141:                        return 1;
                    142:        } 
                    143:        return 0;
                    144: }
                    145: 
                    146: /*
                    147:  * CALLED FROM:
                    148:  *  tp_good_ack()
                    149:  * FUNCTION and ARGUMENTS:
                    150:  *  updates
                    151:  *  smoothed average round trip time (base_rtt)
                    152:  *  roundtrip time variance (base_rtv) - actually deviation, not variance
                    153:  *  given the new value (diff)
                    154:  * RETURN VALUE:
                    155:  * void
                    156:  */
                    157: 
                    158: void
                    159: tp_rtt_rtv( base_rtt, base_rtv, newmeas )
                    160:        struct  timeval *base_rtt, *base_rtv, *newmeas;
                    161: {
                    162:        /* update  rt variance (really just the deviation): 
                    163:         *      rtv.smooth_ave =  SMOOTH( | oldrtt.smooth_avg - rtt.this_instance | )
                    164:         */
                    165:        base_rtv->tv_sec = 
                    166:                SMOOTH( long,  TP_RTV_ALPHA, base_rtv->tv_sec, 
                    167:                        ABS( long, base_rtt->tv_sec - newmeas->tv_sec ));
                    168:        base_rtv->tv_usec = 
                    169:                SMOOTH( long,  TP_RTV_ALPHA, base_rtv->tv_usec, 
                    170:                        ABS(long, base_rtt->tv_usec - newmeas->tv_usec ));
                    171: 
                    172:        /* update smoothed average rtt */
                    173:        base_rtt->tv_sec = 
                    174:                SMOOTH( long,  TP_RTT_ALPHA, base_rtt->tv_sec, newmeas->tv_sec);
                    175:        base_rtt->tv_usec =
                    176:                SMOOTH( long,  TP_RTT_ALPHA, base_rtt->tv_usec, newmeas->tv_usec);
                    177: 
                    178: }
                    179: 
                    180: /*
                    181:  * CALLED FROM:
                    182:  *  tp.trans when an AK arrives
                    183:  * FUNCTION and ARGUMENTS:
                    184:  *     Given (cdt), the credit from the AK tpdu, and 
                    185:  *     (seq), the sequence number from the AK tpdu,
                    186:  *  tp_goodack() determines if the AK acknowledges something in the send
                    187:  *     window, and if so, drops the appropriate packets from the retransmission
                    188:  *  list, computes the round trip time, and updates the retransmission timer
                    189:  *  based on the new smoothed round trip time.
                    190:  * RETURN VALUE:
                    191:  *     Returns 1 if
                    192:  *     EITHER it actually acked something heretofore unacknowledged
                    193:  *     OR no news but the credit should be processed.
                    194:  *     If something heretofore unacked was acked with this sequence number,
                    195:  *     the appropriate tpdus are dropped from the retransmission control list,
                    196:  *     by calling tp_sbdrop().
                    197:  *     No need to see the tpdu itself.
                    198:  */
                    199: int
                    200: tp_goodack(tpcb, cdt, seq, subseq)
                    201:        register struct tp_pcb  *tpcb;
                    202:        u_int                                   cdt;
                    203:        register SeqNum                 seq, subseq;
                    204: {
                    205:        int     old_fcredit = tpcb->tp_fcredit; 
                    206:        int     bang = 0;       /* bang --> ack for something heretofore unacked */
                    207: 
                    208:        IFDEBUG(D_ACKRECV)
                    209:                printf("goodack seq 0x%x cdt 0x%x snduna 0x%x sndhiwat 0x%x\n",
                    210:                        seq, cdt, tpcb->tp_snduna, tpcb->tp_sndhiwat);
                    211:        ENDDEBUG
                    212:        IFTRACE(D_ACKRECV)
                    213:                tptraceTPCB(TPPTgotack, 
                    214:                        seq,cdt, tpcb->tp_snduna,tpcb->tp_sndhiwat,subseq); 
                    215:        ENDTRACE
                    216: 
                    217:        IFPERF(tpcb)
                    218:                tpmeas(tpcb->tp_lref, TPtime_ack_rcvd, (struct timeval *)0, seq, 0, 0);
                    219:        ENDPERF
                    220: 
                    221:        if ( subseq != 0 && (subseq <= tpcb->tp_r_subseq) ) {
                    222:                /* discard the ack */
                    223:                IFTRACE(D_ACKRECV)
                    224:                        tptraceTPCB(TPPTmisc, "goodack discard : subseq tp_r_subseq",
                    225:                                subseq, tpcb->tp_r_subseq, 0, 0);
                    226:                ENDTRACE
                    227:                return 0;
                    228:        } else {
                    229:                tpcb->tp_r_subseq = subseq;
                    230:        }
                    231: 
                    232:        if ( IN_SWINDOW(tpcb, seq, 
                    233:                        tpcb->tp_snduna, SEQ(tpcb, tpcb->tp_sndhiwat+1)) ) {
                    234: 
                    235:                IFDEBUG(D_XPD)
                    236:                        dump_mbuf(tpcb->tp_sock->so_snd.sb_mb, 
                    237:                                "tp_goodack snd before sbdrop");
                    238:                ENDDEBUG
                    239:                tp_sbdrop(tpcb, SEQ_SUB(tpcb, seq, 1) );
                    240: 
                    241:                /* increase congestion window but don't let it get too big */
                    242:                {
                    243:                        register int maxcdt = tpcb->tp_xtd_format?0xffff:0xf;
                    244:                        CONG_ACK(tpcb, seq);
                    245:                }
                    246: 
                    247:                /* Compute smoothed round trip time.
                    248:                 * Only measure rtt for tp_snduna if tp_snduna was among 
                    249:                 * the last TP_RTT_NUM seq numbers sent, and if the data
                    250:                 * were not retransmitted.
                    251:                 */
                    252:                if (SEQ_GEQ(tpcb, tpcb->tp_snduna, 
                    253:                        SEQ(tpcb, tpcb->tp_sndhiwat - TP_RTT_NUM))
                    254:                        && SEQ_GT(tpcb, seq, SEQ_ADD(tpcb, tpcb->tp_retrans_hiwat, 1))) {
                    255: 
                    256:                        struct timeval *t = &tpcb->tp_rttemit[tpcb->tp_snduna & TP_RTT_NUM];
                    257:                        struct timeval x;
                    258: 
                    259:                        GET_TIME_SINCE(t, &x);
                    260: 
                    261:                        tp_rtt_rtv( &(tpcb->tp_rtt), &(tpcb->tp_rtv), &x );
                    262: 
                    263:                        {       /* update the global rtt, rtv stats */
                    264:                                register int i =
                    265:                                   (int) tpcb->tp_flags & (TPF_PEER_ON_SAMENET | TPF_NLQOS_PDN);
                    266:                                tp_rtt_rtv( &(tp_stat.ts_rtt[i]), &(tp_stat.ts_rtv[i]), &x );
                    267: 
                    268:                                IFTRACE(D_RTT)
                    269:                                        tptraceTPCB(TPPTmisc, "Global rtt, rtv: i", i, 0, 0, 0);
                    270:                                ENDTRACE
                    271:                        }
                    272: 
                    273:                        IFTRACE(D_RTT)
                    274:                                tptraceTPCB(TPPTmisc, 
                    275:                                "Smoothed rtt: tp_snduna, (time.sec, time.usec), peer_acktime",
                    276:                                tpcb->tp_snduna, time.tv_sec, time.tv_usec,
                    277:                                        tpcb->tp_peer_acktime);
                    278: 
                    279:                                tptraceTPCB(TPPTmisc, 
                    280:                                "(secs): emittime diff(x) rtt, rtv",
                    281:                                        t->tv_sec, 
                    282:                                        x.tv_sec, 
                    283:                                        tpcb->tp_rtt.tv_sec,
                    284:                                        tpcb->tp_rtv.tv_sec);
                    285:                                tptraceTPCB(TPPTmisc, 
                    286:                                "(usecs): emittime diff(x) rtt rtv",
                    287:                                        t->tv_usec, 
                    288:                                        x.tv_usec, 
                    289:                                        tpcb->tp_rtt.tv_usec,
                    290:                                        tpcb->tp_rtv.tv_usec);
                    291:                        ENDTRACE
                    292: 
                    293:                        {
                    294:                                /* Update data retransmission timer based on the smoothed
                    295:                                 * round trip time, peer ack time, and the pseudo-arbitrary
                    296:                                 * number 4.
                    297:                                 * new ticks: avg rtt + 2*dev
                    298:                                 * rtt, rtv are in microsecs, and ticks are 500 ms
                    299:                                 * so 1 tick = 500*1000 us = 500000 us
                    300:                                 * so ticks = (rtt + 2 rtv)/500000
                    301:                                 * with ticks no les than peer ack time and no less than 4
                    302:                                 */
                    303: 
                    304:                                int rtt = tpcb->tp_rtt.tv_usec +
                    305:                                        tpcb->tp_rtt.tv_sec*1000000;
                    306:                                int rtv = tpcb->tp_rtv.tv_usec +
                    307:                                        tpcb->tp_rtv.tv_sec*1000000;
                    308: 
                    309:                                IFTRACE(D_RTT)
                    310:                                        tptraceTPCB(TPPTmisc, "oldticks ,rtv, rtt, newticks",
                    311:                                                tpcb->tp_dt_ticks, 
                    312:                                                rtv, rtt,
                    313:                                                (rtt/500000 + (2 * rtv)/500000));
                    314:                                ENDTRACE
                    315:                                tpcb->tp_dt_ticks = (rtt+ (2 * rtv))/500000;
                    316:                                tpcb->tp_dt_ticks = MAX( tpcb->tp_dt_ticks, 
                    317:                                        tpcb->tp_peer_acktime);
                    318:                                tpcb->tp_dt_ticks = MAX( tpcb->tp_dt_ticks,  4);
                    319:                        }
                    320:                }
                    321:                tpcb->tp_snduna = seq;
                    322:                tpcb->tp_retrans = tpcb->tp_Nretrans; /* CE_BIT */
                    323: 
                    324:                bang++;
                    325:        } 
                    326: 
                    327:        if( cdt != 0 && old_fcredit == 0 ) {
                    328:                tpcb->tp_sendfcc = 1;
                    329:        }
                    330:        if( cdt == 0 && old_fcredit != 0 ) {
                    331:                IncStat(ts_zfcdt);
                    332:        }
                    333:        tpcb->tp_fcredit = cdt;
                    334: 
                    335:        IFDEBUG(D_ACKRECV)
                    336:                printf("goodack returning 0x%x, bang 0x%x cdt 0x%x old_fcredit 0x%x\n",
                    337:                        (bang || (old_fcredit < cdt) ), bang, cdt, old_fcredit );
                    338:        ENDDEBUG
                    339: 
                    340:        return (bang || (old_fcredit < cdt)) ;
                    341: }
                    342: 
                    343: /*
                    344:  * CALLED FROM:
                    345:  *  tp_goodack()
                    346:  * FUNCTION and ARGUMENTS:
                    347:  *  drops everything up TO and INCLUDING seq # (seq)
                    348:  *  from the retransmission queue.
                    349:  */
                    350: static void
                    351: tp_sbdrop(tpcb, seq) 
                    352:        struct  tp_pcb                  *tpcb;
                    353:        SeqNum                                  seq;
                    354: {
                    355:        register struct tp_rtc  *s = tpcb->tp_snduna_rtc;
                    356: 
                    357:        IFDEBUG(D_ACKRECV)
                    358:                printf("tp_sbdrop up through seq 0x%x\n", seq);
                    359:        ENDDEBUG
                    360:        while (s != (struct tp_rtc *)0 && (SEQ_LEQ(tpcb, s->tprt_seq, seq))) {
                    361:                m_freem( s->tprt_data );
                    362:                tpcb->tp_snduna_rtc = s->tprt_next;
                    363:                (void) m_free( dtom( s ) );
                    364:                s = tpcb->tp_snduna_rtc;
                    365:        }
                    366:        if(tpcb->tp_snduna_rtc == (struct tp_rtc *)0)
                    367:                tpcb->tp_sndhiwat_rtc = (struct tp_rtc *) 0;
                    368: 
                    369: }
                    370: 
                    371: /*
                    372:  * CALLED FROM:
                    373:  *     tp.trans on user send request, arrival of AK and arrival of XAK
                    374:  * FUNCTION and ARGUMENTS:
                    375:  *     Emits tpdus starting at sequence number (lowseq).
                    376:  *     Emits until a) runs out of data, or  b) runs into an XPD mark, or
                    377:  *                     c) it hits seq number (highseq)
                    378:  *     Removes the octets from the front of the socket buffer 
                    379:  *     and repackages them in one mbuf chain per tpdu.
                    380:  *     Moves the mbuf chain to the doubly linked list that runs from
                    381:  *     tpcb->tp_sndhiwat_rtc to tpcb->tp_snduna_rtc.
                    382:  *
                    383:  *     Creates tpdus that are no larger than <tpcb->tp_l_tpdusize - headersize>,
                    384:  *
                    385:  *     If you want XPD to buffer > 1 du per socket buffer, you can
                    386:  *     modifiy this to issue XPD tpdus also, but then it'll have
                    387:  *     to take some argument(s) to distinguish between the type of DU to
                    388:  *     hand tp_emit, the socket buffer from which to get the data, and
                    389:  *     the chain of tp_rtc structures on which to put the data sent.
                    390:  *
                    391:  *     When something is sent for the first time, its time-of-send
                    392:  *     is stashed (the last RTT_NUM of them are stashed).  When the
                    393:  *     ack arrives, the smoothed round-trip time is figured using this value.
                    394:  * RETURN VALUE:
                    395:  *     the highest seq # sent successfully.
                    396:  */
                    397: tp_send(tpcb)
                    398:        register struct tp_pcb  *tpcb;
                    399: {
                    400:        register int                    len;
                    401:        register struct mbuf    *m; /* the one we're inspecting now */
                    402:        struct mbuf                             *mb;/* beginning of this tpdu */
                    403:        struct mbuf                     *nextrecord; /* NOT next tpdu but next sb record */
                    404:        struct  sockbuf                 *sb = &tpcb->tp_sock->so_snd;
                    405:        int                                             maxsize = tpcb->tp_l_tpdusize 
                    406:                                                                                - tp_headersize(DT_TPDU_type, tpcb)
                    407:                                                                                - (tpcb->tp_use_checksum?4:0) ;
                    408:        unsigned int                    eotsdu_reached=0;
                    409:        SeqNum                                  lowseq, highseq ;
                    410:        SeqNum                                  lowsave; 
                    411: #ifdef TP_PERF_MEAS
                    412:        struct timeval                  send_start_time;
                    413: #endif TP_PERF_MEAS
                    414: 
                    415:        lowsave =  lowseq = SEQ(tpcb, tpcb->tp_sndhiwat + 1);
                    416: 
                    417:        ASSERT( tpcb->tp_cong_win > 0 && tpcb->tp_cong_win < 0xffff);
                    418: 
                    419:        if( tpcb->tp_rx_strat & TPRX_USE_CW ) {
                    420:                        /*first hiseq is temp vbl*/
                    421:                highseq = MIN(tpcb->tp_fcredit, tpcb->tp_cong_win); 
                    422:        } else {
                    423:                highseq = tpcb->tp_fcredit;
                    424:        }
                    425:        highseq = SEQ(tpcb, tpcb->tp_snduna + highseq);
                    426:                
                    427:        SEQ_DEC(tpcb, highseq);
                    428: 
                    429:        IFDEBUG(D_DATA)
                    430:                printf( 
                    431:                        "tp_send enter tpcb 0x%x l %d -> h %d\ndump of sb_mb:\n",
                    432:                        tpcb, lowseq, highseq);
                    433:                dump_mbuf(sb->sb_mb, "sb_mb:");
                    434:        ENDDEBUG
                    435:        IFTRACE(D_DATA)
                    436:                tptraceTPCB( TPPTmisc, "tp_send lowsave sndhiwat snduna", 
                    437:                        lowsave, tpcb->tp_sndhiwat,  tpcb->tp_snduna, 0);
                    438:                tptraceTPCB( TPPTmisc, "tp_send low high fcredit congwin", 
                    439:                        lowseq, highseq, tpcb->tp_fcredit,  tpcb->tp_cong_win);
                    440:        ENDTRACE
                    441: 
                    442: 
                    443:        if      ( SEQ_GT(tpcb, lowseq, highseq) )
                    444:                        return ; /* don't send, don't change hiwat, don't set timers */
                    445: 
                    446:        IFPERF(tpcb)
                    447:                GET_CUR_TIME(&send_start_time);
                    448:        ENDPERF
                    449: 
                    450:        ASSERT( SEQ_LEQ(tpcb, lowseq, highseq) );
                    451:        SEQ_DEC(tpcb, lowseq);
                    452: 
                    453:        IFTRACE(D_DATA)
                    454:                tptraceTPCB( TPPTmisc, "tp_send 2 low high fcredit congwin", 
                    455:                        lowseq, highseq, tpcb->tp_fcredit,  tpcb->tp_cong_win);
                    456:        ENDTRACE
                    457: 
                    458:        while ((SEQ_LT(tpcb, lowseq, highseq)) && (mb = m = sb->sb_mb)) {
                    459:                if (tpcb->tp_Xsnd.sb_mb) {
                    460:                        IFTRACE(D_XPD)
                    461:                                tptraceTPCB( TPPTmisc,
                    462:                                        "tp_send XPD mark low high tpcb.Xuna", 
                    463:                                        lowseq, highseq, tpcb->tp_Xsnd.sb_mb, 0);
                    464:                        ENDTRACE
                    465:                        /* stop sending here because there are unacked XPD which were 
                    466:                         * given to us before the next data were.
                    467:                         */
                    468:                        IncStat(ts_xpd_intheway);
                    469:                        break;
                    470:                }
                    471:                eotsdu_reached = 0;
                    472:                nextrecord = m->m_act;
                    473:                for (len = 0; m; m = m->m_next) {
                    474:                        len += m->m_len; 
                    475:                        if (m->m_flags & M_EOR)
                    476:                                eotsdu_reached = 1;
                    477:                        sbfree(sb, m); /* reduce counts in socket buffer */
                    478:                }
                    479:                sb->sb_mb = nextrecord;
                    480:                IFTRACE(D_STASH)
                    481:                        tptraceTPCB(TPPTmisc, "tp_send whole mbuf: m_len len maxsize",
                    482:                                 0, mb->m_len, len, maxsize);
                    483:                ENDTRACE
                    484: 
                    485:                if ( len == 0 && !eotsdu_reached) {
                    486:                        /* THIS SHOULD NEVER HAPPEN! */
                    487:                        ASSERT( 0 );
                    488:                        goto done;
                    489:                }
                    490: 
                    491:                /* If we arrive here one of the following holds:
                    492:                 * 1. We have exactly <maxsize> octets of whole mbufs,
                    493:                 * 2. We accumulated <maxsize> octets using partial mbufs,
                    494:                 * 3. We found an TPMT_EOT or an XPD mark 
                    495:                 * 4. We hit the end of a chain through m_next.
                    496:                 *    In this case, we'd LIKE to continue with the next record,
                    497:                 *    but for the time being, for simplicity, we'll stop here.
                    498:                 * In all cases, m points to mbuf containing first octet to be
                    499:                 * sent in the tpdu AFTER the one we're going to send now,
                    500:                 * or else m is null.
                    501:                 *
                    502:                 * The chain we're working on now begins at mb and has length <len>.
                    503:                 */
                    504: 
                    505:                IFTRACE(D_STASH)
                    506:                        tptraceTPCB( TPPTmisc, 
                    507:                                "tp_send mcopy low high eotsdu_reached len", 
                    508:                                lowseq, highseq, eotsdu_reached, len);
                    509:                ENDTRACE
                    510: 
                    511:                /* make a copy - mb goes into the retransmission list 
                    512:                 * while m gets emitted.  m_copy won't copy a zero-length mbuf.
                    513:                 */
                    514:                if (len) {
                    515:                        if ((m = m_copy(mb, 0, len )) == MNULL)
                    516:                                goto done;
                    517:                } else {
                    518:                        /* eotsdu reached */
                    519:                        MGET(m, M_WAIT, TPMT_DATA);
                    520:                        if (m == MNULL)
                    521:                                goto done;
                    522:                        m->m_len = 0;
                    523:                }
                    524: 
                    525:                SEQ_INC(tpcb,lowseq);   /* it was decremented at the beginning */
                    526:                {
                    527:                        struct tp_rtc *t;
                    528:                        /* make an rtc and put it at the end of the chain */
                    529: 
                    530:                        TP_MAKE_RTC( t, lowseq, eotsdu_reached, mb, len, lowseq, 
                    531:                                TPMT_SNDRTC);
                    532:                        t->tprt_next = (struct tp_rtc *)0;
                    533: 
                    534:                        if ( tpcb->tp_sndhiwat_rtc != (struct tp_rtc *)0 )
                    535:                                tpcb->tp_sndhiwat_rtc->tprt_next = t;
                    536:                        else {
                    537:                                ASSERT( tpcb->tp_snduna_rtc == (struct tp_rtc *)0 );
                    538:                                tpcb->tp_snduna_rtc = t;
                    539:                        }
                    540: 
                    541:                        tpcb->tp_sndhiwat_rtc = t;
                    542:                }
                    543: 
                    544:                IFTRACE(D_DATA)
                    545:                        tptraceTPCB( TPPTmisc, 
                    546:                                "tp_send emitting DT lowseq eotsdu_reached len",
                    547:                                lowseq, eotsdu_reached, len, 0);
                    548:                ENDTRACE
                    549:                if( tpcb->tp_sock->so_error =
                    550:                        tp_emit(DT_TPDU_type, tpcb, lowseq, eotsdu_reached, m) )  {
                    551:                        /* error */
                    552:                        SEQ_DEC(tpcb, lowseq); 
                    553:                        goto done;
                    554:                }
                    555:                /* set the transmit-time for computation of round-trip times */
                    556:                bcopy( (caddr_t)&time, 
                    557:                                (caddr_t)&( tpcb->tp_rttemit[ lowseq & TP_RTT_NUM ] ), 
                    558:                                sizeof(struct timeval));
                    559: 
                    560:        }
                    561: 
                    562: done:
                    563:        IFPERF(tpcb)
                    564:                {
                    565:                        register int npkts;
                    566:                        struct timeval send_end_time;
                    567:                        register struct timeval *t;
                    568: 
                    569:                        npkts = lowseq;
                    570:                        SEQ_INC(tpcb, npkts);
                    571:                        npkts = SEQ_SUB(tpcb, npkts, lowsave);
                    572: 
                    573:                        if(npkts > 0) 
                    574:                                tpcb->tp_Nwindow++;
                    575: 
                    576:                        if (npkts > TP_PM_MAX) 
                    577:                                npkts = TP_PM_MAX; 
                    578: 
                    579:                        GET_TIME_SINCE(&send_start_time, &send_end_time);
                    580:                        t = &(tpcb->tp_p_meas->tps_sendtime[npkts]);
                    581:                        t->tv_sec =
                    582:                                SMOOTH( long, TP_RTT_ALPHA, t->tv_sec, send_end_time.tv_sec);
                    583:                        t->tv_usec =
                    584:                                SMOOTH( long, TP_RTT_ALPHA, t->tv_usec, send_end_time.tv_usec);
                    585: 
                    586:                        if ( SEQ_LT(tpcb, lowseq, highseq) ) {
                    587:                                IncPStat(tpcb, tps_win_lim_by_data[npkts] );
                    588:                        } else {
                    589:                                IncPStat(tpcb, tps_win_lim_by_cdt[npkts] );
                    590:                                /* not true with congestion-window being used */
                    591:                        }
                    592:                        tpmeas( tpcb->tp_lref, 
                    593:                                        TPsbsend, &send_end_time, lowsave, tpcb->tp_Nwindow, npkts);
                    594:                }
                    595:        ENDPERF
                    596: 
                    597:        tpcb->tp_sndhiwat = lowseq;
                    598: 
                    599:        if ( SEQ_LEQ(tpcb, lowsave, tpcb->tp_sndhiwat)  && 
                    600:                        (tpcb->tp_class != TP_CLASS_0) ) 
                    601:                        tp_etimeout(tpcb->tp_refp, TM_data_retrans, lowsave, 
                    602:                                tpcb->tp_sndhiwat,
                    603:                                (u_int)tpcb->tp_Nretrans, (int)tpcb->tp_dt_ticks);
                    604:        IFTRACE(D_DATA)
                    605:                tptraceTPCB( TPPTmisc, 
                    606:                        "tp_send at end: sndhiwat lowseq eotsdu_reached error",
                    607:                        tpcb->tp_sndhiwat, lowseq, eotsdu_reached, tpcb->tp_sock->so_error);
                    608:                
                    609:        ENDTRACE
                    610: }
                    611: 
                    612: /*
                    613:  * NAME: tp_stash()
                    614:  * CALLED FROM:
                    615:  *     tp.trans on arrival of a DT tpdu
                    616:  * FUNCTION, ARGUMENTS, and RETURN VALUE:
                    617:  *     Returns 1 if 
                    618:  *             a) something new arrived and it's got eotsdu_reached bit on,
                    619:  *             b) this arrival was caused other out-of-sequence things to be
                    620:  *     accepted, or
                    621:  *             c) this arrival is the highest seq # for which we last gave credit
                    622:  *     (sender just sent a whole window)
                    623:  *  In other words, returns 1 if tp should send an ack immediately, 0 if 
                    624:  *  the ack can wait a while.
                    625:  *
                    626:  * Note: this implementation no longer renegs on credit, (except
                    627:  * when debugging option D_RENEG is on, for the purpose of testing
                    628:  * ack subsequencing), so we don't  need to check for incoming tpdus 
                    629:  * being in a reneged portion of the window.
                    630:  */
                    631: 
                    632: int
                    633: tp_stash( tpcb, e )
                    634:        register struct tp_pcb          *tpcb;
                    635:        register struct tp_event        *e;
                    636: {
                    637:        register int            ack_reason= tpcb->tp_ack_strat & ACK_STRAT_EACH;
                    638:                                                                        /* 0--> delay acks until full window */
                    639:                                                                        /* 1--> ack each tpdu */
                    640:        int             newrec = 0;
                    641: 
                    642: #ifndef lint
                    643: #define E e->ATTR(DT_TPDU)
                    644: #else lint
                    645: #define E e->ev_union.EV_DT_TPDU
                    646: #endif lint
                    647: 
                    648:        if ( E.e_eot ) {
                    649:                register struct mbuf *n = E.e_data;
                    650:                n->m_flags |= M_EOR;
                    651:                n->m_act = 0;
                    652:        }
                    653:                IFDEBUG(D_STASH)
                    654:                        dump_mbuf(tpcb->tp_sock->so_rcv.sb_mb, 
                    655:                                "stash: so_rcv before appending");
                    656:                        dump_mbuf(E.e_data,
                    657:                                "stash: e_data before appending");
                    658:                ENDDEBUG
                    659: 
                    660:        IFPERF(tpcb)
                    661:                PStat(tpcb, Nb_from_ll) += E.e_datalen;
                    662:                tpmeas(tpcb->tp_lref, TPtime_from_ll, &e->e_time,
                    663:                        E.e_seq, (u_int)PStat(tpcb, Nb_from_ll), (u_int)E.e_datalen);
                    664:        ENDPERF
                    665: 
                    666:        if( E.e_seq == tpcb->tp_rcvnxt ) {
                    667: 
                    668:                IFDEBUG(D_STASH)
                    669:                        printf("stash EQ: seq 0x%x datalen 0x%x eot 0x%x\n", 
                    670:                        E.e_seq, E.e_datalen, E.e_eot);
                    671:                ENDDEBUG
                    672: 
                    673:                IFTRACE(D_STASH)
                    674:                        tptraceTPCB(TPPTmisc, "stash EQ: seq len eot", 
                    675:                        E.e_seq, E.e_datalen, E.e_eot, 0);
                    676:                ENDTRACE
                    677: 
                    678:                sbappend(&tpcb->tp_sock->so_rcv, E.e_data);
                    679: 
                    680:                if (newrec = E.e_eot ) /* ASSIGNMENT */
                    681:                        ack_reason |= ACK_EOT;
                    682: 
                    683:                SEQ_INC( tpcb, tpcb->tp_rcvnxt );
                    684:                /* 
                    685:                 * move chains from the rtc list to the socket buffer
                    686:                 * and free the rtc header
                    687:                 */
                    688:                {
                    689:                        register struct tp_rtc  **r =  &tpcb->tp_rcvnxt_rtc;
                    690:                        register struct tp_rtc  *s = tpcb->tp_rcvnxt_rtc;
                    691: 
                    692:                        while (s != (struct tp_rtc *)0 && s->tprt_seq == tpcb->tp_rcvnxt) {
                    693:                                *r = s->tprt_next;
                    694: 
                    695:                                sbappend(&tpcb->tp_sock->so_rcv, s->tprt_data);
                    696: 
                    697:                                SEQ_INC( tpcb, tpcb->tp_rcvnxt );
                    698: 
                    699:                                (void) m_free( dtom( s ) );
                    700:                                s = *r;
                    701:                                ack_reason |= ACK_REORDER;
                    702:                        }
                    703:                }
                    704:                IFDEBUG(D_STASH)
                    705:                        dump_mbuf(tpcb->tp_sock->so_rcv.sb_mb, 
                    706:                                "stash: so_rcv after appending");
                    707:                ENDDEBUG
                    708: 
                    709:        } else {
                    710:                register struct tp_rtc **s = &tpcb->tp_rcvnxt_rtc;
                    711:                register struct tp_rtc *r = tpcb->tp_rcvnxt_rtc;
                    712:                register struct tp_rtc *t;
                    713: 
                    714:                IFTRACE(D_STASH)
                    715:                        tptraceTPCB(TPPTmisc, "stash Reseq: seq rcvnxt lcdt", 
                    716:                        E.e_seq, tpcb->tp_rcvnxt, tpcb->tp_lcredit, 0);
                    717:                ENDTRACE
                    718: 
                    719:                r = tpcb->tp_rcvnxt_rtc;
                    720:                while (r != (struct tp_rtc *)0  && SEQ_LT(tpcb, r->tprt_seq, E.e_seq)) {
                    721:                        s = &r->tprt_next;
                    722:                        r = r->tprt_next;
                    723:                }
                    724: 
                    725:                if (r == (struct tp_rtc *)0 || SEQ_GT(tpcb, r->tprt_seq, E.e_seq) ) {
                    726:                        IncStat(ts_dt_ooo);
                    727: 
                    728:                        IFTRACE(D_STASH)
                    729:                                tptrace(TPPTmisc,
                    730:                                "tp_stash OUT OF ORDER- MAKE RTC: seq, 1st seq in list\n",
                    731:                                        E.e_seq, r->tprt_seq,0,0);
                    732:                        ENDTRACE
                    733:                        IFDEBUG(D_STASH)
                    734:                                printf("tp_stash OUT OF ORDER- MAKE RTC\n");
                    735:                        ENDDEBUG
                    736:                        TP_MAKE_RTC(t, E.e_seq, E.e_eot, E.e_data, E.e_datalen, 0,
                    737:                                TPMT_RCVRTC);
                    738: 
                    739:                        *s = t;
                    740:                        t->tprt_next = (struct tp_rtc *)r;
                    741:                        ack_reason = ACK_DONT;
                    742:                        goto done;
                    743:                } else {
                    744:                        IFDEBUG(D_STASH)
                    745:                                printf("tp_stash - drop & ack\n");
                    746:                        ENDDEBUG
                    747: 
                    748:                        /* retransmission - drop it and force an ack */
                    749:                        IncStat(ts_dt_dup);
                    750:                        IFPERF(tpcb)
                    751:                                IncPStat(tpcb, tps_n_ack_cuz_dup);
                    752:                        ENDPERF
                    753: 
                    754:                        m_freem( E.e_data );
                    755:                        ack_reason |= ACK_DUP;
                    756:                        goto done;
                    757:                }
                    758:        }
                    759: 
                    760: 
                    761:        /*
                    762:         * an ack should be sent when at least one of the
                    763:         * following holds:
                    764:         * a) we've received a TPDU with EOTSDU set
                    765:         * b) the TPDU that just arrived represents the
                    766:         *    full window last advertised, or
                    767:         * c) when seq X arrives [ where
                    768:         *              X = last_sent_uwe - 1/2 last_lcredit_sent 
                    769:         *              (the packet representing 1/2 the last advertised window) ]
                    770:         *              and lcredit at the time of X arrival >  last_lcredit_sent/2
                    771:         *              In other words, if the last ack sent advertised cdt=8 and uwe = 8
                    772:         *              then when seq 4 arrives I'd like to send a new ack
                    773:         *              iff the credit at the time of 4's arrival is > 4.
                    774:         *              The other end thinks it has cdt of 4 so if local cdt
                    775:         *              is still 4 there's no point in sending an ack, but if
                    776:         *              my credit has increased because the receiver has taken
                    777:         *              some data out of the buffer (soreceive doesn't notify
                    778:         *              me until the SYSTEM CALL finishes), I'd like to tell
                    779:         *              the other end.  
                    780:         */
                    781: 
                    782: done:
                    783:        {
                    784:                LOCAL_CREDIT(tpcb);
                    785: 
                    786:                if ( E.e_seq ==  tpcb->tp_sent_uwe )
                    787:                        ack_reason |= ACK_STRAT_FULLWIN;
                    788: 
                    789:                IFTRACE(D_STASH)
                    790:                        tptraceTPCB(TPPTmisc, 
                    791:                                "end of stash, eot, ack_reason, sent_uwe ",
                    792:                                E.e_eot, ack_reason, tpcb->tp_sent_uwe, 0); 
                    793:                ENDTRACE
                    794: 
                    795:                if ( ack_reason == ACK_DONT ) {
                    796:                        IncStat( ts_ackreason[ACK_DONT] );
                    797:                        return 0;
                    798:                } else {
                    799:                        IFPERF(tpcb)
                    800:                                if(ack_reason & ACK_EOT) {
                    801:                                        IncPStat(tpcb, tps_n_ack_cuz_eot);
                    802:                                } 
                    803:                                if(ack_reason & ACK_STRAT_EACH) {
                    804:                                        IncPStat(tpcb, tps_n_ack_cuz_strat);
                    805:                                } else if(ack_reason & ACK_STRAT_FULLWIN) {
                    806:                                        IncPStat(tpcb, tps_n_ack_cuz_fullwin);
                    807:                                } else if(ack_reason & ACK_REORDER) {
                    808:                                        IncPStat(tpcb, tps_n_ack_cuz_reorder);
                    809:                                }
                    810:                                tpmeas(tpcb->tp_lref, TPtime_ack_sent, 0, 
                    811:                                                        SEQ_ADD(tpcb, E.e_seq, 1), 0, 0);
                    812:                        ENDPERF
                    813:                        {
                    814:                                register int i;
                    815: 
                    816:                                /* keep track of all reasons that apply */
                    817:                                for( i=1; i<_ACK_NUM_REASONS_ ;i++) {
                    818:                                        if( ack_reason & (1<<i) ) 
                    819:                                                IncStat( ts_ackreason[i] );
                    820:                                }
                    821:                        }
                    822:                        return 1;
                    823:                }
                    824:        }
                    825: }
                    826: 
                    827: /* class zero version */
                    828: void
                    829: tp0_stash( tpcb, e )
                    830:        register struct tp_pcb          *tpcb;
                    831:        register struct tp_event        *e;
                    832: {
                    833: #ifndef lint
                    834: #define E e->ATTR(DT_TPDU)
                    835: #else lint
                    836: #define E e->ev_union.EV_DT_TPDU
                    837: #endif lint
                    838: 
                    839:        IFPERF(tpcb)
                    840:                PStat(tpcb, Nb_from_ll) += E.e_datalen;
                    841:                tpmeas(tpcb->tp_lref, TPtime_from_ll, &e->e_time,
                    842:                                E.e_seq, PStat(tpcb, Nb_from_ll), E.e_datalen);
                    843:        ENDPERF
                    844: 
                    845:        IFDEBUG(D_STASH)
                    846:                printf("stash EQ: seq 0x%x datalen 0x%x eot 0x%x", 
                    847:                E.e_seq, E.e_datalen, E.e_eot);
                    848:        ENDDEBUG
                    849: 
                    850:        IFTRACE(D_STASH)
                    851:                tptraceTPCB(TPPTmisc, "stash EQ: seq len eot", 
                    852:                E.e_seq, E.e_datalen, E.e_eot, 0);
                    853:        ENDTRACE
                    854: 
                    855:        if ( E.e_eot ) {
                    856:                register struct mbuf *n = E.e_data;
                    857:                n->m_flags |= M_EOR;
                    858:                n->m_act = MNULL; /* set on tp_input */
                    859:        }
                    860:        sbappend(&tpcb->tp_sock->so_rcv, E.e_data);
                    861:        IFDEBUG(D_STASH)
                    862:                dump_mbuf(tpcb->tp_sock->so_rcv.sb_mb, 
                    863:                        "stash 0: so_rcv after appending");
                    864:        ENDDEBUG
                    865: } 

unix.superglobalmegacorp.com

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