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