UbixOS V2 2.0

tcp_out.c
Go to the documentation of this file.
1
9 /*
10 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
11 * All rights reserved.
12 *
13 * Redistribution and use in source and binary forms, with or without modification,
14 * are permitted provided that the following conditions are met:
15 *
16 * 1. Redistributions of source code must retain the above copyright notice,
17 * this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 * 3. The name of the author may not be used to endorse or promote products
22 * derived from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
25 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
27 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
29 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
32 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
33 * OF SUCH DAMAGE.
34 *
35 * This file is part of the lwIP TCP/IP stack.
36 *
37 * Author: Adam Dunkels <adam@sics.se>
38 *
39 */
40
41 #include "net/opt.h"
42
43 #if LWIP_TCP /* don't build if not configured for use in lwipopts.h */
44
45 #include "net/priv/tcp_priv.h"
46 #include "net/def.h"
47 #include "net/mem.h"
48 #include "net/memp.h"
49 #include "net/ip_addr.h"
50 #include "net/netif.h"
51 #include "net/inet_chksum.h"
52 #include "net/stats.h"
53 #include "net/ip6.h"
54 #include "net/ip6_addr.h"
55 #if LWIP_TCP_TIMESTAMPS
56 #include "net/sys.h"
57 #endif
58
59 #include <string.h>
60
61 /* Define some copy-macros for checksum-on-copy so that the code looks
62 nicer by preventing too many ifdef's. */
63 #if TCP_CHECKSUM_ON_COPY
64 #define TCP_DATA_COPY(dst, src, len, seg) do { \
65 tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), \
66 len, &seg->chksum, &seg->chksum_swapped); \
67 seg->flags |= TF_SEG_DATA_CHECKSUMMED; } while(0)
68 #define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) \
69 tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), len, chksum, chksum_swapped);
70 #else /* TCP_CHECKSUM_ON_COPY*/
71 #define TCP_DATA_COPY(dst, src, len, seg) MEMCPY(dst, src, len)
72 #define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) MEMCPY(dst, src, len)
73 #endif /* TCP_CHECKSUM_ON_COPY*/
74
77 #ifndef TCP_CHECKSUM_ON_COPY_SANITY_CHECK
78 #define TCP_CHECKSUM_ON_COPY_SANITY_CHECK 0
79 #endif
80 /* Allow to override the failure of sanity check from warning to e.g. hard failure */
81 #if TCP_CHECKSUM_ON_COPY_SANITY_CHECK
82 #ifndef TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL
83 #define TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL(msg) LWIP_DEBUGF(TCP_DEBUG | LWIP_DBG_LEVEL_WARNING, msg)
84 #endif
85 #endif
86
87 #if TCP_OVERSIZE
88
89 #ifndef TCP_OVERSIZE_CALC_LENGTH
90 #define TCP_OVERSIZE_CALC_LENGTH(length) ((length) + TCP_OVERSIZE)
91 #endif
92 #endif
93
94 /* Forward declarations.*/
95 static err_t tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb, struct netif *netif);
96
107 static struct pbuf *
108 tcp_output_alloc_header(struct tcp_pcb *pcb, u16_t optlen, u16_t datalen,
109 u32_t seqno_be /* already in network byte order */)
110 {
111 struct tcp_hdr *tcphdr;
112 struct pbuf *p = pbuf_alloc(PBUF_IP, TCP_HLEN + optlen + datalen, PBUF_RAM);
113 if (p != NULL) {
114 LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr",
115 (p->len >= TCP_HLEN + optlen));
116 tcphdr = (struct tcp_hdr *)p->payload;
117 tcphdr->src = lwip_htons(pcb->local_port);
118 tcphdr->dest = lwip_htons(pcb->remote_port);
119 tcphdr->seqno = seqno_be;
120 tcphdr->ackno = lwip_htonl(pcb->rcv_nxt);
121 TCPH_HDRLEN_FLAGS_SET(tcphdr, (5 + optlen / 4), TCP_ACK);
122 tcphdr->wnd = lwip_htons(TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd)));
123 tcphdr->chksum = 0;
124 tcphdr->urgp = 0;
125
126 /* If we're sending a packet, update the announced right window edge */
127 pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
128 }
129 return p;
130 }
131
138 err_t
139 tcp_send_fin(struct tcp_pcb *pcb)
140 {
141 /* first, try to add the fin to the last unsent segment */
142 if (pcb->unsent != NULL) {
143 struct tcp_seg *last_unsent;
144 for (last_unsent = pcb->unsent; last_unsent->next != NULL;
145 last_unsent = last_unsent->next);
146
147 if ((TCPH_FLAGS(last_unsent->tcphdr) & (TCP_SYN | TCP_FIN | TCP_RST)) == 0) {
148 /* no SYN/FIN/RST flag in the header, we can add the FIN flag */
149 TCPH_SET_FLAG(last_unsent->tcphdr, TCP_FIN);
150 pcb->flags |= TF_FIN;
151 return ERR_OK;
152 }
153 }
154 /* no data, no length, flags, copy=1, no optdata */
155 return tcp_enqueue_flags(pcb, TCP_FIN);
156 }
157
172 static struct tcp_seg *
173 tcp_create_segment(struct tcp_pcb *pcb, struct pbuf *p, u8_t flags, u32_t seqno, u8_t optflags)
174 {
175 struct tcp_seg *seg;
176 u8_t optlen = LWIP_TCP_OPT_LENGTH(optflags);
177
178 if ((seg = (struct tcp_seg *)memp_malloc(MEMP_TCP_SEG)) == NULL) {
179 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_create_segment: no memory.\n"));
180 pbuf_free(p);
181 return NULL;
182 }
183 seg->flags = optflags;
184 seg->next = NULL;
185 seg->p = p;
186 LWIP_ASSERT("p->tot_len >= optlen", p->tot_len >= optlen);
187 seg->len = p->tot_len - optlen;
188 #if TCP_OVERSIZE_DBGCHECK
189 seg->oversize_left = 0;
190 #endif /* TCP_OVERSIZE_DBGCHECK */
191 #if TCP_CHECKSUM_ON_COPY
192 seg->chksum = 0;
193 seg->chksum_swapped = 0;
194 /* check optflags */
195 LWIP_ASSERT("invalid optflags passed: TF_SEG_DATA_CHECKSUMMED",
196 (optflags & TF_SEG_DATA_CHECKSUMMED) == 0);
197 #endif /* TCP_CHECKSUM_ON_COPY */
198
199 /* build TCP header */
200 if (pbuf_header(p, TCP_HLEN)) {
201 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_create_segment: no room for TCP header in pbuf.\n"));
202 TCP_STATS_INC(tcp.err);
203 tcp_seg_free(seg);
204 return NULL;
205 }
206 seg->tcphdr = (struct tcp_hdr *)seg->p->payload;
207 seg->tcphdr->src = lwip_htons(pcb->local_port);
208 seg->tcphdr->dest = lwip_htons(pcb->remote_port);
209 seg->tcphdr->seqno = lwip_htonl(seqno);
210 /* ackno is set in tcp_output */
211 TCPH_HDRLEN_FLAGS_SET(seg->tcphdr, (5 + optlen / 4), flags);
212 /* wnd and chksum are set in tcp_output */
213 seg->tcphdr->urgp = 0;
214 return seg;
215 }
216
231 #if TCP_OVERSIZE
232 static struct pbuf *
233 tcp_pbuf_prealloc(pbuf_layer layer, u16_t length, u16_t max_length,
234 u16_t *oversize, struct tcp_pcb *pcb, u8_t apiflags,
235 u8_t first_seg)
236 {
237 struct pbuf *p;
238 u16_t alloc = length;
239
240 #if LWIP_NETIF_TX_SINGLE_PBUF
241 LWIP_UNUSED_ARG(max_length);
242 LWIP_UNUSED_ARG(pcb);
243 LWIP_UNUSED_ARG(apiflags);
244 LWIP_UNUSED_ARG(first_seg);
245 alloc = max_length;
246 #else /* LWIP_NETIF_TX_SINGLE_PBUF */
247 if (length < max_length) {
248 /* Should we allocate an oversized pbuf, or just the minimum
249 * length required? If tcp_write is going to be called again
250 * before this segment is transmitted, we want the oversized
251 * buffer. If the segment will be transmitted immediately, we can
252 * save memory by allocating only length. We use a simple
253 * heuristic based on the following information:
254 *
255 * Did the user set TCP_WRITE_FLAG_MORE?
256 *
257 * Will the Nagle algorithm defer transmission of this segment?
258 */
259 if ((apiflags & TCP_WRITE_FLAG_MORE) ||
260 (!(pcb->flags & TF_NODELAY) &&
261 (!first_seg ||
262 pcb->unsent != NULL ||
263 pcb->unacked != NULL))) {
264 alloc = LWIP_MIN(max_length, LWIP_MEM_ALIGN_SIZE(TCP_OVERSIZE_CALC_LENGTH(length)));
265 }
266 }
267 #endif /* LWIP_NETIF_TX_SINGLE_PBUF */
268 p = pbuf_alloc(layer, alloc, PBUF_RAM);
269 if (p == NULL) {
270 return NULL;
271 }
272 LWIP_ASSERT("need unchained pbuf", p->next == NULL);
273 *oversize = p->len - length;
274 /* trim p->len to the currently used size */
275 p->len = p->tot_len = length;
276 return p;
277 }
278 #else /* TCP_OVERSIZE */
279 #define tcp_pbuf_prealloc(layer, length, mx, os, pcb, api, fst) pbuf_alloc((layer), (length), PBUF_RAM)
280 #endif /* TCP_OVERSIZE */
281
282 #if TCP_CHECKSUM_ON_COPY
283
284 static void
285 tcp_seg_add_chksum(u16_t chksum, u16_t len, u16_t *seg_chksum,
286 u8_t *seg_chksum_swapped)
287 {
288 u32_t helper;
289 /* add chksum to old chksum and fold to u16_t */
290 helper = chksum + *seg_chksum;
291 chksum = FOLD_U32T(helper);
292 if ((len & 1) != 0) {
293 *seg_chksum_swapped = 1 - *seg_chksum_swapped;
294 chksum = SWAP_BYTES_IN_WORD(chksum);
295 }
296 *seg_chksum = chksum;
297 }
298 #endif /* TCP_CHECKSUM_ON_COPY */
299
306 static err_t
307 tcp_write_checks(struct tcp_pcb *pcb, u16_t len)
308 {
309 /* connection is in invalid state for data transmission? */
310 if ((pcb->state != ESTABLISHED) &&
311 (pcb->state != CLOSE_WAIT) &&
312 (pcb->state != SYN_SENT) &&
313 (pcb->state != SYN_RCVD)) {
314 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_STATE | LWIP_DBG_LEVEL_SEVERE, ("tcp_write() called in invalid state\n"));
315 return ERR_CONN;
316 } else if (len == 0) {
317 return ERR_OK;
318 }
319
320 /* fail on too much data */
321 if (len > pcb->snd_buf) {
322 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("tcp_write: too much data (len=%"U16_F" > snd_buf=%"TCPWNDSIZE_F")\n",
323 len, pcb->snd_buf));
324 pcb->flags |= TF_NAGLEMEMERR;
325 return ERR_MEM;
326 }
327
328 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: queuelen: %"TCPWNDSIZE_F"\n", (tcpwnd_size_t)pcb->snd_queuelen));
329
330 /* If total number of pbufs on the unsent/unacked queues exceeds the
331 * configured maximum, return an error */
332 /* check for configured max queuelen and possible overflow */
333 if ((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
334 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("tcp_write: too long queue %"U16_F" (max %"U16_F")\n",
335 pcb->snd_queuelen, (u16_t)TCP_SND_QUEUELEN));
336 TCP_STATS_INC(tcp.memerr);
337 pcb->flags |= TF_NAGLEMEMERR;
338 return ERR_MEM;
339 }
340 if (pcb->snd_queuelen != 0) {
341 LWIP_ASSERT("tcp_write: pbufs on queue => at least one queue non-empty",
342 pcb->unacked != NULL || pcb->unsent != NULL);
343 } else {
344 LWIP_ASSERT("tcp_write: no pbufs on queue => both queues empty",
345 pcb->unacked == NULL && pcb->unsent == NULL);
346 }
347 return ERR_OK;
348 }
349
367 err_t
368 tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
369 {
370 struct pbuf *concat_p = NULL;
371 struct tcp_seg *last_unsent = NULL, *seg = NULL, *prev_seg = NULL, *queue = NULL;
372 u16_t pos = 0; /* position in 'arg' data */
373 u16_t queuelen;
374 u8_t optlen = 0;
375 u8_t optflags = 0;
376 #if TCP_OVERSIZE
377 u16_t oversize = 0;
378 u16_t oversize_used = 0;
379 #if TCP_OVERSIZE_DBGCHECK
380 u16_t oversize_add = 0;
381 #endif /* TCP_OVERSIZE_DBGCHECK*/
382 #endif /* TCP_OVERSIZE */
383 u16_t extendlen = 0;
384 #if TCP_CHECKSUM_ON_COPY
385 u16_t concat_chksum = 0;
386 u8_t concat_chksum_swapped = 0;
387 u16_t concat_chksummed = 0;
388 #endif /* TCP_CHECKSUM_ON_COPY */
389 err_t err;
390 /* don't allocate segments bigger than half the maximum window we ever received */
391 u16_t mss_local = LWIP_MIN(pcb->mss, TCPWND_MIN16(pcb->snd_wnd_max/2));
392 mss_local = mss_local ? mss_local : pcb->mss;
393
394 #if LWIP_NETIF_TX_SINGLE_PBUF
395 /* Always copy to try to create single pbufs for TX */
396 apiflags |= TCP_WRITE_FLAG_COPY;
397 #endif /* LWIP_NETIF_TX_SINGLE_PBUF */
398
399 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, data=%p, len=%"U16_F", apiflags=%"U16_F")\n",
400 (void *)pcb, arg, len, (u16_t)apiflags));
401 LWIP_ERROR("tcp_write: arg == NULL (programmer violates API)",
402 arg != NULL, return ERR_ARG;);
403
404 err = tcp_write_checks(pcb, len);
405 if (err != ERR_OK) {
406 return err;
407 }
408 queuelen = pcb->snd_queuelen;
409
410 #if LWIP_TCP_TIMESTAMPS
411 if ((pcb->flags & TF_TIMESTAMP)) {
412 /* Make sure the timestamp option is only included in data segments if we
413 agreed about it with the remote host. */
414 optflags = TF_SEG_OPTS_TS;
415 optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS);
416 /* ensure that segments can hold at least one data byte... */
417 mss_local = LWIP_MAX(mss_local, LWIP_TCP_OPT_LEN_TS + 1);
418 }
419 #endif /* LWIP_TCP_TIMESTAMPS */
420
421
422 /*
423 * TCP segmentation is done in three phases with increasing complexity:
424 *
425 * 1. Copy data directly into an oversized pbuf.
426 * 2. Chain a new pbuf to the end of pcb->unsent.
427 * 3. Create new segments.
428 *
429 * We may run out of memory at any point. In that case we must
430 * return ERR_MEM and not change anything in pcb. Therefore, all
431 * changes are recorded in local variables and committed at the end
432 * of the function. Some pcb fields are maintained in local copies:
433 *
434 * queuelen = pcb->snd_queuelen
435 * oversize = pcb->unsent_oversize
436 *
437 * These variables are set consistently by the phases:
438 *
439 * seg points to the last segment tampered with.
440 *
441 * pos records progress as data is segmented.
442 */
443
444 /* Find the tail of the unsent queue. */
445 if (pcb->unsent != NULL) {
446 u16_t space;
447 u16_t unsent_optlen;
448
449 /* @todo: this could be sped up by keeping last_unsent in the pcb */
450 for (last_unsent = pcb->unsent; last_unsent->next != NULL;
451 last_unsent = last_unsent->next);
452
453 /* Usable space at the end of the last unsent segment */
454 unsent_optlen = LWIP_TCP_OPT_LENGTH(last_unsent->flags);
455 LWIP_ASSERT("mss_local is too small", mss_local >= last_unsent->len + unsent_optlen);
456 space = mss_local - (last_unsent->len + unsent_optlen);
457
458 /*
459 * Phase 1: Copy data directly into an oversized pbuf.
460 *
461 * The number of bytes copied is recorded in the oversize_used
462 * variable. The actual copying is done at the bottom of the
463 * function.
464 */
465 #if TCP_OVERSIZE
466 #if TCP_OVERSIZE_DBGCHECK
467 /* check that pcb->unsent_oversize matches last_unsent->oversize_left */
468 LWIP_ASSERT("unsent_oversize mismatch (pcb vs. last_unsent)",
469 pcb->unsent_oversize == last_unsent->oversize_left);
470 #endif /* TCP_OVERSIZE_DBGCHECK */
471 oversize = pcb->unsent_oversize;
472 if (oversize > 0) {
473 LWIP_ASSERT("inconsistent oversize vs. space", oversize <= space);
474 seg = last_unsent;
475 oversize_used = LWIP_MIN(space, LWIP_MIN(oversize, len));
476 pos += oversize_used;
477 oversize -= oversize_used;
478 space -= oversize_used;
479 }
480 /* now we are either finished or oversize is zero */
481 LWIP_ASSERT("inconsistent oversize vs. len", (oversize == 0) || (pos == len));
482 #endif /* TCP_OVERSIZE */
483
484 /*
485 * Phase 2: Chain a new pbuf to the end of pcb->unsent.
486 *
487 * As an exception when NOT copying the data, if the given data buffer
488 * directly follows the last unsent data buffer in memory, extend the last
489 * ROM pbuf reference to the buffer, thus saving a ROM pbuf allocation.
490 *
491 * We don't extend segments containing SYN/FIN flags or options
492 * (len==0). The new pbuf is kept in concat_p and pbuf_cat'ed at
493 * the end.
494 */
495 if ((pos < len) && (space > 0) && (last_unsent->len > 0)) {
496 u16_t seglen = LWIP_MIN(space, len - pos);
497 seg = last_unsent;
498
499 /* Create a pbuf with a copy or reference to seglen bytes. We
500 * can use PBUF_RAW here since the data appears in the middle of
501 * a segment. A header will never be prepended. */
502 if (apiflags & TCP_WRITE_FLAG_COPY) {
503 /* Data is copied */
504 if ((concat_p = tcp_pbuf_prealloc(PBUF_RAW, seglen, space, &oversize, pcb, apiflags, 1)) == NULL) {
505 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
506 ("tcp_write : could not allocate memory for pbuf copy size %"U16_F"\n",
507 seglen));
508 goto memerr;
509 }
510 #if TCP_OVERSIZE_DBGCHECK
511 oversize_add = oversize;
512 #endif /* TCP_OVERSIZE_DBGCHECK */
513 TCP_DATA_COPY2(concat_p->payload, (const u8_t*)arg + pos, seglen, &concat_chksum, &concat_chksum_swapped);
514 #if TCP_CHECKSUM_ON_COPY
515 concat_chksummed += seglen;
516 #endif /* TCP_CHECKSUM_ON_COPY */
517 queuelen += pbuf_clen(concat_p);
518 } else {
519 /* Data is not copied */
520 /* If the last unsent pbuf is of type PBUF_ROM, try to extend it. */
521 struct pbuf *p;
522 for (p = last_unsent->p; p->next != NULL; p = p->next);
523 if (p->type == PBUF_ROM && (const u8_t *)p->payload + p->len == (const u8_t *)arg) {
524 LWIP_ASSERT("tcp_write: ROM pbufs cannot be oversized", pos == 0);
525 extendlen = seglen;
526 } else {
527 if ((concat_p = pbuf_alloc(PBUF_RAW, seglen, PBUF_ROM)) == NULL) {
528 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
529 ("tcp_write: could not allocate memory for zero-copy pbuf\n"));
530 goto memerr;
531 }
532 /* reference the non-volatile payload data */
533 ((struct pbuf_rom*)concat_p)->payload = (const u8_t*)arg + pos;
534 queuelen += pbuf_clen(concat_p);
535 }
536 #if TCP_CHECKSUM_ON_COPY
537 /* calculate the checksum of nocopy-data */
538 tcp_seg_add_chksum(~inet_chksum((const u8_t*)arg + pos, seglen), seglen,
539 &concat_chksum, &concat_chksum_swapped);
540 concat_chksummed += seglen;
541 #endif /* TCP_CHECKSUM_ON_COPY */
542 }
543
544 pos += seglen;
545 }
546 } else {
547 #if TCP_OVERSIZE
548 LWIP_ASSERT("unsent_oversize mismatch (pcb->unsent is NULL)",
549 pcb->unsent_oversize == 0);
550 #endif /* TCP_OVERSIZE */
551 }
552
553 /*
554 * Phase 3: Create new segments.
555 *
556 * The new segments are chained together in the local 'queue'
557 * variable, ready to be appended to pcb->unsent.
558 */
559 while (pos < len) {
560 struct pbuf *p;
561 u16_t left = len - pos;
562 u16_t max_len = mss_local - optlen;
563 u16_t seglen = LWIP_MIN(left, max_len);
564 #if TCP_CHECKSUM_ON_COPY
565 u16_t chksum = 0;
566 u8_t chksum_swapped = 0;
567 #endif /* TCP_CHECKSUM_ON_COPY */
568
569 if (apiflags & TCP_WRITE_FLAG_COPY) {
570 /* If copy is set, memory should be allocated and data copied
571 * into pbuf */
572 if ((p = tcp_pbuf_prealloc(PBUF_TRANSPORT, seglen + optlen, mss_local, &oversize, pcb, apiflags, queue == NULL)) == NULL) {
573 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write : could not allocate memory for pbuf copy size %"U16_F"\n", seglen));
574 goto memerr;
575 }
576 LWIP_ASSERT("tcp_write: check that first pbuf can hold the complete seglen",
577 (p->len >= seglen));
578 TCP_DATA_COPY2((char *)p->payload + optlen, (const u8_t*)arg + pos, seglen, &chksum, &chksum_swapped);
579 } else {
580 /* Copy is not set: First allocate a pbuf for holding the data.
581 * Since the referenced data is available at least until it is
582 * sent out on the link (as it has to be ACKed by the remote
583 * party) we can safely use PBUF_ROM instead of PBUF_REF here.
584 */
585 struct pbuf *p2;
586 #if TCP_OVERSIZE
587 LWIP_ASSERT("oversize == 0", oversize == 0);
588 #endif /* TCP_OVERSIZE */
589 if ((p2 = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_ROM)) == NULL) {
590 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write: could not allocate memory for zero-copy pbuf\n"));
591 goto memerr;
592 }
593 #if TCP_CHECKSUM_ON_COPY
594 /* calculate the checksum of nocopy-data */
595 chksum = ~inet_chksum((const u8_t*)arg + pos, seglen);
596 if (seglen & 1) {
597 chksum_swapped = 1;
598 chksum = SWAP_BYTES_IN_WORD(chksum);
599 }
600 #endif /* TCP_CHECKSUM_ON_COPY */
601 /* reference the non-volatile payload data */
602 ((struct pbuf_rom*)p2)->payload = (const u8_t*)arg + pos;
603
604 /* Second, allocate a pbuf for the headers. */
605 if ((p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
606 /* If allocation fails, we have to deallocate the data pbuf as
607 * well. */
608 pbuf_free(p2);
609 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write: could not allocate memory for header pbuf\n"));
610 goto memerr;
611 }
612 /* Concatenate the headers and data pbufs together. */
613 pbuf_cat(p/*header*/, p2/*data*/);
614 }
615
616 queuelen += pbuf_clen(p);
617
618 /* Now that there are more segments queued, we check again if the
619 * length of the queue exceeds the configured maximum or
620 * overflows. */
621 if ((queuelen > TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
622 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write: queue too long %"U16_F" (%d)\n",
623 queuelen, (int)TCP_SND_QUEUELEN));
624 pbuf_free(p);
625 goto memerr;
626 }
627
628 if ((seg = tcp_create_segment(pcb, p, 0, pcb->snd_lbb + pos, optflags)) == NULL) {
629 goto memerr;
630 }
631 #if TCP_OVERSIZE_DBGCHECK
632 seg->oversize_left = oversize;
633 #endif /* TCP_OVERSIZE_DBGCHECK */
634 #if TCP_CHECKSUM_ON_COPY
635 seg->chksum = chksum;
636 seg->chksum_swapped = chksum_swapped;
637 seg->flags |= TF_SEG_DATA_CHECKSUMMED;
638 #endif /* TCP_CHECKSUM_ON_COPY */
639
640 /* first segment of to-be-queued data? */
641 if (queue == NULL) {
642 queue = seg;
643 } else {
644 /* Attach the segment to the end of the queued segments */
645 LWIP_ASSERT("prev_seg != NULL", prev_seg != NULL);
646 prev_seg->next = seg;
647 }
648 /* remember last segment of to-be-queued data for next iteration */
649 prev_seg = seg;
650
651 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, ("tcp_write: queueing %"U32_F":%"U32_F"\n",
652 lwip_ntohl(seg->tcphdr->seqno),
653 lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg)));
654
655 pos += seglen;
656 }
657
658 /*
659 * All three segmentation phases were successful. We can commit the
660 * transaction.
661 */
662 #if TCP_OVERSIZE_DBGCHECK
663 if ((last_unsent != NULL) && (oversize_add != 0)) {
664 last_unsent->oversize_left += oversize_add;
665 }
666 #endif /* TCP_OVERSIZE_DBGCHECK */
667
668 /*
669 * Phase 1: If data has been added to the preallocated tail of
670 * last_unsent, we update the length fields of the pbuf chain.
671 */
672 #if TCP_OVERSIZE
673 if (oversize_used > 0) {
674 struct pbuf *p;
675 /* Bump tot_len of whole chain, len of tail */
676 for (p = last_unsent->p; p; p = p->next) {
677 p->tot_len += oversize_used;
678 if (p->next == NULL) {
679 TCP_DATA_COPY((char *)p->payload + p->len, arg, oversize_used, last_unsent);
680 p->len += oversize_used;
681 }
682 }
683 last_unsent->len += oversize_used;
684 #if TCP_OVERSIZE_DBGCHECK
685 LWIP_ASSERT("last_unsent->oversize_left >= oversize_used",
686 last_unsent->oversize_left >= oversize_used);
687 last_unsent->oversize_left -= oversize_used;
688 #endif /* TCP_OVERSIZE_DBGCHECK */
689 }
690 pcb->unsent_oversize = oversize;
691 #endif /* TCP_OVERSIZE */
692
693 /*
694 * Phase 2: concat_p can be concatenated onto last_unsent->p, unless we
695 * determined that the last ROM pbuf can be extended to include the new data.
696 */
697 if (concat_p != NULL) {
698 LWIP_ASSERT("tcp_write: cannot concatenate when pcb->unsent is empty",
699 (last_unsent != NULL));
700 pbuf_cat(last_unsent->p, concat_p);
701 last_unsent->len += concat_p->tot_len;
702 } else if (extendlen > 0) {
703 struct pbuf *p;
704 LWIP_ASSERT("tcp_write: extension of reference requires reference",
705 last_unsent != NULL && last_unsent->p != NULL);
706 for (p = last_unsent->p; p->next != NULL; p = p->next) {
707 p->tot_len += extendlen;
708 }
709 p->tot_len += extendlen;
710 p->len += extendlen;
711 last_unsent->len += extendlen;
712 }
713
714 #if TCP_CHECKSUM_ON_COPY
715 if (concat_chksummed) {
716 LWIP_ASSERT("tcp_write: concat checksum needs concatenated data",
717 concat_p != NULL || extendlen > 0);
718 /*if concat checksumm swapped - swap it back */
719 if (concat_chksum_swapped) {
720 concat_chksum = SWAP_BYTES_IN_WORD(concat_chksum);
721 }
722 tcp_seg_add_chksum(concat_chksum, concat_chksummed, &last_unsent->chksum,
723 &last_unsent->chksum_swapped);
724 last_unsent->flags |= TF_SEG_DATA_CHECKSUMMED;
725 }
726 #endif /* TCP_CHECKSUM_ON_COPY */
727
728 /*
729 * Phase 3: Append queue to pcb->unsent. Queue may be NULL, but that
730 * is harmless
731 */
732 if (last_unsent == NULL) {
733 pcb->unsent = queue;
734 } else {
735 last_unsent->next = queue;
736 }
737
738 /*
739 * Finally update the pcb state.
740 */
741 pcb->snd_lbb += len;
742 pcb->snd_buf -= len;
743 pcb->snd_queuelen = queuelen;
744
745 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: %"S16_F" (after enqueued)\n",
746 pcb->snd_queuelen));
747 if (pcb->snd_queuelen != 0) {
748 LWIP_ASSERT("tcp_write: valid queue length",
749 pcb->unacked != NULL || pcb->unsent != NULL);
750 }
751
752 /* Set the PSH flag in the last segment that we enqueued. */
753 if (seg != NULL && seg->tcphdr != NULL && ((apiflags & TCP_WRITE_FLAG_MORE)==0)) {
754 TCPH_SET_FLAG(seg->tcphdr, TCP_PSH);
755 }
756
757 return ERR_OK;
758 memerr:
759 pcb->flags |= TF_NAGLEMEMERR;
760 TCP_STATS_INC(tcp.memerr);
761
762 if (concat_p != NULL) {
763 pbuf_free(concat_p);
764 }
765 if (queue != NULL) {
766 tcp_segs_free(queue);
767 }
768 if (pcb->snd_queuelen != 0) {
769 LWIP_ASSERT("tcp_write: valid queue length", pcb->unacked != NULL ||
770 pcb->unsent != NULL);
771 }
772 LWIP_DEBUGF(TCP_QLEN_DEBUG | LWIP_DBG_STATE, ("tcp_write: %"S16_F" (with mem err)\n", pcb->snd_queuelen));
773 return ERR_MEM;
774 }
775
784 err_t
785 tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags)
786 {
787 struct pbuf *p;
788 struct tcp_seg *seg;
789 u8_t optflags = 0;
790 u8_t optlen = 0;
791
792 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen));
793
794 LWIP_ASSERT("tcp_enqueue_flags: need either TCP_SYN or TCP_FIN in flags (programmer violates API)",
795 (flags & (TCP_SYN | TCP_FIN)) != 0);
796
797 /* check for configured max queuelen and possible overflow (FIN flag should always come through!) */
798 if (((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) &&
799 ((flags & TCP_FIN) == 0)) {
800 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("tcp_enqueue_flags: too long queue %"U16_F" (max %"U16_F")\n",
801 pcb->snd_queuelen, (u16_t)TCP_SND_QUEUELEN));
802 TCP_STATS_INC(tcp.memerr);
803 pcb->flags |= TF_NAGLEMEMERR;
804 return ERR_MEM;
805 }
806
807 if (flags & TCP_SYN) {
808 optflags = TF_SEG_OPTS_MSS;
809 #if LWIP_WND_SCALE
810 if ((pcb->state != SYN_RCVD) || (pcb->flags & TF_WND_SCALE)) {
811 /* In a <SYN,ACK> (sent in state SYN_RCVD), the window scale option may only
812 be sent if we received a window scale option from the remote host. */
813 optflags |= TF_SEG_OPTS_WND_SCALE;
814 }
815 #endif /* LWIP_WND_SCALE */
816 }
817 #if LWIP_TCP_TIMESTAMPS
818 if ((pcb->flags & TF_TIMESTAMP)) {
819 /* Make sure the timestamp option is only included in data segments if we
820 agreed about it with the remote host. */
821 optflags |= TF_SEG_OPTS_TS;
822 }
823 #endif /* LWIP_TCP_TIMESTAMPS */
824 optlen = LWIP_TCP_OPT_LENGTH(optflags);
825
826 /* Allocate pbuf with room for TCP header + options */
827 if ((p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
828 pcb->flags |= TF_NAGLEMEMERR;
829 TCP_STATS_INC(tcp.memerr);
830 return ERR_MEM;
831 }
832 LWIP_ASSERT("tcp_enqueue_flags: check that first pbuf can hold optlen",
833 (p->len >= optlen));
834
835 /* Allocate memory for tcp_seg, and fill in fields. */
836 if ((seg = tcp_create_segment(pcb, p, flags, pcb->snd_lbb, optflags)) == NULL) {
837 pcb->flags |= TF_NAGLEMEMERR;
838 TCP_STATS_INC(tcp.memerr);
839 return ERR_MEM;
840 }
841 LWIP_ASSERT("seg->tcphdr not aligned", ((mem_ptr_t)seg->tcphdr % LWIP_MIN(MEM_ALIGNMENT, 4)) == 0);
842 LWIP_ASSERT("tcp_enqueue_flags: invalid segment length", seg->len == 0);
843
844 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE,
845 ("tcp_enqueue_flags: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n",
846 lwip_ntohl(seg->tcphdr->seqno),
847 lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
848 (u16_t)flags));
849
850 /* Now append seg to pcb->unsent queue */
851 if (pcb->unsent == NULL) {
852 pcb->unsent = seg;
853 } else {
854 struct tcp_seg *useg;
855 for (useg = pcb->unsent; useg->next != NULL; useg = useg->next);
856 useg->next = seg;
857 }
858 #if TCP_OVERSIZE
859 /* The new unsent tail has no space */
860 pcb->unsent_oversize = 0;
861 #endif /* TCP_OVERSIZE */
862
863 /* SYN and FIN bump the sequence number */
864 if ((flags & TCP_SYN) || (flags & TCP_FIN)) {
865 pcb->snd_lbb++;
866 /* optlen does not influence snd_buf */
867 }
868 if (flags & TCP_FIN) {
869 pcb->flags |= TF_FIN;
870 }
871
872 /* update number of segments on the queues */
873 pcb->snd_queuelen += pbuf_clen(seg->p);
874 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: %"S16_F" (after enqueued)\n", pcb->snd_queuelen));
875 if (pcb->snd_queuelen != 0) {
876 LWIP_ASSERT("tcp_enqueue_flags: invalid queue length",
877 pcb->unacked != NULL || pcb->unsent != NULL);
878 }
879
880 return ERR_OK;
881 }
882
883 #if LWIP_TCP_TIMESTAMPS
884 /* Build a timestamp option (12 bytes long) at the specified options pointer)
885 *
886 * @param pcb tcp_pcb
887 * @param opts option pointer where to store the timestamp option
888 */
889 static void
890 tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts)
891 {
892 /* Pad with two NOP options to make everything nicely aligned */
893 opts[0] = PP_HTONL(0x0101080A);
894 opts[1] = lwip_htonl(sys_now());
895 opts[2] = lwip_htonl(pcb->ts_recent);
896 }
897 #endif
898
899 #if LWIP_WND_SCALE
900
904 static void
905 tcp_build_wnd_scale_option(u32_t *opts)
906 {
907 /* Pad with one NOP option to make everything nicely aligned */
908 opts[0] = PP_HTONL(0x01030300 | TCP_RCV_SCALE);
909 }
910 #endif
911
917 err_t
918 tcp_send_empty_ack(struct tcp_pcb *pcb)
919 {
920 err_t err;
921 struct pbuf *p;
922 u8_t optlen = 0;
923 struct netif *netif;
924 #if LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP
925 struct tcp_hdr *tcphdr;
926 #endif /* LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP */
927
928 #if LWIP_TCP_TIMESTAMPS
929 if (pcb->flags & TF_TIMESTAMP) {
930 optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS);
931 }
932 #endif
933
934 p = tcp_output_alloc_header(pcb, optlen, 0, lwip_htonl(pcb->snd_nxt));
935 if (p == NULL) {
936 /* let tcp_fasttmr retry sending this ACK */
937 pcb->flags |= (TF_ACK_DELAY | TF_ACK_NOW);
938 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n"));
939 return ERR_BUF;
940 }
941 #if LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP
942 tcphdr = (struct tcp_hdr *)p->payload;
943 #endif /* LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP */
944 LWIP_DEBUGF(TCP_OUTPUT_DEBUG,
945 ("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt));
946
947 /* NB. MSS and window scale options are only sent on SYNs, so ignore them here */
948 #if LWIP_TCP_TIMESTAMPS
949 pcb->ts_lastacksent = pcb->rcv_nxt;
950
951 if (pcb->flags & TF_TIMESTAMP) {
952 tcp_build_timestamp_option(pcb, (u32_t *)(tcphdr + 1));
953 }
954 #endif
955
956 netif = ip_route(&pcb->local_ip, &pcb->remote_ip);
957 if (netif == NULL) {
958 err = ERR_RTE;
959 } else {
960 #if CHECKSUM_GEN_TCP
961 IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) {
962 tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len,
963 &pcb->local_ip, &pcb->remote_ip);
964 }
965 #endif
966 NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint));
967 err = ip_output_if(p, &pcb->local_ip, &pcb->remote_ip,
968 pcb->ttl, pcb->tos, IP_PROTO_TCP, netif);
969 NETIF_SET_HWADDRHINT(netif, NULL);
970 }
971 pbuf_free(p);
972
973 if (err != ERR_OK) {
974 /* let tcp_fasttmr retry sending this ACK */
975 pcb->flags |= (TF_ACK_DELAY | TF_ACK_NOW);
976 } else {
977 /* remove ACK flags from the PCB, as we sent an empty ACK now */
978 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
979 }
980
981 return err;
982 }
983
992 err_t
993 tcp_output(struct tcp_pcb *pcb)
994 {
995 struct tcp_seg *seg, *useg;
996 u32_t wnd, snd_nxt;
997 err_t err;
998 struct netif *netif;
999 #if TCP_CWND_DEBUG
1000 s16_t i = 0;
1001 #endif /* TCP_CWND_DEBUG */
1002
1003 /* pcb->state LISTEN not allowed here */
1004 LWIP_ASSERT("don't call tcp_output for listen-pcbs",
1005 pcb->state != LISTEN);
1006
1007 /* First, check if we are invoked by the TCP input processing
1008 code. If so, we do not output anything. Instead, we rely on the
1009 input processing code to call us when input processing is done
1010 with. */
1011 if (tcp_input_pcb == pcb) {
1012 return ERR_OK;
1013 }
1014
1015 wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd);
1016
1017 seg = pcb->unsent;
1018
1019 /* If the TF_ACK_NOW flag is set and no data will be sent (either
1020 * because the ->unsent queue is empty or because the window does
1021 * not allow it), construct an empty ACK segment and send it.
1022 *
1023 * If data is to be sent, we will just piggyback the ACK (see below).
1024 */
1025 if (pcb->flags & TF_ACK_NOW &&
1026 (seg == NULL ||
1027 lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
1028 return tcp_send_empty_ack(pcb);
1029 }
1030
1031 /* useg should point to last segment on unacked queue */
1032 useg = pcb->unacked;
1033 if (useg != NULL) {
1034 for (; useg->next != NULL; useg = useg->next);
1035 }
1036
1037 netif = ip_route(&pcb->local_ip, &pcb->remote_ip);
1038 if (netif == NULL) {
1039 return ERR_RTE;
1040 }
1041
1042 /* If we don't have a local IP address, we get one from netif */
1043 if (ip_addr_isany(&pcb->local_ip)) {
1044 const ip_addr_t *local_ip = ip_netif_get_local_ip(netif, &pcb->remote_ip);
1045 if (local_ip == NULL) {
1046 return ERR_RTE;
1047 }
1048 ip_addr_copy(pcb->local_ip, *local_ip);
1049 }
1050
1051 #if TCP_OUTPUT_DEBUG
1052 if (seg == NULL) {
1053 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n",
1054 (void*)pcb->unsent));
1055 }
1056 #endif /* TCP_OUTPUT_DEBUG */
1057 #if TCP_CWND_DEBUG
1058 if (seg == NULL) {
1059 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"TCPWNDSIZE_F
1060 ", cwnd %"TCPWNDSIZE_F", wnd %"U32_F
1061 ", seg == NULL, ack %"U32_F"\n",
1062 pcb->snd_wnd, pcb->cwnd, wnd, pcb->lastack));
1063 } else {
1064 LWIP_DEBUGF(TCP_CWND_DEBUG,
1065 ("tcp_output: snd_wnd %"TCPWNDSIZE_F", cwnd %"TCPWNDSIZE_F", wnd %"U32_F
1066 ", effwnd %"U32_F", seq %"U32_F", ack %"U32_F"\n",
1067 pcb->snd_wnd, pcb->cwnd, wnd,
1068 lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len,
1069 lwip_ntohl(seg->tcphdr->seqno), pcb->lastack));
1070 }
1071 #endif /* TCP_CWND_DEBUG */
1072 /* Check if we need to start the persistent timer when the next unsent segment
1073 * does not fit within the remaining send window and RTO timer is not running (we
1074 * have no in-flight data). A traditional approach would fill the remaining window
1075 * with part of the unsent segment (which will engage zero-window probing upon
1076 * reception of the zero window update from the receiver). This ensures the
1077 * subsequent window update is reliably received. With the goal of being lightweight,
1078 * we avoid splitting the unsent segment and treat the window as already zero.
1079 */
1080 if (seg != NULL &&
1081 lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd &&
1082 wnd > 0 && wnd == pcb->snd_wnd && pcb->unacked == NULL) {
1083 /* Start the persist timer */
1084 if (pcb->persist_backoff == 0) {
1085 pcb->persist_cnt = 0;
1086 pcb->persist_backoff = 1;
1087 }
1088 goto output_done;
1089 }
1090 /* data available and window allows it to be sent? */
1091 while (seg != NULL &&
1092 lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
1093 LWIP_ASSERT("RST not expected here!",
1094 (TCPH_FLAGS(seg->tcphdr) & TCP_RST) == 0);
1095 /* Stop sending if the nagle algorithm would prevent it
1096 * Don't stop:
1097 * - if tcp_write had a memory error before (prevent delayed ACK timeout) or
1098 * - if FIN was already enqueued for this PCB (SYN is always alone in a segment -
1099 * either seg->next != NULL or pcb->unacked == NULL;
1100 * RST is no sent using tcp_write/tcp_output.
1101 */
1102 if ((tcp_do_output_nagle(pcb) == 0) &&
1103 ((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)) {
1104 break;
1105 }
1106 #if TCP_CWND_DEBUG
1107 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",
1108 pcb->snd_wnd, pcb->cwnd, wnd,
1109 lwip_ntohl(seg->tcphdr->seqno) + seg->len -
1110 pcb->lastack,
1111 lwip_ntohl(seg->tcphdr->seqno), pcb->lastack, i));
1112 ++i;
1113 #endif /* TCP_CWND_DEBUG */
1114
1115 if (pcb->state != SYN_SENT) {
1116 TCPH_SET_FLAG(seg->tcphdr, TCP_ACK);
1117 }
1118
1119 #if TCP_OVERSIZE_DBGCHECK
1120 seg->oversize_left = 0;
1121 #endif /* TCP_OVERSIZE_DBGCHECK */
1122 err = tcp_output_segment(seg, pcb, netif);
1123 if (err != ERR_OK) {
1124 /* segment could not be sent, for whatever reason */
1125 pcb->flags |= TF_NAGLEMEMERR;
1126 return err;
1127 }
1128 pcb->unsent = seg->next;
1129 if (pcb->state != SYN_SENT) {
1130 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
1131 }
1132 snd_nxt = lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);
1133 if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) {
1134 pcb->snd_nxt = snd_nxt;
1135 }
1136 /* put segment on unacknowledged list if length > 0 */
1137 if (TCP_TCPLEN(seg) > 0) {
1138 seg->next = NULL;
1139 /* unacked list is empty? */
1140 if (pcb->unacked == NULL) {
1141 pcb->unacked = seg;
1142 useg = seg;
1143 /* unacked list is not empty? */
1144 } else {
1145 /* In the case of fast retransmit, the packet should not go to the tail
1146 * of the unacked queue, but rather somewhere before it. We need to check for
1147 * this case. -STJ Jul 27, 2004 */
1148 if (TCP_SEQ_LT(lwip_ntohl(seg->tcphdr->seqno), lwip_ntohl(useg->tcphdr->seqno))) {
1149 /* add segment to before tail of unacked list, keeping the list sorted */
1150 struct tcp_seg **cur_seg = &(pcb->unacked);
1151 while (*cur_seg &&
1152 TCP_SEQ_LT(lwip_ntohl((*cur_seg)->tcphdr->seqno), lwip_ntohl(seg->tcphdr->seqno))) {
1153 cur_seg = &((*cur_seg)->next );
1154 }
1155 seg->next = (*cur_seg);
1156 (*cur_seg) = seg;
1157 } else {
1158 /* add segment to tail of unacked list */
1159 useg->next = seg;
1160 useg = useg->next;
1161 }
1162 }
1163 /* do not queue empty segments on the unacked list */
1164 } else {
1165 tcp_seg_free(seg);
1166 }
1167 seg = pcb->unsent;
1168 }
1169 output_done:
1170 #if TCP_OVERSIZE
1171 if (pcb->unsent == NULL) {
1172 /* last unsent has been removed, reset unsent_oversize */
1173 pcb->unsent_oversize = 0;
1174 }
1175 #endif /* TCP_OVERSIZE */
1176
1177 pcb->flags &= ~TF_NAGLEMEMERR;
1178 return ERR_OK;
1179 }
1180
1188 static err_t
1189 tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb, struct netif *netif)
1190 {
1191 err_t err;
1192 u16_t len;
1193 u32_t *opts;
1194
1195 if (seg->p->ref != 1) {
1196 /* This can happen if the pbuf of this segment is still referenced by the
1197 netif driver due to deferred transmission. Since this function modifies
1198 p->len, we must not continue in this case. */
1199 return ERR_OK;
1200 }
1201
1202 /* The TCP header has already been constructed, but the ackno and
1203 wnd fields remain. */
1204 seg->tcphdr->ackno = lwip_htonl(pcb->rcv_nxt);
1205
1206 /* advertise our receive window size in this TCP segment */
1207 #if LWIP_WND_SCALE
1208 if (seg->flags & TF_SEG_OPTS_WND_SCALE) {
1209 /* The Window field in a SYN segment itself (the only type where we send
1210 the window scale option) is never scaled. */
1211 seg->tcphdr->wnd = lwip_htons(TCPWND_MIN16(pcb->rcv_ann_wnd));
1212 } else
1213 #endif /* LWIP_WND_SCALE */
1214 {
1215 seg->tcphdr->wnd = lwip_htons(TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd)));
1216 }
1217
1218 pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
1219
1220 /* Add any requested options. NB MSS option is only set on SYN
1221 packets, so ignore it here */
1222 /* cast through void* to get rid of alignment warnings */
1223 opts = (u32_t *)(void *)(seg->tcphdr + 1);
1224 if (seg->flags & TF_SEG_OPTS_MSS) {
1225 u16_t mss;
1226 #if TCP_CALCULATE_EFF_SEND_MSS
1227 mss = tcp_eff_send_mss(TCP_MSS, &pcb->local_ip, &pcb->remote_ip);
1228 #else /* TCP_CALCULATE_EFF_SEND_MSS */
1229 mss = TCP_MSS;
1230 #endif /* TCP_CALCULATE_EFF_SEND_MSS */
1231 *opts = TCP_BUILD_MSS_OPTION(mss);
1232 opts += 1;
1233 }
1234 #if LWIP_TCP_TIMESTAMPS
1235 pcb->ts_lastacksent = pcb->rcv_nxt;
1236
1237 if (seg->flags & TF_SEG_OPTS_TS) {
1238 tcp_build_timestamp_option(pcb, opts);
1239 opts += 3;
1240 }
1241 #endif
1242 #if LWIP_WND_SCALE
1243 if (seg->flags & TF_SEG_OPTS_WND_SCALE) {
1244 tcp_build_wnd_scale_option(opts);
1245 opts += 1;
1246 }
1247 #endif
1248
1249 /* Set retransmission timer running if it is not currently enabled
1250 This must be set before checking the route. */
1251 if (pcb->rtime < 0) {
1252 pcb->rtime = 0;
1253 }
1254
1255 if (pcb->rttest == 0) {
1256 pcb->rttest = tcp_ticks;
1257 pcb->rtseq = lwip_ntohl(seg->tcphdr->seqno);
1258
1259 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq));
1260 }
1261 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n",
1262 lwip_htonl(seg->tcphdr->seqno), lwip_htonl(seg->tcphdr->seqno) +
1263 seg->len));
1264
1265 len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload);
1266 if (len == 0) {
1268 MIB2_STATS_INC(mib2.tcpoutsegs);
1269 }
1270
1271 seg->p->len -= len;
1272 seg->p->tot_len -= len;
1273
1274 seg->p->payload = seg->tcphdr;
1275
1276 seg->tcphdr->chksum = 0;
1277 #if CHECKSUM_GEN_TCP
1278 IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) {
1279 #if TCP_CHECKSUM_ON_COPY
1280 u32_t acc;
1281 #if TCP_CHECKSUM_ON_COPY_SANITY_CHECK
1282 u16_t chksum_slow = ip_chksum_pseudo(seg->p, IP_PROTO_TCP,
1283 seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip);
1284 #endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */
1285 if ((seg->flags & TF_SEG_DATA_CHECKSUMMED) == 0) {
1286 LWIP_ASSERT("data included but not checksummed",
1287 seg->p->tot_len == (TCPH_HDRLEN(seg->tcphdr) * 4));
1288 }
1289
1290 /* rebuild TCP header checksum (TCP header changes for retransmissions!) */
1291 acc = ip_chksum_pseudo_partial(seg->p, IP_PROTO_TCP,
1292 seg->p->tot_len, TCPH_HDRLEN(seg->tcphdr) * 4, &pcb->local_ip, &pcb->remote_ip);
1293 /* add payload checksum */
1294 if (seg->chksum_swapped) {
1295 seg->chksum = SWAP_BYTES_IN_WORD(seg->chksum);
1296 seg->chksum_swapped = 0;
1297 }
1298 acc += (u16_t)~(seg->chksum);
1299 seg->tcphdr->chksum = FOLD_U32T(acc);
1300 #if TCP_CHECKSUM_ON_COPY_SANITY_CHECK
1301 if (chksum_slow != seg->tcphdr->chksum) {
1302 TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL(
1303 ("tcp_output_segment: calculated checksum is %"X16_F" instead of %"X16_F"\n",
1304 seg->tcphdr->chksum, chksum_slow));
1305 seg->tcphdr->chksum = chksum_slow;
1306 }
1307 #endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */
1308 #else /* TCP_CHECKSUM_ON_COPY */
1309 seg->tcphdr->chksum = ip_chksum_pseudo(seg->p, IP_PROTO_TCP,
1310 seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip);
1311 #endif /* TCP_CHECKSUM_ON_COPY */
1312 }
1313 #endif /* CHECKSUM_GEN_TCP */
1314 TCP_STATS_INC(tcp.xmit);
1315
1316 NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint));
1317 err = ip_output_if(seg->p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl,
1318 pcb->tos, IP_PROTO_TCP, netif);
1319 NETIF_SET_HWADDRHINT(netif, NULL);
1320 return err;
1321 }
1322
1343 void
1344 tcp_rst(u32_t seqno, u32_t ackno,
1345 const ip_addr_t *local_ip, const ip_addr_t *remote_ip,
1346 u16_t local_port, u16_t remote_port)
1347 {
1348 struct pbuf *p;
1349 struct tcp_hdr *tcphdr;
1350 struct netif *netif;
1351 p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
1352 if (p == NULL) {
1353 LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n"));
1354 return;
1355 }
1356 LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr",
1357 (p->len >= sizeof(struct tcp_hdr)));
1358
1359 tcphdr = (struct tcp_hdr *)p->payload;
1360 tcphdr->src = lwip_htons(local_port);
1361 tcphdr->dest = lwip_htons(remote_port);
1362 tcphdr->seqno = lwip_htonl(seqno);
1363 tcphdr->ackno = lwip_htonl(ackno);
1364 TCPH_HDRLEN_FLAGS_SET(tcphdr, TCP_HLEN/4, TCP_RST | TCP_ACK);
1365 #if LWIP_WND_SCALE
1366 tcphdr->wnd = PP_HTONS(((TCP_WND >> TCP_RCV_SCALE) & 0xFFFF));
1367 #else
1368 tcphdr->wnd = PP_HTONS(TCP_WND);
1369 #endif
1370 tcphdr->chksum = 0;
1371 tcphdr->urgp = 0;
1372
1373 TCP_STATS_INC(tcp.xmit);
1374 MIB2_STATS_INC(mib2.tcpoutrsts);
1375
1376 netif = ip_route(local_ip, remote_ip);
1377 if (netif != NULL) {
1378 #if CHECKSUM_GEN_TCP
1379 IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) {
1380 tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len,
1381 local_ip, remote_ip);
1382 }
1383 #endif
1384 /* Send output with hardcoded TTL/HL since we have no access to the pcb */
1385 ip_output_if(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP, netif);
1386 }
1387 pbuf_free(p);
1388 LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno));
1389 }
1390
1398 void
1399 tcp_rexmit_rto(struct tcp_pcb *pcb)
1400 {
1401 struct tcp_seg *seg;
1402
1403 if (pcb->unacked == NULL) {
1404 return;
1405 }
1406
1407 /* Move all unacked segments to the head of the unsent queue */
1408 for (seg = pcb->unacked; seg->next != NULL; seg = seg->next);
1409 /* concatenate unsent queue after unacked queue */
1410 seg->next = pcb->unsent;
1411 #if TCP_OVERSIZE_DBGCHECK
1412 /* if last unsent changed, we need to update unsent_oversize */
1413 if (pcb->unsent == NULL) {
1414 pcb->unsent_oversize = seg->oversize_left;
1415 }
1416 #endif /* TCP_OVERSIZE_DBGCHECK */
1417 /* unsent queue is the concatenated queue (of unacked, unsent) */
1418 pcb->unsent = pcb->unacked;
1419 /* unacked queue is now empty */
1420 pcb->unacked = NULL;
1421
1422 /* increment number of retransmissions */
1423 if (pcb->nrtx < 0xFF) {
1424 ++pcb->nrtx;
1425 }
1426
1427 /* Don't take any RTT measurements after retransmitting. */
1428 pcb->rttest = 0;
1429
1430 /* Do the actual retransmission */
1431 tcp_output(pcb);
1432 }
1433
1441 void
1442 tcp_rexmit(struct tcp_pcb *pcb)
1443 {
1444 struct tcp_seg *seg;
1445 struct tcp_seg **cur_seg;
1446
1447 if (pcb->unacked == NULL) {
1448 return;
1449 }
1450
1451 /* Move the first unacked segment to the unsent queue */
1452 /* Keep the unsent queue sorted. */
1453 seg = pcb->unacked;
1454 pcb->unacked = seg->next;
1455
1456 cur_seg = &(pcb->unsent);
1457 while (*cur_seg &&
1458 TCP_SEQ_LT(lwip_ntohl((*cur_seg)->tcphdr->seqno), lwip_ntohl(seg->tcphdr->seqno))) {
1459 cur_seg = &((*cur_seg)->next );
1460 }
1461 seg->next = *cur_seg;
1462 *cur_seg = seg;
1463 #if TCP_OVERSIZE
1464 if (seg->next == NULL) {
1465 /* the retransmitted segment is last in unsent, so reset unsent_oversize */
1466 pcb->unsent_oversize = 0;
1467 }
1468 #endif /* TCP_OVERSIZE */
1469
1470 if (pcb->nrtx < 0xFF) {
1471 ++pcb->nrtx;
1472 }
1473
1474 /* Don't take any rtt measurements after retransmitting. */
1475 pcb->rttest = 0;
1476
1477 /* Do the actual retransmission. */
1478 MIB2_STATS_INC(mib2.tcpretranssegs);
1479 /* No need to call tcp_output: we are always called from tcp_input()
1480 and thus tcp_output directly returns. */
1481 }
1482
1483
1489 void
1490 tcp_rexmit_fast(struct tcp_pcb *pcb)
1491 {
1492 if (pcb->unacked != NULL && !(pcb->flags & TF_INFR)) {
1493 /* This is fast retransmit. Retransmit the first unacked segment. */
1494 LWIP_DEBUGF(TCP_FR_DEBUG,
1495 ("tcp_receive: dupacks %"U16_F" (%"U32_F
1496 "), fast retransmit %"U32_F"\n",
1497 (u16_t)pcb->dupacks, pcb->lastack,
1498 lwip_ntohl(pcb->unacked->tcphdr->seqno)));
1499 tcp_rexmit(pcb);
1500
1501 /* Set ssthresh to half of the minimum of the current
1502 * cwnd and the advertised window */
1503 pcb->ssthresh = LWIP_MIN(pcb->cwnd, pcb->snd_wnd) / 2;
1504
1505 /* The minimum value for ssthresh should be 2 MSS */
1506 if (pcb->ssthresh < (2U * pcb->mss)) {
1507 LWIP_DEBUGF(TCP_FR_DEBUG,
1508 ("tcp_receive: The minimum value for ssthresh %"TCPWNDSIZE_F
1509 " should be min 2 mss %"U16_F"...\n",
1510 pcb->ssthresh, (u16_t)(2*pcb->mss)));
1511 pcb->ssthresh = 2*pcb->mss;
1512 }
1513
1514 pcb->cwnd = pcb->ssthresh + 3 * pcb->mss;
1515 pcb->flags |= TF_INFR;
1516
1517 /* Reset the retransmission timer to prevent immediate rto retransmissions */
1518 pcb->rtime = 0;
1519 }
1520 }
1521
1522
1531 err_t
1532 tcp_keepalive(struct tcp_pcb *pcb)
1533 {
1534 err_t err;
1535 struct pbuf *p;
1536 struct netif *netif;
1537
1538 LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to "));
1539 ip_addr_debug_print(TCP_DEBUG, &pcb->remote_ip);
1540 LWIP_DEBUGF(TCP_DEBUG, ("\n"));
1541
1542 LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n",
1543 tcp_ticks, pcb->tmr, (u16_t)pcb->keep_cnt_sent));
1544
1545 p = tcp_output_alloc_header(pcb, 0, 0, lwip_htonl(pcb->snd_nxt - 1));
1546 if (p == NULL) {
1547 LWIP_DEBUGF(TCP_DEBUG,
1548 ("tcp_keepalive: could not allocate memory for pbuf\n"));
1549 return ERR_MEM;
1550 }
1551 netif = ip_route(&pcb->local_ip, &pcb->remote_ip);
1552 if (netif == NULL) {
1553 err = ERR_RTE;
1554 } else {
1555 #if CHECKSUM_GEN_TCP
1556 IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) {
1557 struct tcp_hdr *tcphdr = (struct tcp_hdr *)p->payload;
1558 tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len,
1559 &pcb->local_ip, &pcb->remote_ip);
1560 }
1561 #endif /* CHECKSUM_GEN_TCP */
1562 TCP_STATS_INC(tcp.xmit);
1563
1564 /* Send output to IP */
1565 NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint));
1566 err = ip_output_if(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP, netif);
1567 NETIF_SET_HWADDRHINT(netif, NULL);
1568 }
1569 pbuf_free(p);
1570
1571 LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F" err %d.\n",
1572 pcb->snd_nxt - 1, pcb->rcv_nxt, (int)err));
1573 return err;
1574 }
1575
1576
1585 err_t
1586 tcp_zero_window_probe(struct tcp_pcb *pcb)
1587 {
1588 err_t err;
1589 struct pbuf *p;
1590 struct tcp_hdr *tcphdr;
1591 struct tcp_seg *seg;
1592 u16_t len;
1593 u8_t is_fin;
1594 u32_t snd_nxt;
1595 struct netif *netif;
1596
1597 LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: sending ZERO WINDOW probe to "));
1598 ip_addr_debug_print(TCP_DEBUG, &pcb->remote_ip);
1599 LWIP_DEBUGF(TCP_DEBUG, ("\n"));
1600
1601 LWIP_DEBUGF(TCP_DEBUG,
1602 ("tcp_zero_window_probe: tcp_ticks %"U32_F
1603 " pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n",
1604 tcp_ticks, pcb->tmr, (u16_t)pcb->keep_cnt_sent));
1605
1606 seg = pcb->unacked;
1607
1608 if (seg == NULL) {
1609 seg = pcb->unsent;
1610 }
1611 if (seg == NULL) {
1612 /* nothing to send, zero window probe not needed */
1613 return ERR_OK;
1614 }
1615
1616 is_fin = ((TCPH_FLAGS(seg->tcphdr) & TCP_FIN) != 0) && (seg->len == 0);
1617 /* we want to send one seqno: either FIN or data (no options) */
1618 len = is_fin ? 0 : 1;
1619
1620 p = tcp_output_alloc_header(pcb, 0, len, seg->tcphdr->seqno);
1621 if (p == NULL) {
1622 LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: no memory for pbuf\n"));
1623 return ERR_MEM;
1624 }
1625 tcphdr = (struct tcp_hdr *)p->payload;
1626
1627 if (is_fin) {
1628 /* FIN segment, no data */
1629 TCPH_FLAGS_SET(tcphdr, TCP_ACK | TCP_FIN);
1630 } else {
1631 /* Data segment, copy in one byte from the head of the unacked queue */
1632 char *d = ((char *)p->payload + TCP_HLEN);
1633 /* Depending on whether the segment has already been sent (unacked) or not
1634 (unsent), seg->p->payload points to the IP header or TCP header.
1635 Ensure we copy the first TCP data byte: */
1636 pbuf_copy_partial(seg->p, d, 1, seg->p->tot_len - seg->len);
1637 }
1638
1639 /* The byte may be acknowledged without the window being opened. */
1640 snd_nxt = lwip_ntohl(seg->tcphdr->seqno) + 1;
1641 if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) {
1642 pcb->snd_nxt = snd_nxt;
1643 }
1644
1645 netif = ip_route(&pcb->local_ip, &pcb->remote_ip);
1646 if (netif == NULL) {
1647 err = ERR_RTE;
1648 } else {
1649 #if CHECKSUM_GEN_TCP
1650 IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) {
1651 tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len,
1652 &pcb->local_ip, &pcb->remote_ip);
1653 }
1654 #endif
1655 TCP_STATS_INC(tcp.xmit);
1656
1657 /* Send output to IP */
1658 NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint));
1659 err = ip_output_if(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl,
1660 0, IP_PROTO_TCP, netif);
1661 NETIF_SET_HWADDRHINT(netif, NULL);
1662 }
1663
1664 pbuf_free(p);
1665
1666 LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: seqno %"U32_F
1667 " ackno %"U32_F" err %d.\n",
1668 pcb->snd_nxt - 1, pcb->rcv_nxt, (int)err));
1669 return err;
1670 }
1671 #endif /* LWIP_TCP */
TCP_SYN
#define TCP_SYN
Definition: tcp.h:73
sys.h
S16_F
#define S16_F
Definition: arch.h:151
TCP_ACK
#define TCP_ACK
Definition: tcp.h:76
opt.h
pbuf::len
u16_t len
Definition: pbuf.h:159
s16_t
int16_t s16_t
Definition: arch.h:125
def.h
LWIP_ASSERT
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:116
TCPH_FLAGS_SET
#define TCPH_FLAGS_SET(phdr, flags)
Definition: tcp.h:87
PBUF_ROM
Definition: pbuf.h:112
PBUF_RAW
Definition: pbuf.h:94
LWIP_DBG_LEVEL_SEVERE
#define LWIP_DBG_LEVEL_SEVERE
Definition: debug.h:59
ERR_BUF
Definition: err.h:67
u16_t
uint16_t u16_t
Definition: arch.h:124
string.h
TCP_CWND_DEBUG
#define TCP_CWND_DEBUG
Definition: lwipopts.h:471
PBUF_IP
Definition: pbuf.h:80
TCP_FR_DEBUG
#define TCP_FR_DEBUG
Definition: lwipopts.h:467
ip_addr_isany
#define ip_addr_isany(ipaddr)
Definition: ip_addr.h:317
pbuf::tot_len
u16_t tot_len
Definition: pbuf.h:156
u32_t
uint32_t u32_t
Definition: arch.h:126
pbuf_rom
Definition: pbuf.h:180
pbuf_clen
u16_t pbuf_clen(const struct pbuf *p)
Definition: pbuf.c:801
pbuf::next
struct pbuf * next
Definition: pbuf.h:144
PBUF_TRANSPORT
Definition: pbuf.h:76
pbuf_free
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:715
ip_chksum_pseudo_partial
u16_t ip_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, u16_t chksum_len, const ip_addr_t *src, const ip_addr_t *dest)
Definition: inet_chksum.c:526
memp_malloc
void * memp_malloc(memp_t type)
Definition: memp.c:385
LWIP_DBG_TRACE
#define LWIP_DBG_TRACE
Definition: debug.h:83
TCP_QLEN_DEBUG
#define TCP_QLEN_DEBUG
Definition: lwipopts.h:479
ip_chksum_pseudo
u16_t ip_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, const ip_addr_t *src, const ip_addr_t *dest)
Definition: inet_chksum.c:379
NETIF_SET_HWADDRHINT
#define NETIF_SET_HWADDRHINT(netif, hint)
Definition: netif.h:475
X16_F
#define X16_F
Definition: arch.h:154
LWIP_MIN
#define LWIP_MIN(x, y)
Definition: def.h:55
IF__NETIF_CHECKSUM_ENABLED
#define IF__NETIF_CHECKSUM_ENABLED(netif, chksumflag)
Definition: netif.h:357
pbuf::flags
u8_t flags
Definition: pbuf.h:165
SWAP_BYTES_IN_WORD
#define SWAP_BYTES_IN_WORD(w)
Definition: inet_chksum.h:47
ip_addr_debug_print
#define ip_addr_debug_print(debug, ipaddr)
Definition: ip_addr.h:323
TCP_RST_DEBUG
#define TCP_RST_DEBUG
Definition: lwipopts.h:477
stats.h
ERR_MEM
Definition: err.h:65
pbuf_copy_partial
u16_t pbuf_copy_partial(const struct pbuf *p, void *dataptr, u16_t len, u16_t offset)
Definition: pbuf.c:1016
LWIP_DBG_LEVEL_SERIOUS
#define LWIP_DBG_LEVEL_SERIOUS
Definition: debug.h:57
netif.h
sys_now
u32_t sys_now(void)
Definition: sys_arch.c:497
LWIP_ERROR
#define LWIP_ERROR(message, expression, handler)
Definition: debug.h:135
TCP_SND_QUEUELEN
#define TCP_SND_QUEUELEN
Definition: lwipopts.h:186
IP_PROTO_TCP
#define IP_PROTO_TCP
Definition: ip.h:46
TCP_OUTPUT_DEBUG
#define TCP_OUTPUT_DEBUG
Definition: lwipopts.h:475
lwip_ntohl
#define lwip_ntohl(x)
Definition: def.h:78
TCP_MSS
#define TCP_MSS
Definition: lwipopts.h:180
pbuf_alloc
struct pbuf * pbuf_alloc(pbuf_layer l, u16_t length, pbuf_type type)
Definition: pbuf.c:248
TCPH_SET_FLAG
#define TCPH_SET_FLAG(phdr, flags)
Definition: tcp.h:90
u8_t
uint8_t u8_t
Definition: arch.h:122
ip_addr_t
ip6_addr_t ip_addr_t
Definition: ip_addr.h:290
ERR_CONN
Definition: err.h:85
TCP_RST
#define TCP_RST
Definition: tcp.h:74
TCP_DEBUG
#define TCP_DEBUG
Definition: lwipopts.h:463
tcp_priv.h
pbuf_layer
pbuf_layer
Definition: pbuf.h:72
LWIP_MEM_ALIGN_SIZE
#define LWIP_MEM_ALIGN_SIZE(size)
Definition: arch.h:221
netif
Definition: netif.h:233
LWIP_MAX
#define LWIP_MAX(x, y)
Definition: def.h:54
MIB2_STATS_INC
#define MIB2_STATS_INC(x)
Definition: stats.h:467
ERR_ARG
Definition: err.h:96
LWIP_UNUSED_ARG
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:315
lwip_htonl
u32_t lwip_htonl(u32_t n)
Definition: def.c:88
TCP_FIN
#define TCP_FIN
Definition: tcp.h:72
lwip_htons
u16_t lwip_htons(u16_t n)
Definition: def.c:75
MEM_ALIGNMENT
#define MEM_ALIGNMENT
Definition: lwipopts.h:54
pbuf_cat
void pbuf_cat(struct pbuf *head, struct pbuf *tail)
Definition: pbuf.c:841
PBUF_RAM
Definition: pbuf.h:108
TCP_STATS_INC
#define TCP_STATS_INC(x)
Definition: stats.h:328
U16_F
#define U16_F
Definition: arch.h:148
TCP_WND
#define TCP_WND
Definition: lwipopts.h:172
ERR_OK
Definition: err.h:63
err_t
s8_t err_t
Definition: err.h:57
mem_ptr_t
uintptr_t mem_ptr_t
Definition: arch.h:128
ip_addr_copy
#define ip_addr_copy(dest, src)
Definition: ip_addr.h:305
TCP_TTL
#define TCP_TTL
Definition: lwipopts.h:171
inet_chksum
u16_t inet_chksum(const void *dataptr, u16_t len)
Definition: inet_chksum.c:555
ip6_addr.h
TCP_RCV_SCALE
#define TCP_RCV_SCALE
Definition: opt.h:1289
TCP_PSH
#define TCP_PSH
Definition: tcp.h:75
TCP_HLEN
#define TCP_HLEN
Definition: tcp.h:47
TCPH_HDRLEN
#define TCPH_HDRLEN(phdr)
Definition: tcp.h:83
tcp_hdr
Definition: tcp.h:56
U32_F
#define U32_F
Definition: arch.h:157
memp.h
pbuf::type
u8_t type
Definition: pbuf.h:162
TCP_RTO_DEBUG
#define TCP_RTO_DEBUG
Definition: lwipopts.h:469
TCPH_HDRLEN_FLAGS_SET
#define TCPH_HDRLEN_FLAGS_SET(phdr, len, flags)
Definition: tcp.h:88
mem.h
PP_HTONL
#define PP_HTONL(x)
Definition: def.h:81
ERR_RTE
Definition: err.h:71
FOLD_U32T
#define FOLD_U32T(u)
Definition: inet_chksum.h:52
pbuf
Definition: pbuf.h:142
LWIP_DEBUGF
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:164
ip6.h
LWIP_DBG_STATE
#define LWIP_DBG_STATE
Definition: debug.h:85
TCPH_FLAGS
#define TCPH_FLAGS(phdr)
Definition: tcp.h:84
ip_addr.h
inet_chksum.h
pbuf_header
u8_t pbuf_header(struct pbuf *p, s16_t header_size)
Definition: pbuf.c:665
pbuf::payload
void * payload
Definition: pbuf.h:147
PP_HTONS
#define PP_HTONS(x)
Definition: def.h:79
NULL
#define NULL
Definition: fat_string.h:17