Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: mbed-os-example-blinky-gr-lychee GR-Boads_Camera_sample GR-Boards_Audio_Recoder GR-Boads_Camera_DisplayApp ... more
lwip_tcp_out.c
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/priv/tcp_priv.h" 00046 #include "lwip/def.h" 00047 #include "lwip/mem.h" 00048 #include "lwip/memp.h" 00049 #include "lwip/ip_addr.h" 00050 #include "lwip/netif.h" 00051 #include "lwip/inet_chksum.h" 00052 #include "lwip/stats.h" 00053 #include "lwip/ip6.h" 00054 #include "lwip/ip6_addr.h" 00055 #if LWIP_TCP_TIMESTAMPS 00056 #include "lwip/sys.h" 00057 #endif 00058 00059 #include <string.h> 00060 00061 /* Define some copy-macros for checksum-on-copy so that the code looks 00062 nicer by preventing too many ifdef's. */ 00063 #if TCP_CHECKSUM_ON_COPY 00064 #define TCP_DATA_COPY(dst, src, len, seg) do { \ 00065 tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), \ 00066 len, &seg->chksum, &seg->chksum_swapped); \ 00067 seg->flags |= TF_SEG_DATA_CHECKSUMMED; } while(0) 00068 #define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) \ 00069 tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), len, chksum, chksum_swapped); 00070 #else /* TCP_CHECKSUM_ON_COPY*/ 00071 #define TCP_DATA_COPY(dst, src, len, seg) MEMCPY(dst, src, len) 00072 #define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) MEMCPY(dst, src, len) 00073 #endif /* TCP_CHECKSUM_ON_COPY*/ 00074 00075 /** Define this to 1 for an extra check that the output checksum is valid 00076 * (usefule when the checksum is generated by the application, not the stack) */ 00077 #ifndef TCP_CHECKSUM_ON_COPY_SANITY_CHECK 00078 #define TCP_CHECKSUM_ON_COPY_SANITY_CHECK 0 00079 #endif 00080 /* Allow to override the failure of sanity check from warning to e.g. hard failure */ 00081 #if TCP_CHECKSUM_ON_COPY_SANITY_CHECK 00082 #ifndef TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL 00083 #define TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL(msg) LWIP_DEBUGF(TCP_DEBUG | LWIP_DBG_LEVEL_WARNING, msg) 00084 #endif 00085 #endif 00086 00087 #if TCP_OVERSIZE 00088 /** The size of segment pbufs created when TCP_OVERSIZE is enabled */ 00089 #ifndef TCP_OVERSIZE_CALC_LENGTH 00090 #define TCP_OVERSIZE_CALC_LENGTH(length) ((length) + TCP_OVERSIZE) 00091 #endif 00092 #endif 00093 00094 /* Forward declarations.*/ 00095 static err_t tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb, struct netif *netif); 00096 00097 /** Allocate a pbuf and create a tcphdr at p->payload, used for output 00098 * functions other than the default tcp_output -> tcp_output_segment 00099 * (e.g. tcp_send_empty_ack, etc.) 00100 * 00101 * @param pcb tcp pcb for which to send a packet (used to initialize tcp_hdr) 00102 * @param optlen length of header-options 00103 * @param datalen length of tcp data to reserve in pbuf 00104 * @param seqno_be seqno in network byte order (big-endian) 00105 * @return pbuf with p->payload being the tcp_hdr 00106 */ 00107 static struct pbuf * 00108 tcp_output_alloc_header(struct tcp_pcb *pcb, u16_t optlen, u16_t datalen, 00109 u32_t seqno_be /* already in network byte order */) 00110 { 00111 struct tcp_hdr *tcphdr; 00112 struct pbuf *p = pbuf_alloc(PBUF_IP, TCP_HLEN + optlen + datalen, PBUF_RAM); 00113 if (p != NULL) { 00114 LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr", 00115 (p->len >= TCP_HLEN + optlen)); 00116 tcphdr = (struct tcp_hdr *)p->payload; 00117 tcphdr->src = lwip_htons(pcb->local_port); 00118 tcphdr->dest = lwip_htons(pcb->remote_port); 00119 tcphdr->seqno = seqno_be; 00120 tcphdr->ackno = lwip_htonl(pcb->rcv_nxt); 00121 TCPH_HDRLEN_FLAGS_SET(tcphdr, (5 + optlen / 4), TCP_ACK); 00122 tcphdr->wnd = lwip_htons(TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd))); 00123 tcphdr->chksum = 0; 00124 tcphdr->urgp = 0; 00125 00126 /* If we're sending a packet, update the announced right window edge */ 00127 pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd; 00128 } 00129 return p; 00130 } 00131 00132 /** 00133 * Called by tcp_close() to send a segment including FIN flag but not data. 00134 * 00135 * @param pcb the tcp_pcb over which to send a segment 00136 * @return ERR_OK if sent, another err_t otherwise 00137 */ 00138 err_t 00139 tcp_send_fin(struct tcp_pcb *pcb) 00140 { 00141 /* first, try to add the fin to the last unsent segment */ 00142 if (pcb->unsent != NULL) { 00143 struct tcp_seg *last_unsent; 00144 for (last_unsent = pcb->unsent; last_unsent->next != NULL; 00145 last_unsent = last_unsent->next); 00146 00147 if ((TCPH_FLAGS(last_unsent->tcphdr) & (TCP_SYN | TCP_FIN | TCP_RST)) == 0) { 00148 /* no SYN/FIN/RST flag in the header, we can add the FIN flag */ 00149 TCPH_SET_FLAG(last_unsent->tcphdr, TCP_FIN); 00150 pcb->flags |= TF_FIN; 00151 return ERR_OK; 00152 } 00153 } 00154 /* no data, no length, flags, copy=1, no optdata */ 00155 return tcp_enqueue_flags(pcb, TCP_FIN); 00156 } 00157 00158 /** 00159 * Create a TCP segment with prefilled header. 00160 * 00161 * Called by tcp_write and tcp_enqueue_flags. 00162 * 00163 * @param pcb Protocol control block for the TCP connection. 00164 * @param p pbuf that is used to hold the TCP header. 00165 * @param flags TCP flags for header. 00166 * @param seqno TCP sequence number of this packet 00167 * @param optflags options to include in TCP header 00168 * @return a new tcp_seg pointing to p, or NULL. 00169 * The TCP header is filled in except ackno and wnd. 00170 * p is freed on failure. 00171 */ 00172 static struct tcp_seg * 00173 tcp_create_segment(struct tcp_pcb *pcb, struct pbuf *p, u8_t flags, u32_t seqno, u8_t optflags) 00174 { 00175 struct tcp_seg *seg; 00176 u8_t optlen = LWIP_TCP_OPT_LENGTH(optflags); 00177 00178 if ((seg = (struct tcp_seg *)memp_malloc(MEMP_TCP_SEG)) == NULL) { 00179 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_create_segment: no memory.\n")); 00180 pbuf_free(p); 00181 return NULL; 00182 } 00183 seg->flags = optflags; 00184 seg->next = NULL; 00185 seg->p = p; 00186 LWIP_ASSERT("p->tot_len >= optlen", p->tot_len >= optlen); 00187 seg->len = p->tot_len - optlen; 00188 #if TCP_OVERSIZE_DBGCHECK 00189 seg->oversize_left = 0; 00190 #endif /* TCP_OVERSIZE_DBGCHECK */ 00191 #if TCP_CHECKSUM_ON_COPY 00192 seg->chksum = 0; 00193 seg->chksum_swapped = 0; 00194 /* check optflags */ 00195 LWIP_ASSERT("invalid optflags passed: TF_SEG_DATA_CHECKSUMMED", 00196 (optflags & TF_SEG_DATA_CHECKSUMMED) == 0); 00197 #endif /* TCP_CHECKSUM_ON_COPY */ 00198 00199 /* build TCP header */ 00200 if (pbuf_header(p, TCP_HLEN)) { 00201 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_create_segment: no room for TCP header in pbuf.\n")); 00202 TCP_STATS_INC(tcp.err); 00203 tcp_seg_free(seg); 00204 return NULL; 00205 } 00206 seg->tcphdr = (struct tcp_hdr *)seg->p->payload; 00207 seg->tcphdr->src = lwip_htons(pcb->local_port); 00208 seg->tcphdr->dest = lwip_htons(pcb->remote_port); 00209 seg->tcphdr->seqno = lwip_htonl(seqno); 00210 /* ackno is set in tcp_output */ 00211 TCPH_HDRLEN_FLAGS_SET(seg->tcphdr, (5 + optlen / 4), flags); 00212 /* wnd and chksum are set in tcp_output */ 00213 seg->tcphdr->urgp = 0; 00214 return seg; 00215 } 00216 00217 /** 00218 * Allocate a PBUF_RAM pbuf, perhaps with extra space at the end. 00219 * 00220 * This function is like pbuf_alloc(layer, length, PBUF_RAM) except 00221 * there may be extra bytes available at the end. 00222 * 00223 * @param layer flag to define header size. 00224 * @param length size of the pbuf's payload. 00225 * @param max_length maximum usable size of payload+oversize. 00226 * @param oversize pointer to a u16_t that will receive the number of usable tail bytes. 00227 * @param pcb The TCP connection that will enqueue the pbuf. 00228 * @param apiflags API flags given to tcp_write. 00229 * @param first_seg true when this pbuf will be used in the first enqueued segment. 00230 */ 00231 #if TCP_OVERSIZE 00232 static struct pbuf * 00233 tcp_pbuf_prealloc(pbuf_layer layer, u16_t length, u16_t max_length, 00234 u16_t *oversize, struct tcp_pcb *pcb, u8_t apiflags, 00235 u8_t first_seg) 00236 { 00237 struct pbuf *p; 00238 u16_t alloc = length; 00239 00240 #if LWIP_NETIF_TX_SINGLE_PBUF 00241 LWIP_UNUSED_ARG(max_length); 00242 LWIP_UNUSED_ARG(pcb); 00243 LWIP_UNUSED_ARG(apiflags); 00244 LWIP_UNUSED_ARG(first_seg); 00245 alloc = max_length; 00246 #else /* LWIP_NETIF_TX_SINGLE_PBUF */ 00247 if (length < max_length) { 00248 /* Should we allocate an oversized pbuf, or just the minimum 00249 * length required? If tcp_write is going to be called again 00250 * before this segment is transmitted, we want the oversized 00251 * buffer. If the segment will be transmitted immediately, we can 00252 * save memory by allocating only length. We use a simple 00253 * heuristic based on the following information: 00254 * 00255 * Did the user set TCP_WRITE_FLAG_MORE? 00256 * 00257 * Will the Nagle algorithm defer transmission of this segment? 00258 */ 00259 if ((apiflags & TCP_WRITE_FLAG_MORE) || 00260 (!(pcb->flags & TF_NODELAY) && 00261 (!first_seg || 00262 pcb->unsent != NULL || 00263 pcb->unacked != NULL))) { 00264 alloc = LWIP_MIN(max_length, LWIP_MEM_ALIGN_SIZE(TCP_OVERSIZE_CALC_LENGTH(length))); 00265 } 00266 } 00267 #endif /* LWIP_NETIF_TX_SINGLE_PBUF */ 00268 p = pbuf_alloc(layer, alloc, PBUF_RAM); 00269 if (p == NULL) { 00270 return NULL; 00271 } 00272 LWIP_ASSERT("need unchained pbuf", p->next == NULL); 00273 *oversize = p->len - length; 00274 /* trim p->len to the currently used size */ 00275 p->len = p->tot_len = length; 00276 return p; 00277 } 00278 #else /* TCP_OVERSIZE */ 00279 #define tcp_pbuf_prealloc(layer, length, mx, os, pcb, api, fst) pbuf_alloc((layer), (length), PBUF_RAM) 00280 #endif /* TCP_OVERSIZE */ 00281 00282 #if TCP_CHECKSUM_ON_COPY 00283 /** Add a checksum of newly added data to the segment */ 00284 static void 00285 tcp_seg_add_chksum(u16_t chksum, u16_t len, u16_t *seg_chksum, 00286 u8_t *seg_chksum_swapped) 00287 { 00288 u32_t helper; 00289 /* add chksum to old chksum and fold to u16_t */ 00290 helper = chksum + *seg_chksum; 00291 chksum = FOLD_U32T(helper); 00292 if ((len & 1) != 0) { 00293 *seg_chksum_swapped = 1 - *seg_chksum_swapped; 00294 chksum = SWAP_BYTES_IN_WORD(chksum); 00295 } 00296 *seg_chksum = chksum; 00297 } 00298 #endif /* TCP_CHECKSUM_ON_COPY */ 00299 00300 /** Checks if tcp_write is allowed or not (checks state, snd_buf and snd_queuelen). 00301 * 00302 * @param pcb the tcp pcb to check for 00303 * @param len length of data to send (checked agains snd_buf) 00304 * @return ERR_OK if tcp_write is allowed to proceed, another err_t otherwise 00305 */ 00306 static err_t 00307 tcp_write_checks(struct tcp_pcb *pcb, u16_t len) 00308 { 00309 /* connection is in invalid state for data transmission? */ 00310 if ((pcb->state != ESTABLISHED) && 00311 (pcb->state != CLOSE_WAIT) && 00312 (pcb->state != SYN_SENT) && 00313 (pcb->state != SYN_RCVD)) { 00314 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_STATE | LWIP_DBG_LEVEL_SEVERE, ("tcp_write() called in invalid state\n")); 00315 return ERR_CONN; 00316 } else if (len == 0) { 00317 return ERR_OK; 00318 } 00319 00320 /* fail on too much data */ 00321 if (len > pcb->snd_buf) { 00322 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("tcp_write: too much data (len=%"U16_F" > snd_buf=%"TCPWNDSIZE_F")\n", 00323 len, pcb->snd_buf)); 00324 pcb->flags |= TF_NAGLEMEMERR; 00325 return ERR_MEM; 00326 } 00327 00328 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: queuelen: %"TCPWNDSIZE_F"\n", (tcpwnd_size_t)pcb->snd_queuelen)); 00329 00330 /* If total number of pbufs on the unsent/unacked queues exceeds the 00331 * configured maximum, return an error */ 00332 /* check for configured max queuelen and possible overflow */ 00333 if ((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { 00334 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("tcp_write: too long queue %"U16_F" (max %"U16_F")\n", 00335 pcb->snd_queuelen, (u16_t)TCP_SND_QUEUELEN)); 00336 TCP_STATS_INC(tcp.memerr); 00337 pcb->flags |= TF_NAGLEMEMERR; 00338 return ERR_MEM; 00339 } 00340 if (pcb->snd_queuelen != 0) { 00341 LWIP_ASSERT("tcp_write: pbufs on queue => at least one queue non-empty", 00342 pcb->unacked != NULL || pcb->unsent != NULL); 00343 } else { 00344 LWIP_ASSERT("tcp_write: no pbufs on queue => both queues empty", 00345 pcb->unacked == NULL && pcb->unsent == NULL); 00346 } 00347 return ERR_OK; 00348 } 00349 00350 /** 00351 * @ingroup tcp_raw 00352 * Write data for sending (but does not send it immediately). 00353 * 00354 * It waits in the expectation of more data being sent soon (as 00355 * it can send them more efficiently by combining them together). 00356 * To prompt the system to send data now, call tcp_output() after 00357 * calling tcp_write(). 00358 * 00359 * @param pcb Protocol control block for the TCP connection to enqueue data for. 00360 * @param arg Pointer to the data to be enqueued for sending. 00361 * @param len Data length in bytes 00362 * @param apiflags combination of following flags : 00363 * - TCP_WRITE_FLAG_COPY (0x01) data will be copied into memory belonging to the stack 00364 * - TCP_WRITE_FLAG_MORE (0x02) for TCP connection, PSH flag will not be set on last segment sent, 00365 * @return ERR_OK if enqueued, another err_t on error 00366 */ 00367 err_t 00368 tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags) 00369 { 00370 struct pbuf *concat_p = NULL; 00371 struct tcp_seg *last_unsent = NULL, *seg = NULL, *prev_seg = NULL, *queue = NULL; 00372 u16_t pos = 0; /* position in 'arg' data */ 00373 u16_t queuelen; 00374 u8_t optlen = 0; 00375 u8_t optflags = 0; 00376 #if TCP_OVERSIZE 00377 u16_t oversize = 0; 00378 u16_t oversize_used = 0; 00379 #endif /* TCP_OVERSIZE */ 00380 u16_t extendlen = 0; 00381 #if TCP_CHECKSUM_ON_COPY 00382 u16_t concat_chksum = 0; 00383 u8_t concat_chksum_swapped = 0; 00384 u16_t concat_chksummed = 0; 00385 #endif /* TCP_CHECKSUM_ON_COPY */ 00386 err_t err; 00387 /* don't allocate segments bigger than half the maximum window we ever received */ 00388 u16_t mss_local = LWIP_MIN(pcb->mss, TCPWND_MIN16(pcb->snd_wnd_max/2)); 00389 mss_local = mss_local ? mss_local : pcb->mss; 00390 00391 #if LWIP_NETIF_TX_SINGLE_PBUF 00392 /* Always copy to try to create single pbufs for TX */ 00393 apiflags |= TCP_WRITE_FLAG_COPY; 00394 #endif /* LWIP_NETIF_TX_SINGLE_PBUF */ 00395 00396 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, data=%p, len=%"U16_F", apiflags=%"U16_F")\n", 00397 (void *)pcb, arg, len, (u16_t)apiflags)); 00398 LWIP_ERROR("tcp_write: arg == NULL (programmer violates API)", 00399 arg != NULL, return ERR_ARG;); 00400 00401 err = tcp_write_checks(pcb, len); 00402 if (err != ERR_OK) { 00403 return err; 00404 } 00405 queuelen = pcb->snd_queuelen; 00406 00407 #if LWIP_TCP_TIMESTAMPS 00408 if ((pcb->flags & TF_TIMESTAMP)) { 00409 /* Make sure the timestamp option is only included in data segments if we 00410 agreed about it with the remote host. */ 00411 optflags = TF_SEG_OPTS_TS; 00412 optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS); 00413 /* ensure that segments can hold at least one data byte... */ 00414 mss_local = LWIP_MAX(mss_local, LWIP_TCP_OPT_LEN_TS + 1); 00415 } 00416 #endif /* LWIP_TCP_TIMESTAMPS */ 00417 00418 00419 /* 00420 * TCP segmentation is done in three phases with increasing complexity: 00421 * 00422 * 1. Copy data directly into an oversized pbuf. 00423 * 2. Chain a new pbuf to the end of pcb->unsent. 00424 * 3. Create new segments. 00425 * 00426 * We may run out of memory at any point. In that case we must 00427 * return ERR_MEM and not change anything in pcb. Therefore, all 00428 * changes are recorded in local variables and committed at the end 00429 * of the function. Some pcb fields are maintained in local copies: 00430 * 00431 * queuelen = pcb->snd_queuelen 00432 * oversize = pcb->unsent_oversize 00433 * 00434 * These variables are set consistently by the phases: 00435 * 00436 * seg points to the last segment tampered with. 00437 * 00438 * pos records progress as data is segmented. 00439 */ 00440 00441 /* Find the tail of the unsent queue. */ 00442 if (pcb->unsent != NULL) { 00443 u16_t space; 00444 u16_t unsent_optlen; 00445 00446 /* @todo: this could be sped up by keeping last_unsent in the pcb */ 00447 for (last_unsent = pcb->unsent; last_unsent->next != NULL; 00448 last_unsent = last_unsent->next); 00449 00450 /* Usable space at the end of the last unsent segment */ 00451 unsent_optlen = LWIP_TCP_OPT_LENGTH(last_unsent->flags); 00452 LWIP_ASSERT("mss_local is too small", mss_local >= last_unsent->len + unsent_optlen); 00453 space = mss_local - (last_unsent->len + unsent_optlen); 00454 00455 /* 00456 * Phase 1: Copy data directly into an oversized pbuf. 00457 * 00458 * The number of bytes copied is recorded in the oversize_used 00459 * variable. The actual copying is done at the bottom of the 00460 * function. 00461 */ 00462 #if TCP_OVERSIZE 00463 #if TCP_OVERSIZE_DBGCHECK 00464 /* check that pcb->unsent_oversize matches last_unsent->unsent_oversize */ 00465 LWIP_ASSERT("unsent_oversize mismatch (pcb vs. last_unsent)", 00466 pcb->unsent_oversize == last_unsent->oversize_left); 00467 #endif /* TCP_OVERSIZE_DBGCHECK */ 00468 oversize = pcb->unsent_oversize; 00469 if (oversize > 0) { 00470 LWIP_ASSERT("inconsistent oversize vs. space", oversize_used <= space); 00471 seg = last_unsent; 00472 oversize_used = LWIP_MIN(space, LWIP_MIN(oversize, len)); 00473 pos += oversize_used; 00474 oversize -= oversize_used; 00475 space -= oversize_used; 00476 } 00477 /* now we are either finished or oversize is zero */ 00478 LWIP_ASSERT("inconsistend oversize vs. len", (oversize == 0) || (pos == len)); 00479 #endif /* TCP_OVERSIZE */ 00480 00481 /* 00482 * Phase 2: Chain a new pbuf to the end of pcb->unsent. 00483 * 00484 * As an exception when NOT copying the data, if the given data buffer 00485 * directly follows the last unsent data buffer in memory, extend the last 00486 * ROM pbuf reference to the buffer, thus saving a ROM pbuf allocation. 00487 * 00488 * We don't extend segments containing SYN/FIN flags or options 00489 * (len==0). The new pbuf is kept in concat_p and pbuf_cat'ed at 00490 * the end. 00491 */ 00492 if ((pos < len) && (space > 0) && (last_unsent->len > 0)) { 00493 u16_t seglen = space < len - pos ? space : len - pos; 00494 seg = last_unsent; 00495 00496 /* Create a pbuf with a copy or reference to seglen bytes. We 00497 * can use PBUF_RAW here since the data appears in the middle of 00498 * a segment. A header will never be prepended. */ 00499 if (apiflags & TCP_WRITE_FLAG_COPY) { 00500 /* Data is copied */ 00501 if ((concat_p = tcp_pbuf_prealloc(PBUF_RAW, seglen, space, &oversize, pcb, apiflags, 1)) == NULL) { 00502 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, 00503 ("tcp_write : could not allocate memory for pbuf copy size %"U16_F"\n", 00504 seglen)); 00505 goto memerr; 00506 } 00507 #if TCP_OVERSIZE_DBGCHECK 00508 last_unsent->oversize_left += oversize; 00509 #endif /* TCP_OVERSIZE_DBGCHECK */ 00510 TCP_DATA_COPY2(concat_p->payload, (const u8_t*)arg + pos, seglen, &concat_chksum, &concat_chksum_swapped); 00511 #if TCP_CHECKSUM_ON_COPY 00512 concat_chksummed += seglen; 00513 #endif /* TCP_CHECKSUM_ON_COPY */ 00514 queuelen += pbuf_clen(concat_p); 00515 } else { 00516 /* Data is not copied */ 00517 /* If the last unsent pbuf is of type PBUF_ROM, try to extend it. */ 00518 struct pbuf *p; 00519 for (p = last_unsent->p; p->next != NULL; p = p->next); 00520 if (p->type == PBUF_ROM && (const u8_t *)p->payload + p->len == (const u8_t *)arg) { 00521 LWIP_ASSERT("tcp_write: ROM pbufs cannot be oversized", pos == 0); 00522 extendlen = seglen; 00523 } else { 00524 if ((concat_p = pbuf_alloc(PBUF_RAW, seglen, PBUF_ROM)) == NULL) { 00525 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, 00526 ("tcp_write: could not allocate memory for zero-copy pbuf\n")); 00527 goto memerr; 00528 } 00529 /* reference the non-volatile payload data */ 00530 ((struct pbuf_rom*)concat_p)->payload = (const u8_t*)arg + pos; 00531 queuelen += pbuf_clen(concat_p); 00532 } 00533 #if TCP_CHECKSUM_ON_COPY 00534 /* calculate the checksum of nocopy-data */ 00535 tcp_seg_add_chksum(~inet_chksum((const u8_t*)arg + pos, seglen), seglen, 00536 &concat_chksum, &concat_chksum_swapped); 00537 concat_chksummed += seglen; 00538 #endif /* TCP_CHECKSUM_ON_COPY */ 00539 } 00540 00541 pos += seglen; 00542 } 00543 } else { 00544 #if TCP_OVERSIZE 00545 LWIP_ASSERT("unsent_oversize mismatch (pcb->unsent is NULL)", 00546 pcb->unsent_oversize == 0); 00547 #endif /* TCP_OVERSIZE */ 00548 } 00549 00550 /* 00551 * Phase 3: Create new segments. 00552 * 00553 * The new segments are chained together in the local 'queue' 00554 * variable, ready to be appended to pcb->unsent. 00555 */ 00556 while (pos < len) { 00557 struct pbuf *p; 00558 u16_t left = len - pos; 00559 u16_t max_len = mss_local - optlen; 00560 u16_t seglen = left > max_len ? max_len : left; 00561 #if TCP_CHECKSUM_ON_COPY 00562 u16_t chksum = 0; 00563 u8_t chksum_swapped = 0; 00564 #endif /* TCP_CHECKSUM_ON_COPY */ 00565 00566 if (apiflags & TCP_WRITE_FLAG_COPY) { 00567 /* If copy is set, memory should be allocated and data copied 00568 * into pbuf */ 00569 if ((p = tcp_pbuf_prealloc(PBUF_TRANSPORT, seglen + optlen, mss_local, &oversize, pcb, apiflags, queue == NULL)) == NULL) { 00570 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write : could not allocate memory for pbuf copy size %"U16_F"\n", seglen)); 00571 goto memerr; 00572 } 00573 LWIP_ASSERT("tcp_write: check that first pbuf can hold the complete seglen", 00574 (p->len >= seglen)); 00575 TCP_DATA_COPY2((char *)p->payload + optlen, (const u8_t*)arg + pos, seglen, &chksum, &chksum_swapped); 00576 } else { 00577 /* Copy is not set: First allocate a pbuf for holding the data. 00578 * Since the referenced data is available at least until it is 00579 * sent out on the link (as it has to be ACKed by the remote 00580 * party) we can safely use PBUF_ROM instead of PBUF_REF here. 00581 */ 00582 struct pbuf *p2; 00583 #if TCP_OVERSIZE 00584 LWIP_ASSERT("oversize == 0", oversize == 0); 00585 #endif /* TCP_OVERSIZE */ 00586 if ((p2 = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_ROM)) == NULL) { 00587 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write: could not allocate memory for zero-copy pbuf\n")); 00588 goto memerr; 00589 } 00590 #if TCP_CHECKSUM_ON_COPY 00591 /* calculate the checksum of nocopy-data */ 00592 chksum = ~inet_chksum((const u8_t*)arg + pos, seglen); 00593 if (seglen & 1) { 00594 chksum_swapped = 1; 00595 chksum = SWAP_BYTES_IN_WORD(chksum); 00596 } 00597 #endif /* TCP_CHECKSUM_ON_COPY */ 00598 /* reference the non-volatile payload data */ 00599 ((struct pbuf_rom*)p2)->payload = (const u8_t*)arg + pos; 00600 00601 /* Second, allocate a pbuf for the headers. */ 00602 if ((p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) { 00603 /* If allocation fails, we have to deallocate the data pbuf as 00604 * well. */ 00605 pbuf_free(p2); 00606 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write: could not allocate memory for header pbuf\n")); 00607 goto memerr; 00608 } 00609 /* Concatenate the headers and data pbufs together. */ 00610 pbuf_cat(p/*header*/, p2/*data*/); 00611 } 00612 00613 queuelen += pbuf_clen(p); 00614 00615 /* Now that there are more segments queued, we check again if the 00616 * length of the queue exceeds the configured maximum or 00617 * overflows. */ 00618 if ((queuelen > TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { 00619 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write: queue too long %"U16_F" (%d)\n", 00620 queuelen, (int)TCP_SND_QUEUELEN)); 00621 pbuf_free(p); 00622 goto memerr; 00623 } 00624 00625 if ((seg = tcp_create_segment(pcb, p, 0, pcb->snd_lbb + pos, optflags)) == NULL) { 00626 goto memerr; 00627 } 00628 #if TCP_OVERSIZE_DBGCHECK 00629 seg->oversize_left = oversize; 00630 #endif /* TCP_OVERSIZE_DBGCHECK */ 00631 #if TCP_CHECKSUM_ON_COPY 00632 seg->chksum = chksum; 00633 seg->chksum_swapped = chksum_swapped; 00634 seg->flags |= TF_SEG_DATA_CHECKSUMMED; 00635 #endif /* TCP_CHECKSUM_ON_COPY */ 00636 00637 /* first segment of to-be-queued data? */ 00638 if (queue == NULL) { 00639 queue = seg; 00640 } else { 00641 /* Attach the segment to the end of the queued segments */ 00642 LWIP_ASSERT("prev_seg != NULL", prev_seg != NULL); 00643 prev_seg->next = seg; 00644 } 00645 /* remember last segment of to-be-queued data for next iteration */ 00646 prev_seg = seg; 00647 00648 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, ("tcp_write: queueing %"U32_F":%"U32_F"\n", 00649 lwip_ntohl(seg->tcphdr->seqno), 00650 lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg))); 00651 00652 pos += seglen; 00653 } 00654 00655 /* 00656 * All three segmentation phases were successful. We can commit the 00657 * transaction. 00658 */ 00659 00660 /* 00661 * Phase 1: If data has been added to the preallocated tail of 00662 * last_unsent, we update the length fields of the pbuf chain. 00663 */ 00664 #if TCP_OVERSIZE 00665 if (oversize_used > 0) { 00666 struct pbuf *p; 00667 /* Bump tot_len of whole chain, len of tail */ 00668 for (p = last_unsent->p; p; p = p->next) { 00669 p->tot_len += oversize_used; 00670 if (p->next == NULL) { 00671 TCP_DATA_COPY((char *)p->payload + p->len, arg, oversize_used, last_unsent); 00672 p->len += oversize_used; 00673 } 00674 } 00675 last_unsent->len += oversize_used; 00676 #if TCP_OVERSIZE_DBGCHECK 00677 LWIP_ASSERT("last_unsent->oversize_left >= oversize_used", 00678 last_unsent->oversize_left >= oversize_used); 00679 last_unsent->oversize_left -= oversize_used; 00680 #endif /* TCP_OVERSIZE_DBGCHECK */ 00681 } 00682 pcb->unsent_oversize = oversize; 00683 #endif /* TCP_OVERSIZE */ 00684 00685 /* 00686 * Phase 2: concat_p can be concatenated onto last_unsent->p, unless we 00687 * determined that the last ROM pbuf can be extended to include the new data. 00688 */ 00689 if (concat_p != NULL) { 00690 LWIP_ASSERT("tcp_write: cannot concatenate when pcb->unsent is empty", 00691 (last_unsent != NULL)); 00692 pbuf_cat(last_unsent->p, concat_p); 00693 last_unsent->len += concat_p->tot_len; 00694 } else if (extendlen > 0) { 00695 struct pbuf *p; 00696 LWIP_ASSERT("tcp_write: extension of reference requires reference", 00697 last_unsent != NULL && last_unsent->p != NULL); 00698 for (p = last_unsent->p; p->next != NULL; p = p->next) { 00699 p->tot_len += extendlen; 00700 } 00701 p->tot_len += extendlen; 00702 p->len += extendlen; 00703 last_unsent->len += extendlen; 00704 } 00705 00706 #if TCP_CHECKSUM_ON_COPY 00707 if (concat_chksummed) { 00708 LWIP_ASSERT("tcp_write: concat checksum needs concatenated data", 00709 concat_p != NULL || extendlen > 0); 00710 /*if concat checksumm swapped - swap it back */ 00711 if (concat_chksum_swapped) { 00712 concat_chksum = SWAP_BYTES_IN_WORD(concat_chksum); 00713 } 00714 tcp_seg_add_chksum(concat_chksum, concat_chksummed, &last_unsent->chksum, 00715 &last_unsent->chksum_swapped); 00716 last_unsent->flags |= TF_SEG_DATA_CHECKSUMMED; 00717 } 00718 #endif /* TCP_CHECKSUM_ON_COPY */ 00719 00720 /* 00721 * Phase 3: Append queue to pcb->unsent. Queue may be NULL, but that 00722 * is harmless 00723 */ 00724 if (last_unsent == NULL) { 00725 pcb->unsent = queue; 00726 } else { 00727 last_unsent->next = queue; 00728 } 00729 00730 /* 00731 * Finally update the pcb state. 00732 */ 00733 pcb->snd_lbb += len; 00734 pcb->snd_buf -= len; 00735 pcb->snd_queuelen = queuelen; 00736 00737 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: %"S16_F" (after enqueued)\n", 00738 pcb->snd_queuelen)); 00739 if (pcb->snd_queuelen != 0) { 00740 LWIP_ASSERT("tcp_write: valid queue length", 00741 pcb->unacked != NULL || pcb->unsent != NULL); 00742 } 00743 00744 /* Set the PSH flag in the last segment that we enqueued. */ 00745 if (seg != NULL && seg->tcphdr != NULL && ((apiflags & TCP_WRITE_FLAG_MORE)==0)) { 00746 TCPH_SET_FLAG(seg->tcphdr, TCP_PSH); 00747 } 00748 00749 return ERR_OK; 00750 memerr: 00751 pcb->flags |= TF_NAGLEMEMERR; 00752 TCP_STATS_INC(tcp.memerr); 00753 00754 if (concat_p != NULL) { 00755 pbuf_free(concat_p); 00756 } 00757 if (queue != NULL) { 00758 tcp_segs_free(queue); 00759 } 00760 if (pcb->snd_queuelen != 0) { 00761 LWIP_ASSERT("tcp_write: valid queue length", pcb->unacked != NULL || 00762 pcb->unsent != NULL); 00763 } 00764 LWIP_DEBUGF(TCP_QLEN_DEBUG | LWIP_DBG_STATE, ("tcp_write: %"S16_F" (with mem err)\n", pcb->snd_queuelen)); 00765 return ERR_MEM; 00766 } 00767 00768 /** 00769 * Enqueue TCP options for transmission. 00770 * 00771 * Called by tcp_connect(), tcp_listen_input(), and tcp_send_ctrl(). 00772 * 00773 * @param pcb Protocol control block for the TCP connection. 00774 * @param flags TCP header flags to set in the outgoing segment. 00775 */ 00776 err_t 00777 tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags) 00778 { 00779 struct pbuf *p; 00780 struct tcp_seg *seg; 00781 u8_t optflags = 0; 00782 u8_t optlen = 0; 00783 00784 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen)); 00785 00786 LWIP_ASSERT("tcp_enqueue_flags: need either TCP_SYN or TCP_FIN in flags (programmer violates API)", 00787 (flags & (TCP_SYN | TCP_FIN)) != 0); 00788 00789 /* check for configured max queuelen and possible overflow (FIN flag should always come through!) */ 00790 if (((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) && 00791 ((flags & TCP_FIN) == 0)) { 00792 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("tcp_enqueue_flags: too long queue %"U16_F" (max %"U16_F")\n", 00793 pcb->snd_queuelen, (u16_t)TCP_SND_QUEUELEN)); 00794 TCP_STATS_INC(tcp.memerr); 00795 pcb->flags |= TF_NAGLEMEMERR; 00796 return ERR_MEM; 00797 } 00798 00799 if (flags & TCP_SYN) { 00800 optflags = TF_SEG_OPTS_MSS; 00801 #if LWIP_WND_SCALE 00802 if ((pcb->state != SYN_RCVD) || (pcb->flags & TF_WND_SCALE)) { 00803 /* In a <SYN,ACK> (sent in state SYN_RCVD), the window scale option may only 00804 be sent if we received a window scale option from the remote host. */ 00805 optflags |= TF_SEG_OPTS_WND_SCALE; 00806 } 00807 #endif /* LWIP_WND_SCALE */ 00808 } 00809 #if LWIP_TCP_TIMESTAMPS 00810 if ((pcb->flags & TF_TIMESTAMP)) { 00811 /* Make sure the timestamp option is only included in data segments if we 00812 agreed about it with the remote host. */ 00813 optflags |= TF_SEG_OPTS_TS; 00814 } 00815 #endif /* LWIP_TCP_TIMESTAMPS */ 00816 optlen = LWIP_TCP_OPT_LENGTH(optflags); 00817 00818 /* Allocate pbuf with room for TCP header + options */ 00819 if ((p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) { 00820 pcb->flags |= TF_NAGLEMEMERR; 00821 TCP_STATS_INC(tcp.memerr); 00822 return ERR_MEM; 00823 } 00824 LWIP_ASSERT("tcp_enqueue_flags: check that first pbuf can hold optlen", 00825 (p->len >= optlen)); 00826 00827 /* Allocate memory for tcp_seg, and fill in fields. */ 00828 if ((seg = tcp_create_segment(pcb, p, flags, pcb->snd_lbb, optflags)) == NULL) { 00829 pcb->flags |= TF_NAGLEMEMERR; 00830 TCP_STATS_INC(tcp.memerr); 00831 return ERR_MEM; 00832 } 00833 LWIP_ASSERT("seg->tcphdr not aligned", ((mem_ptr_t)seg->tcphdr % LWIP_MIN(MEM_ALIGNMENT, 4)) == 0); 00834 LWIP_ASSERT("tcp_enqueue_flags: invalid segment length", seg->len == 0); 00835 00836 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, 00837 ("tcp_enqueue_flags: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n", 00838 lwip_ntohl(seg->tcphdr->seqno), 00839 lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg), 00840 (u16_t)flags)); 00841 00842 /* Now append seg to pcb->unsent queue */ 00843 if (pcb->unsent == NULL) { 00844 pcb->unsent = seg; 00845 } else { 00846 struct tcp_seg *useg; 00847 for (useg = pcb->unsent; useg->next != NULL; useg = useg->next); 00848 useg->next = seg; 00849 } 00850 #if TCP_OVERSIZE 00851 /* The new unsent tail has no space */ 00852 pcb->unsent_oversize = 0; 00853 #endif /* TCP_OVERSIZE */ 00854 00855 /* SYN and FIN bump the sequence number */ 00856 if ((flags & TCP_SYN) || (flags & TCP_FIN)) { 00857 pcb->snd_lbb++; 00858 /* optlen does not influence snd_buf */ 00859 } 00860 if (flags & TCP_FIN) { 00861 pcb->flags |= TF_FIN; 00862 } 00863 00864 /* update number of segments on the queues */ 00865 pcb->snd_queuelen += pbuf_clen(seg->p); 00866 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: %"S16_F" (after enqueued)\n", pcb->snd_queuelen)); 00867 if (pcb->snd_queuelen != 0) { 00868 LWIP_ASSERT("tcp_enqueue_flags: invalid queue length", 00869 pcb->unacked != NULL || pcb->unsent != NULL); 00870 } 00871 00872 return ERR_OK; 00873 } 00874 00875 #if LWIP_TCP_TIMESTAMPS 00876 /* Build a timestamp option (12 bytes long) at the specified options pointer) 00877 * 00878 * @param pcb tcp_pcb 00879 * @param opts option pointer where to store the timestamp option 00880 */ 00881 static void 00882 tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts) 00883 { 00884 /* Pad with two NOP options to make everything nicely aligned */ 00885 opts[0] = PP_HTONL(0x0101080A); 00886 opts[1] = lwip_htonl(sys_now()); 00887 opts[2] = lwip_htonl(pcb->ts_recent); 00888 } 00889 #endif 00890 00891 #if LWIP_WND_SCALE 00892 /** Build a window scale option (3 bytes long) at the specified options pointer) 00893 * 00894 * @param opts option pointer where to store the window scale option 00895 */ 00896 static void 00897 tcp_build_wnd_scale_option(u32_t *opts) 00898 { 00899 /* Pad with one NOP option to make everything nicely aligned */ 00900 opts[0] = PP_HTONL(0x01030300 | TCP_RCV_SCALE); 00901 } 00902 #endif 00903 00904 /** 00905 * Send an ACK without data. 00906 * 00907 * @param pcb Protocol control block for the TCP connection to send the ACK 00908 */ 00909 err_t 00910 tcp_send_empty_ack(struct tcp_pcb *pcb) 00911 { 00912 err_t err; 00913 struct pbuf *p; 00914 u8_t optlen = 0; 00915 struct netif *netif; 00916 #if LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP 00917 struct tcp_hdr *tcphdr; 00918 #endif /* LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP */ 00919 00920 #if LWIP_TCP_TIMESTAMPS 00921 if (pcb->flags & TF_TIMESTAMP) { 00922 optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS); 00923 } 00924 #endif 00925 00926 p = tcp_output_alloc_header(pcb, optlen, 0, lwip_htonl(pcb->snd_nxt)); 00927 if (p == NULL) { 00928 /* let tcp_fasttmr retry sending this ACK */ 00929 pcb->flags |= (TF_ACK_DELAY | TF_ACK_NOW); 00930 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n")); 00931 return ERR_BUF; 00932 } 00933 #if LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP 00934 tcphdr = (struct tcp_hdr *)p->payload; 00935 #endif /* LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP */ 00936 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, 00937 ("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt)); 00938 00939 /* NB. MSS and window scale options are only sent on SYNs, so ignore them here */ 00940 #if LWIP_TCP_TIMESTAMPS 00941 pcb->ts_lastacksent = pcb->rcv_nxt; 00942 00943 if (pcb->flags & TF_TIMESTAMP) { 00944 tcp_build_timestamp_option(pcb, (u32_t *)(tcphdr + 1)); 00945 } 00946 #endif 00947 00948 netif = ip_route(&pcb->local_ip, &pcb->remote_ip); 00949 if (netif == NULL) { 00950 err = ERR_RTE; 00951 } else { 00952 #if CHECKSUM_GEN_TCP 00953 IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) { 00954 tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, 00955 &pcb->local_ip, &pcb->remote_ip); 00956 } 00957 #endif 00958 NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint)); 00959 err = ip_output_if(p, &pcb->local_ip, &pcb->remote_ip, 00960 pcb->ttl, pcb->tos, IP_PROTO_TCP, netif); 00961 NETIF_SET_HWADDRHINT(netif, NULL); 00962 } 00963 pbuf_free(p); 00964 00965 if (err != ERR_OK) { 00966 /* let tcp_fasttmr retry sending this ACK */ 00967 pcb->flags |= (TF_ACK_DELAY | TF_ACK_NOW); 00968 } else { 00969 /* remove ACK flags from the PCB, as we sent an empty ACK now */ 00970 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); 00971 } 00972 00973 return err; 00974 } 00975 00976 /** 00977 * @ingroup tcp_raw 00978 * Find out what we can send and send it 00979 * 00980 * @param pcb Protocol control block for the TCP connection to send data 00981 * @return ERR_OK if data has been sent or nothing to send 00982 * another err_t on error 00983 */ 00984 err_t 00985 tcp_output(struct tcp_pcb *pcb) 00986 { 00987 struct tcp_seg *seg, *useg; 00988 u32_t wnd, snd_nxt; 00989 err_t err; 00990 struct netif *netif; 00991 #if TCP_CWND_DEBUG 00992 s16_t i = 0; 00993 #endif /* TCP_CWND_DEBUG */ 00994 00995 /* pcb->state LISTEN not allowed here */ 00996 LWIP_ASSERT("don't call tcp_output for listen-pcbs", 00997 pcb->state != LISTEN); 00998 00999 /* First, check if we are invoked by the TCP input processing 01000 code. If so, we do not output anything. Instead, we rely on the 01001 input processing code to call us when input processing is done 01002 with. */ 01003 if (tcp_input_pcb == pcb) { 01004 return ERR_OK; 01005 } 01006 01007 wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd); 01008 01009 seg = pcb->unsent; 01010 01011 /* If the TF_ACK_NOW flag is set and no data will be sent (either 01012 * because the ->unsent queue is empty or because the window does 01013 * not allow it), construct an empty ACK segment and send it. 01014 * 01015 * If data is to be sent, we will just piggyback the ACK (see below). 01016 */ 01017 if (pcb->flags & TF_ACK_NOW && 01018 (seg == NULL || 01019 lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) { 01020 return tcp_send_empty_ack(pcb); 01021 } 01022 01023 /* useg should point to last segment on unacked queue */ 01024 useg = pcb->unacked; 01025 if (useg != NULL) { 01026 for (; useg->next != NULL; useg = useg->next); 01027 } 01028 01029 netif = ip_route(&pcb->local_ip, &pcb->remote_ip); 01030 if (netif == NULL) { 01031 return ERR_RTE; 01032 } 01033 01034 /* If we don't have a local IP address, we get one from netif */ 01035 if (ip_addr_isany(&pcb->local_ip)) { 01036 const ip_addr_t *local_ip = ip_netif_get_local_ip(netif, &pcb->remote_ip); 01037 if (local_ip == NULL) { 01038 return ERR_RTE; 01039 } 01040 ip_addr_copy(pcb->local_ip, *local_ip); 01041 } 01042 01043 #if TCP_OUTPUT_DEBUG 01044 if (seg == NULL) { 01045 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n", 01046 (void*)pcb->unsent)); 01047 } 01048 #endif /* TCP_OUTPUT_DEBUG */ 01049 #if TCP_CWND_DEBUG 01050 if (seg == NULL) { 01051 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"TCPWNDSIZE_F 01052 ", cwnd %"TCPWNDSIZE_F", wnd %"U32_F 01053 ", seg == NULL, ack %"U32_F"\n", 01054 pcb->snd_wnd, pcb->cwnd, wnd, pcb->lastack)); 01055 } else { 01056 LWIP_DEBUGF(TCP_CWND_DEBUG, 01057 ("tcp_output: snd_wnd %"TCPWNDSIZE_F", cwnd %"TCPWNDSIZE_F", wnd %"U32_F 01058 ", effwnd %"U32_F", seq %"U32_F", ack %"U32_F"\n", 01059 pcb->snd_wnd, pcb->cwnd, wnd, 01060 lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len, 01061 lwip_ntohl(seg->tcphdr->seqno), pcb->lastack)); 01062 } 01063 #endif /* TCP_CWND_DEBUG */ 01064 /* Check if we need to start the persistent timer when the next unsent segment 01065 * does not fit within the remaining send window and RTO timer is not running (we 01066 * have no in-flight data). A traditional approach would fill the remaining window 01067 * with part of the unsent segment (which will engage zero-window probing upon 01068 * reception of the zero window update from the receiver). This ensures the 01069 * subsequent window update is reliably received. With the goal of being lightweight, 01070 * we avoid splitting the unsent segment and treat the window as already zero. 01071 */ 01072 if (seg != NULL && 01073 lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd && 01074 wnd > 0 && wnd == pcb->snd_wnd && pcb->unacked == NULL) { 01075 /* Start the persist timer */ 01076 if (pcb->persist_backoff == 0) { 01077 pcb->persist_cnt = 0; 01078 pcb->persist_backoff = 1; 01079 } 01080 goto output_done; 01081 } 01082 /* data available and window allows it to be sent? */ 01083 while (seg != NULL && 01084 lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) { 01085 LWIP_ASSERT("RST not expected here!", 01086 (TCPH_FLAGS(seg->tcphdr) & TCP_RST) == 0); 01087 /* Stop sending if the nagle algorithm would prevent it 01088 * Don't stop: 01089 * - if tcp_write had a memory error before (prevent delayed ACK timeout) or 01090 * - if FIN was already enqueued for this PCB (SYN is always alone in a segment - 01091 * either seg->next != NULL or pcb->unacked == NULL; 01092 * RST is no sent using tcp_write/tcp_output. 01093 */ 01094 if ((tcp_do_output_nagle(pcb) == 0) && 01095 ((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)) { 01096 break; 01097 } 01098 #if TCP_CWND_DEBUG 01099 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"TCPWNDSIZE_F", cwnd %"TCPWNDSIZE_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F", i %"S16_F"\n", 01100 pcb->snd_wnd, pcb->cwnd, wnd, 01101 lwip_ntohl(seg->tcphdr->seqno) + seg->len - 01102 pcb->lastack, 01103 lwip_ntohl(seg->tcphdr->seqno), pcb->lastack, i)); 01104 ++i; 01105 #endif /* TCP_CWND_DEBUG */ 01106 01107 if (pcb->state != SYN_SENT) { 01108 TCPH_SET_FLAG(seg->tcphdr, TCP_ACK); 01109 } 01110 01111 #if TCP_OVERSIZE_DBGCHECK 01112 seg->oversize_left = 0; 01113 #endif /* TCP_OVERSIZE_DBGCHECK */ 01114 err = tcp_output_segment(seg, pcb, netif); 01115 if (err != ERR_OK) { 01116 /* segment could not be sent, for whatever reason */ 01117 pcb->flags |= TF_NAGLEMEMERR; 01118 return err; 01119 } 01120 pcb->unsent = seg->next; 01121 if (pcb->state != SYN_SENT) { 01122 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); 01123 } 01124 snd_nxt = lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg); 01125 if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) { 01126 pcb->snd_nxt = snd_nxt; 01127 } 01128 /* put segment on unacknowledged list if length > 0 */ 01129 if (TCP_TCPLEN(seg) > 0) { 01130 seg->next = NULL; 01131 /* unacked list is empty? */ 01132 if (pcb->unacked == NULL) { 01133 pcb->unacked = seg; 01134 useg = seg; 01135 /* unacked list is not empty? */ 01136 } else { 01137 /* In the case of fast retransmit, the packet should not go to the tail 01138 * of the unacked queue, but rather somewhere before it. We need to check for 01139 * this case. -STJ Jul 27, 2004 */ 01140 if (TCP_SEQ_LT(lwip_ntohl(seg->tcphdr->seqno), lwip_ntohl(useg->tcphdr->seqno))) { 01141 /* add segment to before tail of unacked list, keeping the list sorted */ 01142 struct tcp_seg **cur_seg = &(pcb->unacked); 01143 while (*cur_seg && 01144 TCP_SEQ_LT(lwip_ntohl((*cur_seg)->tcphdr->seqno), lwip_ntohl(seg->tcphdr->seqno))) { 01145 cur_seg = &((*cur_seg)->next ); 01146 } 01147 seg->next = (*cur_seg); 01148 (*cur_seg) = seg; 01149 } else { 01150 /* add segment to tail of unacked list */ 01151 useg->next = seg; 01152 useg = useg->next; 01153 } 01154 } 01155 /* do not queue empty segments on the unacked list */ 01156 } else { 01157 tcp_seg_free(seg); 01158 } 01159 seg = pcb->unsent; 01160 } 01161 output_done: 01162 #if TCP_OVERSIZE 01163 if (pcb->unsent == NULL) { 01164 /* last unsent has been removed, reset unsent_oversize */ 01165 pcb->unsent_oversize = 0; 01166 } 01167 #endif /* TCP_OVERSIZE */ 01168 01169 pcb->flags &= ~TF_NAGLEMEMERR; 01170 return ERR_OK; 01171 } 01172 01173 /** 01174 * Called by tcp_output() to actually send a TCP segment over IP. 01175 * 01176 * @param seg the tcp_seg to send 01177 * @param pcb the tcp_pcb for the TCP connection used to send the segment 01178 * @param netif the netif used to send the segment 01179 */ 01180 static err_t 01181 tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb, struct netif *netif) 01182 { 01183 err_t err; 01184 u16_t len; 01185 u32_t *opts; 01186 01187 if (seg->p->ref != 1) { 01188 /* This can happen if the pbuf of this segment is still referenced by the 01189 netif driver due to deferred transmission. Since this function modifies 01190 p->len, we must not continue in this case. */ 01191 return ERR_OK; 01192 } 01193 01194 /* The TCP header has already been constructed, but the ackno and 01195 wnd fields remain. */ 01196 seg->tcphdr->ackno = lwip_htonl(pcb->rcv_nxt); 01197 01198 /* advertise our receive window size in this TCP segment */ 01199 #if LWIP_WND_SCALE 01200 if (seg->flags & TF_SEG_OPTS_WND_SCALE) { 01201 /* The Window field in a SYN segment itself (the only type where we send 01202 the window scale option) is never scaled. */ 01203 seg->tcphdr->wnd = lwip_htons(TCPWND_MIN16(pcb->rcv_ann_wnd)); 01204 } else 01205 #endif /* LWIP_WND_SCALE */ 01206 { 01207 seg->tcphdr->wnd = lwip_htons(TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd))); 01208 } 01209 01210 pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd; 01211 01212 /* Add any requested options. NB MSS option is only set on SYN 01213 packets, so ignore it here */ 01214 /* cast through void* to get rid of alignment warnings */ 01215 opts = (u32_t *)(void *)(seg->tcphdr + 1); 01216 if (seg->flags & TF_SEG_OPTS_MSS) { 01217 u16_t mss; 01218 #if TCP_CALCULATE_EFF_SEND_MSS 01219 mss = tcp_eff_send_mss(TCP_MSS, &pcb->local_ip, &pcb->remote_ip); 01220 #else /* TCP_CALCULATE_EFF_SEND_MSS */ 01221 mss = TCP_MSS; 01222 #endif /* TCP_CALCULATE_EFF_SEND_MSS */ 01223 *opts = TCP_BUILD_MSS_OPTION(mss); 01224 opts += 1; 01225 } 01226 #if LWIP_TCP_TIMESTAMPS 01227 pcb->ts_lastacksent = pcb->rcv_nxt; 01228 01229 if (seg->flags & TF_SEG_OPTS_TS) { 01230 tcp_build_timestamp_option(pcb, opts); 01231 opts += 3; 01232 } 01233 #endif 01234 #if LWIP_WND_SCALE 01235 if (seg->flags & TF_SEG_OPTS_WND_SCALE) { 01236 tcp_build_wnd_scale_option(opts); 01237 opts += 1; 01238 } 01239 #endif 01240 01241 /* Set retransmission timer running if it is not currently enabled 01242 This must be set before checking the route. */ 01243 if (pcb->rtime < 0) { 01244 pcb->rtime = 0; 01245 } 01246 01247 if (pcb->rttest == 0) { 01248 pcb->rttest = tcp_ticks; 01249 pcb->rtseq = lwip_ntohl(seg->tcphdr->seqno); 01250 01251 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq)); 01252 } 01253 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n", 01254 lwip_htonl(seg->tcphdr->seqno), lwip_htonl(seg->tcphdr->seqno) + 01255 seg->len)); 01256 01257 len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload); 01258 if (len == 0) { 01259 /** Exclude retransmitted segments from this count. */ 01260 MIB2_STATS_INC(mib2.tcpoutsegs); 01261 } 01262 01263 seg->p->len -= len; 01264 seg->p->tot_len -= len; 01265 01266 seg->p->payload = seg->tcphdr; 01267 01268 seg->tcphdr->chksum = 0; 01269 #if CHECKSUM_GEN_TCP 01270 IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) { 01271 #if TCP_CHECKSUM_ON_COPY 01272 u32_t acc; 01273 #if TCP_CHECKSUM_ON_COPY_SANITY_CHECK 01274 u16_t chksum_slow = ip_chksum_pseudo(seg->p, IP_PROTO_TCP, 01275 seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip); 01276 #endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */ 01277 if ((seg->flags & TF_SEG_DATA_CHECKSUMMED) == 0) { 01278 LWIP_ASSERT("data included but not checksummed", 01279 seg->p->tot_len == (TCPH_HDRLEN(seg->tcphdr) * 4)); 01280 } 01281 01282 /* rebuild TCP header checksum (TCP header changes for retransmissions!) */ 01283 acc = ip_chksum_pseudo_partial(seg->p, IP_PROTO_TCP, 01284 seg->p->tot_len, TCPH_HDRLEN(seg->tcphdr) * 4, &pcb->local_ip, &pcb->remote_ip); 01285 /* add payload checksum */ 01286 if (seg->chksum_swapped) { 01287 seg->chksum = SWAP_BYTES_IN_WORD(seg->chksum); 01288 seg->chksum_swapped = 0; 01289 } 01290 acc += (u16_t)~(seg->chksum); 01291 seg->tcphdr->chksum = FOLD_U32T(acc); 01292 #if TCP_CHECKSUM_ON_COPY_SANITY_CHECK 01293 if (chksum_slow != seg->tcphdr->chksum) { 01294 TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL( 01295 ("tcp_output_segment: calculated checksum is %"X16_F" instead of %"X16_F"\n", 01296 seg->tcphdr->chksum, chksum_slow)); 01297 seg->tcphdr->chksum = chksum_slow; 01298 } 01299 #endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */ 01300 #else /* TCP_CHECKSUM_ON_COPY */ 01301 seg->tcphdr->chksum = ip_chksum_pseudo(seg->p, IP_PROTO_TCP, 01302 seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip); 01303 #endif /* TCP_CHECKSUM_ON_COPY */ 01304 } 01305 #endif /* CHECKSUM_GEN_TCP */ 01306 TCP_STATS_INC(tcp.xmit); 01307 01308 NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint)); 01309 err = ip_output_if(seg->p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 01310 pcb->tos, IP_PROTO_TCP, netif); 01311 NETIF_SET_HWADDRHINT(netif, NULL); 01312 return err; 01313 } 01314 01315 /** 01316 * Send a TCP RESET packet (empty segment with RST flag set) either to 01317 * abort a connection or to show that there is no matching local connection 01318 * for a received segment. 01319 * 01320 * Called by tcp_abort() (to abort a local connection), tcp_input() (if no 01321 * matching local pcb was found), tcp_listen_input() (if incoming segment 01322 * has ACK flag set) and tcp_process() (received segment in the wrong state) 01323 * 01324 * Since a RST segment is in most cases not sent for an active connection, 01325 * tcp_rst() has a number of arguments that are taken from a tcp_pcb for 01326 * most other segment output functions. 01327 * 01328 * @param seqno the sequence number to use for the outgoing segment 01329 * @param ackno the acknowledge number to use for the outgoing segment 01330 * @param local_ip the local IP address to send the segment from 01331 * @param remote_ip the remote IP address to send the segment to 01332 * @param local_port the local TCP port to send the segment from 01333 * @param remote_port the remote TCP port to send the segment to 01334 */ 01335 void 01336 tcp_rst(u32_t seqno, u32_t ackno, 01337 const ip_addr_t *local_ip, const ip_addr_t *remote_ip, 01338 u16_t local_port, u16_t remote_port) 01339 { 01340 struct pbuf *p; 01341 struct tcp_hdr *tcphdr; 01342 struct netif *netif; 01343 p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM); 01344 if (p == NULL) { 01345 LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n")); 01346 return; 01347 } 01348 LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr", 01349 (p->len >= sizeof(struct tcp_hdr))); 01350 01351 tcphdr = (struct tcp_hdr *)p->payload; 01352 tcphdr->src = lwip_htons(local_port); 01353 tcphdr->dest = lwip_htons(remote_port); 01354 tcphdr->seqno = lwip_htonl(seqno); 01355 tcphdr->ackno = lwip_htonl(ackno); 01356 TCPH_HDRLEN_FLAGS_SET(tcphdr, TCP_HLEN/4, TCP_RST | TCP_ACK); 01357 #if LWIP_WND_SCALE 01358 tcphdr->wnd = PP_HTONS(((TCP_WND >> TCP_RCV_SCALE) & 0xFFFF)); 01359 #else 01360 tcphdr->wnd = PP_HTONS(TCP_WND); 01361 #endif 01362 tcphdr->chksum = 0; 01363 tcphdr->urgp = 0; 01364 01365 TCP_STATS_INC(tcp.xmit); 01366 MIB2_STATS_INC(mib2.tcpoutrsts); 01367 01368 netif = ip_route(local_ip, remote_ip); 01369 if (netif != NULL) { 01370 #if CHECKSUM_GEN_TCP 01371 IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) { 01372 tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, 01373 local_ip, remote_ip); 01374 } 01375 #endif 01376 /* Send output with hardcoded TTL/HL since we have no access to the pcb */ 01377 ip_output_if(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP, netif); 01378 } 01379 pbuf_free(p); 01380 LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno)); 01381 } 01382 01383 /** 01384 * Requeue all unacked segments for retransmission 01385 * 01386 * Called by tcp_slowtmr() for slow retransmission. 01387 * 01388 * @param pcb the tcp_pcb for which to re-enqueue all unacked segments 01389 */ 01390 void 01391 tcp_rexmit_rto(struct tcp_pcb *pcb) 01392 { 01393 struct tcp_seg *seg; 01394 01395 if (pcb->unacked == NULL) { 01396 return; 01397 } 01398 01399 /* Move all unacked segments to the head of the unsent queue */ 01400 for (seg = pcb->unacked; seg->next != NULL; seg = seg->next); 01401 /* concatenate unsent queue after unacked queue */ 01402 seg->next = pcb->unsent; 01403 #if TCP_OVERSIZE_DBGCHECK 01404 /* if last unsent changed, we need to update unsent_oversize */ 01405 if (pcb->unsent == NULL) { 01406 pcb->unsent_oversize = seg->oversize_left; 01407 } 01408 #endif /* TCP_OVERSIZE_DBGCHECK */ 01409 /* unsent queue is the concatenated queue (of unacked, unsent) */ 01410 pcb->unsent = pcb->unacked; 01411 /* unacked queue is now empty */ 01412 pcb->unacked = NULL; 01413 01414 /* increment number of retransmissions */ 01415 ++pcb->nrtx; 01416 01417 /* Don't take any RTT measurements after retransmitting. */ 01418 pcb->rttest = 0; 01419 01420 /* Do the actual retransmission */ 01421 tcp_output(pcb); 01422 } 01423 01424 /** 01425 * Requeue the first unacked segment for retransmission 01426 * 01427 * Called by tcp_receive() for fast retransmit. 01428 * 01429 * @param pcb the tcp_pcb for which to retransmit the first unacked segment 01430 */ 01431 void 01432 tcp_rexmit(struct tcp_pcb *pcb) 01433 { 01434 struct tcp_seg *seg; 01435 struct tcp_seg **cur_seg; 01436 01437 if (pcb->unacked == NULL) { 01438 return; 01439 } 01440 01441 /* Move the first unacked segment to the unsent queue */ 01442 /* Keep the unsent queue sorted. */ 01443 seg = pcb->unacked; 01444 pcb->unacked = seg->next; 01445 01446 cur_seg = &(pcb->unsent); 01447 while (*cur_seg && 01448 TCP_SEQ_LT(lwip_ntohl((*cur_seg)->tcphdr->seqno), lwip_ntohl(seg->tcphdr->seqno))) { 01449 cur_seg = &((*cur_seg)->next ); 01450 } 01451 seg->next = *cur_seg; 01452 *cur_seg = seg; 01453 #if TCP_OVERSIZE 01454 if (seg->next == NULL) { 01455 /* the retransmitted segment is last in unsent, so reset unsent_oversize */ 01456 pcb->unsent_oversize = 0; 01457 } 01458 #endif /* TCP_OVERSIZE */ 01459 01460 ++pcb->nrtx; 01461 01462 /* Don't take any rtt measurements after retransmitting. */ 01463 pcb->rttest = 0; 01464 01465 /* Do the actual retransmission. */ 01466 MIB2_STATS_INC(mib2.tcpretranssegs); 01467 /* No need to call tcp_output: we are always called from tcp_input() 01468 and thus tcp_output directly returns. */ 01469 } 01470 01471 01472 /** 01473 * Handle retransmission after three dupacks received 01474 * 01475 * @param pcb the tcp_pcb for which to retransmit the first unacked segment 01476 */ 01477 void 01478 tcp_rexmit_fast(struct tcp_pcb *pcb) 01479 { 01480 if (pcb->unacked != NULL && !(pcb->flags & TF_INFR)) { 01481 /* This is fast retransmit. Retransmit the first unacked segment. */ 01482 LWIP_DEBUGF(TCP_FR_DEBUG, 01483 ("tcp_receive: dupacks %"U16_F" (%"U32_F 01484 "), fast retransmit %"U32_F"\n", 01485 (u16_t)pcb->dupacks, pcb->lastack, 01486 lwip_ntohl(pcb->unacked->tcphdr->seqno))); 01487 tcp_rexmit(pcb); 01488 01489 /* Set ssthresh to half of the minimum of the current 01490 * cwnd and the advertised window */ 01491 if (pcb->cwnd > pcb->snd_wnd) { 01492 pcb->ssthresh = pcb->snd_wnd / 2; 01493 } else { 01494 pcb->ssthresh = pcb->cwnd / 2; 01495 } 01496 01497 /* The minimum value for ssthresh should be 2 MSS */ 01498 if (pcb->ssthresh < (2U * pcb->mss)) { 01499 LWIP_DEBUGF(TCP_FR_DEBUG, 01500 ("tcp_receive: The minimum value for ssthresh %"TCPWNDSIZE_F 01501 " should be min 2 mss %"U16_F"...\n", 01502 pcb->ssthresh, (u16_t)(2*pcb->mss))); 01503 pcb->ssthresh = 2*pcb->mss; 01504 } 01505 01506 pcb->cwnd = pcb->ssthresh + 3 * pcb->mss; 01507 pcb->flags |= TF_INFR; 01508 01509 /* Reset the retransmission timer to prevent immediate rto retransmissions */ 01510 pcb->rtime = 0; 01511 } 01512 } 01513 01514 01515 /** 01516 * Send keepalive packets to keep a connection active although 01517 * no data is sent over it. 01518 * 01519 * Called by tcp_slowtmr() 01520 * 01521 * @param pcb the tcp_pcb for which to send a keepalive packet 01522 */ 01523 err_t 01524 tcp_keepalive(struct tcp_pcb *pcb) 01525 { 01526 err_t err; 01527 struct pbuf *p; 01528 struct netif *netif; 01529 01530 LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to ")); 01531 ip_addr_debug_print(TCP_DEBUG, &pcb->remote_ip); 01532 LWIP_DEBUGF(TCP_DEBUG, ("\n")); 01533 01534 LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", 01535 tcp_ticks, pcb->tmr, (u16_t)pcb->keep_cnt_sent)); 01536 01537 p = tcp_output_alloc_header(pcb, 0, 0, lwip_htonl(pcb->snd_nxt - 1)); 01538 if (p == NULL) { 01539 LWIP_DEBUGF(TCP_DEBUG, 01540 ("tcp_keepalive: could not allocate memory for pbuf\n")); 01541 return ERR_MEM; 01542 } 01543 netif = ip_route(&pcb->local_ip, &pcb->remote_ip); 01544 if (netif == NULL) { 01545 err = ERR_RTE; 01546 } else { 01547 #if CHECKSUM_GEN_TCP 01548 IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) { 01549 struct tcp_hdr *tcphdr = (struct tcp_hdr *)p->payload; 01550 tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, 01551 &pcb->local_ip, &pcb->remote_ip); 01552 } 01553 #endif /* CHECKSUM_GEN_TCP */ 01554 TCP_STATS_INC(tcp.xmit); 01555 01556 /* Send output to IP */ 01557 NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint)); 01558 err = ip_output_if(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP, netif); 01559 NETIF_SET_HWADDRHINT(netif, NULL); 01560 } 01561 pbuf_free(p); 01562 01563 LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F" err %d.\n", 01564 pcb->snd_nxt - 1, pcb->rcv_nxt, (int)err)); 01565 return err; 01566 } 01567 01568 01569 /** 01570 * Send persist timer zero-window probes to keep a connection active 01571 * when a window update is lost. 01572 * 01573 * Called by tcp_slowtmr() 01574 * 01575 * @param pcb the tcp_pcb for which to send a zero-window probe packet 01576 */ 01577 err_t 01578 tcp_zero_window_probe(struct tcp_pcb *pcb) 01579 { 01580 err_t err; 01581 struct pbuf *p; 01582 struct tcp_hdr *tcphdr; 01583 struct tcp_seg *seg; 01584 u16_t len; 01585 u8_t is_fin; 01586 u32_t snd_nxt; 01587 struct netif *netif; 01588 01589 LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: sending ZERO WINDOW probe to ")); 01590 ip_addr_debug_print(TCP_DEBUG, &pcb->remote_ip); 01591 LWIP_DEBUGF(TCP_DEBUG, ("\n")); 01592 01593 LWIP_DEBUGF(TCP_DEBUG, 01594 ("tcp_zero_window_probe: tcp_ticks %"U32_F 01595 " pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", 01596 tcp_ticks, pcb->tmr, (u16_t)pcb->keep_cnt_sent)); 01597 01598 seg = pcb->unacked; 01599 01600 if (seg == NULL) { 01601 seg = pcb->unsent; 01602 } 01603 if (seg == NULL) { 01604 /* nothing to send, zero window probe not needed */ 01605 return ERR_OK; 01606 } 01607 01608 is_fin = ((TCPH_FLAGS(seg->tcphdr) & TCP_FIN) != 0) && (seg->len == 0); 01609 /* we want to send one seqno: either FIN or data (no options) */ 01610 len = is_fin ? 0 : 1; 01611 01612 p = tcp_output_alloc_header(pcb, 0, len, seg->tcphdr->seqno); 01613 if (p == NULL) { 01614 LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: no memory for pbuf\n")); 01615 return ERR_MEM; 01616 } 01617 tcphdr = (struct tcp_hdr *)p->payload; 01618 01619 if (is_fin) { 01620 /* FIN segment, no data */ 01621 TCPH_FLAGS_SET(tcphdr, TCP_ACK | TCP_FIN); 01622 } else { 01623 /* Data segment, copy in one byte from the head of the unacked queue */ 01624 char *d = ((char *)p->payload + TCP_HLEN); 01625 /* Depending on whether the segment has already been sent (unacked) or not 01626 (unsent), seg->p->payload points to the IP header or TCP header. 01627 Ensure we copy the first TCP data byte: */ 01628 pbuf_copy_partial(seg->p, d, 1, seg->p->tot_len - seg->len); 01629 } 01630 01631 /* The byte may be acknowledged without the window being opened. */ 01632 snd_nxt = lwip_ntohl(seg->tcphdr->seqno) + 1; 01633 if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) { 01634 pcb->snd_nxt = snd_nxt; 01635 } 01636 01637 netif = ip_route(&pcb->local_ip, &pcb->remote_ip); 01638 if (netif == NULL) { 01639 err = ERR_RTE; 01640 } else { 01641 #if CHECKSUM_GEN_TCP 01642 IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) { 01643 tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, 01644 &pcb->local_ip, &pcb->remote_ip); 01645 } 01646 #endif 01647 TCP_STATS_INC(tcp.xmit); 01648 01649 /* Send output to IP */ 01650 NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint)); 01651 err = ip_output_if(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 01652 0, IP_PROTO_TCP, netif); 01653 NETIF_SET_HWADDRHINT(netif, NULL); 01654 } 01655 01656 pbuf_free(p); 01657 01658 LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: seqno %"U32_F 01659 " ackno %"U32_F" err %d.\n", 01660 pcb->snd_nxt - 1, pcb->rcv_nxt, (int)err)); 01661 return err; 01662 } 01663 #endif /* LWIP_TCP */
Generated on Tue Jul 12 2022 11:02:28 by
1.7.2