FD.io VPP  v17.01.1-3-gc6833f8
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 
19 
20 static clib_error_t *
22 {
26  u32 arc_index = 0;
27 
28  fm->arc_index_by_name = hash_create_string (0, sizeof (uword));
29  areg = fm->next_arc;
30 
31  /* process feature arc registrations */
32  while (areg)
33  {
34  char *s;
35  int i = 0;
36  areg->feature_arc_index = arc_index;
37  if (areg->arc_index_ptr)
38  *areg->arc_index_ptr = arc_index;
39  hash_set_mem (fm->arc_index_by_name, areg->arc_name,
40  pointer_to_uword (areg));
41 
42  /* process start nodes */
43  while ((s = areg->start_nodes[i]))
44  {
45  i++;
46  }
47  areg->n_start_nodes = i;
48 
49  /* next */
50  areg = areg->next;
51  arc_index++;
52  }
53 
54  vec_validate (fm->next_feature_by_arc, arc_index - 1);
55  vec_validate (fm->feature_nodes, arc_index - 1);
56  vec_validate (fm->feature_config_mains, arc_index - 1);
57  vec_validate (fm->next_feature_by_name, arc_index - 1);
58  vec_validate (fm->sw_if_index_has_features, arc_index - 1);
59  vec_validate (fm->feature_count_by_sw_if_index, arc_index - 1);
60 
61  freg = fm->next_feature;
62  while (freg)
63  {
65  uword *p = hash_get_mem (fm->arc_index_by_name, freg->arc_name);
66  if (p == 0)
67  return clib_error_return (0, "Unknown feature arc '%s'",
68  freg->arc_name);
69 
71  arc_index = areg->feature_arc_index;
72 
73  next = freg->next;
74  freg->next = fm->next_feature_by_arc[arc_index];
75  fm->next_feature_by_arc[arc_index] = freg;
76 
77  /* next */
78  freg = next;
79  }
80 
81  areg = fm->next_arc;
82  while (areg)
83  {
84  clib_error_t *error;
86  vnet_config_main_t *vcm;
87 
88  arc_index = areg->feature_arc_index;
89  cm = &fm->feature_config_mains[arc_index];
90  vcm = &cm->config_main;
91  if ((error = vnet_feature_arc_init (vm, vcm,
92  areg->start_nodes,
93  areg->n_start_nodes,
94  fm->next_feature_by_arc[arc_index],
95  &fm->feature_nodes[arc_index])))
96  {
97  return error;
98  }
99 
100  fm->next_feature_by_name[arc_index] =
101  hash_create_string (0, sizeof (uword));
102  freg = fm->next_feature_by_arc[arc_index];
103 
104  while (freg)
105  {
106  hash_set_mem (fm->next_feature_by_name[arc_index],
107  freg->node_name, pointer_to_uword (freg));
108  freg = freg->next;
109  }
110 
111  cm->end_feature_index =
112  vnet_get_feature_index (arc_index, areg->end_node);
113 
114  /* next */
115  areg = areg->next;
116  arc_index++;
117  }
118 
119  return 0;
120 }
121 
123 
124 u8
126 {
129  uword *p;
130 
131  p = hash_get_mem (fm->arc_index_by_name, s);
132  if (p == 0)
133  return ~0;
134 
136  return reg->feature_arc_index;
137 }
138 
140 vnet_get_feature_reg (const char *arc_name, const char *node_name)
141 {
142  u8 arc_index;
143 
144  arc_index = vnet_get_feature_arc_index (arc_name);
145  if (arc_index == (u8) ~ 0)
146  return 0;
147 
150  uword *p;
151 
152  p = hash_get_mem (fm->next_feature_by_name[arc_index], node_name);
153  if (p == 0)
154  return 0;
155 
157  return reg;
158 }
159 
160 u32
161 vnet_get_feature_index (u8 arc, const char *s)
162 {
165  uword *p;
166 
167  if (s == 0)
168  return ~0;
169 
170  p = hash_get_mem (fm->next_feature_by_name[arc], s);
171  if (p == 0)
172  return ~0;
173 
175  return reg->feature_index;
176 }
177 
178 int
180  u32 sw_if_index, int enable_disable,
181  void *feature_config,
182  u32 n_feature_config_bytes)
183 {
186  i16 feature_count;
187  int is_first_or_last;
188  u32 ci;
189 
190  if (arc_index == (u8) ~ 0)
191  return VNET_API_ERROR_INVALID_VALUE;
192 
193  if (feature_index == ~0)
194  return VNET_API_ERROR_INVALID_VALUE_2;
195 
196  cm = &fm->feature_config_mains[arc_index];
198  ci = cm->config_index_by_sw_if_index[sw_if_index];
199 
200  vec_validate (fm->feature_count_by_sw_if_index[arc_index], sw_if_index);
201  feature_count = fm->feature_count_by_sw_if_index[arc_index][sw_if_index];
202 
203  if (!enable_disable && feature_count < 1)
204  return 0;
205 
206  ci = (enable_disable
209  (vlib_get_main (), &cm->config_main, ci, feature_index, feature_config,
210  n_feature_config_bytes);
211  cm->config_index_by_sw_if_index[sw_if_index] = ci;
212 
213  /* update feature count */
214  enable_disable = (enable_disable > 0);
215  feature_count += enable_disable ? 1 : -1;
216  is_first_or_last = (feature_count == enable_disable);
217  ASSERT (feature_count >= 0);
218 
219  if (is_first_or_last && cm->end_feature_index != ~0)
220  {
221  /*register end node */
222  ci = (enable_disable
225  (vlib_get_main (), &cm->config_main, ci, cm->end_feature_index, 0, 0);
226  cm->config_index_by_sw_if_index[sw_if_index] = ci;
227  }
228 
229  fm->sw_if_index_has_features[arc_index] =
230  clib_bitmap_set (fm->sw_if_index_has_features[arc_index], sw_if_index,
231  (feature_count > 0));
232 
233  fm->feature_count_by_sw_if_index[arc_index][sw_if_index] = feature_count;
234  return 0;
235 }
236 
237 int
238 vnet_feature_enable_disable (const char *arc_name, const char *node_name,
239  u32 sw_if_index, int enable_disable,
240  void *feature_config, u32 n_feature_config_bytes)
241 {
242  u32 feature_index;
243  u8 arc_index;
244 
245  arc_index = vnet_get_feature_arc_index (arc_name);
246 
247  if (arc_index == (u8) ~ 0)
248  return VNET_API_ERROR_INVALID_VALUE;
249 
250  feature_index = vnet_get_feature_index (arc_index, node_name);
251 
252  return vnet_feature_enable_disable_with_index (arc_index, feature_index,
253  sw_if_index, enable_disable,
254  feature_config,
255  n_feature_config_bytes);
256 }
257 
258 
259 /** Display the set of available driver features.
260  Useful for verifying that expected features are present
261 */
262 
263 static clib_error_t *
265  unformat_input_t * input, vlib_cli_command_t * cmd)
266 {
270 
271  vlib_cli_output (vm, "Available feature paths");
272 
273  areg = fm->next_arc;
274  while (areg)
275  {
276  vlib_cli_output (vm, "%s:", areg->arc_name);
277  freg = fm->next_feature_by_arc[areg->feature_arc_index];
278  while (freg)
279  {
280  vlib_cli_output (vm, " %s\n", freg->node_name);
281  freg = freg->next;
282  }
283 
284 
285  /* next */
286  areg = areg->next;
287  }
288 
289  return 0;
290 }
291 
292 /*?
293  * Display the set of available driver features
294  *
295  * @cliexpar
296  * Example:
297  * @cliexcmd{show ip features}
298  * @cliexend
299  * @endparblock
300 ?*/
301 /* *INDENT-OFF* */
302 VLIB_CLI_COMMAND (show_features_command, static) = {
303  .path = "show features",
304  .short_help = "show features",
305  .function = show_features_command_fn,
306 };
307 /* *INDENT-ON* */
308 
309 /** Display the set of driver features configured on a specific interface
310  * Called by "show interface" handler
311  */
312 
313 void
315 {
317  u32 node_index, current_config_index;
318  u16 feature_arc;
321  vnet_config_main_t *vcm;
322  vnet_config_t *cfg;
323  u32 cfg_index;
324  vnet_config_feature_t *feat;
325  vlib_node_t *n;
326  int i;
327 
328  vlib_cli_output (vm, "Driver feature paths configured on %U...",
330  vnet_get_main (), sw_if_index);
331 
332  areg = fm->next_arc;
333  while (areg)
334  {
335  feature_arc = areg->feature_arc_index;
336  vcm = &(cm[feature_arc].config_main);
337 
338  vlib_cli_output (vm, "\n%s:", areg->arc_name);
339  areg = areg->next;
340 
341  if (NULL == cm[feature_arc].config_index_by_sw_if_index ||
342  vec_len (cm[feature_arc].config_index_by_sw_if_index) <=
343  sw_if_index)
344  {
345  vlib_cli_output (vm, " none configured");
346  continue;
347  }
348 
349  current_config_index =
350  vec_elt (cm[feature_arc].config_index_by_sw_if_index, sw_if_index);
351 
352  if (current_config_index == ~0)
353  {
354  vlib_cli_output (vm, " none configured");
355  continue;
356  }
357 
358  ASSERT (current_config_index
360 
361  cfg_index = vcm->config_pool_index_by_user_index[current_config_index];
362  cfg = pool_elt_at_index (vcm->config_pool, cfg_index);
363 
364  for (i = 0; i < vec_len (cfg->features); i++)
365  {
366  feat = cfg->features + i;
367  node_index = feat->node_index;
368  n = vlib_get_node (vm, node_index);
369  vlib_cli_output (vm, " %v", n->name);
370  }
371  }
372 }
373 
374 static clib_error_t *
376  unformat_input_t * input,
377  vlib_cli_command_t * cmd)
378 {
379  vnet_main_t *vnm = vnet_get_main ();
380  unformat_input_t _line_input, *line_input = &_line_input;
381  clib_error_t *error = 0;
382 
383  u8 *arc_name = 0;
384  u8 *feature_name = 0;
385  u32 sw_if_index = ~0;
386  u8 enable = 1;
387 
388  /* Get a line of input. */
389  if (!unformat_user (input, unformat_line_input, line_input))
390  goto done;
391 
392  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
393  {
394  if (unformat
395  (line_input, "%U %v", unformat_vnet_sw_interface, vnm, &sw_if_index,
396  &feature_name))
397  ;
398  else if (unformat (line_input, "arc %v", &arc_name))
399  ;
400  else if (unformat (line_input, "disable"))
401  enable = 0;
402  else
403  {
404  error = unformat_parse_error (line_input);
405  goto done;
406  }
407  }
408 
409  if (sw_if_index == ~0)
410  {
411  error = clib_error_return (0, "Interface not specified...");
412  goto done;
413  }
414 
415  vec_add1 (arc_name, 0);
416  vec_add1 (feature_name, 0);
417 
419  reg =
420  vnet_get_feature_reg ((const char *) arc_name,
421  (const char *) feature_name);
422  if (reg == 0)
423  {
424  error = clib_error_return (0, "Unknown feature...");
425  goto done;
426  }
427  if (reg->enable_disable_cb)
428  error = reg->enable_disable_cb (sw_if_index, enable);
429  if (!error)
430  vnet_feature_enable_disable ((const char *) arc_name,
431  (const char *) feature_name, sw_if_index,
432  enable, 0, 0);
433 
434 done:
435  vec_free (feature_name);
436  vec_free (arc_name);
437  return error;
438 }
439 
440 /*?
441  * Set feature for given interface
442  *
443  * @cliexpar
444  * Example:
445  * @cliexcmd{set interface feature GigabitEthernet2/0/0 ip4_flow_classify arc ip4_unicast}
446  * @cliexend
447  * @endparblock
448 ?*/
449 /* *INDENT-OFF* */
450 VLIB_CLI_COMMAND (set_interface_feature_command, static) = {
451  .path = "set interface feature",
452  .short_help = "set interface feature <intfc> <feature_name> arc <arc_name>",
454 };
455 /* *INDENT-ON* */
456 
457 /*
458  * fd.io coding-style-patch-verification: ON
459  *
460  * Local Variables:
461  * eval: (c-set-style "gnu")
462  * End:
463  */
vnet_config_main_t config_main
Definition: feature.h:66
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:396
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
vnet_config_feature_t * features
Definition: config.h:71
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:966
u8 vnet_get_feature_arc_index(const char *s)
Definition: feature.c:125
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
char *** feature_nodes
Save partial order results for show command.
Definition: feature.h:86
vnet_feature_registration_t * next_feature
feature path configuration lists
Definition: feature.h:78
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
#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:482
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
#define hash_set_mem(h, key, value)
Definition: hash.h:274
unformat_function_t unformat_vnet_sw_interface
format_function_t format_vnet_sw_if_index_name
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
vnet_feature_registration_t * vnet_get_feature_reg(const char *arc_name, const char *node_name)
Definition: feature.c:140
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:179
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:977
u32 vnet_get_feature_index(u8 arc, const char *s)
Definition: feature.c:161
static clib_error_t * vnet_feature_init(vlib_main_t *vm)
Definition: feature.c:21
static uword pointer_to_uword(const void *p)
Definition: types.h:131
#define hash_create_string(elts, value_bytes)
Definition: hash.h:652
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:369
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
#define unformat_parse_error(input)
Definition: format.h:267
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:375
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:576
uword ** next_feature_by_name
Definition: feature.h:80
#define uword_to_pointer(u, type)
Definition: types.h:136
u8 * name
Definition: node.h:221
u32 * config_pool_index_by_user_index
Definition: config.h:104
void vnet_interface_features_show(vlib_main_t *vm, u32 sw_if_index)
Display the set of driver features configured on a specific interface Called by "show interface" hand...
Definition: feature.c:314
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:300
uword ** arc_index_by_name
Definition: feature.h:75
i16 ** feature_count_by_sw_if_index
feature reference counts by interface
Definition: feature.h:92
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
vnet_feature_registration_t ** next_feature_by_arc
Definition: feature.h:79
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
u64 uword
Definition: types.h:112
#define vec_elt(v, i)
Get vector value at index i.
unsigned short u16
Definition: types.h:57
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
struct _vnet_feature_arc_registration vnet_feature_arc_registration_t
feature registration object
#define hash_get_mem(h, key)
Definition: hash.h:268
short i16
Definition: types.h:46
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
vnet_feature_arc_registration_t * next_arc
feature arc configuration list
Definition: feature.h:74
uword ** sw_if_index_has_features
bitmap of interfaces which have driver rx features configured
Definition: feature.h:89
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:58
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:264
#define clib_error_return(e, args...)
Definition: error.h:111
struct _unformat_input_t unformat_input_t
vnet_feature_config_main_t * feature_config_mains
feature config main objects
Definition: feature.h:83
#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:445
unformat_function_t unformat_line_input
Definition: format.h:281
vnet_feature_main_t feature_main
Definition: feature.c:18
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:238
struct _vnet_feature_registration vnet_feature_registration_t
feature registration object