Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit de6d5cdf authored by Patrick McHardy's avatar Patrick McHardy Committed by David S. Miller
Browse files

net_sched: make cls_ops->change and cls_ops->delete optional



Some schedulers don't support creating, changing or deleting classes.
Make the respective callbacks optionally and consistently return
-EOPNOTSUPP for unsupported operations, instead of currently either
-EOPNOTSUPP, -ENOSYS or no error.

In case of sch_prio and sch_multiq, the removed operations additionally
checked for an invalid class. This is not necessary since the class
argument can only orginate from ->get() or in case of ->change is 0
for creation of new classes, in which case ->change() incorrectly
returned -ENOENT.

As a side-effect, this patch fixes a possible (root-only) NULL pointer
function call in sch_ingress, which didn't implement a so far mandatory
->delete() operation.

Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 71ebe5e9
Loading
Loading
Loading
Loading
+6 −2
Original line number Original line Diff line number Diff line
@@ -1417,6 +1417,8 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
				goto out;
				goto out;
			break;
			break;
		case RTM_DELTCLASS:
		case RTM_DELTCLASS:
			err = -EOPNOTSUPP;
			if (cops->delete)
				err = cops->delete(q, cl);
				err = cops->delete(q, cl);
			if (err == 0)
			if (err == 0)
				tclass_notify(skb, n, q, cl, RTM_DELTCLASS);
				tclass_notify(skb, n, q, cl, RTM_DELTCLASS);
@@ -1431,6 +1433,8 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
	}
	}


	new_cl = cl;
	new_cl = cl;
	err = -EOPNOTSUPP;
	if (cops->change)
		err = cops->change(q, clid, pid, tca, &new_cl);
		err = cops->change(q, clid, pid, tca, &new_cl);
	if (err == 0)
	if (err == 0)
		tclass_notify(skb, n, q, new_cl, RTM_NEWTCLASS);
		tclass_notify(skb, n, q, new_cl, RTM_NEWTCLASS);
+0 −7
Original line number Original line Diff line number Diff line
@@ -42,12 +42,6 @@ static void ingress_put(struct Qdisc *sch, unsigned long cl)
{
{
}
}


static int ingress_change(struct Qdisc *sch, u32 classid, u32 parent,
			  struct nlattr **tca, unsigned long *arg)
{
	return 0;
}

static void ingress_walk(struct Qdisc *sch, struct qdisc_walker *walker)
static void ingress_walk(struct Qdisc *sch, struct qdisc_walker *walker)
{
{
	return;
	return;
@@ -120,7 +114,6 @@ static const struct Qdisc_class_ops ingress_class_ops = {
	.leaf		=	ingress_leaf,
	.leaf		=	ingress_leaf,
	.get		=	ingress_get,
	.get		=	ingress_get,
	.put		=	ingress_put,
	.put		=	ingress_put,
	.change		=	ingress_change,
	.walk		=	ingress_walk,
	.walk		=	ingress_walk,
	.tcf_chain	=	ingress_find_tcf,
	.tcf_chain	=	ingress_find_tcf,
	.bind_tcf	=	ingress_bind_filter,
	.bind_tcf	=	ingress_bind_filter,
+0 −22
Original line number Original line Diff line number Diff line
@@ -348,26 +348,6 @@ static void multiq_put(struct Qdisc *q, unsigned long cl)
	return;
	return;
}
}


static int multiq_change(struct Qdisc *sch, u32 handle, u32 parent,
			 struct nlattr **tca, unsigned long *arg)
{
	unsigned long cl = *arg;
	struct multiq_sched_data *q = qdisc_priv(sch);

	if (cl - 1 > q->bands)
		return -ENOENT;
	return 0;
}

static int multiq_delete(struct Qdisc *sch, unsigned long cl)
{
	struct multiq_sched_data *q = qdisc_priv(sch);
	if (cl - 1 > q->bands)
		return -ENOENT;
	return 0;
}


static int multiq_dump_class(struct Qdisc *sch, unsigned long cl,
static int multiq_dump_class(struct Qdisc *sch, unsigned long cl,
			     struct sk_buff *skb, struct tcmsg *tcm)
			     struct sk_buff *skb, struct tcmsg *tcm)
{
{
@@ -430,8 +410,6 @@ static const struct Qdisc_class_ops multiq_class_ops = {
	.leaf		=	multiq_leaf,
	.leaf		=	multiq_leaf,
	.get		=	multiq_get,
	.get		=	multiq_get,
	.put		=	multiq_put,
	.put		=	multiq_put,
	.change		=	multiq_change,
	.delete		=	multiq_delete,
	.walk		=	multiq_walk,
	.walk		=	multiq_walk,
	.tcf_chain	=	multiq_find_tcf,
	.tcf_chain	=	multiq_find_tcf,
	.bind_tcf	=	multiq_bind,
	.bind_tcf	=	multiq_bind,
+0 −21
Original line number Original line Diff line number Diff line
@@ -311,25 +311,6 @@ static void prio_put(struct Qdisc *q, unsigned long cl)
	return;
	return;
}
}


static int prio_change(struct Qdisc *sch, u32 handle, u32 parent, struct nlattr **tca, unsigned long *arg)
{
	unsigned long cl = *arg;
	struct prio_sched_data *q = qdisc_priv(sch);

	if (cl - 1 > q->bands)
		return -ENOENT;
	return 0;
}

static int prio_delete(struct Qdisc *sch, unsigned long cl)
{
	struct prio_sched_data *q = qdisc_priv(sch);
	if (cl - 1 > q->bands)
		return -ENOENT;
	return 0;
}


static int prio_dump_class(struct Qdisc *sch, unsigned long cl, struct sk_buff *skb,
static int prio_dump_class(struct Qdisc *sch, unsigned long cl, struct sk_buff *skb,
			   struct tcmsg *tcm)
			   struct tcmsg *tcm)
{
{
@@ -392,8 +373,6 @@ static const struct Qdisc_class_ops prio_class_ops = {
	.leaf		=	prio_leaf,
	.leaf		=	prio_leaf,
	.get		=	prio_get,
	.get		=	prio_get,
	.put		=	prio_put,
	.put		=	prio_put,
	.change		=	prio_change,
	.delete		=	prio_delete,
	.walk		=	prio_walk,
	.walk		=	prio_walk,
	.tcf_chain	=	prio_find_tcf,
	.tcf_chain	=	prio_find_tcf,
	.bind_tcf	=	prio_bind,
	.bind_tcf	=	prio_bind,
+0 −13
Original line number Original line Diff line number Diff line
@@ -308,17 +308,6 @@ static void red_put(struct Qdisc *sch, unsigned long arg)
	return;
	return;
}
}


static int red_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
			    struct nlattr **tca, unsigned long *arg)
{
	return -ENOSYS;
}

static int red_delete(struct Qdisc *sch, unsigned long cl)
{
	return -ENOSYS;
}

static void red_walk(struct Qdisc *sch, struct qdisc_walker *walker)
static void red_walk(struct Qdisc *sch, struct qdisc_walker *walker)
{
{
	if (!walker->stop) {
	if (!walker->stop) {
@@ -336,8 +325,6 @@ static const struct Qdisc_class_ops red_class_ops = {
	.leaf		=	red_leaf,
	.leaf		=	red_leaf,
	.get		=	red_get,
	.get		=	red_get,
	.put		=	red_put,
	.put		=	red_put,
	.change		=	red_change_class,
	.delete		=	red_delete,
	.walk		=	red_walk,
	.walk		=	red_walk,
	.dump		=	red_dump_class,
	.dump		=	red_dump_class,
};
};
Loading