diff options
author | glebius <glebius@FreeBSD.org> | 2004-10-18 20:13:57 +0000 |
---|---|---|
committer | glebius <glebius@FreeBSD.org> | 2004-10-18 20:13:57 +0000 |
commit | 3c69856ec59055937844e49a3b20699d15b2bdfc (patch) | |
tree | 8c0ce186ab50c929b13a350edcdc8adfa4becefd /sys/netgraph | |
parent | 7b853afb002723c73c5121562d0e6da52a480cc5 (diff) | |
download | FreeBSD-src-3c69856ec59055937844e49a3b20699d15b2bdfc.zip FreeBSD-src-3c69856ec59055937844e49a3b20699d15b2bdfc.tar.gz |
Major overhaul.
List of functional changes:
- Make a single device per single node with a single hook.
This gives us parrallelizm, which can't be achieved on a single
node with many devices/hooks. This also gives us flexibility - we
can play with a particular device node, not affecting others.
- Remove read queue as it is. Use struct ifqueue instead. This change
removes a lot of extra memcpy()ing, m_devget()ting and m_copymem()ming.
In ng_device_receivedata() we enqueue an mbuf and wake readers.
In ngdread() we take one mbuf from qeueue and uiomove() it to
userspace. If no mbuf is present we optionally block. [1]
- In ngdwrite() we create an mbuf from uio using m_uiotombuf().
This is faster then uiomove() into buffer, and then m_copydata(),
and this is much better than huge m_pullup().
- Perform locking of device
- Perform locking of connection list.
- Clear out _rcvmsg method, since it does nothing good yet.
- Implement NGM_DEVICE_GET_DEVNAME message.
- #if 0 ioctl method, while nothing is done here yet.
- Return immediately from ngdwrite() if uio_resid == 0.
List of tidyness changes:
- Introduce device2priv(), to remove cut'n'paste.
- Use MALLOC/FREE, instead of malloc/free.
- Use unit2minor().
- Use UID_ROOT/GID_WHEEL instead of 0/0.
- Define NGD_DEVICE_DEVNAME, use it.
- Use more nice macros for debugging. [2]
- Return Exxx, not -1.
style(9) changes:
- No "#endif" after short block.
- Break long lines.
- Remove extra spaces, add needed spaces.
[1] Obtained from: if_tun.c
[2] Obtained from: ng_pppoe.c
Reviewed by: marks
Approved by: julian (mentor)
MFC after: 1 month
Diffstat (limited to 'sys/netgraph')
-rw-r--r-- | sys/netgraph/ng_device.c | 629 | ||||
-rw-r--r-- | sys/netgraph/ng_device.h | 11 |
2 files changed, 280 insertions, 360 deletions
diff --git a/sys/netgraph/ng_device.c b/sys/netgraph/ng_device.c index 7dcaea3..c209fd1 100644 --- a/sys/netgraph/ng_device.c +++ b/sys/netgraph/ng_device.c @@ -23,13 +23,19 @@ * * Netgraph "device" node * - * This node presents a /dev/ngd%d device that interfaces to an other + * This node presents a /dev/ngd%d device that interfaces to an other * netgraph node. * * $FreeBSD$ * */ +#if 0 +#define AAA printf("ng_device: %s\n", __func__ ); +#else +#define AAA +#endif + #include <sys/param.h> #include <sys/conf.h> #include <sys/ioccom.h> @@ -38,407 +44,328 @@ #include <sys/mbuf.h> #include <sys/poll.h> #include <sys/queue.h> +#include <sys/socket.h> #include <sys/systm.h> #include <sys/uio.h> +#include <sys/vnode.h> + +#include <net/if.h> +#include <net/if_var.h> +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> #include <netgraph/ng_message.h> #include <netgraph/netgraph.h> #include <netgraph/ng_device.h> -/* turn this on for verbose messages */ -#define NGD_DEBUG - #define ERROUT(x) do { error = (x); goto done; } while (0) /* Netgraph methods */ -static ng_constructor_t ng_device_cons; +static ng_constructor_t ng_device_constructor; static ng_rcvmsg_t ng_device_rcvmsg; +static ng_shutdown_t ng_device_shutdown; static ng_newhook_t ng_device_newhook; -static ng_connect_t ng_device_connect; static ng_rcvdata_t ng_device_rcvdata; static ng_disconnect_t ng_device_disconnect; -static int ng_device_mod_event(module_t mod, int event, void *data); - -static int ng_device_init(void); -static int get_free_unit(void); /* Netgraph type */ -static struct ng_type typestruct = { +static struct ng_type ngd_typestruct = { .version = NG_ABI_VERSION, .name = NG_DEVICE_NODE_TYPE, - .mod_event = ng_device_mod_event, - .constructor = ng_device_cons, - .rcvmsg = ng_device_rcvmsg, + .constructor = ng_device_constructor, + .rcvmsg = ng_device_rcvmsg, + .shutdown = ng_device_shutdown, .newhook = ng_device_newhook, - .connect = ng_device_connect, .rcvdata = ng_device_rcvdata, .disconnect = ng_device_disconnect, }; -NETGRAPH_INIT(device, &typestruct); - -/* per hook data */ -struct ngd_connection { - SLIST_ENTRY(ngd_connection) links; - - struct cdev *ngddev; - struct ng_hook *active_hook; - char *readq; - int loc; - int unit; +NETGRAPH_INIT(device, &ngd_typestruct); + +/* per node data */ +struct ngd_private { + struct ifqueue readq; + SLIST_ENTRY(ngd_private) links; + struct ng_node *node; + struct ng_hook *hook; + struct cdev *ngddev; + struct mtx ngd_mtx; + int unit; + uint16_t flags; +#define NGDF_OPEN 0x0001 +#define NGDF_RWAIT 0x0002 }; +typedef struct ngd_private *priv_p; -/* global data */ -struct ngd_softc { - SLIST_HEAD(, ngd_connection) head; - - node_p node; - char nodename[NG_NODESIZ]; -} ngd_softc; - -/* the per connection receiving queue maximum */ -#define NGD_QUEUE_SIZE (1024*10) +/* List of all active nodes and mutex to protect it */ +static SLIST_HEAD(, ngd_private) ngd_nodes = SLIST_HEAD_INITIALIZER(ngd_nodes); +static struct mtx ng_device_mtx; +MTX_SYSINIT(ng_device, &ng_device_mtx, "ng_device", MTX_DEF); /* Maximum number of NGD devices */ -#define MAX_NGD 25 /* should be more than enough for now */ +#define MAX_NGD 25 /* should be more than enough for now */ static d_close_t ngdclose; static d_open_t ngdopen; static d_read_t ngdread; static d_write_t ngdwrite; +#if 0 static d_ioctl_t ngdioctl; +#endif static d_poll_t ngdpoll; static struct cdevsw ngd_cdevsw = { .d_version = D_VERSION, - .d_flags = D_NEEDGIANT, .d_open = ngdopen, .d_close = ngdclose, .d_read = ngdread, .d_write = ngdwrite, +#if 0 .d_ioctl = ngdioctl, +#endif .d_poll = ngdpoll, - .d_name = "ngd", + .d_name = NG_DEVICE_DEVNAME, }; -/* - * this holds all the stuff that should be done at load time +/* Helper functions */ +static int get_free_unit(void); + +/****************************************************************************** + * Netgraph methods + ******************************************************************************/ + +/* + * create new node */ static int -ng_device_mod_event(module_t mod, int event, void *data) +ng_device_constructor(node_p node) { - int error = 0; + priv_p priv; -#ifdef NGD_DEBUG - printf("%s()\n",__func__); -#endif /* NGD_DEBUG */ +AAA - switch (event) { - case MOD_LOAD: + MALLOC(priv, priv_p, sizeof(*priv), M_NETGRAPH, M_NOWAIT | M_ZERO); + if (priv == NULL) + return (ENOMEM); - ng_device_init(); - break; + mtx_init(&priv->ngd_mtx, "ng_device", NULL, MTX_DEF); + mtx_lock(&priv->ngd_mtx); - case MOD_UNLOAD: - /* XXX do we need to do something specific ? */ - /* ng_device_breakdown */ - break; - - default: - error = EOPNOTSUPP; - break; - } + mtx_lock(&ng_device_mtx); - return(error); -} + priv->unit = get_free_unit(); + if(priv->unit < 0) { + printf("%s: No free unit found by get_free_unit(), " + "increase MAX_NGD\n",__func__); + mtx_unlock(&ng_device_mtx); + mtx_destroy(&priv->ngd_mtx); + FREE(priv, M_NETGRAPH); + return(EINVAL); + } + priv->ngddev = make_dev(&ngd_cdevsw, unit2minor(priv->unit), UID_ROOT, + GID_WHEEL, 0600, NG_DEVICE_DEVNAME "%d", priv->unit); + if(priv->ngddev == NULL) { + printf("%s(): make_dev() failed\n",__func__); + mtx_unlock(&ng_device_mtx); + mtx_destroy(&priv->ngd_mtx); + FREE(priv, M_NETGRAPH); + return(EINVAL); + } -static int -ng_device_init() -{ - struct ngd_softc *sc = &ngd_softc; - -#ifdef NGD_DEBUG - printf("%s()\n",__func__); -#endif /* NGD_DEBUG */ - - SLIST_INIT(&sc->head); - - if (ng_make_node_common(&typestruct, &sc->node) != 0) { - printf("%s(): ng_make_node_common failed\n",__func__); - return(ENXIO); - } - sprintf(sc->nodename, "%s", NG_DEVICE_NODE_TYPE); - if (ng_name_node(sc->node, sc->nodename)) { - NG_NODE_UNREF(sc->node); /* make it go away again */ - printf("%s(): ng_name_node failed\n",__func__); - return(ENXIO); - } - NG_NODE_SET_PRIVATE(sc->node, sc); + SLIST_INSERT_HEAD(&ngd_nodes, priv, links); - return(0); -} + mtx_unlock(&ng_device_mtx); -/* - * don't allow to be created, only the device can do that - */ -static int -ng_device_cons(node_p node) -{ + mtx_init(&priv->readq.ifq_mtx, "ng_device queue", NULL, MTX_DEF); + IFQ_SET_MAXLEN(&priv->readq, ifqmaxlen); -#ifdef NGD_DEBUG - printf("%s()\n",__func__); -#endif /* NGD_DEBUG */ + /* Link everything together */ + NG_NODE_SET_PRIVATE(node, priv); + priv->node = node; + priv->ngddev->si_drv1 = priv; - return(EINVAL); + mtx_unlock(&priv->ngd_mtx); + + return(0); } /* - * Receive control message. We just bounce it back as a reply. + * Process control message. */ + static int ng_device_rcvmsg(node_p node, item_p item, hook_p lasthook) { - struct ngd_softc *sc = &ngd_softc; + const priv_p priv = NG_NODE_PRIVATE(node); struct ng_mesg *msg; + struct ng_mesg *resp = NULL; int error = 0; - struct ngd_connection * connection = NULL; - struct ngd_connection *tmp = NULL; -#ifdef NGD_DEBUG - printf("%s()\n",__func__); -#endif /* NGD_DEBUG */ + NGI_GET_MSG(item, msg); - NGI_GET_MSG(item, msg); + if (msg->header.typecookie == NGM_DEVICE_COOKIE) { + switch (msg->header.cmd) { + case NGM_DEVICE_GET_DEVNAME: + /* XXX: Fix when NGD_MAX us bigger */ + NG_MKRESPONSE(resp, msg, + strlen(NG_DEVICE_DEVNAME) + 3, M_NOWAIT); - SLIST_FOREACH(tmp,&sc->head,links) { - if(tmp->active_hook == lasthook) { - connection = tmp; - } - } - if(connection == NULL) { - printf("%s(): connection is still NULL, no hook found\n",__func__); - return(-1); - } + if (resp == NULL) + ERROUT(ENOMEM); - return(error); -} - -static int -get_free_unit() -{ - struct ngd_connection *tmp = NULL; - struct ngd_softc *sc = &ngd_softc; - int n = 0; - int unit = -1; - -#ifdef NGD_DEBUG - printf("%s()\n",__func__); -#endif /* NGD_DEBUG */ - - /* When there is no list yet, the first device unit is always 0. */ - if SLIST_EMPTY(&sc->head) { - unit = 0; - return(unit); - } - - /* Just do a brute force loop to find the first free unit that is - * smaller than MAX_NGD. - * Set MAX_NGD to a large value, doesn't impact performance. - */ - for(n = 0;n<MAX_NGD && unit == -1;n++) { - SLIST_FOREACH(tmp,&sc->head,links) { + strlcpy((char *)resp->data, priv->ngddev->si_name, + strlen(priv->ngddev->si_name) + 1); + break; - if(tmp->unit == n) { - unit = -1; - break; - } - unit = n; + default: + error = EINVAL; + break; } - } + } else + error = EINVAL; - return(unit); +done: + NG_RESPOND_MSG(error, node, item, resp); + NG_FREE_MSG(msg); + return (error); } /* - * incoming hook + * Accept incoming hook. We support only one hook per node. */ static int ng_device_newhook(node_p node, hook_p hook, const char *name) { - struct ngd_softc *sc = &ngd_softc; - struct ngd_connection * new_connection = NULL; - -#ifdef NGD_DEBUG - printf("%s()\n",__func__); -#endif - - new_connection = malloc(sizeof(struct ngd_connection), M_DEVBUF, M_NOWAIT); - if(new_connection == NULL) { - printf("%s(): ERROR: new_connection == NULL\n",__func__); - return(ENOMEM); - } - - new_connection->unit = get_free_unit(); - if(new_connection->unit<0) { - printf("%s: No free unit found by get_free_unit(), " - "increase MAX_NGD\n",__func__); - free(new_connection, M_DEVBUF); - return(EINVAL); - } - new_connection->ngddev = make_dev(&ngd_cdevsw, new_connection->unit, 0, 0,0600,"ngd%d",new_connection->unit); - if(new_connection->ngddev == NULL) { - printf("%s(): make_dev failed\n",__func__); - free(new_connection, M_DEVBUF); - return(EINVAL); - } - - new_connection->readq = malloc(sizeof(char)*NGD_QUEUE_SIZE, M_DEVBUF, M_NOWAIT | M_ZERO); - if(new_connection->readq == NULL) { - printf("%s(): readq malloc failed\n",__func__); - free(new_connection, M_DEVBUF); - return(ENOMEM); - } - - /* point to begin of buffer */ - new_connection->loc = 0; - new_connection->active_hook = hook; - - SLIST_INSERT_HEAD(&sc->head, new_connection, links); + priv_p priv = NG_NODE_PRIVATE(node); - return(0); -} +AAA -/* - * we gave ok to a new hook - * now connect - */ -static int -ng_device_connect(hook_p hook) -{ + /* We have only one hook per node */ + if (priv->hook != NULL) + return (EISCONN); -#ifdef NGD_DEBUG - printf("%s()\n",__func__); -#endif /* NGD_DEBUG */ + priv->hook = hook; return(0); } - /* - * Receive data from hook + * Receive data from hook, write it to device. */ static int ng_device_rcvdata(hook_p hook, item_p item) { + priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); struct mbuf *m; - struct ngd_softc *sc = &ngd_softc; - struct ngd_connection * connection = NULL; - struct ngd_connection * tmp; - char *buffer; - int error = 0; -#ifdef NGD_DEBUG - printf("%s()\n",__func__); -#endif +AAA NGI_GET_M(item, m); NG_FREE_ITEM(item); - SLIST_FOREACH(tmp,&sc->head,links) - if(tmp->active_hook == hook) - connection = tmp; - - if (connection == NULL) { - printf("%s(): connection is still NULL, no hook found\n",__func__); - ERROUT(ENOTCONN); - } - - if ((m = m_pullup(m,m->m_len)) == NULL) { - printf("%s(): ERROR: m_pullup failed\n",__func__); - ERROUT(ENOMEM); + IF_LOCK(&priv->readq); + if (_IF_QFULL(&priv->readq)) { + _IF_DROP(&priv->readq); + IF_UNLOCK(&priv->readq); + NG_FREE_M(m); + return (ENOBUFS); } - buffer = mtod(m,char *); - - if ((connection->loc + m->m_len) < NGD_QUEUE_SIZE) { - memcpy(connection->readq + connection->loc, buffer, m->m_len); - connection->loc += m->m_len; - } else { - printf("%s(): queue full, first read out a bit\n",__func__); - ERROUT(ENOSPC); + _IF_ENQUEUE(&priv->readq, m); + IF_UNLOCK(&priv->readq); + mtx_lock(&priv->ngd_mtx); + if (priv->flags & NGDF_RWAIT) { + priv->flags &= ~NGDF_RWAIT; + wakeup(priv); } + mtx_unlock(&priv->ngd_mtx); -done: - NG_FREE_M(m); - return(error); + return(0); } /* - * Removal of the last link destroys the node + * Removal of the hook destroys the node. */ static int ng_device_disconnect(hook_p hook) { - struct ngd_softc *sc = &ngd_softc; - struct ngd_connection * connection = NULL; - struct ngd_connection * tmp; + priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); -#ifdef NGD_DEBUG - printf("%s()\n",__func__); -#endif +AAA - SLIST_FOREACH(tmp,&sc->head,links) - if(tmp->active_hook == hook) - connection = tmp; + destroy_dev(priv->ngddev); + mtx_destroy(&priv->ngd_mtx); - if(connection == NULL) { - printf("%s(): connection is still NULL, no hook found\n",__func__); - return(ENOTCONN); - } + mtx_lock(&ng_device_mtx); + SLIST_REMOVE(&ngd_nodes, priv, ngd_private, links); + mtx_unlock(&ng_device_mtx); - free(connection->readq, M_DEVBUF); + IF_DRAIN(&priv->readq); + mtx_destroy(&(priv)->readq.ifq_mtx); - destroy_dev(connection->ngddev); + FREE(priv, M_NETGRAPH); - SLIST_REMOVE(&sc->head,connection,ngd_connection,links); - free(connection, M_DEVBUF); + ng_rmnode_self(NG_HOOK_NODE(hook)); return(0); } + /* - * the device is opened + * Node shutdown. Everything is already done in disconnect method. + */ +static int +ng_device_shutdown(node_p node) +{ + NG_NODE_UNREF(node); + return (0); +} + +/****************************************************************************** + * Device methods + ******************************************************************************/ + +/* + * the device is opened */ static int ngdopen(struct cdev *dev, int flag, int mode, struct thread *td) { + priv_p priv = (priv_p )dev->si_drv1; -#ifdef NGD_DEBUG - printf("%s()\n",__func__); -#endif /* NGD_DEBUG */ +AAA + mtx_lock(&priv->ngd_mtx); + priv->flags |= NGDF_OPEN; + mtx_unlock(&priv->ngd_mtx); return(0); } /* - * the device is closed + * the device is closed */ static int ngdclose(struct cdev *dev, int flag, int mode, struct thread *td) { + priv_p priv = (priv_p )dev->si_drv1; -#ifdef NGD_DEBUG - printf("%s()\n",__func__); -#endif +AAA + mtx_lock(&priv->ngd_mtx); + priv->flags &= ~NGDF_OPEN; + mtx_unlock(&priv->ngd_mtx); return(0); } - +#if 0 /* + * The ioctl is transformed into netgraph control message. + * We do not process them, yet. + */ /* * process ioctl * * they are translated into netgraph messages and passed on - * + * */ static int ngdioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td) @@ -448,11 +375,9 @@ ngdioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td struct ngd_connection * tmp; int error = 0; struct ng_mesg *msg; - struct ngd_param_s * datap; + struct ngd_param_s * datap; -#ifdef NGD_DEBUG - printf("%s()\n",__func__); -#endif /* NGD_DEBUG */ +AAA SLIST_FOREACH(tmp,&sc->head,links) { if(tmp->ngddev == dev) { @@ -464,8 +389,7 @@ ngdioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td return(-1); } - /* NG_MKMESSAGE(msg, cookie, cmdid, len, how) */ - NG_MKMESSAGE(msg, NGM_DEVICE_COOKIE, cmd, sizeof(struct ngd_param_s), + NG_MKMESSAGE(msg, NGM_DEVICE_COOKIE, cmd, sizeof(struct ngd_param_s), M_NOWAIT); if (msg == NULL) { printf("%s(): msg == NULL\n",__func__); @@ -474,7 +398,7 @@ ngdioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td /* pass the ioctl data into the ->data area */ datap = (struct ngd_param_s *)msg->data; - datap->p = addr; + datap->p = addr; NG_SEND_MSG_HOOK(error, sc->node, msg, connection->active_hook, 0); if(error) @@ -484,108 +408,76 @@ nomsg: return(0); } - +#endif /* if 0 */ /* * This function is called when a read(2) is done to our device. - * We pass the data available in kernelspace on into userland using - * uiomove. + * We process one mbuf from queue. */ static int ngdread(struct cdev *dev, struct uio *uio, int flag) { - int ret = 0, amnt; - char buffer[uio->uio_resid+1]; - struct ngd_softc *sc = &ngd_softc; - struct ngd_connection * connection = NULL; - struct ngd_connection * tmp; - -#ifdef NGD_DEBUG - printf("%s()\n",__func__); -#endif /* NGD_DEBUG */ - - SLIST_FOREACH(tmp,&sc->head,links) { - if(tmp->ngddev == dev) { - connection = tmp; + priv_p priv = (priv_p )dev->si_drv1; + struct mbuf *m; + int len, error = 0; + +AAA + + /* get an mbuf */ + do { + IF_DEQUEUE(&priv->readq, m); + if (m == NULL) { + if (flag & IO_NDELAY) + return (EWOULDBLOCK); + mtx_lock(&priv->ngd_mtx); + priv->flags |= NGDF_RWAIT; + mtx_unlock(&priv->ngd_mtx); + if ((error = tsleep(priv, PCATCH | (PZERO + 1), + "ngdread", 0)) != 0) + return (error); } - } - if(connection == NULL) { - printf("%s(): connection is still NULL, no dev found\n",__func__); - return(-1); - } - - while ( ( uio->uio_resid > 0 ) && ( connection->loc > 0 ) ) { - amnt = MIN(uio->uio_resid,connection->loc); - - memcpy(buffer,connection->readq, amnt); - memcpy(connection->readq, connection->readq+amnt, - connection->loc-amnt); - connection->loc -= amnt; - - ret = uiomove((caddr_t)buffer, amnt, uio); - if(ret != 0) - goto error; + } while (m == NULL); + while (m && uio->uio_resid > 0 && error == 0) { + len = MIN(uio->uio_resid, m->m_len); + if (len != 0) + error = uiomove(mtod(m, void *), len, uio); + m = m_free(m); } - return(0); -error: - printf("%s(): uiomove returns error %d\n",__func__,ret); - /* do error cleanup here */ - return(ret); + if (m) + m_freem(m); + + return (error); } -/* +/* * This function is called when our device is written to. - * We read the data from userland into our local buffer and pass it on - * into the remote hook. + * We read the data from userland into mbuf chain and pass it to the remote hook. * */ static int ngdwrite(struct cdev *dev, struct uio *uio, int flag) { - int ret; - int error = 0; + priv_p priv = (priv_p )dev->si_drv1; struct mbuf *m; - char buffer[uio->uio_resid]; - int len = uio->uio_resid; - struct ngd_softc *sc =& ngd_softc; - struct ngd_connection * connection = NULL; - struct ngd_connection * tmp; - -#ifdef NGD_DEBUG - printf("%s()\n",__func__); -#endif /* NGD_DEBUG */ - - SLIST_FOREACH(tmp,&sc->head,links) { - if(tmp->ngddev == dev) { - connection = tmp; - } - } - - if(connection == NULL) { - printf("%s(): connection is still NULL, no dev found\n",__func__); - return(-1); - } + int error = 0; - if (len > 0) { - if ((ret = uiomove((caddr_t)buffer, len, uio)) != 0) - goto error; - } else - printf("%s(): len <= 0 : is this supposed to happen?!\n",__func__); +AAA - m = m_devget(buffer,len,0,NULL,NULL); + if (uio->uio_resid == 0) + return (0); - NG_SEND_DATA_ONLY(error,connection->active_hook,m); + if (uio->uio_resid < 0 || uio->uio_resid > IP_MAXPACKET) + return (EIO); - return(0); + if ((m = m_uiotombuf(uio, M_DONTWAIT, 0)) == NULL) + return (ENOBUFS); -error: - /* do error cleanup here */ - printf("%s(): uiomove returned err: %d\n",__func__,ret); + NG_SEND_DATA_ONLY(error, priv->hook, m); - return(ret); + return (error); } /* @@ -595,28 +487,49 @@ error: static int ngdpoll(struct cdev *dev, int events, struct thread *td) { + priv_p priv = (priv_p )dev->si_drv1; int revents = 0; - struct ngd_softc *sc = &ngd_softc; - struct ngd_connection * connection = NULL; - struct ngd_connection * tmp; + if (events & (POLLIN | POLLRDNORM) && + !IFQ_IS_EMPTY(&priv->readq)) + revents |= events & (POLLIN | POLLRDNORM); + + return (revents); +} + +/****************************************************************************** + * Helper subroutines + ******************************************************************************/ + +static int +get_free_unit() +{ + struct ngd_private *priv = NULL; + int n = 0; + int unit = -1; + +AAA + + mtx_assert(&ng_device_mtx, MA_OWNED); - if (events & (POLLIN | POLLRDNORM)) { - /* get the connection we have to know the loc from */ - SLIST_FOREACH(tmp,&sc->head,links) { - if(tmp->ngddev == dev) { - connection = tmp; + /* When there is no list yet, the first device unit is always 0. */ + if SLIST_EMPTY(&ngd_nodes) + return(0); + + /* Just do a brute force loop to find the first free unit that is + * smaller than MAX_NGD. + * Set MAX_NGD to a large value, doesn't impact performance. + */ + for(n = 0; n<MAX_NGD && unit == -1; n++) { + SLIST_FOREACH(priv, &ngd_nodes, links) { + + if(priv->unit == n) { + unit = -1; + break; } + unit = n; } - if(connection == NULL) { - printf("%s(): ERROR: connection is still NULL," - "no dev found\n",__func__); - return(-1); - } - - if (connection->loc > 0) - revents |= events & (POLLIN | POLLRDNORM); } - return(revents); + return (unit); } diff --git a/sys/netgraph/ng_device.h b/sys/netgraph/ng_device.h index 5596134..9f33369 100644 --- a/sys/netgraph/ng_device.h +++ b/sys/netgraph/ng_device.h @@ -31,12 +31,19 @@ /* Node type name and magic cookie */ #define NG_DEVICE_NODE_TYPE "device" -#define NGM_DEVICE_COOKIE 1009920473 +#define NGM_DEVICE_COOKIE 1091129178 +#define NG_DEVICE_DEVNAME "ngd" +/* Netgraph control messages */ +enum { + NGM_DEVICE_GET_DEVNAME, +}; + +#if 0 /* passing ioctl params */ struct ngd_param_s { void * p; }; - +#endif #endif /* _NETGRAPH_NG_DEVICE_H_ */ |