diff options
author | Jakub Kicinski <kuba@kernel.org> | 2025-05-05 23:22:58 +0300 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2025-05-05 23:22:58 +0300 |
commit | b4cd2ee54ca47c4575e30419f39a31249c1ee9b0 (patch) | |
tree | 07bdf715b5a4c923268346e7626f5d715378ada0 /net/sched | |
parent | 836b313a14a316290886dcc2ce7e78bf5ecc8658 (diff) | |
parent | 30190f82a1a9eb555703879cfe835627cff7a0e2 (diff) | |
download | linux-b4cd2ee54ca47c4575e30419f39a31249c1ee9b0.tar.xz |
Merge tag 'for-netdev' of https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next
Martin KaFai Lau says:
====================
pull-request: bpf-next 2025-05-02
We've added 14 non-merge commits during the last 10 day(s) which contain
a total of 13 files changed, 740 insertions(+), 121 deletions(-).
The main changes are:
1) Avoid skipping or repeating a sk when using a UDP bpf_iter,
from Jordan Rife.
2) Fixed a crash when a bpf qdisc is set in
the net.core.default_qdisc, from Amery Hung.
3) A few other fixes in the bpf qdisc, from Amery Hung.
- Always call qdisc_watchdog_init() in the .init prologue such that
the .reset/.destroy epilogue can always call qdisc_watchdog_cancel()
without issue.
- bpf_qdisc_init_prologue() was incorrectly returning an error
when the bpf qdisc is set as the default_qdisc and the mq is creating
the default_qdisc. It is now fixed.
* tag 'for-netdev' of https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next:
selftests/bpf: Cleanup bpf qdisc selftests
selftests/bpf: Test attaching a bpf qdisc with incomplete operators
bpf: net_sched: Make some Qdisc_ops ops mandatory
selftests/bpf: Test setting and creating bpf qdisc as default qdisc
bpf: net_sched: Fix bpf qdisc init prologue when set as default qdisc
selftests/bpf: Add tests for bucket resume logic in UDP socket iterators
selftests/bpf: Return socket cookies from sock_iter_batch progs
bpf: udp: Avoid socket skips and repeats during iteration
bpf: udp: Use bpf_udp_iter_batch_item for bpf_udp_iter_state batch items
bpf: udp: Get rid of st_bucket_done
bpf: udp: Make sure iter->batch always contains a full bucket snapshot
bpf: udp: Make mem flags configurable through bpf_iter_udp_realloc_batch
bpf: net_sched: Fix using bpf qdisc as default qdisc
selftests/bpf: Fix compilation errors
====================
Link: https://patch.msgid.link/20250503010755.4030524-1-martin.lau@linux.dev
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'net/sched')
-rw-r--r-- | net/sched/bpf_qdisc.c | 24 | ||||
-rw-r--r-- | net/sched/sch_api.c | 4 | ||||
-rw-r--r-- | net/sched/sch_generic.c | 4 |
3 files changed, 23 insertions, 9 deletions
diff --git a/net/sched/bpf_qdisc.c b/net/sched/bpf_qdisc.c index 9f32b305636f..7ea8b54b2ab1 100644 --- a/net/sched/bpf_qdisc.c +++ b/net/sched/bpf_qdisc.c @@ -234,18 +234,20 @@ __bpf_kfunc int bpf_qdisc_init_prologue(struct Qdisc *sch, struct net_device *dev = qdisc_dev(sch); struct Qdisc *p; + qdisc_watchdog_init(&q->watchdog, sch); + if (sch->parent != TC_H_ROOT) { + /* If qdisc_lookup() returns NULL, it means .init is called by + * qdisc_create_dflt() in mq/mqprio_init and the parent qdisc + * has not been added to qdisc_hash yet. + */ p = qdisc_lookup(dev, TC_H_MAJ(sch->parent)); - if (!p) - return -ENOENT; - - if (!(p->flags & TCQ_F_MQROOT)) { + if (p && !(p->flags & TCQ_F_MQROOT)) { NL_SET_ERR_MSG(extack, "BPF qdisc only supported on root or mq"); return -EINVAL; } } - qdisc_watchdog_init(&q->watchdog, sch); return 0; } @@ -393,6 +395,17 @@ static void bpf_qdisc_unreg(void *kdata, struct bpf_link *link) return unregister_qdisc(kdata); } +static int bpf_qdisc_validate(void *kdata) +{ + struct Qdisc_ops *ops = (struct Qdisc_ops *)kdata; + + if (!ops->enqueue || !ops->dequeue || !ops->init || + !ops->reset || !ops->destroy) + return -EINVAL; + + return 0; +} + static int Qdisc_ops__enqueue(struct sk_buff *skb__ref, struct Qdisc *sch, struct sk_buff **to_free) { @@ -430,6 +443,7 @@ static struct bpf_struct_ops bpf_Qdisc_ops = { .verifier_ops = &bpf_qdisc_verifier_ops, .reg = bpf_qdisc_reg, .unreg = bpf_qdisc_unreg, + .validate = bpf_qdisc_validate, .init_member = bpf_qdisc_init_member, .init = bpf_qdisc_init, .name = "Qdisc_ops", diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index db6330258dda..c5e3673aadbe 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -208,7 +208,7 @@ static struct Qdisc_ops *qdisc_lookup_default(const char *name) for (q = qdisc_base; q; q = q->next) { if (!strcmp(name, q->id)) { - if (!try_module_get(q->owner)) + if (!bpf_try_module_get(q, q->owner)) q = NULL; break; } @@ -238,7 +238,7 @@ int qdisc_set_default(const char *name) if (ops) { /* Set new default */ - module_put(default_qdisc_ops->owner); + bpf_module_put(default_qdisc_ops, default_qdisc_ops->owner); default_qdisc_ops = ops; } write_unlock(&qdisc_mod_lock); diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index fc5ef69359db..08e0e3aff976 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -1002,14 +1002,14 @@ struct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue, { struct Qdisc *sch; - if (!try_module_get(ops->owner)) { + if (!bpf_try_module_get(ops, ops->owner)) { NL_SET_ERR_MSG(extack, "Failed to increase module reference counter"); return NULL; } sch = qdisc_alloc(dev_queue, ops, extack); if (IS_ERR(sch)) { - module_put(ops->owner); + bpf_module_put(ops, ops->owner); return NULL; } sch->parent = parentid; |