aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/dev.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2009-01-27 19:34:47 -0500
committerDavid S. Miller <davem@davemloft.net>2009-01-27 19:34:47 -0500
commit7019298a2a5058c4e324494d6c8d0598214c28f4 (patch)
treefec5e5cf9c5caacc83fc929f978896938ff199a4 /net/core/dev.c
parentf7105d63940899ece79bda024f668e6c761cfebf (diff)
net: Get rid of by-hand TX queue hashing.
We now only TX hash on pre-computed SKB properties. The thinking is: 1) High performance routing and firewalling setups will have a multiqueue capable card used for receive, and therefore would have RX queue recordings made into the SKB which can be used for the TX side hash. 2) Locally generated packets will have an attached socket and thus a valid sk->sk_hash to make use of. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/dev.c')
-rw-r--r--net/core/dev.c73
1 files changed, 14 insertions, 59 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index cb8caa93caca..e61b95c11fc0 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1708,72 +1708,27 @@ out_kfree_skb:
1708 return 0; 1708 return 0;
1709} 1709}
1710 1710
1711static u32 simple_tx_hashrnd; 1711static u32 skb_tx_hashrnd;
1712static int simple_tx_hashrnd_initialized = 0; 1712static int skb_tx_hashrnd_initialized = 0;
1713 1713
1714static u16 simple_tx_hash(struct net_device *dev, struct sk_buff *skb) 1714static u16 skb_tx_hash(struct net_device *dev, struct sk_buff *skb)
1715{ 1715{
1716 u32 addr1, addr2, ports; 1716 u32 hash;
1717 u32 hash, ihl;
1718 u8 ip_proto = 0;
1719 1717
1720 if (unlikely(!simple_tx_hashrnd_initialized)) { 1718 if (unlikely(!skb_tx_hashrnd_initialized)) {
1721 get_random_bytes(&simple_tx_hashrnd, 4); 1719 get_random_bytes(&skb_tx_hashrnd, 4);
1722 simple_tx_hashrnd_initialized = 1; 1720 skb_tx_hashrnd_initialized = 1;
1723 } 1721 }
1724 1722
1725 if (skb_rx_queue_recorded(skb)) { 1723 if (skb_rx_queue_recorded(skb)) {
1726 u32 val = skb_get_rx_queue(skb); 1724 hash = skb_get_rx_queue(skb);
1727 1725 } else if (skb->sk && skb->sk->sk_hash) {
1728 hash = jhash_1word(val, simple_tx_hashrnd); 1726 hash = skb->sk->sk_hash;
1729 goto out; 1727 } else
1730 } 1728 hash = skb->protocol;
1731
1732 if (skb->sk && skb->sk->sk_hash) {
1733 u32 val = skb->sk->sk_hash;
1734
1735 hash = jhash_1word(val, simple_tx_hashrnd);
1736 goto out;
1737 }
1738
1739 switch (skb->protocol) {
1740 case htons(ETH_P_IP):
1741 if (!(ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)))
1742 ip_proto = ip_hdr(skb)->protocol;
1743 addr1 = ip_hdr(skb)->saddr;
1744 addr2 = ip_hdr(skb)->daddr;
1745 ihl = ip_hdr(skb)->ihl;
1746 break;
1747 case htons(ETH_P_IPV6):
1748 ip_proto = ipv6_hdr(skb)->nexthdr;
1749 addr1 = ipv6_hdr(skb)->saddr.s6_addr32[3];
1750 addr2 = ipv6_hdr(skb)->daddr.s6_addr32[3];
1751 ihl = (40 >> 2);
1752 break;
1753 default:
1754 return 0;
1755 }
1756
1757
1758 switch (ip_proto) {
1759 case IPPROTO_TCP:
1760 case IPPROTO_UDP:
1761 case IPPROTO_DCCP:
1762 case IPPROTO_ESP:
1763 case IPPROTO_AH:
1764 case IPPROTO_SCTP:
1765 case IPPROTO_UDPLITE:
1766 ports = *((u32 *) (skb_network_header(skb) + (ihl * 4)));
1767 break;
1768
1769 default:
1770 ports = 0;
1771 break;
1772 }
1773 1729
1774 hash = jhash_3words(addr1, addr2, ports, simple_tx_hashrnd); 1730 hash = jhash_1word(hash, skb_tx_hashrnd);
1775 1731
1776out:
1777 return (u16) (((u64) hash * dev->real_num_tx_queues) >> 32); 1732 return (u16) (((u64) hash * dev->real_num_tx_queues) >> 32);
1778} 1733}
1779 1734
@@ -1786,7 +1741,7 @@ static struct netdev_queue *dev_pick_tx(struct net_device *dev,
1786 if (ops->ndo_select_queue) 1741 if (ops->ndo_select_queue)
1787 queue_index = ops->ndo_select_queue(dev, skb); 1742 queue_index = ops->ndo_select_queue(dev, skb);
1788 else if (dev->real_num_tx_queues > 1) 1743 else if (dev->real_num_tx_queues > 1)
1789 queue_index = simple_tx_hash(dev, skb); 1744 queue_index = skb_tx_hash(dev, skb);
1790 1745
1791 skb_set_queue_mapping(skb, queue_index); 1746 skb_set_queue_mapping(skb, queue_index);
1792 return netdev_get_tx_queue(dev, queue_index); 1747 return netdev_get_tx_queue(dev, queue_index);