FD.io VPP  v19.04-6-g6f05f72
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  fm->next_feature_by_arc[arc_index],
126  fm->next_constraint_by_arc[arc_index],
127  &fm->feature_nodes[arc_index])))
128  {
129  clib_error_report (error);
130  os_exit (1);
131  }
132 
133  features_in_order = fm->feature_nodes[arc_index];
134 
135  /* If specified, verify that the last node in the arc is actually last */
136  if (areg->last_in_arc && vec_len (features_in_order) > 0)
137  {
138  last_feature = features_in_order[vec_len (features_in_order) - 1];
139  if (strncmp (areg->last_in_arc, last_feature,
140  strlen (areg->last_in_arc)))
142  ("WARNING: %s arc: last node is %s, but expected %s!",
143  areg->arc_name, last_feature, areg->last_in_arc);
144  }
145 
146  fm->next_feature_by_name[arc_index] =
147  hash_create_string (0, sizeof (uword));
148  freg = fm->next_feature_by_arc[arc_index];
149 
150  while (freg)
151  {
152  hash_set_mem (fm->next_feature_by_name[arc_index],
153  freg->node_name, pointer_to_uword (freg));
154  freg = freg->next_in_arc;
155  }
156 
157  /* next */
158  areg = areg->next;
159  arc_index++;
160  }
161 
162  return 0;
163 }
164 
166 
167 u8
169 {
172  uword *p;
173 
174  p = hash_get_mem (fm->arc_index_by_name, s);
175  if (p == 0)
176  return ~0;
177 
179  return reg->feature_arc_index;
180 }
181 
183 vnet_get_feature_reg (const char *arc_name, const char *node_name)
184 {
185  u8 arc_index;
186 
187  arc_index = vnet_get_feature_arc_index (arc_name);
188  if (arc_index == (u8) ~ 0)
189  return 0;
190 
193  uword *p;
194 
195  p = hash_get_mem (fm->next_feature_by_name[arc_index], node_name);
196  if (p == 0)
197  return 0;
198 
200  return reg;
201 }
202 
203 u32
204 vnet_get_feature_index (u8 arc, const char *s)
205 {
208  uword *p;
209 
210  if (s == 0)
211  return ~0;
212 
213  p = hash_get_mem (fm->next_feature_by_name[arc], s);
214  if (p == 0)
215  return ~0;
216 
218  return reg->feature_index;
219 }
220 
221 int
223  u32 sw_if_index, int enable_disable,
224  void *feature_config,
225  u32 n_feature_config_bytes)
226 {
229  i16 feature_count;
230  u32 ci;
231 
232  if (arc_index == (u8) ~ 0)
233  return VNET_API_ERROR_INVALID_VALUE;
234 
235  if (feature_index == ~0)
236  return VNET_API_ERROR_INVALID_VALUE_2;
237 
238  cm = &fm->feature_config_mains[arc_index];
241 
242  vec_validate (fm->feature_count_by_sw_if_index[arc_index], sw_if_index);
243  feature_count = fm->feature_count_by_sw_if_index[arc_index][sw_if_index];
244 
245  if (!enable_disable && feature_count < 1)
246  return 0;
247 
248  ci = (enable_disable
251  (vlib_get_main (), &cm->config_main, ci, feature_index, feature_config,
252  n_feature_config_bytes);
253  if (ci == ~0)
254  {
255  return 0;
256  }
258 
259  /* update feature count */
260  enable_disable = (enable_disable > 0);
261  feature_count += enable_disable ? 1 : -1;
262  ASSERT (feature_count >= 0);
263 
264  fm->sw_if_index_has_features[arc_index] =
265  clib_bitmap_set (fm->sw_if_index_has_features[arc_index], sw_if_index,
266  (feature_count > 0));
267  adj_feature_update (sw_if_index, arc_index, (feature_count > 0));
268 
269  fm->feature_count_by_sw_if_index[arc_index][sw_if_index] = feature_count;
270  return 0;
271 }
272 
273 int
274 vnet_feature_enable_disable (const char *arc_name, const char *node_name,
275  u32 sw_if_index, int enable_disable,
276  void *feature_config, u32 n_feature_config_bytes)
277 {
278  u32 feature_index;
279  u8 arc_index;
280 
281  arc_index = vnet_get_feature_arc_index (arc_name);
282 
283  if (arc_index == (u8) ~ 0)
284  return VNET_API_ERROR_INVALID_VALUE;
285 
286  feature_index = vnet_get_feature_index (arc_index, node_name);
287 
288  return vnet_feature_enable_disable_with_index (arc_index, feature_index,
289  sw_if_index, enable_disable,
290  feature_config,
291  n_feature_config_bytes);
292 }
293 
294 static int
295 feature_cmp (void *a1, void *a2)
296 {
297  vnet_feature_registration_t *reg1 = a1;
298  vnet_feature_registration_t *reg2 = a2;
299 
300  return (int) reg1->feature_index - reg2->feature_index;
301 }
302 
303 /** Display the set of available driver features.
304  Useful for verifying that expected features are present
305 */
306 
307 static clib_error_t *
309  unformat_input_t * input, vlib_cli_command_t * cmd)
310 {
314  vnet_feature_registration_t *feature_regs = 0;
315  int verbose = 0;
316 
317  if (unformat (input, "verbose"))
318  verbose = 1;
319 
320  vlib_cli_output (vm, "Available feature paths");
321 
322  areg = fm->next_arc;
323  while (areg)
324  {
325  if (verbose)
326  vlib_cli_output (vm, "[%2d] %s:", areg->feature_arc_index,
327  areg->arc_name);
328  else
329  vlib_cli_output (vm, "%s:", areg->arc_name);
330 
331  freg = fm->next_feature_by_arc[areg->feature_arc_index];
332  while (freg)
333  {
334  vec_add1 (feature_regs, freg[0]);
335  freg = freg->next_in_arc;
336  }
337 
338  vec_sort_with_function (feature_regs, feature_cmp);
339 
340  vec_foreach (freg, feature_regs)
341  {
342  if (verbose)
343  vlib_cli_output (vm, " [%2d]: %s\n", freg->feature_index,
344  freg->node_name);
345  else
346  vlib_cli_output (vm, " %s\n", freg->node_name);
347  }
348  vec_reset_length (feature_regs);
349  /* next */
350  areg = areg->next;
351  }
352  vec_free (feature_regs);
353 
354  return 0;
355 }
356 
357 /*?
358  * Display the set of available driver features
359  *
360  * @cliexpar
361  * Example:
362  * @cliexcmd{show features [verbose]}
363  * @cliexend
364  * @endparblock
365 ?*/
366 /* *INDENT-OFF* */
367 VLIB_CLI_COMMAND (show_features_command, static) = {
368  .path = "show features",
369  .short_help = "show features",
370  .function = show_features_command_fn,
371 };
372 /* *INDENT-ON* */
373 
374 /** Display the set of driver features configured on a specific interface
375  * Called by "show interface" handler
376  */
377 
378 void
380 {
382  u32 node_index, current_config_index;
383  u16 feature_arc;
386  vnet_config_main_t *vcm;
387  vnet_config_t *cfg;
388  u32 cfg_index;
389  vnet_config_feature_t *feat;
390  vlib_node_t *n;
391  int i;
392 
393  vlib_cli_output (vm, "Feature paths configured on %U...",
395  vnet_get_main (), sw_if_index);
396 
397  areg = fm->next_arc;
398  while (areg)
399  {
400  feature_arc = areg->feature_arc_index;
401  vcm = &(cm[feature_arc].config_main);
402 
403  vlib_cli_output (vm, "\n%s:", areg->arc_name);
404  areg = areg->next;
405 
406  if (NULL == cm[feature_arc].config_index_by_sw_if_index ||
407  vec_len (cm[feature_arc].config_index_by_sw_if_index) <=
408  sw_if_index)
409  {
410  vlib_cli_output (vm, " none configured");
411  continue;
412  }
413 
414  current_config_index =
415  vec_elt (cm[feature_arc].config_index_by_sw_if_index, sw_if_index);
416 
417  if (current_config_index == ~0)
418  {
419  vlib_cli_output (vm, " none configured");
420  continue;
421  }
422 
423  ASSERT (current_config_index
425 
426  cfg_index = vcm->config_pool_index_by_user_index[current_config_index];
427  cfg = pool_elt_at_index (vcm->config_pool, cfg_index);
428 
429  for (i = 0; i < vec_len (cfg->features); i++)
430  {
431  feat = cfg->features + i;
432  node_index = feat->node_index;
433  n = vlib_get_node (vm, node_index);
434  if (verbose)
435  vlib_cli_output (vm, " [%2d] %v", feat->feature_index, n->name);
436  else
437  vlib_cli_output (vm, " %v", n->name);
438  }
439  }
440 }
441 
442 static clib_error_t *
444  unformat_input_t * input,
445  vlib_cli_command_t * cmd)
446 {
447  vnet_main_t *vnm = vnet_get_main ();
448  unformat_input_t _line_input, *line_input = &_line_input;
449  clib_error_t *error = 0;
450 
451  u8 *arc_name = 0;
452  u8 *feature_name = 0;
453  u32 sw_if_index = ~0;
454  u8 enable = 1;
455 
456  /* Get a line of input. */
457  if (!unformat_user (input, unformat_line_input, line_input))
458  return 0;
459 
460  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
461  {
462  if (unformat
463  (line_input, "%U %v", unformat_vnet_sw_interface, vnm, &sw_if_index,
464  &feature_name))
465  ;
466  else if (unformat (line_input, "arc %v", &arc_name))
467  ;
468  else if (unformat (line_input, "disable"))
469  enable = 0;
470  else
471  {
472  if (feature_name && arc_name)
473  break;
474  error = unformat_parse_error (line_input);
475  goto done;
476  }
477  }
478 
479  if (sw_if_index == ~0)
480  {
481  error = clib_error_return (0, "Interface not specified...");
482  goto done;
483  }
484 
485  vec_add1 (arc_name, 0);
486  vec_add1 (feature_name, 0);
487 
489  reg =
490  vnet_get_feature_reg ((const char *) arc_name,
491  (const char *) feature_name);
492  if (reg == 0)
493  {
494  error = clib_error_return (0, "Unknown feature...");
495  goto done;
496  }
497  if (reg->enable_disable_cb)
498  error = reg->enable_disable_cb (sw_if_index, enable);
499  if (!error)
500  vnet_feature_enable_disable ((const char *) arc_name,
501  (const char *) feature_name, sw_if_index,
502  enable, 0, 0);
503 
504 done:
505  vec_free (feature_name);
506  vec_free (arc_name);
507  unformat_free (line_input);
508  return error;
509 }
510 
511 /*?
512  * Set feature for given interface
513  *
514  * @cliexpar
515  * Example:
516  * @cliexcmd{set interface feature GigabitEthernet2/0/0 ip4_flow_classify arc ip4_unicast}
517  * @cliexend
518  * @endparblock
519 ?*/
520 /* *INDENT-OFF* */
521 VLIB_CLI_COMMAND (set_interface_feature_command, static) = {
522  .path = "set interface feature",
523  .short_help = "set interface feature <intfc> <feature_name> arc <arc_name> "
524  "[disable]",
526 };
527 /* *INDENT-ON* */
528 
529 /*
530  * fd.io coding-style-patch-verification: ON
531  *
532  * Local Variables:
533  * eval: (c-set-style "gnu")
534  * End:
535  */
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
u32 sw_if_index
Definition: ipsec_gre.api:37
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:168
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
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
#define NULL
Definition: clib.h:58
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:299
#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:983
#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
vnet_feature_constraint_registration_t * next_constraint
Definition: feature.h:95
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:163
vnet_feature_registration_t * vnet_get_feature_reg(const char *arc_name, const char *node_name)
Definition: feature.c:183
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:222
#define clib_error_return(e, args...)
Definition: error.h:99
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, 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
unsigned int u32
Definition: types.h:88
u32 vnet_get_feature_index(u8 arc, const char *s)
Definition: feature.c:204
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:282
#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:443
uword ** next_feature_by_name
Definition: feature.h:97
u8 * name
Definition: node.h:263
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
u32 * config_pool_index_by_user_index
Definition: config.h:104
vlib_main_t * vm
Definition: buffer.c:312
static int feature_cmp(void *a1, void *a2)
Definition: feature.c:295
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:379
#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:155
#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:268
#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:980
static void unformat_free(unformat_input_t *i)
Definition: format.h:162
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:405
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:308
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:725
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
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:274
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:170
struct _vnet_feature_registration vnet_feature_registration_t
feature registration object
signed short i16
Definition: types.h:46