Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

net: tcp2: Lock connection when running from work queue #28595

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions subsys/net/ip/connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,10 @@ enum net_verdict net_conn_input(struct net_pkt *pkt,
src_port = proto_hdr->udp->src_port;
dst_port = proto_hdr->udp->dst_port;
} else if (IS_ENABLED(CONFIG_NET_TCP) && proto == IPPROTO_TCP) {
if (proto_hdr->tcp == NULL) {
return NET_DROP;
}

src_port = proto_hdr->tcp->src_port;
dst_port = proto_hdr->tcp->dst_port;
} else if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET)) {
Expand Down
29 changes: 22 additions & 7 deletions subsys/net/ip/tcp2.c
Original file line number Diff line number Diff line change
Expand Up @@ -363,11 +363,15 @@ int net_tcp_unref(struct net_context *context)
static void tcp_send_process(struct k_work *work)
{
struct tcp *conn = CONTAINER_OF(work, struct tcp, send_timer);
struct net_pkt *pkt = tcp_slist(&conn->send_queue, peek_head,
struct net_pkt, next);
bool unref = false;
struct net_pkt *pkt;

k_mutex_lock(&conn->lock, K_FOREVER);

pkt = tcp_slist(&conn->send_queue, peek_head,
struct net_pkt, next);
if (!pkt) {
return;
goto out;
}

NET_DBG("%s %s", log_strdup(tcp_th(pkt)), conn->in_retransmission ?
Expand All @@ -382,8 +386,8 @@ static void tcp_send_process(struct k_work *work)
conn->send_retries--;
}
} else {
tcp_conn_unref(conn);
conn = NULL;
unref = true;
goto out;
}
} else {
uint8_t fl = th_get(pkt)->th_flags;
Expand All @@ -394,7 +398,7 @@ static void tcp_send_process(struct k_work *work)
next) : tcp_pkt_clone(pkt);
if (!pkt) {
NET_ERR("net_pkt alloc failure");
return;
goto out;
}

tcp_send(pkt);
Expand All @@ -406,9 +410,16 @@ static void tcp_send_process(struct k_work *work)
}
}

if (conn && conn->in_retransmission) {
if (conn->in_retransmission) {
k_delayed_work_submit(&conn->send_timer, K_MSEC(tcp_rto));
}

out:
jukkar marked this conversation as resolved.
Show resolved Hide resolved
k_mutex_unlock(&conn->lock);

if (unref) {
tcp_conn_unref(conn);
}
}

static void tcp_send_timer_cancel(struct tcp *conn)
Expand Down Expand Up @@ -863,6 +874,8 @@ static void tcp_resend_data(struct k_work *work)
bool conn_unref = false;
int ret;

k_mutex_lock(&conn->lock, K_FOREVER);

NET_DBG("send_data_retries=%hu", conn->send_data_retries);

if (conn->send_data_retries >= tcp_retries) {
Expand Down Expand Up @@ -899,6 +912,8 @@ static void tcp_resend_data(struct k_work *work)
k_delayed_work_submit(&conn->send_data_timer, K_MSEC(tcp_rto));

out:
k_mutex_unlock(&conn->lock);

if (conn_unref) {
tcp_conn_unref(conn);
}
Expand Down
13 changes: 12 additions & 1 deletion subsys/net/l2/ethernet/ethernet.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,10 +174,21 @@ static enum net_verdict ethernet_recv(struct net_if *iface,
struct ethernet_context *ctx = net_if_l2_data(iface);
struct net_eth_hdr *hdr = NET_ETH_HDR(pkt);
uint8_t hdr_len = sizeof(struct net_eth_hdr);
uint16_t type = ntohs(hdr->type);
uint16_t type;
struct net_linkaddr *lladdr;
sa_family_t family;

/* This expects that the Ethernet header is in the first net_buf
* fragment. This is a safe expectation here as it would not make
* any sense to split the Ethernet header to two net_buf's by the
* Ethernet driver.
*/
if (hdr == NULL || pkt->buffer->len < hdr_len) {
goto drop;
}

type = ntohs(hdr->type);

if (net_eth_is_vlan_enabled(ctx, iface) &&
type == NET_ETH_PTYPE_VLAN &&
!eth_is_vlan_tag_stripped(iface)) {
Expand Down