diff options
Diffstat (limited to 'src/vnet/ipfix-export')
-rw-r--r-- | src/vnet/ipfix-export/flow_api.c | 38 | ||||
-rw-r--r-- | src/vnet/ipfix-export/flow_report.c | 139 | ||||
-rw-r--r-- | src/vnet/ipfix-export/flow_report.h | 21 | ||||
-rw-r--r-- | src/vnet/ipfix-export/flow_report_classify.c | 14 |
4 files changed, 125 insertions, 87 deletions
diff --git a/src/vnet/ipfix-export/flow_api.c b/src/vnet/ipfix-export/flow_api.c index deee9d6909a..7e4f1fe8626 100644 --- a/src/vnet/ipfix-export/flow_api.c +++ b/src/vnet/ipfix-export/flow_api.c @@ -41,6 +41,7 @@ vl_api_set_ipfix_exporter_t_handler (vl_api_set_ipfix_exporter_t * mp) { vlib_main_t *vm = vlib_get_main (); flow_report_main_t *frm = &flow_report_main; + ipfix_exporter_t *exp = pool_elt_at_index (frm->exporters, 0); vl_api_registration_t *reg; vl_api_set_ipfix_exporter_reply_t *rmp; ip4_address_t collector, src; @@ -113,18 +114,18 @@ vl_api_set_ipfix_exporter_t_handler (vl_api_set_ipfix_exporter_t * mp) } /* Reset report streams if we are reconfiguring IP addresses */ - if (frm->ipfix_collector.as_u32 != collector.as_u32 || - frm->src_address.as_u32 != src.as_u32 || - frm->collector_port != collector_port) + if (exp->ipfix_collector.as_u32 != collector.as_u32 || + exp->src_address.as_u32 != src.as_u32 || + exp->collector_port != collector_port) vnet_flow_reports_reset (frm); - frm->ipfix_collector.as_u32 = collector.as_u32; - frm->collector_port = collector_port; - frm->src_address.as_u32 = src.as_u32; - frm->fib_index = fib_index; - frm->path_mtu = path_mtu; - frm->template_interval = template_interval; - frm->udp_checksum = udp_checksum; + exp->ipfix_collector.as_u32 = collector.as_u32; + exp->collector_port = collector_port; + exp->src_address.as_u32 = src.as_u32; + exp->fib_index = fib_index; + exp->path_mtu = path_mtu; + exp->template_interval = template_interval; + exp->udp_checksum = udp_checksum; /* Turn on the flow reporting process */ vlib_process_signal_event (vm, flow_report_process_node.index, 1, 0); @@ -137,6 +138,7 @@ static void vl_api_ipfix_exporter_dump_t_handler (vl_api_ipfix_exporter_dump_t * mp) { flow_report_main_t *frm = &flow_report_main; + ipfix_exporter_t *exp = pool_elt_at_index (flow_report_main.exporters, 0); vl_api_registration_t *reg; vl_api_ipfix_exporter_details_t *rmp; ip4_main_t *im = &ip4_main; @@ -154,22 +156,22 @@ vl_api_ipfix_exporter_dump_t_handler (vl_api_ipfix_exporter_dump_t * mp) ntohs ((REPLY_MSG_ID_BASE) + VL_API_IPFIX_EXPORTER_DETAILS); rmp->context = mp->context; - memcpy (&collector.ip4, &frm->ipfix_collector, sizeof (ip4_address_t)); + memcpy (&collector.ip4, &exp->ipfix_collector, sizeof (ip4_address_t)); ip_address_encode (&collector, IP46_TYPE_IP4, &rmp->collector_address); - rmp->collector_port = htons (frm->collector_port); + rmp->collector_port = htons (exp->collector_port); - memcpy (&src.ip4, &frm->src_address, sizeof (ip4_address_t)); + memcpy (&src.ip4, &exp->src_address, sizeof (ip4_address_t)); ip_address_encode (&src, IP46_TYPE_IP4, &rmp->src_address); - if (frm->fib_index == ~0) + if (exp->fib_index == ~0) vrf_id = ~0; else - vrf_id = im->fibs[frm->fib_index].ft_table_id; + vrf_id = im->fibs[exp->fib_index].ft_table_id; rmp->vrf_id = htonl (vrf_id); - rmp->path_mtu = htonl (frm->path_mtu); - rmp->template_interval = htonl (frm->template_interval); - rmp->udp_checksum = (frm->udp_checksum != 0); + rmp->path_mtu = htonl (exp->path_mtu); + rmp->template_interval = htonl (exp->template_interval); + rmp->udp_checksum = (exp->udp_checksum != 0); vl_api_send_msg (reg, (u8 *) rmp); } diff --git a/src/vnet/ipfix-export/flow_report.c b/src/vnet/ipfix-export/flow_report.c index 85839323b3e..a28f783130d 100644 --- a/src/vnet/ipfix-export/flow_report.c +++ b/src/vnet/ipfix-export/flow_report.c @@ -24,43 +24,45 @@ flow_report_main_t flow_report_main; static_always_inline u8 stream_index_valid (u32 index) { - flow_report_main_t *frm = &flow_report_main; - return index < vec_len (frm->streams) && - frm->streams[index].domain_id != ~0; + ipfix_exporter_t *exp = pool_elt_at_index (flow_report_main.exporters, 0); + + return index < vec_len (exp->streams) && exp->streams[index].domain_id != ~0; } static_always_inline flow_report_stream_t * add_stream (void) { - flow_report_main_t *frm = &flow_report_main; + ipfix_exporter_t *exp = pool_elt_at_index (flow_report_main.exporters, 0); + u32 i; - for (i = 0; i < vec_len (frm->streams); i++) + for (i = 0; i < vec_len (exp->streams); i++) if (!stream_index_valid (i)) - return &frm->streams[i]; - u32 index = vec_len (frm->streams); - vec_validate (frm->streams, index); - return &frm->streams[index]; + return &exp->streams[i]; + u32 index = vec_len (exp->streams); + vec_validate (exp->streams, index); + return &exp->streams[index]; } static_always_inline void delete_stream (u32 index) { - flow_report_main_t *frm = &flow_report_main; - ASSERT (index < vec_len (frm->streams)); - ASSERT (frm->streams[index].domain_id != ~0); - frm->streams[index].domain_id = ~0; + ipfix_exporter_t *exp = pool_elt_at_index (flow_report_main.exporters, 0); + + ASSERT (index < vec_len (exp->streams)); + ASSERT (exp->streams[index].domain_id != ~0); + exp->streams[index].domain_id = ~0; } static i32 find_stream (u32 domain_id, u16 src_port) { - flow_report_main_t *frm = &flow_report_main; + ipfix_exporter_t *exp = pool_elt_at_index (flow_report_main.exporters, 0); flow_report_stream_t *stream; u32 i; - for (i = 0; i < vec_len (frm->streams); i++) + for (i = 0; i < vec_len (exp->streams); i++) if (stream_index_valid (i)) { - stream = &frm->streams[i]; + stream = &exp->streams[i]; if (domain_id == stream->domain_id) { if (src_port != stream->src_port) @@ -87,12 +89,13 @@ send_template_packet (flow_report_main_t * frm, udp_header_t *udp; vlib_main_t *vm = frm->vlib_main; flow_report_stream_t *stream; + ipfix_exporter_t *exp = pool_elt_at_index (frm->exporters, 0); ASSERT (buffer_indexp); if (fr->update_rewrite || fr->rewrite == 0) { - if (frm->ipfix_collector.as_u32 == 0 || frm->src_address.as_u32 == 0) + if (exp->ipfix_collector.as_u32 == 0 || exp->src_address.as_u32 == 0) { vlib_node_set_state (frm->vlib_main, flow_report_process_node.index, VLIB_NODE_STATE_DISABLED); @@ -104,13 +107,9 @@ send_template_packet (flow_report_main_t * frm, if (fr->update_rewrite) { - fr->rewrite = fr->rewrite_callback (frm, fr, - &frm->ipfix_collector, - &frm->src_address, - frm->collector_port, - fr->report_elements, - fr->n_report_elements, - fr->stream_indexp); + fr->rewrite = fr->rewrite_callback ( + frm, fr, &exp->ipfix_collector, &exp->src_address, exp->collector_port, + fr->report_elements, fr->n_report_elements, fr->stream_indexp); fr->update_rewrite = 0; } @@ -126,7 +125,7 @@ send_template_packet (flow_report_main_t * frm, b0->current_length = vec_len (fr->rewrite); b0->flags |= (VLIB_BUFFER_TOTAL_LENGTH_VALID | VNET_BUFFER_F_FLOW_REPORT); vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0; - vnet_buffer (b0)->sw_if_index[VLIB_TX] = frm->fib_index; + vnet_buffer (b0)->sw_if_index[VLIB_TX] = exp->fib_index; tp = vlib_buffer_get_current (b0); ip = (ip4_header_t *) & tp->ip4; @@ -139,7 +138,7 @@ send_template_packet (flow_report_main_t * frm, (vlib_time_now (frm->vlib_main) - frm->vlib_time_0)); h->export_time = clib_host_to_net_u32 (h->export_time); - stream = &frm->streams[fr->stream_index]; + stream = &exp->streams[fr->stream_index]; /* FIXUP: message header sequence_number. Templates do not increase it */ h->sequence_number = clib_host_to_net_u32 (stream->sequence_number); @@ -147,7 +146,7 @@ send_template_packet (flow_report_main_t * frm, /* FIXUP: udp length */ udp->length = clib_host_to_net_u16 (b0->current_length - sizeof (*ip)); - if (frm->udp_checksum) + if (exp->udp_checksum) { /* RFC 7011 section 10.3.2. */ udp->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ip); @@ -183,12 +182,13 @@ vnet_flow_rewrite_generic_callback (flow_report_main_t * frm, flow_report_stream_t *stream; int i; ipfix_report_element_t *ep; + ipfix_exporter_t *exp = pool_elt_at_index (frm->exporters, 0); ASSERT (stream_indexp); ASSERT (n_elts); ASSERT (report_elts); - stream = &frm->streams[fr->stream_index]; + stream = &exp->streams[fr->stream_index]; *stream_indexp = fr->stream_index; /* allocate rewrite space */ @@ -284,18 +284,19 @@ flow_report_process (vlib_main_t * vm, vlib_process_wait_for_event_or_clock (vm, wait_time); event_type = vlib_process_get_events (vm, &event_data); vec_reset_length (event_data); + ipfix_exporter_t *exp = pool_elt_at_index (frm->exporters, 0); /* 5s delay by default, possibly reduced by template intervals */ wait_time = def_wait_time; - vec_foreach (fr, frm->reports) + vec_foreach (fr, exp->reports) { f64 next_template; now = vlib_time_now (vm); /* Need to send a template packet? */ send_template = - now > (fr->last_template_sent + frm->template_interval); + now > (fr->last_template_sent + exp->template_interval); send_template += fr->last_template_sent == 0; template_bi = ~0; rv = 0; @@ -308,7 +309,7 @@ flow_report_process (vlib_main_t * vm, /* decide if template should be sent sooner than current wait time */ next_template = - (fr->last_template_sent + frm->template_interval) - now; + (fr->last_template_sent + exp->template_interval) - now; wait_time = clib_min (wait_time, next_template); nf = vlib_get_frame_to_node (vm, ip4_lookup_node_index); @@ -350,6 +351,7 @@ vnet_flow_report_add_del (flow_report_main_t * frm, flow_report_t *fr; flow_report_stream_t *stream; u32 si; + ipfix_exporter_t *exp = pool_elt_at_index (frm->exporters, 0); si = find_stream (a->domain_id, a->src_port); if (si == -2) @@ -357,9 +359,9 @@ vnet_flow_report_add_del (flow_report_main_t * frm, if (si == -1 && a->is_add == 0) return VNET_API_ERROR_NO_SUCH_ENTRY; - for (i = 0; i < vec_len (frm->reports); i++) + for (i = 0; i < vec_len (exp->reports); i++) { - fr = vec_elt_at_index (frm->reports, i); + fr = vec_elt_at_index (exp->reports, i); if (fr->opaque.as_uword == a->opaque.as_uword && fr->rewrite_callback == a->rewrite_callback && fr->flow_data_callback == a->flow_data_callback) @@ -375,8 +377,8 @@ vnet_flow_report_add_del (flow_report_main_t * frm, { if (found_index != ~0) { - vec_delete (frm->reports, 1, found_index); - stream = &frm->streams[si]; + vec_delete (exp->reports, 1, found_index); + stream = &exp->streams[si]; stream->n_reports--; if (stream->n_reports == 0) delete_stream (si); @@ -395,14 +397,14 @@ vnet_flow_report_add_del (flow_report_main_t * frm, stream->src_port = a->src_port; stream->sequence_number = 0; stream->n_reports = 0; - si = stream - frm->streams; + si = stream - exp->streams; } else - stream = &frm->streams[si]; + stream = &exp->streams[si]; stream->n_reports++; - vec_add2 (frm->reports, fr, 1); + vec_add2 (exp->reports, fr, 1); fr->stream_index = si; fr->template_id = 256 + stream->next_template_no; @@ -446,12 +448,13 @@ vnet_flow_reports_reset (flow_report_main_t * frm) { flow_report_t *fr; u32 i; + ipfix_exporter_t *exp = pool_elt_at_index (frm->exporters, 0); - for (i = 0; i < vec_len (frm->streams); i++) + for (i = 0; i < vec_len (exp->streams); i++) if (stream_index_valid (i)) - frm->streams[i].sequence_number = 0; + exp->streams[i].sequence_number = 0; - vec_foreach (fr, frm->reports) + vec_foreach (fr, exp->reports) { fr->update_rewrite = 1; fr->last_template_sent = 0; @@ -462,11 +465,12 @@ void vnet_stream_reset (flow_report_main_t * frm, u32 stream_index) { flow_report_t *fr; + ipfix_exporter_t *exp = pool_elt_at_index (frm->exporters, 0); - frm->streams[stream_index].sequence_number = 0; + exp->streams[stream_index].sequence_number = 0; - vec_foreach (fr, frm->reports) - if (frm->reports->stream_index == stream_index) + vec_foreach (fr, exp->reports) + if (exp->reports->stream_index == stream_index) { fr->update_rewrite = 1; fr->last_template_sent = 0; @@ -478,10 +482,12 @@ vnet_stream_change (flow_report_main_t * frm, u32 old_domain_id, u16 old_src_port, u32 new_domain_id, u16 new_src_port) { + ipfix_exporter_t *exp = pool_elt_at_index (frm->exporters, 0); + i32 stream_index = find_stream (old_domain_id, old_src_port); if (stream_index < 0) return 1; - flow_report_stream_t *stream = &frm->streams[stream_index]; + flow_report_stream_t *stream = &exp->streams[stream_index]; stream->domain_id = new_domain_id; stream->src_port = new_src_port; if (old_domain_id != new_domain_id || old_src_port != new_src_port) @@ -505,6 +511,7 @@ set_ipfix_exporter_command_fn (vlib_main_t * vm, u32 path_mtu = 512; // RFC 7011 section 10.3.3. u32 template_interval = 20; u8 udp_checksum = 0; + ipfix_exporter_t *exp = pool_elt_at_index (frm->exporters, 0); while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { @@ -543,28 +550,28 @@ set_ipfix_exporter_command_fn (vlib_main_t * vm, return clib_error_return (0, "too small path-mtu value, minimum is 68"); /* Reset report streams if we are reconfiguring IP addresses */ - if (frm->ipfix_collector.as_u32 != collector.as_u32 || - frm->src_address.as_u32 != src.as_u32 || - frm->collector_port != collector_port) + if (exp->ipfix_collector.as_u32 != collector.as_u32 || + exp->src_address.as_u32 != src.as_u32 || + exp->collector_port != collector_port) vnet_flow_reports_reset (frm); - frm->ipfix_collector.as_u32 = collector.as_u32; - frm->collector_port = collector_port; - frm->src_address.as_u32 = src.as_u32; - frm->fib_index = fib_index; - frm->path_mtu = path_mtu; - frm->template_interval = template_interval; - frm->udp_checksum = udp_checksum; + exp->ipfix_collector.as_u32 = collector.as_u32; + exp->collector_port = collector_port; + exp->src_address.as_u32 = src.as_u32; + exp->fib_index = fib_index; + exp->path_mtu = path_mtu; + exp->template_interval = template_interval; + exp->udp_checksum = udp_checksum; if (collector.as_u32) - vlib_cli_output (vm, "Collector %U, src address %U, " + vlib_cli_output (vm, + "Collector %U, src address %U, " "fib index %d, path MTU %u, " "template resend interval %us, " "udp checksum %s", - format_ip4_address, &frm->ipfix_collector, - format_ip4_address, &frm->src_address, - fib_index, path_mtu, template_interval, - udp_checksum ? "enabled" : "disabled"); + format_ip4_address, exp->ipfix_collector, + format_ip4_address, exp->src_address, fib_index, path_mtu, + template_interval, udp_checksum ? "enabled" : "disabled"); else vlib_cli_output (vm, "IPFIX Collector is disabled"); @@ -608,13 +615,21 @@ static clib_error_t * flow_report_init (vlib_main_t * vm) { flow_report_main_t *frm = &flow_report_main; + ipfix_exporter_t *exp; frm->vlib_main = vm; frm->vnet_main = vnet_get_main (); frm->unix_time_0 = time (0); frm->vlib_time_0 = vlib_time_now (frm->vlib_main); - frm->fib_index = ~0; - + /* + * Make sure that we can always access the first exporter for + * backwards compatibility reasons. + */ + pool_alloc (frm->exporters, IPFIX_EXPORTERS_MAX); + pool_get (frm->exporters, exp); + /* Verify that this is at index 0 */ + ASSERT (frm->exporters == exp); + exp->fib_index = ~0; return 0; } diff --git a/src/vnet/ipfix-export/flow_report.h b/src/vnet/ipfix-export/flow_report.h index 30df8a93c82..d1f308011b8 100644 --- a/src/vnet/ipfix-export/flow_report.h +++ b/src/vnet/ipfix-export/flow_report.h @@ -107,7 +107,16 @@ typedef struct flow_report vnet_flow_data_callback_t *flow_data_callback; } flow_report_t; -typedef struct flow_report_main +/* + * The maximum number of ipfix exporters we can have at once + */ +#define IPFIX_EXPORTERS_MAX 5 + +/* + * We support multiple exporters. Each one has its own configured + * destination, and its own set of reports and streams. + */ +typedef struct ipfix_exporter { flow_report_t *reports; flow_report_stream_t *streams; @@ -126,6 +135,16 @@ typedef struct flow_report_main /* UDP checksum calculation enable flag */ u8 udp_checksum; +} ipfix_exporter_t; + +typedef struct flow_report_main +{ + /* + * A pool of the exporters. Entry 0 is always there for backwards + * compatability reasons. Entries 1 and above have to be created by + * the users. + */ + ipfix_exporter_t *exporters; /* time scale transform. Joy. */ u32 unix_time_0; diff --git a/src/vnet/ipfix-export/flow_report_classify.c b/src/vnet/ipfix-export/flow_report_classify.c index 21b6411a292..35abf979bd9 100644 --- a/src/vnet/ipfix-export/flow_report_classify.c +++ b/src/vnet/ipfix-export/flow_report_classify.c @@ -60,8 +60,9 @@ ipfix_classify_template_rewrite (flow_report_main_t * frm, u8 transport_protocol; u8 *virt_mask; u8 *real_mask; + ipfix_exporter_t *exp = pool_elt_at_index (frm->exporters, 0); - stream = &frm->streams[fr->stream_index]; + stream = &exp->streams[fr->stream_index]; ipfix_classify_table_t *table = &fcm->tables[flow_table_index]; @@ -190,8 +191,9 @@ ipfix_classify_send_flows (flow_report_main_t * frm, u8 ip_version; u8 transport_protocol; u8 *virt_key; + ipfix_exporter_t *exp = pool_elt_at_index (frm->exporters, 0); - stream = &frm->streams[fr->stream_index]; + stream = &exp->streams[fr->stream_index]; ipfix_classify_table_t *table = &fcm->tables[flow_table_index]; @@ -233,7 +235,7 @@ ipfix_classify_send_flows (flow_report_main_t * frm, b0->current_length = copy_len; b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID; vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0; - vnet_buffer (b0)->sw_if_index[VLIB_TX] = frm->fib_index; + vnet_buffer (b0)->sw_if_index[VLIB_TX] = exp->fib_index; tp = vlib_buffer_get_current (b0); ip = (ip4_header_t *) & tp->ip4; @@ -285,7 +287,7 @@ ipfix_classify_send_flows (flow_report_main_t * frm, u32 next_record_size = next_offset - record_offset; record_offset = next_offset; - if (next_offset + next_record_size > frm->path_mtu) + if (next_offset + next_record_size > exp->path_mtu) { s->set_id_length = ipfix_set_id_length (fr->template_id, next_offset - @@ -314,7 +316,7 @@ ipfix_classify_send_flows (flow_report_main_t * frm, udp->length = clib_host_to_net_u16 (b0->current_length - sizeof (*ip)); - if (frm->udp_checksum) + if (exp->udp_checksum) { /* RFC 7011 section 10.3.2. */ udp->checksum = @@ -370,7 +372,7 @@ flush: ip->length = new_l0; udp->length = clib_host_to_net_u16 (b0->current_length - sizeof (*ip)); - if (frm->udp_checksum) + if (exp->udp_checksum) { /* RFC 7011 section 10.3.2. */ udp->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ip); |