1195972f6Sopenharmony_ci/** 2195972f6Sopenharmony_ci * @file 3195972f6Sopenharmony_ci * Ethernet common functions 4195972f6Sopenharmony_ci * 5195972f6Sopenharmony_ci * @defgroup ethernet Ethernet 6195972f6Sopenharmony_ci * @ingroup callbackstyle_api 7195972f6Sopenharmony_ci */ 8195972f6Sopenharmony_ci 9195972f6Sopenharmony_ci/* 10195972f6Sopenharmony_ci * Copyright (c) 2001-2003 Swedish Institute of Computer Science. 11195972f6Sopenharmony_ci * Copyright (c) 2003-2004 Leon Woestenberg <leon.woestenberg@axon.tv> 12195972f6Sopenharmony_ci * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. 13195972f6Sopenharmony_ci * All rights reserved. 14195972f6Sopenharmony_ci * 15195972f6Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification, 16195972f6Sopenharmony_ci * are permitted provided that the following conditions are met: 17195972f6Sopenharmony_ci * 18195972f6Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, 19195972f6Sopenharmony_ci * this list of conditions and the following disclaimer. 20195972f6Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, 21195972f6Sopenharmony_ci * this list of conditions and the following disclaimer in the documentation 22195972f6Sopenharmony_ci * and/or other materials provided with the distribution. 23195972f6Sopenharmony_ci * 3. The name of the author may not be used to endorse or promote products 24195972f6Sopenharmony_ci * derived from this software without specific prior written permission. 25195972f6Sopenharmony_ci * 26195972f6Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 27195972f6Sopenharmony_ci * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 28195972f6Sopenharmony_ci * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 29195972f6Sopenharmony_ci * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 30195972f6Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 31195972f6Sopenharmony_ci * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32195972f6Sopenharmony_ci * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33195972f6Sopenharmony_ci * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 34195972f6Sopenharmony_ci * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 35195972f6Sopenharmony_ci * OF SUCH DAMAGE. 36195972f6Sopenharmony_ci * 37195972f6Sopenharmony_ci * This file is part of the lwIP TCP/IP stack. 38195972f6Sopenharmony_ci * 39195972f6Sopenharmony_ci */ 40195972f6Sopenharmony_ci 41195972f6Sopenharmony_ci#include "lwip/opt.h" 42195972f6Sopenharmony_ci 43195972f6Sopenharmony_ci#if LWIP_ARP || LWIP_ETHERNET 44195972f6Sopenharmony_ci 45195972f6Sopenharmony_ci#include "netif/ethernet.h" 46195972f6Sopenharmony_ci#include "lwip/def.h" 47195972f6Sopenharmony_ci#include "lwip/stats.h" 48195972f6Sopenharmony_ci#include "lwip/etharp.h" 49195972f6Sopenharmony_ci#include "lwip/ip.h" 50195972f6Sopenharmony_ci#include "lwip/snmp.h" 51195972f6Sopenharmony_ci 52195972f6Sopenharmony_ci#include <string.h> 53195972f6Sopenharmony_ci 54195972f6Sopenharmony_ci#include "netif/ppp/ppp_opts.h" 55195972f6Sopenharmony_ci#if PPPOE_SUPPORT 56195972f6Sopenharmony_ci#include "netif/ppp/pppoe.h" 57195972f6Sopenharmony_ci#endif /* PPPOE_SUPPORT */ 58195972f6Sopenharmony_ci 59195972f6Sopenharmony_ci#ifdef LWIP_HOOK_FILENAME 60195972f6Sopenharmony_ci#include LWIP_HOOK_FILENAME 61195972f6Sopenharmony_ci#endif 62195972f6Sopenharmony_ci 63195972f6Sopenharmony_ciconst struct eth_addr ethbroadcast = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; 64195972f6Sopenharmony_ciconst struct eth_addr ethzero = {{0, 0, 0, 0, 0, 0}}; 65195972f6Sopenharmony_ci 66195972f6Sopenharmony_ci/** 67195972f6Sopenharmony_ci * @ingroup lwip_nosys 68195972f6Sopenharmony_ci * Process received ethernet frames. Using this function instead of directly 69195972f6Sopenharmony_ci * calling ip_input and passing ARP frames through etharp in ethernetif_input, 70195972f6Sopenharmony_ci * the ARP cache is protected from concurrent access.\n 71195972f6Sopenharmony_ci * Don't call directly, pass to netif_add() and call netif->input(). 72195972f6Sopenharmony_ci * 73195972f6Sopenharmony_ci * @param p the received packet, p->payload pointing to the ethernet header 74195972f6Sopenharmony_ci * @param netif the network interface on which the packet was received 75195972f6Sopenharmony_ci * 76195972f6Sopenharmony_ci * @see LWIP_HOOK_UNKNOWN_ETH_PROTOCOL 77195972f6Sopenharmony_ci * @see ETHARP_SUPPORT_VLAN 78195972f6Sopenharmony_ci * @see LWIP_HOOK_VLAN_CHECK 79195972f6Sopenharmony_ci */ 80195972f6Sopenharmony_cierr_t 81195972f6Sopenharmony_ciethernet_input(struct pbuf *p, struct netif *netif) 82195972f6Sopenharmony_ci{ 83195972f6Sopenharmony_ci struct eth_hdr *ethhdr; 84195972f6Sopenharmony_ci u16_t type; 85195972f6Sopenharmony_ci#if LWIP_ARP || ETHARP_SUPPORT_VLAN || LWIP_IPV6 86195972f6Sopenharmony_ci u16_t next_hdr_offset = SIZEOF_ETH_HDR; 87195972f6Sopenharmony_ci#endif /* LWIP_ARP || ETHARP_SUPPORT_VLAN */ 88195972f6Sopenharmony_ci 89195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 90195972f6Sopenharmony_ci 91195972f6Sopenharmony_ci if (p->len <= SIZEOF_ETH_HDR) { 92195972f6Sopenharmony_ci /* a packet with only an ethernet header (or less) is not valid for us */ 93195972f6Sopenharmony_ci ETHARP_STATS_INC(etharp.proterr); 94195972f6Sopenharmony_ci ETHARP_STATS_INC(etharp.drop); 95195972f6Sopenharmony_ci MIB2_STATS_NETIF_INC(netif, ifinerrors); 96195972f6Sopenharmony_ci goto free_and_return; 97195972f6Sopenharmony_ci } 98195972f6Sopenharmony_ci 99195972f6Sopenharmony_ci if (p->if_idx == NETIF_NO_INDEX) { 100195972f6Sopenharmony_ci p->if_idx = netif_get_index(netif); 101195972f6Sopenharmony_ci } 102195972f6Sopenharmony_ci 103195972f6Sopenharmony_ci /* points to packet payload, which starts with an Ethernet header */ 104195972f6Sopenharmony_ci ethhdr = (struct eth_hdr *)p->payload; 105195972f6Sopenharmony_ci LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 106195972f6Sopenharmony_ci ("ethernet_input: dest:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", src:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", type:%"X16_F"\n", 107195972f6Sopenharmony_ci (unsigned char)ethhdr->dest.addr[0], (unsigned char)ethhdr->dest.addr[1], (unsigned char)ethhdr->dest.addr[2], 108195972f6Sopenharmony_ci (unsigned char)ethhdr->dest.addr[3], (unsigned char)ethhdr->dest.addr[4], (unsigned char)ethhdr->dest.addr[5], 109195972f6Sopenharmony_ci (unsigned char)ethhdr->src.addr[0], (unsigned char)ethhdr->src.addr[1], (unsigned char)ethhdr->src.addr[2], 110195972f6Sopenharmony_ci (unsigned char)ethhdr->src.addr[3], (unsigned char)ethhdr->src.addr[4], (unsigned char)ethhdr->src.addr[5], 111195972f6Sopenharmony_ci lwip_htons(ethhdr->type))); 112195972f6Sopenharmony_ci 113195972f6Sopenharmony_ci type = ethhdr->type; 114195972f6Sopenharmony_ci#if ETHARP_SUPPORT_VLAN 115195972f6Sopenharmony_ci if (type == PP_HTONS(ETHTYPE_VLAN)) { 116195972f6Sopenharmony_ci struct eth_vlan_hdr *vlan = (struct eth_vlan_hdr *)(((char *)ethhdr) + SIZEOF_ETH_HDR); 117195972f6Sopenharmony_ci next_hdr_offset = SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR; 118195972f6Sopenharmony_ci if (p->len <= SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) { 119195972f6Sopenharmony_ci /* a packet with only an ethernet/vlan header (or less) is not valid for us */ 120195972f6Sopenharmony_ci ETHARP_STATS_INC(etharp.proterr); 121195972f6Sopenharmony_ci ETHARP_STATS_INC(etharp.drop); 122195972f6Sopenharmony_ci MIB2_STATS_NETIF_INC(netif, ifinerrors); 123195972f6Sopenharmony_ci goto free_and_return; 124195972f6Sopenharmony_ci } 125195972f6Sopenharmony_ci#if defined(LWIP_HOOK_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN) /* if not, allow all VLANs */ 126195972f6Sopenharmony_ci#ifdef LWIP_HOOK_VLAN_CHECK 127195972f6Sopenharmony_ci if (!LWIP_HOOK_VLAN_CHECK(netif, ethhdr, vlan)) { 128195972f6Sopenharmony_ci#elif defined(ETHARP_VLAN_CHECK_FN) 129195972f6Sopenharmony_ci if (!ETHARP_VLAN_CHECK_FN(ethhdr, vlan)) { 130195972f6Sopenharmony_ci#elif defined(ETHARP_VLAN_CHECK) 131195972f6Sopenharmony_ci if (VLAN_ID(vlan) != ETHARP_VLAN_CHECK) { 132195972f6Sopenharmony_ci#endif 133195972f6Sopenharmony_ci /* silently ignore this packet: not for our VLAN */ 134195972f6Sopenharmony_ci pbuf_free(p); 135195972f6Sopenharmony_ci return ERR_OK; 136195972f6Sopenharmony_ci } 137195972f6Sopenharmony_ci#endif /* defined(LWIP_HOOK_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN) */ 138195972f6Sopenharmony_ci type = vlan->tpid; 139195972f6Sopenharmony_ci } 140195972f6Sopenharmony_ci#endif /* ETHARP_SUPPORT_VLAN */ 141195972f6Sopenharmony_ci 142195972f6Sopenharmony_ci#if LWIP_ARP_FILTER_NETIF 143195972f6Sopenharmony_ci netif = LWIP_ARP_FILTER_NETIF_FN(p, netif, lwip_htons(type)); 144195972f6Sopenharmony_ci#endif /* LWIP_ARP_FILTER_NETIF*/ 145195972f6Sopenharmony_ci 146195972f6Sopenharmony_ci if (ethhdr->dest.addr[0] & 1) { 147195972f6Sopenharmony_ci /* this might be a multicast or broadcast packet */ 148195972f6Sopenharmony_ci if (ethhdr->dest.addr[0] == LL_IP4_MULTICAST_ADDR_0) { 149195972f6Sopenharmony_ci#if LWIP_IPV4 150195972f6Sopenharmony_ci if ((ethhdr->dest.addr[1] == LL_IP4_MULTICAST_ADDR_1) && 151195972f6Sopenharmony_ci (ethhdr->dest.addr[2] == LL_IP4_MULTICAST_ADDR_2)) { 152195972f6Sopenharmony_ci /* mark the pbuf as link-layer multicast */ 153195972f6Sopenharmony_ci p->flags |= PBUF_FLAG_LLMCAST; 154195972f6Sopenharmony_ci } 155195972f6Sopenharmony_ci#endif /* LWIP_IPV4 */ 156195972f6Sopenharmony_ci } 157195972f6Sopenharmony_ci#if LWIP_IPV6 158195972f6Sopenharmony_ci else if ((ethhdr->dest.addr[0] == LL_IP6_MULTICAST_ADDR_0) && 159195972f6Sopenharmony_ci (ethhdr->dest.addr[1] == LL_IP6_MULTICAST_ADDR_1)) { 160195972f6Sopenharmony_ci /* mark the pbuf as link-layer multicast */ 161195972f6Sopenharmony_ci p->flags |= PBUF_FLAG_LLMCAST; 162195972f6Sopenharmony_ci } 163195972f6Sopenharmony_ci#endif /* LWIP_IPV6 */ 164195972f6Sopenharmony_ci else if (eth_addr_cmp(ðhdr->dest, ðbroadcast)) { 165195972f6Sopenharmony_ci /* mark the pbuf as link-layer broadcast */ 166195972f6Sopenharmony_ci p->flags |= PBUF_FLAG_LLBCAST; 167195972f6Sopenharmony_ci } 168195972f6Sopenharmony_ci } 169195972f6Sopenharmony_ci 170195972f6Sopenharmony_ci switch (type) { 171195972f6Sopenharmony_ci#if LWIP_IPV4 && LWIP_ARP 172195972f6Sopenharmony_ci /* IP packet? */ 173195972f6Sopenharmony_ci case PP_HTONS(ETHTYPE_IP): 174195972f6Sopenharmony_ci if (!(netif->flags & NETIF_FLAG_ETHARP)) { 175195972f6Sopenharmony_ci goto free_and_return; 176195972f6Sopenharmony_ci } 177195972f6Sopenharmony_ci /* skip Ethernet header (min. size checked above) */ 178195972f6Sopenharmony_ci if (pbuf_remove_header(p, next_hdr_offset)) { 179195972f6Sopenharmony_ci LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, 180195972f6Sopenharmony_ci ("ethernet_input: IPv4 packet dropped, too short (%"U16_F"/%"U16_F")\n", 181195972f6Sopenharmony_ci p->tot_len, next_hdr_offset)); 182195972f6Sopenharmony_ci LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("Can't move over header in packet")); 183195972f6Sopenharmony_ci goto free_and_return; 184195972f6Sopenharmony_ci } else { 185195972f6Sopenharmony_ci /* pass to IP layer */ 186195972f6Sopenharmony_ci ip4_input(p, netif); 187195972f6Sopenharmony_ci } 188195972f6Sopenharmony_ci break; 189195972f6Sopenharmony_ci 190195972f6Sopenharmony_ci case PP_HTONS(ETHTYPE_ARP): 191195972f6Sopenharmony_ci if (!(netif->flags & NETIF_FLAG_ETHARP)) { 192195972f6Sopenharmony_ci goto free_and_return; 193195972f6Sopenharmony_ci } 194195972f6Sopenharmony_ci /* skip Ethernet header (min. size checked above) */ 195195972f6Sopenharmony_ci if (pbuf_remove_header(p, next_hdr_offset)) { 196195972f6Sopenharmony_ci LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, 197195972f6Sopenharmony_ci ("ethernet_input: ARP response packet dropped, too short (%"U16_F"/%"U16_F")\n", 198195972f6Sopenharmony_ci p->tot_len, next_hdr_offset)); 199195972f6Sopenharmony_ci LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("Can't move over header in packet")); 200195972f6Sopenharmony_ci ETHARP_STATS_INC(etharp.lenerr); 201195972f6Sopenharmony_ci ETHARP_STATS_INC(etharp.drop); 202195972f6Sopenharmony_ci goto free_and_return; 203195972f6Sopenharmony_ci } else { 204195972f6Sopenharmony_ci /* pass p to ARP module */ 205195972f6Sopenharmony_ci etharp_input(p, netif); 206195972f6Sopenharmony_ci } 207195972f6Sopenharmony_ci break; 208195972f6Sopenharmony_ci#endif /* LWIP_IPV4 && LWIP_ARP */ 209195972f6Sopenharmony_ci#if PPPOE_SUPPORT 210195972f6Sopenharmony_ci case PP_HTONS(ETHTYPE_PPPOEDISC): /* PPP Over Ethernet Discovery Stage */ 211195972f6Sopenharmony_ci pppoe_disc_input(netif, p); 212195972f6Sopenharmony_ci break; 213195972f6Sopenharmony_ci 214195972f6Sopenharmony_ci case PP_HTONS(ETHTYPE_PPPOE): /* PPP Over Ethernet Session Stage */ 215195972f6Sopenharmony_ci pppoe_data_input(netif, p); 216195972f6Sopenharmony_ci break; 217195972f6Sopenharmony_ci#endif /* PPPOE_SUPPORT */ 218195972f6Sopenharmony_ci 219195972f6Sopenharmony_ci#if LWIP_IPV6 220195972f6Sopenharmony_ci case PP_HTONS(ETHTYPE_IPV6): /* IPv6 */ 221195972f6Sopenharmony_ci /* skip Ethernet header */ 222195972f6Sopenharmony_ci if ((p->len < next_hdr_offset) || pbuf_remove_header(p, next_hdr_offset)) { 223195972f6Sopenharmony_ci LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, 224195972f6Sopenharmony_ci ("ethernet_input: IPv6 packet dropped, too short (%"U16_F"/%"U16_F")\n", 225195972f6Sopenharmony_ci p->tot_len, next_hdr_offset)); 226195972f6Sopenharmony_ci goto free_and_return; 227195972f6Sopenharmony_ci } else { 228195972f6Sopenharmony_ci /* pass to IPv6 layer */ 229195972f6Sopenharmony_ci ip6_input(p, netif); 230195972f6Sopenharmony_ci } 231195972f6Sopenharmony_ci break; 232195972f6Sopenharmony_ci#endif /* LWIP_IPV6 */ 233195972f6Sopenharmony_ci 234195972f6Sopenharmony_ci default: 235195972f6Sopenharmony_ci#ifdef LWIP_HOOK_UNKNOWN_ETH_PROTOCOL 236195972f6Sopenharmony_ci if (LWIP_HOOK_UNKNOWN_ETH_PROTOCOL(p, netif) == ERR_OK) { 237195972f6Sopenharmony_ci break; 238195972f6Sopenharmony_ci } 239195972f6Sopenharmony_ci#endif 240195972f6Sopenharmony_ci ETHARP_STATS_INC(etharp.proterr); 241195972f6Sopenharmony_ci ETHARP_STATS_INC(etharp.drop); 242195972f6Sopenharmony_ci MIB2_STATS_NETIF_INC(netif, ifinunknownprotos); 243195972f6Sopenharmony_ci goto free_and_return; 244195972f6Sopenharmony_ci } 245195972f6Sopenharmony_ci 246195972f6Sopenharmony_ci /* This means the pbuf is freed or consumed, 247195972f6Sopenharmony_ci so the caller doesn't have to free it again */ 248195972f6Sopenharmony_ci return ERR_OK; 249195972f6Sopenharmony_ci 250195972f6Sopenharmony_cifree_and_return: 251195972f6Sopenharmony_ci pbuf_free(p); 252195972f6Sopenharmony_ci return ERR_OK; 253195972f6Sopenharmony_ci} 254195972f6Sopenharmony_ci 255195972f6Sopenharmony_ci/** 256195972f6Sopenharmony_ci * @ingroup ethernet 257195972f6Sopenharmony_ci * Send an ethernet packet on the network using netif->linkoutput(). 258195972f6Sopenharmony_ci * The ethernet header is filled in before sending. 259195972f6Sopenharmony_ci * 260195972f6Sopenharmony_ci * @see LWIP_HOOK_VLAN_SET 261195972f6Sopenharmony_ci * 262195972f6Sopenharmony_ci * @param netif the lwIP network interface on which to send the packet 263195972f6Sopenharmony_ci * @param p the packet to send. pbuf layer must be @ref PBUF_LINK. 264195972f6Sopenharmony_ci * @param src the source MAC address to be copied into the ethernet header 265195972f6Sopenharmony_ci * @param dst the destination MAC address to be copied into the ethernet header 266195972f6Sopenharmony_ci * @param eth_type ethernet type (@ref lwip_ieee_eth_type) 267195972f6Sopenharmony_ci * @return ERR_OK if the packet was sent, any other err_t on failure 268195972f6Sopenharmony_ci */ 269195972f6Sopenharmony_cierr_t 270195972f6Sopenharmony_ciethernet_output(struct netif * netif, struct pbuf * p, 271195972f6Sopenharmony_ci const struct eth_addr * src, const struct eth_addr * dst, 272195972f6Sopenharmony_ci u16_t eth_type) { 273195972f6Sopenharmony_ci struct eth_hdr *ethhdr; 274195972f6Sopenharmony_ci u16_t eth_type_be = lwip_htons(eth_type); 275195972f6Sopenharmony_ci 276195972f6Sopenharmony_ci#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) 277195972f6Sopenharmony_ci s32_t vlan_prio_vid = LWIP_HOOK_VLAN_SET(netif, p, src, dst, eth_type); 278195972f6Sopenharmony_ci if (vlan_prio_vid >= 0) { 279195972f6Sopenharmony_ci struct eth_vlan_hdr *vlanhdr; 280195972f6Sopenharmony_ci 281195972f6Sopenharmony_ci LWIP_ASSERT("prio_vid must be <= 0xFFFF", vlan_prio_vid <= 0xFFFF); 282195972f6Sopenharmony_ci 283195972f6Sopenharmony_ci if (pbuf_add_header(p, SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) != 0) { 284195972f6Sopenharmony_ci goto pbuf_header_failed; 285195972f6Sopenharmony_ci } 286195972f6Sopenharmony_ci vlanhdr = (struct eth_vlan_hdr *)(((u8_t *)p->payload) + SIZEOF_ETH_HDR); 287195972f6Sopenharmony_ci vlanhdr->tpid = eth_type_be; 288195972f6Sopenharmony_ci vlanhdr->prio_vid = lwip_htons((u16_t)vlan_prio_vid); 289195972f6Sopenharmony_ci 290195972f6Sopenharmony_ci eth_type_be = PP_HTONS(ETHTYPE_VLAN); 291195972f6Sopenharmony_ci } else 292195972f6Sopenharmony_ci#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ 293195972f6Sopenharmony_ci { 294195972f6Sopenharmony_ci if (pbuf_add_header(p, SIZEOF_ETH_HDR) != 0) { 295195972f6Sopenharmony_ci goto pbuf_header_failed; 296195972f6Sopenharmony_ci } 297195972f6Sopenharmony_ci } 298195972f6Sopenharmony_ci 299195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 300195972f6Sopenharmony_ci 301195972f6Sopenharmony_ci ethhdr = (struct eth_hdr *)p->payload; 302195972f6Sopenharmony_ci ethhdr->type = eth_type_be; 303195972f6Sopenharmony_ci SMEMCPY(ðhdr->dest, dst, ETH_HWADDR_LEN); 304195972f6Sopenharmony_ci SMEMCPY(ðhdr->src, src, ETH_HWADDR_LEN); 305195972f6Sopenharmony_ci 306195972f6Sopenharmony_ci LWIP_ASSERT("netif->hwaddr_len must be 6 for ethernet_output!", 307195972f6Sopenharmony_ci (netif->hwaddr_len == ETH_HWADDR_LEN)); 308195972f6Sopenharmony_ci LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 309195972f6Sopenharmony_ci ("ethernet_output: sending packet %p\n", (void *)p)); 310195972f6Sopenharmony_ci 311195972f6Sopenharmony_ci /* send the packet */ 312195972f6Sopenharmony_ci return netif->linkoutput(netif, p); 313195972f6Sopenharmony_ci 314195972f6Sopenharmony_cipbuf_header_failed: 315195972f6Sopenharmony_ci LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, 316195972f6Sopenharmony_ci ("ethernet_output: could not allocate room for header.\n")); 317195972f6Sopenharmony_ci LINK_STATS_INC(link.lenerr); 318195972f6Sopenharmony_ci return ERR_BUF; 319195972f6Sopenharmony_ci} 320195972f6Sopenharmony_ci 321195972f6Sopenharmony_ci#endif /* LWIP_ARP || LWIP_ETHERNET */ 322