|
@@ -62,6 +62,21 @@ struct dsmark_qdisc_data {
|
|
|
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 ------------------------- */
|
|
|
|
|
@@ -120,31 +135,39 @@ static void dsmark_put(struct Qdisc *sch, unsigned long cl)
|
|
|
|
|
|
|
|
|
static int dsmark_change(struct Qdisc *sch, u32 classid, u32 parent,
|
|
|
- struct rtattr **tca, unsigned long *arg)
|
|
|
+ struct rtattr **tca, unsigned long *arg)
|
|
|
{
|
|
|
struct dsmark_qdisc_data *p = PRIV(sch);
|
|
|
struct rtattr *opt = tca[TCA_OPTIONS-1];
|
|
|
struct rtattr *tb[TCA_DSMARK_MAX];
|
|
|
+ int err = -EINVAL;
|
|
|
+ u8 mask = 0;
|
|
|
|
|
|
DPRINTK("dsmark_change(sch %p,[qdisc %p],classid %x,parent %x),"
|
|
|
- "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]);
|
|
|
+ "arg 0x%lx\n", sch, p, classid, parent, *arg);
|
|
|
+
|
|
|
+ if (!dsmark_valid_index(p, *arg)) {
|
|
|
+ err = -ENOENT;
|
|
|
+ goto rtattr_failure;
|
|
|
}
|
|
|
- return 0;
|
|
|
-}
|
|
|
|
|
|
+ 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)
|
|
|
{
|
|
@@ -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 rtattr *tb[TCA_DSMARK_MAX];
|
|
|
- __u16 tmp;
|
|
|
-
|
|
|
- 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 ||
|
|
|
- !tb[TCA_DSMARK_INDICES-1] ||
|
|
|
- RTA_PAYLOAD(tb[TCA_DSMARK_INDICES-1]) < sizeof(__u16))
|
|
|
- return -EINVAL;
|
|
|
- p->indices = *(__u16 *) RTA_DATA(tb[TCA_DSMARK_INDICES-1]);
|
|
|
- if (!p->indices)
|
|
|
- return -EINVAL;
|
|
|
- for (tmp = p->indices; tmp != 1; tmp >>= 1) {
|
|
|
- if (tmp & 1)
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
- p->default_index = NO_DEFAULT_INDEX;
|
|
|
- if (tb[TCA_DSMARK_DEFAULT_INDEX-1]) {
|
|
|
- if (RTA_PAYLOAD(tb[TCA_DSMARK_DEFAULT_INDEX-1]) < sizeof(__u16))
|
|
|
- return -EINVAL;
|
|
|
- p->default_index =
|
|
|
- *(__u16 *) RTA_DATA(tb[TCA_DSMARK_DEFAULT_INDEX-1]);
|
|
|
+ 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);
|
|
|
+
|
|
|
+ if (!opt || rtattr_parse_nested(tb, TCA_DSMARK_MAX, opt) < 0)
|
|
|
+ goto errout;
|
|
|
+
|
|
|
+ indices = RTA_GET_U16(tb[TCA_DSMARK_INDICES-1]);
|
|
|
+ if (!indices || !dsmark_valid_indices(indices))
|
|
|
+ goto errout;
|
|
|
+
|
|
|
+ if (tb[TCA_DSMARK_DEFAULT_INDEX-1])
|
|
|
+ default_index = RTA_GET_U16(tb[TCA_DSMARK_DEFAULT_INDEX-1]);
|
|
|
+
|
|
|
+ mask = kmalloc(indices * 2, GFP_KERNEL);
|
|
|
+ if (mask == NULL) {
|
|
|
+ err = -ENOMEM;
|
|
|
+ goto errout;
|
|
|
}
|
|
|
- p->set_tc_index = !!tb[TCA_DSMARK_SET_TC_INDEX-1];
|
|
|
- p->mask = kmalloc(p->indices*2,GFP_KERNEL);
|
|
|
- if (!p->mask)
|
|
|
- return -ENOMEM;
|
|
|
- p->value = p->mask+p->indices;
|
|
|
- memset(p->mask,0xff,p->indices);
|
|
|
- memset(p->value,0,p->indices);
|
|
|
- if (!(p->q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops)))
|
|
|
+
|
|
|
+ p->mask = mask;
|
|
|
+ memset(p->mask, 0xff, indices);
|
|
|
+
|
|
|
+ p->value = p->mask + indices;
|
|
|
+ memset(p->value, 0, indices);
|
|
|
+
|
|
|
+ p->indices = indices;
|
|
|
+ p->default_index = default_index;
|
|
|
+ p->set_tc_index = RTA_GET_FLAG(tb[TCA_DSMARK_SET_TC_INDEX-1]);
|
|
|
+
|
|
|
+ p->q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
|
|
|
+ if (p->q == NULL)
|
|
|
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;
|
|
|
}
|
|
|
|
|
|
|