* [IPV4 3/5] fib_trie: dump doesnt use RCU
From: Stephen Hemminger @ 2008-01-23 22:48 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20080123224844.610730277@linux-foundation.org>
[-- Attachment #1: fib-dump-rtnl.patch --]
[-- Type: text/plain, Size: 3261 bytes --]
Since fib dump (via netlink) holds the RTNL mutex, it is unnecessary
to use RCU, and it is impossible to get truncated (-EBUSY) result.
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
--- a/net/ipv4/fib_trie.c 2008-01-23 13:55:12.000000000 -0800
+++ b/net/ipv4/fib_trie.c 2008-01-23 14:00:35.000000000 -0800
@@ -1684,7 +1684,7 @@ static int trie_flush_leaf(struct trie *
* Scan for the next right leaf starting at node p->child[idx]
* Since we have back pointer, no recursion necessary.
*/
-static struct leaf *leaf_walk_rcu(struct tnode *p, struct node *c)
+static struct leaf *leaf_walk(struct tnode *p, struct node *c)
{
do {
t_key idx;
@@ -1695,7 +1695,7 @@ static struct leaf *leaf_walk_rcu(struct
idx = 0;
while (idx < 1u << p->bits) {
- c = tnode_get_child_rcu(p, idx++);
+ c = tnode_get_child(p, idx++);
if (!c)
continue;
@@ -1711,14 +1711,14 @@ static struct leaf *leaf_walk_rcu(struct
/* Node empty, walk back up to parent */
c = (struct node *) p;
- } while ( (p = node_parent_rcu(c)) != NULL);
+ } while ( (p = node_parent(c)) != NULL);
return NULL; /* Root of trie */
}
static struct leaf *trie_firstleaf(struct trie *t)
{
- struct tnode *n = (struct tnode *) rcu_dereference(t->trie);
+ struct tnode *n = (struct tnode *) t->trie;
if (!n)
return NULL;
@@ -1726,7 +1726,7 @@ static struct leaf *trie_firstleaf(struc
if (IS_LEAF(n)) /* trie is just a leaf */
return (struct leaf *) n;
- return leaf_walk_rcu(n, NULL);
+ return leaf_walk(n, NULL);
}
static struct leaf *trie_nextleaf(struct leaf *l)
@@ -1737,7 +1737,7 @@ static struct leaf *trie_nextleaf(struct
if (!p)
return NULL; /* trie with just one leaf */
- return leaf_walk_rcu(p, c);
+ return leaf_walk(p, c);
}
/*
@@ -1848,9 +1848,7 @@ static int fn_trie_dump_fa(t_key key, in
s_i = cb->args[4];
i = 0;
- /* rcu_read_lock is hold by caller */
-
- list_for_each_entry_rcu(fa, fah, fa_list) {
+ list_for_each_entry(fa, fah, fa_list) {
if (i < s_i) {
i++;
continue;
@@ -1885,8 +1883,7 @@ static int fn_trie_dump_leaf(struct leaf
s_i = cb->args[3];
i = 0;
- /* rcu_read_lock is hold by caller */
- hlist_for_each_entry_rcu(li, node, &l->list, hlist) {
+ hlist_for_each_entry(li, node, &l->list, hlist) {
if (i < s_i) {
i++;
continue;
@@ -1916,35 +1913,25 @@ static int fn_trie_dump(struct fib_table
struct trie *t = (struct trie *) tb->tb_data;
t_key key = cb->args[2];
- rcu_read_lock();
+ ASSERT_RTNL();
+
/* Dump starting at last key.
* Note: 0.0.0.0/0 (ie default) is first key.
*/
if (!key)
l = trie_firstleaf(t);
- else {
+ else
l = fib_find_node(t, key);
- if (!l) {
- /* The table changed during the dump, rather than
- * giving partial data, just make application retry.
- */
- rcu_read_unlock();
- return -EBUSY;
- }
- }
while (l) {
cb->args[2] = l->key;
- if (fn_trie_dump_leaf(l, tb, skb, cb) < 0) {
- rcu_read_unlock();
+ if (fn_trie_dump_leaf(l, tb, skb, cb) < 0)
return -1;
- }
l = trie_nextleaf(l);
memset(&cb->args[3], 0,
sizeof(cb->args) - 3*sizeof(cb->args[0]));
}
- rcu_read_unlock();
return skb->len;
}
--
Stephen Hemminger <stephen.hemminger@vyatta.com>
^ permalink raw reply
* [IPV4 4/5] fib_trie: version 0.410
From: Stephen Hemminger @ 2008-01-23 22:48 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20080123224844.610730277@linux-foundation.org>
[-- Attachment #1: fib-trie-minor.patch --]
[-- Type: text/plain, Size: 450 bytes --]
Increase version to reflect recent changes.
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
--- a/net/ipv4/fib_trie.c 2008-01-22 17:50:58.000000000 -0800
+++ b/net/ipv4/fib_trie.c 2008-01-22 17:51:02.000000000 -0800
@@ -50,7 +50,7 @@
* Patrick McHardy <kaber@trash.net>
*/
-#define VERSION "0.408"
+#define VERSION "0.410"
#include <asm/uaccess.h>
#include <asm/system.h>
--
Stephen Hemminger <stephen.hemminger@vyatta.com>
^ permalink raw reply
* [IPV4 5/5] fib_semantics: sparse warnings
From: Stephen Hemminger @ 2008-01-23 22:48 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20080123224844.610730277@linux-foundation.org>
[-- Attachment #1: fib-semantic-sparse.patch --]
[-- Type: text/plain, Size: 1824 bytes --]
The magic macro change_nexthops introduces a variable nh which overlaps
previous declaration of nh.
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
--- a/net/ipv4/fib_semantics.c 2008-01-23 11:03:55.000000000 -0800
+++ b/net/ipv4/fib_semantics.c 2008-01-23 11:05:12.000000000 -0800
@@ -1059,14 +1059,14 @@ int fib_sync_down(__be32 local, struct n
unsigned int hash = fib_devindex_hashfn(dev->ifindex);
struct hlist_head *head = &fib_info_devhash[hash];
struct hlist_node *node;
- struct fib_nh *nh;
+ struct fib_nh *nh1;
- hlist_for_each_entry(nh, node, head, nh_hash) {
- struct fib_info *fi = nh->nh_parent;
+ hlist_for_each_entry(nh1, node, head, nh_hash) {
+ struct fib_info *fi = nh1->nh_parent;
int dead;
BUG_ON(!fi->fib_nhs);
- if (nh->nh_dev != dev || fi == prev_fi)
+ if (nh1->nh_dev != dev || fi == prev_fi)
continue;
prev_fi = fi;
dead = 0;
@@ -1091,6 +1091,7 @@ int fib_sync_down(__be32 local, struct n
}
#endif
} endfor_nexthops(fi)
+
if (dead == fi->fib_nhs) {
fi->fib_flags |= RTNH_F_DEAD;
ret++;
@@ -1114,7 +1115,7 @@ int fib_sync_up(struct net_device *dev)
unsigned int hash;
struct hlist_head *head;
struct hlist_node *node;
- struct fib_nh *nh;
+ struct fib_nh *nh1;
int ret;
if (!(dev->flags&IFF_UP))
@@ -1125,12 +1126,12 @@ int fib_sync_up(struct net_device *dev)
head = &fib_info_devhash[hash];
ret = 0;
- hlist_for_each_entry(nh, node, head, nh_hash) {
- struct fib_info *fi = nh->nh_parent;
+ hlist_for_each_entry(nh1, node, head, nh_hash) {
+ struct fib_info *fi = nh1->nh_parent;
int alive;
BUG_ON(!fi->fib_nhs);
- if (nh->nh_dev != dev || fi == prev_fi)
+ if (nh1->nh_dev != dev || fi == prev_fi)
continue;
prev_fi = fi;
--
Stephen Hemminger <stephen.hemminger@vyatta.com>
^ permalink raw reply
* [IPV4 1/5] fib_trie: more whitespace cleanup
From: Stephen Hemminger @ 2008-01-23 22:48 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20080123224844.610730277@linux-foundation.org>
[-- Attachment #1: trie-whitespace.patch --]
[-- Type: text/plain, Size: 1454 bytes --]
Remove extra blank lines.
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
--- a/net/ipv4/fib_trie.c 2008-01-22 17:46:28.000000000 -0800
+++ b/net/ipv4/fib_trie.c 2008-01-22 17:50:44.000000000 -0800
@@ -447,7 +447,6 @@ static void tnode_put_child_reorg(struct
BUG_ON(i >= 1<<tn->bits);
-
/* update emptyChildren */
if (n == NULL && chi != NULL)
tn->empty_children++;
@@ -1303,7 +1302,6 @@ err:
return err;
}
-
/* should be called with rcu_read_lock */
static int check_leaf(struct trie *t, struct leaf *l,
t_key key, const struct flowi *flp,
@@ -1718,7 +1716,6 @@ static struct leaf *leaf_walk_rcu(struct
return NULL; /* Root of trie */
}
-
static struct leaf *trie_firstleaf(struct trie *t)
{
struct tnode *n = (struct tnode *) rcu_dereference(t->trie);
@@ -1846,7 +1843,6 @@ static int fn_trie_dump_fa(t_key key, in
{
int i, s_i;
struct fib_alias *fa;
-
__be32 xkey = htonl(key);
s_i = cb->args[4];
@@ -1879,7 +1875,6 @@ static int fn_trie_dump_fa(t_key key, in
return skb->len;
}
-
static int fn_trie_dump_leaf(struct leaf *l, struct fib_table *tb,
struct sk_buff *skb, struct netlink_callback *cb)
{
@@ -2385,7 +2380,6 @@ static int fib_trie_seq_show(struct seq_
struct leaf *l = (struct leaf *) n;
struct leaf_info *li;
struct hlist_node *node;
-
__be32 val = htonl(l->key);
seq_indent(seq, iter->depth);
--
Stephen Hemminger <stephen.hemminger@vyatta.com>
^ permalink raw reply
* [IPV4 2/5] fib_trie: remove unneeded NULL check
From: Stephen Hemminger @ 2008-01-23 22:48 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20080123224844.610730277@linux-foundation.org>
[-- Attachment #1: trie-already-hlist.patch --]
[-- Type: text/plain, Size: 535 bytes --]
Since fib_route_seq_show now uses hlist_for_each_entry(), the
leaf info can not be NULL.
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
--- a/net/ipv4/fib_trie.c 2008-01-22 17:50:44.000000000 -0800
+++ b/net/ipv4/fib_trie.c 2008-01-22 17:50:58.000000000 -0800
@@ -2474,9 +2474,6 @@ static int fib_route_seq_show(struct seq
struct fib_alias *fa;
__be32 mask, prefix;
- if (!li)
- continue;
-
mask = inet_make_mask(li->plen);
prefix = htonl(l->key);
--
Stephen Hemminger <stephen.hemminger@vyatta.com>
^ permalink raw reply
* Re: [PATCH] BUG_ON() bad input to request_irq
From: Rusty Russell @ 2008-01-23 22:15 UTC (permalink / raw)
To: Andrew Morton; +Cc: jeff, netdev, linux-kernel
In-Reply-To: <20080123140414.e1ff2263.akpm@linux-foundation.org>
On Thursday 24 January 2008 09:04:14 Andrew Morton wrote:
> > On Thu, 17 Jan 2008 17:59:58 +1100 Rusty Russell <rusty@rustcorp.com.au>
> If no driver is passing in args which will trigger this BUG, we presumably
> don't need the patch.
You're only thinking of current code. The BUG catches future changes, too.
> If some driver _is_ passing in args which will trigger these BUGs then it is
> presumably working OK anyway. Taking a working system and making it go BUG
> is likely to upset people.
That's why I did the audit. See patch below which preceeded it, which Jeff
hasn't responded to. Breaking his drivers might make him notice :)
> IOW: WARN_ON, please.
At end of cycles, sure, but not for 2.6.25: they're even more invisible than
deprecated warnings :(
Rusty.
===
request_irq() always returns -EINVAL with a NULL handler.
I assume that these ancient network drivers were trying to find out if
an irq is available. eepro.c expecting +EBUSY was doubly wrong.
Request_irq should BUG() on bad input, and these would have been found
earlier.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
---
drivers/net/3c503.c | 2 +-
drivers/net/e2100.c | 2 +-
drivers/net/eepro.c | 2 +-
drivers/net/hp.c | 2 +-
kernel/irq/manage.c | 1 +
5 files changed, 5 insertions(+), 4 deletions(-)
diff -r 0b7e4fbb6238 drivers/net/3c503.c
--- a/drivers/net/3c503.c Thu Jan 17 15:49:34 2008 +1100
+++ b/drivers/net/3c503.c Thu Jan 17 16:40:28 2008 +1100
@@ -379,7 +379,7 @@ el2_open(struct net_device *dev)
outb(EGACFR_NORM, E33G_GACFR); /* Enable RAM and interrupts. */
do {
- if (request_irq (*irqp, NULL, 0, "bogus", dev) != -EBUSY) {
+ if (can_request_irq(*irqp, 0)) {
/* Twinkle the interrupt, and check if it's seen. */
unsigned long cookie = probe_irq_on();
outb_p(0x04 << ((*irqp == 9) ? 2 : *irqp), E33G_IDCFR);
diff -r 0b7e4fbb6238 drivers/net/e2100.c
--- a/drivers/net/e2100.c Thu Jan 17 15:49:34 2008 +1100
+++ b/drivers/net/e2100.c Thu Jan 17 16:40:28 2008 +1100
@@ -202,7 +202,7 @@ static int __init e21_probe1(struct net_
if (dev->irq < 2) {
int irqlist[] = {15,11,10,12,5,9,3,4}, i;
for (i = 0; i < 8; i++)
- if (request_irq (irqlist[i], NULL, 0, "bogus", NULL) != -EBUSY) {
+ if (can_request_irq(irqlist[i], 0)) {
dev->irq = irqlist[i];
break;
}
diff -r 0b7e4fbb6238 drivers/net/eepro.c
--- a/drivers/net/eepro.c Thu Jan 17 15:49:34 2008 +1100
+++ b/drivers/net/eepro.c Thu Jan 17 16:40:28 2008 +1100
@@ -914,7 +914,7 @@ static int eepro_grab_irq(struct net_dev
eepro_sw2bank0(ioaddr); /* Switch back to Bank 0 */
- if (request_irq (*irqp, NULL, IRQF_SHARED, "bogus", dev) != EBUSY) {
+ if (can_request_irq(*irqp, IRQF_SHARED)) {
unsigned long irq_mask;
/* Twinkle the interrupt, and check if it's seen */
irq_mask = probe_irq_on();
diff -r 0b7e4fbb6238 drivers/net/hp.c
--- a/drivers/net/hp.c Thu Jan 17 15:49:34 2008 +1100
+++ b/drivers/net/hp.c Thu Jan 17 16:40:28 2008 +1100
@@ -170,7 +170,7 @@ static int __init hp_probe1(struct net_d
int *irqp = wordmode ? irq_16list : irq_8list;
do {
int irq = *irqp;
- if (request_irq (irq, NULL, 0, "bogus", NULL) != -EBUSY) {
+ if (can_request_irq(irq, 0)) {
unsigned long cookie = probe_irq_on();
/* Twinkle the interrupt, and check if it's seen. */
outb_p(irqmap[irq] | HP_RUN, ioaddr + HP_CONFIGURE);
diff -r 0b7e4fbb6238 kernel/irq/manage.c
--- a/kernel/irq/manage.c Thu Jan 17 15:49:34 2008 +1100
+++ b/kernel/irq/manage.c Thu Jan 17 16:40:28 2008 +1100
@@ -252,6 +252,7 @@ int can_request_irq(unsigned int irq, un
return !action;
}
+EXPORT_SYMBOL(can_request_irq);
void compat_irq_chip_set_default_handler(struct irq_desc *desc)
{
^ permalink raw reply
* Re: [PATCH] bluetooth : move children of connection device to NULL before connection down
From: Andrew Morton @ 2008-01-23 22:06 UTC (permalink / raw)
To: Marcel Holtmann
Cc: davem, hidave.darkstar, netdev, linux-kernel, bluez-devel,
cornelia.huck, gombasg, htejun, viro, kay.sievers, greg
In-Reply-To: <1200982696.7978.148.camel@aeonflux>
> On Tue, 22 Jan 2008 07:18:16 +0100 Marcel Holtmann <marcel@holtmann.org> wrote:
> Hi Dave,
>
> > > Add people missed in cc-list.
> >
> > Thanks Dave for your continued efforts on Bluetooth bugs like this.
> >
> > Marcel, are you going to review/ACK/integrate/push-upstream/whatever
> > any of these Bluetooth patches?
> >
> > It hasn't been getting much love from you as of late, you are one of
> > the listed maintainers, and I don't want to lose any of Dave's
> > valuable bug fixing work.
>
> I will be fully back in business next week. Just got stuck in a project
> that needed 200% of my time to get it going.
>
These patches in -mm:
bluetooth-hidp_process_hid_control-remove-unnecessary-parameter-dealing.patch
bluetooth-uninlining.patch
drivers-bluetooth-bpa10xc-fix-memleak.patch
drivers-bluetooth-btsdioc-fix-double-free.patch
bluetooth-blacklist-another-broadcom-bcm2035-device.patch
bluetooth-rfcomm-tty_close-before-destruct.patch
hci_ldisc-fix-null-pointer-deref.patch
could benefit from some attention please.
^ permalink raw reply
* Re: [PATCH] BUG_ON() bad input to request_irq
From: Andrew Morton @ 2008-01-23 22:04 UTC (permalink / raw)
To: Rusty Russell; +Cc: jeff, netdev, linux-kernel
In-Reply-To: <200801171759.59029.rusty@rustcorp.com.au>
> On Thu, 17 Jan 2008 17:59:58 +1100 Rusty Russell <rusty@rustcorp.com.au> wrote:
> Is there any reason why these bugs should be treated gently? The
> caller might not want to check NR_IRQS and IRQ_NOREQUEST cases, but
> a NULL handler or NULL dev_id w/ shared are coding bugs.
>
> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
> ---
> kernel/irq/manage.c | 7 +++----
> 1 file changed, 3 insertions(+), 4 deletions(-)
>
> diff -r c2eb8ef5a0be kernel/irq/manage.c
> --- a/kernel/irq/manage.c Thu Jan 17 15:48:03 2008 +1100
> +++ b/kernel/irq/manage.c Thu Jan 17 15:49:33 2008 +1100
> @@ -532,13 +532,12 @@ int request_irq(unsigned int irq, irq_ha
> * which interrupt is which (messes up the interrupt freeing
> * logic etc).
> */
> - if ((irqflags & IRQF_SHARED) && !dev_id)
> - return -EINVAL;
> + BUG_ON((irqflags & IRQF_SHARED) && !dev_id);
> + BUG_ON(!handler);
> +
> if (irq >= NR_IRQS)
> return -EINVAL;
> if (irq_desc[irq].status & IRQ_NOREQUEST)
> - return -EINVAL;
> - if (!handler)
> return -EINVAL;
>
> action = kmalloc(sizeof(struct irqaction), GFP_ATOMIC);
If no driver is passing in args which will trigger this BUG, we presumably
don't need the patch.
If some driver _is_ passing in ags which will trigger these BUGs then it is
presumably working OK anyway. Taking a working system and making it go BUG
is likely to upset people.
IOW: WARN_ON, please.
^ permalink raw reply
* arping
From: Michaelian Ennis @ 2008-01-23 22:03 UTC (permalink / raw)
To: netdev
Someone filed a bug at bugs.gentoo.org reflecting a possible
enhancement to arping. In short the patches author felt that select
should be used instead of signals to avoid missing a timeout.
The bug is located at:
http://bugs.gentoo.org/show_bug.cgi?id=144526
The diff follows:
--- arping.c 2006-08-20 19:14:39.000000000 -0500
+++ /var/tmp/portage/iputils-021109-r3/work/iputils/arping.c 2006-08-20
19:17:40.000000000 -0500
@@ -7,9 +7,6 @@
* 2 of the License, or (at your option) any later version.
*
* Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
- * 2006.08.18 erik quanstrom <quanstro@quanstro.net>
- * use select instead of signals so timeouts will work.
- *
*/
#include <stdlib.h>
@@ -18,6 +15,7 @@
#include <linux/sockios.h>
#include <sys/file.h>
#include <sys/time.h>
+#include <sys/signal.h>
#include <sys/ioctl.h>
#include <linux/if.h>
#include <linux/if_arp.h>
@@ -31,12 +29,12 @@
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
-#include <stdarg.h>
#include "SNAPSHOT.h"
static void usage(void) __attribute__((noreturn));
+int quit_on_reply=0;
char *device="eth0";
int ifindex;
char *source;
@@ -45,10 +43,7 @@
int dad, unsolicited, advert;
int quiet;
int count=-1;
-int ntosend=-1;
-int ntorecv=-1;
int timeout;
-struct timeval timeouttv;
int unicasting;
int s;
int broadcast_only;
@@ -64,19 +59,6 @@
#define MS_TDIFF(tv1,tv2) ( ((tv1).tv_sec-(tv2).tv_sec)*1000 + \
((tv1).tv_usec-(tv2).tv_usec)/1000 )
-#define pkttrace(...) /* fprintf(stderr, __VA_ARGS__) */
-
-void
-errexit(int err, const char* fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
- exit(err);
-}
-
void usage(void)
{
fprintf(stderr,
@@ -97,6 +79,16 @@
exit(2);
}
+void set_signal(int signo, void (*handler)(void))
+{
+ struct sigaction sa;
+
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = (void (*)(int))handler;
+ sa.sa_flags = SA_RESTART;
+ sigaction(signo, &sa, NULL);
+}
+
int send_pack(int s, struct in_addr src, struct in_addr dst,
struct sockaddr_ll *ME, struct sockaddr_ll *HE)
{
@@ -130,9 +122,7 @@
p+=4;
gettimeofday(&now, NULL);
- pkttrace("sendto->\n");
err = sendto(s, buf, p-buf, 0, (struct sockaddr*)HE, sizeof(*HE));
- pkttrace("sendto<-\n");
if (err == p-buf) {
last = now;
sent++;
@@ -145,20 +135,20 @@
void finish(void)
{
if (!quiet) {
- fflush(stdout);
- fprintf(stderr, "Sent %d probes (%d broadcast(s))\n", sent, brd_sent);
- fprintf(stderr, "Received %d response(s)", received);
+ printf("Sent %d probes (%d broadcast(s))\n", sent, brd_sent);
+ printf("Received %d response(s)", received);
if (brd_recv || req_recv) {
- fprintf(stderr, " (");
+ printf(" (");
if (req_recv)
- fprintf(stderr, "%d request(s)", req_recv);
+ printf("%d request(s)", req_recv);
if (brd_recv)
- fprintf(stderr, "%s%d broadcast(s)",
+ printf("%s%d broadcast(s)",
req_recv ? ", " : "",
brd_recv);
- fprintf(stderr, ")");
+ printf(")");
}
- fprintf(stderr, "\n");
+ printf("\n");
+ fflush(stdout);
}
if (dad)
exit(!!received);
@@ -167,13 +157,34 @@
exit(!received);
}
+void catcher(void)
+{
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+
+ if (start.tv_sec==0)
+ start = tv;
+
+ if (count-- == 0 || (timeout && MS_TDIFF(tv,start) > timeout*1000 + 500))
+ finish();
+
+ if (last.tv_sec==0 || MS_TDIFF(tv,last) > 500) {
+ send_pack(s, src, dst, &me, &he);
+ if (count == 0 && unsolicited)
+ finish();
+ }
+ alarm(1);
+}
+
void print_hex(unsigned char *p, int len)
{
int i;
- for (i=0; i<len-1; i++)
- printf("%02X:", p[i]);
- if(len)
+ for (i=0; i<len; i++) {
printf("%02X", p[i]);
+ if (i != len-1)
+ printf(":");
+ }
}
int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
@@ -274,6 +285,8 @@
brd_recv++;
if (ah->ar_op == htons(ARPOP_REQUEST))
req_recv++;
+ if (quit_on_reply)
+ finish();
if(!broadcast_only) {
memcpy(he.sll_addr, p, me.sll_halen);
unicasting=1;
@@ -281,75 +294,26 @@
return 1;
}
-
-unsigned char packet[4096]; // too big for stack on some arch.
-
-void
-pktloop(void)
-{
- struct sockaddr_ll from;
- socklen_t alen = sizeof(from);
- fd_set rset;
- struct timeval tmo;
- int cc, i;
-
- for(;;){
- if(ntosend-- == 0)
- break;
- send_pack(s, src, dst, &me, &he);
-
- gettimeofday(&tmo, 0);
- if(timeout)
- i = MS_TDIFF(timeouttv, tmo) ;
- else
- i = 1000;
- if(i < 0)
- break;
- if(i > 1000)
- i = 1000; // maximum select 1s.
- tmo.tv_sec = i/1000;
- tmo.tv_usec = (i%1000)*1000;
-
- FD_ZERO(&rset);
- FD_SET(s, &rset);
- pkttrace("select %d ; %d\n", (int)tmo.tv_sec, (int)tmo.tv_usec);
- i = select(s+1, &rset, 0, 0, &tmo);
- pkttrace("<- select\n");
- if(i == -1){
- perror("arping: select");
- exit(1);
- }
- if(i == 0){
- gettimeofday(&tmo, 0);
- i = MS_TDIFF(timeouttv, tmo);
- if(timeout && i <= 0)
- break;
- continue;
- }
- if ((cc = recvfrom(s, packet, sizeof(packet), 0,
- (struct sockaddr *)&from, &alen)) < 0) {
- perror("arping: recvfrom");
- continue;
- }
- if(recv_pack(packet, cc, &from))
- if(--ntorecv == 0)
- break;
- }
-}
-
int
main(int argc, char **argv)
{
- int ch, onereply;
+ int socket_errno;
+ int ch;
+ uid_t uid = getuid();
+
+ s = socket(PF_PACKET, SOCK_DGRAM, 0);
+ socket_errno = errno;
+
+ setuid(uid);
while ((ch = getopt(argc, argv, "h?bfDUAqc:w:s:I:V")) != EOF) {
switch(ch) {
case 'b':
- broadcast_only = 1;
+ broadcast_only=1;
break;
case 'D':
dad++;
- onereply = 1;
+ quit_on_reply=1;
break;
case 'U':
unsolicited++;
@@ -365,15 +329,13 @@
count = atoi(optarg);
break;
case 'w':
- gettimeofday(&timeouttv, 0);
- timeouttv.tv_sec += atoi(optarg);
- timeout = 1;
+ timeout = atoi(optarg);
break;
case 'I':
device = optarg;
break;
case 'f':
- onereply = 1;
+ quit_on_reply=1;
break;
case 's':
source = optarg;
@@ -392,26 +354,19 @@
if (argc != 1)
usage();
- target = *argv;
- if(onereply)
- ntorecv = 1;
- if(timeout) // strange ping compatability.
- ntorecv = count;
- else
- ntosend = count;
+ target = *argv;
- if (device == 0) {
+ if (device == NULL) {
fprintf(stderr, "arping: device (option -I) is required\n");
usage();
}
- s = socket(PF_PACKET, SOCK_DGRAM, 0);
if (s < 0) {
+ errno = socket_errno;
perror("arping: socket");
exit(2);
}
- setuid(getuid());
if (1) {
struct ifreq ifr;
@@ -424,13 +379,19 @@
ifindex = ifr.ifr_ifindex;
if (ioctl(s, SIOCGIFFLAGS, (char*)&ifr)) {
- perror("arping: ioctl(SIOCGIFFLAGS)");
+ perror("ioctl(SIOCGIFFLAGS)");
exit(2);
}
- if (!(ifr.ifr_flags&IFF_UP))
- errexit(2, "Interface \"%s\" is down\n", device);
- if (ifr.ifr_flags&(IFF_NOARP|IFF_LOOPBACK))
- errexit(dad ? 0 : 2, "Interface \"%s\" is not ARPable\n", device);
+ if (!(ifr.ifr_flags&IFF_UP)) {
+ if (!quiet)
+ printf("Interface \"%s\" is down\n", device);
+ exit(2);
+ }
+ if (ifr.ifr_flags&(IFF_NOARP|IFF_LOOPBACK)) {
+ if (!quiet)
+ printf("Interface \"%s\" is not ARPable\n", device);
+ exit(dad?0:2);
+ }
}
if (inet_aton(target, &dst) != 1) {
@@ -456,7 +417,7 @@
int probe_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (probe_fd < 0) {
- perror("arping: socket");
+ perror("socket");
exit(2);
}
if (device) {
@@ -468,7 +429,7 @@
if (src.s_addr) {
saddr.sin_addr = src;
if (bind(probe_fd, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) {
- perror("arping: bind");
+ perror("bind");
exit(2);
}
} else if (!dad) {
@@ -481,11 +442,11 @@
if (setsockopt(probe_fd, SOL_SOCKET, SO_DONTROUTE, (char*)&on,
sizeof(on)) == -1)
perror("WARNING: setsockopt(SO_DONTROUTE)");
if (connect(probe_fd, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) {
- perror("arping: connect");
+ perror("connect");
exit(2);
}
if (getsockname(probe_fd, (struct sockaddr*)&saddr, &alen) == -1) {
- perror("arping: getsockname");
+ perror("getsockname");
exit(2);
}
src = saddr.sin_addr;
@@ -497,34 +458,60 @@
me.sll_ifindex = ifindex;
me.sll_protocol = htons(ETH_P_ARP);
if (bind(s, (struct sockaddr*)&me, sizeof(me)) == -1) {
- perror("arping: bind");
+ perror("bind");
exit(2);
}
if (1) {
socklen_t alen = sizeof(me);
if (getsockname(s, (struct sockaddr*)&me, &alen) == -1) {
- perror("arping: getsockname");
+ perror("getsockname");
exit(2);
}
}
- if (me.sll_halen == 0)
- errexit(dad ? 0 : 2, "Interface \"%s\" is not ARPable (no ll
address)\n", device);
+ if (me.sll_halen == 0) {
+ if (!quiet)
+ printf("Interface \"%s\" is not ARPable (no ll address)\n", device);
+ exit(dad?0:2);
+ }
he = me;
memset(he.sll_addr, -1, he.sll_halen);
if (!quiet) {
- fprintf(stderr, "ARPING %s ", inet_ntoa(dst));
- fprintf(stderr, "from %s %s\n", inet_ntoa(src), device ? : "");
+ printf("ARPING %s ", inet_ntoa(dst));
+ printf("from %s %s\n", inet_ntoa(src), device ? : "");
}
- if (!src.s_addr && !dad)
- errexit(2, "arping: no source address in not-DAD mode\n");
+ if (!src.s_addr && !dad) {
+ fprintf(stderr, "arping: no source address in not-DAD mode\n");
+ exit(2);
+ }
+
+ set_signal(SIGINT, finish);
+ set_signal(SIGALRM, catcher);
+
+ catcher();
- pktloop();
- finish();
- return 1; // shut up gcc.
+ while(1) {
+ sigset_t sset, osset;
+ unsigned char packet[4096];
+ struct sockaddr_ll from;
+ socklen_t alen = sizeof(from);
+ int cc;
+
+ if ((cc = recvfrom(s, packet, sizeof(packet), 0,
+ (struct sockaddr *)&from, &alen)) < 0) {
+ perror("arping: recvfrom");
+ continue;
+ }
+ sigemptyset(&sset);
+ sigaddset(&sset, SIGALRM);
+ sigaddset(&sset, SIGINT);
+ sigprocmask(SIG_BLOCK, &sset, &osset);
+ recv_pack(packet, cc, &from);
+ sigprocmask(SIG_SETMASK, &osset, NULL);
+ }
}
^ permalink raw reply
* RE: [PATCH 2.6.25 1/1]S2io: Multiqueue network device support implementation
From: Ramkrishna Vepa @ 2008-01-23 20:48 UTC (permalink / raw)
To: Andi Kleen, Sreenivasa Honnur; +Cc: netdev, jeff, support
In-Reply-To: <p73odbclsft.fsf@crumb.suse.de>
> Sreenivasa Honnur <Sreenivasa.Honnur@neterion.com> writes:
>
> > Multiqueue netwrok device support implementation.
> > - Added a loadable parameter "multiq" to enable/disable multiqueue
> support,
> > by default it is disabled.
> > - skb->queue_mapping is not used for queue/fifo selection. FIFO
> iselection is
> > based on IP-TOS value, 0x0-0xF TOS values are mapped to 8 FIFOs.
>
> Standard way to use that would be using skb->priority
[Ram] Thanks. We can use this field to determine the priority. It should
simplify the code.
>
> But I'm surprised you bother with TOS for multi queues at all. TOS
> isn't a too important mechanism.
[Ram] Agreed TOS is not too important. The purpose of this patch was to
add the multiqueue functionality with a feature that can use it. With
multiple transmit fifos enabled, a whole new set of features that can be
enabled.
>
> I would have thought the primary use case would be per CPU TX
completion
> interrupts. With that the queue should be selected based on
> the the current CPU.
>
[Ram] I am assuming that this is with regards to msi-x interrupts. We
have done away with handling tx completion in the interrupt handler, and
are instead handling them in the context of the transmit. The slow path,
straggling transmit completions will be handled in the timer context.
This patch (along with other new features) will be sent soon.
Ram
> -Andi
^ permalink raw reply
* Re: [PATCH] [IPV4] route: fix locking in rt_run_flush()
From: Eric Dumazet @ 2008-01-23 20:44 UTC (permalink / raw)
To: joonwpark81; +Cc: David Miller, netdev
In-Reply-To: <20080123074320.GB9017@ehus.geninetworks.com>
joonwpark81@gmail.com a écrit :
> On Mon, Jan 21, 2008 at 02:40:43AM -0800, David Miller wrote:
>> From: Joonwoo Park <joonwpark81@gmail.com>
>> Date: Tue, 22 Jan 2008 00:08:57 +0900
>>
>>> The rt_run_flush() can be stucked if it was called while netdev is on the
>>> high load.
>>> It's possible when pushing rtable to rt_hash is faster than pulling
>>> from it.
>>>
>>> Signed-off-by: Joonwoo Park <joonwpark81@gmail.com>
>> I agree with the analysis of the problem, however not the solution.
>>
>> This will absolutely kill software interrupt latency.
>>
>> In fact, we have moved much of the flush work into a workqueue in
>> net-2.6.25 because of how important that is
>>
>> We need to find some other way to solve this.
>>
>
> Dave, Eric,
> Thanks so much for comments.
>
> I did stress tests and I found that the real problem was not consumer & supplier
> issue.
> It was the problem for me to innumerable enabling & disabling the softirq.
> But I'm still thinking need of considering issue 'faster caching than flush'. :)
>
> ifconfig up on heavy loaded interface.
> Before patching:
> time ifconfig eth1 up
> BUG: soft lockup - CPU#0 stuck for 11s! [events/0:9]
> ...
>
> After patching:
> time ifconfig eth1 up
> real 0m0.007s
> user 0m0.000s
> sys 0m0.004s
>
> Thanks!
> Joonwoo
>
>
>>From 87c29506de967e811ad5b57cd2e1a002134e878f Mon Sep 17 00:00:00 2001
> From: Joonwoo Park <joonwpark81@gmail.com>
> Date: Wed, 23 Jan 2008 15:16:54 +0900
> Subject: [PATCH] [IPV4] route: reduce locking/unlocking in rt_run_flush
>
> The rt_run_flush does spin_lock_bh/spin_unlock_bh for rt_hash_mask + 1
> times.
> The rt_hash_mask takes from 32767 to 65535, so it's big overhead.
> In addition, disable_bh/enable_bh for many times in the rt_run_flush
> can cause stuck on a machine with heavily pended softirqs.
>
> This patch reduces locking/unlocking as doing it with jumping the lock
> slots.
>
> ifconfig up on heavy loaded interface.
> Before:
> time ifconfig eth1 up
> BUG: soft lockup - CPU#0 stuck for 11s! [events/0:9]
> ...
>
> After:
> time ifconfig eth1 up
> real 0m0.007s
> user 0m0.000s
> sys 0m0.004s
>
Unfortunatly, your patch doesnt work on CONFIG_SMP=n (softirq will be disabled
for the whole scan of table)
Also, some machines around there have 2^22 slots in hash table, and NR_CPUS=4,
so softirqs will be disabled for a too long time.
Please try net-2.6.25 and submit patches on top of it if necessary, since
rt_run_flush() has pending changes, not in net-2.6
Note : The 'soft lockup' can be avoided by other means.
^ permalink raw reply
* arp queries and ipsec policy
From: Marco Berizzi @ 2008-01-23 20:37 UTC (permalink / raw)
To: netdev
Hello everybody.
I'm using openswan 2.4.x to drive the linux 2.4.23.14 ipsec
native stack (netkey).
Openswan by default insert a static route when an ipsec SA
is established: this is needed by the klips stack as it is
routing based. For example when a roadwarrior establish
an ipsec SA with the linux box I see a static route like
this:
# ip r s
road_warrior_public_ip dev eth0 scope link
This static route is placed by the default updown script.
When there is this route, I see linux doing arp queries for
the road_warrior_public_ip:
# tcpdump -pnvi eth0 arp
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes
17:25:11.608179 arp who-has road_warrior_public_ip tell linux_public_ip_address
17:25:12.608171 arp who-has road_warrior_public_ip tell linux_public_ip_address
17:25:13.608224 arp who-has road_warrior_public_ip tell linux_public_ip_address
Is this behaviour expected?
I have seen this behaviour today because the ISP router
isn't configured with proxy_arp and linux is unable to
send the ESP packets because the is no arp reply from nobody.
However it is able to receive/decrypt them:
# tcpdump -pnvi eth0 ip host road_warrior_public_ip
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes
17:24:55.107497 IP (tos 0x0, ttl 120, id 55048, offset 0, flags [none], proto:
ESP (50), length: 112) road_warrior_public_ip > linux_public_ip_address:
ESP(spi=0xe215d75f,seq=0x25), length 92
17:24:55.109304 IP (tos 0x0, ttl 128, id 2262, offset 0, flags [none], proto:
ICMP (1), length: 60) road_warrior_public_ip > 172.25.5.4: ICMP echo request,
id 512, seq 50694, length 40
I have resolved the problem modifying the updown script so
it doesn't place the static route anymore.
PS: default parameters for eth0 on /proc except proxy_arp,
arp_announce and rp_filter
^ permalink raw reply
* [PATCH 1/3] pasemi_mac: Add support for changing mac address
From: Olof Johansson @ 2008-01-23 19:56 UTC (permalink / raw)
To: jgarzik; +Cc: netdev
In-Reply-To: <20080123195537.GA32380@lixom.net>
Straightforward. It used to be hardcoded and impossible to override
with ifconfig.
Signed-off-by: Olof Johansson <olof@lixom.net>
diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c
index bb88a41..59dea3f 100644
--- a/drivers/net/pasemi_mac.c
+++ b/drivers/net/pasemi_mac.c
@@ -221,6 +221,33 @@ static int pasemi_get_mac_addr(struct pasemi_mac *mac)
return 0;
}
+static int pasemi_mac_set_mac_addr(struct net_device *dev, void *p)
+{
+ struct pasemi_mac *mac = netdev_priv(dev);
+ struct sockaddr *addr = p;
+ unsigned int adr0, adr1;
+
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EINVAL;
+
+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+ adr0 = dev->dev_addr[2] << 24 |
+ dev->dev_addr[3] << 16 |
+ dev->dev_addr[4] << 8 |
+ dev->dev_addr[5];
+ adr1 = read_mac_reg(mac, PAS_MAC_CFG_ADR1);
+ adr1 &= ~0xffff;
+ adr1 |= dev->dev_addr[0] << 8 | dev->dev_addr[1];
+
+ pasemi_mac_intf_disable(mac);
+ write_mac_reg(mac, PAS_MAC_CFG_ADR0, adr0);
+ write_mac_reg(mac, PAS_MAC_CFG_ADR1, adr1);
+ pasemi_mac_intf_enable(mac);
+
+ return 0;
+}
+
static int get_skb_hdr(struct sk_buff *skb, void **iphdr,
void **tcph, u64 *hdr_flags, void *data)
{
@@ -1475,6 +1502,7 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
dev->stop = pasemi_mac_close;
dev->hard_start_xmit = pasemi_mac_start_tx;
dev->set_multicast_list = pasemi_mac_set_rx_mode;
+ dev->set_mac_address = pasemi_mac_set_mac_addr;
if (err)
goto out;
diff --git a/drivers/net/pasemi_mac.h b/drivers/net/pasemi_mac.h
index 8bee2a6..39d3259 100644
--- a/drivers/net/pasemi_mac.h
+++ b/drivers/net/pasemi_mac.h
@@ -96,6 +96,8 @@ struct pasemi_mac_buffer {
/* MAC CFG register offsets */
enum {
PAS_MAC_CFG_PCFG = 0x80,
+ PAS_MAC_CFG_ADR0 = 0x8c,
+ PAS_MAC_CFG_ADR1 = 0x90,
PAS_MAC_CFG_TXP = 0x98,
PAS_MAC_IPC_CHNL = 0x208,
};
^ permalink raw reply related
* [PATCH 3/3] pasemi_mac: Disable interface on close
From: Olof Johansson @ 2008-01-23 19:57 UTC (permalink / raw)
To: jgarzik; +Cc: netdev
In-Reply-To: <20080123195537.GA32380@lixom.net>
Turns out we never disable the interface. It doesn't really cause
any problems since the channel is off, but it's still better to do it
this way.
Signed-off-by: Olof Johansson <olof@lixom.net>
diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c
index 059c6b0..2e39e02 100644
--- a/drivers/net/pasemi_mac.c
+++ b/drivers/net/pasemi_mac.c
@@ -1287,6 +1287,7 @@ static int pasemi_mac_close(struct net_device *dev)
pasemi_mac_pause_txchan(mac);
pasemi_mac_pause_rxint(mac);
pasemi_mac_pause_rxchan(mac);
+ pasemi_mac_intf_disable(mac);
free_irq(mac->tx->chan.irq, mac->tx);
free_irq(mac->rx->chan.irq, mac->rx);
^ permalink raw reply related
* [PATCH 2/3] pasemi_mac: add support for setting MTU
From: Olof Johansson @ 2008-01-23 19:56 UTC (permalink / raw)
To: jgarzik; +Cc: netdev
In-Reply-To: <20080123195537.GA32380@lixom.net>
Currently keeping it at 1500 bytes or below since jumbo frames need
special checksum offload on TX.
Signed-off-by: Olof Johansson <olof@lixom.net>
diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c
index 59dea3f..059c6b0 100644
--- a/drivers/net/pasemi_mac.c
+++ b/drivers/net/pasemi_mac.c
@@ -62,6 +62,10 @@
#define LRO_MAX_AGGR 64
+#define PE_MIN_MTU 64
+#define PE_MAX_MTU 1500
+#define PE_DEF_MTU ETH_DATA_LEN
+
#define DEFAULT_MSG_ENABLE \
(NETIF_MSG_DRV | \
NETIF_MSG_PROBE | \
@@ -82,8 +86,6 @@
& ((ring)->size - 1))
#define RING_AVAIL(ring) ((ring->size) - RING_USED(ring))
-#define BUF_SIZE 1646 /* 1500 MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */
-
MODULE_LICENSE("GPL");
MODULE_AUTHOR ("Olof Johansson <olof@lixom.net>");
MODULE_DESCRIPTION("PA Semi PWRficient Ethernet driver");
@@ -175,6 +177,24 @@ static int mac_to_intf(struct pasemi_mac *mac)
return -1;
}
+static void pasemi_mac_intf_disable(struct pasemi_mac *mac)
+{
+ unsigned int flags;
+
+ flags = read_mac_reg(mac, PAS_MAC_CFG_PCFG);
+ flags &= ~PAS_MAC_CFG_PCFG_PE;
+ write_mac_reg(mac, PAS_MAC_CFG_PCFG, flags);
+}
+
+static void pasemi_mac_intf_enable(struct pasemi_mac *mac)
+{
+ unsigned int flags;
+
+ flags = read_mac_reg(mac, PAS_MAC_CFG_PCFG);
+ flags |= PAS_MAC_CFG_PCFG_PE;
+ write_mac_reg(mac, PAS_MAC_CFG_PCFG, flags);
+}
+
static int pasemi_get_mac_addr(struct pasemi_mac *mac)
{
struct pci_dev *pdev = mac->pdev;
@@ -480,7 +500,7 @@ static void pasemi_mac_free_tx_resources(struct pasemi_mac *mac)
}
-static void pasemi_mac_free_rx_resources(struct pasemi_mac *mac)
+static void pasemi_mac_free_rx_buffers(struct pasemi_mac *mac)
{
struct pasemi_mac_rxring *rx = rx_ring(mac);
unsigned int i;
@@ -500,7 +520,12 @@ static void pasemi_mac_free_rx_resources(struct pasemi_mac *mac)
}
for (i = 0; i < RX_RING_SIZE; i++)
- RX_DESC(rx, i) = 0;
+ RX_BUFF(rx, i) = 0;
+}
+
+static void pasemi_mac_free_rx_resources(struct pasemi_mac *mac)
+{
+ pasemi_mac_free_rx_buffers(mac);
dma_free_coherent(&mac->dma_pdev->dev, RX_RING_SIZE * sizeof(u64),
rx_ring(mac)->buffers, rx_ring(mac)->buf_dma);
@@ -530,14 +555,14 @@ static void pasemi_mac_replenish_rx_ring(const struct net_device *dev,
/* Entry in use? */
WARN_ON(*buff);
- skb = dev_alloc_skb(BUF_SIZE);
+ skb = dev_alloc_skb(mac->bufsz);
skb_reserve(skb, LOCAL_SKB_ALIGN);
if (unlikely(!skb))
break;
dma = pci_map_single(mac->dma_pdev, skb->data,
- BUF_SIZE - LOCAL_SKB_ALIGN,
+ mac->bufsz - LOCAL_SKB_ALIGN,
PCI_DMA_FROMDEVICE);
if (unlikely(dma_mapping_error(dma))) {
@@ -547,7 +572,7 @@ static void pasemi_mac_replenish_rx_ring(const struct net_device *dev,
info->skb = skb;
info->dma = dma;
- *buff = XCT_RXB_LEN(BUF_SIZE) | XCT_RXB_ADDR(dma);
+ *buff = XCT_RXB_LEN(mac->bufsz) | XCT_RXB_ADDR(dma);
fill++;
}
@@ -677,7 +702,7 @@ static int pasemi_mac_clean_rx(struct pasemi_mac_rxring *rx,
len = (macrx & XCT_MACRX_LLEN_M) >> XCT_MACRX_LLEN_S;
- pci_unmap_single(pdev, dma, BUF_SIZE-LOCAL_SKB_ALIGN,
+ pci_unmap_single(pdev, dma, mac->bufsz - LOCAL_SKB_ALIGN,
PCI_DMA_FROMDEVICE);
if (macrx & XCT_MACRX_CRC) {
@@ -901,24 +926,6 @@ static irqreturn_t pasemi_mac_tx_intr(int irq, void *data)
return IRQ_HANDLED;
}
-static void pasemi_mac_intf_disable(struct pasemi_mac *mac)
-{
- unsigned int flags;
-
- flags = read_mac_reg(mac, PAS_MAC_CFG_PCFG);
- flags &= ~PAS_MAC_CFG_PCFG_PE;
- write_mac_reg(mac, PAS_MAC_CFG_PCFG, flags);
-}
-
-static void pasemi_mac_intf_enable(struct pasemi_mac *mac)
-{
- unsigned int flags;
-
- flags = read_mac_reg(mac, PAS_MAC_CFG_PCFG);
- flags |= PAS_MAC_CFG_PCFG_PE;
- write_mac_reg(mac, PAS_MAC_CFG_PCFG, flags);
-}
-
static void pasemi_adjust_link(struct net_device *dev)
{
struct pasemi_mac *mac = netdev_priv(dev);
@@ -1175,11 +1182,71 @@ out_rx_resources:
#define MAX_RETRIES 5000
+static void pasemi_mac_pause_txchan(struct pasemi_mac *mac)
+{
+ unsigned int sta, retries;
+ int txch = tx_ring(mac)->chan.chno;
+
+ write_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(txch),
+ PAS_DMA_TXCHAN_TCMDSTA_ST);
+
+ for (retries = 0; retries < MAX_RETRIES; retries++) {
+ sta = read_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(txch));
+ if (!(sta & PAS_DMA_TXCHAN_TCMDSTA_ACT))
+ break;
+ cond_resched();
+ }
+
+ if (sta & PAS_DMA_TXCHAN_TCMDSTA_ACT)
+ dev_err(&mac->dma_pdev->dev,
+ "Failed to stop tx channel, tcmdsta %08x\n", sta);
+
+ write_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(txch), 0);
+}
+
+static void pasemi_mac_pause_rxchan(struct pasemi_mac *mac)
+{
+ unsigned int sta, retries;
+ int rxch = rx_ring(mac)->chan.chno;
+
+ write_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(rxch),
+ PAS_DMA_RXCHAN_CCMDSTA_ST);
+ for (retries = 0; retries < MAX_RETRIES; retries++) {
+ sta = read_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(rxch));
+ if (!(sta & PAS_DMA_RXCHAN_CCMDSTA_ACT))
+ break;
+ cond_resched();
+ }
+
+ if (sta & PAS_DMA_RXCHAN_CCMDSTA_ACT)
+ dev_err(&mac->dma_pdev->dev,
+ "Failed to stop rx channel, ccmdsta 08%x\n", sta);
+ write_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(rxch), 0);
+}
+
+static void pasemi_mac_pause_rxint(struct pasemi_mac *mac)
+{
+ unsigned int sta, retries;
+
+ write_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if),
+ PAS_DMA_RXINT_RCMDSTA_ST);
+ for (retries = 0; retries < MAX_RETRIES; retries++) {
+ sta = read_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if));
+ if (!(sta & PAS_DMA_RXINT_RCMDSTA_ACT))
+ break;
+ cond_resched();
+ }
+
+ if (sta & PAS_DMA_RXINT_RCMDSTA_ACT)
+ dev_err(&mac->dma_pdev->dev,
+ "Failed to stop rx interface, rcmdsta %08x\n", sta);
+ write_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if), 0);
+}
+
static int pasemi_mac_close(struct net_device *dev)
{
struct pasemi_mac *mac = netdev_priv(dev);
unsigned int sta;
- int retries;
int rxch, txch;
rxch = rx_ring(mac)->chan.chno;
@@ -1217,51 +1284,9 @@ static int pasemi_mac_close(struct net_device *dev)
pasemi_mac_clean_tx(tx_ring(mac));
pasemi_mac_clean_rx(rx_ring(mac), RX_RING_SIZE);
- /* Disable interface */
- write_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(txch),
- PAS_DMA_TXCHAN_TCMDSTA_ST);
- write_dma_reg( PAS_DMA_RXINT_RCMDSTA(mac->dma_if),
- PAS_DMA_RXINT_RCMDSTA_ST);
- write_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(rxch),
- PAS_DMA_RXCHAN_CCMDSTA_ST);
-
- for (retries = 0; retries < MAX_RETRIES; retries++) {
- sta = read_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(rxch));
- if (!(sta & PAS_DMA_TXCHAN_TCMDSTA_ACT))
- break;
- cond_resched();
- }
-
- if (sta & PAS_DMA_TXCHAN_TCMDSTA_ACT)
- dev_err(&mac->dma_pdev->dev, "Failed to stop tx channel\n");
-
- for (retries = 0; retries < MAX_RETRIES; retries++) {
- sta = read_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(rxch));
- if (!(sta & PAS_DMA_RXCHAN_CCMDSTA_ACT))
- break;
- cond_resched();
- }
-
- if (sta & PAS_DMA_RXCHAN_CCMDSTA_ACT)
- dev_err(&mac->dma_pdev->dev, "Failed to stop rx channel\n");
-
- for (retries = 0; retries < MAX_RETRIES; retries++) {
- sta = read_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if));
- if (!(sta & PAS_DMA_RXINT_RCMDSTA_ACT))
- break;
- cond_resched();
- }
-
- if (sta & PAS_DMA_RXINT_RCMDSTA_ACT)
- dev_err(&mac->dma_pdev->dev, "Failed to stop rx interface\n");
-
- /* Then, disable the channel. This must be done separately from
- * stopping, since you can't disable when active.
- */
-
- write_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(txch), 0);
- write_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(rxch), 0);
- write_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if), 0);
+ pasemi_mac_pause_txchan(mac);
+ pasemi_mac_pause_rxint(mac);
+ pasemi_mac_pause_rxchan(mac);
free_irq(mac->tx->chan.irq, mac->tx);
free_irq(mac->rx->chan.irq, mac->rx);
@@ -1415,6 +1440,62 @@ static int pasemi_mac_poll(struct napi_struct *napi, int budget)
return pkts;
}
+static int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu)
+{
+ struct pasemi_mac *mac = netdev_priv(dev);
+ unsigned int reg;
+ unsigned int rcmdsta;
+ int running;
+
+ if (new_mtu < PE_MIN_MTU || new_mtu > PE_MAX_MTU)
+ return -EINVAL;
+
+ running = netif_running(dev);
+
+ if (running) {
+ /* Need to stop the interface, clean out all already
+ * received buffers, free all unused buffers on the RX
+ * interface ring, then finally re-fill the rx ring with
+ * the new-size buffers and restart.
+ */
+
+ napi_disable(&mac->napi);
+ netif_tx_disable(dev);
+ pasemi_mac_intf_disable(mac);
+
+ rcmdsta = read_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if));
+ pasemi_mac_pause_rxint(mac);
+ pasemi_mac_clean_rx(rx_ring(mac), RX_RING_SIZE);
+ pasemi_mac_free_rx_buffers(mac);
+ }
+
+ /* Change maxf, i.e. what size frames are accepted.
+ * Need room for ethernet header and CRC word
+ */
+ reg = read_mac_reg(mac, PAS_MAC_CFG_MACCFG);
+ reg &= ~PAS_MAC_CFG_MACCFG_MAXF_M;
+ reg |= PAS_MAC_CFG_MACCFG_MAXF(new_mtu + ETH_HLEN + 4);
+ write_mac_reg(mac, PAS_MAC_CFG_MACCFG, reg);
+
+ dev->mtu = new_mtu;
+ /* MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */
+ mac->bufsz = new_mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128;
+
+ if (running) {
+ write_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if),
+ rcmdsta | PAS_DMA_RXINT_RCMDSTA_EN);
+
+ rx_ring(mac)->next_to_fill = 0;
+ pasemi_mac_replenish_rx_ring(dev, RX_RING_SIZE-1);
+
+ napi_enable(&mac->napi);
+ netif_start_queue(dev);
+ pasemi_mac_intf_enable(mac);
+ }
+
+ return 0;
+}
+
static int __devinit
pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
@@ -1503,6 +1584,11 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
dev->hard_start_xmit = pasemi_mac_start_tx;
dev->set_multicast_list = pasemi_mac_set_rx_mode;
dev->set_mac_address = pasemi_mac_set_mac_addr;
+ dev->mtu = PE_DEF_MTU;
+ /* 1500 MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */
+ mac->bufsz = dev->mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128;
+
+ dev->change_mtu = pasemi_mac_change_mtu;
if (err)
goto out;
diff --git a/drivers/net/pasemi_mac.h b/drivers/net/pasemi_mac.h
index 39d3259..99e7b93 100644
--- a/drivers/net/pasemi_mac.h
+++ b/drivers/net/pasemi_mac.h
@@ -59,6 +59,7 @@ struct pasemi_mac {
struct phy_device *phydev;
struct napi_struct napi;
+ int bufsz; /* RX ring buffer size */
u8 type;
#define MAC_TYPE_GMAC 1
#define MAC_TYPE_XAUI 2
@@ -96,6 +97,7 @@ struct pasemi_mac_buffer {
/* MAC CFG register offsets */
enum {
PAS_MAC_CFG_PCFG = 0x80,
+ PAS_MAC_CFG_MACCFG = 0x84,
PAS_MAC_CFG_ADR0 = 0x8c,
PAS_MAC_CFG_ADR1 = 0x90,
PAS_MAC_CFG_TXP = 0x98,
@@ -132,6 +134,18 @@ enum {
#define PAS_MAC_CFG_PCFG_SPD_100M 0x00000001
#define PAS_MAC_CFG_PCFG_SPD_1G 0x00000002
#define PAS_MAC_CFG_PCFG_SPD_10G 0x00000003
+
+#define PAS_MAC_CFG_MACCFG_TXT_M 0x70000000
+#define PAS_MAC_CFG_MACCFG_TXT_S 28
+#define PAS_MAC_CFG_MACCFG_PRES_M 0x0f000000
+#define PAS_MAC_CFG_MACCFG_PRES_S 24
+#define PAS_MAC_CFG_MACCFG_MAXF_M 0x00ffff00
+#define PAS_MAC_CFG_MACCFG_MAXF_S 8
+#define PAS_MAC_CFG_MACCFG_MAXF(x) (((x) << PAS_MAC_CFG_MACCFG_MAXF_S) & \
+ PAS_MAC_CFG_MACCFG_MAXF_M)
+#define PAS_MAC_CFG_MACCFG_MINF_M 0x000000ff
+#define PAS_MAC_CFG_MACCFG_MINF_S 0
+
#define PAS_MAC_CFG_TXP_FCF 0x01000000
#define PAS_MAC_CFG_TXP_FCE 0x00800000
#define PAS_MAC_CFG_TXP_FC 0x00400000
^ permalink raw reply related
* [PATCH 0/3] A few more pasemi_mac patches for 2.6.25
From: Olof Johansson @ 2008-01-23 19:55 UTC (permalink / raw)
To: jgarzik; +Cc: netdev
Hi,
This should be the last of my updates for 2.6.25:
1/3: pasemi_mac: Add support for changing mac address
2/3: pasemi_mac: add support for setting MTU
3/3: pasemi_mac: Disable interface on close
Thanks,
Olof
^ permalink raw reply
* Re: [PATCH 1/5] iwlwifi: iwl3945 flush interrupt mask
From: Chatre, Reinette @ 2008-01-23 18:50 UTC (permalink / raw)
To: Joonwoo Park, Zhu, Yi, netdev; +Cc: linux-wireless, lkml, ipw3945-devel
In-Reply-To: <11998765342443-git-send-email-joonwpark81@gmail.com>
Joonwoo Park <joonwpark81@gmail.com> wrote:
> interrupt mask
>
> After enabling/disabling interrupts flushing is required
>
I have been looking at this patch and I would like to get some more
feedback from the experts in the group.
First off, the register used for the read in order to flush has to be
safe. We have to make sure that the register has no side effects. To do
this we could use CSR_INT_MASK, as in "#define iwl_flush32(iwl)
iwl_read32(iwl, CSR_INT_MASK)" This also enables us to flush at the end
of a sequence of writes instead of after every write.
Digging deeper it is not 100% clear to me when we should do flushing to
handle write posting. I understand that it should be done in time
sensitive code, but that could on a high level mean any write operation
in the driver. How should it be decided which writes to the device need
to be flushed?
Patch is kept below fyi.
Reinette
> Signed-off-by: Joonwoo Park <joonwpark81@gmail.com> ---
> drivers/net/wireless/iwlwifi/iwl-io.h | 2 ++
> drivers/net/wireless/iwlwifi/iwl3945-base.c | 6 ++++++
> 2 files changed, 8 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h
> b/drivers/net/wireless/iwlwifi/iwl-io.h
> index 8a8b96f..f2bc30e 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-io.h
> +++ b/drivers/net/wireless/iwlwifi/iwl-io.h
> @@ -87,6 +87,8 @@ static inline u32 __iwl_read32(char *f, u32
> l, struct iwl_priv *iwl, u32 ofs)
> #define iwl_read32(p, o) _iwl_read32(p, o)
> #endif
>
> +#define iwl_flush32(iwl, ofs) iwl_read32(iwl, ofs) +
> static inline int _iwl_poll_bit(struct iwl_priv *priv, u32 addr,
> u32 bits, u32 mask, int timeout)
> {
> diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c
> b/drivers/net/wireless/iwlwifi/iwl3945-base.c
> index 8ed898d..85f1112 100644
> --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
> +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
> @@ -4410,6 +4410,7 @@ static void iwl_enable_interrupts(struct
> iwl_priv *priv) IWL_DEBUG_ISR("Enabling interrupts\n");
> set_bit(STATUS_INT_ENABLED, &priv->status);
> iwl_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK);
> + iwl_flush32(priv, CSR_INT_MASK);
> }
>
> static inline void iwl_disable_interrupts(struct iwl_priv *priv)
> @@ -4418,11 +4419,15 @@ static inline void
> iwl_disable_interrupts(struct iwl_priv *priv)
>
> /* disable interrupts from uCode/NIC to host */
> iwl_write32(priv, CSR_INT_MASK, 0x00000000);
> + iwl_flush32(priv, CSR_INT_MASK);
>
> /* acknowledge/clear/reset any interrupts still pending
> * from uCode or flow handler (Rx/Tx DMA) */
> iwl_write32(priv, CSR_INT, 0xffffffff);
> + iwl_flush32(priv, CSR_INT);
> iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff);
> + iwl_flush32(priv, CSR_FH_INT_STATUS);
> +
> IWL_DEBUG_ISR("Disabled interrupts\n");
> }
>
> @@ -4840,6 +4845,7 @@ static irqreturn_t iwl_isr(int irq, void *data)
> * If we *don't* have something, we'll re-enable before
> leaving here. */
> inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just
> for debug */
> iwl_write32(priv, CSR_INT_MASK, 0x00000000);
> + iwl_flush32(priv, CSR_INT_MASK);
>
> /* Discover which interrupts are active/pending */
> inta = iwl_read32(priv, CSR_INT);
> --
> 1.5.3.rc5
>
>
> ---------------------------------------------------------------
> ----------
> Check out the new SourceForge.net Marketplace.
> It's the best place to buy or sell services for
> just about anything Open Source.
> http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.ne
> t/marketplace _______________________________________________
> Ipw3945-devel mailing list
> Ipw3945-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/ipw3945-devel
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply
* SCTP NAT module for netfilter
From: Sohan Shetty @ 2008-01-23 17:41 UTC (permalink / raw)
To: netdev, netfilter-devel-owner
Is anyone aware if there an NAT module for netfilter being developed for SCTP protocol ?
I have searched the netfilter development tree source code and also mailing list and so far I have not found the NAT module for SCTP . There is SCTP conntrack module and packet match module.
If anyone is aware and can point me to some one who is already working on this or has evaluated this it would be of great help.
SCTP is defined in [RFC 2960] Stewart, R., Xie, Q., Morneault, K., Sharp, C., Schwarzbauer, H., Taylor, T., Rytina, I., Kalla, M., Zhang, L. and V. Paxson, "Stream Control Transmission Protocol", RFC 2960, October 2000.
Thanks and best regards
sohan
^ permalink raw reply
* Re: My 802.3ad is my bond
From: Steven Whitehouse @ 2008-01-23 17:19 UTC (permalink / raw)
To: Jay Vosburgh; +Cc: netdev
In-Reply-To: <26889.1201108405@death>
Hi,
On Wed, 2008-01-23 at 09:13 -0800, Jay Vosburgh wrote:
> Steven Whitehouse <swhiteho@redhat.com> wrote:
> [...]
> >This commit: ece95f7fefe3afae19e641e1b3f5e64b00d5b948 seems to have
> >caused a problem with parsing bond arguments as now only the numeric
> >arguments seem to work (in modprobe.conf) and specifying 802.3ad fails.
> >When I revert that patch in my local tree all seems ok.
>
> Thanks for the report; I know what the problem here is. I'll
> get a fix out.
>
> >Also I notice that one of my two NICs now reports this:
> >
> >bonding: bond0: link status definitely down for interface eth0,
> >disabling it
> >bonding: bond0: Interface eth0 is already enslaved!
> >bond0.5: no IPv6 routers present
> >
> >which I think is also new with this set of bonding updates, before it
> >used to use both interfaces ok. I've not worked out which of the other
> >patches causes this so far, but I can if its helpful,
>
> That would be helpful, as would some more details: e.g., the
> various options passed to bonding, the complete dmesg log, contents of
> /proc/net/bonding/bond0 [or whatever your interface is called], and
> anything else you think would be helpful.
>
> -J
>
> ---
> -Jay Vosburgh, IBM Linux Technology Center, fubar@us.ibm.com
Ok. I'll try and work out which patch it is, but in the mean time:
Ethernet Channel Bonding Driver: v3.2.3 (December 6, 2007)
Bonding Mode: IEEE 802.3ad Dynamic link aggregation
Transmit Hash Policy: layer2 (0)
MII Status: up
MII Polling Interval (ms): 100
Up Delay (ms): 0
Down Delay (ms): 0
802.3ad info
LACP rate: slow
Active Aggregator Info:
Aggregator ID: 1
Number of ports: 1
Actor Key: 17
Partner Key: 4
Partner Mac Address: 00:12:a9:13:3f:67
Slave Interface: eth0
MII Status: down <-- this one should be up as well
Link Failure Count: 2
Permanent HW addr: 00:11:43:d7:75:74
Aggregator ID: 2
Slave Interface: eth1
MII Status: up
Link Failure Count: 1
Permanent HW addr: 00:11:43:d7:75:75
Aggregator ID: 1
Bonding options:
options bond0 miimon=100 mode=802.3ad
I'll send the dmesg by private email as its quite large,
Steve.
^ permalink raw reply
* Re: My 802.3ad is my bond
From: Jay Vosburgh @ 2008-01-23 17:13 UTC (permalink / raw)
To: Steven Whitehouse; +Cc: netdev
In-Reply-To: <1201103100.22038.254.camel@quoit>
Steven Whitehouse <swhiteho@redhat.com> wrote:
[...]
>This commit: ece95f7fefe3afae19e641e1b3f5e64b00d5b948 seems to have
>caused a problem with parsing bond arguments as now only the numeric
>arguments seem to work (in modprobe.conf) and specifying 802.3ad fails.
>When I revert that patch in my local tree all seems ok.
Thanks for the report; I know what the problem here is. I'll
get a fix out.
>Also I notice that one of my two NICs now reports this:
>
>bonding: bond0: link status definitely down for interface eth0,
>disabling it
>bonding: bond0: Interface eth0 is already enslaved!
>bond0.5: no IPv6 routers present
>
>which I think is also new with this set of bonding updates, before it
>used to use both interfaces ok. I've not worked out which of the other
>patches causes this so far, but I can if its helpful,
That would be helpful, as would some more details: e.g., the
various options passed to bonding, the complete dmesg log, contents of
/proc/net/bonding/bond0 [or whatever your interface is called], and
anything else you think would be helpful.
-J
---
-Jay Vosburgh, IBM Linux Technology Center, fubar@us.ibm.com
^ permalink raw reply
* [NET_SCHED 15/15]: Use nla_policy for attribute validation in ematches
From: Patrick McHardy @ 2008-01-23 16:36 UTC (permalink / raw)
To: davem; +Cc: netdev, Patrick McHardy
In-Reply-To: <20080123163555.6459.69501.sendpatchset@localhost.localdomain>
[NET_SCHED]: Use nla_policy for attribute validation in ematches
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
commit 9420f06512465a8a90f3ff0df8b943989bc7e2e7
tree 7556b31b93647c9d2c30eb567b50671d368f8ced
parent 99302e1c1ed003305e9a0102aa772e2f2d61114c
author Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:23:09 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:23:09 +0100
net/sched/em_meta.c | 9 ++++++---
net/sched/ematch.c | 11 ++++++-----
2 files changed, 12 insertions(+), 8 deletions(-)
diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c
index d9f487d..a1e5619 100644
--- a/net/sched/em_meta.c
+++ b/net/sched/em_meta.c
@@ -745,6 +745,10 @@ static inline int meta_is_supported(struct meta_value *val)
return (!meta_id(val) || meta_ops(val)->get);
}
+static const struct nla_policy meta_policy[TCA_EM_META_MAX + 1] = {
+ [TCA_EM_META_HDR] = { .len = sizeof(struct tcf_meta_hdr) },
+};
+
static int em_meta_change(struct tcf_proto *tp, void *data, int len,
struct tcf_ematch *m)
{
@@ -753,13 +757,12 @@ static int em_meta_change(struct tcf_proto *tp, void *data, int len,
struct tcf_meta_hdr *hdr;
struct meta_match *meta = NULL;
- err = nla_parse(tb, TCA_EM_META_MAX, data, len, NULL);
+ err = nla_parse(tb, TCA_EM_META_MAX, data, len, meta_policy);
if (err < 0)
goto errout;
err = -EINVAL;
- if (tb[TCA_EM_META_HDR] == NULL ||
- nla_len(tb[TCA_EM_META_HDR]) < sizeof(*hdr))
+ if (tb[TCA_EM_META_HDR] == NULL)
goto errout;
hdr = nla_data(tb[TCA_EM_META_HDR]);
diff --git a/net/sched/ematch.c b/net/sched/ematch.c
index daa9c4e..74ff918 100644
--- a/net/sched/ematch.c
+++ b/net/sched/ematch.c
@@ -282,6 +282,11 @@ errout:
return err;
}
+static const struct nla_policy em_policy[TCA_EMATCH_TREE_MAX + 1] = {
+ [TCA_EMATCH_TREE_HDR] = { .len = sizeof(struct tcf_ematch_tree_hdr) },
+ [TCA_EMATCH_TREE_LIST] = { .type = NLA_NESTED },
+};
+
/**
* tcf_em_tree_validate - validate ematch config TLV and build ematch tree
*
@@ -312,7 +317,7 @@ int tcf_em_tree_validate(struct tcf_proto *tp, struct nlattr *nla,
return 0;
}
- err = nla_parse_nested(tb, TCA_EMATCH_TREE_MAX, nla, NULL);
+ err = nla_parse_nested(tb, TCA_EMATCH_TREE_MAX, nla, em_policy);
if (err < 0)
goto errout;
@@ -323,10 +328,6 @@ int tcf_em_tree_validate(struct tcf_proto *tp, struct nlattr *nla,
if (rt_hdr == NULL || rt_list == NULL)
goto errout;
- if (nla_len(rt_hdr) < sizeof(*tree_hdr) ||
- nla_len(rt_list) < sizeof(*rt_match))
- goto errout;
-
tree_hdr = nla_data(rt_hdr);
memcpy(&tree->hdr, tree_hdr, sizeof(*tree_hdr));
^ permalink raw reply related
* [NET_SCHED 14/15]: Use nla_policy for attribute validation in actions
From: Patrick McHardy @ 2008-01-23 16:36 UTC (permalink / raw)
To: davem; +Cc: netdev, Patrick McHardy
In-Reply-To: <20080123163555.6459.69501.sendpatchset@localhost.localdomain>
[NET_SCHED]: Use nla_policy for attribute validation in actions
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
commit 99302e1c1ed003305e9a0102aa772e2f2d61114c
tree 05286e8f9d74ad273d6a6e12d7bc794a19c4ea4c
parent d177578bdf08849a388f1bc42a1d0566c6a3aded
author Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:23:07 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:23:07 +0100
net/sched/act_gact.c | 15 ++++++++-------
net/sched/act_ipt.c | 19 ++++++++++++-------
net/sched/act_mirred.c | 9 ++++++---
net/sched/act_nat.c | 9 ++++++---
net/sched/act_pedit.c | 9 ++++++---
net/sched/act_police.c | 16 ++++++++--------
net/sched/act_simple.c | 7 +++++--
7 files changed, 51 insertions(+), 33 deletions(-)
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index df214d4..422872c 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -53,6 +53,11 @@ typedef int (*g_rand)(struct tcf_gact *gact);
static g_rand gact_rand[MAX_RAND]= { NULL, gact_net_rand, gact_determ };
#endif /* CONFIG_GACT_PROB */
+static const struct nla_policy gact_policy[TCA_GACT_MAX + 1] = {
+ [TCA_GACT_PARMS] = { .len = sizeof(struct tc_gact) },
+ [TCA_GACT_PROB] = { .len = sizeof(struct tc_gact_p) },
+};
+
static int tcf_gact_init(struct nlattr *nla, struct nlattr *est,
struct tc_action *a, int ovr, int bind)
{
@@ -66,20 +71,16 @@ static int tcf_gact_init(struct nlattr *nla, struct nlattr *est,
if (nla == NULL)
return -EINVAL;
- err = nla_parse_nested(tb, TCA_GACT_MAX, nla, NULL);
+ err = nla_parse_nested(tb, TCA_GACT_MAX, nla, gact_policy);
if (err < 0)
return err;
- if (tb[TCA_GACT_PARMS] == NULL ||
- nla_len(tb[TCA_GACT_PARMS]) < sizeof(*parm))
+ if (tb[TCA_GACT_PARMS] == NULL)
return -EINVAL;
parm = nla_data(tb[TCA_GACT_PARMS]);
+#ifndef CONFIG_GACT_PROB
if (tb[TCA_GACT_PROB] != NULL)
-#ifdef CONFIG_GACT_PROB
- if (nla_len(tb[TCA_GACT_PROB]) < sizeof(struct tc_gact_p))
- return -EINVAL;
-#else
return -EOPNOTSUPP;
#endif
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index 7ab2419..da696fd 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -92,6 +92,13 @@ static int tcf_ipt_release(struct tcf_ipt *ipt, int bind)
return ret;
}
+static const struct nla_policy ipt_policy[TCA_IPT_MAX + 1] = {
+ [TCA_IPT_TABLE] = { .type = NLA_STRING, .len = IFNAMSIZ },
+ [TCA_IPT_HOOK] = { .type = NLA_U32 },
+ [TCA_IPT_INDEX] = { .type = NLA_U32 },
+ [TCA_IPT_TARG] = { .len = sizeof(struct ipt_entry_target) },
+};
+
static int tcf_ipt_init(struct nlattr *nla, struct nlattr *est,
struct tc_action *a, int ovr, int bind)
{
@@ -107,22 +114,20 @@ static int tcf_ipt_init(struct nlattr *nla, struct nlattr *est,
if (nla == NULL)
return -EINVAL;
- err = nla_parse_nested(tb, TCA_IPT_MAX, nla, NULL);
+ err = nla_parse_nested(tb, TCA_IPT_MAX, nla, ipt_policy);
if (err < 0)
return err;
- if (tb[TCA_IPT_HOOK] == NULL ||
- nla_len(tb[TCA_IPT_HOOK]) < sizeof(u32))
+ if (tb[TCA_IPT_HOOK] == NULL)
return -EINVAL;
- if (tb[TCA_IPT_TARG] == NULL ||
- nla_len(tb[TCA_IPT_TARG]) < sizeof(*t))
+ if (tb[TCA_IPT_TARG] == NULL)
return -EINVAL;
+
td = (struct ipt_entry_target *)nla_data(tb[TCA_IPT_TARG]);
if (nla_len(tb[TCA_IPT_TARG]) < td->u.target_size)
return -EINVAL;
- if (tb[TCA_IPT_INDEX] != NULL &&
- nla_len(tb[TCA_IPT_INDEX]) >= sizeof(u32))
+ if (tb[TCA_IPT_INDEX] != NULL)
index = nla_get_u32(tb[TCA_IPT_INDEX]);
pc = tcf_hash_check(index, a, bind, &ipt_hash_info);
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index 6cb5e30..1aff005 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -54,6 +54,10 @@ static inline int tcf_mirred_release(struct tcf_mirred *m, int bind)
return 0;
}
+static const struct nla_policy mirred_policy[TCA_MIRRED_MAX + 1] = {
+ [TCA_MIRRED_PARMS] = { .len = sizeof(struct tc_mirred) },
+};
+
static int tcf_mirred_init(struct nlattr *nla, struct nlattr *est,
struct tc_action *a, int ovr, int bind)
{
@@ -68,12 +72,11 @@ static int tcf_mirred_init(struct nlattr *nla, struct nlattr *est,
if (nla == NULL)
return -EINVAL;
- err = nla_parse_nested(tb, TCA_MIRRED_MAX, nla, NULL);
+ err = nla_parse_nested(tb, TCA_MIRRED_MAX, nla, mirred_policy);
if (err < 0)
return err;
- if (tb[TCA_MIRRED_PARMS] == NULL ||
- nla_len(tb[TCA_MIRRED_PARMS]) < sizeof(*parm))
+ if (tb[TCA_MIRRED_PARMS] == NULL)
return -EINVAL;
parm = nla_data(tb[TCA_MIRRED_PARMS]);
diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c
index 5a512d4..0a3c833 100644
--- a/net/sched/act_nat.c
+++ b/net/sched/act_nat.c
@@ -40,6 +40,10 @@ static struct tcf_hashinfo nat_hash_info = {
.lock = &nat_lock,
};
+static const struct nla_policy nat_policy[TCA_NAT_MAX + 1] = {
+ [TCA_NAT_PARMS] = { .len = sizeof(struct tc_nat) },
+};
+
static int tcf_nat_init(struct nlattr *nla, struct nlattr *est,
struct tc_action *a, int ovr, int bind)
{
@@ -52,12 +56,11 @@ static int tcf_nat_init(struct nlattr *nla, struct nlattr *est,
if (nla == NULL)
return -EINVAL;
- err = nla_parse_nested(tb, TCA_NAT_MAX, nla, NULL);
+ err = nla_parse_nested(tb, TCA_NAT_MAX, nla, nat_policy);
if (err < 0)
return err;
- if (tb[TCA_NAT_PARMS] == NULL ||
- nla_len(tb[TCA_NAT_PARMS]) < sizeof(*parm))
+ if (tb[TCA_NAT_PARMS] == NULL)
return -EINVAL;
parm = nla_data(tb[TCA_NAT_PARMS]);
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
index 1b9ca45..3cc4cb9 100644
--- a/net/sched/act_pedit.c
+++ b/net/sched/act_pedit.c
@@ -33,6 +33,10 @@ static struct tcf_hashinfo pedit_hash_info = {
.lock = &pedit_lock,
};
+static const struct nla_policy pedit_policy[TCA_PEDIT_MAX + 1] = {
+ [TCA_PEDIT_PARMS] = { .len = sizeof(struct tcf_pedit) },
+};
+
static int tcf_pedit_init(struct nlattr *nla, struct nlattr *est,
struct tc_action *a, int ovr, int bind)
{
@@ -47,12 +51,11 @@ static int tcf_pedit_init(struct nlattr *nla, struct nlattr *est,
if (nla == NULL)
return -EINVAL;
- err = nla_parse_nested(tb, TCA_PEDIT_MAX, nla, NULL);
+ err = nla_parse_nested(tb, TCA_PEDIT_MAX, nla, pedit_policy);
if (err < 0)
return err;
- if (tb[TCA_PEDIT_PARMS] == NULL ||
- nla_len(tb[TCA_PEDIT_PARMS]) < sizeof(*parm))
+ if (tb[TCA_PEDIT_PARMS] == NULL)
return -EINVAL;
parm = nla_data(tb[TCA_PEDIT_PARMS]);
ksize = parm->nkeys * sizeof(struct tc_pedit_key);
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index 62de806..0898120 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -119,6 +119,13 @@ static void tcf_police_destroy(struct tcf_police *p)
BUG_TRAP(0);
}
+static const struct nla_policy police_policy[TCA_POLICE_MAX + 1] = {
+ [TCA_POLICE_RATE] = { .len = TC_RTAB_SIZE },
+ [TCA_POLICE_PEAKRATE] = { .len = TC_RTAB_SIZE },
+ [TCA_POLICE_AVRATE] = { .type = NLA_U32 },
+ [TCA_POLICE_RESULT] = { .type = NLA_U32 },
+};
+
static int tcf_act_police_locate(struct nlattr *nla, struct nlattr *est,
struct tc_action *a, int ovr, int bind)
{
@@ -133,7 +140,7 @@ static int tcf_act_police_locate(struct nlattr *nla, struct nlattr *est,
if (nla == NULL)
return -EINVAL;
- err = nla_parse_nested(tb, TCA_POLICE_MAX, nla, NULL);
+ err = nla_parse_nested(tb, TCA_POLICE_MAX, nla, police_policy);
if (err < 0)
return err;
@@ -144,13 +151,6 @@ static int tcf_act_police_locate(struct nlattr *nla, struct nlattr *est,
return -EINVAL;
parm = nla_data(tb[TCA_POLICE_TBF]);
- if (tb[TCA_POLICE_RESULT] != NULL &&
- nla_len(tb[TCA_POLICE_RESULT]) != sizeof(u32))
- return -EINVAL;
- if (tb[TCA_POLICE_RESULT] != NULL &&
- nla_len(tb[TCA_POLICE_RESULT]) != sizeof(u32))
- return -EINVAL;
-
if (parm->index) {
struct tcf_common *pc;
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c
index cedaadf..fbde461 100644
--- a/net/sched/act_simple.c
+++ b/net/sched/act_simple.c
@@ -84,6 +84,10 @@ static int realloc_defdata(struct tcf_defact *d, u32 datalen, void *defdata)
return alloc_defdata(d, datalen, defdata);
}
+static const struct nla_policy simple_policy[TCA_DEF_MAX + 1] = {
+ [TCA_DEF_PARMS] = { .len = sizeof(struct tc_defact) },
+};
+
static int tcf_simp_init(struct nlattr *nla, struct nlattr *est,
struct tc_action *a, int ovr, int bind)
{
@@ -102,8 +106,7 @@ static int tcf_simp_init(struct nlattr *nla, struct nlattr *est,
if (err < 0)
return err;
- if (tb[TCA_DEF_PARMS] == NULL ||
- nla_len(tb[TCA_DEF_PARMS]) < sizeof(*parm))
+ if (tb[TCA_DEF_PARMS] == NULL)
return -EINVAL;
parm = nla_data(tb[TCA_DEF_PARMS]);
^ permalink raw reply related
* [NET_SCHED 13/15]: Use nla_policy for attribute validation in classifiers
From: Patrick McHardy @ 2008-01-23 16:36 UTC (permalink / raw)
To: davem; +Cc: netdev, Patrick McHardy
In-Reply-To: <20080123163555.6459.69501.sendpatchset@localhost.localdomain>
[NET_SCHED]: Use nla_policy for attribute validation in classifiers
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
commit d177578bdf08849a388f1bc42a1d0566c6a3aded
tree 2eda0cf1e0479dab464acda9def525df27bd4307
parent 76c3c24283fa9f78d8dc30c8eb73e0f11934bf69
author Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:14:08 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:14:08 +0100
net/sched/cls_basic.c | 12 +++++++-----
net/sched/cls_fw.c | 17 ++++++++---------
net/sched/cls_route.c | 19 ++++++++-----------
net/sched/cls_rsvp.h | 26 +++++++++++---------------
net/sched/cls_tcindex.c | 31 +++++++++++++------------------
net/sched/cls_u32.c | 22 ++++++++++++----------
6 files changed, 59 insertions(+), 68 deletions(-)
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
index 0c872a7..bfb4342 100644
--- a/net/sched/cls_basic.c
+++ b/net/sched/cls_basic.c
@@ -129,6 +129,11 @@ static int basic_delete(struct tcf_proto *tp, unsigned long arg)
return -ENOENT;
}
+static const struct nla_policy basic_policy[TCA_BASIC_MAX + 1] = {
+ [TCA_BASIC_CLASSID] = { .type = NLA_U32 },
+ [TCA_BASIC_EMATCHES] = { .type = NLA_NESTED },
+};
+
static inline int basic_set_parms(struct tcf_proto *tp, struct basic_filter *f,
unsigned long base, struct nlattr **tb,
struct nlattr *est)
@@ -137,10 +142,6 @@ static inline int basic_set_parms(struct tcf_proto *tp, struct basic_filter *f,
struct tcf_exts e;
struct tcf_ematch_tree t;
- if (tb[TCA_BASIC_CLASSID])
- if (nla_len(tb[TCA_BASIC_CLASSID]) < sizeof(u32))
- return err;
-
err = tcf_exts_validate(tp, tb, est, &e, &basic_ext_map);
if (err < 0)
return err;
@@ -174,7 +175,8 @@ static int basic_change(struct tcf_proto *tp, unsigned long base, u32 handle,
if (tca[TCA_OPTIONS] == NULL)
return -EINVAL;
- err = nla_parse_nested(tb, TCA_BASIC_MAX, tca[TCA_OPTIONS], NULL);
+ err = nla_parse_nested(tb, TCA_BASIC_MAX, tca[TCA_OPTIONS],
+ basic_policy);
if (err < 0)
return err;
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index b75696d..436a6e7 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -186,6 +186,12 @@ out:
return -EINVAL;
}
+static const struct nla_policy fw_policy[TCA_FW_MAX + 1] = {
+ [TCA_FW_CLASSID] = { .type = NLA_U32 },
+ [TCA_FW_INDEV] = { .type = NLA_STRING, .len = IFNAMSIZ },
+ [TCA_FW_MASK] = { .type = NLA_U32 },
+};
+
static int
fw_change_attrs(struct tcf_proto *tp, struct fw_filter *f,
struct nlattr **tb, struct nlattr **tca, unsigned long base)
@@ -201,8 +207,6 @@ fw_change_attrs(struct tcf_proto *tp, struct fw_filter *f,
err = -EINVAL;
if (tb[TCA_FW_CLASSID]) {
- if (nla_len(tb[TCA_FW_CLASSID]) != sizeof(u32))
- goto errout;
f->res.classid = nla_get_u32(tb[TCA_FW_CLASSID]);
tcf_bind_filter(tp, &f->res, base);
}
@@ -216,8 +220,6 @@ fw_change_attrs(struct tcf_proto *tp, struct fw_filter *f,
#endif /* CONFIG_NET_CLS_IND */
if (tb[TCA_FW_MASK]) {
- if (nla_len(tb[TCA_FW_MASK]) != sizeof(u32))
- goto errout;
mask = nla_get_u32(tb[TCA_FW_MASK]);
if (mask != head->mask)
goto errout;
@@ -246,7 +248,7 @@ static int fw_change(struct tcf_proto *tp, unsigned long base,
if (!opt)
return handle ? -EINVAL : 0;
- err = nla_parse_nested(tb, TCA_FW_MAX, opt, NULL);
+ err = nla_parse_nested(tb, TCA_FW_MAX, opt, fw_policy);
if (err < 0)
return err;
@@ -261,11 +263,8 @@ static int fw_change(struct tcf_proto *tp, unsigned long base,
if (head == NULL) {
u32 mask = 0xFFFFFFFF;
- if (tb[TCA_FW_MASK]) {
- if (nla_len(tb[TCA_FW_MASK]) != sizeof(u32))
- return -EINVAL;
+ if (tb[TCA_FW_MASK])
mask = nla_get_u32(tb[TCA_FW_MASK]);
- }
head = kzalloc(sizeof(struct fw_head), GFP_KERNEL);
if (head == NULL)
diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c
index ae97238..f7e7d39 100644
--- a/net/sched/cls_route.c
+++ b/net/sched/cls_route.c
@@ -323,6 +323,13 @@ static int route4_delete(struct tcf_proto *tp, unsigned long arg)
return 0;
}
+static const struct nla_policy route4_policy[TCA_ROUTE4_MAX + 1] = {
+ [TCA_ROUTE4_CLASSID] = { .type = NLA_U32 },
+ [TCA_ROUTE4_TO] = { .type = NLA_U32 },
+ [TCA_ROUTE4_FROM] = { .type = NLA_U32 },
+ [TCA_ROUTE4_IIF] = { .type = NLA_U32 },
+};
+
static int route4_set_parms(struct tcf_proto *tp, unsigned long base,
struct route4_filter *f, u32 handle, struct route4_head *head,
struct nlattr **tb, struct nlattr *est, int new)
@@ -339,15 +346,9 @@ static int route4_set_parms(struct tcf_proto *tp, unsigned long base,
return err;
err = -EINVAL;
- if (tb[TCA_ROUTE4_CLASSID])
- if (nla_len(tb[TCA_ROUTE4_CLASSID]) < sizeof(u32))
- goto errout;
-
if (tb[TCA_ROUTE4_TO]) {
if (new && handle & 0x8000)
goto errout;
- if (nla_len(tb[TCA_ROUTE4_TO]) < sizeof(u32))
- goto errout;
to = nla_get_u32(tb[TCA_ROUTE4_TO]);
if (to > 0xFF)
goto errout;
@@ -357,15 +358,11 @@ static int route4_set_parms(struct tcf_proto *tp, unsigned long base,
if (tb[TCA_ROUTE4_FROM]) {
if (tb[TCA_ROUTE4_IIF])
goto errout;
- if (nla_len(tb[TCA_ROUTE4_FROM]) < sizeof(u32))
- goto errout;
id = nla_get_u32(tb[TCA_ROUTE4_FROM]);
if (id > 0xFF)
goto errout;
nhandle |= id << 16;
} else if (tb[TCA_ROUTE4_IIF]) {
- if (nla_len(tb[TCA_ROUTE4_IIF]) < sizeof(u32))
- goto errout;
id = nla_get_u32(tb[TCA_ROUTE4_IIF]);
if (id > 0x7FFF)
goto errout;
@@ -440,7 +437,7 @@ static int route4_change(struct tcf_proto *tp, unsigned long base,
if (opt == NULL)
return handle ? -EINVAL : 0;
- err = nla_parse_nested(tb, TCA_ROUTE4_MAX, opt, NULL);
+ err = nla_parse_nested(tb, TCA_ROUTE4_MAX, opt, route4_policy);
if (err < 0)
return err;
diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h
index 61286a0..4f2c3f1 100644
--- a/net/sched/cls_rsvp.h
+++ b/net/sched/cls_rsvp.h
@@ -397,6 +397,15 @@ static u32 gen_tunnel(struct rsvp_head *data)
return 0;
}
+static const struct nla_policy rsvp_policy[TCA_RSVP_MAX + 1] = {
+ [TCA_RSVP_CLASSID] = { .type = NLA_U32 },
+ [TCA_RSVP_DST] = { .type = NLA_BINARY,
+ .len = RSVP_DST_LEN * sizeof(u32) },
+ [TCA_RSVP_SRC] = { .type = NLA_BINARY,
+ .len = RSVP_DST_LEN * sizeof(u32) },
+ [TCA_RSVP_PINFO] = { .len = sizeof(struct tc_rsvp_pinfo) },
+};
+
static int rsvp_change(struct tcf_proto *tp, unsigned long base,
u32 handle,
struct nlattr **tca,
@@ -416,7 +425,7 @@ static int rsvp_change(struct tcf_proto *tp, unsigned long base,
if (opt == NULL)
return handle ? -EINVAL : 0;
- err = nla_parse_nested(tb, TCA_RSVP_MAX, opt, NULL);
+ err = nla_parse_nested(tb, TCA_RSVP_MAX, opt, rsvp_policy);
if (err < 0)
return err;
@@ -452,30 +461,17 @@ static int rsvp_change(struct tcf_proto *tp, unsigned long base,
h2 = 16;
if (tb[TCA_RSVP_SRC-1]) {
- err = -EINVAL;
- if (nla_len(tb[TCA_RSVP_SRC-1]) != sizeof(f->src))
- goto errout;
memcpy(f->src, nla_data(tb[TCA_RSVP_SRC-1]), sizeof(f->src));
h2 = hash_src(f->src);
}
if (tb[TCA_RSVP_PINFO-1]) {
- err = -EINVAL;
- if (nla_len(tb[TCA_RSVP_PINFO-1]) < sizeof(struct tc_rsvp_pinfo))
- goto errout;
pinfo = nla_data(tb[TCA_RSVP_PINFO-1]);
f->spi = pinfo->spi;
f->tunnelhdr = pinfo->tunnelhdr;
}
- if (tb[TCA_RSVP_CLASSID-1]) {
- err = -EINVAL;
- if (nla_len(tb[TCA_RSVP_CLASSID-1]) != 4)
- goto errout;
+ if (tb[TCA_RSVP_CLASSID-1])
f->res.classid = nla_get_u32(tb[TCA_RSVP_CLASSID-1]);
- }
- err = -EINVAL;
- if (nla_len(tb[TCA_RSVP_DST-1]) != sizeof(f->src))
- goto errout;
dst = nla_data(tb[TCA_RSVP_DST-1]);
h1 = hash_dst(dst, pinfo ? pinfo->protocol : 0, pinfo ? pinfo->tunnelid : 0);
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c
index 2809856..ee60b2d 100644
--- a/net/sched/cls_tcindex.c
+++ b/net/sched/cls_tcindex.c
@@ -193,6 +193,14 @@ valid_perfect_hash(struct tcindex_data *p)
return p->hash > (p->mask >> p->shift);
}
+static const struct nla_policy tcindex_policy[TCA_TCINDEX_MAX + 1] = {
+ [TCA_TCINDEX_HASH] = { .type = NLA_U32 },
+ [TCA_TCINDEX_MASK] = { .type = NLA_U16 },
+ [TCA_TCINDEX_SHIFT] = { .type = NLA_U32 },
+ [TCA_TCINDEX_FALL_THROUGH] = { .type = NLA_U32 },
+ [TCA_TCINDEX_CLASSID] = { .type = NLA_U32 },
+};
+
static int
tcindex_set_parms(struct tcf_proto *tp, unsigned long base, u32 handle,
struct tcindex_data *p, struct tcindex_filter_result *r,
@@ -217,24 +225,14 @@ tcindex_set_parms(struct tcf_proto *tp, unsigned long base, u32 handle,
else
memset(&cr, 0, sizeof(cr));
- err = -EINVAL;
- if (tb[TCA_TCINDEX_HASH]) {
- if (nla_len(tb[TCA_TCINDEX_HASH]) < sizeof(u32))
- goto errout;
+ if (tb[TCA_TCINDEX_HASH])
cp.hash = nla_get_u32(tb[TCA_TCINDEX_HASH]);
- }
- if (tb[TCA_TCINDEX_MASK]) {
- if (nla_len(tb[TCA_TCINDEX_MASK]) < sizeof(u16))
- goto errout;
+ if (tb[TCA_TCINDEX_MASK])
cp.mask = nla_get_u16(tb[TCA_TCINDEX_MASK]);
- }
- if (tb[TCA_TCINDEX_SHIFT]) {
- if (nla_len(tb[TCA_TCINDEX_SHIFT]) < sizeof(int))
- goto errout;
+ if (tb[TCA_TCINDEX_SHIFT])
cp.shift = nla_get_u32(tb[TCA_TCINDEX_SHIFT]);
- }
err = -EBUSY;
/* Hash already allocated, make sure that we still meet the
@@ -248,11 +246,8 @@ tcindex_set_parms(struct tcf_proto *tp, unsigned long base, u32 handle,
goto errout;
err = -EINVAL;
- if (tb[TCA_TCINDEX_FALL_THROUGH]) {
- if (nla_len(tb[TCA_TCINDEX_FALL_THROUGH]) < sizeof(u32))
- goto errout;
+ if (tb[TCA_TCINDEX_FALL_THROUGH])
cp.fall_through = nla_get_u32(tb[TCA_TCINDEX_FALL_THROUGH]);
- }
if (!cp.hash) {
/* Hash not specified, use perfect hash if the upper limit
@@ -358,7 +353,7 @@ tcindex_change(struct tcf_proto *tp, unsigned long base, u32 handle,
if (!opt)
return 0;
- err = nla_parse_nested(tb, TCA_TCINDEX_MAX, opt, NULL);
+ err = nla_parse_nested(tb, TCA_TCINDEX_MAX, opt, tcindex_policy);
if (err < 0)
return err;
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index a4e72e8..e8a7756 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -460,6 +460,16 @@ static u32 gen_new_kid(struct tc_u_hnode *ht, u32 handle)
return handle|(i>0xFFF ? 0xFFF : i);
}
+static const struct nla_policy u32_policy[TCA_U32_MAX + 1] = {
+ [TCA_U32_CLASSID] = { .type = NLA_U32 },
+ [TCA_U32_HASH] = { .type = NLA_U32 },
+ [TCA_U32_LINK] = { .type = NLA_U32 },
+ [TCA_U32_DIVISOR] = { .type = NLA_U32 },
+ [TCA_U32_SEL] = { .len = sizeof(struct tc_u32_sel) },
+ [TCA_U32_INDEV] = { .type = NLA_STRING, .len = IFNAMSIZ },
+ [TCA_U32_MARK] = { .len = sizeof(struct tc_u32_mark) },
+};
+
static int u32_set_parms(struct tcf_proto *tp, unsigned long base,
struct tc_u_hnode *ht,
struct tc_u_knode *n, struct nlattr **tb,
@@ -531,7 +541,7 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
if (opt == NULL)
return handle ? -EINVAL : 0;
- err = nla_parse_nested(tb, TCA_U32_MAX, opt, NULL);
+ err = nla_parse_nested(tb, TCA_U32_MAX, opt, u32_policy);
if (err < 0)
return err;
@@ -593,8 +603,7 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
} else
handle = gen_new_kid(ht, htid);
- if (tb[TCA_U32_SEL] == NULL ||
- nla_len(tb[TCA_U32_SEL]) < sizeof(struct tc_u32_sel))
+ if (tb[TCA_U32_SEL] == NULL)
return -EINVAL;
s = nla_data(tb[TCA_U32_SEL]);
@@ -620,13 +629,6 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
if (tb[TCA_U32_MARK]) {
struct tc_u32_mark *mark;
- if (nla_len(tb[TCA_U32_MARK]) < sizeof(struct tc_u32_mark)) {
-#ifdef CONFIG_CLS_U32_PERF
- kfree(n->pf);
-#endif
- kfree(n);
- return -EINVAL;
- }
mark = nla_data(tb[TCA_U32_MARK]);
memcpy(&n->mark, mark, sizeof(struct tc_u32_mark));
n->mark.success = 0;
^ permalink raw reply related
* [NET_SCHED 12/15]: Use nla_policy for attribute validation in packet schedulers
From: Patrick McHardy @ 2008-01-23 16:36 UTC (permalink / raw)
To: davem; +Cc: netdev, Patrick McHardy
In-Reply-To: <20080123163555.6459.69501.sendpatchset@localhost.localdomain>
[NET_SCHED]: Use nla_policy for attribute validation in packet schedulers
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
commit 76c3c24283fa9f78d8dc30c8eb73e0f11934bf69
tree bcc9baf4eae9086d377efff17fbd37a360ac64b7
parent b21f31e516f993016f8a1ade331bcaf71576b4e2
author Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:12:57 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:12:57 +0100
net/sched/sch_atm.c | 12 ++++++++----
net/sched/sch_cbq.c | 47 +++++++++++++----------------------------------
net/sched/sch_dsmark.c | 33 +++++++++++++++------------------
net/sched/sch_gred.c | 16 ++++++++++------
net/sched/sch_hfsc.c | 14 +++++++-------
net/sched/sch_htb.c | 17 +++++++++++------
net/sched/sch_netem.c | 19 ++++++++-----------
net/sched/sch_red.c | 11 +++++++----
net/sched/sch_tbf.c | 11 ++++++++---
9 files changed, 87 insertions(+), 93 deletions(-)
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index 0c71f2e..3352734 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -195,6 +195,11 @@ static const u8 llc_oui_ip[] = {
0x08, 0x00
}; /* Ethertype IP (0800) */
+static const struct nla_policy atm_policy[TCA_ATM_MAX + 1] = {
+ [TCA_ATM_FD] = { .type = NLA_U32 },
+ [TCA_ATM_EXCESS] = { .type = NLA_U32 },
+};
+
static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
struct nlattr **tca, unsigned long *arg)
{
@@ -225,11 +230,12 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
return -EBUSY;
if (opt == NULL)
return -EINVAL;
- error = nla_parse_nested(tb, TCA_ATM_MAX, opt, NULL);
+
+ error = nla_parse_nested(tb, TCA_ATM_MAX, opt, atm_policy);
if (error < 0)
return error;
- if (!tb[TCA_ATM_FD] || nla_len(tb[TCA_ATM_FD]) < sizeof(fd))
+ if (!tb[TCA_ATM_FD])
return -EINVAL;
fd = nla_get_u32(tb[TCA_ATM_FD]);
pr_debug("atm_tc_change: fd %d\n", fd);
@@ -243,8 +249,6 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
if (!tb[TCA_ATM_EXCESS])
excess = NULL;
else {
- if (nla_len(tb[TCA_ATM_EXCESS]) != sizeof(u32))
- return -EINVAL;
excess = (struct atm_flow_data *)
atm_tc_get(sch, nla_get_u32(tb[TCA_ATM_EXCESS]));
if (!excess)
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index da0f6c0..09969c1 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -1377,6 +1377,16 @@ static int cbq_set_fopt(struct cbq_class *cl, struct tc_cbq_fopt *fopt)
return 0;
}
+static const struct nla_policy cbq_policy[TCA_CBQ_MAX + 1] = {
+ [TCA_CBQ_LSSOPT] = { .len = sizeof(struct tc_cbq_lssopt) },
+ [TCA_CBQ_WRROPT] = { .len = sizeof(struct tc_cbq_wrropt) },
+ [TCA_CBQ_FOPT] = { .len = sizeof(struct tc_cbq_fopt) },
+ [TCA_CBQ_OVL_STRATEGY] = { .len = sizeof(struct tc_cbq_ovl) },
+ [TCA_CBQ_RATE] = { .len = sizeof(struct tc_ratespec) },
+ [TCA_CBQ_RTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
+ [TCA_CBQ_POLICE] = { .len = sizeof(struct tc_cbq_police) },
+};
+
static int cbq_init(struct Qdisc *sch, struct nlattr *opt)
{
struct cbq_sched_data *q = qdisc_priv(sch);
@@ -1384,16 +1394,11 @@ static int cbq_init(struct Qdisc *sch, struct nlattr *opt)
struct tc_ratespec *r;
int err;
- err = nla_parse_nested(tb, TCA_CBQ_MAX, opt, NULL);
+ err = nla_parse_nested(tb, TCA_CBQ_MAX, opt, cbq_policy);
if (err < 0)
return err;
- if (tb[TCA_CBQ_RTAB] == NULL || tb[TCA_CBQ_RATE] == NULL ||
- nla_len(tb[TCA_CBQ_RATE]) < sizeof(struct tc_ratespec))
- return -EINVAL;
-
- if (tb[TCA_CBQ_LSSOPT] &&
- nla_len(tb[TCA_CBQ_LSSOPT]) < sizeof(struct tc_cbq_lssopt))
+ if (tb[TCA_CBQ_RTAB] == NULL || tb[TCA_CBQ_RATE] == NULL)
return -EINVAL;
r = nla_data(tb[TCA_CBQ_RATE]);
@@ -1771,36 +1776,10 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
if (opt == NULL)
return -EINVAL;
- err = nla_parse_nested(tb, TCA_CBQ_MAX, opt, NULL);
+ err = nla_parse_nested(tb, TCA_CBQ_MAX, opt, cbq_policy);
if (err < 0)
return err;
- if (tb[TCA_CBQ_OVL_STRATEGY] &&
- nla_len(tb[TCA_CBQ_OVL_STRATEGY]) < sizeof(struct tc_cbq_ovl))
- return -EINVAL;
-
- if (tb[TCA_CBQ_FOPT] &&
- nla_len(tb[TCA_CBQ_FOPT]) < sizeof(struct tc_cbq_fopt))
- return -EINVAL;
-
- if (tb[TCA_CBQ_RATE] &&
- nla_len(tb[TCA_CBQ_RATE]) < sizeof(struct tc_ratespec))
- return -EINVAL;
-
- if (tb[TCA_CBQ_LSSOPT] &&
- nla_len(tb[TCA_CBQ_LSSOPT]) < sizeof(struct tc_cbq_lssopt))
- return -EINVAL;
-
- if (tb[TCA_CBQ_WRROPT] &&
- nla_len(tb[TCA_CBQ_WRROPT]) < sizeof(struct tc_cbq_wrropt))
- return -EINVAL;
-
-#ifdef CONFIG_NET_CLS_ACT
- if (tb[TCA_CBQ_POLICE] &&
- nla_len(tb[TCA_CBQ_POLICE]) < sizeof(struct tc_cbq_police))
- return -EINVAL;
-#endif
-
if (cl) {
/* Check parent */
if (parentid) {
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c
index f1d0a08..0df911f 100644
--- a/net/sched/sch_dsmark.c
+++ b/net/sched/sch_dsmark.c
@@ -99,6 +99,14 @@ static void dsmark_put(struct Qdisc *sch, unsigned long cl)
{
}
+static const struct nla_policy dsmark_policy[TCA_DSMARK_MAX + 1] = {
+ [TCA_DSMARK_INDICES] = { .type = NLA_U16 },
+ [TCA_DSMARK_DEFAULT_INDEX] = { .type = NLA_U16 },
+ [TCA_DSMARK_SET_TC_INDEX] = { .type = NLA_FLAG },
+ [TCA_DSMARK_MASK] = { .type = NLA_U8 },
+ [TCA_DSMARK_VALUE] = { .type = NLA_U8 },
+};
+
static int dsmark_change(struct Qdisc *sch, u32 classid, u32 parent,
struct nlattr **tca, unsigned long *arg)
{
@@ -119,21 +127,15 @@ static int dsmark_change(struct Qdisc *sch, u32 classid, u32 parent,
if (!opt)
goto errout;
- err = nla_parse_nested(tb, TCA_DSMARK_MAX, opt, NULL);
+ err = nla_parse_nested(tb, TCA_DSMARK_MAX, opt, dsmark_policy);
if (err < 0)
- return err;
+ goto errout;
- err = -EINVAL;
- if (tb[TCA_DSMARK_MASK]) {
- if (nla_len(tb[TCA_DSMARK_MASK]) < sizeof(u8))
- goto errout;
+ if (tb[TCA_DSMARK_MASK])
mask = nla_get_u8(tb[TCA_DSMARK_MASK]);
- }
- if (tb[TCA_DSMARK_VALUE]) {
- if (nla_len(tb[TCA_DSMARK_VALUE]) < sizeof(u8))
- goto errout;
+
+ if (tb[TCA_DSMARK_VALUE])
p->value[*arg-1] = nla_get_u8(tb[TCA_DSMARK_VALUE]);
- }
if (tb[TCA_DSMARK_MASK])
p->mask[*arg-1] = mask;
@@ -359,23 +361,18 @@ static int dsmark_init(struct Qdisc *sch, struct nlattr *opt)
if (!opt)
goto errout;
- err = nla_parse_nested(tb, TCA_DSMARK_MAX, opt, NULL);
+ err = nla_parse_nested(tb, TCA_DSMARK_MAX, opt, dsmark_policy);
if (err < 0)
goto errout;
err = -EINVAL;
- if (nla_len(tb[TCA_DSMARK_INDICES]) < sizeof(u16))
- goto errout;
indices = nla_get_u16(tb[TCA_DSMARK_INDICES]);
if (hweight32(indices) != 1)
goto errout;
- if (tb[TCA_DSMARK_DEFAULT_INDEX]) {
- if (nla_len(tb[TCA_DSMARK_DEFAULT_INDEX]) < sizeof(u16))
- goto errout;
+ if (tb[TCA_DSMARK_DEFAULT_INDEX])
default_index = nla_get_u16(tb[TCA_DSMARK_DEFAULT_INDEX]);
- }
mask = kmalloc(indices * 2, GFP_KERNEL);
if (mask == NULL) {
diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c
index 365c7d8..3a9d226 100644
--- a/net/sched/sch_gred.c
+++ b/net/sched/sch_gred.c
@@ -356,7 +356,7 @@ static inline int gred_change_table_def(struct Qdisc *sch, struct nlattr *dps)
struct tc_gred_sopt *sopt;
int i;
- if (dps == NULL || nla_len(dps) < sizeof(*sopt))
+ if (dps == NULL)
return -EINVAL;
sopt = nla_data(dps);
@@ -425,6 +425,12 @@ static inline int gred_change_vq(struct Qdisc *sch, int dp,
return 0;
}
+static const struct nla_policy gred_policy[TCA_GRED_MAX + 1] = {
+ [TCA_GRED_PARMS] = { .len = sizeof(struct tc_gred_qopt) },
+ [TCA_GRED_STAB] = { .len = 256 },
+ [TCA_GRED_DPS] = { .len = sizeof(struct tc_gred_sopt) },
+};
+
static int gred_change(struct Qdisc *sch, struct nlattr *opt)
{
struct gred_sched *table = qdisc_priv(sch);
@@ -436,7 +442,7 @@ static int gred_change(struct Qdisc *sch, struct nlattr *opt)
if (opt == NULL)
return -EINVAL;
- err = nla_parse_nested(tb, TCA_GRED_MAX, opt, NULL);
+ err = nla_parse_nested(tb, TCA_GRED_MAX, opt, gred_policy);
if (err < 0)
return err;
@@ -444,9 +450,7 @@ static int gred_change(struct Qdisc *sch, struct nlattr *opt)
return gred_change_table_def(sch, opt);
if (tb[TCA_GRED_PARMS] == NULL ||
- nla_len(tb[TCA_GRED_PARMS]) < sizeof(*ctl) ||
- tb[TCA_GRED_STAB] == NULL ||
- nla_len(tb[TCA_GRED_STAB]) < 256)
+ tb[TCA_GRED_STAB] == NULL)
return -EINVAL;
err = -EINVAL;
@@ -499,7 +503,7 @@ static int gred_init(struct Qdisc *sch, struct nlattr *opt)
if (opt == NULL)
return -EINVAL;
- err = nla_parse_nested(tb, TCA_GRED_MAX, opt, NULL);
+ err = nla_parse_nested(tb, TCA_GRED_MAX, opt, gred_policy);
if (err < 0)
return err;
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index 54c3e90..94bf186 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -986,6 +986,12 @@ hfsc_change_usc(struct hfsc_class *cl, struct tc_service_curve *usc,
cl->cl_flags |= HFSC_USC;
}
+static const struct nla_policy hfsc_policy[TCA_HFSC_MAX + 1] = {
+ [TCA_HFSC_RSC] = { .len = sizeof(struct tc_service_curve) },
+ [TCA_HFSC_FSC] = { .len = sizeof(struct tc_service_curve) },
+ [TCA_HFSC_USC] = { .len = sizeof(struct tc_service_curve) },
+};
+
static int
hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
struct nlattr **tca, unsigned long *arg)
@@ -1002,29 +1008,23 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
if (opt == NULL)
return -EINVAL;
- err = nla_parse_nested(tb, TCA_HFSC_MAX, opt, NULL);
+ err = nla_parse_nested(tb, TCA_HFSC_MAX, opt, hfsc_policy);
if (err < 0)
return err;
if (tb[TCA_HFSC_RSC]) {
- if (nla_len(tb[TCA_HFSC_RSC]) < sizeof(*rsc))
- return -EINVAL;
rsc = nla_data(tb[TCA_HFSC_RSC]);
if (rsc->m1 == 0 && rsc->m2 == 0)
rsc = NULL;
}
if (tb[TCA_HFSC_FSC]) {
- if (nla_len(tb[TCA_HFSC_FSC]) < sizeof(*fsc))
- return -EINVAL;
fsc = nla_data(tb[TCA_HFSC_FSC]);
if (fsc->m1 == 0 && fsc->m2 == 0)
fsc = NULL;
}
if (tb[TCA_HFSC_USC]) {
- if (nla_len(tb[TCA_HFSC_USC]) < sizeof(*usc))
- return -EINVAL;
usc = nla_data(tb[TCA_HFSC_USC]);
if (usc->m1 == 0 && usc->m2 == 0)
usc = NULL;
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 69fac32..e1a579e 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -992,6 +992,13 @@ static void htb_reset(struct Qdisc *sch)
INIT_LIST_HEAD(q->drops + i);
}
+static const struct nla_policy htb_policy[TCA_HTB_MAX + 1] = {
+ [TCA_HTB_PARMS] = { .len = sizeof(struct tc_htb_opt) },
+ [TCA_HTB_INIT] = { .len = sizeof(struct tc_htb_glob) },
+ [TCA_HTB_CTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
+ [TCA_HTB_RTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
+};
+
static int htb_init(struct Qdisc *sch, struct nlattr *opt)
{
struct htb_sched *q = qdisc_priv(sch);
@@ -1003,12 +1010,11 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt)
if (!opt)
return -EINVAL;
- err = nla_parse_nested(tb, TCA_HTB_INIT, opt, NULL);
+ err = nla_parse_nested(tb, TCA_HTB_INIT, opt, htb_policy);
if (err < 0)
return err;
- if (tb[TCA_HTB_INIT] == NULL ||
- nla_len(tb[TCA_HTB_INIT]) < sizeof(*gopt)) {
+ if (tb[TCA_HTB_INIT] == NULL) {
printk(KERN_ERR "HTB: hey probably you have bad tc tool ?\n");
return -EINVAL;
}
@@ -1319,13 +1325,12 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
if (!opt)
goto failure;
- err = nla_parse_nested(tb, TCA_HTB_RTAB, opt, NULL);
+ err = nla_parse_nested(tb, TCA_HTB_RTAB, opt, htb_policy);
if (err < 0)
goto failure;
err = -EINVAL;
- if (tb[TCA_HTB_PARMS] == NULL ||
- nla_len(tb[TCA_HTB_PARMS]) < sizeof(*hopt))
+ if (tb[TCA_HTB_PARMS] == NULL)
goto failure;
parent = parentid == TC_H_ROOT ? NULL : htb_find(parentid, sch);
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 1a75579..c9c649b 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -368,9 +368,6 @@ static int get_correlation(struct Qdisc *sch, const struct nlattr *attr)
struct netem_sched_data *q = qdisc_priv(sch);
const struct tc_netem_corr *c = nla_data(attr);
- if (nla_len(attr) != sizeof(*c))
- return -EINVAL;
-
init_crandom(&q->delay_cor, c->delay_corr);
init_crandom(&q->loss_cor, c->loss_corr);
init_crandom(&q->dup_cor, c->dup_corr);
@@ -382,9 +379,6 @@ static int get_reorder(struct Qdisc *sch, const struct nlattr *attr)
struct netem_sched_data *q = qdisc_priv(sch);
const struct tc_netem_reorder *r = nla_data(attr);
- if (nla_len(attr) != sizeof(*r))
- return -EINVAL;
-
q->reorder = r->probability;
init_crandom(&q->reorder_cor, r->correlation);
return 0;
@@ -395,14 +389,17 @@ static int get_corrupt(struct Qdisc *sch, const struct nlattr *attr)
struct netem_sched_data *q = qdisc_priv(sch);
const struct tc_netem_corrupt *r = nla_data(attr);
- if (nla_len(attr) != sizeof(*r))
- return -EINVAL;
-
q->corrupt = r->probability;
init_crandom(&q->corrupt_cor, r->correlation);
return 0;
}
+static const struct nla_policy netem_policy[TCA_NETEM_MAX + 1] = {
+ [TCA_NETEM_CORR] = { .len = sizeof(struct tc_netem_corr) },
+ [TCA_NETEM_REORDER] = { .len = sizeof(struct tc_netem_reorder) },
+ [TCA_NETEM_CORRUPT] = { .len = sizeof(struct tc_netem_corrupt) },
+};
+
/* Parse netlink message to set options */
static int netem_change(struct Qdisc *sch, struct nlattr *opt)
{
@@ -414,8 +411,8 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt)
if (opt == NULL)
return -EINVAL;
- ret = nla_parse_nested_compat(tb, TCA_NETEM_MAX, opt, NULL, qopt,
- sizeof(*qopt));
+ ret = nla_parse_nested_compat(tb, TCA_NETEM_MAX, opt, netem_policy,
+ qopt, sizeof(*qopt));
if (ret < 0)
return ret;
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c
index dcf6afc..3dcd493 100644
--- a/net/sched/sch_red.c
+++ b/net/sched/sch_red.c
@@ -201,6 +201,11 @@ static struct Qdisc *red_create_dflt(struct Qdisc *sch, u32 limit)
return NULL;
}
+static const struct nla_policy red_policy[TCA_RED_MAX + 1] = {
+ [TCA_RED_PARMS] = { .len = sizeof(struct tc_red_qopt) },
+ [TCA_RED_STAB] = { .len = RED_STAB_SIZE },
+};
+
static int red_change(struct Qdisc *sch, struct nlattr *opt)
{
struct red_sched_data *q = qdisc_priv(sch);
@@ -212,14 +217,12 @@ static int red_change(struct Qdisc *sch, struct nlattr *opt)
if (opt == NULL)
return -EINVAL;
- err = nla_parse_nested(tb, TCA_RED_MAX, opt, NULL);
+ err = nla_parse_nested(tb, TCA_RED_MAX, opt, red_policy);
if (err < 0)
return err;
if (tb[TCA_RED_PARMS] == NULL ||
- nla_len(tb[TCA_RED_PARMS]) < sizeof(*ctl) ||
- tb[TCA_RED_STAB] == NULL ||
- nla_len(tb[TCA_RED_STAB]) < RED_STAB_SIZE)
+ tb[TCA_RED_STAB] == NULL)
return -EINVAL;
ctl = nla_data(tb[TCA_RED_PARMS]);
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
index b7a185d..0b7d78f 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -270,6 +270,12 @@ static struct Qdisc *tbf_create_dflt_qdisc(struct Qdisc *sch, u32 limit)
return NULL;
}
+static const struct nla_policy tbf_policy[TCA_TBF_MAX + 1] = {
+ [TCA_TBF_PARMS] = { .len = sizeof(struct tc_tbf_qopt) },
+ [TCA_TBF_RTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
+ [TCA_TBF_PTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
+};
+
static int tbf_change(struct Qdisc* sch, struct nlattr *opt)
{
int err;
@@ -281,13 +287,12 @@ static int tbf_change(struct Qdisc* sch, struct nlattr *opt)
struct Qdisc *child = NULL;
int max_size,n;
- err = nla_parse_nested(tb, TCA_TBF_PTAB, opt, NULL);
+ err = nla_parse_nested(tb, TCA_TBF_PTAB, opt, tbf_policy);
if (err < 0)
return err;
err = -EINVAL;
- if (tb[TCA_TBF_PARMS] == NULL ||
- nla_len(tb[TCA_TBF_PARMS]) < sizeof(*qopt))
+ if (tb[TCA_TBF_PARMS] == NULL)
goto done;
qopt = nla_data(tb[TCA_TBF_PARMS]);
^ permalink raw reply related
* [NET_SCHED 11/15]: sch_api: introduce constant for rate table size
From: Patrick McHardy @ 2008-01-23 16:36 UTC (permalink / raw)
To: davem; +Cc: netdev, Patrick McHardy
In-Reply-To: <20080123163555.6459.69501.sendpatchset@localhost.localdomain>
[NET_SCHED]: sch_api: introduce constant for rate table size
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
commit b21f31e516f993016f8a1ade331bcaf71576b4e2
tree e59049e1fb3f2711d83c196d2f54b5021dc68330
parent 3e73383f7c353af51e8cc475f1c217a6b81fcecf
author Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:12:56 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:12:56 +0100
include/linux/pkt_sched.h | 2 ++
net/sched/sch_api.c | 3 ++-
2 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h
index 919af93..3276135 100644
--- a/include/linux/pkt_sched.h
+++ b/include/linux/pkt_sched.h
@@ -83,6 +83,8 @@ struct tc_ratespec
__u32 rate;
};
+#define TC_RTAB_SIZE 1024
+
/* FIFO section */
struct tc_fifo_qopt
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 8db554d..7e3c048 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -244,7 +244,8 @@ struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r, struct nlattr *ta
}
}
- if (tab == NULL || r->rate == 0 || r->cell_log == 0 || nla_len(tab) != 1024)
+ if (tab == NULL || r->rate == 0 || r->cell_log == 0 ||
+ nla_len(tab) != TC_RTAB_SIZE)
return NULL;
rtab = kmalloc(sizeof(*rtab), GFP_KERNEL);
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox