summaryrefslogtreecommitdiffstats
path: root/sys/netgraph/ng_async.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netgraph/ng_async.c')
-rw-r--r--sys/netgraph/ng_async.c113
1 files changed, 72 insertions, 41 deletions
diff --git a/sys/netgraph/ng_async.c b/sys/netgraph/ng_async.c
index cbc51bb..8f9e118 100644
--- a/sys/netgraph/ng_async.c
+++ b/sys/netgraph/ng_async.c
@@ -94,8 +94,8 @@ static ng_newhook_t nga_newhook;
static ng_disconnect_t nga_disconnect;
/* Helper stuff */
-static int nga_rcv_sync(const sc_p sc, struct mbuf *m, meta_p meta);
-static int nga_rcv_async(const sc_p sc, struct mbuf *m, meta_p meta);
+static int nga_rcv_sync(const sc_p sc, item_p item);
+static int nga_rcv_async(const sc_p sc, item_p item);
/* Parse type for struct ng_async_cfg */
static const struct ng_parse_struct_info
@@ -174,13 +174,10 @@ static const u_int16_t fcstab[];
* Initialize a new node
*/
static int
-nga_constructor(node_p *nodep)
+nga_constructor(node_p node)
{
sc_p sc;
- int error;
- if ((error = ng_make_node_common(&typestruct, nodep)))
- return (error);
MALLOC(sc, sc_p, sizeof(*sc), M_NETGRAPH, M_NOWAIT | M_ZERO);
if (sc == NULL)
return (ENOMEM);
@@ -200,8 +197,8 @@ fail:
FREE(sc, M_NETGRAPH);
return (ENOMEM);
}
- (*nodep)->private = sc;
- sc->node = *nodep;
+ node->private = sc;
+ sc->node = node;
return (0);
}
@@ -214,13 +211,30 @@ nga_newhook(node_p node, hook_p hook, const char *name)
const sc_p sc = node->private;
hook_p *hookp;
- if (!strcmp(name, NG_ASYNC_HOOK_ASYNC))
+ if (!strcmp(name, NG_ASYNC_HOOK_ASYNC)) {
+ /*
+ * We use a static buffer here so only one packet
+ * at a time can be allowed to travel in this direction.
+ * Force Writer semantics.
+ */
+ hook->flags |= HK_FORCE_WRITER;
+ hookp = &sc->async;
+ } else if (!strcmp(name, NG_ASYNC_HOOK_SYNC)) {
+ /*
+ * We use a static state here so only one packet
+ * at a time can be allowed to travel in this direction.
+ * Force Writer semantics.
+ * Since we set this for both directions
+ * we might as well set it for the whole node
+ * bit I haven;t done that (yet).
+ */
+ hook->flags |= HK_FORCE_WRITER;
hookp = &sc->async;
- else if (!strcmp(name, NG_ASYNC_HOOK_SYNC))
hookp = &sc->sync;
- else
+ } else {
return (EINVAL);
- if (*hookp)
+ }
+ if (*hookp) /* actually can't happen I think [JRE] */
return (EISCONN);
*hookp = hook;
return (0);
@@ -230,15 +244,17 @@ nga_newhook(node_p node, hook_p hook, const char *name)
* Receive incoming data
*/
static int
-nga_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
- struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
+nga_rcvdata(hook_p hook, item_p item)
{
const sc_p sc = hook->node->private;
+#ifdef ITEM_DEBUG
+ meta_p meta = NGI_META(item);
+#endif
if (hook == sc->sync)
- return (nga_rcv_sync(sc, m, meta));
+ return (nga_rcv_sync(sc, item));
if (hook == sc->async)
- return (nga_rcv_async(sc, m, meta));
+ return (nga_rcv_async(sc, item));
panic(__FUNCTION__);
}
@@ -246,13 +262,15 @@ nga_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
* Receive incoming control message
*/
static int
-nga_rcvmsg(node_p node, struct ng_mesg *msg,
- const char *rtn, struct ng_mesg **rptr, hook_p lasthook)
+nga_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
const sc_p sc = (sc_p) node->private;
struct ng_mesg *resp = NULL;
int error = 0;
+ struct ng_mesg *msg;
+
+ NGI_GET_MSG(item, msg);
switch (msg->header.typecookie) {
case NGM_ASYNC_COOKIE:
switch (msg->header.cmd) {
@@ -317,13 +335,9 @@ nga_rcvmsg(node_p node, struct ng_mesg *msg,
default:
ERROUT(EINVAL);
}
- if (rptr)
- *rptr = resp;
- else if (resp)
- FREE(resp, M_NETGRAPH);
-
done:
- FREE(msg, M_NETGRAPH);
+ NG_RESPOND_MSG(error, node, item, resp);
+ NG_FREE_MSG(msg);
return (error);
}
@@ -335,8 +349,6 @@ nga_shutdown(node_p node)
{
const sc_p sc = node->private;
- ng_cutlinks(node);
- ng_unname(node);
FREE(sc->abuf, M_NETGRAPH);
FREE(sc->sbuf, M_NETGRAPH);
bzero(sc, sizeof(*sc));
@@ -366,8 +378,9 @@ nga_disconnect(hook_p hook)
*hookp = NULL;
bzero(&sc->stats, sizeof(sc->stats));
sc->lasttime = 0;
- if (hook->node->numhooks == 0)
- ng_rmnode(hook->node);
+ if ((hook->node->numhooks == 0)
+ && ((hook->node->flags & NG_INVALID) == 0))
+ ng_rmnode_self(hook->node);
return (0);
}
@@ -395,21 +408,26 @@ nga_async_add(const sc_p sc, u_int16_t *fcs, u_int32_t accm, int *len, u_char x)
* Receive incoming synchronous data.
*/
static int
-nga_rcv_sync(const sc_p sc, struct mbuf *m, meta_p meta)
+nga_rcv_sync(const sc_p sc, item_p item)
{
- struct ifnet *const rcvif = m->m_pkthdr.rcvif;
+ struct ifnet *rcvif;
int alen, error = 0;
struct timeval time;
u_int16_t fcs, fcs0;
u_int32_t accm;
+ struct mbuf *m;
+
#define ADD_BYTE(x) nga_async_add(sc, &fcs, accm, &alen, (x))
/* Check for bypass mode */
if (!sc->cfg.enabled) {
- NG_SEND_DATA(error, sc->async, m, meta);
+ NG_FWD_DATA(error, item, sc->async );
return (error);
}
+ NGI_GET_M(item, m);
+
+ rcvif = m->m_pkthdr.rcvif;
/* Get ACCM; special case LCP frames, which use full ACCM */
accm = sc->cfg.accm;
@@ -430,7 +448,8 @@ nga_rcv_sync(const sc_p sc, struct mbuf *m, meta_p meta)
/* Check for overflow */
if (m->m_pkthdr.len > sc->cfg.smru) {
sc->stats.syncOverflows++;
- NG_FREE_DATA(m, meta);
+ NG_FREE_M(m);
+ NG_FREE_ITEM(item);
return (EMSGSIZE);
}
@@ -470,10 +489,11 @@ nga_rcv_sync(const sc_p sc, struct mbuf *m, meta_p meta)
/* Put frame in an mbuf and ship it off */
if (!(m = m_devget(sc->abuf, alen, 0, rcvif, NULL))) {
- NG_FREE_META(meta);
+ NG_FREE_ITEM(item);
error = ENOBUFS;
- } else
- NG_SEND_DATA(error, sc->async, m, meta);
+ } else {
+ NG_FWD_NEW_DATA(error, item, sc->async, m);
+ }
return (error);
}
@@ -483,16 +503,18 @@ nga_rcv_sync(const sc_p sc, struct mbuf *m, meta_p meta)
* that are in our ACCM. Not sure if this is good or not.
*/
static int
-nga_rcv_async(const sc_p sc, struct mbuf * m, meta_p meta)
+nga_rcv_async(const sc_p sc, item_p item)
{
- struct ifnet *const rcvif = m->m_pkthdr.rcvif;
+ struct ifnet *rcvif;
int error;
+ struct mbuf *m;
if (!sc->cfg.enabled) {
- NG_SEND_DATA(error, sc->sync, m, meta);
+ NG_FWD_DATA(error, item, sc->sync);
return (error);
}
- NG_FREE_META(meta);
+ NGI_GET_M(item, m);
+ rcvif = m->m_pkthdr.rcvif;
while (m) {
struct mbuf *n;
@@ -531,8 +553,15 @@ nga_rcv_async(const sc_p sc, struct mbuf * m, meta_p meta)
/* OK, ship it out */
if ((n = m_devget(sc->sbuf + skip,
- sc->slen - skip, 0, rcvif, NULL)))
- NG_SEND_DATA(error, sc->sync, n, meta);
+ sc->slen - skip, 0, rcvif, NULL))) {
+ if (item) { /* sets NULL -> item */
+ NG_FWD_NEW_DATA(error, item,
+ sc->sync, n);
+ } else {
+ NG_SEND_DATA_ONLY(error,
+ sc->sync ,n);
+ }
+ }
sc->stats.asyncFrames++;
reset:
sc->amode = MODE_NORMAL;
@@ -569,6 +598,8 @@ reset:
MFREE(m, n);
m = n;
}
+ if (item)
+ NG_FREE_ITEM(item);
return (0);
}
OpenPOWER on IntegriCloud