TCP: Change how initial MSS is handled. From Max Holtzberg
This commit is contained in:
parent
69dac5c775
commit
cbed482747
@ -5782,4 +5782,7 @@
|
||||
checking for timeout. From Max Holtzberg (2013-10-17).
|
||||
* net/net_sendfile.c: Correct paramter passed to netdev_txnotify()
|
||||
from Max Holtzberg (2013-10-17).
|
||||
* include/nuttx/net/uip/uip-tcp.h, net/send.c, uip/uip_tcpconn.c, and
|
||||
uip/uip_tcpinput.c: Change how the inital minimum MSS is calculated.
|
||||
Max Holtzberg (2013-10-17).
|
||||
|
||||
|
@ -105,6 +105,24 @@
|
||||
#define UIP_IPTCPH_LEN (UIP_TCPH_LEN + UIP_IPH_LEN) /* Size of IP + TCP header */
|
||||
#define UIP_TCPIP_HLEN UIP_IPTCPH_LEN
|
||||
|
||||
/* Initial minimum MSS according to RFC 879
|
||||
*
|
||||
* There have been some assumptions made about using other than the
|
||||
* default size for datagrams with some unfortunate results.
|
||||
*
|
||||
* HOSTS MUST NOT SEND DATAGRAMS LARGER THAN 576 OCTETS UNLESS THEY
|
||||
* HAVE SPECIFIC KNOWLEDGE THAT THE DESTINATION HOST IS PREPARED TO
|
||||
* ACCEPT LARGER DATAGRAMS.
|
||||
*
|
||||
* This is a long established rule.
|
||||
*/
|
||||
|
||||
#if UIP_TCP_MSS > 576
|
||||
# define UIP_TCP_INITIAL_MSS 576
|
||||
#else
|
||||
# define UIP_TCP_INITIAL_MSS UIP_TCP_MSS
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Type Definitions
|
||||
****************************************************************************/
|
||||
@ -135,8 +153,6 @@ struct uip_conn
|
||||
uint16_t mss; /* Current maximum segment size for the
|
||||
* connection */
|
||||
uint16_t winsize; /* Current window size of the connection */
|
||||
uint16_t initialmss; /* Initial maximum segment size for the
|
||||
* connection */
|
||||
uint8_t crefs; /* Reference counts on this instance */
|
||||
uint8_t sa; /* Retransmission time-out calculation state
|
||||
* variable */
|
||||
@ -444,18 +460,8 @@ extern int uip_backlogdelete(FAR struct uip_conn *conn, FAR struct uip_conn *blc
|
||||
(conn)->tcpstateflags &= ~UIP_STOPPED; \
|
||||
} while(0)
|
||||
|
||||
/* Get the initial maxium segment size (MSS) of the current
|
||||
* connection.
|
||||
*/
|
||||
|
||||
#define uip_initialmss(conn) ((conn)->initialmss)
|
||||
|
||||
/* Get the current maximum segment size that can be sent on the current
|
||||
* connection.
|
||||
*
|
||||
* The current maxiumum segment size that can be sent on the connection is
|
||||
* computed from the receiver's window and the MSS of the connection (which
|
||||
* also is available by calling uip_initialmss()).
|
||||
*/
|
||||
|
||||
#define uip_mss(conn) ((conn)->mss)
|
||||
|
69
net/send.c
69
net/send.c
@ -356,45 +356,52 @@ static uint16_t send_interrupt(FAR struct uip_driver_s *dev, FAR void *pvconn,
|
||||
sndlen = uip_mss(conn);
|
||||
}
|
||||
|
||||
/* Set the sequence number for this packet. NOTE: uIP updates
|
||||
* sndseq on recept of ACK *before* this function is called. In that
|
||||
* case sndseq will point to the next unacknowledge byte (which might
|
||||
* have already been sent). We will overwrite the value of sndseq
|
||||
* here before the packet is sent.
|
||||
*/
|
||||
/* Check if we have "space" in the window */
|
||||
|
||||
seqno = pstate->snd_sent + pstate->snd_isn;
|
||||
nllvdbg("SEND: sndseq %08x->%08x\n", conn->sndseq, seqno);
|
||||
uip_tcpsetsequence(conn->sndseq, seqno);
|
||||
if ((pstate->snd_sent - pstate->snd_acked + sndlen) < conn->winsize)
|
||||
{
|
||||
|
||||
/* Then set-up to send that amount of data. (this won't actually
|
||||
* happen until the polling cycle completes).
|
||||
*/
|
||||
/* Set the sequence number for this packet. NOTE: uIP updates
|
||||
* sndseq on recept of ACK *before* this function is called. In that
|
||||
* case sndseq will point to the next unacknowledge byte (which might
|
||||
* have already been sent). We will overwrite the value of sndseq
|
||||
* here before the packet is sent.
|
||||
*/
|
||||
|
||||
uip_send(dev, &pstate->snd_buffer[pstate->snd_sent], sndlen);
|
||||
seqno = pstate->snd_sent + pstate->snd_isn;
|
||||
nllvdbg("SEND: sndseq %08x->%08x\n", conn->sndseq, seqno);
|
||||
uip_tcpsetsequence(conn->sndseq, seqno);
|
||||
|
||||
/* Check if the destination IP address is in the ARP table. If not,
|
||||
* then the send won't actually make it out... it will be replaced with
|
||||
* an ARP request.
|
||||
*
|
||||
* NOTE 1: This could be an expensive check if there are a lot of entries
|
||||
* in the ARP table. Hence, we only check on the first packet -- when
|
||||
* snd_sent is zero.
|
||||
*
|
||||
* NOTE 2: If we are actually harvesting IP addresses on incomming IP
|
||||
* packets, then this check should not be necessary; the MAC mapping
|
||||
* should already be in the ARP table.
|
||||
*/
|
||||
/* Then set-up to send that amount of data. (this won't actually
|
||||
* happen until the polling cycle completes).
|
||||
*/
|
||||
|
||||
uip_send(dev, &pstate->snd_buffer[pstate->snd_sent], sndlen);
|
||||
|
||||
/* Check if the destination IP address is in the ARP table. If not,
|
||||
* then the send won't actually make it out... it will be replaced with
|
||||
* an ARP request.
|
||||
*
|
||||
* NOTE 1: This could be an expensive check if there are a lot of entries
|
||||
* in the ARP table. Hence, we only check on the first packet -- when
|
||||
* snd_sent is zero.
|
||||
*
|
||||
* NOTE 2: If we are actually harvesting IP addresses on incomming IP
|
||||
* packets, then this check should not be necessary; the MAC mapping
|
||||
* should already be in the ARP table.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_NET_ETHERNET) && !defined(CONFIG_NET_ARP_IPIN)
|
||||
if (pstate->snd_sent != 0 || uip_arp_find(conn->ripaddr) != NULL)
|
||||
if (pstate->snd_sent != 0 || uip_arp_find(conn->ripaddr) != NULL)
|
||||
#endif
|
||||
{
|
||||
/* Update the amount of data sent (but not necessarily ACKed) */
|
||||
{
|
||||
/* Update the amount of data sent (but not necessarily ACKed) */
|
||||
|
||||
pstate->snd_sent += sndlen;
|
||||
nllvdbg("SEND: acked=%d sent=%d buflen=%d\n",
|
||||
pstate->snd_acked, pstate->snd_sent, pstate->snd_buflen);
|
||||
pstate->snd_sent += sndlen;
|
||||
nllvdbg("SEND: acked=%d sent=%d buflen=%d\n",
|
||||
pstate->snd_acked, pstate->snd_sent, pstate->snd_buflen);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -496,6 +496,7 @@ struct uip_conn *uip_tcpaccept(struct uip_tcpip_hdr *buf)
|
||||
conn->nrtx = 0;
|
||||
conn->lport = buf->destport;
|
||||
conn->rport = buf->srcport;
|
||||
conn->mss = UIP_TCP_INITIAL_MSS;
|
||||
uip_ipaddr_copy(conn->ripaddr, uip_ip4addr_conv(buf->srcipaddr));
|
||||
conn->tcpstateflags = UIP_SYN_RCVD;
|
||||
|
||||
@ -632,7 +633,7 @@ int uip_tcpconnect(struct uip_conn *conn, const struct sockaddr_in *addr)
|
||||
conn->tcpstateflags = UIP_SYN_SENT;
|
||||
uip_tcpinitsequence(conn->sndseq);
|
||||
|
||||
conn->initialmss = conn->mss = UIP_TCP_MSS;
|
||||
conn->mss = UIP_TCP_INITIAL_MSS;
|
||||
conn->unacked = 1; /* TCP length of the SYN is one. */
|
||||
conn->nrtx = 0;
|
||||
conn->timer = 1; /* Send the SYN next time around. */
|
||||
|
@ -2,7 +2,7 @@
|
||||
* net/uip/uip_tcpinput.c
|
||||
* Handling incoming TCP input
|
||||
*
|
||||
* Copyright (C) 2007-2012 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007-2013 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Adapted for NuttX from logic in uIP which also has a BSD-like license:
|
||||
@ -244,8 +244,7 @@ void uip_tcpinput(struct uip_driver_s *dev)
|
||||
|
||||
tmp16 = ((uint16_t)dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + i] << 8) |
|
||||
(uint16_t)dev->d_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + 3 + i];
|
||||
conn->initialmss = conn->mss =
|
||||
tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
|
||||
conn->mss = tmp16 > UIP_TCP_MSS ? UIP_TCP_MSS : tmp16;
|
||||
|
||||
/* And we are done processing options. */
|
||||
|
||||
@ -300,7 +299,7 @@ found:
|
||||
|
||||
/* Update the connection's window size */
|
||||
|
||||
conn->winsize = BUF->wnd[0] << 8 | BUF->wnd[1];
|
||||
conn->winsize = ((uint16_t)pbuf->wnd[0] << 8) + (uint16_t)pbuf->wnd[1];
|
||||
|
||||
flags = 0;
|
||||
|
||||
@ -522,9 +521,7 @@ found:
|
||||
tmp16 =
|
||||
(dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + i] << 8) |
|
||||
dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + i];
|
||||
conn->initialmss =
|
||||
conn->mss =
|
||||
tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
|
||||
conn->mss = tmp16 > UIP_TCP_MSS ? UIP_TCP_MSS : tmp16;
|
||||
|
||||
/* And we are done processing options. */
|
||||
|
||||
@ -595,10 +592,17 @@ found:
|
||||
|
||||
if ((pbuf->flags & TCP_FIN) != 0 && (conn->tcpstateflags & UIP_STOPPED) == 0)
|
||||
{
|
||||
/* Needs to be investigated further.
|
||||
* Windows often sends FIN packets together with the last ACK for
|
||||
* the received data. So the socket layer has to get this ACK even
|
||||
* if the connection is going to be closed.
|
||||
*/
|
||||
#if 0
|
||||
if (conn->unacked > 0)
|
||||
{
|
||||
goto drop;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Update the sequence number and indicate that the connection has
|
||||
* been closed.
|
||||
@ -663,26 +667,6 @@ found:
|
||||
flags |= UIP_NEWDATA;
|
||||
}
|
||||
|
||||
/* Check if the available buffer space advertised by the other end
|
||||
* is smaller than the initial MSS for this connection. If so, we
|
||||
* set the current MSS to the window size to ensure that the
|
||||
* application does not send more data than the other end can
|
||||
* handle.
|
||||
*
|
||||
* If the remote host advertises a zero window, we set the MSS to
|
||||
* the initial MSS so that the application will send an entire MSS
|
||||
* of data. This data will not be acknowledged by the receiver,
|
||||
* and the application will retransmit it. This is called the
|
||||
* "persistent timer" and uses the retransmission mechanim.
|
||||
*/
|
||||
|
||||
tmp16 = ((uint16_t)pbuf->wnd[0] << 8) + (uint16_t)pbuf->wnd[1];
|
||||
if (tmp16 > conn->initialmss || tmp16 == 0)
|
||||
{
|
||||
tmp16 = conn->initialmss;
|
||||
}
|
||||
conn->mss = tmp16;
|
||||
|
||||
/* If this packet constitutes an ACK for outstanding data (flagged
|
||||
* by the UIP_ACKDATA flag), we should call the application since it
|
||||
* might want to send more data. If the incoming packet had data
|
||||
|
Loading…
Reference in New Issue
Block a user