[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <4BA16AB8.3090800@google.com>
Date: Wed, 17 Mar 2010 16:50:16 -0700
From: Tom Herbert <therbert@...gle.com>
To: Eric Dumazet <eric.dumazet@...il.com>
CC: Changli Gao <xiaosuo@...il.com>,
David Miller <davem@...emloft.net>, netdev@...r.kernel.org
Subject: Re: [PATCH v7] rps: Receive Packet Steering
>>
>> # echo "0 1 0 1 0 1 1 1 1 1" >/sys/class/net/eth0/queues/rx-0/rps_map
>> # cat /sys/class/net/eth0/queues/rx-0/rps_cpus
>> 3
>> # cat /sys/class/net/eth0/queues/rx-0/rps_map
>> 0 1 0 1 0 1 1 1 1 1
>> # echo 3 >/sys/class/net/eth0/queues/rx-0/rps_cpus
>> # cat /sys/class/net/eth0/queues/rx-0/rps_map
>> 0 1
>
> Alternatively, the rps_map could be specified explicitly, which will
> allow weighting. For example "0 0 0 0 2 10 10 10" would select CPUs
> 0, 2, 10 for the map with weights four, one, and three respectively.
> This would go back to have sysfs files with multiple values in them,
> so it might not be the right interface.
Here is a patch for this...
Allow specification of CPUs in rps to be done with a vector instead of a bit map. This allows relative weighting of CPUs in the map by repeating ones to give higher weight.
For example "echo 0 0 0 3 4 4 4 4 > /sys/class/net/eth0/queues/rx-0/rps_cpus"
assigns CPUs 0, 3, and 4 to the RPS mask with relative weights 3, 1, and 4 respectively.
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 7a46343..41956a5 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -17,6 +17,7 @@
#include <linux/rtnetlink.h>
#include <linux/wireless.h>
#include <net/wext.h>
+#include <linux/ctype.h>
#include "net-sysfs.h"
@@ -514,30 +515,20 @@ static ssize_t show_rps_map(struct netdev_rx_queue *queue,
struct rx_queue_attribute *attribute, char *buf)
{
struct rps_map *map;
- cpumask_var_t mask;
size_t len = 0;
int i;
- if (!zalloc_cpumask_var(&mask, GFP_KERNEL))
- return -ENOMEM;
-
rcu_read_lock();
+
map = rcu_dereference(queue->rps_map);
if (map)
for (i = 0; i < map->len; i++)
- cpumask_set_cpu(map->cpus[i], mask);
+ len += snprintf(buf + len, PAGE_SIZE - len, "%u%s",
+ map->cpus[i], i + 1 < map->len ? " " : "\n");
- len += cpumask_scnprintf(buf + len, PAGE_SIZE, mask);
- if (PAGE_SIZE - len < 3) {
- rcu_read_unlock();
- free_cpumask_var(mask);
- return -EINVAL;
- }
rcu_read_unlock();
- free_cpumask_var(mask);
- len += sprintf(buf + len, "\n");
- return len;
+ return len < PAGE_SIZE ? len : -EINVAL;
}
static void rps_map_release(struct rcu_head *rcu)
@@ -552,41 +543,50 @@ ssize_t store_rps_map(struct netdev_rx_queue *queue,
const char *buf, size_t len)
{
struct rps_map *old_map, *map;
- cpumask_var_t mask;
- int err, cpu, i;
+ int i, count = 0;
+ unsigned int val;
static DEFINE_SPINLOCK(rps_map_lock);
+ char *tbuf;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
- if (!alloc_cpumask_var(&mask, GFP_KERNEL))
- return -ENOMEM;
+ /* Validate and count the number of CPUs in the input list. */
+ tbuf = (char *)buf;
+ while (tbuf < buf + len) {
+ char *rbuf;
- err = bitmap_parse(buf, len, cpumask_bits(mask), nr_cpumask_bits);
- if (err) {
- free_cpumask_var(mask);
- return err;
- }
+ if (isspace(*tbuf)) {
+ tbuf++;
+ continue;
+ }
- map = kzalloc(max_t(unsigned,
- RPS_MAP_SIZE(cpumask_weight(mask)), L1_CACHE_BYTES),
- GFP_KERNEL);
- if (!map) {
- free_cpumask_var(mask);
- return -ENOMEM;
- }
+ val = simple_strtoul(tbuf, &rbuf, 0);
- i = 0;
- for_each_cpu_and(cpu, mask, cpu_online_mask)
- map->cpus[i++] = cpu;
+ if ((tbuf == rbuf) || (val >= num_possible_cpus()))
+ return -EINVAL;
- if (i)
- map->len = i;
- else {
- kfree(map);
- map = NULL;
+ tbuf = rbuf;
+ count++;
}
+ if (count) {
+ map = kzalloc(max_t(unsigned, RPS_MAP_SIZE(count),
+ L1_CACHE_BYTES), GFP_KERNEL);
+ if (!map)
+ return -ENOMEM;
+
+ tbuf = (char *)buf;
+ for (i = 0; i < count; i++) {
+ while (isspace(*tbuf))
+ tbuf++;
+ map->cpus[i] = simple_strtoul(tbuf, &tbuf, 0);
+ }
+ map->len = count;
+ } else
+ map = NULL;
+
+
spin_lock(&rps_map_lock);
old_map = queue->rps_map;
rcu_assign_pointer(queue->rps_map, map);
@@ -595,7 +595,6 @@ ssize_t store_rps_map(struct netdev_rx_queue *queue,
if (old_map)
call_rcu(&old_map->rcu, rps_map_release);
- free_cpumask_var(mask);
return len;
}
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists