Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[safe/jmp/linux-2.6] / net / sched / cls_route.c
index ae97238..694dcd8 100644 (file)
@@ -10,6 +10,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
@@ -62,7 +63,7 @@ struct route4_filter
 
 #define ROUTE4_FAILURE ((struct route4_filter*)(-1L))
 
-static struct tcf_ext_map route_ext_map = {
+static const struct tcf_ext_map route_ext_map = {
        .police = TCA_ROUTE4_POLICE,
        .action = TCA_ROUTE4_ACT
 };
@@ -73,11 +74,13 @@ static __inline__ int route4_fastmap_hash(u32 id, int iif)
 }
 
 static inline
-void route4_reset_fastmap(struct net_device *dev, struct route4_head *head, u32 id)
+void route4_reset_fastmap(struct Qdisc *q, struct route4_head *head, u32 id)
 {
-       qdisc_lock_tree(dev);
+       spinlock_t *root_lock = qdisc_root_sleeping_lock(q);
+
+       spin_lock_bh(root_lock);
        memset(head->fastmap, 0, sizeof(head->fastmap));
-       qdisc_unlock_tree(dev);
+       spin_unlock_bh(root_lock);
 }
 
 static inline void
@@ -135,7 +138,7 @@ static int route4_classify(struct sk_buff *skb, struct tcf_proto *tp,
        u32 id, h;
        int iif, dont_cache = 0;
 
-       if ((dst = skb->dst) == NULL)
+       if ((dst = skb_dst(skb)) == NULL)
                goto failure;
 
        id = dst->tclassid;
@@ -258,7 +261,7 @@ route4_delete_filter(struct tcf_proto *tp, struct route4_filter *f)
 
 static void route4_destroy(struct tcf_proto *tp)
 {
-       struct route4_head *head = xchg(&tp->root, NULL);
+       struct route4_head *head = tp->root;
        int h1, h2;
 
        if (head == NULL)
@@ -302,7 +305,7 @@ static int route4_delete(struct tcf_proto *tp, unsigned long arg)
                        *fp = f->next;
                        tcf_tree_unlock(tp);
 
-                       route4_reset_fastmap(tp->q->dev, head, f->id);
+                       route4_reset_fastmap(tp->q, head, f->id);
                        route4_delete_filter(tp, f);
 
                        /* Strip tree */
@@ -323,6 +326,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 +349,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 +361,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 +440,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;
 
@@ -503,7 +503,7 @@ reinsert:
        }
        tcf_tree_unlock(tp);
 
-       route4_reset_fastmap(tp->q->dev, head, f->id);
+       route4_reset_fastmap(tp->q, head, f->id);
        *arg = (unsigned long)f;
        return 0;