Author: mav
Date: Wed Oct  8 10:37:07 2008
New Revision: 183693
URL: http://svn.freebsd.org/changeset/base/183693

Log:
  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:
  head/sys/netgraph/netflow/netflow.c
  head/sys/netgraph/netflow/ng_netflow.c
  head/sys/netgraph/netflow/ng_netflow.h

Modified: head/sys/netgraph/netflow/netflow.c
==============================================================================
--- head/sys/netgraph/netflow/netflow.c Wed Oct  8 08:08:03 2008        
(r183692)
+++ head/sys/netgraph/netflow/netflow.c Wed Oct  8 10:37:07 2008        
(r183693)
@@ -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 
        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: head/sys/netgraph/netflow/ng_netflow.c
==============================================================================
--- head/sys/netgraph/netflow/ng_netflow.c      Wed Oct  8 08:08:03 2008        
(r183692)
+++ head/sys/netgraph/netflow/ng_netflow.c      Wed Oct  8 10:37:07 2008        
(r183693)
@@ -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: head/sys/netgraph/netflow/ng_netflow.h
==============================================================================
--- head/sys/netgraph/netflow/ng_netflow.h      Wed Oct  8 08:08:03 2008        
(r183692)
+++ head/sys/netgraph/netflow/ng_netflow.h      Wed Oct  8 10:37:07 2008        
(r183693)
@@ -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 */
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to