Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/net Add a bpf_register_track_event() function (and dereg...



details:   https://anonhg.NetBSD.org/src/rev/3ec5d0dc8e15
branches:  trunk
changeset: 379583:3ec5d0dc8e15
user:      martin <martin%NetBSD.org@localhost>
date:      Wed Jun 09 15:44:15 2021 +0000

description:
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.

diffstat:

 sys/net/bpf.c     |  87 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 sys/net/bpf.h     |  31 ++++++++++++++++++-
 sys/net/bpfdesc.h |  11 ++++++-
 3 files changed, 124 insertions(+), 5 deletions(-)

diffs (253 lines):

diff -r cd6e5c8046b1 -r 3ec5d0dc8e15 sys/net/bpf.c
--- a/sys/net/bpf.c     Wed Jun 09 15:38:39 2021 +0000
+++ b/sys/net/bpf.c     Wed Jun 09 15:44:15 2021 +0000
@@ -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 @@ static void
        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 @@ static void
        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 @@ static void
                        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,
diff -r cd6e5c8046b1 -r 3ec5d0dc8e15 sys/net/bpf.h
--- a/sys/net/bpf.h     Wed Jun 09 15:38:39 2021 +0000
+++ b/sys/net/bpf.h     Wed Jun 09 15:44:15 2021 +0000
@@ -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
 
diff -r cd6e5c8046b1 -r 3ec5d0dc8e15 sys/net/bpfdesc.h
--- a/sys/net/bpfdesc.h Wed Jun 09 15:38:39 2021 +0000
+++ b/sys/net/bpfdesc.h Wed Jun 09 15:44:15 2021 +0000
@@ -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
 };
 



Home | Main Index | Thread Index | Old Index