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