56 #if LWIP_TCP_TIMESTAMPS 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); 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) 78 #ifndef TCP_CHECKSUM_ON_COPY_SANITY_CHECK 79 #define TCP_CHECKSUM_ON_COPY_SANITY_CHECK 0 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) 90 #ifndef TCP_OVERSIZE_CALC_LENGTH 91 #define TCP_OVERSIZE_CALC_LENGTH(length) ((length) + TCP_OVERSIZE) 96 static err_t tcp_output_segment(
struct tcp_seg *seg,
struct tcp_pcb *pcb);
109 tcp_output_alloc_header(
struct tcp_pcb *pcb,
u16_t optlen,
u16_t datalen,
112 struct tcp_hdr *tcphdr;
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)));
128 pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
140 tcp_send_fin(
struct tcp_pcb *pcb)
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);
148 if ((TCPH_FLAGS(last_unsent->tcphdr) & (TCP_SYN | TCP_FIN | TCP_RST)) == 0) {
150 TCPH_SET_FLAG(last_unsent->tcphdr, TCP_FIN);
151 pcb->flags |= TF_FIN;
156 return tcp_enqueue_flags(pcb, TCP_FIN);
173 static struct tcp_seg *
177 u8_t optlen = LWIP_TCP_OPT_LENGTH(optflags);
184 seg->flags = optflags;
188 seg->len = p->
tot_len - optlen;
189 #if TCP_OVERSIZE_DBGCHECK 190 seg->oversize_left = 0;
192 #if TCP_CHECKSUM_ON_COPY 194 seg->chksum_swapped = 0;
196 LWIP_ASSERT(
"invalid optflags passed: TF_SEG_DATA_CHECKSUMMED",
197 (optflags & TF_SEG_DATA_CHECKSUMMED) == 0);
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);
212 TCPH_HDRLEN_FLAGS_SET(seg->tcphdr, (5 + optlen / 4), flags);
214 seg->tcphdr->urgp = 0;
235 u16_t *oversize,
struct tcp_pcb *pcb,
u8_t apiflags,
239 u16_t alloc = length;
241 #if LWIP_NETIF_TX_SINGLE_PBUF 249 if (length < max_length) {
261 if ((apiflags & TCP_WRITE_FLAG_MORE) ||
262 (!(pcb->flags & TF_NODELAY) &&
264 pcb->unsent !=
NULL ||
265 pcb->unacked !=
NULL))) {
275 *oversize = p->
len - length;
281 #define tcp_pbuf_prealloc(layer, length, mx, os, pcb, api, fst) pbuf_alloc((layer), (length), PBUF_RAM) 284 #if TCP_CHECKSUM_ON_COPY 288 u8_t *seg_chksum_swapped)
292 helper = chksum + *seg_chksum;
294 if ((len & 1) != 0) {
295 *seg_chksum_swapped = 1 - *seg_chksum_swapped;
298 *seg_chksum = chksum;
309 tcp_write_checks(
struct tcp_pcb *pcb,
u16_t len)
312 if ((pcb->state != ESTABLISHED) &&
313 (pcb->state != CLOSE_WAIT) &&
314 (pcb->state != SYN_SENT) &&
315 (pcb->state != SYN_RCVD)) {
318 }
else if (len == 0) {
323 if (len > pcb->snd_buf) {
326 pcb->flags |= TF_NAGLEMEMERR;
335 if ((pcb->snd_queuelen >=
TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
339 pcb->flags |= TF_NAGLEMEMERR;
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);
346 LWIP_ASSERT(
"tcp_write: no pbufs on queue => both queues empty",
347 pcb->unacked ==
NULL && pcb->unsent ==
NULL);
369 tcp_write(
struct tcp_pcb *pcb,
const void *arg,
u16_t len,
u8_t apiflags)
372 struct tcp_seg *last_unsent =
NULL, *seg =
NULL, *prev_seg =
NULL, *queue =
NULL;
379 u16_t oversize_used = 0;
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;
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;
391 #if LWIP_NETIF_TX_SINGLE_PBUF 393 apiflags |= TCP_WRITE_FLAG_COPY;
397 (
void *)pcb, arg, len, (
u16_t)apiflags));
398 LWIP_ERROR(
"tcp_write: arg == NULL (programmer violates API)",
401 err = tcp_write_checks(pcb, len);
405 queuelen = pcb->snd_queuelen;
407 #if LWIP_TCP_TIMESTAMPS 408 if ((pcb->flags & TF_TIMESTAMP)) {
411 optflags = TF_SEG_OPTS_TS;
412 optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS);
414 mss_local =
LWIP_MAX(mss_local, LWIP_TCP_OPT_LEN_TS + 1);
442 if (pcb->unsent !=
NULL) {
447 for (last_unsent = pcb->unsent; last_unsent->next !=
NULL;
448 last_unsent = last_unsent->next);
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);
463 #if TCP_OVERSIZE_DBGCHECK 465 LWIP_ASSERT(
"unsent_oversize mismatch (pcb vs. last_unsent)",
466 pcb->unsent_oversize == last_unsent->oversize_left);
468 oversize = pcb->unsent_oversize;
470 LWIP_ASSERT(
"inconsistent oversize vs. space", oversize_used <= space);
472 oversize_used = oversize < len ? oversize : len;
473 pos += oversize_used;
474 oversize -= oversize_used;
475 space -= oversize_used;
478 LWIP_ASSERT(
"inconsistend oversize vs. len", (oversize == 0) || (pos == len));
488 if ((pos < len) && (space > 0) && (last_unsent->len > 0)) {
489 u16_t seglen = space < len - pos ? space : len - pos;
495 if (apiflags & TCP_WRITE_FLAG_COPY) {
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",
503 #if TCP_OVERSIZE_DBGCHECK 504 last_unsent->oversize_left += oversize;
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;
514 (
"tcp_write: could not allocate memory for zero-copy pbuf\n"));
517 #if TCP_CHECKSUM_ON_COPY 519 tcp_seg_add_chksum(~
inet_chksum((
const u8_t*)arg + pos, seglen), seglen,
520 &concat_chksum, &concat_chksum_swapped);
521 concat_chksummed += seglen;
524 ((
struct pbuf_rom*)concat_p)->payload = (
const u8_t*)arg + pos;
532 LWIP_ASSERT(
"unsent_oversize mismatch (pcb->unsent is NULL)",
533 pcb->unsent_oversize == 0);
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 550 u8_t chksum_swapped = 0;
553 if (apiflags & TCP_WRITE_FLAG_COPY) {
556 if ((p = tcp_pbuf_prealloc(
PBUF_TRANSPORT, seglen + optlen, mss_local, &oversize, pcb, apiflags, queue ==
NULL)) ==
NULL) {
560 LWIP_ASSERT(
"tcp_write: check that first pbuf can hold the complete seglen",
562 TCP_DATA_COPY2((
char *)p->
payload + optlen, (
const u8_t*)arg + pos, seglen, &chksum, &chksum_swapped);
577 #if TCP_CHECKSUM_ON_COPY 586 ((
struct pbuf_rom*)p2)->payload = (
const u8_t*)arg + pos;
605 if ((queuelen >
TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
615 #if TCP_OVERSIZE_DBGCHECK 616 seg->oversize_left = oversize;
618 #if TCP_CHECKSUM_ON_COPY 619 seg->chksum = chksum;
620 seg->chksum_swapped = chksum_swapped;
621 seg->flags |= TF_SEG_DATA_CHECKSUMMED;
630 prev_seg->next = seg;
636 ntohl(seg->tcphdr->seqno),
637 ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg)));
652 if (oversize_used > 0) {
655 for (p = last_unsent->p; p; p = p->
next) {
658 TCP_DATA_COPY((
char *)p->
payload + p->
len, arg, oversize_used, last_unsent);
659 p->
len += oversize_used;
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;
669 pcb->unsent_oversize = oversize;
675 if (concat_p !=
NULL) {
676 LWIP_ASSERT(
"tcp_write: cannot concatenate when pcb->unsent is empty",
677 (last_unsent !=
NULL));
679 last_unsent->len += concat_p->
tot_len;
680 #if TCP_CHECKSUM_ON_COPY 681 if (concat_chksummed) {
683 if (concat_chksum_swapped) {
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;
697 if (last_unsent ==
NULL) {
700 last_unsent->next = queue;
708 pcb->snd_queuelen = queuelen;
712 if (pcb->snd_queuelen != 0) {
714 pcb->unacked !=
NULL || pcb->unsent !=
NULL);
718 if (seg !=
NULL && seg->tcphdr !=
NULL && ((apiflags & TCP_WRITE_FLAG_MORE)==0)) {
719 TCPH_SET_FLAG(seg->tcphdr, TCP_PSH);
724 pcb->flags |= TF_NAGLEMEMERR;
727 if (concat_p !=
NULL) {
731 tcp_segs_free(queue);
733 if (pcb->snd_queuelen != 0) {
735 pcb->unsent !=
NULL);
752 tcp_enqueue_flags(
struct tcp_pcb *pcb,
u8_t flags)
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);
765 if (((pcb->snd_queuelen >=
TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) &&
766 ((flags & TCP_FIN) == 0)) {
770 pcb->flags |= TF_NAGLEMEMERR;
774 if (flags & TCP_SYN) {
775 optflags = TF_SEG_OPTS_MSS;
777 if ((pcb->state != SYN_RCVD) || (pcb->flags & TF_WND_SCALE)) {
780 optflags |= TF_SEG_OPTS_WND_SCALE;
784 #if LWIP_TCP_TIMESTAMPS 785 if ((pcb->flags & TF_TIMESTAMP)) {
788 optflags |= TF_SEG_OPTS_TS;
791 optlen = LWIP_TCP_OPT_LENGTH(optflags);
797 if (pcb->snd_buf == 0) {
805 pcb->flags |= TF_NAGLEMEMERR;
809 LWIP_ASSERT(
"tcp_enqueue_flags: check that first pbuf can hold optlen",
814 pcb->flags |= TF_NAGLEMEMERR;
819 LWIP_ASSERT(
"tcp_enqueue_flags: invalid segment length", seg->len == 0);
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),
828 if (pcb->unsent ==
NULL) {
831 struct tcp_seg *useg;
832 for (useg = pcb->unsent; useg->next !=
NULL; useg = useg->next);
837 pcb->unsent_oversize = 0;
841 if ((flags & TCP_SYN) || (flags & TCP_FIN)) {
846 if (flags & TCP_FIN) {
847 pcb->flags |= TF_FIN;
853 if (pcb->snd_queuelen != 0) {
854 LWIP_ASSERT(
"tcp_enqueue_flags: invalid queue length",
855 pcb->unacked !=
NULL || pcb->unsent !=
NULL);
861 #if LWIP_TCP_TIMESTAMPS 868 tcp_build_timestamp_option(
struct tcp_pcb *pcb,
u32_t *opts)
873 opts[2] =
htonl(pcb->ts_recent);
883 tcp_build_wnd_scale_option(
u32_t *opts)
895 tcp_send_empty_ack(
struct tcp_pcb *pcb)
901 #if LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP 902 struct tcp_hdr *tcphdr;
905 #if LWIP_TCP_TIMESTAMPS 906 if (pcb->flags & TF_TIMESTAMP) {
907 optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS);
911 p = tcp_output_alloc_header(pcb, optlen, 0,
htonl(pcb->snd_nxt));
914 pcb->flags |= (TF_ACK_DELAY | TF_ACK_NOW);
918 #if LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP 919 tcphdr = (
struct tcp_hdr *)p->
payload;
922 (
"tcp_output: sending ACK for %"U32_F
"\n", pcb->rcv_nxt));
925 #if LWIP_TCP_TIMESTAMPS 926 pcb->ts_lastacksent = pcb->rcv_nxt;
928 if (pcb->flags & TF_TIMESTAMP) {
929 tcp_build_timestamp_option(pcb, (
u32_t *)(tcphdr + 1));
933 netif = ip_route(
PCB_ISIPV6(pcb), &pcb->local_ip, &pcb->remote_ip);
940 &pcb->local_ip, &pcb->remote_ip);
944 err = ip_output_if(
PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip,
952 pcb->flags |= (TF_ACK_DELAY | TF_ACK_NOW);
955 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
969 tcp_output(
struct tcp_pcb *pcb)
971 struct tcp_seg *seg, *useg;
979 LWIP_ASSERT(
"don't call tcp_output for listen-pcbs",
980 pcb->state != LISTEN);
986 if (tcp_input_pcb == pcb) {
990 wnd =
LWIP_MIN(pcb->snd_wnd, pcb->cwnd);
1000 if (pcb->flags & TF_ACK_NOW &&
1002 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
1003 return tcp_send_empty_ack(pcb);
1007 useg = pcb->unacked;
1009 for (; useg->next !=
NULL; useg = useg->next);
1012 #if TCP_OUTPUT_DEBUG 1015 (
void*)pcb->unsent));
1021 ", cwnd %"TCPWNDSIZE_F
", wnd %"U32_F
1022 ", seg == NULL, ack %"U32_F
"\n",
1023 pcb->snd_wnd, pcb->cwnd, wnd, pcb->lastack));
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));
1034 while (seg !=
NULL &&
1035 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
1037 (TCPH_FLAGS(seg->tcphdr) & TCP_RST) == 0);
1045 if((tcp_do_output_nagle(pcb) == 0) &&
1046 ((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)) {
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 -
1054 ntohl(seg->tcphdr->seqno), pcb->lastack, i));
1058 if (pcb->state != SYN_SENT) {
1059 TCPH_SET_FLAG(seg->tcphdr, TCP_ACK);
1062 #if TCP_OVERSIZE_DBGCHECK 1063 seg->oversize_left = 0;
1065 err = tcp_output_segment(seg, pcb);
1068 pcb->flags |= TF_NAGLEMEMERR;
1071 pcb->unsent = seg->next;
1072 if (pcb->state != SYN_SENT) {
1073 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
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;
1080 if (TCP_TCPLEN(seg) > 0) {
1083 if (pcb->unacked ==
NULL) {
1091 if (TCP_SEQ_LT(
ntohl(seg->tcphdr->seqno),
ntohl(useg->tcphdr->seqno))) {
1093 struct tcp_seg **cur_seg = &(pcb->unacked);
1095 TCP_SEQ_LT(
ntohl((*cur_seg)->tcphdr->seqno),
ntohl(seg->tcphdr->seqno))) {
1096 cur_seg = &((*cur_seg)->next );
1098 seg->next = (*cur_seg);
1113 if (pcb->unsent ==
NULL) {
1115 pcb->unsent_oversize = 0;
1119 pcb->flags &= ~TF_NAGLEMEMERR;
1130 tcp_output_segment(
struct tcp_seg *seg,
struct tcp_pcb *pcb)
1135 struct netif *netif;
1142 seg->tcphdr->ackno =
htonl(pcb->rcv_nxt);
1146 if (seg->flags & TF_SEG_OPTS_WND_SCALE) {
1149 seg->tcphdr->wnd =
htons(TCPWND_MIN16(pcb->rcv_ann_wnd));
1153 seg->tcphdr->wnd =
htons(TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd)));
1156 pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
1160 opts = (
u32_t *)(
void *)(seg->tcphdr + 1);
1161 if (seg->flags & TF_SEG_OPTS_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));
1168 *opts = TCP_BUILD_MSS_OPTION(mss);
1171 #if LWIP_TCP_TIMESTAMPS 1172 pcb->ts_lastacksent = pcb->rcv_nxt;
1174 if (seg->flags & TF_SEG_OPTS_TS) {
1175 tcp_build_timestamp_option(pcb, opts);
1180 if (seg->flags & TF_SEG_OPTS_WND_SCALE) {
1181 tcp_build_wnd_scale_option(opts);
1188 if (pcb->rtime == -1) {
1192 netif = ip_route(
PCB_ISIPV6(pcb), &pcb->local_ip, &pcb->remote_ip);
1193 if (netif ==
NULL) {
1201 if (local_ip ==
NULL) {
1207 if (pcb->rttest == 0) {
1208 pcb->rttest = tcp_ticks;
1209 pcb->rtseq =
ntohl(seg->tcphdr->seqno);
1214 htonl(seg->tcphdr->seqno),
htonl(seg->tcphdr->seqno) +
1217 len = (
u16_t)((
u8_t *)seg->tcphdr - (
u8_t *)seg->p->payload);
1220 seg->p->tot_len -= len;
1222 seg->p->payload = seg->tcphdr;
1224 seg->tcphdr->chksum = 0;
1225 #if CHECKSUM_GEN_TCP 1227 #if TCP_CHECKSUM_ON_COPY 1229 #if TCP_CHECKSUM_ON_COPY_SANITY_CHECK 1231 seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip);
1233 if ((seg->flags & TF_SEG_DATA_CHECKSUMMED) == 0) {
1235 seg->p->tot_len == (TCPH_HDRLEN(seg->tcphdr) * 4));
1240 seg->p->tot_len, TCPH_HDRLEN(seg->tcphdr) * 4, &pcb->local_ip, &pcb->remote_ip);
1242 if (seg->chksum_swapped) {
1244 seg->chksum_swapped = 0;
1246 acc += (
u16_t)~(seg->chksum);
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;
1258 seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip);
1265 err = ip_output_if(
PCB_ISIPV6(pcb), seg->p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl,
1297 struct tcp_hdr *tcphdr;
1298 struct netif *netif;
1304 LWIP_ASSERT(
"check that first pbuf can hold struct tcp_hdr",
1305 (p->
len >=
sizeof(
struct tcp_hdr)));
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);
1324 netif = ip_route(
IP_IS_V6(remote_ip), local_ip, remote_ip);
1325 if (netif !=
NULL) {
1326 #if CHECKSUM_GEN_TCP 1329 local_ip, remote_ip);
1347 tcp_rexmit_rto(
struct tcp_pcb *pcb)
1349 struct tcp_seg *seg;
1351 if (pcb->unacked ==
NULL) {
1356 for (seg = pcb->unacked; seg->next !=
NULL; seg = seg->next);
1358 seg->next = pcb->unsent;
1359 #if TCP_OVERSIZE_DBGCHECK 1361 if (pcb->unsent ==
NULL) {
1362 pcb->unsent_oversize = seg->oversize_left;
1366 pcb->unsent = pcb->unacked;
1368 pcb->unacked =
NULL;
1388 tcp_rexmit(
struct tcp_pcb *pcb)
1390 struct tcp_seg *seg;
1391 struct tcp_seg **cur_seg;
1393 if (pcb->unacked ==
NULL) {
1400 pcb->unacked = seg->next;
1402 cur_seg = &(pcb->unsent);
1404 TCP_SEQ_LT(
ntohl((*cur_seg)->tcphdr->seqno),
ntohl(seg->tcphdr->seqno))) {
1405 cur_seg = &((*cur_seg)->next );
1407 seg->next = *cur_seg;
1410 if (seg->next ==
NULL) {
1412 pcb->unsent_oversize = 0;
1434 tcp_rexmit_fast(
struct tcp_pcb *pcb)
1436 if (pcb->unacked !=
NULL && !(pcb->flags & TF_INFR)) {
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)));
1447 if (pcb->cwnd > pcb->snd_wnd) {
1448 pcb->ssthresh = pcb->snd_wnd / 2;
1450 pcb->ssthresh = pcb->cwnd / 2;
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;
1462 pcb->cwnd = pcb->ssthresh + 3 * pcb->mss;
1463 pcb->flags |= TF_INFR;
1477 tcp_keepalive(
struct tcp_pcb *pcb)
1481 struct netif *netif;
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));
1490 p = tcp_output_alloc_header(pcb, 0, 0,
htonl(pcb->snd_nxt - 1));
1493 (
"tcp_keepalive: could not allocate memory for pbuf\n"));
1496 netif = ip_route(
PCB_ISIPV6(pcb), &pcb->local_ip, &pcb->remote_ip);
1497 if (netif ==
NULL) {
1500 #if CHECKSUM_GEN_TCP 1502 struct tcp_hdr *tcphdr = (
struct tcp_hdr *)p->
payload;
1504 &pcb->local_ip, &pcb->remote_ip);
1511 err = ip_output_if(
PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl,
1518 pcb->snd_nxt - 1, pcb->rcv_nxt, (
int)err));
1532 tcp_zero_window_probe(
struct tcp_pcb *pcb)
1536 struct tcp_hdr *tcphdr;
1537 struct tcp_seg *seg;
1540 struct netif *netif;
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));
1561 is_fin = ((TCPH_FLAGS(seg->tcphdr) & TCP_FIN) != 0) && (seg->len == 0);
1563 len = is_fin ? 0 : 1;
1565 p = tcp_output_alloc_header(pcb, 0, len, seg->tcphdr->seqno);
1570 tcphdr = (
struct tcp_hdr *)p->
payload;
1574 TCPH_FLAGS_SET(tcphdr, TCP_ACK | TCP_FIN);
1577 char *d = ((
char *)p->
payload + TCP_HLEN);
1584 netif = ip_route(
PCB_ISIPV6(pcb), &pcb->local_ip, &pcb->remote_ip);
1585 if (netif ==
NULL) {
1588 #if CHECKSUM_GEN_TCP 1591 &pcb->local_ip, &pcb->remote_ip);
1598 err = ip_output_if(
PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl,
1606 " ackno %"U32_F
" err %d.\n",
1607 pcb->snd_nxt - 1, pcb->rcv_nxt, (
int)err));
#define MIB2_STATS_INC(x)
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)
#define LWIP_DBG_LEVEL_SERIOUS
#define ip_addr_isany(ipaddr)
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)
u8_t pbuf_header(struct pbuf *p, s16_t header_size_increment)
#define IF__NETIF_CHECKSUM_ENABLED(netif, chksumflag)
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
u16_t inet_chksum(const void *dataptr, u16_t len)
u8_t pbuf_free(struct pbuf *p)
#define ip_addr_copy(dest, src)
#define NETIF_SET_HWADDRHINT(netif, hint)
#define SWAP_BYTES_IN_WORD(w)
#define LWIP_ASSERT(message, assertion)
#define ip_addr_debug_print(debug, ipaddr)
u16_t pbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
u8_t pbuf_clen(struct pbuf *p)
void pbuf_cat(struct pbuf *h, struct pbuf *t)
#define LWIP_DBG_LEVEL_SEVERE
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)
#define LWIP_ERROR(message, expression, handler)
#define LWIP_MEM_ALIGN_SIZE(size)
void * memp_malloc(memp_t type)
#define LWIP_DEBUGF(debug, message)
#define LWIP_UNUSED_ARG(x)