LCOV - code coverage report
Current view: top level - plugins/ioam/udp-ping - udp_ping_util.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 0 154 0.0 %
Date: 2023-07-05 22:20:52 Functions: 0 7 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2017 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/vnet.h>
      17             : #include <vnet/ip/ip.h>
      18             : #include <vnet/ip/ip6_hop_by_hop.h>
      19             : #include <ioam/encap/ip6_ioam_e2e.h>
      20             : #include <ioam/encap/ip6_ioam_trace.h>
      21             : #include <ioam/udp-ping/udp_ping_packet.h>
      22             : #include <ioam/udp-ping/udp_ping.h>
      23             : 
      24             : #define UDP_PING_REWRITE_LEN 1000
      25             : 
      26             : u16
      27           0 : udp_ping_fill_udp_data (udp_ping_t * udp_ping,
      28             :                         u16 src_port, u16 dst_port, u8 msg_type, u16 ctx)
      29             : {
      30             :   /* Populate udp ping header */
      31           0 :   udp_ping->udp.src_port = clib_host_to_net_u16 (src_port);
      32           0 :   udp_ping->udp.dst_port = clib_host_to_net_u16 (dst_port);
      33           0 :   udp_ping->udp.length = clib_host_to_net_u16 (sizeof (udp_ping_t));
      34           0 :   udp_ping->udp.checksum = 0;
      35           0 :   udp_ping->ping_data.probe_marker1 =
      36           0 :     clib_host_to_net_u32 (UDP_PING_PROBE_MARKER1);
      37           0 :   udp_ping->ping_data.probe_marker2 =
      38           0 :     clib_host_to_net_u32 (UDP_PING_PROBE_MARKER2);
      39           0 :   udp_ping->ping_data.version = 1;
      40           0 :   udp_ping->ping_data.msg_type = msg_type;
      41           0 :   udp_ping->ping_data.flags = clib_host_to_net_u16 (0);
      42           0 :   udp_ping->ping_data.tel_req_vec = clib_host_to_net_u16 (0);
      43           0 :   udp_ping->ping_data.hop_limit = 254;
      44           0 :   udp_ping->ping_data.hop_count = 0;
      45           0 :   udp_ping->ping_data.reserve = clib_host_to_net_u16 (0);
      46           0 :   udp_ping->ping_data.max_len =
      47           0 :     udp_ping->ping_data.cur_len = clib_host_to_net_u16 (0);
      48           0 :   udp_ping->ping_data.sender_handle = clib_host_to_net_u16 (ctx);
      49           0 :   udp_ping->ping_data.seq_no = clib_host_to_net_u16 (0);
      50             : 
      51           0 :   return (sizeof (udp_ping_t));
      52             : }
      53             : 
      54             : /**
      55             :  * @brief Frame IPv6 udp-ping probe packet.
      56             :  *
      57             :  * Creates IPv6 UDP-Ping probe packet along with iOAM headers.
      58             :  *
      59             :  */
      60             : int
      61           0 : udp_ping_create_ip6_pak (u8 * buf,      /*u16 len, */
      62             :                          ip6_address_t src, ip6_address_t dst,
      63             :                          u16 src_port, u16 dst_port, u8 msg_type, u16 ctx)
      64             : {
      65             :   ip6_header_t *ip0;
      66             :   ip6_hop_by_hop_header_t *hbh0;
      67             :   //trace_profile *profile = NULL;
      68           0 :   u16 hbh_len = 0, rnd_size = 0, ip0_len = 0, udp_len = 0;
      69           0 :   u16 trace_len = 0, trace_data_size = 0;
      70           0 :   u16 e2e_len = sizeof (ioam_e2e_option_t) - sizeof (ip6_hop_by_hop_option_t);
      71           0 :   u8 *current = NULL;
      72             :   ioam_trace_option_t *trace_option;
      73             :   ioam_e2e_option_t *e2e;
      74             : 
      75           0 :   ip0 = (ip6_header_t *) buf;
      76             : 
      77           0 :   ip0->ip_version_traffic_class_and_flow_label =
      78           0 :     clib_host_to_net_u32 (0x6 << 28);
      79             : 
      80           0 :   ip0->protocol = IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS;
      81           0 :   ip0->hop_limit = 255;
      82             : 
      83           0 :   ip0->src_address = src;
      84           0 :   ip0->dst_address = dst;
      85             : 
      86           0 :   hbh0 = (ip6_hop_by_hop_header_t *) (ip0 + 1);
      87             : 
      88             :   /* Calculate hbh header len */
      89             :   //profile = trace_profile_find();
      90           0 :   trace_data_size = fetch_trace_data_size (TRACE_TYPE_IF_TS_APP);
      91             :   /* We need 2 times data for trace as packet traverse back to source */
      92           0 :   trace_len = sizeof (ioam_trace_option_t) +
      93           0 :     (5 * trace_data_size * 2) - sizeof (ip6_hop_by_hop_option_t);
      94             :   //(profile->num_elts * trace_data_size * 2);
      95           0 :   hbh_len = e2e_len + trace_len + sizeof (ip6_hop_by_hop_header_t);
      96           0 :   rnd_size = (hbh_len + 7) & ~7;
      97             : 
      98             :   /* Length of header in 8 octet units, not incl first 8 octets */
      99           0 :   hbh0->length = (rnd_size >> 3) - 1;
     100           0 :   hbh0->protocol = IP_PROTOCOL_UDP;
     101             : 
     102             :   /* Populate hbh header */
     103           0 :   current = (u8 *) (hbh0 + 1);
     104             : 
     105             :   /* Populate trace */
     106           0 :   trace_option = (ioam_trace_option_t *) current;
     107           0 :   trace_option->hdr.type = HBH_OPTION_TYPE_IOAM_TRACE_DATA_LIST |
     108             :     HBH_OPTION_TYPE_DATA_CHANGE_ENROUTE;
     109           0 :   trace_option->hdr.length = trace_len;
     110           0 :   trace_option->trace_hdr.ioam_trace_type =
     111             :     TRACE_TYPE_IF_TS_APP & TRACE_TYPE_MASK;
     112             : 
     113           0 :   trace_option->trace_hdr.data_list_elts_left = 5 * 2;
     114             :   //profile->num_elts * 2;
     115             : 
     116           0 :   current += trace_option->hdr.length + sizeof (ip6_hop_by_hop_option_t);
     117             : 
     118             :   /* Populate e2e */
     119           0 :   e2e = (ioam_e2e_option_t *) current;
     120           0 :   e2e->hdr.type = HBH_OPTION_TYPE_IOAM_EDGE_TO_EDGE;
     121           0 :   e2e->hdr.length = e2e_len;
     122             : 
     123             :   /* Move past hbh header */
     124           0 :   current = ((u8 *) hbh0) + ((hbh0->length + 1) << 3);
     125             : 
     126             :   /* Populate udp ping header */
     127           0 :   udp_len = udp_ping_fill_udp_data ((udp_ping_t *) current,
     128             :                                     src_port, dst_port, msg_type, ctx);
     129             : 
     130             :   /* Calculate total length and set it in ip6 header */
     131           0 :   ip0_len = ((hbh0->length + 1) << 3) + udp_len;
     132             :   //ip0_len = (len > ip0_len) ? len : ip0_len;
     133           0 :   ip0->payload_length = clib_host_to_net_u16 (ip0_len);
     134             : 
     135           0 :   return (ip0_len + sizeof (ip6_header_t));
     136             : }
     137             : 
     138             : int
     139           0 : udp_ping_compare_flow (ip46_address_t src, ip46_address_t dst,
     140             :                        u16 start_src_port, u16 end_src_port,
     141             :                        u16 start_dst_port, u16 end_dst_port,
     142             :                        ip46_udp_ping_flow * flow)
     143             : {
     144           0 :   if ((0 == ip46_address_cmp (&flow->src, &src)) &&
     145           0 :       (0 == ip46_address_cmp (&flow->dst, &dst)) &&
     146           0 :       (flow->udp_data.start_src_port == start_src_port) &&
     147           0 :       (flow->udp_data.end_src_port == end_src_port) &&
     148           0 :       (flow->udp_data.start_dst_port == start_dst_port) &&
     149           0 :       (flow->udp_data.end_dst_port == end_dst_port))
     150             :     {
     151           0 :       return 0;
     152             :     }
     153             : 
     154           0 :   return -1;
     155             : }
     156             : 
     157             : void
     158           0 : udp_ping_populate_flow (ip46_address_t src, ip46_address_t dst,
     159             :                         u16 start_src_port, u16 end_src_port,
     160             :                         u16 start_dst_port, u16 end_dst_port,
     161             :                         u16 interval, u8 fault_det, ip46_udp_ping_flow * flow)
     162             : {
     163           0 :   flow->src = src;
     164           0 :   flow->dst = dst;
     165           0 :   flow->udp_data.start_src_port = start_src_port;
     166           0 :   flow->udp_data.end_src_port = end_src_port;
     167           0 :   flow->udp_data.start_dst_port = start_dst_port;
     168           0 :   flow->udp_data.end_dst_port = end_dst_port;
     169           0 :   flow->udp_data.interval = interval;
     170           0 :   flow->udp_data.next_send_time = 0;
     171           0 :   flow->fault_det = fault_det;
     172           0 : }
     173             : 
     174             : void
     175           0 : udp_ping_create_rewrite (ip46_udp_ping_flow * flow, u16 ctx)
     176             : {
     177             :   u16 src_port;
     178             :   u16 dst_port;
     179             :   u16 no_flows;
     180             :   int i;
     181             :   udp_ping_flow_data *stats;
     182             : 
     183           0 :   no_flows =
     184           0 :     (flow->udp_data.end_dst_port - flow->udp_data.start_dst_port) + 1;
     185           0 :   no_flows *=
     186           0 :     ((flow->udp_data.end_src_port - flow->udp_data.start_src_port) + 1);
     187             : 
     188           0 :   vec_validate_aligned (flow->udp_data.stats,
     189             :                         no_flows - 1, CLIB_CACHE_LINE_BYTES);
     190             : 
     191           0 :   i = 0;
     192           0 :   for (src_port = flow->udp_data.start_src_port;
     193           0 :        src_port <= flow->udp_data.end_src_port; src_port++)
     194             :     {
     195           0 :       for (dst_port = flow->udp_data.start_dst_port;
     196           0 :            dst_port <= flow->udp_data.end_dst_port; dst_port++)
     197             :         {
     198           0 :           u8 *rewrite = NULL;
     199             : 
     200           0 :           stats = flow->udp_data.stats + i;
     201           0 :           ioam_analyse_init_data (&stats->analyse_data);
     202           0 :           stats->analyse_data.is_free = 0;
     203             : 
     204           0 :           vec_validate (rewrite, UDP_PING_REWRITE_LEN - 1);
     205           0 :           stats->ping_rewrite = rewrite;
     206           0 :           stats->rewrite_len =
     207           0 :             udp_ping_create_ip6_pak (rewrite,
     208             :                                      flow->src.ip6, flow->dst.ip6,
     209             :                                      src_port, dst_port, UDP_PING_PROBE, ctx);
     210             :           /* For each flow we need to create ioam e2e flow */
     211           0 :           stats->flow_ctx = ioam_flow_add (1, (u8 *) "udp_ping");  //FIXME
     212           0 :           i++;
     213             :         }
     214             :     }
     215           0 : }
     216             : 
     217             : void
     218           0 : udp_ping_free_flow_data (ip46_udp_ping_flow * flow)
     219             : {
     220             :   int i;
     221             :   udp_ping_flow_data *stats;
     222             : 
     223           0 :   for (i = 0; i < vec_len (flow->udp_data.stats); i++)
     224             :     {
     225           0 :       stats = flow->udp_data.stats + i;
     226           0 :       vec_free (stats->ping_rewrite);
     227           0 :       stats->ping_rewrite = NULL;
     228           0 :       stats->rewrite_len = 0;
     229             :     }
     230             : 
     231           0 :   vec_free (flow->udp_data.stats);
     232           0 :   flow->udp_data.stats = NULL;
     233           0 : }
     234             : 
     235             : /**
     236             :  * @brief Create and send ipv6 udp-ping probe packet.
     237             :  *
     238             :  */
     239             : void
     240           0 : udp_ping_send_ip6_pak (vlib_main_t * vm, ip46_udp_ping_flow * flow)
     241             : {
     242             :   u16 no_pak;
     243           0 :   u32 *buffers = NULL;
     244             :   int i;
     245             :   vlib_buffer_t *b0;
     246             :   udp_ping_flow_data *stats;
     247           0 :   vlib_frame_t *nf = 0;
     248             :   u32 *to_next;
     249             :   vlib_node_t *next_node;
     250             : 
     251           0 :   next_node = vlib_get_node_by_name (vm, (u8 *) "ip6-lookup");
     252           0 :   nf = vlib_get_frame_to_node (vm, next_node->index);
     253           0 :   nf->n_vectors = 0;
     254           0 :   to_next = vlib_frame_vector_args (nf);
     255             : 
     256           0 :   no_pak = vec_len (flow->udp_data.stats);
     257           0 :   vec_validate (buffers, (no_pak - 1));
     258           0 :   if (vlib_buffer_alloc (vm, buffers, vec_len (buffers)) != no_pak)
     259             :     {
     260             :       //Error
     261           0 :       return;
     262             :     }
     263             : 
     264           0 :   for (i = 0; i < no_pak; i++)
     265             :     {
     266             :       int bogus;
     267           0 :       b0 = vlib_get_buffer (vm, buffers[i]);
     268           0 :       stats = flow->udp_data.stats + i;
     269           0 :       clib_memcpy_fast (b0->data, stats->ping_rewrite, stats->rewrite_len);
     270           0 :       b0->current_data = 0;
     271           0 :       b0->current_length = stats->rewrite_len;
     272           0 :       b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
     273             : 
     274             :       /* If session is going down, then set path down */
     275           0 :       if ((stats->retry != 0) && ((stats->retry % MAX_PING_RETRIES) == 0))
     276           0 :         ip6_ioam_analyse_set_paths_down (&stats->analyse_data);
     277             : 
     278           0 :       stats->retry++;
     279           0 :       stats->analyse_data.pkt_sent++;
     280           0 :       vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0;
     281           0 :       vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0;
     282           0 :       vnet_buffer (b0)->l2_classify.opaque_index = stats->flow_ctx;
     283             : 
     284           0 :       ip6_header_t *ip6 = vlib_buffer_get_current (b0);
     285           0 :       ip6_hop_by_hop_header_t *hbh = (ip6_hop_by_hop_header_t *) (ip6 + 1);
     286           0 :       udp_header_t *udp =
     287           0 :         (udp_header_t *) ((u8 *) hbh + ((hbh->length + 1) << 3));
     288             : 
     289             :       /* If session is down, then set loopback flag in probe.
     290             :        * This is for fault isolation.
     291             :        */
     292           0 :       if (flow->fault_det && (stats->retry > MAX_PING_RETRIES))
     293             :         {
     294             :           ioam_trace_option_t *opt = (ioam_trace_option_t *)
     295           0 :             ip6_hbh_get_option (hbh, HBH_OPTION_TYPE_IOAM_TRACE_DATA_LIST);
     296           0 :           ip6_hbh_ioam_trace_set_bit (opt, BIT_LOOPBACK);
     297             :         }
     298             : 
     299             :       /* Checksum not pre-computed as we intend to vary packet length for every
     300             :        * probe. its isnt done yet, but to be taken up later.
     301             :        */
     302           0 :       udp->checksum = ip6_tcp_udp_icmp_compute_checksum (vm, b0, ip6, &bogus);
     303           0 :       ASSERT (bogus == 0);
     304           0 :       if (udp->checksum == 0)
     305           0 :         udp->checksum = 0xffff;
     306             : 
     307           0 :       if (nf->n_vectors == VLIB_FRAME_SIZE)
     308             :         {
     309           0 :           vlib_put_frame_to_node (vm, next_node->index, nf);
     310           0 :           nf = vlib_get_frame_to_node (vm, next_node->index);
     311           0 :           nf->n_vectors = 0;
     312           0 :           to_next = vlib_frame_vector_args (nf);
     313             :         }
     314           0 :       *to_next = buffers[i];
     315           0 :       nf->n_vectors++;
     316           0 :       to_next++;
     317             :     }
     318           0 :   vlib_put_frame_to_node (vm, next_node->index, nf);
     319             : 
     320           0 :   flow->udp_data.next_send_time =
     321           0 :     vlib_time_now (vm) + flow->udp_data.interval;
     322             : }
     323             : 
     324             : /*
     325             :  * fd.io coding-style-patch-verification: ON
     326             :  *
     327             :  * Local Variables:
     328             :  * eval: (c-set-style "gnu")
     329             :  * End:
     330             :  */

Generated by: LCOV version 1.14