sch_netem: return errcode before setting params

get_dist_table() and get_loss_clg() may be failed. These
two functions should be called after setting the members
of qdisc_priv(sch), or it will break the old settings while
either of them is failed.

Signed-off-by: Yang Yingliang <yangyingliang@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Yang Yingliang 2014-02-14 10:30:41 +08:00 committed by David S. Miller
parent d4f2fa6ad6
commit 54a4b05cd2

View File

@ -821,6 +821,8 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt)
struct netem_sched_data *q = qdisc_priv(sch); struct netem_sched_data *q = qdisc_priv(sch);
struct nlattr *tb[TCA_NETEM_MAX + 1]; struct nlattr *tb[TCA_NETEM_MAX + 1];
struct tc_netem_qopt *qopt; struct tc_netem_qopt *qopt;
struct clgstate old_clg;
int old_loss_model = CLG_RANDOM;
int ret; int ret;
if (opt == NULL) if (opt == NULL)
@ -831,6 +833,33 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt)
if (ret < 0) if (ret < 0)
return ret; return ret;
/* backup q->clg and q->loss_model */
old_clg = q->clg;
old_loss_model = q->loss_model;
if (tb[TCA_NETEM_LOSS]) {
ret = get_loss_clg(sch, tb[TCA_NETEM_LOSS]);
if (ret) {
q->loss_model = old_loss_model;
return ret;
}
} else {
q->loss_model = CLG_RANDOM;
}
if (tb[TCA_NETEM_DELAY_DIST]) {
ret = get_dist_table(sch, tb[TCA_NETEM_DELAY_DIST]);
if (ret) {
/* recover clg and loss_model, in case of
* q->clg and q->loss_model were modified
* in get_loss_clg()
*/
q->clg = old_clg;
q->loss_model = old_loss_model;
return ret;
}
}
sch->limit = qopt->limit; sch->limit = qopt->limit;
q->latency = qopt->latency; q->latency = qopt->latency;
@ -850,12 +879,6 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt)
if (tb[TCA_NETEM_CORR]) if (tb[TCA_NETEM_CORR])
get_correlation(sch, tb[TCA_NETEM_CORR]); get_correlation(sch, tb[TCA_NETEM_CORR]);
if (tb[TCA_NETEM_DELAY_DIST]) {
ret = get_dist_table(sch, tb[TCA_NETEM_DELAY_DIST]);
if (ret)
return ret;
}
if (tb[TCA_NETEM_REORDER]) if (tb[TCA_NETEM_REORDER])
get_reorder(sch, tb[TCA_NETEM_REORDER]); get_reorder(sch, tb[TCA_NETEM_REORDER]);
@ -872,10 +895,6 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt)
if (tb[TCA_NETEM_ECN]) if (tb[TCA_NETEM_ECN])
q->ecn = nla_get_u32(tb[TCA_NETEM_ECN]); q->ecn = nla_get_u32(tb[TCA_NETEM_ECN]);
q->loss_model = CLG_RANDOM;
if (tb[TCA_NETEM_LOSS])
ret = get_loss_clg(sch, tb[TCA_NETEM_LOSS]);
return ret; return ret;
} }