Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygentcp_out.c
Go to the documentation of this file.
00001 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 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 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 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 pcb->flags |= TF_FIN; 00135 return ERR_OK; 00136 } 00137 } 00138 /* no data, no length, flags, copy=1, no optdata */ 00139 return tcp_enqueue_flags(pcb, TCP_FIN); 00140 } 00141 00156 static struct tcp_seg * 00157 tcp_create_segment(struct tcp_pcb *pcb, struct pbuf *p, u8_t flags, u32_t seqno, u8_t optflags) 00158 { 00159 struct tcp_seg *seg; 00160 u8_t optlen = LWIP_TCP_OPT_LENGTH(optflags); 00161 00162 if ((seg = (struct tcp_seg *)memp_malloc(MEMP_TCP_SEG)) == NULL) { 00163 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_create_segment: no memory.\n")); 00164 pbuf_free(p); 00165 return NULL; 00166 } 00167 seg->flags = optflags; 00168 seg->next = NULL; 00169 seg->p = p; 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 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 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 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 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 00594 /* first segment of to-be-queued data? */ 00595 if (queue == NULL) { 00596 queue = seg; 00597 } else { 00598 /* Attach the segment to the end of the queued segments */ 00599 LWIP_ASSERT("prev_seg != NULL", prev_seg != NULL); 00600 prev_seg->next = seg; 00601 } 00602 /* remember last segment of to-be-queued data for next iteration */ 00603 prev_seg = seg; 00604 00605 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, ("tcp_write: queueing %"U32_F":%"U32_F"\n", 00606 ntohl(seg->tcphdr->seqno), 00607 ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg))); 00608 00609 pos += seglen; 00610 } 00611 00612 /* 00613 * All three segmentation phases were successful. We can commit the 00614 * transaction. 00615 */ 00616 00617 /* 00618 * Phase 1: If data has been added to the preallocated tail of 00619 * last_unsent, we update the length fields of the pbuf chain. 00620 */ 00621 #if TCP_OVERSIZE 00622 if (oversize_used > 0) { 00623 struct pbuf *p; 00624 /* Bump tot_len of whole chain, len of tail */ 00625 for (p = last_unsent->p; p; p = p->next) { 00626 p->tot_len += oversize_used; 00627 if (p->next == NULL) { 00628 TCP_DATA_COPY((char *)p->payload + p->len, arg, oversize_used, last_unsent); 00629 p->len += oversize_used; 00630 } 00631 } 00632 last_unsent->len += oversize_used; 00633 #if TCP_OVERSIZE_DBGCHECK 00634 last_unsent->oversize_left -= oversize_used; 00635 #endif /* TCP_OVERSIZE_DBGCHECK */ 00636 } 00637 pcb->unsent_oversize = oversize; 00638 #endif /* TCP_OVERSIZE */ 00639 00640 /* 00641 * Phase 2: concat_p can be concatenated onto last_unsent->p 00642 */ 00643 if (concat_p != NULL) { 00644 LWIP_ASSERT("tcp_write: cannot concatenate when pcb->unsent is empty", 00645 (last_unsent != NULL)); 00646 pbuf_cat(last_unsent->p, concat_p); 00647 last_unsent->len += concat_p->tot_len; 00648 #if TCP_CHECKSUM_ON_COPY 00649 if (concat_chksummed) { 00650 tcp_seg_add_chksum(concat_chksum, concat_chksummed, &last_unsent->chksum, 00651 &last_unsent->chksum_swapped); 00652 last_unsent->flags |= TF_SEG_DATA_CHECKSUMMED; 00653 } 00654 #endif /* TCP_CHECKSUM_ON_COPY */ 00655 } 00656 00657 /* 00658 * Phase 3: Append queue to pcb->unsent. Queue may be NULL, but that 00659 * is harmless 00660 */ 00661 if (last_unsent == NULL) { 00662 pcb->unsent = queue; 00663 } else { 00664 last_unsent->next = queue; 00665 } 00666 00667 /* 00668 * Finally update the pcb state. 00669 */ 00670 pcb->snd_lbb += len; 00671 pcb->snd_buf -= len; 00672 pcb->snd_queuelen = queuelen; 00673 00674 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: %"S16_F" (after enqueued)\n", 00675 pcb->snd_queuelen)); 00676 if (pcb->snd_queuelen != 0) { 00677 LWIP_ASSERT("tcp_write: valid queue length", 00678 pcb->unacked != NULL || pcb->unsent != NULL); 00679 } 00680 00681 /* Set the PSH flag in the last segment that we enqueued. */ 00682 if (seg != NULL && seg->tcphdr != NULL && ((apiflags & TCP_WRITE_FLAG_MORE)==0)) { 00683 TCPH_SET_FLAG(seg->tcphdr, TCP_PSH); 00684 } 00685 00686 return ERR_OK; 00687 memerr: 00688 pcb->flags |= TF_NAGLEMEMERR; 00689 TCP_STATS_INC(tcp.memerr); 00690 00691 if (concat_p != NULL) { 00692 pbuf_free(concat_p); 00693 } 00694 if (queue != NULL) { 00695 tcp_segs_free(queue); 00696 } 00697 if (pcb->snd_queuelen != 0) { 00698 LWIP_ASSERT("tcp_write: valid queue length", pcb->unacked != NULL || 00699 pcb->unsent != NULL); 00700 } 00701 LWIP_DEBUGF(TCP_QLEN_DEBUG | LWIP_DBG_STATE, ("tcp_write: %"S16_F" (with mem err)\n", pcb->snd_queuelen)); 00702 return ERR_MEM; 00703 } 00704 00715 err_t 00716 tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags) 00717 { 00718 struct pbuf *p; 00719 struct tcp_seg *seg; 00720 u8_t optflags = 0; 00721 u8_t optlen = 0; 00722 00723 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen)); 00724 00725 LWIP_ASSERT("tcp_enqueue_flags: need either TCP_SYN or TCP_FIN in flags (programmer violates API)", 00726 (flags & (TCP_SYN | TCP_FIN)) != 0); 00727 00728 /* check for configured max queuelen and possible overflow */ 00729 if ((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { 00730 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue_flags: too long queue %"U16_F" (max %"U16_F")\n", 00731 pcb->snd_queuelen, TCP_SND_QUEUELEN)); 00732 TCP_STATS_INC(tcp.memerr); 00733 pcb->flags |= TF_NAGLEMEMERR; 00734 return ERR_MEM; 00735 } 00736 00737 if (flags & TCP_SYN) { 00738 optflags = TF_SEG_OPTS_MSS; 00739 } 00740 #if LWIP_TCP_TIMESTAMPS 00741 if ((pcb->flags & TF_TIMESTAMP)) { 00742 optflags |= TF_SEG_OPTS_TS; 00743 } 00744 #endif /* LWIP_TCP_TIMESTAMPS */ 00745 optlen = LWIP_TCP_OPT_LENGTH(optflags); 00746 00747 /* tcp_enqueue_flags is always called with either SYN or FIN in flags. 00748 * We need one available snd_buf byte to do that. 00749 * This means we can't send FIN while snd_buf==0. A better fix would be to 00750 * not include SYN and FIN sequence numbers in the snd_buf count. */ 00751 if (pcb->snd_buf == 0) { 00752 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue_flags: no send buffer available\n")); 00753 TCP_STATS_INC(tcp.memerr); 00754 return ERR_MEM; 00755 } 00756 00757 /* Allocate pbuf with room for TCP header + options */ 00758 if ((p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) { 00759 pcb->flags |= TF_NAGLEMEMERR; 00760 TCP_STATS_INC(tcp.memerr); 00761 return ERR_MEM; 00762 } 00763 LWIP_ASSERT("tcp_enqueue_flags: check that first pbuf can hold optlen", 00764 (p->len >= optlen)); 00765 00766 /* Allocate memory for tcp_seg, and fill in fields. */ 00767 if ((seg = tcp_create_segment(pcb, p, flags, pcb->snd_lbb, optflags)) == NULL) { 00768 pcb->flags |= TF_NAGLEMEMERR; 00769 TCP_STATS_INC(tcp.memerr); 00770 return ERR_MEM; 00771 } 00772 LWIP_ASSERT("seg->tcphdr not aligned", ((mem_ptr_t)seg->tcphdr % MEM_ALIGNMENT) == 0); 00773 LWIP_ASSERT("tcp_enqueue_flags: invalid segment length", seg->len == 0); 00774 00775 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, 00776 ("tcp_enqueue_flags: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n", 00777 ntohl(seg->tcphdr->seqno), 00778 ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg), 00779 (u16_t)flags)); 00780 00781 /* Now append seg to pcb->unsent queue */ 00782 if (pcb->unsent == NULL) { 00783 pcb->unsent = seg; 00784 } else { 00785 struct tcp_seg *useg; 00786 for (useg = pcb->unsent; useg->next != NULL; useg = useg->next); 00787 useg->next = seg; 00788 } 00789 #if TCP_OVERSIZE 00790 /* The new unsent tail has no space */ 00791 pcb->unsent_oversize = 0; 00792 #endif /* TCP_OVERSIZE */ 00793 00794 /* SYN and FIN bump the sequence number */ 00795 if ((flags & TCP_SYN) || (flags & TCP_FIN)) { 00796 pcb->snd_lbb++; 00797 /* optlen does not influence snd_buf */ 00798 pcb->snd_buf--; 00799 } 00800 if (flags & TCP_FIN) { 00801 pcb->flags |= TF_FIN; 00802 } 00803 00804 /* update number of segments on the queues */ 00805 pcb->snd_queuelen += pbuf_clen(seg->p); 00806 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: %"S16_F" (after enqueued)\n", pcb->snd_queuelen)); 00807 if (pcb->snd_queuelen != 0) { 00808 LWIP_ASSERT("tcp_enqueue_flags: invalid queue length", 00809 pcb->unacked != NULL || pcb->unsent != NULL); 00810 } 00811 00812 return ERR_OK; 00813 } 00814 00815 00816 #if LWIP_TCP_TIMESTAMPS 00817 /* Build a timestamp option (12 bytes long) at the specified options pointer) 00818 * 00819 * @param pcb tcp_pcb 00820 * @param opts option pointer where to store the timestamp option 00821 */ 00822 static void 00823 tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts) 00824 { 00825 /* Pad with two NOP options to make everything nicely aligned */ 00826 opts[0] = PP_HTONL(0x0101080A); 00827 opts[1] = htonl(sys_now()); 00828 opts[2] = htonl(pcb->ts_recent); 00829 } 00830 #endif 00831 00836 err_t 00837 tcp_send_empty_ack(struct tcp_pcb *pcb) 00838 { 00839 struct pbuf *p; 00840 struct tcp_hdr *tcphdr; 00841 u8_t optlen = 0; 00842 00843 #if LWIP_TCP_TIMESTAMPS 00844 if (pcb->flags & TF_TIMESTAMP) { 00845 optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS); 00846 } 00847 #endif 00848 00849 p = tcp_output_alloc_header(pcb, optlen, 0, htonl(pcb->snd_nxt)); 00850 if (p == NULL) { 00851 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n")); 00852 return ERR_BUF; 00853 } 00854 tcphdr = (struct tcp_hdr *)p->payload; 00855 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, 00856 ("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt)); 00857 /* remove ACK flags from the PCB, as we send an empty ACK now */ 00858 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); 00859 00860 /* NB. MSS option is only sent on SYNs, so ignore it here */ 00861 #if LWIP_TCP_TIMESTAMPS 00862 pcb->ts_lastacksent = pcb->rcv_nxt; 00863 00864 if (pcb->flags & TF_TIMESTAMP) { 00865 tcp_build_timestamp_option(pcb, (u32_t *)(tcphdr + 1)); 00866 } 00867 #endif 00868 00869 #if CHECKSUM_GEN_TCP 00870 tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip), 00871 IP_PROTO_TCP, p->tot_len); 00872 #endif 00873 #if LWIP_NETIF_HWADDRHINT 00874 ip_output_hinted(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos, 00875 IP_PROTO_TCP, &(pcb->addr_hint)); 00876 #else /* LWIP_NETIF_HWADDRHINT*/ 00877 ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos, 00878 IP_PROTO_TCP); 00879 #endif /* LWIP_NETIF_HWADDRHINT*/ 00880 pbuf_free(p); 00881 00882 return ERR_OK; 00883 } 00884 00892 err_t 00893 tcp_output(struct tcp_pcb *pcb) 00894 { 00895 struct tcp_seg *seg, *useg; 00896 u32_t wnd, snd_nxt; 00897 #if TCP_CWND_DEBUG 00898 s16_t i = 0; 00899 #endif /* TCP_CWND_DEBUG */ 00900 00901 /* First, check if we are invoked by the TCP input processing 00902 code. If so, we do not output anything. Instead, we rely on the 00903 input processing code to call us when input processing is done 00904 with. */ 00905 if (tcp_input_pcb == pcb) { 00906 return ERR_OK; 00907 } 00908 00909 wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd); 00910 00911 seg = pcb->unsent; 00912 00913 /* If the TF_ACK_NOW flag is set and no data will be sent (either 00914 * because the ->unsent queue is empty or because the window does 00915 * not allow it), construct an empty ACK segment and send it. 00916 * 00917 * If data is to be sent, we will just piggyback the ACK (see below). 00918 */ 00919 if (pcb->flags & TF_ACK_NOW && 00920 (seg == NULL || 00921 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) { 00922 return tcp_send_empty_ack(pcb); 00923 } 00924 00925 /* useg should point to last segment on unacked queue */ 00926 useg = pcb->unacked; 00927 if (useg != NULL) { 00928 for (; useg->next != NULL; useg = useg->next); 00929 } 00930 00931 #if TCP_OUTPUT_DEBUG 00932 if (seg == NULL) { 00933 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n", 00934 (void*)pcb->unsent)); 00935 } 00936 #endif /* TCP_OUTPUT_DEBUG */ 00937 #if TCP_CWND_DEBUG 00938 if (seg == NULL) { 00939 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U16_F 00940 ", cwnd %"U16_F", wnd %"U32_F 00941 ", seg == NULL, ack %"U32_F"\n", 00942 pcb->snd_wnd, pcb->cwnd, wnd, pcb->lastack)); 00943 } else { 00944 LWIP_DEBUGF(TCP_CWND_DEBUG, 00945 ("tcp_output: snd_wnd %"U16_F", cwnd %"U16_F", wnd %"U32_F 00946 ", effwnd %"U32_F", seq %"U32_F", ack %"U32_F"\n", 00947 pcb->snd_wnd, pcb->cwnd, wnd, 00948 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len, 00949 ntohl(seg->tcphdr->seqno), pcb->lastack)); 00950 } 00951 #endif /* TCP_CWND_DEBUG */ 00952 /* data available and window allows it to be sent? */ 00953 while (seg != NULL && 00954 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) { 00955 LWIP_ASSERT("RST not expected here!", 00956 (TCPH_FLAGS(seg->tcphdr) & TCP_RST) == 0); 00957 /* Stop sending if the nagle algorithm would prevent it 00958 * Don't stop: 00959 * - if tcp_write had a memory error before (prevent delayed ACK timeout) or 00960 * - if FIN was already enqueued for this PCB (SYN is always alone in a segment - 00961 * either seg->next != NULL or pcb->unacked == NULL; 00962 * RST is no sent using tcp_write/tcp_output. 00963 */ 00964 if((tcp_do_output_nagle(pcb) == 0) && 00965 ((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)){ 00966 break; 00967 } 00968 #if TCP_CWND_DEBUG 00969 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", 00970 pcb->snd_wnd, pcb->cwnd, wnd, 00971 ntohl(seg->tcphdr->seqno) + seg->len - 00972 pcb->lastack, 00973 ntohl(seg->tcphdr->seqno), pcb->lastack, i)); 00974 ++i; 00975 #endif /* TCP_CWND_DEBUG */ 00976 00977 pcb->unsent = seg->next; 00978 00979 if (pcb->state != SYN_SENT) { 00980 TCPH_SET_FLAG(seg->tcphdr, TCP_ACK); 00981 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); 00982 } 00983 00984 tcp_output_segment(seg, pcb); 00985 snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg); 00986 if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) { 00987 pcb->snd_nxt = snd_nxt; 00988 } 00989 /* put segment on unacknowledged list if length > 0 */ 00990 if (TCP_TCPLEN(seg) > 0) { 00991 seg->next = NULL; 00992 /* unacked list is empty? */ 00993 if (pcb->unacked == NULL) { 00994 pcb->unacked = seg; 00995 useg = seg; 00996 /* unacked list is not empty? */ 00997 } else { 00998 /* In the case of fast retransmit, the packet should not go to the tail 00999 * of the unacked queue, but rather somewhere before it. We need to check for 01000 * this case. -STJ Jul 27, 2004 */ 01001 if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))) { 01002 /* add segment to before tail of unacked list, keeping the list sorted */ 01003 struct tcp_seg **cur_seg = &(pcb->unacked); 01004 while (*cur_seg && 01005 TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) { 01006 cur_seg = &((*cur_seg)->next ); 01007 } 01008 seg->next = (*cur_seg); 01009 (*cur_seg) = seg; 01010 } else { 01011 /* add segment to tail of unacked list */ 01012 useg->next = seg; 01013 useg = useg->next; 01014 } 01015 } 01016 /* do not queue empty segments on the unacked list */ 01017 } else { 01018 tcp_seg_free(seg); 01019 } 01020 seg = pcb->unsent; 01021 } 01022 #if TCP_OVERSIZE 01023 if (pcb->unsent == NULL) { 01024 /* last unsent has been removed, reset unsent_oversize */ 01025 pcb->unsent_oversize = 0; 01026 } 01027 #endif /* TCP_OVERSIZE */ 01028 01029 if (seg != NULL && pcb->persist_backoff == 0 && 01030 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > pcb->snd_wnd) { 01031 /* prepare for persist timer */ 01032 pcb->persist_cnt = 0; 01033 pcb->persist_backoff = 1; 01034 } 01035 01036 pcb->flags &= ~TF_NAGLEMEMERR; 01037 return ERR_OK; 01038 } 01039 01046 static void 01047 tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb) 01048 { 01049 u16_t len; 01050 struct netif *netif; 01051 u32_t *opts; 01052 01054 snmp_inc_tcpoutsegs(); 01055 01056 /* The TCP header has already been constructed, but the ackno and 01057 wnd fields remain. */ 01058 seg->tcphdr->ackno = htonl(pcb->rcv_nxt); 01059 01060 /* advertise our receive window size in this TCP segment */ 01061 seg->tcphdr->wnd = htons(pcb->rcv_ann_wnd); 01062 01063 pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd; 01064 01065 /* Add any requested options. NB MSS option is only set on SYN 01066 packets, so ignore it here */ 01067 LWIP_ASSERT("seg->tcphdr not aligned", ((mem_ptr_t)seg->tcphdr % MEM_ALIGNMENT) == 0); 01068 opts = (u32_t *)(void *)(seg->tcphdr + 1); 01069 if (seg->flags & TF_SEG_OPTS_MSS) { 01070 TCP_BUILD_MSS_OPTION(*opts); 01071 opts += 1; 01072 } 01073 #if LWIP_TCP_TIMESTAMPS 01074 pcb->ts_lastacksent = pcb->rcv_nxt; 01075 01076 if (seg->flags & TF_SEG_OPTS_TS) { 01077 tcp_build_timestamp_option(pcb, opts); 01078 opts += 3; 01079 } 01080 #endif 01081 01082 /* Set retransmission timer running if it is not currently enabled 01083 This must be set before checking the route. */ 01084 if (pcb->rtime == -1) { 01085 pcb->rtime = 0; 01086 } 01087 01088 /* If we don't have a local IP address, we get one by 01089 calling ip_route(). */ 01090 if (ip_addr_isany(&(pcb->local_ip))) { 01091 netif = ip_route(&(pcb->remote_ip)); 01092 if (netif == NULL) { 01093 return; 01094 } 01095 ip_addr_copy(pcb->local_ip, netif->ip_addr); 01096 } 01097 01098 if (pcb->rttest == 0) { 01099 pcb->rttest = tcp_ticks; 01100 pcb->rtseq = ntohl(seg->tcphdr->seqno); 01101 01102 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq)); 01103 } 01104 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n", 01105 htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) + 01106 seg->len)); 01107 01108 len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload); 01109 01110 seg->p->len -= len; 01111 seg->p->tot_len -= len; 01112 01113 seg->p->payload = seg->tcphdr; 01114 01115 seg->tcphdr->chksum = 0; 01116 #if CHECKSUM_GEN_TCP 01117 #if TCP_CHECKSUM_ON_COPY 01118 { 01119 u32_t acc; 01120 #if TCP_CHECKSUM_ON_COPY_SANITY_CHECK 01121 u16_t chksum_slow = inet_chksum_pseudo(seg->p, &(pcb->local_ip), 01122 &(pcb->remote_ip), 01123 IP_PROTO_TCP, seg->p->tot_len); 01124 #endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */ 01125 if ((seg->flags & TF_SEG_DATA_CHECKSUMMED) == 0) { 01126 LWIP_ASSERT("data included but not checksummed", 01127 seg->p->tot_len == (TCPH_HDRLEN(seg->tcphdr) * 4)); 01128 } 01129 01130 /* rebuild TCP header checksum (TCP header changes for retransmissions!) */ 01131 acc = inet_chksum_pseudo_partial(seg->p, &(pcb->local_ip), 01132 &(pcb->remote_ip), 01133 IP_PROTO_TCP, seg->p->tot_len, TCPH_HDRLEN(seg->tcphdr) * 4); 01134 /* add payload checksum */ 01135 if (seg->chksum_swapped) { 01136 seg->chksum = SWAP_BYTES_IN_WORD(seg->chksum); 01137 seg->chksum_swapped = 0; 01138 } 01139 acc += (u16_t)~(seg->chksum); 01140 seg->tcphdr->chksum = FOLD_U32T(acc); 01141 #if TCP_CHECKSUM_ON_COPY_SANITY_CHECK 01142 if (chksum_slow != seg->tcphdr->chksum) { 01143 LWIP_DEBUGF(TCP_DEBUG | LWIP_DBG_LEVEL_WARNING, 01144 ("tcp_output_segment: calculated checksum is %"X16_F" instead of %"X16_F"\n", 01145 seg->tcphdr->chksum, chksum_slow)); 01146 seg->tcphdr->chksum = chksum_slow; 01147 } 01148 #endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */ 01149 } 01150 #else /* TCP_CHECKSUM_ON_COPY */ 01151 seg->tcphdr->chksum = inet_chksum_pseudo(seg->p, &(pcb->local_ip), 01152 &(pcb->remote_ip), 01153 IP_PROTO_TCP, seg->p->tot_len); 01154 #endif /* TCP_CHECKSUM_ON_COPY */ 01155 #endif /* CHECKSUM_GEN_TCP */ 01156 TCP_STATS_INC(tcp.xmit); 01157 01158 #if LWIP_NETIF_HWADDRHINT 01159 ip_output_hinted(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos, 01160 IP_PROTO_TCP, &(pcb->addr_hint)); 01161 #else /* LWIP_NETIF_HWADDRHINT*/ 01162 ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos, 01163 IP_PROTO_TCP); 01164 #endif /* LWIP_NETIF_HWADDRHINT*/ 01165 } 01166 01187 void 01188 tcp_rst(u32_t seqno, u32_t ackno, 01189 ip_addr_t *local_ip, ip_addr_t *remote_ip, 01190 u16_t local_port, u16_t remote_port) 01191 { 01192 struct pbuf *p; 01193 struct tcp_hdr *tcphdr; 01194 p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM); 01195 if (p == NULL) { 01196 LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n")); 01197 return; 01198 } 01199 LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr", 01200 (p->len >= sizeof(struct tcp_hdr))); 01201 01202 tcphdr = (struct tcp_hdr *)p->payload; 01203 tcphdr->src = htons(local_port); 01204 tcphdr->dest = htons(remote_port); 01205 tcphdr->seqno = htonl(seqno); 01206 tcphdr->ackno = htonl(ackno); 01207 TCPH_HDRLEN_FLAGS_SET(tcphdr, TCP_HLEN/4, TCP_RST | TCP_ACK); 01208 tcphdr->wnd = PP_HTONS(TCP_WND); 01209 tcphdr->chksum = 0; 01210 tcphdr->urgp = 0; 01211 01212 #if CHECKSUM_GEN_TCP 01213 tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip, 01214 IP_PROTO_TCP, p->tot_len); 01215 #endif 01216 TCP_STATS_INC(tcp.xmit); 01217 snmp_inc_tcpoutrsts(); 01218 /* Send output with hardcoded TTL since we have no access to the pcb */ 01219 ip_output(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP); 01220 pbuf_free(p); 01221 LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno)); 01222 } 01223 01231 void 01232 tcp_rexmit_rto(struct tcp_pcb *pcb) 01233 { 01234 struct tcp_seg *seg; 01235 01236 if (pcb->unacked == NULL) { 01237 return; 01238 } 01239 01240 /* Move all unacked segments to the head of the unsent queue */ 01241 for (seg = pcb->unacked; seg->next != NULL; seg = seg->next); 01242 /* concatenate unsent queue after unacked queue */ 01243 seg->next = pcb->unsent; 01244 /* unsent queue is the concatenated queue (of unacked, unsent) */ 01245 pcb->unsent = pcb->unacked; 01246 /* unacked queue is now empty */ 01247 pcb->unacked = NULL; 01248 01249 /* increment number of retransmissions */ 01250 ++pcb->nrtx; 01251 01252 /* Don't take any RTT measurements after retransmitting. */ 01253 pcb->rttest = 0; 01254 01255 /* Do the actual retransmission */ 01256 tcp_output(pcb); 01257 } 01258 01266 void 01267 tcp_rexmit(struct tcp_pcb *pcb) 01268 { 01269 struct tcp_seg *seg; 01270 struct tcp_seg **cur_seg; 01271 01272 if (pcb->unacked == NULL) { 01273 return; 01274 } 01275 01276 /* Move the first unacked segment to the unsent queue */ 01277 /* Keep the unsent queue sorted. */ 01278 seg = pcb->unacked; 01279 pcb->unacked = seg->next; 01280 01281 cur_seg = &(pcb->unsent); 01282 while (*cur_seg && 01283 TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) { 01284 cur_seg = &((*cur_seg)->next ); 01285 } 01286 seg->next = *cur_seg; 01287 *cur_seg = seg; 01288 01289 ++pcb->nrtx; 01290 01291 /* Don't take any rtt measurements after retransmitting. */ 01292 pcb->rttest = 0; 01293 01294 /* Do the actual retransmission. */ 01295 snmp_inc_tcpretranssegs(); 01296 /* No need to call tcp_output: we are always called from tcp_input() 01297 and thus tcp_output directly returns. */ 01298 } 01299 01300 01306 void 01307 tcp_rexmit_fast(struct tcp_pcb *pcb) 01308 { 01309 if (pcb->unacked != NULL && !(pcb->flags & TF_INFR)) { 01310 /* This is fast retransmit. Retransmit the first unacked segment. */ 01311 LWIP_DEBUGF(TCP_FR_DEBUG, 01312 ("tcp_receive: dupacks %"U16_F" (%"U32_F 01313 "), fast retransmit %"U32_F"\n", 01314 (u16_t)pcb->dupacks, pcb->lastack, 01315 ntohl(pcb->unacked->tcphdr->seqno))); 01316 tcp_rexmit(pcb); 01317 01318 /* Set ssthresh to half of the minimum of the current 01319 * cwnd and the advertised window */ 01320 if (pcb->cwnd > pcb->snd_wnd) { 01321 pcb->ssthresh = pcb->snd_wnd / 2; 01322 } else { 01323 pcb->ssthresh = pcb->cwnd / 2; 01324 } 01325 01326 /* The minimum value for ssthresh should be 2 MSS */ 01327 if (pcb->ssthresh < 2*pcb->mss) { 01328 LWIP_DEBUGF(TCP_FR_DEBUG, 01329 ("tcp_receive: The minimum value for ssthresh %"U16_F 01330 " should be min 2 mss %"U16_F"...\n", 01331 pcb->ssthresh, 2*pcb->mss)); 01332 pcb->ssthresh = 2*pcb->mss; 01333 } 01334 01335 pcb->cwnd = pcb->ssthresh + 3 * pcb->mss; 01336 pcb->flags |= TF_INFR; 01337 } 01338 } 01339 01340 01349 void 01350 tcp_keepalive(struct tcp_pcb *pcb) 01351 { 01352 struct pbuf *p; 01353 struct tcp_hdr *tcphdr; 01354 01355 LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", 01356 ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip), 01357 ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip))); 01358 01359 LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", 01360 tcp_ticks, pcb->tmr, pcb->keep_cnt_sent)); 01361 01362 p = tcp_output_alloc_header(pcb, 0, 0, htonl(pcb->snd_nxt - 1)); 01363 if(p == NULL) { 01364 LWIP_DEBUGF(TCP_DEBUG, 01365 ("tcp_keepalive: could not allocate memory for pbuf\n")); 01366 return; 01367 } 01368 tcphdr = (struct tcp_hdr *)p->payload; 01369 01370 #if CHECKSUM_GEN_TCP 01371 tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip, 01372 IP_PROTO_TCP, p->tot_len); 01373 #endif 01374 TCP_STATS_INC(tcp.xmit); 01375 01376 /* Send output to IP */ 01377 #if LWIP_NETIF_HWADDRHINT 01378 ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP, 01379 &(pcb->addr_hint)); 01380 #else /* LWIP_NETIF_HWADDRHINT*/ 01381 ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP); 01382 #endif /* LWIP_NETIF_HWADDRHINT*/ 01383 01384 pbuf_free(p); 01385 01386 LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F".\n", 01387 pcb->snd_nxt - 1, pcb->rcv_nxt)); 01388 } 01389 01390 01399 void 01400 tcp_zero_window_probe(struct tcp_pcb *pcb) 01401 { 01402 struct pbuf *p; 01403 struct tcp_hdr *tcphdr; 01404 struct tcp_seg *seg; 01405 u16_t len; 01406 u8_t is_fin; 01407 01408 LWIP_DEBUGF(TCP_DEBUG, 01409 ("tcp_zero_window_probe: sending ZERO WINDOW probe to %" 01410 U16_F".%"U16_F".%"U16_F".%"U16_F"\n", 01411 ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip), 01412 ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip))); 01413 01414 LWIP_DEBUGF(TCP_DEBUG, 01415 ("tcp_zero_window_probe: tcp_ticks %"U32_F 01416 " pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", 01417 tcp_ticks, pcb->tmr, pcb->keep_cnt_sent)); 01418 01419 seg = pcb->unacked; 01420 01421 if(seg == NULL) { 01422 seg = pcb->unsent; 01423 } 01424 if(seg == NULL) { 01425 return; 01426 } 01427 01428 is_fin = ((TCPH_FLAGS(seg->tcphdr) & TCP_FIN) != 0) && (seg->len == 0); 01429 /* we want to send one seqno: either FIN or data (no options) */ 01430 len = is_fin ? 0 : 1; 01431 01432 p = tcp_output_alloc_header(pcb, 0, len, seg->tcphdr->seqno); 01433 if(p == NULL) { 01434 LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: no memory for pbuf\n")); 01435 return; 01436 } 01437 tcphdr = (struct tcp_hdr *)p->payload; 01438 01439 if (is_fin) { 01440 /* FIN segment, no data */ 01441 TCPH_FLAGS_SET(tcphdr, TCP_ACK | TCP_FIN); 01442 } else { 01443 /* Data segment, copy in one byte from the head of the unacked queue */ 01444 struct tcp_hdr *thdr = (struct tcp_hdr *)seg->p->payload; 01445 char *d = ((char *)p->payload + TCP_HLEN); 01446 pbuf_copy_partial(seg->p, d, 1, TCPH_HDRLEN(thdr) * 4); 01447 } 01448 01449 #if CHECKSUM_GEN_TCP 01450 tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip, 01451 IP_PROTO_TCP, p->tot_len); 01452 #endif 01453 TCP_STATS_INC(tcp.xmit); 01454 01455 /* Send output to IP */ 01456 #if LWIP_NETIF_HWADDRHINT 01457 ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP, 01458 &(pcb->addr_hint)); 01459 #else /* LWIP_NETIF_HWADDRHINT*/ 01460 ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP); 01461 #endif /* LWIP_NETIF_HWADDRHINT*/ 01462 01463 pbuf_free(p); 01464 01465 LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: seqno %"U32_F 01466 " ackno %"U32_F".\n", 01467 pcb->snd_nxt - 1, pcb->rcv_nxt)); 01468 } 01469 #endif /* LWIP_TCP */ Generated on Sat May 26 2012 04:34:59 for ReactOS by
1.7.6.1
|