summaryrefslogtreecommitdiffstats
path: root/sys/netgraph
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2008-10-08 10:37:07 +0000
committermav <mav@FreeBSD.org>2008-10-08 10:37:07 +0000
commitca86878f8ef29199f5f364805feee84e55568984 (patch)
tree51356cffcfdf3b2d0746d5d5dd684f8729c8e227 /sys/netgraph
parentdf4f3faa2850ffae295b4b18cf5caf3a9008ee4b (diff)
downloadFreeBSD-src-ca86878f8ef29199f5f364805feee84e55568984.zip
FreeBSD-src-ca86878f8ef29199f5f364805feee84e55568984.tar.gz
Add ability to generate egress netflow instead or in addition to ingress.
Use mbuf tagging for accounted packets to not account packets twice when both ingress and egress netflow enabled. To keep compatibility new "setconfig" message added to control new functionality. By default node works as before, doing only ingress accounting without using mbuf tags. Reviewed by: glebius
Diffstat (limited to 'sys/netgraph')
-rw-r--r--sys/netgraph/netflow/netflow.c10
-rw-r--r--sys/netgraph/netflow/ng_netflow.c100
-rw-r--r--sys/netgraph/netflow/ng_netflow.h26
3 files changed, 116 insertions, 20 deletions
diff --git a/sys/netgraph/netflow/netflow.c b/sys/netgraph/netflow/netflow.c
index 51a87dd..29193ab 100644
--- a/sys/netgraph/netflow/netflow.c
+++ b/sys/netgraph/netflow/netflow.c
@@ -389,8 +389,7 @@ ng_netflow_cache_flush(priv_p priv)
/* Insert packet from into flow cache. */
int
-ng_netflow_flow_add(priv_p priv, struct ip *ip, iface_p iface,
- struct ifnet *ifp)
+ng_netflow_flow_add(priv_p priv, struct ip *ip, unsigned int src_if_index)
{
register struct flow_entry *fle, *fle1;
struct flow_hash_entry *hsh;
@@ -421,12 +420,7 @@ ng_netflow_flow_add(priv_p priv, struct ip *ip, iface_p iface,
r.r_ip_p = ip->ip_p;
r.r_tos = ip->ip_tos;
- /* Configured in_ifx overrides mbuf's */
- if (iface->info.ifinfo_index == 0) {
- if (ifp != NULL)
- r.r_i_ifx = ifp->if_index;
- } else
- r.r_i_ifx = iface->info.ifinfo_index;
+ r.r_i_ifx = src_if_index;
/*
* XXX NOTE: only first fragment of fragmented TCP, UDP and
diff --git a/sys/netgraph/netflow/ng_netflow.c b/sys/netgraph/netflow/ng_netflow.c
index c813e50..76fece8 100644
--- a/sys/netgraph/netflow/ng_netflow.c
+++ b/sys/netgraph/netflow/ng_netflow.c
@@ -106,6 +106,14 @@ static const struct ng_parse_type ng_netflow_settimeouts_type = {
&ng_netflow_settimeouts_type_fields
};
+/* Parse type for ng_netflow_setconfig */
+static const struct ng_parse_struct_field ng_netflow_setconfig_type_fields[]
+ = NG_NETFLOW_SETCONFIG_TYPE;
+static const struct ng_parse_type ng_netflow_setconfig_type = {
+ &ng_parse_struct_type,
+ &ng_netflow_setconfig_type_fields
+};
+
/* List of commands and how to convert arguments to/from ASCII */
static const struct ng_cmdlist ng_netflow_cmds[] = {
{
@@ -143,6 +151,13 @@ static const struct ng_cmdlist ng_netflow_cmds[] = {
&ng_netflow_settimeouts_type,
NULL
},
+ {
+ NGM_NETFLOW_COOKIE,
+ NGM_NETFLOW_SETCONFIG,
+ "setconfig",
+ &ng_netflow_setconfig_type,
+ NULL
+ },
{ 0 }
};
@@ -167,7 +182,7 @@ static int
ng_netflow_constructor(node_p node)
{
priv_p priv;
- int error = 0;
+ int error = 0, i;
/* Initialize private data */
MALLOC(priv, priv_p, sizeof(*priv), M_NETGRAPH, M_NOWAIT);
@@ -183,6 +198,10 @@ ng_netflow_constructor(node_p node)
priv->info.nfinfo_inact_t = INACTIVE_TIMEOUT;
priv->info.nfinfo_act_t = ACTIVE_TIMEOUT;
+ /* Set default config */
+ for (i = 0; i < NG_NETFLOW_MAXIFACES; i++)
+ priv->ifaces[i].info.conf = NG_NETFLOW_CONF_INGRESS;
+
/* Initialize callout handle */
callout_init(&priv->exp_callout, CALLOUT_MPSAFE);
@@ -399,6 +418,22 @@ ng_netflow_rcvmsg (node_p node, item_p item, hook_p lasthook)
break;
}
+ case NGM_NETFLOW_SETCONFIG:
+ {
+ struct ng_netflow_setconfig *set;
+
+ if (msg->header.arglen != sizeof(struct ng_netflow_settimeouts))
+ ERROUT(EINVAL);
+
+ set = (struct ng_netflow_setconfig *)msg->data;
+
+ if (set->iface >= NG_NETFLOW_MAXIFACES)
+ ERROUT(EINVAL);
+
+ priv->ifaces[set->iface].info.conf = set->conf;
+
+ break;
+ }
case NGM_NETFLOW_SHOW:
{
uint32_t *last;
@@ -445,10 +480,13 @@ ng_netflow_rcvdata (hook_p hook, item_p item)
const node_p node = NG_HOOK_NODE(hook);
const priv_p priv = NG_NODE_PRIVATE(node);
const iface_p iface = NG_HOOK_PRIVATE(hook);
+ hook_p out;
struct mbuf *m = NULL;
struct ip *ip;
+ struct m_tag *mtag;
int pullup_len = 0;
- int error = 0;
+ int error = 0, bypass = 0;
+ unsigned int src_if_index;
if (hook == priv->export) {
/*
@@ -459,16 +497,48 @@ ng_netflow_rcvdata (hook_p hook, item_p item)
ERROUT(EINVAL);
};
- if (hook == iface->out) {
- /*
- * Data arrived on out hook. Bypass it.
- */
- if (iface->hook == NULL)
+ if (hook == iface->hook) {
+ if ((iface->info.conf & NG_NETFLOW_CONF_INGRESS) == 0)
+ bypass = 1;
+ out = iface->out;
+ } else if (hook == iface->out) {
+ if ((iface->info.conf & NG_NETFLOW_CONF_EGRESS) == 0)
+ bypass = 1;
+ out = iface->hook;
+ } else
+ ERROUT(EINVAL);
+
+ if ((!bypass) &&
+ (iface->info.conf & (NG_NETFLOW_CONF_ONCE | NG_NETFLOW_CONF_THISONCE))) {
+ mtag = m_tag_locate(NGI_M(item), MTAG_NETFLOW,
+ MTAG_NETFLOW_CALLED, NULL);
+ while (mtag != NULL) {
+ if ((iface->info.conf & NG_NETFLOW_CONF_ONCE) ||
+ ((ng_ID_t *)(mtag + 1))[0] == NG_NODE_ID(node)) {
+ bypass = 1;
+ break;
+ }
+ mtag = m_tag_locate(NGI_M(item), MTAG_NETFLOW,
+ MTAG_NETFLOW_CALLED, mtag);
+ }
+ }
+
+ if (bypass) {
+ if (out == NULL)
ERROUT(ENOTCONN);
- NG_FWD_ITEM_HOOK(error, item, iface->hook);
+ NG_FWD_ITEM_HOOK(error, item, out);
return (error);
}
+
+ if (iface->info.conf & (NG_NETFLOW_CONF_ONCE | NG_NETFLOW_CONF_THISONCE)) {
+ mtag = m_tag_alloc(MTAG_NETFLOW, MTAG_NETFLOW_CALLED,
+ sizeof(ng_ID_t), M_NOWAIT);
+ if (mtag) {
+ ((ng_ID_t *)(mtag + 1))[0] = NG_NODE_ID(node);
+ m_tag_prepend(NGI_M(item), mtag);
+ }
+ }
NGI_GET_M(item, m);
@@ -592,12 +662,20 @@ ng_netflow_rcvdata (hook_p hook, item_p item)
#undef M_CHECK
- error = ng_netflow_flow_add(priv, ip, iface, m->m_pkthdr.rcvif);
+ /* Determine packet input interface. Prefer configured. */
+ src_if_index = 0;
+ if (hook == iface->out || iface->info.ifinfo_index == 0) {
+ if (m->m_pkthdr.rcvif != NULL)
+ src_if_index = m->m_pkthdr.rcvif->if_index;
+ } else
+ src_if_index = iface->info.ifinfo_index;
+
+ error = ng_netflow_flow_add(priv, ip, src_if_index);
bypass:
- if (iface->out != NULL) {
+ if (out != NULL) {
/* XXX: error gets overwritten here */
- NG_FWD_NEW_DATA(error, item, iface->out, m);
+ NG_FWD_NEW_DATA(error, item, out, m);
return (error);
}
done:
diff --git a/sys/netgraph/netflow/ng_netflow.h b/sys/netgraph/netflow/ng_netflow.h
index bd35cf0..a7f52f3 100644
--- a/sys/netgraph/netflow/ng_netflow.h
+++ b/sys/netgraph/netflow/ng_netflow.h
@@ -50,6 +50,7 @@ enum {
NGM_NETFLOW_SETDLT = 4, /* set data-link type */
NGM_NETFLOW_SETIFINDEX = 5, /* set interface index */
NGM_NETFLOW_SETTIMEOUTS = 6, /* set active/inactive flow timeouts */
+ NGM_NETFLOW_SETCONFIG = 7, /* set flow generation options */
};
/* This structure is returned by the NGM_NETFLOW_INFO message */
@@ -71,6 +72,7 @@ struct ng_netflow_ifinfo {
uint8_t ifinfo_dlt; /* Data Link Type, DLT_XXX */
#define MAXDLTNAMELEN 20
u_int16_t ifinfo_index; /* connected iface index */
+ uint32_t conf;
};
@@ -92,6 +94,17 @@ struct ng_netflow_settimeouts {
uint32_t active_timeout; /* flow active timeout */
};
+#define NG_NETFLOW_CONF_INGRESS 1
+#define NG_NETFLOW_CONF_EGRESS 2
+#define NG_NETFLOW_CONF_ONCE 4
+#define NG_NETFLOW_CONF_THISONCE 8
+
+/* This structure is passed to NGM_NETFLOW_SETCONFIG */
+struct ng_netflow_setconfig {
+ u_int16_t iface; /* which iface config change */
+ u_int32_t conf; /* new config */
+};
+
/* This is unique data, which identifies flow */
struct flow_rec {
struct in_addr r_src;
@@ -182,6 +195,7 @@ struct flow_entry {
{ "packets", &ng_parse_uint32_type }, \
{ "data link type", &ng_parse_uint8_type }, \
{ "index", &ng_parse_uint16_type }, \
+ { "conf", &ng_parse_uint32_type }, \
{ NULL } \
}
@@ -206,6 +220,13 @@ struct flow_entry {
{ NULL } \
}
+/* Parse the setifindex structure */
+#define NG_NETFLOW_SETCONFIG_TYPE { \
+ { "iface", &ng_parse_uint16_type }, \
+ { "conf", &ng_parse_uint32_type }, \
+ { NULL } \
+}
+
/* Private hook data */
struct ng_netflow_iface {
hook_p hook; /* NULL when disconnected */
@@ -263,12 +284,15 @@ struct flow_hash_entry {
#define ERROUT(x) { error = (x); goto done; }
+#define MTAG_NETFLOW 1221656444
+#define MTAG_NETFLOW_CALLED 0
+
/* Prototypes for netflow.c */
int ng_netflow_cache_init(priv_p);
void ng_netflow_cache_flush(priv_p);
void ng_netflow_copyinfo(priv_p, struct ng_netflow_info *);
timeout_t ng_netflow_expire;
-int ng_netflow_flow_add(priv_p, struct ip *, iface_p, struct ifnet *);
+int ng_netflow_flow_add(priv_p, struct ip *, unsigned int src_if_index);
int ng_netflow_flow_show(priv_p, uint32_t last, struct ng_mesg *);
#endif /* _KERNEL */
OpenPOWER on IntegriCloud