tcp_send_buffered: throttle IOB allocations for send

Consider a bi-directional TCP connection:

1. we use all IOBs for tx queue
2. we advertize zero recv window because we have no free IOBs
3. if the peer tcp does the same thing,
   both sides advertize zero window and can not drain the tx queue.

For a similar stall to happen, the peer doesn't need to be
a naive tcp implementation like nuttx. A naive application blocking
on send() without draining its read buffer is enough.
(Probably such an application should be fixed to drain rx even
when tx is full. However, it's another story.)

This commit avoids the situation by prevent tx from grabbing
the all IOBs in the first place. (assuming CONFIG_IOB_THROTTLE > 0)
This commit is contained in:
YAMAMOTO Takashi 2021-07-12 20:05:18 +09:00 committed by archer
parent 136662f5f9
commit 09f3a1ec8e
3 changed files with 4 additions and 4 deletions

View File

@ -68,10 +68,10 @@
# define TCP_WBIOB(wrb) ((wrb)->wb_iob)
# define TCP_WBCOPYOUT(wrb,dest,n) (iob_copyout(dest,(wrb)->wb_iob,(n),0))
# define TCP_WBCOPYIN(wrb,src,n,off) \
(iob_copyin((wrb)->wb_iob,src,(n),(off),false,\
(iob_copyin((wrb)->wb_iob,src,(n),(off),true,\
IOBUSER_NET_TCP_WRITEBUFFER))
# define TCP_WBTRYCOPYIN(wrb,src,n,off) \
(iob_trycopyin((wrb)->wb_iob,src,(n),(off),false,\
(iob_trycopyin((wrb)->wb_iob,src,(n),(off),true,\
IOBUSER_NET_TCP_WRITEBUFFER))
# define TCP_WBTRIM(wrb,n) \

View File

@ -1309,7 +1309,7 @@ int psock_tcp_cansend(FAR struct socket *psock)
* but we don't know how many more.
*/
if (tcp_wrbuffer_test() < 0 || iob_navail(false) <= 0)
if (tcp_wrbuffer_test() < 0 || iob_navail(true) <= 0)
{
return -EWOULDBLOCK;
}

View File

@ -145,7 +145,7 @@ FAR struct tcp_wrbuffer_s *tcp_wrbuffer_alloc(void)
/* Now get the first I/O buffer for the write buffer structure */
wrb->wb_iob = net_ioballoc(false, IOBUSER_NET_TCP_WRITEBUFFER);
wrb->wb_iob = net_ioballoc(true, IOBUSER_NET_TCP_WRITEBUFFER);
/* Did we get an IOB? We should always get one except under some really
* weird error conditions.