xref: /dflybsd-src/sys/netgraph7/netflow/ng_netflow.h (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
1*86d7f5d3SJohn Marino /*-
2*86d7f5d3SJohn Marino  * Copyright (c) 2004-2005 Gleb Smirnoff <glebius@FreeBSD.org>
3*86d7f5d3SJohn Marino  * Copyright (c) 2001-2003 Roman V. Palagin <romanp@unshadow.net>
4*86d7f5d3SJohn Marino  * All rights reserved.
5*86d7f5d3SJohn Marino  *
6*86d7f5d3SJohn Marino  * Redistribution and use in source and binary forms, with or without
7*86d7f5d3SJohn Marino  * modification, are permitted provided that the following conditions
8*86d7f5d3SJohn Marino  * are met:
9*86d7f5d3SJohn Marino  * 1. Redistributions of source code must retain the above copyright
10*86d7f5d3SJohn Marino  *    notice, this list of conditions and the following disclaimer.
11*86d7f5d3SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
12*86d7f5d3SJohn Marino  *    notice, this list of conditions and the following disclaimer in the
13*86d7f5d3SJohn Marino  *    documentation and/or other materials provided with the distribution.
14*86d7f5d3SJohn Marino  *
15*86d7f5d3SJohn Marino  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16*86d7f5d3SJohn Marino  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*86d7f5d3SJohn Marino  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*86d7f5d3SJohn Marino  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19*86d7f5d3SJohn Marino  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20*86d7f5d3SJohn Marino  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21*86d7f5d3SJohn Marino  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22*86d7f5d3SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23*86d7f5d3SJohn Marino  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24*86d7f5d3SJohn Marino  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25*86d7f5d3SJohn Marino  * SUCH DAMAGE.
26*86d7f5d3SJohn Marino  *
27*86d7f5d3SJohn Marino  *	 $SourceForge: ng_netflow.h,v 1.26 2004/09/04 15:44:55 glebius Exp $
28*86d7f5d3SJohn Marino  *	 $FreeBSD: src/sys/netgraph/netflow/ng_netflow.h,v 1.10 2007/03/28 13:59:13 glebius Exp $
29*86d7f5d3SJohn Marino  */
30*86d7f5d3SJohn Marino 
31*86d7f5d3SJohn Marino #ifndef	_NG_NETFLOW_H_
32*86d7f5d3SJohn Marino #define	_NG_NETFLOW_H_
33*86d7f5d3SJohn Marino 
34*86d7f5d3SJohn Marino #define NG_NETFLOW_NODE_TYPE	"netflow"
35*86d7f5d3SJohn Marino #define NGM_NETFLOW_COOKIE	1137078102
36*86d7f5d3SJohn Marino 
37*86d7f5d3SJohn Marino #define	NG_NETFLOW_MAXIFACES	USHRT_MAX
38*86d7f5d3SJohn Marino 
39*86d7f5d3SJohn Marino /* Hook names */
40*86d7f5d3SJohn Marino 
41*86d7f5d3SJohn Marino #define	NG_NETFLOW_HOOK_DATA	"iface"
42*86d7f5d3SJohn Marino #define	NG_NETFLOW_HOOK_OUT	"out"
43*86d7f5d3SJohn Marino #define NG_NETFLOW_HOOK_EXPORT	"export"
44*86d7f5d3SJohn Marino 
45*86d7f5d3SJohn Marino /* Netgraph commands understood by netflow node */
46*86d7f5d3SJohn Marino enum {
47*86d7f5d3SJohn Marino     NGM_NETFLOW_INFO = 1|NGM_READONLY|NGM_HASREPLY,	/* get node info */
48*86d7f5d3SJohn Marino     NGM_NETFLOW_IFINFO = 2|NGM_READONLY|NGM_HASREPLY,	/* get iface info */
49*86d7f5d3SJohn Marino     NGM_NETFLOW_SHOW = 3|NGM_READONLY|NGM_HASREPLY,	/* show ip cache flow */
50*86d7f5d3SJohn Marino     NGM_NETFLOW_SETDLT		= 4,	/* set data-link type */
51*86d7f5d3SJohn Marino     NGM_NETFLOW_SETIFINDEX	= 5, 	/* set interface index */
52*86d7f5d3SJohn Marino     NGM_NETFLOW_SETTIMEOUTS	= 6, 	/* set active/inactive flow timeouts */
53*86d7f5d3SJohn Marino };
54*86d7f5d3SJohn Marino 
55*86d7f5d3SJohn Marino /* This structure is returned by the NGM_NETFLOW_INFO message */
56*86d7f5d3SJohn Marino struct ng_netflow_info {
57*86d7f5d3SJohn Marino 	uint64_t	nfinfo_bytes;		/* accounted bytes */
58*86d7f5d3SJohn Marino 	uint32_t	nfinfo_packets;		/* accounted packets */
59*86d7f5d3SJohn Marino 	uint32_t	nfinfo_used;		/* used cache records */
60*86d7f5d3SJohn Marino 	uint32_t	nfinfo_alloc_failed;	/* failed allocations */
61*86d7f5d3SJohn Marino 	uint32_t	nfinfo_export_failed;	/* failed exports */
62*86d7f5d3SJohn Marino 	uint32_t	nfinfo_act_exp;		/* active expiries */
63*86d7f5d3SJohn Marino 	uint32_t	nfinfo_inact_exp;	/* inactive expiries */
64*86d7f5d3SJohn Marino 	uint32_t	nfinfo_inact_t;		/* flow inactive timeout */
65*86d7f5d3SJohn Marino 	uint32_t	nfinfo_act_t;		/* flow active timeout */
66*86d7f5d3SJohn Marino };
67*86d7f5d3SJohn Marino 
68*86d7f5d3SJohn Marino /* This structure is returned by the NGM_NETFLOW_IFINFO message */
69*86d7f5d3SJohn Marino struct ng_netflow_ifinfo {
70*86d7f5d3SJohn Marino 	uint32_t	ifinfo_packets;	/* number of packets for this iface */
71*86d7f5d3SJohn Marino 	uint8_t		ifinfo_dlt;	/* Data Link Type, DLT_XXX */
72*86d7f5d3SJohn Marino #define	MAXDLTNAMELEN	20
73*86d7f5d3SJohn Marino 	u_int16_t	ifinfo_index;	/* connected iface index */
74*86d7f5d3SJohn Marino };
75*86d7f5d3SJohn Marino 
76*86d7f5d3SJohn Marino 
77*86d7f5d3SJohn Marino /* This structure is passed to NGM_NETFLOW_SETDLT message */
78*86d7f5d3SJohn Marino struct ng_netflow_setdlt {
79*86d7f5d3SJohn Marino 	uint16_t iface;		/* which iface dlt change */
80*86d7f5d3SJohn Marino 	uint8_t  dlt;			/* DLT_XXX from bpf.h */
81*86d7f5d3SJohn Marino };
82*86d7f5d3SJohn Marino 
83*86d7f5d3SJohn Marino /* This structure is passed to NGM_NETFLOW_SETIFINDEX */
84*86d7f5d3SJohn Marino struct ng_netflow_setifindex {
85*86d7f5d3SJohn Marino 	u_int16_t iface;		/* which iface index change */
86*86d7f5d3SJohn Marino 	u_int16_t index;		/* new index */
87*86d7f5d3SJohn Marino };
88*86d7f5d3SJohn Marino 
89*86d7f5d3SJohn Marino /* This structure is passed to NGM_NETFLOW_SETTIMEOUTS */
90*86d7f5d3SJohn Marino struct ng_netflow_settimeouts {
91*86d7f5d3SJohn Marino 	uint32_t	inactive_timeout;	/* flow inactive timeout */
92*86d7f5d3SJohn Marino 	uint32_t	active_timeout;		/* flow active timeout */
93*86d7f5d3SJohn Marino };
94*86d7f5d3SJohn Marino 
95*86d7f5d3SJohn Marino /* This is unique data, which identifies flow */
96*86d7f5d3SJohn Marino struct flow_rec {
97*86d7f5d3SJohn Marino 	struct in_addr	r_src;
98*86d7f5d3SJohn Marino 	struct in_addr	r_dst;
99*86d7f5d3SJohn Marino 	union {
100*86d7f5d3SJohn Marino 		struct {
101*86d7f5d3SJohn Marino 			uint16_t	s_port;	/* source TCP/UDP port */
102*86d7f5d3SJohn Marino 			uint16_t	d_port; /* destination TCP/UDP port */
103*86d7f5d3SJohn Marino 		} dir;
104*86d7f5d3SJohn Marino 		uint32_t both;
105*86d7f5d3SJohn Marino 	} ports;
106*86d7f5d3SJohn Marino 	union {
107*86d7f5d3SJohn Marino 		struct {
108*86d7f5d3SJohn Marino 			u_char		prot;	/* IP protocol */
109*86d7f5d3SJohn Marino 			u_char		tos;	/* IP TOS */
110*86d7f5d3SJohn Marino 			uint16_t	i_ifx;	/* input interface index */
111*86d7f5d3SJohn Marino 		} i;
112*86d7f5d3SJohn Marino 		uint32_t all;
113*86d7f5d3SJohn Marino 	} misc;
114*86d7f5d3SJohn Marino };
115*86d7f5d3SJohn Marino 
116*86d7f5d3SJohn Marino #define	r_ip_p	misc.i.prot
117*86d7f5d3SJohn Marino #define	r_tos	misc.i.tos
118*86d7f5d3SJohn Marino #define	r_i_ifx	misc.i.i_ifx
119*86d7f5d3SJohn Marino #define r_misc	misc.all
120*86d7f5d3SJohn Marino #define r_ports	ports.both
121*86d7f5d3SJohn Marino #define r_sport	ports.dir.s_port
122*86d7f5d3SJohn Marino #define r_dport	ports.dir.d_port
123*86d7f5d3SJohn Marino 
124*86d7f5d3SJohn Marino /* A flow entry which accumulates statistics */
125*86d7f5d3SJohn Marino struct flow_entry_data {
126*86d7f5d3SJohn Marino 	struct flow_rec		r;
127*86d7f5d3SJohn Marino 	struct in_addr		next_hop;
128*86d7f5d3SJohn Marino 	uint16_t		fle_o_ifx;	/* output interface index */
129*86d7f5d3SJohn Marino #define				fle_i_ifx	r.misc.i.i_ifx
130*86d7f5d3SJohn Marino 	uint8_t		dst_mask;	/* destination route mask bits */
131*86d7f5d3SJohn Marino 	uint8_t		src_mask;	/* source route mask bits */
132*86d7f5d3SJohn Marino 	u_long			packets;
133*86d7f5d3SJohn Marino 	u_long			bytes;
134*86d7f5d3SJohn Marino 	long			first;	/* uptime on first packet */
135*86d7f5d3SJohn Marino 	long			last;	/* uptime on last packet */
136*86d7f5d3SJohn Marino 	u_char			tcp_flags;	/* cumulative OR */
137*86d7f5d3SJohn Marino };
138*86d7f5d3SJohn Marino 
139*86d7f5d3SJohn Marino /*
140*86d7f5d3SJohn Marino  * How many flow records we will transfer at once
141*86d7f5d3SJohn Marino  * without overflowing socket receive buffer
142*86d7f5d3SJohn Marino  */
143*86d7f5d3SJohn Marino #define NREC_AT_ONCE		1000
144*86d7f5d3SJohn Marino #define NGRESP_SIZE		(sizeof(struct ngnf_flows) + (NREC_AT_ONCE * \
145*86d7f5d3SJohn Marino 				sizeof(struct flow_entry_data)))
146*86d7f5d3SJohn Marino #define SORCVBUF_SIZE		(NGRESP_SIZE + 2 * sizeof(struct ng_mesg))
147*86d7f5d3SJohn Marino 
148*86d7f5d3SJohn Marino /* This struct is returned to userland, when "show cache ip flow" */
149*86d7f5d3SJohn Marino struct ngnf_flows {
150*86d7f5d3SJohn Marino 	uint32_t		nentries;
151*86d7f5d3SJohn Marino 	uint32_t		last;
152*86d7f5d3SJohn Marino 	struct flow_entry_data	entries[0];
153*86d7f5d3SJohn Marino };
154*86d7f5d3SJohn Marino 
155*86d7f5d3SJohn Marino /* Everything below is for kernel */
156*86d7f5d3SJohn Marino 
157*86d7f5d3SJohn Marino #ifdef _KERNEL
158*86d7f5d3SJohn Marino 
159*86d7f5d3SJohn Marino struct flow_entry {
160*86d7f5d3SJohn Marino 	struct flow_entry_data	f;
161*86d7f5d3SJohn Marino 	TAILQ_ENTRY(flow_entry)	fle_hash;	/* entries in hash slot */
162*86d7f5d3SJohn Marino };
163*86d7f5d3SJohn Marino 
164*86d7f5d3SJohn Marino /* Parsing declarations */
165*86d7f5d3SJohn Marino 
166*86d7f5d3SJohn Marino /* Parse the info structure */
167*86d7f5d3SJohn Marino #define	NG_NETFLOW_INFO_TYPE	{			\
168*86d7f5d3SJohn Marino 	{ "Bytes",	&ng_parse_uint64_type },	\
169*86d7f5d3SJohn Marino 	{ "Packets",	&ng_parse_uint32_type },	\
170*86d7f5d3SJohn Marino 	{ "Records used",	&ng_parse_uint32_type },\
171*86d7f5d3SJohn Marino 	{ "Failed allocations",	&ng_parse_uint32_type },\
172*86d7f5d3SJohn Marino 	{ "Failed exports",	&ng_parse_uint32_type },\
173*86d7f5d3SJohn Marino 	{ "Active expiries",	&ng_parse_uint32_type },\
174*86d7f5d3SJohn Marino 	{ "Inactive expiries",	&ng_parse_uint32_type },\
175*86d7f5d3SJohn Marino 	{ "Inactive timeout",	&ng_parse_uint32_type },\
176*86d7f5d3SJohn Marino 	{ "Active timeout",	&ng_parse_uint32_type },\
177*86d7f5d3SJohn Marino 	{ NULL }					\
178*86d7f5d3SJohn Marino }
179*86d7f5d3SJohn Marino 
180*86d7f5d3SJohn Marino /* Parse the ifinfo structure */
181*86d7f5d3SJohn Marino #define NG_NETFLOW_IFINFO_TYPE	{			\
182*86d7f5d3SJohn Marino 	{ "packets",	&ng_parse_uint32_type },	\
183*86d7f5d3SJohn Marino 	{ "data link type", &ng_parse_uint8_type },	\
184*86d7f5d3SJohn Marino 	{ "index", &ng_parse_uint16_type },		\
185*86d7f5d3SJohn Marino 	{ NULL }					\
186*86d7f5d3SJohn Marino }
187*86d7f5d3SJohn Marino 
188*86d7f5d3SJohn Marino /* Parse the setdlt structure */
189*86d7f5d3SJohn Marino #define	NG_NETFLOW_SETDLT_TYPE {			\
190*86d7f5d3SJohn Marino 	{ "iface",	&ng_parse_uint16_type },	\
191*86d7f5d3SJohn Marino 	{ "dlt",	&ng_parse_uint8_type  },	\
192*86d7f5d3SJohn Marino 	{ NULL }					\
193*86d7f5d3SJohn Marino }
194*86d7f5d3SJohn Marino 
195*86d7f5d3SJohn Marino /* Parse the setifindex structure */
196*86d7f5d3SJohn Marino #define	NG_NETFLOW_SETIFINDEX_TYPE {			\
197*86d7f5d3SJohn Marino 	{ "iface",	&ng_parse_uint16_type },	\
198*86d7f5d3SJohn Marino 	{ "index",	&ng_parse_uint16_type },	\
199*86d7f5d3SJohn Marino 	{ NULL }					\
200*86d7f5d3SJohn Marino }
201*86d7f5d3SJohn Marino 
202*86d7f5d3SJohn Marino /* Parse the settimeouts structure */
203*86d7f5d3SJohn Marino #define NG_NETFLOW_SETTIMEOUTS_TYPE {			\
204*86d7f5d3SJohn Marino 	{ "inactive",	&ng_parse_uint32_type },	\
205*86d7f5d3SJohn Marino 	{ "active",	&ng_parse_uint32_type },	\
206*86d7f5d3SJohn Marino 	{ NULL }					\
207*86d7f5d3SJohn Marino }
208*86d7f5d3SJohn Marino 
209*86d7f5d3SJohn Marino /* Private hook data */
210*86d7f5d3SJohn Marino struct ng_netflow_iface {
211*86d7f5d3SJohn Marino 	hook_p		hook;		/* NULL when disconnected */
212*86d7f5d3SJohn Marino 	hook_p		out;		/* NULL when no bypass hook */
213*86d7f5d3SJohn Marino 	struct ng_netflow_ifinfo	info;
214*86d7f5d3SJohn Marino };
215*86d7f5d3SJohn Marino 
216*86d7f5d3SJohn Marino typedef struct ng_netflow_iface *iface_p;
217*86d7f5d3SJohn Marino typedef struct ng_netflow_ifinfo *ifinfo_p;
218*86d7f5d3SJohn Marino 
219*86d7f5d3SJohn Marino /* Structure describing our flow engine */
220*86d7f5d3SJohn Marino struct netflow {
221*86d7f5d3SJohn Marino 	node_p			node;		/* link to the node itself */
222*86d7f5d3SJohn Marino 	hook_p			export;		/* export data goes there */
223*86d7f5d3SJohn Marino 
224*86d7f5d3SJohn Marino 	struct ng_netflow_info	info;
225*86d7f5d3SJohn Marino 	struct callout		exp_callout;	/* expiry periodic job */
226*86d7f5d3SJohn Marino 
227*86d7f5d3SJohn Marino 	/*
228*86d7f5d3SJohn Marino 	 * Flow entries are allocated in uma(9) zone zone. They are
229*86d7f5d3SJohn Marino 	 * indexed by hash hash. Each hash element consist of tailqueue
230*86d7f5d3SJohn Marino 	 * head and mutex to protect this element.
231*86d7f5d3SJohn Marino 	 */
232*86d7f5d3SJohn Marino #define	CACHESIZE			(65536*4)
233*86d7f5d3SJohn Marino #define	CACHELOWAT			(CACHESIZE * 3/4)
234*86d7f5d3SJohn Marino #define	CACHEHIGHWAT			(CACHESIZE * 9/10)
235*86d7f5d3SJohn Marino 	uma_zone_t		zone;
236*86d7f5d3SJohn Marino 	struct flow_hash_entry	*hash;
237*86d7f5d3SJohn Marino 
238*86d7f5d3SJohn Marino 	/*
239*86d7f5d3SJohn Marino 	 * NetFlow data export
240*86d7f5d3SJohn Marino 	 *
241*86d7f5d3SJohn Marino 	 * export_item is a data item, it has an mbuf with cluster
242*86d7f5d3SJohn Marino 	 * attached to it. A thread detaches export_item from priv
243*86d7f5d3SJohn Marino 	 * and works with it. If the export is full it is sent, and
244*86d7f5d3SJohn Marino 	 * a new one is allocated. Before exiting thread re-attaches
245*86d7f5d3SJohn Marino 	 * its current item back to priv. If there is item already,
246*86d7f5d3SJohn Marino 	 * current incomplete datagram is sent.
247*86d7f5d3SJohn Marino 	 * export_mtx is used for attaching/detaching.
248*86d7f5d3SJohn Marino 	 */
249*86d7f5d3SJohn Marino 	item_p			export_item;
250*86d7f5d3SJohn Marino 	struct mtx		export_mtx;
251*86d7f5d3SJohn Marino 	uint32_t		flow_seq;	/* current flow sequence */
252*86d7f5d3SJohn Marino 
253*86d7f5d3SJohn Marino 	struct ng_netflow_iface	ifaces[NG_NETFLOW_MAXIFACES];
254*86d7f5d3SJohn Marino };
255*86d7f5d3SJohn Marino 
256*86d7f5d3SJohn Marino typedef struct netflow *priv_p;
257*86d7f5d3SJohn Marino 
258*86d7f5d3SJohn Marino /* Header of a small list in hash cell */
259*86d7f5d3SJohn Marino struct flow_hash_entry {
260*86d7f5d3SJohn Marino 	struct mtx		mtx;
261*86d7f5d3SJohn Marino 	TAILQ_HEAD(fhead, flow_entry) head;
262*86d7f5d3SJohn Marino };
263*86d7f5d3SJohn Marino 
264*86d7f5d3SJohn Marino #define	ERROUT(x)	{ error = (x); goto done; }
265*86d7f5d3SJohn Marino 
266*86d7f5d3SJohn Marino /* Prototypes for netflow.c */
267*86d7f5d3SJohn Marino int	ng_netflow_cache_init(priv_p);
268*86d7f5d3SJohn Marino void	ng_netflow_cache_flush(priv_p);
269*86d7f5d3SJohn Marino void	ng_netflow_copyinfo(priv_p, struct ng_netflow_info *);
270*86d7f5d3SJohn Marino timeout_t ng_netflow_expire;
271*86d7f5d3SJohn Marino int	ng_netflow_flow_add(priv_p, struct ip *, iface_p, struct ifnet *);
272*86d7f5d3SJohn Marino int	ng_netflow_flow_show(priv_p, uint32_t last, struct ng_mesg *);
273*86d7f5d3SJohn Marino 
274*86d7f5d3SJohn Marino #endif	/* _KERNEL */
275*86d7f5d3SJohn Marino #endif	/* _NG_NETFLOW_H_ */
276