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