summaryrefslogtreecommitdiffstats
path: root/sys/netgraph/netflow/ng_netflow.h
blob: bd35cf09281aedf1be1c5504146f79683fdc4c1e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
/*-
 * Copyright (c) 2004-2005 Gleb Smirnoff <glebius@FreeBSD.org>
 * Copyright (c) 2001-2003 Roman V. Palagin <romanp@unshadow.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	 $SourceForge: ng_netflow.h,v 1.26 2004/09/04 15:44:55 glebius Exp $
 *	 $FreeBSD$
 */

#ifndef	_NG_NETFLOW_H_
#define	_NG_NETFLOW_H_

#define NG_NETFLOW_NODE_TYPE	"netflow"
#define NGM_NETFLOW_COOKIE	1137078102

#define	NG_NETFLOW_MAXIFACES	USHRT_MAX

/* Hook names */

#define	NG_NETFLOW_HOOK_DATA	"iface"
#define	NG_NETFLOW_HOOK_OUT	"out"
#define NG_NETFLOW_HOOK_EXPORT	"export"

/* Netgraph commands understood by netflow node */
enum {
    NGM_NETFLOW_INFO = 1|NGM_READONLY|NGM_HASREPLY,	/* get node info */
    NGM_NETFLOW_IFINFO = 2|NGM_READONLY|NGM_HASREPLY,	/* get iface info */
    NGM_NETFLOW_SHOW = 3|NGM_READONLY|NGM_HASREPLY,	/* show ip cache flow */
    NGM_NETFLOW_SETDLT		= 4,	/* set data-link type */	
    NGM_NETFLOW_SETIFINDEX	= 5, 	/* set interface index */
    NGM_NETFLOW_SETTIMEOUTS	= 6, 	/* set active/inactive flow timeouts */
};

/* This structure is returned by the NGM_NETFLOW_INFO message */
struct ng_netflow_info {
	uint64_t	nfinfo_bytes;		/* accounted bytes */
	uint32_t	nfinfo_packets;		/* accounted packets */
	uint32_t	nfinfo_used;		/* used cache records */
	uint32_t	nfinfo_alloc_failed;	/* failed allocations */
	uint32_t	nfinfo_export_failed;	/* failed exports */
	uint32_t	nfinfo_act_exp;		/* active expiries */
	uint32_t	nfinfo_inact_exp;	/* inactive expiries */
	uint32_t	nfinfo_inact_t;		/* flow inactive timeout */
	uint32_t	nfinfo_act_t;		/* flow active timeout */
};

/* This structure is returned by the NGM_NETFLOW_IFINFO message */
struct ng_netflow_ifinfo {
	uint32_t	ifinfo_packets;	/* number of packets for this iface */
	uint8_t		ifinfo_dlt;	/* Data Link Type, DLT_XXX */
#define	MAXDLTNAMELEN	20
	u_int16_t	ifinfo_index;	/* connected iface index */
};


/* This structure is passed to NGM_NETFLOW_SETDLT message */
struct ng_netflow_setdlt {
	uint16_t iface;		/* which iface dlt change */
	uint8_t  dlt;			/* DLT_XXX from bpf.h */
};

/* This structure is passed to NGM_NETFLOW_SETIFINDEX */
struct ng_netflow_setifindex {
	u_int16_t iface;		/* which iface index change */
	u_int16_t index;		/* new index */
};

/* This structure is passed to NGM_NETFLOW_SETTIMEOUTS */
struct ng_netflow_settimeouts {
	uint32_t	inactive_timeout;	/* flow inactive timeout */
	uint32_t	active_timeout;		/* flow active timeout */
};

/* This is unique data, which identifies flow */
struct flow_rec {
	struct in_addr	r_src;
	struct in_addr	r_dst;
	union {
		struct {
			uint16_t	s_port;	/* source TCP/UDP port */
			uint16_t	d_port; /* destination TCP/UDP port */
		} dir;
		uint32_t both;
	} ports;
	union {
		struct {
			u_char		prot;	/* IP protocol */
			u_char		tos;	/* IP TOS */
			uint16_t	i_ifx;	/* input interface index */
		} i;
		uint32_t all;
	} misc;
};

#define	r_ip_p	misc.i.prot
#define	r_tos	misc.i.tos
#define	r_i_ifx	misc.i.i_ifx
#define r_misc	misc.all
#define r_ports	ports.both
#define r_sport	ports.dir.s_port
#define r_dport	ports.dir.d_port
	
/* A flow entry which accumulates statistics */
struct flow_entry_data {
	struct flow_rec		r;
	struct in_addr		next_hop;
	uint16_t		fle_o_ifx;	/* output interface index */
#define				fle_i_ifx	r.misc.i.i_ifx
	uint8_t		dst_mask;	/* destination route mask bits */
	uint8_t		src_mask;	/* source route mask bits */
	u_long			packets;
	u_long			bytes;
	long			first;	/* uptime on first packet */
	long			last;	/* uptime on last packet */
	u_char			tcp_flags;	/* cumulative OR */
};

/*
 * How many flow records we will transfer at once
 * without overflowing socket receive buffer
 */
#define NREC_AT_ONCE		1000
#define NGRESP_SIZE		(sizeof(struct ngnf_flows) + (NREC_AT_ONCE * \
				sizeof(struct flow_entry_data)))
#define SORCVBUF_SIZE		(NGRESP_SIZE + 2 * sizeof(struct ng_mesg))

/* This struct is returned to userland, when "show cache ip flow" */
struct ngnf_flows {
	uint32_t		nentries;
	uint32_t		last;
	struct flow_entry_data	entries[0];
};

/* Everything below is for kernel */

#ifdef _KERNEL

struct flow_entry {
	struct flow_entry_data	f;
	TAILQ_ENTRY(flow_entry)	fle_hash;	/* entries in hash slot */
};

/* Parsing declarations */

/* Parse the info structure */
#define	NG_NETFLOW_INFO_TYPE	{			\
	{ "Bytes",	&ng_parse_uint64_type },	\
	{ "Packets",	&ng_parse_uint32_type },	\
	{ "Records used",	&ng_parse_uint32_type },\
	{ "Failed allocations",	&ng_parse_uint32_type },\
	{ "Failed exports",	&ng_parse_uint32_type },\
	{ "Active expiries",	&ng_parse_uint32_type },\
	{ "Inactive expiries",	&ng_parse_uint32_type },\
	{ "Inactive timeout",	&ng_parse_uint32_type },\
	{ "Active timeout",	&ng_parse_uint32_type },\
	{ NULL }					\
}

/* Parse the ifinfo structure */
#define NG_NETFLOW_IFINFO_TYPE	{			\
	{ "packets",	&ng_parse_uint32_type },	\
	{ "data link type", &ng_parse_uint8_type },	\
	{ "index", &ng_parse_uint16_type },		\
	{ NULL }					\
}

/* Parse the setdlt structure */
#define	NG_NETFLOW_SETDLT_TYPE {			\
	{ "iface",	&ng_parse_uint16_type },	\
	{ "dlt",	&ng_parse_uint8_type  },	\
	{ NULL }					\
}

/* Parse the setifindex structure */
#define	NG_NETFLOW_SETIFINDEX_TYPE {			\
	{ "iface",	&ng_parse_uint16_type },	\
	{ "index",	&ng_parse_uint16_type },	\
	{ NULL }					\
}

/* Parse the settimeouts structure */
#define NG_NETFLOW_SETTIMEOUTS_TYPE {			\
	{ "inactive",	&ng_parse_uint32_type },	\
	{ "active",	&ng_parse_uint32_type },	\
	{ NULL }					\
}

/* Private hook data */
struct ng_netflow_iface {
	hook_p		hook;		/* NULL when disconnected */
	hook_p		out;		/* NULL when no bypass hook */
	struct ng_netflow_ifinfo	info;
};

typedef struct ng_netflow_iface *iface_p;
typedef struct ng_netflow_ifinfo *ifinfo_p;

/* Structure describing our flow engine */
struct netflow {
	node_p			node;		/* link to the node itself */
	hook_p			export;		/* export data goes there */

	struct ng_netflow_info	info;
	struct callout		exp_callout;	/* expiry periodic job */

	/*
	 * Flow entries are allocated in uma(9) zone zone. They are
	 * indexed by hash hash. Each hash element consist of tailqueue
	 * head and mutex to protect this element.
	 */
#define	CACHESIZE			(65536*4)
#define	CACHELOWAT			(CACHESIZE * 3/4)
#define	CACHEHIGHWAT			(CACHESIZE * 9/10)
	uma_zone_t		zone;
	struct flow_hash_entry	*hash;

	/*
	 * NetFlow data export
	 *
	 * export_item is a data item, it has an mbuf with cluster
	 * attached to it. A thread detaches export_item from priv
	 * and works with it. If the export is full it is sent, and
	 * a new one is allocated. Before exiting thread re-attaches
	 * its current item back to priv. If there is item already,
	 * current incomplete datagram is sent. 
	 * export_mtx is used for attaching/detaching.
	 */
	item_p			export_item;
	struct mtx		export_mtx;
	uint32_t		flow_seq;	/* current flow sequence */

	struct ng_netflow_iface	ifaces[NG_NETFLOW_MAXIFACES];
};

typedef struct netflow *priv_p;

/* Header of a small list in hash cell */
struct flow_hash_entry {
	struct mtx		mtx;
	TAILQ_HEAD(fhead, flow_entry) head;
};

#define	ERROUT(x)	{ error = (x); goto done; }

/* 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_show(priv_p, uint32_t last, struct ng_mesg *);

#endif	/* _KERNEL */
#endif	/* _NG_NETFLOW_H_ */
OpenPOWER on IntegriCloud