Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F152674011
D52541.id162603.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D52541.id162603.diff
View Options
diff --git a/sys/netgraph/ng_device.c b/sys/netgraph/ng_device.c
--- a/sys/netgraph/ng_device.c
+++ b/sys/netgraph/ng_device.c
@@ -3,6 +3,7 @@
*
* Copyright (c) 2002 Mark Santcroos <marks@ripe.net>
* Copyright (c) 2004-2005 Gleb Smirnoff <glebius@FreeBSD.org>
+ * Copyright (c) 2025 Quentin Thebault <quentin.thebault@defenso.fr>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -50,6 +51,7 @@
#include <sys/poll.h>
#include <sys/proc.h>
#include <sys/queue.h>
+#include <sys/selinfo.h>
#include <sys/socket.h>
#include <sys/syslog.h>
#include <sys/uio.h>
@@ -117,6 +119,8 @@
struct ng_node *node;
struct ng_hook *hook;
struct cdev *ngddev;
+ struct selinfo rsel;
+ struct selinfo wsel;
struct mtx ngd_mtx;
int unit;
int ether_align;
@@ -138,6 +142,24 @@
static d_write_t ngdwrite;
static d_ioctl_t ngdioctl;
static d_poll_t ngdpoll;
+static d_kqfilter_t ngdkqfilter;
+
+static int ngd_kqread_event(struct knote *, long);
+static int ngd_kqwrite_event(struct knote *, long);
+static void ngd_kqread_detach(struct knote *);
+static void ngd_kqwrite_detach(struct knote *);
+
+static const struct filterops ngd_read_filterops = {
+ .f_isfd = 1,
+ .f_detach = ngd_kqread_detach,
+ .f_event = ngd_kqread_event
+};
+
+static const struct filterops ngd_write_filterops = {
+ .f_isfd = 1,
+ .f_detach = ngd_kqwrite_detach,
+ .f_event = ngd_kqwrite_event
+};
static struct cdevsw ngd_cdevsw = {
.d_version = D_VERSION,
@@ -146,6 +168,7 @@
.d_read = ngdread,
.d_write = ngdwrite,
.d_ioctl = ngdioctl,
+ .d_kqfilter = ngdkqfilter,
.d_poll = ngdpoll,
.d_name = NG_DEVICE_DEVNAME,
};
@@ -198,6 +221,9 @@
mtx_init(&priv->readq.ifq_mtx, "ng_device queue", NULL, MTX_DEF);
IFQ_SET_MAXLEN(&priv->readq, ifqmaxlen);
+ knlist_init_mtx(&priv->rsel.si_note, &priv->ngd_mtx);
+ knlist_init_mtx(&priv->wsel.si_note, &priv->ngd_mtx);
+
/* Link everything together */
NG_NODE_SET_PRIVATE(node, priv);
priv->node = node;
@@ -209,6 +235,8 @@
mtx_destroy(&priv->ngd_mtx);
mtx_destroy(&priv->readq.ifq_mtx);
free_unr(ngd_unit, priv->unit);
+ knlist_destroy(&priv->rsel.si_note);
+ knlist_destroy(&priv->wsel.si_note);
free(priv, M_NETGRAPH);
return (EINVAL);
}
@@ -319,6 +347,8 @@
priv->flags &= ~NGDF_RWAIT;
wakeup(priv);
}
+ selwakeup(&priv->rsel);
+ KNOTE_LOCKED(&priv->rsel.si_note, 0);
mtx_unlock(&priv->ngd_mtx);
return (0);
@@ -337,6 +367,11 @@
destroy_dev(priv->ngddev);
mtx_destroy(&priv->ngd_mtx);
+ knlist_destroy(&priv->rsel.si_note);
+ knlist_destroy(&priv->wsel.si_note);
+ seldrain(&priv->rsel);
+ seldrain(&priv->wsel);
+
IF_DRAIN(&priv->readq);
mtx_destroy(&(priv)->readq.ifq_mtx);
@@ -487,17 +522,21 @@
/* get an mbuf */
do {
+ mtx_lock(&priv->ngd_mtx);
IF_DEQUEUE(&priv->readq, m);
if (m == NULL) {
- if (flag & O_NONBLOCK)
+ if (flag & O_NONBLOCK) {
+ mtx_unlock(&priv->ngd_mtx);
return (EWOULDBLOCK);
- mtx_lock(&priv->ngd_mtx);
+ }
priv->flags |= NGDF_RWAIT;
- if ((error = msleep(priv, &priv->ngd_mtx,
- PDROP | PCATCH | PZERO,
- "ngdread", 0)) != 0)
+ if ((error = mtx_sleep(priv, &priv->ngd_mtx,
+ PCATCH, "ngdread", 0)) != 0) {
+ mtx_unlock(&priv->ngd_mtx);
return (error);
+ }
}
+ mtx_unlock(&priv->ngd_mtx);
} while (m == NULL);
while (m && uio->uio_resid > 0 && error == 0) {
@@ -538,9 +577,12 @@
if (m == NULL)
return (ENOBUFS);
+ // Setting VNET is required if connecting to a ng_bridge.
+ CURVNET_SET(priv->node->nd_vnet);
NET_EPOCH_ENTER(et);
NG_SEND_DATA_ONLY(error, priv->hook, m);
NET_EPOCH_EXIT(et);
+ CURVNET_RESTORE();
return (error);
}
@@ -561,3 +603,66 @@
return (revents);
}
+
+static void
+ngd_kqread_detach(struct knote *kn)
+{
+ priv_p priv = (priv_p)kn->kn_hook;
+
+ knlist_remove(&priv->rsel.si_note, kn, 0);
+}
+
+static int
+ngd_kqread_event(struct knote *kn, long hint)
+{
+ priv_p priv = (priv_p)kn->kn_hook;
+ struct mbuf *m;
+
+ IFQ_LOCK(&priv->readq);
+ if (IFQ_IS_EMPTY(&priv->readq)) {
+ kn->kn_data = 0;
+ } else {
+ IF_POLL(&priv->readq, m);
+ kn->kn_data = m->m_len;
+ }
+ IFQ_UNLOCK(&priv->readq);
+
+ return (kn->kn_data > 0);
+}
+
+static void
+ngd_kqwrite_detach(struct knote *kn)
+{
+ priv_p priv = (priv_p)kn->kn_hook;
+
+ knlist_remove(&priv->wsel.si_note, kn, 0);
+}
+
+static int
+ngd_kqwrite_event(struct knote *kn, long hint)
+{
+ kn->kn_data = IP_MAXPACKET;
+
+ return (1);
+}
+
+static int
+ngdkqfilter(struct cdev *dev, struct knote *kn)
+{
+ priv_p priv = (priv_p)dev->si_drv1;
+
+ switch (kn->kn_filter) {
+ case EVFILT_READ:
+ kn->kn_fop = &ngd_read_filterops;
+ kn->kn_hook = priv;
+ knlist_add(&priv->rsel.si_note, kn, 0);
+ return (0);
+ case EVFILT_WRITE:
+ kn->kn_fop = &ngd_write_filterops;
+ kn->kn_hook = priv;
+ knlist_add(&priv->wsel.si_note, kn, 0);
+ return (0);
+ default:
+ return (EINVAL);
+ }
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Apr 17, 11:02 AM (8 h, 25 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31655887
Default Alt Text
D52541.id162603.diff (4 KB)
Attached To
Mode
D52541: ng_device: add kqueue support
Attached
Detach File
Event Timeline
Log In to Comment