net: lib: openthread: Handle OT transmission in Thread task
OpenThread API is not thread-safe. Moved creation of otMessage to the Thread task and created api for passing it properly. This way it should be less possible for an issue to occure eg. during message buffer allocation. Signed-off-by: Marek Porwisz <marek.porwisz@nordicsemi.no>
This commit is contained in:
parent
a8585ac35c
commit
1130f8484e
3 changed files with 66 additions and 31 deletions
|
@ -299,42 +299,15 @@ static enum net_verdict openthread_recv(struct net_if *iface,
|
|||
|
||||
int openthread_send(struct net_if *iface, struct net_pkt *pkt)
|
||||
{
|
||||
struct openthread_context *ot_context = net_if_l2_data(iface);
|
||||
int len = net_pkt_get_len(pkt);
|
||||
struct net_buf *buf;
|
||||
otMessage *message;
|
||||
otMessageSettings settings;
|
||||
|
||||
NET_DBG("Sending Ip6 packet to ot stack");
|
||||
|
||||
settings.mPriority = OT_MESSAGE_PRIORITY_NORMAL;
|
||||
settings.mLinkSecurityEnabled = true;
|
||||
message = otIp6NewMessage(ot_context->instance, &settings);
|
||||
if (message == NULL) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
for (buf = pkt->buffer; buf; buf = buf->frags) {
|
||||
if (otMessageAppend(message, buf->data,
|
||||
buf->len) != OT_ERROR_NONE) {
|
||||
|
||||
NET_ERR("Error while appending to otMessage");
|
||||
otMessageFree(message);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (otIp6Send(ot_context->instance, message) != OT_ERROR_NONE) {
|
||||
NET_ERR("Error while calling otIp6Send");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_OPENTHREAD_L2_DEBUG_DUMP_IPV6)) {
|
||||
net_pkt_hexdump(pkt, "Sent IPv6 packet");
|
||||
net_pkt_hexdump(pkt, "IPv6 packet to send");
|
||||
}
|
||||
|
||||
exit:
|
||||
net_pkt_unref(pkt);
|
||||
if (notify_new_tx_frame(pkt) != 0) {
|
||||
net_pkt_unref(pkt);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
|
|
@ -82,4 +82,9 @@ void platformShellInit(otInstance *aInstance);
|
|||
*/
|
||||
int notify_new_rx_frame(struct net_pkt *pkt);
|
||||
|
||||
/**
|
||||
* Notify OpenThread task about new tx message.
|
||||
*/
|
||||
int notify_new_tx_frame(struct net_pkt *pkt);
|
||||
|
||||
#endif /* PLATFORM_POSIX_H_ */
|
||||
|
|
|
@ -27,10 +27,12 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_OPENTHREAD_L2_LOG_LEVEL);
|
|||
#include <net/net_pkt.h>
|
||||
#include <sys/__assert.h>
|
||||
|
||||
#include <openthread/ip6.h>
|
||||
#include <openthread-system.h>
|
||||
#include <openthread/instance.h>
|
||||
#include <openthread/platform/radio.h>
|
||||
#include <openthread/platform/diag.h>
|
||||
#include <openthread/message.h>
|
||||
|
||||
#include "platform-zephyr.h"
|
||||
|
||||
|
@ -46,6 +48,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_OPENTHREAD_L2_LOG_LEVEL);
|
|||
#define OT_WORKER_PRIORITY K_PRIO_COOP(CONFIG_OPENTHREAD_THREAD_PRIORITY)
|
||||
|
||||
enum pending_events {
|
||||
PENDING_EVENT_FRAME_TO_SEND, /* There is a tx frame to send */
|
||||
PENDING_EVENT_FRAME_RECEIVED, /* Radio has received new frame */
|
||||
PENDING_EVENT_TX_STARTED, /* Radio has started transmitting */
|
||||
PENDING_EVENT_TX_DONE, /* Radio transmission finished */
|
||||
|
@ -84,6 +87,7 @@ static struct k_work_q ot_work_q;
|
|||
static otError tx_result;
|
||||
|
||||
K_FIFO_DEFINE(rx_pkt_fifo);
|
||||
K_FIFO_DEFINE(tx_pkt_fifo);
|
||||
|
||||
static inline bool is_pending_event_set(enum pending_events event)
|
||||
{
|
||||
|
@ -302,6 +306,40 @@ static void openthread_handle_received_frame(otInstance *instance,
|
|||
net_pkt_unref(pkt);
|
||||
}
|
||||
|
||||
static void openthread_handle_frame_to_send(otInstance *instance,
|
||||
struct net_pkt *pkt)
|
||||
{
|
||||
struct net_buf *buf;
|
||||
otMessage *message;
|
||||
otMessageSettings settings;
|
||||
|
||||
NET_DBG("Sending Ip6 packet to ot stack");
|
||||
|
||||
settings.mPriority = OT_MESSAGE_PRIORITY_NORMAL;
|
||||
settings.mLinkSecurityEnabled = true;
|
||||
message = otIp6NewMessage(instance, &settings);
|
||||
if (message == NULL) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
for (buf = pkt->buffer; buf; buf = buf->frags) {
|
||||
if (otMessageAppend(message, buf->data,
|
||||
buf->len) != OT_ERROR_NONE) {
|
||||
NET_ERR("Error while appending to otMessage");
|
||||
otMessageFree(message);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (otIp6Send(instance, message) != OT_ERROR_NONE) {
|
||||
NET_ERR("Error while calling otIp6Send");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
net_pkt_unref(pkt);
|
||||
}
|
||||
|
||||
int notify_new_rx_frame(struct net_pkt *pkt)
|
||||
{
|
||||
k_fifo_put(&rx_pkt_fifo, pkt);
|
||||
|
@ -310,6 +348,14 @@ int notify_new_rx_frame(struct net_pkt *pkt)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int notify_new_tx_frame(struct net_pkt *pkt)
|
||||
{
|
||||
k_fifo_put(&tx_pkt_fifo, pkt);
|
||||
set_pending_event(PENDING_EVENT_FRAME_TO_SEND);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int run_tx_task(otInstance *aInstance)
|
||||
{
|
||||
static struct k_work tx_job;
|
||||
|
@ -331,6 +377,17 @@ void platformRadioProcess(otInstance *aInstance)
|
|||
{
|
||||
bool event_pending = false;
|
||||
|
||||
if (is_pending_event_set(PENDING_EVENT_FRAME_TO_SEND)) {
|
||||
struct net_pkt *tx_pkt;
|
||||
|
||||
reset_pending_event(PENDING_EVENT_FRAME_TO_SEND);
|
||||
while ((tx_pkt = (struct net_pkt *)k_fifo_get(&tx_pkt_fifo,
|
||||
K_NO_WAIT))
|
||||
!= NULL) {
|
||||
openthread_handle_frame_to_send(aInstance, tx_pkt);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_pending_event_set(PENDING_EVENT_FRAME_RECEIVED)) {
|
||||
struct net_pkt *rx_pkt;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue