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 56LWIP_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 78LWIP_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 125LWIP_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 153void 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 */ 211void 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 */ 278err_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