Module Name: src Committed By: martin Date: Wed Jun 9 15:44:15 UTC 2021
Modified Files: src/sys/net: bpf.c bpf.h bpfdesc.h Log Message: Add a bpf_register_track_event() function (and deregister equivalent) that allows a driver to track listeners attaching/detaching from tap points. This is usefull for drivers that would have to do extra work for some taps and can not easily decide (at the driver level) if the work would be needed further up the stack. An example is providing radiotap headers for IEEE 802.11 frames. To generate a diff of this commit: cvs rdiff -u -r1.239 -r1.240 src/sys/net/bpf.c cvs rdiff -u -r1.76 -r1.77 src/sys/net/bpf.h cvs rdiff -u -r1.47 -r1.48 src/sys/net/bpfdesc.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/net/bpf.c diff -u src/sys/net/bpf.c:1.239 src/sys/net/bpf.c:1.240 --- src/sys/net/bpf.c:1.239 Fri Dec 18 01:31:49 2020 +++ src/sys/net/bpf.c Wed Jun 9 15:44:15 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: bpf.c,v 1.239 2020/12/18 01:31:49 thorpej Exp $ */ +/* $NetBSD: bpf.c,v 1.240 2021/06/09 15:44:15 martin Exp $ */ /* * Copyright (c) 1990, 1991, 1993 @@ -39,7 +39,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: bpf.c,v 1.239 2020/12/18 01:31:49 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: bpf.c,v 1.240 2021/06/09 15:44:15 martin Exp $"); #if defined(_KERNEL_OPT) #include "opt_bpf.h" @@ -461,6 +461,7 @@ bad: static void bpf_attachd(struct bpf_d *d, struct bpf_if *bp) { + struct bpf_event_tracker *t; KASSERT(mutex_owned(&bpf_mtx)); KASSERT(mutex_owned(d->bd_mtx)); @@ -473,6 +474,11 @@ bpf_attachd(struct bpf_d *d, struct bpf_ BPFIF_DLIST_WRITER_INSERT_HEAD(bp, d); *bp->bif_driverp = bp; + + SLIST_FOREACH(t, &bp->bif_trackers, bet_entries) { + t->bet_notify(bp, bp->bif_ifp, bp->bif_dlt, + BPF_TRACK_EVENT_ATTACH); + } } /* @@ -482,6 +488,7 @@ static void bpf_detachd(struct bpf_d *d) { struct bpf_if *bp; + struct bpf_event_tracker *t; KASSERT(mutex_owned(&bpf_mtx)); KASSERT(mutex_owned(d->bd_mtx)); @@ -522,7 +529,13 @@ bpf_detachd(struct bpf_d *d) */ *d->bd_bif->bif_driverp = NULL; } + d->bd_bif = NULL; + + SLIST_FOREACH(t, &bp->bif_trackers, bet_entries) { + t->bet_notify(bp, bp->bif_ifp, bp->bif_dlt, + BPF_TRACK_EVENT_DETACH); + } } static void @@ -2125,6 +2138,7 @@ _bpfattach(struct ifnet *ifp, u_int dlt, BPF_IFLIST_ENTRY_INIT(bp); PSLIST_INIT(&bp->bif_dlist_head); psref_target_init(&bp->bif_psref, bpf_psref_class); + SLIST_INIT(&bp->bif_trackers); BPF_IFLIST_WRITER_INSERT_HEAD(bp); @@ -2133,7 +2147,7 @@ _bpfattach(struct ifnet *ifp, u_int dlt, bp->bif_hdrlen = hdrlen; mutex_exit(&bpf_mtx); #if 0 - printf("bpf: %s attached\n", ifp->if_xname); + printf("bpf: %s attached with dlt %x\n", ifp->if_xname, dlt); #endif } @@ -2196,6 +2210,14 @@ _bpfdetach(struct ifnet *ifp) pserialize_perform(bpf_psz); psref_target_destroy(&bp->bif_psref, bpf_psref_class); + while (!SLIST_EMPTY(&bp->bif_trackers)) { + struct bpf_event_tracker *t = + SLIST_FIRST(&bp->bif_trackers); + SLIST_REMOVE_HEAD(&bp->bif_trackers, + bet_entries); + kmem_free(t, sizeof(*t)); + } + BPF_IFLIST_ENTRY_DESTROY(bp); if (bp->bif_si != NULL) { /* XXX NOMPSAFE: assumed running on one CPU */ @@ -2523,10 +2545,69 @@ SYSCTL_SETUP(sysctl_net_bpf_setup, "bpf } +static int +_bpf_register_track_event(struct bpf_if **driverp, + void (*_fun)(struct bpf_if *, struct ifnet *, int, int)) +{ + struct bpf_if *bp; + struct bpf_event_tracker *t; + int ret = ENOENT; + + t = kmem_zalloc(sizeof(*t), KM_SLEEP); + if (!t) + return ENOMEM; + t->bet_notify = _fun; + + mutex_enter(&bpf_mtx); + BPF_IFLIST_WRITER_FOREACH(bp) { + if (bp->bif_driverp != driverp) + continue; + SLIST_INSERT_HEAD(&bp->bif_trackers, t, bet_entries); + ret = 0; + break; + } + mutex_exit(&bpf_mtx); + + return ret; +} + +static int +_bpf_deregister_track_event(struct bpf_if **driverp, + void (*_fun)(struct bpf_if *, struct ifnet *, int, int)) +{ + struct bpf_if *bp; + struct bpf_event_tracker *t = NULL; + int ret = ENOENT; + + mutex_enter(&bpf_mtx); + BPF_IFLIST_WRITER_FOREACH(bp) { + if (bp->bif_driverp != driverp) + continue; + SLIST_FOREACH(t, &bp->bif_trackers, bet_entries) { + if (t->bet_notify == _fun) { + ret = 0; + break; + } + } + if (ret == 0) + break; + } + if (ret == 0 && t && t->bet_notify == _fun) { + SLIST_REMOVE(&bp->bif_trackers, t, bpf_event_tracker, + bet_entries); + } + mutex_exit(&bpf_mtx); + if (ret == 0) + kmem_free(t, sizeof(*t)); + return ret; +} + struct bpf_ops bpf_ops_kernel = { .bpf_attach = _bpfattach, .bpf_detach = _bpfdetach, .bpf_change_type = _bpf_change_type, + .bpf_register_track_event = _bpf_register_track_event, + .bpf_deregister_track_event = _bpf_deregister_track_event, .bpf_mtap = _bpf_mtap, .bpf_mtap2 = _bpf_mtap2, Index: src/sys/net/bpf.h diff -u src/sys/net/bpf.h:1.76 src/sys/net/bpf.h:1.77 --- src/sys/net/bpf.h:1.76 Wed Jun 9 15:38:39 2021 +++ src/sys/net/bpf.h Wed Jun 9 15:44:15 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: bpf.h,v 1.76 2021/06/09 15:38:39 martin Exp $ */ +/* $NetBSD: bpf.h,v 1.77 2021/06/09 15:44:15 martin Exp $ */ /* * Copyright (c) 1990, 1991, 1993 @@ -450,6 +450,11 @@ struct bpf_ops { void (*bpf_mtap_softint_init)(struct ifnet *); void (*bpf_mtap_softint)(struct ifnet *, struct mbuf *); + + int (*bpf_register_track_event)(struct bpf_if **, + void (*)(struct bpf_if *, struct ifnet *, int, int)); + int (*bpf_deregister_track_event)(struct bpf_if **, + void (*)(struct bpf_if *, struct ifnet *, int, int)); }; extern struct bpf_ops *bpf_ops; @@ -545,6 +550,24 @@ bpf_mtap_softint(struct ifnet *_ifp, str bpf_ops->bpf_mtap_softint(_ifp, _m); } +static __inline int +bpf_register_track_event(struct bpf_if **_dp, + void (*_fun)(struct bpf_if *, struct ifnet *, int, int)) +{ + if (bpf_ops->bpf_register_track_event == NULL) + return ENXIO; + return bpf_ops->bpf_register_track_event(_dp, _fun); +} + +static __inline int +bpf_deregister_track_event(struct bpf_if **_dp, + void (*_fun)(struct bpf_if *, struct ifnet *, int, int)) +{ + if (bpf_ops->bpf_deregister_track_event == NULL) + return ENXIO; + return bpf_ops->bpf_deregister_track_event(_dp, _fun); +} + void bpf_setops(void); void bpf_ops_handover_enter(struct bpf_ops *); @@ -570,6 +593,12 @@ u_int bpf_filter(const struct bpf_insn * u_int bpf_filter_with_aux_data(const struct bpf_insn *, const u_char *, u_int, u_int, const struct bpf_aux_data *); +/* + * events to be tracked by bpf_register_track_event callbacks + */ +#define BPF_TRACK_EVENT_ATTACH 1 +#define BPF_TRACK_EVENT_DETACH 2 + __END_DECLS Index: src/sys/net/bpfdesc.h diff -u src/sys/net/bpfdesc.h:1.47 src/sys/net/bpfdesc.h:1.48 --- src/sys/net/bpfdesc.h:1.47 Thu Jun 11 13:36:20 2020 +++ src/sys/net/bpfdesc.h Wed Jun 9 15:44:15 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: bpfdesc.h,v 1.47 2020/06/11 13:36:20 roy Exp $ */ +/* $NetBSD: bpfdesc.h,v 1.48 2021/06/09 15:44:15 martin Exp $ */ /* * Copyright (c) 1990, 1991, 1993 @@ -162,6 +162,14 @@ struct bpf_d_ext { /* + * Record for each event tracker watching a tap point + */ +struct bpf_event_tracker { + SLIST_ENTRY(bpf_event_tracker) bet_entries; + void (*bet_notify)(struct bpf_if *, struct ifnet *, int, int); +}; + +/* * Descriptor associated with each attached hardware interface. */ struct bpf_if { @@ -179,6 +187,7 @@ struct bpf_if { struct pslist_entry bif_iflist_entry; struct pslist_head bif_dlist_head; struct psref_target bif_psref; + SLIST_HEAD(, bpf_event_tracker) bif_trackers; #endif };