ipfix-export: Change exp to use ip_address 21/34021/3
authorPaul Atkins <patkins@graphiant.com>
Mon, 4 Oct 2021 14:43:56 +0000 (15:43 +0100)
committerNeale Ranns <neale@graphiant.com>
Mon, 22 Nov 2021 09:30:09 +0000 (09:30 +0000)
Modify the ipfix_exporter to use ip_address instead of the ipv4 specific
version. Modify the current code so that it writes into the v4 specific
part of the address, i.e. we are not yet fully supporting IPv6.  For the
exporter configured via the original API (the one that is always in slot0)
we will not support IPv6 addresses.

Type: improvement
Signed-off-by: Paul Atkins <patkins@graphiant.com>
Change-Id: Ic9854ac62aaee76a7a55a958234c456fd9828c4c

src/plugins/flowprobe/flowprobe.c
src/plugins/flowprobe/node.c
src/plugins/ioam/analyse/ioam_summary_export.c
src/plugins/nat/lib/ipfix_logging.c
src/vnet/ipfix-export/flow_api.c
src/vnet/ipfix-export/flow_report.c
src/vnet/ipfix-export/flow_report.h
src/vnet/ipfix-export/flow_report_classify.c

index 5e91a15..27cb400 100644 (file)
@@ -260,8 +260,8 @@ flowprobe_template_rewrite_inline (ipfix_exporter_t *exp, flow_report_t *fr,
   ip->ip_version_and_header_length = 0x45;
   ip->ttl = 254;
   ip->protocol = IP_PROTOCOL_UDP;
-  ip->src_address.as_u32 = exp->src_address.as_u32;
-  ip->dst_address.as_u32 = exp->ipfix_collector.as_u32;
+  ip->src_address.as_u32 = exp->src_address.ip.ip4.as_u32;
+  ip->dst_address.as_u32 = exp->ipfix_collector.ip.ip4.as_u32;
   udp->src_port = clib_host_to_net_u16 (stream->src_port);
   udp->dst_port = clib_host_to_net_u16 (collector_port);
   udp->length = clib_host_to_net_u16 (vec_len (rewrite) - sizeof (*ip));
index 611ce62..928d752 100644 (file)
@@ -575,8 +575,8 @@ flowprobe_export_send (vlib_main_t * vm, vlib_buffer_t * b0,
   ip->ttl = 254;
   ip->protocol = IP_PROTOCOL_UDP;
   ip->flags_and_fragment_offset = 0;
-  ip->src_address.as_u32 = exp->src_address.as_u32;
-  ip->dst_address.as_u32 = exp->ipfix_collector.as_u32;
+  ip->src_address.as_u32 = exp->src_address.ip.ip4.as_u32;
+  ip->dst_address.as_u32 = exp->ipfix_collector.ip.ip4.as_u32;
   udp->src_port = clib_host_to_net_u16 (stream->src_port);
   udp->dst_port = clib_host_to_net_u16 (exp->collector_port);
   udp->checksum = 0;
@@ -943,7 +943,8 @@ flowprobe_walker_process (vlib_main_t * vm,
    * $$$$ Remove this check from here and track FRM status and disable
    * this process if required.
    */
-  if (exp->ipfix_collector.as_u32 == 0 || exp->src_address.as_u32 == 0)
+  if (ip_address_is_zero (&exp->ipfix_collector) ||
+      ip_address_is_zero (&exp->src_address))
     {
       fm->disabled = true;
       return 0;
index 9fbeaa2..ceec155 100644 (file)
@@ -72,8 +72,8 @@ ioam_template_rewrite (ipfix_exporter_t *exp, flow_report_t *fr,
   ip->ip_version_and_header_length = 0x45;
   ip->ttl = 254;
   ip->protocol = IP_PROTOCOL_UDP;
-  ip->src_address.as_u32 = exp->src_address.as_u32;
-  ip->dst_address.as_u32 = exp->ipfix_collector.as_u32;
+  ip->src_address.as_u32 = exp->src_address.ip.ip4.as_u32;
+  ip->dst_address.as_u32 = exp->ipfix_collector.ip.ip4.as_u32;
   udp->src_port = clib_host_to_net_u16 (collector_port);
   udp->dst_port = clib_host_to_net_u16 (UDP_DST_PORT_ipfix);
   udp->length = clib_host_to_net_u16 (vec_len (rewrite) - sizeof (*ip));
index 1c39e85..50dbb2b 100644 (file)
@@ -238,8 +238,8 @@ nat_template_rewrite (ipfix_exporter_t *exp, flow_report_t *fr,
   ip->ip_version_and_header_length = 0x45;
   ip->ttl = 254;
   ip->protocol = IP_PROTOCOL_UDP;
-  ip->src_address.as_u32 = exp->src_address.as_u32;
-  ip->dst_address.as_u32 = exp->ipfix_collector.as_u32;
+  ip->src_address.as_u32 = exp->src_address.ip.ip4.as_u32;
+  ip->dst_address.as_u32 = exp->ipfix_collector.ip.ip4.as_u32;
   udp->src_port = clib_host_to_net_u16 (stream->src_port);
   udp->dst_port = clib_host_to_net_u16 (collector_port);
   udp->length = clib_host_to_net_u16 (vec_len (rewrite) - sizeof (*ip));
@@ -490,8 +490,8 @@ nat_ipfix_header_create (flow_report_main_t * frm,
   ip->ttl = 254;
   ip->protocol = IP_PROTOCOL_UDP;
   ip->flags_and_fragment_offset = 0;
-  ip->src_address.as_u32 = exp->src_address.as_u32;
-  ip->dst_address.as_u32 = exp->ipfix_collector.as_u32;
+  ip->src_address.as_u32 = exp->src_address.ip.ip4.as_u32;
+  ip->dst_address.as_u32 = exp->ipfix_collector.ip.ip4.as_u32;
   udp->src_port = clib_host_to_net_u16 (stream->src_port);
   udp->dst_port = clib_host_to_net_u16 (exp->collector_port);
   udp->checksum = 0;
index 62dc703..4a9b525 100644 (file)
 #include <vlibapi/api_helper_macros.h>
 
 ipfix_exporter_t *
-vnet_ipfix_exporter_lookup (ip4_address_t *ipfix_collector)
+vnet_ipfix_exporter_lookup (const ip_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)
+      if (ip_address_cmp (&exp->ipfix_collector, ipfix_collector) == 0)
        return exp;
     }
 
@@ -70,29 +70,34 @@ vl_api_set_ipfix_exporter_t_internal (
   flow_report_main_t *frm = &flow_report_main;
   ipfix_exporter_t *exp;
   vl_api_registration_t *reg;
-  ip4_address_t collector, src;
+  ip_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;
+  u32 ip_header_size;
 
   reg = vl_api_client_index_to_registration (client_index);
   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];
+    {
+      /*
+       * In this case we update the existing exporter. There is no delete
+       * for exp[0]
+       */
+      exp = &frm->exporters[0];
+
+      /* Collector address must be IPv4 for exp[0] */
+      collector.version = AF_IP4;
+      ip4_address_decode (mp_collector_address->un.ip4, &collector.ip.ip4);
+    }
   else
     {
+      ip_address_decode2 (mp_collector_address, &collector);
       if (is_create)
        {
          exp = vnet_ipfix_exporter_lookup (&collector);
@@ -118,16 +123,10 @@ vl_api_set_ipfix_exporter_t_internal (
        }
     }
 
-  if (mp_src_address->af == ADDRESS_IP6 ||
-      mp_collector_address->af == ADDRESS_IP6)
-    {
-      return VNET_API_ERROR_UNIMPLEMENTED;
-    }
-
   collector_port = ntohs (mp_collector_port);
   if (collector_port == (u16) ~ 0)
     collector_port = UDP_DST_PORT_ipfix;
-  ip4_address_decode (mp_src_address->un.ip4, &src);
+  ip_address_decode2 (mp_src_address, &src);
   fib_id = ntohl (mp_vrf_id);
 
   ip4_main_t *im = &ip4_main;
@@ -151,7 +150,13 @@ vl_api_set_ipfix_exporter_t_internal (
     template_interval = 20;
   udp_checksum = mp_udp_checksum;
 
-  if (collector.as_u32 != 0 && src.as_u32 == 0)
+  /*
+   * If the collector address is set then the src must be too.
+   * Collector address can be set to 0 to disable exporter
+   */
+  if (!ip_address_is_zero (&collector) && ip_address_is_zero (&src))
+    return VNET_API_ERROR_INVALID_VALUE;
+  if (collector.version != src.version)
     return VNET_API_ERROR_INVALID_VALUE;
 
   if (path_mtu > 1450 /* vpp does not support fragmentation */ )
@@ -161,19 +166,23 @@ vl_api_set_ipfix_exporter_t_internal (
     return VNET_API_ERROR_INVALID_VALUE;
 
   /* Calculate how much header data we need. */
-  exp->all_headers_size = sizeof (ip4_header_t) + sizeof (udp_header_t) +
+  if (collector.version == AF_IP4)
+    ip_header_size = sizeof (ip4_header_t);
+  else
+    ip_header_size = sizeof (ip6_header_t);
+  exp->all_headers_size = ip_header_size + sizeof (udp_header_t) +
                          sizeof (ipfix_message_header_t) +
                          sizeof (ipfix_set_header_t);
 
   /* Reset report streams if we are reconfiguring IP addresses */
-  if (exp->ipfix_collector.as_u32 != collector.as_u32 ||
-      exp->src_address.as_u32 != src.as_u32 ||
+  if (ip_address_cmp (&exp->ipfix_collector, &collector) ||
+      ip_address_cmp (&exp->src_address, &src) ||
       exp->collector_port != collector_port)
     vnet_flow_reports_reset (exp);
 
-  exp->ipfix_collector.as_u32 = collector.as_u32;
+  exp->ipfix_collector = collector;
   exp->collector_port = collector_port;
-  exp->src_address.as_u32 = src.as_u32;
+  exp->src_address = src;
   exp->fib_index = fib_index;
   exp->path_mtu = path_mtu;
   exp->template_interval = template_interval;
@@ -220,8 +229,6 @@ vl_api_ipfix_exporter_dump_t_handler (vl_api_ipfix_exporter_dump_t * mp)
   vl_api_registration_t *reg;
   vl_api_ipfix_exporter_details_t *rmp;
   ip4_main_t *im = &ip4_main;
-  ip46_address_t collector = {.as_u64[0] = 0,.as_u64[1] = 0 };
-  ip46_address_t src = {.as_u64[0] = 0,.as_u64[1] = 0 };
   u32 vrf_id;
 
   reg = vl_api_client_index_to_registration (mp->client_index);
@@ -234,13 +241,9 @@ 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, &exp->ipfix_collector, sizeof (ip4_address_t));
-  ip_address_encode (&collector, IP46_TYPE_IP4, &rmp->collector_address);
-
+  ip_address_encode2 (&exp->ipfix_collector, &rmp->collector_address);
   rmp->collector_port = htons (exp->collector_port);
-
-  memcpy (&src.ip4, &exp->src_address, sizeof (ip4_address_t));
-  ip_address_encode (&src, IP46_TYPE_IP4, &rmp->src_address);
+  ip_address_encode2 (&exp->src_address, &rmp->src_address);
 
   if (exp->fib_index == ~0)
     vrf_id = ~0;
@@ -259,17 +262,11 @@ ipfix_all_fill_details (vl_api_ipfix_all_exporter_details_t *rmp,
                        ipfix_exporter_t *exp)
 {
   ip4_main_t *im = &ip4_main;
-  ip46_address_t collector = { .as_u64[0] = 0, .as_u64[1] = 0 };
-  ip46_address_t src = { .as_u64[0] = 0, .as_u64[1] = 0 };
   u32 vrf_id;
 
-  memcpy (&collector.ip4, &exp->ipfix_collector, sizeof (ip4_address_t));
-  ip_address_encode (&collector, IP46_TYPE_IP4, &rmp->collector_address);
-
+  ip_address_encode2 (&exp->ipfix_collector, &rmp->collector_address);
   rmp->collector_port = htons (exp->collector_port);
-
-  memcpy (&src.ip4, &exp->src_address, sizeof (ip4_address_t));
-  ip_address_encode (&src, IP46_TYPE_IP4, &rmp->src_address);
+  ip_address_encode2 (&exp->src_address, &rmp->src_address);
 
   if (exp->fib_index == ~0)
     vrf_id = ~0;
index 1660a2b..bb7a863 100644 (file)
@@ -88,7 +88,8 @@ send_template_packet (flow_report_main_t *frm, ipfix_exporter_t *exp,
 
   if (fr->update_rewrite || fr->rewrite == 0)
     {
-      if (exp->ipfix_collector.as_u32 == 0 || exp->src_address.as_u32 == 0)
+      if (ip_address_is_zero (&exp->ipfix_collector) ||
+         ip_address_is_zero (&exp->src_address))
        {
          vlib_node_set_state (frm->vlib_main, flow_report_process_node.index,
                               VLIB_NODE_STATE_DISABLED);
@@ -198,8 +199,8 @@ vnet_flow_rewrite_generic_callback (ipfix_exporter_t *exp, flow_report_t *fr,
   ip4->ip_version_and_header_length = 0x45;
   ip4->ttl = 254;
   ip4->protocol = IP_PROTOCOL_UDP;
-  ip4->src_address.as_u32 = exp->src_address.as_u32;
-  ip4->dst_address.as_u32 = exp->ipfix_collector.as_u32;
+  ip4->src_address.as_u32 = exp->src_address.ip.ip4.as_u32;
+  ip4->dst_address.as_u32 = exp->ipfix_collector.ip.ip4.as_u32;
   udp->src_port = clib_host_to_net_u16 (stream->src_port);
   udp->dst_port = clib_host_to_net_u16 (collector_port);
   udp->length = clib_host_to_net_u16 (vec_len (rewrite) - sizeof (*ip4));
@@ -295,8 +296,8 @@ vnet_ipfix_exp_send_buffer (vlib_main_t *vm, ipfix_exporter_t *exp,
   ip4->ttl = 254;
   ip4->protocol = IP_PROTOCOL_UDP;
   ip4->flags_and_fragment_offset = 0;
-  ip4->src_address.as_u32 = exp->src_address.as_u32;
-  ip4->dst_address.as_u32 = exp->ipfix_collector.as_u32;
+  ip4->src_address.as_u32 = exp->src_address.ip.ip4.as_u32;
+  ip4->dst_address.as_u32 = exp->ipfix_collector.ip.ip4.as_u32;
   udp->src_port = clib_host_to_net_u16 (stream->src_port);
   udp->dst_port = clib_host_to_net_u16 (exp->collector_port);
   udp->checksum = 0;
@@ -644,26 +645,26 @@ set_ipfix_exporter_command_fn (vlib_main_t * vm,
                               vlib_cli_command_t * cmd)
 {
   flow_report_main_t *frm = &flow_report_main;
-  ip4_address_t collector, src;
+  ip_address_t collector = IP_ADDRESS_V4_ALL_0S, src = IP_ADDRESS_V4_ALL_0S;
   u16 collector_port = UDP_DST_PORT_ipfix;
   u32 fib_id;
   u32 fib_index = ~0;
 
-  collector.as_u32 = 0;
-  src.as_u32 = 0;
   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);
+  u32 ip_header_size;
 
   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     {
-      if (unformat (input, "collector %U", unformat_ip4_address, &collector))
+      if (unformat (input, "collector %U", unformat_ip4_address,
+                   &collector.ip.ip4))
        ;
       else if (unformat (input, "port %U", unformat_udp_port,
                         &collector_port))
        ;
-      else if (unformat (input, "src %U", unformat_ip4_address, &src))
+      else if (unformat (input, "src %U", unformat_ip4_address, &src.ip.ip4))
        ;
       else if (unformat (input, "fib-id %u", &fib_id))
        {
@@ -683,8 +684,15 @@ set_ipfix_exporter_command_fn (vlib_main_t * vm,
        break;
     }
 
-  if (collector.as_u32 != 0 && src.as_u32 == 0)
+  /*
+   * If the collector address is set then the src must be too.
+   * Collector address can be set to 0 to disable exporter
+   */
+  if (!ip_address_is_zero (&collector) && ip_address_is_zero (&src))
     return clib_error_return (0, "src address required");
+  if (collector.version != src.version)
+    return clib_error_return (
+      0, "src address and dest address must use same IP version");
 
   if (path_mtu > 1450 /* vpp does not support fragmentation */ )
     return clib_error_return (0, "too big path-mtu value, maximum is 1450");
@@ -693,25 +701,29 @@ set_ipfix_exporter_command_fn (vlib_main_t * vm,
     return clib_error_return (0, "too small path-mtu value, minimum is 68");
 
   /* Calculate how much header data we need. */
-  exp->all_headers_size = sizeof (ip4_header_t) + sizeof (udp_header_t) +
+  if (collector.version == AF_IP4)
+    ip_header_size = sizeof (ip4_header_t);
+  else
+    ip_header_size = sizeof (ip6_header_t);
+  exp->all_headers_size = ip_header_size + sizeof (udp_header_t) +
                          sizeof (ipfix_message_header_t) +
                          sizeof (ipfix_set_header_t);
 
   /* Reset report streams if we are reconfiguring IP addresses */
-  if (exp->ipfix_collector.as_u32 != collector.as_u32 ||
-      exp->src_address.as_u32 != src.as_u32 ||
+  if (ip_address_cmp (&exp->ipfix_collector, &collector) ||
+      ip_address_cmp (&exp->src_address, &src) ||
       exp->collector_port != collector_port)
     vnet_flow_reports_reset (exp);
 
-  exp->ipfix_collector.as_u32 = collector.as_u32;
+  exp->ipfix_collector = collector;
   exp->collector_port = collector_port;
-  exp->src_address.as_u32 = src.as_u32;
+  exp->src_address = src;
   exp->fib_index = fib_index;
   exp->path_mtu = path_mtu;
   exp->template_interval = template_interval;
   exp->udp_checksum = udp_checksum;
 
-  if (collector.as_u32)
+  if (collector.ip.ip4.as_u32)
     vlib_cli_output (vm,
                     "Collector %U, src address %U, "
                     "fib index %d, path MTU %u, "
index 319533d..cd0cafb 100644 (file)
@@ -46,6 +46,14 @@ typedef struct
   ipfix_template_packet_t ipfix;
 } ip4_ipfix_template_packet_t;
 
+/* Used to build the rewrite */
+typedef struct
+{
+  ip6_header_t ip6;
+  udp_header_t udp;
+  ipfix_template_packet_t ipfix;
+} ip6_ipfix_template_packet_t;
+
 struct flow_report_main;
 struct flow_report;
 struct ipfix_exporter;
@@ -155,9 +163,9 @@ typedef struct ipfix_exporter
   flow_report_stream_t *streams;
 
   /* ipfix collector ip address, port, our ip address, fib index */
-  ip4_address_t ipfix_collector;
+  ip_address_t ipfix_collector;
   u16 collector_port;
-  ip4_address_t src_address;
+  ip_address_t src_address;
   u32 fib_index;
 
   /* Path MTU */
@@ -235,7 +243,8 @@ int vnet_stream_change (ipfix_exporter_t *exp, u32 old_domain_id,
 /*
  * Search all the exporters for one that has a matching destination address.
  */
-ipfix_exporter_t *vnet_ipfix_exporter_lookup (ip4_address_t *ipfix_collector);
+ipfix_exporter_t *
+vnet_ipfix_exporter_lookup (const ip_address_t *ipfix_collector);
 
 /*
  * Get the currently in use buffer for the given stream on the given core.
index 2c4285b..ea6ba5c 100644 (file)
@@ -106,8 +106,8 @@ ipfix_classify_template_rewrite (ipfix_exporter_t *exp, flow_report_t *fr,
   ip->ip_version_and_header_length = 0x45;
   ip->ttl = 254;
   ip->protocol = IP_PROTOCOL_UDP;
-  ip->src_address.as_u32 = exp->src_address.as_u32;
-  ip->dst_address.as_u32 = exp->ipfix_collector.as_u32;
+  ip->src_address.as_u32 = exp->src_address.ip.ip4.as_u32;
+  ip->dst_address.as_u32 = exp->ipfix_collector.ip.ip4.as_u32;
   udp->src_port = clib_host_to_net_u16 (stream->src_port);
   udp->dst_port = clib_host_to_net_u16 (collector_port);
   udp->length = clib_host_to_net_u16 (vec_len (rewrite) - sizeof (*ip));