~jderose/ubuntu/raring/qemu/vde-again

« back to all changes in this revision

Viewing changes to slirp/tcp_output.c

  • Committer: Bazaar Package Importer
  • Author(s): Aurelien Jarno, Aurelien Jarno
  • Date: 2008-08-25 04:38:35 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20080825043835-8e3tftavy8bujdch
Tags: 0.9.1-6
[ Aurelien Jarno ]
* debian/control: 
  - Update list of supported targets (Closes: bug#488339).
* debian/qemu-make-debian-root:
  - Use mktemp instead of $$ to create temporary directories (Closes: 
    bug#496394).
* debian/links:
  - Add missing links to manpages.

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