[PKT_SCHED]: Fix dsmark to apply changes consistent
Fixes dsmark to do all configuration sanity checks first and only apply the changes if all of them can be applied without any errors. Also fixes the weak sanity checks for DSMARK_VALUE and DSMASK_MASK. Signed-off-by: Thomas Graf <tgraf@suug.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
8f48bcd4ef
Коммит
758cc43c6d
|
@ -62,6 +62,21 @@ struct dsmark_qdisc_data {
|
||||||
int set_tc_index;
|
int set_tc_index;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline int dsmark_valid_indices(u16 indices)
|
||||||
|
{
|
||||||
|
while (indices != 1) {
|
||||||
|
if (indices & 1)
|
||||||
|
return 0;
|
||||||
|
indices >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int dsmark_valid_index(struct dsmark_qdisc_data *p, u16 index)
|
||||||
|
{
|
||||||
|
return (index <= p->indices && index > 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* ------------------------- Class/flow operations ------------------------- */
|
/* ------------------------- Class/flow operations ------------------------- */
|
||||||
|
|
||||||
|
@ -125,26 +140,34 @@ static int dsmark_change(struct Qdisc *sch, u32 classid, u32 parent,
|
||||||
struct dsmark_qdisc_data *p = PRIV(sch);
|
struct dsmark_qdisc_data *p = PRIV(sch);
|
||||||
struct rtattr *opt = tca[TCA_OPTIONS-1];
|
struct rtattr *opt = tca[TCA_OPTIONS-1];
|
||||||
struct rtattr *tb[TCA_DSMARK_MAX];
|
struct rtattr *tb[TCA_DSMARK_MAX];
|
||||||
|
int err = -EINVAL;
|
||||||
|
u8 mask = 0;
|
||||||
|
|
||||||
DPRINTK("dsmark_change(sch %p,[qdisc %p],classid %x,parent %x),"
|
DPRINTK("dsmark_change(sch %p,[qdisc %p],classid %x,parent %x),"
|
||||||
"arg 0x%lx\n",sch,p,classid,parent,*arg);
|
"arg 0x%lx\n", sch, p, classid, parent, *arg);
|
||||||
if (*arg > p->indices)
|
|
||||||
return -ENOENT;
|
|
||||||
if (!opt || rtattr_parse_nested(tb, TCA_DSMARK_MAX, opt))
|
|
||||||
return -EINVAL;
|
|
||||||
if (tb[TCA_DSMARK_MASK-1]) {
|
|
||||||
if (!RTA_PAYLOAD(tb[TCA_DSMARK_MASK-1]))
|
|
||||||
return -EINVAL;
|
|
||||||
p->mask[*arg-1] = *(__u8 *) RTA_DATA(tb[TCA_DSMARK_MASK-1]);
|
|
||||||
}
|
|
||||||
if (tb[TCA_DSMARK_VALUE-1]) {
|
|
||||||
if (!RTA_PAYLOAD(tb[TCA_DSMARK_VALUE-1]))
|
|
||||||
return -EINVAL;
|
|
||||||
p->value[*arg-1] = *(__u8 *) RTA_DATA(tb[TCA_DSMARK_VALUE-1]);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (!dsmark_valid_index(p, *arg)) {
|
||||||
|
err = -ENOENT;
|
||||||
|
goto rtattr_failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!opt || rtattr_parse_nested(tb, TCA_DSMARK_MAX, opt))
|
||||||
|
goto rtattr_failure;
|
||||||
|
|
||||||
|
if (tb[TCA_DSMARK_MASK-1])
|
||||||
|
mask = RTA_GET_U8(tb[TCA_DSMARK_MASK-1]);
|
||||||
|
|
||||||
|
if (tb[TCA_DSMARK_VALUE-1])
|
||||||
|
p->value[*arg-1] = RTA_GET_U8(tb[TCA_DSMARK_VALUE-1]);
|
||||||
|
|
||||||
|
if (tb[TCA_DSMARK_MASK-1])
|
||||||
|
p->mask[*arg-1] = mask;
|
||||||
|
|
||||||
|
err = 0;
|
||||||
|
|
||||||
|
rtattr_failure:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
static int dsmark_delete(struct Qdisc *sch,unsigned long arg)
|
static int dsmark_delete(struct Qdisc *sch,unsigned long arg)
|
||||||
{
|
{
|
||||||
|
@ -328,43 +351,53 @@ static unsigned int dsmark_drop(struct Qdisc *sch)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int dsmark_init(struct Qdisc *sch,struct rtattr *opt)
|
static int dsmark_init(struct Qdisc *sch, struct rtattr *opt)
|
||||||
{
|
{
|
||||||
struct dsmark_qdisc_data *p = PRIV(sch);
|
struct dsmark_qdisc_data *p = PRIV(sch);
|
||||||
struct rtattr *tb[TCA_DSMARK_MAX];
|
struct rtattr *tb[TCA_DSMARK_MAX];
|
||||||
__u16 tmp;
|
int err = -EINVAL;
|
||||||
|
u32 default_index = NO_DEFAULT_INDEX;
|
||||||
|
u16 indices;
|
||||||
|
u8 *mask;
|
||||||
|
|
||||||
DPRINTK("dsmark_init(sch %p,[qdisc %p],opt %p)\n",sch,p,opt);
|
DPRINTK("dsmark_init(sch %p,[qdisc %p],opt %p)\n", sch, p, opt);
|
||||||
if (!opt ||
|
|
||||||
rtattr_parse(tb,TCA_DSMARK_MAX,RTA_DATA(opt),RTA_PAYLOAD(opt)) < 0 ||
|
if (!opt || rtattr_parse_nested(tb, TCA_DSMARK_MAX, opt) < 0)
|
||||||
!tb[TCA_DSMARK_INDICES-1] ||
|
goto errout;
|
||||||
RTA_PAYLOAD(tb[TCA_DSMARK_INDICES-1]) < sizeof(__u16))
|
|
||||||
return -EINVAL;
|
indices = RTA_GET_U16(tb[TCA_DSMARK_INDICES-1]);
|
||||||
p->indices = *(__u16 *) RTA_DATA(tb[TCA_DSMARK_INDICES-1]);
|
if (!indices || !dsmark_valid_indices(indices))
|
||||||
if (!p->indices)
|
goto errout;
|
||||||
return -EINVAL;
|
|
||||||
for (tmp = p->indices; tmp != 1; tmp >>= 1) {
|
if (tb[TCA_DSMARK_DEFAULT_INDEX-1])
|
||||||
if (tmp & 1)
|
default_index = RTA_GET_U16(tb[TCA_DSMARK_DEFAULT_INDEX-1]);
|
||||||
return -EINVAL;
|
|
||||||
|
mask = kmalloc(indices * 2, GFP_KERNEL);
|
||||||
|
if (mask == NULL) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto errout;
|
||||||
}
|
}
|
||||||
p->default_index = NO_DEFAULT_INDEX;
|
|
||||||
if (tb[TCA_DSMARK_DEFAULT_INDEX-1]) {
|
p->mask = mask;
|
||||||
if (RTA_PAYLOAD(tb[TCA_DSMARK_DEFAULT_INDEX-1]) < sizeof(__u16))
|
memset(p->mask, 0xff, indices);
|
||||||
return -EINVAL;
|
|
||||||
p->default_index =
|
p->value = p->mask + indices;
|
||||||
*(__u16 *) RTA_DATA(tb[TCA_DSMARK_DEFAULT_INDEX-1]);
|
memset(p->value, 0, indices);
|
||||||
}
|
|
||||||
p->set_tc_index = !!tb[TCA_DSMARK_SET_TC_INDEX-1];
|
p->indices = indices;
|
||||||
p->mask = kmalloc(p->indices*2,GFP_KERNEL);
|
p->default_index = default_index;
|
||||||
if (!p->mask)
|
p->set_tc_index = RTA_GET_FLAG(tb[TCA_DSMARK_SET_TC_INDEX-1]);
|
||||||
return -ENOMEM;
|
|
||||||
p->value = p->mask+p->indices;
|
p->q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
|
||||||
memset(p->mask,0xff,p->indices);
|
if (p->q == NULL)
|
||||||
memset(p->value,0,p->indices);
|
|
||||||
if (!(p->q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops)))
|
|
||||||
p->q = &noop_qdisc;
|
p->q = &noop_qdisc;
|
||||||
DPRINTK("dsmark_init: qdisc %p\n",&p->q);
|
|
||||||
return 0;
|
DPRINTK("dsmark_init: qdisc %p\n", p->q);
|
||||||
|
|
||||||
|
err = 0;
|
||||||
|
errout:
|
||||||
|
rtattr_failure:
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче