aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/dev.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-07-15 06:47:03 -0400
committerDavid S. Miller <davem@davemloft.net>2008-07-17 22:21:13 -0400
commit8f0f2223cc08a5ae9a77f40edfe02e8a9f1abd77 (patch)
tree48185f0e8c5a0d220e33a98fe4ac9b323e25579e /net/core/dev.c
parent51cb6db0f5654f08a4a6bfa3888dc36a51c2df3e (diff)
net: Implement simple sw TX hashing.
It just xor hashes over IPv4/IPv6 addresses and ports of transport. The only assumption it makes is that skb_network_header() is set correctly. With bug fixes from Eric Dumazet. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/dev.c')
-rw-r--r--net/core/dev.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 7ca9564d2f44..467bfb325123 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -121,6 +121,9 @@
121#include <linux/ctype.h> 121#include <linux/ctype.h>
122#include <linux/if_arp.h> 122#include <linux/if_arp.h>
123#include <linux/if_vlan.h> 123#include <linux/if_vlan.h>
124#include <linux/ip.h>
125#include <linux/ipv6.h>
126#include <linux/in.h>
124 127
125#include "net-sysfs.h" 128#include "net-sysfs.h"
126 129
@@ -1665,6 +1668,53 @@ out_kfree_skb:
1665 * --BLG 1668 * --BLG
1666 */ 1669 */
1667 1670
1671static u16 simple_tx_hash(struct net_device *dev, struct sk_buff *skb)
1672{
1673 u32 *addr, *ports, hash, ihl;
1674 u8 ip_proto;
1675 int alen;
1676
1677 switch (skb->protocol) {
1678 case __constant_htons(ETH_P_IP):
1679 ip_proto = ip_hdr(skb)->protocol;
1680 addr = &ip_hdr(skb)->saddr;
1681 ihl = ip_hdr(skb)->ihl;
1682 alen = 2;
1683 break;
1684 case __constant_htons(ETH_P_IPV6):
1685 ip_proto = ipv6_hdr(skb)->nexthdr;
1686 addr = &ipv6_hdr(skb)->saddr.s6_addr32[0];
1687 ihl = (40 >> 2);
1688 alen = 8;
1689 break;
1690 default:
1691 return 0;
1692 }
1693
1694 ports = (u32 *) (skb_network_header(skb) + (ihl * 4));
1695
1696 hash = 0;
1697 while (alen--)
1698 hash ^= *addr++;
1699
1700 switch (ip_proto) {
1701 case IPPROTO_TCP:
1702 case IPPROTO_UDP:
1703 case IPPROTO_DCCP:
1704 case IPPROTO_ESP:
1705 case IPPROTO_AH:
1706 case IPPROTO_SCTP:
1707 case IPPROTO_UDPLITE:
1708 hash ^= *ports;
1709 break;
1710
1711 default:
1712 break;
1713 }
1714
1715 return hash % dev->real_num_tx_queues;
1716}
1717
1668static struct netdev_queue *dev_pick_tx(struct net_device *dev, 1718static struct netdev_queue *dev_pick_tx(struct net_device *dev,
1669 struct sk_buff *skb) 1719 struct sk_buff *skb)
1670{ 1720{
@@ -1672,6 +1722,8 @@ static struct netdev_queue *dev_pick_tx(struct net_device *dev,
1672 1722
1673 if (dev->select_queue) 1723 if (dev->select_queue)
1674 queue_index = dev->select_queue(dev, skb); 1724 queue_index = dev->select_queue(dev, skb);
1725 else if (dev->real_num_tx_queues > 1)
1726 queue_index = simple_tx_hash(dev, skb);
1675 1727
1676 skb_set_queue_mapping(skb, queue_index); 1728 skb_set_queue_mapping(skb, queue_index);
1677 return netdev_get_tx_queue(dev, queue_index); 1729 return netdev_get_tx_queue(dev, queue_index);