patch #6537/#7858: TCP window scaling support (OOS queueing still needs special handling)

This commit is contained in:
Simon Goldschmidt 2014-02-06 22:34:06 +01:00
parent 33086e6db0
commit d2a89b424b
9 changed files with 2445 additions and 2301 deletions

View File

@ -6,6 +6,9 @@ HISTORY
++ New features: ++ New features:
2014-02-05: Simon Goldschmidt (patch by "xtian" and "alex_ab")
* patch #6537/#7858: TCP window scaling support
2014-01-17: Jiri Engelthaler 2014-01-17: Jiri Engelthaler
* icmp, icmp6, opt.h: patch #8027: Completed HW checksuming for IPv4 and * icmp, icmp6, opt.h: patch #8027: Completed HW checksuming for IPv4 and
IPv6 ICMP's IPv6 ICMP's

View File

@ -115,9 +115,24 @@
#error "MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS doesn't make sense since each struct ip_reassdata must hold 2 pbufs at least!" #error "MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS doesn't make sense since each struct ip_reassdata must hold 2 pbufs at least!"
#endif #endif
#endif /* !MEMP_MEM_MALLOC */ #endif /* !MEMP_MEM_MALLOC */
#if (LWIP_TCP && (TCP_WND > 0xffff)) #if LWIP_WND_SCALE
#error "If you want to use TCP, TCP_WND must fit in an u16_t, so, you have to reduce it in your lwipopts.h" #if (LWIP_TCP && (TCP_WND > 0xffffffff))
#error "If you want to use TCP, TCP_WND must fit in an u32_t, so, you have to reduce it in your lwipopts.h"
#endif #endif
#if (LWIP_TCP && LWIP_WND_SCALE > 14)
#error "The maximum valid window scale value is 14!"
#endif
#if (LWIP_TCP && (TCP_WND > (0xFFFFU << TCP_RCV_SCALE)))
#error "TCP_WND is bigger than the configured LWIP_WND_SCALE allows!"
#endif
#if (LWIP_TCP && ((TCP_WND >> TCP_RCV_SCALE) == 0))
#error "TCP_WND is too small for the configured LWIP_WND_SCALE (results in zero window)!"
#endif
#else /* LWIP_WND_SCALE */
#if (LWIP_TCP && (TCP_WND > 0xffff))
#error "If you want to use TCP, TCP_WND must fit in an u16_t, so, you have to reduce it in your lwipopts.h (or enable window scaling)"
#endif
#endif /* LWIP_WND_SCALE */
#if (LWIP_TCP && (TCP_SND_QUEUELEN > 0xffff)) #if (LWIP_TCP && (TCP_SND_QUEUELEN > 0xffff))
#error "If you want to use TCP, TCP_SND_QUEUELEN must fit in an u16_t, so, you have to reduce it in your lwipopts.h" #error "If you want to use TCP, TCP_SND_QUEUELEN must fit in an u16_t, so, you have to reduce it in your lwipopts.h"
#endif #endif

View File

@ -625,8 +625,10 @@ u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb)
} else { } else {
/* keep the right edge of window constant */ /* keep the right edge of window constant */
u32_t new_rcv_ann_wnd = pcb->rcv_ann_right_edge - pcb->rcv_nxt; u32_t new_rcv_ann_wnd = pcb->rcv_ann_right_edge - pcb->rcv_nxt;
#if !LWIP_WND_SCALE
LWIP_ASSERT("new_rcv_ann_wnd <= 0xffff", new_rcv_ann_wnd <= 0xffff); LWIP_ASSERT("new_rcv_ann_wnd <= 0xffff", new_rcv_ann_wnd <= 0xffff);
pcb->rcv_ann_wnd = (u16_t)new_rcv_ann_wnd; #endif
pcb->rcv_ann_wnd = (tcpwnd_size_t)new_rcv_ann_wnd;
} }
return 0; return 0;
} }
@ -649,7 +651,7 @@ tcp_recved(struct tcp_pcb *pcb, u16_t len)
LWIP_ASSERT("don't call tcp_recved for listen-pcbs", LWIP_ASSERT("don't call tcp_recved for listen-pcbs",
pcb->state != LISTEN); pcb->state != LISTEN);
LWIP_ASSERT("tcp_recved: len would wrap rcv_wnd\n", LWIP_ASSERT("tcp_recved: len would wrap rcv_wnd\n",
len <= 0xffff - pcb->rcv_wnd ); len <= TCPWND_MAX - pcb->rcv_wnd);
pcb->rcv_wnd += len; pcb->rcv_wnd += len;
if (pcb->rcv_wnd > TCP_WND) { if (pcb->rcv_wnd > TCP_WND) {
@ -824,7 +826,7 @@ void
tcp_slowtmr(void) tcp_slowtmr(void)
{ {
struct tcp_pcb *pcb, *prev; struct tcp_pcb *pcb, *prev;
u16_t eff_wnd; tcpwnd_size_t eff_wnd;
u8_t pcb_remove; /* flag if a PCB should be removed */ u8_t pcb_remove; /* flag if a PCB should be removed */
u8_t pcb_reset; /* flag if a RST should be sent when removing */ u8_t pcb_reset; /* flag if a RST should be sent when removing */
err_t err; err_t err;
@ -899,14 +901,14 @@ tcp_slowtmr_start:
/* Reduce congestion window and ssthresh. */ /* Reduce congestion window and ssthresh. */
eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd); eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd);
pcb->ssthresh = eff_wnd >> 1; pcb->ssthresh = eff_wnd >> 1;
if (pcb->ssthresh < (pcb->mss << 1)) { if (pcb->ssthresh < (tcpwnd_size_t)(pcb->mss << 1)) {
pcb->ssthresh = (pcb->mss << 1); pcb->ssthresh = (pcb->mss << 1);
} }
pcb->cwnd = pcb->mss; pcb->cwnd = pcb->mss;
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %"U16_F LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %"TCPWNDSIZE_F
" ssthresh %"U16_F"\n", " ssthresh %"TCPWNDSIZE_F"\n",
pcb->cwnd, pcb->ssthresh)); pcb->cwnd, pcb->ssthresh));
/* The following needs to be called AFTER cwnd is set to one /* The following needs to be called AFTER cwnd is set to one
mss - STJ */ mss - STJ */
tcp_rexmit_rto(pcb); tcp_rexmit_rto(pcb);
@ -1348,6 +1350,11 @@ tcp_alloc(u8_t prio)
pcb->snd_queuelen = 0; pcb->snd_queuelen = 0;
pcb->rcv_wnd = TCP_WND; pcb->rcv_wnd = TCP_WND;
pcb->rcv_ann_wnd = TCP_WND; pcb->rcv_ann_wnd = TCP_WND;
#if LWIP_WND_SCALE
/* snd_scale and rcv_scale are zero unless both sides agree to use scaling */
pcb->snd_scale = 0;
pcb->rcv_scale = 0;
#endif
pcb->tos = 0; pcb->tos = 0;
pcb->ttl = TCP_TTL; pcb->ttl = TCP_TTL;
/* As initial send MSS, we use TCP_MSS but limit it to 536. /* As initial send MSS, we use TCP_MSS but limit it to 536.

View File

@ -500,9 +500,6 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
npcb->state = SYN_RCVD; npcb->state = SYN_RCVD;
npcb->rcv_nxt = seqno + 1; npcb->rcv_nxt = seqno + 1;
npcb->rcv_ann_right_edge = npcb->rcv_nxt; npcb->rcv_ann_right_edge = npcb->rcv_nxt;
npcb->snd_wnd = tcphdr->wnd;
npcb->snd_wnd_max = tcphdr->wnd;
npcb->ssthresh = npcb->snd_wnd;
npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */ npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */
npcb->callback_arg = pcb->callback_arg; npcb->callback_arg = pcb->callback_arg;
#if LWIP_CALLBACK_API #if LWIP_CALLBACK_API
@ -516,6 +513,10 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
/* Parse any options in the SYN. */ /* Parse any options in the SYN. */
tcp_parseopt(npcb); tcp_parseopt(npcb);
npcb->snd_wnd = SND_WND_SCALE(npcb, tcphdr->wnd);
npcb->snd_wnd_max = npcb->snd_wnd;
npcb->ssthresh = npcb->snd_wnd;
#if TCP_CALCULATE_EFF_SEND_MSS #if TCP_CALCULATE_EFF_SEND_MSS
npcb->mss = tcp_eff_send_mss(npcb->mss, &npcb->local_ip, npcb->mss = tcp_eff_send_mss(npcb->mss, &npcb->local_ip,
&npcb->remote_ip, PCB_ISIPV6(npcb)); &npcb->remote_ip, PCB_ISIPV6(npcb));
@ -653,8 +654,8 @@ tcp_process(struct tcp_pcb *pcb)
pcb->rcv_nxt = seqno + 1; pcb->rcv_nxt = seqno + 1;
pcb->rcv_ann_right_edge = pcb->rcv_nxt; pcb->rcv_ann_right_edge = pcb->rcv_nxt;
pcb->lastack = ackno; pcb->lastack = ackno;
pcb->snd_wnd = tcphdr->wnd; pcb->snd_wnd = SND_WND_SCALE(pcb, tcphdr->wnd);
pcb->snd_wnd_max = tcphdr->wnd; pcb->snd_wnd_max = pcb->snd_wnd;
pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */ pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */
pcb->state = ESTABLISHED; pcb->state = ESTABLISHED;
@ -670,7 +671,7 @@ tcp_process(struct tcp_pcb *pcb)
pcb->cwnd = ((pcb->cwnd == 1) ? (pcb->mss * 2) : pcb->mss); pcb->cwnd = ((pcb->cwnd == 1) ? (pcb->mss * 2) : pcb->mss);
LWIP_ASSERT("pcb->snd_queuelen > 0", (pcb->snd_queuelen > 0)); LWIP_ASSERT("pcb->snd_queuelen > 0", (pcb->snd_queuelen > 0));
--pcb->snd_queuelen; --pcb->snd_queuelen;
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"U16_F"\n", (u16_t)pcb->snd_queuelen)); LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"TCPWNDSIZE_F"\n", (tcpwnd_size_t)pcb->snd_queuelen));
rseg = pcb->unacked; rseg = pcb->unacked;
pcb->unacked = rseg->next; pcb->unacked = rseg->next;
tcp_seg_free(rseg); tcp_seg_free(rseg);
@ -703,7 +704,7 @@ tcp_process(struct tcp_pcb *pcb)
if (flags & TCP_ACK) { if (flags & TCP_ACK) {
/* expected ACK number? */ /* expected ACK number? */
if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) { if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) {
u16_t old_cwnd; tcpwnd_size_t old_cwnd;
pcb->state = ESTABLISHED; pcb->state = ESTABLISHED;
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
#if LWIP_CALLBACK_API #if LWIP_CALLBACK_API
@ -889,11 +890,11 @@ tcp_receive(struct tcp_pcb *pcb)
if (TCP_SEQ_LT(pcb->snd_wl1, seqno) || if (TCP_SEQ_LT(pcb->snd_wl1, seqno) ||
(pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) || (pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) ||
(pcb->snd_wl2 == ackno && tcphdr->wnd > pcb->snd_wnd)) { (pcb->snd_wl2 == ackno && tcphdr->wnd > pcb->snd_wnd)) {
pcb->snd_wnd = tcphdr->wnd; pcb->snd_wnd = SND_WND_SCALE(pcb, tcphdr->wnd);
/* keep track of the biggest window announced by the remote host to calculate /* keep track of the biggest window announced by the remote host to calculate
the maximum segment size */ the maximum segment size */
if (pcb->snd_wnd_max < tcphdr->wnd) { if (pcb->snd_wnd_max < pcb->snd_wnd) {
pcb->snd_wnd_max = tcphdr->wnd; pcb->snd_wnd_max = pcb->snd_wnd;
} }
pcb->snd_wl1 = seqno; pcb->snd_wl1 = seqno;
pcb->snd_wl2 = ackno; pcb->snd_wl2 = ackno;
@ -957,7 +958,7 @@ tcp_receive(struct tcp_pcb *pcb)
if (pcb->dupacks > 3) { if (pcb->dupacks > 3) {
/* Inflate the congestion window, but not if it means that /* Inflate the congestion window, but not if it means that
the value overflows. */ the value overflows. */
if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { if ((tcpwnd_size_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
pcb->cwnd += pcb->mss; pcb->cwnd += pcb->mss;
} }
} else if (pcb->dupacks == 3) { } else if (pcb->dupacks == 3) {
@ -1003,16 +1004,16 @@ tcp_receive(struct tcp_pcb *pcb)
ssthresh). */ ssthresh). */
if (pcb->state >= ESTABLISHED) { if (pcb->state >= ESTABLISHED) {
if (pcb->cwnd < pcb->ssthresh) { if (pcb->cwnd < pcb->ssthresh) {
if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { if ((tcpwnd_size_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
pcb->cwnd += pcb->mss; pcb->cwnd += pcb->mss;
} }
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %"U16_F"\n", pcb->cwnd)); LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %"TCPWNDSIZE_F"\n", pcb->cwnd));
} else { } else {
u16_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd); tcpwnd_size_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd);
if (new_cwnd > pcb->cwnd) { if (new_cwnd > pcb->cwnd) {
pcb->cwnd = new_cwnd; pcb->cwnd = new_cwnd;
} }
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %"U16_F"\n", pcb->cwnd)); LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %"TCPWNDSIZE_F"\n", pcb->cwnd));
} }
} }
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %"U32_F", unacked->seqno %"U32_F":%"U32_F"\n", LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %"U32_F", unacked->seqno %"U32_F":%"U32_F"\n",
@ -1035,7 +1036,7 @@ tcp_receive(struct tcp_pcb *pcb)
next = pcb->unacked; next = pcb->unacked;
pcb->unacked = pcb->unacked->next; pcb->unacked = pcb->unacked->next;
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen)); LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"TCPWNDSIZE_F" ... ", (tcpwnd_size_t)pcb->snd_queuelen));
LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p)));
/* Prevent ACK for FIN to generate a sent event */ /* Prevent ACK for FIN to generate a sent event */
if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) { if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) {
@ -1045,7 +1046,7 @@ tcp_receive(struct tcp_pcb *pcb)
pcb->snd_queuelen -= pbuf_clen(next->p); pcb->snd_queuelen -= pbuf_clen(next->p);
tcp_seg_free(next); tcp_seg_free(next);
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unacked)\n", (u16_t)pcb->snd_queuelen)); LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"TCPWNDSIZE_F" (after freeing unacked)\n", (tcpwnd_size_t)pcb->snd_queuelen));
if (pcb->snd_queuelen != 0) { if (pcb->snd_queuelen != 0) {
LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL || LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL ||
pcb->unsent != NULL); pcb->unsent != NULL);
@ -1054,10 +1055,11 @@ tcp_receive(struct tcp_pcb *pcb)
/* If there's nothing left to acknowledge, stop the retransmit /* If there's nothing left to acknowledge, stop the retransmit
timer, otherwise reset it to start again */ timer, otherwise reset it to start again */
if(pcb->unacked == NULL) if (pcb->unacked == NULL) {
pcb->rtime = -1; pcb->rtime = -1;
else } else {
pcb->rtime = 0; pcb->rtime = 0;
}
pcb->polltmr = 0; pcb->polltmr = 0;
@ -1092,7 +1094,7 @@ tcp_receive(struct tcp_pcb *pcb)
pcb->unsent_oversize = 0; pcb->unsent_oversize = 0;
} }
#endif /* TCP_OVERSIZE */ #endif /* TCP_OVERSIZE */
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen)); LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"TCPWNDSIZE_F" ... ", (tcpwnd_size_t)pcb->snd_queuelen));
LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p)));
/* Prevent ACK for FIN to generate a sent event */ /* Prevent ACK for FIN to generate a sent event */
if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) { if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) {
@ -1100,7 +1102,7 @@ tcp_receive(struct tcp_pcb *pcb)
} }
pcb->snd_queuelen -= pbuf_clen(next->p); pcb->snd_queuelen -= pbuf_clen(next->p);
tcp_seg_free(next); tcp_seg_free(next);
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unsent)\n", (u16_t)pcb->snd_queuelen)); LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"TCPWNDSIZE_F" (after freeing unsent)\n", (tcpwnd_size_t)pcb->snd_queuelen));
if (pcb->snd_queuelen != 0) { if (pcb->snd_queuelen != 0) {
LWIP_ASSERT("tcp_receive: valid queue length", LWIP_ASSERT("tcp_receive: valid queue length",
pcb->unacked != NULL || pcb->unsent != NULL); pcb->unacked != NULL || pcb->unsent != NULL);
@ -1584,7 +1586,7 @@ tcp_parseopt(struct tcp_pcb *pcb)
opts = (u8_t *)tcphdr + TCP_HLEN; opts = (u8_t *)tcphdr + TCP_HLEN;
/* Parse the TCP MSS option, if present. */ /* Parse the TCP MSS option, if present. */
if(TCPH_HDRLEN(tcphdr) > 0x5) { if (TCPH_HDRLEN(tcphdr) > 0x5) {
max_c = (TCPH_HDRLEN(tcphdr) - 5) << 2; max_c = (TCPH_HDRLEN(tcphdr) - 5) << 2;
for (c = 0; c < max_c; ) { for (c = 0; c < max_c; ) {
opt = opts[c]; opt = opts[c];
@ -1612,6 +1614,29 @@ tcp_parseopt(struct tcp_pcb *pcb)
/* Advance to next option */ /* Advance to next option */
c += 0x04; c += 0x04;
break; break;
#if LWIP_WND_SCALE
case 0x03:
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: WND_SCALE\n"));
if (opts[c + 1] != 0x03 || c + 0x03 > max_c) {
/* Bad length */
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
return;
}
/* If syn was received with wnd scale option,
activate wnd scale opt */
if (flags & TCP_SYN) {
/* An WND_SCALE option with the right option length. */
pcb->snd_scale = opts[c + 2];
if (pcb->snd_scale > 14U) {
pcb->snd_scale = 14U;
}
pcb->rcv_scale = TCP_RCV_SCALE;
pcb->flags |= TF_WND_SCALE;
}
/* Advance to next option */
c += 0x03;
break;
#endif
#if LWIP_TCP_TIMESTAMPS #if LWIP_TCP_TIMESTAMPS
case 0x08: case 0x08:
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: TS\n")); LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: TS\n"));

File diff suppressed because it is too large Load Diff

View File

@ -1,247 +1,247 @@
/* /*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science. * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met: * are permitted provided that the following conditions are met:
* *
* 1. Redistributions of source code must retain the above copyright notice, * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, * 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission. * derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE. * OF SUCH DAMAGE.
* *
* This file is part of the lwIP TCP/IP stack. * This file is part of the lwIP TCP/IP stack.
* *
* Author: Adam Dunkels <adam@sics.se> * Author: Adam Dunkels <adam@sics.se>
* *
*/ */
#ifndef __LWIP_IP4_ADDR_H__ #ifndef __LWIP_IP4_ADDR_H__
#define __LWIP_IP4_ADDR_H__ #define __LWIP_IP4_ADDR_H__
#include "lwip/opt.h" #include "lwip/opt.h"
#include "lwip/def.h" #include "lwip/def.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* This is the aligned version of ip_addr_t, /* This is the aligned version of ip_addr_t,
used as local variable, on the stack, etc. */ used as local variable, on the stack, etc. */
struct ip_addr { struct ip_addr {
u32_t addr; u32_t addr;
}; };
/* This is the packed version of ip_addr_t, /* This is the packed version of ip_addr_t,
used in network headers that are itself packed */ used in network headers that are itself packed */
#ifdef PACK_STRUCT_USE_INCLUDES #ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h" # include "arch/bpstruct.h"
#endif #endif
PACK_STRUCT_BEGIN PACK_STRUCT_BEGIN
struct ip_addr_packed { struct ip_addr_packed {
PACK_STRUCT_FIELD(u32_t addr); PACK_STRUCT_FIELD(u32_t addr);
} PACK_STRUCT_STRUCT; } PACK_STRUCT_STRUCT;
PACK_STRUCT_END PACK_STRUCT_END
#ifdef PACK_STRUCT_USE_INCLUDES #ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/epstruct.h" # include "arch/epstruct.h"
#endif #endif
/** ip_addr_t uses a struct for convenience only, so that the same defines can /** ip_addr_t uses a struct for convenience only, so that the same defines can
* operate both on ip_addr_t as well as on ip_addr_p_t. */ * operate both on ip_addr_t as well as on ip_addr_p_t. */
typedef struct ip_addr ip_addr_t; typedef struct ip_addr ip_addr_t;
typedef struct ip_addr_packed ip_addr_p_t; typedef struct ip_addr_packed ip_addr_p_t;
/* /*
* struct ipaddr2 is used in the definition of the ARP packet format in * struct ipaddr2 is used in the definition of the ARP packet format in
* order to support compilers that don't have structure packing. * order to support compilers that don't have structure packing.
*/ */
#ifdef PACK_STRUCT_USE_INCLUDES #ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h" # include "arch/bpstruct.h"
#endif #endif
PACK_STRUCT_BEGIN PACK_STRUCT_BEGIN
struct ip_addr2 { struct ip_addr2 {
PACK_STRUCT_FIELD(u16_t addrw[2]); PACK_STRUCT_FIELD(u16_t addrw[2]);
} PACK_STRUCT_STRUCT; } PACK_STRUCT_STRUCT;
PACK_STRUCT_END PACK_STRUCT_END
#ifdef PACK_STRUCT_USE_INCLUDES #ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/epstruct.h" # include "arch/epstruct.h"
#endif #endif
/* Forward declaration to not include netif.h */ /* Forward declaration to not include netif.h */
struct netif; struct netif;
extern const ip_addr_t ip_addr_any; extern const ip_addr_t ip_addr_any;
extern const ip_addr_t ip_addr_broadcast; extern const ip_addr_t ip_addr_broadcast;
/** IP_ADDR_ can be used as a fixed IP address /** IP_ADDR_ can be used as a fixed IP address
* for the wildcard and the broadcast address * for the wildcard and the broadcast address
*/ */
#define IP_ADDR_ANY ((ip_addr_t *)&ip_addr_any) #define IP_ADDR_ANY ((ip_addr_t *)&ip_addr_any)
#define IP_ADDR_BROADCAST ((ip_addr_t *)&ip_addr_broadcast) #define IP_ADDR_BROADCAST ((ip_addr_t *)&ip_addr_broadcast)
/** 255.255.255.255 */ /** 255.255.255.255 */
#define IPADDR_NONE ((u32_t)0xffffffffUL) #define IPADDR_NONE ((u32_t)0xffffffffUL)
/** 127.0.0.1 */ /** 127.0.0.1 */
#define IPADDR_LOOPBACK ((u32_t)0x7f000001UL) #define IPADDR_LOOPBACK ((u32_t)0x7f000001UL)
/** 0.0.0.0 */ /** 0.0.0.0 */
#define IPADDR_ANY ((u32_t)0x00000000UL) #define IPADDR_ANY ((u32_t)0x00000000UL)
/** 255.255.255.255 */ /** 255.255.255.255 */
#define IPADDR_BROADCAST ((u32_t)0xffffffffUL) #define IPADDR_BROADCAST ((u32_t)0xffffffffUL)
/* Definitions of the bits in an Internet address integer. /* Definitions of the bits in an Internet address integer.
On subnets, host and network parts are found according to On subnets, host and network parts are found according to
the subnet mask, not these masks. */ the subnet mask, not these masks. */
#define IP_CLASSA(a) ((((u32_t)(a)) & 0x80000000UL) == 0) #define IP_CLASSA(a) ((((u32_t)(a)) & 0x80000000UL) == 0)
#define IP_CLASSA_NET 0xff000000 #define IP_CLASSA_NET 0xff000000
#define IP_CLASSA_NSHIFT 24 #define IP_CLASSA_NSHIFT 24
#define IP_CLASSA_HOST (0xffffffff & ~IP_CLASSA_NET) #define IP_CLASSA_HOST (0xffffffff & ~IP_CLASSA_NET)
#define IP_CLASSA_MAX 128 #define IP_CLASSA_MAX 128
#define IP_CLASSB(a) ((((u32_t)(a)) & 0xc0000000UL) == 0x80000000UL) #define IP_CLASSB(a) ((((u32_t)(a)) & 0xc0000000UL) == 0x80000000UL)
#define IP_CLASSB_NET 0xffff0000 #define IP_CLASSB_NET 0xffff0000
#define IP_CLASSB_NSHIFT 16 #define IP_CLASSB_NSHIFT 16
#define IP_CLASSB_HOST (0xffffffff & ~IP_CLASSB_NET) #define IP_CLASSB_HOST (0xffffffff & ~IP_CLASSB_NET)
#define IP_CLASSB_MAX 65536 #define IP_CLASSB_MAX 65536
#define IP_CLASSC(a) ((((u32_t)(a)) & 0xe0000000UL) == 0xc0000000UL) #define IP_CLASSC(a) ((((u32_t)(a)) & 0xe0000000UL) == 0xc0000000UL)
#define IP_CLASSC_NET 0xffffff00 #define IP_CLASSC_NET 0xffffff00
#define IP_CLASSC_NSHIFT 8 #define IP_CLASSC_NSHIFT 8
#define IP_CLASSC_HOST (0xffffffff & ~IP_CLASSC_NET) #define IP_CLASSC_HOST (0xffffffff & ~IP_CLASSC_NET)
#define IP_CLASSD(a) (((u32_t)(a) & 0xf0000000UL) == 0xe0000000UL) #define IP_CLASSD(a) (((u32_t)(a) & 0xf0000000UL) == 0xe0000000UL)
#define IP_CLASSD_NET 0xf0000000 /* These ones aren't really */ #define IP_CLASSD_NET 0xf0000000 /* These ones aren't really */
#define IP_CLASSD_NSHIFT 28 /* net and host fields, but */ #define IP_CLASSD_NSHIFT 28 /* net and host fields, but */
#define IP_CLASSD_HOST 0x0fffffff /* routing needn't know. */ #define IP_CLASSD_HOST 0x0fffffff /* routing needn't know. */
#define IP_MULTICAST(a) IP_CLASSD(a) #define IP_MULTICAST(a) IP_CLASSD(a)
#define IP_EXPERIMENTAL(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL) #define IP_EXPERIMENTAL(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL)
#define IP_BADCLASS(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL) #define IP_BADCLASS(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL)
#define IP_LOOPBACKNET 127 /* official! */ #define IP_LOOPBACKNET 127 /* official! */
#if BYTE_ORDER == BIG_ENDIAN #if BYTE_ORDER == BIG_ENDIAN
/** Set an IP address given by the four byte-parts */ /** Set an IP address given by the four byte-parts */
#define IP4_ADDR(ipaddr, a,b,c,d) \ #define IP4_ADDR(ipaddr, a,b,c,d) \
(ipaddr)->addr = ((u32_t)((a) & 0xff) << 24) | \ (ipaddr)->addr = ((u32_t)((a) & 0xff) << 24) | \
((u32_t)((b) & 0xff) << 16) | \ ((u32_t)((b) & 0xff) << 16) | \
((u32_t)((c) & 0xff) << 8) | \ ((u32_t)((c) & 0xff) << 8) | \
(u32_t)((d) & 0xff) (u32_t)((d) & 0xff)
#else #else
/** Set an IP address given by the four byte-parts. /** Set an IP address given by the four byte-parts.
Little-endian version that prevents the use of htonl. */ Little-endian version that prevents the use of htonl. */
#define IP4_ADDR(ipaddr, a,b,c,d) \ #define IP4_ADDR(ipaddr, a,b,c,d) \
(ipaddr)->addr = ((u32_t)((d) & 0xff) << 24) | \ (ipaddr)->addr = ((u32_t)((d) & 0xff) << 24) | \
((u32_t)((c) & 0xff) << 16) | \ ((u32_t)((c) & 0xff) << 16) | \
((u32_t)((b) & 0xff) << 8) | \ ((u32_t)((b) & 0xff) << 8) | \
(u32_t)((a) & 0xff) (u32_t)((a) & 0xff)
#endif #endif
/** MEMCPY-like copying of IP addresses where addresses are known to be /** MEMCPY-like copying of IP addresses where addresses are known to be
* 16-bit-aligned if the port is correctly configured (so a port could define * 16-bit-aligned if the port is correctly configured (so a port could define
* this to copying 2 u16_t's) - no NULL-pointer-checking needed. */ * this to copying 2 u16_t's) - no NULL-pointer-checking needed. */
#ifndef IPADDR2_COPY #ifndef IPADDR2_COPY
#define IPADDR2_COPY(dest, src) SMEMCPY(dest, src, sizeof(ip_addr_t)) #define IPADDR2_COPY(dest, src) SMEMCPY(dest, src, sizeof(ip_addr_t))
#endif #endif
/** Copy IP address - faster than ip_addr_set: no NULL check */ /** Copy IP address - faster than ip_addr_set: no NULL check */
#define ip_addr_copy(dest, src) ((dest).addr = (src).addr) #define ip_addr_copy(dest, src) ((dest).addr = (src).addr)
/** Safely copy one IP address to another (src may be NULL) */ /** Safely copy one IP address to another (src may be NULL) */
#define ip_addr_set(dest, src) ((dest)->addr = \ #define ip_addr_set(dest, src) ((dest)->addr = \
((src) == NULL ? 0 : \ ((src) == NULL ? 0 : \
(src)->addr)) (src)->addr))
/** Set complete address to zero */ /** Set complete address to zero */
#define ip_addr_set_zero(ipaddr) ((ipaddr)->addr = 0) #define ip_addr_set_zero(ipaddr) ((ipaddr)->addr = 0)
/** Set address to IPADDR_ANY (no need for htonl()) */ /** Set address to IPADDR_ANY (no need for htonl()) */
#define ip_addr_set_any(ipaddr) ((ipaddr)->addr = IPADDR_ANY) #define ip_addr_set_any(ipaddr) ((ipaddr)->addr = IPADDR_ANY)
/** Set address to loopback address */ /** Set address to loopback address */
#define ip_addr_set_loopback(ipaddr) ((ipaddr)->addr = PP_HTONL(IPADDR_LOOPBACK)) #define ip_addr_set_loopback(ipaddr) ((ipaddr)->addr = PP_HTONL(IPADDR_LOOPBACK))
/** Safely copy one IP address to another and change byte order /** Safely copy one IP address to another and change byte order
* from host- to network-order. */ * from host- to network-order. */
#define ip_addr_set_hton(dest, src) ((dest)->addr = \ #define ip_addr_set_hton(dest, src) ((dest)->addr = \
((src) == NULL ? 0:\ ((src) == NULL ? 0:\
htonl((src)->addr))) htonl((src)->addr)))
/** IPv4 only: set the IP address given as an u32_t */ /** IPv4 only: set the IP address given as an u32_t */
#define ip4_addr_set_u32(dest_ipaddr, src_u32) ((dest_ipaddr)->addr = (src_u32)) #define ip4_addr_set_u32(dest_ipaddr, src_u32) ((dest_ipaddr)->addr = (src_u32))
/** IPv4 only: get the IP address as an u32_t */ /** IPv4 only: get the IP address as an u32_t */
#define ip4_addr_get_u32(src_ipaddr) ((src_ipaddr)->addr) #define ip4_addr_get_u32(src_ipaddr) ((src_ipaddr)->addr)
/** Get the network address by combining host address with netmask */ /** Get the network address by combining host address with netmask */
#define ip_addr_get_network(target, host, netmask) ((target)->addr = ((host)->addr) & ((netmask)->addr)) #define ip_addr_get_network(target, host, netmask) ((target)->addr = ((host)->addr) & ((netmask)->addr))
/** /**
* Determine if two address are on the same network. * Determine if two address are on the same network.
* *
* @arg addr1 IP address 1 * @arg addr1 IP address 1
* @arg addr2 IP address 2 * @arg addr2 IP address 2
* @arg mask network identifier mask * @arg mask network identifier mask
* @return !0 if the network identifiers of both address match * @return !0 if the network identifiers of both address match
*/ */
#define ip_addr_netcmp(addr1, addr2, mask) (((addr1)->addr & \ #define ip_addr_netcmp(addr1, addr2, mask) (((addr1)->addr & \
(mask)->addr) == \ (mask)->addr) == \
((addr2)->addr & \ ((addr2)->addr & \
(mask)->addr)) (mask)->addr))
#define ip_addr_cmp(addr1, addr2) ((addr1)->addr == (addr2)->addr) #define ip_addr_cmp(addr1, addr2) ((addr1)->addr == (addr2)->addr)
#define ip_addr_isany(addr1) ((addr1) == NULL || (addr1)->addr == IPADDR_ANY) #define ip_addr_isany(addr1) ((addr1) == NULL || (addr1)->addr == IPADDR_ANY)
#define ip_addr_isbroadcast(ipaddr, netif) ip4_addr_isbroadcast((ipaddr)->addr, (netif)) #define ip_addr_isbroadcast(ipaddr, netif) ip4_addr_isbroadcast((ipaddr)->addr, (netif))
u8_t ip4_addr_isbroadcast(u32_t addr, const struct netif *netif); u8_t ip4_addr_isbroadcast(u32_t addr, const struct netif *netif);
#define ip_addr_netmask_valid(netmask) ip4_addr_netmask_valid((netmask)->addr) #define ip_addr_netmask_valid(netmask) ip4_addr_netmask_valid((netmask)->addr)
u8_t ip4_addr_netmask_valid(u32_t netmask); u8_t ip4_addr_netmask_valid(u32_t netmask);
#define ip_addr_ismulticast(addr1) (((addr1)->addr & PP_HTONL(0xf0000000UL)) == PP_HTONL(0xe0000000UL)) #define ip_addr_ismulticast(addr1) (((addr1)->addr & PP_HTONL(0xf0000000UL)) == PP_HTONL(0xe0000000UL))
#define ip_addr_islinklocal(addr1) (((addr1)->addr & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xa9fe0000UL)) #define ip_addr_islinklocal(addr1) (((addr1)->addr & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xa9fe0000UL))
#define ip_addr_debug_print(debug, ipaddr) \ #define ip_addr_debug_print(debug, ipaddr) \
LWIP_DEBUGF(debug, ("%" U16_F ".%" U16_F ".%" U16_F ".%" U16_F, \ LWIP_DEBUGF(debug, ("%" U16_F ".%" U16_F ".%" U16_F ".%" U16_F, \
ipaddr != NULL ? ip4_addr1_16(ipaddr) : 0, \ ipaddr != NULL ? ip4_addr1_16(ipaddr) : 0, \
ipaddr != NULL ? ip4_addr2_16(ipaddr) : 0, \ ipaddr != NULL ? ip4_addr2_16(ipaddr) : 0, \
ipaddr != NULL ? ip4_addr3_16(ipaddr) : 0, \ ipaddr != NULL ? ip4_addr3_16(ipaddr) : 0, \
ipaddr != NULL ? ip4_addr4_16(ipaddr) : 0)) ipaddr != NULL ? ip4_addr4_16(ipaddr) : 0))
/* Get one byte from the 4-byte address */ /* Get one byte from the 4-byte address */
#define ip4_addr1(ipaddr) (((u8_t*)(ipaddr))[0]) #define ip4_addr1(ipaddr) (((u8_t*)(ipaddr))[0])
#define ip4_addr2(ipaddr) (((u8_t*)(ipaddr))[1]) #define ip4_addr2(ipaddr) (((u8_t*)(ipaddr))[1])
#define ip4_addr3(ipaddr) (((u8_t*)(ipaddr))[2]) #define ip4_addr3(ipaddr) (((u8_t*)(ipaddr))[2])
#define ip4_addr4(ipaddr) (((u8_t*)(ipaddr))[3]) #define ip4_addr4(ipaddr) (((u8_t*)(ipaddr))[3])
/* These are cast to u16_t, with the intent that they are often arguments /* These are cast to u16_t, with the intent that they are often arguments
* to printf using the U16_F format from cc.h. */ * to printf using the U16_F format from cc.h. */
#define ip4_addr1_16(ipaddr) ((u16_t)ip4_addr1(ipaddr)) #define ip4_addr1_16(ipaddr) ((u16_t)ip4_addr1(ipaddr))
#define ip4_addr2_16(ipaddr) ((u16_t)ip4_addr2(ipaddr)) #define ip4_addr2_16(ipaddr) ((u16_t)ip4_addr2(ipaddr))
#define ip4_addr3_16(ipaddr) ((u16_t)ip4_addr3(ipaddr)) #define ip4_addr3_16(ipaddr) ((u16_t)ip4_addr3(ipaddr))
#define ip4_addr4_16(ipaddr) ((u16_t)ip4_addr4(ipaddr)) #define ip4_addr4_16(ipaddr) ((u16_t)ip4_addr4(ipaddr))
#define IP4ADDR_STRLEN_MAX 16 #define IP4ADDR_STRLEN_MAX 16
#define IPADDR_STRLEN_MAX IP4ADDR_STRLEN_MAX #define IPADDR_STRLEN_MAX IP4ADDR_STRLEN_MAX
/** For backwards compatibility */ /** For backwards compatibility */
#define ip_ntoa(ipaddr) ipaddr_ntoa(ipaddr) #define ip_ntoa(ipaddr) ipaddr_ntoa(ipaddr)
u32_t ipaddr_addr(const char *cp); u32_t ipaddr_addr(const char *cp);
int ipaddr_aton(const char *cp, ip_addr_t *addr); int ipaddr_aton(const char *cp, ip_addr_t *addr);
/** returns ptr to static buffer; not reentrant! */ /** returns ptr to static buffer; not reentrant! */
char *ipaddr_ntoa(const ip_addr_t *addr); char *ipaddr_ntoa(const ip_addr_t *addr);
char *ipaddr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen); char *ipaddr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* __LWIP_IP_ADDR_H__ */ #endif /* __LWIP_IP_ADDR_H__ */

View File

@ -1080,6 +1080,19 @@
#define LWIP_CALLBACK_API 1 #define LWIP_CALLBACK_API 1
#endif #endif
/**
* LWIP_WND_SCALE and TCP_RCV_SCALE:
* Set LWIP_WND_SCALE to 1 to enable window scaling.
* Set TCP_RCV_SCALE to the desired scaling factor (shift count in the
* range of [0..14]).
* When LWIP_WND_SCALE is enabled but TCP_RCV_SCALE is 0, we can use a large
* send window while having a small receive window only.
*/
#ifndef LWIP_WND_SCALE
#define LWIP_WND_SCALE 0
#define TCP_RCV_SCALE 0
#endif
/* /*
---------------------------------- ----------------------------------

View File

@ -125,6 +125,18 @@ typedef void (*tcp_err_fn)(void *arg, err_t err);
*/ */
typedef err_t (*tcp_connected_fn)(void *arg, struct tcp_pcb *tpcb, err_t err); typedef err_t (*tcp_connected_fn)(void *arg, struct tcp_pcb *tpcb, err_t err);
#if LWIP_WND_SCALE
#define RCV_WND_SCALE(pcb, wnd) (((wnd) >> (pcb)->rcv_scale))
#define SND_WND_SCALE(pcb, wnd) (((wnd) << (pcb)->snd_scale))
typedef u32_t tcpwnd_size_t;
typedef u16_t tcpflags_t;
#else
#define RCV_WND_SCALE(pcb, wnd) (wnd)
#define SND_WND_SCALE(pcb, wnd) (wnd)
typedef u16_t tcpwnd_size_t;
typedef u8_t tcpflags_t;
#endif
enum tcp_state { enum tcp_state {
CLOSED = 0, CLOSED = 0,
LISTEN = 1, LISTEN = 1,
@ -176,15 +188,18 @@ struct tcp_pcb {
/* ports are in host byte order */ /* ports are in host byte order */
u16_t remote_port; u16_t remote_port;
u8_t flags; tcpflags_t flags;
#define TF_ACK_DELAY ((u8_t)0x01U) /* Delayed ACK. */ #define TF_ACK_DELAY ((tcpflags_t)0x0001U) /* Delayed ACK. */
#define TF_ACK_NOW ((u8_t)0x02U) /* Immediate ACK. */ #define TF_ACK_NOW ((tcpflags_t)0x0002U) /* Immediate ACK. */
#define TF_INFR ((u8_t)0x04U) /* In fast recovery. */ #define TF_INFR ((tcpflags_t)0x0004U) /* In fast recovery. */
#define TF_TIMESTAMP ((u8_t)0x08U) /* Timestamp option enabled */ #define TF_TIMESTAMP ((tcpflags_t)0x0008U) /* Timestamp option enabled */
#define TF_RXCLOSED ((u8_t)0x10U) /* rx closed by tcp_shutdown */ #define TF_RXCLOSED ((tcpflags_t)0x0010U) /* rx closed by tcp_shutdown */
#define TF_FIN ((u8_t)0x20U) /* Connection was closed locally (FIN segment enqueued). */ #define TF_FIN ((tcpflags_t)0x0020U) /* Connection was closed locally (FIN segment enqueued). */
#define TF_NODELAY ((u8_t)0x40U) /* Disable Nagle algorithm */ #define TF_NODELAY ((tcpflags_t)0x0040U) /* Disable Nagle algorithm */
#define TF_NAGLEMEMERR ((u8_t)0x80U) /* nagle enabled, memerr, try to output to prevent delayed ACK to happen */ #define TF_NAGLEMEMERR ((tcpflags_t)0x0080U) /* nagle enabled, memerr, try to output to prevent delayed ACK to happen */
#if LWIP_WND_SCALE
#define TF_WND_SCALE ((tcpflags_t)0x0100U) /* Window Scale option enabled */
#endif
/* the rest of the fields are in host byte order /* the rest of the fields are in host byte order
as we have to do some math with them */ as we have to do some math with them */
@ -196,8 +211,8 @@ struct tcp_pcb {
/* receiver variables */ /* receiver variables */
u32_t rcv_nxt; /* next seqno expected */ u32_t rcv_nxt; /* next seqno expected */
u16_t rcv_wnd; /* receiver window available */ tcpwnd_size_t rcv_wnd; /* receiver window available */
u16_t rcv_ann_wnd; /* receiver window to announce */ tcpwnd_size_t rcv_ann_wnd; /* receiver window to announce */
u32_t rcv_ann_right_edge; /* announced right edge of window */ u32_t rcv_ann_right_edge; /* announced right edge of window */
/* Retransmission timer. */ /* Retransmission timer. */
@ -218,27 +233,27 @@ struct tcp_pcb {
u32_t lastack; /* Highest acknowledged seqno. */ u32_t lastack; /* Highest acknowledged seqno. */
/* congestion avoidance/control variables */ /* congestion avoidance/control variables */
u16_t cwnd; tcpwnd_size_t cwnd;
u16_t ssthresh; tcpwnd_size_t ssthresh;
/* sender variables */ /* sender variables */
u32_t snd_nxt; /* next new seqno to be sent */ u32_t snd_nxt; /* next new seqno to be sent */
u32_t snd_wl1, snd_wl2; /* Sequence and acknowledgement numbers of last u32_t snd_wl1, snd_wl2; /* Sequence and acknowledgement numbers of last
window update. */ window update. */
u32_t snd_lbb; /* Sequence number of next byte to be buffered. */ u32_t snd_lbb; /* Sequence number of next byte to be buffered. */
u16_t snd_wnd; /* sender window */ tcpwnd_size_t snd_wnd; /* sender window */
u16_t snd_wnd_max; /* the maximum sender window announced by the remote host */ tcpwnd_size_t snd_wnd_max; /* the maximum sender window announced by the remote host */
u16_t acked; u16_t acked;
u16_t snd_buf; /* Available buffer space for sending (in bytes). */ tcpwnd_size_t snd_buf; /* Available buffer space for sending (in bytes). */
#define TCP_SNDQUEUELEN_OVERFLOW (0xffffU-3) #define TCP_SNDQUEUELEN_OVERFLOW (0xffffU-3)
u16_t snd_queuelen; /* Available buffer space for sending (in pbufs). */ u16_t snd_queuelen; /* Available buffer space for sending (in pbufs). */
#if TCP_OVERSIZE #if TCP_OVERSIZE
/* Extra bytes available at the end of the last pbuf in unsent. */ /* Extra bytes available at the end of the last pbuf in unsent. */
u16_t unsent_oversize; u16_t unsent_oversize;
#endif /* TCP_OVERSIZE */ #endif /* TCP_OVERSIZE */
/* These are ordered by sequence number: */ /* These are ordered by sequence number: */
struct tcp_seg *unsent; /* Unsent (queued) segments. */ struct tcp_seg *unsent; /* Unsent (queued) segments. */
@ -281,6 +296,11 @@ struct tcp_pcb {
/* KEEPALIVE counter */ /* KEEPALIVE counter */
u8_t keep_cnt_sent; u8_t keep_cnt_sent;
#if LWIP_WND_SCALE
u8_t snd_scale;
u8_t rcv_scale;
#endif
}; };
struct tcp_pcb_listen { struct tcp_pcb_listen {

File diff suppressed because it is too large Load Diff