diff options
Diffstat (limited to 'net/ethernet/eth.c')
| -rw-r--r-- | net/ethernet/eth.c | 121 | 
1 files changed, 65 insertions, 56 deletions
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index f00ef2f1d81..5dc638cad2e 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c @@ -58,8 +58,7 @@  #include <net/ipv6.h>  #include <net/ip.h>  #include <net/dsa.h> -#include <asm/uaccess.h> -#include <asm/system.h> +#include <linux/uaccess.h>  __setup("ether=", netdev_boot_setup); @@ -78,7 +77,7 @@ __setup("ether=", netdev_boot_setup);   */  int eth_header(struct sk_buff *skb, struct net_device *dev,  	       unsigned short type, -	       const void *daddr, const void *saddr, unsigned len) +	       const void *daddr, const void *saddr, unsigned int len)  {  	struct ethhdr *eth = (struct ethhdr *)skb_push(skb, ETH_HLEN); @@ -134,7 +133,7 @@ int eth_rebuild_header(struct sk_buff *skb)  		return arp_find(eth->h_dest, skb);  #endif  	default: -		printk(KERN_DEBUG +		netdev_dbg(dev,  		       "%s: unable to resolve type %X addresses.\n",  		       dev->name, ntohs(eth->h_proto)); @@ -157,7 +156,9 @@ EXPORT_SYMBOL(eth_rebuild_header);   */  __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)  { -	struct ethhdr *eth; +	unsigned short _service_access_point; +	const unsigned short *sap; +	const struct ethhdr *eth;  	skb->dev = dev;  	skb_reset_mac_header(skb); @@ -165,24 +166,14 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)  	eth = eth_hdr(skb);  	if (unlikely(is_multicast_ether_addr(eth->h_dest))) { -		if (!compare_ether_addr_64bits(eth->h_dest, dev->broadcast)) +		if (ether_addr_equal_64bits(eth->h_dest, dev->broadcast))  			skb->pkt_type = PACKET_BROADCAST;  		else  			skb->pkt_type = PACKET_MULTICAST;  	} - -	/* -	 *      This ALLMULTI check should be redundant by 1.4 -	 *      so don't forget to remove it. -	 * -	 *      Seems, you forgot to remove it. All silly devices -	 *      seems to set IFF_PROMISC. -	 */ - -	else if (1 /*dev->flags&IFF_PROMISC */ ) { -		if (unlikely(compare_ether_addr_64bits(eth->h_dest, dev->dev_addr))) -			skb->pkt_type = PACKET_OTHERHOST; -	} +	else if (unlikely(!ether_addr_equal_64bits(eth->h_dest, +						   dev->dev_addr))) +		skb->pkt_type = PACKET_OTHERHOST;  	/*  	 * Some variants of DSA tagging don't have an ethertype field @@ -190,12 +181,13 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)  	 * variants has been configured on the receiving interface,  	 * and if so, set skb->protocol without looking at the packet.  	 */ -	if (netdev_uses_dsa_tags(dev)) +	if (unlikely(netdev_uses_dsa_tags(dev)))  		return htons(ETH_P_DSA); -	if (netdev_uses_trailer_tags(dev)) + +	if (unlikely(netdev_uses_trailer_tags(dev)))  		return htons(ETH_P_TRAILER); -	if (ntohs(eth->h_proto) >= 1536) +	if (likely(ntohs(eth->h_proto) >= ETH_P_802_3_MIN))  		return eth->h_proto;  	/* @@ -204,7 +196,8 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)  	 *      layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This  	 *      won't work for fault tolerant netware but does for the rest.  	 */ -	if (skb->len >= 2 && *(unsigned short *)(skb->data) == 0xFFFF) +	sap = skb_header_pointer(skb, 0, sizeof(*sap), &_service_access_point); +	if (sap && *sap == 0xFFFF)  		return htons(ETH_P_802_3);  	/* @@ -231,11 +224,12 @@ EXPORT_SYMBOL(eth_header_parse);   * eth_header_cache - fill cache entry from neighbour   * @neigh: source neighbour   * @hh: destination cache entry + * @type: Ethernet type field + *   * Create an Ethernet header template from the neighbour.   */ -int eth_header_cache(const struct neighbour *neigh, struct hh_cache *hh) +int eth_header_cache(const struct neighbour *neigh, struct hh_cache *hh, __be16 type)  { -	__be16 type = hh->hh_type;  	struct ethhdr *eth;  	const struct net_device *dev = neigh->dev; @@ -271,9 +265,40 @@ void eth_header_cache_update(struct hh_cache *hh,  EXPORT_SYMBOL(eth_header_cache_update);  /** + * eth_prepare_mac_addr_change - prepare for mac change + * @dev: network device + * @p: socket address + */ +int eth_prepare_mac_addr_change(struct net_device *dev, void *p) +{ +	struct sockaddr *addr = p; + +	if (!(dev->priv_flags & IFF_LIVE_ADDR_CHANGE) && netif_running(dev)) +		return -EBUSY; +	if (!is_valid_ether_addr(addr->sa_data)) +		return -EADDRNOTAVAIL; +	return 0; +} +EXPORT_SYMBOL(eth_prepare_mac_addr_change); + +/** + * eth_commit_mac_addr_change - commit mac change + * @dev: network device + * @p: socket address + */ +void eth_commit_mac_addr_change(struct net_device *dev, void *p) +{ +	struct sockaddr *addr = p; + +	memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); +} +EXPORT_SYMBOL(eth_commit_mac_addr_change); + +/**   * eth_mac_addr - set new Ethernet hardware address   * @dev: network device   * @p: socket address + *   * Change hardware address of device.   *   * This doesn't change hardware matching, so needs to be overridden @@ -281,13 +306,12 @@ EXPORT_SYMBOL(eth_header_cache_update);   */  int eth_mac_addr(struct net_device *dev, void *p)  { -	struct sockaddr *addr = p; +	int ret; -	if (netif_running(dev)) -		return -EBUSY; -	if (!is_valid_ether_addr(addr->sa_data)) -		return -EADDRNOTAVAIL; -	memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); +	ret = eth_prepare_mac_addr_change(dev, p); +	if (ret < 0) +		return ret; +	eth_commit_mac_addr_change(dev, p);  	return 0;  }  EXPORT_SYMBOL(eth_mac_addr); @@ -329,6 +353,7 @@ const struct header_ops eth_header_ops ____cacheline_aligned = {  /**   * ether_setup - setup Ethernet network device   * @dev: network device + *   * Fill in the fields of the device structure with Ethernet-generic values.   */  void ether_setup(struct net_device *dev) @@ -340,6 +365,7 @@ void ether_setup(struct net_device *dev)  	dev->addr_len		= ETH_ALEN;  	dev->tx_queue_len	= 1000;	/* Ethernet wants good queues */  	dev->flags		= IFF_BROADCAST|IFF_MULTICAST; +	dev->priv_flags		|= IFF_TX_SKB_SHARING;  	memset(dev->broadcast, 0xFF, ETH_ALEN); @@ -347,10 +373,11 @@ void ether_setup(struct net_device *dev)  EXPORT_SYMBOL(ether_setup);  /** - * alloc_etherdev_mq - Allocates and sets up an Ethernet device + * alloc_etherdev_mqs - Allocates and sets up an Ethernet device   * @sizeof_priv: Size of additional driver-private structure to be allocated   *	for this Ethernet device - * @queue_count: The number of queues this device has. + * @txqs: The number of TX queues this device has. + * @rxqs: The number of RX queues this device has.   *   * Fill in the fields of the device structure with Ethernet-generic   * values. Basically does everything except registering the device. @@ -360,33 +387,15 @@ EXPORT_SYMBOL(ether_setup);   * this private data area.   */ -struct net_device *alloc_etherdev_mq(int sizeof_priv, unsigned int queue_count) +struct net_device *alloc_etherdev_mqs(int sizeof_priv, unsigned int txqs, +				      unsigned int rxqs)  { -	return alloc_netdev_mq(sizeof_priv, "eth%d", ether_setup, queue_count); -} -EXPORT_SYMBOL(alloc_etherdev_mq); - -static size_t _format_mac_addr(char *buf, int buflen, -			       const unsigned char *addr, int len) -{ -	int i; -	char *cp = buf; - -	for (i = 0; i < len; i++) { -		cp += scnprintf(cp, buflen - (cp - buf), "%02x", addr[i]); -		if (i == len - 1) -			break; -		cp += scnprintf(cp, buflen - (cp - buf), ":"); -	} -	return cp - buf; +	return alloc_netdev_mqs(sizeof_priv, "eth%d", ether_setup, txqs, rxqs);  } +EXPORT_SYMBOL(alloc_etherdev_mqs);  ssize_t sysfs_format_mac(char *buf, const unsigned char *addr, int len)  { -	size_t l; - -	l = _format_mac_addr(buf, PAGE_SIZE, addr, len); -	l += scnprintf(buf + l, PAGE_SIZE - l, "\n"); -	return (ssize_t)l; +	return scnprintf(buf, PAGE_SIZE, "%*phC\n", len, addr);  }  EXPORT_SYMBOL(sysfs_format_mac);  | 
