summaryrefslogtreecommitdiffstats
path: root/src/vnet/ipfix-export
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet/ipfix-export')
-rw-r--r--src/vnet/ipfix-export/flow_api.c81
-rw-r--r--src/vnet/ipfix-export/flow_report.c87
-rw-r--r--src/vnet/ipfix-export/flow_report.h6
-rw-r--r--src/vnet/ipfix-export/ipfix_export.api40
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