Skip to content

Commit 0b27f4b

Browse files
rluboscarlescufi
authored andcommitted
net: tcp: Report TCP errors through recv_cb()
Make use of the status argument in the recv_cb() callback function - instead of blindly reporting ECONNRESET whenever TCP context is dereferenced, indicate whether an actual error condition happened (by setting respective errno value) or a graceful shutdown took place (by setting status to 0). Signed-off-by: Robert Lubos <[email protected]>
1 parent b3dfc24 commit 0b27f4b

File tree

1 file changed

+22
-14
lines changed

1 file changed

+22
-14
lines changed

subsys/net/ip/tcp.c

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -358,12 +358,13 @@ static void tcp_send_queue_flush(struct tcp *conn)
358358
}
359359

360360
#if CONFIG_NET_TCP_LOG_LEVEL >= LOG_LEVEL_DBG
361-
#define tcp_conn_unref(conn) \
362-
tcp_conn_unref_debug(conn, __func__, __LINE__)
361+
#define tcp_conn_unref(conn, status) \
362+
tcp_conn_unref_debug(conn, status, __func__, __LINE__)
363363

364-
static int tcp_conn_unref_debug(struct tcp *conn, const char *caller, int line)
364+
static int tcp_conn_unref_debug(struct tcp *conn, int status,
365+
const char *caller, int line)
365366
#else
366-
static int tcp_conn_unref(struct tcp *conn)
367+
static int tcp_conn_unref(struct tcp *conn, int status)
367368
#endif
368369
{
369370
int ref_count = atomic_get(&conn->ref_count);
@@ -409,7 +410,7 @@ static int tcp_conn_unref(struct tcp *conn)
409410

410411
if (conn->context->recv_cb) {
411412
conn->context->recv_cb(conn->context, NULL, NULL, NULL,
412-
-ECONNRESET, conn->recv_user_data);
413+
status, conn->recv_user_data);
413414
}
414415

415416
conn->context->tcp = NULL;
@@ -446,7 +447,7 @@ int net_tcp_unref(struct net_context *context)
446447
NET_DBG("context: %p, conn: %p", context, context->tcp);
447448

448449
if (context->tcp) {
449-
ref_count = tcp_conn_unref(context->tcp);
450+
ref_count = tcp_conn_unref(context->tcp, 0);
450451
}
451452

452453
return ref_count;
@@ -530,7 +531,7 @@ static void tcp_send_process(struct k_work *work)
530531
k_mutex_unlock(&conn->lock);
531532

532533
if (unref) {
533-
tcp_conn_unref(conn);
534+
tcp_conn_unref(conn, -ETIMEDOUT);
534535
}
535536
}
536537

@@ -929,7 +930,7 @@ static int tcp_out_ext(struct tcp *conn, uint8_t flags, struct net_pkt *data,
929930
k_work_schedule_for_queue(&tcp_work_q,
930931
&conn->send_timer, K_NO_WAIT);
931932
} else if (tcp_send_process_no_lock(conn)) {
932-
tcp_conn_unref(conn);
933+
tcp_conn_unref(conn, -ETIMEDOUT);
933934
}
934935
out:
935936
return ret;
@@ -1172,7 +1173,7 @@ static void tcp_resend_data(struct k_work *work)
11721173
k_mutex_unlock(&conn->lock);
11731174

11741175
if (conn_unref) {
1175-
tcp_conn_unref(conn);
1176+
tcp_conn_unref(conn, -ETIMEDOUT);
11761177
}
11771178
}
11781179

@@ -1192,7 +1193,7 @@ static void tcp_establish_timeout(struct tcp *conn)
11921193
NET_DBG("Did not receive %s in %dms", "ACK", ACK_TIMEOUT_MS);
11931194
NET_DBG("conn: %p %s", conn, log_strdup(tcp_conn_state(conn, NULL)));
11941195

1195-
(void)tcp_conn_unref(conn);
1196+
(void)tcp_conn_unref(conn, -ETIMEDOUT);
11961197
}
11971198

11981199
static void tcp_fin_timeout(struct k_work *work)
@@ -1745,6 +1746,7 @@ static void tcp_in(struct tcp *conn, struct net_pkt *pkt)
17451746
size_t len;
17461747
int ret;
17471748
int sndbuf_opt = 0;
1749+
int close_status = 0;
17481750

17491751
if (th) {
17501752
/* Currently we ignore ECN and CWR flags */
@@ -1764,6 +1766,7 @@ static void tcp_in(struct tcp *conn, struct net_pkt *pkt)
17641766
if (th && th_off(th) < 5) {
17651767
tcp_out(conn, RST);
17661768
conn_state(conn, TCP_CLOSED);
1769+
close_status = -ECONNRESET;
17671770
goto next_state;
17681771
}
17691772

@@ -1777,6 +1780,7 @@ static void tcp_in(struct tcp *conn, struct net_pkt *pkt)
17771780

17781781
net_stats_update_tcp_seg_rst(net_pkt_iface(pkt));
17791782
conn_state(conn, TCP_CLOSED);
1783+
close_status = -ECONNRESET;
17801784
goto next_state;
17811785
}
17821786

@@ -1785,6 +1789,7 @@ static void tcp_in(struct tcp *conn, struct net_pkt *pkt)
17851789
NET_DBG("DROP: Invalid TCP option list");
17861790
tcp_out(conn, RST);
17871791
conn_state(conn, TCP_CLOSED);
1792+
close_status = -ECONNRESET;
17881793
goto next_state;
17891794
}
17901795

@@ -1953,6 +1958,7 @@ static void tcp_in(struct tcp *conn, struct net_pkt *pkt)
19531958
net_stats_update_tcp_seg_drop(conn->iface);
19541959
tcp_out(conn, RST);
19551960
conn_state(conn, TCP_CLOSED);
1961+
close_status = -ECONNRESET;
19561962
break;
19571963
}
19581964

@@ -1994,6 +2000,7 @@ static void tcp_in(struct tcp *conn, struct net_pkt *pkt)
19942000
if (ret < 0 && ret != -ENOBUFS) {
19952001
tcp_out(conn, RST);
19962002
conn_state(conn, TCP_CLOSED);
2003+
close_status = ret;
19972004
break;
19982005
}
19992006
}
@@ -2021,6 +2028,7 @@ static void tcp_in(struct tcp *conn, struct net_pkt *pkt)
20212028
if (th && FL(&fl, ==, ACK, th_seq(th) == conn->ack)) {
20222029
tcp_send_timer_cancel(conn);
20232030
next = TCP_CLOSED;
2031+
close_status = 0;
20242032
}
20252033
break;
20262034
case TCP_CLOSED:
@@ -2119,7 +2127,7 @@ static void tcp_in(struct tcp *conn, struct net_pkt *pkt)
21192127
* to a deadlock.
21202128
*/
21212129
if (do_close) {
2122-
tcp_conn_unref(conn);
2130+
tcp_conn_unref(conn, close_status);
21232131
}
21242132
}
21252133

@@ -2277,7 +2285,7 @@ int net_tcp_queue_data(struct net_context *context, struct net_pkt *pkt)
22772285

22782286
ret = tcp_send_queued_data(conn);
22792287
if (ret < 0 && ret != -ENOBUFS) {
2280-
tcp_conn_unref(conn);
2288+
tcp_conn_unref(conn, ret);
22812289
goto out;
22822290
}
22832291

@@ -2433,7 +2441,7 @@ int net_tcp_connect(struct net_context *context,
24332441
if (k_sem_take(&conn->connect_sem, timeout) != 0 &&
24342442
conn->state != TCP_ESTABLISHED) {
24352443
conn->in_connect = false;
2436-
tcp_conn_unref(conn);
2444+
tcp_conn_unref(conn, -ETIMEDOUT);
24372445
ret = -ETIMEDOUT;
24382446
goto out;
24392447
}
@@ -2739,7 +2747,7 @@ enum net_verdict tp_input(struct net_conn *net_conn,
27392747

27402748
conn = (void *)sys_slist_peek_head(&tcp_conns);
27412749
context = conn->context;
2742-
while (tcp_conn_unref(conn))
2750+
while (tcp_conn_unref(conn, 0))
27432751
;
27442752
tcp_free(context);
27452753
}

0 commit comments

Comments
 (0)