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

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

net-sched: consolidate default fifo qdisc setup

parent aee18a8c
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -72,6 +72,10 @@ extern void qdisc_watchdog_cancel(struct qdisc_watchdog *wd);
extern struct Qdisc_ops pfifo_qdisc_ops;
extern struct Qdisc_ops pfifo_qdisc_ops;
extern struct Qdisc_ops bfifo_qdisc_ops;
extern struct Qdisc_ops bfifo_qdisc_ops;


extern int fifo_set_limit(struct Qdisc *q, unsigned int limit);
extern struct Qdisc *fifo_create_dflt(struct Qdisc *sch, struct Qdisc_ops *ops,
				      unsigned int limit);

extern int register_qdisc(struct Qdisc_ops *qops);
extern int register_qdisc(struct Qdisc_ops *qops);
extern int unregister_qdisc(struct Qdisc_ops *qops);
extern int unregister_qdisc(struct Qdisc_ops *qops);
extern struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle);
extern struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle);
+42 −0
Original line number Original line Diff line number Diff line
@@ -107,3 +107,45 @@ struct Qdisc_ops bfifo_qdisc_ops __read_mostly = {
	.owner		=	THIS_MODULE,
	.owner		=	THIS_MODULE,
};
};
EXPORT_SYMBOL(bfifo_qdisc_ops);
EXPORT_SYMBOL(bfifo_qdisc_ops);

/* Pass size change message down to embedded FIFO */
int fifo_set_limit(struct Qdisc *q, unsigned int limit)
{
	struct nlattr *nla;
	int ret = -ENOMEM;

	/* Hack to avoid sending change message to non-FIFO */
	if (strncmp(q->ops->id + 1, "fifo", 4) != 0)
		return 0;

	nla = kmalloc(nla_attr_size(sizeof(struct tc_fifo_qopt)), GFP_KERNEL);
	if (nla) {
		nla->nla_type = RTM_NEWQDISC;
		nla->nla_len = nla_attr_size(sizeof(struct tc_fifo_qopt));
		((struct tc_fifo_qopt *)nla_data(nla))->limit = limit;

		ret = q->ops->change(q, nla);
		kfree(nla);
	}
	return ret;
}
EXPORT_SYMBOL(fifo_set_limit);

struct Qdisc *fifo_create_dflt(struct Qdisc *sch, struct Qdisc_ops *ops,
			       unsigned int limit)
{
	struct Qdisc *q;
	int err = -ENOMEM;

	q = qdisc_create_dflt(sch->dev, ops, TC_H_MAKE(sch->handle, 1));
	if (q) {
		err = fifo_set_limit(q, limit);
		if (err < 0) {
			qdisc_destroy(q);
			q = NULL;
		}
	}

	return q ? : ERR_PTR(err);
}
EXPORT_SYMBOL(fifo_create_dflt);
+1 −23
Original line number Original line Diff line number Diff line
@@ -310,28 +310,6 @@ static void netem_reset(struct Qdisc *sch)
	qdisc_watchdog_cancel(&q->watchdog);
	qdisc_watchdog_cancel(&q->watchdog);
}
}


/* Pass size change message down to embedded FIFO */
static int set_fifo_limit(struct Qdisc *q, int limit)
{
	struct nlattr *nla;
	int ret = -ENOMEM;

	/* Hack to avoid sending change message to non-FIFO */
	if (strncmp(q->ops->id + 1, "fifo", 4) != 0)
		return 0;

	nla = kmalloc(nla_attr_size(sizeof(struct tc_fifo_qopt)), GFP_KERNEL);
	if (nla) {
		nla->nla_type = RTM_NEWQDISC;
		nla->nla_len = nla_attr_size(sizeof(struct tc_fifo_qopt));
		((struct tc_fifo_qopt *)nla_data(nla))->limit = limit;

		ret = q->ops->change(q, nla);
		kfree(nla);
	}
	return ret;
}

/*
/*
 * Distribution data is a variable size payload containing
 * Distribution data is a variable size payload containing
 * signed 16 bit values.
 * signed 16 bit values.
@@ -416,7 +394,7 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt)
	if (ret < 0)
	if (ret < 0)
		return ret;
		return ret;


	ret = set_fifo_limit(q->qdisc, qopt->limit);
	ret = fifo_set_limit(q->qdisc, qopt->limit);
	if (ret) {
	if (ret) {
		pr_debug("netem: can't set fifo limit\n");
		pr_debug("netem: can't set fifo limit\n");
		return ret;
		return ret;
+3 −30
Original line number Original line Diff line number Diff line
@@ -174,33 +174,6 @@ static void red_destroy(struct Qdisc *sch)
	qdisc_destroy(q->qdisc);
	qdisc_destroy(q->qdisc);
}
}


static struct Qdisc *red_create_dflt(struct Qdisc *sch, u32 limit)
{
	struct Qdisc *q;
	struct nlattr *nla;
	int ret;

	q = qdisc_create_dflt(sch->dev, &bfifo_qdisc_ops,
			      TC_H_MAKE(sch->handle, 1));
	if (q) {
		nla = kmalloc(nla_attr_size(sizeof(struct tc_fifo_qopt)),
			      GFP_KERNEL);
		if (nla) {
			nla->nla_type = RTM_NEWQDISC;
			nla->nla_len = nla_attr_size(sizeof(struct tc_fifo_qopt));
			((struct tc_fifo_qopt *)nla_data(nla))->limit = limit;

			ret = q->ops->change(q, nla);
			kfree(nla);

			if (ret == 0)
				return q;
		}
		qdisc_destroy(q);
	}
	return NULL;
}

static const struct nla_policy red_policy[TCA_RED_MAX + 1] = {
static const struct nla_policy red_policy[TCA_RED_MAX + 1] = {
	[TCA_RED_PARMS]	= { .len = sizeof(struct tc_red_qopt) },
	[TCA_RED_PARMS]	= { .len = sizeof(struct tc_red_qopt) },
	[TCA_RED_STAB]	= { .len = RED_STAB_SIZE },
	[TCA_RED_STAB]	= { .len = RED_STAB_SIZE },
@@ -228,9 +201,9 @@ static int red_change(struct Qdisc *sch, struct nlattr *opt)
	ctl = nla_data(tb[TCA_RED_PARMS]);
	ctl = nla_data(tb[TCA_RED_PARMS]);


	if (ctl->limit > 0) {
	if (ctl->limit > 0) {
		child = red_create_dflt(sch, ctl->limit);
		child = fifo_create_dflt(sch, &bfifo_qdisc_ops, ctl->limit);
		if (child == NULL)
		if (IS_ERR(child))
			return -ENOMEM;
			return PTR_ERR(child);
	}
	}


	sch_tree_lock(sch);
	sch_tree_lock(sch);
+4 −29
Original line number Original line Diff line number Diff line
@@ -242,34 +242,6 @@ static void tbf_reset(struct Qdisc* sch)
	qdisc_watchdog_cancel(&q->watchdog);
	qdisc_watchdog_cancel(&q->watchdog);
}
}


static struct Qdisc *tbf_create_dflt_qdisc(struct Qdisc *sch, u32 limit)
{
	struct Qdisc *q;
	struct nlattr *nla;
	int ret;

	q = qdisc_create_dflt(sch->dev, &bfifo_qdisc_ops,
			      TC_H_MAKE(sch->handle, 1));
	if (q) {
		nla = kmalloc(nla_attr_size(sizeof(struct tc_fifo_qopt)),
			      GFP_KERNEL);
		if (nla) {
			nla->nla_type = RTM_NEWQDISC;
			nla->nla_len = nla_attr_size(sizeof(struct tc_fifo_qopt));
			((struct tc_fifo_qopt *)nla_data(nla))->limit = limit;

			ret = q->ops->change(q, nla);
			kfree(nla);

			if (ret == 0)
				return q;
		}
		qdisc_destroy(q);
	}

	return NULL;
}

static const struct nla_policy tbf_policy[TCA_TBF_MAX + 1] = {
static const struct nla_policy tbf_policy[TCA_TBF_MAX + 1] = {
	[TCA_TBF_PARMS]	= { .len = sizeof(struct tc_tbf_qopt) },
	[TCA_TBF_PARMS]	= { .len = sizeof(struct tc_tbf_qopt) },
	[TCA_TBF_RTAB]	= { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
	[TCA_TBF_RTAB]	= { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
@@ -322,9 +294,12 @@ static int tbf_change(struct Qdisc* sch, struct nlattr *opt)
		goto done;
		goto done;


	if (qopt->limit > 0) {
	if (qopt->limit > 0) {
		if ((child = tbf_create_dflt_qdisc(sch, qopt->limit)) == NULL)
		child = fifo_create_dflt(sch, &bfifo_qdisc_ops, qopt->limit);
		if (IS_ERR(child)) {
			err = PTR_ERR(child);
			goto done;
			goto done;
		}
		}
	}


	sch_tree_lock(sch);
	sch_tree_lock(sch);
	if (child) {
	if (child) {