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