FD.io VPP  v18.07.1-19-g511ce25
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 {
27  u32 arc_index = 0;
28 
29  fm->arc_index_by_name = hash_create_string (0, sizeof (uword));
30  areg = fm->next_arc;
31 
32  /* process feature arc registrations */
33  while (areg)
34  {
35  char *s;
36  int i = 0;
37  areg->feature_arc_index = arc_index;
38  if (areg->arc_index_ptr)
39  *areg->arc_index_ptr = arc_index;
40  hash_set_mem (fm->arc_index_by_name, areg->arc_name,
41  pointer_to_uword (areg));
42 
43  /* process start nodes */
44  while ((s = areg->start_nodes[i]))
45  {
46  i++;
47  }
48  areg->n_start_nodes = i;
49 
50  /* next */
51  areg = areg->next;
52  arc_index++;
53  }
54 
55  vec_validate (fm->next_feature_by_arc, arc_index - 1);
56  vec_validate (fm->feature_nodes, arc_index - 1);
57  vec_validate (fm->feature_config_mains, arc_index - 1);
58  vec_validate (fm->next_feature_by_name, arc_index - 1);
59  vec_validate (fm->sw_if_index_has_features, arc_index - 1);
60  vec_validate (fm->feature_count_by_sw_if_index, arc_index - 1);
61 
62  freg = fm->next_feature;
63  while (freg)
64  {
66  uword *p = hash_get_mem (fm->arc_index_by_name, freg->arc_name);
67  if (p == 0)
68  {
69  /* Don't start vpp with broken features arcs */
70  clib_warning ("Unknown feature arc '%s'", freg->arc_name);
71  os_exit (1);
72  }
73 
75  arc_index = areg->feature_arc_index;
76 
77  next = freg->next;
78  freg->next_in_arc = fm->next_feature_by_arc[arc_index];
79  fm->next_feature_by_arc[arc_index] = freg;
80 
81  /* next */
82  freg = next;
83  }
84 
85  areg = fm->next_arc;
86  while (areg)
87  {
88  clib_error_t *error;
90  vnet_config_main_t *vcm;
91 
92  arc_index = areg->feature_arc_index;
93  cm = &fm->feature_config_mains[arc_index];
94  vcm = &cm->config_main;
95  if ((error = vnet_feature_arc_init (vm, vcm,
96  areg->start_nodes,
97  areg->n_start_nodes,
98  fm->next_feature_by_arc[arc_index],
99  &fm->feature_nodes[arc_index])))
100  {
101  clib_error_report (error);
102  os_exit (1);
103  }
104 
105  fm->next_feature_by_name[arc_index] =
106  hash_create_string (0, sizeof (uword));
107  freg = fm->next_feature_by_arc[arc_index];
108 
109  while (freg)
110  {
111  hash_set_mem (fm->next_feature_by_name[arc_index],
112  freg->node_name, pointer_to_uword (freg));
113  freg = freg->next_in_arc;
114  }
115 
116  /* next */
117  areg = areg->next;
118  arc_index++;
119  }
120 
121  return 0;
122 }
123 
125 
126 u8
128 {
131  uword *p;
132 
133  p = hash_get_mem (fm->arc_index_by_name, s);
134  if (p == 0)
135  return ~0;
136 
138  return reg->feature_arc_index;
139 }
140 
142 vnet_get_feature_reg (const char *arc_name, const char *node_name)
143 {
144  u8 arc_index;
145 
146  arc_index = vnet_get_feature_arc_index (arc_name);
147  if (arc_index == (u8) ~ 0)
148  return 0;
149 
152  uword *p;
153 
154  p = hash_get_mem (fm->next_feature_by_name[arc_index], node_name);
155  if (p == 0)
156  return 0;
157 
159  return reg;
160 }
161 
162 u32
163 vnet_get_feature_index (u8 arc, const char *s)
164 {
167  uword *p;
168 
169  if (s == 0)
170  return ~0;
171 
172  p = hash_get_mem (fm->next_feature_by_name[arc], s);
173  if (p == 0)
174  return ~0;
175 
177  return reg->feature_index;
178 }
179 
180 int
182  u32 sw_if_index, int enable_disable,
183  void *feature_config,
184  u32 n_feature_config_bytes)
185 {
188  i16 feature_count;
189  u32 ci;
190 
191  if (arc_index == (u8) ~ 0)
192  return VNET_API_ERROR_INVALID_VALUE;
193 
194  if (feature_index == ~0)
195  return VNET_API_ERROR_INVALID_VALUE_2;
196 
197  cm = &fm->feature_config_mains[arc_index];
199  ci = cm->config_index_by_sw_if_index[sw_if_index];
200 
201  vec_validate (fm->feature_count_by_sw_if_index[arc_index], sw_if_index);
202  feature_count = fm->feature_count_by_sw_if_index[arc_index][sw_if_index];
203 
204  if (!enable_disable && feature_count < 1)
205  return 0;
206 
207  ci = (enable_disable
210  (vlib_get_main (), &cm->config_main, ci, feature_index, feature_config,
211  n_feature_config_bytes);
212  if (ci == ~0)
213  {
214  return 0;
215  }
216  cm->config_index_by_sw_if_index[sw_if_index] = ci;
217 
218  /* update feature count */
219  enable_disable = (enable_disable > 0);
220  feature_count += enable_disable ? 1 : -1;
221  ASSERT (feature_count >= 0);
222 
223  fm->sw_if_index_has_features[arc_index] =
224  clib_bitmap_set (fm->sw_if_index_has_features[arc_index], sw_if_index,
225  (feature_count > 0));
226  adj_feature_update (sw_if_index, arc_index, (feature_count > 0));
227 
228  fm->feature_count_by_sw_if_index[arc_index][sw_if_index] = feature_count;
229  return 0;
230 }
231 
232 int
233 vnet_feature_enable_disable (const char *arc_name, const char *node_name,
234  u32 sw_if_index, int enable_disable,
235  void *feature_config, u32 n_feature_config_bytes)
236 {
237  u32 feature_index;
238  u8 arc_index;
239 
240  arc_index = vnet_get_feature_arc_index (arc_name);
241 
242  if (arc_index == (u8) ~ 0)
243  return VNET_API_ERROR_INVALID_VALUE;
244 
245  feature_index = vnet_get_feature_index (arc_index, node_name);
246 
247  return vnet_feature_enable_disable_with_index (arc_index, feature_index,
248  sw_if_index, enable_disable,
249  feature_config,
250  n_feature_config_bytes);
251 }
252 
253 static int
254 feature_cmp (void *a1, void *a2)
255 {
256  vnet_feature_registration_t *reg1 = a1;
257  vnet_feature_registration_t *reg2 = a2;
258 
259  return (int) reg1->feature_index - reg2->feature_index;
260 }
261 
262 /** Display the set of available driver features.
263  Useful for verifying that expected features are present
264 */
265 
266 static clib_error_t *
268  unformat_input_t * input, vlib_cli_command_t * cmd)
269 {
273  vnet_feature_registration_t *feature_regs = 0;
274  int verbose = 0;
275 
276  if (unformat (input, "verbose"))
277  verbose = 1;
278 
279  vlib_cli_output (vm, "Available feature paths");
280 
281  areg = fm->next_arc;
282  while (areg)
283  {
284  if (verbose)
285  vlib_cli_output (vm, "[%2d] %s:", areg->feature_arc_index,
286  areg->arc_name);
287  else
288  vlib_cli_output (vm, "%s:", areg->arc_name);
289 
290  freg = fm->next_feature_by_arc[areg->feature_arc_index];
291  while (freg)
292  {
293  vec_add1 (feature_regs, freg[0]);
294  freg = freg->next_in_arc;
295  }
296 
297  vec_sort_with_function (feature_regs, feature_cmp);
298 
299  vec_foreach (freg, feature_regs)
300  {
301  if (verbose)
302  vlib_cli_output (vm, " [%2d]: %s\n", freg->feature_index,
303  freg->node_name);
304  else
305  vlib_cli_output (vm, " %s\n", freg->node_name);
306  }
307  vec_reset_length (feature_regs);
308  /* next */
309  areg = areg->next;
310  }
311  vec_free (feature_regs);
312 
313  return 0;
314 }
315 
316 /*?
317  * Display the set of available driver features
318  *
319  * @cliexpar
320  * Example:
321  * @cliexcmd{show features [verbose]}
322  * @cliexend
323  * @endparblock
324 ?*/
325 /* *INDENT-OFF* */
326 VLIB_CLI_COMMAND (show_features_command, static) = {
327  .path = "show features",
328  .short_help = "show features",
329  .function = show_features_command_fn,
330 };
331 /* *INDENT-ON* */
332 
333 /** Display the set of driver features configured on a specific interface
334  * Called by "show interface" handler
335  */
336 
337 void
338 vnet_interface_features_show (vlib_main_t * vm, u32 sw_if_index, int verbose)
339 {
341  u32 node_index, current_config_index;
342  u16 feature_arc;
345  vnet_config_main_t *vcm;
346  vnet_config_t *cfg;
347  u32 cfg_index;
348  vnet_config_feature_t *feat;
349  vlib_node_t *n;
350  int i;
351 
352  vlib_cli_output (vm, "Feature paths configured on %U...",
354  vnet_get_main (), sw_if_index);
355 
356  areg = fm->next_arc;
357  while (areg)
358  {
359  feature_arc = areg->feature_arc_index;
360  vcm = &(cm[feature_arc].config_main);
361 
362  vlib_cli_output (vm, "\n%s:", areg->arc_name);
363  areg = areg->next;
364 
365  if (NULL == cm[feature_arc].config_index_by_sw_if_index ||
366  vec_len (cm[feature_arc].config_index_by_sw_if_index) <=
367  sw_if_index)
368  {
369  vlib_cli_output (vm, " none configured");
370  continue;
371  }
372 
373  current_config_index =
374  vec_elt (cm[feature_arc].config_index_by_sw_if_index, sw_if_index);
375 
376  if (current_config_index == ~0)
377  {
378  vlib_cli_output (vm, " none configured");
379  continue;
380  }
381 
382  ASSERT (current_config_index
384 
385  cfg_index = vcm->config_pool_index_by_user_index[current_config_index];
386  cfg = pool_elt_at_index (vcm->config_pool, cfg_index);
387 
388  for (i = 0; i < vec_len (cfg->features); i++)
389  {
390  feat = cfg->features + i;
391  node_index = feat->node_index;
392  n = vlib_get_node (vm, node_index);
393  if (verbose)
394  vlib_cli_output (vm, " [%2d] %v", feat->feature_index, n->name);
395  else
396  vlib_cli_output (vm, " %v", n->name);
397  }
398  }
399 }
400 
401 static clib_error_t *
403  unformat_input_t * input,
404  vlib_cli_command_t * cmd)
405 {
406  vnet_main_t *vnm = vnet_get_main ();
407  unformat_input_t _line_input, *line_input = &_line_input;
408  clib_error_t *error = 0;
409 
410  u8 *arc_name = 0;
411  u8 *feature_name = 0;
412  u32 sw_if_index = ~0;
413  u8 enable = 1;
414 
415  /* Get a line of input. */
416  if (!unformat_user (input, unformat_line_input, line_input))
417  goto done;
418 
419  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
420  {
421  if (unformat
422  (line_input, "%U %v", unformat_vnet_sw_interface, vnm, &sw_if_index,
423  &feature_name))
424  ;
425  else if (unformat (line_input, "arc %v", &arc_name))
426  ;
427  else if (unformat (line_input, "disable"))
428  enable = 0;
429  else
430  {
431  if (feature_name && arc_name)
432  break;
433  error = unformat_parse_error (line_input);
434  goto done;
435  }
436  }
437 
438  if (sw_if_index == ~0)
439  {
440  error = clib_error_return (0, "Interface not specified...");
441  goto done;
442  }
443 
444  vec_add1 (arc_name, 0);
445  vec_add1 (feature_name, 0);
446 
448  reg =
449  vnet_get_feature_reg ((const char *) arc_name,
450  (const char *) feature_name);
451  if (reg == 0)
452  {
453  error = clib_error_return (0, "Unknown feature...");
454  goto done;
455  }
456  if (reg->enable_disable_cb)
457  error = reg->enable_disable_cb (sw_if_index, enable);
458  if (!error)
459  vnet_feature_enable_disable ((const char *) arc_name,
460  (const char *) feature_name, sw_if_index,
461  enable, 0, 0);
462 
463 done:
464  vec_free (feature_name);
465  vec_free (arc_name);
466  unformat_free (line_input);
467  return error;
468 }
469 
470 /*?
471  * Set feature for given interface
472  *
473  * @cliexpar
474  * Example:
475  * @cliexcmd{set interface feature GigabitEthernet2/0/0 ip4_flow_classify arc ip4_unicast}
476  * @cliexend
477  * @endparblock
478 ?*/
479 /* *INDENT-OFF* */
480 VLIB_CLI_COMMAND (set_interface_feature_command, static) = {
481  .path = "set interface feature",
482  .short_help = "set interface feature <intfc> <feature_name> arc <arc_name> "
483  "[disable]",
485 };
486 /* *INDENT-ON* */
487 
488 /*
489  * fd.io coding-style-patch-verification: ON
490  *
491  * Local Variables:
492  * eval: (c-set-style "gnu")
493  * End:
494  */
vnet_config_main_t config_main
Definition: feature.h:65
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:437
vnet_config_feature_t * features
Definition: config.h:71
u8 vnet_get_feature_arc_index(const char *s)
Definition: feature.c:127
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
char *** feature_nodes
Save partial order results for show command.
Definition: feature.h:84
vnet_feature_registration_t * next_feature
feature path configuration lists
Definition: feature.h:76
#define NULL
Definition: clib.h:55
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:523
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 VLIB_INIT_FUNCTION(x)
Definition: init.h:156
vnet_feature_registration_t * vnet_get_feature_reg(const char *arc_name, const char *node_name)
Definition: feature.c:142
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:181
#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:163
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:464
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, char ***feature_nodes)
Initialize a feature graph arc.
Definition: registration.c:118
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:402
uword ** next_feature_by_name
Definition: feature.h:78
u8 * name
Definition: node.h:257
#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:294
static int feature_cmp(void *a1, void *a2)
Definition: feature.c:254
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:338
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:339
#define clib_warning(format, args...)
Definition: error.h:59
void os_exit(int code)
Definition: unix-misc.c:182
uword ** arc_index_by_name
Definition: feature.h:73
i16 ** feature_count_by_sw_if_index
feature reference counts by interface
Definition: feature.h:90
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
#define uword_to_pointer(u, type)
Definition: types.h:136
#define ASSERT(truth)
vnet_feature_registration_t ** next_feature_by_arc
Definition: feature.h:77
#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:982
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:72
uword ** sw_if_index_has_features
bitmap of interfaces which have driver rx features configured
Definition: feature.h:87
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:327
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:267
vnet_feature_config_main_t * feature_config_mains
feature config main objects
Definition: feature.h:81
#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:681
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:233
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