• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Chipsea Technologies (Shenzhen) Corp., Ltd. All rights reserved.
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  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "porting_net_def.h"
16 #include "lwip/tcpip.h"
17 #include "lwip/etharp.h"
18 #include "lwip/netifapi.h"
19 #include "lwip/sockets.h"
20 #include "lwip/netbuf.h"
21 #include "lwip/api.h"
22 #include "lwip/dns.h"
23 #include "netif/ethernet.h"
24 #include "wifi_host_tx.h"
25 #include "dbg_assert.h"
26 #include "lwiphooks.h"
27 #include "lwip/priv/sockets_priv.h"
28 
29 #define NX_NB_L2_FILTER 2
30 
31 struct l2_filter_tag
32 {
33     struct netif *net_if;
34     int sock;
35     struct netconn *conn;
36     uint16_t ethertype;
37 };
38 
39 static struct l2_filter_tag l2_filter[NX_NB_L2_FILTER];
40 static rtos_semaphore l2_semaphore;
41 static rtos_mutex     l2_mutex;
42 
43 /*
44  * FUNCTIONS
45  ****************************************************************************************
46  */
47 /// Fake function used to detected too small link encapsulation header length
48 void p_buf_link_encapsulation_hlen_too_small(void);
49 
50 /// Declaration of the LwIP checksum computation function
51 u16_t lwip_standard_chksum(const void *dataptr, int len);
52 
update_etharp_table(struct netif * netif,const ip4_addr_t * ipaddr)53 void update_etharp_table(struct netif *netif, const ip4_addr_t *ipaddr)
54 {
55 
56 }
57 /**
58  ****************************************************************************************
59  * @brief Callback used by the networking stack to push a buffer for transmission by the
60  * WiFi interface.
61  *
62  * @param[in] net_if Pointer to the network interface on which the TX is done
63  * @param[in] p_buf  Pointer to the buffer to transmit
64  *
65  * @return ERR_OK upon successful pushing of the buffer, ERR_BUF otherwise
66  ****************************************************************************************
67  */
net_if_output(struct netif * net_if,struct pbuf * p_buf)68 static err_t net_if_output(struct netif *net_if, struct pbuf *p_buf)
69 {
70     err_t status = ERR_BUF;
71 
72     // Increase the ref count so that the buffer is not freed by the networking stack
73     // until it is actually sent over the WiFi interface
74     pbuf_ref(p_buf);
75 
76     // Push the buffer and verify the status
77     if (netif_is_up(net_if) && fhost_tx_start(net_if->state, p_buf, NULL, NULL) == 0)
78     {
79         status = ERR_OK;
80     }
81     else
82     {
83         // Failed to push message to TX task, call pbuf_free only to decrease ref count
84         pbuf_free(p_buf);
85     }
86 
87     return (status);
88 }
89 
90 /**
91  ****************************************************************************************
92  * @brief Callback used by the networking stack to setup the network interface.
93  * This function should be passed as a parameter to netifapi_netif_add().
94  *
95  * @param[in] net_if Pointer to the network interface to setup
96  * @param[in] p_buf  Pointer to the buffer to transmit
97  *
98  * @return ERR_OK upon successful setup of the interface, other status otherwise
99  ****************************************************************************************
100  */
101 
net_if_init(struct netif * net_if)102 static err_t net_if_init(struct netif *net_if)
103 {
104     err_t status = ERR_OK;
105     static uint8_t net_num = 1;
106     struct fhost_vif_tag *vif = (struct fhost_vif_tag *)net_if->state;
107 
108     #if LWIP_NETIF_HOSTNAME
109     {
110         /* Initialize interface hostname */
111         net_if->hostname = "CsWlan";
112     }
113     #endif /* LWIP_NETIF_HOSTNAME */
114 
115     net_if->name[ 0 ] = 'w';
116     net_if->name[ 1 ] = 'l';
117     net_if->full_name[0] = 'w';
118     net_if->full_name[1] = 'l';
119     net_if->full_name[2] = '0' + net_num++;
120     net_if->full_name[3] = '\0';
121 
122     net_if->output = etharp_output;
123     net_if->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_IGMP;
124     net_if->hwaddr_len = ETHARP_HWADDR_LEN;
125     net_if->mtu = LLC_ETHER_MTU;
126     net_if->linkoutput = net_if_output;
127     memcpy(net_if->hwaddr, &vif->mac_addr, ETHARP_HWADDR_LEN);
128 
129     return status;
130 }
131 
net_ip_chksum(const void * dataptr,int len)132 uint16_t net_ip_chksum(const void *dataptr, int len)
133 {
134     // Simply call the LwIP function
135     return lwip_standard_chksum(dataptr, len);
136 }
137 
net_if_add(net_if_t * net_if,const uint32_t * ipaddr,const uint32_t * netmask,const uint32_t * gw,struct fhost_vif_tag * vif)138 int net_if_add(net_if_t *net_if,
139                const uint32_t *ipaddr,
140                const uint32_t *netmask,
141                const uint32_t *gw,
142                struct fhost_vif_tag *vif)
143 {
144     err_t status;
145 
146     status = netifapi_netif_add(net_if,
147                                (const ip4_addr_t *)ipaddr,
148                                (const ip4_addr_t *)netmask,
149                                (const ip4_addr_t *)gw,
150                                vif,
151                                net_if_init,
152                                tcpip_input);
153 
154     return (status == ERR_OK ? 0 : -1);
155 }
156 
net_if_get_mac_addr(net_if_t * net_if)157 const uint8_t *net_if_get_mac_addr(net_if_t *net_if)
158 {
159     return net_if->hwaddr;
160 }
161 
net_if_find_from_name(const char * name)162 net_if_t *net_if_find_from_name(const char *name)
163 {
164     return netif_find(name);
165 }
166 
net_if_find_from_wifi_idx(unsigned int idx)167 net_if_t *net_if_find_from_wifi_idx(unsigned int idx)
168 {
169     if ((idx >= NX_VIRT_DEV_MAX) || (fhost_env.vif[idx].mac_vif == NULL))
170         return NULL;
171 
172 
173     if (fhost_env.vif[idx].mac_vif->type != VIF_UNKNOWN)
174     {
175         return &fhost_env.vif[idx].net_if;
176     }
177 
178     return NULL;
179 }
180 
net_if_get_name(net_if_t * net_if,char * buf,int len)181 int net_if_get_name(net_if_t *net_if, char *buf, int len)
182 {
183     if (len > 0)
184         buf[0] = net_if->name[0];
185     if (len > 1)
186         buf[1] = net_if->name[1];
187     if (len > 2)
188         buf[2] = net_if->num + '0';
189     if ( len > 3)
190         buf[3] = '\0';
191 
192     return 3;
193 }
194 
net_if_get_wifi_idx(net_if_t * net_if)195 int net_if_get_wifi_idx(net_if_t *net_if)
196 {
197     struct fhost_vif_tag *vif;
198     int idx;
199 
200     if (!net_if)
201         return -1;
202 
203     vif = (struct fhost_vif_tag *)net_if;
204     idx = CO_GET_INDEX(vif, fhost_env.vif);
205 
206     /* sanity check */
207     if (&fhost_env.vif[idx].net_if == net_if)
208         return idx;
209 
210     return -1;
211 }
212 
net_if_up(net_if_t * net_if)213 void net_if_up(net_if_t *net_if)
214 {
215     netifapi_netif_set_up(net_if);
216 }
217 
net_if_down(net_if_t * net_if)218 void net_if_down(net_if_t *net_if)
219 {
220     netifapi_netif_set_down(net_if);
221 }
222 
net_if_set_default(net_if_t * net_if)223 void net_if_set_default(net_if_t *net_if)
224 {
225     netifapi_netif_set_default(net_if);
226 }
227 
net_if_set_ip(net_if_t * net_if,uint32_t ip,uint32_t mask,uint32_t gw)228 void net_if_set_ip(net_if_t *net_if, uint32_t ip, uint32_t mask, uint32_t gw)
229 {
230     if (!net_if)
231         return;
232     netif_set_addr(net_if, (const ip4_addr_t *)&ip, (const ip4_addr_t *)&mask,
233                    (const ip4_addr_t *)&gw);
234 }
235 
net_if_get_ip(net_if_t * net_if,uint32_t * ip,uint32_t * mask,uint32_t * gw)236 int net_if_get_ip(net_if_t *net_if, uint32_t *ip, uint32_t *mask, uint32_t *gw)
237 {
238     if (!net_if)
239         return -1;
240 
241     if (ip)
242         *ip = netif_ip4_addr(net_if)->addr;
243     if (mask)
244         *mask = netif_ip4_netmask(net_if)->addr;
245     if (gw)
246         *gw = netif_ip4_gw(net_if)->addr;
247 
248     return 0;
249 }
250 
net_if_input(net_buf_rx_t * buf,net_if_t * net_if,void * addr,uint16_t len,net_buf_free_fn free_fn)251 int net_if_input(net_buf_rx_t *buf, net_if_t *net_if, void *addr, uint16_t len, net_buf_free_fn free_fn)
252 {
253     struct pbuf* p;
254 
255     buf->custom_free_function = (pbuf_free_custom_fn)free_fn;
256     p = pbuf_alloced_custom(PBUF_RAW, len, PBUF_REF, buf, addr, len);
257     ASSERT_ERR(p != NULL);
258 
259     if (net_if->input(p, net_if))
260     {
261         free_fn(buf);
262         return -1;
263     }
264 
265     return 0;
266 }
267 
net_if_vif_info(net_if_t * net_if)268 struct fhost_vif_tag *net_if_vif_info(net_if_t *net_if)
269 {
270     return ((struct fhost_vif_tag *)net_if->state);
271 }
272 
net_buf_tx_alloc(const uint8_t * payload,uint32_t length)273 net_buf_tx_t *net_buf_tx_alloc(const uint8_t *payload, uint32_t length)
274 {
275     struct pbuf *pbuf;
276 
277     pbuf = pbuf_alloc(PBUF_RAW_TX, length, PBUF_RAM);
278     if (pbuf == NULL)
279         return NULL;
280 
281     memcpy(pbuf->payload, payload, length);
282     return pbuf;
283 }
284 
net_buf_tx_info(net_buf_tx_t * buf,uint16_t * tot_len,uint8_t * seg_cnt)285 void net_buf_tx_info(net_buf_tx_t *buf, uint16_t *tot_len, uint8_t *seg_cnt)
286 {
287     uint8_t  idx;
288     uint16_t length = buf->tot_len;
289 
290     *tot_len = length;
291 
292     idx = 0;
293     while (length && buf)
294     {
295         // Sanity check - the payload shall be in shared RAM
296         //ASSERT_ERR(!TST_SHRAM_PTR(buf->payload));
297 
298         length -= buf->len;
299         idx++;
300         // Get info of extra segments if any
301         buf = buf->next;
302     }
303 
304     *seg_cnt = idx;
305     if (length != 0)
306     {
307         // The complete buffer must be included in all the segments
308         ASSERT_ERR(0);
309     }
310 }
311 
net_buf_tx_free(net_buf_tx_t * buf)312 void net_buf_tx_free(net_buf_tx_t *buf)
313 {
314     // Free the buffer
315     pbuf_free(buf);
316 }
317 
net_init(void)318 int net_init(void)
319 {
320     int i;
321 
322     for (i = 0; i < NX_NB_L2_FILTER; i++)
323     {
324         l2_filter[i].net_if = NULL;
325     }
326 
327     if (rtos_semaphore_create(&l2_semaphore, 1, 0))
328     {
329         ASSERT_ERR(0);
330     }
331 
332     if (rtos_mutex_create(&l2_mutex))
333     {
334         ASSERT_ERR(0);
335     }
336 
337     // Initialize the TCP/IP stack
338     tcpip_init(NULL, NULL);
339 
340 #ifdef DSOFTBUS_ENABLED
341     ipc_host_cntrl_start();
342 #endif
343 
344     return 0;
345 }
346 
net_l2_send_cfm(uint32_t frame_id,bool acknowledged,void * arg)347 static void net_l2_send_cfm(uint32_t frame_id, bool acknowledged, void *arg)
348 {
349     if (arg)
350         *((bool *)arg) = acknowledged;
351     rtos_semaphore_signal(l2_semaphore, false);
352 }
353 
net_l2_send(net_if_t * net_if,const uint8_t * data,int data_len,uint16_t ethertype,const uint8_t * dst_addr,bool * ack)354 int net_l2_send(net_if_t *net_if, const uint8_t *data, int data_len, uint16_t ethertype,
355                 const uint8_t *dst_addr, bool *ack)
356 {
357     struct pbuf *pbuf;
358     int res;
359 
360     if (net_if == NULL || data == NULL || data_len >= net_if->mtu || !netif_is_up(net_if))
361         return -1;
362 
363     pbuf = pbuf_alloc(PBUF_LINK, data_len, PBUF_RAM);
364     if (pbuf == NULL)
365         return -1;
366 
367     memcpy(pbuf->payload, data, data_len);
368 
369     if (dst_addr)
370     {
371         // Need to add ethernet header as fhost_tx_start is called directly
372         struct eth_hdr* ethhdr;
373         if (pbuf_header(pbuf, SIZEOF_ETH_HDR))
374         {
375             pbuf_free(pbuf);
376             return -1;
377         }
378         ethhdr = (struct eth_hdr*)pbuf->payload;
379         ethhdr->type = htons(ethertype);
380         memcpy(&ethhdr->dest, dst_addr, sizeof(struct eth_addr));
381         memcpy(&ethhdr->src, net_if->hwaddr, sizeof(struct eth_addr));
382     }
383 
384     // Ensure no other thread will program a L2 transmission while this one is waiting
385     // for its confirmation
386     rtos_mutex_lock(l2_mutex, -1);
387 
388     // In order to implement this function as blocking until the completion of the frame
389     // transmission, directly call fhost_tx_start with a confirmation callback.
390     res = fhost_tx_start(net_if->state, pbuf, net_l2_send_cfm, ack);
391 
392     // Wait for the transmission completion
393     rtos_semaphore_wait(l2_semaphore, -1);
394 
395     // Now new L2 transmissions are possible
396     rtos_mutex_unlock(l2_mutex);
397 
398     return res;
399 }
400 
net_l2_socket_create(net_if_t * net_if,uint16_t ethertype)401 int net_l2_socket_create(net_if_t *net_if, uint16_t ethertype)
402 {
403     struct l2_filter_tag *filter = NULL;
404     socklen_t len = sizeof(filter->conn);
405     int i;
406 
407     /* First find free filter and check that socket for this ethertype/net_if couple
408        doesn't already exists */
409     for (i = 0; i < NX_NB_L2_FILTER; i++)
410     {
411         if ((l2_filter[i].net_if == net_if) &&
412             (l2_filter[i].ethertype == ethertype))
413         {
414             return -1;
415         }
416         else if ((filter == NULL) && (l2_filter[i].net_if == NULL))
417         {
418             filter = &l2_filter[i];
419         }
420     }
421 
422     if (!filter)
423         return -1;
424 
425     /* Note: we create DGRAM socket here but in practice we don't care, net_eth_receive
426        will use the socket as a L2 raw socket */
427     filter->sock = socket(PF_INET, SOCK_DGRAM, 0);
428     if (filter->sock < 0) {
429         return -1;
430     }
431 
432 
433     if (getsockopt(filter->sock, SOL_SOCKET, SO_CONNINFO, &(filter->conn), &len))
434     {
435         close(filter->sock);
436         return -1;
437     }
438 
439     filter->net_if = net_if;
440     filter->ethertype = ethertype;
441 
442     return filter->sock;
443 }
444 
net_l2_socket_delete(int sock)445 int net_l2_socket_delete(int sock)
446 {
447     int i;
448     for (i = 0; i < NX_NB_L2_FILTER; i++)
449     {
450         if ((l2_filter[i].net_if != NULL) &&
451             (l2_filter[i].sock == sock))
452         {
453             l2_filter[i].net_if = NULL;
454             close(l2_filter[i].sock);
455             l2_filter[i].sock = -1;
456             return 0;
457         }
458     }
459 
460     return -1;
461 }
462 
net_eth_receive(struct pbuf * pbuf,struct netif * netif)463 err_t net_eth_receive(struct pbuf *pbuf, struct netif *netif)
464 {
465     struct l2_filter_tag *filter = NULL;
466     struct eth_hdr* ethhdr = pbuf->payload;
467     uint16_t ethertype = ntohs(ethhdr->type);
468     struct netconn *conn;
469     struct netbuf *buf;
470     int i;
471 
472     for (i = 0; i < NX_NB_L2_FILTER; i++)
473     {
474         if ((l2_filter[i].net_if == netif) &&
475             (l2_filter[i].ethertype == ethertype))
476         {
477             filter = &l2_filter[i];
478             break;
479         }
480     }
481 
482     if (!filter)
483         return ERR_VAL;
484 
485 
486     buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
487     if (buf == NULL)
488     {
489         return ERR_MEM;
490     }
491 
492     buf->p = pbuf;
493     buf->ptr = pbuf;
494     conn = filter->conn;
495 
496     int ret = sys_mbox_trypost(&conn->recvmbox, buf);
497     if (ret != ERR_OK)
498     {
499         netbuf_delete(buf);
500         return ERR_OK;
501     }
502     else
503     {
504         #if LWIP_SO_RCVBUF
505         SYS_ARCH_INC(conn->recv_avail, pbuf->tot_len);
506         #endif /* LWIP_SO_RCVBUF */
507         /* Register event with callback */
508         API_EVENT(conn, NETCONN_EVT_RCVPLUS, pbuf->tot_len);
509     }
510 
511     return ERR_OK;
512 }
513 
514 static int net_dhcp_started = 0;
net_dhcp_start(net_if_t * net_if)515 int net_dhcp_start(net_if_t *net_if)
516 {
517     #if LWIP_IPV4 && LWIP_DHCP
518     if (netifapi_dhcp_start(net_if) ==  ERR_OK) {
519         net_dhcp_started = 1;
520         return 0;
521     }
522     #endif //LWIP_IPV4 && LWIP_DHCP
523     return -1;
524 }
525 
net_dhcp_stop(net_if_t * net_if)526 void net_dhcp_stop(net_if_t *net_if)
527 {
528     #if LWIP_IPV4 && LWIP_DHCP
529     netifapi_dhcp_stop(net_if);
530     net_dhcp_started = 0;
531     #endif //LWIP_IPV4 && LWIP_DHCP
532 }
533 
net_dhcp_start_status(void)534 int net_dhcp_start_status(void)
535 {
536     return net_dhcp_started;
537 }
538 
net_dhcp_release(net_if_t * net_if)539 int net_dhcp_release(net_if_t *net_if)
540 {
541     #if LWIP_IPV4 && LWIP_DHCP
542     if (netifapi_dhcp_release(net_if) ==  ERR_OK)
543         return 0;
544     #endif //LWIP_IPV4 && LWIP_DHCP
545     return -1;
546 }
547 
net_dhcp_address_obtained(net_if_t * net_if)548 int net_dhcp_address_obtained(net_if_t *net_if)
549 {
550     #if LWIP_IPV4 && LWIP_DHCP
551     if (dhcp_supplied_address(net_if))
552         return 0;
553     #endif //LWIP_IPV4 && LWIP_DHCP
554     return -1;
555 }
556 
net_set_dns(uint32_t dns_server)557 int net_set_dns(uint32_t dns_server)
558 {
559     #if LWIP_DNS
560     ip_addr_t ip;
561     ip_addr_set_ip4_u32(&ip, dns_server);
562     dns_setserver(0, &ip);
563     return 0;
564     #else
565     return -1;
566     #endif
567 }
568 
net_get_dns(uint32_t * dns_server)569 int net_get_dns(uint32_t *dns_server)
570 {
571     #if LWIP_DNS
572     const ip_addr_t *ip;
573 
574     if (dns_server == NULL)
575         return -1;
576 
577     ip = dns_getserver(0);
578     *dns_server = ip_addr_get_ip4_u32(ip);
579     return 0;
580     #else
581     return -1;
582     #endif
583 }
584 
lwip_sockopt_hook(int s,struct lwip_sock * sock,int level,int optname,void * optval,uint32_t * optlen,int * err)585 int lwip_sockopt_hook(int s, struct lwip_sock *sock, int level, int optname, void *optval, uint32_t *optlen, int *err)
586 {
587     if (level == SOL_SOCKET && optname == SO_CONNINFO) {
588         if ((sock->conn == NULL) || (*optlen < sizeof(void *))) {
589             return EINVAL;
590         }
591         *(void **)optval = sock->conn;
592     }
593     *err = 0;
594 }
595 
596