svn commit: r186973 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb netgraph/netflow

Alexander Motin mav at FreeBSD.org
Fri Jan 9 12:55:27 PST 2009


Author: mav
Date: Fri Jan  9 20:55:26 2009
New Revision: 186973
URL: http://svn.freebsd.org/changeset/base/186973

Log:
  MFC rev. 183693
  
  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

Modified:
  stable/7/sys/   (props changed)
  stable/7/sys/contrib/pf/   (props changed)
  stable/7/sys/dev/ath/ath_hal/   (props changed)
  stable/7/sys/dev/cxgb/   (props changed)
  stable/7/sys/netgraph/netflow/netflow.c
  stable/7/sys/netgraph/netflow/ng_netflow.c
  stable/7/sys/netgraph/netflow/ng_netflow.h

Modified: stable/7/sys/netgraph/netflow/netflow.c
==============================================================================
--- stable/7/sys/netgraph/netflow/netflow.c	Fri Jan  9 20:43:06 2009	(r186972)
+++ stable/7/sys/netgraph/netflow/netflow.c	Fri Jan  9 20:55:26 2009	(r186973)
@@ -395,8 +395,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;
@@ -427,12 +426,7 @@ ng_netflow_flow_add(priv_p priv, struct 
 	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

Modified: stable/7/sys/netgraph/netflow/ng_netflow.c
==============================================================================
--- stable/7/sys/netgraph/netflow/ng_netflow.c	Fri Jan  9 20:43:06 2009	(r186972)
+++ stable/7/sys/netgraph/netflow/ng_netflow.c	Fri Jan  9 20:55:26 2009	(r186973)
@@ -106,6 +106,14 @@ static const struct ng_parse_type ng_net
 	&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_netflo
 	&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 i
 
 			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 
 	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 
 		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 
 
 #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:

Modified: stable/7/sys/netgraph/netflow/ng_netflow.h
==============================================================================
--- stable/7/sys/netgraph/netflow/ng_netflow.h	Fri Jan  9 20:43:06 2009	(r186972)
+++ stable/7/sys/netgraph/netflow/ng_netflow.h	Fri Jan  9 20:55:26 2009	(r186973)
@@ -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 */


More information about the svn-src-all mailing list