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