lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
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