@@ -1359,4 +1359,8 @@ static inline void qdisc_synchronize(const struct Qdisc *q)
msleep(1);
}
+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
@@ -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),
@@ -36,28 +33,31 @@ static int bpf_qdisc_init(struct btf *btf)
return 0;
}
-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);
qdisc_watchdog_init(&q->watchdog, sch);
return 0;
}
+EXPORT_SYMBOL(bpf_qdisc_init_pre_op);
-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);
qdisc_watchdog_cancel(&q->watchdog);
}
+EXPORT_SYMBOL(bpf_qdisc_reset_post_op);
-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);
qdisc_watchdog_cancel(&q->watchdog);
}
+EXPORT_SYMBOL(bpf_qdisc_destroy_post_op);
static const struct bpf_func_proto *
bpf_qdisc_get_func_proto(enum bpf_func_id func_id,
@@ -235,15 +235,6 @@ static int bpf_qdisc_init_member(const struct btf_type *t,
return -EINVAL;
qdisc_ops->static_flags = TCQ_F_BPF;
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;
@@ -1352,6 +1352,13 @@ static struct Qdisc *qdisc_create(struct net_device *dev,
rcu_assign_pointer(sch->stab, stab);
}
+#ifdef CONFIG_NET_SCH_BPF
+ if (sch->flags & TCQ_F_BPF) {
+ 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 +1395,10 @@ static struct Qdisc *qdisc_create(struct net_device *dev,
*/
if (ops->destroy)
ops->destroy(sch);
+#ifdef CONFIG_NET_SCH_BPF
+ if (sch->flags & TCQ_F_BPF)
+ bpf_qdisc_destroy_post_op(sch);
+#endif
qdisc_put_stab(rtnl_dereference(sch->stab));
err_out3:
lockdep_unregister_key(&sch->root_lock_key);
@@ -1033,6 +1033,10 @@ void qdisc_reset(struct Qdisc *qdisc)
if (ops->reset)
ops->reset(qdisc);
+#ifdef CONFIG_NET_SCH_BPF
+ if (qdisc->flags & TCQ_F_BPF)
+ bpf_qdisc_reset_post_op(qdisc);
+#endif
__skb_queue_purge(&qdisc->gso_skb);
__skb_queue_purge(&qdisc->skb_bad_txq);
@@ -1076,6 +1080,10 @@ static void __qdisc_destroy(struct Qdisc *qdisc)
if (ops->destroy)
ops->destroy(qdisc);
+#ifdef CONFIG_NET_SCH_BPF
+ if (qdisc->flags & TCQ_F_BPF)
+ bpf_qdisc_destroy_post_op(qdisc);
+#endif
lockdep_unregister_key(&qdisc->root_lock_key);
bpf_module_put(ops, ops->owner);