merge sock_alloc_fd/sock_attach_fd into a new helper
[safe/jmp/linux-2.6] / net / ethernet / eth.c
index 4bd78c8..dd3db88 100644 (file)
  *             Mark Evans, <evansmp@uhura.aston.ac.uk>
  *             Florian  La Roche, <rzsfl@rz.uni-sb.de>
  *             Alan Cox, <gw4pts@gw4pts.ampr.org>
- * 
+ *
  * Fixes:
  *             Mr Linux        : Arp problems
  *             Alan Cox        : Generic queue tidyup (very tiny here)
  *             Alan Cox        : eth_header ntohs should be htons
  *             Alan Cox        : eth_rebuild_header missing an htons and
  *                               minor other things.
- *             Tegge           : Arp bug fixes. 
+ *             Tegge           : Arp bug fixes.
  *             Florian         : Removed many unnecessary functions, code cleanup
  *                               and changes for new arp and skbuff.
  *             Alan Cox        : Redid header building to reflect new format.
@@ -40,7 +40,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
@@ -58,9 +57,9 @@
 #include <net/sock.h>
 #include <net/ipv6.h>
 #include <net/ip.h>
+#include <net/dsa.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
-#include <asm/checksum.h>
 
 __setup("ether=", netdev_boot_setup);
 
@@ -77,8 +76,9 @@ __setup("ether=", netdev_boot_setup);
  * Set the protocol type. For a packet of type ETH_P_802_3 we put the length
  * in here instead. It is up to the 802.2 layer to carry protocol information.
  */
-int eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
-              void *daddr, void *saddr, unsigned len)
+int eth_header(struct sk_buff *skb, struct net_device *dev,
+              unsigned short type,
+              const void *daddr, const void *saddr, unsigned len)
 {
        struct ethhdr *eth = (struct ethhdr *)skb_push(skb, ETH_HLEN);
 
@@ -93,10 +93,10 @@ int eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
 
        if (!saddr)
                saddr = dev->dev_addr;
-       memcpy(eth->h_source, saddr, dev->addr_len);
+       memcpy(eth->h_source, saddr, ETH_ALEN);
 
        if (daddr) {
-               memcpy(eth->h_dest, daddr, dev->addr_len);
+               memcpy(eth->h_dest, daddr, ETH_ALEN);
                return ETH_HLEN;
        }
 
@@ -105,12 +105,13 @@ int eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
         */
 
        if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) {
-               memset(eth->h_dest, 0, dev->addr_len);
+               memset(eth->h_dest, 0, ETH_ALEN);
                return ETH_HLEN;
        }
 
        return -ETH_HLEN;
 }
+EXPORT_SYMBOL(eth_header);
 
 /**
  * eth_rebuild_header- rebuild the Ethernet MAC header.
@@ -129,7 +130,7 @@ int eth_rebuild_header(struct sk_buff *skb)
 
        switch (eth->h_proto) {
 #ifdef CONFIG_INET
-       case __constant_htons(ETH_P_IP):
+       case htons(ETH_P_IP):
                return arp_find(eth->h_dest, skb);
 #endif
        default:
@@ -137,12 +138,13 @@ int eth_rebuild_header(struct sk_buff *skb)
                       "%s: unable to resolve type %X addresses.\n",
                       dev->name, (int)eth->h_proto);
 
-               memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
+               memcpy(eth->h_source, dev->dev_addr, ETH_ALEN);
                break;
        }
 
        return 0;
 }
+EXPORT_SYMBOL(eth_rebuild_header);
 
 /**
  * eth_type_trans - determine the packet's protocol ID.
@@ -158,12 +160,13 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)
        struct ethhdr *eth;
        unsigned char *rawp;
 
-       skb->mac.raw = skb->data;
+       skb->dev = dev;
+       skb_reset_mac_header(skb);
        skb_pull(skb, ETH_HLEN);
        eth = eth_hdr(skb);
 
-       if (is_multicast_ether_addr(eth->h_dest)) {
-               if (!compare_ether_addr(eth->h_dest, dev->broadcast))
+       if (unlikely(is_multicast_ether_addr(eth->h_dest))) {
+               if (!compare_ether_addr_64bits(eth->h_dest, dev->broadcast))
                        skb->pkt_type = PACKET_BROADCAST;
                else
                        skb->pkt_type = PACKET_MULTICAST;
@@ -178,10 +181,21 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)
         */
 
        else if (1 /*dev->flags&IFF_PROMISC */ ) {
-               if (unlikely(compare_ether_addr(eth->h_dest, dev->dev_addr)))
+               if (unlikely(compare_ether_addr_64bits(eth->h_dest, dev->dev_addr)))
                        skb->pkt_type = PACKET_OTHERHOST;
        }
 
+       /*
+        * Some variants of DSA tagging don't have an ethertype field
+        * at all, so we check here whether one of those tagging
+        * 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))
+               return htons(ETH_P_DSA);
+       if (netdev_uses_trailer_tags(dev))
+               return htons(ETH_P_TRAILER);
+
        if (ntohs(eth->h_proto) >= 1536)
                return eth->h_proto;
 
@@ -208,12 +222,13 @@ EXPORT_SYMBOL(eth_type_trans);
  * @skb: packet to extract header from
  * @haddr: destination buffer
  */
-static int eth_header_parse(struct sk_buff *skb, unsigned char *haddr)
+int eth_header_parse(const struct sk_buff *skb, unsigned char *haddr)
 {
-       struct ethhdr *eth = eth_hdr(skb);
+       const struct ethhdr *eth = eth_hdr(skb);
        memcpy(haddr, eth->h_source, ETH_ALEN);
        return ETH_ALEN;
 }
+EXPORT_SYMBOL(eth_header_parse);
 
 /**
  * eth_header_cache - fill cache entry from neighbour
@@ -221,24 +236,25 @@ static int eth_header_parse(struct sk_buff *skb, unsigned char *haddr)
  * @hh: destination cache entry
  * Create an Ethernet header template from the neighbour.
  */
-int eth_header_cache(struct neighbour *neigh, struct hh_cache *hh)
+int eth_header_cache(const struct neighbour *neigh, struct hh_cache *hh)
 {
        __be16 type = hh->hh_type;
        struct ethhdr *eth;
-       struct net_device *dev = neigh->dev;
+       const struct net_device *dev = neigh->dev;
 
        eth = (struct ethhdr *)
            (((u8 *) hh->hh_data) + (HH_DATA_OFF(sizeof(*eth))));
 
-       if (type == __constant_htons(ETH_P_802_3))
+       if (type == htons(ETH_P_802_3))
                return -1;
 
        eth->h_proto = type;
-       memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
-       memcpy(eth->h_dest, neigh->ha, dev->addr_len);
+       memcpy(eth->h_source, dev->dev_addr, ETH_ALEN);
+       memcpy(eth->h_dest, neigh->ha, ETH_ALEN);
        hh->hh_len = ETH_HLEN;
        return 0;
 }
+EXPORT_SYMBOL(eth_header_cache);
 
 /**
  * eth_header_cache_update - update cache entry
@@ -248,12 +264,14 @@ int eth_header_cache(struct neighbour *neigh, struct hh_cache *hh)
  *
  * Called by Address Resolution module to notify changes in address.
  */
-void eth_header_cache_update(struct hh_cache *hh, struct net_device *dev,
-                            unsigned char *haddr)
+void eth_header_cache_update(struct hh_cache *hh,
+                            const struct net_device *dev,
+                            const unsigned char *haddr)
 {
        memcpy(((u8 *) hh->hh_data) + HH_DATA_OFF(sizeof(struct ethhdr)),
-              haddr, dev->addr_len);
+              haddr, ETH_ALEN);
 }
+EXPORT_SYMBOL(eth_header_cache_update);
 
 /**
  * eth_mac_addr - set new Ethernet hardware address
@@ -264,14 +282,18 @@ void eth_header_cache_update(struct hh_cache *hh, struct net_device *dev,
  * This doesn't change hardware matching, so needs to be overridden
  * for most real devices.
  */
-static int eth_mac_addr(struct net_device *dev, void *p)
+int eth_mac_addr(struct net_device *dev, void *p)
 {
        struct sockaddr *addr = p;
+
        if (netif_running(dev))
                return -EBUSY;
-       memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+       if (!is_valid_ether_addr(addr->sa_data))
+               return -EADDRNOTAVAIL;
+       memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
        return 0;
 }
+EXPORT_SYMBOL(eth_mac_addr);
 
 /**
  * eth_change_mtu - set new MTU size
@@ -281,13 +303,31 @@ static int eth_mac_addr(struct net_device *dev, void *p)
  * Allow changing MTU size. Needs to be overridden for devices
  * supporting jumbo frames.
  */
-static int eth_change_mtu(struct net_device *dev, int new_mtu)
+int eth_change_mtu(struct net_device *dev, int new_mtu)
 {
        if (new_mtu < 68 || new_mtu > ETH_DATA_LEN)
                return -EINVAL;
        dev->mtu = new_mtu;
        return 0;
 }
+EXPORT_SYMBOL(eth_change_mtu);
+
+int eth_validate_addr(struct net_device *dev)
+{
+       if (!is_valid_ether_addr(dev->dev_addr))
+               return -EADDRNOTAVAIL;
+
+       return 0;
+}
+EXPORT_SYMBOL(eth_validate_addr);
+
+const struct header_ops eth_header_ops ____cacheline_aligned = {
+       .create         = eth_header,
+       .parse          = eth_header_parse,
+       .rebuild        = eth_rebuild_header,
+       .cache          = eth_header_cache,
+       .cache_update   = eth_header_cache_update,
+};
 
 /**
  * ether_setup - setup Ethernet network device
@@ -296,30 +336,24 @@ static int eth_change_mtu(struct net_device *dev, int new_mtu)
  */
 void ether_setup(struct net_device *dev)
 {
-       dev->change_mtu         = eth_change_mtu;
-       dev->hard_header        = eth_header;
-       dev->rebuild_header     = eth_rebuild_header;
-       dev->set_mac_address    = eth_mac_addr;
-       dev->hard_header_cache  = eth_header_cache;
-       dev->header_cache_update= eth_header_cache_update;
-       dev->hard_header_parse  = eth_header_parse;
-
+       dev->header_ops         = &eth_header_ops;
        dev->type               = ARPHRD_ETHER;
        dev->hard_header_len    = ETH_HLEN;
        dev->mtu                = ETH_DATA_LEN;
        dev->addr_len           = ETH_ALEN;
-       dev->tx_queue_len       = 1000; /* Ethernet wants good queues */        
+       dev->tx_queue_len       = 1000; /* Ethernet wants good queues */
        dev->flags              = IFF_BROADCAST|IFF_MULTICAST;
-       
+
        memset(dev->broadcast, 0xFF, ETH_ALEN);
 
 }
 EXPORT_SYMBOL(ether_setup);
 
 /**
- * alloc_etherdev - Allocates and sets up an Ethernet device
+ * alloc_etherdev_mq - 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.
  *
  * Fill in the fields of the device structure with Ethernet-generic
  * values. Basically does everything except registering the device.
@@ -329,8 +363,33 @@ EXPORT_SYMBOL(ether_setup);
  * this private data area.
  */
 
-struct net_device *alloc_etherdev(int sizeof_priv)
+struct net_device *alloc_etherdev_mq(int sizeof_priv, unsigned int queue_count)
+{
+       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)
 {
-       return alloc_netdev(sizeof_priv, "eth%d", ether_setup);
+       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 += strlcpy(cp, ":", buflen - (cp - buf));
+       }
+       return cp - buf;
+}
+
+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 += strlcpy(buf + l, "\n", PAGE_SIZE - l);
+       return ((ssize_t) l);
 }
-EXPORT_SYMBOL(alloc_etherdev);
+EXPORT_SYMBOL(sysfs_format_mac);