tech-net archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: Adding a bpf peers_present function and "peers added/gone" callback
On Tue, May 25, 2021 at 07:03:02PM +0200, Martin Husemann wrote:
> Hey folks,
>
> some drivers (i.e. ieee 802.11 ones) offer bpf tap points that require
> quite a bit of work just for the bpf tap and are in a hot network path.
As probably was to be expected, this design did not survive the first
implementation :-)
I learned hat we already have a quite effective expression for "any peer
present on this tap point" - our code makes sure the struct bpf_if* is NULL
if not.
Still I prefer the more explicit version and would like to provide an inline
function to test for that.
Since most of the time the bpf_if* is NULL, the interface to the new event
register/deregister function needed tiny changes - it now passes the address
of the pointer (in bpf terms: the driver pointer, where at attach time the
bpf_d pointer is stored).
The patch below works for me. (Of course the debug changes/printfs
will go away before commit.)
Any comments?
Martin
Index: bpfdesc.h
===================================================================
RCS file: /cvsroot/src/sys/net/bpfdesc.h,v
retrieving revision 1.47
diff -u -p -r1.47 bpfdesc.h
--- bpfdesc.h 11 Jun 2020 13:36:20 -0000 1.47
+++ bpfdesc.h 1 Jun 2021 13:22:59 -0000
@@ -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
};
Index: bpf.h
===================================================================
RCS file: /cvsroot/src/sys/net/bpf.h,v
retrieving revision 1.75
diff -u -p -r1.75 bpf.h
--- bpf.h 11 Jun 2020 13:36:20 -0000 1.75
+++ bpf.h 1 Jun 2021 13:22:59 -0000
@@ -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;
@@ -501,6 +506,16 @@ bpf_change_type(struct ifnet *_ifp, u_in
bpf_ops->bpf_change_type(_ifp, _dlt, _hdrlen);
}
+static __inline bool
+bpf_peers_present(struct bpf_if *dp)
+{
+ /*
+ * Our code makes sure the driver visible point is NULL
+ * whenever there is no listener on this tap.
+ */
+ return dp != NULL;
+}
+
static __inline void
bpf_detach(struct ifnet *_ifp)
{
@@ -535,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 *);
@@ -560,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: bpf.c
===================================================================
RCS file: /cvsroot/src/sys/net/bpf.c,v
retrieving revision 1.239
diff -u -p -r1.239 bpf.c
--- bpf.c 18 Dec 2020 01:31:49 -0000 1.239
+++ bpf.c 1 Jun 2021 13:22:59 -0000
@@ -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);
@@ -2132,8 +2146,8 @@ _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);
+#if 1
+ printf("bpf: %s attached with dlt %x\n", ifp->if_xname, dlt);
#endif
}
@@ -2171,6 +2185,10 @@ _bpfdetach(struct ifnet *ifp)
int s;
mutex_enter(&bpf_mtx);
+#if 1
+ printf("bpf: %s detached\n", ifp->if_xname);
+#endif
+
/* Nuke the vnodes for any open instances */
again_d:
BPF_DLIST_WRITER_FOREACH(d) {
@@ -2196,6 +2214,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 +2549,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,
Home |
Main Index |
Thread Index |
Old Index