FD.io VPP  v17.10-9-gd594711
Vector Packet Processing
parse.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 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 #include <vlib/parse.h>
16 
17 #define PARSE_DEBUG 0
18 
22 
23 u8 *
24 format_vlib_parse_value (u8 * s, va_list * args)
25 {
26  vlib_parse_main_t *pm = va_arg (*args, vlib_parse_main_t *);
27  vlib_parse_type_t *type;
28  vlib_parse_value_t *v;
29  u16 type_index;
30 
31  s = format (s, "%d items:\n", vec_len (pm->parse_value));
32  vec_foreach (v, pm->parse_value)
33  {
34  type_index = v->type;
35  type = pool_elt_at_index (pm->parse_types, type_index);
36  if (type->format_value)
37  s = format (s, "[%d]: %U\n", v - pm->parse_value,
38  type->format_value, v);
39  else
40  s = format (s, "[%d]: (nofun)\n", v - pm->parse_value);
41  }
42  return s;
43 }
44 
45 static u8 *
46 format_vlib_parse_match (u8 * s, va_list * args)
47 {
48  vlib_parse_match_t m = va_arg (*args, vlib_parse_match_t);
49  char *t = 0;
50  switch (m)
51  {
52 #define _(a) case VLIB_PARSE_##a: t = #a; break;
54 #undef _
55  default:
56  t = 0;
57  break;
58  }
59 
60  if (t)
61  return format (s, "%s", t);
62  else
63  return format (s, "unknown 0x%x", m);
64 }
65 
66 static u8 *
67 format_vlib_parse_item (u8 * s, va_list * args)
68 {
69  vlib_parse_main_t *pm = va_arg (*args, vlib_parse_main_t *);
70  vlib_parse_item_t *item = va_arg (*args, vlib_parse_item_t *);
72 
73  if (item->type == word_type_index)
74  s = format (s, "%s", item->value.as_pointer);
75  else
76  s = format (s, "<%s>", type->name);
77  return s;
78 }
79 
80 static u8 *
81 format_vlib_parse_graph (u8 * s, va_list * args)
82 {
83  vlib_parse_main_t *pm = va_arg (*args, vlib_parse_main_t *);
84  vlib_parse_graph_t *node = va_arg (*args, vlib_parse_graph_t *);
85  vlib_parse_item_t *item;
86  vlib_parse_type_t *type;
87 
88  /* $$$ hash table */
89  /* *INDENT-OFF* */
90  pool_foreach (type, pm->parse_types,
91  ({
92  if (type->rule_index == node - pm->parse_graph)
93  s = format (s, "\n<%s>\n", type->name);
94  }));
95 /* *INDENT-ON* */
96 
97  if (pm->root_index == (node - pm->parse_graph))
98  s = format (s, "\n<root>\n");
99 
100  item = pool_elt_at_index (pm->parse_items, node->item);
101 
102  s = format (s, "[%d] %U ", node - pm->parse_graph,
103  format_vlib_parse_item, pm, item);
104 
105  if (node->peer == (u32) ~ 0)
106  s = format (s, "peer nil ");
107  else
108  s = format (s, "peer %4u ", node->peer);
109 
110  if (node->deeper == (u32) ~ 0)
111  s = format (s, "deeper nil ");
112  else
113  s = format (s, "deeper %4u ", node->deeper);
114 
115  return s;
116 }
117 
118 void
120 {
122  vlib_parse_graph_t *node;
123 
124  /* *INDENT-OFF* */
125  pool_foreach (node, pm->parse_graph, ({
126  fformat(stdout, "%U\n", format_vlib_parse_graph, pm, node);
127  }));
128 /* *INDENT-ON* */
129 }
130 
131 always_inline void
132 parse_cleanup_value (vlib_parse_main_t * pm, vlib_parse_value_t * pv)
133 {
134  vlib_parse_type_t *type = pool_elt_at_index (pm->parse_types, pv->type);
135  if (type->value_cleanup_function)
136  type->value_cleanup_function (pv);
137 }
138 
139 static void
141 {
142  vlib_lex_token_t *t;
143  vlib_parse_value_t *pv;
144 
145  vlib_lex_reset (pm->lex_main, input);
146 
148 
149  vec_foreach (pv, pm->parse_value) parse_cleanup_value (pm, pv);
150 
151  _vec_len (pm->parse_value) = 0;
152  _vec_len (pm->tokens) = 0;
153  pm->current_token_index = 0;
154 }
155 
156 static void
158 {
159  vlib_parse_graph_t *node;
160  vlib_parse_item_t *item;
161  vlib_parse_type_t *type;
162  vlib_main_t *vm = pm->vlib_main;
163  u8 *help_input;
164  int i;
165 
166  help_input = vec_dup (pm->lex_main->input_vector);
167 
168  for (i = vec_len (help_input) - 1; i >= 0; i--)
169  if (help_input[i] == '?')
170  {
171  help_input[i] = 0;
172  _vec_len (help_input) = i;
173  break;
174  }
175 
176  for (i = vec_len (help_input) - 1; i >= 0; i--)
177  {
178  if (help_input[i] != ' ' && help_input[i] != '\t')
179  break;
180  help_input[i] = 0;
181  break;
182  }
183  _vec_len (help_input) = i + 1;
184 
185  while (index != (u32) ~ 0)
186  {
187  node = pool_elt_at_index (pm->parse_graph, index);
188  item = pool_elt_at_index (pm->parse_items, node->item);
189  type = pool_elt_at_index (pm->parse_types, item->type);
190 
191  if (item->type == eof_type_index && vec_len (pm->match_items) == 0)
192  /* do nothing */ ;
193  else if (item->type == word_type_index)
194  vlib_cli_output (vm, "%s %s\n", help_input, item->value.as_pointer);
195  else
196  vlib_cli_output (vm, "%s <%s>\n", help_input, type->name);
197  index = node->peer;
198  }
199  vec_free (help_input);
200 }
201 
202 static vlib_parse_match_t
204 {
205  vlib_parse_graph_t *node;
206  vlib_parse_item_t *item;
207  vlib_parse_type_t *type;
208  vlib_parse_value_t value, *pv;
210  u32 *partial_matches = 0;
211  vlib_lex_token_t *t;
212  u32 save_token_index = (u32) ~ 0, save_match_items = 0;
213  int had_value = 0;
214 
215  if (pm->current_token_index >= vec_len (pm->tokens))
216  return VLIB_PARSE_MATCH_FAIL;
217 
218  /* current token */
220 
221  /* Help ? */
222  if (PREDICT_FALSE (t->token == VLIB_LEX_qmark))
223  {
224  parse_help (pm, index);
225  _vec_len (pm->match_items) = 0;
226  return VLIB_PARSE_MATCH_DONE;
227  }
228 
229  /* Across all peers at this level of the parse graph */
230  while (index != (u32) ~ 0)
231  {
232  node = pool_elt_at_index (pm->parse_graph, index);
233  item = pool_elt_at_index (pm->parse_items, node->item);
234  type = pool_elt_at_index (pm->parse_types, item->type);
235 
236  /*
237  * Save the token index. We may have to back up several
238  * trie plies. Type-specific match functions can consume
239  * multiple tokens, and they may not be optimally careful
240  */
241  save_token_index = pm->current_token_index;
242  save_match_items = vec_len (pm->match_items);
243  vec_add1 (pm->match_items, node->item);
244 
245  if (PARSE_DEBUG > 1)
246  clib_warning ("Try to match token %U against node %d",
247  format_vlib_lex_token, pm->lex_main, t, index);
248 
249  /* Call the type-specific match function */
250  rv = type->match_function (pm, type, t, &value);
251 
252  if (PARSE_DEBUG > 1)
253  clib_warning ("returned %U", format_vlib_parse_match, rv);
254 
255  switch (rv)
256  {
257  case VLIB_PARSE_MATCH_VALUE:
258  /*
259  * Matched, and returned a value to append to the
260  * set of args passed to the action function
261  */
262  value.type = item->type;
263  vec_add1 (pm->parse_value, value);
264  had_value = 1;
265  /* fallthrough */
266 
267  case VLIB_PARSE_MATCH_FULL:
268  unambiguous_partial_match:
269  /* Consume the matched token */
270  pm->current_token_index++;
271 
272  /* continue matching along this path */
273  rv = parse_eval_internal (pm, node->deeper);
274 
275  /* this is not the right path */
276  if (rv == VLIB_PARSE_MATCH_FAIL)
277  {
278  if (had_value)
279  {
280  /* Delete the value */
281  value = pm->parse_value[vec_len (pm->parse_value) - 1];
282  parse_cleanup_value (pm, &value);
283  _vec_len (pm->parse_value) -= 1;
284  }
285  /* Continue with the next sibling */
286  pm->current_token_index = save_token_index;
287  _vec_len (pm->match_items) = save_match_items;
288  index = node->peer;
289  break;
290  }
291  return rv;
292 
293  case VLIB_PARSE_MATCH_PARTIAL:
294  /* Partial (substring) match, remember it but keep going */
295  vec_add1 (partial_matches, node - pm->parse_graph);
296  index = node->peer;
297  break;
298 
299  case VLIB_PARSE_MATCH_FAIL:
300  /* Continue with the next sibling */
301  index = node->peer;
302  _vec_len (pm->match_items) = save_match_items;
303  break;
304 
305  case VLIB_PARSE_MATCH_DONE:
306  /* Parse complete, invoke the action function */
307  if (PARSE_DEBUG > 0)
308  clib_warning ("parse_value: %U", format_vlib_parse_value, pm);
309 
310  {
312  if (f)
313  rv = f (pm, item, pm->parse_value);
314  }
315 
316  vec_foreach (pv, pm->parse_value) parse_cleanup_value (pm, pv);
317  _vec_len (pm->parse_value) = 0;
318  _vec_len (pm->match_items) = 0;
319  return rv;
320 
321  case VLIB_PARSE_MATCH_AMBIGUOUS:
322  case VLIB_PARSE_MATCH_EVAL_FAIL:
323  case VLIB_PARSE_MATCH_RULE:
324  _vec_len (pm->match_items) = save_match_items;
325  return rv;
326  }
327  }
328 
329  /*
330  * Out of siblings. If we have exactly one partial match
331  * we win
332  */
333  if (vec_len (partial_matches) == 1)
334  {
335  index = partial_matches[0];
336  node = pool_elt_at_index (pm->parse_graph, index);
337  vec_free (partial_matches);
338  goto unambiguous_partial_match;
339  }
340 
341  /* Ordinary loser */
342  rv = VLIB_PARSE_MATCH_FAIL;
343 
344  /* Ambiguous loser */
345  if (vec_len (partial_matches) > 1)
346  {
347  vec_free (partial_matches);
348  rv = VLIB_PARSE_MATCH_AMBIGUOUS;
349  }
350 
351  _vec_len (pm->match_items) = save_match_items;
352  return rv;
353 }
354 
357  vlib_lex_token_t * t, vlib_parse_value_t * valuep)
358 {
360  static int recursion_level;
361 
362  if (PARSE_DEBUG > 1)
363  clib_warning ("[%d]: try to match type %s graph index %d",
364  recursion_level, type->name, type->rule_index);
365  recursion_level++;
366  rv = parse_eval_internal (pm, type->rule_index);
367  recursion_level--;
368 
369  /* Break the recusive unwind here... */
370  if (rv == VLIB_PARSE_MATCH_RULE)
371  {
372  if (PARSE_DEBUG > 1)
373  clib_warning ("[%d]: type %s matched", recursion_level, type->name);
374 
375  return VLIB_PARSE_MATCH_FULL;
376  }
377  else
378  {
379  if (PARSE_DEBUG > 1)
380  clib_warning ("[%d]: type %s returns %U", recursion_level, type->name,
382  }
383  return rv;
384 }
385 
386 static int
388 {
389  vlib_lex_token_t *t;
390 
391  parse_reset (pm, input);
392 
393  /* Tokenize the entire input vector */
394  do
395  {
396  vec_add2 (pm->tokens, t, 1);
397  vlib_lex_get_token (pm->lex_main, t);
398  }
399  while (t->token != VLIB_LEX_eof);
400 
401  /* Feed it to the parser */
402  return parse_eval_internal (pm, pm->root_index);
403 }
404 
405 /* Temporary vlib stub */
408 {
409  return parse_eval (&vlib_parse_main, input);
410 }
411 
412 u16
414 {
415  uword *p;
417  u8 *name_copy;
418 
420  if (p)
421  return p[0];
422 
423  pool_get (pm->parse_types, n);
424  *n = *t;
425  n->rule_index = (u32) ~ 0;
426 
427  name_copy = format (0, "%s%c", n->name, 0);
428 
429  hash_set_mem (pm->parse_type_by_name_hash, name_copy, n - pm->parse_types);
430  return n - pm->parse_types;
431 }
432 
433 u16
435 {
436  uword *p;
437 
438  p = hash_get_mem (pm->parse_type_by_name_hash, name);
439  if (p)
440  return p[0];
441 
442  return (u16) ~ 0;
443 }
444 
445 u32
447 {
448  uword *p;
450 
451  /* Exact match the entire item */
452  p = mhash_get (&pm->parse_item_hash, item);
453  if (p)
454  return p[0];
455 
456  pool_get (pm->parse_items, i);
457  *i = *item;
458 
459  mhash_set (&pm->parse_item_hash, i, i - pm->parse_items, 0);
460  return i - pm->parse_items;
461 }
462 
463 static void
465 {
466  u32 eof_index;
467  vlib_parse_type_t type;
468  vlib_parse_item_t item;
469 
470  memset (&type, 0, sizeof (type));
471 
472 #define foreach_token_type \
473  _ (eof) \
474  _ (rule_eof) \
475  _ (word) \
476  _ (number) \
477  _ (plus) \
478  _ (minus) \
479  _ (star) \
480  _ (slash) \
481  _ (lpar) \
482  _ (rpar)
483 
484 #define _(a) a##_type_index = parse_type_find_by_name (pm, #a);
486 #undef _
487  memset (&item, 0, sizeof (item));
488  item.type = eof_type_index;
489 
490  eof_index = parse_item_find_or_create (pm, &item);
491  pm->root_index = (u32) ~ 0;
492 
493 #if 0
494  pool_get (pm->parse_graph, g);
495  memset (g, 0xff, sizeof (*g));
496  g->item = eof_index;
497  pm->root_index = 0;
498 #endif
499 }
500 
501 
502 
503 static void
505 {
506  vlib_lex_token_t *t;
508  "%s%c", pr->initializer, 0);
509 
510  parse_reset (pm, pm->register_input);
511 
512  do
513  {
514  vec_add2 (pm->tokens, t, 1);
515  vlib_lex_get_token (pm->lex_main, t);
516  }
517  while (t->token != VLIB_LEX_eof);
518  _vec_len (pm->register_input) = 0;
519 }
520 
521 static int
523 {
525 
526  /* <mytype> = blah blah blah */
527  if (vec_len (pm->tokens) >= 4
528  && t[0].token == VLIB_LEX_lt
529  && t[1].token == VLIB_LEX_word
530  && t[2].token == VLIB_LEX_gt && t[3].token == VLIB_LEX_equals)
531  return 1;
532  return 0;
533 }
534 
535 static int
537  vlib_lex_token_t * t,
538  vlib_parse_graph_t * node,
539  vlib_parse_item_t * item,
540  vlib_parse_type_t * type, u32 * token_increment)
541 {
542  /* EOFs don't match */
543  if (t->token == VLIB_LEX_eof)
544  return 0;
545 
546  /* New chain element is a word */
547  if (t->token == VLIB_LEX_word)
548  {
549  /* but the item in hand is not a word */
550  if (item->type != word_type_index)
551  return 0;
552 
553  /* Or it's not this particular word */
554  if (strcmp (t->value.as_pointer, item->value.as_pointer))
555  return 0;
556  *token_increment = 1;
557  return 1;
558  }
559  /* New chain element is a type-name: < TYPE-NAME > */
560  if (t->token == VLIB_LEX_lt)
561  {
562  u16 token_type_index;
563 
564  /* < TYPE > */
565  if (t[1].token != VLIB_LEX_word || t[2].token != VLIB_LEX_gt)
566  {
567  clib_warning (0, "broken type name in '%s'", pm->register_input);
568  return 0;
569  }
570 
571  token_type_index = parse_type_find_by_name (pm, t[1].value.as_pointer);
572  if (token_type_index == (u16) ~ 0)
573  {
574  clib_warning (0, "unknown type '%s'", t[1].value.as_pointer);
575  return 0;
576  }
577 
578  /* Its a known type but does not match. */
579  if (item->type != token_type_index)
580  return 0;
581 
582  *token_increment = 3;
583  return 1;
584  }
585  clib_warning ("BUG: t->token = %d", t->token);
586  return 0;
587 }
588 
589 u32
591  vlib_lex_token_t * t,
592  u32 * new_subgraph_depth,
593  parse_registration_t * pr, int not_a_rule)
594 {
595  vlib_parse_graph_t *g, *last_g;
596  vlib_parse_item_t new_item;
597  u32 rv = (u32) ~ 0, new_item_index, last_index = (u32) ~ 0;
598  u16 token_type_index;
599  u32 depth = 0;
600 
601  while (t < pm->tokens + vec_len (pm->tokens))
602  {
603  memset (&new_item, 0, sizeof (new_item));
604 
605  if (t->token == VLIB_LEX_word)
606  {
607  new_item.type = word_type_index;
608  new_item.value.as_pointer = vec_dup ((u8 *) t->value.as_pointer);
609  new_item_index = parse_item_find_or_create (pm, &new_item);
610  t++;
611  }
612  else if (t->token == VLIB_LEX_lt)
613  {
614  if (t[1].token != VLIB_LEX_word || t[2].token != VLIB_LEX_gt)
615  {
616  clib_warning ("broken type name in '%s'", pm->register_input);
617  goto screwed;
618  }
619  token_type_index = parse_type_find_by_name (pm,
620  t[1].value.as_pointer);
621  if (token_type_index == (u16) ~ 0)
622  {
623  clib_warning ("unknown type 2 '%s'", t[1].value.as_pointer);
624  goto screwed;
625  }
626 
627  new_item.type = token_type_index;
628  new_item.value.as_pointer = 0;
629  new_item_index = parse_item_find_or_create (pm, &new_item);
630  t += 3; /* skip < <type-name> and > */
631  }
632  else if (t->token == VLIB_LEX_eof)
633  {
634  screwed:
635  new_item.type = not_a_rule ? eof_type_index : rule_eof_type_index;
636  new_item.value.as_pointer = pr->eof_match;
637  new_item_index = parse_item_find_or_create (pm, &new_item);
638  t++;
639  }
640  else
641  {
642  clib_warning ("unexpected token %U index %d in '%s'",
644  t - pm->tokens, pm->register_input);
645  goto screwed;
646  }
647 
648  pool_get (pm->parse_graph, g);
649  memset (g, 0xff, sizeof (*g));
650  g->item = new_item_index;
651  depth++;
652 
653  if (rv == (u32) ~ 0)
654  {
655  rv = g - pm->parse_graph;
656  last_index = rv;
657  }
658  else
659  {
660  last_g = pool_elt_at_index (pm->parse_graph, last_index);
661  last_index = last_g->deeper = g - pm->parse_graph;
662  }
663  }
664  *new_subgraph_depth = depth;
665  return rv;
666 }
667 
668 static u32
670 {
671  vlib_parse_graph_t *node;
672  vlib_parse_item_t *item;
673  u32 max = 0;
674  u32 depth;
675 
676  if (index == (u32) ~ 0)
677  return 0;
678 
679  node = pool_elt_at_index (pm->parse_graph, index);
680  item = pool_elt_at_index (pm->parse_items, node->item);
681 
682  if (item->type == eof_type_index)
683  return 1;
684 
685  while (index != (u32) ~ 0)
686  {
687  node = pool_elt_at_index (pm->parse_graph, index);
688  depth = measure_depth (pm, node->deeper);
689  if (max < depth)
690  max = depth;
691  index = node->peer;
692  }
693 
694  return max + 1;
695 }
696 
697 static void
699  u32 last_matching_index,
700  u32 graph_root_index,
701  u32 new_subgraph_index, u32 new_subgraph_depth)
702 {
703  vlib_parse_graph_t *parent_node;
704  int new_subgraph_longest = 1;
705  u32 current_peer_index;
706  u32 current_depth;
707  vlib_parse_graph_t *current_peer = 0;
708  vlib_parse_graph_t *new_subgraph_node =
709  pool_elt_at_index (pm->parse_graph, new_subgraph_index);
710 
711  /*
712  * Case 1: top-level peer. Splice into the top-level
713  * peer chain according to rule depth
714  */
715  if (last_matching_index == (u32) ~ 0)
716  {
717  u32 index = graph_root_index;
718  while (1)
719  {
720  current_peer = pool_elt_at_index (pm->parse_graph, index);
721  current_depth = measure_depth (pm, index);
722  if (current_depth < new_subgraph_depth
723  || current_peer->peer == (u32) ~ 0)
724  break;
725  index = current_peer->peer;
726  }
727  new_subgraph_node->peer = current_peer->peer;
728  current_peer->peer = new_subgraph_index;
729  return;
730  }
731 
732  parent_node = pool_elt_at_index (pm->parse_graph, last_matching_index);
733  current_peer_index = parent_node->deeper;
734 
735  while (current_peer_index != (u32) ~ 0)
736  {
737  current_peer = pool_elt_at_index (pm->parse_graph, current_peer_index);
738  current_depth = measure_depth (pm, current_peer_index);
739  if (current_depth < new_subgraph_depth)
740  break;
741  new_subgraph_longest = 0;
742  current_peer_index = current_peer->peer;
743  }
744 
745  ASSERT (current_peer);
746 
747  if (new_subgraph_longest)
748  {
749  new_subgraph_node->peer = parent_node->deeper;
750  parent_node->deeper = new_subgraph_index;
751  }
752  else
753  {
754  new_subgraph_node->peer = current_peer->peer;
755  current_peer->peer = new_subgraph_index;
756  }
757 }
758 
759 static clib_error_t *
761 {
762  u32 graph_root_index;
763  u16 subgraph_type_index = (u16) ~ 0;
764  vlib_parse_type_t *subgraph_type = 0;
765  vlib_lex_token_t *t;
766  vlib_parse_graph_t *node;
767  u32 node_index, last_index, token_increment, new_subgraph_index;
768  u32 new_subgraph_depth, last_matching_index;
769  vlib_parse_item_t *item;
770  vlib_parse_type_t *type;
771 
772  int use_main_graph = 1;
773 
774  tokenize (pm, pr);
775 
776  /* A typed rule? */
777  if (is_typed_rule (pm))
778  {
779  /* Get the type and its current subgraph root, if any */
780  t = vec_elt_at_index (pm->tokens, 1);
781  subgraph_type_index = parse_type_find_by_name (pm, t->value.as_pointer);
782  if (subgraph_type_index == (u16) ~ 0)
783  return clib_error_return (0, "undeclared type '%s'",
784  t->value.as_pointer);
785  subgraph_type =
786  pool_elt_at_index (pm->parse_types, subgraph_type_index);
787  graph_root_index = subgraph_type->rule_index;
788  /* Skip "mytype> = */
789  t += 3;
790  use_main_graph = 0;
791  }
792  else
793  {
794  /* top-level graph */
795  graph_root_index = pm->root_index;
796  t = vec_elt_at_index (pm->tokens, 0);
797  }
798 
799  last_matching_index = (u32) ~ 0;
800  last_index = node_index = graph_root_index;
801 
802  /* Find the first token which isn't already being parsed */
803  while (t < pm->tokens + vec_len (pm->tokens) && node_index != (u32) ~ 0)
804  {
805  node = pool_elt_at_index (pm->parse_graph, node_index);
806  item = pool_elt_at_index (pm->parse_items, node->item);
807  type = pool_elt_at_index (pm->parse_types, item->type);
808  last_index = node_index;
809 
811  (pm, t, node, item, type, &token_increment))
812  {
813  t += token_increment;
814  last_matching_index = node_index;
815  node_index = node->deeper;
816  }
817  else
818  node_index = node->peer;
819  }
820 
821  new_subgraph_index =
822  generate_subgraph_from_tokens (pm, t, &new_subgraph_depth, pr,
823  use_main_graph);
824 
825  /* trivial cases: first graph node or first type rule */
826  if (graph_root_index == (u32) ~ 0)
827  {
828  if (use_main_graph)
829  pm->root_index = new_subgraph_index;
830  else
831  subgraph_type->rule_index = new_subgraph_index;
832  return 0;
833  }
834 
835  add_subgraph_to_graph (pm, last_matching_index, graph_root_index,
836  new_subgraph_index, new_subgraph_depth);
837  return 0;
838 }
839 
840 static clib_error_t *
844 {
846 
847  for (pr = lo; pr < hi; pr = vlib_elf_section_data_next (pr, 0))
848  vec_add1 (pm->parse_registrations, pr);
849 
850  return 0;
851 }
852 
853 static clib_error_t *
855 {
856  (void) parse_type_find_or_create (pm, (vlib_parse_type_t *) rp);
857  return 0;
858 }
859 
860 static clib_error_t *
864 {
865  clib_error_t *error = 0;
866  vlib_parse_type_t *ptr;
867 
868  for (ptr = lo; ptr < hi; ptr = vlib_elf_section_data_next (ptr, 0))
869  {
870  error = parse_register_one_type (pm, ptr);
871  if (error)
872  goto done;
873  }
874 
875 done:
876  return error;
877 }
878 
879 clib_error_t *vlib_stdlex_init (vlib_main_t * vm) __attribute__ ((weak));
880 clib_error_t *
882 {
883  (void) vlib_lex_add_table ("ignore_everything");
884  return 0;
885 }
886 
887 static int
889 {
890  int length, i;
892 
893  if (r->rule_length)
894  return r->rule_length;
895 
896  length = 0;
897 
898  tokenize (pm, r);
899  length = vec_len (pm->tokens);
900 
901  /* Account for "<foo> = " in "<foo> = bar" etc. */
902  if (is_typed_rule (pm))
903  length -= 2;
904 
905  for (i = 0; i < vec_len (pm->tokens); i++)
906  {
907  switch (pm->tokens[i].token)
908  {
909  case VLIB_LEX_lt:
910  case VLIB_LEX_gt:
911  length -= 1;
912 
913  default:
914  break;
915  }
916  }
917 
918  ASSERT (length > 0);
919  r->rule_length = length;
920  return length;
921 }
922 
923 static int
925 {
926  compute_rule_length (r1);
927  compute_rule_length (r2);
928  /* Descending sort */
929  return r2->rule_length - r1->rule_length;
930 }
931 
932 
933 static clib_error_t *
935 {
938  vlib_elf_section_bounds_t *b, *bounds;
939  clib_error_t *error = 0;
940  parse_registration_t *rule;
941  int i;
942 
943  if ((error = vlib_call_init_function (vm, lex_onetime_init)))
944  return error;
945 
946  if ((error = vlib_stdlex_init (vm)))
947  return error;
948 
949  if ((error = vlib_call_init_function (vm, parse_builtin_init)))
950  return error;
951 
952  pm->vlib_main = vm;
953  pm->lex_main = lm;
954 
955  mhash_init (&pm->parse_item_hash, sizeof (u32), sizeof (vlib_parse_item_t));
956  pm->parse_type_by_name_hash = hash_create_string (0, sizeof (u32));
957 
958  vec_validate (pm->parse_value, 16);
959  vec_validate (pm->tokens, 16);
960  vec_validate (pm->register_input, 32);
961  vec_validate (pm->match_items, 16);
962 
963  _vec_len (pm->parse_value) = 0;
964  _vec_len (pm->tokens) = 0;
965  _vec_len (pm->register_input) = 0;
966  _vec_len (pm->match_items) = 0;
967 
968  bounds = vlib_get_elf_section_bounds (vm, "parse_type_registrations");
969  vec_foreach (b, bounds)
970  {
971  error = parse_type_register (vm, b->lo, b->hi, pm);
972  if (error)
973  break;
974  }
975  vec_free (bounds);
976 
978 
979  bounds = vlib_get_elf_section_bounds (vm, "parse_registrations");
980  vec_foreach (b, bounds)
981  {
982  error = parse_register (vm, b->lo, b->hi, pm);
983  if (error)
984  break;
985  }
986  vec_free (bounds);
987 
989 
990  for (i = 0; i < vec_len (pm->parse_registrations); i++)
991  {
992  rule = pm->parse_registrations[i];
993  parse_register_one (pm, rule);
994  }
995 
996  return error;
997 }
998 
1000 
1001 /*
1002  * fd.io coding-style-patch-verification: ON
1003  *
1004  * Local Variables:
1005  * eval: (c-set-style "gnu")
1006  * End:
1007  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:432
u16 parse_type_find_by_name(vlib_parse_main_t *pm, char *name)
Definition: parse.c:434
u16 parse_type_find_or_create(vlib_parse_main_t *pm, vlib_parse_type_t *t)
Definition: parse.c:413
char * initializer
Definition: parse.h:124
vmrglw vmrglh hi
u8 * register_input
Definition: parse.h:146
static clib_error_t * parse_register_one(vlib_parse_main_t *pm, parse_registration_t *pr)
Definition: parse.c:760
u16 eof_type_index
Definition: parse.c:19
vlib_parse_match_t rule_match(vlib_parse_main_t *pm, vlib_parse_type_t *type, vlib_lex_token_t *t, vlib_parse_value_t *valuep)
Definition: parse.c:356
void * as_pointer
Definition: parse.h:54
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:337
mhash_t parse_item_hash
Definition: parse.h:137
static vlib_parse_match_t parse_eval_internal(vlib_parse_main_t *pm, u32 index)
Definition: parse.c:203
u8 * format_vlib_parse_value(u8 *s, va_list *args)
Definition: parse.c:24
static int compute_rule_length(parse_registration_t *r)
Definition: parse.c:888
u8 * input_vector
Definition: lex.h:108
void * eof_match
Definition: parse.h:126
u16 lpar_type_index
Definition: parse.c:19
u16 star_type_index
Definition: parse.c:19
vlib_parse_main_t vlib_parse_main
Definition: parse.h:177
u16 rule_eof_type_index
Definition: parse.c:19
static void parse_help(vlib_parse_main_t *pm, u32 index)
Definition: parse.c:157
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:518
vlib_parse_graph_t * parse_graph
Definition: parse.h:141
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:557
vlib_main_t * vlib_main
Definition: parse.h:173
#define hash_set_mem(h, key, value)
Definition: hash.h:274
vlib_lex_main_t * lex_main
Definition: parse.h:171
u16 plus_type_index
Definition: parse.c:19
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
static clib_error_t * parse_register_one_type(vlib_parse_main_t *pm, vlib_parse_type_t *rp)
Definition: parse.c:854
static clib_error_t * parse_register(vlib_main_t *vm, parse_registration_t *lo, parse_registration_t *hi, vlib_parse_main_t *pm)
Definition: parse.c:841
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:225
u32 current_token_index
Definition: parse.h:168
vlib_parse_match_function_t * match_function
Definition: parse.h:109
static int parse_eval(vlib_parse_main_t *pm, u8 *input)
Definition: parse.c:387
vlib_parse_value_t * parse_value
Definition: parse.h:156
u32 parse_item_find_or_create(vlib_parse_main_t *pm, vlib_parse_item_t *item)
Definition: parse.c:446
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:437
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
#define always_inline
Definition: clib.h:84
vlib_parse_type_t * parse_types
Definition: parse.h:150
vlib_parse_item_t * parse_items
Definition: parse.h:135
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
#define clib_error_return(e, args...)
Definition: error.h:99
static u8 * format_vlib_parse_item(u8 *s, va_list *args)
Definition: parse.c:67
clib_error_t * vlib_stdlex_init(vlib_main_t *vm)
Definition: parse.c:881
void dump_parse_graph(void)
Definition: parse.c:119
#define vlib_call_init_function(vm, x)
Definition: init.h:162
static void tokenize(vlib_parse_main_t *pm, parse_registration_t *pr)
Definition: parse.c:504
static void vlib_lex_cleanup_token(vlib_lex_token_t *t)
Definition: lex.h:120
#define hash_create_string(elts, value_bytes)
Definition: hash.h:652
u16 vlib_lex_add_table(char *name)
Definition: lex.c:207
static clib_error_t * parse_init(vlib_main_t *vm)
Definition: parse.c:934
static void parse_type_and_graph_init(vlib_parse_main_t *pm)
Definition: parse.c:464
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:458
static u8 * format_vlib_parse_graph(u8 *s, va_list *args)
Definition: parse.c:81
u16 word_type_index
Definition: parse.c:19
#define v
Definition: acl.c:323
u32 generate_subgraph_from_tokens(vlib_parse_main_t *pm, vlib_lex_token_t *t, u32 *new_subgraph_depth, parse_registration_t *pr, int not_a_rule)
Definition: parse.c:590
static u8 * format_vlib_parse_match(u8 *s, va_list *args)
Definition: parse.c:46
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:370
char * name
Definition: parse.h:106
static foreach_vanilla_lex_match_function clib_error_t * parse_builtin_init(vlib_main_t *vm)
u16 rpar_type_index
Definition: parse.c:19
#define PREDICT_FALSE(x)
Definition: clib.h:97
static void parse_reset(vlib_parse_main_t *pm, u8 *input)
Definition: parse.c:140
static uword mhash_set(mhash_t *h, void *key, uword new_value, uword *old_value)
Definition: mhash.h:117
format_function_t format_vlib_lex_token
Definition: lex.h:135
void mhash_init(mhash_t *h, uword n_value_bytes, uword n_key_bytes)
Definition: mhash.c:168
vlib_parse_match_t vlib_parse_eval(u8 *input)
Definition: parse.c:407
vlib_main_t * vm
Definition: buffer.c:283
#define foreach_token_type
static clib_error_t * parse_type_register(vlib_main_t *vm, vlib_parse_type_t *lo, vlib_parse_type_t *hi, vlib_parse_main_t *pm)
Definition: parse.c:861
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:336
#define clib_warning(format, args...)
Definition: error.h:59
vlib_parse_value_cleanup_function_t * value_cleanup_function
Definition: parse.h:112
u16 slash_type_index
Definition: parse.c:19
u32 * match_items
Definition: parse.h:158
static int rule_length_compare(parse_registration_t *r1, parse_registration_t *r2)
Definition: parse.c:924
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
static uword * mhash_get(mhash_t *h, const void *key)
Definition: mhash.h:110
u16 number_type_index
Definition: parse.c:19
void * as_pointer
Definition: lex.h:78
void vlib_lex_reset(vlib_lex_main_t *lm, u8 *input_vector)
Definition: lex.c:233
union vlib_lex_token_t::@31 value
union vlib_parse_item_t::@35 value
parse_registration_t ** parse_registrations
Definition: parse.h:162
u16 minus_type_index
Definition: parse.c:19
u64 uword
Definition: types.h:112
format_function_t * format_value
Definition: parse.h:115
uword * parse_type_by_name_hash
Definition: parse.h:152
unsigned short u16
Definition: types.h:57
u32 rule_index
Definition: parse.h:118
static void parse_cleanup_value(vlib_parse_main_t *pm, vlib_parse_value_t *pv)
Definition: parse.c:132
vlib_lex_main_t vlib_lex_main
Definition: lex.c:18
static int token_matches_graph_node(vlib_parse_main_t *pm, vlib_lex_token_t *t, vlib_parse_graph_t *node, vlib_parse_item_t *item, vlib_parse_type_t *type, u32 *token_increment)
Definition: parse.c:536
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
Definition: vec.h:956
void vlib_lex_get_token(vlib_lex_main_t *lm, vlib_lex_token_t *rv)
Definition: lex.c:36
static clib_error_t * lex_onetime_init(vlib_main_t *vm)
Definition: lex.c:244
static u32 measure_depth(vlib_parse_main_t *pm, u32 index)
Definition: parse.c:669
#define PARSE_DEBUG
Definition: parse.c:17
vlib_parse_match_t( vlib_parse_eval_function_t)(vlib_parse_main_t *, vlib_parse_item_t *, vlib_parse_value_t *)
Definition: parse.h:181
static void add_subgraph_to_graph(vlib_parse_main_t *pm, u32 last_matching_index, u32 graph_root_index, u32 new_subgraph_index, u32 new_subgraph_depth)
Definition: parse.c:698
vlib_lex_token_t * tokens
Definition: parse.h:166
#define hash_get_mem(h, key)
Definition: hash.h:268
#define vec_foreach(var, vec)
Vector iterator.
static int is_typed_rule(vlib_parse_main_t *pm)
Definition: parse.c:522
u32 root_index
Definition: parse.h:143
u32 token
Definition: lex.h:73
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:680
vlib_parse_match_t
Definition: parse.h:85