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