Skip to content

Commit f3483c8

Browse files
edumazetkuba-moo
authored andcommitted
net: rfs: hash function change
RFS is using two kinds of hash tables. First one is controlled by /proc/sys/net/core/rps_sock_flow_entries = 2^N and using the N low order bits of the l4 hash is good enough. Then each RX queue has its own hash table, controlled by /sys/class/net/eth1/queues/rx-$q/rps_flow_cnt = 2^X Current hash function, using the X low order bits is suboptimal, because RSS is usually using Func(hash) = (hash % power_of_two); For example, with 32 RX queues, 6 low order bits have no entropy for a given queue. Switch this hash function to hash_32(hash, log) to increase chances to use all possible slots and reduce collisions. Signed-off-by: Eric Dumazet <[email protected]> Cc: Tom Herbert <[email protected]> Reviewed-by: Simon Horman <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 1952e19 commit f3483c8

File tree

3 files changed

+12
-7
lines changed

3 files changed

+12
-7
lines changed

include/net/rps.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ struct rps_dev_flow {
3939
* The rps_dev_flow_table structure contains a table of flow mappings.
4040
*/
4141
struct rps_dev_flow_table {
42-
unsigned int mask;
42+
u8 log;
4343
struct rcu_head rcu;
4444
struct rps_dev_flow flows[];
4545
};

net/core/dev.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4751,6 +4751,11 @@ EXPORT_SYMBOL(rps_needed);
47514751
struct static_key_false rfs_needed __read_mostly;
47524752
EXPORT_SYMBOL(rfs_needed);
47534753

4754+
static u32 rfs_slot(u32 hash, const struct rps_dev_flow_table *flow_table)
4755+
{
4756+
return hash_32(hash, flow_table->log);
4757+
}
4758+
47544759
static struct rps_dev_flow *
47554760
set_rps_cpu(struct net_device *dev, struct sk_buff *skb,
47564761
struct rps_dev_flow *rflow, u16 next_cpu)
@@ -4777,7 +4782,7 @@ set_rps_cpu(struct net_device *dev, struct sk_buff *skb,
47774782
flow_table = rcu_dereference(rxqueue->rps_flow_table);
47784783
if (!flow_table)
47794784
goto out;
4780-
flow_id = skb_get_hash(skb) & flow_table->mask;
4785+
flow_id = rfs_slot(skb_get_hash(skb), flow_table);
47814786
rc = dev->netdev_ops->ndo_rx_flow_steer(dev, skb,
47824787
rxq_index, flow_id);
47834788
if (rc < 0)
@@ -4856,7 +4861,7 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb,
48564861
/* OK, now we know there is a match,
48574862
* we can look at the local (per receive queue) flow table
48584863
*/
4859-
rflow = &flow_table->flows[hash & flow_table->mask];
4864+
rflow = &flow_table->flows[rfs_slot(hash, flow_table)];
48604865
tcpu = rflow->cpu;
48614866

48624867
/*
@@ -4923,13 +4928,13 @@ bool rps_may_expire_flow(struct net_device *dev, u16 rxq_index,
49234928

49244929
rcu_read_lock();
49254930
flow_table = rcu_dereference(rxqueue->rps_flow_table);
4926-
if (flow_table && flow_id <= flow_table->mask) {
4931+
if (flow_table && flow_id < (1UL << flow_table->log)) {
49274932
rflow = &flow_table->flows[flow_id];
49284933
cpu = READ_ONCE(rflow->cpu);
49294934
if (READ_ONCE(rflow->filter) == filter_id && cpu < nr_cpu_ids &&
49304935
((int)(READ_ONCE(per_cpu(softnet_data, cpu).input_queue_head) -
49314936
READ_ONCE(rflow->last_qtail)) <
4932-
(int)(10 * flow_table->mask)))
4937+
(int)(10 << flow_table->log)))
49334938
expire = false;
49344939
}
49354940
rcu_read_unlock();

net/core/net-sysfs.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,7 +1056,7 @@ static ssize_t show_rps_dev_flow_table_cnt(struct netdev_rx_queue *queue,
10561056
rcu_read_lock();
10571057
flow_table = rcu_dereference(queue->rps_flow_table);
10581058
if (flow_table)
1059-
val = (unsigned long)flow_table->mask + 1;
1059+
val = 1UL << flow_table->log;
10601060
rcu_read_unlock();
10611061

10621062
return sysfs_emit(buf, "%lu\n", val);
@@ -1109,7 +1109,7 @@ static ssize_t store_rps_dev_flow_table_cnt(struct netdev_rx_queue *queue,
11091109
if (!table)
11101110
return -ENOMEM;
11111111

1112-
table->mask = mask;
1112+
table->log = ilog2(mask) + 1;
11131113
for (count = 0; count <= mask; count++)
11141114
table->flows[count].cpu = RPS_NO_CPU;
11151115
} else {

0 commit comments

Comments
 (0)