aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@nuts.davemloft.net>2005-01-13 04:26:52 -0800
committerDavid S. Miller <davem@nuts.davemloft.net>2005-01-13 04:26:52 -0800
commitaf06ea11b1e55ad590633ec89322848eaf4d2242 (patch)
tree278c70fac134b38646ec385d204f397c0fe9dbfa /net
parent453269c56af16eabea712fdbc304cd290a78a2fb (diff)
parent437293de63d8979bd9288a29352899e72fff581a (diff)
downloadhistory-af06ea11b1e55ad590633ec89322848eaf4d2242.tar.gz
Merge bk://212.42.230.204/net-2.6-sched
into nuts.davemloft.net:/disk1/BK/tgraf-2.6
Diffstat (limited to 'net')
-rw-r--r--net/sched/act_api.c42
-rw-r--r--net/sched/cls_api.c53
-rw-r--r--net/sched/cls_u32.c16
-rw-r--r--net/sched/gact.c3
-rw-r--r--net/sched/ipt.c3
-rw-r--r--net/sched/mirred.c7
-rw-r--r--net/sched/pedit.c3
-rw-r--r--net/sched/police.c10
-rw-r--r--net/sched/sch_atm.c4
-rw-r--r--net/sched/sch_cbq.c5
-rw-r--r--net/sched/sch_dsmark.c3
-rw-r--r--net/sched/sch_gred.c15
-rw-r--r--net/sched/sch_hfsc.c3
-rw-r--r--net/sched/sch_htb.c4
-rw-r--r--net/sched/sch_red.c2
-rw-r--r--net/sched/sch_tbf.c2
16 files changed, 98 insertions, 77 deletions
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index d4842643928a0f..338e259484aa48 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -279,8 +279,7 @@ struct tc_action *tcf_action_init_1(struct rtattr *rta, struct rtattr *est,
*err = -EINVAL;
if (name == NULL) {
- if (rtattr_parse(tb, TCA_ACT_MAX, RTA_DATA(rta),
- RTA_PAYLOAD(rta)) < 0)
+ if (rtattr_parse_nested(tb, TCA_ACT_MAX, rta) < 0)
goto err_out;
kind = tb[TCA_ACT_KIND-1];
if (kind == NULL)
@@ -292,16 +291,28 @@ struct tc_action *tcf_action_init_1(struct rtattr *rta, struct rtattr *est,
goto err_out;
}
- *err = -ENOENT;
a_o = tc_lookup_action_n(act_name);
-#ifdef CONFIG_KMOD
if (a_o == NULL) {
+#ifdef CONFIG_KMOD
+ rtnl_unlock();
request_module(act_name);
+ rtnl_lock();
+
a_o = tc_lookup_action_n(act_name);
- }
+
+ /* We dropped the RTNL semaphore in order to
+ * perform the module load. So, even if we
+ * succeeded in loading the module we have to
+ * tell the caller to replay the request. We
+ * indicate this using -EAGAIN.
+ */
+ if (a_o != NULL) {
+ *err = -EAGAIN;
+ goto err_mod;
+ }
#endif
- if (a_o == NULL)
goto err_out;
+ }
*err = -ENOMEM;
a = kmalloc(sizeof(*a), GFP_KERNEL);
@@ -344,8 +355,7 @@ struct tc_action *tcf_action_init(struct rtattr *rta, struct rtattr *est,
struct tc_action *head = NULL, *act, *act_prev = NULL;
int i;
- if (rtattr_parse(tb, TCA_ACT_MAX_PRIO, RTA_DATA(rta),
- RTA_PAYLOAD(rta)) < 0) {
+ if (rtattr_parse_nested(tb, TCA_ACT_MAX_PRIO, rta) < 0) {
*err = -EINVAL;
return head;
}
@@ -467,7 +477,7 @@ tcf_action_get_1(struct rtattr *rta, struct nlmsghdr *n, u32 pid, int *err)
int index;
*err = -EINVAL;
- if (rtattr_parse(tb, TCA_ACT_MAX, RTA_DATA(rta), RTA_PAYLOAD(rta)) < 0)
+ if (rtattr_parse_nested(tb, TCA_ACT_MAX, rta) < 0)
return NULL;
if (tb[TCA_ACT_INDEX - 1] == NULL ||
@@ -552,7 +562,7 @@ static int tca_action_flush(struct rtattr *rta, struct nlmsghdr *n, u32 pid)
b = (unsigned char *)skb->tail;
- if (rtattr_parse(tb, TCA_ACT_MAX, RTA_DATA(rta), RTA_PAYLOAD(rta)) < 0)
+ if (rtattr_parse_nested(tb, TCA_ACT_MAX, rta) < 0)
goto err_out;
kind = tb[TCA_ACT_KIND-1];
@@ -599,8 +609,7 @@ tca_action_gd(struct rtattr *rta, struct nlmsghdr *n, u32 pid, int event)
struct rtattr *tb[TCA_ACT_MAX_PRIO+1];
struct tc_action *head = NULL, *act, *act_prev = NULL;
- if (rtattr_parse(tb, TCA_ACT_MAX_PRIO, RTA_DATA(rta),
- RTA_PAYLOAD(rta)) < 0)
+ if (rtattr_parse_nested(tb, TCA_ACT_MAX_PRIO, rta) < 0)
return -EINVAL;
if (event == RTM_DELACTION && n->nlmsg_flags&NLM_F_ROOT) {
@@ -743,7 +752,10 @@ static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
*/
if (n->nlmsg_flags&NLM_F_REPLACE)
ovr = 1;
+replay:
ret = tcf_action_add(tca[TCA_ACT_TAB-1], n, pid, ovr);
+ if (ret == -EAGAIN)
+ goto replay;
break;
case RTM_DELACTION:
ret = tca_action_gd(tca[TCA_ACT_TAB-1], n, pid, RTM_DELACTION);
@@ -871,11 +883,5 @@ subsys_initcall(tc_action_init);
EXPORT_SYMBOL(tcf_register_action);
EXPORT_SYMBOL(tcf_unregister_action);
-EXPORT_SYMBOL(tcf_action_init_1);
-EXPORT_SYMBOL(tcf_action_init);
-EXPORT_SYMBOL(tcf_action_destroy);
EXPORT_SYMBOL(tcf_action_exec);
-EXPORT_SYMBOL(tcf_action_copy_stats);
-EXPORT_SYMBOL(tcf_action_dump);
EXPORT_SYMBOL(tcf_action_dump_1);
-EXPORT_SYMBOL(tcf_action_dump_old);
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index c2e298468d27c8..47cdb71d6b3a00 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -130,22 +130,31 @@ 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 rtattr **tca = arg;
- struct tcmsg *t = NLMSG_DATA(n);
- u32 protocol = TC_H_MIN(t->tcm_info);
- u32 prio = TC_H_MAJ(t->tcm_info);
- u32 nprio = prio;
- u32 parent = t->tcm_parent;
+ struct rtattr **tca;
+ struct tcmsg *t;
+ u32 protocol;
+ u32 prio;
+ u32 nprio;
+ u32 parent;
struct net_device *dev;
struct Qdisc *q;
struct tcf_proto **back, **chain;
- struct tcf_proto *tp = NULL;
+ struct tcf_proto *tp;
struct tcf_proto_ops *tp_ops;
struct Qdisc_class_ops *cops;
- unsigned long cl = 0;
+ unsigned long cl;
unsigned long fh;
int err;
+replay:
+ tca = arg;
+ t = NLMSG_DATA(n);
+ protocol = TC_H_MIN(t->tcm_info);
+ prio = TC_H_MAJ(t->tcm_info);
+ nprio = prio;
+ parent = t->tcm_parent;
+ cl = 0;
+
if (prio == 0) {
/* If no priority is given, user wants we allocated it. */
if (n->nlmsg_type != RTM_NEWTFILTER || !(n->nlmsg_flags&NLM_F_CREATE))
@@ -211,20 +220,29 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
err = -ENOBUFS;
if ((tp = kmalloc(sizeof(*tp), GFP_KERNEL)) == NULL)
goto errout;
+ err = -EINVAL;
tp_ops = tcf_proto_lookup_ops(tca[TCA_KIND-1]);
+ if (tp_ops == NULL) {
#ifdef CONFIG_KMOD
- if (tp_ops==NULL && tca[TCA_KIND-1] != NULL) {
struct rtattr *kind = tca[TCA_KIND-1];
char name[IFNAMSIZ];
- if (rtattr_strlcpy(name, kind, IFNAMSIZ) < IFNAMSIZ) {
+ if (kind != NULL &&
+ rtattr_strlcpy(name, kind, IFNAMSIZ) < IFNAMSIZ) {
+ rtnl_unlock();
request_module("cls_%s", name);
+ rtnl_lock();
tp_ops = tcf_proto_lookup_ops(kind);
+ /* We dropped the RTNL semaphore in order to
+ * perform the module load. So, even if we
+ * succeeded in loading the module we have to
+ * replay the request. We indicate this using
+ * -EAGAIN.
+ */
+ if (tp_ops != NULL)
+ err = -EAGAIN;
}
- }
#endif
- if (tp_ops == NULL) {
- err = -EINVAL;
kfree(tp);
goto errout;
}
@@ -294,6 +312,9 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
errout:
if (cl)
cops->put(q, cl);
+ if (err == -EAGAIN)
+ /* Replay the request. */
+ goto replay;
return err;
}
@@ -468,7 +489,7 @@ tcf_exts_validate(struct tcf_proto *tp, struct rtattr **tb,
int err;
struct tc_action *act;
- if (map->police && tb[map->police-1] && rate_tlv) {
+ if (map->police && tb[map->police-1]) {
act = tcf_action_init_1(tb[map->police-1], rate_tlv, "police",
TCA_ACT_NOREPLACE, TCA_ACT_BIND, &err);
if (act == NULL)
@@ -476,7 +497,7 @@ tcf_exts_validate(struct tcf_proto *tp, struct rtattr **tb,
act->type = TCA_OLD_COMPAT;
exts->action = act;
- } else if (map->action && tb[map->action-1] && rate_tlv) {
+ } 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)
@@ -485,7 +506,7 @@ tcf_exts_validate(struct tcf_proto *tp, struct rtattr **tb,
exts->action = act;
}
#elif defined CONFIG_NET_CLS_POLICE
- if (map->police && tb[map->police-1] && rate_tlv) {
+ if (map->police && tb[map->police-1]) {
struct tcf_police *p;
p = tcf_police_locate(tb[map->police-1], rate_tlv);
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 1b1224b1747e36..8b870402bc96a2 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -549,7 +549,6 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
struct tc_u_hnode *ht;
struct tc_u_knode *n;
struct tc_u32_sel *s;
- struct tc_u32_mark *mark;
struct rtattr *opt = tca[TCA_OPTIONS-1];
struct rtattr *tb[TCA_U32_MAX];
u32 htid;
@@ -654,15 +653,22 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
n->fshift = i;
}
-#ifdef CONFIG_CLS_U32_MARK
+#ifdef CONFIG_CLS_U32_MARK
if (tb[TCA_U32_MARK-1]) {
- if (RTA_PAYLOAD(tb[TCA_U32_MARK-1]) < sizeof(struct tc_u32_mark))
+ struct tc_u32_mark *mark;
+
+ if (RTA_PAYLOAD(tb[TCA_U32_MARK-1]) < sizeof(struct tc_u32_mark)) {
+#ifdef CONFIG_CLS_U32_PERF
+ kfree(n->pf);
+#endif
+ kfree(n);
return -EINVAL;
+ }
mark = RTA_DATA(tb[TCA_U32_MARK-1]);
memcpy(&n->mark, mark, sizeof(struct tc_u32_mark));
n->mark.success = 0;
- }
-#endif
+ }
+#endif
err = u32_set_parms(tp, base, ht, n, tb, tca[TCA_RATE-1]);
if (err == 0) {
diff --git a/net/sched/gact.c b/net/sched/gact.c
index b83c1a6a7f318d..e0a64086d749f4 100644
--- a/net/sched/gact.c
+++ b/net/sched/gact.c
@@ -79,8 +79,7 @@ static int tcf_gact_init(struct rtattr *rta, struct rtattr *est,
struct tcf_gact *p;
int ret = 0;
- if (rta == NULL ||
- rtattr_parse(tb, TCA_GACT_MAX, RTA_DATA(rta), RTA_PAYLOAD(rta)) < 0)
+ if (rta == NULL || rtattr_parse_nested(tb, TCA_GACT_MAX, rta) < 0)
return -EINVAL;
if (tb[TCA_GACT_PARMS - 1] == NULL ||
diff --git a/net/sched/ipt.c b/net/sched/ipt.c
index cd309e49f231c0..e6881990801c1f 100644
--- a/net/sched/ipt.c
+++ b/net/sched/ipt.c
@@ -122,8 +122,7 @@ tcf_ipt_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a,
u32 hook = 0;
u32 index = 0;
- if (rta == NULL ||
- rtattr_parse(tb, TCA_IPT_MAX, RTA_DATA(rta), RTA_PAYLOAD(rta)) < 0)
+ if (rta == NULL || rtattr_parse_nested(tb, TCA_IPT_MAX, rta) < 0)
return -EINVAL;
if (tb[TCA_IPT_HOOK-1] == NULL ||
diff --git a/net/sched/mirred.c b/net/sched/mirred.c
index 4ff3fd740fa329..4402bd53be2928 100644
--- a/net/sched/mirred.c
+++ b/net/sched/mirred.c
@@ -84,8 +84,7 @@ tcf_mirred_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a,
int ret = 0;
int ok_push = 0;
- if (rta == NULL || rtattr_parse(tb, TCA_MIRRED_MAX, RTA_DATA(rta),
- RTA_PAYLOAD(rta)) < 0)
+ if (rta == NULL || rtattr_parse_nested(tb, TCA_MIRRED_MAX, rta) < 0)
return -EINVAL;
if (tb[TCA_MIRRED_PARMS-1] == NULL ||
@@ -127,7 +126,7 @@ tcf_mirred_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a,
}
}
- spin_lock(&p->lock);
+ spin_lock_bh(&p->lock);
p->action = parm->action;
p->eaction = parm->eaction;
if (parm->ifindex) {
@@ -138,7 +137,7 @@ tcf_mirred_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a,
dev_hold(dev);
p->ok_push = ok_push;
}
- spin_unlock(&p->lock);
+ spin_unlock_bh(&p->lock);
if (ret == ACT_P_CREATED)
tcf_hash_insert(p);
diff --git a/net/sched/pedit.c b/net/sched/pedit.c
index e4943c59202901..e1b4bedace58d9 100644
--- a/net/sched/pedit.c
+++ b/net/sched/pedit.c
@@ -63,8 +63,7 @@ tcf_pedit_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a,
struct tc_pedit_key *keys = NULL;
int ksize;
- if (rta == NULL || rtattr_parse(tb, TCA_PEDIT_MAX, RTA_DATA(rta),
- RTA_PAYLOAD(rta)) < 0)
+ if (rta == NULL || rtattr_parse_nested(tb, TCA_PEDIT_MAX, rta) < 0)
return -EINVAL;
if (tb[TCA_PEDIT_PARMS - 1] == NULL ||
diff --git a/net/sched/police.c b/net/sched/police.c
index 7efd037f49023d..4edaf7e748fdbf 100644
--- a/net/sched/police.c
+++ b/net/sched/police.c
@@ -171,8 +171,7 @@ static int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est,
struct tcf_police *p;
struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL;
- if (rta == NULL || rtattr_parse(tb, TCA_POLICE_MAX, RTA_DATA(rta),
- RTA_PAYLOAD(rta)) < 0)
+ if (rta == NULL || rtattr_parse_nested(tb, TCA_POLICE_MAX, rta) < 0)
return -EINVAL;
if (tb[TCA_POLICE_TBF-1] == NULL ||
@@ -225,7 +224,7 @@ override:
}
}
/* No failure allowed after this point */
- spin_lock(&p->lock);
+ spin_lock_bh(&p->lock);
if (R_tab != NULL) {
qdisc_put_rtab(p->R_tab);
p->R_tab = R_tab;
@@ -255,7 +254,7 @@ override:
gen_replace_estimator(&p->bstats, &p->rate_est, p->stats_lock, est);
#endif
- spin_unlock(&p->lock);
+ spin_unlock_bh(&p->lock);
if (ret != ACT_P_CREATED)
return ret;
@@ -417,8 +416,7 @@ struct tcf_police * tcf_police_locate(struct rtattr *rta, struct rtattr *est)
struct rtattr *tb[TCA_POLICE_MAX];
struct tc_police *parm;
- if (rtattr_parse(tb, TCA_POLICE_MAX, RTA_DATA(rta),
- RTA_PAYLOAD(rta)) < 0)
+ if (rtattr_parse_nested(tb, TCA_POLICE_MAX, rta) < 0)
return NULL;
if (tb[TCA_POLICE_TBF-1] == NULL ||
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index 711143443182ea..427b6fe7bfac08 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -255,8 +255,8 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
* later.)
*/
if (flow) return -EBUSY;
- if (opt == NULL || rtattr_parse(tb,TCA_ATM_MAX,RTA_DATA(opt),
- RTA_PAYLOAD(opt))) return -EINVAL;
+ if (opt == NULL || rtattr_parse_nested(tb, TCA_ATM_MAX, opt))
+ return -EINVAL;
if (!tb[TCA_ATM_FD-1] || RTA_PAYLOAD(tb[TCA_ATM_FD-1]) < sizeof(fd))
return -EINVAL;
fd = *(int *) RTA_DATA(tb[TCA_ATM_FD-1]);
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index 74ca4ee720e4c2..b4c1c1f15dc2dd 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -1439,7 +1439,7 @@ static int cbq_init(struct Qdisc *sch, struct rtattr *opt)
struct rtattr *tb[TCA_CBQ_MAX];
struct tc_ratespec *r;
- if (rtattr_parse(tb, TCA_CBQ_MAX, RTA_DATA(opt), RTA_PAYLOAD(opt)) < 0 ||
+ if (rtattr_parse_nested(tb, TCA_CBQ_MAX, opt) < 0 ||
tb[TCA_CBQ_RTAB-1] == NULL || tb[TCA_CBQ_RATE-1] == NULL ||
RTA_PAYLOAD(tb[TCA_CBQ_RATE-1]) < sizeof(struct tc_ratespec))
return -EINVAL;
@@ -1824,8 +1824,7 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t
struct cbq_class *parent;
struct qdisc_rate_table *rtab = NULL;
- if (opt==NULL ||
- rtattr_parse(tb, TCA_CBQ_MAX, RTA_DATA(opt), RTA_PAYLOAD(opt)))
+ if (opt==NULL || rtattr_parse_nested(tb, TCA_CBQ_MAX, opt))
return -EINVAL;
if (tb[TCA_CBQ_OVL_STRATEGY-1] &&
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c
index 19f4e4fa7f4844..8a3db9d95bab23 100644
--- a/net/sched/sch_dsmark.c
+++ b/net/sched/sch_dsmark.c
@@ -125,8 +125,7 @@ static int dsmark_change(struct Qdisc *sch, u32 classid, u32 parent,
"arg 0x%lx\n",sch,p,classid,parent,*arg);
if (*arg > p->indices)
return -ENOENT;
- if (!opt || rtattr_parse(tb, TCA_DSMARK_MAX, RTA_DATA(opt),
- RTA_PAYLOAD(opt)))
+ if (!opt || rtattr_parse_nested(tb, TCA_DSMARK_MAX, opt))
return -EINVAL;
if (tb[TCA_DSMARK_MASK-1]) {
if (!RTA_PAYLOAD(tb[TCA_DSMARK_MASK-1]))
diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c
index decd7ba297e797..25c171c3271542 100644
--- a/net/sched/sch_gred.c
+++ b/net/sched/sch_gred.c
@@ -332,13 +332,11 @@ static int gred_change(struct Qdisc *sch, struct rtattr *opt)
struct rtattr *tb2[TCA_GRED_DPS];
int i;
- if (opt == NULL ||
- rtattr_parse(tb, TCA_GRED_STAB, RTA_DATA(opt), RTA_PAYLOAD(opt)) )
- return -EINVAL;
+ if (opt == NULL || rtattr_parse_nested(tb, TCA_GRED_STAB, opt))
+ return -EINVAL;
if (tb[TCA_GRED_PARMS-1] == 0 && tb[TCA_GRED_STAB-1] == 0) {
- rtattr_parse(tb2, TCA_GRED_DPS, RTA_DATA(opt),
- RTA_PAYLOAD(opt));
+ rtattr_parse_nested(tb2, TCA_GRED_DPS, opt);
if (tb2[TCA_GRED_DPS-1] == 0)
return -EINVAL;
@@ -475,12 +473,11 @@ static int gred_init(struct Qdisc *sch, struct rtattr *opt)
struct rtattr *tb[TCA_GRED_STAB];
struct rtattr *tb2[TCA_GRED_DPS];
- if (opt == NULL ||
- rtattr_parse(tb, TCA_GRED_STAB, RTA_DATA(opt), RTA_PAYLOAD(opt)) )
- return -EINVAL;
+ if (opt == NULL || rtattr_parse_nested(tb, TCA_GRED_STAB, opt))
+ return -EINVAL;
if (tb[TCA_GRED_PARMS-1] == 0 && tb[TCA_GRED_STAB-1] == 0) {
- rtattr_parse(tb2, TCA_GRED_DPS, RTA_DATA(opt),RTA_PAYLOAD(opt));
+ rtattr_parse_nested(tb2, TCA_GRED_DPS, opt);
if (tb2[TCA_GRED_DPS-1] == 0)
return -EINVAL;
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index c6288dedc660e1..d09e0b0cb5f99c 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -1046,8 +1046,7 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
struct tc_service_curve *rsc = NULL, *fsc = NULL, *usc = NULL;
u64 cur_time;
- if (opt == NULL ||
- rtattr_parse(tb, TCA_HFSC_MAX, RTA_DATA(opt), RTA_PAYLOAD(opt)))
+ if (opt == NULL || rtattr_parse_nested(tb, TCA_HFSC_MAX, opt))
return -EINVAL;
if (tb[TCA_HFSC_RSC-1]) {
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 25fa2c06f139cb..116028554ae454 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -1267,7 +1267,7 @@ static int htb_init(struct Qdisc *sch, struct rtattr *opt)
printk(KERN_INFO "HTB init, kernel part version %d.%d\n",
HTB_VER >> 16,HTB_VER & 0xffff);
#endif
- if (!opt || rtattr_parse(tb, TCA_HTB_INIT, RTA_DATA(opt), RTA_PAYLOAD(opt)) ||
+ if (!opt || rtattr_parse_nested(tb, TCA_HTB_INIT, opt) ||
tb[TCA_HTB_INIT-1] == NULL ||
RTA_PAYLOAD(tb[TCA_HTB_INIT-1]) < sizeof(*gopt)) {
printk(KERN_ERR "HTB: hey probably you have bad tc tool ?\n");
@@ -1559,7 +1559,7 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
struct tc_htb_opt *hopt;
/* extract all subattrs from opt attr */
- if (!opt || rtattr_parse(tb, TCA_HTB_RTAB, RTA_DATA(opt), RTA_PAYLOAD(opt)) ||
+ if (!opt || rtattr_parse_nested(tb, TCA_HTB_RTAB, opt) ||
tb[TCA_HTB_PARMS-1] == NULL ||
RTA_PAYLOAD(tb[TCA_HTB_PARMS-1]) < sizeof(*hopt))
goto failure;
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c
index 4ea63bc58a2826..664d0e47374fd1 100644
--- a/net/sched/sch_red.c
+++ b/net/sched/sch_red.c
@@ -364,7 +364,7 @@ static int red_change(struct Qdisc *sch, struct rtattr *opt)
struct tc_red_qopt *ctl;
if (opt == NULL ||
- rtattr_parse(tb, TCA_RED_STAB, RTA_DATA(opt), RTA_PAYLOAD(opt)) ||
+ rtattr_parse_nested(tb, TCA_RED_STAB, opt) ||
tb[TCA_RED_PARMS-1] == 0 || tb[TCA_RED_STAB-1] == 0 ||
RTA_PAYLOAD(tb[TCA_RED_PARMS-1]) < sizeof(*ctl) ||
RTA_PAYLOAD(tb[TCA_RED_STAB-1]) < 256)
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
index 2c3f14a8492df1..cb9711ea8c6cac 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -310,7 +310,7 @@ static int tbf_change(struct Qdisc* sch, struct rtattr *opt)
struct Qdisc *child = NULL;
int max_size,n;
- if (rtattr_parse(tb, TCA_TBF_PTAB, RTA_DATA(opt), RTA_PAYLOAD(opt)) ||
+ if (rtattr_parse_nested(tb, TCA_TBF_PTAB, opt) ||
tb[TCA_TBF_PARMS-1] == NULL ||
RTA_PAYLOAD(tb[TCA_TBF_PARMS-1]) < sizeof(*qopt))
goto done;