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:
parent
948e77c67b
commit
9094c56bb6
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user