diff options
author | Juraj Sloboda <jsloboda@cisco.com> | 2016-08-07 23:43:42 -0700 |
---|---|---|
committer | Damjan Marion <dmarion.lists@gmail.com> | 2016-09-07 07:35:50 +0000 |
commit | ffa652afd8847438af4d0bdc253789a67a4f1da1 (patch) | |
tree | 015e35fab6437930af127a16b4db68ff7dc0b4bb /vpp | |
parent | d4798a394a337ad11c306309bb68611251b4e593 (diff) |
VPP-204 Rework and finish IPFIX implementation
Rework flow report registration system - add streams
Add support for IPv6 and src and dst ports for TCP and UDP protocols
Implement binary API for IPFIX classifier module
Change-Id: Id05cc0127a7b95ceaeebf9c79a32c6936449bd63
Signed-off-by: Juraj Sloboda <jsloboda@cisco.com>
Diffstat (limited to 'vpp')
-rw-r--r-- | vpp/vpp-api/api.c | 221 | ||||
-rw-r--r-- | vpp/vpp-api/custom_dump.c | 68 | ||||
-rw-r--r-- | vpp/vpp-api/vpe.api | 114 |
3 files changed, 370 insertions, 33 deletions
diff --git a/vpp/vpp-api/api.c b/vpp/vpp-api/api.c index c339cb44..36532434 100644 --- a/vpp/vpp-api/api.c +++ b/vpp/vpp-api/api.c @@ -84,6 +84,7 @@ #include <vnet/devices/netmap/netmap.h> #include <vnet/flow/flow_report.h> #include <vnet/ipsec-gre/ipsec_gre.h> +#include <vnet/flow/flow_report_classify.h> #undef BIHASH_TYPE #undef __included_bihash_template_h__ @@ -391,8 +392,12 @@ _(CLASSIFY_TABLE_BY_INTERFACE, classify_table_by_interface) \ _(CLASSIFY_TABLE_INFO,classify_table_info) \ _(CLASSIFY_SESSION_DUMP,classify_session_dump) \ _(CLASSIFY_SESSION_DETAILS,classify_session_details) \ -_(IPFIX_ENABLE,ipfix_enable) \ -_(IPFIX_DUMP,ipfix_dump) \ +_(SET_IPFIX_EXPORTER, set_ipfix_exporter) \ +_(IPFIX_EXPORTER_DUMP, ipfix_exporter_dump) \ +_(SET_IPFIX_CLASSIFY_STREAM, set_ipfix_classify_stream) \ +_(IPFIX_CLASSIFY_STREAM_DUMP, ipfix_classify_stream_dump) \ +_(IPFIX_CLASSIFY_TABLE_ADD_DEL, ipfix_classify_table_add_del) \ +_(IPFIX_CLASSIFY_TABLE_DUMP, ipfix_classify_table_dump) \ _(GET_NEXT_INDEX, get_next_index) \ _(PG_CREATE_INTERFACE, pg_create_interface) \ _(PG_CAPTURE, pg_capture) \ @@ -7928,15 +7933,16 @@ vl_api_classify_session_dump_t_handler (vl_api_classify_session_dump_t * mp) } static void -vl_api_ipfix_enable_t_handler (vl_api_ipfix_enable_t * mp) +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; - vl_api_ipfix_enable_reply_t *rmp; + vl_api_set_ipfix_exporter_reply_t *rmp; ip4_address_t collector, src; u16 collector_port = UDP_DST_PORT_ipfix; u32 path_mtu; u32 template_interval; + u8 udp_checksum; u32 fib_id; u32 fib_index = ~0; int rv = 0; @@ -7949,13 +7955,20 @@ vl_api_ipfix_enable_t_handler (vl_api_ipfix_enable_t * mp) fib_id = ntohl (mp->vrf_id); ip4_main_t *im = &ip4_main; - uword *p = hash_get (im->fib_index_by_table_id, fib_id); - if (!p) + if (fib_id == ~0) { - rv = VNET_API_ERROR_NO_SUCH_FIB; - goto out; + fib_index = ~0; + } + else + { + uword *p = hash_get (im->fib_index_by_table_id, fib_id); + if (!p) + { + rv = VNET_API_ERROR_NO_SUCH_FIB; + goto out; + } + fib_index = p[0]; } - fib_index = p[0]; path_mtu = ntohl (mp->path_mtu); if (path_mtu == ~0) @@ -7963,6 +7976,7 @@ vl_api_ipfix_enable_t_handler (vl_api_ipfix_enable_t * mp) template_interval = ntohl (mp->template_interval); if (template_interval == ~0) template_interval = 20; + udp_checksum = mp->udp_checksum; if (collector.as_u32 == 0) { @@ -8000,20 +8014,23 @@ vl_api_ipfix_enable_t_handler (vl_api_ipfix_enable_t * mp) frm->fib_index = fib_index; frm->path_mtu = path_mtu; frm->template_interval = template_interval; + frm->udp_checksum = udp_checksum; /* Turn on the flow reporting process */ vlib_process_signal_event (vm, flow_report_process_node.index, 1, 0); out: - REPLY_MACRO (VL_API_IPFIX_ENABLE_REPLY); + REPLY_MACRO (VL_API_SET_IPFIX_EXPORTER_REPLY); } static void -vl_api_ipfix_dump_t_handler (vl_api_ipfix_dump_t * mp) +vl_api_ipfix_exporter_dump_t_handler (vl_api_ipfix_exporter_dump_t * mp) { flow_report_main_t *frm = &flow_report_main; unix_shared_memory_queue_t *q; - vl_api_ipfix_details_t *rmp; + vl_api_ipfix_exporter_details_t *rmp; + ip4_main_t *im = &ip4_main; + u32 vrf_id; q = vl_api_client_index_to_input_queue (mp->client_index); if (!q) @@ -8021,21 +8038,197 @@ vl_api_ipfix_dump_t_handler (vl_api_ipfix_dump_t * mp) rmp = vl_msg_api_alloc (sizeof (*rmp)); memset (rmp, 0, sizeof (*rmp)); - rmp->_vl_msg_id = ntohs (VL_API_IPFIX_DETAILS); + rmp->_vl_msg_id = ntohs (VL_API_IPFIX_EXPORTER_DETAILS); rmp->context = mp->context; memcpy (rmp->collector_address, frm->ipfix_collector.data, sizeof (frm->ipfix_collector.data)); rmp->collector_port = htons (frm->collector_port); memcpy (rmp->src_address, frm->src_address.data, sizeof (frm->src_address.data)); - rmp->fib_index = htonl (frm->fib_index); + if (frm->fib_index == ~0) + vrf_id = ~0; + else + vrf_id = im->fibs[frm->fib_index].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); + + vl_msg_api_send_shmem (q, (u8 *) & rmp); +} + +static void + vl_api_set_ipfix_classify_stream_t_handler + (vl_api_set_ipfix_classify_stream_t * mp) +{ + vl_api_set_ipfix_classify_stream_reply_t *rmp; + flow_report_classify_main_t *fcm = &flow_report_classify_main; + flow_report_main_t *frm = &flow_report_main; + u32 domain_id = 0; + u32 src_port = UDP_DST_PORT_ipfix; + int rv = 0; + + domain_id = ntohl (mp->domain_id); + src_port = ntohs (mp->src_port); + + if (fcm->src_port != 0 && + (fcm->domain_id != domain_id || fcm->src_port != (u16) src_port)) + { + int rv = vnet_stream_change (frm, fcm->domain_id, fcm->src_port, + domain_id, (u16) src_port); + ASSERT (rv == 0); + } + + fcm->domain_id = domain_id; + fcm->src_port = (u16) src_port; + + REPLY_MACRO (VL_API_SET_IPFIX_CLASSIFY_STREAM_REPLY); +} + +static void + vl_api_ipfix_classify_stream_dump_t_handler + (vl_api_ipfix_classify_stream_dump_t * mp) +{ + flow_report_classify_main_t *fcm = &flow_report_classify_main; + unix_shared_memory_queue_t *q; + vl_api_ipfix_classify_stream_details_t *rmp; + + q = vl_api_client_index_to_input_queue (mp->client_index); + + rmp = vl_msg_api_alloc (sizeof (*rmp)); + memset (rmp, 0, sizeof (*rmp)); + rmp->_vl_msg_id = ntohs (VL_API_IPFIX_CLASSIFY_STREAM_DETAILS); + rmp->context = mp->context; + rmp->domain_id = htonl (fcm->domain_id); + rmp->src_port = htons (fcm->src_port); vl_msg_api_send_shmem (q, (u8 *) & rmp); } static void + vl_api_ipfix_classify_table_add_del_t_handler + (vl_api_ipfix_classify_table_add_del_t * mp) +{ + vl_api_ipfix_classify_table_add_del_reply_t *rmp; + flow_report_classify_main_t *fcm = &flow_report_classify_main; + flow_report_main_t *frm = &flow_report_main; + vnet_flow_report_add_del_args_t args; + ipfix_classify_table_t *table; + int is_add; + u32 classify_table_index; + u8 ip_version; + u8 transport_protocol; + int rv = 0; + + classify_table_index = ntohl (mp->table_id); + ip_version = mp->ip_version; + transport_protocol = mp->transport_protocol; + is_add = mp->is_add; + + if (fcm->src_port == 0) + { + /* call set_ipfix_classify_stream first */ + rv = VNET_API_ERROR_UNSPECIFIED; + goto out; + } + + memset (&args, 0, sizeof (args)); + + table = 0; + int i; + for (i = 0; i < vec_len (fcm->tables); i++) + if (ipfix_classify_table_index_valid (i)) + if (fcm->tables[i].classify_table_index == classify_table_index) + { + table = &fcm->tables[i]; + break; + } + + if (is_add) + { + if (table) + { + rv = VNET_API_ERROR_VALUE_EXIST; + goto out; + } + table = ipfix_classify_add_table (); + table->classify_table_index = classify_table_index; + } + else + { + if (!table) + { + rv = VNET_API_ERROR_NO_SUCH_ENTRY; + goto out; + } + } + + table->ip_version = ip_version; + table->transport_protocol = transport_protocol; + + args.opaque.as_uword = table - fcm->tables; + args.rewrite_callback = ipfix_classify_template_rewrite; + args.flow_data_callback = ipfix_classify_send_flows; + args.is_add = is_add; + args.domain_id = fcm->domain_id; + args.src_port = fcm->src_port; + + rv = vnet_flow_report_add_del (frm, &args); + if (rv != 0) + goto out; + + if (is_add) + { + if (rv != 0) + ipfix_classify_delete_table (table - fcm->tables); + } + else + { + if (rv == 0) + ipfix_classify_delete_table (table - fcm->tables); + } + +out: + REPLY_MACRO (VL_API_SET_IPFIX_CLASSIFY_STREAM_REPLY); +} + +static void +send_ipfix_classify_table_details (u32 table_index, + unix_shared_memory_queue_t * q, + u32 context) +{ + flow_report_classify_main_t *fcm = &flow_report_classify_main; + vl_api_ipfix_classify_table_details_t *mp; + + ipfix_classify_table_t *table = &fcm->tables[table_index]; + + mp = vl_msg_api_alloc (sizeof (*mp)); + memset (mp, 0, sizeof (*mp)); + mp->_vl_msg_id = ntohs (VL_API_IPFIX_CLASSIFY_TABLE_DETAILS); + mp->context = context; + mp->table_id = htonl (table->classify_table_index); + mp->ip_version = table->ip_version; + mp->transport_protocol = table->transport_protocol; + + vl_msg_api_send_shmem (q, (u8 *) & mp); +} + +static void + vl_api_ipfix_classify_table_dump_t_handler + (vl_api_ipfix_classify_table_dump_t * mp) +{ + flow_report_classify_main_t *fcm = &flow_report_classify_main; + unix_shared_memory_queue_t *q; + u32 i; + + q = vl_api_client_index_to_input_queue (mp->client_index); + + for (i = 0; i < vec_len (fcm->tables); i++) + if (ipfix_classify_table_index_valid (i)) + send_ipfix_classify_table_details (i, q, mp->context); +} + +static void vl_api_pg_create_interface_t_handler (vl_api_pg_create_interface_t * mp) { vl_api_pg_create_interface_reply_t *rmp; diff --git a/vpp/vpp-api/custom_dump.c b/vpp/vpp-api/custom_dump.c index 5ca7ccc9..e8ee5516 100644 --- a/vpp/vpp-api/custom_dump.c +++ b/vpp/vpp-api/custom_dump.c @@ -2093,12 +2093,12 @@ static void *vl_api_classify_session_dump_t_print FINISH; } -static void *vl_api_ipfix_enable_t_print - (vl_api_ipfix_enable_t * mp, void *handle) +static void *vl_api_set_ipfix_exporter_t_print + (vl_api_set_ipfix_exporter_t * mp, void *handle) { u8 *s; - s = format (0, "SCRIPT: ipfix_enable "); + s = format (0, "SCRIPT: set_ipfix_exporter "); s = format (s, "collector-address %U ", format_ip4_address, (ip4_address_t *) mp->collector_address); @@ -2108,16 +2108,64 @@ static void *vl_api_ipfix_enable_t_print s = format (s, "vrf-id %d ", ntohl (mp->vrf_id)); s = format (s, "path-mtu %d ", ntohl (mp->path_mtu)); s = format (s, "template-interval %d ", ntohl (mp->template_interval)); + s = format (s, "udp-checksum %d ", mp->udp_checksum); FINISH; } -static void *vl_api_ipfix_dump_t_print - (vl_api_ipfix_dump_t * mp, void *handle) +static void *vl_api_ipfix_exporter_dump_t_print + (vl_api_ipfix_exporter_dump_t * mp, void *handle) { u8 *s; - s = format (0, "SCRIPT: ipfix_dump "); + s = format (0, "SCRIPT: ipfix_exporter_dump "); + + FINISH; +} + +static void *vl_api_set_ipfix_classify_stream_t_print + (vl_api_set_ipfix_classify_stream_t * mp, void *handle) +{ + u8 *s; + + s = format (0, "SCRIPT: set_ipfix_classify_stream "); + + s = format (s, "domain-id %d ", ntohl (mp->domain_id)); + s = format (s, "src-port %d ", ntohs (mp->src_port)); + + FINISH; +} + +static void *vl_api_ipfix_classify_stream_dump_t_print + (vl_api_ipfix_classify_stream_dump_t * mp, void *handle) +{ + u8 *s; + + s = format (0, "SCRIPT: ipfix_classify_stream_dump "); + + FINISH; +} + +static void *vl_api_ipfix_classify_table_add_del_t_print + (vl_api_ipfix_classify_table_add_del_t * mp, void *handle) +{ + u8 *s; + + s = format (0, "SCRIPT: ipfix_classify_table_add_del "); + + s = format (s, "table-id %d ", ntohl (mp->table_id)); + s = format (s, "ip-version %d ", mp->ip_version); + s = format (s, "transport-protocol %d ", mp->transport_protocol); + + FINISH; +} + +static void *vl_api_ipfix_classify_table_dump_t_print + (vl_api_ipfix_classify_table_dump_t * mp, void *handle) +{ + u8 *s; + + s = format (0, "SCRIPT: ipfix_classify_table_dump "); FINISH; } @@ -2733,8 +2781,12 @@ _(CLASSIFY_TABLE_IDS,classify_table_ids) \ _(CLASSIFY_TABLE_BY_INTERFACE, classify_table_by_interface) \ _(CLASSIFY_TABLE_INFO,classify_table_info) \ _(CLASSIFY_SESSION_DUMP,classify_session_dump) \ -_(IPFIX_ENABLE,ipfix_enable) \ -_(IPFIX_DUMP,ipfix_dump) \ +_(SET_IPFIX_EXPORTER, set_ipfix_exporter) \ +_(IPFIX_EXPORTER_DUMP, ipfix_exporter_dump) \ +_(SET_IPFIX_CLASSIFY_STREAM, set_ipfix_classify_stream) \ +_(IPFIX_CLASSIFY_STREAM_DUMP, ipfix_classify_stream_dump) \ +_(IPFIX_CLASSIFY_TABLE_ADD_DEL, ipfix_classify_table_add_del) \ +_(IPFIX_CLASSIFY_TABLE_DUMP, ipfix_classify_table_dump) \ _(GET_NEXT_INDEX, get_next_index) \ _(PG_CREATE_INTERFACE,pg_create_interface) \ _(PG_CAPTURE, pg_capture) \ diff --git a/vpp/vpp-api/vpe.api b/vpp/vpp-api/vpe.api index 5c1502a8..11bb30c1 100644 --- a/vpp/vpp-api/vpe.api +++ b/vpp/vpp-api/vpe.api @@ -4570,17 +4570,18 @@ define classify_session_details u8 match[match_length]; }; -/** \brief Enable and configure IPFIX exporter process request +/** \brief Configure IPFIX exporter process request @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request @param collector_address - address of IPFIX collector - @param collector_port - port of IPFIX 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_enable +define set_ipfix_exporter { u32 client_index; u32 context; @@ -4590,45 +4591,136 @@ define ipfix_enable u32 vrf_id; u32 path_mtu; u32 template_interval; + u8 udp_checksum; }; -/** \brief Reply to IPFIX enable and configure request +/** \brief Reply to IPFIX exporter configure request @param context - sender context which was passed in the request */ -define ipfix_enable_reply +define set_ipfix_exporter_reply { u32 context; i32 retval; }; -/** \brief IPFIX dump request +/** \brief IPFIX exporter dump request @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request */ -define ipfix_dump +define ipfix_exporter_dump { u32 client_index; u32 context; }; -/** \brief Reply to IPFIX dump request +/** \brief Reply to IPFIX exporter dump request @param context - sender context which was passed in the request @param collector_address - address of IPFIX collector - @param collector_port - port of IPFIX IPFIX collector + @param collector_port - port of IPFIX collector @param src_address - address of IPFIX exporter @param fib_index - fib table index @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_details +define ipfix_exporter_details { u32 context; u8 collector_address[16]; u16 collector_port; u8 src_address[16]; - u32 fib_index; + u32 vrf_id; u32 path_mtu; u32 template_interval; + u8 udp_checksum; +}; + +/** \brief IPFIX classify stream configure request + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param domain_id - domain ID reported in IPFIX messages for classify stream + @param src_port - source port of UDP session for classify stream +*/ +define set_ipfix_classify_stream { + u32 client_index; + u32 context; + u32 domain_id; + u16 src_port; +}; + +/** \brief IPFIX classify stream configure response + @param context - sender context, to match reply w/ request + @param retval - return value for request +*/ +define set_ipfix_classify_stream_reply { + u32 context; + i32 retval; +}; + +/** \brief IPFIX classify stream dump request + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request +*/ +define ipfix_classify_stream_dump { + u32 client_index; + u32 context; +}; + +/** \brief Reply to IPFIX classify stream dump request + @param context - sender context, to match reply w/ request + @param domain_id - domain ID reported in IPFIX messages for classify stream + @param src_port - source port of UDP session for classify stream +*/ +define ipfix_classify_stream_details { + u32 context; + u32 domain_id; + u16 src_port; +}; + +/** \brief IPFIX add or delete classifier table request + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param table_id - classifier table ID + @param ip_version - version of IP used in the classifier table + @param transport_protocol - transport protocol used in the classifier table or 255 for unspecified +*/ +define ipfix_classify_table_add_del { + u32 client_index; + u32 context; + u32 table_id; + u8 ip_version; + u8 transport_protocol; + u8 is_add; +}; + +/** \brief IPFIX add classifier table response + @param context - sender context which was passed in the request +*/ +define ipfix_classify_table_add_del_reply { + u32 context; + i32 retval; +}; + +/** \brief IPFIX classify tables dump request + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request +*/ +define ipfix_classify_table_dump { + u32 client_index; + u32 context; +}; + +/** \brief Reply to IPFIX classify tables dump request + @param context - sender context, to match reply w/ request + @param table_id - classifier table ID + @param ip_version - version of IP used in the classifier table + @param transport_protocol - transport protocol used in the classifier table or 255 for unspecified +*/ +define ipfix_classify_table_details { + u32 context; + u32 table_id; + u8 ip_version; + u8 transport_protocol; }; /** \brief Query relative index via node names |