Initial commit of vpp code.
[vpp.git] / vlib / example / plex_test.c
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 #include <vlib/unix/unix.h>
17
18 static u8 * format_value_v4_address (u8 * s, va_list * args)
19 {
20   vlib_parse_value_t *v = va_arg (*args, vlib_parse_value_t *);
21   u32 a = v->value.as_uword;
22
23   s = format (s, "%d.%d.%d.%d",
24               (a>>24) & 0xFF,
25               (a>>16) & 0xFF,
26               (a>>8)  & 0xFF,
27               (a>>0)  & 0xFF);
28
29   return s;
30 }
31
32 static vlib_parse_match_t
33 v4_address_match (vlib_parse_main_t *pm, vlib_parse_type_t *type, 
34                   vlib_lex_token_t *t, vlib_parse_value_t *valuep)
35 {
36   u32 digit;
37   u32 value = 0;
38   int i;
39
40   if (vec_len (pm->tokens) - (t - pm->tokens) < 7)
41     return VLIB_PARSE_MATCH_FAIL;
42
43   /* NUMBER DOT NUMBER DOT NUMBER DOT NUMBER */
44
45   for (i = 0; i < 7; i++) {
46     if ((i & 1) == 0) {
47       if (t[i].token != VLIB_LEX_number)
48         return VLIB_PARSE_MATCH_FAIL;
49       if (t[i].value.as_uword > 0xff)
50         return VLIB_PARSE_MATCH_FAIL;
51       digit = t[i].value.as_uword;
52       value = (value << 8) | digit;
53     } else {
54       if (t[i].token != VLIB_LEX_dot)
55         return VLIB_PARSE_MATCH_FAIL;
56     }
57   }
58   /* note: caller advances by 1 */
59   pm->current_token_index += 6;
60   valuep->value.as_uword = value;
61   return VLIB_PARSE_MATCH_VALUE;
62 }
63
64 PARSE_TYPE_INIT (v4_address, v4_address_match, 0, format_value_v4_address)
65
66 static u8 * format_value_v4_address_and_mask (u8 * s, va_list * args)
67 {
68   vlib_parse_value_t *v = va_arg (*args, vlib_parse_value_t *);
69   u32 * a = v->value.as_pointer;
70
71   s = format (s, "%d.%d.%d.%d",
72               (a[0]>>24) & 0xFF,
73               (a[0]>>16) & 0xFF,
74               (a[0]>>8)  & 0xFF,
75               (a[0]>>0)  & 0xFF);
76   s = format (s, "/%d", a[1]);
77
78   return s;
79 }
80
81 static vlib_parse_match_t
82 v4_address_and_mask_match (vlib_parse_main_t *pm, vlib_parse_type_t *type, 
83                            vlib_lex_token_t *t, vlib_parse_value_t *valuep)
84 {
85   u32 digit;
86   u32 address = 0;
87   u32 *rv = 0;
88   int i;
89
90   if (vec_len (pm->tokens) - (t - pm->tokens) < 9)
91     return VLIB_PARSE_MATCH_FAIL;
92
93   /* NUMBER DOT NUMBER DOT NUMBER DOT NUMBER */
94
95   for (i = 0; i < 7; i++) {
96     if ((i & 1) == 0) {
97       if (t[i].token != VLIB_LEX_number)
98         return VLIB_PARSE_MATCH_FAIL;
99       if (t[i].value.as_uword > 0xff)
100         return VLIB_PARSE_MATCH_FAIL;
101       digit = t[i].value.as_uword;
102       address = (address << 8) | digit;
103     } else {
104       if (t[i].token != VLIB_LEX_dot)
105         return VLIB_PARSE_MATCH_FAIL;
106     }
107   }
108
109   if (t[7].token != VLIB_LEX_slash || t[8].token != VLIB_LEX_number)
110     return VLIB_PARSE_MATCH_FAIL;
111
112   vec_add1 (rv, address);
113   vec_add1 (rv, t[8].value.as_uword);
114
115   /* note: caller advances by 1 */
116   pm->current_token_index += 8;
117   valuep->value.as_pointer = rv;
118   return VLIB_PARSE_MATCH_VALUE;
119 }
120
121 void v4_address_and_mask_cleanup (vlib_parse_value_t *valuep)
122 {
123   u32 * trash = valuep->value.as_pointer;
124   vec_free (trash);
125 }
126
127 PARSE_TYPE_INIT (v4_address_and_mask, v4_address_and_mask_match, 
128                  v4_address_and_mask_cleanup, 
129                  format_value_v4_address_and_mask)
130
131 vlib_lex_main_t vlib_lex_main;
132
133
134
135 vlib_parse_match_t eval_factor0 (vlib_parse_main_t *pm, 
136                                  vlib_parse_item_t *item,
137                                  vlib_parse_value_t *value)
138 {
139   clib_warning ("%U", format_vlib_parse_value, pm);
140   return VLIB_PARSE_MATCH_RULE;
141 }
142 vlib_parse_match_t eval_factor1 (vlib_parse_main_t *pm, 
143                                  vlib_parse_item_t *item,
144                                  vlib_parse_value_t *value)
145 {
146   clib_warning ("%U", format_vlib_parse_value, pm);
147   return VLIB_PARSE_MATCH_RULE;
148 }
149 vlib_parse_match_t eval_factor2 (vlib_parse_main_t *pm, 
150                                  vlib_parse_item_t *item,
151                                  vlib_parse_value_t *value)
152 {
153   word a;
154   int index = vec_len (pm->parse_value)-1;
155   
156   a = pm->parse_value [index].value.as_word;
157   
158   pm->parse_value[index].value.as_word = -a;
159   return VLIB_PARSE_MATCH_RULE;
160 }
161 vlib_parse_match_t eval_term0 (vlib_parse_main_t *pm, 
162                                vlib_parse_item_t *item,
163                                vlib_parse_value_t *value)
164 {
165   clib_warning ("%U", format_vlib_parse_value, pm);
166   return VLIB_PARSE_MATCH_RULE;
167 }
168 vlib_parse_match_t eval_term1 (vlib_parse_main_t *pm, 
169                                vlib_parse_item_t *item,
170                                vlib_parse_value_t *value)
171 {
172   uword a, b;
173   int index = vec_len (pm->parse_value)-2;
174   
175   a = pm->parse_value [index].value.as_uword;
176   b = pm->parse_value [index+1].value.as_uword;
177   
178   pm->parse_value[index].value.as_uword = a * b;
179   _vec_len (pm->parse_value) -= 1;
180   clib_warning ("%U", format_vlib_parse_value, pm);
181   
182   return VLIB_PARSE_MATCH_RULE;
183 }
184 vlib_parse_match_t eval_term2 (vlib_parse_main_t *pm, 
185                                vlib_parse_item_t *item,
186                                vlib_parse_value_t *value)
187 {
188   uword a, b;
189   int index = vec_len (pm->parse_value)-2;
190   
191   a = pm->parse_value [index].value.as_uword;
192   b = pm->parse_value [index+1].value.as_uword;
193   
194   pm->parse_value[index].value.as_uword = a / b;
195   _vec_len (pm->parse_value) -= 1;
196   clib_warning ("%U", format_vlib_parse_value, pm);
197   
198   return VLIB_PARSE_MATCH_RULE;
199 }
200 vlib_parse_match_t eval_exp0 (vlib_parse_main_t *pm, 
201                               vlib_parse_item_t *item,
202                               vlib_parse_value_t *value)
203 {
204   return VLIB_PARSE_MATCH_RULE;
205 }
206 vlib_parse_match_t eval_exp1 (vlib_parse_main_t *pm, 
207                               vlib_parse_item_t *item,
208                               vlib_parse_value_t *value)
209 {
210   uword a, b;
211   int index = vec_len (pm->parse_value)-2;
212   
213   a = pm->parse_value [index].value.as_uword;
214   b = pm->parse_value [index+1].value.as_uword;
215   
216   pm->parse_value[index].value.as_uword = a + b;
217   _vec_len (pm->parse_value) -= 1;
218   clib_warning ("%U", format_vlib_parse_value, pm);
219   
220   return VLIB_PARSE_MATCH_RULE;
221 }
222 vlib_parse_match_t eval_exp2 (vlib_parse_main_t *pm, 
223                               vlib_parse_item_t *item,
224                               vlib_parse_value_t *value)
225 {
226   uword a, b;
227   int index = vec_len (pm->parse_value)-2;
228   
229   a = pm->parse_value [index].value.as_uword;
230   b = pm->parse_value [index+1].value.as_uword;
231   
232   pm->parse_value[index].value.as_uword = a - b;
233   _vec_len (pm->parse_value) -= 1;
234   clib_warning ("%U", format_vlib_parse_value, pm);
235   
236   return VLIB_PARSE_MATCH_RULE;
237 }
238
239 vlib_parse_match_t eval_result (vlib_parse_main_t *pm, 
240                                 vlib_parse_item_t *item,
241                                 vlib_parse_value_t *value)
242 {
243   clib_warning ("%U", format_vlib_parse_value, pm);
244   return VLIB_PARSE_MATCH_DONE;
245 }
246
247 vlib_parse_match_t noop_match_rule (vlib_parse_main_t *pm, 
248                                vlib_parse_item_t *item,
249                                vlib_parse_value_t *value)
250 {
251   clib_warning ("%U", format_vlib_parse_value, pm);
252   return VLIB_PARSE_MATCH_RULE;
253 }
254
255 #if 0
256 PARSE_INIT (t1, "moo", eval0);
257 PARSE_INIT (t2, "moo cow mumble", eval1);
258 PARSE_INIT (t3, "moo cow", eval2);
259 PARSE_INIT (t4, "moo cow mumble grunch", eval3);
260 #endif
261
262 #if 0
263 PARSE_INIT (r1, "eval <exp>", eval_result);
264
265 PARSE_INIT (r2, "<exp> = <term><exp2>", eval_exp0);
266 PARSE_INIT (r3, "<exp2> = <plus> <exp>", eval_exp1);
267 PARSE_INIT (r4, "<exp2> = <minus> <exp>", eval_exp2);
268 PARSE_INIT (r5, "<exp2> = ", noop_match_rule);
269 PARSE_TYPE_INIT (exp, rule_match, 0, 0);
270 PARSE_TYPE_INIT (exp2, rule_match, 0, 0);
271
272 PARSE_INIT (r6, "<term> = <factor><term2>", eval_term0);
273 PARSE_INIT (r7, "<term2> = <star> <term>", eval_term1);
274 PARSE_INIT (r8, "<term2> = <slash> <term>", eval_term2);
275 PARSE_INIT (r9, "<term2> = ", noop_match_rule);
276 PARSE_TYPE_INIT (term, rule_match, 0, 0);
277 PARSE_TYPE_INIT (term2, rule_match, 0, 0);
278
279 PARSE_INIT (r11, "<factor> = <lpar> <exp> <rpar>", eval_factor1);
280 PARSE_INIT (r10, "<factor> = <number>", eval_factor0);
281 PARSE_INIT (r12, "<factor> = <minus> <factor>", eval_factor2);
282
283 PARSE_TYPE_INIT (factor, rule_match, 0, 0);
284 #endif
285
286 PARSE_INIT (r1, "eval <exp>", eval_result);
287
288 #if 1
289 PARSE_INIT (r2, "<exp> = <term><exp2>", eval_exp0);
290 PARSE_INIT (r3, "<exp2> = <plus> <exp>", eval_exp1);
291 PARSE_INIT (r4, "<exp2> = <minus> <exp>", eval_exp2);
292 PARSE_INIT (r5, "<exp2> = ", noop_match_rule);
293 PARSE_TYPE_INIT (exp, rule_match, 0, 0);
294 PARSE_TYPE_INIT (exp2, rule_match, 0, 0);
295
296 PARSE_INIT (r6, "<term> = <factor><term2>", eval_term0);
297 PARSE_INIT (r7, "<term2> = <star> <term>", eval_term1);
298 PARSE_INIT (r8, "<term2> = <slash> <term>", eval_term2);
299 PARSE_INIT (r9, "<term2> = ", noop_match_rule);
300 PARSE_TYPE_INIT (term, rule_match, 0, 0);
301 PARSE_TYPE_INIT (term2, rule_match, 0, 0);
302
303 PARSE_INIT (r11, "<factor> = <lpar> <exp> <rpar>", eval_factor1);
304 PARSE_INIT (r10, "<factor> = <number>", eval_factor0);
305 PARSE_INIT (r12, "<factor> = <minus> <factor>", eval_factor2);
306
307 PARSE_TYPE_INIT (factor, rule_match, 0, 0);
308 #endif
309
310 #if 0
311 PARSE_TYPE_INIT (exp, rule_match, 0, 0);
312 PARSE_INIT (r6, "<exp> = a b", eval_term0);
313 PARSE_INIT (r7, "<exp> = c d", eval_term1);
314 PARSE_INIT (r9, "<exp> = ", noop_match_rule);
315 #endif
316
317 #if 0
318 #define foreach_rule_evaluator                  \
319 _(0)                                            \
320 _(1)                                            \
321 _(2)                                            \
322 _(3)
323
324 #define _(n)                                            \
325 vlib_parse_match_t eval##n (vlib_parse_main_t *pm,      \
326                             vlib_parse_item_t *item,    \
327                             vlib_parse_value_t *value)  \
328 {                                                       \
329   clib_warning ("%U", format_vlib_parse_value, pm);     \
330   return VLIB_PARSE_MATCH_DONE;                         \
331 }
332 foreach_rule_evaluator
333
334 #undef _
335
336 PARSE_INIT (r1, "eval <moo>", eval_result);
337
338 PARSE_INIT (r2, "<moo> = cow", eval0);
339 PARSE_INIT (r4, "<moo> = ", eval1);
340 PARSE_TYPE_INIT (moo, rule_match, 0, 0);
341 #endif 
342
343
344 clib_error_t *test_init (vlib_main_t *vm)
345 {
346   clib_error_t *error;
347
348   if ((error = vlib_call_init_function (vm, parse_init)))
349     return error;
350
351   return 0;
352 }
353
354 VLIB_INIT_FUNCTION (test_init);
355
356 clib_error_t *
357 vlib_stdlex_init (vlib_main_t * vm)
358 {
359   vlib_lex_main_t * lm = &vlib_lex_main;
360   u16 top_index;
361   u16 slash_index, slash_star_index, slash_slash_index, slash_star_star_index;
362   u16 slash_token;
363   u16 word_index;
364   u16 zero_index, octal_index, decimal_index, hex_index, binary_index;
365     
366   top_index = vlib_lex_add_table ("top");
367
368 #define foreach_top_level_single_character_token        \
369   _('(', lpar)                                          \
370   _(')', rpar)                                          \
371   _(';', semi)                                          \
372   _('[', lbrack)                                        \
373   _(']', rbrack)                                        \
374   _('{', lcurly)                                        \
375   _('}', rcurly)                                        \
376   _('+', plus)                                          \
377   _('-', minus)                                         \
378   _('*', star)                                          \
379   _('%', percent)                                       \
380   _('@', atsign)                                        \
381   _(',', comma)                                         \
382   _('.', dot)                                           \
383   _('?', qmark)
384
385 #define _(c,t) \
386   vlib_lex_set_action_range(top_index,c,c,VLIB_LEX_RETURN,vlib_lex_add_token(lm, #t), top_index);
387   foreach_top_level_single_character_token;
388 #undef _
389
390   /* Numbers */
391   zero_index = vlib_lex_add_table ("zero");
392   octal_index = vlib_lex_add_table ("octal");
393   decimal_index = vlib_lex_add_table ("decimal");
394   hex_index = vlib_lex_add_table ("hex");
395   binary_index = vlib_lex_add_table ("binary");
396
397   /* Support 0x 0b 0t and 0123 [octal] */
398   vlib_lex_set_action_range (top_index, '0', '0', VLIB_LEX_START_NUMBER, 10, zero_index);
399   vlib_lex_set_action_range (top_index, '1', '9', VLIB_LEX_START_NUMBER, 10, decimal_index);
400
401   vlib_lex_set_action_range (zero_index, 0, 0x7F, VLIB_LEX_RETURN_AND_RESCAN, VLIB_LEX_number, top_index);
402
403   vlib_lex_set_action_range (zero_index, 'x', 'x', VLIB_LEX_IGNORE, ~0, hex_index); 
404   vlib_lex_set_action_range (zero_index, 'b', 'b', VLIB_LEX_IGNORE, ~0, binary_index); 
405   vlib_lex_set_action_range (zero_index, 't', 't', VLIB_LEX_IGNORE, ~0, decimal_index); 
406   vlib_lex_set_action_range (zero_index, '0', '7', VLIB_LEX_START_NUMBER, 8, octal_index);
407     
408   /* Octal */
409   vlib_lex_set_action_range (octal_index, 0, 0x7f, VLIB_LEX_RETURN_AND_RESCAN,
410                         VLIB_LEX_number, top_index);
411   vlib_lex_set_action_range (octal_index, '0', '7', VLIB_LEX_ADD_TO_NUMBER, 8, 
412                         octal_index);
413
414   /* Decimal */
415   vlib_lex_set_action_range (decimal_index, 0, 0x7f, VLIB_LEX_RETURN_AND_RESCAN,
416                         VLIB_LEX_number, top_index);
417   vlib_lex_set_action_range (decimal_index, '0', '9', VLIB_LEX_ADD_TO_NUMBER, 10, 
418                         decimal_index);
419     
420   /* Hex */
421   vlib_lex_set_action_range (hex_index, 0, 0x7f, VLIB_LEX_RETURN_AND_RESCAN,
422                         VLIB_LEX_number, top_index);
423   vlib_lex_set_action_range (hex_index, '0', '9', VLIB_LEX_ADD_TO_NUMBER, 16, 
424                         hex_index);
425   vlib_lex_set_action_range (hex_index, 'a', 'f', VLIB_LEX_ADD_TO_NUMBER, 16, 
426                         hex_index);
427   vlib_lex_set_action_range (hex_index, 'A', 'F', VLIB_LEX_ADD_TO_NUMBER, 16, 
428                         hex_index);
429     
430   /* Binary */
431   vlib_lex_set_action_range (binary_index, 0, 0x7f, VLIB_LEX_RETURN_AND_RESCAN,
432                         VLIB_LEX_number, top_index);
433   vlib_lex_set_action_range (binary_index, '0', '1', VLIB_LEX_ADD_TO_NUMBER, 2, 
434                         binary_index);
435
436   /* c/c++ comment syntax is the worst... */
437
438   slash_index = vlib_lex_add_table ("slash");
439   slash_star_index = vlib_lex_add_table ("slash_star");
440   slash_star_star_index = vlib_lex_add_table ("slash_star_star");
441   slash_slash_index = vlib_lex_add_table ("slash_slash");
442   slash_token = vlib_lex_add_token (lm, "slash");
443
444   /* Top level: see a slash, ignore, go to slash table */
445   vlib_lex_set_action_range (top_index, '/', '/', VLIB_LEX_IGNORE, ~0, slash_index);
446
447   /* default for slash table: return SLASH, go to top table */
448   vlib_lex_set_action_range (slash_index, 1, 0x7F, VLIB_LEX_RETURN_AND_RESCAN, slash_token, 
449                         top_index);
450   /* see slash-slash, go to s-s table */
451   vlib_lex_set_action_range (slash_index, '/', '/', VLIB_LEX_IGNORE, ~0, 
452                         slash_slash_index);
453   /* see slash-star, go to s-* table */
454   vlib_lex_set_action_range (slash_index, '*', '*', VLIB_LEX_IGNORE, ~0, 
455                         slash_star_index);
456
457   /* EOL in s-s table, ignore, go to top table */
458   vlib_lex_set_action_range (slash_slash_index, '\n', '\n', VLIB_LEX_IGNORE, ~0, 
459                         top_index);
460
461   /* slash-star blah blah star */
462   vlib_lex_set_action_range (slash_star_index, '*', '*', VLIB_LEX_IGNORE, ~0,
463                         slash_star_star_index);
464
465   /* slash star blah blah star slash */
466   vlib_lex_set_action_range (slash_star_star_index, '/', '/', VLIB_LEX_IGNORE, ~0,
467                         top_index);
468
469   /* LT, =, GT */
470   vlib_lex_set_action_range (top_index, '<', '<', VLIB_LEX_RETURN, VLIB_LEX_lt, top_index);
471   vlib_lex_set_action_range (top_index, '=', '=', VLIB_LEX_RETURN, VLIB_LEX_equals,
472                         top_index);
473   vlib_lex_set_action_range (top_index, '>', '>', VLIB_LEX_RETURN, VLIB_LEX_gt, top_index);
474
475   /* words, key and otherwise */
476   word_index = vlib_lex_add_table ("word");
477
478   vlib_lex_set_action_range (top_index, 'a', 'z', VLIB_LEX_ADD_TO_TOKEN, ~0, word_index);
479   vlib_lex_set_action_range (top_index, 'A', 'Z', VLIB_LEX_ADD_TO_TOKEN, ~0, word_index);
480
481   vlib_lex_set_action_range (word_index, 0, 0x7f, VLIB_LEX_KEYWORD_CHECK, ~0, top_index);
482
483   vlib_lex_set_action_range (word_index, 'a', 'z', VLIB_LEX_ADD_TO_TOKEN, ~0, word_index);
484   vlib_lex_set_action_range (word_index, 'A', 'Z', VLIB_LEX_ADD_TO_TOKEN, ~0, word_index);
485   vlib_lex_set_action_range (word_index, '_', '_', VLIB_LEX_ADD_TO_TOKEN, ~0, word_index);
486   vlib_lex_set_action_range (word_index, '0', '9', VLIB_LEX_ADD_TO_TOKEN, ~0, word_index);
487     
488   return 0;
489 }
490