#include <net/sock.h>
#include <net/ipv6.h>
#include <net/ip.h>
+#include <net/dsa.h>
#include <asm/uaccess.h>
#include <asm/system.h>
* 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);
return -ETH_HLEN;
}
+EXPORT_SYMBOL(eth_header);
/**
* eth_rebuild_header- rebuild the Ethernet MAC header.
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:
return 0;
}
+EXPORT_SYMBOL(eth_rebuild_header);
/**
* eth_type_trans - determine the packet's protocol ID.
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;
*/
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;
* @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
* @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))));
hh->hh_len = ETH_HLEN;
return 0;
}
+EXPORT_SYMBOL(eth_header_cache);
/**
* eth_header_cache_update - update cache entry
*
* 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, ETH_ALEN);
}
+EXPORT_SYMBOL(eth_header_cache_update);
/**
* eth_mac_addr - set new Ethernet hardware address
* 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;
memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
return 0;
}
+EXPORT_SYMBOL(eth_mac_addr);
/**
* eth_change_mtu - set new MTU size
* 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
*/
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 = ð_header_ops;
dev->type = ARPHRD_ETHER;
dev->hard_header_len = ETH_HLEN;
dev->mtu = ETH_DATA_LEN;
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 += 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(sysfs_format_mac);
+
+char *print_mac(char *buf, const unsigned char *addr)
+{
+ _format_mac_addr(buf, MAC_BUF_SIZE, addr, ETH_ALEN);
+ return buf;
+}
+EXPORT_SYMBOL(print_mac);