77#if LWIP_TCP_TIMESTAMPS
83#ifdef LWIP_HOOK_FILENAME
84#include LWIP_HOOK_FILENAME
88#ifdef LWIP_HOOK_TCP_OUT_TCPOPT_LENGTH
89#define LWIP_TCP_OPT_LENGTH_SEGMENT(flags, pcb) LWIP_HOOK_TCP_OUT_TCPOPT_LENGTH(pcb, LWIP_TCP_OPT_LENGTH(flags))
91#define LWIP_TCP_OPT_LENGTH_SEGMENT(flags, pcb) LWIP_TCP_OPT_LENGTH(flags)
96#if TCP_CHECKSUM_ON_COPY
97#define TCP_DATA_COPY(dst, src, len, seg) do { \
98 tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), \
99 len, &seg->chksum, &seg->chksum_swapped); \
100 seg->flags |= TF_SEG_DATA_CHECKSUMMED; } while(0)
101#define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) \
102 tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), len, chksum, chksum_swapped);
104#define TCP_DATA_COPY(dst, src, len, seg) MEMCPY(dst, src, len)
105#define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) MEMCPY(dst, src, len)
110#ifndef TCP_CHECKSUM_ON_COPY_SANITY_CHECK
111#define TCP_CHECKSUM_ON_COPY_SANITY_CHECK 0
114#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK
115#ifndef TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL
116#define TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL(msg) LWIP_DEBUGF(TCP_DEBUG | LWIP_DBG_LEVEL_WARNING, msg)
122#ifndef TCP_OVERSIZE_CALC_LENGTH
123#define TCP_OVERSIZE_CALC_LENGTH(length) ((length) + TCP_OVERSIZE)
128static err_t tcp_output_segment(
struct tcp_seg *seg,
struct tcp_pcb *pcb,
struct netif *
netif);
129static err_t tcp_output_control_segment_netif(
const struct tcp_pcb *pcb,
struct pbuf *p,
130 const ip_addr_t *src,
const ip_addr_t *dst,
135tcp_route(
const struct tcp_pcb *pcb,
const ip_addr_t *src,
const ip_addr_t *dst)
139 if ((pcb != NULL) && (pcb->netif_idx != NETIF_NO_INDEX)) {
142 return ip_route(src, dst);
160static struct tcp_seg *
161tcp_create_segment(
const struct tcp_pcb *pcb,
struct pbuf *p, u8_t hdrflags, u32_t seqno, u8_t optflags)
166 LWIP_ASSERT(
"tcp_create_segment: invalid pcb", pcb != NULL);
167 LWIP_ASSERT(
"tcp_create_segment: invalid pbuf", p != NULL);
169 optlen = LWIP_TCP_OPT_LENGTH_SEGMENT(optflags, pcb);
171 if ((seg = (
struct tcp_seg *)
memp_malloc(MEMP_TCP_SEG)) == NULL) {
176 seg->flags = optflags;
179 LWIP_ASSERT(
"p->tot_len >= optlen", p->tot_len >= optlen);
180 seg->len = p->tot_len - optlen;
181#if TCP_OVERSIZE_DBGCHECK
182 seg->oversize_left = 0;
184#if TCP_CHECKSUM_ON_COPY
186 seg->chksum_swapped = 0;
188 LWIP_ASSERT(
"invalid optflags passed: TF_SEG_DATA_CHECKSUMMED",
189 (optflags & TF_SEG_DATA_CHECKSUMMED) == 0);
195 TCP_STATS_INC(tcp.err);
199 seg->tcphdr = (
struct tcp_hdr *)seg->p->payload;
200 seg->tcphdr->src = lwip_htons(pcb->local_port);
201 seg->tcphdr->dest = lwip_htons(pcb->remote_port);
202 seg->tcphdr->seqno = lwip_htonl(seqno);
204 TCPH_HDRLEN_FLAGS_SET(seg->tcphdr, (5 + optlen / 4), hdrflags);
206 seg->tcphdr->urgp = 0;
228tcp_pbuf_prealloc(
pbuf_layer layer, u16_t length, u16_t max_length,
229 u16_t *oversize,
const struct tcp_pcb *pcb, u8_t apiflags,
233 u16_t alloc = length;
235 LWIP_ASSERT(
"tcp_pbuf_prealloc: invalid oversize", oversize != NULL);
236 LWIP_ASSERT(
"tcp_pbuf_prealloc: invalid pcb", pcb != NULL);
238#if LWIP_NETIF_TX_SINGLE_PBUF
245 if (length < max_length) {
257 if ((apiflags & TCP_WRITE_FLAG_MORE) ||
258 (!(pcb->flags & TF_NODELAY) &&
260 pcb->unsent != NULL ||
261 pcb->unacked != NULL))) {
266 p = pbuf_alloc(layer, alloc,
PBUF_RAM);
270 LWIP_ASSERT(
"need unchained pbuf", p->next == NULL);
271 *oversize = p->len - length;
273 p->len = p->tot_len = length;
277#define tcp_pbuf_prealloc(layer, length, mx, os, pcb, api, fst) pbuf_alloc((layer), (length), PBUF_RAM)
280#if TCP_CHECKSUM_ON_COPY
286tcp_seg_add_chksum(u16_t chksum, u16_t
len, u16_t *seg_chksum,
287 u8_t *seg_chksum_swapped)
291 helper = chksum + *seg_chksum;
293 if ((
len & 1) != 0) {
294 *seg_chksum_swapped = 1 - *seg_chksum_swapped;
297 *seg_chksum = chksum;
308tcp_write_checks(
struct tcp_pcb *pcb, u16_t
len)
310 LWIP_ASSERT(
"tcp_write_checks: invalid pcb", pcb != NULL);
313 if ((pcb->state != ESTABLISHED) &&
314 (pcb->state != CLOSE_WAIT) &&
315 (pcb->state != SYN_SENT) &&
316 (pcb->state != SYN_RCVD)) {
319 }
else if (
len == 0) {
324 if (
len > pcb->snd_buf) {
327 tcp_set_flags(pcb, TF_NAGLEMEMERR);
331 LWIP_DEBUGF(
TCP_QLEN_DEBUG, (
"tcp_write: queuelen: %"TCPWNDSIZE_F
"\n", (tcpwnd_size_t)pcb->snd_queuelen));
336 if (pcb->snd_queuelen >= LWIP_MIN(
TCP_SND_QUEUELEN, (TCP_SNDQUEUELEN_OVERFLOW + 1))) {
339 TCP_STATS_INC(tcp.memerr);
340 tcp_set_flags(pcb, TF_NAGLEMEMERR);
343 if (pcb->snd_queuelen != 0) {
344 LWIP_ASSERT(
"tcp_write: pbufs on queue => at least one queue non-empty",
345 pcb->unacked != NULL || pcb->unsent != NULL);
347 LWIP_ASSERT(
"tcp_write: no pbufs on queue => both queues empty",
348 pcb->unacked == NULL && pcb->unsent == NULL);
393tcp_write(
struct tcp_pcb *pcb,
const void *arg, u16_t
len, u8_t apiflags)
395 struct pbuf *concat_p = NULL;
396 struct tcp_seg *last_unsent = NULL, *seg = NULL, *prev_seg = NULL, *queue = NULL;
403 u16_t oversize_used = 0;
404#if TCP_OVERSIZE_DBGCHECK
405 u16_t oversize_add = 0;
409#if TCP_CHECKSUM_ON_COPY
410 u16_t concat_chksum = 0;
411 u8_t concat_chksum_swapped = 0;
412 u16_t concat_chksummed = 0;
417 LWIP_ERROR(
"tcp_write: invalid pcb", pcb != NULL,
return ERR_ARG);
420 mss_local = LWIP_MIN(pcb->mss, TCPWND_MIN16(pcb->snd_wnd_max / 2));
421 mss_local = mss_local ? mss_local : pcb->mss;
425#if LWIP_NETIF_TX_SINGLE_PBUF
427 apiflags |= TCP_WRITE_FLAG_COPY;
430 LWIP_DEBUGF(
TCP_OUTPUT_DEBUG, (
"tcp_write(pcb=%p, data=%p, len=%"U16_F
", apiflags=%"U16_F
")\n",
431 (
void *)pcb, arg, len, (u16_t)apiflags));
432 LWIP_ERROR(
"tcp_write: arg == NULL (programmer violates API)",
435 err = tcp_write_checks(pcb, len);
439 queuelen = pcb->snd_queuelen;
441#if LWIP_TCP_TIMESTAMPS
442 if ((pcb->flags & TF_TIMESTAMP)) {
445 optflags = TF_SEG_OPTS_TS;
446 optlen = LWIP_TCP_OPT_LENGTH_SEGMENT(TF_SEG_OPTS_TS, pcb);
448 mss_local = LWIP_MAX(mss_local, LWIP_TCP_OPT_LEN_TS + 1);
452 optlen = LWIP_TCP_OPT_LENGTH_SEGMENT(0, pcb);
479 if (pcb->unsent != NULL) {
484 for (last_unsent = pcb->unsent; last_unsent->next != NULL;
485 last_unsent = last_unsent->next);
488 unsent_optlen = LWIP_TCP_OPT_LENGTH_SEGMENT(last_unsent->flags, pcb);
489 LWIP_ASSERT(
"mss_local is too small", mss_local >= last_unsent->len + unsent_optlen);
490 space = mss_local - (last_unsent->len + unsent_optlen);
500#if TCP_OVERSIZE_DBGCHECK
502 LWIP_ASSERT(
"unsent_oversize mismatch (pcb vs. last_unsent)",
503 pcb->unsent_oversize == last_unsent->oversize_left);
505 oversize = pcb->unsent_oversize;
507 LWIP_ASSERT(
"inconsistent oversize vs. space", oversize <= space);
509 oversize_used = LWIP_MIN(space, LWIP_MIN(oversize, len));
510 pos += oversize_used;
511 oversize -= oversize_used;
512 space -= oversize_used;
515 LWIP_ASSERT(
"inconsistent oversize vs. len", (oversize == 0) || (pos == len));
518#if !LWIP_NETIF_TX_SINGLE_PBUF
534 if ((pos < len) && (space > 0) && (last_unsent->len > 0)) {
535 u16_t seglen = LWIP_MIN(space, len - pos);
541 if (apiflags & TCP_WRITE_FLAG_COPY) {
543 if ((concat_p = tcp_pbuf_prealloc(
PBUF_RAW, seglen, space, &oversize, pcb, apiflags, 1)) == NULL) {
545 (
"tcp_write : could not allocate memory for pbuf copy size %"U16_F
"\n",
549#if TCP_OVERSIZE_DBGCHECK
550 oversize_add = oversize;
552 TCP_DATA_COPY2(concat_p->
payload, (
const u8_t *)arg + pos, seglen, &concat_chksum, &concat_chksum_swapped);
553#if TCP_CHECKSUM_ON_COPY
554 concat_chksummed += seglen;
556 queuelen += pbuf_clen(concat_p);
561 for (p = last_unsent->p; p->next != NULL; p = p->next);
563 (
const u8_t *)p->payload + p->len == (
const u8_t *)arg) {
564 LWIP_ASSERT(
"tcp_write: ROM pbufs cannot be oversized", pos == 0);
569 (
"tcp_write: could not allocate memory for zero-copy pbuf\n"));
574 queuelen += pbuf_clen(concat_p);
576#if TCP_CHECKSUM_ON_COPY
578 tcp_seg_add_chksum(~inet_chksum((
const u8_t *)arg + pos, seglen), seglen,
579 &concat_chksum, &concat_chksum_swapped);
580 concat_chksummed += seglen;
589 LWIP_ASSERT(
"unsent_oversize mismatch (pcb->unsent is NULL)",
590 pcb->unsent_oversize == 0);
602 u16_t left =
len - pos;
603 u16_t max_len = mss_local - optlen;
604 u16_t seglen = LWIP_MIN(left, max_len);
605#if TCP_CHECKSUM_ON_COPY
607 u8_t chksum_swapped = 0;
610 if (apiflags & TCP_WRITE_FLAG_COPY) {
613 if ((p = tcp_pbuf_prealloc(
PBUF_TRANSPORT, seglen + optlen, mss_local, &oversize, pcb, apiflags, queue == NULL)) == NULL) {
617 LWIP_ASSERT(
"tcp_write: check that first pbuf can hold the complete seglen",
619 TCP_DATA_COPY2((
char *)p->payload + optlen, (
const u8_t *)arg + pos, seglen, &chksum, &chksum_swapped);
628 LWIP_ASSERT(
"oversize == 0", oversize == 0);
634#if TCP_CHECKSUM_ON_COPY
636 chksum = ~inet_chksum((
const u8_t *)arg + pos, seglen);
657 queuelen += pbuf_clen(p);
669 if ((seg = tcp_create_segment(pcb, p, 0, pcb->snd_lbb + pos, optflags)) == NULL) {
672#if TCP_OVERSIZE_DBGCHECK
673 seg->oversize_left = oversize;
675#if TCP_CHECKSUM_ON_COPY
676 seg->chksum = chksum;
677 seg->chksum_swapped = chksum_swapped;
678 seg->flags |= TF_SEG_DATA_CHECKSUMMED;
686 LWIP_ASSERT(
"prev_seg != NULL", prev_seg != NULL);
687 prev_seg->next = seg;
693 lwip_ntohl(seg->tcphdr->seqno),
694 lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg)));
703#if TCP_OVERSIZE_DBGCHECK
704 if ((last_unsent != NULL) && (oversize_add != 0)) {
705 last_unsent->oversize_left += oversize_add;
714 if (oversize_used > 0) {
717 for (p = last_unsent->p; p; p = p->next) {
718 p->tot_len += oversize_used;
719 if (p->next == NULL) {
720 TCP_DATA_COPY((
char *)p->payload + p->len, arg, oversize_used, last_unsent);
721 p->len += oversize_used;
724 last_unsent->
len += oversize_used;
725#if TCP_OVERSIZE_DBGCHECK
726 LWIP_ASSERT(
"last_unsent->oversize_left >= oversize_used",
727 last_unsent->oversize_left >= oversize_used);
728 last_unsent->oversize_left -= oversize_used;
731 pcb->unsent_oversize = oversize;
738 if (concat_p != NULL) {
739 LWIP_ASSERT(
"tcp_write: cannot concatenate when pcb->unsent is empty",
740 (last_unsent != NULL));
742 last_unsent->len += concat_p->
tot_len;
743 }
else if (extendlen > 0) {
745 LWIP_ASSERT(
"tcp_write: extension of reference requires reference",
746 last_unsent != NULL && last_unsent->p != NULL);
747 for (p = last_unsent->p; p->next != NULL; p = p->next) {
748 p->tot_len += extendlen;
750 p->tot_len += extendlen;
752 last_unsent->len += extendlen;
755#if TCP_CHECKSUM_ON_COPY
756 if (concat_chksummed) {
757 LWIP_ASSERT(
"tcp_write: concat checksum needs concatenated data",
758 concat_p != NULL || extendlen > 0);
760 if (concat_chksum_swapped) {
763 tcp_seg_add_chksum(concat_chksum, concat_chksummed, &last_unsent->chksum,
764 &last_unsent->chksum_swapped);
765 last_unsent->flags |= TF_SEG_DATA_CHECKSUMMED;
773 if (last_unsent == NULL) {
776 last_unsent->next = queue;
784 pcb->snd_queuelen = queuelen;
786 LWIP_DEBUGF(
TCP_QLEN_DEBUG, (
"tcp_write: %"S16_F
" (after enqueued)\n",
788 if (pcb->snd_queuelen != 0) {
789 LWIP_ASSERT(
"tcp_write: valid queue length",
790 pcb->unacked != NULL || pcb->unsent != NULL);
794 if (seg != NULL && seg->tcphdr != NULL && ((apiflags & TCP_WRITE_FLAG_MORE) == 0)) {
795 TCPH_SET_FLAG(seg->tcphdr, TCP_PSH);
800 tcp_set_flags(pcb, TF_NAGLEMEMERR);
801 TCP_STATS_INC(tcp.memerr);
803 if (concat_p != NULL) {
807 tcp_segs_free(queue);
809 if (pcb->snd_queuelen != 0) {
810 LWIP_ASSERT(
"tcp_write: valid queue length", pcb->unacked != NULL ||
811 pcb->unsent != NULL);
830tcp_split_unsent_seg(
struct tcp_pcb *pcb, u16_t split)
832 struct tcp_seg *seg = NULL, *useg = NULL;
833 struct pbuf *p = NULL;
837 u8_t remainder_flags;
840#if TCP_CHECKSUM_ON_COPY
842 u8_t chksum_swapped = 0;
846 LWIP_ASSERT(
"tcp_split_unsent_seg: invalid pcb", pcb != NULL);
854 LWIP_ASSERT(
"Can't split segment into length 0", 0);
858 if (useg->len <= split) {
862 LWIP_ASSERT(
"split <= mss", split <= pcb->mss);
863 LWIP_ASSERT(
"useg->len > 0", useg->len > 0);
869 LWIP_DEBUGF(
TCP_QLEN_DEBUG, (
"tcp_enqueue: split_unsent_seg: %u\n", (
unsigned int)pcb->snd_queuelen));
871 optflags = useg->flags;
872#if TCP_CHECKSUM_ON_COPY
874 optflags &= ~TF_SEG_DATA_CHECKSUMMED;
876 optlen = LWIP_TCP_OPT_LENGTH(optflags);
877 remainder = useg->len - split;
883 (
"tcp_split_unsent_seg: could not allocate memory for pbuf remainder %u\n", remainder));
888 offset = useg->p->tot_len - useg->len + split;
890 if (
pbuf_copy_partial(useg->p, (u8_t *)p->payload + optlen, remainder, offset ) != remainder) {
892 (
"tcp_split_unsent_seg: could not copy pbuf remainder %u\n", remainder));
895#if TCP_CHECKSUM_ON_COPY
897 tcp_seg_add_chksum(~inet_chksum((
const u8_t *)p->payload + optlen, remainder), remainder,
898 &chksum, &chksum_swapped);
904 split_flags = TCPH_FLAGS(useg->tcphdr);
907 if (split_flags & TCP_PSH) {
908 split_flags &= ~TCP_PSH;
909 remainder_flags |= TCP_PSH;
911 if (split_flags & TCP_FIN) {
912 split_flags &= ~TCP_FIN;
913 remainder_flags |= TCP_FIN;
917 seg = tcp_create_segment(pcb, p, remainder_flags, lwip_ntohl(useg->tcphdr->seqno) + split, optflags);
921 (
"tcp_split_unsent_seg: could not create new TCP segment\n"));
925#if TCP_CHECKSUM_ON_COPY
926 seg->chksum = chksum;
927 seg->chksum_swapped = chksum_swapped;
928 seg->flags |= TF_SEG_DATA_CHECKSUMMED;
932 pcb->snd_queuelen -= pbuf_clen(useg->p);
936 pbuf_realloc(useg->p, useg->p->tot_len - remainder);
937 useg->len -= remainder;
938 TCPH_SET_FLAG(useg->tcphdr, split_flags);
939#if TCP_OVERSIZE_DBGCHECK
941 useg->oversize_left = 0;
945 pcb->snd_queuelen += pbuf_clen(useg->p);
947#if TCP_CHECKSUM_ON_COPY
950 useg->chksum_swapped = 0;
952 offset = q->tot_len - useg->len;
955 while (q != NULL && offset > q->len) {
959 LWIP_ASSERT(
"Found start of payload pbuf", q != NULL);
961 for (; q != NULL; offset = 0, q = q->next) {
962 tcp_seg_add_chksum(~inet_chksum((
const u8_t *)q->payload + offset, q->len - offset), q->len - offset,
963 &useg->chksum, &useg->chksum_swapped);
970 pcb->snd_queuelen += pbuf_clen(seg->p);
973 seg->next = useg->next;
979 if (seg->next == NULL) {
980 pcb->unsent_oversize = 0;
986 TCP_STATS_INC(tcp.memerr);
988 LWIP_ASSERT(
"seg == NULL", seg == NULL);
1005tcp_send_fin(
struct tcp_pcb *pcb)
1007 LWIP_ASSERT(
"tcp_send_fin: invalid pcb", pcb != NULL);
1010 if (pcb->unsent != NULL) {
1011 struct tcp_seg *last_unsent;
1012 for (last_unsent = pcb->unsent; last_unsent->next != NULL;
1013 last_unsent = last_unsent->next);
1015 if ((TCPH_FLAGS(last_unsent->tcphdr) & (TCP_SYN | TCP_FIN | TCP_RST)) == 0) {
1017 TCPH_SET_FLAG(last_unsent->tcphdr, TCP_FIN);
1018 tcp_set_flags(pcb, TF_FIN);
1023 return tcp_enqueue_flags(pcb, TCP_FIN);
1036tcp_enqueue_flags(
struct tcp_pcb *pcb, u8_t flags)
1039 struct tcp_seg *seg;
1043 LWIP_ASSERT(
"tcp_enqueue_flags: need either TCP_SYN or TCP_FIN in flags (programmer violates API)",
1044 (flags & (TCP_SYN | TCP_FIN)) != 0);
1045 LWIP_ASSERT(
"tcp_enqueue_flags: invalid pcb", pcb != NULL);
1047 LWIP_DEBUGF(
TCP_QLEN_DEBUG, (
"tcp_enqueue_flags: queuelen: %"U16_F
"\n", (u16_t)pcb->snd_queuelen));
1053 if (flags & TCP_SYN) {
1054 optflags = TF_SEG_OPTS_MSS;
1056 if ((pcb->state != SYN_RCVD) || (pcb->flags & TF_WND_SCALE)) {
1059 optflags |= TF_SEG_OPTS_WND_SCALE;
1062#if LWIP_TCP_SACK_OUT
1063 if ((pcb->state != SYN_RCVD) || (pcb->flags & TF_SACK)) {
1066 optflags |= TF_SEG_OPTS_SACK_PERM;
1070#if LWIP_TCP_TIMESTAMPS
1071 if ((pcb->flags & TF_TIMESTAMP) || ((flags & TCP_SYN) && (pcb->state != SYN_RCVD))) {
1074 optflags |= TF_SEG_OPTS_TS;
1077 optlen = LWIP_TCP_OPT_LENGTH_SEGMENT(optflags, pcb);
1081 tcp_set_flags(pcb, TF_NAGLEMEMERR);
1082 TCP_STATS_INC(tcp.memerr);
1085 LWIP_ASSERT(
"tcp_enqueue_flags: check that first pbuf can hold optlen",
1086 (p->len >= optlen));
1089 if ((seg = tcp_create_segment(pcb, p, flags, pcb->snd_lbb, optflags)) == NULL) {
1090 tcp_set_flags(pcb, TF_NAGLEMEMERR);
1091 TCP_STATS_INC(tcp.memerr);
1094 LWIP_ASSERT(
"seg->tcphdr not aligned", ((mem_ptr_t)seg->tcphdr % LWIP_MIN(MEM_ALIGNMENT, 4)) == 0);
1095 LWIP_ASSERT(
"tcp_enqueue_flags: invalid segment length", seg->len == 0);
1098 (
"tcp_enqueue_flags: queueing %"U32_F
":%"U32_F
" (0x%"X16_F
")\n",
1099 lwip_ntohl(seg->tcphdr->seqno),
1100 lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
1104 if (pcb->unsent == NULL) {
1107 struct tcp_seg *useg;
1108 for (useg = pcb->unsent; useg->next != NULL; useg = useg->next);
1113 pcb->unsent_oversize = 0;
1117 if ((flags & TCP_SYN) || (flags & TCP_FIN)) {
1121 if (flags & TCP_FIN) {
1122 tcp_set_flags(pcb, TF_FIN);
1126 pcb->snd_queuelen += pbuf_clen(seg->p);
1127 LWIP_DEBUGF(
TCP_QLEN_DEBUG, (
"tcp_enqueue_flags: %"S16_F
" (after enqueued)\n", pcb->snd_queuelen));
1128 if (pcb->snd_queuelen != 0) {
1129 LWIP_ASSERT(
"tcp_enqueue_flags: invalid queue length",
1130 pcb->unacked != NULL || pcb->unsent != NULL);
1136#if LWIP_TCP_TIMESTAMPS
1143tcp_build_timestamp_option(
const struct tcp_pcb *pcb, u32_t *opts)
1145 LWIP_ASSERT(
"tcp_build_timestamp_option: invalid pcb", pcb != NULL);
1148 opts[0] = PP_HTONL(0x0101080A);
1149 opts[1] = lwip_htonl(
sys_now());
1150 opts[2] = lwip_htonl(pcb->ts_recent);
1154#if LWIP_TCP_SACK_OUT
1166tcp_get_num_sacks(
const struct tcp_pcb *pcb, u8_t optlen)
1170 LWIP_ASSERT(
"tcp_get_num_sacks: invalid pcb", pcb != NULL);
1172 if (pcb->flags & TF_SACK) {
1181 LWIP_TCP_SACK_VALID(pcb, i); ++i) {
1197tcp_build_sack_option(
const struct tcp_pcb *pcb, u32_t *opts, u8_t num_sacks)
1201 LWIP_ASSERT(
"tcp_build_sack_option: invalid pcb", pcb != NULL);
1202 LWIP_ASSERT(
"tcp_build_sack_option: invalid opts", opts != NULL);
1207 *(opts++) = PP_HTONL(0x01010500 + 2 + num_sacks * 8);
1209 for (i = 0; i < num_sacks; ++i) {
1210 *(opts++) = lwip_htonl(pcb->rcv_sacks[i].left);
1211 *(opts++) = lwip_htonl(pcb->rcv_sacks[i].right);
1223tcp_build_wnd_scale_option(u32_t *opts)
1225 LWIP_ASSERT(
"tcp_build_wnd_scale_option: invalid opts", opts != NULL);
1228 opts[0] = PP_HTONL(0x01030300 | TCP_RCV_SCALE);
1241tcp_output(
struct tcp_pcb *pcb)
1243 struct tcp_seg *seg, *useg;
1253 LWIP_ASSERT(
"tcp_output: invalid pcb", pcb != NULL);
1255 LWIP_ASSERT(
"don't call tcp_output for listen-pcbs",
1256 pcb->state != LISTEN);
1262 if (tcp_input_pcb == pcb) {
1266 wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd);
1272 (
void *)pcb->unsent));
1274 ", cwnd %"TCPWNDSIZE_F
", wnd %"U32_F
1275 ", seg == NULL, ack %"U32_F
"\n",
1276 pcb->snd_wnd, pcb->cwnd, wnd, pcb->lastack));
1280 if (pcb->flags & TF_ACK_NOW) {
1281 return tcp_send_empty_ack(pcb);
1287 (
"tcp_output: snd_wnd %"TCPWNDSIZE_F
", cwnd %"TCPWNDSIZE_F
", wnd %"U32_F
1288 ", effwnd %"U32_F
", seq %"U32_F
", ack %"U32_F
"\n",
1289 pcb->snd_wnd, pcb->cwnd, wnd,
1290 lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len,
1291 lwip_ntohl(seg->tcphdr->seqno), pcb->lastack));
1294 netif = tcp_route(pcb, &pcb->local_ip, &pcb->remote_ip);
1295 if (
netif == NULL) {
1300 if (ip_addr_isany(&pcb->local_ip)) {
1301 const ip_addr_t *local_ip = ip_netif_get_local_ip(
netif, &pcb->remote_ip);
1302 if (local_ip == NULL) {
1305 ip_addr_copy(pcb->local_ip, *local_ip);
1309 if (lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd) {
1316 if (wnd == pcb->snd_wnd && pcb->unacked == NULL && pcb->persist_backoff == 0) {
1317 pcb->persist_cnt = 0;
1318 pcb->persist_backoff = 1;
1319 pcb->persist_probe = 0;
1322 if (pcb->flags & TF_ACK_NOW) {
1323 return tcp_send_empty_ack(pcb);
1328 pcb->persist_backoff = 0;
1331 useg = pcb->unacked;
1333 for (; useg->next != NULL; useg = useg->next);
1336 while (seg != NULL &&
1337 lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
1338 LWIP_ASSERT(
"RST not expected here!",
1339 (TCPH_FLAGS(seg->tcphdr) & TCP_RST) == 0);
1347 if ((tcp_do_output_nagle(pcb) == 0) &&
1348 ((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)) {
1352 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",
1353 pcb->snd_wnd, pcb->cwnd, wnd,
1354 lwip_ntohl(seg->tcphdr->seqno) + seg->len -
1356 lwip_ntohl(seg->tcphdr->seqno), pcb->lastack, i));
1360 if (pcb->state != SYN_SENT) {
1361 TCPH_SET_FLAG(seg->tcphdr, TCP_ACK);
1364 err = tcp_output_segment(seg, pcb,
netif);
1367 tcp_set_flags(pcb, TF_NAGLEMEMERR);
1370#if TCP_OVERSIZE_DBGCHECK
1371 seg->oversize_left = 0;
1373 pcb->unsent = seg->next;
1374 if (pcb->state != SYN_SENT) {
1375 tcp_clear_flags(pcb, TF_ACK_DELAY | TF_ACK_NOW);
1377 snd_nxt = lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);
1378 if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) {
1379 pcb->snd_nxt = snd_nxt;
1382 if (TCP_TCPLEN(seg) > 0) {
1385 if (pcb->unacked == NULL) {
1393 if (TCP_SEQ_LT(lwip_ntohl(seg->tcphdr->seqno), lwip_ntohl(useg->tcphdr->seqno))) {
1395 struct tcp_seg **cur_seg = &(pcb->unacked);
1397 TCP_SEQ_LT(lwip_ntohl((*cur_seg)->tcphdr->seqno), lwip_ntohl(seg->tcphdr->seqno))) {
1398 cur_seg = &((*cur_seg)->next );
1400 seg->next = (*cur_seg);
1415 if (pcb->unsent == NULL) {
1417 pcb->unsent_oversize = 0;
1422 tcp_clear_flags(pcb, TF_NAGLEMEMERR);
1436tcp_output_segment_busy(
const struct tcp_seg *seg)
1438 LWIP_ASSERT(
"tcp_output_segment_busy: invalid seg", seg != NULL);
1443 if (seg->p->ref != 1) {
1459tcp_output_segment(
struct tcp_seg *seg,
struct tcp_pcb *pcb,
struct netif *
netif)
1464#if TCP_CHECKSUM_ON_COPY
1465 int seg_chksum_was_swapped = 0;
1468 LWIP_ASSERT(
"tcp_output_segment: invalid seg", seg != NULL);
1469 LWIP_ASSERT(
"tcp_output_segment: invalid pcb", pcb != NULL);
1470 LWIP_ASSERT(
"tcp_output_segment: invalid netif",
netif != NULL);
1472 if (tcp_output_segment_busy(seg)) {
1481 seg->tcphdr->ackno = lwip_htonl(pcb->rcv_nxt);
1485 if (seg->flags & TF_SEG_OPTS_WND_SCALE) {
1488 seg->tcphdr->wnd = lwip_htons(TCPWND_MIN16(pcb->rcv_ann_wnd));
1492 seg->tcphdr->wnd = lwip_htons(TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd)));
1495 pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
1500 opts = (u32_t *)(
void *)(seg->tcphdr + 1);
1501 if (seg->flags & TF_SEG_OPTS_MSS) {
1503#if TCP_CALCULATE_EFF_SEND_MSS
1504 mss = tcp_eff_send_mss_netif(TCP_MSS,
netif, &pcb->remote_ip);
1508 *opts = TCP_BUILD_MSS_OPTION(mss);
1511#if LWIP_TCP_TIMESTAMPS
1512 pcb->ts_lastacksent = pcb->rcv_nxt;
1514 if (seg->flags & TF_SEG_OPTS_TS) {
1515 tcp_build_timestamp_option(pcb, opts);
1520 if (seg->flags & TF_SEG_OPTS_WND_SCALE) {
1521 tcp_build_wnd_scale_option(opts);
1525#if LWIP_TCP_SACK_OUT
1526 if (seg->flags & TF_SEG_OPTS_SACK_PERM) {
1532 *(opts++) = PP_HTONL(0x01010402);
1538 if (pcb->rtime < 0) {
1542 if (pcb->rttest == 0) {
1543 pcb->rttest = tcp_ticks;
1544 pcb->rtseq = lwip_ntohl(seg->tcphdr->seqno);
1546 LWIP_DEBUGF(
TCP_RTO_DEBUG, (
"tcp_output_segment: rtseq %"U32_F
"\n", pcb->rtseq));
1549 lwip_htonl(seg->tcphdr->seqno), lwip_htonl(seg->tcphdr->seqno) +
1552 len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload);
1555 MIB2_STATS_INC(mib2.tcpoutsegs);
1559 seg->p->tot_len -= len;
1561 seg->p->payload = seg->tcphdr;
1563 seg->tcphdr->chksum = 0;
1565#ifdef LWIP_HOOK_TCP_OUT_ADD_TCPOPTS
1566 opts = LWIP_HOOK_TCP_OUT_ADD_TCPOPTS(seg->p, seg->tcphdr, pcb, opts);
1568 LWIP_ASSERT(
"options not filled", (u8_t *)opts == ((u8_t *)(seg->tcphdr + 1)) + LWIP_TCP_OPT_LENGTH_SEGMENT(seg->flags, pcb));
1571 IF__NETIF_CHECKSUM_ENABLED(
netif, NETIF_CHECKSUM_GEN_TCP) {
1572#if TCP_CHECKSUM_ON_COPY
1574#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK
1575 u16_t chksum_slow = ip_chksum_pseudo(seg->p, IP_PROTO_TCP,
1576 seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip);
1578 if ((seg->flags & TF_SEG_DATA_CHECKSUMMED) == 0) {
1579 LWIP_ASSERT(
"data included but not checksummed",
1580 seg->p->tot_len == TCPH_HDRLEN_BYTES(seg->tcphdr));
1584 acc = ip_chksum_pseudo_partial(seg->p, IP_PROTO_TCP,
1585 seg->p->tot_len, TCPH_HDRLEN_BYTES(seg->tcphdr), &pcb->local_ip, &pcb->remote_ip);
1587 if (seg->chksum_swapped) {
1588 seg_chksum_was_swapped = 1;
1590 seg->chksum_swapped = 0;
1592 acc = (u16_t)~acc + seg->chksum;
1593 seg->tcphdr->chksum = (u16_t)~
FOLD_U32T(acc);
1594#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK
1595 if (chksum_slow != seg->tcphdr->chksum) {
1596 TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL(
1597 (
"tcp_output_segment: calculated checksum is %"X16_F
" instead of %"X16_F
"\n",
1598 seg->tcphdr->chksum, chksum_slow));
1599 seg->tcphdr->chksum = chksum_slow;
1603 seg->tcphdr->chksum = ip_chksum_pseudo(seg->p, IP_PROTO_TCP,
1604 seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip);
1608 TCP_STATS_INC(tcp.xmit);
1610 NETIF_SET_HINTS(
netif, &(pcb->netif_hints));
1611 err = ip_output_if(seg->p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl,
1612 pcb->tos, IP_PROTO_TCP,
netif);
1613 NETIF_RESET_HINTS(
netif);
1615#if TCP_CHECKSUM_ON_COPY
1616 if (seg_chksum_was_swapped) {
1620 seg->chksum_swapped = 1;
1635tcp_rexmit_rto_prepare(
struct tcp_pcb *pcb)
1637 struct tcp_seg *seg;
1639 LWIP_ASSERT(
"tcp_rexmit_rto_prepare: invalid pcb", pcb != NULL);
1641 if (pcb->unacked == NULL) {
1649 for (seg = pcb->unacked; seg->next != NULL; seg = seg->next) {
1650 if (tcp_output_segment_busy(seg)) {
1651 LWIP_DEBUGF(
TCP_RTO_DEBUG, (
"tcp_rexmit_rto: segment busy\n"));
1655 if (tcp_output_segment_busy(seg)) {
1656 LWIP_DEBUGF(
TCP_RTO_DEBUG, (
"tcp_rexmit_rto: segment busy\n"));
1660 seg->next = pcb->unsent;
1661#if TCP_OVERSIZE_DBGCHECK
1663 if (pcb->unsent == NULL) {
1664 pcb->unsent_oversize = seg->oversize_left;
1668 pcb->unsent = pcb->unacked;
1670 pcb->unacked = NULL;
1673 tcp_set_flags(pcb, TF_RTO);
1675 pcb->rto_end = lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);
1690tcp_rexmit_rto_commit(
struct tcp_pcb *pcb)
1692 LWIP_ASSERT(
"tcp_rexmit_rto_commit: invalid pcb", pcb != NULL);
1695 if (pcb->nrtx < 0xFF) {
1711tcp_rexmit_rto(
struct tcp_pcb *pcb)
1713 LWIP_ASSERT(
"tcp_rexmit_rto: invalid pcb", pcb != NULL);
1715 if (tcp_rexmit_rto_prepare(pcb) ==
ERR_OK) {
1716 tcp_rexmit_rto_commit(pcb);
1728tcp_rexmit(
struct tcp_pcb *pcb)
1730 struct tcp_seg *seg;
1731 struct tcp_seg **cur_seg;
1733 LWIP_ASSERT(
"tcp_rexmit: invalid pcb", pcb != NULL);
1735 if (pcb->unacked == NULL) {
1743 if (tcp_output_segment_busy(seg)) {
1750 pcb->unacked = seg->next;
1752 cur_seg = &(pcb->unsent);
1754 TCP_SEQ_LT(lwip_ntohl((*cur_seg)->tcphdr->seqno), lwip_ntohl(seg->tcphdr->seqno))) {
1755 cur_seg = &((*cur_seg)->next );
1757 seg->next = *cur_seg;
1760 if (seg->next == NULL) {
1762 pcb->unsent_oversize = 0;
1766 if (pcb->nrtx < 0xFF) {
1774 MIB2_STATS_INC(mib2.tcpretranssegs);
1787tcp_rexmit_fast(
struct tcp_pcb *pcb)
1789 LWIP_ASSERT(
"tcp_rexmit_fast: invalid pcb", pcb != NULL);
1791 if (pcb->unacked != NULL && !(pcb->flags & TF_INFR)) {
1794 (
"tcp_receive: dupacks %"U16_F
" (%"U32_F
1795 "), fast retransmit %"U32_F
"\n",
1796 (u16_t)pcb->dupacks, pcb->lastack,
1797 lwip_ntohl(pcb->unacked->tcphdr->seqno)));
1798 if (tcp_rexmit(pcb) ==
ERR_OK) {
1801 pcb->ssthresh = LWIP_MIN(pcb->cwnd, pcb->snd_wnd) / 2;
1804 if (pcb->ssthresh < (2U * pcb->mss)) {
1806 (
"tcp_receive: The minimum value for ssthresh %"TCPWNDSIZE_F
1807 " should be min 2 mss %"U16_F
"...\n",
1808 pcb->ssthresh, (u16_t)(2 * pcb->mss)));
1809 pcb->ssthresh = 2 * pcb->mss;
1812 pcb->cwnd = pcb->ssthresh + 3 * pcb->mss;
1813 tcp_set_flags(pcb, TF_INFR);
1822tcp_output_alloc_header_common(u32_t ackno, u16_t optlen, u16_t datalen,
1824 u16_t src_port, u16_t dst_port, u8_t flags, u16_t wnd)
1831 LWIP_ASSERT(
"check that first pbuf can hold struct tcp_hdr",
1832 (p->len >= TCP_HLEN + optlen));
1833 tcphdr = (
struct tcp_hdr *)p->payload;
1834 tcphdr->src = lwip_htons(src_port);
1835 tcphdr->dest = lwip_htons(dst_port);
1836 tcphdr->seqno = seqno_be;
1837 tcphdr->ackno = lwip_htonl(ackno);
1838 TCPH_HDRLEN_FLAGS_SET(tcphdr, (5 + optlen / 4), flags);
1839 tcphdr->wnd = lwip_htons(wnd);
1857tcp_output_alloc_header(
struct tcp_pcb *pcb, u16_t optlen, u16_t datalen,
1862 LWIP_ASSERT(
"tcp_output_alloc_header: invalid pcb", pcb != NULL);
1864 p = tcp_output_alloc_header_common(pcb->rcv_nxt, optlen, datalen,
1865 seqno_be, pcb->local_port, pcb->remote_port, TCP_ACK,
1866 TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd)));
1869 pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
1876tcp_output_fill_options(
const struct tcp_pcb *pcb,
struct pbuf *p, u8_t optflags, u8_t num_sacks)
1880 u16_t sacks_len = 0;
1882 LWIP_ASSERT(
"tcp_output_fill_options: invalid pbuf", p != NULL);
1884 tcphdr = (
struct tcp_hdr *)p->payload;
1885 opts = (u32_t *)(
void *)(tcphdr + 1);
1889#if LWIP_TCP_TIMESTAMPS
1890 if (optflags & TF_SEG_OPTS_TS) {
1891 tcp_build_timestamp_option(pcb, opts);
1896#if LWIP_TCP_SACK_OUT
1897 if (pcb && (num_sacks > 0)) {
1898 tcp_build_sack_option(pcb, opts, num_sacks);
1900 sacks_len = 1 + num_sacks * 2;
1907#ifdef LWIP_HOOK_TCP_OUT_ADD_TCPOPTS
1908 opts = LWIP_HOOK_TCP_OUT_ADD_TCPOPTS(p, tcphdr, pcb, opts);
1913 LWIP_ASSERT(
"options not filled", (u8_t *)opts == ((u8_t *)(tcphdr + 1)) + sacks_len * 4 + LWIP_TCP_OPT_LENGTH_SEGMENT(optflags, pcb));
1925tcp_output_control_segment(
const struct tcp_pcb *pcb,
struct pbuf *p,
1926 const ip_addr_t *src,
const ip_addr_t *dst)
1930 LWIP_ASSERT(
"tcp_output_control_segment: invalid pbuf", p != NULL);
1932 netif = tcp_route(pcb, src, dst);
1933 if (
netif == NULL) {
1937 return tcp_output_control_segment_netif(pcb, p, src, dst,
netif);
1946tcp_output_control_segment_netif(
const struct tcp_pcb *pcb,
struct pbuf *p,
1947 const ip_addr_t *src,
const ip_addr_t *dst,
1953 LWIP_ASSERT(
"tcp_output_control_segment_netif: no netif given",
netif != NULL);
1956 IF__NETIF_CHECKSUM_ENABLED(
netif, NETIF_CHECKSUM_GEN_TCP) {
1958 tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len,
1971 TCP_STATS_INC(tcp.xmit);
1972 err = ip_output_if(p, src, dst, ttl, tos, IP_PROTO_TCP,
netif);
1973 NETIF_RESET_HINTS(
netif);
1980tcp_rst_common(
const struct tcp_pcb *pcb, u32_t seqno, u32_t ackno,
1981 const ip_addr_t *local_ip,
const ip_addr_t *remote_ip,
1982 u16_t local_port, u16_t remote_port)
1988 LWIP_ASSERT(
"tcp_rst: invalid local_ip", local_ip != NULL);
1989 LWIP_ASSERT(
"tcp_rst: invalid remote_ip", remote_ip != NULL);
1994 optlen = LWIP_TCP_OPT_LENGTH_SEGMENT(0, pcb);
1997 wnd = PP_HTONS(((TCP_WND >> TCP_RCV_SCALE) & 0xFFFF));
1999 wnd = PP_HTONS(TCP_WND);
2002 p = tcp_output_alloc_header_common(ackno, optlen, 0, lwip_htonl(seqno), local_port,
2003 remote_port, TCP_RST | TCP_ACK, wnd);
2005 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_rst: could not allocate memory for pbuf\n"));
2008 tcp_output_fill_options(pcb, p, 0, 0);
2010 MIB2_STATS_INC(mib2.tcpoutrsts);
2012 LWIP_DEBUGF(
TCP_RST_DEBUG, (
"tcp_rst: seqno %"U32_F
" ackno %"U32_F
".\n", seqno, ackno));
2037tcp_rst(
const struct tcp_pcb *pcb, u32_t seqno, u32_t ackno,
2038 const ip_addr_t *local_ip,
const ip_addr_t *remote_ip,
2039 u16_t local_port, u16_t remote_port)
2043 p = tcp_rst_common(pcb, seqno, ackno, local_ip, remote_ip, local_port, remote_port);
2045 tcp_output_control_segment(pcb, p, local_ip, remote_ip);
2069tcp_rst_netif(
struct netif *
netif, u32_t seqno, u32_t ackno,
2070 const ip_addr_t *local_ip,
const ip_addr_t *remote_ip,
2071 u16_t local_port, u16_t remote_port)
2074 struct pbuf *p = tcp_rst_common(NULL, seqno, ackno, local_ip, remote_ip, local_port, remote_port);
2076 tcp_output_control_segment_netif(NULL, p, local_ip, remote_ip,
netif);
2089tcp_send_empty_ack(
struct tcp_pcb *pcb)
2093 u8_t optlen, optflags = 0;
2096 LWIP_ASSERT(
"tcp_send_empty_ack: invalid pcb", pcb != NULL);
2098#if LWIP_TCP_TIMESTAMPS
2099 if (pcb->flags & TF_TIMESTAMP) {
2100 optflags = TF_SEG_OPTS_TS;
2103 optlen = LWIP_TCP_OPT_LENGTH_SEGMENT(optflags, pcb);
2105#if LWIP_TCP_SACK_OUT
2107 if ((num_sacks = tcp_get_num_sacks(pcb, optlen)) > 0) {
2108 optlen += 4 + num_sacks * 8;
2112 p = tcp_output_alloc_header(pcb, optlen, 0, lwip_htonl(pcb->snd_nxt));
2115 tcp_set_flags(pcb, TF_ACK_DELAY | TF_ACK_NOW);
2116 LWIP_DEBUGF(
TCP_OUTPUT_DEBUG, (
"tcp_output: (ACK) could not allocate pbuf\n"));
2119 tcp_output_fill_options(pcb, p, optflags, num_sacks);
2121#if LWIP_TCP_TIMESTAMPS
2122 pcb->ts_lastacksent = pcb->rcv_nxt;
2126 (
"tcp_output: sending ACK for %"U32_F
"\n", pcb->rcv_nxt));
2127 err = tcp_output_control_segment(pcb, p, &pcb->local_ip, &pcb->remote_ip);
2130 tcp_set_flags(pcb, TF_ACK_DELAY | TF_ACK_NOW);
2133 tcp_clear_flags(pcb, TF_ACK_DELAY | TF_ACK_NOW);
2148tcp_keepalive(
struct tcp_pcb *pcb)
2152 u8_t optlen = LWIP_TCP_OPT_LENGTH_SEGMENT(0, pcb);
2154 LWIP_ASSERT(
"tcp_keepalive: invalid pcb", pcb != NULL);
2156 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_keepalive: sending KEEPALIVE probe to "));
2157 ip_addr_debug_print_val(
TCP_DEBUG, pcb->remote_ip);
2160 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_keepalive: tcp_ticks %"U32_F
" pcb->tmr %"U32_F
" pcb->keep_cnt_sent %"U16_F
"\n",
2161 tcp_ticks, pcb->tmr, (u16_t)pcb->keep_cnt_sent));
2163 p = tcp_output_alloc_header(pcb, optlen, 0, lwip_htonl(pcb->snd_nxt - 1));
2166 (
"tcp_keepalive: could not allocate memory for pbuf\n"));
2169 tcp_output_fill_options(pcb, p, 0, 0);
2170 err = tcp_output_control_segment(pcb, p, &pcb->local_ip, &pcb->remote_ip);
2172 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_keepalive: seqno %"U32_F
" ackno %"U32_F
" err %d.\n",
2173 pcb->snd_nxt - 1, pcb->rcv_nxt, (
int)err));
2186tcp_zero_window_probe(
struct tcp_pcb *pcb)
2191 struct tcp_seg *seg;
2195 u8_t optlen = LWIP_TCP_OPT_LENGTH_SEGMENT(0, pcb);
2197 LWIP_ASSERT(
"tcp_zero_window_probe: invalid pcb", pcb != NULL);
2199 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_zero_window_probe: sending ZERO WINDOW probe to "));
2200 ip_addr_debug_print_val(
TCP_DEBUG, pcb->remote_ip);
2204 (
"tcp_zero_window_probe: tcp_ticks %"U32_F
2205 " pcb->tmr %"U32_F
" pcb->keep_cnt_sent %"U16_F
"\n",
2206 tcp_ticks, pcb->tmr, (u16_t)pcb->keep_cnt_sent));
2219 if (pcb->persist_probe < 0xFF) {
2220 ++pcb->persist_probe;
2223 is_fin = ((TCPH_FLAGS(seg->tcphdr) & TCP_FIN) != 0) && (seg->len == 0);
2225 len = is_fin ? 0 : 1;
2227 p = tcp_output_alloc_header(pcb, optlen, len, seg->tcphdr->seqno);
2229 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_zero_window_probe: no memory for pbuf\n"));
2232 tcphdr = (
struct tcp_hdr *)p->payload;
2236 TCPH_FLAGS_SET(tcphdr, TCP_ACK | TCP_FIN);
2239 char *d = ((
char *)p->payload + TCP_HLEN);
2247 snd_nxt = lwip_ntohl(seg->tcphdr->seqno) + 1;
2248 if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) {
2249 pcb->snd_nxt = snd_nxt;
2251 tcp_output_fill_options(pcb, p, 0, 0);
2253 err = tcp_output_control_segment(pcb, p, &pcb->local_ip, &pcb->remote_ip);
2255 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_zero_window_probe: seqno %"U32_F
2256 " ackno %"U32_F
" err %d.\n",
2257 pcb->snd_nxt - 1, pcb->rcv_nxt, (
int)err));
#define LWIP_UNUSED_ARG(x)
#define LWIP_CONST_CAST(target_type, val)
#define LWIP_MEM_ALIGN_SIZE(size)
#define LWIP_DBG_LEVEL_SERIOUS
#define LWIP_DBG_LEVEL_SEVERE
#define LWIP_ASSERT_CORE_LOCKED()
#define LWIP_TCP_MAX_SACK_NUM
struct netif * netif_get_by_index(u8_t idx)
void pbuf_cat(struct pbuf *head, struct pbuf *tail)
u8 pbuf_free(struct pbuf *p)
u16_t pbuf_copy_partial(const struct pbuf *p, void *dataptr, u16_t len, u16_t offset)
#define SWAP_BYTES_IN_WORD(w)
void * memp_malloc(memp_t type)
#define PBUF_TYPE_FLAG_DATA_VOLATILE
u8_t pbuf_add_header(struct pbuf *p, size_t header_size_increment)
#define PBUF_TYPE_FLAG_STRUCT_DATA_CONTIGUOUS