Skip to content

Commit 985d6c3

Browse files
lpereirajukkar
authored andcommitted
net: tcp: Limit number of segment retransmissions
Defines a new tunable, CONFIG_NET_TCP_RETRY_COUNT, that determines the number of segment retransmissions that the IP stack will attempt to perform before resetting the connection. The default value is 9 retransmissions, which amounts to 1:42 minutes, as close as possible to the minimum recommended by RFC1122. Jira: ZEP-1956, ZEP-1957 Signed-off-by: Leandro Pereira <leandro.pereira@intel.com>
1 parent bad6e28 commit 985d6c3

File tree

2 files changed

+39
-0
lines changed

2 files changed

+39
-0
lines changed

subsys/net/ip/Kconfig

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,25 @@ config NET_TCP_ACK_TIMEOUT
139139
various TCP states. The value is in milliseconds. Note that
140140
having a very low value here could prevent connectivity.
141141

142+
config NET_TCP_RETRY_COUNT
143+
int "Maximum number of TCP segment retransmissions"
144+
depends on NET_TCP
145+
default 9
146+
help
147+
The following formula can be used to determine the time (in ms)
148+
that a segment will be be buffered awaiting retransmission:
149+
n=NET_TCP_RETRY_COUNT
150+
∑((1<<n) * 200)
151+
n=0
152+
With the default value of 9, the IP stack will try to
153+
retransmit for up to 1:42 minutes. This is as close as possible
154+
to the minimum value recommended by RFC1122 (1:40 minutes).
155+
Only 5 bits are dedicated for the retransmission count, so accepted
156+
values are in the 0-31 range. It's highly recommended to not go
157+
below 9, though.
158+
Should a retransmission timeout occur, the receive callback is
159+
called with -ECONNRESET error code and the context is dereferenced.
160+
142161
config NET_UDP
143162
bool "Enable UDP"
144163
default y

subsys/net/ip/tcp.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,20 @@ static inline void do_ref_if_needed(struct net_pkt *pkt)
141141
}
142142
}
143143

144+
static void abort_connection(struct net_tcp *tcp)
145+
{
146+
struct net_context *ctx = tcp->context;
147+
148+
NET_DBG("Segment retransmission exceeds %d, resetting context %p",
149+
CONFIG_NET_TCP_RETRY_COUNT, ctx);
150+
151+
if (ctx->recv_cb) {
152+
ctx->recv_cb(ctx, NULL, -ECONNRESET, tcp->recv_user_data);
153+
}
154+
155+
net_context_unref(ctx);
156+
}
157+
144158
static void tcp_retry_expired(struct k_timer *timer)
145159
{
146160
struct net_tcp *tcp = CONTAINER_OF(timer, struct net_tcp, retry_timer);
@@ -151,6 +165,12 @@ static void tcp_retry_expired(struct k_timer *timer)
151165
*/
152166
if (!sys_slist_is_empty(&tcp->sent_list)) {
153167
tcp->retry_timeout_shift++;
168+
169+
if (tcp->retry_timeout_shift > CONFIG_NET_TCP_RETRY_COUNT) {
170+
abort_connection(tcp);
171+
return;
172+
}
173+
154174
k_timer_start(&tcp->retry_timer, retry_timeout(tcp), 0);
155175

156176
pkt = CONTAINER_OF(sys_slist_peek_head(&tcp->sent_list),

0 commit comments

Comments
 (0)