From: Tom Herbert <therbert@google.com>
To: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Changli Gao <xiaosuo@gmail.com>,
David Miller <davem@davemloft.net>,
netdev@vger.kernel.org
Subject: Re: [PATCH v7] rps: Receive Packet Steering
Date: Wed, 17 Mar 2010 16:50:16 -0700 [thread overview]
Message-ID: <4BA16AB8.3090800@google.com> (raw)
In-Reply-To: <65634d661003170801x1042a6am563c9d937ba672a4@mail.gmail.com>
>>
>> # 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;
}
next prev parent reply other threads:[~2010-03-17 23:50 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-03-12 20:13 [PATCH v7] rps: Receive Packet Steering Tom Herbert
2010-03-12 21:28 ` Eric Dumazet
2010-03-12 23:08 ` Tom Herbert
2010-03-16 18:03 ` Tom Herbert
2010-03-16 21:00 ` Eric Dumazet
2010-03-16 21:13 ` David Miller
2010-03-17 1:54 ` Changli Gao
2010-03-17 7:07 ` Eric Dumazet
2010-03-17 7:59 ` Changli Gao
2010-03-17 14:09 ` Eric Dumazet
2010-03-17 15:01 ` Tom Herbert
2010-03-17 15:34 ` Eric Dumazet
2010-03-17 23:50 ` Tom Herbert [this message]
2010-03-18 2:14 ` Changli Gao
2010-03-18 6:30 ` Eric Dumazet
2010-03-18 6:20 ` Eric Dumazet
2010-03-18 6:48 ` Changli Gao
2010-03-18 20:37 ` Eric Dumazet
2010-03-18 21:23 ` Stephen Hemminger
2010-03-17 4:26 ` David Miller
2010-03-12 22:20 ` Stephen Hemminger
2010-03-12 22:32 ` David Miller
2010-03-12 22:23 ` Stephen Hemminger
2010-03-12 22:33 ` David Miller
2010-03-12 23:05 ` Tom Herbert
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4BA16AB8.3090800@google.com \
--to=therbert@google.com \
--cc=davem@davemloft.net \
--cc=eric.dumazet@gmail.com \
--cc=netdev@vger.kernel.org \
--cc=xiaosuo@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).