Port of LwIP performed by Ralf in 2010. Not recommended for use with recent mbed libraries, but good demos of raw LwIP possible

Dependents:   LwIP_raw_API_serverExample tiny-dtls

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers tcp_out.c Source File

tcp_out.c

Go to the documentation of this file.
00001 /**
00002  * @file
00003  * Transmission Control Protocol, outgoing traffic
00004  *
00005  * The output functions of TCP.
00006  *
00007  */
00008 
00009 /*
00010  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
00011  * All rights reserved.
00012  *
00013  * Redistribution and use in source and binary forms, with or without modification,
00014  * are permitted provided that the following conditions are met:
00015  *
00016  * 1. Redistributions of source code must retain the above copyright notice,
00017  *    this list of conditions and the following disclaimer.
00018  * 2. Redistributions in binary form must reproduce the above copyright notice,
00019  *    this list of conditions and the following disclaimer in the documentation
00020  *    and/or other materials provided with the distribution.
00021  * 3. The name of the author may not be used to endorse or promote products
00022  *    derived from this software without specific prior written permission.
00023  *
00024  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
00025  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00026  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
00027  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00028  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
00029  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00030  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00031  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
00032  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
00033  * OF SUCH DAMAGE.
00034  *
00035  * This file is part of the lwIP TCP/IP stack.
00036  *
00037  * Author: Adam Dunkels <adam@sics.se>
00038  *
00039  */
00040 
00041 #include "lwip/opt.h"
00042 
00043 #if LWIP_TCP /* don't build if not configured for use in lwipopts.h */
00044 
00045 #include "lwip/tcp.h"
00046 #include "lwip/def.h"
00047 #include "lwip/mem.h"
00048 #include "lwip/memp.h"
00049 #include "lwip/sys.h"
00050 #include "lwip/ip_addr.h"
00051 #include "lwip/netif.h"
00052 #include "lwip/inet.h"
00053 #include "lwip/inet_chksum.h"
00054 #include "lwip/stats.h"
00055 #include "lwip/snmp.h"
00056 
00057 #include <string.h>
00058 
00059 /* Forward declarations.*/
00060 static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb);
00061 
00062 static struct tcp_hdr *
00063 tcp_output_set_header(struct tcp_pcb *pcb, struct pbuf *p, int optlen,
00064                       u32_t seqno_be /* already in network byte order */)
00065 {
00066   struct tcp_hdr *tcphdr = (struct tcp_hdr *)p->payload;
00067   tcphdr->src = htons(pcb->local_port);
00068   tcphdr->dest = htons(pcb->remote_port);
00069   tcphdr->seqno = seqno_be;
00070   tcphdr->ackno = htonl(pcb->rcv_nxt);
00071   TCPH_FLAGS_SET(tcphdr, TCP_ACK);
00072   tcphdr->wnd = htons(pcb->rcv_ann_wnd);
00073   tcphdr->urgp = 0;
00074   TCPH_HDRLEN_SET(tcphdr, (5 + optlen / 4));
00075   tcphdr->chksum = 0;
00076 
00077   /* If we're sending a packet, update the announced right window edge */
00078   pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
00079 
00080   return tcphdr;
00081 }
00082 
00083 /**
00084  * Called by tcp_close() to send a segment including flags but not data.
00085  *
00086  * @param pcb the tcp_pcb over which to send a segment
00087  * @param flags the flags to set in the segment header
00088  * @return ERR_OK if sent, another err_t otherwise
00089  */
00090 err_t
00091 tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags)
00092 {
00093   /* no data, no length, flags, copy=1, no optdata */
00094   return tcp_enqueue(pcb, NULL, 0, flags, TCP_WRITE_FLAG_COPY, 0);
00095 }
00096 
00097 /**
00098  * Write data for sending (but does not send it immediately).
00099  *
00100  * It waits in the expectation of more data being sent soon (as
00101  * it can send them more efficiently by combining them together).
00102  * To prompt the system to send data now, call tcp_output() after
00103  * calling tcp_write().
00104  * 
00105  * @param pcb Protocol control block of the TCP connection to enqueue data for.
00106  * @param data pointer to the data to send
00107  * @param len length (in bytes) of the data to send
00108  * @param apiflags combination of following flags :
00109  * - TCP_WRITE_FLAG_COPY (0x01) data will be copied into memory belonging to the stack
00110  * - TCP_WRITE_FLAG_MORE (0x02) for TCP connection, PSH flag will be set on last segment sent,
00111  * @return ERR_OK if enqueued, another err_t on error
00112  * 
00113  * @see tcp_write()
00114  */
00115 err_t
00116 tcp_write(struct tcp_pcb *pcb, const void *data, u16_t len, u8_t apiflags)
00117 {
00118   LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, data=%p, len=%"U16_F", apiflags=%"U16_F")\n", (void *)pcb,
00119     data, len, (u16_t)apiflags));
00120   /* connection is in valid state for data transmission? */
00121   if (pcb->state == ESTABLISHED ||
00122      pcb->state == CLOSE_WAIT ||
00123      pcb->state == SYN_SENT ||
00124      pcb->state == SYN_RCVD) {
00125     if (len > 0) {
00126 #if LWIP_TCP_TIMESTAMPS
00127       return tcp_enqueue(pcb, (void *)data, len, 0, apiflags, 
00128                          pcb->flags & TF_TIMESTAMP ? TF_SEG_OPTS_TS : 0);
00129 #else
00130       return tcp_enqueue(pcb, (void *)data, len, 0, apiflags, 0);
00131 #endif
00132     }
00133     return ERR_OK;
00134   } else {
00135     LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_STATE | 3, ("tcp_write() called in invalid state\n"));
00136     return ERR_CONN;
00137   }
00138 }
00139 
00140 /**
00141  * Enqueue data and/or TCP options for transmission
00142  *
00143  * Called by tcp_connect(), tcp_listen_input(), tcp_send_ctrl() and tcp_write().
00144  *
00145  * @param pcb Protocol control block for the TCP connection to enqueue data for.
00146  * @param arg Pointer to the data to be enqueued for sending.
00147  * @param len Data length in bytes
00148  * @param flags tcp header flags to set in the outgoing segment
00149  * @param apiflags combination of following flags :
00150  * - TCP_WRITE_FLAG_COPY (0x01) data will be copied into memory belonging to the stack
00151  * - TCP_WRITE_FLAG_MORE (0x02) for TCP connection, PSH flag will be set on last segment sent,
00152  * @param optflags options to include in segment later on (see definition of struct tcp_seg)
00153  */
00154 err_t
00155 tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
00156             u8_t flags, u8_t apiflags, u8_t optflags)
00157 {
00158   struct pbuf *p;
00159   struct tcp_seg *seg, *useg, *queue;
00160   u32_t seqno;
00161   u16_t left, seglen;
00162   void *ptr;
00163   u16_t queuelen;
00164   u8_t optlen;
00165 
00166   LWIP_DEBUGF(TCP_OUTPUT_DEBUG, 
00167               ("tcp_enqueue(pcb=%p, arg=%p, len=%"U16_F", flags=%"X16_F", apiflags=%"U16_F")\n",
00168                (void *)pcb, arg, len, (u16_t)flags, (u16_t)apiflags));
00169   LWIP_ERROR("tcp_enqueue: packet needs payload, options, or SYN/FIN (programmer violates API)",
00170              ((len != 0) || (optflags != 0) || ((flags & (TCP_SYN | TCP_FIN)) != 0)),
00171              return ERR_ARG;);
00172   LWIP_ERROR("tcp_enqueue: len != 0 || arg == NULL (programmer violates API)", 
00173              ((len != 0) || (arg == NULL)), return ERR_ARG;);
00174 
00175   /* fail on too much data */
00176   if (len > pcb->snd_buf) {
00177     LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too much data (len=%"U16_F" > snd_buf=%"U16_F")\n", len, pcb->snd_buf));
00178     pcb->flags |= TF_NAGLEMEMERR;
00179     return ERR_MEM;
00180   }
00181   left = len;
00182   ptr = arg;
00183 
00184   optlen = LWIP_TCP_OPT_LENGTH(optflags);
00185 
00186   /* seqno will be the sequence number of the first segment enqueued
00187    * by the call to this function. */
00188   seqno = pcb->snd_lbb;
00189 
00190   LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen));
00191 
00192   /* If total number of pbufs on the unsent/unacked queues exceeds the
00193    * configured maximum, return an error */
00194   queuelen = pcb->snd_queuelen;
00195   /* check for configured max queuelen and possible overflow */
00196   if ((queuelen >= TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
00197     LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too long queue %"U16_F" (max %"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
00198     TCP_STATS_INC(tcp.memerr);
00199     pcb->flags |= TF_NAGLEMEMERR;
00200     return ERR_MEM;
00201   }
00202   if (queuelen != 0) {
00203     LWIP_ASSERT("tcp_enqueue: pbufs on queue => at least one queue non-empty",
00204       pcb->unacked != NULL || pcb->unsent != NULL);
00205   } else {
00206     LWIP_ASSERT("tcp_enqueue: no pbufs on queue => both queues empty",
00207       pcb->unacked == NULL && pcb->unsent == NULL);
00208   }
00209 
00210   /* First, break up the data into segments and tuck them together in
00211    * the local "queue" variable. */
00212   useg = queue = seg = NULL;
00213   seglen = 0;
00214   while (queue == NULL || left > 0) {
00215     /* The segment length (including options) should be at most the MSS */
00216     seglen = left > (pcb->mss - optlen) ? (pcb->mss - optlen) : left;
00217 
00218     /* Allocate memory for tcp_seg, and fill in fields. */
00219     seg = (struct tcp_seg *)memp_malloc(MEMP_TCP_SEG);
00220     if (seg == NULL) {
00221       LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, 
00222                   ("tcp_enqueue: could not allocate memory for tcp_seg\n"));
00223       goto memerr;
00224     }
00225     seg->next = NULL;
00226     seg->p = NULL;
00227 
00228     /* first segment of to-be-queued data? */
00229     if (queue == NULL) {
00230       queue = seg;
00231     }
00232     /* subsequent segments of to-be-queued data */
00233     else {
00234       /* Attach the segment to the end of the queued segments */
00235       LWIP_ASSERT("useg != NULL", useg != NULL);
00236       useg->next = seg;
00237     }
00238     /* remember last segment of to-be-queued data for next iteration */
00239     useg = seg;
00240 
00241     /* If copy is set, memory should be allocated
00242      * and data copied into pbuf, otherwise data comes from
00243      * ROM or other static memory, and need not be copied.  */
00244     if (apiflags & TCP_WRITE_FLAG_COPY) {
00245       if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, seglen + optlen, PBUF_RAM)) == NULL) {
00246         LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, 
00247                     ("tcp_enqueue : could not allocate memory for pbuf copy size %"U16_F"\n", seglen));
00248         goto memerr;
00249       }
00250       LWIP_ASSERT("check that first pbuf can hold the complete seglen",
00251                   (seg->p->len >= seglen + optlen));
00252       queuelen += pbuf_clen(seg->p);
00253       if (arg != NULL) {
00254         MEMCPY((char *)seg->p->payload + optlen, ptr, seglen);
00255       }
00256       seg->dataptr = seg->p->payload;
00257     }
00258     /* do not copy data */
00259     else {
00260       /* First, allocate a pbuf for the headers. */
00261       if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
00262         LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, 
00263                     ("tcp_enqueue: could not allocate memory for header pbuf\n"));
00264         goto memerr;
00265       }
00266       queuelen += pbuf_clen(seg->p);
00267 
00268       /* Second, allocate a pbuf for holding the data.
00269        * since the referenced data is available at least until it is sent out on the
00270        * link (as it has to be ACKed by the remote party) we can safely use PBUF_ROM
00271        * instead of PBUF_REF here.
00272        */
00273       if (left > 0) {
00274         if ((p = pbuf_alloc(PBUF_RAW, seglen, PBUF_ROM)) == NULL) {
00275           /* If allocation fails, we have to deallocate the header pbuf as well. */
00276           pbuf_free(seg->p);
00277           seg->p = NULL;
00278           LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, 
00279                       ("tcp_enqueue: could not allocate memory for zero-copy pbuf\n"));
00280           goto memerr;
00281         }
00282         ++queuelen;
00283         /* reference the non-volatile payload data */
00284         p->payload = ptr;
00285         seg->dataptr = ptr;
00286 
00287         /* Concatenate the headers and data pbufs together. */
00288         pbuf_cat(seg->p/*header*/, p/*data*/);
00289         p = NULL;
00290       }
00291     }
00292 
00293     /* Now that there are more segments queued, we check again if the
00294     length of the queue exceeds the configured maximum or overflows. */
00295     if ((queuelen > TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
00296       LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: queue too long %"U16_F" (%"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
00297       goto memerr;
00298     }
00299 
00300     seg->len = seglen;
00301 
00302     /* build TCP header */
00303     if (pbuf_header(seg->p, TCP_HLEN)) {
00304       LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: no room for TCP header in pbuf.\n"));
00305       TCP_STATS_INC(tcp.err);
00306       goto memerr;
00307     }
00308     seg->tcphdr = (struct tcp_hdr *)seg->p->payload;
00309     seg->tcphdr->src = htons(pcb->local_port);
00310     seg->tcphdr->dest = htons(pcb->remote_port);
00311     seg->tcphdr->seqno = htonl(seqno);
00312     seg->tcphdr->urgp = 0;
00313     TCPH_FLAGS_SET(seg->tcphdr, flags);
00314     /* don't fill in tcphdr->ackno and tcphdr->wnd until later */
00315 
00316     seg->flags = optflags;
00317 
00318     /* Set the length of the header */
00319     TCPH_HDRLEN_SET(seg->tcphdr, (5 + optlen / 4));
00320     LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, ("tcp_enqueue: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n",
00321       ntohl(seg->tcphdr->seqno),
00322       ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
00323       (u16_t)flags));
00324 
00325     left -= seglen;
00326     seqno += seglen;
00327     ptr = (void *)((u8_t *)ptr + seglen);
00328   }
00329 
00330   /* Now that the data to be enqueued has been broken up into TCP
00331   segments in the queue variable, we add them to the end of the
00332   pcb->unsent queue. */
00333   if (pcb->unsent == NULL) {
00334     useg = NULL;
00335   }
00336   else {
00337     for (useg = pcb->unsent; useg->next != NULL; useg = useg->next);
00338   }
00339   /* { useg is last segment on the unsent queue, NULL if list is empty } */
00340 
00341   /* If there is room in the last pbuf on the unsent queue,
00342   chain the first pbuf on the queue together with that. */
00343   if (useg != NULL &&
00344     TCP_TCPLEN(useg) != 0 &&
00345     !(TCPH_FLAGS(useg->tcphdr) & (TCP_SYN | TCP_FIN)) &&
00346     !(flags & (TCP_SYN | TCP_FIN)) &&
00347     /* fit within max seg size */
00348     (useg->len + queue->len <= pcb->mss) &&
00349     /* only concatenate segments with the same options */
00350     (useg->flags == queue->flags) &&
00351     /* segments are consecutive */
00352     (ntohl(useg->tcphdr->seqno) + useg->len == ntohl(queue->tcphdr->seqno)) ) {
00353     /* Remove TCP header from first segment of our to-be-queued list */
00354     if(pbuf_header(queue->p, -(TCP_HLEN + optlen))) {
00355       /* Can we cope with this failing?  Just assert for now */
00356       LWIP_ASSERT("pbuf_header failed\n", 0);
00357       TCP_STATS_INC(tcp.err);
00358       goto memerr;
00359     }
00360     if (queue->p->len == 0) {
00361       /* free the first (header-only) pbuf if it is now empty (contained only headers) */
00362       struct pbuf *old_q = queue->p;
00363       queue->p = queue->p->next;
00364       old_q->next = NULL;
00365       queuelen--;
00366       pbuf_free(old_q);
00367     }
00368     LWIP_ASSERT("zero-length pbuf", (queue->p != NULL) && (queue->p->len > 0));
00369     pbuf_cat(useg->p, queue->p);
00370     useg->len += queue->len;
00371     useg->next = queue->next;
00372 
00373     LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("tcp_enqueue: chaining segments, new len %"U16_F"\n", useg->len));
00374     if (seg == queue) {
00375       seg = useg;
00376       seglen = useg->len;
00377     }
00378     memp_free(MEMP_TCP_SEG, queue);
00379   }
00380   else {
00381     /* empty list */
00382     if (useg == NULL) {
00383       /* initialize list with this segment */
00384       pcb->unsent = queue;
00385     }
00386     /* enqueue segment */
00387     else {
00388       useg->next = queue;
00389     }
00390   }
00391   if ((flags & TCP_SYN) || (flags & TCP_FIN)) {
00392     ++len;
00393   }
00394   if (flags & TCP_FIN) {
00395     pcb->flags |= TF_FIN;
00396   }
00397   pcb->snd_lbb += len;
00398 
00399   pcb->snd_buf -= len;
00400 
00401   /* update number of segments on the queues */
00402   pcb->snd_queuelen = queuelen;
00403   LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %"S16_F" (after enqueued)\n", pcb->snd_queuelen));
00404   if (pcb->snd_queuelen != 0) {
00405     LWIP_ASSERT("tcp_enqueue: valid queue length",
00406       pcb->unacked != NULL || pcb->unsent != NULL);
00407   }
00408 
00409   /* Set the PSH flag in the last segment that we enqueued, but only
00410   if the segment has data (indicated by seglen > 0). */
00411   if (seg != NULL && seglen > 0 && seg->tcphdr != NULL && ((apiflags & TCP_WRITE_FLAG_MORE)==0)) {
00412     TCPH_SET_FLAG(seg->tcphdr, TCP_PSH);
00413   }
00414 
00415   return ERR_OK;
00416 memerr:
00417   pcb->flags |= TF_NAGLEMEMERR;
00418   TCP_STATS_INC(tcp.memerr);
00419 
00420   if (queue != NULL) {
00421     tcp_segs_free(queue);
00422   }
00423   if (pcb->snd_queuelen != 0) {
00424     LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
00425       pcb->unsent != NULL);
00426   }
00427   LWIP_DEBUGF(TCP_QLEN_DEBUG | LWIP_DBG_STATE, ("tcp_enqueue: %"S16_F" (with mem err)\n", pcb->snd_queuelen));
00428   return ERR_MEM;
00429 }
00430 
00431 
00432 #if LWIP_TCP_TIMESTAMPS
00433 /* Build a timestamp option (12 bytes long) at the specified options pointer)
00434  *
00435  * @param pcb tcp_pcb
00436  * @param opts option pointer where to store the timestamp option
00437  */
00438 static void
00439 tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts)
00440 {
00441   /* Pad with two NOP options to make everything nicely aligned */
00442   opts[0] = htonl(0x0101080A);
00443   opts[1] = htonl(sys_now());
00444   opts[2] = htonl(pcb->ts_recent);
00445 }
00446 #endif
00447 
00448 
00449 /**
00450  * Find out what we can send and send it
00451  *
00452  * @param pcb Protocol control block for the TCP connection to send data
00453  * @return ERR_OK if data has been sent or nothing to send
00454  *         another err_t on error
00455  */
00456 err_t
00457 tcp_output(struct tcp_pcb *pcb)
00458 {
00459   struct pbuf *p;
00460   struct tcp_hdr *tcphdr;
00461   struct tcp_seg *seg, *useg;
00462   u32_t wnd, snd_nxt;
00463 #if TCP_CWND_DEBUG
00464   s16_t i = 0;
00465 #endif /* TCP_CWND_DEBUG */
00466   u8_t optlen = 0;
00467 
00468   /* First, check if we are invoked by the TCP input processing
00469      code. If so, we do not output anything. Instead, we rely on the
00470      input processing code to call us when input processing is done
00471      with. */
00472   if (tcp_input_pcb == pcb) {
00473     return ERR_OK;
00474   }
00475 
00476   wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd);
00477 
00478   seg = pcb->unsent;
00479 
00480   /* useg should point to last segment on unacked queue */
00481   useg = pcb->unacked;
00482   if (useg != NULL) {
00483     for (; useg->next != NULL; useg = useg->next);
00484   }
00485 
00486   /* If the TF_ACK_NOW flag is set and no data will be sent (either
00487    * because the ->unsent queue is empty or because the window does
00488    * not allow it), construct an empty ACK segment and send it.
00489    *
00490    * If data is to be sent, we will just piggyback the ACK (see below).
00491    */
00492   if (pcb->flags & TF_ACK_NOW &&
00493      (seg == NULL ||
00494       ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
00495 #if LWIP_TCP_TIMESTAMPS
00496     if (pcb->flags & TF_TIMESTAMP)
00497       optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS);
00498 #endif
00499     p = pbuf_alloc(PBUF_IP, TCP_HLEN + optlen, PBUF_RAM);
00500     if (p == NULL) {
00501       LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n"));
00502       return ERR_BUF;
00503     }
00504     LWIP_DEBUGF(TCP_OUTPUT_DEBUG, 
00505                 ("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt));
00506     /* remove ACK flags from the PCB, as we send an empty ACK now */
00507     pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
00508 
00509     tcphdr = tcp_output_set_header(pcb, p, optlen, htonl(pcb->snd_nxt));
00510 
00511     /* NB. MSS option is only sent on SYNs, so ignore it here */
00512 #if LWIP_TCP_TIMESTAMPS
00513     pcb->ts_lastacksent = pcb->rcv_nxt;
00514 
00515     if (pcb->flags & TF_TIMESTAMP)
00516       tcp_build_timestamp_option(pcb, (u32_t *)(tcphdr + 1));
00517 #endif 
00518 
00519 #if CHECKSUM_GEN_TCP
00520     tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
00521           IP_PROTO_TCP, p->tot_len);
00522 #endif
00523 #if LWIP_NETIF_HWADDRHINT
00524     ip_output_hinted(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
00525         IP_PROTO_TCP, &(pcb->addr_hint));
00526 #else /* LWIP_NETIF_HWADDRHINT*/
00527     ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
00528         IP_PROTO_TCP);
00529 #endif /* LWIP_NETIF_HWADDRHINT*/
00530     pbuf_free(p);
00531 
00532     return ERR_OK;
00533   }
00534 
00535 #if TCP_OUTPUT_DEBUG
00536   if (seg == NULL) {
00537     LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n",
00538                                    (void*)pcb->unsent));
00539   }
00540 #endif /* TCP_OUTPUT_DEBUG */
00541 #if TCP_CWND_DEBUG
00542   if (seg == NULL) {
00543     LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U16_F
00544                                  ", cwnd %"U16_F", wnd %"U32_F
00545                                  ", seg == NULL, ack %"U32_F"\n",
00546                                  pcb->snd_wnd, pcb->cwnd, wnd, pcb->lastack));
00547   } else {
00548     LWIP_DEBUGF(TCP_CWND_DEBUG, 
00549                 ("tcp_output: snd_wnd %"U16_F", cwnd %"U16_F", wnd %"U32_F
00550                  ", effwnd %"U32_F", seq %"U32_F", ack %"U32_F"\n",
00551                  pcb->snd_wnd, pcb->cwnd, wnd,
00552                  ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len,
00553                  ntohl(seg->tcphdr->seqno), pcb->lastack));
00554   }
00555 #endif /* TCP_CWND_DEBUG */
00556   /* data available and window allows it to be sent? */
00557   while (seg != NULL &&
00558          ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
00559     LWIP_ASSERT("RST not expected here!", 
00560                 (TCPH_FLAGS(seg->tcphdr) & TCP_RST) == 0);
00561     /* Stop sending if the nagle algorithm would prevent it
00562      * Don't stop:
00563      * - if tcp_enqueue had a memory error before (prevent delayed ACK timeout) or
00564      * - if FIN was already enqueued for this PCB (SYN is always alone in a segment -
00565      *   either seg->next != NULL or pcb->unacked == NULL;
00566      *   RST is no sent using tcp_enqueue/tcp_output.
00567      */
00568     if((tcp_do_output_nagle(pcb) == 0) &&
00569       ((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)){
00570       break;
00571     }
00572 #if TCP_CWND_DEBUG
00573     LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U16_F", cwnd %"U16_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F", i %"S16_F"\n",
00574                             pcb->snd_wnd, pcb->cwnd, wnd,
00575                             ntohl(seg->tcphdr->seqno) + seg->len -
00576                             pcb->lastack,
00577                             ntohl(seg->tcphdr->seqno), pcb->lastack, i));
00578     ++i;
00579 #endif /* TCP_CWND_DEBUG */
00580 
00581     pcb->unsent = seg->next;
00582 
00583     if (pcb->state != SYN_SENT) {
00584       TCPH_SET_FLAG(seg->tcphdr, TCP_ACK);
00585       pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
00586     }
00587 
00588     tcp_output_segment(seg, pcb);
00589     snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);
00590     if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) {
00591       pcb->snd_nxt = snd_nxt;
00592     }
00593     /* put segment on unacknowledged list if length > 0 */
00594     if (TCP_TCPLEN(seg) > 0) {
00595       seg->next = NULL;
00596       /* unacked list is empty? */
00597       if (pcb->unacked == NULL) {
00598         pcb->unacked = seg;
00599         useg = seg;
00600       /* unacked list is not empty? */
00601       } else {
00602         /* In the case of fast retransmit, the packet should not go to the tail
00603          * of the unacked queue, but rather somewhere before it. We need to check for
00604          * this case. -STJ Jul 27, 2004 */
00605         if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))){
00606           /* add segment to before tail of unacked list, keeping the list sorted */
00607           struct tcp_seg **cur_seg = &(pcb->unacked);
00608           while (*cur_seg &&
00609             TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) {
00610               cur_seg = &((*cur_seg)->next );
00611           }
00612           seg->next = (*cur_seg);
00613           (*cur_seg) = seg;
00614         } else {
00615           /* add segment to tail of unacked list */
00616           useg->next = seg;
00617           useg = useg->next;
00618         }
00619       }
00620     /* do not queue empty segments on the unacked list */
00621     } else {
00622       tcp_seg_free(seg);
00623     }
00624     seg = pcb->unsent;
00625   }
00626 
00627   if (seg != NULL && pcb->persist_backoff == 0 && 
00628       ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > pcb->snd_wnd) {
00629     /* prepare for persist timer */
00630     pcb->persist_cnt = 0;
00631     pcb->persist_backoff = 1;
00632   }
00633 
00634   pcb->flags &= ~TF_NAGLEMEMERR;
00635   return ERR_OK;
00636 }
00637 
00638 /**
00639  * Called by tcp_output() to actually send a TCP segment over IP.
00640  *
00641  * @param seg the tcp_seg to send
00642  * @param pcb the tcp_pcb for the TCP connection used to send the segment
00643  */
00644 static void
00645 tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
00646 {
00647   u16_t len;
00648   struct netif *netif;
00649   u32_t *opts;
00650 
00651   /** @bug Exclude retransmitted segments from this count. */
00652   snmp_inc_tcpoutsegs();
00653 
00654   /* The TCP header has already been constructed, but the ackno and
00655    wnd fields remain. */
00656   seg->tcphdr->ackno = htonl(pcb->rcv_nxt);
00657 
00658   /* advertise our receive window size in this TCP segment */
00659   seg->tcphdr->wnd = htons(pcb->rcv_ann_wnd);
00660 
00661   pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
00662 
00663   /* Add any requested options.  NB MSS option is only set on SYN
00664      packets, so ignore it here */
00665   opts = (u32_t *)(seg->tcphdr + 1);
00666   if (seg->flags & TF_SEG_OPTS_MSS) {
00667     TCP_BUILD_MSS_OPTION(*opts);
00668     opts += 1;
00669   }
00670 #if LWIP_TCP_TIMESTAMPS
00671   pcb->ts_lastacksent = pcb->rcv_nxt;
00672 
00673   if (seg->flags & TF_SEG_OPTS_TS) {
00674     tcp_build_timestamp_option(pcb, opts);
00675     opts += 3;
00676   }
00677 #endif
00678 
00679   /* If we don't have a local IP address, we get one by
00680      calling ip_route(). */
00681   if (ip_addr_isany(&(pcb->local_ip))) {
00682     netif = ip_route(&(pcb->remote_ip));
00683     if (netif == NULL) {
00684       return;
00685     }
00686     ip_addr_set(&(pcb->local_ip), &(netif->ip_addr));
00687   }
00688 
00689   /* Set retransmission timer running if it is not currently enabled */
00690   if(pcb->rtime == -1)
00691     pcb->rtime = 0;
00692 
00693   if (pcb->rttest == 0) {
00694     pcb->rttest = tcp_ticks;
00695     pcb->rtseq = ntohl(seg->tcphdr->seqno);
00696 
00697     LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq));
00698   }
00699   LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n",
00700           htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) +
00701           seg->len));
00702 
00703   len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload);
00704 
00705   seg->p->len -= len;
00706   seg->p->tot_len -= len;
00707 
00708   seg->p->payload = seg->tcphdr;
00709 
00710   seg->tcphdr->chksum = 0;
00711 #if CHECKSUM_GEN_TCP
00712   seg->tcphdr->chksum = inet_chksum_pseudo(seg->p,
00713              &(pcb->local_ip),
00714              &(pcb->remote_ip),
00715              IP_PROTO_TCP, seg->p->tot_len);
00716 #endif
00717   TCP_STATS_INC(tcp.xmit);
00718 
00719 #if LWIP_NETIF_HWADDRHINT
00720   ip_output_hinted(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
00721       IP_PROTO_TCP, &(pcb->addr_hint));
00722 #else /* LWIP_NETIF_HWADDRHINT*/
00723   ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
00724       IP_PROTO_TCP);
00725 #endif /* LWIP_NETIF_HWADDRHINT*/
00726 }
00727 
00728 /**
00729  * Send a TCP RESET packet (empty segment with RST flag set) either to
00730  * abort a connection or to show that there is no matching local connection
00731  * for a received segment.
00732  *
00733  * Called by tcp_abort() (to abort a local connection), tcp_input() (if no
00734  * matching local pcb was found), tcp_listen_input() (if incoming segment
00735  * has ACK flag set) and tcp_process() (received segment in the wrong state)
00736  *
00737  * Since a RST segment is in most cases not sent for an active connection,
00738  * tcp_rst() has a number of arguments that are taken from a tcp_pcb for
00739  * most other segment output functions.
00740  *
00741  * @param seqno the sequence number to use for the outgoing segment
00742  * @param ackno the acknowledge number to use for the outgoing segment
00743  * @param local_ip the local IP address to send the segment from
00744  * @param remote_ip the remote IP address to send the segment to
00745  * @param local_port the local TCP port to send the segment from
00746  * @param remote_port the remote TCP port to send the segment to
00747  */
00748 void
00749 tcp_rst(u32_t seqno, u32_t ackno,
00750   struct ip_addr *local_ip, struct ip_addr *remote_ip,
00751   u16_t local_port, u16_t remote_port)
00752 {
00753   struct pbuf *p;
00754   struct tcp_hdr *tcphdr;
00755   p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
00756   if (p == NULL) {
00757       LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n"));
00758       return;
00759   }
00760   LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr",
00761               (p->len >= sizeof(struct tcp_hdr)));
00762 
00763   tcphdr = (struct tcp_hdr *)p->payload;
00764   tcphdr->src = htons(local_port);
00765   tcphdr->dest = htons(remote_port);
00766   tcphdr->seqno = htonl(seqno);
00767   tcphdr->ackno = htonl(ackno);
00768   TCPH_FLAGS_SET(tcphdr, TCP_RST | TCP_ACK);
00769   tcphdr->wnd = htons(TCP_WND);
00770   tcphdr->urgp = 0;
00771   TCPH_HDRLEN_SET(tcphdr, 5);
00772 
00773   tcphdr->chksum = 0;
00774 #if CHECKSUM_GEN_TCP
00775   tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip,
00776               IP_PROTO_TCP, p->tot_len);
00777 #endif
00778   TCP_STATS_INC(tcp.xmit);
00779   snmp_inc_tcpoutrsts();
00780    /* Send output with hardcoded TTL since we have no access to the pcb */
00781   ip_output(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP);
00782   pbuf_free(p);
00783   LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno));
00784 }
00785 
00786 /**
00787  * Requeue all unacked segments for retransmission
00788  *
00789  * Called by tcp_slowtmr() for slow retransmission.
00790  *
00791  * @param pcb the tcp_pcb for which to re-enqueue all unacked segments
00792  */
00793 void
00794 tcp_rexmit_rto(struct tcp_pcb *pcb)
00795 {
00796   struct tcp_seg *seg;
00797 
00798   if (pcb->unacked == NULL) {
00799     return;
00800   }
00801 
00802   /* Move all unacked segments to the head of the unsent queue */
00803   for (seg = pcb->unacked; seg->next != NULL; seg = seg->next);
00804   /* concatenate unsent queue after unacked queue */
00805   seg->next = pcb->unsent;
00806   /* unsent queue is the concatenated queue (of unacked, unsent) */
00807   pcb->unsent = pcb->unacked;
00808   /* unacked queue is now empty */
00809   pcb->unacked = NULL;
00810 
00811   /* increment number of retransmissions */
00812   ++pcb->nrtx;
00813 
00814   /* Don't take any RTT measurements after retransmitting. */
00815   pcb->rttest = 0;
00816 
00817   /* Do the actual retransmission */
00818   tcp_output(pcb);
00819 }
00820 
00821 /**
00822  * Requeue the first unacked segment for retransmission
00823  *
00824  * Called by tcp_receive() for fast retramsmit.
00825  *
00826  * @param pcb the tcp_pcb for which to retransmit the first unacked segment
00827  */
00828 void
00829 tcp_rexmit(struct tcp_pcb *pcb)
00830 {
00831   struct tcp_seg *seg;
00832   struct tcp_seg **cur_seg;
00833 
00834   if (pcb->unacked == NULL) {
00835     return;
00836   }
00837 
00838   /* Move the first unacked segment to the unsent queue */
00839   /* Keep the unsent queue sorted. */
00840   seg = pcb->unacked;
00841   pcb->unacked = seg->next;
00842 
00843   cur_seg = &(pcb->unsent);
00844   while (*cur_seg &&
00845     TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) {
00846       cur_seg = &((*cur_seg)->next );
00847   }
00848   seg->next = *cur_seg;
00849   *cur_seg = seg;
00850 
00851   ++pcb->nrtx;
00852 
00853   /* Don't take any rtt measurements after retransmitting. */
00854   pcb->rttest = 0;
00855 
00856   /* Do the actual retransmission. */
00857   snmp_inc_tcpretranssegs();
00858   tcp_output(pcb);
00859 }
00860 
00861 
00862 /**
00863  * Handle retransmission after three dupacks received
00864  *
00865  * @param pcb the tcp_pcb for which to retransmit the first unacked segment
00866  */
00867 void 
00868 tcp_rexmit_fast(struct tcp_pcb *pcb)
00869 {
00870   if (pcb->unacked != NULL && !(pcb->flags & TF_INFR)) {
00871     /* This is fast retransmit. Retransmit the first unacked segment. */
00872     LWIP_DEBUGF(TCP_FR_DEBUG, 
00873                 ("tcp_receive: dupacks %"U16_F" (%"U32_F
00874                  "), fast retransmit %"U32_F"\n",
00875                  (u16_t)pcb->dupacks, pcb->lastack,
00876                  ntohl(pcb->unacked->tcphdr->seqno)));
00877     tcp_rexmit(pcb);
00878 
00879     /* Set ssthresh to half of the minimum of the current
00880      * cwnd and the advertised window */
00881     if (pcb->cwnd > pcb->snd_wnd)
00882       pcb->ssthresh = pcb->snd_wnd / 2;
00883     else
00884       pcb->ssthresh = pcb->cwnd / 2;
00885     
00886     /* The minimum value for ssthresh should be 2 MSS */
00887     if (pcb->ssthresh < 2*pcb->mss) {
00888       LWIP_DEBUGF(TCP_FR_DEBUG, 
00889                   ("tcp_receive: The minimum value for ssthresh %"U16_F
00890                    " should be min 2 mss %"U16_F"...\n",
00891                    pcb->ssthresh, 2*pcb->mss));
00892       pcb->ssthresh = 2*pcb->mss;
00893     }
00894     
00895     pcb->cwnd = pcb->ssthresh + 3 * pcb->mss;
00896     pcb->flags |= TF_INFR;
00897   } 
00898 }
00899 
00900 
00901 /**
00902  * Send keepalive packets to keep a connection active although
00903  * no data is sent over it.
00904  *
00905  * Called by tcp_slowtmr()
00906  *
00907  * @param pcb the tcp_pcb for which to send a keepalive packet
00908  */
00909 void
00910 tcp_keepalive(struct tcp_pcb *pcb)
00911 {
00912   struct pbuf *p;
00913   struct tcp_hdr *tcphdr;
00914 
00915   LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
00916                           ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
00917                           ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
00918 
00919   LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F"   pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", 
00920                           tcp_ticks, pcb->tmr, pcb->keep_cnt_sent));
00921    
00922   p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
00923    
00924   if(p == NULL) {
00925     LWIP_DEBUGF(TCP_DEBUG, 
00926                 ("tcp_keepalive: could not allocate memory for pbuf\n"));
00927     return;
00928   }
00929   LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr",
00930               (p->len >= sizeof(struct tcp_hdr)));
00931 
00932   tcphdr = tcp_output_set_header(pcb, p, 0, htonl(pcb->snd_nxt - 1));
00933 
00934 #if CHECKSUM_GEN_TCP
00935   tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip,
00936                                       IP_PROTO_TCP, p->tot_len);
00937 #endif
00938   TCP_STATS_INC(tcp.xmit);
00939 
00940   /* Send output to IP */
00941 #if LWIP_NETIF_HWADDRHINT
00942   ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP,
00943     &(pcb->addr_hint));
00944 #else /* LWIP_NETIF_HWADDRHINT*/
00945   ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
00946 #endif /* LWIP_NETIF_HWADDRHINT*/
00947 
00948   pbuf_free(p);
00949 
00950   LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F".\n",
00951                           pcb->snd_nxt - 1, pcb->rcv_nxt));
00952 }
00953 
00954 
00955 /**
00956  * Send persist timer zero-window probes to keep a connection active
00957  * when a window update is lost.
00958  *
00959  * Called by tcp_slowtmr()
00960  *
00961  * @param pcb the tcp_pcb for which to send a zero-window probe packet
00962  */
00963 void
00964 tcp_zero_window_probe(struct tcp_pcb *pcb)
00965 {
00966   struct pbuf *p;
00967   struct tcp_hdr *tcphdr;
00968   struct tcp_seg *seg;
00969   u16_t len;
00970   u8_t is_fin;
00971 
00972   LWIP_DEBUGF(TCP_DEBUG, 
00973               ("tcp_zero_window_probe: sending ZERO WINDOW probe to %"
00974                U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
00975                ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
00976                ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
00977 
00978   LWIP_DEBUGF(TCP_DEBUG, 
00979               ("tcp_zero_window_probe: tcp_ticks %"U32_F
00980                "   pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", 
00981                tcp_ticks, pcb->tmr, pcb->keep_cnt_sent));
00982 
00983   seg = pcb->unacked;
00984 
00985   if(seg == NULL)
00986     seg = pcb->unsent;
00987 
00988   if(seg == NULL)
00989     return;
00990 
00991   is_fin = ((TCPH_FLAGS(seg->tcphdr) & TCP_FIN) != 0) && (seg->len == 0);
00992   len = is_fin ? TCP_HLEN : TCP_HLEN + 1;
00993 
00994   p = pbuf_alloc(PBUF_IP, len, PBUF_RAM);
00995   if(p == NULL) {
00996     LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: no memory for pbuf\n"));
00997     return;
00998   }
00999   LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr",
01000               (p->len >= sizeof(struct tcp_hdr)));
01001 
01002   tcphdr = tcp_output_set_header(pcb, p, 0, seg->tcphdr->seqno);
01003 
01004   if (is_fin) {
01005     /* FIN segment, no data */
01006     TCPH_FLAGS_SET(tcphdr, TCP_ACK | TCP_FIN);
01007   } else {
01008     /* Data segment, copy in one byte from the head of the unacked queue */
01009     *((char *)p->payload + sizeof(struct tcp_hdr)) = *(char *)seg->dataptr;
01010   }
01011 
01012 #if CHECKSUM_GEN_TCP
01013   tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip,
01014                                       IP_PROTO_TCP, p->tot_len);
01015 #endif
01016   TCP_STATS_INC(tcp.xmit);
01017 
01018   /* Send output to IP */
01019 #if LWIP_NETIF_HWADDRHINT
01020   ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP,
01021     &(pcb->addr_hint));
01022 #else /* LWIP_NETIF_HWADDRHINT*/
01023   ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
01024 #endif /* LWIP_NETIF_HWADDRHINT*/
01025 
01026   pbuf_free(p);
01027 
01028   LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: seqno %"U32_F
01029                           " ackno %"U32_F".\n",
01030                           pcb->snd_nxt - 1, pcb->rcv_nxt));
01031 }
01032 #endif /* LWIP_TCP */