LCOV - code coverage report
Current view: top level - plugins/ioam/udp-ping - udp_ping_export.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 4 143 2.8 %
Date: 2023-07-05 22:20:52 Functions: 5 9 55.6 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2016 Cisco and/or its affiliates.
       3             :  * Licensed under the Apache License, Version 2.0 (the "License");
       4             :  * you may not use this file except in compliance with the License.
       5             :  * You may obtain a copy of the License at:
       6             :  *
       7             :  *     http://www.apache.org/licenses/LICENSE-2.0
       8             :  *
       9             :  * Unless required by applicable law or agreed to in writing, software
      10             :  * distributed under the License is distributed on an "AS IS" BASIS,
      11             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             :  * See the License for the specific language governing permissions and
      13             :  * limitations under the License.
      14             :  */
      15             : 
      16             : #include <vnet/ipfix-export/flow_report.h>
      17             : #include <ioam/analyse/ioam_summary_export.h>
      18             : #include <vnet/api_errno.h>
      19             : #include <vnet/ip/ip4.h>
      20             : #include <vnet/udp/udp_local.h>
      21             : #include <ioam/udp-ping/udp_ping.h>
      22             : 
      23             : #define UDP_PING_EXPORT_RECORD_SIZE 400
      24             : 
      25             : static u8 *
      26           0 : udp_ping_template_rewrite (ipfix_exporter_t *exp, flow_report_t *fr,
      27             :                            u16 collector_port, ipfix_report_element_t *elts,
      28             :                            u32 n_elts, u32 *stream_index)
      29             : {
      30           0 :   return ioam_template_rewrite (exp, fr, collector_port, elts, n_elts,
      31             :                                 stream_index);
      32             : }
      33             : 
      34             : static vlib_frame_t *
      35           0 : udp_ping_send_flows (flow_report_main_t *frm, ipfix_exporter_t *exp,
      36             :                      flow_report_t *fr, vlib_frame_t *f, u32 *to_next,
      37             :                      u32 node_index)
      38             : {
      39           0 :   vlib_buffer_t *b0 = NULL;
      40           0 :   u32 next_offset = 0;
      41           0 :   u32 bi0 = ~0;
      42             :   int i, j;
      43             :   ip4_ipfix_template_packet_t *tp;
      44             :   ipfix_message_header_t *h;
      45           0 :   ipfix_set_header_t *s = NULL;
      46             :   ip4_header_t *ip;
      47             :   udp_header_t *udp;
      48             :   u16 new_l0, old_l0;
      49             :   ip_csum_t sum0;
      50           0 :   vlib_main_t *vm = vlib_get_main ();
      51             :   flow_report_stream_t *stream;
      52             :   udp_ping_flow_data *stats;
      53             :   ip46_udp_ping_flow *ip46_flow;
      54             :   u16 src_port, dst_port;
      55             :   u16 data_len;
      56             : 
      57           0 :   stream = &exp->streams[fr->stream_index];
      58           0 :   data_len = vec_len (udp_ping_main.ip46_flow);
      59             : 
      60           0 :   for (i = 0; i < data_len; i++)
      61             :     {
      62           0 :       if (pool_is_free_index (udp_ping_main.ip46_flow, i))
      63           0 :         continue;
      64             : 
      65           0 :       ip46_flow = pool_elt_at_index (udp_ping_main.ip46_flow, i);
      66           0 :       j = 0;
      67           0 :       for (src_port = ip46_flow->udp_data.start_src_port;
      68           0 :            src_port <= ip46_flow->udp_data.end_src_port; src_port++)
      69             :         {
      70           0 :           for (dst_port = ip46_flow->udp_data.start_dst_port;
      71           0 :                dst_port <= ip46_flow->udp_data.end_dst_port; dst_port++, j++)
      72             :             {
      73           0 :               stats = ip46_flow->udp_data.stats + j;
      74           0 :               if (PREDICT_FALSE (b0 == NULL))
      75             :                 {
      76           0 :                   if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
      77           0 :                     break;
      78             : 
      79             : 
      80           0 :                   b0 = vlib_get_buffer (vm, bi0);
      81           0 :                   memcpy (b0->data, fr->rewrite, vec_len (fr->rewrite));
      82           0 :                   b0->current_data = 0;
      83           0 :                   b0->current_length = vec_len (fr->rewrite);
      84           0 :                   b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
      85           0 :                   vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0;
      86           0 :                   vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0;
      87             : 
      88           0 :                   tp = vlib_buffer_get_current (b0);
      89           0 :                   ip = &tp->ip4;
      90           0 :                   h = &tp->ipfix.h;
      91           0 :                   s = &tp->ipfix.s;
      92             : 
      93             :                   /* FIXUP: message header export_time */
      94           0 :                   h->export_time = clib_host_to_net_u32 (((u32) time (NULL)));
      95             : 
      96             :                   /* FIXUP: message header sequence_number */
      97           0 :                   h->sequence_number = stream->sequence_number++;
      98           0 :                   h->sequence_number =
      99           0 :                     clib_host_to_net_u32 (h->sequence_number);
     100           0 :                   next_offset = (u32) (((u8 *) (s + 1)) - (u8 *) tp);
     101             :                 }
     102             : 
     103           0 :               next_offset = ioam_analyse_add_ipfix_record (fr,
     104             :                                                            &stats->analyse_data,
     105             :                                                            b0, next_offset,
     106             :                                                            &ip46_flow->
     107             :                                                            src.ip6,
     108             :                                                            &ip46_flow->
     109             :                                                            dst.ip6, src_port,
     110             :                                                            dst_port);
     111             : 
     112             :               //u32 pak_sent = clib_host_to_net_u32(stats->pak_sent);
     113             :               //memcpy (b0->data + next_offset, &pak_sent, sizeof(u32));
     114             :               //next_offset += sizeof(u32);
     115             : 
     116             :               /* Flush data if packet len is about to reach path mtu */
     117           0 :               if (next_offset > (exp->path_mtu - UDP_PING_EXPORT_RECORD_SIZE))
     118             :                 {
     119           0 :                   b0->current_length = next_offset;
     120           0 :                   b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
     121           0 :                   tp = vlib_buffer_get_current (b0);
     122           0 :                   ip = (ip4_header_t *) & tp->ip4;
     123           0 :                   udp = (udp_header_t *) (ip + 1);
     124           0 :                   h = &tp->ipfix.h;
     125           0 :                   s = &tp->ipfix.s;
     126             : 
     127           0 :                   s->set_id_length =
     128           0 :                     ipfix_set_id_length (IOAM_FLOW_TEMPLATE_ID,
     129           0 :                                          next_offset - (sizeof (*ip) +
     130             :                                                         sizeof (*udp) +
     131             :                                                         sizeof (*h)));
     132           0 :                   h->version_length =
     133           0 :                     version_length (next_offset -
     134             :                                     (sizeof (*ip) + sizeof (*udp)));
     135             : 
     136           0 :                   sum0 = ip->checksum;
     137           0 :                   old_l0 = ip->length;
     138           0 :                   new_l0 = clib_host_to_net_u16 ((u16) next_offset);
     139           0 :                   sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t,
     140             :                                          length /* changed member */ );
     141             : 
     142           0 :                   ip->checksum = ip_csum_fold (sum0);
     143           0 :                   ip->length = new_l0;
     144           0 :                   udp->length =
     145           0 :                     clib_host_to_net_u16 (b0->current_length - sizeof (*ip));
     146             : 
     147           0 :                   udp->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ip);
     148           0 :                   if (udp->checksum == 0)
     149           0 :                     udp->checksum = 0xffff;
     150             : 
     151           0 :                   ASSERT (ip4_header_checksum_is_valid (ip));
     152             : 
     153           0 :                   to_next[0] = bi0;
     154           0 :                   f->n_vectors++;
     155           0 :                   to_next++;
     156             : 
     157           0 :                   if (f->n_vectors == VLIB_FRAME_SIZE)
     158             :                     {
     159           0 :                       vlib_put_frame_to_node (vm, node_index, f);
     160           0 :                       f = vlib_get_frame_to_node (vm, node_index);
     161           0 :                       f->n_vectors = 0;
     162           0 :                       to_next = vlib_frame_vector_args (f);
     163             :                     }
     164           0 :                   b0 = 0;
     165           0 :                   bi0 = ~0;
     166             :                 }
     167             :             }
     168             :         }
     169             :     }
     170             : 
     171           0 :   if (b0)
     172             :     {
     173           0 :       b0->current_length = next_offset;
     174           0 :       b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
     175           0 :       tp = vlib_buffer_get_current (b0);
     176           0 :       ip = (ip4_header_t *) & tp->ip4;
     177           0 :       udp = (udp_header_t *) (ip + 1);
     178           0 :       h = &tp->ipfix.h;
     179           0 :       s = &tp->ipfix.s;
     180             : 
     181           0 :       s->set_id_length = ipfix_set_id_length (IOAM_FLOW_TEMPLATE_ID,
     182           0 :                                               next_offset - (sizeof (*ip) +
     183             :                                                              sizeof (*udp) +
     184             :                                                              sizeof (*h)));
     185           0 :       h->version_length =
     186           0 :         version_length (next_offset - (sizeof (*ip) + sizeof (*udp)));
     187             : 
     188           0 :       sum0 = ip->checksum;
     189           0 :       old_l0 = ip->length;
     190           0 :       new_l0 = clib_host_to_net_u16 ((u16) next_offset);
     191           0 :       sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t,
     192             :                              length /* changed member */ );
     193             : 
     194           0 :       ip->checksum = ip_csum_fold (sum0);
     195           0 :       ip->length = new_l0;
     196           0 :       udp->length = clib_host_to_net_u16 (b0->current_length - sizeof (*ip));
     197             : 
     198           0 :       udp->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ip);
     199           0 :       if (udp->checksum == 0)
     200           0 :         udp->checksum = 0xffff;
     201             : 
     202           0 :       ASSERT (ip4_header_checksum_is_valid (ip));
     203             : 
     204           0 :       to_next[0] = bi0;
     205           0 :       f->n_vectors++;
     206           0 :       to_next++;
     207             : 
     208           0 :       if (f->n_vectors == VLIB_FRAME_SIZE)
     209             :         {
     210           0 :           vlib_put_frame_to_node (vm, node_index, f);
     211           0 :           f = vlib_get_frame_to_node (vm, node_index);
     212           0 :           f->n_vectors = 0;
     213           0 :           to_next = vlib_frame_vector_args (f);
     214             :         }
     215           0 :       b0 = 0;
     216           0 :       bi0 = ~0;
     217             :     }
     218           0 :   return f;
     219             : }
     220             : 
     221             : clib_error_t *
     222           0 : udp_ping_flow_create (u8 del)
     223             : {
     224             :   vnet_flow_report_add_del_args_t args;
     225             :   int rv;
     226           0 :   u32 domain_id = 0;
     227           0 :   ipfix_exporter_t *exp = &flow_report_main.exporters[0];
     228             :   u16 template_id;
     229             : 
     230           0 :   clib_memset (&args, 0, sizeof (args));
     231           0 :   args.rewrite_callback = udp_ping_template_rewrite;
     232           0 :   args.flow_data_callback = udp_ping_send_flows;
     233           0 :   del ? (args.is_add = 0) : (args.is_add = 1);
     234           0 :   args.domain_id = domain_id;
     235           0 :   args.src_port = UDP_DST_PORT_ipfix;
     236             : 
     237           0 :   rv = vnet_flow_report_add_del (exp, &args, &template_id);
     238             : 
     239           0 :   switch (rv)
     240             :     {
     241           0 :     case 0:
     242           0 :       break;
     243           0 :     case VNET_API_ERROR_NO_SUCH_ENTRY:
     244           0 :       return clib_error_return (0, "registration not found...");
     245           0 :     default:
     246           0 :       return clib_error_return (0, "vnet_flow_report_add_del returned %d",
     247             :                                 rv);
     248             :     }
     249             : 
     250           0 :   return 0;
     251             : }
     252             : 
     253             : static clib_error_t *
     254           0 : set_udp_ping_export_command_fn (vlib_main_t * vm, unformat_input_t * input,
     255             :                                 vlib_cli_command_t * cmd)
     256             : {
     257             :   //int rv;
     258           0 :   int is_add = 1;
     259             : 
     260           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     261             :     {
     262           0 :       if (unformat (input, "export-ipfix"))
     263           0 :         is_add = 1;
     264           0 :       else if (unformat (input, "disable"))
     265           0 :         is_add = 0;
     266             :       else
     267           0 :         break;
     268             :     }
     269             : 
     270           0 :   if (is_add)
     271           0 :     (void) udp_ping_flow_create (0);
     272             :   else
     273           0 :     (void) udp_ping_flow_create (1);
     274             : 
     275           0 :   return 0;
     276             : }
     277             : 
     278             : /* *INDENT-OFF* */
     279      176567 : VLIB_CLI_COMMAND (set_udp_ping_export_command, static) = {
     280             :     .path = "set udp-ping export-ipfix",
     281             :     .short_help = "set udp-ping export-ipfix [disable]",
     282             :     .function = set_udp_ping_export_command_fn,
     283             : };
     284             : /* *INDENT-ON* */
     285             : 
     286             : clib_error_t *
     287         559 : udp_ping_flow_report_init (vlib_main_t * vm)
     288             : {
     289         559 :   return 0;
     290             : }
     291             : 
     292             : /* *INDENT-OFF* */
     293        8399 : VLIB_INIT_FUNCTION (udp_ping_flow_report_init) =
     294             : {
     295             :   .runs_after = VLIB_INITS ("flow_report_init"),
     296             : };
     297             : /* *INDENT-ON* */
     298             : 
     299             : 
     300             : /*
     301             :  * fd.io coding-style-patch-verification: ON
     302             :  *
     303             :  * Local Variables:
     304             :  * eval: (c-set-style "gnu")
     305             :  * End:
     306             :  */

Generated by: LCOV version 1.14