Commit 62a6de62 authored by Alexander Aring's avatar Alexander Aring Committed by David S. Miller

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: default avatarJamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: default avatarAlexander Aring <aring@mojatatu.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a38a9882
......@@ -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);
q->delay_timer.function = cbq_undelay;
if (!opt)
if (!opt) {
NL_SET_ERR_MSG(extack, "CBQ options are required for this operation");
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)
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;
}
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 qdisc_rate_table *rtab = NULL;
if (!opt)
if (!opt) {
NL_SET_ERR_MSG(extack, "Mandatory qdisc options missing");
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)
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;
}
if (cl) {
/* Check parent */
if (parentid) {
if (cl->tparent &&
cl->tparent->common.classid != parentid)
cl->tparent->common.classid != parentid) {
NL_SET_ERR_MSG(extack, "Invalid parent id");
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;
}
}
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),
tca[TCA_RATE]);
if (err) {
NL_SET_ERR_MSG(extack, "Failed to replace specified rate estimator");
qdisc_put_rtab(rtab);
return err;
}
......@@ -1534,8 +1547,10 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
if (parentid == TC_H_ROOT)
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;
}
rtab = qdisc_get_rtab(nla_data(tb[TCA_CBQ_RATE]), tb[TCA_CBQ_RTAB],
extack);
......@@ -1545,8 +1560,10 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
if (classid) {
err = -EINVAL;
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;
}
} else {
int i;
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;
}
err = -ENOSR;
if (i >= 0x8000)
if (i >= 0x8000) {
NL_SET_ERR_MSG(extack, "Unable to generate classid");
goto failure;
}
classid = classid|q->hgenerator;
}
......@@ -1567,8 +1586,10 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
if (parentid) {
parent = cbq_class_lookup(q, parentid);
err = -EINVAL;
if (!parent)
if (!parent) {
NL_SET_ERR_MSG(extack, "Failed to find parentid");
goto failure;
}
}
err = -ENOBUFS;
......@@ -1588,6 +1609,7 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
qdisc_root_sleeping_running(sch),
tca[TCA_RATE]);
if (err) {
NL_SET_ERR_MSG(extack, "Couldn't create new estimator");
tcf_block_put(cl->block);
kfree(cl);
goto failure;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment