Skip to content

Commit

Permalink
net: Get rid of by-hand TX queue hashing.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
David S. Miller committed Jan 28, 2009
1 parent f7105d6 commit 7019298
Showing 1 changed file with 14 additions and 59 deletions.
73 changes: 14 additions & 59 deletions net/core/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -1708,72 +1708,27 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
return 0;
}

static u32 simple_tx_hashrnd;
static int simple_tx_hashrnd_initialized = 0;
static u32 skb_tx_hashrnd;
static int skb_tx_hashrnd_initialized = 0;

static u16 simple_tx_hash(struct net_device *dev, struct sk_buff *skb)
static u16 skb_tx_hash(struct net_device *dev, struct sk_buff *skb)
{
u32 addr1, addr2, ports;
u32 hash, ihl;
u8 ip_proto = 0;
u32 hash;

if (unlikely(!simple_tx_hashrnd_initialized)) {
get_random_bytes(&simple_tx_hashrnd, 4);
simple_tx_hashrnd_initialized = 1;
if (unlikely(!skb_tx_hashrnd_initialized)) {
get_random_bytes(&skb_tx_hashrnd, 4);
skb_tx_hashrnd_initialized = 1;
}

if (skb_rx_queue_recorded(skb)) {
u32 val = skb_get_rx_queue(skb);

hash = jhash_1word(val, simple_tx_hashrnd);
goto out;
}

if (skb->sk && skb->sk->sk_hash) {
u32 val = skb->sk->sk_hash;

hash = jhash_1word(val, simple_tx_hashrnd);
goto out;
}

switch (skb->protocol) {
case htons(ETH_P_IP):
if (!(ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)))
ip_proto = ip_hdr(skb)->protocol;
addr1 = ip_hdr(skb)->saddr;
addr2 = ip_hdr(skb)->daddr;
ihl = ip_hdr(skb)->ihl;
break;
case htons(ETH_P_IPV6):
ip_proto = ipv6_hdr(skb)->nexthdr;
addr1 = ipv6_hdr(skb)->saddr.s6_addr32[3];
addr2 = ipv6_hdr(skb)->daddr.s6_addr32[3];
ihl = (40 >> 2);
break;
default:
return 0;
}


switch (ip_proto) {
case IPPROTO_TCP:
case IPPROTO_UDP:
case IPPROTO_DCCP:
case IPPROTO_ESP:
case IPPROTO_AH:
case IPPROTO_SCTP:
case IPPROTO_UDPLITE:
ports = *((u32 *) (skb_network_header(skb) + (ihl * 4)));
break;

default:
ports = 0;
break;
}
hash = skb_get_rx_queue(skb);
} else if (skb->sk && skb->sk->sk_hash) {
hash = skb->sk->sk_hash;
} else
hash = skb->protocol;

hash = jhash_3words(addr1, addr2, ports, simple_tx_hashrnd);
hash = jhash_1word(hash, skb_tx_hashrnd);

out:
return (u16) (((u64) hash * dev->real_num_tx_queues) >> 32);
}

Expand All @@ -1786,7 +1741,7 @@ static struct netdev_queue *dev_pick_tx(struct net_device *dev,
if (ops->ndo_select_queue)
queue_index = ops->ndo_select_queue(dev, skb);
else if (dev->real_num_tx_queues > 1)
queue_index = simple_tx_hash(dev, skb);
queue_index = skb_tx_hash(dev, skb);

skb_set_queue_mapping(skb, queue_index);
return netdev_get_tx_queue(dev, queue_index);
Expand Down

0 comments on commit 7019298

Please sign in to comment.