net: sched: mq: add simple offload notification
mq offload is trivial, we just need to let the device know that the root qdisc is mq. Alternative approach would be to export qdisc_lookup() and make drivers check the root type themselves, but notification via ndo_setup_tc is more in line with other qdiscs. Note that mq doesn't hold any stats on it's own, it just adds up stats of its children. Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

committed by
David S. Miller

parent
2ef3c253f1
commit
f971b13230
@@ -791,6 +791,7 @@ enum tc_setup_type {
|
|||||||
TC_SETUP_QDISC_CBS,
|
TC_SETUP_QDISC_CBS,
|
||||||
TC_SETUP_QDISC_RED,
|
TC_SETUP_QDISC_RED,
|
||||||
TC_SETUP_QDISC_PRIO,
|
TC_SETUP_QDISC_PRIO,
|
||||||
|
TC_SETUP_QDISC_MQ,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* These structures hold the attributes of bpf state that are being passed
|
/* These structures hold the attributes of bpf state that are being passed
|
||||||
|
@@ -778,6 +778,16 @@ struct tc_qopt_offload_stats {
|
|||||||
struct gnet_stats_queue *qstats;
|
struct gnet_stats_queue *qstats;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum tc_mq_command {
|
||||||
|
TC_MQ_CREATE,
|
||||||
|
TC_MQ_DESTROY,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tc_mq_qopt_offload {
|
||||||
|
enum tc_mq_command command;
|
||||||
|
u32 handle;
|
||||||
|
};
|
||||||
|
|
||||||
enum tc_red_command {
|
enum tc_red_command {
|
||||||
TC_RED_REPLACE,
|
TC_RED_REPLACE,
|
||||||
TC_RED_DESTROY,
|
TC_RED_DESTROY,
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/skbuff.h>
|
#include <linux/skbuff.h>
|
||||||
#include <net/netlink.h>
|
#include <net/netlink.h>
|
||||||
|
#include <net/pkt_cls.h>
|
||||||
#include <net/pkt_sched.h>
|
#include <net/pkt_sched.h>
|
||||||
#include <net/sch_generic.h>
|
#include <net/sch_generic.h>
|
||||||
|
|
||||||
@@ -23,12 +24,28 @@ struct mq_sched {
|
|||||||
struct Qdisc **qdiscs;
|
struct Qdisc **qdiscs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int mq_offload(struct Qdisc *sch, enum tc_mq_command cmd)
|
||||||
|
{
|
||||||
|
struct net_device *dev = qdisc_dev(sch);
|
||||||
|
struct tc_mq_qopt_offload opt = {
|
||||||
|
.command = cmd,
|
||||||
|
.handle = sch->handle,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!tc_can_offload(dev) || !dev->netdev_ops->ndo_setup_tc)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
return dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_QDISC_MQ, &opt);
|
||||||
|
}
|
||||||
|
|
||||||
static void mq_destroy(struct Qdisc *sch)
|
static void mq_destroy(struct Qdisc *sch)
|
||||||
{
|
{
|
||||||
struct net_device *dev = qdisc_dev(sch);
|
struct net_device *dev = qdisc_dev(sch);
|
||||||
struct mq_sched *priv = qdisc_priv(sch);
|
struct mq_sched *priv = qdisc_priv(sch);
|
||||||
unsigned int ntx;
|
unsigned int ntx;
|
||||||
|
|
||||||
|
mq_offload(sch, TC_MQ_DESTROY);
|
||||||
|
|
||||||
if (!priv->qdiscs)
|
if (!priv->qdiscs)
|
||||||
return;
|
return;
|
||||||
for (ntx = 0; ntx < dev->num_tx_queues && priv->qdiscs[ntx]; ntx++)
|
for (ntx = 0; ntx < dev->num_tx_queues && priv->qdiscs[ntx]; ntx++)
|
||||||
@@ -70,6 +87,8 @@ static int mq_init(struct Qdisc *sch, struct nlattr *opt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
sch->flags |= TCQ_F_MQROOT;
|
sch->flags |= TCQ_F_MQROOT;
|
||||||
|
|
||||||
|
mq_offload(sch, TC_MQ_CREATE);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user