@@ -1356,4 +1356,12 @@ static inline void qdisc_synchronize(const struct Qdisc *q)
msleep(1);
}
+#if defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_BPF_JIT)
+extern const struct Qdisc_class_ops sch_bpf_class_ops;
+
+int bpf_qdisc_init_pre_op(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack);
+void bpf_qdisc_destroy_post_op(struct Qdisc *sch);
+void bpf_qdisc_reset_post_op(struct Qdisc *sch);
+#endif
+
#endif
@@ -9,9 +9,6 @@
static struct bpf_struct_ops bpf_Qdisc_ops;
static u32 unsupported_ops[] = {
- offsetof(struct Qdisc_ops, init),
- offsetof(struct Qdisc_ops, reset),
- offsetof(struct Qdisc_ops, destroy),
offsetof(struct Qdisc_ops, change),
offsetof(struct Qdisc_ops, attach),
offsetof(struct Qdisc_ops, change_real_num_tx),
@@ -191,8 +188,8 @@ static void sch_bpf_walk(struct Qdisc *sch, struct qdisc_walker *arg)
}
}
-static int bpf_qdisc_init_op(struct Qdisc *sch, struct nlattr *opt,
- struct netlink_ext_ack *extack)
+int bpf_qdisc_init_pre_op(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
{
struct bpf_sched_data *q = qdisc_priv(sch);
int err;
@@ -210,7 +207,7 @@ static int bpf_qdisc_init_op(struct Qdisc *sch, struct nlattr *opt,
return 0;
}
-static void bpf_qdisc_reset_op(struct Qdisc *sch)
+void bpf_qdisc_reset_post_op(struct Qdisc *sch)
{
struct bpf_sched_data *q = qdisc_priv(sch);
struct sch_bpf_class *cl;
@@ -233,7 +230,7 @@ static void bpf_qdisc_destroy_class(struct Qdisc *sch, struct sch_bpf_class *cl)
kfree(cl);
}
-static void bpf_qdisc_destroy_op(struct Qdisc *sch)
+void bpf_qdisc_destroy_post_op(struct Qdisc *sch)
{
struct bpf_sched_data *q = qdisc_priv(sch);
struct sch_bpf_class *cl;
@@ -255,7 +252,7 @@ static void bpf_qdisc_destroy_op(struct Qdisc *sch)
qdisc_class_hash_destroy(&q->clhash);
}
-static const struct Qdisc_class_ops sch_bpf_class_ops = {
+const struct Qdisc_class_ops sch_bpf_class_ops = {
.graft = sch_bpf_graft,
.leaf = sch_bpf_leaf,
.find = sch_bpf_search,
@@ -611,15 +608,6 @@ static int bpf_qdisc_init_member(const struct btf_type *t,
return -EINVAL;
qdisc_ops->priv_size = sizeof(struct bpf_sched_data);
return 1;
- case offsetof(struct Qdisc_ops, init):
- qdisc_ops->init = bpf_qdisc_init_op;
- return 1;
- case offsetof(struct Qdisc_ops, reset):
- qdisc_ops->reset = bpf_qdisc_reset_op;
- return 1;
- case offsetof(struct Qdisc_ops, destroy):
- qdisc_ops->destroy = bpf_qdisc_destroy_op;
- return 1;
case offsetof(struct Qdisc_ops, peek):
if (!uqdisc_ops->peek)
qdisc_ops->peek = qdisc_peek_dequeued;
@@ -1249,7 +1249,6 @@ static int qdisc_block_indexes_set(struct Qdisc *sch, struct nlattr **tca,
Parameters are passed via opt.
*/
-
static struct Qdisc *qdisc_create(struct net_device *dev,
struct netdev_queue *dev_queue,
u32 parent, u32 handle,
@@ -1352,6 +1351,13 @@ static struct Qdisc *qdisc_create(struct net_device *dev,
rcu_assign_pointer(sch->stab, stab);
}
+#if defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_BPF_JIT)
+ if (ops->cl_ops == &sch_bpf_class_ops) {
+ err = bpf_qdisc_init_pre_op(sch, tca[TCA_OPTIONS], extack);
+ if (err != 0)
+ goto err_out4;
+ }
+#endif
if (ops->init) {
err = ops->init(sch, tca[TCA_OPTIONS], extack);
if (err != 0)
@@ -1388,6 +1394,10 @@ static struct Qdisc *qdisc_create(struct net_device *dev,
*/
if (ops->destroy)
ops->destroy(sch);
+#if defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_BPF_JIT)
+ if (ops->cl_ops == &sch_bpf_class_ops)
+ bpf_qdisc_destroy_post_op(sch);
+#endif
qdisc_put_stab(rtnl_dereference(sch->stab));
err_out3:
netdev_put(dev, &sch->dev_tracker);
@@ -1024,6 +1024,10 @@ void qdisc_reset(struct Qdisc *qdisc)
if (ops->reset)
ops->reset(qdisc);
+#if defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_BPF_JIT)
+ if (ops->cl_ops == &sch_bpf_class_ops)
+ bpf_qdisc_reset_post_op(qdisc);
+#endif
__skb_queue_purge(&qdisc->gso_skb);
__skb_queue_purge(&qdisc->skb_bad_txq);
@@ -1067,6 +1071,10 @@ static void __qdisc_destroy(struct Qdisc *qdisc)
if (ops->destroy)
ops->destroy(qdisc);
+#if defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_BPF_JIT)
+ if (ops->cl_ops == &sch_bpf_class_ops)
+ bpf_qdisc_destroy_post_op(qdisc);
+#endif
bpf_module_put(ops, ops->owner);
netdev_put(dev, &qdisc->dev_tracker);
So far, init, reset, and destroy are implemented by bpf qdisc infra as fixed methods that manipulate the watchdog and the class hash table according to the occasion. This patch allows users to supply these three ops to perform the desired work alongside the predefined methods. Signed-off-by: Amery Hung <amery.hung@bytedance.com> --- include/net/sch_generic.h | 8 ++++++++ net/sched/bpf_qdisc.c | 22 +++++----------------- net/sched/sch_api.c | 12 +++++++++++- net/sched/sch_generic.c | 8 ++++++++ 4 files changed, 32 insertions(+), 18 deletions(-)