FD.io VPP  v19.08.3-2-gbabecb413
Vector Packet Processing
feature.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 
16 #include <vnet/feature/feature.h>
17 #include <vnet/adj/adj.h>
18 
20 
21 static clib_error_t *
23 {
28  u32 arc_index = 0;
29 
30  fm->arc_index_by_name = hash_create_string (0, sizeof (uword));
31  areg = fm->next_arc;
32 
33  /* process feature arc registrations */
34  while (areg)
35  {
36  char *s;
37  int i = 0;
38  areg->feature_arc_index = arc_index;
39  if (areg->arc_index_ptr)
40  *areg->arc_index_ptr = arc_index;
41  hash_set_mem (fm->arc_index_by_name, areg->arc_name,
42  pointer_to_uword (areg));
43 
44  /* process start nodes */
45  while ((s = areg->start_nodes[i]))
46  {
47  i++;
48  }
49  areg->n_start_nodes = i;
50 
51  /* next */
52  areg = areg->next;
53  arc_index++;
54  }
55 
56  vec_validate (fm->next_feature_by_arc, arc_index - 1);
57  vec_validate (fm->feature_nodes, arc_index - 1);
58  vec_validate (fm->feature_config_mains, arc_index - 1);
59  vec_validate (fm->next_feature_by_name, arc_index - 1);
60  vec_validate (fm->sw_if_index_has_features, arc_index - 1);
61  vec_validate (fm->feature_count_by_sw_if_index, arc_index - 1);
62  vec_validate (fm->next_constraint_by_arc, arc_index - 1);
63 
64  freg = fm->next_feature;
65  while (freg)
66  {
68  uword *p = hash_get_mem (fm->arc_index_by_name, freg->arc_name);
69  if (p == 0)
70  {
71  /* Don't start vpp with broken features arcs */
72  clib_warning ("Unknown feature arc '%s'", freg->arc_name);
73  os_exit (1);
74  }
75 
77  arc_index = areg->feature_arc_index;
78 
79  next = freg->next;
80  freg->next_in_arc = fm->next_feature_by_arc[arc_index];
81  fm->next_feature_by_arc[arc_index] = freg;
82 
83  /* next */
84  freg = next;
85  }
86 
87  /* Move bulk constraints to the constraint by arc lists */
88  creg = fm->next_constraint;
89  while (creg)
90  {
92  uword *p = hash_get_mem (fm->arc_index_by_name, creg->arc_name);
93  if (p == 0)
94  {
95  /* Don't start vpp with broken features arcs */
96  clib_warning ("Unknown feature arc '%s'", creg->arc_name);
97  os_exit (1);
98  }
99 
101  arc_index = areg->feature_arc_index;
102 
103  next = creg->next;
104  creg->next_in_arc = fm->next_constraint_by_arc[arc_index];
105  fm->next_constraint_by_arc[arc_index] = creg;
106 
107  /* next */
108  creg = next;
109  }
110 
111 
112  areg = fm->next_arc;
113  while (areg)
114  {
115  clib_error_t *error;
117  vnet_config_main_t *vcm;
118  char **features_in_order, *last_feature;
119 
120  arc_index = areg->feature_arc_index;
121  cm = &fm->feature_config_mains[arc_index];
122  vcm = &cm->config_main;
123  if ((error = vnet_feature_arc_init
124  (vm, vcm, areg->start_nodes, areg->n_start_nodes,
125  areg->last_in_arc,
126  fm->next_feature_by_arc[arc_index],
127  fm->next_constraint_by_arc[arc_index],
128  &fm->feature_nodes[arc_index])))
129  {
130  clib_error_report (error);
131  os_exit (1);
132  }
133 
134  features_in_order = fm->feature_nodes[arc_index];
135 
136  /* If specified, verify that the last node in the arc is actually last */
137  if (areg->last_in_arc && vec_len (features_in_order) > 0)
138  {
139  last_feature = features_in_order[vec_len (features_in_order) - 1];
140  if (strncmp (areg->last_in_arc, last_feature,
141  strlen (areg->last_in_arc)))
143  ("WARNING: %s arc: last node is %s, but expected %s!",
144  areg->arc_name, last_feature, areg->last_in_arc);
145  }
146 
147  fm->next_feature_by_name[arc_index] =
148  hash_create_string (0, sizeof (uword));
149  freg = fm->next_feature_by_arc[arc_index];
150 
151  while (freg)
152  {
153  hash_set_mem (fm->next_feature_by_name[arc_index],
154  freg->node_name, pointer_to_uword (freg));
155  freg = freg->next_in_arc;
156  }
157 
158  /* next */
159  areg = areg->next;
160  arc_index++;
161  }
162 
163  return 0;
164 }
165 
167 
168 u8
170 {
173  uword *p;
174 
175  p = hash_get_mem (fm->arc_index_by_name, s);
176  if (p == 0)
177  return ~0;
178 
180  return reg->feature_arc_index;
181 }
182 
184 vnet_get_feature_reg (const char *arc_name, const char *node_name)
185 {
186  u8 arc_index;
187 
188  arc_index = vnet_get_feature_arc_index (arc_name);
189  if (arc_index == (u8) ~ 0)
190  return 0;
191 
194  uword *p;
195 
196  p = hash_get_mem (fm->next_feature_by_name[arc_index], node_name);
197  if (p == 0)
198  return 0;
199 
201  return reg;
202 }
203 
204 u32
205 vnet_get_feature_index (u8 arc, const char *s)
206 {
209  uword *p;
210 
211  if (s == 0)
212  return ~0;
213 
214  p = hash_get_mem (fm->next_feature_by_name[arc], s);
215  if (p == 0)
216  return ~0;
217 
219  return reg->feature_index;
220 }
221 
222 int
224  u32 sw_if_index, int enable_disable,
225  void *feature_config,
226  u32 n_feature_config_bytes)
227 {
230  i16 feature_count;
231  u32 ci;
232 
233  if (arc_index == (u8) ~ 0)
234  return VNET_API_ERROR_INVALID_VALUE;
235 
236  if (feature_index == ~0)
237  return VNET_API_ERROR_INVALID_VALUE_2;
238 
239  cm = &fm->feature_config_mains[arc_index];
242 
243  vec_validate (fm->feature_count_by_sw_if_index[arc_index], sw_if_index);
244  feature_count = fm->feature_count_by_sw_if_index[arc_index][sw_if_index];
245 
246  if (!enable_disable && feature_count < 1)
247  return 0;
248 
249  ci = (enable_disable
252  (vlib_get_main (), &cm->config_main, ci, feature_index, feature_config,
253  n_feature_config_bytes);
254  if (ci == ~0)
255  {
256  return 0;
257  }
259 
260  /* update feature count */
261  enable_disable = (enable_disable > 0);
262  feature_count += enable_disable ? 1 : -1;
263  ASSERT (feature_count >= 0);
264 
265  fm->sw_if_index_has_features[arc_index] =
266  clib_bitmap_set (fm->sw_if_index_has_features[arc_index], sw_if_index,
267  (feature_count > 0));
268  adj_feature_update (sw_if_index, arc_index, (feature_count > 0));
269 
270  fm->feature_count_by_sw_if_index[arc_index][sw_if_index] = feature_count;
271  return 0;
272 }
273 
274 int
275 vnet_feature_enable_disable (const char *arc_name, const char *node_name,
276  u32 sw_if_index, int enable_disable,
277  void *feature_config, u32 n_feature_config_bytes)
278 {
279  u32 feature_index;
280  u8 arc_index;
281 
282  arc_index = vnet_get_feature_arc_index (arc_name);
283 
284  if (arc_index == (u8) ~ 0)
285  return VNET_API_ERROR_INVALID_VALUE;
286 
287  feature_index = vnet_get_feature_index (arc_index, node_name);
288 
289  return vnet_feature_enable_disable_with_index (arc_index, feature_index,
290  sw_if_index, enable_disable,
291  feature_config,
292  n_feature_config_bytes);
293 }
294 
295 static int
296 feature_cmp (void *a1, void *a2)
297 {
298  vnet_feature_registration_t *reg1 = a1;
299  vnet_feature_registration_t *reg2 = a2;
300 
301  return (int) reg1->feature_index - reg2->feature_index;
302 }
303 
304 /** Display the set of available driver features.
305  Useful for verifying that expected features are present
306 */
307 
308 static clib_error_t *
310  unformat_input_t * input, vlib_cli_command_t * cmd)
311 {
315  vnet_feature_registration_t *feature_regs = 0;
316  int verbose = 0;
317 
318  if (unformat (input, "verbose"))
319  verbose = 1;
320 
321  vlib_cli_output (vm, "Available feature paths");
322 
323  areg = fm->next_arc;
324  while (areg)
325  {
326  if (verbose)
327  vlib_cli_output (vm, "[%2d] %s:", areg->feature_arc_index,
328  areg->arc_name);
329  else
330  vlib_cli_output (vm, "%s:", areg->arc_name);
331 
332  freg = fm->next_feature_by_arc[areg->feature_arc_index];
333  while (freg)
334  {
335  vec_add1 (feature_regs, freg[0]);
336  freg = freg->next_in_arc;
337  }
338 
339  vec_sort_with_function (feature_regs, feature_cmp);
340 
341  vec_foreach (freg, feature_regs)
342  {
343  if (verbose)
344  vlib_cli_output (vm, " [%2d]: %s\n", freg->feature_index,
345  freg->node_name);
346  else
347  vlib_cli_output (vm, " %s\n", freg->node_name);
348  }
349  vec_reset_length (feature_regs);
350  /* next */
351  areg = areg->next;
352  }
353  vec_free (feature_regs);
354 
355  return 0;
356 }
357 
358 /*?
359  * Display the set of available driver features
360  *
361  * @cliexpar
362  * Example:
363  * @cliexcmd{show features [verbose]}
364  * @cliexend
365  * @endparblock
366 ?*/
367 /* *INDENT-OFF* */
368 VLIB_CLI_COMMAND (show_features_command, static) = {
369  .path = "show features",
370  .short_help = "show features [verbose]",
371  .function = show_features_command_fn,
372 };
373 /* *INDENT-ON* */
374 
375 /** Display the set of driver features configured on a specific interface
376  * Called by "show interface" handler
377  */
378 
379 void
381 {
383  u32 node_index, current_config_index;
384  u16 feature_arc;
387  vnet_config_main_t *vcm;
388  vnet_config_t *cfg;
389  u32 cfg_index;
390  vnet_config_feature_t *feat;
391  vlib_node_t *n;
392  int i;
393 
394  vlib_cli_output (vm, "Feature paths configured on %U...",
396  vnet_get_main (), sw_if_index);
397 
398  areg = fm->next_arc;
399  while (areg)
400  {
401  feature_arc = areg->feature_arc_index;
402  vcm = &(cm[feature_arc].config_main);
403 
404  vlib_cli_output (vm, "\n%s:", areg->arc_name);
405  areg = areg->next;
406 
407  if (NULL == cm[feature_arc].config_index_by_sw_if_index ||
408  vec_len (cm[feature_arc].config_index_by_sw_if_index) <=
409  sw_if_index)
410  {
411  vlib_cli_output (vm, " none configured");
412  continue;
413  }
414 
415  current_config_index =
416  vec_elt (cm[feature_arc].config_index_by_sw_if_index, sw_if_index);
417 
418  if (current_config_index == ~0)
419  {
420  vlib_cli_output (vm, " none configured");
421  continue;
422  }
423 
424  ASSERT (current_config_index
426 
427  cfg_index = vcm->config_pool_index_by_user_index[current_config_index];
428  cfg = pool_elt_at_index (vcm->config_pool, cfg_index);
429 
430  for (i = 0; i < vec_len (cfg->features); i++)
431  {
432  feat = cfg->features + i;
433  node_index = feat->node_index;
434  n = vlib_get_node (vm, node_index);
435  if (verbose)
436  vlib_cli_output (vm, " [%2d] %v", feat->feature_index, n->name);
437  else
438  vlib_cli_output (vm, " %v", n->name);
439  }
440  }
441 }
442 
443 static clib_error_t *
445  unformat_input_t * input,
446  vlib_cli_command_t * cmd)
447 {
448  vnet_main_t *vnm = vnet_get_main ();
449  unformat_input_t _line_input, *line_input = &_line_input;
450  clib_error_t *error = 0;
451 
452  u8 *arc_name = 0;
453  u8 *feature_name = 0;
454  u32 sw_if_index = ~0;
455  u8 enable = 1;
456 
457  /* Get a line of input. */
458  if (!unformat_user (input, unformat_line_input, line_input))
459  return 0;
460 
461  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
462  {
463  if (unformat
464  (line_input, "%U %s arc %s", unformat_vnet_sw_interface, vnm,
465  &sw_if_index, &feature_name, &arc_name))
466  ;
467  else if (unformat (line_input, "disable"))
468  enable = 0;
469  else
470  {
471  error = unformat_parse_error (line_input);
472  goto done;
473  }
474  }
475  if (!feature_name || !arc_name)
476  {
477  error = clib_error_return (0, "Both feature name and arc required...");
478  goto done;
479  }
480 
481  if (sw_if_index == ~0)
482  {
483  error = clib_error_return (0, "Interface not specified...");
484  goto done;
485  }
486 
487  vec_add1 (arc_name, 0);
488  vec_add1 (feature_name, 0);
489 
490  u8 arc_index;
491 
492  arc_index = vnet_get_feature_arc_index ((const char *) arc_name);
493 
494  if (arc_index == (u8) ~ 0)
495  {
496  error =
497  clib_error_return (0, "Unknown arc name (%s)... ",
498  (const char *) arc_name);
499  goto done;
500  }
501 
503  reg =
504  vnet_get_feature_reg ((const char *) arc_name,
505  (const char *) feature_name);
506  if (reg == 0)
507  {
508  error =
510  "Feature (%s) not registered to arc (%s)... See 'show features verbose' for valid feature/arc combinations. ",
511  feature_name, arc_name);
512  goto done;
513  }
514  if (reg->enable_disable_cb)
515  error = reg->enable_disable_cb (sw_if_index, enable);
516  if (!error)
517  vnet_feature_enable_disable ((const char *) arc_name,
518  (const char *) feature_name, sw_if_index,
519  enable, 0, 0);
520 
521 done:
522  vec_free (feature_name);
523  vec_free (arc_name);
524  unformat_free (line_input);
525  return error;
526 }
527 
528 /*?
529  * Set feature for given interface
530  *
531  * @cliexpar
532  * Example:
533  * @cliexcmd{set interface feature GigabitEthernet2/0/0 ip4_flow_classify arc ip4_unicast}
534  * @cliexend
535  * @endparblock
536 ?*/
537 /* *INDENT-OFF* */
538 VLIB_CLI_COMMAND (set_interface_feature_command, static) = {
539  .path = "set interface feature",
540  .short_help = "set interface feature <intfc> <feature_name> arc <arc_name> "
541  "[disable]",
543 };
544 /* *INDENT-ON* */
545 
546 /*
547  * fd.io coding-style-patch-verification: ON
548  *
549  * Local Variables:
550  * eval: (c-set-style "gnu")
551  * End:
552  */
vnet_config_main_t config_main
Definition: feature.h:82
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:439
vnet_config_feature_t * features
Definition: config.h:71
struct _vnet_feature_constraint_registration vnet_feature_constraint_registration_t
constraint registration object
u8 vnet_get_feature_arc_index(const char *s)
Definition: feature.c:169
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
char *** feature_nodes
Save partial order results for show command.
Definition: feature.h:103
vnet_feature_registration_t * next_feature
feature path configuration lists
Definition: feature.h:93
u32 vnet_config_del_feature(vlib_main_t *vm, vnet_config_main_t *cm, u32 config_string_heap_index, u32 feature_index, void *feature_config, u32 n_feature_config_bytes)
Definition: config.c:304
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:522
int i
static uword * clib_bitmap_set(uword *ai, uword i, uword value)
Sets the ith bit of a bitmap to new_value Removes trailing zeros from the bitmap. ...
Definition: bitmap.h:167
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:989
#define hash_set_mem(h, key, value)
Definition: hash.h:275
unformat_function_t unformat_vnet_sw_interface
format_function_t format_vnet_sw_if_index_name
unsigned char u8
Definition: types.h:56
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
#define fm
clib_error_t * vnet_feature_arc_init(vlib_main_t *vm, vnet_config_main_t *vcm, char **feature_start_nodes, int num_feature_start_nodes, char *last_in_arc, vnet_feature_registration_t *first_reg, vnet_feature_constraint_registration_t *first_const_set, char ***in_feature_nodes)
Initialize a feature graph arc.
Definition: registration.c:121
vnet_feature_constraint_registration_t * next_constraint
Definition: feature.h:95
vl_api_interface_index_t sw_if_index
Definition: gre.api:50
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
vnet_feature_registration_t * vnet_get_feature_reg(const char *arc_name, const char *node_name)
Definition: feature.c:184
int vnet_feature_enable_disable_with_index(u8 arc_index, u32 feature_index, u32 sw_if_index, int enable_disable, void *feature_config, u32 n_feature_config_bytes)
Definition: feature.c:223
#define clib_error_return(e, args...)
Definition: error.h:99
unsigned int u32
Definition: types.h:88
u32 vnet_get_feature_index(u8 arc, const char *s)
Definition: feature.c:205
static clib_error_t * vnet_feature_init(vlib_main_t *vm)
Definition: feature.c:22
#define hash_create_string(elts, value_bytes)
Definition: hash.h:690
unformat_function_t unformat_line_input
Definition: format.h:283
vnet_crypto_main_t * cm
Definition: quic_crypto.c:41
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:514
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
static clib_error_t * set_interface_features_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: feature.c:444
uword ** next_feature_by_name
Definition: feature.h:97
u8 * name
Definition: node.h:264
#define UNFORMAT_END_OF_INPUT
Definition: format.h:145
u32 * config_pool_index_by_user_index
Definition: config.h:104
vlib_main_t * vm
Definition: buffer.c:323
static int feature_cmp(void *a1, void *a2)
Definition: feature.c:296
void vnet_interface_features_show(vlib_main_t *vm, u32 sw_if_index, int verbose)
Display the set of driver features configured on a specific interface Called by "show interface" hand...
Definition: feature.c:380
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:341
#define clib_warning(format, args...)
Definition: error.h:59
void os_exit(int code)
Definition: unix-misc.c:182
vnet_feature_constraint_registration_t ** next_constraint_by_arc
Definition: feature.h:96
uword ** arc_index_by_name
Definition: feature.h:90
i16 ** feature_count_by_sw_if_index
feature reference counts by interface
Definition: feature.h:109
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:161
#define uword_to_pointer(u, type)
Definition: types.h:136
#define ASSERT(truth)
vnet_feature_registration_t ** next_feature_by_arc
Definition: feature.h:94
#define clib_error_report(e)
Definition: error.h:113
u32 vnet_config_add_feature(vlib_main_t *vm, vnet_config_main_t *cm, u32 config_string_heap_index, u32 feature_index, void *feature_config, u32 n_feature_config_bytes)
Definition: config.c:238
static uword pointer_to_uword(const void *p)
Definition: types.h:131
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
#define vec_elt(v, i)
Get vector value at index i.
#define unformat_parse_error(input)
Definition: format.h:269
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
u64 uword
Definition: types.h:112
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
Definition: vec.h:983
static void unformat_free(unformat_input_t *i)
Definition: format.h:163
struct _vnet_feature_arc_registration vnet_feature_arc_registration_t
feature registration object
#define hash_get_mem(h, key)
Definition: hash.h:269
vnet_feature_arc_registration_t * next_arc
feature arc configuration list
Definition: feature.h:89
uword ** sw_if_index_has_features
bitmap of interfaces which have driver rx features configured
Definition: feature.h:106
void adj_feature_update(u32 sw_if_index, u8 arc_index, u8 is_enable)
Notify the adjacency subsystem that the features settings for an interface have changed.
Definition: adj.c:434
vnet_config_t * config_pool
Definition: config.h:89
static vlib_node_t * vlib_get_node(vlib_main_t *vm, u32 i)
Get vlib node by index.
Definition: node_funcs.h:59
#define vec_foreach(var, vec)
Vector iterator.
static clib_error_t * show_features_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Display the set of available driver features.
Definition: feature.c:309
vnet_feature_config_main_t * feature_config_mains
feature config main objects
Definition: feature.h:100
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
Definition: vec.h:486
vnet_feature_main_t feature_main
Definition: feature.c:19
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:772
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
int vnet_feature_enable_disable(const char *arc_name, const char *node_name, u32 sw_if_index, int enable_disable, void *feature_config, u32 n_feature_config_bytes)
Definition: feature.c:275
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:171
struct _vnet_feature_registration vnet_feature_registration_t
feature registration object
signed short i16
Definition: types.h:46