LCOV - code coverage report
Current view: top level - plugins/ioam/encap - ip6_ioam_pot.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 11 97 11.3 %
Date: 2023-07-05 22:20:52 Functions: 5 12 41.7 %

          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             : #include <vlib/vlib.h>
      16             : #include <vnet/vnet.h>
      17             : #include <vppinfra/error.h>
      18             : #include <vnet/ip/ip6.h>
      19             : 
      20             : #include <vppinfra/hash.h>
      21             : #include <vppinfra/error.h>
      22             : #include <vppinfra/elog.h>
      23             : 
      24             : #include <ioam/encap/ip6_ioam_pot.h>
      25             : #include <ioam/lib-pot/pot_util.h>
      26             : 
      27             : #define foreach_ip6_hop_by_hop_ioam_pot_stats                           \
      28             :   _(PROCESSED, "Pkts with ip6 hop-by-hop pot options")                        \
      29             :   _(PROFILE_MISS, "Pkts with ip6 hop-by-hop pot options but no profile set") \
      30             :   _(PASSED, "Pkts with POT in Policy")                                        \
      31             :   _(FAILED, "Pkts with POT out of Policy")
      32             : 
      33             : static char * ip6_hop_by_hop_ioam_pot_stats_strings[] = {
      34             : #define _(sym,string) string,
      35             :   foreach_ip6_hop_by_hop_ioam_pot_stats
      36             : #undef _
      37             : };
      38             : 
      39             : typedef enum {
      40             : #define _(sym,str) IP6_IOAM_POT_##sym,
      41             :   foreach_ip6_hop_by_hop_ioam_pot_stats
      42             : #undef _
      43             :   IP6_IOAM_POT_N_STATS,
      44             : } ip6_ioam_pot_stats_t;
      45             : 
      46             : typedef struct {
      47             :   /* stats */
      48             :   u64 counters[ARRAY_LEN(ip6_hop_by_hop_ioam_pot_stats_strings)];
      49             : 
      50             :   /* convenience */
      51             :   vlib_main_t * vlib_main;
      52             :   vnet_main_t * vnet_main;
      53             : } ip6_hop_by_hop_ioam_pot_main_t;
      54             : 
      55             : ip6_hop_by_hop_ioam_pot_main_t ip6_hop_by_hop_ioam_pot_main;
      56             : 
      57             : always_inline void
      58           0 : ip6_ioam_stats_increment_counter (u32 counter_index, u64 increment)
      59             : {
      60           0 :   ip6_hop_by_hop_ioam_pot_main_t *hm = &ip6_hop_by_hop_ioam_pot_main;
      61             : 
      62           0 :   hm->counters[counter_index] += increment;
      63           0 : }
      64             : 
      65             : 
      66           0 : static u8 * format_ioam_pot (u8 * s, va_list * args)
      67             : {
      68           0 :   ioam_pot_option_t * pot0 = va_arg (*args, ioam_pot_option_t *);
      69             :   u64 random, cumulative;
      70           0 :   random = cumulative = 0;
      71           0 :   if (pot0)
      72             :     {
      73           0 :       random = clib_net_to_host_u64 (pot0->random);
      74           0 :       cumulative = clib_net_to_host_u64 (pot0->cumulative);
      75             :     }
      76             : 
      77           0 :   s = format (s, "random = 0x%Lx, Cumulative = 0x%Lx, Index = 0x%x",
      78           0 :               random, cumulative, pot0 ? pot0->reserved_profile_id : ~0);
      79           0 :   return s;
      80             : }
      81             : 
      82             : u8 *
      83           0 : ip6_hbh_ioam_proof_of_transit_trace_handler (u8 *s, ip6_hop_by_hop_option_t *opt)
      84             : {
      85             :   ioam_pot_option_t *pot;
      86             : 
      87           0 :   s = format (s, "    POT opt present\n");
      88           0 :   pot = (ioam_pot_option_t *) opt;
      89           0 :   s = format (s, "         %U\n", format_ioam_pot, pot);
      90           0 :   return (s);
      91             : }
      92             : 
      93             : int
      94           0 : ip6_hbh_ioam_proof_of_transit_handler (vlib_buffer_t *b,
      95             :                                        ip6_header_t *ip,
      96             :                                        ip6_hop_by_hop_option_t *opt0)
      97             : {
      98             :   ioam_pot_option_t * pot0;
      99           0 :   u64 random = 0, cumulative = 0;
     100           0 :   int rv = 0;
     101             :   u8 pot_profile_index;
     102           0 :   pot_profile *pot_profile = 0, *new_profile = 0;
     103           0 :   u8 pot_encap = 0;
     104             : 
     105           0 :   pot0 = (ioam_pot_option_t *) opt0;
     106           0 :   pot_encap = (pot0->random == 0);
     107           0 :   pot_profile_index = pot_profile_get_active_id();
     108           0 :   pot_profile = pot_profile_get_active();
     109           0 :   if (pot_encap && PREDICT_FALSE(!pot_profile))
     110             :     {
     111           0 :       ip6_ioam_stats_increment_counter (IP6_IOAM_POT_PROFILE_MISS, 1);
     112           0 :       return(-1);
     113             :     }
     114           0 :   if (pot_encap)
     115             :     {
     116           0 :       pot0->reserved_profile_id =
     117           0 :         pot_profile_index & PROFILE_ID_MASK;
     118           0 :       pot_profile_incr_usage_stats(pot_profile);
     119             :     }
     120             :   else
     121             :     { /* Non encap node */
     122           0 :       if (PREDICT_FALSE(pot0->reserved_profile_id !=
     123             :                         pot_profile_index || pot_profile == 0))
     124             :         {
     125             :           /* New profile announced by encap node. */
     126             :           new_profile =
     127           0 :             pot_profile_find(pot0->reserved_profile_id);
     128           0 :           if (PREDICT_FALSE(new_profile == 0 ||
     129             :                             new_profile->valid == 0))
     130             :             {
     131           0 :               ip6_ioam_stats_increment_counter (IP6_IOAM_POT_PROFILE_MISS, 1);
     132           0 :               return(-1);
     133             :             }
     134             :           else
     135             :             {
     136           0 :               pot_profile_index = pot0->reserved_profile_id;
     137           0 :               pot_profile = new_profile;
     138           0 :               pot_profile_set_active(pot_profile_index);
     139           0 :               pot_profile_reset_usage_stats(pot_profile);
     140             :             }
     141             :         }
     142           0 :       pot_profile_incr_usage_stats(pot_profile);
     143             :     }
     144             : 
     145           0 :   if (pot0->random == 0)
     146             :     {
     147           0 :       pot0->random = clib_host_to_net_u64(pot_generate_random(pot_profile));
     148           0 :       pot0->cumulative = 0;
     149             :     }
     150           0 :   random = clib_net_to_host_u64(pot0->random);
     151           0 :   cumulative = clib_net_to_host_u64(pot0->cumulative);
     152           0 :   pot0->cumulative = clib_host_to_net_u64(
     153             :                                           pot_update_cumulative(pot_profile,
     154             :                                                                 cumulative,
     155             :                                                                 random));
     156           0 :   ip6_ioam_stats_increment_counter (IP6_IOAM_POT_PROCESSED, 1);
     157             : 
     158           0 :   return (rv);
     159             : }
     160             : 
     161             : int
     162           0 : ip6_hbh_ioam_proof_of_transit_pop_handler (vlib_buffer_t *b, ip6_header_t *ip,
     163             :                                            ip6_hop_by_hop_option_t *opt0)
     164             : {
     165             :   ioam_pot_option_t * pot0;
     166           0 :   u64 random = 0;
     167           0 :   u64 cumulative = 0;
     168           0 :   int rv = 0;
     169           0 :   pot_profile *pot_profile = 0;
     170           0 :   u8 result = 0;
     171             : 
     172           0 :   pot0 = (ioam_pot_option_t *) opt0;
     173           0 :   random = clib_net_to_host_u64(pot0->random);
     174           0 :   cumulative = clib_net_to_host_u64(pot0->cumulative);
     175           0 :   pot_profile = pot_profile_get_active();
     176           0 :   result =  pot_validate (pot_profile,
     177             :                           cumulative, random);
     178             : 
     179           0 :   if (result == 1)
     180             :     {
     181           0 :       ip6_ioam_stats_increment_counter (IP6_IOAM_POT_PASSED, 1);
     182             :     }
     183             :   else
     184             :     {
     185           0 :       ip6_ioam_stats_increment_counter (IP6_IOAM_POT_FAILED, 1);
     186             :     }
     187           0 :   return (rv);
     188             : }
     189             : 
     190           0 : int ip6_hop_by_hop_ioam_pot_rewrite_handler (u8 *rewrite_string, u8 *rewrite_size)
     191             : {
     192             :   ioam_pot_option_t * pot_option;
     193           0 :   if (rewrite_string && *rewrite_size == sizeof(ioam_pot_option_t))
     194             :     {
     195           0 :       pot_option = (ioam_pot_option_t *)rewrite_string;
     196           0 :       pot_option->hdr.type = HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT
     197             :         | HBH_OPTION_TYPE_DATA_CHANGE_ENROUTE;
     198           0 :       pot_option->hdr.length = sizeof (ioam_pot_option_t) -
     199             :         sizeof (ip6_hop_by_hop_option_t);
     200           0 :       return(0);
     201             :     }
     202           0 :   return(-1);
     203             : }
     204             : 
     205             : static clib_error_t *
     206           0 : ip6_show_ioam_pot_cmd_fn (vlib_main_t * vm,
     207             :                           unformat_input_t * input,
     208             :                           vlib_cli_command_t * cmd)
     209             : {
     210           0 :   ip6_hop_by_hop_ioam_pot_main_t *hm = &ip6_hop_by_hop_ioam_pot_main;
     211           0 :   u8 *s = 0;
     212           0 :   int i = 0;
     213             : 
     214           0 :   for ( i = 0; i < IP6_IOAM_POT_N_STATS; i++)
     215             :     {
     216           0 :       s = format(s, " %s - %lu\n", ip6_hop_by_hop_ioam_pot_stats_strings[i],
     217             :                hm->counters[i]);
     218             :     }
     219             : 
     220           0 :   vlib_cli_output(vm, "%v", s);
     221           0 :   vec_free(s);
     222           0 :   return 0;
     223             : }
     224             : 
     225             : 
     226      176567 : VLIB_CLI_COMMAND (ip6_show_ioam_pot_cmd, static) = {
     227             :   .path = "show ioam pot",
     228             :   .short_help = "iOAM pot statistics",
     229             :   .function = ip6_show_ioam_pot_cmd_fn,
     230             : };
     231             : 
     232             : 
     233             : static clib_error_t *
     234         559 : ip6_hop_by_hop_ioam_pot_init (vlib_main_t * vm)
     235             : {
     236         559 :   ip6_hop_by_hop_ioam_pot_main_t * hm = &ip6_hop_by_hop_ioam_pot_main;
     237             : 
     238         559 :   hm->vlib_main = vm;
     239         559 :   hm->vnet_main = vnet_get_main();
     240         559 :   clib_memset(hm->counters, 0, sizeof(hm->counters));
     241             : 
     242         559 :   if (ip6_hbh_register_option(HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT, ip6_hbh_ioam_proof_of_transit_handler,
     243             :                               ip6_hbh_ioam_proof_of_transit_trace_handler) < 0)
     244           0 :     return (clib_error_create("registration of HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT failed"));
     245             : 
     246         559 :   if (ip6_hbh_add_register_option(HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT,
     247             :                                   sizeof(ioam_pot_option_t),
     248             :                                   ip6_hop_by_hop_ioam_pot_rewrite_handler) < 0)
     249           0 :     return (clib_error_create("registration of HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT for rewrite failed"));
     250             : 
     251         559 :   if (ip6_hbh_pop_register_option(HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT,
     252             :                                   ip6_hbh_ioam_proof_of_transit_pop_handler) < 0)
     253           0 :     return (clib_error_create("registration of HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT POP failed"));
     254             : 
     255         559 :   return (0);
     256             : }
     257             : 
     258             : /* *INDENT-OFF* */
     259        1119 : VLIB_INIT_FUNCTION (ip6_hop_by_hop_ioam_pot_init) =
     260             : {
     261             :   .runs_after = VLIB_INITS("ip6_hop_by_hop_ioam_init"),
     262             : };
     263             : /* *INDENT-OFF* */

Generated by: LCOV version 1.14