~vcs-imports/qemu/git

« back to all changes in this revision

Viewing changes to slirp/tcp_output.c

  • Committer: pbrook
  • Date: 2006-10-22 00:18:54 UTC
  • Revision ID: git-v1:e6e5906b6e0a81718066ca43aef57515026c6624
ColdFire target.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2196 c046a42c-6fe2-441c-8c8c-71466251a162

Show diffs side-by-side

added added

removed removed

Lines of Context:
37
37
/*
38
38
 * Changes and additions relating to SLiRP
39
39
 * Copyright (c) 1995 Danny Gasparovski.
40
 
 *
41
 
 * Please read the file COPYRIGHT for the
 
40
 * 
 
41
 * Please read the file COPYRIGHT for the 
42
42
 * terms and conditions of the copyright.
43
43
 */
44
44
 
48
48
 * Since this is only used in "stats socket", we give meaning
49
49
 * names instead of the REAL names
50
50
 */
51
 
const char * const tcpstates[] = {
 
51
char *tcpstates[] = {
52
52
/*      "CLOSED",       "LISTEN",       "SYN_SENT",     "SYN_RCVD", */
53
53
        "REDIRECT",     "LISTEN",       "SYN_SENT",     "SYN_RCVD",
54
54
        "ESTABLISHED",  "CLOSE_WAIT",   "FIN_WAIT_1",   "CLOSING",
55
55
        "LAST_ACK",     "FIN_WAIT_2",   "TIME_WAIT",
56
56
};
57
57
 
58
 
static const u_char  tcp_outflags[TCP_NSTATES] = {
 
58
u_char  tcp_outflags[TCP_NSTATES] = {
59
59
        TH_RST|TH_ACK, 0,      TH_SYN,        TH_SYN|TH_ACK,
60
 
        TH_ACK,        TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK,
 
60
        TH_ACK,        TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK, 
61
61
        TH_FIN|TH_ACK, TH_ACK, TH_ACK,
62
62
};
63
63
 
79
79
        u_char opt[MAX_TCPOPTLEN];
80
80
        unsigned optlen, hdrlen;
81
81
        int idle, sendalot;
82
 
 
 
82
        
83
83
        DEBUG_CALL("tcp_output");
84
84
        DEBUG_ARG("tp = %lx", (long )tp);
85
 
 
 
85
        
86
86
        /*
87
87
         * Determine length of data that should be transmitted,
88
88
         * and flags that will be used.
103
103
        win = min(tp->snd_wnd, tp->snd_cwnd);
104
104
 
105
105
        flags = tcp_outflags[tp->t_state];
106
 
 
 
106
        
107
107
        DEBUG_MISC((dfd, " --- tcp_output flags = 0x%x\n",flags));
108
 
 
 
108
        
109
109
        /*
110
110
         * If in persist timeout with window of 0, send 1 byte.
111
111
         * Otherwise, if window is small but nonzero
158
158
                        tp->snd_nxt = tp->snd_una;
159
159
                }
160
160
        }
161
 
 
 
161
        
162
162
        if (len > tp->t_maxseg) {
163
163
                len = tp->t_maxseg;
164
164
                sendalot = 1;
200
200
         * window, then want to send a window update to peer.
201
201
         */
202
202
        if (win > 0) {
203
 
                /*
 
203
                /* 
204
204
                 * "adv" is the amount we can increase the window,
205
205
                 * taking into account that we are limited by
206
206
                 * TCP_MAXWIN << tp->rcv_scale.
263
263
        /*
264
264
         * No reason to send a segment, just return.
265
265
         */
266
 
        STAT(tcpstat.tcps_didnuttin++);
267
 
 
 
266
        tcpstat.tcps_didnuttin++;
 
267
        
268
268
        return (0);
269
269
 
270
270
send:
302
302
 */
303
303
                }
304
304
        }
305
 
 
 
305
 
306
306
        /*
307
 
         * Send a timestamp and echo-reply if this is a SYN and our side
 
307
         * Send a timestamp and echo-reply if this is a SYN and our side 
308
308
         * wants to use timestamps (TF_REQ_TSTMP is set) or both our side
309
309
         * and our peer have sent timestamps in our SYN's.
310
310
         */
322
322
 *      }
323
323
 */
324
324
        hdrlen += optlen;
325
 
 
 
325
 
326
326
        /*
327
327
         * Adjust data length if insertion of options will
328
328
         * bump the packet length beyond the t_maxseg length.
339
339
         */
340
340
        if (len) {
341
341
                if (tp->t_force && len == 1)
342
 
                        STAT(tcpstat.tcps_sndprobe++);
 
342
                        tcpstat.tcps_sndprobe++;
343
343
                else if (SEQ_LT(tp->snd_nxt, tp->snd_max)) {
344
 
                        STAT(tcpstat.tcps_sndrexmitpack++);
345
 
                        STAT(tcpstat.tcps_sndrexmitbyte += len);
 
344
                        tcpstat.tcps_sndrexmitpack++;
 
345
                        tcpstat.tcps_sndrexmitbyte += len;
346
346
                } else {
347
 
                        STAT(tcpstat.tcps_sndpack++);
348
 
                        STAT(tcpstat.tcps_sndbyte += len);
 
347
                        tcpstat.tcps_sndpack++;
 
348
                        tcpstat.tcps_sndbyte += len;
349
349
                }
350
350
 
351
351
                m = m_get();
354
354
                        error = 1;
355
355
                        goto out;
356
356
                }
357
 
                m->m_data += IF_MAXLINKHDR;
 
357
                m->m_data += if_maxlinkhdr;
358
358
                m->m_len = hdrlen;
359
 
 
360
 
                /*
 
359
                
 
360
                /* 
361
361
                 * This will always succeed, since we make sure our mbufs
362
362
                 * are big enough to hold one MSS packet + header + ... etc.
363
363
                 */
382
382
                        flags |= TH_PUSH;
383
383
        } else {
384
384
                if (tp->t_flags & TF_ACKNOW)
385
 
                        STAT(tcpstat.tcps_sndacks++);
 
385
                        tcpstat.tcps_sndacks++;
386
386
                else if (flags & (TH_SYN|TH_FIN|TH_RST))
387
 
                        STAT(tcpstat.tcps_sndctrl++);
 
387
                        tcpstat.tcps_sndctrl++;
388
388
                else if (SEQ_GT(tp->snd_up, tp->snd_una))
389
 
                        STAT(tcpstat.tcps_sndurg++);
 
389
                        tcpstat.tcps_sndurg++;
390
390
                else
391
 
                        STAT(tcpstat.tcps_sndwinup++);
 
391
                        tcpstat.tcps_sndwinup++;
392
392
 
393
393
                m = m_get();
394
394
                if (m == NULL) {
396
396
                        error = 1;
397
397
                        goto out;
398
398
                }
399
 
                m->m_data += IF_MAXLINKHDR;
 
399
                m->m_data += if_maxlinkhdr;
400
400
                m->m_len = hdrlen;
401
401
        }
402
402
 
403
403
        ti = mtod(m, struct tcpiphdr *);
404
 
 
 
404
        
405
405
        memcpy((caddr_t)ti, &tp->t_template, sizeof (struct tcpiphdr));
406
406
 
407
407
        /*
409
409
         * window for use in delaying messages about window sizes.
410
410
         * If resending a FIN, be sure not to use a new sequence number.
411
411
         */
412
 
        if (flags & TH_FIN && tp->t_flags & TF_SENTFIN &&
 
412
        if (flags & TH_FIN && tp->t_flags & TF_SENTFIN && 
413
413
            tp->snd_nxt == tp->snd_max)
414
414
                tp->snd_nxt--;
415
415
        /*
446
446
        if (win < (long)(tp->rcv_adv - tp->rcv_nxt))
447
447
                win = (long)(tp->rcv_adv - tp->rcv_nxt);
448
448
        ti->ti_win = htons((u_int16_t) (win>>tp->rcv_scale));
449
 
 
 
449
        
450
450
        if (SEQ_GT(tp->snd_up, tp->snd_una)) {
451
451
                ti->ti_urp = htons((u_int16_t)(tp->snd_up - ntohl(ti->ti_seq)));
452
 
#ifdef notdef
 
452
#ifdef notdef           
453
453
        if (SEQ_GT(tp->snd_up, tp->snd_nxt)) {
454
454
                ti->ti_urp = htons((u_int16_t)(tp->snd_up - tp->snd_nxt));
455
455
#endif
500
500
                        if (tp->t_rtt == 0) {
501
501
                                tp->t_rtt = 1;
502
502
                                tp->t_rtseq = startseq;
503
 
                                STAT(tcpstat.tcps_segstimed++);
 
503
                                tcpstat.tcps_segstimed++;
504
504
                        }
505
505
                }
506
506
 
531
531
         * the template, but need a way to checksum without them.
532
532
         */
533
533
        m->m_len = hdrlen + len; /* XXX Needed? m_len should be correct */
534
 
 
 
534
        
535
535
    {
536
 
 
 
536
            
537
537
        ((struct ip *)ti)->ip_len = m->m_len;
538
538
 
539
 
        ((struct ip *)ti)->ip_ttl = IPDEFTTL;
 
539
        ((struct ip *)ti)->ip_ttl = ip_defttl;
540
540
        ((struct ip *)ti)->ip_tos = so->so_iptos;
541
 
 
 
541
            
542
542
/* #if BSD >= 43 */
543
543
        /* Don't do IP options... */
544
544
/*      error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route,
547
547
        error = ip_output(so, m);
548
548
 
549
549
/* #else
550
 
 *      error = ip_output(m, (struct mbuf *)0, &tp->t_inpcb->inp_route,
 
550
 *      error = ip_output(m, (struct mbuf *)0, &tp->t_inpcb->inp_route, 
551
551
 *          so->so_options & SO_DONTROUTE);
552
552
 * #endif
553
553
 */
567
567
 */
568
568
                return (error);
569
569
        }
570
 
        STAT(tcpstat.tcps_sndtotal++);
 
570
        tcpstat.tcps_sndtotal++;
571
571
 
572
572
        /*
573
573
         * Data sent (as far as we can tell).