]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lwip.git/blob - src/core/tcp_out.c
patches 1492, 1493 and 1494 from Marc
[pes-rpp/rpp-lwip.git] / src / core / tcp_out.c
1 /**
2  * @file
3  *
4  * Transmission Control Protocol, outgoing traffic
5  */
6 /*
7  * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
8  * All rights reserved. 
9  * 
10  * Redistribution and use in source and binary forms, with or without modification, 
11  * are permitted provided that the following conditions are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright notice,
14  *    this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright notice,
16  *    this list of conditions and the following disclaimer in the documentation
17  *    and/or other materials provided with the distribution.
18  * 3. The name of the author may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission. 
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
22  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
23  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
24  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
26  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
29  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
30  * OF SUCH DAMAGE.
31  *
32  * This file is part of the lwIP TCP/IP stack.
33  * 
34  * Author: Adam Dunkels <adam@sics.se>
35  *
36  */
37
38 /*-----------------------------------------------------------------------------------*/
39 /* tcp_output.c
40  *
41  * The output functions of TCP.
42  *
43  */
44 /*-----------------------------------------------------------------------------------*/
45
46
47 #include "lwip/def.h"
48 #include "lwip/opt.h"
49
50 #include "lwip/mem.h"
51 #include "lwip/memp.h"
52 #include "lwip/sys.h"
53
54 #include "lwip/netif.h"
55
56 #include "lwip/inet.h"
57 #include "lwip/tcp.h"
58
59 #include "lwip/stats.h"
60
61 #if LWIP_TCP
62 #define LWIP_MIN(x,y) (x) < (y)? (x): (y)
63
64
65
66 /* Forward declarations.*/
67 static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb);
68
69
70 /*-----------------------------------------------------------------------------------*/
71 err_t
72 tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags)
73 {
74   return tcp_enqueue(pcb, NULL, 0, flags, 1, NULL, 0);
75
76 }
77 /*-----------------------------------------------------------------------------------*/
78 err_t
79 tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy)
80 {
81   DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, arg=%p, len=%u, copy=%d)\n", (void *)pcb, arg, len, copy));
82   if (pcb->state == SYN_SENT ||
83      pcb->state == SYN_RCVD ||
84      pcb->state == ESTABLISHED ||
85      pcb->state == CLOSE_WAIT) {
86     if (len > 0) {
87       return tcp_enqueue(pcb, (void *)arg, len, 0, copy, NULL, 0);
88     }
89     return ERR_OK;
90   } else {
91     DEBUGF(TCP_OUTPUT_DEBUG | DBG_STATE | 3, ("tcp_write() called in invalid state\n"));
92     return ERR_CONN;
93   }
94 }
95 /*-----------------------------------------------------------------------------------*/
96 err_t
97 tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
98             u8_t flags, u8_t copy,
99             u8_t *optdata, u8_t optlen)
100 {
101   struct pbuf *p;
102   struct tcp_seg *seg, *useg, *queue;
103   u32_t left, seqno;
104   u16_t seglen;
105   void *ptr;
106   u8_t queuelen;
107
108   DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue(pcb=%p, arg=%p, len=%u, flags=%x, copy=%d)\n", (void *)pcb, arg, len, flags, copy));
109   left = len;
110   ptr = arg;
111   /* fail on too much data */
112   if (len > pcb->snd_buf) {
113     DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too much data (len=%d > snd_buf=%d)\n", len, pcb->snd_buf));
114     return ERR_MEM;
115   }
116
117   /* seqno will be the sequence number of the first segment enqueued
118   by the call to this function. */
119   seqno = pcb->snd_lbb;
120
121     queue = NULL;
122   DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: queuelen: %d\n", pcb->snd_queuelen));
123
124   /* Check if the queue length exceeds the configured maximum queue
125   length. If so, we return an error. */
126   queuelen = pcb->snd_queuelen;
127   if (queuelen >= TCP_SND_QUEUELEN) {
128     DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too long queue %d (max %d)\n", queuelen, TCP_SND_QUEUELEN));
129     goto memerr;
130   }   
131
132   if (pcb->snd_queuelen != 0) {
133     LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
134     pcb->unsent != NULL);      
135   }
136
137   seg = NULL;
138   seglen = 0;
139
140   /* First, break up the data into segments and tuck them together in
141   the local "queue" variable. */
142   while (queue == NULL || left > 0) {
143
144     /* The segment length should be the MSS if the data to be enqueued
145     is larger than the MSS. */
146     seglen = left > pcb->mss? pcb->mss: left;
147
148     /* Allocate memory for tcp_seg, and fill in fields. */
149     seg = memp_malloc(MEMP_TCP_SEG);
150     if (seg == NULL) {
151       DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: could not allocate memory for tcp_seg\n"));
152       goto memerr;
153     }
154     seg->next = NULL;
155     seg->p = NULL;
156
157     if (queue == NULL) {
158       queue = seg;
159     }
160     else {
161       /* Attach the segment to the end of the queued segments. */
162       for(useg = queue; useg->next != NULL; useg = useg->next);
163       useg->next = seg;
164     }
165
166     /* If copy is set, memory should be allocated
167     and data copied into pbuf, otherwise data comes from
168     ROM or other static memory, and need not be copied. If
169     optdata is != NULL, we have options instead of data. */
170     if (optdata != NULL) {
171       if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
172         goto memerr;
173       }
174       ++queuelen;
175       seg->dataptr = seg->p->payload;
176     }
177     else if (copy) {
178       if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_RAM)) == NULL) {
179         DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue : could not allocate memory for pbuf copy size %u\n", seglen));        
180         goto memerr;
181       }
182       ++queuelen;
183       if (arg != NULL) {
184         memcpy(seg->p->payload, ptr, seglen);
185       }
186       seg->dataptr = seg->p->payload;
187     }
188     /* do not copy data */
189     else {
190
191       /* first, allocate a pbuf for holding the data.
192        * since the referenced data is available at least until it is sent out on the
193        * link (as it has to be ACKed by the remote party) we can safely use PBUF_ROM
194        * instead of PBUF_REF here.
195        */
196       if ((p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_ROM)) == NULL) {
197         DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: could not allocate memory for zero-copy pbuf\n"));            
198         goto memerr;
199       }
200       ++queuelen;
201       p->payload = ptr;
202       seg->dataptr = ptr;
203
204       /* Second, allocate a pbuf for the headers. */
205       if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_RAM)) == NULL) {
206         /* If allocation fails, we have to deallocate the data pbuf as
207            well. */
208         pbuf_free(p);
209         DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: could not allocate memory for header pbuf\n"));               
210         goto memerr;
211       }
212       ++queuelen;
213
214       /* Chain the headers and data pbufs together. */
215       pbuf_chain(seg->p, p);
216       pbuf_free(p);
217     }
218
219     /* Now that there are more segments queued, we check again if the
220     length of the queue exceeds the configured maximum. */
221     if (queuelen > TCP_SND_QUEUELEN) {
222       DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: queue too long %d (%d)\n", queuelen, TCP_SND_QUEUELEN));      
223       goto memerr;
224     }
225
226     seg->len = seglen;
227     /*    if ((flags & TCP_SYN) || (flags & TCP_FIN)) { 
228     ++seg->len;
229     }*/
230
231     /* Build TCP header. */
232     if (pbuf_header(seg->p, TCP_HLEN)) {
233
234       DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: no room for TCP header in pbuf.\n"));
235
236 #ifdef TCP_STATS
237       ++lwip_stats.tcp.err;
238 #endif /* TCP_STATS */
239       goto memerr;
240     }
241     seg->tcphdr = seg->p->payload;
242     seg->tcphdr->src = htons(pcb->local_port);
243     seg->tcphdr->dest = htons(pcb->remote_port);
244     seg->tcphdr->seqno = htonl(seqno);
245     seg->tcphdr->urgp = 0;
246     TCPH_FLAGS_SET(seg->tcphdr, flags);
247     /* don't fill in tcphdr->ackno and tcphdr->wnd until later */
248
249     /* Copy the options into the header, if they are present. */
250     if (optdata == NULL) {
251       TCPH_OFFSET_SET(seg->tcphdr, 5 << 4);
252     }
253     else {
254       TCPH_OFFSET_SET(seg->tcphdr, (5 + optlen / 4) << 4);
255       /* Copy options into data portion of segment.
256        Options can thus only be sent in non data carrying
257        segments such as SYN|ACK. */
258       memcpy(seg->dataptr, optdata, optlen);
259     }
260     DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE, ("tcp_enqueue: queueing %lu:%lu (0x%x)\n",
261       ntohl(seg->tcphdr->seqno),
262       ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
263       flags));
264
265     left -= seglen;
266     seqno += seglen;
267     ptr = (void *)((char *)ptr + seglen);
268   }
269
270
271   /* Now that the data to be enqueued has been broken up into TCP
272   segments in the queue variable, we add them to the end of the
273   pcb->unsent queue. */
274   if (pcb->unsent == NULL) {
275     useg = NULL;
276   }
277   else {
278     for(useg = pcb->unsent; useg->next != NULL; useg = useg->next);
279   }
280
281   /* If there is room in the last pbuf on the unsent queue,
282   chain the first pbuf on the queue together with that. */
283   if (useg != NULL &&
284     TCP_TCPLEN(useg) != 0 &&
285     !(TCPH_FLAGS(useg->tcphdr) & (TCP_SYN | TCP_FIN)) &&
286     !(flags & (TCP_SYN | TCP_FIN)) &&
287     useg->len + queue->len <= pcb->mss) {
288     /* Remove TCP header from first segment. */
289     pbuf_header(queue->p, -TCP_HLEN);
290     pbuf_chain(useg->p, queue->p);
291     /* Free buffer which was merged. Note that the previous pbuf_chain call
292      * will have incremented the ref count, so here the ref count will still
293      * be 1 for the 1 pointer still being used on this buffer. */
294     pbuf_free(queue->p);
295     useg->len += queue->len;
296     useg->next = queue->next;
297
298     DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE | DBG_STATE, ("tcp_enqueue: chaining, new len %u\n", useg->len));
299     if (seg == queue) {
300       seg = NULL;
301     }
302     memp_free(MEMP_TCP_SEG, queue);
303   }
304   else {      
305     if (useg == NULL) {
306       pcb->unsent = queue;
307
308     }
309     else {
310       useg->next = queue;
311     }
312   }
313   if ((flags & TCP_SYN) || (flags & TCP_FIN)) {
314     ++len;
315   }
316   pcb->snd_lbb += len;
317   pcb->snd_buf -= len;
318   pcb->snd_queuelen = queuelen;
319   DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %d (after enqueued)\n", pcb->snd_queuelen));
320   if (pcb->snd_queuelen != 0) {
321     LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
322       pcb->unsent != NULL);
323
324   }
325
326   /* Set the PSH flag in the last segment that we enqueued, but only
327   if the segment has data (indicated by seglen > 0). */
328   if (seg != NULL && seglen > 0 && seg->tcphdr != NULL) {
329     TCPH_FLAGS_SET(seg->tcphdr, TCPH_FLAGS(seg->tcphdr) | TCP_PSH);
330   }
331
332   return ERR_OK;
333   memerr:
334 #ifdef TCP_STATS
335   ++lwip_stats.tcp.memerr;
336 #endif /* TCP_STATS */
337
338   if (queue != NULL) {
339     tcp_segs_free(queue);
340   }
341   if (pcb->snd_queuelen != 0) {
342     LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
343       pcb->unsent != NULL);
344
345   }
346   DEBUGF(TCP_QLEN_DEBUG | DBG_STATE, ("tcp_enqueue: %d (with mem err)\n", pcb->snd_queuelen));
347   return ERR_MEM;
348 }
349 /*-----------------------------------------------------------------------------------*/
350 /* find out what we can send and send it */
351 err_t
352 tcp_output(struct tcp_pcb *pcb)
353 {
354   struct pbuf *p;
355   struct tcp_hdr *tcphdr;
356   struct tcp_seg *seg, *useg;
357   u32_t wnd;
358 #if TCP_CWND_DEBUG
359   int i = 0;
360 #endif /* TCP_CWND_DEBUG */
361
362   /* First, check if we are invoked by the TCP input processing
363      code. If so, we do not output anything. Instead, we rely on the
364      input processing code to call us when input processing is done
365      with. */
366   if (tcp_input_pcb == pcb) {
367     return ERR_OK;
368   }
369   
370   wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd);
371
372   
373   seg = pcb->unsent;
374
375   /* If the TF_ACK_NOW flag is set, we check if there is data that is
376      to be sent. If data is to be sent out, we'll just piggyback our
377      acknowledgement with the outgoing segment. If no data will be
378      sent (either because the ->unsent queue is empty or because the
379      window doesn't allow it) we'll have to construct an empty ACK
380      segment and send it. */
381   if (pcb->flags & TF_ACK_NOW &&
382      (seg == NULL ||
383       ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
384     pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
385     p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
386     if (p == NULL) {
387       DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n"));
388       return ERR_BUF;
389     }
390     DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: sending ACK for %lu\n", pcb->rcv_nxt));    
391     
392     tcphdr = p->payload;
393     tcphdr->src = htons(pcb->local_port);
394     tcphdr->dest = htons(pcb->remote_port);
395     tcphdr->seqno = htonl(pcb->snd_nxt);
396     tcphdr->ackno = htonl(pcb->rcv_nxt);
397     TCPH_FLAGS_SET(tcphdr, TCP_ACK);
398     tcphdr->wnd = htons(pcb->rcv_wnd);
399     tcphdr->urgp = 0;
400     TCPH_OFFSET_SET(tcphdr, 5 << 4);
401     
402     tcphdr->chksum = 0;
403     tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
404                                         IP_PROTO_TCP, p->tot_len);
405
406     ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), TCP_TTL,
407               IP_PROTO_TCP);
408     pbuf_free(p);
409
410     return ERR_OK;
411   } 
412   
413 #if TCP_OUTPUT_DEBUG
414   if (seg == NULL) {
415     DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n", pcb->unsent));
416   }
417 #endif /* TCP_OUTPUT_DEBUG */
418 #if TCP_CWND_DEBUG
419   if (seg == NULL) {
420     DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, seg == NULL, ack %lu\n",
421                             pcb->snd_wnd, pcb->cwnd, wnd,
422                             pcb->lastack));
423   } else {
424     DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, effwnd %lu, seq %lu, ack %lu\n",
425                             pcb->snd_wnd, pcb->cwnd, wnd,
426                             ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len,
427                             ntohl(seg->tcphdr->seqno), pcb->lastack));
428   }
429 #endif /* TCP_CWND_DEBUG */
430   
431   while (seg != NULL &&
432         ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
433 #if TCP_CWND_DEBUG
434     DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, effwnd %lu, seq %lu, ack %lu, i%d\n",
435                             pcb->snd_wnd, pcb->cwnd, wnd,
436                             ntohl(seg->tcphdr->seqno) + seg->len -
437                             pcb->lastack,
438                             ntohl(seg->tcphdr->seqno), pcb->lastack, i));
439     ++i;
440 #endif /* TCP_CWND_DEBUG */
441
442     pcb->unsent = seg->next;
443     
444     if (pcb->state != SYN_SENT) {
445       TCPH_FLAGS_SET(seg->tcphdr, TCPH_FLAGS(seg->tcphdr) | TCP_ACK);
446       pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
447     }
448     
449     tcp_output_segment(seg, pcb);
450     pcb->snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);
451     if (TCP_SEQ_LT(pcb->snd_max, pcb->snd_nxt)) {
452       pcb->snd_max = pcb->snd_nxt;
453     }
454     /* put segment on unacknowledged list if length > 0 */
455     if (TCP_TCPLEN(seg) > 0) {
456       seg->next = NULL;
457       if (pcb->unacked == NULL) {
458         pcb->unacked = seg;
459         
460         
461       } else {
462         for(useg = pcb->unacked; useg->next != NULL; useg = useg->next);
463         useg->next = seg;
464       }
465     } else {
466       tcp_seg_free(seg);
467     }
468     seg = pcb->unsent;
469   }  
470   return ERR_OK;
471 }
472 /*-----------------------------------------------------------------------------------*/
473 static void
474 tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
475 {
476   u16_t len;
477   struct netif *netif;
478
479   /* The TCP header has already been constructed, but the ackno and
480    wnd fields remain. */
481   seg->tcphdr->ackno = htonl(pcb->rcv_nxt);
482
483   /* silly window avoidance */
484   if (pcb->rcv_wnd < pcb->mss) {
485     seg->tcphdr->wnd = 0;
486   } else {
487     /* advertise our receive window size in this TCP segment */
488     seg->tcphdr->wnd = htons(pcb->rcv_wnd);
489   }
490
491   /* If we don't have a local IP address, we get one by
492      calling ip_route(). */
493   if (ip_addr_isany(&(pcb->local_ip))) {
494     netif = ip_route(&(pcb->remote_ip));
495     if (netif == NULL) {
496       return;
497     }
498     ip_addr_set(&(pcb->local_ip), &(netif->ip_addr));
499   }
500
501   pcb->rtime = 0;
502   
503   if (pcb->rttest == 0) {
504     pcb->rttest = tcp_ticks;
505     pcb->rtseq = ntohl(seg->tcphdr->seqno);
506
507     DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %lu\n", pcb->rtseq));
508   }
509   DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %lu:%lu\n",
510                             htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) +
511                             seg->len));
512
513   len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload);
514   
515   seg->p->len -= len;
516   seg->p->tot_len -= len;
517   
518   seg->p->payload = seg->tcphdr;
519     
520   seg->tcphdr->chksum = 0;
521   seg->tcphdr->chksum = inet_chksum_pseudo(seg->p,
522                                            &(pcb->local_ip),
523                                            &(pcb->remote_ip),
524                                            IP_PROTO_TCP, seg->p->tot_len);
525 #ifdef TCP_STATS
526   ++lwip_stats.tcp.xmit;
527 #endif /* TCP_STATS */
528
529   ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), TCP_TTL,
530             IP_PROTO_TCP);
531 }
532 /*-----------------------------------------------------------------------------------*/
533 void
534 tcp_rst(u32_t seqno, u32_t ackno,
535         struct ip_addr *local_ip, struct ip_addr *remote_ip,
536         u16_t local_port, u16_t remote_port)
537 {
538   struct pbuf *p;
539   struct tcp_hdr *tcphdr;
540   p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
541   if (p == NULL) {
542       DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n"));
543       return;
544   }
545
546   tcphdr = p->payload;
547   tcphdr->src = htons(local_port);
548   tcphdr->dest = htons(remote_port);
549   tcphdr->seqno = htonl(seqno);
550   tcphdr->ackno = htonl(ackno);
551   TCPH_FLAGS_SET(tcphdr, TCP_RST | TCP_ACK);
552   tcphdr->wnd = htons(TCP_WND);
553   tcphdr->urgp = 0;
554   TCPH_OFFSET_SET(tcphdr, 5 << 4);
555   
556   tcphdr->chksum = 0;
557   tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip,
558                                       IP_PROTO_TCP, p->tot_len);
559
560 #ifdef TCP_STATS
561   ++lwip_stats.tcp.xmit;
562 #endif /* TCP_STATS */
563   ip_output(p, local_ip, remote_ip, TCP_TTL, IP_PROTO_TCP);
564   pbuf_free(p);
565   DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %lu ackno %lu.\n", seqno, ackno));
566 }
567 /*-----------------------------------------------------------------------------------*/
568 void
569 tcp_rexmit(struct tcp_pcb *pcb)
570 {
571   struct tcp_seg *seg;
572
573   if (pcb->unacked == NULL) {
574     return;
575   }
576   
577   /* Move all unacked segments to the unsent queue. */
578   for(seg = pcb->unacked; seg->next != NULL; seg = seg->next);
579   
580   seg->next = pcb->unsent;
581   pcb->unsent = pcb->unacked;
582   
583   pcb->unacked = NULL;
584   
585   
586   pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);
587   
588   ++pcb->nrtx;
589   
590   /* Don't take any rtt measurements after retransmitting. */    
591   pcb->rttest = 0;
592   
593   /* Do the actual retransmission. */
594   tcp_output(pcb);
595
596 }
597 #endif /* LWIP_TCP */
598
599
600
601
602
603
604
605
606