/* * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. * Copyright (c) 2020-2022 Huawei Device Co., Ltd. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #ifdef LOSCFG_NET_CONTAINER #include #endif #define LWIP_NETIF_HOSTNAME_DEFAULT "default" #define LINK_SPEED_OF_YOUR_NETIF_IN_BPS 100000000 // 100Mbps #define link_rx_drop cachehit #define link_rx_overrun cachehit #define LWIP_STATIC static #ifndef LWIP_NETIF_IFINDEX_MAX_EX #define LWIP_NETIF_IFINDEX_MAX_EX 255 #endif LWIP_STATIC void driverif_init_ifname(struct netif *netif) { struct netif *tmpnetif = NULL; const char *prefix = (netif->link_layer_type == WIFI_DRIVER_IF) ? "wlan" : "eth"; netif->name[0] = prefix[0]; netif->name[1] = prefix[1]; for (int i = 0; i < LWIP_NETIF_IFINDEX_MAX_EX; ++i) { if (snprintf_s(netif->full_name, sizeof(netif->full_name), sizeof(netif->full_name) - 1, "%s%d", prefix, i) < 0) { break; } #ifdef LOSCFG_NET_CONTAINER NETIF_FOREACH(tmpnetif, get_net_group_from_netif(netif)) { #else NETIF_FOREACH(tmpnetif) { #endif if (strcmp(tmpnetif->full_name, netif->full_name) == 0) { break; } } if (tmpnetif == NULL) { return; } } netif->full_name[0] = '\0'; } /* * This function should do the actual transmission of the packet. The packet is * contained in the pbuf that is passed to the function. This pbuf * might be chained. * * @param netif the lwip network interface structure for this driverif * @param p the MAC packet to send (e.g. IP packet including MAC_addresses and type) * @return ERR_OK if the packet could be sent * an err_t value if the packet couldn't be sent * * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to * strange results. You might consider waiting for space in the DMA queue * to become available since the stack doesn't retry to send a packet * dropped because of memory failure (except for the TCP timers). */ LWIP_STATIC err_t driverif_output(struct netif *netif, struct pbuf *p) { LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_output : going to send packet pbuf 0x%p of length %"U16_F" through netif 0x%p\n", \ (void *)p, p->tot_len, (void *)netif)); #if PF_PKT_SUPPORT if (all_pkt_raw_pcbs != NULL) { p->flags = (u16_t)(p->flags & ~(PBUF_FLAG_LLMCAST | PBUF_FLAG_LLBCAST | PBUF_FLAG_HOST)); p->flags |= PBUF_FLAG_OUTGOING; (void)raw_pkt_input(p, netif, NULL); } #endif #if ETH_PAD_SIZE (void)pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ #endif netif->drv_send(netif, p); #if ETH_PAD_SIZE (void)pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ #endif MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len); LINK_STATS_INC(link.xmit); return ERR_OK; } /* * This function should be called by network driver to pass the input packet to LwIP. * Before calling this API, driver has to keep the packet in pbuf structure. Driver has to * call pbuf_alloc() with type as PBUF_RAM to create pbuf structure. Then driver * has to pass the pbuf structure to this API. This will add the pbuf into the TCPIP thread. * Once this packet is processed by TCPIP thread, pbuf will be freed. Driver is not required to * free the pbuf. * * @param netif the lwip network interface structure for this driverif * @param p packet in pbuf structure format */ void driverif_input(struct netif *netif, struct pbuf *p) { #if PF_PKT_SUPPORT #if (DRIVERIF_DEBUG & LWIP_DBG_OFF) u16_t ethhdr_type; struct eth_hdr* ethhdr = NULL; #endif #else u16_t ethhdr_type; struct eth_hdr *ethhdr = NULL; #endif err_t ret = ERR_VAL; LWIP_ERROR("driverif_input : invalid arguments", ((netif != NULL) && (p != NULL)), return); LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_input : going to receive input packet. netif 0x%p, pbuf 0x%p, \ packet_length %"U16_F"\n", (void *)netif, (void *)p, p->tot_len)); /* points to packet payload, which starts with an Ethernet header */ MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len); if (p->len < SIZEOF_ETH_HDR) { (void)pbuf_free(p); LINK_STATS_INC(link.drop); LINK_STATS_INC(link.link_rx_drop); return; } #if PF_PKT_SUPPORT #if (DRIVERIF_DEBUG & LWIP_DBG_OFF) ethhdr = (struct eth_hdr *)p->payload; ethhdr_type = ntohs(ethhdr->type); LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_input : received packet of type %"U16_F" netif->input=%p\n", ethhdr_type, netif->input)); #endif /* full packet send to tcpip_thread to process */ if (netif->input) { ret = netif->input(p, netif); } if (ret != ERR_OK) { LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_input: IP input error\n")); (void)pbuf_free(p); LINK_STATS_INC(link.drop); LINK_STATS_INC(link.link_rx_drop); if (ret == ERR_MEM) { LINK_STATS_INC(link.link_rx_overrun); } } else { LINK_STATS_INC(link.recv); } #else ethhdr = (struct eth_hdr *)p->payload; ethhdr_type = ntohs(ethhdr->type); switch (ethhdr_type) { /* IP or ARP packet? */ case ETHTYPE_IP: case ETHTYPE_IPV6: case ETHTYPE_ARP: #if ETHARP_SUPPORT_VLAN case ETHTYPE_VLAN: #endif /* ETHARP_SUPPORT_VLAN */ LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_input : received packet of type %"U16_F"\n", ethhdr_type)); /* full packet send to tcpip_thread to process */ if (netif->input != NULL) { ret = netif->input(p, netif); } if (ret != ERR_OK) { LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_input: IP input error\n")); (void)pbuf_free(p); LINK_STATS_INC(link.drop); LINK_STATS_INC(link.link_rx_drop); if (ret == ERR_MEM) { MIB2_STATS_NETIF_INC(netif, ifinoverruns); LINK_STATS_INC(link.link_rx_overrun); } } else { LINK_STATS_INC(link.recv); } break; default: LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_input : received packet is of unsupported type %"U16_F"\n", ethhdr_type)); (void)pbuf_free(p); LINK_STATS_INC(link.drop); LINK_STATS_INC(link.link_rx_drop); break; } #endif LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_input : received packet is processed\n")); } /* * Should be called at the beginning of the program to set up the * network interface. It calls the function low_level_init() to do the * actual setup of the hardware. * * This function should be passed as a parameter to netif_add(). * * @param netif the lwip network interface structure for this driverif * @return ERR_OK if the loopif is initialized * ERR_MEM on Allocation Failure * any other err_t on error */ err_t driverif_init(struct netif *netif) { u16_t link_layer_type; if (netif == NULL) { return ERR_IF; } link_layer_type = netif->link_layer_type; LWIP_ERROR("driverif_init : invalid link_layer_type in netif", \ ((link_layer_type == ETHERNET_DRIVER_IF) || (link_layer_type == WIFI_DRIVER_IF)), \ return ERR_IF); LWIP_ERROR("driverif_init : netif hardware length is greater than maximum supported", \ (netif->hwaddr_len <= NETIF_MAX_HWADDR_LEN), return ERR_IF); LWIP_ERROR("driverif_init : drv_send is null", (netif->drv_send != NULL), return ERR_IF); #if LWIP_NETIF_PROMISC LWIP_ERROR("driverif_init : drv_config is null", (netif->drv_config != NULL), return ERR_IF); #endif #if LWIP_NETIF_HOSTNAME /* Initialize interface hostname */ netif->hostname = LWIP_NETIF_HOSTNAME_DEFAULT; #endif /* LWIP_NETIF_HOSTNAME */ /* * Initialize the snmp variables and counters inside the struct netif. * The last argument should be replaced with your link speed, in units * of bits per second. */ NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS); netif->output = etharp_output; netif->linkoutput = driverif_output; /* init the netif's full name */ driverif_init_ifname(netif); /* maximum transfer unit */ netif->mtu = IP_FRAG_MAX_MTU; /* device capabilities */ /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | #if DRIVER_STATUS_CHECK NETIF_FLAG_DRIVER_RDY | #endif #if LWIP_IGMP NETIF_FLAG_IGMP | #endif /** @page RFC-2710 RFC-2710 @par Compliant Sections Section 5. Node State Transition Diagram @par Behavior Description MLD messages are sent for multicast addresses whose scope is 2 (link-local), including Solicited-Node multicast addresses.\n Behavior:Stack will send MLD6 report /Done to solicited node multicast address if the LWIP_MLD6_ENABLE_MLD_ON_DAD is enabled. By default, this is disabled. */ /* Enable sending MLD report /done for solicited address during neighbour discovery */ #if LWIP_IPV6 && LWIP_IPV6_MLD #if LWIP_MLD6_ENABLE_MLD_ON_DAD NETIF_FLAG_MLD6 | #endif /* LWIP_MLD6_ENABLE_MLD_ON_DAD */ #endif NETIF_FLAG_LINK_UP; #if DRIVER_STATUS_CHECK netif->waketime = -1; #endif /* DRIVER_STATUS_CHECK */ LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_init : Initialized netif 0x%p\n", (void *)netif)); return ERR_OK; } #ifdef LOSCFG_NET_CONTAINER static err_t netif_veth_output(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr) { LWIP_UNUSED_ARG(addr); return netif_loop_output(netif->peer, p); } static void veth_init_fullname(struct netif *netif) { struct netif *tmpnetif = NULL; for (int i = 0; i < LWIP_NETIF_IFINDEX_MAX_EX; ++i) { if (snprintf_s(netif->full_name, sizeof(netif->full_name), sizeof(netif->full_name) - 1, "%s%d", "veth", i) < 0) { break; } NETIF_FOREACH(tmpnetif, get_net_group_from_netif(netif)) { if (strcmp(tmpnetif->full_name, netif->full_name) == 0) { break; } } if (tmpnetif == NULL) { return; } } netif->full_name[0] = '\0'; } static err_t netif_vethif_init(struct netif *netif) { LWIP_ASSERT("netif_vethif_init: invalid netif", netif != NULL); /* initialize the snmp variables and counters inside the struct netif * ifSpeed: no assumption can be made! */ MIB2_INIT_NETIF(netif, snmp_ifType_other, 0); netif->link_layer_type = VETH_DRIVER_IF; netif->name[0] = 'v'; netif->name[1] = 'e'; veth_init_fullname(netif); netif->output = netif_veth_output; netif_set_flags(netif, NETIF_FLAG_IGMP); NETIF_SET_CHECKSUM_CTRL(netif, NETIF_CHECKSUM_DISABLE_ALL); return ERR_OK; } void veth_init(struct netif *netif, struct net_group *group) { netif_add_noaddr(netif, group, NULL, netif_vethif_init, tcpip_input); netif_set_link_up(netif); netif_set_up(netif); } #endif