65 #if TCP_CHECKSUM_ON_COPY 66 #define TCP_DATA_COPY(dst, src, len, seg) do { \ 67 tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), \ 68 len, &seg->chksum, &seg->chksum_swapped); \ 69 seg->flags |= TF_SEG_DATA_CHECKSUMMED; } while(0) 70 #define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) \ 71 tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), len, chksum, chksum_swapped); 73 #define TCP_DATA_COPY(dst, src, len, seg) MEMCPY(dst, src, len) 74 #define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) MEMCPY(dst, src, len) 79 #ifndef TCP_CHECKSUM_ON_COPY_SANITY_CHECK 80 #define TCP_CHECKSUM_ON_COPY_SANITY_CHECK 0 84 static void tcp_output_segment(
struct tcp_seg *seg,
struct tcp_pcb *pcb);
97 tcp_output_alloc_header(
struct tcp_pcb *pcb,
u16_t optlen,
u16_t datalen,
100 struct tcp_hdr *tcphdr;
103 LWIP_ASSERT(
"check that first pbuf can hold struct tcp_hdr",
104 (p->
len >= TCP_HLEN + optlen));
105 tcphdr = (
struct tcp_hdr *)p->
payload;
106 tcphdr->src =
htons(pcb->local_port);
107 tcphdr->dest =
htons(pcb->remote_port);
108 tcphdr->seqno = seqno_be;
109 tcphdr->ackno =
htonl(pcb->rcv_nxt);
110 TCPH_HDRLEN_FLAGS_SET(tcphdr, (5 + optlen / 4), TCP_ACK);
111 tcphdr->wnd =
htons(pcb->rcv_ann_wnd);
116 pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
128 tcp_send_fin(
struct tcp_pcb *pcb)
131 if (pcb->unsent !=
NULL) {
132 struct tcp_seg *last_unsent;
133 for (last_unsent = pcb->unsent; last_unsent->next !=
NULL;
134 last_unsent = last_unsent->next);
136 if ((TCPH_FLAGS(last_unsent->tcphdr) & (TCP_SYN | TCP_FIN | TCP_RST)) == 0) {
138 TCPH_SET_FLAG(last_unsent->tcphdr, TCP_FIN);
143 return tcp_enqueue_flags(pcb, TCP_FIN);
161 tcp_create_segment(
struct tcp_pcb *pcb,
struct pbuf *p,
u8_t flags,
u32_t seqno,
u8_t optflags)
164 u8_t optlen = LWIP_TCP_OPT_LENGTH(optflags);
171 seg->flags = optflags;
175 #if TCP_OVERSIZE_DBGCHECK 176 seg->oversize_left = 0;
178 #if TCP_CHECKSUM_ON_COPY 180 seg->chksum_swapped = 0;
182 LWIP_ASSERT(
"invalid optflags passed: TF_SEG_DATA_CHECKSUMMED",
183 (optflags & TF_SEG_DATA_CHECKSUMMED) == 0);
193 seg->tcphdr = (
struct tcp_hdr *)seg->p->payload;
194 seg->tcphdr->src =
htons(pcb->local_port);
195 seg->tcphdr->dest =
htons(pcb->remote_port);
196 seg->tcphdr->seqno =
htonl(seqno);
198 TCPH_HDRLEN_FLAGS_SET(seg->tcphdr, (5 + optlen / 4), flags);
200 seg->tcphdr->urgp = 0;
222 u16_t *oversize,
struct tcp_pcb *pcb,
u8_t apiflags,
226 u16_t alloc = length;
228 #if LWIP_NETIF_TX_SINGLE_PBUF 236 if (length < max_length) {
248 if ((apiflags & TCP_WRITE_FLAG_MORE) ||
249 (!(pcb->flags & TF_NODELAY) &&
251 pcb->unsent !=
NULL ||
252 pcb->unacked !=
NULL))) {
262 *oversize = p->
len - length;
268 #define tcp_pbuf_prealloc(layer, length, mx, os, pcb, api, fst) pbuf_alloc((layer), (length), PBUF_RAM) 271 #if TCP_CHECKSUM_ON_COPY 275 u8_t *seg_chksum_swapped)
279 helper = chksum + *seg_chksum;
281 if ((len & 1) != 0) {
282 *seg_chksum_swapped = 1 - *seg_chksum_swapped;
285 *seg_chksum = chksum;
296 tcp_write_checks(
struct tcp_pcb *pcb,
u16_t len)
299 if ((pcb->state != ESTABLISHED) &&
300 (pcb->state != CLOSE_WAIT) &&
301 (pcb->state != SYN_SENT) &&
302 (pcb->state != SYN_RCVD)) {
305 }
else if (len == 0) {
310 if (len > pcb->snd_buf) {
313 pcb->flags |= TF_NAGLEMEMERR;
322 if ((pcb->snd_queuelen >=
TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
326 pcb->flags |= TF_NAGLEMEMERR;
329 if (pcb->snd_queuelen != 0) {
330 LWIP_ASSERT(
"tcp_write: pbufs on queue => at least one queue non-empty",
331 pcb->unacked !=
NULL || pcb->unsent !=
NULL);
333 LWIP_ASSERT(
"tcp_write: no pbufs on queue => both queues empty",
334 pcb->unacked ==
NULL && pcb->unsent ==
NULL);
356 tcp_write(
struct tcp_pcb *pcb,
const void *arg,
u16_t len,
u8_t apiflags)
359 struct tcp_seg *last_unsent =
NULL, *seg =
NULL, *prev_seg =
NULL, *queue =
NULL;
366 u16_t oversize_used = 0;
368 #if TCP_CHECKSUM_ON_COPY 369 u16_t concat_chksum = 0;
370 u8_t concat_chksum_swapped = 0;
371 u16_t concat_chksummed = 0;
375 #if LWIP_NETIF_TX_SINGLE_PBUF 377 apiflags |= TCP_WRITE_FLAG_COPY;
381 (
void *)pcb, arg, len, (
u16_t)apiflags));
382 LWIP_ERROR(
"tcp_write: arg == NULL (programmer violates API)",
385 err = tcp_write_checks(pcb, len);
389 queuelen = pcb->snd_queuelen;
391 #if LWIP_TCP_TIMESTAMPS 392 if ((pcb->flags & TF_TIMESTAMP)) {
393 optflags = TF_SEG_OPTS_TS;
394 optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS);
422 if (pcb->unsent !=
NULL) {
427 for (last_unsent = pcb->unsent; last_unsent->next !=
NULL;
428 last_unsent = last_unsent->next);
431 unsent_optlen = LWIP_TCP_OPT_LENGTH(last_unsent->flags);
432 space = pcb->mss - (last_unsent->len + unsent_optlen);
442 #if TCP_OVERSIZE_DBGCHECK 444 LWIP_ASSERT(
"unsent_oversize mismatch (pcb vs. last_unsent)",
445 pcb->unsent_oversize == last_unsent->oversize_left);
447 oversize = pcb->unsent_oversize;
449 LWIP_ASSERT(
"inconsistent oversize vs. space", oversize_used <= space);
451 oversize_used = oversize < len ? oversize : len;
452 pos += oversize_used;
453 oversize -= oversize_used;
454 space -= oversize_used;
457 LWIP_ASSERT(
"inconsistend oversize vs. len", (oversize == 0) || (pos == len));
467 if ((pos < len) && (space > 0) && (last_unsent->len > 0)) {
468 u16_t seglen = space < len - pos ? space : len - pos;
474 if (apiflags & TCP_WRITE_FLAG_COPY) {
476 if ((concat_p = tcp_pbuf_prealloc(
PBUF_RAW, seglen, space, &oversize, pcb, apiflags, 1)) ==
NULL) {
478 (
"tcp_write : could not allocate memory for pbuf copy size %"U16_F
"\n",
482 #if TCP_OVERSIZE_DBGCHECK 483 last_unsent->oversize_left = oversize;
485 TCP_DATA_COPY2(concat_p->
payload, (
u8_t*)arg + pos, seglen, &concat_chksum, &concat_chksum_swapped);
486 #if TCP_CHECKSUM_ON_COPY 487 concat_chksummed += seglen;
493 (
"tcp_write: could not allocate memory for zero-copy pbuf\n"));
496 #if TCP_CHECKSUM_ON_COPY 499 &concat_chksum, &concat_chksum_swapped);
500 concat_chksummed += seglen;
511 LWIP_ASSERT(
"unsent_oversize mismatch (pcb->unsent is NULL)",
512 pcb->unsent_oversize == 0);
524 u16_t left = len - pos;
525 u16_t max_len = pcb->mss - optlen;
526 u16_t seglen = left > max_len ? max_len : left;
527 #if TCP_CHECKSUM_ON_COPY 529 u8_t chksum_swapped = 0;
532 if (apiflags & TCP_WRITE_FLAG_COPY) {
535 if ((p = tcp_pbuf_prealloc(
PBUF_TRANSPORT, seglen + optlen, pcb->mss, &oversize, pcb, apiflags, queue ==
NULL)) ==
NULL) {
539 LWIP_ASSERT(
"tcp_write: check that first pbuf can hold the complete seglen",
541 TCP_DATA_COPY2((
char *)p->
payload + optlen, (
u8_t*)arg + pos, seglen, &chksum, &chksum_swapped);
556 #if TCP_CHECKSUM_ON_COPY 580 if ((queuelen >
TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
586 if ((seg = tcp_create_segment(pcb, p, 0, pcb->snd_lbb + pos, optflags)) ==
NULL) {
589 #if TCP_OVERSIZE_DBGCHECK 590 seg->oversize_left = oversize;
592 #if TCP_CHECKSUM_ON_COPY 593 seg->chksum = chksum;
594 seg->chksum_swapped = chksum_swapped;
595 seg->flags |= TF_SEG_DATA_CHECKSUMMED;
604 prev_seg->next = seg;
610 ntohl(seg->tcphdr->seqno),
611 ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg)));
626 if (oversize_used > 0) {
629 for (p = last_unsent->p; p; p = p->
next) {
632 TCP_DATA_COPY((
char *)p->
payload + p->
len, arg, oversize_used, last_unsent);
633 p->
len += oversize_used;
636 last_unsent->len += oversize_used;
637 #if TCP_OVERSIZE_DBGCHECK 638 last_unsent->oversize_left -= oversize_used;
641 pcb->unsent_oversize = oversize;
647 if (concat_p !=
NULL) {
648 LWIP_ASSERT(
"tcp_write: cannot concatenate when pcb->unsent is empty",
649 (last_unsent !=
NULL));
651 last_unsent->len += concat_p->
tot_len;
652 #if TCP_CHECKSUM_ON_COPY 653 if (concat_chksummed) {
654 tcp_seg_add_chksum(concat_chksum, concat_chksummed, &last_unsent->chksum,
655 &last_unsent->chksum_swapped);
656 last_unsent->flags |= TF_SEG_DATA_CHECKSUMMED;
665 if (last_unsent ==
NULL) {
668 last_unsent->next = queue;
676 pcb->snd_queuelen = queuelen;
680 if (pcb->snd_queuelen != 0) {
682 pcb->unacked !=
NULL || pcb->unsent !=
NULL);
686 if (seg !=
NULL && seg->tcphdr !=
NULL && ((apiflags & TCP_WRITE_FLAG_MORE)==0)) {
687 TCPH_SET_FLAG(seg->tcphdr, TCP_PSH);
692 pcb->flags |= TF_NAGLEMEMERR;
695 if (concat_p !=
NULL) {
699 tcp_segs_free(queue);
701 if (pcb->snd_queuelen != 0) {
703 pcb->unsent !=
NULL);
720 tcp_enqueue_flags(
struct tcp_pcb *pcb,
u8_t flags)
729 LWIP_ASSERT(
"tcp_enqueue_flags: need either TCP_SYN or TCP_FIN in flags (programmer violates API)",
730 (flags & (TCP_SYN | TCP_FIN)) != 0);
733 if ((pcb->snd_queuelen >=
TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
737 pcb->flags |= TF_NAGLEMEMERR;
741 if (flags & TCP_SYN) {
742 optflags = TF_SEG_OPTS_MSS;
744 #if LWIP_TCP_TIMESTAMPS 745 if ((pcb->flags & TF_TIMESTAMP)) {
746 optflags |= TF_SEG_OPTS_TS;
749 optlen = LWIP_TCP_OPT_LENGTH(optflags);
755 if (pcb->snd_buf == 0) {
763 pcb->flags |= TF_NAGLEMEMERR;
767 LWIP_ASSERT(
"tcp_enqueue_flags: check that first pbuf can hold optlen",
771 if ((seg = tcp_create_segment(pcb, p, flags, pcb->snd_lbb, optflags)) ==
NULL) {
772 pcb->flags |= TF_NAGLEMEMERR;
777 LWIP_ASSERT(
"tcp_enqueue_flags: invalid segment length", seg->len == 0);
780 (
"tcp_enqueue_flags: queueing %"U32_F
":%"U32_F
" (0x%"X16_F")\n",
781 ntohl(seg->tcphdr->seqno),
782 ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
786 if (pcb->unsent ==
NULL) {
789 struct tcp_seg *useg;
790 for (useg = pcb->unsent; useg->next !=
NULL; useg = useg->next);
795 pcb->unsent_oversize = 0;
799 if ((flags & TCP_SYN) || (flags & TCP_FIN)) {
804 if (flags & TCP_FIN) {
805 pcb->flags |= TF_FIN;
811 if (pcb->snd_queuelen != 0) {
812 LWIP_ASSERT(
"tcp_enqueue_flags: invalid queue length",
813 pcb->unacked !=
NULL || pcb->unsent !=
NULL);
820 #if LWIP_TCP_TIMESTAMPS 827 tcp_build_timestamp_option(
struct tcp_pcb *pcb,
u32_t *opts)
832 opts[2] =
htonl(pcb->ts_recent);
841 tcp_send_empty_ack(
struct tcp_pcb *pcb)
844 struct tcp_hdr *tcphdr;
847 #if LWIP_TCP_TIMESTAMPS 848 if (pcb->flags & TF_TIMESTAMP) {
849 optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS);
853 p = tcp_output_alloc_header(pcb, optlen, 0,
htonl(pcb->snd_nxt));
858 tcphdr = (
struct tcp_hdr *)p->
payload;
860 (
"tcp_output: sending ACK for %"U32_F
"\n", pcb->rcv_nxt));
862 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
865 #if LWIP_TCP_TIMESTAMPS 866 pcb->ts_lastacksent = pcb->rcv_nxt;
868 if (pcb->flags & TF_TIMESTAMP) {
869 tcp_build_timestamp_option(pcb, (
u32_t *)(tcphdr + 1));
877 #if LWIP_NETIF_HWADDRHINT 878 ip_output_hinted(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
881 ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
897 tcp_output(
struct tcp_pcb *pcb)
899 struct tcp_seg *seg, *useg;
908 if (tcp_input_pcb == pcb) {
912 wnd =
LWIP_MIN(pcb->snd_wnd, pcb->cwnd);
922 if (pcb->flags & TF_ACK_NOW &&
924 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
925 return tcp_send_empty_ack(pcb);
931 for (; useg->next !=
NULL; useg = useg->next);
937 (
void*)pcb->unsent));
943 ", cwnd %"U16_F
", wnd %"U32_F
944 ", seg == NULL, ack %"U32_F
"\n",
945 pcb->snd_wnd, pcb->cwnd, wnd, pcb->lastack));
948 (
"tcp_output: snd_wnd %"U16_F
", cwnd %"U16_F
", wnd %"U32_F
949 ", effwnd %"U32_F
", seq %"U32_F
", ack %"U32_F
"\n",
950 pcb->snd_wnd, pcb->cwnd, wnd,
951 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len,
952 ntohl(seg->tcphdr->seqno), pcb->lastack));
957 while (seg !=
NULL &&
958 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
960 (TCPH_FLAGS(seg->tcphdr) & TCP_RST) == 0);
968 if((tcp_do_output_nagle(pcb) == 0) &&
969 ((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)){
973 LWIP_DEBUGF(
TCP_CWND_DEBUG, (
"tcp_output: snd_wnd %"U16_F
", cwnd %"U16_F
", wnd %"U32_F
", effwnd %"U32_F
", seq %"U32_F
", ack %"U32_F
", i %"S16_F"\n",
974 pcb->snd_wnd, pcb->cwnd, wnd,
975 ntohl(seg->tcphdr->seqno) + seg->len -
977 ntohl(seg->tcphdr->seqno), pcb->lastack, i));
981 pcb->unsent = seg->next;
983 if (pcb->state != SYN_SENT) {
984 TCPH_SET_FLAG(seg->tcphdr, TCP_ACK);
985 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
988 tcp_output_segment(seg, pcb);
990 snd_nxt =
ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);
991 if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) {
992 pcb->snd_nxt = snd_nxt;
996 if (TCP_TCPLEN(seg) > 0) {
999 if (pcb->unacked ==
NULL) {
1008 if (TCP_SEQ_LT(
ntohl(seg->tcphdr->seqno),
ntohl(useg->tcphdr->seqno))) {
1010 struct tcp_seg **cur_seg = &(pcb->unacked);
1012 TCP_SEQ_LT(
ntohl((*cur_seg)->tcphdr->seqno),
ntohl(seg->tcphdr->seqno))) {
1013 cur_seg = &((*cur_seg)->next );
1015 seg->next = (*cur_seg);
1030 if (pcb->unsent ==
NULL) {
1032 pcb->unsent_oversize = 0;
1037 if (seg !=
NULL && pcb->persist_backoff == 0 &&
1038 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > pcb->snd_wnd) {
1040 pcb->persist_cnt = 0;
1041 pcb->persist_backoff = 1;
1044 pcb->flags &= ~TF_NAGLEMEMERR;
1056 tcp_output_segment(
struct tcp_seg *seg,
struct tcp_pcb *pcb)
1066 seg->tcphdr->ackno =
htonl(pcb->rcv_nxt);
1069 seg->tcphdr->wnd =
htons(pcb->rcv_ann_wnd);
1071 pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
1076 opts = (
u32_t *)(
void *)(seg->tcphdr + 1);
1077 if (seg->flags & TF_SEG_OPTS_MSS) {
1078 TCP_BUILD_MSS_OPTION(*opts);
1081 #if LWIP_TCP_TIMESTAMPS 1082 pcb->ts_lastacksent = pcb->rcv_nxt;
1084 if (seg->flags & TF_SEG_OPTS_TS) {
1085 tcp_build_timestamp_option(pcb, opts);
1092 if (pcb->rtime == -1) {
1099 netif =
ip_route(&(pcb->remote_ip));
1100 if (netif ==
NULL) {
1106 if (pcb->rttest == 0) {
1107 pcb->rttest = tcp_ticks;
1108 pcb->rtseq =
ntohl(seg->tcphdr->seqno);
1113 htonl(seg->tcphdr->seqno),
htonl(seg->tcphdr->seqno) +
1116 len = (
u16_t)((
u8_t *)seg->tcphdr - (
u8_t *)seg->p->payload);
1119 seg->p->tot_len -= len;
1121 seg->p->payload = seg->tcphdr;
1123 seg->tcphdr->chksum = 0;
1124 #if CHECKSUM_GEN_TCP 1125 #if TCP_CHECKSUM_ON_COPY 1128 #if TCP_CHECKSUM_ON_COPY_SANITY_CHECK 1133 if ((seg->flags & TF_SEG_DATA_CHECKSUMMED) == 0) {
1135 seg->p->tot_len == (TCPH_HDRLEN(seg->tcphdr) * 4));
1141 IP_PROTO_TCP, seg->p->tot_len, TCPH_HDRLEN(seg->tcphdr) * 4);
1143 if (seg->chksum_swapped) {
1145 seg->chksum_swapped = 0;
1147 acc += (
u16_t)~(seg->chksum);
1149 #if TCP_CHECKSUM_ON_COPY_SANITY_CHECK 1150 if (chksum_slow != seg->tcphdr->chksum) {
1152 (
"tcp_output_segment: calculated checksum is %"X16_F
" instead of %"X16_F
"\n",
1153 seg->tcphdr->chksum, chksum_slow));
1154 seg->tcphdr->chksum = chksum_slow;
1166 #if LWIP_NETIF_HWADDRHINT 1167 ip_output_hinted(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
1170 ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
1201 struct tcp_hdr *tcphdr;
1207 LWIP_ASSERT(
"check that first pbuf can hold struct tcp_hdr",
1208 (p->
len >=
sizeof(
struct tcp_hdr)));
1210 tcphdr = (
struct tcp_hdr *)p->
payload;
1211 tcphdr->src =
htons(local_port);
1212 tcphdr->dest =
htons(remote_port);
1213 tcphdr->seqno =
htonl(seqno);
1214 tcphdr->ackno =
htonl(ackno);
1215 TCPH_HDRLEN_FLAGS_SET(tcphdr, TCP_HLEN/4, TCP_RST | TCP_ACK);
1220 #if CHECKSUM_GEN_TCP 1240 tcp_rexmit_rto(
struct tcp_pcb *pcb)
1242 struct tcp_seg *seg;
1243 struct tcp_seg *t0_head =
NULL, *t0_tail =
NULL;
1244 struct tcp_seg *t1_head =
NULL, *t1_tail =
NULL;
1245 bool t0_1st =
true, t1_1st =
true;
1247 if (pcb->unacked ==
NULL) {
1253 while (seg !=
NULL) {
1256 t0_head = t0_tail = seg;
1259 t0_tail->next = seg;
1263 t0_tail->next =
NULL;
1266 t1_head = t1_tail = seg;
1269 t1_tail->next = seg;
1273 t1_tail->next =
NULL;
1276 if (t1_head && t1_tail) {
1277 t1_tail->next = pcb->unsent;
1278 pcb->unsent = t1_head;
1280 pcb->unacked = t0_head;
1285 for (seg = pcb->unacked; seg->next !=
NULL; seg = seg->next);
1287 seg->next = pcb->unsent;
1289 pcb->unsent = pcb->unacked;
1291 pcb->unacked =
NULL;
1312 tcp_rexmit(
struct tcp_pcb *pcb)
1314 struct tcp_seg *seg;
1315 struct tcp_seg **cur_seg;
1317 if (pcb->unacked ==
NULL) {
1324 pcb->unacked = seg->next;
1326 cur_seg = &(pcb->unsent);
1328 TCP_SEQ_LT(
ntohl((*cur_seg)->tcphdr->seqno),
ntohl(seg->tcphdr->seqno))) {
1329 cur_seg = &((*cur_seg)->next );
1331 seg->next = *cur_seg;
1352 tcp_rexmit_fast(
struct tcp_pcb *pcb)
1354 if (pcb->unacked !=
NULL && !(pcb->flags & TF_INFR)) {
1357 (
"tcp_receive: dupacks %"U16_F
" (%"U32_F
1358 "), fast retransmit %"U32_F
"\n",
1359 (
u16_t)pcb->dupacks, pcb->lastack,
1360 ntohl(pcb->unacked->tcphdr->seqno)));
1365 if (pcb->cwnd > pcb->snd_wnd) {
1366 pcb->ssthresh = pcb->snd_wnd / 2;
1368 pcb->ssthresh = pcb->cwnd / 2;
1372 if (pcb->ssthresh < 2*pcb->mss) {
1374 (
"tcp_receive: The minimum value for ssthresh %"U16_F
1375 " should be min 2 mss %"U16_F
"...\n",
1376 pcb->ssthresh, 2*pcb->mss));
1377 pcb->ssthresh = 2*pcb->mss;
1380 pcb->cwnd = pcb->ssthresh + 3 * pcb->mss;
1381 pcb->flags |= TF_INFR;
1395 tcp_keepalive(
struct tcp_pcb *pcb)
1398 struct tcp_hdr *tcphdr;
1400 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_keepalive: sending KEEPALIVE probe to %"U16_F
".%"U16_F
".%"U16_F
".%"U16_F
"\n",
1404 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_keepalive: tcp_ticks %"U32_F
" pcb->tmr %"U32_F
" pcb->keep_cnt_sent %"U16_F
"\n",
1405 tcp_ticks, pcb->tmr, pcb->keep_cnt_sent));
1407 p = tcp_output_alloc_header(pcb, 0, 0,
htonl(pcb->snd_nxt - 1));
1410 (
"tcp_keepalive: could not allocate memory for pbuf\n"));
1413 tcphdr = (
struct tcp_hdr *)p->
payload;
1422 #if LWIP_NETIF_HWADDRHINT 1423 ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0,
IP_PROTO_TCP,
1432 pcb->snd_nxt - 1, pcb->rcv_nxt));
1445 tcp_zero_window_probe(
struct tcp_pcb *pcb)
1448 struct tcp_hdr *tcphdr;
1449 struct tcp_seg *seg;
1455 (
"tcp_zero_window_probe: sending ZERO WINDOW probe to %" 1456 U16_F
".%"U16_F
".%"U16_F
".%"U16_F
"\n",
1461 (
"tcp_zero_window_probe: tcp_ticks %"U32_F
1462 " pcb->tmr %"U32_F
" pcb->keep_cnt_sent %"U16_F
"\n",
1463 tcp_ticks, pcb->tmr, pcb->keep_cnt_sent));
1471 iphdr = (
struct ip_hdr *)((
char*)seg->p->payload + SIZEOF_ETH_HDR);
1472 offset =
IPH_HL(iphdr)*4;
1473 offset += SIZEOF_ETH_HDR;
1479 is_fin = ((TCPH_FLAGS(seg->tcphdr) & TCP_FIN) != 0) && (seg->len == 0);
1481 len = is_fin ? 0 : 1;
1483 p = tcp_output_alloc_header(pcb, 0, len, seg->tcphdr->seqno);
1488 tcphdr = (
struct tcp_hdr *)p->
payload;
1492 TCPH_FLAGS_SET(tcphdr, TCP_ACK | TCP_FIN);
1495 struct tcp_hdr *thdr = (
struct tcp_hdr *)seg->p->payload;
1496 char *d = ((
char *)p->
payload + TCP_HLEN);
1497 if (pcb->unacked ==
NULL)
1500 thdr = (
struct tcp_hdr *)((
char*)seg->p->payload + offset);
1505 #if CHECKSUM_GEN_TCP 1512 #if LWIP_NETIF_HWADDRHINT 1513 ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0,
IP_PROTO_TCP,
1522 " ackno %"U32_F
".\n",
1523 pcb->snd_nxt - 1, pcb->rcv_nxt));
#define ip4_addr3_16(ipaddr)
u16_t inet_chksum(void *dataptr, u16_t len) ICACHE_FLASH_ATTR
#define snmp_inc_tcpoutsegs()
const ip_addr_t ip_addr_any ICACHE_RODATA_ATTR
#define ICACHE_FLASH_ATTR
void * memp_malloc(memp_t type) ICACHE_FLASH_ATTR
#define LWIP_DBG_LEVEL_SEVERE
void pbuf_cat(struct pbuf *head, struct pbuf *tail) ICACHE_FLASH_ATTR
#define LWIP_ERROR(message, expression, handler)
static u32_t sys_now(void) ICACHE_FLASH_ATTR
struct netif * ip_route(ip_addr_t *dest) ICACHE_FLASH_ATTR
#define LWIP_MEM_ALIGN_SIZE(size)
#define LWIP_DEBUGF(debug, message)
#define ip_addr_copy(dest, src)
#define SWAP_BYTES_IN_WORD(w)
typedefPACK_STRUCT_END struct ip_addr ip_addr_t
#define LWIP_DBG_LEVEL_WARNING
#define ip4_addr4_16(ipaddr)
#define ip_addr_isany(addr1)
u8_t pbuf_free(struct pbuf *p) ICACHE_FLASH_ATTR
u16_t inet_chksum_pseudo(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, u8_t proto, u16_t proto_len) ICACHE_FLASH_ATTR
u16_t inet_chksum_pseudo_partial(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, u8_t proto, u16_t proto_len, u16_t chksum_len) ICACHE_FLASH_ATTR
u8_t pbuf_header(struct pbuf *p, s16_t header_size) ICACHE_FLASH_ATTR
#define ip4_addr1_16(ipaddr)
#define LWIP_ASSERT(message, assertion)
#define snmp_inc_tcpretranssegs()
#define snmp_inc_tcpoutrsts()
u16_t pbuf_copy_partial(struct pbuf *p, void *dataptr, u16_t len, u16_t offset) ICACHE_FLASH_ATTR
#define ip4_addr2_16(ipaddr)
err_t ip_output(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, u8_t ttl, u8_t tos, u8_t proto) ICACHE_FLASH_ATTR
#define LWIP_UNUSED_ARG(x)
struct pbuf * pbuf_alloc(pbuf_layer l, u16_t length, pbuf_type type) ICACHE_FLASH_ATTR
u8_t pbuf_clen(struct pbuf *p) ICACHE_FLASH_ATTR