58#if LWIP_ND6_TCP_REACHABILITY_HINTS
64#ifdef LWIP_HOOK_FILENAME
65#include LWIP_HOOK_FILENAME
69#define LWIP_TCP_CALC_INITIAL_CWND(mss) ((tcpwnd_size_t)LWIP_MIN((4U * (mss)), LWIP_MAX((2U * (mss)), 4380U)))
74static struct tcp_seg inseg;
76static u16_t tcphdr_optlen;
77static u16_t tcphdr_opt1len;
78static u8_t *tcphdr_opt2;
79static u16_t tcp_optidx;
80static u32_t seqno, ackno;
81static tcpwnd_size_t recv_acked;
85static u8_t recv_flags;
86static struct pbuf *recv_data;
88struct tcp_pcb *tcp_input_pcb;
91static err_t tcp_process(
struct tcp_pcb *pcb);
92static void tcp_receive(
struct tcp_pcb *pcb);
93static void tcp_parseopt(
struct tcp_pcb *pcb);
95static void tcp_listen_input(
struct tcp_pcb_listen *pcb);
96static void tcp_timewait_input(
struct tcp_pcb *pcb);
98static int tcp_input_delayed_close(
struct tcp_pcb *pcb);
101static void tcp_add_sack(
struct tcp_pcb *pcb, u32_t left, u32_t right);
102static void tcp_remove_sacks_lt(
struct tcp_pcb *pcb, u32_t seq);
103#if defined(TCP_OOSEQ_BYTES_LIMIT) || defined(TCP_OOSEQ_PBUFS_LIMIT)
104static void tcp_remove_sacks_gt(
struct tcp_pcb *pcb, u32_t seq);
118tcp_input(
struct pbuf *p,
struct netif *inp)
120 struct tcp_pcb *pcb, *prev;
121 struct tcp_pcb_listen *lpcb;
123 struct tcp_pcb *lpcb_prev = NULL;
124 struct tcp_pcb_listen *lpcb_any = NULL;
131 LWIP_ASSERT(
"tcp_input: invalid pbuf", p != NULL);
135 TCP_STATS_INC(tcp.recv);
136 MIB2_STATS_INC(mib2.tcpinsegs);
138 tcphdr = (
struct tcp_hdr *)p->payload;
141 tcp_debug_print(tcphdr);
145 if (p->len < TCP_HLEN) {
147 LWIP_DEBUGF(
TCP_INPUT_DEBUG, (
"tcp_input: short packet (%"U16_F
" bytes) discarded\n", p->tot_len));
148 TCP_STATS_INC(tcp.lenerr);
155 TCP_STATS_INC(tcp.proterr);
159#if CHECKSUM_CHECK_TCP
160 IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_TCP) {
162 u16_t chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len,
165 LWIP_DEBUGF(
TCP_INPUT_DEBUG, (
"tcp_input: packet discarded due to failing checksum 0x%04"X16_F
"\n",
167 tcp_debug_print(tcphdr);
168 TCP_STATS_INC(tcp.chkerr);
175 hdrlen_bytes = TCPH_HDRLEN_BYTES(tcphdr);
176 if ((hdrlen_bytes < TCP_HLEN) || (hdrlen_bytes > p->tot_len)) {
177 LWIP_DEBUGF(
TCP_INPUT_DEBUG, (
"tcp_input: invalid header length (%"U16_F
")\n", (u16_t)hdrlen_bytes));
178 TCP_STATS_INC(tcp.lenerr);
184 tcphdr_optlen = (u16_t)(hdrlen_bytes - TCP_HLEN);
186 if (p->len >= hdrlen_bytes) {
188 tcphdr_opt1len = tcphdr_optlen;
194 LWIP_ASSERT(
"p->next != NULL", p->next != NULL);
200 tcphdr_opt1len = p->len;
201 opt2len = (u16_t)(tcphdr_optlen - tcphdr_opt1len);
208 if (opt2len > p->next->len) {
210 LWIP_DEBUGF(
TCP_INPUT_DEBUG, (
"tcp_input: options overflow second pbuf (%"U16_F
" bytes)\n", p->next->len));
211 TCP_STATS_INC(tcp.lenerr);
216 tcphdr_opt2 = (u8_t *)p->next->payload;
221 p->tot_len = (u16_t)(p->tot_len - opt2len);
223 LWIP_ASSERT(
"p->len == 0", p->len == 0);
224 LWIP_ASSERT(
"p->tot_len == p->next->tot_len", p->tot_len == p->next->tot_len);
228 tcphdr->src = lwip_ntohs(tcphdr->src);
229 tcphdr->dest = lwip_ntohs(tcphdr->dest);
230 seqno = tcphdr->seqno = lwip_ntohl(tcphdr->seqno);
231 ackno = tcphdr->ackno = lwip_ntohl(tcphdr->ackno);
232 tcphdr->wnd = lwip_ntohs(tcphdr->wnd);
234 flags = TCPH_FLAGS(tcphdr);
236 if (flags & (TCP_FIN | TCP_SYN)) {
238 if (tcplen < p->tot_len) {
240 LWIP_DEBUGF(
TCP_INPUT_DEBUG, (
"tcp_input: length u16_t overflow, cannot handle this\n"));
241 TCP_STATS_INC(tcp.lenerr);
250 for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
251 LWIP_ASSERT(
"tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED);
252 LWIP_ASSERT(
"tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
253 LWIP_ASSERT(
"tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN);
256 if ((pcb->netif_idx != NETIF_NO_INDEX) &&
257 (pcb->netif_idx != netif_get_index(ip_data.current_input_netif))) {
262 if (pcb->remote_port == tcphdr->src &&
263 pcb->local_port == tcphdr->dest &&
269 LWIP_ASSERT(
"tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb);
271 prev->next = pcb->next;
272 pcb->next = tcp_active_pcbs;
273 tcp_active_pcbs = pcb;
275 TCP_STATS_INC(tcp.cachehit);
277 LWIP_ASSERT(
"tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb);
286 for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
287 LWIP_ASSERT(
"tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
290 if ((pcb->netif_idx != NETIF_NO_INDEX) &&
291 (pcb->netif_idx != netif_get_index(ip_data.current_input_netif))) {
295 if (pcb->remote_port == tcphdr->src &&
296 pcb->local_port == tcphdr->dest &&
302 LWIP_DEBUGF(
TCP_INPUT_DEBUG, (
"tcp_input: packed for TIME_WAITing connection.\n"));
303#ifdef LWIP_HOOK_TCP_INPACKET_PCB
304 if (LWIP_HOOK_TCP_INPACKET_PCB(pcb, tcphdr, tcphdr_optlen, tcphdr_opt1len,
305 tcphdr_opt2, p) ==
ERR_OK)
308 tcp_timewait_input(pcb);
318 for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
320 if ((lpcb->netif_idx != NETIF_NO_INDEX) &&
321 (lpcb->netif_idx != netif_get_index(ip_data.current_input_netif))) {
322 prev = (
struct tcp_pcb *)lpcb;
326 if (lpcb->local_port == tcphdr->dest) {
327 if (IP_IS_ANY_TYPE_VAL(lpcb->local_ip)) {
339 }
else if (ip_addr_isany(&lpcb->local_ip)) {
350 prev = (
struct tcp_pcb *)lpcb;
365 ((
struct tcp_pcb_listen *)prev)->next = lpcb->next;
367 lpcb->next = tcp_listen_pcbs.listen_pcbs;
369 tcp_listen_pcbs.listen_pcbs = lpcb;
371 TCP_STATS_INC(tcp.cachehit);
374 LWIP_DEBUGF(
TCP_INPUT_DEBUG, (
"tcp_input: packed for LISTENing connection.\n"));
375#ifdef LWIP_HOOK_TCP_INPACKET_PCB
376 if (LWIP_HOOK_TCP_INPACKET_PCB((
struct tcp_pcb *)lpcb, tcphdr, tcphdr_optlen,
377 tcphdr_opt1len, tcphdr_opt2, p) ==
ERR_OK)
380 tcp_listen_input(lpcb);
388 LWIP_DEBUGF(
TCP_INPUT_DEBUG, (
"+-+-+-+-+-+-+-+-+-+-+-+-+-+- tcp_input: flags "));
389 tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
394#ifdef LWIP_HOOK_TCP_INPACKET_PCB
395 if ((pcb != NULL) && LWIP_HOOK_TCP_INPACKET_PCB(pcb, tcphdr, tcphdr_optlen,
396 tcphdr_opt1len, tcphdr_opt2, p) !=
ERR_OK) {
404 tcp_debug_print_state(pcb->state);
409 inseg.len = p->tot_len;
411 inseg.tcphdr = tcphdr;
417 if (flags & TCP_PSH) {
422 if (pcb->refused_data != NULL) {
423 if ((tcp_process_refused_data(pcb) ==
ERR_ABRT) ||
424 ((pcb->refused_data != NULL) && (tcplen > 0))) {
427 if (pcb->rcv_ann_wnd == 0) {
430 tcp_send_empty_ack(pcb);
432 TCP_STATS_INC(tcp.drop);
433 MIB2_STATS_INC(mib2.tcpinerrs);
438 err = tcp_process(pcb);
442 if (recv_flags & TF_RESET) {
447 TCP_EVENT_ERR(pcb->state, pcb->errf, pcb->callback_arg,
ERR_RST);
448 tcp_pcb_remove(&tcp_active_pcbs, pcb);
455 if (recv_acked > 0) {
460 u32_t acked = recv_acked;
462 acked16 = (u16_t)LWIP_MIN(acked, 0xffffu);
466 acked16 = recv_acked;
468 TCP_EVENT_SENT(pcb, (u16_t)acked16, err);
475 if (tcp_input_delayed_close(pcb)) {
478#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE
479 while (recv_data != NULL) {
480 struct pbuf *rest = NULL;
481 pbuf_split_64k(recv_data, &rest);
483 if (recv_data != NULL) {
486 LWIP_ASSERT(
"pcb->refused_data == NULL", pcb->refused_data == NULL);
487 if (pcb->flags & TF_RXCLOSED) {
491#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE
501 TCP_EVENT_RECV(pcb, recv_data,
ERR_OK, err);
503#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE
513#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE
518 pcb->refused_data = recv_data;
519 LWIP_DEBUGF(
TCP_INPUT_DEBUG, (
"tcp_input: keep incoming packet, because pcb is \"full\"\n"));
520#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE
531 if (recv_flags & TF_GOT_FIN) {
532 if (pcb->refused_data != NULL) {
538 if (pcb->rcv_wnd != TCP_WND_MAX(pcb)) {
541 TCP_EVENT_CLOSED(pcb, err);
548 tcp_input_pcb = NULL;
549 if (tcp_input_delayed_close(pcb)) {
556 tcp_debug_print_state(pcb->state);
564 tcp_input_pcb = NULL;
568 if (inseg.p != NULL) {
575 LWIP_DEBUGF(
TCP_RST_DEBUG, (
"tcp_input: no PCB match found, resetting.\n"));
576 if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) {
577 TCP_STATS_INC(tcp.proterr);
578 TCP_STATS_INC(tcp.drop);
585 LWIP_ASSERT(
"tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane());
586 PERF_STOP(
"tcp_input");
589 TCP_STATS_INC(tcp.drop);
590 MIB2_STATS_INC(mib2.tcpinerrs);
600tcp_input_delayed_close(
struct tcp_pcb *pcb)
602 LWIP_ASSERT(
"tcp_input_delayed_close: invalid pcb", pcb != NULL);
604 if (recv_flags & TF_CLOSED) {
607 if (!(pcb->flags & TF_RXCLOSED)) {
611 TCP_EVENT_ERR(pcb->state, pcb->errf, pcb->callback_arg,
ERR_CLSD);
613 tcp_pcb_remove(&tcp_active_pcbs, pcb);
630tcp_listen_input(
struct tcp_pcb_listen *pcb)
632 struct tcp_pcb *npcb;
636 if (flags & TCP_RST) {
641 LWIP_ASSERT(
"tcp_listen_input: invalid pcb", pcb != NULL);
645 if (flags & TCP_ACK) {
648 LWIP_DEBUGF(
TCP_RST_DEBUG, (
"tcp_listen_input: ACK in LISTEN, sending reset\n"));
651 }
else if (flags & TCP_SYN) {
652 LWIP_DEBUGF(
TCP_DEBUG, (
"TCP connection request %"U16_F
" -> %"U16_F
".\n", tcphdr->src, tcphdr->dest));
653#if TCP_LISTEN_BACKLOG
654 if (pcb->accepts_pending >= pcb->backlog) {
655 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_listen_input: listen backlog exceeded for port %"U16_F
"\n", tcphdr->dest));
659 npcb = tcp_alloc(pcb->prio);
665 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_listen_input: could not allocate PCB\n"));
666 TCP_STATS_INC(tcp.memerr);
667 TCP_EVENT_ACCEPT(pcb, NULL, pcb->callback_arg,
ERR_MEM, err);
671#if TCP_LISTEN_BACKLOG
672 pcb->accepts_pending++;
673 tcp_set_flags(npcb, TF_BACKLOGPEND);
678 npcb->local_port = pcb->local_port;
679 npcb->remote_port = tcphdr->src;
680 npcb->state = SYN_RCVD;
681 npcb->rcv_nxt = seqno + 1;
682 npcb->rcv_ann_right_edge = npcb->rcv_nxt;
683 iss = tcp_next_iss(npcb);
688 npcb->snd_wl1 = seqno - 1;
689 npcb->callback_arg = pcb->callback_arg;
690#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG
691 npcb->listener = pcb;
694 npcb->netif_hints.tci = pcb->netif_hints.tci;
697 npcb->so_options = pcb->so_options & SOF_INHERITED;
698 npcb->netif_idx = pcb->netif_idx;
701 TCP_REG_ACTIVE(npcb);
705 npcb->snd_wnd = tcphdr->wnd;
706 npcb->snd_wnd_max = npcb->snd_wnd;
708#if TCP_CALCULATE_EFF_SEND_MSS
709 npcb->mss = tcp_eff_send_mss(npcb->mss, &npcb->local_ip, &npcb->remote_ip);
712 MIB2_STATS_INC(mib2.tcppassiveopens);
714#if LWIP_TCP_PCB_NUM_EXT_ARGS
715 if (tcp_ext_arg_invoke_callbacks_passive_open(pcb, npcb) !=
ERR_OK) {
716 tcp_abandon(npcb, 0);
722 rc = tcp_enqueue_flags(npcb, TCP_SYN | TCP_ACK);
724 tcp_abandon(npcb, 0);
742tcp_timewait_input(
struct tcp_pcb *pcb)
749 if (flags & TCP_RST) {
753 LWIP_ASSERT(
"tcp_timewait_input: invalid pcb", pcb != NULL);
756 if (flags & TCP_SYN) {
759 if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd)) {
765 }
else if (flags & TCP_FIN) {
768 pcb->tmr = tcp_ticks;
791tcp_process(
struct tcp_pcb *pcb)
793 struct tcp_seg *rseg;
799 LWIP_ASSERT(
"tcp_process: invalid pcb", pcb != NULL);
802 if (flags & TCP_RST) {
804 if (pcb->state == SYN_SENT) {
807 if (ackno == pcb->snd_nxt) {
813 if (seqno == pcb->rcv_nxt) {
815 }
else if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
816 pcb->rcv_nxt + pcb->rcv_wnd)) {
827 LWIP_ASSERT(
"tcp_input: pcb->state != CLOSED", pcb->state != CLOSED);
828 recv_flags |= TF_RESET;
829 tcp_clear_flags(pcb, TF_ACK_DELAY);
832 LWIP_DEBUGF(
TCP_INPUT_DEBUG, (
"tcp_process: unacceptable reset seqno %"U32_F
" rcv_nxt %"U32_F
"\n",
833 seqno, pcb->rcv_nxt));
834 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_process: unacceptable reset seqno %"U32_F
" rcv_nxt %"U32_F
"\n",
835 seqno, pcb->rcv_nxt));
840 if ((flags & TCP_SYN) && (pcb->state != SYN_SENT && pcb->state != SYN_RCVD)) {
846 if ((pcb->flags & TF_RXCLOSED) == 0) {
848 pcb->tmr = tcp_ticks;
850 pcb->keep_cnt_sent = 0;
851 pcb->persist_probe = 0;
855 if (flags & TCP_SYN) {
857 if ((pcb->state != SYN_SENT) && (pcb->state != SYN_RCVD)) {
863 switch (pcb->state) {
865 LWIP_DEBUGF(
TCP_INPUT_DEBUG, (
"SYN-SENT: ackno %"U32_F
" pcb->snd_nxt %"U32_F
" unacked %s %"U32_F
"\n",
866 ackno, pcb->snd_nxt, pcb->unacked ?
"" :
" empty:",
867 pcb->unacked ? lwip_ntohl(pcb->unacked->tcphdr->seqno) : 0));
869 if ((flags & TCP_ACK) && (flags & TCP_SYN)
870 && (ackno == pcb->lastack + 1)) {
871 pcb->rcv_nxt = seqno + 1;
872 pcb->rcv_ann_right_edge = pcb->rcv_nxt;
873 pcb->lastack = ackno;
874 pcb->snd_wnd = tcphdr->wnd;
875 pcb->snd_wnd_max = pcb->snd_wnd;
876 pcb->snd_wl1 = seqno - 1;
877 pcb->state = ESTABLISHED;
879#if TCP_CALCULATE_EFF_SEND_MSS
880 pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip);
883 pcb->cwnd = LWIP_TCP_CALC_INITIAL_CWND(pcb->mss);
884 LWIP_DEBUGF(
TCP_CWND_DEBUG, (
"tcp_process (SENT): cwnd %"TCPWNDSIZE_F
885 " ssthresh %"TCPWNDSIZE_F
"\n",
886 pcb->cwnd, pcb->ssthresh));
887 LWIP_ASSERT(
"pcb->snd_queuelen > 0", (pcb->snd_queuelen > 0));
889 LWIP_DEBUGF(
TCP_QLEN_DEBUG, (
"tcp_process: SYN-SENT --queuelen %"TCPWNDSIZE_F
"\n", (tcpwnd_size_t)pcb->snd_queuelen));
895 LWIP_ASSERT(
"no segment to free", rseg != NULL);
896 pcb->unsent = rseg->next;
898 pcb->unacked = rseg->next;
904 if (pcb->unacked == NULL) {
913 TCP_EVENT_CONNECTED(pcb,
ERR_OK, err);
920 else if (flags & TCP_ACK) {
934 if (flags & TCP_SYN) {
935 if (seqno == pcb->rcv_nxt - 1) {
939 }
else if (flags & TCP_ACK) {
941 if (TCP_SEQ_BETWEEN(ackno, pcb->lastack + 1, pcb->snd_nxt)) {
942 pcb->state = ESTABLISHED;
943 LWIP_DEBUGF(
TCP_DEBUG, (
"TCP connection established %"U16_F
" -> %"U16_F
".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
944#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG
945 if (pcb->listener == NULL) {
952 LWIP_ASSERT(
"pcb->listener->accept != NULL", pcb->listener->accept != NULL);
954 tcp_backlog_accepted(pcb);
956 TCP_EVENT_ACCEPT(pcb->listener, pcb, pcb->callback_arg,
ERR_OK, err);
972 if (recv_acked != 0) {
976 pcb->cwnd = LWIP_TCP_CALC_INITIAL_CWND(pcb->mss);
977 LWIP_DEBUGF(
TCP_CWND_DEBUG, (
"tcp_process (SYN_RCVD): cwnd %"TCPWNDSIZE_F
978 " ssthresh %"TCPWNDSIZE_F
"\n",
979 pcb->cwnd, pcb->ssthresh));
981 if (recv_flags & TF_GOT_FIN) {
983 pcb->state = CLOSE_WAIT;
996 if (recv_flags & TF_GOT_FIN) {
998 pcb->state = CLOSE_WAIT;
1003 if (recv_flags & TF_GOT_FIN) {
1004 if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt) &&
1005 pcb->unsent == NULL) {
1007 (
"TCP connection closed: FIN_WAIT_1 %"U16_F
" -> %"U16_F
".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
1010 TCP_RMV_ACTIVE(pcb);
1011 pcb->state = TIME_WAIT;
1012 TCP_REG(&tcp_tw_pcbs, pcb);
1015 pcb->state = CLOSING;
1017 }
else if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt) &&
1018 pcb->unsent == NULL) {
1019 pcb->state = FIN_WAIT_2;
1024 if (recv_flags & TF_GOT_FIN) {
1025 LWIP_DEBUGF(
TCP_DEBUG, (
"TCP connection closed: FIN_WAIT_2 %"U16_F
" -> %"U16_F
".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
1028 TCP_RMV_ACTIVE(pcb);
1029 pcb->state = TIME_WAIT;
1030 TCP_REG(&tcp_tw_pcbs, pcb);
1035 if ((flags & TCP_ACK) && ackno == pcb->snd_nxt && pcb->unsent == NULL) {
1036 LWIP_DEBUGF(
TCP_DEBUG, (
"TCP connection closed: CLOSING %"U16_F
" -> %"U16_F
".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
1038 TCP_RMV_ACTIVE(pcb);
1039 pcb->state = TIME_WAIT;
1040 TCP_REG(&tcp_tw_pcbs, pcb);
1045 if ((flags & TCP_ACK) && ackno == pcb->snd_nxt && pcb->unsent == NULL) {
1046 LWIP_DEBUGF(
TCP_DEBUG, (
"TCP connection closed: LAST_ACK %"U16_F
" -> %"U16_F
".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
1048 recv_flags |= TF_CLOSED;
1064tcp_oos_insert_segment(
struct tcp_seg *cseg,
struct tcp_seg *next)
1066 struct tcp_seg *old_seg;
1068 LWIP_ASSERT(
"tcp_oos_insert_segment: invalid cseg", cseg != NULL);
1070 if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
1072 tcp_segs_free(next);
1078 TCP_SEQ_GEQ((seqno + cseg->len),
1079 (next->tcphdr->seqno + next->len))) {
1081 if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) {
1082 TCPH_SET_FLAG(cseg->tcphdr, TCP_FIN);
1086 tcp_seg_free(old_seg);
1089 TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) {
1091 cseg->len = (u16_t)(next->tcphdr->seqno - seqno);
1092 pbuf_realloc(cseg->p, cseg->len);
1100static struct tcp_seg *
1101tcp_free_acked_segments(
struct tcp_pcb *pcb,
struct tcp_seg *seg_list,
const char *dbg_list_name,
1102 struct tcp_seg *dbg_other_seg_list)
1104 struct tcp_seg *next;
1110 while (seg_list != NULL &&
1111 TCP_SEQ_LEQ(lwip_ntohl(seg_list->tcphdr->seqno) +
1112 TCP_TCPLEN(seg_list), ackno)) {
1113 LWIP_DEBUGF(
TCP_INPUT_DEBUG, (
"tcp_receive: removing %"U32_F
":%"U32_F
" from pcb->%s\n",
1114 lwip_ntohl(seg_list->tcphdr->seqno),
1115 lwip_ntohl(seg_list->tcphdr->seqno) + TCP_TCPLEN(seg_list),
1119 seg_list = seg_list->next;
1121 clen = pbuf_clen(next->p);
1122 LWIP_DEBUGF(
TCP_QLEN_DEBUG, (
"tcp_receive: queuelen %"TCPWNDSIZE_F
" ... ",
1123 (tcpwnd_size_t)pcb->snd_queuelen));
1124 LWIP_ASSERT(
"pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= clen));
1126 pcb->snd_queuelen = (u16_t)(pcb->snd_queuelen - clen);
1127 recv_acked = (tcpwnd_size_t)(recv_acked + next->len);
1130 LWIP_DEBUGF(
TCP_QLEN_DEBUG, (
"%"TCPWNDSIZE_F
" (after freeing %s)\n",
1131 (tcpwnd_size_t)pcb->snd_queuelen,
1133 if (pcb->snd_queuelen != 0) {
1134 LWIP_ASSERT(
"tcp_receive: valid queue length",
1135 seg_list != NULL || dbg_other_seg_list != NULL);
1154tcp_receive(
struct tcp_pcb *pcb)
1157 u32_t right_wnd_edge;
1159 LWIP_ASSERT(
"tcp_receive: invalid pcb", pcb != NULL);
1160 LWIP_ASSERT(
"tcp_receive: wrong state", pcb->state >= ESTABLISHED);
1162 if (flags & TCP_ACK) {
1163 right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2;
1166 if (TCP_SEQ_LT(pcb->snd_wl1, seqno) ||
1167 (pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) ||
1168 (pcb->snd_wl2 == ackno && (u32_t)SND_WND_SCALE(pcb, tcphdr->wnd) > pcb->snd_wnd)) {
1169 pcb->snd_wnd = SND_WND_SCALE(pcb, tcphdr->wnd);
1172 if (pcb->snd_wnd_max < pcb->snd_wnd) {
1173 pcb->snd_wnd_max = pcb->snd_wnd;
1175 pcb->snd_wl1 = seqno;
1176 pcb->snd_wl2 = ackno;
1177 LWIP_DEBUGF(
TCP_WND_DEBUG, (
"tcp_receive: window update %"TCPWNDSIZE_F
"\n", pcb->snd_wnd));
1180 if (pcb->snd_wnd != (tcpwnd_size_t)SND_WND_SCALE(pcb, tcphdr->wnd)) {
1182 (
"tcp_receive: no window update lastack %"U32_F
" ackno %"
1183 U32_F
" wl1 %"U32_F
" seqno %"U32_F
" wl2 %"U32_F
"\n",
1184 pcb->lastack, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2));
1210 if (TCP_SEQ_LEQ(ackno, pcb->lastack)) {
1214 if (pcb->snd_wl2 + pcb->snd_wnd == right_wnd_edge) {
1216 if (pcb->rtime >= 0) {
1218 if (pcb->lastack == ackno) {
1219 if ((u8_t)(pcb->dupacks + 1) > pcb->dupacks) {
1222 if (pcb->dupacks > 3) {
1224 TCP_WND_INC(pcb->cwnd, pcb->mss);
1226 if (pcb->dupacks >= 3) {
1228 tcp_rexmit_fast(pcb);
1234 }
else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack + 1, pcb->snd_nxt)) {
1236 tcpwnd_size_t acked;
1241 if (pcb->flags & TF_INFR) {
1242 tcp_clear_flags(pcb, TF_INFR);
1243 pcb->cwnd = pcb->ssthresh;
1244 pcb->bytes_acked = 0;
1251 pcb->rto = (s16_t)((pcb->sa >> 3) + pcb->sv);
1254 acked = (tcpwnd_size_t)(ackno - pcb->lastack);
1258 pcb->lastack = ackno;
1262 if (pcb->state >= ESTABLISHED) {
1263 if (pcb->cwnd < pcb->ssthresh) {
1264 tcpwnd_size_t increase;
1266 u8_t num_seg = (pcb->flags & TF_RTO) ? 1 : 2;
1268 increase = LWIP_MIN(acked, (tcpwnd_size_t)(num_seg * pcb->mss));
1269 TCP_WND_INC(pcb->cwnd, increase);
1270 LWIP_DEBUGF(
TCP_CWND_DEBUG, (
"tcp_receive: slow start cwnd %"TCPWNDSIZE_F
"\n", pcb->cwnd));
1273 TCP_WND_INC(pcb->bytes_acked, acked);
1274 if (pcb->bytes_acked >= pcb->cwnd) {
1275 pcb->bytes_acked = (tcpwnd_size_t)(pcb->bytes_acked - pcb->cwnd);
1276 TCP_WND_INC(pcb->cwnd, pcb->mss);
1278 LWIP_DEBUGF(
TCP_CWND_DEBUG, (
"tcp_receive: congestion avoidance cwnd %"TCPWNDSIZE_F
"\n", pcb->cwnd));
1281 LWIP_DEBUGF(
TCP_INPUT_DEBUG, (
"tcp_receive: ACK for %"U32_F
", unacked->seqno %"U32_F
":%"U32_F
"\n",
1283 pcb->unacked != NULL ?
1284 lwip_ntohl(pcb->unacked->tcphdr->seqno) : 0,
1285 pcb->unacked != NULL ?
1286 lwip_ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked) : 0));
1290 pcb->unacked = tcp_free_acked_segments(pcb, pcb->unacked,
"unacked", pcb->unsent);
1297 pcb->unsent = tcp_free_acked_segments(pcb, pcb->unsent,
"unsent", pcb->unacked);
1301 if (pcb->unacked == NULL) {
1310 if (pcb->unsent == NULL) {
1311 pcb->unsent_oversize = 0;
1315#if LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS
1316 if (ip_current_is_v6()) {
1318 nd6_reachability_hint(ip6_current_src_addr());
1322 pcb->snd_buf = (tcpwnd_size_t)(pcb->snd_buf + recv_acked);
1324 if (pcb->flags & TF_RTO) {
1329 if (pcb->unacked == NULL) {
1330 if ((pcb->unsent == NULL) ||
1331 (TCP_SEQ_LEQ(pcb->rto_end, lwip_ntohl(pcb->unsent->tcphdr->seqno)))) {
1332 tcp_clear_flags(pcb, TF_RTO);
1334 }
else if (TCP_SEQ_LEQ(pcb->rto_end, lwip_ntohl(pcb->unacked->tcphdr->seqno))) {
1335 tcp_clear_flags(pcb, TF_RTO);
1341 tcp_send_empty_ack(pcb);
1344 LWIP_DEBUGF(
TCP_RTO_DEBUG, (
"tcp_receive: pcb->rttest %"U32_F
" rtseq %"U32_F
" ackno %"U32_F
"\n",
1345 pcb->rttest, pcb->rtseq, ackno));
1350 if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) {
1353 m = (s16_t)(tcp_ticks - pcb->rttest);
1355 LWIP_DEBUGF(
TCP_RTO_DEBUG, (
"tcp_receive: experienced rtt %"U16_F
" ticks (%"U16_F
" msec).\n",
1356 m, (u16_t)(m * TCP_SLOW_INTERVAL)));
1359 m = (s16_t)(m - (pcb->sa >> 3));
1360 pcb->sa = (s16_t)(pcb->sa + m);
1364 m = (s16_t)(m - (pcb->sv >> 2));
1365 pcb->sv = (s16_t)(pcb->sv + m);
1366 pcb->rto = (s16_t)((pcb->sa >> 3) + pcb->sv);
1368 LWIP_DEBUGF(
TCP_RTO_DEBUG, (
"tcp_receive: RTO %"U16_F
" (%"U16_F
" milliseconds)\n",
1369 pcb->rto, (u16_t)(pcb->rto * TCP_SLOW_INTERVAL)));
1379 if ((tcplen > 0) && (pcb->state < CLOSE_WAIT)) {
1410 if (TCP_SEQ_BETWEEN(pcb->rcv_nxt, seqno + 1, seqno + tcplen - 1)) {
1431 struct pbuf *p = inseg.p;
1432 u32_t off32 = pcb->rcv_nxt - seqno;
1433 u16_t new_tot_len, off;
1434 LWIP_ASSERT(
"inseg.p != NULL", inseg.p);
1435 LWIP_ASSERT(
"insane offset!", (off32 < 0xffff));
1437 LWIP_ASSERT(
"pbuf too short!", (((s32_t)inseg.p->tot_len) >= off));
1439 new_tot_len = (u16_t)(inseg.p->tot_len - off);
1440 while (p->len < off) {
1443 p->tot_len = new_tot_len;
1449 inseg.tcphdr->seqno = seqno = pcb->rcv_nxt;
1451 if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)) {
1455 LWIP_DEBUGF(
TCP_INPUT_DEBUG, (
"tcp_receive: duplicate seqno %"U32_F
"\n", seqno));
1463 if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
1464 pcb->rcv_nxt + pcb->rcv_wnd - 1)) {
1465 if (pcb->rcv_nxt == seqno) {
1469 tcplen = TCP_TCPLEN(&inseg);
1471 if (tcplen > pcb->rcv_wnd) {
1473 (
"tcp_receive: other end overran receive window"
1474 "seqno %"U32_F
" len %"U16_F
" right edge %"U32_F
"\n",
1475 seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd));
1476 if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
1479 TCPH_FLAGS_SET(inseg.tcphdr, TCPH_FLAGS(inseg.tcphdr) & ~(
unsigned int)TCP_FIN);
1482 TCPWND_CHECK16(pcb->rcv_wnd);
1483 inseg.len = (u16_t)pcb->rcv_wnd;
1484 if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) {
1487 pbuf_realloc(inseg.p, inseg.len);
1488 tcplen = TCP_TCPLEN(&inseg);
1489 LWIP_ASSERT(
"tcp_receive: segment not trimmed correctly to rcv_wnd",
1490 (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd));
1496 if (pcb->ooseq != NULL) {
1497 if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
1499 (
"tcp_receive: received in-order FIN, binning ooseq queue\n"));
1503 while (pcb->ooseq != NULL) {
1504 struct tcp_seg *old_ooseq = pcb->ooseq;
1505 pcb->ooseq = pcb->ooseq->next;
1506 tcp_seg_free(old_ooseq);
1509 struct tcp_seg *next = pcb->ooseq;
1513 TCP_SEQ_GEQ(seqno + tcplen,
1514 next->tcphdr->seqno + next->len)) {
1515 struct tcp_seg *tmp;
1517 if ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0 &&
1518 (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) == 0) {
1519 TCPH_SET_FLAG(inseg.tcphdr, TCP_FIN);
1520 tcplen = TCP_TCPLEN(&inseg);
1529 TCP_SEQ_GT(seqno + tcplen,
1530 next->tcphdr->seqno)) {
1532 inseg.len = (u16_t)(next->tcphdr->seqno - seqno);
1533 if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) {
1536 pbuf_realloc(inseg.p, inseg.len);
1537 tcplen = TCP_TCPLEN(&inseg);
1538 LWIP_ASSERT(
"tcp_receive: segment not trimmed correctly to ooseq queue",
1539 (seqno + tcplen) == next->tcphdr->seqno);
1546 pcb->rcv_nxt = seqno + tcplen;
1549 LWIP_ASSERT(
"tcp_receive: tcplen > rcv_wnd", pcb->rcv_wnd >= tcplen);
1550 pcb->rcv_wnd -= tcplen;
1552 tcp_update_rcv_ann_wnd(pcb);
1563 if (inseg.p->tot_len > 0) {
1564 recv_data = inseg.p;
1570 if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
1572 recv_flags |= TF_GOT_FIN;
1578 while (pcb->ooseq != NULL &&
1579 pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) {
1581 struct tcp_seg *cseg = pcb->ooseq;
1582 seqno = pcb->ooseq->tcphdr->seqno;
1584 pcb->rcv_nxt += TCP_TCPLEN(cseg);
1585 LWIP_ASSERT(
"tcp_receive: ooseq tcplen > rcv_wnd",
1586 pcb->rcv_wnd >= TCP_TCPLEN(cseg));
1587 pcb->rcv_wnd -= TCP_TCPLEN(cseg);
1589 tcp_update_rcv_ann_wnd(pcb);
1591 if (cseg->p->tot_len > 0) {
1600 recv_data = cseg->p;
1604 if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
1606 recv_flags |= TF_GOT_FIN;
1607 if (pcb->state == ESTABLISHED) {
1608 pcb->state = CLOSE_WAIT;
1612 pcb->ooseq = cseg->next;
1615#if LWIP_TCP_SACK_OUT
1616 if (pcb->flags & TF_SACK) {
1617 if (pcb->ooseq != NULL) {
1620 tcp_remove_sacks_lt(pcb, pcb->ooseq->tcphdr->seqno);
1621 }
else if (LWIP_TCP_SACK_VALID(pcb, 0)) {
1623 memset(pcb->rcv_sacks, 0,
sizeof(pcb->rcv_sacks));
1633#if LWIP_TCP_SACK_OUT
1634 if (LWIP_TCP_SACK_VALID(pcb, 0)) {
1639 tcp_send_empty_ack(pcb);
1643#if LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS
1644 if (ip_current_is_v6()) {
1646 nd6_reachability_hint(ip6_current_src_addr());
1655 if (pcb->ooseq == NULL) {
1656 pcb->ooseq = tcp_seg_copy(&inseg);
1657#if LWIP_TCP_SACK_OUT
1658 if (pcb->flags & TF_SACK) {
1660 pcb->rcv_sacks[0].left = seqno;
1661 pcb->rcv_sacks[0].right = seqno + inseg.len;
1677#if LWIP_TCP_SACK_OUT
1680 u32_t sackbeg = TCP_SEQ_LT(seqno, pcb->ooseq->tcphdr->seqno) ? seqno : pcb->ooseq->tcphdr->seqno;
1682 struct tcp_seg *next, *prev = NULL;
1683 for (next = pcb->ooseq; next != NULL; next = next->next) {
1684 if (seqno == next->tcphdr->seqno) {
1689 if (inseg.len > next->len) {
1690 struct tcp_seg* cseg;
1696 if (next->next == NULL) {
1703 cseg = tcp_seg_copy(&inseg);
1710 tcp_oos_insert_segment(cseg, next);
1721 if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {
1726 struct tcp_seg *cseg = tcp_seg_copy(&inseg);
1729 tcp_oos_insert_segment(cseg, next);
1736 if (TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno + 1, next->tcphdr->seqno - 1)) {
1742 struct tcp_seg *cseg = tcp_seg_copy(&inseg);
1744 if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) {
1746 prev->len = (u16_t)(seqno - prev->tcphdr->seqno);
1747 pbuf_realloc(prev->p, prev->len);
1750 tcp_oos_insert_segment(cseg, next);
1756#if LWIP_TCP_SACK_OUT
1759 if (prev != NULL && prev->tcphdr->seqno + prev->len != next->tcphdr->seqno) {
1760 sackbeg = next->tcphdr->seqno;
1772 if (next->next == NULL &&
1773 TCP_SEQ_GT(seqno, next->tcphdr->seqno)) {
1774 if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) {
1778 next->next = tcp_seg_copy(&inseg);
1779 if (next->next != NULL) {
1780 if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) {
1782 next->len = (u16_t)(seqno - next->tcphdr->seqno);
1783 pbuf_realloc(next->p, next->len);
1786 if (TCP_SEQ_GT((u32_t)tcplen + seqno, pcb->rcv_nxt + (u32_t)pcb->rcv_wnd)) {
1788 (
"tcp_receive: other end overran receive window"
1789 "seqno %"U32_F
" len %"U16_F
" right edge %"U32_F
"\n",
1790 seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd));
1791 if (TCPH_FLAGS(next->next->tcphdr) & TCP_FIN) {
1794 TCPH_FLAGS_SET(next->next->tcphdr, TCPH_FLAGS(next->next->tcphdr) & ~TCP_FIN);
1797 next->next->len = (u16_t)(pcb->rcv_nxt + pcb->rcv_wnd - seqno);
1798 pbuf_realloc(next->next->p, next->next->len);
1799 tcplen = TCP_TCPLEN(next->next);
1800 LWIP_ASSERT(
"tcp_receive: segment not trimmed correctly to rcv_wnd",
1801 (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd));
1809#if LWIP_TCP_SACK_OUT
1810 if (pcb->flags & TF_SACK) {
1815 }
else if (prev->next != NULL) {
1819 if (prev->tcphdr->seqno + prev->len != next->tcphdr->seqno) {
1820 sackbeg = next->tcphdr->seqno;
1826 u32_t sackend = next->tcphdr->seqno;
1827 for ( ; (next != NULL) && (sackend == next->tcphdr->seqno); next = next->next) {
1828 sackend += next->len;
1830 tcp_add_sack(pcb, sackbeg, sackend);
1835#if defined(TCP_OOSEQ_BYTES_LIMIT) || defined(TCP_OOSEQ_PBUFS_LIMIT)
1839#ifdef TCP_OOSEQ_BYTES_LIMIT
1840 const u32_t ooseq_max_blen = TCP_OOSEQ_BYTES_LIMIT(pcb);
1841 u32_t ooseq_blen = 0;
1843#ifdef TCP_OOSEQ_PBUFS_LIMIT
1844 const u16_t ooseq_max_qlen = TCP_OOSEQ_PBUFS_LIMIT(pcb);
1845 u16_t ooseq_qlen = 0;
1847 struct tcp_seg *next, *prev = NULL;
1848 for (next = pcb->ooseq; next != NULL; prev = next, next = next->next) {
1849 struct pbuf *p = next->p;
1851#ifdef TCP_OOSEQ_BYTES_LIMIT
1853 if (ooseq_blen > ooseq_max_blen) {
1857#ifdef TCP_OOSEQ_PBUFS_LIMIT
1858 ooseq_qlen += pbuf_clen(p);
1859 if (ooseq_qlen > ooseq_max_qlen) {
1864#if LWIP_TCP_SACK_OUT
1865 if (pcb->flags & TF_SACK) {
1867 tcp_remove_sacks_gt(pcb, next->tcphdr->seqno);
1871 tcp_segs_free(next);
1888 tcp_send_empty_ack(pcb);
1892 tcp_send_empty_ack(pcb);
1897 if (!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd - 1)) {
1904tcp_get_next_optbyte(
void)
1906 u16_t optidx = tcp_optidx++;
1907 if ((tcphdr_opt2 == NULL) || (optidx < tcphdr_opt1len)) {
1908 u8_t *opts = (u8_t *)tcphdr + TCP_HLEN;
1909 return opts[optidx];
1911 u8_t idx = (u8_t)(optidx - tcphdr_opt1len);
1912 return tcphdr_opt2[idx];
1925tcp_parseopt(
struct tcp_pcb *pcb)
1929#if LWIP_TCP_TIMESTAMPS
1933 LWIP_ASSERT(
"tcp_parseopt: invalid pcb", pcb != NULL);
1936 if (tcphdr_optlen != 0) {
1937 for (tcp_optidx = 0; tcp_optidx < tcphdr_optlen; ) {
1938 u8_t opt = tcp_get_next_optbyte();
1940 case LWIP_TCP_OPT_EOL:
1944 case LWIP_TCP_OPT_NOP:
1948 case LWIP_TCP_OPT_MSS:
1950 if (tcp_get_next_optbyte() != LWIP_TCP_OPT_LEN_MSS || (tcp_optidx - 2 + LWIP_TCP_OPT_LEN_MSS) > tcphdr_optlen) {
1956 mss = (u16_t)(tcp_get_next_optbyte() << 8);
1957 mss |= tcp_get_next_optbyte();
1959 pcb->mss = ((mss > TCP_MSS) || (mss == 0)) ? TCP_MSS : mss;
1962 case LWIP_TCP_OPT_WS:
1964 if (tcp_get_next_optbyte() != LWIP_TCP_OPT_LEN_WS || (tcp_optidx - 2 + LWIP_TCP_OPT_LEN_WS) > tcphdr_optlen) {
1970 data = tcp_get_next_optbyte();
1973 if ((flags & TCP_SYN) && !(pcb->flags & TF_WND_SCALE)) {
1974 pcb->snd_scale = data;
1975 if (pcb->snd_scale > 14U) {
1976 pcb->snd_scale = 14U;
1978 pcb->rcv_scale = TCP_RCV_SCALE;
1979 tcp_set_flags(pcb, TF_WND_SCALE);
1981 LWIP_ASSERT(
"window not at default value", pcb->rcv_wnd == TCPWND_MIN16(TCP_WND));
1982 LWIP_ASSERT(
"window not at default value", pcb->rcv_ann_wnd == TCPWND_MIN16(TCP_WND));
1983 pcb->rcv_wnd = pcb->rcv_ann_wnd = TCP_WND;
1987#if LWIP_TCP_TIMESTAMPS
1988 case LWIP_TCP_OPT_TS:
1990 if (tcp_get_next_optbyte() != LWIP_TCP_OPT_LEN_TS || (tcp_optidx - 2 + LWIP_TCP_OPT_LEN_TS) > tcphdr_optlen) {
1996 tsval = tcp_get_next_optbyte();
1997 tsval |= (tcp_get_next_optbyte() << 8);
1998 tsval |= (tcp_get_next_optbyte() << 16);
1999 tsval |= (tcp_get_next_optbyte() << 24);
2000 if (flags & TCP_SYN) {
2001 pcb->ts_recent = lwip_ntohl(tsval);
2004 tcp_set_flags(pcb, TF_TIMESTAMP);
2005 }
else if (TCP_SEQ_BETWEEN(pcb->ts_lastacksent, seqno, seqno + tcplen)) {
2006 pcb->ts_recent = lwip_ntohl(tsval);
2009 tcp_optidx += LWIP_TCP_OPT_LEN_TS - 6;
2012#if LWIP_TCP_SACK_OUT
2013 case LWIP_TCP_OPT_SACK_PERM:
2015 if (tcp_get_next_optbyte() != LWIP_TCP_OPT_LEN_SACK_PERM || (tcp_optidx - 2 + LWIP_TCP_OPT_LEN_SACK_PERM) > tcphdr_optlen) {
2021 if (flags & TCP_SYN) {
2023 tcp_set_flags(pcb, TF_SACK);
2029 data = tcp_get_next_optbyte();
2038 tcp_optidx += data - 2;
2045tcp_trigger_input_pcb_close(
void)
2047 recv_flags |= TF_CLOSED;
2050#if LWIP_TCP_SACK_OUT
2063tcp_add_sack(
struct tcp_pcb *pcb, u32_t left, u32_t right)
2068 if ((pcb->flags & TF_SACK) == 0 || !TCP_SEQ_LT(left, right)) {
2081 if (TCP_SEQ_LEQ(pcb->rcv_sacks[i].right, left) || TCP_SEQ_LEQ(right, pcb->rcv_sacks[i].left)) {
2082 if (unused_idx != i) {
2084 pcb->rcv_sacks[unused_idx] = pcb->rcv_sacks[i];
2099 if (i - 1 >= unused_idx) {
2101 pcb->rcv_sacks[i].left = pcb->rcv_sacks[i].right = 0;
2103 pcb->rcv_sacks[i] = pcb->rcv_sacks[i - 1];
2108 pcb->rcv_sacks[0].left = left;
2109 pcb->rcv_sacks[0].right = right;
2123tcp_remove_sacks_lt(
struct tcp_pcb *pcb, u32_t seq)
2132 if (TCP_SEQ_GT(pcb->rcv_sacks[i].right, seq)) {
2133 if (unused_idx != i) {
2135 pcb->rcv_sacks[unused_idx] = pcb->rcv_sacks[i];
2138 if (TCP_SEQ_LT(pcb->rcv_sacks[unused_idx].left, seq)) {
2139 pcb->rcv_sacks[unused_idx].left = seq;
2147 pcb->rcv_sacks[i].left = pcb->rcv_sacks[i].right = 0;
2151#if defined(TCP_OOSEQ_BYTES_LIMIT) || defined(TCP_OOSEQ_PBUFS_LIMIT)
2163tcp_remove_sacks_gt(
struct tcp_pcb *pcb, u32_t seq)
2172 if (TCP_SEQ_LT(pcb->rcv_sacks[i].left, seq)) {
2173 if (unused_idx != i) {
2175 pcb->rcv_sacks[unused_idx] = pcb->rcv_sacks[i];
2178 if (TCP_SEQ_GT(pcb->rcv_sacks[unused_idx].right, seq)) {
2179 pcb->rcv_sacks[unused_idx].right = seq;
2187 pcb->rcv_sacks[i].left = pcb->rcv_sacks[i].right = 0;
#define LWIP_UNUSED_ARG(x)
#define LWIP_ASSERT_CORE_LOCKED()
#define LWIP_TCP_MAX_SACK_NUM
void pbuf_cat(struct pbuf *head, struct pbuf *tail)
u8 pbuf_free(struct pbuf *p)
#define ip_current_src_addr()
#define ip_current_dest_addr()
#define ip_current_netif()
#define PBUF_FLAG_TCP_FIN
u8_t pbuf_remove_header(struct pbuf *p, size_t header_size)