Commit f62d6b93 authored by Thomas Graf's avatar Thomas Graf Committed by Thomas Graf

[PKT_SCHED]: GRED: Use central VQ change procedure

Introduces a function gred_change_vq() acting as a central point
to change VQ parameters. Fixes priority inheritance in rio mode
when the default DP equals 0. Adds proper locking during changes.
Signed-off-by: default avatarThomas Graf <tgraf@suug.ch>
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@mandriva.com>
parent a8aaa995
...@@ -58,6 +58,8 @@ ...@@ -58,6 +58,8 @@
#define D2PRINTK(format,args...) #define D2PRINTK(format,args...)
#endif #endif
#define GRED_DEF_PRIO (MAX_DPs / 2)
struct gred_sched_data; struct gred_sched_data;
struct gred_sched; struct gred_sched;
...@@ -432,59 +434,23 @@ static inline int gred_change_table_def(struct Qdisc *sch, struct rtattr *dps) ...@@ -432,59 +434,23 @@ static inline int gred_change_table_def(struct Qdisc *sch, struct rtattr *dps)
return 0; return 0;
} }
static int gred_change(struct Qdisc *sch, struct rtattr *opt) static inline int gred_change_vq(struct Qdisc *sch, int dp,
struct tc_gred_qopt *ctl, int prio, u8 *stab)
{ {
struct gred_sched *table = qdisc_priv(sch); struct gred_sched *table = qdisc_priv(sch);
struct gred_sched_data *q; struct gred_sched_data *q;
struct tc_gred_qopt *ctl;
struct rtattr *tb[TCA_GRED_STAB];
if (opt == NULL || rtattr_parse_nested(tb, TCA_GRED_STAB, opt))
return -EINVAL;
if (tb[TCA_GRED_PARMS-1] == NULL && tb[TCA_GRED_STAB-1] == NULL)
return gred_change_table_def(sch, tb[TCA_GRED_DPS-1]);
if (!table->DPs || tb[TCA_GRED_PARMS-1] == 0 || tb[TCA_GRED_STAB-1] == 0 ||
RTA_PAYLOAD(tb[TCA_GRED_PARMS-1]) < sizeof(*ctl) ||
RTA_PAYLOAD(tb[TCA_GRED_STAB-1]) < 256)
return -EINVAL;
ctl = RTA_DATA(tb[TCA_GRED_PARMS-1]);
if (ctl->DP >= table->DPs)
return -EINVAL;
if (table->tab[ctl->DP] == NULL) { if (table->tab[dp] == NULL) {
table->tab[ctl->DP]=kmalloc(sizeof(struct gred_sched_data), table->tab[dp] = kmalloc(sizeof(*q), GFP_KERNEL);
GFP_KERNEL); if (table->tab[dp] == NULL)
if (NULL == table->tab[ctl->DP])
return -ENOMEM; return -ENOMEM;
memset(table->tab[ctl->DP], 0, (sizeof(struct gred_sched_data))); memset(table->tab[dp], 0, sizeof(*q));
}
q= table->tab[ctl->DP];
if (gred_rio_mode(table)) {
if (ctl->prio <=0) {
if (table->def && table->tab[table->def]) {
DPRINTK("\nGRED: DP %u does not have a prio"
"setting default to %d\n",ctl->DP,
table->tab[table->def]->prio);
q->prio=table->tab[table->def]->prio;
} else {
DPRINTK("\nGRED: DP %u does not have a prio"
" setting default to 8\n",ctl->DP);
q->prio=8;
}
} else {
q->prio=ctl->prio;
}
} else {
q->prio=8;
} }
q = table->tab[dp];
q->DP = dp;
q->prio = prio;
q->DP=ctl->DP;
q->Wlog = ctl->Wlog; q->Wlog = ctl->Wlog;
q->Plog = ctl->Plog; q->Plog = ctl->Plog;
q->limit = ctl->limit; q->limit = ctl->limit;
...@@ -502,52 +468,81 @@ static int gred_change(struct Qdisc *sch, struct rtattr *opt) ...@@ -502,52 +468,81 @@ static int gred_change(struct Qdisc *sch, struct rtattr *opt)
q->early=0; q->early=0;
PSCHED_SET_PASTPERFECT(q->qidlestart); PSCHED_SET_PASTPERFECT(q->qidlestart);
memcpy(q->Stab, RTA_DATA(tb[TCA_GRED_STAB-1]), 256); memcpy(q->Stab, stab, 256);
return 0;
}
static int gred_change(struct Qdisc *sch, struct rtattr *opt)
{
struct gred_sched *table = qdisc_priv(sch);
struct tc_gred_qopt *ctl;
struct rtattr *tb[TCA_GRED_MAX];
int err = -EINVAL, prio = GRED_DEF_PRIO;
u8 *stab;
if (opt == NULL || rtattr_parse_nested(tb, TCA_GRED_MAX, opt))
return -EINVAL;
if (tb[TCA_GRED_PARMS-1] == NULL && tb[TCA_GRED_STAB-1] == NULL)
return gred_change_table_def(sch, opt);
if (tb[TCA_GRED_PARMS-1] == NULL ||
RTA_PAYLOAD(tb[TCA_GRED_PARMS-1]) < sizeof(*ctl) ||
tb[TCA_GRED_STAB-1] == NULL ||
RTA_PAYLOAD(tb[TCA_GRED_STAB-1]) < 256)
return -EINVAL;
ctl = RTA_DATA(tb[TCA_GRED_PARMS-1]);
stab = RTA_DATA(tb[TCA_GRED_STAB-1]);
if (ctl->DP >= table->DPs)
goto errout;
if (gred_rio_mode(table)) { if (gred_rio_mode(table)) {
gred_disable_wred_mode(table); if (ctl->prio == 0) {
if (gred_wred_mode_check(sch)) int def_prio = GRED_DEF_PRIO;
gred_enable_wred_mode(table);
if (table->tab[table->def])
def_prio = table->tab[table->def]->prio;
printk(KERN_DEBUG "GRED: DP %u does not have a prio "
"setting default to %d\n", ctl->DP, def_prio);
prio = def_prio;
} else
prio = ctl->prio;
} }
if (!table->initd) { sch_tree_lock(sch);
table->initd=1;
/* err = gred_change_vq(sch, ctl->DP, ctl, prio, stab);
the first entry also goes into the default until if (err < 0)
over-written goto errout_locked;
*/
if (table->tab[table->def] == NULL) { if (table->tab[table->def] == NULL) {
table->tab[table->def]= if (gred_rio_mode(table))
kmalloc(sizeof(struct gred_sched_data), GFP_KERNEL); prio = table->tab[ctl->DP]->prio;
if (NULL == table->tab[table->def])
return -ENOMEM;
memset(table->tab[table->def], 0, err = gred_change_vq(sch, table->def, ctl, prio, stab);
(sizeof(struct gred_sched_data))); if (err < 0)
goto errout_locked;
} }
q= table->tab[table->def];
q->DP=table->def;
q->Wlog = ctl->Wlog;
q->Plog = ctl->Plog;
q->limit = ctl->limit;
q->Scell_log = ctl->Scell_log;
q->Rmask = ctl->Plog < 32 ? ((1<<ctl->Plog) - 1) : ~0UL;
q->Scell_max = (255<<q->Scell_log);
q->qth_min = ctl->qth_min<<ctl->Wlog;
q->qth_max = ctl->qth_max<<ctl->Wlog;
if (gred_rio_mode(table)) table->initd = 1;
q->prio=table->tab[ctl->DP]->prio;
else
q->prio=8;
q->qcount = -1; if (gred_rio_mode(table)) {
PSCHED_SET_PASTPERFECT(q->qidlestart); gred_disable_wred_mode(table);
memcpy(q->Stab, RTA_DATA(tb[TCA_GRED_STAB-1]), 256); if (gred_wred_mode_check(sch))
gred_enable_wred_mode(table);
} }
return 0;
err = 0;
errout_locked:
sch_tree_unlock(sch);
errout:
return err;
} }
static int gred_init(struct Qdisc *sch, struct rtattr *opt) static int gred_init(struct Qdisc *sch, struct rtattr *opt)
......
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