diff options
-rw-r--r-- | src/vnet/ipfix-export/flow_api.c | 81 | ||||
-rw-r--r-- | src/vnet/ipfix-export/flow_report.c | 87 | ||||
-rw-r--r-- | src/vnet/ipfix-export/flow_report.h | 6 | ||||
-rw-r--r-- | src/vnet/ipfix-export/ipfix_export.api | 40 |
4 files changed, 169 insertions, 45 deletions
diff --git a/src/vnet/ipfix-export/flow_api.c b/src/vnet/ipfix-export/flow_api.c index dc163fe1e0a..47e1d1103a2 100644 --- a/src/vnet/ipfix-export/flow_api.c +++ b/src/vnet/ipfix-export/flow_api.c @@ -36,15 +36,39 @@ #define REPLY_MSG_ID_BASE frm->msg_id_base #include <vlibapi/api_helper_macros.h> +ipfix_exporter_t * +vnet_ipfix_exporter_lookup (ip4_address_t *ipfix_collector) +{ + flow_report_main_t *frm = &flow_report_main; + ipfix_exporter_t *exp; + + pool_foreach (exp, frm->exporters) + { + if (exp->ipfix_collector.as_u32 == ipfix_collector->as_u32) + return exp; + } + + return NULL; +} + +/* + * For backwards compatibility reasons index 0 in the set of exporters + * is alwyas used for the exporter created via the set_ipfix_exporter + * API. + */ +#define USE_INDEX_0 true +#define USE_ANY_INDEX false + static int vl_api_set_ipfix_exporter_t_internal ( u32 client_index, vl_api_address_t *mp_collector_address, u16 mp_collector_port, vl_api_address_t *mp_src_address, u32 mp_vrf_id, - u32 mp_path_mtu, u32 mp_template_interval, bool mp_udp_checksum) + u32 mp_path_mtu, u32 mp_template_interval, bool mp_udp_checksum, + bool use_index_0, bool is_create) { 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); + ipfix_exporter_t *exp; vl_api_registration_t *reg; ip4_address_t collector, src; u16 collector_port = UDP_DST_PORT_ipfix; @@ -58,13 +82,48 @@ vl_api_set_ipfix_exporter_t_internal ( if (!reg) return VNET_API_ERROR_UNIMPLEMENTED; + /* Collector address is the key for the exporter lookup */ + ip4_address_decode (mp_collector_address->un.ip4, &collector); + + if (use_index_0) + /* + * In this case we update the existing exporter. There is no delete + * for exp[0] + */ + exp = &frm->exporters[0]; + else + { + if (is_create) + { + exp = vnet_ipfix_exporter_lookup (&collector); + if (!exp) + { + /* Create a new exporter instead of updating an existing one */ + if (pool_elts (frm->exporters) >= IPFIX_EXPORTERS_MAX) + return VNET_API_ERROR_INVALID_VALUE; + pool_get (frm->exporters, exp); + if (!exp) + return VNET_API_ERROR_INVALID_VALUE; + } + } + else + { + /* Delete the exporter */ + exp = vnet_ipfix_exporter_lookup (&collector); + if (!exp) + return VNET_API_ERROR_NO_SUCH_ENTRY; + + pool_put (frm->exporters, exp); + return 0; + } + } + if (mp_src_address->af == ADDRESS_IP6 || mp_collector_address->af == ADDRESS_IP6) { return VNET_API_ERROR_UNIMPLEMENTED; } - ip4_address_decode (mp_collector_address->un.ip4, &collector); collector_port = ntohs (mp_collector_port); if (collector_port == (u16) ~ 0) collector_port = UDP_DST_PORT_ipfix; @@ -129,12 +188,26 @@ vl_api_set_ipfix_exporter_t_handler (vl_api_set_ipfix_exporter_t *mp) int rv = vl_api_set_ipfix_exporter_t_internal ( mp->client_index, &mp->collector_address, mp->collector_port, &mp->src_address, mp->vrf_id, mp->path_mtu, mp->template_interval, - mp->udp_checksum); + mp->udp_checksum, USE_INDEX_0, 0); REPLY_MACRO (VL_API_SET_IPFIX_EXPORTER_REPLY); } static void +vl_api_ipfix_exporter_create_delete_t_handler ( + vl_api_ipfix_exporter_create_delete_t *mp) +{ + vl_api_ipfix_exporter_create_delete_reply_t *rmp; + flow_report_main_t *frm = &flow_report_main; + int rv = vl_api_set_ipfix_exporter_t_internal ( + mp->client_index, &mp->collector_address, mp->collector_port, + &mp->src_address, mp->vrf_id, mp->path_mtu, mp->template_interval, + mp->udp_checksum, USE_ANY_INDEX, mp->is_create); + + REPLY_MACRO (VL_API_IPFIX_EXPORTER_CREATE_DELETE_REPLY); +} + +static void vl_api_ipfix_exporter_dump_t_handler (vl_api_ipfix_exporter_dump_t * mp) { flow_report_main_t *frm = &flow_report_main; diff --git a/src/vnet/ipfix-export/flow_report.c b/src/vnet/ipfix-export/flow_report.c index cc042799d5a..38c2454faef 100644 --- a/src/vnet/ipfix-export/flow_report.c +++ b/src/vnet/ipfix-export/flow_report.c @@ -71,8 +71,8 @@ find_stream (ipfix_exporter_t *exp, u32 domain_id, u16 src_port) } int -send_template_packet (flow_report_main_t * frm, - flow_report_t * fr, u32 * buffer_indexp) +send_template_packet (flow_report_main_t *frm, ipfix_exporter_t *exp, + flow_report_t *fr, u32 *buffer_indexp) { u32 bi0; vlib_buffer_t *b0; @@ -82,7 +82,6 @@ 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); @@ -275,49 +274,55 @@ 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, exp->reports) + ipfix_exporter_t *exp; + pool_foreach (exp, frm->exporters) { - f64 next_template; - now = vlib_time_now (vm); - - /* Need to send a template packet? */ - send_template = - now > (fr->last_template_sent + exp->template_interval); - send_template += fr->last_template_sent == 0; - template_bi = ~0; - rv = 0; - if (send_template) - rv = send_template_packet (frm, fr, &template_bi); + /* 5s delay by default, possibly reduced by template intervals */ + wait_time = def_wait_time; - if (rv < 0) - continue; - - /* decide if template should be sent sooner than current wait time */ - next_template = - (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); - nf->n_vectors = 0; - to_next = vlib_frame_vector_args (nf); - - if (template_bi != ~0) + vec_foreach (fr, exp->reports) { - to_next[0] = template_bi; - to_next++; - nf->n_vectors++; + f64 next_template; + now = vlib_time_now (vm); + + /* Need to send a template packet? */ + send_template = + now > (fr->last_template_sent + exp->template_interval); + send_template += fr->last_template_sent == 0; + template_bi = ~0; + rv = 0; + + if (send_template) + rv = send_template_packet (frm, exp, fr, &template_bi); + + if (rv < 0) + continue; + + /* + * decide if template should be sent sooner than current wait + * time + */ + next_template = + (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); + nf->n_vectors = 0; + to_next = vlib_frame_vector_args (nf); + + if (template_bi != ~0) + { + to_next[0] = template_bi; + to_next++; + nf->n_vectors++; + } + + nf = fr->flow_data_callback (frm, exp, fr, nf, to_next, + ip4_lookup_node_index); + if (nf) + vlib_put_frame_to_node (vm, ip4_lookup_node_index, nf); } - - nf = fr->flow_data_callback (frm, exp, fr, nf, to_next, - ip4_lookup_node_index); - if (nf) - vlib_put_frame_to_node (vm, ip4_lookup_node_index, nf); } } diff --git a/src/vnet/ipfix-export/flow_report.h b/src/vnet/ipfix-export/flow_report.h index 7f0c92d3a92..65ddebcac3e 100644 --- a/src/vnet/ipfix-export/flow_report.h +++ b/src/vnet/ipfix-export/flow_report.h @@ -20,6 +20,7 @@ #include <vnet/ethernet/ethernet.h> #include <vnet/ethernet/packet.h> #include <vnet/ip/ip_packet.h> +#include <vnet/ip/ip_types.h> #include <vnet/ip/ip4_packet.h> #include <vnet/ip/ip6_packet.h> #include <vnet/udp/udp_packet.h> @@ -185,6 +186,11 @@ void vnet_stream_reset (ipfix_exporter_t *exp, u32 stream_index); int vnet_stream_change (ipfix_exporter_t *exp, u32 old_domain_id, u16 old_src_port, u32 new_domain_id, u16 new_src_port); +/* + * Search all the exporters for one that has a matching destination address. + */ +ipfix_exporter_t *vnet_ipfix_exporter_lookup (ip4_address_t *ipfix_collector); + #endif /* __included_vnet_flow_report_h__ */ /* diff --git a/src/vnet/ipfix-export/ipfix_export.api b/src/vnet/ipfix-export/ipfix_export.api index a70b72bee39..2b1da36b581 100644 --- a/src/vnet/ipfix-export/ipfix_export.api +++ b/src/vnet/ipfix-export/ipfix_export.api @@ -73,6 +73,46 @@ define ipfix_exporter_details bool udp_checksum; }; + +/** Configure IPFIX exporter within the exporting process. + The exporting process can contain multiple independent exporters, + each of which have their own state. The collector_address is the key + field that identifies a unique exporter. The already existing API + 'set_ipfix_exporter' is used to modify a single exporter (which will + always have stat index 0). If more than one exporter is required then + they can be created and deleted using this API. + + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param is_create - True for create, False for delete + @param collector_address - address of IPFIX collector + @param collector_port - port of IPFIX collector + @param src_address - address of IPFIX exporter + @param vrf_id - VRF / fib table ID + @param path_mtu - Path MTU between exporter and collector + @param template_interval - number of seconds after which to resend template + @param udp_checksum - UDP checksum calculation enable flag +*/ + +define ipfix_exporter_create_delete { + u32 client_index; + u32 context; + bool is_create; + vl_api_address_t collector_address; + u16 collector_port; + vl_api_address_t src_address; + u32 vrf_id; + u32 path_mtu; + u32 template_interval; + bool udp_checksum; +}; + +define ipfix_exporter_create_delete_reply { + u32 context; + i32 retval; + u32 stat_index; +}; + /** \brief IPFIX classify stream configure request @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request |