net: sch: sch_cbq: add extack support
This patch adds extack support for the cbq qdisc implementation by adding NL_SET_ERR_MSG in validation of user input. Also it serves to illustrate a use case of how the infrastructure ops api changes are to be used by individual qdiscs. Cc: David Ahern <dsahern@gmail.com> Acked-by: Jamal Hadi Salim <jhs@mojatatu.com> Signed-off-by: Alexander Aring <aring@mojatatu.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
a38a98821c
commit
62a6de62dc
|
@ -1144,15 +1144,19 @@ static int cbq_init(struct Qdisc *sch, struct nlattr *opt,
|
||||||
hrtimer_init(&q->delay_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED);
|
hrtimer_init(&q->delay_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED);
|
||||||
q->delay_timer.function = cbq_undelay;
|
q->delay_timer.function = cbq_undelay;
|
||||||
|
|
||||||
if (!opt)
|
if (!opt) {
|
||||||
|
NL_SET_ERR_MSG(extack, "CBQ options are required for this operation");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
err = nla_parse_nested(tb, TCA_CBQ_MAX, opt, cbq_policy, NULL);
|
err = nla_parse_nested(tb, TCA_CBQ_MAX, opt, cbq_policy, extack);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
if (!tb[TCA_CBQ_RTAB] || !tb[TCA_CBQ_RATE])
|
if (!tb[TCA_CBQ_RTAB] || !tb[TCA_CBQ_RATE]) {
|
||||||
|
NL_SET_ERR_MSG(extack, "Rate specification missing or incomplete");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
r = nla_data(tb[TCA_CBQ_RATE]);
|
r = nla_data(tb[TCA_CBQ_RATE]);
|
||||||
|
|
||||||
|
@ -1462,24 +1466,32 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
|
||||||
struct cbq_class *parent;
|
struct cbq_class *parent;
|
||||||
struct qdisc_rate_table *rtab = NULL;
|
struct qdisc_rate_table *rtab = NULL;
|
||||||
|
|
||||||
if (!opt)
|
if (!opt) {
|
||||||
|
NL_SET_ERR_MSG(extack, "Mandatory qdisc options missing");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
err = nla_parse_nested(tb, TCA_CBQ_MAX, opt, cbq_policy, NULL);
|
err = nla_parse_nested(tb, TCA_CBQ_MAX, opt, cbq_policy, extack);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
if (tb[TCA_CBQ_OVL_STRATEGY] || tb[TCA_CBQ_POLICE])
|
if (tb[TCA_CBQ_OVL_STRATEGY] || tb[TCA_CBQ_POLICE]) {
|
||||||
|
NL_SET_ERR_MSG(extack, "Neither overlimit strategy nor policing attributes can be used for changing class params");
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
if (cl) {
|
if (cl) {
|
||||||
/* Check parent */
|
/* Check parent */
|
||||||
if (parentid) {
|
if (parentid) {
|
||||||
if (cl->tparent &&
|
if (cl->tparent &&
|
||||||
cl->tparent->common.classid != parentid)
|
cl->tparent->common.classid != parentid) {
|
||||||
|
NL_SET_ERR_MSG(extack, "Invalid parent id");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (!cl->tparent && parentid != TC_H_ROOT)
|
}
|
||||||
|
if (!cl->tparent && parentid != TC_H_ROOT) {
|
||||||
|
NL_SET_ERR_MSG(extack, "Parent must be root");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tb[TCA_CBQ_RATE]) {
|
if (tb[TCA_CBQ_RATE]) {
|
||||||
|
@ -1496,6 +1508,7 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
|
||||||
qdisc_root_sleeping_running(sch),
|
qdisc_root_sleeping_running(sch),
|
||||||
tca[TCA_RATE]);
|
tca[TCA_RATE]);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
NL_SET_ERR_MSG(extack, "Failed to replace specified rate estimator");
|
||||||
qdisc_put_rtab(rtab);
|
qdisc_put_rtab(rtab);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -1534,8 +1547,10 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
|
||||||
if (parentid == TC_H_ROOT)
|
if (parentid == TC_H_ROOT)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (!tb[TCA_CBQ_WRROPT] || !tb[TCA_CBQ_RATE] || !tb[TCA_CBQ_LSSOPT])
|
if (!tb[TCA_CBQ_WRROPT] || !tb[TCA_CBQ_RATE] || !tb[TCA_CBQ_LSSOPT]) {
|
||||||
|
NL_SET_ERR_MSG(extack, "One of the following attributes MUST be specified: WRR, rate or link sharing");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
rtab = qdisc_get_rtab(nla_data(tb[TCA_CBQ_RATE]), tb[TCA_CBQ_RTAB],
|
rtab = qdisc_get_rtab(nla_data(tb[TCA_CBQ_RATE]), tb[TCA_CBQ_RTAB],
|
||||||
extack);
|
extack);
|
||||||
|
@ -1545,8 +1560,10 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
|
||||||
if (classid) {
|
if (classid) {
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
if (TC_H_MAJ(classid ^ sch->handle) ||
|
if (TC_H_MAJ(classid ^ sch->handle) ||
|
||||||
cbq_class_lookup(q, classid))
|
cbq_class_lookup(q, classid)) {
|
||||||
|
NL_SET_ERR_MSG(extack, "Specified class not found");
|
||||||
goto failure;
|
goto failure;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
int i;
|
int i;
|
||||||
classid = TC_H_MAKE(sch->handle, 0x8000);
|
classid = TC_H_MAKE(sch->handle, 0x8000);
|
||||||
|
@ -1558,8 +1575,10 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
err = -ENOSR;
|
err = -ENOSR;
|
||||||
if (i >= 0x8000)
|
if (i >= 0x8000) {
|
||||||
|
NL_SET_ERR_MSG(extack, "Unable to generate classid");
|
||||||
goto failure;
|
goto failure;
|
||||||
|
}
|
||||||
classid = classid|q->hgenerator;
|
classid = classid|q->hgenerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1567,8 +1586,10 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
|
||||||
if (parentid) {
|
if (parentid) {
|
||||||
parent = cbq_class_lookup(q, parentid);
|
parent = cbq_class_lookup(q, parentid);
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
if (!parent)
|
if (!parent) {
|
||||||
|
NL_SET_ERR_MSG(extack, "Failed to find parentid");
|
||||||
goto failure;
|
goto failure;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = -ENOBUFS;
|
err = -ENOBUFS;
|
||||||
|
@ -1588,6 +1609,7 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
|
||||||
qdisc_root_sleeping_running(sch),
|
qdisc_root_sleeping_running(sch),
|
||||||
tca[TCA_RATE]);
|
tca[TCA_RATE]);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
NL_SET_ERR_MSG(extack, "Couldn't create new estimator");
|
||||||
tcf_block_put(cl->block);
|
tcf_block_put(cl->block);
|
||||||
kfree(cl);
|
kfree(cl);
|
||||||
goto failure;
|
goto failure;
|
||||||
|
|
Loading…
Reference in New Issue