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
54LWIP_STATIC void
55driverif_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
100LWIP_STATIC err_t
101driverif_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 */
140void
141driverif_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 */
247err_t
248driverif_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
326static 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
332static 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
353static 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
374void 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