Partial MFC rev. 1.23-1.24

- Avoid data copying. bpf_filter() is able to work directly on mbuf chain
 - Prepare hooks direct pointers on setup to avoid heavy ng_findhook() calls
during operarion.
Merge is 'Partial' due to lack of JITTER support on 6.x.
This commit is contained in:
mav 2008-02-24 13:21:13 +00:00
parent 948e77c67b
commit 9094c56bb6

View File

@ -80,8 +80,9 @@ MALLOC_DEFINE(M_NETGRAPH_BPF, "netgraph_bpf", "netgraph bpf node ");
/* Per hook private info */
struct ng_bpf_hookinfo {
node_p node;
hook_p hook;
hook_p match;
hook_p nomatch;
struct ng_bpf_hookprog *prog;
struct ng_bpf_hookstat stats;
};
@ -225,6 +226,35 @@ ng_bpf_constructor(node_p node)
return (0);
}
/*
* Callback functions to be used by NG_NODE_FOREACH_HOOK() macro.
*/
static int
ng_bpf_addrefs(hook_p hook, void* arg)
{
hinfo_p hip = NG_HOOK_PRIVATE(hook);
hook_p h = (hook_p)arg;
if (strcmp(hip->prog->ifMatch, NG_HOOK_NAME(h)) == 0)
hip->match = h;
if (strcmp(hip->prog->ifNotMatch, NG_HOOK_NAME(h)) == 0)
hip->nomatch = h;
return (1);
}
static int
ng_bpf_remrefs(hook_p hook, void* arg)
{
hinfo_p hip = NG_HOOK_PRIVATE(hook);
hook_p h = (hook_p)arg;
if (hip->match == h)
hip->match = NULL;
if (hip->nomatch == h)
hip->nomatch = NULL;
return (1);
}
/*
* Add a hook
*/
@ -232,6 +262,7 @@ static int
ng_bpf_newhook(node_p node, hook_p hook, const char *name)
{
hinfo_p hip;
hook_p tmp;
int error;
/* Create hook private structure */
@ -240,7 +271,9 @@ ng_bpf_newhook(node_p node, hook_p hook, const char *name)
return (ENOMEM);
hip->hook = hook;
NG_HOOK_SET_PRIVATE(hook, hip);
hip->node = node;
/* Add our reference into other hooks data. */
NG_NODE_FOREACH_HOOK(node, ng_bpf_addrefs, hook, tmp);
/* Attach the default BPF program */
if ((error = ng_bpf_setprog(hook, &ng_bpf_default_prog)) != 0) {
@ -250,8 +283,7 @@ ng_bpf_newhook(node_p node, hook_p hook, const char *name)
}
/* Set hook name */
strncpy(hip->prog->thisHook, name, sizeof(hip->prog->thisHook) - 1);
hip->prog->thisHook[sizeof(hip->prog->thisHook) - 1] = '\0';
strlcpy(hip->prog->thisHook, name, sizeof(hip->prog->thisHook));
return (0);
}
@ -373,8 +405,8 @@ ng_bpf_rcvdata(hook_p hook, item_p item)
{
const hinfo_p hip = NG_HOOK_PRIVATE(hook);
int totlen;
int needfree = 0, error = 0;
u_char *data;
int error = 0;
u_char *data = NULL;
hinfo_p dhip;
hook_p dest;
u_int len;
@ -388,35 +420,30 @@ ng_bpf_rcvdata(hook_p hook, item_p item)
hip->stats.recvFrames++;
hip->stats.recvOctets += totlen;
/* Need to put packet in contiguous memory for bpf */
if (m->m_next != NULL) {
if (totlen > MHLEN) {
MALLOC(data, u_char *, totlen, M_NETGRAPH_BPF, M_NOWAIT);
if (data == NULL) {
NG_FREE_ITEM(item);
return (ENOMEM);
}
needfree = 1;
m_copydata(m, 0, totlen, (caddr_t)data);
} else {
/* Don't call bpf_filter() with totlen == 0! */
if (totlen == 0) {
len = 0;
goto ready;
}
/* Try to put packet in contiguous memory for bpf */
if (m->m_next == NULL || totlen < MHLEN) {
if (m->m_next != NULL) {
NGI_M(item) = m = m_pullup(m, totlen);
if (m == NULL) {
NG_FREE_ITEM(item);
return (ENOBUFS);
}
data = mtod(m, u_char *);
}
} else
data = mtod(m, u_char *);
}
/* Run packet through filter */
if (totlen == 0)
len = 0; /* don't call bpf_filter() with totlen == 0! */
else
if (data)
len = bpf_filter(hip->prog->bpf_prog, data, totlen, totlen);
if (needfree)
FREE(data, M_NETGRAPH_BPF);
else
len = bpf_filter(hip->prog->bpf_prog, (u_char *)m, totlen, 0);
ready:
/* See if we got a match and find destination hook */
if (len > 0) {
@ -429,11 +456,11 @@ ng_bpf_rcvdata(hook_p hook, item_p item)
/* Assume this never changes m */
if (len < totlen) {
m_adj(m, -(totlen - len));
totlen -= len;
totlen = len;
}
dest = ng_findhook(hip->node, hip->prog->ifMatch);
dest = hip->match;
} else
dest = ng_findhook(hip->node, hip->prog->ifNotMatch);
dest = hip->nomatch;
if (dest == NULL) {
NG_FREE_ITEM(item);
return (0);
@ -463,16 +490,20 @@ ng_bpf_shutdown(node_p node)
static int
ng_bpf_disconnect(hook_p hook)
{
const node_p node = NG_HOOK_NODE(hook);
const hinfo_p hip = NG_HOOK_PRIVATE(hook);
hook_p tmp;
KASSERT(hip != NULL, ("%s: null info", __func__));
/* Remove our reference from other hooks data. */
NG_NODE_FOREACH_HOOK(node, ng_bpf_remrefs, hook, tmp);
FREE(hip->prog, M_NETGRAPH_BPF);
bzero(hip, sizeof(*hip));
FREE(hip, M_NETGRAPH_BPF);
NG_HOOK_SET_PRIVATE(hook, NULL); /* for good measure */
if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0)
&& (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) {
ng_rmnode_self(NG_HOOK_NODE(hook));
if ((NG_NODE_NUMHOOKS(node) == 0) &&
(NG_NODE_IS_VALID(node))) {
ng_rmnode_self(node);
}
return (0);
}
@ -506,6 +537,9 @@ ng_bpf_setprog(hook_p hook, const struct ng_bpf_hookprog *hp0)
if (hip->prog != NULL)
FREE(hip->prog, M_NETGRAPH_BPF);
hip->prog = hp;
/* Prepare direct references on target hooks. */
hip->match = ng_findhook(NG_HOOK_NODE(hook), hip->prog->ifMatch);
hip->nomatch = ng_findhook(NG_HOOK_NODE(hook), hip->prog->ifNotMatch);
return (0);
}