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
 };
 

Reply via email to