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