net/tcp: fallback to unthrottle pool to avoid deadlock

Add a fallback mechanism to ensure that there are still available
iobs for an free connection, Guarantees all connections will have
a minimum threshold iob to keep the connection not be hanged.

Change-Id: I59bed98d135ccd1f16264b9ccacdd1b0d91261de
Signed-off-by: chao.an <anchao@xiaomi.com>
This commit is contained in:
chao.an
2020-11-27 09:50:38 +08:00
committed by Xiang Xiao
parent 4b6d117a93
commit bf21056001
5 changed files with 40 additions and 17 deletions
+1 -1
View File
@@ -256,7 +256,7 @@ static int sixlowpan_tcp_header(FAR struct tcp_conn_s *conn,
{
/* Update the TCP received window based on I/O buffer availability */
uint16_t recvwndo = tcp_get_recvwindow(dev);
uint16_t recvwndo = tcp_get_recvwindow(dev, conn);
/* Set the TCP Window */
+4 -2
View File
@@ -1430,14 +1430,16 @@ int tcp_getsockopt(FAR struct socket *psock, int option,
* Calculate the TCP receive window for the specified device.
*
* Input Parameters:
* dev - The device whose TCP receive window will be updated.
* dev - The device whose TCP receive window will be updated.
* conn - The TCP connection structure holding connection information.
*
* Returned Value:
* The value of the TCP receive window to use.
*
****************************************************************************/
uint16_t tcp_get_recvwindow(FAR struct net_driver_s *dev);
uint16_t tcp_get_recvwindow(FAR struct net_driver_s *dev,
FAR struct tcp_conn_s *conn);
/****************************************************************************
* Name: psock_tcp_cansend
+17 -4
View File
@@ -241,6 +241,7 @@ uint16_t tcp_datahandler(FAR struct tcp_conn_s *conn, FAR uint8_t *buffer,
uint16_t buflen)
{
FAR struct iob_s *iob;
bool throttled = true;
int ret;
/* Try to allocate on I/O buffer to start the chain without waiting (and
@@ -248,16 +249,28 @@ uint16_t tcp_datahandler(FAR struct tcp_conn_s *conn, FAR uint8_t *buffer,
* packet.
*/
iob = iob_tryalloc(true, IOBUSER_NET_TCP_READAHEAD);
iob = iob_tryalloc(throttled, IOBUSER_NET_TCP_READAHEAD);
if (iob == NULL)
{
nerr("ERROR: Failed to create new I/O buffer chain\n");
return 0;
#if CONFIG_IOB_THROTTLE > 0
if (IOB_QEMPTY(&conn->readahead))
{
/* Fallback out of the throttled entry */
throttled = false;
iob = iob_tryalloc(throttled, IOBUSER_NET_TCP_READAHEAD);
}
#endif
if (iob == NULL)
{
nerr("ERROR: Failed to create new I/O buffer chain\n");
return 0;
}
}
/* Copy the new appdata into the I/O buffer chain (without waiting) */
ret = iob_trycopyin(iob, buffer, buflen, 0, true,
ret = iob_trycopyin(iob, buffer, buflen, 0, throttled,
IOBUSER_NET_TCP_READAHEAD);
if (ret < 0)
{
+17 -9
View File
@@ -70,7 +70,8 @@
*
****************************************************************************/
uint16_t tcp_get_recvwindow(FAR struct net_driver_s *dev)
uint16_t tcp_get_recvwindow(FAR struct net_driver_s *dev,
FAR struct tcp_conn_s *conn)
{
uint16_t iplen;
uint16_t mss;
@@ -139,9 +140,9 @@ uint16_t tcp_get_recvwindow(FAR struct net_driver_s *dev)
uint32_t rwnd;
/* The optimal TCP window size is the amount of TCP data that we can
* currently buffer via TCP read-ahead buffering plus MSS for the
* device packet buffer. This logic here assumes that all IOBs are
* available for TCP buffering.
* currently buffer via TCP read-ahead buffering for the device packet
* buffer. This logic here assumes that all IOBs are available for
* TCP buffering.
*
* Assume that all of the available IOBs are can be used for buffering
* on this connection. Also assume that at least one chain is available
@@ -154,7 +155,7 @@ uint16_t tcp_get_recvwindow(FAR struct net_driver_s *dev)
* buffering for this connection.
*/
rwnd = (niob_avail * CONFIG_IOB_BUFSIZE) + mss;
rwnd = (niob_avail * CONFIG_IOB_BUFSIZE);
if (rwnd > UINT16_MAX)
{
rwnd = UINT16_MAX;
@@ -164,17 +165,24 @@ uint16_t tcp_get_recvwindow(FAR struct net_driver_s *dev)
recvwndo = (uint16_t)rwnd;
}
else if (IOB_QEMPTY(&conn->readahead))
{
/* Advertise maximum segment size for window edge if here is no
* available iobs on current "free" connection.
*/
recvwndo = mss;
}
else /* nqentry_avail == 0 || niob_avail == 0 */
{
/* No IOB chains or noIOBs are available. The only buffering
* available is within the packet buffer itself. We can buffer no
* more than the MSS (unless we are very fast).
/* No IOB chains or noIOBs are available.
* Advertise the edge of window to zero.
*
* NOTE: If no IOBs are available, then the next packet will be
* lost if there is no listener on the connection.
*/
recvwndo = mss;
recvwndo = 0;
}
return recvwndo;
+1 -1
View File
@@ -360,7 +360,7 @@ static void tcp_sendcommon(FAR struct net_driver_s *dev,
{
/* Update the TCP received window based on I/O buffer availability */
uint16_t recvwndo = tcp_get_recvwindow(dev);
uint16_t recvwndo = tcp_get_recvwindow(dev, conn);
/* Set the TCP Window */