162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * INET An implementation of the TCP/IP protocol suite for the LINUX 462306a36Sopenharmony_ci * operating system. INET is implemented using the BSD Socket 562306a36Sopenharmony_ci * interface as the means of communication with the user level. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Ethernet-type device handling. 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * Version: @(#)eth.c 1.0.7 05/25/93 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * Authors: Ross Biro 1262306a36Sopenharmony_ci * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> 1362306a36Sopenharmony_ci * Mark Evans, <evansmp@uhura.aston.ac.uk> 1462306a36Sopenharmony_ci * Florian La Roche, <rzsfl@rz.uni-sb.de> 1562306a36Sopenharmony_ci * Alan Cox, <gw4pts@gw4pts.ampr.org> 1662306a36Sopenharmony_ci * 1762306a36Sopenharmony_ci * Fixes: 1862306a36Sopenharmony_ci * Mr Linux : Arp problems 1962306a36Sopenharmony_ci * Alan Cox : Generic queue tidyup (very tiny here) 2062306a36Sopenharmony_ci * Alan Cox : eth_header ntohs should be htons 2162306a36Sopenharmony_ci * Alan Cox : eth_rebuild_header missing an htons and 2262306a36Sopenharmony_ci * minor other things. 2362306a36Sopenharmony_ci * Tegge : Arp bug fixes. 2462306a36Sopenharmony_ci * Florian : Removed many unnecessary functions, code cleanup 2562306a36Sopenharmony_ci * and changes for new arp and skbuff. 2662306a36Sopenharmony_ci * Alan Cox : Redid header building to reflect new format. 2762306a36Sopenharmony_ci * Alan Cox : ARP only when compiled with CONFIG_INET 2862306a36Sopenharmony_ci * Greg Page : 802.2 and SNAP stuff. 2962306a36Sopenharmony_ci * Alan Cox : MAC layer pointers/new format. 3062306a36Sopenharmony_ci * Paul Gortmaker : eth_copy_and_sum shouldn't csum padding. 3162306a36Sopenharmony_ci * Alan Cox : Protect against forwarding explosions with 3262306a36Sopenharmony_ci * older network drivers and IFF_ALLMULTI. 3362306a36Sopenharmony_ci * Christer Weinigel : Better rebuild header message. 3462306a36Sopenharmony_ci * Andrew Morton : 26Feb01: kill ether_setup() - use netdev_boot_setup(). 3562306a36Sopenharmony_ci */ 3662306a36Sopenharmony_ci#include <linux/module.h> 3762306a36Sopenharmony_ci#include <linux/types.h> 3862306a36Sopenharmony_ci#include <linux/kernel.h> 3962306a36Sopenharmony_ci#include <linux/string.h> 4062306a36Sopenharmony_ci#include <linux/mm.h> 4162306a36Sopenharmony_ci#include <linux/socket.h> 4262306a36Sopenharmony_ci#include <linux/in.h> 4362306a36Sopenharmony_ci#include <linux/inet.h> 4462306a36Sopenharmony_ci#include <linux/ip.h> 4562306a36Sopenharmony_ci#include <linux/netdevice.h> 4662306a36Sopenharmony_ci#include <linux/nvmem-consumer.h> 4762306a36Sopenharmony_ci#include <linux/etherdevice.h> 4862306a36Sopenharmony_ci#include <linux/skbuff.h> 4962306a36Sopenharmony_ci#include <linux/errno.h> 5062306a36Sopenharmony_ci#include <linux/init.h> 5162306a36Sopenharmony_ci#include <linux/if_ether.h> 5262306a36Sopenharmony_ci#include <linux/of_net.h> 5362306a36Sopenharmony_ci#include <linux/pci.h> 5462306a36Sopenharmony_ci#include <linux/property.h> 5562306a36Sopenharmony_ci#include <net/dst.h> 5662306a36Sopenharmony_ci#include <net/arp.h> 5762306a36Sopenharmony_ci#include <net/sock.h> 5862306a36Sopenharmony_ci#include <net/ipv6.h> 5962306a36Sopenharmony_ci#include <net/ip.h> 6062306a36Sopenharmony_ci#include <net/dsa.h> 6162306a36Sopenharmony_ci#include <net/flow_dissector.h> 6262306a36Sopenharmony_ci#include <net/gro.h> 6362306a36Sopenharmony_ci#include <linux/uaccess.h> 6462306a36Sopenharmony_ci#include <net/pkt_sched.h> 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci/** 6762306a36Sopenharmony_ci * eth_header - create the Ethernet header 6862306a36Sopenharmony_ci * @skb: buffer to alter 6962306a36Sopenharmony_ci * @dev: source device 7062306a36Sopenharmony_ci * @type: Ethernet type field 7162306a36Sopenharmony_ci * @daddr: destination address (NULL leave destination address) 7262306a36Sopenharmony_ci * @saddr: source address (NULL use device source address) 7362306a36Sopenharmony_ci * @len: packet length (<= skb->len) 7462306a36Sopenharmony_ci * 7562306a36Sopenharmony_ci * 7662306a36Sopenharmony_ci * Set the protocol type. For a packet of type ETH_P_802_3/2 we put the length 7762306a36Sopenharmony_ci * in here instead. 7862306a36Sopenharmony_ci */ 7962306a36Sopenharmony_ciint eth_header(struct sk_buff *skb, struct net_device *dev, 8062306a36Sopenharmony_ci unsigned short type, 8162306a36Sopenharmony_ci const void *daddr, const void *saddr, unsigned int len) 8262306a36Sopenharmony_ci{ 8362306a36Sopenharmony_ci struct ethhdr *eth = skb_push(skb, ETH_HLEN); 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci if (type != ETH_P_802_3 && type != ETH_P_802_2) 8662306a36Sopenharmony_ci eth->h_proto = htons(type); 8762306a36Sopenharmony_ci else 8862306a36Sopenharmony_ci eth->h_proto = htons(len); 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci /* 9162306a36Sopenharmony_ci * Set the source hardware address. 9262306a36Sopenharmony_ci */ 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci if (!saddr) 9562306a36Sopenharmony_ci saddr = dev->dev_addr; 9662306a36Sopenharmony_ci memcpy(eth->h_source, saddr, ETH_ALEN); 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci if (daddr) { 9962306a36Sopenharmony_ci memcpy(eth->h_dest, daddr, ETH_ALEN); 10062306a36Sopenharmony_ci return ETH_HLEN; 10162306a36Sopenharmony_ci } 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci /* 10462306a36Sopenharmony_ci * Anyway, the loopback-device should never use this function... 10562306a36Sopenharmony_ci */ 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) { 10862306a36Sopenharmony_ci eth_zero_addr(eth->h_dest); 10962306a36Sopenharmony_ci return ETH_HLEN; 11062306a36Sopenharmony_ci } 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci return -ETH_HLEN; 11362306a36Sopenharmony_ci} 11462306a36Sopenharmony_ciEXPORT_SYMBOL(eth_header); 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci/** 11762306a36Sopenharmony_ci * eth_get_headlen - determine the length of header for an ethernet frame 11862306a36Sopenharmony_ci * @dev: pointer to network device 11962306a36Sopenharmony_ci * @data: pointer to start of frame 12062306a36Sopenharmony_ci * @len: total length of frame 12162306a36Sopenharmony_ci * 12262306a36Sopenharmony_ci * Make a best effort attempt to pull the length for all of the headers for 12362306a36Sopenharmony_ci * a given frame in a linear buffer. 12462306a36Sopenharmony_ci */ 12562306a36Sopenharmony_ciu32 eth_get_headlen(const struct net_device *dev, const void *data, u32 len) 12662306a36Sopenharmony_ci{ 12762306a36Sopenharmony_ci const unsigned int flags = FLOW_DISSECTOR_F_PARSE_1ST_FRAG; 12862306a36Sopenharmony_ci const struct ethhdr *eth = (const struct ethhdr *)data; 12962306a36Sopenharmony_ci struct flow_keys_basic keys; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci /* this should never happen, but better safe than sorry */ 13262306a36Sopenharmony_ci if (unlikely(len < sizeof(*eth))) 13362306a36Sopenharmony_ci return len; 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci /* parse any remaining L2/L3 headers, check for L4 */ 13662306a36Sopenharmony_ci if (!skb_flow_dissect_flow_keys_basic(dev_net(dev), NULL, &keys, data, 13762306a36Sopenharmony_ci eth->h_proto, sizeof(*eth), 13862306a36Sopenharmony_ci len, flags)) 13962306a36Sopenharmony_ci return max_t(u32, keys.control.thoff, sizeof(*eth)); 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci /* parse for any L4 headers */ 14262306a36Sopenharmony_ci return min_t(u32, __skb_get_poff(NULL, data, &keys, len), len); 14362306a36Sopenharmony_ci} 14462306a36Sopenharmony_ciEXPORT_SYMBOL(eth_get_headlen); 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci/** 14762306a36Sopenharmony_ci * eth_type_trans - determine the packet's protocol ID. 14862306a36Sopenharmony_ci * @skb: received socket data 14962306a36Sopenharmony_ci * @dev: receiving network device 15062306a36Sopenharmony_ci * 15162306a36Sopenharmony_ci * The rule here is that we 15262306a36Sopenharmony_ci * assume 802.3 if the type field is short enough to be a length. 15362306a36Sopenharmony_ci * This is normal practice and works for any 'now in use' protocol. 15462306a36Sopenharmony_ci */ 15562306a36Sopenharmony_ci__be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev) 15662306a36Sopenharmony_ci{ 15762306a36Sopenharmony_ci unsigned short _service_access_point; 15862306a36Sopenharmony_ci const unsigned short *sap; 15962306a36Sopenharmony_ci const struct ethhdr *eth; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci skb->dev = dev; 16262306a36Sopenharmony_ci skb_reset_mac_header(skb); 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci eth = (struct ethhdr *)skb->data; 16562306a36Sopenharmony_ci skb_pull_inline(skb, ETH_HLEN); 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci if (unlikely(!ether_addr_equal_64bits(eth->h_dest, 16862306a36Sopenharmony_ci dev->dev_addr))) { 16962306a36Sopenharmony_ci if (unlikely(is_multicast_ether_addr_64bits(eth->h_dest))) { 17062306a36Sopenharmony_ci if (ether_addr_equal_64bits(eth->h_dest, dev->broadcast)) 17162306a36Sopenharmony_ci skb->pkt_type = PACKET_BROADCAST; 17262306a36Sopenharmony_ci else 17362306a36Sopenharmony_ci skb->pkt_type = PACKET_MULTICAST; 17462306a36Sopenharmony_ci } else { 17562306a36Sopenharmony_ci skb->pkt_type = PACKET_OTHERHOST; 17662306a36Sopenharmony_ci } 17762306a36Sopenharmony_ci } 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci /* 18062306a36Sopenharmony_ci * Some variants of DSA tagging don't have an ethertype field 18162306a36Sopenharmony_ci * at all, so we check here whether one of those tagging 18262306a36Sopenharmony_ci * variants has been configured on the receiving interface, 18362306a36Sopenharmony_ci * and if so, set skb->protocol without looking at the packet. 18462306a36Sopenharmony_ci */ 18562306a36Sopenharmony_ci if (unlikely(netdev_uses_dsa(dev))) 18662306a36Sopenharmony_ci return htons(ETH_P_XDSA); 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci if (likely(eth_proto_is_802_3(eth->h_proto))) 18962306a36Sopenharmony_ci return eth->h_proto; 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci /* 19262306a36Sopenharmony_ci * This is a magic hack to spot IPX packets. Older Novell breaks 19362306a36Sopenharmony_ci * the protocol design and runs IPX over 802.3 without an 802.2 LLC 19462306a36Sopenharmony_ci * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This 19562306a36Sopenharmony_ci * won't work for fault tolerant netware but does for the rest. 19662306a36Sopenharmony_ci */ 19762306a36Sopenharmony_ci sap = skb_header_pointer(skb, 0, sizeof(*sap), &_service_access_point); 19862306a36Sopenharmony_ci if (sap && *sap == 0xFFFF) 19962306a36Sopenharmony_ci return htons(ETH_P_802_3); 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci /* 20262306a36Sopenharmony_ci * Real 802.2 LLC 20362306a36Sopenharmony_ci */ 20462306a36Sopenharmony_ci return htons(ETH_P_802_2); 20562306a36Sopenharmony_ci} 20662306a36Sopenharmony_ciEXPORT_SYMBOL(eth_type_trans); 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci/** 20962306a36Sopenharmony_ci * eth_header_parse - extract hardware address from packet 21062306a36Sopenharmony_ci * @skb: packet to extract header from 21162306a36Sopenharmony_ci * @haddr: destination buffer 21262306a36Sopenharmony_ci */ 21362306a36Sopenharmony_ciint eth_header_parse(const struct sk_buff *skb, unsigned char *haddr) 21462306a36Sopenharmony_ci{ 21562306a36Sopenharmony_ci const struct ethhdr *eth = eth_hdr(skb); 21662306a36Sopenharmony_ci memcpy(haddr, eth->h_source, ETH_ALEN); 21762306a36Sopenharmony_ci return ETH_ALEN; 21862306a36Sopenharmony_ci} 21962306a36Sopenharmony_ciEXPORT_SYMBOL(eth_header_parse); 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci/** 22262306a36Sopenharmony_ci * eth_header_cache - fill cache entry from neighbour 22362306a36Sopenharmony_ci * @neigh: source neighbour 22462306a36Sopenharmony_ci * @hh: destination cache entry 22562306a36Sopenharmony_ci * @type: Ethernet type field 22662306a36Sopenharmony_ci * 22762306a36Sopenharmony_ci * Create an Ethernet header template from the neighbour. 22862306a36Sopenharmony_ci */ 22962306a36Sopenharmony_ciint eth_header_cache(const struct neighbour *neigh, struct hh_cache *hh, __be16 type) 23062306a36Sopenharmony_ci{ 23162306a36Sopenharmony_ci struct ethhdr *eth; 23262306a36Sopenharmony_ci const struct net_device *dev = neigh->dev; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci eth = (struct ethhdr *) 23562306a36Sopenharmony_ci (((u8 *) hh->hh_data) + (HH_DATA_OFF(sizeof(*eth)))); 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci if (type == htons(ETH_P_802_3)) 23862306a36Sopenharmony_ci return -1; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci eth->h_proto = type; 24162306a36Sopenharmony_ci memcpy(eth->h_source, dev->dev_addr, ETH_ALEN); 24262306a36Sopenharmony_ci memcpy(eth->h_dest, neigh->ha, ETH_ALEN); 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci /* Pairs with READ_ONCE() in neigh_resolve_output(), 24562306a36Sopenharmony_ci * neigh_hh_output() and neigh_update_hhs(). 24662306a36Sopenharmony_ci */ 24762306a36Sopenharmony_ci smp_store_release(&hh->hh_len, ETH_HLEN); 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci return 0; 25062306a36Sopenharmony_ci} 25162306a36Sopenharmony_ciEXPORT_SYMBOL(eth_header_cache); 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci/** 25462306a36Sopenharmony_ci * eth_header_cache_update - update cache entry 25562306a36Sopenharmony_ci * @hh: destination cache entry 25662306a36Sopenharmony_ci * @dev: network device 25762306a36Sopenharmony_ci * @haddr: new hardware address 25862306a36Sopenharmony_ci * 25962306a36Sopenharmony_ci * Called by Address Resolution module to notify changes in address. 26062306a36Sopenharmony_ci */ 26162306a36Sopenharmony_civoid eth_header_cache_update(struct hh_cache *hh, 26262306a36Sopenharmony_ci const struct net_device *dev, 26362306a36Sopenharmony_ci const unsigned char *haddr) 26462306a36Sopenharmony_ci{ 26562306a36Sopenharmony_ci memcpy(((u8 *) hh->hh_data) + HH_DATA_OFF(sizeof(struct ethhdr)), 26662306a36Sopenharmony_ci haddr, ETH_ALEN); 26762306a36Sopenharmony_ci} 26862306a36Sopenharmony_ciEXPORT_SYMBOL(eth_header_cache_update); 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci/** 27162306a36Sopenharmony_ci * eth_header_parse_protocol - extract protocol from L2 header 27262306a36Sopenharmony_ci * @skb: packet to extract protocol from 27362306a36Sopenharmony_ci */ 27462306a36Sopenharmony_ci__be16 eth_header_parse_protocol(const struct sk_buff *skb) 27562306a36Sopenharmony_ci{ 27662306a36Sopenharmony_ci const struct ethhdr *eth = eth_hdr(skb); 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci return eth->h_proto; 27962306a36Sopenharmony_ci} 28062306a36Sopenharmony_ciEXPORT_SYMBOL(eth_header_parse_protocol); 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci/** 28362306a36Sopenharmony_ci * eth_prepare_mac_addr_change - prepare for mac change 28462306a36Sopenharmony_ci * @dev: network device 28562306a36Sopenharmony_ci * @p: socket address 28662306a36Sopenharmony_ci */ 28762306a36Sopenharmony_ciint eth_prepare_mac_addr_change(struct net_device *dev, void *p) 28862306a36Sopenharmony_ci{ 28962306a36Sopenharmony_ci struct sockaddr *addr = p; 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci if (!(dev->priv_flags & IFF_LIVE_ADDR_CHANGE) && netif_running(dev)) 29262306a36Sopenharmony_ci return -EBUSY; 29362306a36Sopenharmony_ci if (!is_valid_ether_addr(addr->sa_data)) 29462306a36Sopenharmony_ci return -EADDRNOTAVAIL; 29562306a36Sopenharmony_ci return 0; 29662306a36Sopenharmony_ci} 29762306a36Sopenharmony_ciEXPORT_SYMBOL(eth_prepare_mac_addr_change); 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci/** 30062306a36Sopenharmony_ci * eth_commit_mac_addr_change - commit mac change 30162306a36Sopenharmony_ci * @dev: network device 30262306a36Sopenharmony_ci * @p: socket address 30362306a36Sopenharmony_ci */ 30462306a36Sopenharmony_civoid eth_commit_mac_addr_change(struct net_device *dev, void *p) 30562306a36Sopenharmony_ci{ 30662306a36Sopenharmony_ci struct sockaddr *addr = p; 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci eth_hw_addr_set(dev, addr->sa_data); 30962306a36Sopenharmony_ci} 31062306a36Sopenharmony_ciEXPORT_SYMBOL(eth_commit_mac_addr_change); 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci/** 31362306a36Sopenharmony_ci * eth_mac_addr - set new Ethernet hardware address 31462306a36Sopenharmony_ci * @dev: network device 31562306a36Sopenharmony_ci * @p: socket address 31662306a36Sopenharmony_ci * 31762306a36Sopenharmony_ci * Change hardware address of device. 31862306a36Sopenharmony_ci * 31962306a36Sopenharmony_ci * This doesn't change hardware matching, so needs to be overridden 32062306a36Sopenharmony_ci * for most real devices. 32162306a36Sopenharmony_ci */ 32262306a36Sopenharmony_ciint eth_mac_addr(struct net_device *dev, void *p) 32362306a36Sopenharmony_ci{ 32462306a36Sopenharmony_ci int ret; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci ret = eth_prepare_mac_addr_change(dev, p); 32762306a36Sopenharmony_ci if (ret < 0) 32862306a36Sopenharmony_ci return ret; 32962306a36Sopenharmony_ci eth_commit_mac_addr_change(dev, p); 33062306a36Sopenharmony_ci return 0; 33162306a36Sopenharmony_ci} 33262306a36Sopenharmony_ciEXPORT_SYMBOL(eth_mac_addr); 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ciint eth_validate_addr(struct net_device *dev) 33562306a36Sopenharmony_ci{ 33662306a36Sopenharmony_ci if (!is_valid_ether_addr(dev->dev_addr)) 33762306a36Sopenharmony_ci return -EADDRNOTAVAIL; 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci return 0; 34062306a36Sopenharmony_ci} 34162306a36Sopenharmony_ciEXPORT_SYMBOL(eth_validate_addr); 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ciconst struct header_ops eth_header_ops ____cacheline_aligned = { 34462306a36Sopenharmony_ci .create = eth_header, 34562306a36Sopenharmony_ci .parse = eth_header_parse, 34662306a36Sopenharmony_ci .cache = eth_header_cache, 34762306a36Sopenharmony_ci .cache_update = eth_header_cache_update, 34862306a36Sopenharmony_ci .parse_protocol = eth_header_parse_protocol, 34962306a36Sopenharmony_ci}; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci/** 35262306a36Sopenharmony_ci * ether_setup - setup Ethernet network device 35362306a36Sopenharmony_ci * @dev: network device 35462306a36Sopenharmony_ci * 35562306a36Sopenharmony_ci * Fill in the fields of the device structure with Ethernet-generic values. 35662306a36Sopenharmony_ci */ 35762306a36Sopenharmony_civoid ether_setup(struct net_device *dev) 35862306a36Sopenharmony_ci{ 35962306a36Sopenharmony_ci dev->header_ops = ð_header_ops; 36062306a36Sopenharmony_ci dev->type = ARPHRD_ETHER; 36162306a36Sopenharmony_ci dev->hard_header_len = ETH_HLEN; 36262306a36Sopenharmony_ci dev->min_header_len = ETH_HLEN; 36362306a36Sopenharmony_ci dev->mtu = ETH_DATA_LEN; 36462306a36Sopenharmony_ci dev->min_mtu = ETH_MIN_MTU; 36562306a36Sopenharmony_ci dev->max_mtu = ETH_DATA_LEN; 36662306a36Sopenharmony_ci dev->addr_len = ETH_ALEN; 36762306a36Sopenharmony_ci dev->tx_queue_len = DEFAULT_TX_QUEUE_LEN; 36862306a36Sopenharmony_ci dev->flags = IFF_BROADCAST|IFF_MULTICAST; 36962306a36Sopenharmony_ci dev->priv_flags |= IFF_TX_SKB_SHARING; 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci eth_broadcast_addr(dev->broadcast); 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci} 37462306a36Sopenharmony_ciEXPORT_SYMBOL(ether_setup); 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci/** 37762306a36Sopenharmony_ci * alloc_etherdev_mqs - Allocates and sets up an Ethernet device 37862306a36Sopenharmony_ci * @sizeof_priv: Size of additional driver-private structure to be allocated 37962306a36Sopenharmony_ci * for this Ethernet device 38062306a36Sopenharmony_ci * @txqs: The number of TX queues this device has. 38162306a36Sopenharmony_ci * @rxqs: The number of RX queues this device has. 38262306a36Sopenharmony_ci * 38362306a36Sopenharmony_ci * Fill in the fields of the device structure with Ethernet-generic 38462306a36Sopenharmony_ci * values. Basically does everything except registering the device. 38562306a36Sopenharmony_ci * 38662306a36Sopenharmony_ci * Constructs a new net device, complete with a private data area of 38762306a36Sopenharmony_ci * size (sizeof_priv). A 32-byte (not bit) alignment is enforced for 38862306a36Sopenharmony_ci * this private data area. 38962306a36Sopenharmony_ci */ 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_cistruct net_device *alloc_etherdev_mqs(int sizeof_priv, unsigned int txqs, 39262306a36Sopenharmony_ci unsigned int rxqs) 39362306a36Sopenharmony_ci{ 39462306a36Sopenharmony_ci return alloc_netdev_mqs(sizeof_priv, "eth%d", NET_NAME_ENUM, 39562306a36Sopenharmony_ci ether_setup, txqs, rxqs); 39662306a36Sopenharmony_ci} 39762306a36Sopenharmony_ciEXPORT_SYMBOL(alloc_etherdev_mqs); 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_cissize_t sysfs_format_mac(char *buf, const unsigned char *addr, int len) 40062306a36Sopenharmony_ci{ 40162306a36Sopenharmony_ci return sysfs_emit(buf, "%*phC\n", len, addr); 40262306a36Sopenharmony_ci} 40362306a36Sopenharmony_ciEXPORT_SYMBOL(sysfs_format_mac); 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_cistruct sk_buff *eth_gro_receive(struct list_head *head, struct sk_buff *skb) 40662306a36Sopenharmony_ci{ 40762306a36Sopenharmony_ci const struct packet_offload *ptype; 40862306a36Sopenharmony_ci unsigned int hlen, off_eth; 40962306a36Sopenharmony_ci struct sk_buff *pp = NULL; 41062306a36Sopenharmony_ci struct ethhdr *eh, *eh2; 41162306a36Sopenharmony_ci struct sk_buff *p; 41262306a36Sopenharmony_ci __be16 type; 41362306a36Sopenharmony_ci int flush = 1; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci off_eth = skb_gro_offset(skb); 41662306a36Sopenharmony_ci hlen = off_eth + sizeof(*eh); 41762306a36Sopenharmony_ci eh = skb_gro_header(skb, hlen, off_eth); 41862306a36Sopenharmony_ci if (unlikely(!eh)) 41962306a36Sopenharmony_ci goto out; 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci flush = 0; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci list_for_each_entry(p, head, list) { 42462306a36Sopenharmony_ci if (!NAPI_GRO_CB(p)->same_flow) 42562306a36Sopenharmony_ci continue; 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci eh2 = (struct ethhdr *)(p->data + off_eth); 42862306a36Sopenharmony_ci if (compare_ether_header(eh, eh2)) { 42962306a36Sopenharmony_ci NAPI_GRO_CB(p)->same_flow = 0; 43062306a36Sopenharmony_ci continue; 43162306a36Sopenharmony_ci } 43262306a36Sopenharmony_ci } 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci type = eh->h_proto; 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci ptype = gro_find_receive_by_type(type); 43762306a36Sopenharmony_ci if (ptype == NULL) { 43862306a36Sopenharmony_ci flush = 1; 43962306a36Sopenharmony_ci goto out; 44062306a36Sopenharmony_ci } 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci skb_gro_pull(skb, sizeof(*eh)); 44362306a36Sopenharmony_ci skb_gro_postpull_rcsum(skb, eh, sizeof(*eh)); 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci pp = indirect_call_gro_receive_inet(ptype->callbacks.gro_receive, 44662306a36Sopenharmony_ci ipv6_gro_receive, inet_gro_receive, 44762306a36Sopenharmony_ci head, skb); 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ciout: 45062306a36Sopenharmony_ci skb_gro_flush_final(skb, pp, flush); 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci return pp; 45362306a36Sopenharmony_ci} 45462306a36Sopenharmony_ciEXPORT_SYMBOL(eth_gro_receive); 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ciint eth_gro_complete(struct sk_buff *skb, int nhoff) 45762306a36Sopenharmony_ci{ 45862306a36Sopenharmony_ci struct ethhdr *eh = (struct ethhdr *)(skb->data + nhoff); 45962306a36Sopenharmony_ci __be16 type = eh->h_proto; 46062306a36Sopenharmony_ci struct packet_offload *ptype; 46162306a36Sopenharmony_ci int err = -ENOSYS; 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci if (skb->encapsulation) 46462306a36Sopenharmony_ci skb_set_inner_mac_header(skb, nhoff); 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci ptype = gro_find_complete_by_type(type); 46762306a36Sopenharmony_ci if (ptype != NULL) 46862306a36Sopenharmony_ci err = INDIRECT_CALL_INET(ptype->callbacks.gro_complete, 46962306a36Sopenharmony_ci ipv6_gro_complete, inet_gro_complete, 47062306a36Sopenharmony_ci skb, nhoff + sizeof(*eh)); 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci return err; 47362306a36Sopenharmony_ci} 47462306a36Sopenharmony_ciEXPORT_SYMBOL(eth_gro_complete); 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_cistatic struct packet_offload eth_packet_offload __read_mostly = { 47762306a36Sopenharmony_ci .type = cpu_to_be16(ETH_P_TEB), 47862306a36Sopenharmony_ci .priority = 10, 47962306a36Sopenharmony_ci .callbacks = { 48062306a36Sopenharmony_ci .gro_receive = eth_gro_receive, 48162306a36Sopenharmony_ci .gro_complete = eth_gro_complete, 48262306a36Sopenharmony_ci }, 48362306a36Sopenharmony_ci}; 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_cistatic int __init eth_offload_init(void) 48662306a36Sopenharmony_ci{ 48762306a36Sopenharmony_ci dev_add_offload(ð_packet_offload); 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci return 0; 49062306a36Sopenharmony_ci} 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_cifs_initcall(eth_offload_init); 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ciunsigned char * __weak arch_get_platform_mac_address(void) 49562306a36Sopenharmony_ci{ 49662306a36Sopenharmony_ci return NULL; 49762306a36Sopenharmony_ci} 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ciint eth_platform_get_mac_address(struct device *dev, u8 *mac_addr) 50062306a36Sopenharmony_ci{ 50162306a36Sopenharmony_ci unsigned char *addr; 50262306a36Sopenharmony_ci int ret; 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci ret = of_get_mac_address(dev->of_node, mac_addr); 50562306a36Sopenharmony_ci if (!ret) 50662306a36Sopenharmony_ci return 0; 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci addr = arch_get_platform_mac_address(); 50962306a36Sopenharmony_ci if (!addr) 51062306a36Sopenharmony_ci return -ENODEV; 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci ether_addr_copy(mac_addr, addr); 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci return 0; 51562306a36Sopenharmony_ci} 51662306a36Sopenharmony_ciEXPORT_SYMBOL(eth_platform_get_mac_address); 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci/** 51962306a36Sopenharmony_ci * platform_get_ethdev_address - Set netdev's MAC address from a given device 52062306a36Sopenharmony_ci * @dev: Pointer to the device 52162306a36Sopenharmony_ci * @netdev: Pointer to netdev to write the address to 52262306a36Sopenharmony_ci * 52362306a36Sopenharmony_ci * Wrapper around eth_platform_get_mac_address() which writes the address 52462306a36Sopenharmony_ci * directly to netdev->dev_addr. 52562306a36Sopenharmony_ci */ 52662306a36Sopenharmony_ciint platform_get_ethdev_address(struct device *dev, struct net_device *netdev) 52762306a36Sopenharmony_ci{ 52862306a36Sopenharmony_ci u8 addr[ETH_ALEN] __aligned(2); 52962306a36Sopenharmony_ci int ret; 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci ret = eth_platform_get_mac_address(dev, addr); 53262306a36Sopenharmony_ci if (!ret) 53362306a36Sopenharmony_ci eth_hw_addr_set(netdev, addr); 53462306a36Sopenharmony_ci return ret; 53562306a36Sopenharmony_ci} 53662306a36Sopenharmony_ciEXPORT_SYMBOL(platform_get_ethdev_address); 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci/** 53962306a36Sopenharmony_ci * nvmem_get_mac_address - Obtain the MAC address from an nvmem cell named 54062306a36Sopenharmony_ci * 'mac-address' associated with given device. 54162306a36Sopenharmony_ci * 54262306a36Sopenharmony_ci * @dev: Device with which the mac-address cell is associated. 54362306a36Sopenharmony_ci * @addrbuf: Buffer to which the MAC address will be copied on success. 54462306a36Sopenharmony_ci * 54562306a36Sopenharmony_ci * Returns 0 on success or a negative error number on failure. 54662306a36Sopenharmony_ci */ 54762306a36Sopenharmony_ciint nvmem_get_mac_address(struct device *dev, void *addrbuf) 54862306a36Sopenharmony_ci{ 54962306a36Sopenharmony_ci struct nvmem_cell *cell; 55062306a36Sopenharmony_ci const void *mac; 55162306a36Sopenharmony_ci size_t len; 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci cell = nvmem_cell_get(dev, "mac-address"); 55462306a36Sopenharmony_ci if (IS_ERR(cell)) 55562306a36Sopenharmony_ci return PTR_ERR(cell); 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci mac = nvmem_cell_read(cell, &len); 55862306a36Sopenharmony_ci nvmem_cell_put(cell); 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci if (IS_ERR(mac)) 56162306a36Sopenharmony_ci return PTR_ERR(mac); 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci if (len != ETH_ALEN || !is_valid_ether_addr(mac)) { 56462306a36Sopenharmony_ci kfree(mac); 56562306a36Sopenharmony_ci return -EINVAL; 56662306a36Sopenharmony_ci } 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci ether_addr_copy(addrbuf, mac); 56962306a36Sopenharmony_ci kfree(mac); 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci return 0; 57262306a36Sopenharmony_ci} 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_cistatic int fwnode_get_mac_addr(struct fwnode_handle *fwnode, 57562306a36Sopenharmony_ci const char *name, char *addr) 57662306a36Sopenharmony_ci{ 57762306a36Sopenharmony_ci int ret; 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci ret = fwnode_property_read_u8_array(fwnode, name, addr, ETH_ALEN); 58062306a36Sopenharmony_ci if (ret) 58162306a36Sopenharmony_ci return ret; 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci if (!is_valid_ether_addr(addr)) 58462306a36Sopenharmony_ci return -EINVAL; 58562306a36Sopenharmony_ci return 0; 58662306a36Sopenharmony_ci} 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci/** 58962306a36Sopenharmony_ci * fwnode_get_mac_address - Get the MAC from the firmware node 59062306a36Sopenharmony_ci * @fwnode: Pointer to the firmware node 59162306a36Sopenharmony_ci * @addr: Address of buffer to store the MAC in 59262306a36Sopenharmony_ci * 59362306a36Sopenharmony_ci * Search the firmware node for the best MAC address to use. 'mac-address' is 59462306a36Sopenharmony_ci * checked first, because that is supposed to contain to "most recent" MAC 59562306a36Sopenharmony_ci * address. If that isn't set, then 'local-mac-address' is checked next, 59662306a36Sopenharmony_ci * because that is the default address. If that isn't set, then the obsolete 59762306a36Sopenharmony_ci * 'address' is checked, just in case we're using an old device tree. 59862306a36Sopenharmony_ci * 59962306a36Sopenharmony_ci * Note that the 'address' property is supposed to contain a virtual address of 60062306a36Sopenharmony_ci * the register set, but some DTS files have redefined that property to be the 60162306a36Sopenharmony_ci * MAC address. 60262306a36Sopenharmony_ci * 60362306a36Sopenharmony_ci * All-zero MAC addresses are rejected, because those could be properties that 60462306a36Sopenharmony_ci * exist in the firmware tables, but were not updated by the firmware. For 60562306a36Sopenharmony_ci * example, the DTS could define 'mac-address' and 'local-mac-address', with 60662306a36Sopenharmony_ci * zero MAC addresses. Some older U-Boots only initialized 'local-mac-address'. 60762306a36Sopenharmony_ci * In this case, the real MAC is in 'local-mac-address', and 'mac-address' 60862306a36Sopenharmony_ci * exists but is all zeros. 60962306a36Sopenharmony_ci */ 61062306a36Sopenharmony_ciint fwnode_get_mac_address(struct fwnode_handle *fwnode, char *addr) 61162306a36Sopenharmony_ci{ 61262306a36Sopenharmony_ci if (!fwnode_get_mac_addr(fwnode, "mac-address", addr) || 61362306a36Sopenharmony_ci !fwnode_get_mac_addr(fwnode, "local-mac-address", addr) || 61462306a36Sopenharmony_ci !fwnode_get_mac_addr(fwnode, "address", addr)) 61562306a36Sopenharmony_ci return 0; 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci return -ENOENT; 61862306a36Sopenharmony_ci} 61962306a36Sopenharmony_ciEXPORT_SYMBOL(fwnode_get_mac_address); 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci/** 62262306a36Sopenharmony_ci * device_get_mac_address - Get the MAC for a given device 62362306a36Sopenharmony_ci * @dev: Pointer to the device 62462306a36Sopenharmony_ci * @addr: Address of buffer to store the MAC in 62562306a36Sopenharmony_ci */ 62662306a36Sopenharmony_ciint device_get_mac_address(struct device *dev, char *addr) 62762306a36Sopenharmony_ci{ 62862306a36Sopenharmony_ci return fwnode_get_mac_address(dev_fwnode(dev), addr); 62962306a36Sopenharmony_ci} 63062306a36Sopenharmony_ciEXPORT_SYMBOL(device_get_mac_address); 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci/** 63362306a36Sopenharmony_ci * device_get_ethdev_address - Set netdev's MAC address from a given device 63462306a36Sopenharmony_ci * @dev: Pointer to the device 63562306a36Sopenharmony_ci * @netdev: Pointer to netdev to write the address to 63662306a36Sopenharmony_ci * 63762306a36Sopenharmony_ci * Wrapper around device_get_mac_address() which writes the address 63862306a36Sopenharmony_ci * directly to netdev->dev_addr. 63962306a36Sopenharmony_ci */ 64062306a36Sopenharmony_ciint device_get_ethdev_address(struct device *dev, struct net_device *netdev) 64162306a36Sopenharmony_ci{ 64262306a36Sopenharmony_ci u8 addr[ETH_ALEN]; 64362306a36Sopenharmony_ci int ret; 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_ci ret = device_get_mac_address(dev, addr); 64662306a36Sopenharmony_ci if (!ret) 64762306a36Sopenharmony_ci eth_hw_addr_set(netdev, addr); 64862306a36Sopenharmony_ci return ret; 64962306a36Sopenharmony_ci} 65062306a36Sopenharmony_ciEXPORT_SYMBOL(device_get_ethdev_address); 651