diff options
author | Yang Yingliang <yangyingliang@huawei.com> | 2014-02-13 21:30:41 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-02-14 00:15:20 -0500 |
commit | 54a4b05cd281a352d803417a98a72878fb0802cf (patch) | |
tree | f75291053c03b191ab3d8bb5ef51ca57f47e7de0 | |
parent | d4f2fa6ad61ec1db713569a179183df4d0fc6ae7 (diff) |
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>
-rw-r--r-- | net/sched/sch_netem.c | 39 |
1 files changed, 29 insertions, 10 deletions
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index de1059af6da1..b341943555a9 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c | |||
@@ -821,6 +821,8 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt) | |||
821 | struct netem_sched_data *q = qdisc_priv(sch); | 821 | struct netem_sched_data *q = qdisc_priv(sch); |
822 | struct nlattr *tb[TCA_NETEM_MAX + 1]; | 822 | struct nlattr *tb[TCA_NETEM_MAX + 1]; |
823 | struct tc_netem_qopt *qopt; | 823 | struct tc_netem_qopt *qopt; |
824 | struct clgstate old_clg; | ||
825 | int old_loss_model = CLG_RANDOM; | ||
824 | int ret; | 826 | int ret; |
825 | 827 | ||
826 | if (opt == NULL) | 828 | if (opt == NULL) |
@@ -831,6 +833,33 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt) | |||
831 | if (ret < 0) | 833 | if (ret < 0) |
832 | return ret; | 834 | return ret; |
833 | 835 | ||
836 | /* backup q->clg and q->loss_model */ | ||
837 | old_clg = q->clg; | ||
838 | old_loss_model = q->loss_model; | ||
839 | |||
840 | if (tb[TCA_NETEM_LOSS]) { | ||
841 | ret = get_loss_clg(sch, tb[TCA_NETEM_LOSS]); | ||
842 | if (ret) { | ||
843 | q->loss_model = old_loss_model; | ||
844 | return ret; | ||
845 | } | ||
846 | } else { | ||
847 | q->loss_model = CLG_RANDOM; | ||
848 | } | ||
849 | |||
850 | if (tb[TCA_NETEM_DELAY_DIST]) { | ||
851 | ret = get_dist_table(sch, tb[TCA_NETEM_DELAY_DIST]); | ||
852 | if (ret) { | ||
853 | /* recover clg and loss_model, in case of | ||
854 | * q->clg and q->loss_model were modified | ||
855 | * in get_loss_clg() | ||
856 | */ | ||
857 | q->clg = old_clg; | ||
858 | q->loss_model = old_loss_model; | ||
859 | return ret; | ||
860 | } | ||
861 | } | ||
862 | |||
834 | sch->limit = qopt->limit; | 863 | sch->limit = qopt->limit; |
835 | 864 | ||
836 | q->latency = qopt->latency; | 865 | q->latency = qopt->latency; |
@@ -850,12 +879,6 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt) | |||
850 | if (tb[TCA_NETEM_CORR]) | 879 | if (tb[TCA_NETEM_CORR]) |
851 | get_correlation(sch, tb[TCA_NETEM_CORR]); | 880 | get_correlation(sch, tb[TCA_NETEM_CORR]); |
852 | 881 | ||
853 | if (tb[TCA_NETEM_DELAY_DIST]) { | ||
854 | ret = get_dist_table(sch, tb[TCA_NETEM_DELAY_DIST]); | ||
855 | if (ret) | ||
856 | return ret; | ||
857 | } | ||
858 | |||
859 | if (tb[TCA_NETEM_REORDER]) | 882 | if (tb[TCA_NETEM_REORDER]) |
860 | get_reorder(sch, tb[TCA_NETEM_REORDER]); | 883 | get_reorder(sch, tb[TCA_NETEM_REORDER]); |
861 | 884 | ||
@@ -872,10 +895,6 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt) | |||
872 | if (tb[TCA_NETEM_ECN]) | 895 | if (tb[TCA_NETEM_ECN]) |
873 | q->ecn = nla_get_u32(tb[TCA_NETEM_ECN]); | 896 | q->ecn = nla_get_u32(tb[TCA_NETEM_ECN]); |
874 | 897 | ||
875 | q->loss_model = CLG_RANDOM; | ||
876 | if (tb[TCA_NETEM_LOSS]) | ||
877 | ret = get_loss_clg(sch, tb[TCA_NETEM_LOSS]); | ||
878 | |||
879 | return ret; | 898 | return ret; |
880 | } | 899 | } |
881 | 900 | ||