4 * Transmission Control Protocol, outgoing traffic
6 * The output functions of TCP.
11 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
12 * All rights reserved.
14 * Redistribution and use in source and binary forms, with or without modification,
15 * are permitted provided that the following conditions are met:
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.
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
36 * This file is part of the lwIP TCP/IP stack.
38 * Author: Adam Dunkels <adam@sics.se>
47 #include "lwip/memp.h"
49 #include "lwip/ip_addr.h"
50 #include "lwip/netif.h"
51 #include "lwip/inet.h"
53 #include "lwip/stats.h"
57 /* Forward declarations.*/
58 static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb);
61 tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags)
63 /* no data, no length, flags, copy=1, no optdata, no optdatalen */
64 return tcp_enqueue(pcb, NULL, 0, flags, 1, NULL, 0);
68 * Write data for sending (but does not send it immediately).
70 * It waits in the expectation of more data being sent soon (as
71 * it can send them more efficiently by combining them together).
72 * To prompt the system to send data now, call tcp_output() after
73 * calling tcp_write().
75 * @arg pcb Protocol control block of the TCP connection to enqueue data for.
81 tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy)
83 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, arg=%p, len=%"U16_F", copy=%"U16_F")\n", (void *)pcb,
84 arg, len, (u16_t)copy));
85 /* connection is in valid state for data transmission? */
86 if (pcb->state == ESTABLISHED ||
87 pcb->state == CLOSE_WAIT ||
88 pcb->state == SYN_SENT ||
89 pcb->state == SYN_RCVD) {
91 return tcp_enqueue(pcb, (void *)arg, len, 0, copy, NULL, 0);
95 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_STATE | 3, ("tcp_write() called in invalid state\n"));
101 * Enqueue either data or TCP options (but not both) for tranmission
105 * @arg pcb Protocol control block for the TCP connection to enqueue data for.
106 * @arg arg Pointer to the data to be enqueued for sending.
107 * @arg len Data length in bytes
109 * @arg copy 1 if data must be copied, 0 if data is non-volatile and can be
115 tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
116 u8_t flags, u8_t copy,
117 u8_t *optdata, u8_t optlen)
120 struct tcp_seg *seg, *useg, *queue;
126 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue(pcb=%p, arg=%p, len=%"U16_F", flags=%"X16_F", copy=%"U16_F")\n",
127 (void *)pcb, arg, len, (u16_t)flags, (u16_t)copy));
128 LWIP_ASSERT("tcp_enqueue: len == 0 || optlen == 0 (programmer violates API)",
129 len == 0 || optlen == 0);
130 LWIP_ASSERT("tcp_enqueue: arg == NULL || optdata == NULL (programmer violates API)",
131 arg == NULL || optdata == NULL);
132 /* fail on too much data */
133 if (len > pcb->snd_buf) {
134 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too much data (len=%"U16_F" > snd_buf=%"U16_F")\n", len, pcb->snd_buf));
140 /* seqno will be the sequence number of the first segment enqueued
141 * by the call to this function. */
142 seqno = pcb->snd_lbb;
144 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen));
146 /* If total number of pbufs on the unsent/unacked queues exceeds the
147 * configured maximum, return an error */
148 queuelen = pcb->snd_queuelen;
149 if (queuelen >= TCP_SND_QUEUELEN) {
150 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too long queue %"U16_F" (max %"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
151 TCP_STATS_INC(tcp.memerr);
155 LWIP_ASSERT("tcp_enqueue: pbufs on queue => at least one queue non-empty",
156 pcb->unacked != NULL || pcb->unsent != NULL);
158 LWIP_ASSERT("tcp_enqueue: no pbufs on queue => both queues empty",
159 pcb->unacked == NULL && pcb->unsent == NULL);
162 /* First, break up the data into segments and tuck them together in
163 * the local "queue" variable. */
164 useg = queue = seg = NULL;
166 while (queue == NULL || left > 0) {
168 /* The segment length should be the MSS if the data to be enqueued
169 * is larger than the MSS. */
170 seglen = left > pcb->mss? pcb->mss: left;
172 /* Allocate memory for tcp_seg, and fill in fields. */
173 seg = memp_malloc(MEMP_TCP_SEG);
175 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: could not allocate memory for tcp_seg\n"));
181 /* first segment of to-be-queued data? */
185 /* subsequent segments of to-be-queued data */
187 /* Attach the segment to the end of the queued segments */
188 LWIP_ASSERT("useg != NULL", useg != NULL);
191 /* remember last segment of to-be-queued data for next iteration */
194 /* If copy is set, memory should be allocated
195 * and data copied into pbuf, otherwise data comes from
196 * ROM or other static memory, and need not be copied. If
197 * optdata is != NULL, we have options instead of data. */
200 if (optdata != NULL) {
201 if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
205 seg->dataptr = seg->p->payload;
207 /* copy from volatile memory? */
209 if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_RAM)) == NULL) {
210 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue : could not allocate memory for pbuf copy size %"U16_F"\n", seglen));
215 memcpy(seg->p->payload, ptr, seglen);
217 seg->dataptr = seg->p->payload;
219 /* do not copy data */
221 /* First, allocate a pbuf for holding the data.
222 * since the referenced data is available at least until it is sent out on the
223 * link (as it has to be ACKed by the remote party) we can safely use PBUF_ROM
224 * instead of PBUF_REF here.
226 if ((p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_ROM)) == NULL) {
227 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: could not allocate memory for zero-copy pbuf\n"));
231 /* reference the non-volatile payload data */
235 /* Second, allocate a pbuf for the headers. */
236 if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_RAM)) == NULL) {
237 /* If allocation fails, we have to deallocate the data pbuf as
240 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: could not allocate memory for header pbuf\n"));
245 /* Concatenate the headers and data pbufs together. */
246 pbuf_cat(seg->p/*header*/, p/*data*/);
250 /* Now that there are more segments queued, we check again if the
251 length of the queue exceeds the configured maximum. */
252 if (queuelen > TCP_SND_QUEUELEN) {
253 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: queue too long %"U16_F" (%"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
259 /* build TCP header */
260 if (pbuf_header(seg->p, TCP_HLEN)) {
261 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: no room for TCP header in pbuf.\n"));
262 TCP_STATS_INC(tcp.err);
265 seg->tcphdr = seg->p->payload;
266 seg->tcphdr->src = htons(pcb->local_port);
267 seg->tcphdr->dest = htons(pcb->remote_port);
268 seg->tcphdr->seqno = htonl(seqno);
269 seg->tcphdr->urgp = 0;
270 TCPH_FLAGS_SET(seg->tcphdr, flags);
271 /* don't fill in tcphdr->ackno and tcphdr->wnd until later */
273 /* Copy the options into the header, if they are present. */
274 if (optdata == NULL) {
275 TCPH_HDRLEN_SET(seg->tcphdr, 5);
278 TCPH_HDRLEN_SET(seg->tcphdr, (5 + optlen / 4));
279 /* Copy options into data portion of segment.
280 Options can thus only be sent in non data carrying
281 segments such as SYN|ACK. */
282 memcpy(seg->dataptr, optdata, optlen);
284 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE, ("tcp_enqueue: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n",
285 ntohl(seg->tcphdr->seqno),
286 ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
291 ptr = (void *)((u8_t *)ptr + seglen);
294 /* Now that the data to be enqueued has been broken up into TCP
295 segments in the queue variable, we add them to the end of the
296 pcb->unsent queue. */
297 if (pcb->unsent == NULL) {
301 for (useg = pcb->unsent; useg->next != NULL; useg = useg->next);
303 /* { useg is last segment on the unsent queue, NULL if list is empty } */
305 /* If there is room in the last pbuf on the unsent queue,
306 chain the first pbuf on the queue together with that. */
308 TCP_TCPLEN(useg) != 0 &&
309 !(TCPH_FLAGS(useg->tcphdr) & (TCP_SYN | TCP_FIN)) &&
310 !(flags & (TCP_SYN | TCP_FIN)) &&
311 /* fit within max seg size */
312 useg->len + queue->len <= pcb->mss) {
313 /* Remove TCP header from first segment of our to-be-queued list */
314 pbuf_header(queue->p, -TCP_HLEN);
315 pbuf_cat(useg->p, queue->p);
316 useg->len += queue->len;
317 useg->next = queue->next;
319 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE | DBG_STATE, ("tcp_enqueue: chaining segments, new len %"U16_F"\n", useg->len));
323 memp_free(MEMP_TCP_SEG, queue);
328 /* initialize list with this segment */
331 /* enqueue segment */
336 if ((flags & TCP_SYN) || (flags & TCP_FIN)) {
343 /* update number of segments on the queues */
344 pcb->snd_queuelen = queuelen;
345 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %"S16_F" (after enqueued)\n", pcb->snd_queuelen));
346 if (pcb->snd_queuelen != 0) {
347 LWIP_ASSERT("tcp_enqueue: valid queue length",
348 pcb->unacked != NULL || pcb->unsent != NULL);
351 /* Set the PSH flag in the last segment that we enqueued, but only
352 if the segment has data (indicated by seglen > 0). */
353 if (seg != NULL && seglen > 0 && seg->tcphdr != NULL) {
354 TCPH_SET_FLAG(seg->tcphdr, TCP_PSH);
359 TCP_STATS_INC(tcp.memerr);
362 tcp_segs_free(queue);
364 if (pcb->snd_queuelen != 0) {
365 LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
366 pcb->unsent != NULL);
368 LWIP_DEBUGF(TCP_QLEN_DEBUG | DBG_STATE, ("tcp_enqueue: %"S16_F" (with mem err)\n", pcb->snd_queuelen));
372 /* find out what we can send and send it */
374 tcp_output(struct tcp_pcb *pcb)
377 struct tcp_hdr *tcphdr;
378 struct tcp_seg *seg, *useg;
382 #endif /* TCP_CWND_DEBUG */
384 /* First, check if we are invoked by the TCP input processing
385 code. If so, we do not output anything. Instead, we rely on the
386 input processing code to call us when input processing is done
388 if (tcp_input_pcb == pcb) {
392 wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd);
396 /* useg should point to last segment on unacked queue */
399 for (; useg->next != NULL; useg = useg->next);
402 /* If the TF_ACK_NOW flag is set and no data will be sent (either
403 * because the ->unsent queue is empty or because the window does
404 * not allow it), construct an empty ACK segment and send it.
406 * If data is to be sent, we will just piggyback the ACK (see below).
408 if (pcb->flags & TF_ACK_NOW &&
410 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
411 p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
413 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n"));
416 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt));
417 /* remove ACK flags from the PCB, as we send an empty ACK now */
418 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
421 tcphdr->src = htons(pcb->local_port);
422 tcphdr->dest = htons(pcb->remote_port);
423 tcphdr->seqno = htonl(pcb->snd_nxt);
424 tcphdr->ackno = htonl(pcb->rcv_nxt);
425 TCPH_FLAGS_SET(tcphdr, TCP_ACK);
426 tcphdr->wnd = htons(pcb->rcv_wnd);
428 TCPH_HDRLEN_SET(tcphdr, 5);
432 tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
433 IP_PROTO_TCP, p->tot_len);
435 ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
444 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n", (void*)pcb->unsent));
446 #endif /* TCP_OUTPUT_DEBUG */
449 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U32_F", cwnd %"U16_F", wnd %"U32_F", seg == NULL, ack %"U32_F"\n",
450 pcb->snd_wnd, pcb->cwnd, wnd,
453 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U32_F", cwnd %"U16_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F"\n",
454 pcb->snd_wnd, pcb->cwnd, wnd,
455 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len,
456 ntohl(seg->tcphdr->seqno), pcb->lastack));
458 #endif /* TCP_CWND_DEBUG */
459 /* data available and window allows it to be sent? */
460 while (seg != NULL &&
461 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
463 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U32_F", cwnd %"U16_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F", i %"S16_F"\n",
464 pcb->snd_wnd, pcb->cwnd, wnd,
465 ntohl(seg->tcphdr->seqno) + seg->len -
467 ntohl(seg->tcphdr->seqno), pcb->lastack, i));
469 #endif /* TCP_CWND_DEBUG */
471 pcb->unsent = seg->next;
473 if (pcb->state != SYN_SENT) {
474 TCPH_SET_FLAG(seg->tcphdr, TCP_ACK);
475 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
478 tcp_output_segment(seg, pcb);
479 pcb->snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);
480 if (TCP_SEQ_LT(pcb->snd_max, pcb->snd_nxt)) {
481 pcb->snd_max = pcb->snd_nxt;
483 /* put segment on unacknowledged list if length > 0 */
484 if (TCP_TCPLEN(seg) > 0) {
486 /* unacked list is empty? */
487 if (pcb->unacked == NULL) {
490 /* unacked list is not empty? */
492 /* In the case of fast retransmit, the packet should not go to the tail
493 * of the unacked queue, but rather at the head. We need to check for
494 * this case. -STJ Jul 27, 2004 */
495 if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))){
496 /* add segment to head of unacked list */
497 seg->next = pcb->unacked;
500 /* add segment to tail of unacked list */
505 /* do not queue empty segments on the unacked list */
515 * Actually send a TCP segment over IP
518 tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
523 /* The TCP header has already been constructed, but the ackno and
524 wnd fields remain. */
525 seg->tcphdr->ackno = htonl(pcb->rcv_nxt);
527 /* silly window avoidance */
528 if (pcb->rcv_wnd < pcb->mss) {
529 seg->tcphdr->wnd = 0;
531 /* advertise our receive window size in this TCP segment */
532 seg->tcphdr->wnd = htons(pcb->rcv_wnd);
535 /* If we don't have a local IP address, we get one by
536 calling ip_route(). */
537 if (ip_addr_isany(&(pcb->local_ip))) {
538 netif = ip_route(&(pcb->remote_ip));
542 ip_addr_set(&(pcb->local_ip), &(netif->ip_addr));
547 if (pcb->rttest == 0) {
548 pcb->rttest = tcp_ticks;
549 pcb->rtseq = ntohl(seg->tcphdr->seqno);
551 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq));
553 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n",
554 htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) +
557 len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload);
560 seg->p->tot_len -= len;
562 seg->p->payload = seg->tcphdr;
564 seg->tcphdr->chksum = 0;
566 seg->tcphdr->chksum = inet_chksum_pseudo(seg->p,
569 IP_PROTO_TCP, seg->p->tot_len);
571 TCP_STATS_INC(tcp.xmit);
573 ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
578 tcp_rst(u32_t seqno, u32_t ackno,
579 struct ip_addr *local_ip, struct ip_addr *remote_ip,
580 u16_t local_port, u16_t remote_port)
583 struct tcp_hdr *tcphdr;
584 p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
586 LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n"));
591 tcphdr->src = htons(local_port);
592 tcphdr->dest = htons(remote_port);
593 tcphdr->seqno = htonl(seqno);
594 tcphdr->ackno = htonl(ackno);
595 TCPH_FLAGS_SET(tcphdr, TCP_RST | TCP_ACK);
596 tcphdr->wnd = htons(TCP_WND);
598 TCPH_HDRLEN_SET(tcphdr, 5);
602 tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip,
603 IP_PROTO_TCP, p->tot_len);
605 TCP_STATS_INC(tcp.xmit);
606 /* Send output with hardcoded TTL since we have no access to the pcb */
607 ip_output(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP);
609 LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno));
612 /* requeue all unacked segments for retransmission */
614 tcp_rexmit_rto(struct tcp_pcb *pcb)
618 if (pcb->unacked == NULL) {
622 /* Move all unacked segments to the head of the unsent queue */
623 for (seg = pcb->unacked; seg->next != NULL; seg = seg->next);
624 /* concatenate unsent queue after unacked queue */
625 seg->next = pcb->unsent;
626 /* unsent queue is the concatenated queue (of unacked, unsent) */
627 pcb->unsent = pcb->unacked;
628 /* unacked queue is now empty */
631 pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);
632 /* increment number of retransmissions */
635 /* Don't take any RTT measurements after retransmitting. */
638 /* Do the actual retransmission */
643 tcp_rexmit(struct tcp_pcb *pcb)
647 if (pcb->unacked == NULL) {
651 /* Move the first unacked segment to the unsent queue */
652 seg = pcb->unacked->next;
653 pcb->unacked->next = pcb->unsent;
654 pcb->unsent = pcb->unacked;
657 pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);
661 /* Don't take any rtt measurements after retransmitting. */
664 /* Do the actual retransmission. */
671 tcp_keepalive(struct tcp_pcb *pcb)
674 struct tcp_hdr *tcphdr;
676 LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
677 ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
678 ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
680 LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt %"U16_F"\n", tcp_ticks, pcb->tmr, pcb->keep_cnt));
682 p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
685 LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: could not allocate memory for pbuf\n"));
690 tcphdr->src = htons(pcb->local_port);
691 tcphdr->dest = htons(pcb->remote_port);
692 tcphdr->seqno = htonl(pcb->snd_nxt - 1);
693 tcphdr->ackno = htonl(pcb->rcv_nxt);
694 tcphdr->wnd = htons(pcb->rcv_wnd);
696 TCPH_HDRLEN_SET(tcphdr, 5);
700 tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip, IP_PROTO_TCP, p->tot_len);
702 TCP_STATS_INC(tcp.xmit);
704 /* Send output to IP */
705 ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
709 LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F".\n", pcb->snd_nxt - 1, pcb->rcv_nxt));
712 #endif /* LWIP_TCP */