1*3b2bd0f6Slogwang /*-
2*3b2bd0f6Slogwang  * Copyright (c) 2010-2011 Alexander V. Chernikov <[email protected]>
3*3b2bd0f6Slogwang  * Copyright (c) 2004-2005 Gleb Smirnoff <[email protected]>
4*3b2bd0f6Slogwang  * Copyright (c) 2001-2003 Roman V. Palagin <[email protected]>
5*3b2bd0f6Slogwang  * All rights reserved.
6*3b2bd0f6Slogwang  *
7*3b2bd0f6Slogwang  * Redistribution and use in source and binary forms, with or without
8*3b2bd0f6Slogwang  * modification, are permitted provided that the following conditions
9*3b2bd0f6Slogwang  * are met:
10*3b2bd0f6Slogwang  * 1. Redistributions of source code must retain the above copyright
11*3b2bd0f6Slogwang  *    notice, this list of conditions and the following disclaimer.
12*3b2bd0f6Slogwang  * 2. Redistributions in binary form must reproduce the above copyright
13*3b2bd0f6Slogwang  *    notice, this list of conditions and the following disclaimer in the
14*3b2bd0f6Slogwang  *    documentation and/or other materials provided with the distribution.
15*3b2bd0f6Slogwang  *
16*3b2bd0f6Slogwang  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17*3b2bd0f6Slogwang  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*3b2bd0f6Slogwang  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*3b2bd0f6Slogwang  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20*3b2bd0f6Slogwang  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21*3b2bd0f6Slogwang  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22*3b2bd0f6Slogwang  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23*3b2bd0f6Slogwang  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24*3b2bd0f6Slogwang  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25*3b2bd0f6Slogwang  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26*3b2bd0f6Slogwang  * SUCH DAMAGE.
27*3b2bd0f6Slogwang  *
28*3b2bd0f6Slogwang  *	 $SourceForge: ng_netflow.h,v 1.26 2004/09/04 15:44:55 glebius Exp $
29*3b2bd0f6Slogwang  *	 $FreeBSD$
30*3b2bd0f6Slogwang  */
31*3b2bd0f6Slogwang 
32*3b2bd0f6Slogwang #ifndef	_NG_NETFLOW_H_
33*3b2bd0f6Slogwang #define	_NG_NETFLOW_H_
34*3b2bd0f6Slogwang 
35*3b2bd0f6Slogwang #define NG_NETFLOW_NODE_TYPE	"netflow"
36*3b2bd0f6Slogwang #define NGM_NETFLOW_COOKIE	1365756954
37*3b2bd0f6Slogwang #define NGM_NETFLOW_V9_COOKIE	1349865386
38*3b2bd0f6Slogwang 
39*3b2bd0f6Slogwang #define	NG_NETFLOW_MAXIFACES	USHRT_MAX
40*3b2bd0f6Slogwang 
41*3b2bd0f6Slogwang /* Hook names */
42*3b2bd0f6Slogwang 
43*3b2bd0f6Slogwang #define	NG_NETFLOW_HOOK_DATA	"iface"
44*3b2bd0f6Slogwang #define	NG_NETFLOW_HOOK_OUT	"out"
45*3b2bd0f6Slogwang #define NG_NETFLOW_HOOK_EXPORT	"export"
46*3b2bd0f6Slogwang #define NG_NETFLOW_HOOK_EXPORT9	"export9"
47*3b2bd0f6Slogwang 
48*3b2bd0f6Slogwang /* This define effectively disable (v5) netflow export hook! */
49*3b2bd0f6Slogwang /* #define COUNTERS_64 */
50*3b2bd0f6Slogwang 
51*3b2bd0f6Slogwang /* Netgraph commands understood by netflow node */
52*3b2bd0f6Slogwang enum {
53*3b2bd0f6Slogwang     NGM_NETFLOW_INFO = 1|NGM_READONLY|NGM_HASREPLY,	/* get node info */
54*3b2bd0f6Slogwang     NGM_NETFLOW_IFINFO = 2|NGM_READONLY|NGM_HASREPLY,	/* get iface info */
55*3b2bd0f6Slogwang     NGM_NETFLOW_SHOW = 3|NGM_READONLY|NGM_HASREPLY,	/* show ip cache flow */
56*3b2bd0f6Slogwang     NGM_NETFLOW_SETDLT		= 4,	/* set data-link type */
57*3b2bd0f6Slogwang     NGM_NETFLOW_SETIFINDEX	= 5, 	/* set interface index */
58*3b2bd0f6Slogwang     NGM_NETFLOW_SETTIMEOUTS	= 6, 	/* set active/inactive flow timeouts */
59*3b2bd0f6Slogwang     NGM_NETFLOW_SETCONFIG	= 7, 	/* set flow generation options */
60*3b2bd0f6Slogwang     NGM_NETFLOW_SETTEMPLATE	= 8, 	/* set v9 flow template periodic */
61*3b2bd0f6Slogwang     NGM_NETFLOW_SETMTU		= 9, 	/* set outgoing interface MTU */
62*3b2bd0f6Slogwang     NGM_NETFLOW_V9INFO = 10|NGM_READONLY|NGM_HASREPLY, 	/* get v9 info */
63*3b2bd0f6Slogwang };
64*3b2bd0f6Slogwang 
65*3b2bd0f6Slogwang /* This structure is returned by the NGM_NETFLOW_INFO message */
66*3b2bd0f6Slogwang struct ng_netflow_info {
67*3b2bd0f6Slogwang 	uint64_t	nfinfo_bytes;		/* accounted IPv4 bytes */
68*3b2bd0f6Slogwang 	uint64_t	nfinfo_packets;		/* accounted IPv4 packets */
69*3b2bd0f6Slogwang 	uint64_t	nfinfo_bytes6;		/* accounted IPv6 bytes */
70*3b2bd0f6Slogwang 	uint64_t	nfinfo_packets6;	/* accounted IPv6 packets */
71*3b2bd0f6Slogwang 	uint64_t	nfinfo_sbytes;		/* skipped IPv4 bytes */
72*3b2bd0f6Slogwang 	uint64_t	nfinfo_spackets;	/* skipped IPv4 packets */
73*3b2bd0f6Slogwang 	uint64_t	nfinfo_sbytes6;		/* skipped IPv6 bytes */
74*3b2bd0f6Slogwang 	uint64_t	nfinfo_spackets6;	/* skipped IPv6 packets */
75*3b2bd0f6Slogwang 	uint64_t	nfinfo_act_exp;		/* active expiries */
76*3b2bd0f6Slogwang 	uint64_t	nfinfo_inact_exp;	/* inactive expiries */
77*3b2bd0f6Slogwang 	uint32_t	nfinfo_used;		/* used cache records */
78*3b2bd0f6Slogwang 	uint32_t	nfinfo_used6;		/* used IPv6 cache records */
79*3b2bd0f6Slogwang 	uint32_t	nfinfo_alloc_failed;	/* failed allocations */
80*3b2bd0f6Slogwang 	uint32_t	nfinfo_export_failed;	/* failed exports */
81*3b2bd0f6Slogwang 	uint32_t	nfinfo_export9_failed;	/* failed exports */
82*3b2bd0f6Slogwang 	uint32_t	nfinfo_realloc_mbuf;	/* reallocated mbufs */
83*3b2bd0f6Slogwang 	uint32_t	nfinfo_alloc_fibs;	/* fibs allocated */
84*3b2bd0f6Slogwang 	uint32_t	nfinfo_inact_t;		/* flow inactive timeout */
85*3b2bd0f6Slogwang 	uint32_t	nfinfo_act_t;		/* flow active timeout */
86*3b2bd0f6Slogwang };
87*3b2bd0f6Slogwang 
88*3b2bd0f6Slogwang /* Parse the info structure */
89*3b2bd0f6Slogwang #define	NG_NETFLOW_INFO_TYPE {					\
90*3b2bd0f6Slogwang 	{ "IPv4 bytes",			&ng_parse_uint64_type },\
91*3b2bd0f6Slogwang 	{ "IPv4 packets",		&ng_parse_uint64_type },\
92*3b2bd0f6Slogwang 	{ "IPv6 bytes",			&ng_parse_uint64_type },\
93*3b2bd0f6Slogwang 	{ "IPv6 packets",		&ng_parse_uint64_type },\
94*3b2bd0f6Slogwang 	{ "IPv4 skipped bytes",		&ng_parse_uint64_type },\
95*3b2bd0f6Slogwang 	{ "IPv4 skipped packets",	&ng_parse_uint64_type },\
96*3b2bd0f6Slogwang 	{ "IPv6 skipped bytes",		&ng_parse_uint64_type },\
97*3b2bd0f6Slogwang 	{ "IPv6 skipped packets",	&ng_parse_uint64_type },\
98*3b2bd0f6Slogwang 	{ "Active expiries",		&ng_parse_uint64_type },\
99*3b2bd0f6Slogwang 	{ "Inactive expiries",		&ng_parse_uint64_type },\
100*3b2bd0f6Slogwang 	{ "IPv4 records used",		&ng_parse_uint32_type },\
101*3b2bd0f6Slogwang 	{ "IPv6 records used",		&ng_parse_uint32_type },\
102*3b2bd0f6Slogwang 	{ "Failed allocations",		&ng_parse_uint32_type },\
103*3b2bd0f6Slogwang 	{ "V5 failed exports",		&ng_parse_uint32_type },\
104*3b2bd0f6Slogwang 	{ "V9 failed exports",		&ng_parse_uint32_type },\
105*3b2bd0f6Slogwang 	{ "mbuf reallocations",		&ng_parse_uint32_type },\
106*3b2bd0f6Slogwang 	{ "fibs allocated",		&ng_parse_uint32_type },\
107*3b2bd0f6Slogwang 	{ "Inactive timeout",		&ng_parse_uint32_type },\
108*3b2bd0f6Slogwang 	{ "Active timeout",		&ng_parse_uint32_type },\
109*3b2bd0f6Slogwang 	{ NULL }						\
110*3b2bd0f6Slogwang }
111*3b2bd0f6Slogwang 
112*3b2bd0f6Slogwang 
113*3b2bd0f6Slogwang /* This structure is returned by the NGM_NETFLOW_IFINFO message */
114*3b2bd0f6Slogwang struct ng_netflow_ifinfo {
115*3b2bd0f6Slogwang 	uint32_t	ifinfo_packets;	/* number of packets for this iface */
116*3b2bd0f6Slogwang 	uint8_t		ifinfo_dlt;	/* Data Link Type, DLT_XXX */
117*3b2bd0f6Slogwang #define	MAXDLTNAMELEN	20
118*3b2bd0f6Slogwang 	uint16_t	ifinfo_index;	/* connected iface index */
119*3b2bd0f6Slogwang 	uint32_t	conf;
120*3b2bd0f6Slogwang };
121*3b2bd0f6Slogwang 
122*3b2bd0f6Slogwang 
123*3b2bd0f6Slogwang /* This structure is passed to NGM_NETFLOW_SETDLT message */
124*3b2bd0f6Slogwang struct ng_netflow_setdlt {
125*3b2bd0f6Slogwang 	uint16_t iface;		/* which iface dlt change */
126*3b2bd0f6Slogwang 	uint8_t  dlt;		/* DLT_XXX from bpf.h */
127*3b2bd0f6Slogwang };
128*3b2bd0f6Slogwang 
129*3b2bd0f6Slogwang /* This structure is passed to NGM_NETFLOW_SETIFINDEX */
130*3b2bd0f6Slogwang struct ng_netflow_setifindex {
131*3b2bd0f6Slogwang 	uint16_t iface;		/* which iface index change */
132*3b2bd0f6Slogwang 	uint16_t index;		/* new index */
133*3b2bd0f6Slogwang };
134*3b2bd0f6Slogwang 
135*3b2bd0f6Slogwang /* This structure is passed to NGM_NETFLOW_SETTIMEOUTS */
136*3b2bd0f6Slogwang struct ng_netflow_settimeouts {
137*3b2bd0f6Slogwang 	uint32_t	inactive_timeout;	/* flow inactive timeout */
138*3b2bd0f6Slogwang 	uint32_t	active_timeout;		/* flow active timeout */
139*3b2bd0f6Slogwang };
140*3b2bd0f6Slogwang 
141*3b2bd0f6Slogwang #define NG_NETFLOW_CONF_INGRESS		0x01	/* Account on ingress */
142*3b2bd0f6Slogwang #define NG_NETFLOW_CONF_EGRESS		0x02	/* Account on egress */
143*3b2bd0f6Slogwang #define NG_NETFLOW_CONF_ONCE		0x04	/* Add tag to account only once */
144*3b2bd0f6Slogwang #define NG_NETFLOW_CONF_THISONCE	0x08	/* Account once in current node */
145*3b2bd0f6Slogwang #define NG_NETFLOW_CONF_NOSRCLOOKUP	0x10	/* No radix lookup on src */
146*3b2bd0f6Slogwang #define NG_NETFLOW_CONF_NODSTLOOKUP	0x20	/* No radix lookup on dst */
147*3b2bd0f6Slogwang 
148*3b2bd0f6Slogwang #define NG_NETFLOW_IS_FRAG		0x01
149*3b2bd0f6Slogwang #define NG_NETFLOW_FLOW_FLAGS		(NG_NETFLOW_CONF_NOSRCLOOKUP|\
150*3b2bd0f6Slogwang 					NG_NETFLOW_CONF_NODSTLOOKUP)
151*3b2bd0f6Slogwang 
152*3b2bd0f6Slogwang /* This structure is passed to NGM_NETFLOW_SETCONFIG */
153*3b2bd0f6Slogwang struct ng_netflow_setconfig {
154*3b2bd0f6Slogwang 	uint16_t iface;		/* which iface config change */
155*3b2bd0f6Slogwang 	uint32_t conf;		/* new config */
156*3b2bd0f6Slogwang };
157*3b2bd0f6Slogwang 
158*3b2bd0f6Slogwang /* This structure is passed to NGM_NETFLOW_SETTEMPLATE */
159*3b2bd0f6Slogwang struct ng_netflow_settemplate {
160*3b2bd0f6Slogwang 	uint16_t time;		/* max time between announce */
161*3b2bd0f6Slogwang 	uint16_t packets;	/* max packets between announce */
162*3b2bd0f6Slogwang };
163*3b2bd0f6Slogwang 
164*3b2bd0f6Slogwang /* This structure is passed to NGM_NETFLOW_SETMTU */
165*3b2bd0f6Slogwang struct ng_netflow_setmtu {
166*3b2bd0f6Slogwang 	uint16_t mtu;		/* MTU for packet */
167*3b2bd0f6Slogwang };
168*3b2bd0f6Slogwang 
169*3b2bd0f6Slogwang /* This structure is used in NGM_NETFLOW_SHOW request/response */
170*3b2bd0f6Slogwang struct ngnf_show_header {
171*3b2bd0f6Slogwang 	u_char		version;	/* IPv4 or IPv6 */
172*3b2bd0f6Slogwang 	uint32_t	hash_id;	/* current hash index */
173*3b2bd0f6Slogwang 	uint32_t	list_id;	/* current record number in hash */
174*3b2bd0f6Slogwang 	uint32_t	nentries;	/* number of records in response */
175*3b2bd0f6Slogwang };
176*3b2bd0f6Slogwang 
177*3b2bd0f6Slogwang /* This structure is used in NGM_NETFLOW_V9INFO message */
178*3b2bd0f6Slogwang struct ng_netflow_v9info {
179*3b2bd0f6Slogwang 	uint16_t	templ_packets;	/* v9 template packets */
180*3b2bd0f6Slogwang 	uint16_t	templ_time;	/* v9 template time */
181*3b2bd0f6Slogwang 	uint16_t	mtu;		/* v9 MTU */
182*3b2bd0f6Slogwang };
183*3b2bd0f6Slogwang 
184*3b2bd0f6Slogwang /* XXXGL
185*3b2bd0f6Slogwang  * Somewhere flow_rec6 is casted to flow_rec, and flow6_entry_data is
186*3b2bd0f6Slogwang  * casted to flow_entry_data. After casting, fle->r.fib is accessed.
187*3b2bd0f6Slogwang  * So beginning of these structs up to fib should be kept common.
188*3b2bd0f6Slogwang  */
189*3b2bd0f6Slogwang 
190*3b2bd0f6Slogwang /* This is unique data, which identifies flow */
191*3b2bd0f6Slogwang struct flow_rec {
192*3b2bd0f6Slogwang 	uint16_t	flow_type;
193*3b2bd0f6Slogwang 	uint16_t	fib;
194*3b2bd0f6Slogwang 	struct in_addr	r_src;
195*3b2bd0f6Slogwang 	struct in_addr	r_dst;
196*3b2bd0f6Slogwang 	union {
197*3b2bd0f6Slogwang 		struct {
198*3b2bd0f6Slogwang 			uint16_t	s_port;	/* source TCP/UDP port */
199*3b2bd0f6Slogwang 			uint16_t	d_port; /* destination TCP/UDP port */
200*3b2bd0f6Slogwang 		} dir;
201*3b2bd0f6Slogwang 		uint32_t both;
202*3b2bd0f6Slogwang 	} ports;
203*3b2bd0f6Slogwang 	union {
204*3b2bd0f6Slogwang 		struct {
205*3b2bd0f6Slogwang 			u_char		prot;	/* IP protocol */
206*3b2bd0f6Slogwang 			u_char		tos;	/* IP TOS */
207*3b2bd0f6Slogwang 			uint16_t	i_ifx;	/* input interface index */
208*3b2bd0f6Slogwang 		} i;
209*3b2bd0f6Slogwang 		uint32_t all;
210*3b2bd0f6Slogwang 	} misc;
211*3b2bd0f6Slogwang };
212*3b2bd0f6Slogwang 
213*3b2bd0f6Slogwang /* This is unique data, which identifies flow */
214*3b2bd0f6Slogwang struct flow6_rec {
215*3b2bd0f6Slogwang 	uint16_t	flow_type;
216*3b2bd0f6Slogwang 	uint16_t	fib;
217*3b2bd0f6Slogwang 	union {
218*3b2bd0f6Slogwang 		struct in_addr	r_src;
219*3b2bd0f6Slogwang 		struct in6_addr	r_src6;
220*3b2bd0f6Slogwang 	} src;
221*3b2bd0f6Slogwang 	union {
222*3b2bd0f6Slogwang 		struct in_addr	r_dst;
223*3b2bd0f6Slogwang 		struct in6_addr	r_dst6;
224*3b2bd0f6Slogwang 	} dst;
225*3b2bd0f6Slogwang 	union {
226*3b2bd0f6Slogwang 		struct {
227*3b2bd0f6Slogwang 			uint16_t	s_port;	/* source TCP/UDP port */
228*3b2bd0f6Slogwang 			uint16_t	d_port; /* destination TCP/UDP port */
229*3b2bd0f6Slogwang 		} dir;
230*3b2bd0f6Slogwang 		uint32_t both;
231*3b2bd0f6Slogwang 	} ports;
232*3b2bd0f6Slogwang 	union {
233*3b2bd0f6Slogwang 		struct {
234*3b2bd0f6Slogwang 			u_char		prot;	/* IP protocol */
235*3b2bd0f6Slogwang 			u_char		tos;	/* IP TOS */
236*3b2bd0f6Slogwang 			uint16_t	i_ifx;	/* input interface index */
237*3b2bd0f6Slogwang 		} i;
238*3b2bd0f6Slogwang 		uint32_t all;
239*3b2bd0f6Slogwang 	} misc;
240*3b2bd0f6Slogwang };
241*3b2bd0f6Slogwang 
242*3b2bd0f6Slogwang #define	r_ip_p	misc.i.prot
243*3b2bd0f6Slogwang #define	r_tos	misc.i.tos
244*3b2bd0f6Slogwang #define	r_i_ifx	misc.i.i_ifx
245*3b2bd0f6Slogwang #define r_misc	misc.all
246*3b2bd0f6Slogwang #define r_ports	ports.both
247*3b2bd0f6Slogwang #define r_sport	ports.dir.s_port
248*3b2bd0f6Slogwang #define r_dport	ports.dir.d_port
249*3b2bd0f6Slogwang 
250*3b2bd0f6Slogwang /* A flow entry which accumulates statistics */
251*3b2bd0f6Slogwang struct flow_entry_data {
252*3b2bd0f6Slogwang 	uint16_t	version;	/* Protocol version */
253*3b2bd0f6Slogwang 	struct flow_rec	r;
254*3b2bd0f6Slogwang 	struct in_addr	next_hop;
255*3b2bd0f6Slogwang 	uint16_t	fle_o_ifx;	/* output interface index */
256*3b2bd0f6Slogwang #define	fle_i_ifx	r.misc.i.i_ifx
257*3b2bd0f6Slogwang 	uint8_t		dst_mask;	/* destination route mask bits */
258*3b2bd0f6Slogwang 	uint8_t		src_mask;	/* source route mask bits */
259*3b2bd0f6Slogwang 	u_long		packets;
260*3b2bd0f6Slogwang 	u_long		bytes;
261*3b2bd0f6Slogwang 	long		first;		/* uptime on first packet */
262*3b2bd0f6Slogwang 	long		last;		/* uptime on last packet */
263*3b2bd0f6Slogwang 	u_char		tcp_flags;	/* cumulative OR */
264*3b2bd0f6Slogwang };
265*3b2bd0f6Slogwang 
266*3b2bd0f6Slogwang struct flow6_entry_data {
267*3b2bd0f6Slogwang 	uint16_t		version;	/* Protocol version */
268*3b2bd0f6Slogwang 	struct flow6_rec	r;
269*3b2bd0f6Slogwang 	union {
270*3b2bd0f6Slogwang 		struct in_addr	next_hop;
271*3b2bd0f6Slogwang 		struct in6_addr	next_hop6;
272*3b2bd0f6Slogwang 	} n;
273*3b2bd0f6Slogwang 	uint16_t	fle_o_ifx;	/* output interface index */
274*3b2bd0f6Slogwang #define	fle_i_ifx	r.misc.i.i_ifx
275*3b2bd0f6Slogwang 	uint8_t		dst_mask;	/* destination route mask bits */
276*3b2bd0f6Slogwang 	uint8_t		src_mask;	/* source route mask bits */
277*3b2bd0f6Slogwang 	u_long		packets;
278*3b2bd0f6Slogwang 	u_long		bytes;
279*3b2bd0f6Slogwang 	long		first;		/* uptime on first packet */
280*3b2bd0f6Slogwang 	long		last;		/* uptime on last packet */
281*3b2bd0f6Slogwang 	u_char		tcp_flags;	/* cumulative OR */
282*3b2bd0f6Slogwang };
283*3b2bd0f6Slogwang 
284*3b2bd0f6Slogwang /*
285*3b2bd0f6Slogwang  * How many flow records we will transfer at once
286*3b2bd0f6Slogwang  * without overflowing socket receive buffer
287*3b2bd0f6Slogwang  */
288*3b2bd0f6Slogwang #define NREC_AT_ONCE	 1000
289*3b2bd0f6Slogwang #define NREC6_AT_ONCE	(NREC_AT_ONCE * sizeof(struct flow_entry_data) / \
290*3b2bd0f6Slogwang 			sizeof(struct flow6_entry_data))
291*3b2bd0f6Slogwang #define NGRESP_SIZE	(sizeof(struct ngnf_show_header) + (NREC_AT_ONCE * \
292*3b2bd0f6Slogwang 			sizeof(struct flow_entry_data)))
293*3b2bd0f6Slogwang #define SORCVBUF_SIZE	(NGRESP_SIZE + 2 * sizeof(struct ng_mesg))
294*3b2bd0f6Slogwang 
295*3b2bd0f6Slogwang /* Everything below is for kernel */
296*3b2bd0f6Slogwang 
297*3b2bd0f6Slogwang #ifdef _KERNEL
298*3b2bd0f6Slogwang 
299*3b2bd0f6Slogwang struct flow_entry {
300*3b2bd0f6Slogwang 	TAILQ_ENTRY(flow_entry)	fle_hash;	/* entries in hash slot */
301*3b2bd0f6Slogwang 	struct flow_entry_data	f;
302*3b2bd0f6Slogwang };
303*3b2bd0f6Slogwang 
304*3b2bd0f6Slogwang struct flow6_entry {
305*3b2bd0f6Slogwang 	TAILQ_ENTRY(flow_entry)	fle_hash;	/* entries in hash slot */
306*3b2bd0f6Slogwang 	struct flow6_entry_data	f;
307*3b2bd0f6Slogwang };
308*3b2bd0f6Slogwang /* Parsing declarations */
309*3b2bd0f6Slogwang 
310*3b2bd0f6Slogwang /* Parse the ifinfo structure */
311*3b2bd0f6Slogwang #define NG_NETFLOW_IFINFO_TYPE	{			\
312*3b2bd0f6Slogwang 	{ "packets",		&ng_parse_uint32_type },\
313*3b2bd0f6Slogwang 	{ "data link type",	&ng_parse_uint8_type },	\
314*3b2bd0f6Slogwang 	{ "index",		&ng_parse_uint16_type },\
315*3b2bd0f6Slogwang 	{ "conf",		&ng_parse_uint32_type },\
316*3b2bd0f6Slogwang 	{ NULL }					\
317*3b2bd0f6Slogwang }
318*3b2bd0f6Slogwang 
319*3b2bd0f6Slogwang /* Parse the setdlt structure */
320*3b2bd0f6Slogwang #define	NG_NETFLOW_SETDLT_TYPE {			\
321*3b2bd0f6Slogwang 	{ "iface",	&ng_parse_uint16_type },	\
322*3b2bd0f6Slogwang 	{ "dlt",	&ng_parse_uint8_type },		\
323*3b2bd0f6Slogwang 	{ NULL }					\
324*3b2bd0f6Slogwang }
325*3b2bd0f6Slogwang 
326*3b2bd0f6Slogwang /* Parse the setifindex structure */
327*3b2bd0f6Slogwang #define	NG_NETFLOW_SETIFINDEX_TYPE {			\
328*3b2bd0f6Slogwang 	{ "iface",	&ng_parse_uint16_type },	\
329*3b2bd0f6Slogwang 	{ "index",	&ng_parse_uint16_type },	\
330*3b2bd0f6Slogwang 	{ NULL }					\
331*3b2bd0f6Slogwang }
332*3b2bd0f6Slogwang 
333*3b2bd0f6Slogwang /* Parse the settimeouts structure */
334*3b2bd0f6Slogwang #define NG_NETFLOW_SETTIMEOUTS_TYPE {			\
335*3b2bd0f6Slogwang 	{ "inactive",	&ng_parse_uint32_type },	\
336*3b2bd0f6Slogwang 	{ "active",	&ng_parse_uint32_type },	\
337*3b2bd0f6Slogwang 	{ NULL }					\
338*3b2bd0f6Slogwang }
339*3b2bd0f6Slogwang 
340*3b2bd0f6Slogwang /* Parse the setifindex structure */
341*3b2bd0f6Slogwang #define	NG_NETFLOW_SETCONFIG_TYPE {			\
342*3b2bd0f6Slogwang 	{ "iface",	&ng_parse_uint16_type },	\
343*3b2bd0f6Slogwang 	{ "conf",	&ng_parse_uint32_type },	\
344*3b2bd0f6Slogwang 	{ NULL }					\
345*3b2bd0f6Slogwang }
346*3b2bd0f6Slogwang 
347*3b2bd0f6Slogwang /* Parse the settemplate structure */
348*3b2bd0f6Slogwang #define	NG_NETFLOW_SETTEMPLATE_TYPE {		\
349*3b2bd0f6Slogwang 	{ "time",	&ng_parse_uint16_type },	\
350*3b2bd0f6Slogwang 	{ "packets",	&ng_parse_uint16_type },	\
351*3b2bd0f6Slogwang 	{ NULL }					\
352*3b2bd0f6Slogwang }
353*3b2bd0f6Slogwang 
354*3b2bd0f6Slogwang /* Parse the setmtu structure */
355*3b2bd0f6Slogwang #define	NG_NETFLOW_SETMTU_TYPE {			\
356*3b2bd0f6Slogwang 	{ "mtu",	&ng_parse_uint16_type },	\
357*3b2bd0f6Slogwang 	{ NULL }					\
358*3b2bd0f6Slogwang }
359*3b2bd0f6Slogwang 
360*3b2bd0f6Slogwang /* Parse the v9info structure */
361*3b2bd0f6Slogwang #define	NG_NETFLOW_V9INFO_TYPE {				\
362*3b2bd0f6Slogwang 	{ "v9 template packets",	&ng_parse_uint16_type },\
363*3b2bd0f6Slogwang 	{ "v9 template time",		&ng_parse_uint16_type },\
364*3b2bd0f6Slogwang 	{ "v9 MTU",			&ng_parse_uint16_type },\
365*3b2bd0f6Slogwang 	{ NULL }						\
366*3b2bd0f6Slogwang }
367*3b2bd0f6Slogwang 
368*3b2bd0f6Slogwang /* Private hook data */
369*3b2bd0f6Slogwang struct ng_netflow_iface {
370*3b2bd0f6Slogwang 	hook_p		hook;		/* NULL when disconnected */
371*3b2bd0f6Slogwang 	hook_p		out;		/* NULL when no bypass hook */
372*3b2bd0f6Slogwang 	struct ng_netflow_ifinfo	info;
373*3b2bd0f6Slogwang };
374*3b2bd0f6Slogwang 
375*3b2bd0f6Slogwang typedef struct ng_netflow_iface *iface_p;
376*3b2bd0f6Slogwang typedef struct ng_netflow_ifinfo *ifinfo_p;
377*3b2bd0f6Slogwang 
378*3b2bd0f6Slogwang struct netflow_export_item {
379*3b2bd0f6Slogwang 	item_p		item;
380*3b2bd0f6Slogwang 	item_p		item9;
381*3b2bd0f6Slogwang 	struct netflow_v9_packet_opt	*item9_opt;
382*3b2bd0f6Slogwang };
383*3b2bd0f6Slogwang 
384*3b2bd0f6Slogwang /* Structure contatining fib-specific data */
385*3b2bd0f6Slogwang struct fib_export {
386*3b2bd0f6Slogwang 	uint32_t	fib;		/* kernel fib id */
387*3b2bd0f6Slogwang 
388*3b2bd0f6Slogwang 	/* Various data used for export */
389*3b2bd0f6Slogwang 	struct netflow_export_item exp;
390*3b2bd0f6Slogwang 
391*3b2bd0f6Slogwang 	struct mtx	export_mtx;	/* exp.item mutex */
392*3b2bd0f6Slogwang 	struct mtx	export9_mtx;	/* exp.item9 mutex */
393*3b2bd0f6Slogwang 	uint32_t	flow_seq;	/* current V5 flow sequence */
394*3b2bd0f6Slogwang 	uint32_t	flow9_seq;	/* current V9 flow sequence */
395*3b2bd0f6Slogwang 	uint32_t	domain_id;	/* Observartion domain id */
396*3b2bd0f6Slogwang 	/* Netflow V9 counters */
397*3b2bd0f6Slogwang 	uint32_t	templ_last_ts;	/* unixtime of last template announce */
398*3b2bd0f6Slogwang 	uint32_t	templ_last_pkt;	/* packet count on last announce */
399*3b2bd0f6Slogwang 	uint32_t	sent_packets;	/* packets sent by exporter; */
400*3b2bd0f6Slogwang 
401*3b2bd0f6Slogwang 	/* Current packet specific options */
402*3b2bd0f6Slogwang 	struct netflow_v9_packet_opt *export9_opt;
403*3b2bd0f6Slogwang };
404*3b2bd0f6Slogwang 
405*3b2bd0f6Slogwang typedef struct fib_export *fib_export_p;
406*3b2bd0f6Slogwang 
407*3b2bd0f6Slogwang /* Structure describing our flow engine */
408*3b2bd0f6Slogwang struct netflow {
409*3b2bd0f6Slogwang 	node_p		node;		/* link to the node itself */
410*3b2bd0f6Slogwang 	hook_p		export;		/* export data goes there */
411*3b2bd0f6Slogwang 	hook_p		export9;	/* Netflow V9 export data goes there */
412*3b2bd0f6Slogwang 	struct callout	exp_callout;	/* expiry periodic job */
413*3b2bd0f6Slogwang 
414*3b2bd0f6Slogwang 	/*
415*3b2bd0f6Slogwang 	 * Flow entries are allocated in uma(9) zone zone. They are
416*3b2bd0f6Slogwang 	 * indexed by hash hash. Each hash element consist of tailqueue
417*3b2bd0f6Slogwang 	 * head and mutex to protect this element.
418*3b2bd0f6Slogwang 	 */
419*3b2bd0f6Slogwang #define	CACHESIZE			(65536*16)
420*3b2bd0f6Slogwang #define	CACHELOWAT			(CACHESIZE * 3/4)
421*3b2bd0f6Slogwang #define	CACHEHIGHWAT			(CACHESIZE * 9/10)
422*3b2bd0f6Slogwang 	uma_zone_t		zone;
423*3b2bd0f6Slogwang 	struct flow_hash_entry	*hash;
424*3b2bd0f6Slogwang 
425*3b2bd0f6Slogwang 	/*
426*3b2bd0f6Slogwang 	 * NetFlow data export
427*3b2bd0f6Slogwang 	 *
428*3b2bd0f6Slogwang 	 * export_item is a data item, it has an mbuf with cluster
429*3b2bd0f6Slogwang 	 * attached to it. A thread detaches export_item from priv
430*3b2bd0f6Slogwang 	 * and works with it. If the export is full it is sent, and
431*3b2bd0f6Slogwang 	 * a new one is allocated. Before exiting thread re-attaches
432*3b2bd0f6Slogwang 	 * its current item back to priv. If there is item already,
433*3b2bd0f6Slogwang 	 * current incomplete datagram is sent.
434*3b2bd0f6Slogwang 	 * export_mtx is used for attaching/detaching.
435*3b2bd0f6Slogwang 	 */
436*3b2bd0f6Slogwang 
437*3b2bd0f6Slogwang 	/* IPv6 support */
438*3b2bd0f6Slogwang #ifdef INET6
439*3b2bd0f6Slogwang 	uma_zone_t		zone6;
440*3b2bd0f6Slogwang 	struct flow_hash_entry	*hash6;
441*3b2bd0f6Slogwang #endif
442*3b2bd0f6Slogwang 
443*3b2bd0f6Slogwang 	/* Statistics. */
444*3b2bd0f6Slogwang 	counter_u64_t	nfinfo_bytes;		/* accounted IPv4 bytes */
445*3b2bd0f6Slogwang 	counter_u64_t	nfinfo_packets;		/* accounted IPv4 packets */
446*3b2bd0f6Slogwang 	counter_u64_t	nfinfo_bytes6;		/* accounted IPv6 bytes */
447*3b2bd0f6Slogwang 	counter_u64_t	nfinfo_packets6;	/* accounted IPv6 packets */
448*3b2bd0f6Slogwang 	counter_u64_t	nfinfo_sbytes;		/* skipped IPv4 bytes */
449*3b2bd0f6Slogwang 	counter_u64_t	nfinfo_spackets;	/* skipped IPv4 packets */
450*3b2bd0f6Slogwang 	counter_u64_t	nfinfo_sbytes6;		/* skipped IPv6 bytes */
451*3b2bd0f6Slogwang 	counter_u64_t	nfinfo_spackets6;	/* skipped IPv6 packets */
452*3b2bd0f6Slogwang 	counter_u64_t	nfinfo_act_exp;		/* active expiries */
453*3b2bd0f6Slogwang 	counter_u64_t	nfinfo_inact_exp;	/* inactive expiries */
454*3b2bd0f6Slogwang 	uint32_t	nfinfo_alloc_failed;	/* failed allocations */
455*3b2bd0f6Slogwang 	uint32_t	nfinfo_export_failed;	/* failed exports */
456*3b2bd0f6Slogwang 	uint32_t	nfinfo_export9_failed;	/* failed exports */
457*3b2bd0f6Slogwang 	uint32_t	nfinfo_realloc_mbuf;	/* reallocated mbufs */
458*3b2bd0f6Slogwang 	uint32_t	nfinfo_alloc_fibs;	/* fibs allocated */
459*3b2bd0f6Slogwang 	uint32_t	nfinfo_inact_t;		/* flow inactive timeout */
460*3b2bd0f6Slogwang 	uint32_t	nfinfo_act_t;		/* flow active timeout */
461*3b2bd0f6Slogwang 
462*3b2bd0f6Slogwang 	/* Multiple FIB support */
463*3b2bd0f6Slogwang 	fib_export_p	*fib_data;	/* vector to per-fib data */
464*3b2bd0f6Slogwang 	uint16_t	maxfibs;	/* number of allocated fibs */
465*3b2bd0f6Slogwang 
466*3b2bd0f6Slogwang 	/* Netflow v9 configuration options */
467*3b2bd0f6Slogwang 	/*
468*3b2bd0f6Slogwang 	 * RFC 3954 clause 7.3
469*3b2bd0f6Slogwang 	 * "Both options MUST be configurable by the user on the Exporter."
470*3b2bd0f6Slogwang 	 */
471*3b2bd0f6Slogwang 	uint16_t	templ_time;	/* time between sending templates */
472*3b2bd0f6Slogwang 	uint16_t	templ_packets;	/* packets between sending templates */
473*3b2bd0f6Slogwang #define NETFLOW_V9_MAX_FLOWSETS	2
474*3b2bd0f6Slogwang 	u_char		flowsets_count; /* current flowsets used */
475*3b2bd0f6Slogwang 
476*3b2bd0f6Slogwang 	/* Count of records in each flowset */
477*3b2bd0f6Slogwang 	u_char		flowset_records[NETFLOW_V9_MAX_FLOWSETS - 1];
478*3b2bd0f6Slogwang 	uint16_t	mtu;		/* export interface MTU */
479*3b2bd0f6Slogwang 
480*3b2bd0f6Slogwang 	/* Pointers to pre-compiled flowsets */
481*3b2bd0f6Slogwang 	struct netflow_v9_flowset_header
482*3b2bd0f6Slogwang 	    *v9_flowsets[NETFLOW_V9_MAX_FLOWSETS - 1];
483*3b2bd0f6Slogwang 
484*3b2bd0f6Slogwang 	struct ng_netflow_iface	ifaces[NG_NETFLOW_MAXIFACES];
485*3b2bd0f6Slogwang };
486*3b2bd0f6Slogwang 
487*3b2bd0f6Slogwang typedef struct netflow *priv_p;
488*3b2bd0f6Slogwang 
489*3b2bd0f6Slogwang /* Header of a small list in hash cell */
490*3b2bd0f6Slogwang struct flow_hash_entry {
491*3b2bd0f6Slogwang 	struct mtx		mtx;
492*3b2bd0f6Slogwang 	TAILQ_HEAD(fhead, flow_entry) head;
493*3b2bd0f6Slogwang };
494*3b2bd0f6Slogwang 
495*3b2bd0f6Slogwang #define	ERROUT(x)	{ error = (x); goto done; }
496*3b2bd0f6Slogwang 
497*3b2bd0f6Slogwang #define MTAG_NETFLOW		1221656444
498*3b2bd0f6Slogwang #define MTAG_NETFLOW_CALLED	0
499*3b2bd0f6Slogwang 
500*3b2bd0f6Slogwang #define m_pktlen(m)	((m)->m_pkthdr.len)
501*3b2bd0f6Slogwang #define IP6VERSION	6
502*3b2bd0f6Slogwang 
503*3b2bd0f6Slogwang #define priv_to_fib(priv, fib)	(priv)->fib_data[(fib)]
504*3b2bd0f6Slogwang 
505*3b2bd0f6Slogwang /*
506*3b2bd0f6Slogwang  * Cisco uses milliseconds for uptime. Bad idea, since it overflows
507*3b2bd0f6Slogwang  * every 48+ days. But we will do same to keep compatibility. This macro
508*3b2bd0f6Slogwang  * does overflowable multiplication to 1000.
509*3b2bd0f6Slogwang  */
510*3b2bd0f6Slogwang #define	MILLIUPTIME(t)	(((t) << 9) +	/* 512 */	\
511*3b2bd0f6Slogwang 			 ((t) << 8) +	/* 256 */	\
512*3b2bd0f6Slogwang 			 ((t) << 7) +	/* 128 */	\
513*3b2bd0f6Slogwang 			 ((t) << 6) +	/* 64  */	\
514*3b2bd0f6Slogwang 			 ((t) << 5) +	/* 32  */	\
515*3b2bd0f6Slogwang 			 ((t) << 3))	/* 8   */
516*3b2bd0f6Slogwang 
517*3b2bd0f6Slogwang /* Prototypes for netflow.c */
518*3b2bd0f6Slogwang void	ng_netflow_cache_init(priv_p);
519*3b2bd0f6Slogwang void	ng_netflow_cache_flush(priv_p);
520*3b2bd0f6Slogwang int	ng_netflow_fib_init(priv_p priv, int fib);
521*3b2bd0f6Slogwang void	ng_netflow_copyinfo(priv_p, struct ng_netflow_info *);
522*3b2bd0f6Slogwang void	ng_netflow_copyv9info(priv_p, struct ng_netflow_v9info *);
523*3b2bd0f6Slogwang timeout_t ng_netflow_expire;
524*3b2bd0f6Slogwang int 	ng_netflow_flow_add(priv_p, fib_export_p, struct ip *, caddr_t,
525*3b2bd0f6Slogwang 	uint8_t, uint8_t, unsigned int);
526*3b2bd0f6Slogwang int	ng_netflow_flow6_add(priv_p, fib_export_p, struct ip6_hdr *, caddr_t,
527*3b2bd0f6Slogwang 	uint8_t, uint8_t, unsigned int);
528*3b2bd0f6Slogwang int	ng_netflow_flow_show(priv_p, struct ngnf_show_header *req,
529*3b2bd0f6Slogwang 	struct ngnf_show_header *resp);
530*3b2bd0f6Slogwang void	ng_netflow_v9_cache_init(priv_p);
531*3b2bd0f6Slogwang void	ng_netflow_v9_cache_flush(priv_p);
532*3b2bd0f6Slogwang item_p	get_export9_dgram(priv_p, fib_export_p,
533*3b2bd0f6Slogwang 	struct netflow_v9_packet_opt **);
534*3b2bd0f6Slogwang void	return_export9_dgram(priv_p, fib_export_p, item_p,
535*3b2bd0f6Slogwang 	struct netflow_v9_packet_opt *, int);
536*3b2bd0f6Slogwang int	export9_add(item_p, struct netflow_v9_packet_opt *,
537*3b2bd0f6Slogwang 	struct flow_entry *);
538*3b2bd0f6Slogwang int	export9_send(priv_p, fib_export_p, item_p,
539*3b2bd0f6Slogwang 	struct netflow_v9_packet_opt *, int);
540*3b2bd0f6Slogwang 
541*3b2bd0f6Slogwang #endif	/* _KERNEL */
542*3b2bd0f6Slogwang #endif	/* _NG_NETFLOW_H_ */
543