netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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;
 }

  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).