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