55 #if LWIP_TCP_TIMESTAMPS
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);
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)
77 #ifndef TCP_CHECKSUM_ON_COPY_SANITY_CHECK
78 #define TCP_CHECKSUM_ON_COPY_SANITY_CHECK 0
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)
89 #ifndef TCP_OVERSIZE_CALC_LENGTH
90 #define TCP_OVERSIZE_CALC_LENGTH(length) ((length) + TCP_OVERSIZE)
95 static err_t tcp_output_segment(
struct tcp_seg *seg,
struct tcp_pcb *pcb,
struct netif *
netif);
108 tcp_output_alloc_header(
struct tcp_pcb *pcb,
u16_t optlen,
u16_t datalen,
114 LWIP_ASSERT(
"check that first pbuf can hold struct tcp_hdr",
119 tcphdr->seqno = seqno_be;
122 tcphdr->wnd =
lwip_htons(TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd)));
127 pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
139 tcp_send_fin(
struct tcp_pcb *pcb)
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);
150 pcb->flags |= TF_FIN;
155 return tcp_enqueue_flags(pcb,
TCP_FIN);
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)
176 u8_t optlen = LWIP_TCP_OPT_LENGTH(optflags);
183 seg->flags = optflags;
187 seg->len = p->
tot_len - optlen;
188 #if TCP_OVERSIZE_DBGCHECK
189 seg->oversize_left = 0;
191 #if TCP_CHECKSUM_ON_COPY
193 seg->chksum_swapped = 0;
195 LWIP_ASSERT(
"invalid optflags passed: TF_SEG_DATA_CHECKSUMMED",
196 (optflags & TF_SEG_DATA_CHECKSUMMED) == 0);
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);
213 seg->tcphdr->urgp = 0;
234 u16_t *oversize,
struct tcp_pcb *pcb,
u8_t apiflags,
238 u16_t alloc = length;
240 #if LWIP_NETIF_TX_SINGLE_PBUF
247 if (length < max_length) {
259 if ((apiflags & TCP_WRITE_FLAG_MORE) ||
260 (!(pcb->flags & TF_NODELAY) &&
262 pcb->unsent !=
NULL ||
263 pcb->unacked !=
NULL))) {
273 *oversize = p->
len - length;
279 #define tcp_pbuf_prealloc(layer, length, mx, os, pcb, api, fst) pbuf_alloc((layer), (length), PBUF_RAM)
282 #if TCP_CHECKSUM_ON_COPY
286 u8_t *seg_chksum_swapped)
290 helper = chksum + *seg_chksum;
292 if ((
len & 1) != 0) {
293 *seg_chksum_swapped = 1 - *seg_chksum_swapped;
296 *seg_chksum = chksum;
307 tcp_write_checks(
struct tcp_pcb *pcb,
u16_t len)
310 if ((pcb->state != ESTABLISHED) &&
311 (pcb->state != CLOSE_WAIT) &&
312 (pcb->state != SYN_SENT) &&
313 (pcb->state != SYN_RCVD)) {
316 }
else if (
len == 0) {
321 if (
len > pcb->snd_buf) {
324 pcb->flags |= TF_NAGLEMEMERR;
333 if ((pcb->snd_queuelen >=
TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
337 pcb->flags |= TF_NAGLEMEMERR;
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);
344 LWIP_ASSERT(
"tcp_write: no pbufs on queue => both queues empty",
345 pcb->unacked ==
NULL && pcb->unsent ==
NULL);
368 tcp_write(
struct tcp_pcb *pcb,
const void *arg,
u16_t len,
u8_t apiflags)
371 struct tcp_seg *last_unsent =
NULL, *seg =
NULL, *prev_seg =
NULL, *queue =
NULL;
378 u16_t oversize_used = 0;
379 #if TCP_OVERSIZE_DBGCHECK
380 u16_t oversize_add = 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;
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;
394 #if LWIP_NETIF_TX_SINGLE_PBUF
396 apiflags |= TCP_WRITE_FLAG_COPY;
400 (
void *)pcb, arg, len, (
u16_t)apiflags));
401 LWIP_ERROR(
"tcp_write: arg == NULL (programmer violates API)",
404 err = tcp_write_checks(pcb, len);
408 queuelen = pcb->snd_queuelen;
410 #if LWIP_TCP_TIMESTAMPS
411 if ((pcb->flags & TF_TIMESTAMP)) {
414 optflags = TF_SEG_OPTS_TS;
415 optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS);
417 mss_local =
LWIP_MAX(mss_local, LWIP_TCP_OPT_LEN_TS + 1);
445 if (pcb->unsent !=
NULL) {
450 for (last_unsent = pcb->unsent; last_unsent->next !=
NULL;
451 last_unsent = last_unsent->next);
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);
466 #if TCP_OVERSIZE_DBGCHECK
468 LWIP_ASSERT(
"unsent_oversize mismatch (pcb vs. last_unsent)",
469 pcb->unsent_oversize == last_unsent->oversize_left);
471 oversize = pcb->unsent_oversize;
473 LWIP_ASSERT(
"inconsistent oversize vs. space", oversize <= space);
476 pos += oversize_used;
477 oversize -= oversize_used;
478 space -= oversize_used;
481 LWIP_ASSERT(
"inconsistent oversize vs. len", (oversize == 0) || (pos == len));
495 if ((pos < len) && (space > 0) && (last_unsent->len > 0)) {
502 if (apiflags & TCP_WRITE_FLAG_COPY) {
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",
510 #if TCP_OVERSIZE_DBGCHECK
511 oversize_add = oversize;
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;
524 LWIP_ASSERT(
"tcp_write: ROM pbufs cannot be oversized", pos == 0);
529 (
"tcp_write: could not allocate memory for zero-copy pbuf\n"));
533 ((
struct pbuf_rom*)concat_p)->payload = (
const u8_t*)arg + pos;
536 #if TCP_CHECKSUM_ON_COPY
538 tcp_seg_add_chksum(~
inet_chksum((
const u8_t*)arg + pos, seglen), seglen,
539 &concat_chksum, &concat_chksum_swapped);
540 concat_chksummed += seglen;
548 LWIP_ASSERT(
"unsent_oversize mismatch (pcb->unsent is NULL)",
549 pcb->unsent_oversize == 0);
562 u16_t max_len = mss_local - optlen;
564 #if TCP_CHECKSUM_ON_COPY
566 u8_t chksum_swapped = 0;
569 if (apiflags & TCP_WRITE_FLAG_COPY) {
572 if ((p = tcp_pbuf_prealloc(
PBUF_TRANSPORT, seglen + optlen, mss_local, &oversize, pcb, apiflags, queue ==
NULL)) ==
NULL) {
576 LWIP_ASSERT(
"tcp_write: check that first pbuf can hold the complete seglen",
578 TCP_DATA_COPY2((
char *)p->
payload + optlen, (
const u8_t*)arg + pos, seglen, &chksum, &chksum_swapped);
593 #if TCP_CHECKSUM_ON_COPY
602 ((
struct pbuf_rom*)p2)->payload = (
const u8_t*)arg + pos;
621 if ((queuelen >
TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
628 if ((seg = tcp_create_segment(pcb, p, 0, pcb->snd_lbb + pos, optflags)) ==
NULL) {
631 #if TCP_OVERSIZE_DBGCHECK
632 seg->oversize_left = oversize;
634 #if TCP_CHECKSUM_ON_COPY
635 seg->chksum = chksum;
636 seg->chksum_swapped = chksum_swapped;
637 seg->flags |= TF_SEG_DATA_CHECKSUMMED;
646 prev_seg->next = seg;
653 lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg)));
662 #if TCP_OVERSIZE_DBGCHECK
663 if ((last_unsent !=
NULL) && (oversize_add != 0)) {
664 last_unsent->oversize_left += oversize_add;
673 if (oversize_used > 0) {
676 for (p = last_unsent->p; p; p = p->
next) {
679 TCP_DATA_COPY((
char *)p->
payload + p->
len, arg, oversize_used, last_unsent);
680 p->
len += oversize_used;
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;
690 pcb->unsent_oversize = oversize;
697 if (concat_p !=
NULL) {
698 LWIP_ASSERT(
"tcp_write: cannot concatenate when pcb->unsent is empty",
699 (last_unsent !=
NULL));
701 last_unsent->len += concat_p->
tot_len;
702 }
else if (extendlen > 0) {
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) {
711 last_unsent->len += extendlen;
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);
719 if (concat_chksum_swapped) {
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;
732 if (last_unsent ==
NULL) {
735 last_unsent->next = queue;
743 pcb->snd_queuelen = queuelen;
747 if (pcb->snd_queuelen != 0) {
749 pcb->unacked !=
NULL || pcb->unsent !=
NULL);
753 if (seg !=
NULL && seg->tcphdr !=
NULL && ((apiflags & TCP_WRITE_FLAG_MORE)==0)) {
759 pcb->flags |= TF_NAGLEMEMERR;
762 if (concat_p !=
NULL) {
766 tcp_segs_free(queue);
768 if (pcb->snd_queuelen != 0) {
770 pcb->unsent !=
NULL);
785 tcp_enqueue_flags(
struct tcp_pcb *pcb,
u8_t flags)
794 LWIP_ASSERT(
"tcp_enqueue_flags: need either TCP_SYN or TCP_FIN in flags (programmer violates API)",
798 if (((pcb->snd_queuelen >=
TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) &&
803 pcb->flags |= TF_NAGLEMEMERR;
808 optflags = TF_SEG_OPTS_MSS;
810 if ((pcb->state != SYN_RCVD) || (pcb->flags & TF_WND_SCALE)) {
813 optflags |= TF_SEG_OPTS_WND_SCALE;
817 #if LWIP_TCP_TIMESTAMPS
818 if ((pcb->flags & TF_TIMESTAMP)) {
821 optflags |= TF_SEG_OPTS_TS;
824 optlen = LWIP_TCP_OPT_LENGTH(optflags);
828 pcb->flags |= TF_NAGLEMEMERR;
832 LWIP_ASSERT(
"tcp_enqueue_flags: check that first pbuf can hold optlen",
836 if ((seg = tcp_create_segment(pcb, p, flags, pcb->snd_lbb, optflags)) ==
NULL) {
837 pcb->flags |= TF_NAGLEMEMERR;
842 LWIP_ASSERT(
"tcp_enqueue_flags: invalid segment length", seg->len == 0);
847 lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
851 if (pcb->unsent ==
NULL) {
854 struct tcp_seg *useg;
855 for (useg = pcb->unsent; useg->next !=
NULL; useg = useg->next);
860 pcb->unsent_oversize = 0;
869 pcb->flags |= TF_FIN;
875 if (pcb->snd_queuelen != 0) {
876 LWIP_ASSERT(
"tcp_enqueue_flags: invalid queue length",
877 pcb->unacked !=
NULL || pcb->unsent !=
NULL);
883 #if LWIP_TCP_TIMESTAMPS
890 tcp_build_timestamp_option(
struct tcp_pcb *pcb,
u32_t *opts)
905 tcp_build_wnd_scale_option(
u32_t *opts)
918 tcp_send_empty_ack(
struct tcp_pcb *pcb)
924 #if LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP
928 #if LWIP_TCP_TIMESTAMPS
929 if (pcb->flags & TF_TIMESTAMP) {
930 optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS);
934 p = tcp_output_alloc_header(pcb, optlen, 0,
lwip_htonl(pcb->snd_nxt));
937 pcb->flags |= (TF_ACK_DELAY | TF_ACK_NOW);
941 #if LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP
945 (
"tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt));
948 #if LWIP_TCP_TIMESTAMPS
949 pcb->ts_lastacksent = pcb->rcv_nxt;
951 if (pcb->flags & TF_TIMESTAMP) {
952 tcp_build_timestamp_option(pcb, (
u32_t *)(tcphdr + 1));
956 netif = ip_route(&pcb->local_ip, &pcb->remote_ip);
963 &pcb->local_ip, &pcb->remote_ip);
967 err = ip_output_if(p, &pcb->local_ip, &pcb->remote_ip,
975 pcb->flags |= (TF_ACK_DELAY | TF_ACK_NOW);
978 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
993 tcp_output(
struct tcp_pcb *pcb)
995 struct tcp_seg *seg, *useg;
1004 LWIP_ASSERT(
"don't call tcp_output for listen-pcbs",
1005 pcb->state != LISTEN);
1011 if (tcp_input_pcb == pcb) {
1015 wnd =
LWIP_MIN(pcb->snd_wnd, pcb->cwnd);
1025 if (pcb->flags & TF_ACK_NOW &&
1027 lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
1028 return tcp_send_empty_ack(pcb);
1032 useg = pcb->unacked;
1034 for (; useg->next !=
NULL; useg = useg->next);
1037 netif = ip_route(&pcb->local_ip, &pcb->remote_ip);
1044 const ip_addr_t *local_ip = ip_netif_get_local_ip(
netif, &pcb->remote_ip);
1045 if (local_ip ==
NULL) {
1051 #if TCP_OUTPUT_DEBUG
1054 (
void*)pcb->unsent));
1060 ", cwnd %"TCPWNDSIZE_F
", wnd %"U32_F
1061 ", seg == NULL, ack %"U32_F"\n",
1062 pcb->snd_wnd, pcb->cwnd, wnd, pcb->lastack));
1065 (
"tcp_output: snd_wnd %"TCPWNDSIZE_F
", cwnd %"TCPWNDSIZE_F
", wnd %"U32_F
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));
1081 lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd &&
1082 wnd > 0 && wnd == pcb->snd_wnd && pcb->unacked ==
NULL) {
1084 if (pcb->persist_backoff == 0) {
1085 pcb->persist_cnt = 0;
1086 pcb->persist_backoff = 1;
1091 while (seg !=
NULL &&
1092 lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
1102 if ((tcp_do_output_nagle(pcb) == 0) &&
1103 ((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)) {
1108 pcb->snd_wnd, pcb->cwnd, wnd,
1111 lwip_ntohl(seg->tcphdr->seqno), pcb->lastack, i));
1115 if (pcb->state != SYN_SENT) {
1119 #if TCP_OVERSIZE_DBGCHECK
1120 seg->oversize_left = 0;
1122 err = tcp_output_segment(seg, pcb,
netif);
1125 pcb->flags |= TF_NAGLEMEMERR;
1128 pcb->unsent = seg->next;
1129 if (pcb->state != SYN_SENT) {
1130 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
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;
1137 if (TCP_TCPLEN(seg) > 0) {
1140 if (pcb->unacked ==
NULL) {
1150 struct tcp_seg **cur_seg = &(pcb->unacked);
1153 cur_seg = &((*cur_seg)->next );
1155 seg->next = (*cur_seg);
1171 if (pcb->unsent ==
NULL) {
1173 pcb->unsent_oversize = 0;
1177 pcb->flags &= ~TF_NAGLEMEMERR;
1189 tcp_output_segment(
struct tcp_seg *seg,
struct tcp_pcb *pcb,
struct netif *
netif)
1195 if (seg->p->ref != 1) {
1204 seg->tcphdr->ackno =
lwip_htonl(pcb->rcv_nxt);
1208 if (seg->flags & TF_SEG_OPTS_WND_SCALE) {
1211 seg->tcphdr->wnd =
lwip_htons(TCPWND_MIN16(pcb->rcv_ann_wnd));
1215 seg->tcphdr->wnd =
lwip_htons(TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd)));
1218 pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
1223 opts = (
u32_t *)(
void *)(seg->tcphdr + 1);
1224 if (seg->flags & TF_SEG_OPTS_MSS) {
1226 #if TCP_CALCULATE_EFF_SEND_MSS
1227 mss = tcp_eff_send_mss(
TCP_MSS, &pcb->local_ip, &pcb->remote_ip);
1231 *opts = TCP_BUILD_MSS_OPTION(mss);
1234 #if LWIP_TCP_TIMESTAMPS
1235 pcb->ts_lastacksent = pcb->rcv_nxt;
1237 if (seg->flags & TF_SEG_OPTS_TS) {
1238 tcp_build_timestamp_option(pcb, opts);
1243 if (seg->flags & TF_SEG_OPTS_WND_SCALE) {
1244 tcp_build_wnd_scale_option(opts);
1251 if (pcb->rtime < 0) {
1255 if (pcb->rttest == 0) {
1256 pcb->rttest = tcp_ticks;
1265 len = (
u16_t)((
u8_t *)seg->tcphdr - (
u8_t *)seg->p->payload);
1272 seg->p->tot_len -= len;
1274 seg->p->payload = seg->tcphdr;
1276 seg->tcphdr->chksum = 0;
1277 #if CHECKSUM_GEN_TCP
1279 #if TCP_CHECKSUM_ON_COPY
1281 #if TCP_CHECKSUM_ON_COPY_SANITY_CHECK
1283 seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip);
1285 if ((seg->flags & TF_SEG_DATA_CHECKSUMMED) == 0) {
1287 seg->p->tot_len == (
TCPH_HDRLEN(seg->tcphdr) * 4));
1292 seg->p->tot_len,
TCPH_HDRLEN(seg->tcphdr) * 4, &pcb->local_ip, &pcb->remote_ip);
1294 if (seg->chksum_swapped) {
1296 seg->chksum_swapped = 0;
1298 acc += (
u16_t)~(seg->chksum);
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;
1310 seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip);
1317 err = ip_output_if(seg->p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl,
1356 LWIP_ASSERT(
"check that first pbuf can hold struct tcp_hdr",
1376 netif = ip_route(local_ip, remote_ip);
1378 #if CHECKSUM_GEN_TCP
1381 local_ip, remote_ip);
1399 tcp_rexmit_rto(
struct tcp_pcb *pcb)
1401 struct tcp_seg *seg;
1403 if (pcb->unacked ==
NULL) {
1408 for (seg = pcb->unacked; seg->next !=
NULL; seg = seg->next);
1410 seg->next = pcb->unsent;
1411 #if TCP_OVERSIZE_DBGCHECK
1413 if (pcb->unsent ==
NULL) {
1414 pcb->unsent_oversize = seg->oversize_left;
1418 pcb->unsent = pcb->unacked;
1420 pcb->unacked =
NULL;
1423 if (pcb->nrtx < 0xFF) {
1442 tcp_rexmit(
struct tcp_pcb *pcb)
1444 struct tcp_seg *seg;
1445 struct tcp_seg **cur_seg;
1447 if (pcb->unacked ==
NULL) {
1454 pcb->unacked = seg->next;
1456 cur_seg = &(pcb->unsent);
1459 cur_seg = &((*cur_seg)->next );
1461 seg->next = *cur_seg;
1464 if (seg->next ==
NULL) {
1466 pcb->unsent_oversize = 0;
1470 if (pcb->nrtx < 0xFF) {
1490 tcp_rexmit_fast(
struct tcp_pcb *pcb)
1492 if (pcb->unacked !=
NULL && !(pcb->flags & TF_INFR)) {
1496 "), fast retransmit %"U32_F"\n",
1497 (
u16_t)pcb->dupacks, pcb->lastack,
1503 pcb->ssthresh =
LWIP_MIN(pcb->cwnd, pcb->snd_wnd) / 2;
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;
1514 pcb->cwnd = pcb->ssthresh + 3 * pcb->mss;
1515 pcb->flags |= TF_INFR;
1532 tcp_keepalive(
struct tcp_pcb *pcb)
1543 tcp_ticks, pcb->tmr, (
u16_t)pcb->keep_cnt_sent));
1545 p = tcp_output_alloc_header(pcb, 0, 0,
lwip_htonl(pcb->snd_nxt - 1));
1548 (
"tcp_keepalive: could not allocate memory for pbuf\n"));
1551 netif = ip_route(&pcb->local_ip, &pcb->remote_ip);
1555 #if CHECKSUM_GEN_TCP
1559 &pcb->local_ip, &pcb->remote_ip);
1566 err = ip_output_if(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0,
IP_PROTO_TCP,
netif);
1572 pcb->snd_nxt - 1, pcb->rcv_nxt, (
int)err));
1586 tcp_zero_window_probe(
struct tcp_pcb *pcb)
1591 struct tcp_seg *seg;
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));
1618 len = is_fin ? 0 : 1;
1620 p = tcp_output_alloc_header(pcb, 0, len, seg->tcphdr->seqno);
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;
1645 netif = ip_route(&pcb->local_ip, &pcb->remote_ip);
1649 #if CHECKSUM_GEN_TCP
1652 &pcb->local_ip, &pcb->remote_ip);
1659 err = ip_output_if(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl,
1667 " ackno %"U32_F" err %d.\n",
1668 pcb->snd_nxt - 1, pcb->rcv_nxt, (
int)err));