4 * Transmission Control Protocol, outgoing traffic
\r
6 * The output functions of TCP.
\r
11 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
\r
12 * All rights reserved.
\r
14 * Redistribution and use in source and binary forms, with or without modification,
\r
15 * are permitted provided that the following conditions are met:
\r
17 * 1. Redistributions of source code must retain the above copyright notice,
\r
18 * this list of conditions and the following disclaimer.
\r
19 * 2. Redistributions in binary form must reproduce the above copyright notice,
\r
20 * this list of conditions and the following disclaimer in the documentation
\r
21 * and/or other materials provided with the distribution.
\r
22 * 3. The name of the author may not be used to endorse or promote products
\r
23 * derived from this software without specific prior written permission.
\r
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
\r
26 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
\r
27 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
\r
28 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
\r
29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
\r
30 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
\r
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
\r
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
\r
33 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
\r
36 * This file is part of the lwIP TCP/IP stack.
\r
38 * Author: Adam Dunkels <adam@sics.se>
\r
42 #include "lwip/def.h"
\r
43 #include "lwip/opt.h"
\r
45 #include "lwip/mem.h"
\r
46 #include "lwip/memp.h"
\r
47 #include "lwip/sys.h"
\r
49 #include "lwip/ip_addr.h"
\r
50 #include "lwip/netif.h"
\r
52 #include "lwip/inet.h"
\r
53 #include "lwip/tcp.h"
\r
55 #include "lwip/stats.h"
\r
61 /* Forward declarations.*/
\r
62 static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb);
\r
65 tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags)
\r
67 /* no data, no length, flags, copy=1, no optdata, no optdatalen */
\r
68 return tcp_enqueue(pcb, NULL, 0, flags, 1, NULL, 0);
\r
72 * Write data for sending (but does not send it immediately).
\r
74 * It waits in the expectation of more data being sent soon (as
\r
75 * it can send them more efficiently by combining them together).
\r
76 * To prompt the system to send data now, call tcp_output() after
\r
77 * calling tcp_write().
\r
79 * @arg pcb Protocol control block of the TCP connection to enqueue data for.
\r
85 tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy)
\r
87 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, arg=%p, len=%u, copy=%d)\n", (void *)pcb,
\r
88 arg, len, (unsigned int)copy));
\r
89 /* connection is in valid state for data transmission? */
\r
90 if (pcb->state == ESTABLISHED ||
\r
91 pcb->state == CLOSE_WAIT ||
\r
92 pcb->state == SYN_SENT ||
\r
93 pcb->state == SYN_RCVD) {
\r
95 return tcp_enqueue(pcb, (void *)arg, len, 0, copy, NULL, 0);
\r
99 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_STATE | 3, ("tcp_write() called in invalid state\n"));
\r
105 * Enqueue either data or TCP options (but not both) for tranmission
\r
109 * @arg pcb Protocol control block for the TCP connection to enqueue data for.
\r
110 * @arg arg Pointer to the data to be enqueued for sending.
\r
111 * @arg len Data length in bytes
\r
113 * @arg copy 1 if data must be copied, 0 if data is non-volatile and can be
\r
119 tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
\r
120 u8_t flags, u8_t copy,
\r
121 u8_t *optdata, u8_t optlen)
\r
124 struct tcp_seg *seg, *useg, *queue=NULL;
\r
130 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue(pcb=%p, arg=%p, len=%u, flags=%x, copy=%u)\n",
\r
131 (void *)pcb, arg, len, (unsigned int)flags, (unsigned int)copy));
\r
132 LWIP_ASSERT("tcp_enqueue: len == 0 || optlen == 0 (programmer violates API)",
\r
133 len == 0 || optlen == 0);
\r
134 LWIP_ASSERT("tcp_enqueue: arg == NULL || optdata == NULL (programmer violates API)",
\r
135 arg == NULL || optdata == NULL);
\r
136 /* fail on too much data */
\r
137 if (len > pcb->snd_buf) {
\r
138 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too much data (len=%u > snd_buf=%u)\n", len, pcb->snd_buf));
\r
144 /* seqno will be the sequence number of the first segment enqueued
\r
145 * by the call to this function. */
\r
146 seqno = pcb->snd_lbb;
\r
148 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: queuelen: %u\n", (unsigned int)pcb->snd_queuelen));
\r
150 /* If total number of pbufs on the unsent/unacked queues exceeds the
\r
151 * configured maximum, return an error */
\r
152 queuelen = pcb->snd_queuelen;
\r
153 if (queuelen >= TCP_SND_QUEUELEN) {
\r
154 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too long queue %u (max %u)\n", queuelen, TCP_SND_QUEUELEN));
\r
157 if (queuelen != 0) {
\r
158 LWIP_ASSERT("tcp_enqueue: pbufs on queue => at least one queue non-empty",
\r
159 pcb->unacked != NULL || pcb->unsent != NULL);
\r
161 LWIP_ASSERT("tcp_enqueue: no pbufs on queue => both queues empty",
\r
162 pcb->unacked == NULL && pcb->unsent == NULL);
\r
165 /* First, break up the data into segments and tuck them together in
\r
166 * the local "queue" variable. */
\r
171 while (queue == NULL || left > 0) {
\r
173 /* The segment length should be the MSS if the data to be enqueued
\r
174 * is larger than the MSS. */
\r
175 seglen = left > pcb->mss? pcb->mss: left;
\r
177 /* Allocate memory for tcp_seg, and fill in fields. */
\r
178 seg = memp_malloc(MEMP_TCP_SEG);
\r
180 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: could not allocate memory for tcp_seg\n"));
\r
186 /* first segment of to-be-queued data? */
\r
187 if (queue == NULL) {
\r
190 /* subsequent segments of to-be-queued data */
\r
192 /* Attach the segment to the end of the queued segments */
\r
193 LWIP_ASSERT("useg != NULL", useg != NULL);
\r
196 /* remember last segment of to-be-queued data for next iteration */
\r
199 /* If copy is set, memory should be allocated
\r
200 * and data copied into pbuf, otherwise data comes from
\r
201 * ROM or other static memory, and need not be copied. If
\r
202 * optdata is != NULL, we have options instead of data. */
\r
205 if (optdata != NULL) {
\r
206 if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
\r
210 seg->dataptr = seg->p->payload;
\r
212 /* copy from volatile memory? */
\r
214 if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_RAM)) == NULL) {
\r
215 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue : could not allocate memory for pbuf copy size %u\n", seglen));
\r
220 memcpy(seg->p->payload, ptr, seglen);
\r
222 seg->dataptr = seg->p->payload;
\r
224 /* do not copy data */
\r
226 /* First, allocate a pbuf for holding the data.
\r
227 * since the referenced data is available at least until it is sent out on the
\r
228 * link (as it has to be ACKed by the remote party) we can safely use PBUF_ROM
\r
229 * instead of PBUF_REF here.
\r
231 if ((p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_ROM)) == NULL) {
\r
232 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: could not allocate memory for zero-copy pbuf\n"));
\r
236 /* reference the non-volatile payload data */
\r
238 seg->dataptr = ptr;
\r
240 /* Second, allocate a pbuf for the headers. */
\r
241 if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_RAM)) == NULL) {
\r
242 /* If allocation fails, we have to deallocate the data pbuf as
\r
245 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: could not allocate memory for header pbuf\n"));
\r
250 /* Concatenate the headers and data pbufs together. */
\r
251 pbuf_cat(seg->p/*header*/, p/*data*/);
\r
255 /* Now that there are more segments queued, we check again if the
\r
256 length of the queue exceeds the configured maximum. */
\r
257 if (queuelen > TCP_SND_QUEUELEN) {
\r
258 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: queue too long %u (%u)\n", queuelen, TCP_SND_QUEUELEN));
\r
264 /* build TCP header */
\r
265 if (pbuf_header(seg->p, TCP_HLEN)) {
\r
266 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: no room for TCP header in pbuf.\n"));
\r
267 TCP_STATS_INC(tcp.err);
\r
270 seg->tcphdr = seg->p->payload;
\r
271 seg->tcphdr->src = htons(pcb->local_port);
\r
272 seg->tcphdr->dest = htons(pcb->remote_port);
\r
273 seg->tcphdr->seqno = htonl(seqno);
\r
274 seg->tcphdr->urgp = 0;
\r
275 TCPH_FLAGS_SET(seg->tcphdr, flags);
\r
276 /* don't fill in tcphdr->ackno and tcphdr->wnd until later */
\r
278 /* Copy the options into the header, if they are present. */
\r
279 if (optdata == NULL) {
\r
280 TCPH_HDRLEN_SET(seg->tcphdr, 5);
\r
283 TCPH_HDRLEN_SET(seg->tcphdr, (5 + optlen / 4));
\r
284 /* Copy options into data portion of segment.
\r
285 Options can thus only be sent in non data carrying
\r
286 segments such as SYN|ACK. */
\r
287 memcpy(seg->dataptr, optdata, optlen);
\r
289 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE, ("tcp_enqueue: queueing %lu:%lu (0x%x)\n",
\r
290 ntohl(seg->tcphdr->seqno),
\r
291 ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
\r
296 ptr = (void *)((char *)ptr + seglen);
\r
299 /* Now that the data to be enqueued has been broken up into TCP
\r
300 segments in the queue variable, we add them to the end of the
\r
301 pcb->unsent queue. */
\r
302 if (pcb->unsent == NULL) {
\r
306 for (useg = pcb->unsent; useg->next != NULL; useg = useg->next);
\r
308 /* { useg is last segment on the unsent queue, NULL if list is empty } */
\r
310 /* If there is room in the last pbuf on the unsent queue,
\r
311 chain the first pbuf on the queue together with that. */
\r
312 if (useg != NULL &&
\r
313 TCP_TCPLEN(useg) != 0 &&
\r
314 !(TCPH_FLAGS(useg->tcphdr) & (TCP_SYN | TCP_FIN)) &&
\r
315 !(flags & (TCP_SYN | TCP_FIN)) &&
\r
316 /* fit within max seg size */
\r
317 useg->len + queue->len <= pcb->mss) {
\r
318 /* Remove TCP header from first segment of our to-be-queued list */
\r
319 pbuf_header(queue->p, -TCP_HLEN);
\r
320 pbuf_cat(useg->p, queue->p);
\r
321 useg->len += queue->len;
\r
322 useg->next = queue->next;
\r
324 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE | DBG_STATE, ("tcp_enqueue: chaining segments, new len %u\n", useg->len));
\r
325 if (seg == queue) {
\r
328 memp_free(MEMP_TCP_SEG, queue);
\r
332 if (useg == NULL) {
\r
333 /* initialize list with this segment */
\r
334 pcb->unsent = queue;
\r
336 /* enqueue segment */
\r
338 useg->next = queue;
\r
341 if ((flags & TCP_SYN) || (flags & TCP_FIN)) {
\r
344 pcb->snd_lbb += len;
\r
345 pcb->snd_buf -= len;
\r
346 /* update number of segments on the queues */
\r
347 pcb->snd_queuelen = queuelen;
\r
348 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %d (after enqueued)\n", pcb->snd_queuelen));
\r
349 if (pcb->snd_queuelen != 0) {
\r
350 LWIP_ASSERT("tcp_enqueue: valid queue length",
\r
351 pcb->unacked != NULL || pcb->unsent != NULL);
\r
354 /* Set the PSH flag in the last segment that we enqueued, but only
\r
355 if the segment has data (indicated by seglen > 0). */
\r
356 if (seg != NULL && seglen > 0 && seg->tcphdr != NULL) {
\r
357 TCPH_SET_FLAG(seg->tcphdr, TCP_PSH);
\r
362 TCP_STATS_INC(tcp.memerr);
\r
364 if (queue != NULL) {
\r
365 tcp_segs_free(queue);
\r
367 if (pcb->snd_queuelen != 0) {
\r
368 LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
\r
369 pcb->unsent != NULL);
\r
371 LWIP_DEBUGF(TCP_QLEN_DEBUG | DBG_STATE, ("tcp_enqueue: %d (with mem err)\n", pcb->snd_queuelen));
\r
375 /* find out what we can send and send it */
\r
377 tcp_output(struct tcp_pcb *pcb)
\r
380 struct tcp_hdr *tcphdr;
\r
381 struct tcp_seg *seg, *useg;
\r
385 #endif /* TCP_CWND_DEBUG */
\r
387 /* First, check if we are invoked by the TCP input processing
\r
388 code. If so, we do not output anything. Instead, we rely on the
\r
389 input processing code to call us when input processing is done
\r
391 if (tcp_input_pcb == pcb) {
\r
395 wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd);
\r
399 /* useg should point to last segment on unacked queue */
\r
400 useg = pcb->unacked;
\r
401 if (useg != NULL) {
\r
402 for (; useg->next != NULL; useg = useg->next);
\r
405 /* If the TF_ACK_NOW flag is set and no data will be sent (either
\r
406 * because the ->unsent queue is empty or because the window does
\r
407 * not allow it), construct an empty ACK segment and send it.
\r
409 * If data is to be sent, we will just piggyback the ACK (see below).
\r
411 if (pcb->flags & TF_ACK_NOW &&
\r
413 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
\r
414 p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
\r
416 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n"));
\r
419 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: sending ACK for %lu\n", pcb->rcv_nxt));
\r
420 /* remove ACK flags from the PCB, as we send an empty ACK now */
\r
421 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
\r
423 tcphdr = p->payload;
\r
424 tcphdr->src = htons(pcb->local_port);
\r
425 tcphdr->dest = htons(pcb->remote_port);
\r
426 tcphdr->seqno = htonl(pcb->snd_nxt);
\r
427 tcphdr->ackno = htonl(pcb->rcv_nxt);
\r
428 TCPH_FLAGS_SET(tcphdr, TCP_ACK);
\r
429 tcphdr->wnd = htons(pcb->rcv_wnd);
\r
431 TCPH_HDRLEN_SET(tcphdr, 5);
\r
433 tcphdr->chksum = 0;
\r
434 #if CHECKSUM_GEN_TCP
\r
435 tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
\r
436 IP_PROTO_TCP, p->tot_len);
\r
438 ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
\r
445 #if TCP_OUTPUT_DEBUG
\r
447 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n", pcb->unsent));
\r
449 #endif /* TCP_OUTPUT_DEBUG */
\r
452 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, seg == NULL, ack %lu\n",
\r
453 pcb->snd_wnd, pcb->cwnd, wnd,
\r
456 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, effwnd %lu, seq %lu, ack %lu\n",
\r
457 pcb->snd_wnd, pcb->cwnd, wnd,
\r
458 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len,
\r
459 ntohl(seg->tcphdr->seqno), pcb->lastack));
\r
461 #endif /* TCP_CWND_DEBUG */
\r
462 /* data available and window allows it to be sent? */
\r
463 while (seg != NULL &&
\r
464 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
\r
466 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, effwnd %lu, seq %lu, ack %lu, i%d\n",
\r
467 pcb->snd_wnd, pcb->cwnd, wnd,
\r
468 ntohl(seg->tcphdr->seqno) + seg->len -
\r
470 ntohl(seg->tcphdr->seqno), pcb->lastack, i));
\r
472 #endif /* TCP_CWND_DEBUG */
\r
474 pcb->unsent = seg->next;
\r
476 if (pcb->state != SYN_SENT) {
\r
477 TCPH_SET_FLAG(seg->tcphdr, TCP_ACK);
\r
478 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
\r
481 tcp_output_segment(seg, pcb);
\r
482 pcb->snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);
\r
483 if (TCP_SEQ_LT(pcb->snd_max, pcb->snd_nxt)) {
\r
484 pcb->snd_max = pcb->snd_nxt;
\r
486 /* put segment on unacknowledged list if length > 0 */
\r
487 if (TCP_TCPLEN(seg) > 0) {
\r
489 /* unacked list is empty? */
\r
490 if (pcb->unacked == NULL) {
\r
491 pcb->unacked = seg;
\r
493 /* unacked list is not empty? */
\r
495 /* In the case of fast retransmit, the packet should not go to the tail
\r
496 * of the unacked queue, but rather at the head. We need to check for
\r
497 * this case. -STJ Jul 27, 2004 */
\r
498 if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))){
\r
499 /* add segment to head of unacked list */
\r
500 seg->next = pcb->unacked;
\r
501 pcb->unacked = seg;
\r
503 /* add segment to tail of unacked list */
\r
508 /* do not queue empty segments on the unacked list */
\r
518 * Actually send a TCP segment over IP
\r
521 tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
\r
524 struct netif *netif;
\r
526 /* The TCP header has already been constructed, but the ackno and
\r
527 wnd fields remain. */
\r
528 seg->tcphdr->ackno = htonl(pcb->rcv_nxt);
\r
530 /* silly window avoidance */
\r
531 if (pcb->rcv_wnd < pcb->mss) {
\r
532 seg->tcphdr->wnd = 0;
\r
534 /* advertise our receive window size in this TCP segment */
\r
535 seg->tcphdr->wnd = htons(pcb->rcv_wnd);
\r
538 /* If we don't have a local IP address, we get one by
\r
539 calling ip_route(). */
\r
540 if (ip_addr_isany(&(pcb->local_ip))) {
\r
541 netif = ip_route(&(pcb->remote_ip));
\r
542 if (netif == NULL) {
\r
545 ip_addr_set(&(pcb->local_ip), &(netif->ip_addr));
\r
550 if (pcb->rttest == 0) {
\r
551 pcb->rttest = tcp_ticks;
\r
552 pcb->rtseq = ntohl(seg->tcphdr->seqno);
\r
554 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %lu\n", pcb->rtseq));
\r
556 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %lu:%lu\n",
\r
557 htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) +
\r
560 len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload);
\r
562 seg->p->len -= len;
\r
563 seg->p->tot_len -= len;
\r
565 seg->p->payload = seg->tcphdr;
\r
567 seg->tcphdr->chksum = 0;
\r
568 #if CHECKSUM_GEN_TCP
\r
569 seg->tcphdr->chksum = inet_chksum_pseudo(seg->p,
\r
572 IP_PROTO_TCP, seg->p->tot_len);
\r
574 TCP_STATS_INC(tcp.xmit);
\r
576 ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
\r
581 tcp_rst(u32_t seqno, u32_t ackno,
\r
582 struct ip_addr *local_ip, struct ip_addr *remote_ip,
\r
583 u16_t local_port, u16_t remote_port)
\r
586 struct tcp_hdr *tcphdr;
\r
587 p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
\r
589 LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n"));
\r
593 tcphdr = p->payload;
\r
594 tcphdr->src = htons(local_port);
\r
595 tcphdr->dest = htons(remote_port);
\r
596 tcphdr->seqno = htonl(seqno);
\r
597 tcphdr->ackno = htonl(ackno);
\r
598 TCPH_FLAGS_SET(tcphdr, TCP_RST | TCP_ACK);
\r
599 tcphdr->wnd = htons(TCP_WND);
\r
601 TCPH_HDRLEN_SET(tcphdr, 5);
\r
603 tcphdr->chksum = 0;
\r
604 #if CHECKSUM_GEN_TCP
\r
605 tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip,
\r
606 IP_PROTO_TCP, p->tot_len);
\r
608 TCP_STATS_INC(tcp.xmit);
\r
609 /* Send output with hardcoded TTL since we have no access to the pcb */
\r
610 ip_output(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP);
\r
612 LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %lu ackno %lu.\n", seqno, ackno));
\r
615 /* requeue all unacked segments for retransmission */
\r
617 tcp_rexmit_rto(struct tcp_pcb *pcb)
\r
619 struct tcp_seg *seg;
\r
621 if (pcb->unacked == NULL) {
\r
625 /* Move all unacked segments to the head of the unsent queue */
\r
626 for (seg = pcb->unacked; seg->next != NULL; seg = seg->next);
\r
627 /* concatenate unsent queue after unacked queue */
\r
628 seg->next = pcb->unsent;
\r
629 /* unsent queue is the concatenated queue (of unacked, unsent) */
\r
630 pcb->unsent = pcb->unacked;
\r
631 /* unacked queue is now empty */
\r
632 pcb->unacked = NULL;
\r
634 pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);
\r
635 /* increment number of retransmissions */
\r
638 /* Don't take any RTT measurements after retransmitting. */
\r
641 /* Do the actual retransmission */
\r
646 tcp_rexmit(struct tcp_pcb *pcb)
\r
648 struct tcp_seg *seg;
\r
650 if (pcb->unacked == NULL) {
\r
654 /* Move the first unacked segment to the unsent queue */
\r
655 seg = pcb->unacked->next;
\r
656 pcb->unacked->next = pcb->unsent;
\r
657 pcb->unsent = pcb->unacked;
\r
658 pcb->unacked = seg;
\r
660 pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);
\r
664 /* Don't take any rtt measurements after retransmitting. */
\r
667 /* Do the actual retransmission. */
\r
674 tcp_keepalive(struct tcp_pcb *pcb)
\r
677 struct tcp_hdr *tcphdr;
\r
679 LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %u.%u.%u.%u\n",
\r
680 ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
\r
681 ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
\r
683 LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %lu pcb->tmr %lu pcb->keep_cnt %u\n", tcp_ticks, pcb->tmr, pcb->keep_cnt));
\r
685 p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
\r
688 LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: could not allocate memory for pbuf\n"));
\r
692 tcphdr = p->payload;
\r
693 tcphdr->src = htons(pcb->local_port);
\r
694 tcphdr->dest = htons(pcb->remote_port);
\r
695 tcphdr->seqno = htonl(pcb->snd_nxt - 1);
\r
696 tcphdr->ackno = htonl(pcb->rcv_nxt);
\r
697 tcphdr->wnd = htons(pcb->rcv_wnd);
\r
699 TCPH_HDRLEN_SET(tcphdr, 5);
\r
701 tcphdr->chksum = 0;
\r
702 #if CHECKSUM_GEN_TCP
\r
703 tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip, IP_PROTO_TCP, p->tot_len);
\r
705 TCP_STATS_INC(tcp.xmit);
\r
707 /* Send output to IP */
\r
708 ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
\r
712 LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_keepalive: seqno %lu ackno %lu.\n", pcb->snd_nxt - 1, pcb->rcv_nxt));
\r
715 #endif /* LWIP_TCP */
\r