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 <robert.lubos@nordicsemi.no>
This commit is contained in:
parent
1af78b07a7
commit
7eaacdaca6
3 changed files with 41 additions and 0 deletions
|
@ -1078,6 +1078,10 @@ static int tcp_send_queued_data(struct tcp *conn)
|
|||
}
|
||||
}
|
||||
|
||||
if (tcp_window_full(conn)) {
|
||||
(void)k_sem_take(&conn->tx_sem, K_NO_WAIT);
|
||||
}
|
||||
|
||||
if (conn->unacked_len) {
|
||||
subscribe = true;
|
||||
}
|
||||
|
@ -1140,6 +1144,8 @@ static void tcp_resend_data(struct k_work *work)
|
|||
conn->data_mode = TCP_DATA_MODE_RESEND;
|
||||
conn->unacked_len = 0;
|
||||
|
||||
(void)k_sem_take(&conn->tx_sem, K_NO_WAIT);
|
||||
|
||||
ret = tcp_send_data(conn);
|
||||
conn->send_data_retries++;
|
||||
if (ret == 0) {
|
||||
|
@ -1163,6 +1169,11 @@ static void tcp_resend_data(struct k_work *work)
|
|||
}
|
||||
} else if (ret == -ENODATA) {
|
||||
conn->data_mode = TCP_DATA_MODE_SEND;
|
||||
|
||||
if (!tcp_window_full(conn)) {
|
||||
k_sem_give(&conn->tx_sem);
|
||||
}
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -1253,6 +1264,7 @@ static struct tcp *tcp_conn_alloc(struct net_context *context)
|
|||
k_mutex_init(&conn->lock);
|
||||
k_fifo_init(&conn->recv_data);
|
||||
k_sem_init(&conn->connect_sem, 0, K_SEM_MAX_LIMIT);
|
||||
k_sem_init(&conn->tx_sem, 1, 1);
|
||||
|
||||
conn->in_connect = false;
|
||||
conn->state = TCP_LISTEN;
|
||||
|
@ -1822,6 +1834,12 @@ static void tcp_in(struct tcp *conn, struct net_pkt *pkt)
|
|||
|
||||
conn->send_win = max_win;
|
||||
}
|
||||
|
||||
if (tcp_window_full(conn)) {
|
||||
(void)k_sem_take(&conn->tx_sem, K_NO_WAIT);
|
||||
} else {
|
||||
k_sem_give(&conn->tx_sem);
|
||||
}
|
||||
}
|
||||
|
||||
next_state:
|
||||
|
@ -1968,6 +1986,11 @@ next_state:
|
|||
} else {
|
||||
conn->unacked_len -= len_acked;
|
||||
}
|
||||
|
||||
if (!tcp_window_full(conn)) {
|
||||
k_sem_give(&conn->tx_sem);
|
||||
}
|
||||
|
||||
conn_seq(conn, + len_acked);
|
||||
net_stats_update_tcp_seg_recv(conn->iface);
|
||||
|
||||
|
@ -2908,6 +2931,13 @@ const char *net_tcp_state_str(enum tcp_state state)
|
|||
return tcp_state_to_str(state, false);
|
||||
}
|
||||
|
||||
struct k_sem *net_tcp_tx_sem_get(struct net_context *context)
|
||||
{
|
||||
struct tcp *conn = context->tcp;
|
||||
|
||||
return &conn->tx_sem;
|
||||
}
|
||||
|
||||
void net_tcp_init(void)
|
||||
{
|
||||
#if defined(CONFIG_NET_TEST_PROTOCOL)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue