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