1 // Copyright 2021 Espressif Systems (Shanghai) CO LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License
13
14 #include <string.h>
15
16 #include "esp_netif.h"
17 #include "esp_netif_net_stack.h"
18 #include "lwip/netif.h"
19 #include "lwip/pbuf.h"
20 #include "netif/openthreadif.h"
21 #include "openthread/error.h"
22 #include "openthread/ip6.h"
23 #include "openthread/link.h"
24 #include "openthread/message.h"
25
26 #define OPENTHREAD_IP6_MTU 1280
27
openthread_output_ip6(struct netif * netif,struct pbuf * p,const struct ip6_addr * peer_addr)28 static err_t openthread_output_ip6(struct netif *netif, struct pbuf *p, const struct ip6_addr *peer_addr)
29 {
30 struct pbuf *q = p;
31 esp_netif_t *esp_netif = esp_netif_get_handle_from_netif_impl(netif);
32 esp_err_t ret = ESP_FAIL;
33 if (!esp_netif) {
34 LWIP_DEBUGF(NETIF_DEBUG, ("corresponding esp-netif is NULL: netif=%p pbuf=%p len=%d\n", netif, p, p->len));
35 return ERR_IF;
36 }
37
38 if (q->next == NULL) {
39 ret = esp_netif_transmit(esp_netif, q->payload, q->len);
40 } else {
41 LWIP_DEBUGF(PBUF_DEBUG, ("low_level_output: pbuf is a list, application may has bug"));
42 q = pbuf_alloc(PBUF_RAW_TX, p->tot_len, PBUF_RAM);
43 if (q != NULL) {
44 #if ESP_LWIP
45 /* This pbuf RAM was not allocated on layer2, no extra free operation needed in pbuf_free */
46 q->l2_owner = NULL;
47 q->l2_buf = NULL;
48 #endif
49 pbuf_copy(q, p);
50 } else {
51 return ERR_MEM;
52 }
53 ret = esp_netif_transmit(esp_netif, q->payload, q->len);
54 /* content in payload has been copied to OpenThread queue, it's safe to free pbuf now */
55 pbuf_free(q);
56 }
57 /* Check error */
58 if (unlikely(ret != ESP_OK)) {
59 return ERR_ABRT;
60 } else {
61 return ERR_OK;
62 }
63 }
64
openthread_netif_input(void * h,void * buffer,size_t len,void * eb)65 void openthread_netif_input(void *h, void *buffer, size_t len, void *eb)
66 {
67 struct netif *netif = h;
68 struct pbuf *p;
69 otMessage *message = (otMessage *)buffer;
70
71 if (unlikely(buffer == NULL || !netif_is_up(netif))) {
72 return;
73 }
74
75 /* Allocate LINK buffer in case it's forwarded to WiFi/ETH */
76 p = pbuf_alloc(PBUF_LINK, len, PBUF_POOL);
77 if (p == NULL) {
78 LWIP_DEBUGF(NETIF_DEBUG, ("Failed to allocate input pbuf for OpenThread netif\n"));
79 return;
80 }
81
82 if (unlikely(otMessageRead(message, 0, p->payload, len) != OT_ERROR_NONE)) {
83 LWIP_DEBUGF(NETIF_DEBUG, ("Failed to read OpenThread message\n"));
84 }
85
86 #if ESP_LWIP
87 p->l2_owner = NULL;
88 p->l2_buf = NULL;
89 #endif
90 /* full packet send to tcpip_thread to process */
91 if (unlikely(netif->input(p, netif) != ERR_OK)) {
92 LWIP_DEBUGF(NETIF_DEBUG, ("openthread_netif_input: IP input error\n"));
93 pbuf_free(p);
94 }
95 /* the pbuf will be free in upper layer, eg: tcpip_input */
96 }
97
openthread_netif_init(struct netif * netif)98 err_t openthread_netif_init(struct netif *netif)
99 {
100 netif->name[0] = 'o';
101 netif->name[1] = 't';
102 netif->hwaddr_len = sizeof(otExtAddress);
103 memset(netif->hwaddr, 0, sizeof(netif->hwaddr));
104 netif->mtu = OPENTHREAD_IP6_MTU;
105 netif->flags = NETIF_FLAG_BROADCAST;
106 netif->output = NULL;
107 netif->output_ip6 = openthread_output_ip6;
108 netif->l2_buffer_free_notify = NULL;
109 netif_set_link_up(netif);
110
111 return ERR_OK;
112 }
113