FreeBSD/sys/netgraph/netflow/netflow.c
/*
 * Insert a record into defined slot.
 *
 * First we get for us a free flow entry, then fill in all
 * possible fields in it.
 *
 * TODO: consider dropping hash mutex while filling in datagram,
 * as this was done in previous version. Need to test & profile
 * to be sure.
 */
Insert a record into defined slot.
First we get for us a free flow entry, then fill in all
possible fields in it.

consider dropping hash mutex while filling in datagram,
as this was done in previous version. Need to test & profile
to be sure.
Insert a record into defined slot . First we get for us a free flow entry then fill in all possible fields in it . consider dropping hash mutex while filling in datagram as this was done in previous version . Need to test & profile to be sure .
static int
hash_insert(priv_p priv, struct flow_hash_entry *hsh, struct flow_rec *r,
	int plen, uint8_t flags, uint8_t tcp_flags)
{
	struct flow_entry *fle;
	struct sockaddr_in sin, sin_mask;
	struct sockaddr_dl rt_gateway;
	struct rt_addrinfo info;
	mtx_assert(&hsh->mtx, MA_OWNED);
	fle = uma_zalloc_arg(priv->zone, priv, M_NOWAIT);
	if (fle == NULL) {
		priv->nfinfo_alloc_failed++;
		return (ENOMEM);
	}
	fle->f.version = IPVERSION;
	bcopy(r, &fle->f.r, sizeof(struct flow_rec));
	fle->f.bytes = plen;
	fle->f.packets = 1;
	fle->f.tcp_flags = tcp_flags;
	fle->f.first = fle->f.last = time_uptime;
	if ((flags & NG_NETFLOW_CONF_NODSTLOOKUP) == 0) {
		bzero(&sin, sizeof(sin));
		sin.sin_len = sizeof(struct sockaddr_in);
		sin.sin_family = AF_INET;
		sin.sin_addr = fle->f.r.r_dst;
		rt_gateway.sdl_len = sizeof(rt_gateway);
		sin_mask.sin_len = sizeof(struct sockaddr_in);
		bzero(&info, sizeof(info));
		info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&rt_gateway;
		info.rti_info[RTAX_NETMASK] = (struct sockaddr *)&sin_mask;
		if (rib_lookup_info(r->fib, (struct sockaddr *)&sin, NHR_REF, 0,
		    &info) == 0) {
			fle->f.fle_o_ifx = info.rti_ifp->if_index;
			if (info.rti_flags & RTF_GATEWAY &&
			    rt_gateway.sdl_family == AF_INET)
				fle->f.next_hop =
				    ((struct sockaddr_in *)&rt_gateway)->sin_addr;
			if (info.rti_addrs & RTA_NETMASK)
				fle->f.dst_mask = bitcount32(sin_mask.sin_addr.s_addr);
			else if (info.rti_flags & RTF_HOST)
				fle->f.dst_mask = 32;
			rib_free_info(&info);
		}
	}
	if ((flags & NG_NETFLOW_CONF_NOSRCLOOKUP) == 0) {
		bzero(&sin, sizeof(sin));
		sin.sin_len = sizeof(struct sockaddr_in);
		sin.sin_family = AF_INET;
		sin.sin_addr = fle->f.r.r_src;
		sin_mask.sin_len = sizeof(struct sockaddr_in);
		bzero(&info, sizeof(info));
		info.rti_info[RTAX_NETMASK] = (struct sockaddr *)&sin_mask;
		if (rib_lookup_info(r->fib, (struct sockaddr *)&sin, 0, 0,
		    &info) == 0) {
			if (info.rti_addrs & RTA_NETMASK)
				fle->f.src_mask =
				    bitcount32(sin_mask.sin_addr.s_addr);
			else if (info.rti_flags & RTF_HOST)
				fle->f.src_mask = 32;
		}
	}
	TAILQ_INSERT_TAIL(&hsh->head, fle, fle_hash);
	return (0);
}
static int hash_insert ( priv_p priv , struct flow_hash_entry * hsh , struct flow_rec * r , int plen , uint8_t flags , uint8_t tcp_flags ) { struct flow_entry * fle ; struct sockaddr_in sin , sin_mask ; struct sockaddr_dl rt_gateway ; struct rt_addrinfo info ; mtx_assert ( & hsh -> mtx , MA_OWNED ) ; fle = uma_zalloc_arg ( priv -> zone , priv , M_NOWAIT ) ; if ( fle == NULL ) { priv -> nfinfo_alloc_failed ++ ; return ( ENOMEM ) ; } fle -> f . version = IPVERSION ; bcopy ( r , & fle -> f . r , sizeof ( struct flow_rec ) ) ; fle -> f . bytes = plen ; fle -> f . packets = 1 ; fle -> f . tcp_flags = tcp_flags ; fle -> f . first = fle -> f . last = time_uptime ; if ( ( flags & NG_NETFLOW_CONF_NODSTLOOKUP ) == 0 ) { bzero ( & sin , sizeof ( sin ) ) ; sin . sin_len = sizeof ( struct sockaddr_in ) ; sin . sin_family = AF_INET ; sin . sin_addr = fle -> f . r . r_dst ; rt_gateway . sdl_len = sizeof ( rt_gateway ) ; sin_mask . sin_len = sizeof ( struct sockaddr_in ) ; bzero ( & info , sizeof ( info ) ) ; info . rti_info [ RTAX_GATEWAY ] = ( struct sockaddr * ) & rt_gateway ; info . rti_info [ RTAX_NETMASK ] = ( struct sockaddr * ) & sin_mask ; if ( rib_lookup_info ( r -> fib , ( struct sockaddr * ) & sin , NHR_REF , 0 , & info ) == 0 ) { fle -> f . fle_o_ifx = info . rti_ifp -> if_index ; if ( info . rti_flags & RTF_GATEWAY && rt_gateway . sdl_family == AF_INET ) fle -> f . next_hop = ( ( struct sockaddr_in * ) & rt_gateway ) -> sin_addr ; if ( info . rti_addrs & RTA_NETMASK ) fle -> f . dst_mask = bitcount32 ( sin_mask . sin_addr . s_addr ) ; else if ( info . rti_flags & RTF_HOST ) fle -> f . dst_mask = 32 ; rib_free_info ( & info ) ; } } if ( ( flags & NG_NETFLOW_CONF_NOSRCLOOKUP ) == 0 ) { bzero ( & sin , sizeof ( sin ) ) ; sin . sin_len = sizeof ( struct sockaddr_in ) ; sin . sin_family = AF_INET ; sin . sin_addr = fle -> f . r . r_src ; sin_mask . sin_len = sizeof ( struct sockaddr_in ) ; bzero ( & info , sizeof ( info ) ) ; info . rti_info [ RTAX_NETMASK ] = ( struct sockaddr * ) & sin_mask ; if ( rib_lookup_info ( r -> fib , ( struct sockaddr * ) & sin , 0 , 0 , & info ) == 0 ) { if ( info . rti_addrs & RTA_NETMASK ) fle -> f . src_mask = bitcount32 ( sin_mask . sin_addr . s_addr ) ; else if ( info . rti_flags & RTF_HOST ) fle -> f . src_mask = 32 ; } } TAILQ_INSERT_TAIL ( & hsh -> head , fle , fle_hash ) ; return ( 0 ) ; }
Insert a record into defined slot.
Insert a record into defined slot .
/*
	 * Now fle is totally ours. It is detached from all lists,
	 * we can safely edit it.
	 */ /*
	 * First we do route table lookup on destination address. So we can
	 * fill in out_ifx, dst_mask, nexthop, and dst_as in future releases.
	 */ /* Give up. We can't determine mask :( */ /* Do route lookup on source address, to fill in src_mask. */ /* Give up. We can't determine mask :( */ /* Push new flow at the and of hash. */