1818#include "esp_netif_ip_addr.h"
1919#include "esp_openthread.h"
2020#include "esp_openthread_border_router.h"
21+ #include "esp_openthread_common.h"
2122#include "esp_openthread_common_macro.h"
2223#include "esp_openthread_lock.h"
24+ #include "esp_openthread_platform.h"
2325#include "esp_openthread_radio.h"
24- #include "esp_openthread_task_queue .h"
26+ #include "esp_vfs_eventfd .h"
2527#include "lwip/pbuf.h"
2628#include "lwip/tcpip.h"
2729#include "lwip/udp.h"
@@ -54,6 +56,10 @@ typedef struct {
5456
5557static ot_trel_t s_ot_trel = {CONFIG_OPENTHREAD_TREL_PORT , NULL };
5658static bool s_is_service_registered = false;
59+ static ot_trel_recv_task_t s_trel_receive_buffer [CONFIG_OPENTHREAD_TREL_BUFFER_SIZE ];
60+ static esp_openthread_circular_queue_info_t s_recv_queue = {.head = 0 , .tail = 0 , .used = 0 };
61+ static const char * s_trel_workflow = "trel" ;
62+ static int s_trel_event_fd = -1 ;
5763
5864static void trel_browse_notifier (mdns_result_t * result )
5965{
@@ -89,55 +95,27 @@ static void trel_browse_notifier(mdns_result_t *result)
8995 }
9096}
9197
92- static void trel_recv_task (void * ctx )
93- {
94- esp_err_t ret = ESP_OK ;
95- OT_UNUSED_VARIABLE (ret );
96- ot_trel_recv_task_t * task_ctx = (ot_trel_recv_task_t * )ctx ;
97- struct pbuf * recv_buf = task_ctx -> p ;
98- uint8_t * data_buf = (uint8_t * )recv_buf -> payload ;
99- uint8_t * data_buf_to_free = NULL ;
100- uint16_t length = recv_buf -> len ;
101-
102- if (recv_buf -> next != NULL ) {
103- data_buf = (uint8_t * )malloc (recv_buf -> tot_len );
104- ESP_GOTO_ON_FALSE (data_buf , ESP_ERR_NO_MEM , exit , OT_PLAT_LOG_TAG , "Failed to allocate data buf when receiving Thread TREL message" );
105- length = recv_buf -> tot_len ;
106- data_buf_to_free = data_buf ;
107- pbuf_copy_partial (recv_buf , data_buf , recv_buf -> tot_len , 0 );
108- }
109- otPlatTrelHandleReceived (esp_openthread_get_instance (), data_buf , length , task_ctx -> source_addr );
110-
111- exit :
112- if (recv_buf ) {
113- pbuf_free (recv_buf );
114- }
115- free (data_buf_to_free );
116- free (task_ctx -> source_addr );
117- free (task_ctx );
118- }
119-
120- // TZ-1704
12198static void handle_trel_udp_recv (void * ctx , struct udp_pcb * pcb , struct pbuf * p , const ip_addr_t * addr , uint16_t port )
12299{
123100 esp_err_t ret = ESP_OK ;
101+ otSockAddr * source_addr = NULL ;
102+ uint64_t event_trel_rx = 1 ;
124103 ESP_LOGD (OT_PLAT_LOG_TAG , "Receive from %s:%d" , ip6addr_ntoa (& (addr -> u_addr .ip6 )), port );
125-
126- ot_trel_recv_task_t * task_ctx = (ot_trel_recv_task_t * )malloc (sizeof (ot_trel_recv_task_t ));
127- ESP_GOTO_ON_FALSE (task_ctx , ESP_ERR_NO_MEM , exit , OT_PLAT_LOG_TAG , "Failed to allocate buf for Thread TREL" );
128- task_ctx -> p = p ;
129- task_ctx -> source_addr = (otSockAddr * )malloc (sizeof (otSockAddr ));
130- ESP_GOTO_ON_FALSE (task_ctx -> source_addr , ESP_ERR_NO_MEM , exit , OT_PLAT_LOG_TAG , "Failed to allocate buf for Thread TREL" );
131- memset (task_ctx -> source_addr , 0 , sizeof (otSockAddr ));
132- task_ctx -> source_addr -> mPort = port ;
133- memcpy (& task_ctx -> source_addr -> mAddress .mFields .m32 , addr -> u_addr .ip6 .addr , sizeof (addr -> u_addr .ip6 .addr ));
134-
135- ESP_GOTO_ON_ERROR (esp_openthread_task_queue_post (trel_recv_task , task_ctx ), exit , OT_PLAT_LOG_TAG , "Failed to receive OpenThread TREL message" );
104+ ESP_GOTO_ON_FALSE (atomic_load (& s_recv_queue .used ) < CONFIG_OPENTHREAD_TREL_BUFFER_SIZE , ESP_ERR_NO_MEM , exit , OT_PLAT_LOG_TAG , "trel receive buffer full!" );
105+ source_addr = (otSockAddr * )malloc (sizeof (otSockAddr ));
106+ ESP_GOTO_ON_FALSE (source_addr , ESP_ERR_NO_MEM , exit , OT_PLAT_LOG_TAG , "Failed to allocate buf for Thread TREL" );
107+
108+ memset (source_addr , 0 , sizeof (otSockAddr ));
109+ source_addr -> mPort = port ;
110+ memcpy (& source_addr -> mAddress .mFields .m32 , addr -> u_addr .ip6 .addr , sizeof (addr -> u_addr .ip6 .addr ));
111+ s_trel_receive_buffer [s_recv_queue .tail ].source_addr = source_addr ;
112+ s_trel_receive_buffer [s_recv_queue .tail ].p = p ;
113+ s_recv_queue .tail = (s_recv_queue .tail + 1 ) % CONFIG_OPENTHREAD_TREL_BUFFER_SIZE ;
114+ atomic_fetch_add (& s_recv_queue .used , 1 );
115+ assert (write (s_trel_event_fd , & event_trel_rx , sizeof (event_trel_rx )) == sizeof (event_trel_rx ));
136116
137117exit :
138118 if (ret != ESP_OK ) {
139- free (task_ctx -> source_addr );
140- free (task_ctx );
141119 if (p ) {
142120 pbuf_free (p );
143121 }
@@ -146,25 +124,76 @@ static void handle_trel_udp_recv(void *ctx, struct udp_pcb *pcb, struct pbuf *p,
146124
147125static esp_err_t ot_new_trel (void * ctx )
148126{
149- ot_trel_t * task = (ot_trel_t * )ctx ;
127+ s_ot_trel .trel_pcb = udp_new ();
128+ ESP_RETURN_ON_FALSE (s_ot_trel .trel_pcb != NULL , ESP_ERR_NO_MEM , OT_PLAT_LOG_TAG , "Failed to create a new UDP pcb" );
129+ udp_bind (s_ot_trel .trel_pcb , IP6_ADDR_ANY , s_ot_trel .port );
130+ udp_recv (s_ot_trel .trel_pcb , handle_trel_udp_recv , NULL );
131+ return ESP_OK ;
132+ }
133+
134+ void esp_openthread_trel_update (esp_openthread_mainloop_context_t * mainloop )
135+ {
136+ FD_SET (s_trel_event_fd , & mainloop -> read_fds );
137+ if (s_trel_event_fd > mainloop -> max_fd ) {
138+ mainloop -> max_fd = s_trel_event_fd ;
139+ }
140+ }
141+
142+ esp_err_t esp_openthread_trel_process (otInstance * aInstance , const esp_openthread_mainloop_context_t * mainloop )
143+ {
144+ uint64_t event_read = 0 ;
145+ assert (read (s_trel_event_fd , & event_read , sizeof (event_read )) == sizeof (event_read ));
146+ struct pbuf * recv_buf = NULL ;
147+ uint8_t * data_buf = NULL ;
148+ uint16_t length = 0 ;
149+ otSockAddr * source_addr = NULL ;
150+
151+ while (atomic_load (& s_recv_queue .used )) {
152+ if (s_trel_receive_buffer [s_recv_queue .head ].p != NULL ) {
153+
154+ uint8_t * data_buf_to_free = NULL ;
155+ bool should_handle = true;
156+ recv_buf = s_trel_receive_buffer [s_recv_queue .head ].p ;
157+ data_buf = (uint8_t * )recv_buf -> payload ;
158+ length = recv_buf -> len ;
159+ source_addr = s_trel_receive_buffer [s_recv_queue .head ].source_addr ;
160+
161+ if (recv_buf -> next != NULL ) {
162+ data_buf = (uint8_t * )malloc (recv_buf -> tot_len );
163+ if (data_buf ) {
164+ pbuf_copy_partial (recv_buf , data_buf , recv_buf -> tot_len , 0 );
165+ } else {
166+ should_handle = false;
167+ }
168+ length = recv_buf -> tot_len ;
169+ data_buf_to_free = data_buf ;
170+ }
171+ if (should_handle ) {
172+ otPlatTrelHandleReceived (aInstance , data_buf , length , source_addr );
173+ }
174+ pbuf_free (recv_buf );
175+ free (data_buf_to_free );
176+ free (source_addr );
177+
178+ s_recv_queue .head = (s_recv_queue .head + 1 ) % CONFIG_OPENTHREAD_TREL_BUFFER_SIZE ;
179+ atomic_fetch_sub (& s_recv_queue .used , 1 );
180+ }
181+ }
150182
151- task -> trel_pcb = udp_new ();
152- ESP_RETURN_ON_FALSE (task -> trel_pcb != NULL , ESP_ERR_NO_MEM , OT_PLAT_LOG_TAG , "Failed to create a new UDP pcb" );
153- udp_bind (task -> trel_pcb , IP6_ADDR_ANY , task -> port );
154- udp_recv (task -> trel_pcb , handle_trel_udp_recv , NULL );
155183 return ESP_OK ;
156184}
157185
158186void otPlatTrelEnable (otInstance * aInstance , uint16_t * aUdpPort )
159187{
188+ ESP_RETURN_ON_FALSE (s_trel_event_fd == -1 , , OT_PLAT_LOG_TAG , "ot trel has been initialized." );
189+ s_trel_event_fd = eventfd (0 , 0 );
190+ assert (s_trel_event_fd >= 0 );
160191 * aUdpPort = s_ot_trel .port ;
161192 esp_openthread_task_switching_lock_release ();
162- esp_err_t err = esp_netif_tcpip_exec (ot_new_trel , & s_ot_trel );
163- if (err != ESP_OK ) {
164- ESP_LOGE (OT_PLAT_LOG_TAG , "Fail to create trel udp" );
165- }
193+ ESP_ERROR_CHECK (esp_netif_tcpip_exec (ot_new_trel , NULL ));
166194 mdns_browse_new (TREL_MDNS_TYPE , TREL_MDNS_PROTO , trel_browse_notifier );
167195 esp_openthread_task_switching_lock_acquire (portMAX_DELAY );
196+ ESP_ERROR_CHECK (esp_openthread_platform_workflow_register (& esp_openthread_trel_update , & esp_openthread_trel_process , s_trel_workflow ));
168197}
169198
170199static esp_err_t trel_send_task (void * ctx )
@@ -263,23 +292,41 @@ void otPlatTrelResetCounters(otInstance *aInstance)
263292 memset (& s_trel_counters , 0 , sizeof (otPlatTrelCounters ));
264293}
265294
266- static void trel_disable_task (void * ctx )
295+ static esp_err_t trel_disable_task (void * ctx )
267296{
268- struct udp_pcb * pcb = (struct udp_pcb * )ctx ;
269- udp_remove (pcb );
297+ if (ctx ) {
298+ struct udp_pcb * pcb = (struct udp_pcb * )ctx ;
299+ udp_remove (pcb );
300+ }
301+ return ESP_OK ;
302+ }
303+
304+ static void free_all_buffer (void )
305+ {
306+ while (atomic_load (& s_recv_queue .used )) {
307+ if (s_trel_receive_buffer [s_recv_queue .head ].p != NULL ) {
308+ pbuf_free (s_trel_receive_buffer [s_recv_queue .head ].p );
309+ free (s_trel_receive_buffer [s_recv_queue .head ].source_addr );
310+ s_recv_queue .head = (s_recv_queue .head + 1 ) % CONFIG_OPENTHREAD_TREL_BUFFER_SIZE ;
311+ atomic_fetch_sub (& s_recv_queue .used , 1 );
312+ }
313+ }
270314}
271315
272316void otPlatTrelDisable (otInstance * aInstance )
273317{
318+ ESP_RETURN_ON_FALSE (s_trel_event_fd >= 0 , , OT_PLAT_LOG_TAG , "ot trel is not initialized." );
274319 esp_openthread_task_switching_lock_release ();
275- if (s_ot_trel .trel_pcb ) {
276- tcpip_callback (trel_disable_task , s_ot_trel .trel_pcb );
277- }
320+ esp_netif_tcpip_exec (trel_disable_task , s_ot_trel .trel_pcb );
321+ s_ot_trel .trel_pcb = NULL ;
278322 mdns_service_remove (TREL_MDNS_TYPE , TREL_MDNS_PROTO );
279323 s_is_service_registered = false;
280324 mdns_browse_delete (TREL_MDNS_TYPE , TREL_MDNS_PROTO );
281325 esp_openthread_task_switching_lock_acquire (portMAX_DELAY );
282- s_ot_trel .trel_pcb = NULL ;
326+ esp_openthread_platform_workflow_unregister (s_trel_workflow );
327+ free_all_buffer ();
328+ close (s_trel_event_fd );
329+ s_trel_event_fd = -1 ;
283330}
284331
285332const otPlatTrelCounters * otPlatTrelGetCounters (otInstance * aInstance )
0 commit comments