• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3  * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this list of
9  *    conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12  *    of conditions and the following disclaimer in the documentation and/or other materials
13  *    provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16  *    to endorse or promote products derived from this software without specific prior written
17  *    permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <lwip/sys.h>
33 #include <lwip/netif.h>
34 #include <lwip/snmp.h>
35 #include <lwip/etharp.h>
36 #include <lwip/sockets.h>
37 #include <lwip/ethip6.h>
38 
39 #define LWIP_NETIF_HOSTNAME_DEFAULT         "default"
40 #define LINK_SPEED_OF_YOUR_NETIF_IN_BPS     100000000 // 100Mbps
41 
42 #define link_rx_drop cachehit
43 #define link_rx_overrun cachehit
44 
45 #define LWIP_STATIC static
46 
47 #define NETIF_NAME_PREFIX_MAX_LENGTH 10
48 #define NETIF_NAME_PREFIX_ETH "eth"
49 #define NETIF_NAME_PREFIX_WIFI "wlan"
50 #define NETIF_NAME_PREFIX_BT "bt"
51 
52 #ifndef LWIP_NETIF_IFINDEX_MAX_EX
53 #define LWIP_NETIF_IFINDEX_MAX_EX 255
54 #endif
55 
driverif_get_ifname_prefix(struct netif * netif,char * prefix,int prefixLen)56 LWIP_STATIC void driverif_get_ifname_prefix(struct netif *netif, char *prefix, int prefixLen)
57 {
58     if (prefix == NULL || netif == NULL) {
59         LWIP_ASSERT("invalid param", 0);
60         return;
61     }
62     switch (netif->link_layer_type) {
63         case ETHERNET_DRIVER_IF:
64             strcpy_s(prefix, prefixLen, NETIF_NAME_PREFIX_ETH);
65             break;
66         case WIFI_DRIVER_IF:
67             strcpy_s(prefix, prefixLen, NETIF_NAME_PREFIX_WIFI);
68             break;
69         case BT_PROXY_IF:
70             strcpy_s(prefix, prefixLen, NETIF_NAME_PREFIX_BT);
71             break;
72         default:
73             LWIP_ASSERT("invalid link_layer_type", 0);
74             break;
75     }
76 }
77 
driverif_init_ifname(struct netif * netif)78 LWIP_STATIC void driverif_init_ifname(struct netif *netif)
79 {
80     struct netif *tmpnetif = NULL;
81     char prefix[NETIF_NAME_PREFIX_MAX_LENGTH] = {0};
82 
83     driverif_get_ifname_prefix(netif, prefix, NETIF_NAME_PREFIX_MAX_LENGTH);
84     netif->name[0] = prefix[0];
85     netif->name[1] = prefix[1];
86 
87     if (netif->full_name[0] != '\0') {
88         LWIP_DEBUGF(DRIVERIF_DEBUG, ("netif already has fullname %s\n", netif->full_name));
89         return;
90     }
91     for (int i = 0; i < LWIP_NETIF_IFINDEX_MAX_EX; ++i) {
92         if (snprintf_s(netif->full_name, sizeof(netif->full_name), sizeof(netif->full_name) - 1,
93             "%s%d", prefix, i) < 0) {
94             break;
95         }
96         NETIF_FOREACH(tmpnetif) {
97             if (strcmp(tmpnetif->full_name, netif->full_name) == 0) {
98                 break;
99             }
100         }
101         if (tmpnetif == NULL) {
102             LWIP_DEBUGF(DRIVERIF_DEBUG, ("set fullname success %s\n", netif->full_name));
103             return;
104         }
105     }
106     netif->full_name[0] = '\0';
107 }
108 
109 /*
110  * This function should do the actual transmission of the packet. The packet is
111  * contained in the pbuf that is passed to the function. This pbuf
112  * might be chained.
113  *
114  * @param netif the lwip network interface structure for this driverif
115  * @param p the MAC packet to send (e.g. IP packet including MAC_addresses and type)
116  * @return ERR_OK if the packet could be sent
117  *         an err_t value if the packet couldn't be sent
118  *
119  * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
120  *       strange results. You might consider waiting for space in the DMA queue
121  *       to become availale since the stack doesn't retry to send a packet
122  *       dropped because of memory failure (except for the TCP timers).
123  */
124 
driverif_output(struct netif * netif,struct pbuf * p)125 LWIP_STATIC err_t driverif_output(struct netif *netif, struct pbuf *p)
126 {
127     LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_output : send packet pbuf 0x%p of length %"U16_F" through netif 0x%p\n", \
128         (void *)p, p->tot_len, (void *)netif));
129 
130 #if PF_PKT_SUPPORT
131     if (all_pkt_raw_pcbs != NULL) {
132         p->flags = (u16_t)(p->flags & ~(PBUF_FLAG_LLMCAST | PBUF_FLAG_LLBCAST | PBUF_FLAG_HOST));
133         p->flags |= PBUF_FLAG_OUTGOING;
134         (void)raw_pkt_input(p, netif, NULL);
135     }
136 #endif
137 
138 #if ETH_PAD_SIZE
139     (void)pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
140 #endif
141 
142     netif->drv_send(netif, p);
143 
144 #if ETH_PAD_SIZE
145     (void)pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
146 #endif
147     MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len);
148     LINK_STATS_INC(link.xmit);
149 
150     return ERR_OK;
151 }
152 
driverif_input_proc(struct netif * netif,struct pbuf * p)153 void driverif_input_proc(struct netif *netif, struct pbuf *p)
154 {
155     u16_t ethhdr_type;
156     struct eth_hdr *ethhdr = NULL;
157     err_t ret = ERR_VAL;
158 
159     ethhdr = (struct eth_hdr *)p->payload;
160     ethhdr_type = ntohs(ethhdr->type);
161 
162     switch (ethhdr_type) {
163         /* IP or ARP packet? */
164         case ETHTYPE_IP:
165         case ETHTYPE_IPV6:
166         case ETHTYPE_ARP:
167 #if ETHARP_SUPPORT_VLAN
168         case ETHTYPE_VLAN:
169 #endif /* ETHARP_SUPPORT_VLAN */
170             LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_input : received packet of type %"U16_F"\n", ethhdr_type));
171             /* full packet send to tcpip_thread to process */
172             if (netif->input != NULL) {
173                 ret = netif->input(p, netif);
174             }
175 
176             if (ret != ERR_OK) {
177                 LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_input: IP input error\n"));
178                 (void)pbuf_free(p);
179                 LINK_STATS_INC(link.drop);
180                 LINK_STATS_INC(link.link_rx_drop);
181                 if (ret == ERR_MEM) {
182                     MIB2_STATS_NETIF_INC(netif, ifinoverruns);
183                     LINK_STATS_INC(link.link_rx_overrun);
184                 }
185             } else {
186                 LINK_STATS_INC(link.recv);
187             }
188             break;
189 
190         default:
191             LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_input : received packet is of unsupported type %"U16_F"\n", \
192                 ethhdr_type));
193             (void)pbuf_free(p);
194             LINK_STATS_INC(link.drop);
195             LINK_STATS_INC(link.link_rx_drop);
196             break;
197     }
198 }
199 
200 /*
201  * This function should be called by network driver to pass the input packet to LwIP.
202  * Before calling this API, driver has to keep the packet in pbuf structure. Driver has to
203  * call pbuf_alloc() with type as PBUF_RAM to create pbuf structure. Then driver
204  * has to pass the pbuf structure to this API. This will add the pbuf into the TCPIP thread.
205  * Once this packet is processed by TCPIP thread, pbuf will be freed. Driver is not required to
206  * free the pbuf.
207  *
208  * @param netif the lwip network interface structure for this driverif
209  * @param p packet in pbuf structure format
210  */
driverif_input(struct netif * netif,struct pbuf * p)211 void driverif_input(struct netif *netif, struct pbuf *p)
212 {
213 #if PF_PKT_SUPPORT
214 #if  (DRIVERIF_DEBUG & LWIP_DBG_OFF)
215     u16_t ethhdr_type;
216     struct eth_hdr* ethhdr = NULL;
217 #endif
218     err_t ret = ERR_VAL;
219 #endif
220 
221     LWIP_ERROR("driverif_input : invalid arguments", ((netif != NULL) && (p != NULL)), return);
222 
223     LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_input : going to receive input packet. netif 0x%p, pbuf 0x%p, \
224         packet_length %"U16_F"\n", (void *)netif, (void *)p, p->tot_len));
225 
226     /* points to packet payload, which starts with an Ethernet header */
227     MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len);
228     if (p->len < SIZEOF_ETH_HDR) {
229         (void)pbuf_free(p);
230         LINK_STATS_INC(link.drop);
231         LINK_STATS_INC(link.link_rx_drop);
232         return;
233     }
234 
235 #if PF_PKT_SUPPORT
236 #if  (DRIVERIF_DEBUG & LWIP_DBG_OFF)
237     ethhdr = (struct eth_hdr *)p->payload;
238     ethhdr_type = ntohs(ethhdr->type);
239     LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_input : received packet of type %"U16_F" netif->input=%p\n", \
240         ethhdr_type, netif->input));
241 #endif
242 
243     /* full packet send to tcpip_thread to process */
244     if (netif->input) {
245         ret = netif->input(p, netif);
246     }
247     if (ret != ERR_OK) {
248         LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_input: IP input error\n"));
249         (void)pbuf_free(p);
250         LINK_STATS_INC(link.drop);
251         LINK_STATS_INC(link.link_rx_drop);
252         if (ret == ERR_MEM) {
253             LINK_STATS_INC(link.link_rx_overrun);
254         }
255     } else {
256         LINK_STATS_INC(link.recv);
257     }
258 
259 #else
260     driverif_input_proc(netif, p);
261 #endif
262 
263     LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_input : received packet is processed\n"));
264 }
265 
266 /*
267  * Should be called at the beginning of the program to set up the
268  * network interface. It calls the function low_level_init() to do the
269  * actual setup of the hardware.
270  *
271  * This function should be passed as a parameter to netif_add().
272  *
273  * @param netif the lwip network interface structure for this driverif
274  * @return ERR_OK if the loopif is initialized
275  *         ERR_MEM on Allocation Failure
276  *         any other err_t on error
277  */
driverif_init(struct netif * netif)278 err_t driverif_init(struct netif *netif)
279 {
280     u16_t link_layer_type;
281 
282     if (netif == NULL) {
283         return ERR_IF;
284     }
285     link_layer_type = netif->link_layer_type;
286     LWIP_ERROR("driverif_init : invalid link_layer_type in netif", \
287         ((link_layer_type == ETHERNET_DRIVER_IF) \
288         || (link_layer_type == WIFI_DRIVER_IF \
289         || link_layer_type == BT_PROXY_IF)), \
290             return ERR_IF);
291 
292     LWIP_ERROR("driverif_init : netif hardware length is greater than maximum supported", \
293     (netif->hwaddr_len <= NETIF_MAX_HWADDR_LEN), return ERR_IF);
294 
295     LWIP_ERROR("driverif_init : drv_send is null", (netif->drv_send != NULL), return ERR_IF);
296 
297 #if LWIP_NETIF_PROMISC
298     LWIP_ERROR("driverif_init : drv_config is null", (netif->drv_config != NULL), return ERR_IF);
299 #endif
300 
301 #if LWIP_NETIF_HOSTNAME
302     /* Initialize interface hostname */
303     netif->hostname = LWIP_NETIF_HOSTNAME_DEFAULT;
304 #endif /* LWIP_NETIF_HOSTNAME */
305 
306     /*
307      * Initialize the snmp variables and counters inside the struct netif.
308      * The last argument should be replaced with your link speed, in units
309      * of bits per second.
310      */
311     NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS);
312 
313     netif->output = etharp_output;
314     netif->linkoutput = driverif_output;
315 
316     /* init the netif's full name */
317     driverif_init_ifname(netif);
318 
319     /* maximum transfer unit */
320     netif->mtu = IP_FRAG_MAX_MTU;
321 
322     /* device capabilities */
323     /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
324     netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP |
325 #if DRIVER_STATUS_CHECK
326         NETIF_FLAG_DRIVER_RDY |
327 #endif
328 #if LWIP_IGMP
329         NETIF_FLAG_IGMP |
330 #endif
331 
332         /**
333         @page RFC-2710 RFC-2710
334         @par Compliant Sections
335         Section 5. Node State Transition Diagram
336         @par Behavior Description
337         MLD messages are sent for multicast addresses whose scope is 2
338         (link-local), including Solicited-Node multicast addresses.\n
339         Behavior:Stack will send MLD6 report /Done to solicited node multicast address
340         if the LWIP_MLD6_ENABLE_MLD_ON_DAD is enabled. By default, this is disabled.
341         */
342         /* Enable sending MLD report /done for solicited address during neighbour discovery */
343 #if LWIP_IPV6 && LWIP_IPV6_MLD
344 #if LWIP_MLD6_ENABLE_MLD_ON_DAD
345         NETIF_FLAG_MLD6 |
346 #endif /* LWIP_MLD6_ENABLE_MLD_ON_DAD */
347 #endif
348         NETIF_FLAG_LINK_UP;
349 
350 #if DRIVER_STATUS_CHECK
351     netif->waketime = -1;
352 #endif /* DRIVER_STATUS_CHECK */
353     LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_init : Initialized netif 0x%p\n", (void *)netif));
354     return ERR_OK;
355 }
356