Allow the BPF to be select for write. This is needed for boost:asio

which otherwise fails to handle BPFs.
Reviewed by:	ae
Differential Revision:	https://reviews.freebsd.org/D31967
This commit is contained in:
Hartmut Brandt 2021-10-10 17:03:51 +02:00
parent f656df586a
commit ded77e0237
2 changed files with 39 additions and 5 deletions

View File

@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd September 30, 2021
.Dd October 12, 2021
.Dt KQUEUE 2
.Os
.Sh NAME
@ -378,7 +378,7 @@ The filter will set
.Dv EV_EOF
when the reader disconnects, and for the fifo case, this will be cleared
when a new reader connects.
Note that this filter is not supported for vnodes or BPF devices.
Note that this filter is not supported for vnodes.
.Pp
For sockets, the low water mark and socket error handling is
identical to the
@ -389,6 +389,11 @@ For eventfds,
.Va data
will contain the maximum value that can be added to the counter
without blocking.
.Pp
For BPF devices, the filter always indicates that it is possible to
write and
.Va data
will contain the MTU size of the underlying interface.
.It Dv EVFILT_EMPTY
Takes a descriptor as the identifier, and returns whenever
there is no remaining data in the write buffer.

View File

@ -213,6 +213,7 @@ static int bpf_getdltlist(struct bpf_d *, struct bpf_dltlist *);
static int bpf_setdlt(struct bpf_d *, u_int);
static void filt_bpfdetach(struct knote *);
static int filt_bpfread(struct knote *, long);
static int filt_bpfwrite(struct knote *, long);
static void bpf_drvinit(void *);
static int bpf_stats_sysctl(SYSCTL_HANDLER_ARGS);
@ -257,6 +258,12 @@ static struct filterops bpfread_filtops = {
.f_event = filt_bpfread,
};
static struct filterops bpfwrite_filtops = {
.f_isfd = 1,
.f_detach = filt_bpfdetach,
.f_event = filt_bpfwrite,
};
/*
* LOCKING MODEL USED BY BPF
*
@ -2158,16 +2165,27 @@ bpfkqfilter(struct cdev *dev, struct knote *kn)
{
struct bpf_d *d;
if (devfs_get_cdevpriv((void **)&d) != 0 ||
kn->kn_filter != EVFILT_READ)
if (devfs_get_cdevpriv((void **)&d) != 0)
return (1);
switch (kn->kn_filter) {
case EVFILT_READ:
kn->kn_fop = &bpfread_filtops;
break;
case EVFILT_WRITE:
kn->kn_fop = &bpfwrite_filtops;
break;
default:
return (1);
}
/*
* Refresh PID associated with this descriptor.
*/
BPFD_LOCK(d);
BPF_PID_REFRESH_CUR(d);
kn->kn_fop = &bpfread_filtops;
kn->kn_hook = d;
knlist_add(&d->bd_sel.si_note, kn, 1);
BPFD_UNLOCK(d);
@ -2207,6 +2225,17 @@ filt_bpfread(struct knote *kn, long hint)
return (ready);
}
static int
filt_bpfwrite(struct knote *kn, long hint)
{
struct bpf_d *d = (struct bpf_d *)kn->kn_hook;
BPFD_LOCK_ASSERT(d);
kn->kn_data = d->bd_bif->bif_ifp->if_mtu;
return (1);
}
#define BPF_TSTAMP_NONE 0
#define BPF_TSTAMP_FAST 1
#define BPF_TSTAMP_NORMAL 2