]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/sched/cls_api.c
watchdog: fix platform driver hotplug/coldplug
[linux-2.6-omap-h63xx.git] / net / sched / cls_api.c
index 9eeb3c6c82f4e4aa557689aa23734f0467edaa0e..0fbedcabf1110759c41117253ae7cc73d6f7a768 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/init.h>
 #include <linux/kmod.h>
 #include <linux/netlink.h>
+#include <linux/err.h>
 #include <net/net_namespace.h>
 #include <net/sock.h>
 #include <net/netlink.h>
@@ -38,14 +39,14 @@ static DEFINE_RWLOCK(cls_mod_lock);
 
 /* Find classifier type by string name */
 
-static struct tcf_proto_ops *tcf_proto_lookup_ops(struct rtattr *kind)
+static struct tcf_proto_ops *tcf_proto_lookup_ops(struct nlattr *kind)
 {
        struct tcf_proto_ops *t = NULL;
 
        if (kind) {
                read_lock(&cls_mod_lock);
                for (t = tcf_proto_base; t; t = t->next) {
-                       if (rtattr_strcmp(kind, t->kind) == 0) {
+                       if (nla_strcmp(kind, t->kind) == 0) {
                                if (!try_module_get(t->owner))
                                        t = NULL;
                                break;
@@ -118,7 +119,7 @@ static inline u32 tcf_auto_prio(struct tcf_proto *tp)
 static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
 {
        struct net *net = skb->sk->sk_net;
-       struct rtattr **tca;
+       struct nlattr *tca[TCA_MAX + 1];
        struct tcmsg *t;
        u32 protocol;
        u32 prio;
@@ -138,7 +139,6 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
                return -EINVAL;
 
 replay:
-       tca = arg;
        t = NLMSG_DATA(n);
        protocol = TC_H_MIN(t->tcm_info);
        prio = TC_H_MAJ(t->tcm_info);
@@ -160,6 +160,10 @@ replay:
        if (dev == NULL)
                return -ENODEV;
 
+       err = nlmsg_parse(n, sizeof(*t), tca, TCA_MAX, NULL);
+       if (err < 0)
+               return err;
+
        /* Find qdisc */
        if (!parent) {
                q = dev->qdisc_sleeping;
@@ -202,7 +206,7 @@ replay:
        if (tp == NULL) {
                /* Proto-tcf does not exist, create new one */
 
-               if (tca[TCA_KIND-1] == NULL || !protocol)
+               if (tca[TCA_KIND] == NULL || !protocol)
                        goto errout;
 
                err = -ENOENT;
@@ -217,14 +221,14 @@ replay:
                if (tp == NULL)
                        goto errout;
                err = -EINVAL;
-               tp_ops = tcf_proto_lookup_ops(tca[TCA_KIND-1]);
+               tp_ops = tcf_proto_lookup_ops(tca[TCA_KIND]);
                if (tp_ops == NULL) {
 #ifdef CONFIG_KMOD
-                       struct rtattr *kind = tca[TCA_KIND-1];
+                       struct nlattr *kind = tca[TCA_KIND];
                        char name[IFNAMSIZ];
 
                        if (kind != NULL &&
-                           rtattr_strlcpy(name, kind, IFNAMSIZ) < IFNAMSIZ) {
+                           nla_strlcpy(name, kind, IFNAMSIZ) < IFNAMSIZ) {
                                rtnl_unlock();
                                request_module("cls_%s", name);
                                rtnl_lock();
@@ -263,7 +267,7 @@ replay:
                *back = tp;
                qdisc_unlock_tree(dev);
 
-       } else if (tca[TCA_KIND-1] && rtattr_strcmp(tca[TCA_KIND-1], tp->ops->kind))
+       } else if (tca[TCA_KIND] && nla_strcmp(tca[TCA_KIND], tp->ops->kind))
                goto errout;
 
        fh = tp->ops->get(tp, t->tcm_handle);
@@ -333,18 +337,18 @@ static int tcf_fill_node(struct sk_buff *skb, struct tcf_proto *tp,
        tcm->tcm_ifindex = tp->q->dev->ifindex;
        tcm->tcm_parent = tp->classid;
        tcm->tcm_info = TC_H_MAKE(tp->prio, tp->protocol);
-       RTA_PUT(skb, TCA_KIND, IFNAMSIZ, tp->ops->kind);
+       NLA_PUT_STRING(skb, TCA_KIND, tp->ops->kind);
        tcm->tcm_handle = fh;
        if (RTM_DELTFILTER != event) {
                tcm->tcm_handle = 0;
                if (tp->ops->dump && tp->ops->dump(tp, fh, skb, tcm) < 0)
-                       goto rtattr_failure;
+                       goto nla_put_failure;
        }
        nlh->nlmsg_len = skb_tail_pointer(skb) - b;
        return skb->len;
 
 nlmsg_failure:
-rtattr_failure:
+nla_put_failure:
        nlmsg_trim(skb, b);
        return -1;
 }
@@ -476,38 +480,37 @@ void tcf_exts_destroy(struct tcf_proto *tp, struct tcf_exts *exts)
 }
 EXPORT_SYMBOL(tcf_exts_destroy);
 
-int tcf_exts_validate(struct tcf_proto *tp, struct rtattr **tb,
-                 struct rtattr *rate_tlv, struct tcf_exts *exts,
-                 struct tcf_ext_map *map)
+int tcf_exts_validate(struct tcf_proto *tp, struct nlattr **tb,
+                 struct nlattr *rate_tlv, struct tcf_exts *exts,
+                 const struct tcf_ext_map *map)
 {
        memset(exts, 0, sizeof(*exts));
 
 #ifdef CONFIG_NET_CLS_ACT
        {
-               int err;
                struct tc_action *act;
 
-               if (map->police && tb[map->police-1]) {
-                       act = tcf_action_init_1(tb[map->police-1], rate_tlv,
+               if (map->police && tb[map->police]) {
+                       act = tcf_action_init_1(tb[map->police], rate_tlv,
                                                "police", TCA_ACT_NOREPLACE,
-                                               TCA_ACT_BIND, &err);
-                       if (act == NULL)
-                               return err;
+                                               TCA_ACT_BIND);
+                       if (IS_ERR(act))
+                               return PTR_ERR(act);
 
                        act->type = TCA_OLD_COMPAT;
                        exts->action = act;
-               } else if (map->action && tb[map->action-1]) {
-                       act = tcf_action_init(tb[map->action-1], rate_tlv, NULL,
-                               TCA_ACT_NOREPLACE, TCA_ACT_BIND, &err);
-                       if (act == NULL)
-                               return err;
+               } else if (map->action && tb[map->action]) {
+                       act = tcf_action_init(tb[map->action], rate_tlv, NULL,
+                                             TCA_ACT_NOREPLACE, TCA_ACT_BIND);
+                       if (IS_ERR(act))
+                               return PTR_ERR(act);
 
                        exts->action = act;
                }
        }
 #else
-       if ((map->action && tb[map->action-1]) ||
-           (map->police && tb[map->police-1]))
+       if ((map->action && tb[map->action]) ||
+           (map->police && tb[map->police]))
                return -EOPNOTSUPP;
 #endif
 
@@ -532,7 +535,7 @@ void tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst,
 EXPORT_SYMBOL(tcf_exts_change);
 
 int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts,
-             struct tcf_ext_map *map)
+                 const struct tcf_ext_map *map)
 {
 #ifdef CONFIG_NET_CLS_ACT
        if (map->action && exts->action) {
@@ -541,38 +544,42 @@ int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts,
                 * to work with both old and new modes of entering
                 * tc data even if iproute2  was newer - jhs
                 */
-               struct rtattr *p_rta = (struct rtattr *)skb_tail_pointer(skb);
+               struct nlattr *nest;
 
                if (exts->action->type != TCA_OLD_COMPAT) {
-                       RTA_PUT(skb, map->action, 0, NULL);
+                       nest = nla_nest_start(skb, map->action);
+                       if (nest == NULL)
+                               goto nla_put_failure;
                        if (tcf_action_dump(skb, exts->action, 0, 0) < 0)
-                               goto rtattr_failure;
-                       p_rta->rta_len = skb_tail_pointer(skb) - (u8 *)p_rta;
+                               goto nla_put_failure;
+                       nla_nest_end(skb, nest);
                } else if (map->police) {
-                       RTA_PUT(skb, map->police, 0, NULL);
+                       nest = nla_nest_start(skb, map->police);
+                       if (nest == NULL)
+                               goto nla_put_failure;
                        if (tcf_action_dump_old(skb, exts->action, 0, 0) < 0)
-                               goto rtattr_failure;
-                       p_rta->rta_len = skb_tail_pointer(skb) - (u8 *)p_rta;
+                               goto nla_put_failure;
+                       nla_nest_end(skb, nest);
                }
        }
 #endif
        return 0;
-rtattr_failure: __attribute__ ((unused))
+nla_put_failure: __attribute__ ((unused))
        return -1;
 }
 EXPORT_SYMBOL(tcf_exts_dump);
 
 
 int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts,
-                       struct tcf_ext_map *map)
+                       const struct tcf_ext_map *map)
 {
 #ifdef CONFIG_NET_CLS_ACT
        if (exts->action)
                if (tcf_action_copy_stats(skb, exts->action, 1) < 0)
-                       goto rtattr_failure;
+                       goto nla_put_failure;
 #endif
        return 0;
-rtattr_failure: __attribute__ ((unused))
+nla_put_failure: __attribute__ ((unused))
        return -1;
 }
 EXPORT_SYMBOL(tcf_exts_dump_stats);