Improve ipfix template packet rewrite construction 54/12554/2
authorDave Barach <dave@barachs.net>
Sun, 13 May 2018 12:50:25 +0000 (08:50 -0400)
committerFlorin Coras <florin.coras@gmail.com>
Sun, 13 May 2018 17:55:24 +0000 (17:55 +0000)
Instead of repeatedly cutting, pasting, and hacking to create a new
callback, use vnet_flow_rewrite_generic_callback(). Add three
arguments to the flow rewrite callback:

(in) pointer to an array of report elements,
(in) length of array,
(out) pointer to the stream index

Change existing code prototypes. Code owners encouraged to evaluate
whether they can use the generic callback or not, at leisure.

/* ipfix field definitions for a particular report */
typedef struct
{
  u32 info_element;
  u32 size;
} ipfix_report_element_t;

Best generated like so:

_(sourceIPv4Address, 4)                         \
_(destinationIPv4Address, 4)                    \
_(sourceTransportPort, 2)                       \
_(destinationTransportPort, 2)                  \
_(protocolIdentifier, 1)                        \
_(flowStartMicroseconds, 8)                     \
_(flowEndMicroseconds, 8)

static ipfix_report_element_t simple_report_elements[] = {
  foreach_simple_report_ipfix_element
};

  ...
  /* Set up the ipfix report */
  memset (&a, 0, sizeof (a));
  a.is_add = 1 /* to enable the report */ ;
  a.domain_id = 1 /* pick a domain ID */ ;
  a.src_port = UDP_DST_PORT_ipfix /* src port for reports */ ;
  a.rewrite_callback = vnet_flow_rewrite_generic_callback;
  a.report_elements = simple_report_elements;
  a.n_report_elements = ARRAY_LEN (simple_report_elements);
  a.stream_indexp = &jim->stream_index;
  a.flow_data_callback = simple_flow_data_callback;

  /* Create the report */
  rv = vnet_flow_report_add_del (frm, &a, &template_id);
  if (rv)
    return rv;
  ...

Change-Id: If6131e6821d3a37a29269c0d58040cdf18ff05e4
Signed-off-by: Dave Barach <dave@barachs.net>
src/plugins/flowprobe/flowprobe.c
src/plugins/ioam/analyse/ioam_summary_export.c
src/plugins/ioam/analyse/ioam_summary_export.h
src/plugins/ioam/udp-ping/udp_ping_export.c
src/plugins/nat/nat_ipfix_logging.c
src/vnet/ipfix-export/flow_report.c
src/vnet/ipfix-export/flow_report.h
src/vnet/ipfix-export/flow_report_classify.c
src/vnet/ipfix-export/flow_report_classify.h

index 35999d2..ee95196 100644 (file)
@@ -333,7 +333,9 @@ flowprobe_template_rewrite_ip6 (flow_report_main_t * frm,
                                flow_report_t * fr,
                                ip4_address_t * collector_address,
                                ip4_address_t * src_address,
-                               u16 collector_port)
+                               u16 collector_port,
+                               ipfix_report_element_t * elts,
+                               u32 n_elts, u32 * stream_index)
 {
   return flowprobe_template_rewrite_inline
     (frm, fr, collector_address, src_address, collector_port,
@@ -345,7 +347,9 @@ flowprobe_template_rewrite_ip4 (flow_report_main_t * frm,
                                flow_report_t * fr,
                                ip4_address_t * collector_address,
                                ip4_address_t * src_address,
-                               u16 collector_port)
+                               u16 collector_port,
+                               ipfix_report_element_t * elts,
+                               u32 n_elts, u32 * stream_index)
 {
   return flowprobe_template_rewrite_inline
     (frm, fr, collector_address, src_address, collector_port,
@@ -357,7 +361,9 @@ flowprobe_template_rewrite_l2 (flow_report_main_t * frm,
                               flow_report_t * fr,
                               ip4_address_t * collector_address,
                               ip4_address_t * src_address,
-                              u16 collector_port)
+                              u16 collector_port,
+                              ipfix_report_element_t * elts,
+                              u32 n_elts, u32 * stream_index)
 {
   return flowprobe_template_rewrite_inline
     (frm, fr, collector_address, src_address, collector_port,
@@ -369,7 +375,9 @@ flowprobe_template_rewrite_l2_ip4 (flow_report_main_t * frm,
                                   flow_report_t * fr,
                                   ip4_address_t * collector_address,
                                   ip4_address_t * src_address,
-                                  u16 collector_port)
+                                  u16 collector_port,
+                                  ipfix_report_element_t * elts,
+                                  u32 n_elts, u32 * stream_index)
 {
   return flowprobe_template_rewrite_inline
     (frm, fr, collector_address, src_address, collector_port,
@@ -381,7 +389,9 @@ flowprobe_template_rewrite_l2_ip6 (flow_report_main_t * frm,
                                   flow_report_t * fr,
                                   ip4_address_t * collector_address,
                                   ip4_address_t * src_address,
-                                  u16 collector_port)
+                                  u16 collector_port,
+                                  ipfix_report_element_t * elts,
+                                  u32 n_elts, u32 * stream_index)
 {
   return flowprobe_template_rewrite_inline
     (frm, fr, collector_address, src_address, collector_port,
index af2d39a..c118bfa 100644 (file)
@@ -21,7 +21,9 @@
 u8 *
 ioam_template_rewrite (flow_report_main_t * frm, flow_report_t * fr,
                       ip4_address_t * collector_address,
-                      ip4_address_t * src_address, u16 collector_port)
+                      ip4_address_t * src_address, u16 collector_port,
+                      ipfix_report_element_t * elts,
+                      u32 n_elts, u32 * stream_index)
 {
   ip4_header_t *ip;
   udp_header_t *udp;
index 1397f9e..99890ad 100755 (executable)
@@ -67,7 +67,9 @@ clib_error_t *ioam_flow_create (u8 del);
 
 u8 *ioam_template_rewrite (flow_report_main_t * frm, flow_report_t * fr,
                           ip4_address_t * collector_address,
-                          ip4_address_t * src_address, u16 collector_port);
+                          ip4_address_t * src_address, u16 collector_port,
+                          ipfix_report_element_t * elts,
+                          u32 n_elts, u32 * stream_index);
 
 u16 ioam_analyse_add_ipfix_record (flow_report_t * fr,
                                   ioam_analyser_data_t * record,
index 2b3a4de..7383591 100644 (file)
 static u8 *
 udp_ping_template_rewrite (flow_report_main_t * frm, flow_report_t * fr,
                           ip4_address_t * collector_address,
-                          ip4_address_t * src_address, u16 collector_port)
+                          ip4_address_t * src_address, u16 collector_port,
+                          ipfix_report_element_t * elts,
+                          u32 n_elts, u32 * stream_index)
 {
   return ioam_template_rewrite (frm, fr, collector_address,
-                               src_address, collector_port);
+                               src_address, collector_port, elts, n_elts,
+                               stream_index);
 }
 
 static vlib_frame_t *
index b4b940e..0f29133 100644 (file)
@@ -403,7 +403,9 @@ snat_template_rewrite_addr_exhausted (flow_report_main_t * frm,
                                      flow_report_t * fr,
                                      ip4_address_t * collector_address,
                                      ip4_address_t * src_address,
-                                     u16 collector_port)
+                                     u16 collector_port,
+                                      ipfix_report_element_t *elts,
+                                      u32 n_elts, u32 *stream_index)
 {
   return snat_template_rewrite (frm, fr, collector_address, src_address,
                                collector_port, NAT_ADDRESSES_EXHAUTED, 0);
@@ -414,7 +416,9 @@ snat_template_rewrite_nat44_session (flow_report_main_t * frm,
                                     flow_report_t * fr,
                                     ip4_address_t * collector_address,
                                     ip4_address_t * src_address,
-                                    u16 collector_port)
+                                    u16 collector_port,
+                                     ipfix_report_element_t *elts,
+                                     u32 n_elts, u32 *stream_index)
 {
   return snat_template_rewrite (frm, fr, collector_address, src_address,
                                collector_port, NAT44_SESSION_CREATE, 0);
@@ -425,7 +429,9 @@ snat_template_rewrite_max_entries_per_usr (flow_report_main_t * frm,
                                           flow_report_t * fr,
                                           ip4_address_t * collector_address,
                                           ip4_address_t * src_address,
-                                          u16 collector_port)
+                                          u16 collector_port,
+                                           ipfix_report_element_t *elts,
+                                           u32 n_elts, u32 *stream_index)
 {
   return snat_template_rewrite (frm, fr, collector_address, src_address,
                                collector_port, QUOTA_EXCEEDED,
@@ -437,7 +443,9 @@ nat_template_rewrite_max_sessions (flow_report_main_t * frm,
                                   flow_report_t * fr,
                                   ip4_address_t * collector_address,
                                   ip4_address_t * src_address,
-                                  u16 collector_port)
+                                  u16 collector_port,
+                                   ipfix_report_element_t *elts,
+                                   u32 n_elts, u32 *stream_index)
 {
   return snat_template_rewrite (frm, fr, collector_address, src_address,
                                collector_port, QUOTA_EXCEEDED,
@@ -449,7 +457,9 @@ nat_template_rewrite_max_bibs (flow_report_main_t * frm,
                               flow_report_t * fr,
                               ip4_address_t * collector_address,
                               ip4_address_t * src_address,
-                              u16 collector_port)
+                              u16 collector_port,
+                               ipfix_report_element_t *elts,
+                               u32 n_elts, u32 *stream_index)
 {
   return snat_template_rewrite (frm, fr, collector_address, src_address,
                                collector_port, QUOTA_EXCEEDED,
@@ -461,7 +471,9 @@ nat_template_rewrite_max_frags_ip4 (flow_report_main_t * frm,
                                    flow_report_t * fr,
                                    ip4_address_t * collector_address,
                                    ip4_address_t * src_address,
-                                   u16 collector_port)
+                                   u16 collector_port,
+                                    ipfix_report_element_t *elts,
+                                    u32 n_elts, u32 *stream_index)
 {
   return snat_template_rewrite (frm, fr, collector_address, src_address,
                                collector_port, QUOTA_EXCEEDED,
@@ -473,7 +485,9 @@ nat_template_rewrite_max_frags_ip6 (flow_report_main_t * frm,
                                    flow_report_t * fr,
                                    ip4_address_t * collector_address,
                                    ip4_address_t * src_address,
-                                   u16 collector_port)
+                                   u16 collector_port,
+                                    ipfix_report_element_t *elts,
+                                    u32 n_elts, u32 *stream_index)
 {
   return snat_template_rewrite (frm, fr, collector_address, src_address,
                                collector_port, QUOTA_EXCEEDED,
@@ -485,7 +499,9 @@ nat_template_rewrite_nat64_bib (flow_report_main_t * frm,
                                flow_report_t * fr,
                                ip4_address_t * collector_address,
                                ip4_address_t * src_address,
-                               u16 collector_port)
+                               u16 collector_port,
+                                ipfix_report_element_t *elts,
+                                u32 n_elts, u32 *stream_index)
 {
   return snat_template_rewrite (frm, fr, collector_address, src_address,
                                collector_port, NAT64_BIB_CREATE, 0);
@@ -496,7 +512,9 @@ nat_template_rewrite_nat64_session (flow_report_main_t * frm,
                                    flow_report_t * fr,
                                    ip4_address_t * collector_address,
                                    ip4_address_t * src_address,
-                                   u16 collector_port)
+                                   u16 collector_port,
+                                    ipfix_report_element_t *elts,
+                                    u32 n_elts, u32 *stream_index)
 {
   return snat_template_rewrite (frm, fr, collector_address, src_address,
                                collector_port, NAT64_SESSION_CREATE, 0);
index 793eeda..78ad1f5 100644 (file)
@@ -107,7 +107,10 @@ send_template_packet (flow_report_main_t * frm,
       fr->rewrite = fr->rewrite_callback (frm, fr,
                                          &frm->ipfix_collector,
                                          &frm->src_address,
-                                         frm->collector_port);
+                                         frm->collector_port,
+                                         fr->report_elements,
+                                         fr->n_report_elements,
+                                         fr->stream_indexp);
       fr->update_rewrite = 0;
     }
 
@@ -164,6 +167,92 @@ send_template_packet (flow_report_main_t * frm,
   return 0;
 }
 
+u8 *
+vnet_flow_rewrite_generic_callback (flow_report_main_t * frm,
+                                   flow_report_t * fr,
+                                   ip4_address_t * collector_address,
+                                   ip4_address_t * src_address,
+                                   u16 collector_port,
+                                   ipfix_report_element_t * report_elts,
+                                   u32 n_elts, u32 * stream_indexp)
+{
+  ip4_header_t *ip;
+  udp_header_t *udp;
+  ipfix_message_header_t *h;
+  ipfix_set_header_t *s;
+  ipfix_template_header_t *t;
+  ipfix_field_specifier_t *f;
+  ipfix_field_specifier_t *first_field;
+  u8 *rewrite = 0;
+  ip4_ipfix_template_packet_t *tp;
+  flow_report_stream_t *stream;
+  int i;
+  ipfix_report_element_t *ep;
+
+  ASSERT (stream_indexp);
+  ASSERT (n_elts);
+  ASSERT (report_elts);
+
+  stream = &frm->streams[fr->stream_index];
+  *stream_indexp = fr->stream_index;
+
+  /* allocate rewrite space */
+  vec_validate_aligned (rewrite,
+                       sizeof (ip4_ipfix_template_packet_t)
+                       + n_elts * sizeof (ipfix_field_specifier_t) - 1,
+                       CLIB_CACHE_LINE_BYTES);
+
+  /* create the packet rewrite string */
+  tp = (ip4_ipfix_template_packet_t *) rewrite;
+  ip = (ip4_header_t *) & tp->ip4;
+  udp = (udp_header_t *) (ip + 1);
+  h = (ipfix_message_header_t *) (udp + 1);
+  s = (ipfix_set_header_t *) (h + 1);
+  t = (ipfix_template_header_t *) (s + 1);
+  first_field = f = (ipfix_field_specifier_t *) (t + 1);
+
+  ip->ip_version_and_header_length = 0x45;
+  ip->ttl = 254;
+  ip->protocol = IP_PROTOCOL_UDP;
+  ip->src_address.as_u32 = src_address->as_u32;
+  ip->dst_address.as_u32 = collector_address->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));
+
+  /* FIXUP LATER: message header export_time */
+  h->domain_id = clib_host_to_net_u32 (stream->domain_id);
+
+  ep = report_elts;
+
+  for (i = 0; i < n_elts; i++)
+    {
+      f->e_id_length = ipfix_e_id_length (0, ep->info_element, ep->size);
+      f++;
+      ep++;
+    }
+
+  /* Back to the template packet... */
+  ip = (ip4_header_t *) & tp->ip4;
+  udp = (udp_header_t *) (ip + 1);
+
+  ASSERT (f - first_field);
+  /* Field count in this template */
+  t->id_count = ipfix_id_count (fr->template_id, f - first_field);
+
+  /* set length in octets */
+  s->set_id_length =
+    ipfix_set_id_length (2 /* set_id */ , (u8 *) f - (u8 *) s);
+
+  /* message length in octets */
+  h->version_length = version_length ((u8 *) f - (u8 *) h);
+
+  ip->length = clib_host_to_net_u16 ((u8 *) f - (u8 *) ip);
+  ip->checksum = ip4_header_checksum (ip);
+
+  return rewrite;
+}
+
 static uword
 flow_report_process (vlib_main_t * vm,
                     vlib_node_runtime_t * rt, vlib_frame_t * f)
@@ -315,7 +404,9 @@ vnet_flow_report_add_del (flow_report_main_t * frm,
   fr->opaque = a->opaque;
   fr->rewrite_callback = a->rewrite_callback;
   fr->flow_data_callback = a->flow_data_callback;
-
+  fr->report_elements = a->report_elements;
+  fr->n_report_elements = a->n_report_elements;
+  fr->stream_indexp = a->stream_indexp;
   if (template_id)
     *template_id = fr->template_id;
 
index b45ce06..a26232d 100644 (file)
 
 #include <vnet/ipfix-export/ipfix_packet.h>
 
+/* ipfix field definitions for a particular report */
+typedef struct
+{
+  u32 info_element;
+  u32 size;
+} ipfix_report_element_t;
+
 /* Used to build the rewrite */
 typedef struct
 {
@@ -42,16 +49,25 @@ typedef struct
 struct flow_report_main;
 struct flow_report;
 
-typedef u8 *(vnet_flow_rewrite_callback_t) (struct flow_report_main *,
-                                           struct flow_report *,
-                                           ip4_address_t *,
-                                           ip4_address_t *, u16);
-
 typedef vlib_frame_t *(vnet_flow_data_callback_t) (struct flow_report_main *,
                                                   struct flow_report *,
                                                   vlib_frame_t *, u32 *,
                                                   u32);
 
+typedef u8 *(vnet_flow_rewrite_callback_t) (struct flow_report_main *,
+                                           struct flow_report *,
+                                           ip4_address_t *,
+                                           ip4_address_t *, u16,
+                                           ipfix_report_element_t * elts,
+                                           u32 n_elts, u32 * stream_index);
+
+u8 *vnet_flow_rewrite_generic_callback (struct flow_report_main *,
+                                       struct flow_report *,
+                                       ip4_address_t *,
+                                       ip4_address_t *, u16,
+                                       ipfix_report_element_t * elts,
+                                       u32 n_elts, u32 * stream_index);
+
 typedef union
 {
   void *as_ptr;
@@ -82,8 +98,11 @@ typedef struct flow_report
   /* Opaque data */
   opaque_t opaque;
 
-  /* build-the-rewrite callback */
+  /* build-the-template-packet rewrite callback */
   vnet_flow_rewrite_callback_t *rewrite_callback;
+  ipfix_report_element_t *report_elements;
+  u32 n_report_elements;
+  u32 *stream_indexp;
 
   /* Send-flow-data callback */
   vnet_flow_data_callback_t *flow_data_callback;
@@ -128,10 +147,13 @@ typedef struct
 {
   vnet_flow_data_callback_t *flow_data_callback;
   vnet_flow_rewrite_callback_t *rewrite_callback;
+  ipfix_report_element_t *report_elements;
+  u32 n_report_elements;
   opaque_t opaque;
   int is_add;
   u32 domain_id;
   u16 src_port;
+  u32 *stream_indexp;
 } vnet_flow_report_add_del_args_t;
 
 int vnet_flow_report_add_del (flow_report_main_t * frm,
index 46813ee..8fb73fc 100644 (file)
@@ -30,7 +30,9 @@ ipfix_classify_template_rewrite (flow_report_main_t * frm,
                                 flow_report_t * fr,
                                 ip4_address_t * collector_address,
                                 ip4_address_t * src_address,
-                                u16 collector_port)
+                                u16 collector_port,
+                                ipfix_report_element_t * elts,
+                                u32 n_elts, u32 * stream_index)
 {
   flow_report_classify_main_t *fcm = &flow_report_classify_main;
   vnet_classify_table_t *tblp;
index 0533b45..a923f36 100644 (file)
@@ -116,7 +116,9 @@ u8 *ipfix_classify_template_rewrite (flow_report_main_t * frm,
                                     flow_report_t * fr,
                                     ip4_address_t * collector_address,
                                     ip4_address_t * src_address,
-                                    u16 collector_port);
+                                    u16 collector_port,
+                                    ipfix_report_element_t * elts,
+                                    u32 n_elts, u32 * stream_index);
 
 vlib_frame_t *ipfix_classify_send_flows (flow_report_main_t * frm,
                                         flow_report_t * fr,