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