• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3  * Copyright (c) 2020-2022 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 #ifndef LWIP_NETIF_IFINDEX_MAX_EX
48 #define LWIP_NETIF_IFINDEX_MAX_EX 255
49 #endif
50 
51 LWIP_STATIC void
driverif_init_ifname(struct netif * netif)52 driverif_init_ifname(struct netif *netif)
53 {
54     struct netif *tmpnetif = NULL;
55     const char *prefix = (netif->link_layer_type == WIFI_DRIVER_IF) ? "wlan" : "eth";
56 
57     netif->name[0] = prefix[0];
58     netif->name[1] = prefix[1];
59 
60     for (int i = 0; i < LWIP_NETIF_IFINDEX_MAX_EX; ++i) {
61         if (snprintf_s(netif->full_name, sizeof(netif->full_name), sizeof(netif->full_name) - 1,
62                        "%s%d", prefix, i) < 0) {
63             break;
64         }
65         NETIF_FOREACH(tmpnetif) {
66             if (strcmp(tmpnetif->full_name, netif->full_name) == 0) {
67                 break;
68             }
69         }
70         if (tmpnetif == NULL) {
71             return;
72         }
73     }
74     netif->full_name[0] = '\0';
75 }
76 
77 /*
78  * This function should do the actual transmission of the packet. The packet is
79  * contained in the pbuf that is passed to the function. This pbuf
80  * might be chained.
81  *
82  * @param netif the lwip network interface structure for this driverif
83  * @param p the MAC packet to send (e.g. IP packet including MAC_addresses and type)
84  * @return ERR_OK if the packet could be sent
85  *         an err_t value if the packet couldn't be sent
86  *
87  * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
88  *       strange results. You might consider waiting for space in the DMA queue
89  *       to become available since the stack doesn't retry to send a packet
90  *       dropped because of memory failure (except for the TCP timers).
91  */
92 
93 LWIP_STATIC err_t
driverif_output(struct netif * netif,struct pbuf * p)94 driverif_output(struct netif *netif, struct pbuf *p)
95 {
96     LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_output : going to send packet pbuf 0x%p of length %"U16_F" through netif 0x%p\n", \
97     (void *)p, p->tot_len, (void *)netif));
98 
99 #if PF_PKT_SUPPORT
100     if (all_pkt_raw_pcbs != NULL) {
101         p->flags = (u16_t)(p->flags & ~(PBUF_FLAG_LLMCAST | PBUF_FLAG_LLBCAST | PBUF_FLAG_HOST));
102         p->flags |= PBUF_FLAG_OUTGOING;
103         (void)raw_pkt_input(p, netif, NULL);
104     }
105 #endif
106 
107 #if ETH_PAD_SIZE
108     (void)pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
109 #endif
110 
111     netif->drv_send(netif, p);
112 
113 #if ETH_PAD_SIZE
114     (void)pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
115 #endif
116     MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len);
117     LINK_STATS_INC(link.xmit);
118 
119     return ERR_OK;
120 }
121 
122 /*
123  * This function should be called by network driver to pass the input packet to LwIP.
124  * Before calling this API, driver has to keep the packet in pbuf structure. Driver has to
125  * call pbuf_alloc() with type as PBUF_RAM to create pbuf structure. Then driver
126  * has to pass the pbuf structure to this API. This will add the pbuf into the TCPIP thread.
127  * Once this packet is processed by TCPIP thread, pbuf will be freed. Driver is not required to
128  * free the pbuf.
129  *
130  * @param netif the lwip network interface structure for this driverif
131  * @param p packet in pbuf structure format
132  */
133 void
driverif_input(struct netif * netif,struct pbuf * p)134 driverif_input(struct netif *netif, struct pbuf *p)
135 {
136 #if PF_PKT_SUPPORT
137 #if  (DRIVERIF_DEBUG & LWIP_DBG_OFF)
138     u16_t ethhdr_type;
139     struct eth_hdr* ethhdr = NULL;
140 #endif
141 #else
142     u16_t ethhdr_type;
143     struct eth_hdr *ethhdr = NULL;
144 #endif
145     err_t ret = ERR_VAL;
146 
147     LWIP_ERROR("driverif_input : invalid arguments", ((netif != NULL) && (p != NULL)), return);
148 
149     LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_input : going to receive input packet. netif 0x%p, pbuf 0x%p, \
150                                packet_length %"U16_F"\n", (void *)netif, (void *)p, p->tot_len));
151 
152     /* points to packet payload, which starts with an Ethernet header */
153     MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len);
154     if (p->len < SIZEOF_ETH_HDR) {
155         (void)pbuf_free(p);
156         LINK_STATS_INC(link.drop);
157         LINK_STATS_INC(link.link_rx_drop);
158         return;
159     }
160 
161 #if PF_PKT_SUPPORT
162 #if  (DRIVERIF_DEBUG & LWIP_DBG_OFF)
163     ethhdr = (struct eth_hdr *)p->payload;
164     ethhdr_type = ntohs(ethhdr->type);
165     LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_input : received packet of type %"U16_F" netif->input=%p\n", ethhdr_type, netif->input));
166 #endif
167 
168     /* full packet send to tcpip_thread to process */
169     if (netif->input) {
170         ret = netif->input(p, netif);
171     }
172     if (ret != ERR_OK) {
173         LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_input: IP input error\n"));
174         (void)pbuf_free(p);
175         LINK_STATS_INC(link.drop);
176         LINK_STATS_INC(link.link_rx_drop);
177         if (ret == ERR_MEM) {
178             LINK_STATS_INC(link.link_rx_overrun);
179         }
180     } else {
181         LINK_STATS_INC(link.recv);
182     }
183 
184 #else
185     ethhdr = (struct eth_hdr *)p->payload;
186     ethhdr_type = ntohs(ethhdr->type);
187 
188     switch (ethhdr_type) {
189         /* IP or ARP packet? */
190         case ETHTYPE_IP:
191         case ETHTYPE_IPV6:
192         case ETHTYPE_ARP:
193 #if ETHARP_SUPPORT_VLAN
194         case ETHTYPE_VLAN:
195 #endif /* ETHARP_SUPPORT_VLAN */
196             LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_input : received packet of type %"U16_F"\n", ethhdr_type));
197             /* full packet send to tcpip_thread to process */
198             if (netif->input != NULL) {
199                 ret = netif->input(p, netif);
200             }
201 
202             if (ret != ERR_OK) {
203                 LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_input: IP input error\n"));
204                 (void)pbuf_free(p);
205                 LINK_STATS_INC(link.drop);
206                 LINK_STATS_INC(link.link_rx_drop);
207                 if (ret == ERR_MEM) {
208                     MIB2_STATS_NETIF_INC(netif, ifinoverruns);
209                     LINK_STATS_INC(link.link_rx_overrun);
210                 }
211             } else {
212                 LINK_STATS_INC(link.recv);
213             }
214             break;
215 
216         default:
217             LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_input : received packet is of unsupported type %"U16_F"\n", ethhdr_type));
218             (void)pbuf_free(p);
219             LINK_STATS_INC(link.drop);
220             LINK_STATS_INC(link.link_rx_drop);
221             break;
222     }
223 #endif
224 
225     LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_input : received packet is processed\n"));
226 }
227 
228 /*
229  * Should be called at the beginning of the program to set up the
230  * network interface. It calls the function low_level_init() to do the
231  * actual setup of the hardware.
232  *
233  * This function should be passed as a parameter to netif_add().
234  *
235  * @param netif the lwip network interface structure for this driverif
236  * @return ERR_OK if the loopif is initialized
237  *         ERR_MEM on Allocation Failure
238  *         any other err_t on error
239  */
240 err_t
driverif_init(struct netif * netif)241 driverif_init(struct netif *netif)
242 {
243     u16_t link_layer_type;
244 
245     if (netif == NULL) {
246         return ERR_IF;
247     }
248     link_layer_type = netif->link_layer_type;
249     LWIP_ERROR("driverif_init : invalid link_layer_type in netif", \
250     ((link_layer_type == ETHERNET_DRIVER_IF) || (link_layer_type == WIFI_DRIVER_IF)), \
251     return ERR_IF);
252 
253     LWIP_ERROR("driverif_init : netif hardware length is greater than maximum supported", \
254     (netif->hwaddr_len <= NETIF_MAX_HWADDR_LEN), return ERR_IF);
255 
256     LWIP_ERROR("driverif_init : drv_send is null", (netif->drv_send != NULL), return ERR_IF);
257 
258 #if LWIP_NETIF_PROMISC
259     LWIP_ERROR("driverif_init : drv_config is null", (netif->drv_config != NULL), return ERR_IF);
260 #endif
261 
262 #if LWIP_NETIF_HOSTNAME
263     /* Initialize interface hostname */
264     netif->hostname = LWIP_NETIF_HOSTNAME_DEFAULT;
265 #endif /* LWIP_NETIF_HOSTNAME */
266 
267     /*
268      * Initialize the snmp variables and counters inside the struct netif.
269      * The last argument should be replaced with your link speed, in units
270      * of bits per second.
271      */
272     NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS);
273 
274     netif->output = etharp_output;
275     netif->linkoutput = driverif_output;
276 
277     /* init the netif's full name */
278     driverif_init_ifname(netif);
279 
280     /* maximum transfer unit */
281     netif->mtu = IP_FRAG_MAX_MTU;
282 
283     /* device capabilities */
284     /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
285     netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP |
286                    #if DRIVER_STATUS_CHECK
287                    NETIF_FLAG_DRIVER_RDY |
288                    #endif
289                    #if LWIP_IGMP
290                    NETIF_FLAG_IGMP |
291                    #endif
292 
293                    /**
294                    @page RFC-2710 RFC-2710
295                    @par Compliant Sections
296                    Section 5. Node State Transition Diagram
297                    @par Behavior Description
298                    MLD messages are sent for multicast addresses whose scope is 2
299                    (link-local), including Solicited-Node multicast addresses.\n
300                    Behavior:Stack will send MLD6 report /Done to solicited node multicast address
301                    if the LWIP_MLD6_ENABLE_MLD_ON_DAD is enabled. By default, this is disabled.
302                    */
303                    /* Enable sending MLD report /done for solicited address during neighbour discovery */
304                    #if LWIP_IPV6 && LWIP_IPV6_MLD
305                    #if LWIP_MLD6_ENABLE_MLD_ON_DAD
306                    NETIF_FLAG_MLD6 |
307                    #endif /* LWIP_MLD6_ENABLE_MLD_ON_DAD */
308                    #endif
309                    NETIF_FLAG_LINK_UP;
310 
311 #if DRIVER_STATUS_CHECK
312     netif->waketime = -1;
313 #endif /* DRIVER_STATUS_CHECK */
314     LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_init : Initialized netif 0x%p\n", (void *)netif));
315     return ERR_OK;
316 }
317