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