Skip to content

Commit 7eaacda

Browse files
rluboscarlescufi
authored andcommitted
net: tcp: Add semaphore indicating if transfer is possible
The semaphore is reset when TCP layer would normally reject transfer request (either due to TX window being full or entering retransmission mode). Once data is acnowledged, or the reatransmission is done, the semaphore is set again. Upper layers can monitor the semaphore with `k_poll()` instead of waiting blindly before attempting to transmit again. Signed-off-by: Robert Lubos <[email protected]>
1 parent 1af78b0 commit 7eaacda

File tree

3 files changed

+41
-0
lines changed

3 files changed

+41
-0
lines changed

subsys/net/ip/tcp.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,6 +1078,10 @@ static int tcp_send_queued_data(struct tcp *conn)
10781078
}
10791079
}
10801080

1081+
if (tcp_window_full(conn)) {
1082+
(void)k_sem_take(&conn->tx_sem, K_NO_WAIT);
1083+
}
1084+
10811085
if (conn->unacked_len) {
10821086
subscribe = true;
10831087
}
@@ -1140,6 +1144,8 @@ static void tcp_resend_data(struct k_work *work)
11401144
conn->data_mode = TCP_DATA_MODE_RESEND;
11411145
conn->unacked_len = 0;
11421146

1147+
(void)k_sem_take(&conn->tx_sem, K_NO_WAIT);
1148+
11431149
ret = tcp_send_data(conn);
11441150
conn->send_data_retries++;
11451151
if (ret == 0) {
@@ -1163,6 +1169,11 @@ static void tcp_resend_data(struct k_work *work)
11631169
}
11641170
} else if (ret == -ENODATA) {
11651171
conn->data_mode = TCP_DATA_MODE_SEND;
1172+
1173+
if (!tcp_window_full(conn)) {
1174+
k_sem_give(&conn->tx_sem);
1175+
}
1176+
11661177
goto out;
11671178
}
11681179

@@ -1253,6 +1264,7 @@ static struct tcp *tcp_conn_alloc(struct net_context *context)
12531264
k_mutex_init(&conn->lock);
12541265
k_fifo_init(&conn->recv_data);
12551266
k_sem_init(&conn->connect_sem, 0, K_SEM_MAX_LIMIT);
1267+
k_sem_init(&conn->tx_sem, 1, 1);
12561268

12571269
conn->in_connect = false;
12581270
conn->state = TCP_LISTEN;
@@ -1822,6 +1834,12 @@ static void tcp_in(struct tcp *conn, struct net_pkt *pkt)
18221834

18231835
conn->send_win = max_win;
18241836
}
1837+
1838+
if (tcp_window_full(conn)) {
1839+
(void)k_sem_take(&conn->tx_sem, K_NO_WAIT);
1840+
} else {
1841+
k_sem_give(&conn->tx_sem);
1842+
}
18251843
}
18261844

18271845
next_state:
@@ -1968,6 +1986,11 @@ static void tcp_in(struct tcp *conn, struct net_pkt *pkt)
19681986
} else {
19691987
conn->unacked_len -= len_acked;
19701988
}
1989+
1990+
if (!tcp_window_full(conn)) {
1991+
k_sem_give(&conn->tx_sem);
1992+
}
1993+
19711994
conn_seq(conn, + len_acked);
19721995
net_stats_update_tcp_seg_recv(conn->iface);
19731996

@@ -2908,6 +2931,13 @@ const char *net_tcp_state_str(enum tcp_state state)
29082931
return tcp_state_to_str(state, false);
29092932
}
29102933

2934+
struct k_sem *net_tcp_tx_sem_get(struct net_context *context)
2935+
{
2936+
struct tcp *conn = context->tcp;
2937+
2938+
return &conn->tx_sem;
2939+
}
2940+
29112941
void net_tcp_init(void)
29122942
{
29132943
#if defined(CONFIG_NET_TEST_PROTOCOL)

subsys/net/ip/tcp_internal.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,16 @@ void net_tcp_init(void);
367367
#define net_tcp_init(...)
368368
#endif
369369

370+
/**
371+
* @brief Obtain a semaphore indicating if transfers are blocked (either due to
372+
* filling TX window or entering retransmission mode).
373+
*
374+
* @param context Network context
375+
*
376+
* @return semaphore indicating if transfers are blocked
377+
*/
378+
struct k_sem *net_tcp_tx_sem_get(struct net_context *context);
379+
370380
#ifdef __cplusplus
371381
}
372382
#endif

subsys/net/ip/tcp_private.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ struct tcp { /* TCP connection */
234234
};
235235
struct k_mutex lock;
236236
struct k_sem connect_sem; /* semaphore for blocking connect */
237+
struct k_sem tx_sem; /* Semaphore indicating if transfers are blocked . */
237238
struct k_fifo recv_data; /* temp queue before passing data to app */
238239
struct tcp_options recv_options;
239240
struct tcp_options send_options;

0 commit comments

Comments
 (0)