FD.io VPP  v20.05.1-5-g09f167997
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 
18 
20 
22 {
24  void *data;
26 
28 
29 void
31 {
33 
34  vec_add2 (regs, reg, 1);
35 
36  reg->cb = cb;
37  reg->data = data;
38 }
39 
40 static void
41 vent_feature_reg_invoke (u32 sw_if_index, u8 arc_index, u8 is_enable)
42 {
44 
45  vec_foreach (reg, regs)
46  reg->cb (sw_if_index, arc_index, is_enable, reg->data);
47 }
48 
49 
50 static clib_error_t *
52 {
57  u32 arc_index = 0;
58 
59  fm->arc_index_by_name = hash_create_string (0, sizeof (uword));
60  areg = fm->next_arc;
61 
62  /* process feature arc registrations */
63  while (areg)
64  {
65  char *s;
66  int i = 0;
67  areg->feature_arc_index = arc_index;
68  if (areg->arc_index_ptr)
69  *areg->arc_index_ptr = arc_index;
70  hash_set_mem (fm->arc_index_by_name, areg->arc_name,
71  pointer_to_uword (areg));
72 
73  /* process start nodes */
74  while ((s = areg->start_nodes[i]))
75  {
76  i++;
77  }
78  areg->n_start_nodes = i;
79 
80  /* next */
81  areg = areg->next;
82  arc_index++;
83  }
84 
85  vec_validate (fm->next_feature_by_arc, arc_index - 1);
86  vec_validate (fm->feature_nodes, arc_index - 1);
87  vec_validate (fm->feature_config_mains, arc_index - 1);
88  vec_validate (fm->next_feature_by_name, arc_index - 1);
89  vec_validate (fm->sw_if_index_has_features, arc_index - 1);
90  vec_validate (fm->feature_count_by_sw_if_index, arc_index - 1);
91  vec_validate (fm->next_constraint_by_arc, arc_index - 1);
92 
93  freg = fm->next_feature;
94  while (freg)
95  {
97  uword *p = hash_get_mem (fm->arc_index_by_name, freg->arc_name);
98  if (p == 0)
99  {
100  /* Don't start vpp with broken features arcs */
101  clib_warning ("Unknown feature arc '%s'", freg->arc_name);
102  os_exit (1);
103  }
104 
106  arc_index = areg->feature_arc_index;
107 
108  next = freg->next;
109  freg->next_in_arc = fm->next_feature_by_arc[arc_index];
110  fm->next_feature_by_arc[arc_index] = freg;
111 
112  /* next */
113  freg = next;
114  }
115 
116  /* Move bulk constraints to the constraint by arc lists */
117  creg = fm->next_constraint;
118  while (creg)
119  {
121  uword *p = hash_get_mem (fm->arc_index_by_name, creg->arc_name);
122  if (p == 0)
123  {
124  /* Don't start vpp with broken features arcs */
125  clib_warning ("Unknown feature arc '%s'", creg->arc_name);
126  os_exit (1);
127  }
128 
130  arc_index = areg->feature_arc_index;
131 
132  next = creg->next;
133  creg->next_in_arc = fm->next_constraint_by_arc[arc_index];
134  fm->next_constraint_by_arc[arc_index] = creg;
135 
136  /* next */
137  creg = next;
138  }
139 
140 
141  areg = fm->next_arc;
142  while (areg)
143  {
144  clib_error_t *error;
146  vnet_config_main_t *vcm;
147  char **features_in_order, *last_feature;
148 
149  arc_index = areg->feature_arc_index;
150  cm = &fm->feature_config_mains[arc_index];
151  vcm = &cm->config_main;
152  if ((error = vnet_feature_arc_init
153  (vm, vcm, areg->start_nodes, areg->n_start_nodes,
154  areg->last_in_arc,
155  fm->next_feature_by_arc[arc_index],
156  fm->next_constraint_by_arc[arc_index],
157  &fm->feature_nodes[arc_index])))
158  {
159  clib_error_report (error);
160  os_exit (1);
161  }
162 
163  features_in_order = fm->feature_nodes[arc_index];
164 
165  /* If specified, verify that the last node in the arc is actually last */
166  if (areg->last_in_arc && vec_len (features_in_order) > 0)
167  {
168  last_feature = features_in_order[vec_len (features_in_order) - 1];
169  if (strncmp (areg->last_in_arc, last_feature,
170  strlen (areg->last_in_arc)))
172  ("WARNING: %s arc: last node is %s, but expected %s!",
173  areg->arc_name, last_feature, areg->last_in_arc);
174  }
175 
176  fm->next_feature_by_name[arc_index] =
177  hash_create_string (0, sizeof (uword));
178  freg = fm->next_feature_by_arc[arc_index];
179 
180  while (freg)
181  {
182  hash_set_mem (fm->next_feature_by_name[arc_index],
183  freg->node_name, pointer_to_uword (freg));
184  freg = freg->next_in_arc;
185  }
186 
187  /* next */
188  areg = areg->next;
189  arc_index++;
190  }
191 
192  return 0;
193 }
194 
196 
197 u8
199 {
202  uword *p;
203 
204  p = hash_get_mem (fm->arc_index_by_name, s);
205  if (p == 0)
206  return ~0;
207 
209  return reg->feature_arc_index;
210 }
211 
213 vnet_get_feature_reg (const char *arc_name, const char *node_name)
214 {
215  u8 arc_index;
216 
217  arc_index = vnet_get_feature_arc_index (arc_name);
218  if (arc_index == (u8) ~ 0)
219  return 0;
220 
223  uword *p;
224 
225  p = hash_get_mem (fm->next_feature_by_name[arc_index], node_name);
226  if (p == 0)
227  return 0;
228 
230  return reg;
231 }
232 
233 u32
234 vnet_get_feature_index (u8 arc, const char *s)
235 {
238  uword *p;
239 
240  if (s == 0)
241  return ~0;
242 
243  p = hash_get_mem (fm->next_feature_by_name[arc], s);
244  if (p == 0)
245  return ~0;
246 
248  return reg->feature_index;
249 }
250 
251 int
253  u32 sw_if_index, int enable_disable,
254  void *feature_config,
255  u32 n_feature_config_bytes)
256 {
259  i16 feature_count;
260  u32 ci;
261 
262  if (arc_index == (u8) ~ 0)
263  return VNET_API_ERROR_INVALID_VALUE;
264 
265  if (feature_index == ~0)
266  return VNET_API_ERROR_INVALID_VALUE_2;
267 
268  cm = &fm->feature_config_mains[arc_index];
271 
272  vec_validate (fm->feature_count_by_sw_if_index[arc_index], sw_if_index);
273  feature_count = fm->feature_count_by_sw_if_index[arc_index][sw_if_index];
274 
275  if (!enable_disable && feature_count < 1)
276  return 0;
277 
278  ci = (enable_disable
281  (vlib_get_main (), &cm->config_main, ci, feature_index, feature_config,
282  n_feature_config_bytes);
283  if (ci == ~0)
284  {
285  return 0;
286  }
288 
289  /* update feature count */
290  enable_disable = (enable_disable > 0);
291  feature_count += enable_disable ? 1 : -1;
292  ASSERT (feature_count >= 0);
293 
294  fm->sw_if_index_has_features[arc_index] =
295  clib_bitmap_set (fm->sw_if_index_has_features[arc_index], sw_if_index,
296  (feature_count > 0));
297  vent_feature_reg_invoke (sw_if_index, arc_index, (feature_count > 0));
298 
299  fm->feature_count_by_sw_if_index[arc_index][sw_if_index] = feature_count;
300  return 0;
301 }
302 
303 int
304 vnet_feature_enable_disable (const char *arc_name, const char *node_name,
305  u32 sw_if_index, int enable_disable,
306  void *feature_config, u32 n_feature_config_bytes)
307 {
308  u32 feature_index;
309  u8 arc_index;
310 
311  arc_index = vnet_get_feature_arc_index (arc_name);
312 
313  if (arc_index == (u8) ~ 0)
314  return VNET_API_ERROR_INVALID_VALUE;
315 
316  feature_index = vnet_get_feature_index (arc_index, node_name);
317 
318  return vnet_feature_enable_disable_with_index (arc_index, feature_index,
319  sw_if_index, enable_disable,
320  feature_config,
321  n_feature_config_bytes);
322 }
323 
324 u32
326  u32 sw_if_index, u32 end_node_index)
327 {
330  u32 ci;
331 
332  if (arc_index == (u8) ~ 0)
333  return VNET_API_ERROR_INVALID_VALUE;
334 
335  if (end_node_index == ~0)
336  return VNET_API_ERROR_INVALID_VALUE_2;
337 
338  cm = &fm->feature_config_mains[arc_index];
341 
343  ci, end_node_index);
344 
345  if (ci != ~0)
347 
348  return ci;
349 }
350 
351 static int
352 feature_cmp (void *a1, void *a2)
353 {
354  vnet_feature_registration_t *reg1 = a1;
355  vnet_feature_registration_t *reg2 = a2;
356 
357  return (int) reg1->feature_index - reg2->feature_index;
358 }
359 
360 /** Display the set of available driver features.
361  Useful for verifying that expected features are present
362 */
363 
364 static clib_error_t *
366  unformat_input_t * input, vlib_cli_command_t * cmd)
367 {
371  vnet_feature_registration_t *feature_regs = 0;
372  int verbose = 0;
373 
374  if (unformat (input, "verbose"))
375  verbose = 1;
376 
377  vlib_cli_output (vm, "Available feature paths");
378 
379  areg = fm->next_arc;
380  while (areg)
381  {
382  if (verbose)
383  vlib_cli_output (vm, "[%2d] %s:", areg->feature_arc_index,
384  areg->arc_name);
385  else
386  vlib_cli_output (vm, "%s:", areg->arc_name);
387 
388  freg = fm->next_feature_by_arc[areg->feature_arc_index];
389  while (freg)
390  {
391  vec_add1 (feature_regs, freg[0]);
392  freg = freg->next_in_arc;
393  }
394 
395  vec_sort_with_function (feature_regs, feature_cmp);
396 
397  vec_foreach (freg, feature_regs)
398  {
399  if (verbose)
400  vlib_cli_output (vm, " [%2d]: %s\n", freg->feature_index,
401  freg->node_name);
402  else
403  vlib_cli_output (vm, " %s\n", freg->node_name);
404  }
405  vec_reset_length (feature_regs);
406  /* next */
407  areg = areg->next;
408  }
409  vec_free (feature_regs);
410 
411  return 0;
412 }
413 
414 /*?
415  * Display the set of available driver features
416  *
417  * @cliexpar
418  * Example:
419  * @cliexcmd{show features [verbose]}
420  * @cliexend
421  * @endparblock
422 ?*/
423 /* *INDENT-OFF* */
424 VLIB_CLI_COMMAND (show_features_command, static) = {
425  .path = "show features",
426  .short_help = "show features [verbose]",
427  .function = show_features_command_fn,
428 };
429 /* *INDENT-ON* */
430 
431 /** Display the set of driver features configured on a specific interface
432  * Called by "show interface" handler
433  */
434 
435 void
437 {
439  u32 node_index, current_config_index;
440  u16 feature_arc;
443  vnet_config_main_t *vcm;
444  vnet_config_t *cfg;
445  u32 cfg_index;
446  vnet_config_feature_t *feat;
447  vlib_node_t *n;
448  int i;
449 
450  vlib_cli_output (vm, "Feature paths configured on %U...",
452  vnet_get_main (), sw_if_index);
453 
454  areg = fm->next_arc;
455  while (areg)
456  {
457  feature_arc = areg->feature_arc_index;
458  vcm = &(cm[feature_arc].config_main);
459 
460  vlib_cli_output (vm, "\n%s:", areg->arc_name);
461  areg = areg->next;
462 
463  if (NULL == cm[feature_arc].config_index_by_sw_if_index ||
464  vec_len (cm[feature_arc].config_index_by_sw_if_index) <=
465  sw_if_index)
466  {
467  vlib_cli_output (vm, " none configured");
468  continue;
469  }
470 
471  current_config_index =
472  vec_elt (cm[feature_arc].config_index_by_sw_if_index, sw_if_index);
473 
474  if (current_config_index == ~0)
475  {
476  vlib_cli_output (vm, " none configured");
477  continue;
478  }
479 
480  ASSERT (current_config_index
482 
483  cfg_index = vcm->config_pool_index_by_user_index[current_config_index];
484  cfg = pool_elt_at_index (vcm->config_pool, cfg_index);
485 
486  for (i = 0; i < vec_len (cfg->features); i++)
487  {
488  feat = cfg->features + i;
489  node_index = feat->node_index;
490  n = vlib_get_node (vm, node_index);
491  if (verbose)
492  vlib_cli_output (vm, " [%2d] %v", feat->feature_index, n->name);
493  else
494  vlib_cli_output (vm, " %v", n->name);
495  }
496  if (verbose)
497  {
498  n =
499  vlib_get_node (vm,
501  [current_config_index]);
502  vlib_cli_output (vm, " [end] %v", n->name);
503  }
504  }
505 }
506 
507 static clib_error_t *
509  unformat_input_t * input,
510  vlib_cli_command_t * cmd)
511 {
512  vnet_main_t *vnm = vnet_get_main ();
513  unformat_input_t _line_input, *line_input = &_line_input;
514  clib_error_t *error = 0;
515 
516  u8 *arc_name = 0;
517  u8 *feature_name = 0;
518  u32 sw_if_index = ~0;
519  u8 enable = 1;
520 
521  /* Get a line of input. */
522  if (!unformat_user (input, unformat_line_input, line_input))
523  return 0;
524 
525  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
526  {
527  if (unformat
528  (line_input, "%U %s arc %s", unformat_vnet_sw_interface, vnm,
529  &sw_if_index, &feature_name, &arc_name))
530  ;
531  else if (unformat (line_input, "disable"))
532  enable = 0;
533  else
534  {
535  error = unformat_parse_error (line_input);
536  goto done;
537  }
538  }
539  if (!feature_name || !arc_name)
540  {
541  error = clib_error_return (0, "Both feature name and arc required...");
542  goto done;
543  }
544 
545  if (sw_if_index == ~0)
546  {
547  error = clib_error_return (0, "Interface not specified...");
548  goto done;
549  }
550 
551  vec_add1 (arc_name, 0);
552  vec_add1 (feature_name, 0);
553 
554  u8 arc_index;
555 
556  arc_index = vnet_get_feature_arc_index ((const char *) arc_name);
557 
558  if (arc_index == (u8) ~ 0)
559  {
560  error =
561  clib_error_return (0, "Unknown arc name (%s)... ",
562  (const char *) arc_name);
563  goto done;
564  }
565 
567  reg =
568  vnet_get_feature_reg ((const char *) arc_name,
569  (const char *) feature_name);
570  if (reg == 0)
571  {
572  error =
574  "Feature (%s) not registered to arc (%s)... See 'show features verbose' for valid feature/arc combinations. ",
575  feature_name, arc_name);
576  goto done;
577  }
578  if (reg->enable_disable_cb)
579  error = reg->enable_disable_cb (sw_if_index, enable);
580  if (!error)
581  vnet_feature_enable_disable ((const char *) arc_name,
582  (const char *) feature_name, sw_if_index,
583  enable, 0, 0);
584 
585 done:
586  vec_free (feature_name);
587  vec_free (arc_name);
588  unformat_free (line_input);
589  return error;
590 }
591 
592 /*?
593  * Set feature for given interface
594  *
595  * @cliexpar
596  * Example:
597  * @cliexcmd{set interface feature GigabitEthernet2/0/0 ip4_flow_classify arc ip4_unicast}
598  * @cliexend
599  * @endparblock
600 ?*/
601 /* *INDENT-OFF* */
602 VLIB_CLI_COMMAND (set_interface_feature_command, static) = {
603  .path = "set interface feature",
604  .short_help = "set interface feature <intfc> <feature_name> arc <arc_name> "
605  "[disable]",
607 };
608 /* *INDENT-ON* */
609 
610 /*
611  * fd.io coding-style-patch-verification: ON
612  *
613  * Local Variables:
614  * eval: (c-set-style "gnu")
615  * End:
616  */
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:507
void vnet_feature_register(vnet_feature_update_cb_t cb, void *data)
Definition: feature.c:30
vnet_feature_update_cb_t cb
Definition: feature.c:23
static void vent_feature_reg_invoke(u32 sw_if_index, u8 arc_index, u8 is_enable)
Definition: feature.c:41
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:198
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:363
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:590
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:628
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
u32 vnet_config_modify_end_node(vlib_main_t *vm, vnet_config_main_t *cm, u32 config_string_heap_index, u32 end_node_index)
Definition: config.c:245
vnet_feature_constraint_registration_t * next_constraint
Definition: feature.h:95
static vnet_feature_upd_registration_t * regs
Definition: feature.c:27
vl_api_interface_index_t sw_if_index
Definition: gre.api:53
#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:213
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:252
#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:234
static clib_error_t * vnet_feature_init(vlib_main_t *vm)
Definition: feature.c:51
#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:53
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:534
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:508
u32 vnet_feature_modify_end_node(u8 arc_index, u32 sw_if_index, u32 end_node_index)
Definition: feature.c:325
void(* vnet_feature_update_cb_t)(u32 sw_if_index, u8 arc_index, u8 is_enable, void *cb)
Definition: feature.h:485
vlib_main_t * vm
Definition: in2out_ed.c:1599
uword ** next_feature_by_name
Definition: feature.h:97
u8 * name
Definition: node.h:266
#define UNFORMAT_END_OF_INPUT
Definition: format.h:145
u32 * config_pool_index_by_user_index
Definition: config.h:105
static int feature_cmp(void *a1, void *a2)
Definition: feature.c:352
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:436
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
#define clib_warning(format, args...)
Definition: error.h:59
void os_exit(int code)
Definition: unix-misc.c:183
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:152
#define uword_to_pointer(u, type)
Definition: types.h:136
#define ASSERT(truth)
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:689
struct vnet_feature_upd_registration_t_ vnet_feature_upd_registration_t
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:299
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:1053
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
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:365
u32 * end_node_indices_by_user_index
Definition: config.h:98
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:554
vnet_feature_main_t feature_main
Definition: feature.c:19
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:304
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