UbixOS  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) {
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) {
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 
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 */
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);
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 {
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);
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;
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);
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. */
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)) {
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) {
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);
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 
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);
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:496
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