Commit 8b27fd66 authored by Toke Høiland-Jørgensen's avatar Toke Høiland-Jørgensen Committed by Paolo Abeni
Browse files

net/sched: Export mq functions for reuse



To enable the cake_mq qdisc to reuse code from the mq qdisc, export a
bunch of functions from sch_mq. Split common functionality out from some
functions so it can be composed with other code, and export other
functions wholesale. To discourage wanton reuse, put the symbols into a
new NET_SCHED_INTERNAL namespace, and a sch_priv.h header file.

No functional change intended.

Reviewed-by: default avatarWillem de Bruijn <willemb@google.com>
Signed-off-by: default avatarToke Høiland-Jørgensen <toke@redhat.com>
Link: https://patch.msgid.link/20260109-mq-cake-sub-qdisc-v8-1-8d613fece5d8@redhat.com


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent de746f8f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -25454,6 +25454,7 @@ L: netdev@vger.kernel.org
S:	Maintained
F:	include/net/pkt_cls.h
F:	include/net/pkt_sched.h
F:	include/net/sch_priv.h
F:	include/net/tc_act/
F:	include/uapi/linux/pkt_cls.h
F:	include/uapi/linux/pkt_sched.h

include/net/sch_priv.h

0 → 100644
+27 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __NET_SCHED_PRIV_H
#define __NET_SCHED_PRIV_H

#include <net/sch_generic.h>

struct mq_sched {
	struct Qdisc		**qdiscs;
};

int mq_init_common(struct Qdisc *sch, struct nlattr *opt,
		   struct netlink_ext_ack *extack,
		   const struct Qdisc_ops *qdisc_ops);
void mq_destroy_common(struct Qdisc *sch);
void mq_attach(struct Qdisc *sch);
void mq_dump_common(struct Qdisc *sch, struct sk_buff *skb);
struct netdev_queue *mq_select_queue(struct Qdisc *sch,
				     struct tcmsg *tcm);
struct Qdisc *mq_leaf(struct Qdisc *sch, unsigned long cl);
unsigned long mq_find(struct Qdisc *sch, u32 classid);
int mq_dump_class(struct Qdisc *sch, unsigned long cl,
		  struct sk_buff *skb, struct tcmsg *tcm);
int mq_dump_class_stats(struct Qdisc *sch, unsigned long cl,
			struct gnet_dump *d);
void mq_walk(struct Qdisc *sch, struct qdisc_walker *arg);

#endif
+49 −22
Original line number Diff line number Diff line
@@ -15,11 +15,7 @@
#include <net/netlink.h>
#include <net/pkt_cls.h>
#include <net/pkt_sched.h>
#include <net/sch_generic.h>

struct mq_sched {
	struct Qdisc		**qdiscs;
};
#include <net/sch_priv.h>

static int mq_offload(struct Qdisc *sch, enum tc_mq_command cmd)
{
@@ -49,23 +45,29 @@ static int mq_offload_stats(struct Qdisc *sch)
	return qdisc_offload_dump_helper(sch, TC_SETUP_QDISC_MQ, &opt);
}

static void mq_destroy(struct Qdisc *sch)
void mq_destroy_common(struct Qdisc *sch)
{
	struct net_device *dev = qdisc_dev(sch);
	struct mq_sched *priv = qdisc_priv(sch);
	unsigned int ntx;

	mq_offload(sch, TC_MQ_DESTROY);

	if (!priv->qdiscs)
		return;
	for (ntx = 0; ntx < dev->num_tx_queues && priv->qdiscs[ntx]; ntx++)
		qdisc_put(priv->qdiscs[ntx]);
	kfree(priv->qdiscs);
}
EXPORT_SYMBOL_NS_GPL(mq_destroy_common, "NET_SCHED_INTERNAL");

static int mq_init(struct Qdisc *sch, struct nlattr *opt,
		   struct netlink_ext_ack *extack)
static void mq_destroy(struct Qdisc *sch)
{
	mq_offload(sch, TC_MQ_DESTROY);
	mq_destroy_common(sch);
}

int mq_init_common(struct Qdisc *sch, struct nlattr *opt,
		   struct netlink_ext_ack *extack,
		   const struct Qdisc_ops *qdisc_ops)
{
	struct net_device *dev = qdisc_dev(sch);
	struct mq_sched *priv = qdisc_priv(sch);
@@ -87,7 +89,8 @@ static int mq_init(struct Qdisc *sch, struct nlattr *opt,

	for (ntx = 0; ntx < dev->num_tx_queues; ntx++) {
		dev_queue = netdev_get_tx_queue(dev, ntx);
		qdisc = qdisc_create_dflt(dev_queue, get_default_qdisc_ops(dev, ntx),
		qdisc = qdisc_create_dflt(dev_queue,
					  qdisc_ops ?: get_default_qdisc_ops(dev, ntx),
					  TC_H_MAKE(TC_H_MAJ(sch->handle),
						    TC_H_MIN(ntx + 1)),
					  extack);
@@ -98,12 +101,24 @@ static int mq_init(struct Qdisc *sch, struct nlattr *opt,
	}

	sch->flags |= TCQ_F_MQROOT;
	return 0;
}
EXPORT_SYMBOL_NS_GPL(mq_init_common, "NET_SCHED_INTERNAL");

static int mq_init(struct Qdisc *sch, struct nlattr *opt,
		   struct netlink_ext_ack *extack)
{
	int ret;

	ret = mq_init_common(sch, opt, extack, NULL);
	if (ret)
		return ret;

	mq_offload(sch, TC_MQ_CREATE);
	return 0;
}

static void mq_attach(struct Qdisc *sch)
void mq_attach(struct Qdisc *sch)
{
	struct net_device *dev = qdisc_dev(sch);
	struct mq_sched *priv = qdisc_priv(sch);
@@ -124,8 +139,9 @@ static void mq_attach(struct Qdisc *sch)
	kfree(priv->qdiscs);
	priv->qdiscs = NULL;
}
EXPORT_SYMBOL_NS_GPL(mq_attach, "NET_SCHED_INTERNAL");

static int mq_dump(struct Qdisc *sch, struct sk_buff *skb)
void mq_dump_common(struct Qdisc *sch, struct sk_buff *skb)
{
	struct net_device *dev = qdisc_dev(sch);
	struct Qdisc *qdisc;
@@ -152,7 +168,12 @@ static int mq_dump(struct Qdisc *sch, struct sk_buff *skb)

		spin_unlock_bh(qdisc_lock(qdisc));
	}
}
EXPORT_SYMBOL_NS_GPL(mq_dump_common, "NET_SCHED_INTERNAL");

static int mq_dump(struct Qdisc *sch, struct sk_buff *skb)
{
	mq_dump_common(sch, skb);
	return mq_offload_stats(sch);
}

@@ -166,11 +187,12 @@ static struct netdev_queue *mq_queue_get(struct Qdisc *sch, unsigned long cl)
	return netdev_get_tx_queue(dev, ntx);
}

static struct netdev_queue *mq_select_queue(struct Qdisc *sch,
struct netdev_queue *mq_select_queue(struct Qdisc *sch,
				     struct tcmsg *tcm)
{
	return mq_queue_get(sch, TC_H_MIN(tcm->tcm_parent));
}
EXPORT_SYMBOL_NS_GPL(mq_select_queue, "NET_SCHED_INTERNAL");

static int mq_graft(struct Qdisc *sch, unsigned long cl, struct Qdisc *new,
		    struct Qdisc **old, struct netlink_ext_ack *extack)
@@ -198,14 +220,15 @@ static int mq_graft(struct Qdisc *sch, unsigned long cl, struct Qdisc *new,
	return 0;
}

static struct Qdisc *mq_leaf(struct Qdisc *sch, unsigned long cl)
struct Qdisc *mq_leaf(struct Qdisc *sch, unsigned long cl)
{
	struct netdev_queue *dev_queue = mq_queue_get(sch, cl);

	return rtnl_dereference(dev_queue->qdisc_sleeping);
}
EXPORT_SYMBOL_NS_GPL(mq_leaf, "NET_SCHED_INTERNAL");

static unsigned long mq_find(struct Qdisc *sch, u32 classid)
unsigned long mq_find(struct Qdisc *sch, u32 classid)
{
	unsigned int ntx = TC_H_MIN(classid);

@@ -213,8 +236,9 @@ static unsigned long mq_find(struct Qdisc *sch, u32 classid)
		return 0;
	return ntx;
}
EXPORT_SYMBOL_NS_GPL(mq_find, "NET_SCHED_INTERNAL");

static int mq_dump_class(struct Qdisc *sch, unsigned long cl,
int mq_dump_class(struct Qdisc *sch, unsigned long cl,
		  struct sk_buff *skb, struct tcmsg *tcm)
{
	struct netdev_queue *dev_queue = mq_queue_get(sch, cl);
@@ -224,8 +248,9 @@ static int mq_dump_class(struct Qdisc *sch, unsigned long cl,
	tcm->tcm_info = rtnl_dereference(dev_queue->qdisc_sleeping)->handle;
	return 0;
}
EXPORT_SYMBOL_NS_GPL(mq_dump_class, "NET_SCHED_INTERNAL");

static int mq_dump_class_stats(struct Qdisc *sch, unsigned long cl,
int mq_dump_class_stats(struct Qdisc *sch, unsigned long cl,
			struct gnet_dump *d)
{
	struct netdev_queue *dev_queue = mq_queue_get(sch, cl);
@@ -236,8 +261,9 @@ static int mq_dump_class_stats(struct Qdisc *sch, unsigned long cl,
		return -1;
	return 0;
}
EXPORT_SYMBOL_NS_GPL(mq_dump_class_stats, "NET_SCHED_INTERNAL");

static void mq_walk(struct Qdisc *sch, struct qdisc_walker *arg)
void mq_walk(struct Qdisc *sch, struct qdisc_walker *arg)
{
	struct net_device *dev = qdisc_dev(sch);
	unsigned int ntx;
@@ -251,6 +277,7 @@ static void mq_walk(struct Qdisc *sch, struct qdisc_walker *arg)
			break;
	}
}
EXPORT_SYMBOL_NS_GPL(mq_walk, "NET_SCHED_INTERNAL");

static const struct Qdisc_class_ops mq_class_ops = {
	.select_queue	= mq_select_queue,