FD.io VPP  v21.06-3-gbb25fbf28
Vector Packet Processing
ip6_ioam_pot.c
Go to the documentation of this file.
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 
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 
34 #define _(sym,string) string,
36 #undef _
37 };
38 
39 typedef enum {
40 #define _(sym,str) IP6_IOAM_POT_##sym,
42 #undef _
45 
46 typedef struct {
47  /* stats */
49 
50  /* convenience */
54 
56 
57 always_inline void
59 {
61 
62  hm->counters[counter_index] += increment;
63 }
64 
65 
66 static u8 * format_ioam_pot (u8 * s, va_list * args)
67 {
68  ioam_pot_option_t * pot0 = va_arg (*args, ioam_pot_option_t *);
69  u64 random, cumulative;
70  random = cumulative = 0;
71  if (pot0)
72  {
73  random = clib_net_to_host_u64 (pot0->random);
74  cumulative = clib_net_to_host_u64 (pot0->cumulative);
75  }
76 
77  s = format (s, "random = 0x%Lx, Cumulative = 0x%Lx, Index = 0x%x",
78  random, cumulative, pot0 ? pot0->reserved_profile_id : ~0);
79  return s;
80 }
81 
82 u8 *
84 {
85  ioam_pot_option_t *pot;
86 
87  s = format (s, " POT opt present\n");
88  pot = (ioam_pot_option_t *) opt;
89  s = format (s, " %U\n", format_ioam_pot, pot);
90  return (s);
91 }
92 
93 int
97 {
98  ioam_pot_option_t * pot0;
99  u64 random = 0, cumulative = 0;
100  int rv = 0;
101  u8 pot_profile_index;
102  pot_profile *pot_profile = 0, *new_profile = 0;
103  u8 pot_encap = 0;
104 
105  pot0 = (ioam_pot_option_t *) opt0;
106  pot_encap = (pot0->random == 0);
107  pot_profile_index = pot_profile_get_active_id();
109  if (pot_encap && PREDICT_FALSE(!pot_profile))
110  {
111  ip6_ioam_stats_increment_counter (IP6_IOAM_POT_PROFILE_MISS, 1);
112  return(-1);
113  }
114  if (pot_encap)
115  {
116  pot0->reserved_profile_id =
117  pot_profile_index & PROFILE_ID_MASK;
119  }
120  else
121  { /* Non encap node */
122  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  pot_profile_find(pot0->reserved_profile_id);
128  if (PREDICT_FALSE(new_profile == 0 ||
129  new_profile->valid == 0))
130  {
131  ip6_ioam_stats_increment_counter (IP6_IOAM_POT_PROFILE_MISS, 1);
132  return(-1);
133  }
134  else
135  {
136  pot_profile_index = pot0->reserved_profile_id;
137  pot_profile = new_profile;
138  pot_profile_set_active(pot_profile_index);
140  }
141  }
143  }
144 
145  if (pot0->random == 0)
146  {
147  pot0->random = clib_host_to_net_u64(pot_generate_random(pot_profile));
148  pot0->cumulative = 0;
149  }
150  random = clib_net_to_host_u64(pot0->random);
151  cumulative = clib_net_to_host_u64(pot0->cumulative);
152  pot0->cumulative = clib_host_to_net_u64(
154  cumulative,
155  random));
156  ip6_ioam_stats_increment_counter (IP6_IOAM_POT_PROCESSED, 1);
157 
158  return (rv);
159 }
160 
161 int
164 {
165  ioam_pot_option_t * pot0;
166  u64 random = 0;
167  u64 cumulative = 0;
168  int rv = 0;
170  u8 result = 0;
171 
172  pot0 = (ioam_pot_option_t *) opt0;
173  random = clib_net_to_host_u64(pot0->random);
174  cumulative = clib_net_to_host_u64(pot0->cumulative);
176  result = pot_validate (pot_profile,
177  cumulative, random);
178 
179  if (result == 1)
180  {
181  ip6_ioam_stats_increment_counter (IP6_IOAM_POT_PASSED, 1);
182  }
183  else
184  {
185  ip6_ioam_stats_increment_counter (IP6_IOAM_POT_FAILED, 1);
186  }
187  return (rv);
188 }
189 
190 int ip6_hop_by_hop_ioam_pot_rewrite_handler (u8 *rewrite_string, u8 *rewrite_size)
191 {
192  ioam_pot_option_t * pot_option;
193  if (rewrite_string && *rewrite_size == sizeof(ioam_pot_option_t))
194  {
195  pot_option = (ioam_pot_option_t *)rewrite_string;
196  pot_option->hdr.type = HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT
198  pot_option->hdr.length = sizeof (ioam_pot_option_t) -
199  sizeof (ip6_hop_by_hop_option_t);
200  return(0);
201  }
202  return(-1);
203 }
204 
205 static clib_error_t *
207  unformat_input_t * input,
208  vlib_cli_command_t * cmd)
209 {
211  u8 *s = 0;
212  int i = 0;
213 
214  for ( i = 0; i < IP6_IOAM_POT_N_STATS; i++)
215  {
216  s = format(s, " %s - %lu\n", ip6_hop_by_hop_ioam_pot_stats_strings[i],
217  hm->counters[i]);
218  }
219 
220  vlib_cli_output(vm, "%v", s);
221  vec_free(s);
222  return 0;
223 }
224 
225 
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 *
235 {
237 
238  hm->vlib_main = vm;
239  hm->vnet_main = vnet_get_main();
240  clib_memset(hm->counters, 0, sizeof(hm->counters));
241 
244  return (clib_error_create("registration of HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT failed"));
245 
247  sizeof(ioam_pot_option_t),
249  return (clib_error_create("registration of HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT for rewrite failed"));
250 
253  return (clib_error_create("registration of HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT POP failed"));
254 
255  return (0);
256 }
257 
258 /* *INDENT-OFF* */
260 {
261  .runs_after = VLIB_INITS("ip6_hop_by_hop_ioam_init"),
262 };
263 /* *INDENT-OFF* */
vlib.h
IP6_IOAM_POT_N_STATS
@ IP6_IOAM_POT_N_STATS
Definition: ip6_ioam_pot.c:43
pot_generate_random
u64 pot_generate_random(pot_profile *profile)
Definition: pot_util.c:210
ip6_hop_by_hop_ioam_pot_init
static clib_error_t * ip6_hop_by_hop_ioam_pot_init(vlib_main_t *vm)
Definition: ip6_ioam_pot.c:234
ip6_ioam_pot_stats_t
ip6_ioam_pot_stats_t
Definition: ip6_ioam_pot.c:39
elog.h
ip6_ioam_stats_increment_counter
static void ip6_ioam_stats_increment_counter(u32 counter_index, u64 increment)
Definition: ip6_ioam_pot.c:58
pot_util.h
pot_profile_find
pot_profile * pot_profile_find(u8 id)
Definition: pot_util.c:58
vlib_cli_command_t::path
char * path
Definition: cli.h:96
pot_validate
u8 pot_validate(pot_profile *profile, u64 cumulative, u64 random)
Definition: pot_util.c:197
ip6_hbh_ioam_proof_of_transit_pop_handler
int ip6_hbh_ioam_proof_of_transit_pop_handler(vlib_buffer_t *b, ip6_header_t *ip, ip6_hop_by_hop_option_t *opt0)
Definition: ip6_ioam_pot.c:162
vm
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
counter_index
static u32 counter_index(vlib_main_t *vm, vlib_error_t e)
Definition: drop.c:67
ip6_hbh_ioam_proof_of_transit_trace_handler
u8 * ip6_hbh_ioam_proof_of_transit_trace_handler(u8 *s, ip6_hop_by_hop_option_t *opt)
Definition: ip6_ioam_pot.c:83
ip6_hop_by_hop_option_t
Definition: ip6_hop_by_hop_packet.h:29
pot_profile_reset_usage_stats
static void pot_profile_reset_usage_stats(pot_profile *pow)
Definition: pot_util.h:180
unformat_input_t
struct _unformat_input_t unformat_input_t
ip6_ioam_pot.h
ip6_show_ioam_pot_cmd
static vlib_cli_command_t ip6_show_ioam_pot_cmd
(constructor) VLIB_CLI_COMMAND (ip6_show_ioam_pot_cmd)
Definition: ip6_ioam_pot.c:226
ip6_show_ioam_pot_cmd_fn
static clib_error_t * ip6_show_ioam_pot_cmd_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ip6_ioam_pot.c:206
pot_profile_incr_usage_stats
static void pot_profile_incr_usage_stats(pot_profile *pow)
Definition: pot_util.h:187
ip6_hop_by_hop_ioam_pot_main_t::vlib_main
vlib_main_t * vlib_main
Definition: ip6_ioam_pot.c:51
ip6_hbh_register_option
int ip6_hbh_register_option(u8 option, int options(vlib_buffer_t *b, ip6_header_t *ip, ip6_hop_by_hop_option_t *opt), u8 *trace(u8 *s, ip6_hop_by_hop_option_t *opt))
Definition: ip6_forward.c:2731
clib_error_create
#define clib_error_create(args...)
Definition: error.h:96
error.h
vnet_get_main
vnet_main_t * vnet_get_main(void)
Definition: pnat_test_stubs.h:56
PROFILE_ID_MASK
#define PROFILE_ID_MASK
PREDICT_FALSE
#define PREDICT_FALSE(x)
Definition: clib.h:124
ARRAY_LEN
#define ARRAY_LEN(x)
Definition: clib.h:70
format_ioam_pot
static u8 * format_ioam_pot(u8 *s, va_list *args)
Definition: ip6_ioam_pot.c:66
i
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:261
VLIB_CLI_COMMAND
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:163
pot_profile_
Usage:
Definition: pot_util.h:54
vlib_cli_output
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:716
ip6_hop_by_hop_ioam_pot_stats_strings
static char * ip6_hop_by_hop_ioam_pot_stats_strings[]
Definition: ip6_ioam_pot.c:33
vnet_main_t
Definition: vnet.h:76
vec_free
#define vec_free(V)
Free vector's memory (no header).
Definition: vec.h:395
always_inline
#define always_inline
Definition: rdma_mlx5dv.h:23
ip6_hop_by_hop_ioam_pot_rewrite_handler
int ip6_hop_by_hop_ioam_pot_rewrite_handler(u8 *rewrite_string, u8 *rewrite_size)
Definition: ip6_ioam_pot.c:190
u64
unsigned long u64
Definition: types.h:89
HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT
#define HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT
Definition: ip6_hop_by_hop_packet.h:45
format
description fragment has unexpected format
Definition: map.api:433
ip6_hop_by_hop_ioam_pot_main
ip6_hop_by_hop_ioam_pot_main_t ip6_hop_by_hop_ioam_pot_main
Definition: ip6_ioam_pot.c:55
u32
unsigned int u32
Definition: types.h:88
VLIB_INIT_FUNCTION
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:172
ip6_header_t
Definition: ip6_packet.h:294
ip6_hbh_pop_register_option
int ip6_hbh_pop_register_option(u8 option, int options(vlib_buffer_t *b, ip6_header_t *ip, ip6_hop_by_hop_option_t *opt))
Definition: ip6_hop_by_hop.c:481
pot_profile_get_active
static pot_profile * pot_profile_get_active(void)
Definition: pot_util.h:170
HBH_OPTION_TYPE_DATA_CHANGE_ENROUTE
#define HBH_OPTION_TYPE_DATA_CHANGE_ENROUTE
Definition: ip6_hop_by_hop_packet.h:37
clib_memset
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
vlib_main_t
Definition: main.h:102
VLIB_INITS
#define VLIB_INITS(...)
Definition: init.h:352
hash.h
b
vlib_buffer_t ** b
Definition: nat44_ei_out2in.c:717
u8
unsigned char u8
Definition: types.h:56
clib_error_t
Definition: clib_error.h:21
ip6_hbh_ioam_proof_of_transit_handler
int ip6_hbh_ioam_proof_of_transit_handler(vlib_buffer_t *b, ip6_header_t *ip, ip6_hop_by_hop_option_t *opt0)
Definition: ip6_ioam_pot.c:94
ip
vl_api_address_t ip
Definition: l2.api:558
vlib_init_function_t
clib_error_t *() vlib_init_function_t(struct vlib_main_t *vm)
Definition: init.h:51
ip6_hop_by_hop_ioam_pot_main_t::counters
u64 counters[ARRAY_LEN(ip6_hop_by_hop_ioam_pot_stats_strings)]
Definition: ip6_ioam_pot.c:48
foreach_ip6_hop_by_hop_ioam_pot_stats
#define foreach_ip6_hop_by_hop_ioam_pot_stats
Definition: ip6_ioam_pot.c:27
pot_profile_get_active_id
static u8 pot_profile_get_active_id(void)
Definition: pot_util.h:164
ip6_hop_by_hop_ioam_pot_main_t
Definition: ip6_ioam_pot.c:46
rv
int __clib_unused rv
Definition: application.c:491
pot_update_cumulative
u64 pot_update_cumulative(pot_profile *profile, u64 cumulative, u64 random)
Definition: pot_util.c:169
vnet.h
vlib_cli_command_t
Definition: cli.h:92
pot_profile_set_active
static int pot_profile_set_active(u8 id)
Definition: pot_util.h:148
ip6.h
ip6_hbh_add_register_option
int ip6_hbh_add_register_option(u8 option, u8 size, int rewrite_options(u8 *rewrite_string, u8 *rewrite_size))
Definition: ip6_hop_by_hop.c:102
ip6_hop_by_hop_ioam_pot_main_t::vnet_main
vnet_main_t * vnet_main
Definition: ip6_ioam_pot.c:52
vlib_buffer_t
VLIB buffer representation.
Definition: buffer.h:111