FD.io VPP  v17.10-9-gd594711
Vector Packet Processing
ioam_cache.c
Go to the documentation of this file.
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  *------------------------------------------------------------------
17  * ioam_cache.c - ioam ip6 API / debug CLI handling
18  *------------------------------------------------------------------
19  */
20 
21 #include <vnet/vnet.h>
22 #include <vnet/plugin/plugin.h>
23 #include <ioam/ip6/ioam_cache.h>
24 
25 #include <vlibapi/api.h>
26 #include <vlibmemory/api.h>
27 #include <vlibsocket/api.h>
28 #include <vnet/ip/ip6_hop_by_hop.h>
29 
30 #include "ioam_cache.h"
31 
32 /* define message IDs */
34 
35 /* define message structures */
36 #define vl_typedefs
38 #undef vl_typedefs
39 
40 /* define generated endian-swappers */
41 #define vl_endianfun
43 #undef vl_endianfun
44 
45 /* instantiate all the print functions we know about */
46 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
47 #define vl_printfun
49 #undef vl_printfun
50 
51 /* Get the API version number */
52 #define vl_api_version(n,v) static u32 api_version=(v);
54 #undef vl_api_version
55 
56 #define REPLY_MSG_ID_BASE cm->msg_id_base
58 
59 /* List of message types that this plugin understands */
60 #define foreach_ioam_cache_plugin_api_msg \
61 _(IOAM_CACHE_IP6_ENABLE_DISABLE, ioam_cache_ip6_enable_disable)
62 
63 static u8 *
65 {
66  ioam_e2e_id_option_t *e2e = (ioam_e2e_id_option_t *) opt;
67 
68  if (e2e)
69  {
70  s =
71  format (s, "IP6_HOP_BY_HOP E2E ID = %U\n", format_ip6_address,
72  &(e2e->id));
73  }
74 
75 
76  return s;
77 }
78 
79 static u8 *
81 {
82  ioam_e2e_cache_option_t *e2e = (ioam_e2e_cache_option_t *) opt;
83 
84  if (e2e)
85  {
86  s =
87  format (s, "IP6_HOP_BY_HOP E2E CACHE = pool:%d idx:%d\n",
88  e2e->pool_id, e2e->pool_index);
89  }
90 
91 
92  return s;
93 }
94 
95 /* Action function shared between message handler and debug CLI */
96 int
98  ip6_address_t * sr_localsid, u8 is_disable)
99 {
100  vlib_main_t *vm = em->vlib_main;
101 
102  if (is_disable == 0)
103  {
105  em->sr_localsid_cache.as_u64[0] = sr_localsid->as_u64[0];
106  em->sr_localsid_cache.as_u64[1] = sr_localsid->as_u64[1];
112 
113  }
114  else
115  {
118  em->sr_localsid_cache.as_u64[0] = 0;
119  em->sr_localsid_cache.as_u64[1] = 0;
122  }
123 
124  return 0;
125 }
126 
127 /* Action function shared between message handler and debug CLI */
128 int
130  u8 criteria,
131  u8 no_of_responses,
132  ip6_address_t * sr_localsid,
133  u8 is_disable)
134 {
135  vlib_main_t *vm = em->vlib_main;
136 
137  if (is_disable == 0)
138  {
140  em->criteria_oneway = criteria;
141  em->wait_for_responses = no_of_responses;
142  em->sr_localsid_ts.as_u64[0] = sr_localsid->as_u64[0];
143  em->sr_localsid_ts.as_u64[1] = sr_localsid->as_u64[1];
150 
151  /* Turn on the cleanup process */
152  // vlib_process_signal_event (vm, em->cleanup_process_node_index, 1, 0);
153  }
154  else
155  {
158  em->sr_localsid_ts.as_u64[0] = 0;
159  em->sr_localsid_ts.as_u64[1] = 0;
164  }
165 
166  return 0;
167 }
168 
169 /* API message handler */
172 {
173  vl_api_ioam_cache_ip6_enable_disable_reply_t *rmp;
175  ip6_address_t sr_localsid;
176  int rv;
177 
178  sr_localsid.as_u64[0] = 0;
179  sr_localsid.as_u64[1] = 0;
180  rv =
181  ioam_cache_ip6_enable_disable (cm, &sr_localsid, (int) (mp->is_disable));
182  REPLY_MACRO (VL_API_IOAM_CACHE_IP6_ENABLE_DISABLE_REPLY);
183 }
184 
185 /* Set up the API message handling tables */
186 static clib_error_t *
188 {
190 #define _(N,n) \
191  vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base), \
192  #n, \
193  vl_api_##n##_t_handler, \
194  vl_noop_handler, \
195  vl_api_##n##_t_endian, \
196  vl_api_##n##_t_print, \
197  sizeof(vl_api_##n##_t), 1);
199 #undef _
200 
201  return 0;
202 }
203 
204 #define vl_msg_name_crc_list
206 #undef vl_msg_name_crc_list
207 
208 static void
210 {
211 #define _(id,n,crc) \
212  vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + sm->msg_id_base);
213  foreach_vl_msg_name_crc_ioam_cache;
214 #undef _
215 }
216 
217 static clib_error_t *
219  unformat_input_t * input, vlib_cli_command_t * cmd)
220 {
222  u8 is_disable = 0;
223  ip6_address_t sr_localsid;
224  u8 address_set = 0;
225 
227  {
228  if (unformat (input, "disable"))
229  is_disable = 1;
230  else if (!address_set
231  && unformat (input, "sr_localsid %U", unformat_ip6_address,
232  &sr_localsid))
233  address_set = 1;
234  else
235  break;
236  }
237 
238  if (is_disable == 0 && !address_set)
239  return clib_error_return (0, "Error: SRv6 LocalSID address is mandatory");
240 
241  ioam_cache_ip6_enable_disable (em, &sr_localsid, is_disable);
242 
243  return 0;
244 }
245 
246 /* *INDENT_OFF* */
247 VLIB_CLI_COMMAND (set_ioam_cache_command, static) =
248 {
249 .path = "set ioam ip6 cache",.short_help =
250  "set ioam ip6 cache sr_localsid <ip6 address> [disable]",.function =
252 /* *INDENT_ON* */
253 
254 #define IOAM_TS_WAIT_FOR_RESPONSES 3
255 static clib_error_t *
257  unformat_input_t * input,
258  vlib_cli_command_t * cmd)
259 {
261  u8 is_disable = 0;
262  u8 one_way = 0;
263  ip6_address_t sr_localsid;
264  u8 address_set = 0;
265  u8 no_of_responses = IOAM_TS_WAIT_FOR_RESPONSES;
266 
268  {
269  if (unformat (input, "disable"))
270  is_disable = 1;
271  else if (unformat (input, "rtt"))
272  one_way = 0;
273  else if (unformat (input, "oneway"))
274  one_way = 1;
275  else if (unformat (input, "wait_for_responses %d", &no_of_responses))
276  ;
277  else if (!address_set
278  && unformat (input, "sr_localsid %U", unformat_ip6_address,
279  &sr_localsid))
280  address_set = 1;
281  else
282  break;
283  }
284  if (is_disable == 0 && !address_set)
285  return clib_error_return (0,
286  "Error: SRv6 LocalSID address is mandatory to receive response.");
287 
288  ioam_tunnel_select_ip6_enable_disable (em, one_way, no_of_responses,
289  &sr_localsid, is_disable);
290 
291  return 0;
292 }
293 
294 /* *INDENT_OFF* */
295 VLIB_CLI_COMMAND (set_ioam_cache_ts_command, static) =
296 {
297 .path = "set ioam ip6 sr-tunnel-select",.short_help =
298  "set ioam ip6 sr-tunnel-select [disable] [oneway|rtt] [wait_for_responses <n|default 3>] \
299  [sr_localsid <ip6 address>]",.function = set_ioam_tunnel_select_command_fn};
300 /* *INDENT_ON* */
301 
302 static void
304 {
306  ioam_cache_entry_t *entry = 0;
307  ioam_cache_ts_entry_t *ts_entry = 0;
308  int no_of_threads = vec_len (vlib_worker_threads);
309  int i;
310 
311  pool_foreach (entry, cm->ioam_rewrite_pool, (
312  {
313  vlib_cli_output (vm, "%U",
314  format_ioam_cache_entry,
315  entry);
316  }));
317 
318  if (cm->ts_stats)
319  for (i = 0; i < no_of_threads; i++)
320  {
321  vlib_cli_output (vm, "Number of entries in thread-%d selection pool: %lu\n \
322  (pool found to be full: %lu times)", i,
323  cm->ts_stats[i].inuse, cm->ts_stats[i].add_failed);
324 
325  if (verbose == 1)
327  pool_foreach (ts_entry, cm->ioam_ts_pool[i], (
328  {
329  vlib_cli_output (vm,
330  "%U",
331  format_ioam_cache_ts_entry,
332  ts_entry,
333  (u32)
334  i);
335  }
336  ));
338  }
339 
340 }
341 
342 static clib_error_t *
344  unformat_input_t * input,
345  vlib_cli_command_t * cmd)
346 {
347  u8 verbose = 0;
348 
350  {
351  if (unformat (input, "verbose"))
352  verbose = 1;
353  }
354  ioam_cache_table_print (vm, verbose);
355 
356 
357  return 0;
358 }
359 
360 /* *INDENT_OFF* */
361 VLIB_CLI_COMMAND (show_ioam_cache_command, static) =
362 {
363 .path = "show ioam ip6 cache",.short_help =
364  "show ioam ip6 cache [verbose]",.function = show_ioam_cache_command_fn};
365 /* *INDENT_ON* */
366 
367 static clib_error_t *
369 {
371  clib_error_t *error = 0;
372  u8 *name;
373  u32 cache_node_index = ioam_cache_node.index;
374  u32 ts_node_index = ioam_cache_ts_node.index;
375  vlib_node_t *ip6_hbyh_node = NULL, *ip6_hbh_pop_node = NULL, *error_node =
376  NULL;
377 
378  name = format (0, "ioam_cache_%08x%c", api_version, 0);
379 
380  memset (&ioam_cache_main, 0, sizeof (ioam_cache_main));
381  /* Ask for a correctly-sized block of API message decode slots */
383  ((char *) name, VL_MSG_FIRST_AVAILABLE);
384 
385  error = ioam_cache_plugin_api_hookup (vm);
386 
387  /* Add our API messages to the global name_crc hash table */
389 
390  /* Hook this node to ip6-hop-by-hop */
391  ip6_hbyh_node = vlib_get_node_by_name (vm, (u8 *) "ip6-hop-by-hop");
392  em->cache_hbh_slot =
393  vlib_node_add_next (vm, ip6_hbyh_node->index, cache_node_index);
394  em->ts_hbh_slot =
395  vlib_node_add_next (vm, ip6_hbyh_node->index, ts_node_index);
396 
397  ip6_hbh_pop_node = vlib_get_node_by_name (vm, (u8 *) "ip6-pop-hop-by-hop");
398  em->ip6_hbh_pop_node_index = ip6_hbh_pop_node->index;
399 
400  error_node = vlib_get_node_by_name (vm, (u8 *) "error-drop");
401  em->error_node_index = error_node->index;
402  em->vlib_main = vm;
403 
404  vec_free (name);
405 
406  return error;
407 }
408 
410 
411 /*
412  * fd.io coding-style-patch-verification: ON
413  *
414  * Local Variables:
415  * eval: (c-set-style "gnu")
416  * End:
417  */
ip6_address_t sr_localsid_ts
Definition: ioam_cache.h:194
int ioam_tunnel_select_ip6_enable_disable(ioam_cache_main_t *em, u8 criteria, u8 no_of_responses, ip6_address_t *sr_localsid, u8 is_disable)
Definition: ioam_cache.c:129
u16 vl_msg_api_get_msg_ids(const char *name, int n)
Definition: api_shared.c:857
static clib_error_t * set_ioam_cache_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ioam_cache.c:218
ioam_cache_entry_t * ioam_rewrite_pool
Definition: ioam_cache.h:168
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:337
static int ioam_cache_ts_table_init(vlib_main_t *vm)
Definition: ioam_cache.h:521
void ip6_hbh_set_next_override(uword next)
Definition: ip6_forward.c:2979
u64 as_u64[2]
Definition: ip6_packet.h:51
#define NULL
Definition: clib.h:55
u32 index
Definition: node.h:237
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:2987
#define IOAM_TS_WAIT_FOR_RESPONSES
Definition: ioam_cache.c:254
static int ioam_cache_table_init(vlib_main_t *vm)
Definition: ioam_cache.h:442
static int ioam_cache_table_destroy(vlib_main_t *vm)
Definition: ioam_cache.h:461
static clib_error_t * show_ioam_cache_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ioam_cache.c:343
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
static uword vlib_node_add_next(vlib_main_t *vm, uword node, uword next_node)
Definition: node_funcs.h:1108
static clib_error_t * set_ioam_tunnel_select_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ioam_cache.c:256
static void setup_message_id_table(ioam_cache_main_t *sm, api_main_t *am)
Definition: ioam_cache.c:209
#define vlib_worker_thread_barrier_sync(X)
Definition: threads.h:212
Definition: ioam_cache.h:99
int ioam_cache_ip6_enable_disable(ioam_cache_main_t *em, ip6_address_t *sr_localsid, u8 is_disable)
Definition: ioam_cache.c:97
ip6_address_t sr_localsid_cache
Definition: ioam_cache.h:176
static int ip6_ioam_ts_cache_set_rewrite(void)
Definition: ioam_cache.h:847
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:437
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
static void vl_api_ioam_cache_ip6_enable_disable_t_handler(vl_api_ioam_cache_ip6_enable_disable_t *mp)
Definition: ioam_cache.c:171
#define clib_error_return(e, args...)
Definition: error.h:99
#define HBH_OPTION_TYPE_IOAM_EDGE_TO_EDGE_ID
Definition: ioam_cache.h:259
static u8 * ioam_e2e_cache_trace_handler(u8 *s, ip6_hop_by_hop_option_t *opt)
Definition: ioam_cache.c:80
vlib_node_registration_t ioam_cache_ts_node
(constructor) VLIB_REGISTER_NODE (ioam_cache_ts_node)
ioam_cache_ts_pool_stats_t * ts_stats
Definition: ioam_cache.h:184
int ip6_hbh_unregister_option(u8 option)
Definition: ip6_forward.c:3011
vlib_worker_thread_t * vlib_worker_threads
Definition: threads.c:35
Definition: ioam_cache.h:123
ioam_cache_ts_entry_t ** ioam_ts_pool
Definition: ioam_cache.h:183
vlib_node_registration_t ioam_cache_node
(constructor) VLIB_REGISTER_NODE (ioam_cache_node)
static int ip6_ioam_ts_cache_cleanup_rewrite(void)
Definition: ioam_cache.h:886
struct _unformat_input_t unformat_input_t
u32 ip6_hbh_pop_node_index
Definition: ioam_cache.h:201
#define REPLY_MACRO(t)
API main structure, used by both vpp and binary API clients.
Definition: api_common.h:182
unformat_function_t unformat_ip6_address
Definition: format.h:94
static clib_error_t * ioam_cache_init(vlib_main_t *vm)
Definition: ioam_cache.c:368
api_main_t api_main
Definition: api_shared.c:35
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
format_function_t format_ip6_address
Definition: format.h:95
vlib_main_t * vm
Definition: buffer.c:283
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:336
vlib_node_t * vlib_get_node_by_name(vlib_main_t *vm, u8 *name)
Definition: node.c:45
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
unsigned int u32
Definition: types.h:88
void ioam_cache_ts_timer_node_enable(vlib_main_t *vm, u8 enable)
static u8 * ioam_e2e_id_trace_handler(u8 *s, ip6_hop_by_hop_option_t *opt)
Definition: ioam_cache.c:64
#define foreach_ioam_cache_plugin_api_msg
Definition: ioam_cache.c:60
static int ioam_cache_ts_table_destroy(vlib_main_t *vm)
Definition: ioam_cache.h:597
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
vlib_main_t * vlib_main
Definition: ioam_cache.h:197
void vlib_worker_thread_barrier_release(vlib_main_t *vm)
Definition: threads.c:1488
static void ioam_cache_table_print(vlib_main_t *vm, u8 verbose)
Definition: ioam_cache.c:303
ioam_cache_main_t ioam_cache_main
Definition: ioam_cache.h:206
#define HBH_OPTION_TYPE_IOAM_E2E_CACHE_ID
Definition: ioam_cache.h:260
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:680
static clib_error_t * ioam_cache_plugin_api_hookup(vlib_main_t *vm)
Definition: ioam_cache.c:187
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169