From 09f3a1ec8ed41519207a10fd2a2589ffef348465 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Mon, 12 Jul 2021 20:05:18 +0900 Subject: [PATCH] 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) --- net/tcp/tcp.h | 4 ++-- net/tcp/tcp_send_buffered.c | 2 +- net/tcp/tcp_wrbuffer.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/net/tcp/tcp.h b/net/tcp/tcp.h index d2a9975050c..716e9955fee 100644 --- a/net/tcp/tcp.h +++ b/net/tcp/tcp.h @@ -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) \ diff --git a/net/tcp/tcp_send_buffered.c b/net/tcp/tcp_send_buffered.c index a8218d7922a..5740ad4dbc0 100644 --- a/net/tcp/tcp_send_buffered.c +++ b/net/tcp/tcp_send_buffered.c @@ -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; } diff --git a/net/tcp/tcp_wrbuffer.c b/net/tcp/tcp_wrbuffer.c index c93f7495e9f..27d912144c0 100644 --- a/net/tcp/tcp_wrbuffer.c +++ b/net/tcp/tcp_wrbuffer.c @@ -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.