misc: move part of vpe apis to vlibmemory
[vpp.git] / src / vat / api_format.c
1 /*
2  *------------------------------------------------------------------
3  * api_format.c
4  *
5  * Copyright (c) 2014-2020 Cisco and/or its affiliates.
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at:
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *------------------------------------------------------------------
18  */
19
20 #include <vat/vat.h>
21 #include <vlib/pci/pci.h>
22 #include <vpp/api/types.h>
23 #include <vppinfra/socket.h>
24 #include <vlibapi/api.h>
25 #include <vlibmemory/api.h>
26 #include <vnet/ip/ip.h>
27 #include <vnet/ip-neighbor/ip_neighbor.h>
28 #include <vnet/ip/ip_types_api.h>
29 #include <vnet/l2/l2_input.h>
30 #include <vnet/udp/udp_local.h>
31
32 #include <vpp/api/vpe_msg_enum.h>
33 #include <vnet/l2/l2_classify.h>
34 #include <vnet/l2/l2_vtr.h>
35 #include <vnet/classify/in_out_acl.h>
36 #include <vnet/classify/policer_classify.h>
37 #include <vnet/classify/flow_classify.h>
38 #include <vnet/mpls/mpls.h>
39 #include <vnet/ipsec/ipsec.h>
40 #include <inttypes.h>
41 #include <vnet/ip/ip6_hop_by_hop.h>
42 #include <vnet/ip/ip_source_and_port_range_check.h>
43 #include <vnet/policer/xlate.h>
44 #include <vnet/span/span.h>
45 #include <vnet/policer/policer.h>
46 #include <vnet/policer/police.h>
47 #include <vnet/mfib/mfib_types.h>
48 #include <vnet/bonding/node.h>
49 #include <vnet/qos/qos_types.h>
50 #include <vnet/ethernet/ethernet_types_api.h>
51 #include <vnet/ip/ip_types_api.h>
52 #include "vat/json_format.h"
53 #include <vnet/ip/ip_types_api.h>
54 #include <vnet/ethernet/ethernet_types_api.h>
55
56 #include <inttypes.h>
57 #include <sys/stat.h>
58
59 #define vl_typedefs             /* define message structures */
60 #include <vpp/api/vpe_all_api_h.h>
61 #undef vl_typedefs
62
63 /* declare message handlers for each api */
64
65 #define vl_endianfun            /* define message structures */
66 #include <vpp/api/vpe_all_api_h.h>
67 #undef vl_endianfun
68
69 /* instantiate all the print functions we know about */
70 #if VPP_API_TEST_BUILTIN == 0
71 #define vl_print(handle, ...)
72 #else
73 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
74 #endif
75 #define vl_printfun
76 #include <vpp/api/vpe_all_api_h.h>
77 #undef vl_printfun
78
79 #define __plugin_msg_base 0
80 #include <vlibapi/vat_helper_macros.h>
81
82 void vl_api_set_elog_main (elog_main_t * m);
83 int vl_api_set_elog_trace_api_messages (int enable);
84
85 #if VPP_API_TEST_BUILTIN == 0
86 #include <netdb.h>
87
88 u32
89 vl (void *p)
90 {
91   return vec_len (p);
92 }
93
94 int
95 vat_socket_connect (vat_main_t * vam)
96 {
97   int rv;
98   api_main_t *am = vlibapi_get_main ();
99   vam->socket_client_main = &socket_client_main;
100   if ((rv = vl_socket_client_connect ((char *) vam->socket_name,
101                                       "vpp_api_test",
102                                       0 /* default socket rx, tx buffer */ )))
103     return rv;
104
105   /* vpp expects the client index in network order */
106   vam->my_client_index = htonl (socket_client_main.client_index);
107   am->my_client_index = vam->my_client_index;
108   return 0;
109 }
110 #else /* vpp built-in case, we don't do sockets... */
111 int
112 vat_socket_connect (vat_main_t * vam)
113 {
114   return 0;
115 }
116
117 int
118 vl_socket_client_read (int wait)
119 {
120   return -1;
121 };
122
123 int
124 vl_socket_client_write ()
125 {
126   return -1;
127 };
128
129 void *
130 vl_socket_client_msg_alloc (int nbytes)
131 {
132   return 0;
133 }
134 #endif
135
136
137 f64
138 vat_time_now (vat_main_t * vam)
139 {
140 #if VPP_API_TEST_BUILTIN
141   return vlib_time_now (vam->vlib_main);
142 #else
143   return clib_time_now (&vam->clib_time);
144 #endif
145 }
146
147 void
148 errmsg (char *fmt, ...)
149 {
150   vat_main_t *vam = &vat_main;
151   va_list va;
152   u8 *s;
153
154   va_start (va, fmt);
155   s = va_format (0, fmt, &va);
156   va_end (va);
157
158   vec_add1 (s, 0);
159
160 #if VPP_API_TEST_BUILTIN
161   vlib_cli_output (vam->vlib_main, (char *) s);
162 #else
163   {
164     if (vam->ifp != stdin)
165       fformat (vam->ofp, "%s(%d): \n", vam->current_file,
166                vam->input_line_number);
167     else
168       fformat (vam->ofp, "%s\n", (char *) s);
169     fflush (vam->ofp);
170   }
171 #endif
172
173   vec_free (s);
174 }
175
176 #if VPP_API_TEST_BUILTIN == 0
177 static uword
178 api_unformat_sw_if_index (unformat_input_t * input, va_list * args)
179 {
180   vat_main_t *vam = va_arg (*args, vat_main_t *);
181   u32 *result = va_arg (*args, u32 *);
182   u8 *if_name;
183   uword *p;
184
185   if (!unformat (input, "%s", &if_name))
186     return 0;
187
188   p = hash_get_mem (vam->sw_if_index_by_interface_name, if_name);
189   if (p == 0)
190     return 0;
191   *result = p[0];
192   return 1;
193 }
194
195 /* Parse an IP4 address %d.%d.%d.%d. */
196 uword
197 unformat_ip4_address (unformat_input_t * input, va_list * args)
198 {
199   u8 *result = va_arg (*args, u8 *);
200   unsigned a[4];
201
202   if (!unformat (input, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]))
203     return 0;
204
205   if (a[0] >= 256 || a[1] >= 256 || a[2] >= 256 || a[3] >= 256)
206     return 0;
207
208   result[0] = a[0];
209   result[1] = a[1];
210   result[2] = a[2];
211   result[3] = a[3];
212
213   return 1;
214 }
215
216 uword
217 unformat_ethernet_address (unformat_input_t * input, va_list * args)
218 {
219   u8 *result = va_arg (*args, u8 *);
220   u32 i, a[6];
221
222   if (!unformat (input, "%_%x:%x:%x:%x:%x:%x%_",
223                  &a[0], &a[1], &a[2], &a[3], &a[4], &a[5]))
224     return 0;
225
226   /* Check range. */
227   for (i = 0; i < 6; i++)
228     if (a[i] >= (1 << 8))
229       return 0;
230
231   for (i = 0; i < 6; i++)
232     result[i] = a[i];
233
234   return 1;
235 }
236
237 /* Returns ethernet type as an int in host byte order. */
238 uword
239 unformat_ethernet_type_host_byte_order (unformat_input_t * input,
240                                         va_list * args)
241 {
242   u16 *result = va_arg (*args, u16 *);
243   int type;
244
245   /* Numeric type. */
246   if (unformat (input, "0x%x", &type) || unformat (input, "%d", &type))
247     {
248       if (type >= (1 << 16))
249         return 0;
250       *result = type;
251       return 1;
252     }
253   return 0;
254 }
255
256 /* Parse an IP46 address. */
257 uword
258 unformat_ip46_address (unformat_input_t * input, va_list * args)
259 {
260   ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
261   ip46_type_t type = va_arg (*args, ip46_type_t);
262   if ((type != IP46_TYPE_IP6) &&
263       unformat (input, "%U", unformat_ip4_address, &ip46->ip4))
264     {
265       ip46_address_mask_ip4 (ip46);
266       return 1;
267     }
268   else if ((type != IP46_TYPE_IP4) &&
269            unformat (input, "%U", unformat_ip6_address, &ip46->ip6))
270     {
271       return 1;
272     }
273   return 0;
274 }
275
276 /* Parse an IP6 address. */
277 uword
278 unformat_ip6_address (unformat_input_t * input, va_list * args)
279 {
280   ip6_address_t *result = va_arg (*args, ip6_address_t *);
281   u16 hex_quads[8];
282   uword hex_quad, n_hex_quads, hex_digit, n_hex_digits;
283   uword c, n_colon, double_colon_index;
284
285   n_hex_quads = hex_quad = n_hex_digits = n_colon = 0;
286   double_colon_index = ARRAY_LEN (hex_quads);
287   while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
288     {
289       hex_digit = 16;
290       if (c >= '0' && c <= '9')
291         hex_digit = c - '0';
292       else if (c >= 'a' && c <= 'f')
293         hex_digit = c + 10 - 'a';
294       else if (c >= 'A' && c <= 'F')
295         hex_digit = c + 10 - 'A';
296       else if (c == ':' && n_colon < 2)
297         n_colon++;
298       else
299         {
300           unformat_put_input (input);
301           break;
302         }
303
304       /* Too many hex quads. */
305       if (n_hex_quads >= ARRAY_LEN (hex_quads))
306         return 0;
307
308       if (hex_digit < 16)
309         {
310           hex_quad = (hex_quad << 4) | hex_digit;
311
312           /* Hex quad must fit in 16 bits. */
313           if (n_hex_digits >= 4)
314             return 0;
315
316           n_colon = 0;
317           n_hex_digits++;
318         }
319
320       /* Save position of :: */
321       if (n_colon == 2)
322         {
323           /* More than one :: ? */
324           if (double_colon_index < ARRAY_LEN (hex_quads))
325             return 0;
326           double_colon_index = n_hex_quads;
327         }
328
329       if (n_colon > 0 && n_hex_digits > 0)
330         {
331           hex_quads[n_hex_quads++] = hex_quad;
332           hex_quad = 0;
333           n_hex_digits = 0;
334         }
335     }
336
337   if (n_hex_digits > 0)
338     hex_quads[n_hex_quads++] = hex_quad;
339
340   {
341     word i;
342
343     /* Expand :: to appropriate number of zero hex quads. */
344     if (double_colon_index < ARRAY_LEN (hex_quads))
345       {
346         word n_zero = ARRAY_LEN (hex_quads) - n_hex_quads;
347
348         for (i = n_hex_quads - 1; i >= (signed) double_colon_index; i--)
349           hex_quads[n_zero + i] = hex_quads[i];
350
351         for (i = 0; i < n_zero; i++)
352           hex_quads[double_colon_index + i] = 0;
353
354         n_hex_quads = ARRAY_LEN (hex_quads);
355       }
356
357     /* Too few hex quads given. */
358     if (n_hex_quads < ARRAY_LEN (hex_quads))
359       return 0;
360
361     for (i = 0; i < ARRAY_LEN (hex_quads); i++)
362       result->as_u16[i] = clib_host_to_net_u16 (hex_quads[i]);
363
364     return 1;
365   }
366 }
367
368 uword
369 unformat_ipsec_policy_action (unformat_input_t * input, va_list * args)
370 {
371   u32 *r = va_arg (*args, u32 *);
372
373   if (0);
374 #define _(v,f,s) else if (unformat (input, s)) *r = IPSEC_POLICY_ACTION_##f;
375   foreach_ipsec_policy_action
376 #undef _
377     else
378     return 0;
379   return 1;
380 }
381
382 u8 *
383 format_ipsec_crypto_alg (u8 * s, va_list * args)
384 {
385   u32 i = va_arg (*args, u32);
386   u8 *t = 0;
387
388   switch (i)
389     {
390 #define _(v,f,str) case IPSEC_CRYPTO_ALG_##f: t = (u8 *) str; break;
391       foreach_ipsec_crypto_alg
392 #undef _
393     default:
394       return format (s, "unknown");
395     }
396   return format (s, "%s", t);
397 }
398
399 u8 *
400 format_ipsec_integ_alg (u8 * s, va_list * args)
401 {
402   u32 i = va_arg (*args, u32);
403   u8 *t = 0;
404
405   switch (i)
406     {
407 #define _(v,f,str) case IPSEC_INTEG_ALG_##f: t = (u8 *) str; break;
408       foreach_ipsec_integ_alg
409 #undef _
410     default:
411       return format (s, "unknown");
412     }
413   return format (s, "%s", t);
414 }
415
416 #else /* VPP_API_TEST_BUILTIN == 1 */
417 static uword
418 api_unformat_sw_if_index (unformat_input_t * input, va_list * args)
419 {
420   vat_main_t *vam __clib_unused = va_arg (*args, vat_main_t *);
421   vnet_main_t *vnm = vnet_get_main ();
422   u32 *result = va_arg (*args, u32 *);
423
424   return unformat (input, "%U", unformat_vnet_sw_interface, vnm, result);
425 }
426
427 #endif /* VPP_API_TEST_BUILTIN */
428
429 #if (VPP_API_TEST_BUILTIN==0)
430
431 static const char *mfib_flag_names[] = MFIB_ENTRY_NAMES_SHORT;
432 static const char *mfib_flag_long_names[] = MFIB_ENTRY_NAMES_LONG;
433 static const char *mfib_itf_flag_long_names[] = MFIB_ITF_NAMES_LONG;
434 static const char *mfib_itf_flag_names[] = MFIB_ITF_NAMES_SHORT;
435
436 uword
437 unformat_mfib_itf_flags (unformat_input_t * input, va_list * args)
438 {
439   mfib_itf_flags_t old, *iflags = va_arg (*args, mfib_itf_flags_t *);
440   mfib_itf_attribute_t attr;
441
442   old = *iflags;
443   FOR_EACH_MFIB_ITF_ATTRIBUTE (attr)
444   {
445     if (unformat (input, mfib_itf_flag_long_names[attr]))
446       *iflags |= (1 << attr);
447   }
448   FOR_EACH_MFIB_ITF_ATTRIBUTE (attr)
449   {
450     if (unformat (input, mfib_itf_flag_names[attr]))
451       *iflags |= (1 << attr);
452   }
453
454   return (old == *iflags ? 0 : 1);
455 }
456
457 uword
458 unformat_mfib_entry_flags (unformat_input_t * input, va_list * args)
459 {
460   mfib_entry_flags_t old, *eflags = va_arg (*args, mfib_entry_flags_t *);
461   mfib_entry_attribute_t attr;
462
463   old = *eflags;
464   FOR_EACH_MFIB_ATTRIBUTE (attr)
465   {
466     if (unformat (input, mfib_flag_long_names[attr]))
467       *eflags |= (1 << attr);
468   }
469   FOR_EACH_MFIB_ATTRIBUTE (attr)
470   {
471     if (unformat (input, mfib_flag_names[attr]))
472       *eflags |= (1 << attr);
473   }
474
475   return (old == *eflags ? 0 : 1);
476 }
477
478 u8 *
479 format_ip4_address (u8 * s, va_list * args)
480 {
481   u8 *a = va_arg (*args, u8 *);
482   return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
483 }
484
485 u8 *
486 format_ip6_address (u8 * s, va_list * args)
487 {
488   ip6_address_t *a = va_arg (*args, ip6_address_t *);
489   u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;
490
491   i_max_n_zero = ARRAY_LEN (a->as_u16);
492   max_n_zeros = 0;
493   i_first_zero = i_max_n_zero;
494   n_zeros = 0;
495   for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
496     {
497       u32 is_zero = a->as_u16[i] == 0;
498       if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16))
499         {
500           i_first_zero = i;
501           n_zeros = 0;
502         }
503       n_zeros += is_zero;
504       if ((!is_zero && n_zeros > max_n_zeros)
505           || (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros))
506         {
507           i_max_n_zero = i_first_zero;
508           max_n_zeros = n_zeros;
509           i_first_zero = ARRAY_LEN (a->as_u16);
510           n_zeros = 0;
511         }
512     }
513
514   last_double_colon = 0;
515   for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
516     {
517       if (i == i_max_n_zero && max_n_zeros > 1)
518         {
519           s = format (s, "::");
520           i += max_n_zeros - 1;
521           last_double_colon = 1;
522         }
523       else
524         {
525           s = format (s, "%s%x",
526                       (last_double_colon || i == 0) ? "" : ":",
527                       clib_net_to_host_u16 (a->as_u16[i]));
528           last_double_colon = 0;
529         }
530     }
531
532   return s;
533 }
534
535 /* Format an IP46 address. */
536 u8 *
537 format_ip46_address (u8 * s, va_list * args)
538 {
539   ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
540   ip46_type_t type = va_arg (*args, ip46_type_t);
541   int is_ip4 = 1;
542
543   switch (type)
544     {
545     case IP46_TYPE_ANY:
546       is_ip4 = ip46_address_is_ip4 (ip46);
547       break;
548     case IP46_TYPE_IP4:
549       is_ip4 = 1;
550       break;
551     case IP46_TYPE_IP6:
552       is_ip4 = 0;
553       break;
554     }
555
556   return is_ip4 ?
557     format (s, "%U", format_ip4_address, &ip46->ip4) :
558     format (s, "%U", format_ip6_address, &ip46->ip6);
559 }
560
561 u8 *
562 format_ethernet_address (u8 * s, va_list * args)
563 {
564   u8 *a = va_arg (*args, u8 *);
565
566   return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
567                  a[0], a[1], a[2], a[3], a[4], a[5]);
568 }
569 #endif
570
571 void
572 ip_set (ip46_address_t * dst, void *src, u8 is_ip4)
573 {
574   if (is_ip4)
575     dst->ip4.as_u32 = ((ip4_address_t *) src)->as_u32;
576   else
577     clib_memcpy_fast (&dst->ip6, (ip6_address_t *) src,
578                       sizeof (ip6_address_t));
579 }
580
581
582 static void vl_api_show_version_reply_t_handler
583   (vl_api_show_version_reply_t * mp)
584 {
585   vat_main_t *vam = &vat_main;
586   i32 retval = ntohl (mp->retval);
587
588   if (retval >= 0)
589     {
590       errmsg ("        program: %s", mp->program);
591       errmsg ("        version: %s", mp->version);
592       errmsg ("     build date: %s", mp->build_date);
593       errmsg ("build directory: %s", mp->build_directory);
594     }
595   vam->retval = retval;
596   vam->result_ready = 1;
597 }
598
599 static void vl_api_show_version_reply_t_handler_json
600   (vl_api_show_version_reply_t * mp)
601 {
602   vat_main_t *vam = &vat_main;
603   vat_json_node_t node;
604
605   vat_json_init_object (&node);
606   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
607   vat_json_object_add_string_copy (&node, "program", mp->program);
608   vat_json_object_add_string_copy (&node, "version", mp->version);
609   vat_json_object_add_string_copy (&node, "build_date", mp->build_date);
610   vat_json_object_add_string_copy (&node, "build_directory",
611                                    mp->build_directory);
612
613   vat_json_print (vam->ofp, &node);
614   vat_json_free (&node);
615
616   vam->retval = ntohl (mp->retval);
617   vam->result_ready = 1;
618 }
619
620 #define vl_api_bridge_domain_details_t_endian vl_noop_handler
621 #define vl_api_bridge_domain_details_t_print vl_noop_handler
622
623 static void vl_api_control_ping_reply_t_handler
624   (vl_api_control_ping_reply_t * mp)
625 {
626   vat_main_t *vam = &vat_main;
627   i32 retval = ntohl (mp->retval);
628   if (vam->async_mode)
629     {
630       vam->async_errors += (retval < 0);
631     }
632   else
633     {
634       vam->retval = retval;
635       vam->result_ready = 1;
636     }
637   if (vam->socket_client_main)
638     vam->socket_client_main->control_pings_outstanding--;
639 }
640
641 static void vl_api_control_ping_reply_t_handler_json
642   (vl_api_control_ping_reply_t * mp)
643 {
644   vat_main_t *vam = &vat_main;
645   i32 retval = ntohl (mp->retval);
646
647   if (VAT_JSON_NONE != vam->json_tree.type)
648     {
649       vat_json_print (vam->ofp, &vam->json_tree);
650       vat_json_free (&vam->json_tree);
651       vam->json_tree.type = VAT_JSON_NONE;
652     }
653   else
654     {
655       /* just print [] */
656       vat_json_init_array (&vam->json_tree);
657       vat_json_print (vam->ofp, &vam->json_tree);
658       vam->json_tree.type = VAT_JSON_NONE;
659     }
660
661   vam->retval = retval;
662   vam->result_ready = 1;
663 }
664
665
666 static void vl_api_get_first_msg_id_reply_t_handler
667   (vl_api_get_first_msg_id_reply_t * mp)
668 {
669   vat_main_t *vam = &vat_main;
670   i32 retval = ntohl (mp->retval);
671
672   if (vam->async_mode)
673     {
674       vam->async_errors += (retval < 0);
675     }
676   else
677     {
678       vam->retval = retval;
679       vam->result_ready = 1;
680     }
681   if (retval >= 0)
682     {
683       errmsg ("first message id %d", ntohs (mp->first_msg_id));
684     }
685 }
686
687 static void vl_api_get_first_msg_id_reply_t_handler_json
688   (vl_api_get_first_msg_id_reply_t * mp)
689 {
690   vat_main_t *vam = &vat_main;
691   vat_json_node_t node;
692
693   vat_json_init_object (&node);
694   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
695   vat_json_object_add_uint (&node, "first_msg_id",
696                             (uint) ntohs (mp->first_msg_id));
697
698   vat_json_print (vam->ofp, &node);
699   vat_json_free (&node);
700
701   vam->retval = ntohl (mp->retval);
702   vam->result_ready = 1;
703 }
704
705 /* Format hex dump. */
706 u8 *
707 format_hex_bytes (u8 * s, va_list * va)
708 {
709   u8 *bytes = va_arg (*va, u8 *);
710   int n_bytes = va_arg (*va, int);
711   uword i;
712
713   /* Print short or long form depending on byte count. */
714   uword short_form = n_bytes <= 32;
715   u32 indent = format_get_indent (s);
716
717   if (n_bytes == 0)
718     return s;
719
720   for (i = 0; i < n_bytes; i++)
721     {
722       if (!short_form && (i % 32) == 0)
723         s = format (s, "%08x: ", i);
724       s = format (s, "%02x", bytes[i]);
725       if (!short_form && ((i + 1) % 32) == 0 && (i + 1) < n_bytes)
726         s = format (s, "\n%U", format_white_space, indent);
727     }
728
729   return s;
730 }
731
732 /*
733  * Generate boilerplate reply handlers, which
734  * dig the return value out of the xxx_reply_t API message,
735  * stick it into vam->retval, and set vam->result_ready
736  *
737  * Could also do this by pointing N message decode slots at
738  * a single function, but that could break in subtle ways.
739  */
740
741 #define foreach_standard_reply_retval_handler
742
743 #define _(n)                                    \
744     static void vl_api_##n##_t_handler          \
745     (vl_api_##n##_t * mp)                       \
746     {                                           \
747         vat_main_t * vam = &vat_main;           \
748         i32 retval = ntohl(mp->retval);         \
749         if (vam->async_mode) {                  \
750             vam->async_errors += (retval < 0);  \
751         } else {                                \
752             vam->retval = retval;               \
753             vam->result_ready = 1;              \
754         }                                       \
755     }
756 foreach_standard_reply_retval_handler;
757 #undef _
758
759 #define _(n)                                    \
760     static void vl_api_##n##_t_handler_json     \
761     (vl_api_##n##_t * mp)                       \
762     {                                           \
763         vat_main_t * vam = &vat_main;           \
764         vat_json_node_t node;                   \
765         vat_json_init_object(&node);            \
766         vat_json_object_add_int(&node, "retval", ntohl(mp->retval));    \
767         vat_json_print(vam->ofp, &node);        \
768         vam->retval = ntohl(mp->retval);        \
769         vam->result_ready = 1;                  \
770     }
771 foreach_standard_reply_retval_handler;
772 #undef _
773
774 /*
775  * Table of message reply handlers, must include boilerplate handlers
776  * we just generated
777  */
778
779 #define foreach_vpe_api_reply_msg                                             \
780   _ (GET_FIRST_MSG_ID_REPLY, get_first_msg_id_reply)                          \
781   _ (CONTROL_PING_REPLY, control_ping_reply)                                  \
782   _ (SHOW_VERSION_REPLY, show_version_reply)                                  \
783
784 #define foreach_standalone_reply_msg                                    \
785
786 typedef struct
787 {
788   u8 *name;
789   u32 value;
790 } name_sort_t;
791
792 #define STR_VTR_OP_CASE(op)     \
793     case L2_VTR_ ## op:         \
794         return "" # op;
795
796 int
797 api_sw_interface_dump (vat_main_t *vam)
798 {
799   return 0;
800 }
801
802 uword
803 unformat_vlib_pci_addr (unformat_input_t *input, va_list *args)
804 {
805   vlib_pci_addr_t *addr = va_arg (*args, vlib_pci_addr_t *);
806   u32 x[4];
807
808   if (!unformat (input, "%x:%x:%x.%x", &x[0], &x[1], &x[2], &x[3]))
809     return 0;
810
811   addr->domain = x[0];
812   addr->bus = x[1];
813   addr->slot = x[2];
814   addr->function = x[3];
815
816   return 1;
817 }
818
819 uword
820 unformat_fib_path (unformat_input_t *input, va_list *args)
821 {
822   vat_main_t *vam = va_arg (*args, vat_main_t *);
823   vl_api_fib_path_t *path = va_arg (*args, vl_api_fib_path_t *);
824   u32 weight, preference;
825   mpls_label_t out_label;
826
827   clib_memset (path, 0, sizeof (*path));
828   path->weight = 1;
829   path->sw_if_index = ~0;
830   path->rpf_id = ~0;
831   path->n_labels = 0;
832
833   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
834     {
835       if (unformat (input, "%U %U", unformat_vl_api_ip4_address,
836                     &path->nh.address.ip4, api_unformat_sw_if_index, vam,
837                     &path->sw_if_index))
838         {
839           path->proto = FIB_API_PATH_NH_PROTO_IP4;
840         }
841       else if (unformat (input, "%U %U",
842                          unformat_vl_api_ip6_address,
843                          &path->nh.address.ip6,
844                          api_unformat_sw_if_index, vam, &path->sw_if_index))
845         {
846           path->proto = FIB_API_PATH_NH_PROTO_IP6;
847         }
848       else if (unformat (input, "weight %u", &weight))
849         {
850           path->weight = weight;
851         }
852       else if (unformat (input, "preference %u", &preference))
853         {
854           path->preference = preference;
855         }
856       else if (unformat (input, "%U next-hop-table %d",
857                          unformat_vl_api_ip4_address,
858                          &path->nh.address.ip4, &path->table_id))
859         {
860           path->proto = FIB_API_PATH_NH_PROTO_IP4;
861         }
862       else if (unformat (input, "%U next-hop-table %d",
863                          unformat_vl_api_ip6_address,
864                          &path->nh.address.ip6, &path->table_id))
865         {
866           path->proto = FIB_API_PATH_NH_PROTO_IP6;
867         }
868       else if (unformat (input, "%U",
869                          unformat_vl_api_ip4_address, &path->nh.address.ip4))
870         {
871           /*
872            * the recursive next-hops are by default in the default table
873            */
874           path->table_id = 0;
875           path->sw_if_index = ~0;
876           path->proto = FIB_API_PATH_NH_PROTO_IP4;
877         }
878       else if (unformat (input, "%U",
879                          unformat_vl_api_ip6_address, &path->nh.address.ip6))
880         {
881           /*
882            * the recursive next-hops are by default in the default table
883            */
884           path->table_id = 0;
885           path->sw_if_index = ~0;
886           path->proto = FIB_API_PATH_NH_PROTO_IP6;
887         }
888       else if (unformat (input, "resolve-via-host"))
889         {
890           path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_HOST;
891         }
892       else if (unformat (input, "resolve-via-attached"))
893         {
894           path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_ATTACHED;
895         }
896       else if (unformat (input, "ip4-lookup-in-table %d", &path->table_id))
897         {
898           path->type = FIB_API_PATH_TYPE_LOCAL;
899           path->sw_if_index = ~0;
900           path->proto = FIB_API_PATH_NH_PROTO_IP4;
901         }
902       else if (unformat (input, "ip6-lookup-in-table %d", &path->table_id))
903         {
904           path->type = FIB_API_PATH_TYPE_LOCAL;
905           path->sw_if_index = ~0;
906           path->proto = FIB_API_PATH_NH_PROTO_IP6;
907         }
908       else if (unformat (input, "sw_if_index %d", &path->sw_if_index))
909         ;
910       else if (unformat (input, "via-label %d", &path->nh.via_label))
911         {
912           path->proto = FIB_API_PATH_NH_PROTO_MPLS;
913           path->sw_if_index = ~0;
914         }
915       else if (unformat (input, "l2-input-on %d", &path->sw_if_index))
916         {
917           path->proto = FIB_API_PATH_NH_PROTO_ETHERNET;
918           path->type = FIB_API_PATH_TYPE_INTERFACE_RX;
919         }
920       else if (unformat (input, "local"))
921         {
922           path->type = FIB_API_PATH_TYPE_LOCAL;
923         }
924       else if (unformat (input, "out-labels"))
925         {
926           while (unformat (input, "%d", &out_label))
927             {
928               path->label_stack[path->n_labels].label = out_label;
929               path->label_stack[path->n_labels].is_uniform = 0;
930               path->label_stack[path->n_labels].ttl = 64;
931               path->n_labels++;
932             }
933         }
934       else if (unformat (input, "via"))
935         {
936           /* new path, back up and return */
937           unformat_put_input (input);
938           unformat_put_input (input);
939           unformat_put_input (input);
940           unformat_put_input (input);
941           break;
942         }
943       else
944         {
945           return (0);
946         }
947     }
948
949   path->proto = ntohl (path->proto);
950   path->type = ntohl (path->type);
951   path->flags = ntohl (path->flags);
952   path->table_id = ntohl (path->table_id);
953   path->sw_if_index = ntohl (path->sw_if_index);
954
955   return (1);
956 }
957
958 #define foreach_create_subif_bit                \
959 _(no_tags)                                      \
960 _(one_tag)                                      \
961 _(two_tags)                                     \
962 _(dot1ad)                                       \
963 _(exact_match)                                  \
964 _(default_sub)                                  \
965 _(outer_vlan_id_any)                            \
966 _(inner_vlan_id_any)
967
968 #define foreach_create_subif_flag               \
969 _(0, "no_tags")                                 \
970 _(1, "one_tag")                                 \
971 _(2, "two_tags")                                \
972 _(3, "dot1ad")                                  \
973 _(4, "exact_match")                             \
974 _(5, "default_sub")                             \
975 _(6, "outer_vlan_id_any")                       \
976 _(7, "inner_vlan_id_any")
977
978
979 #define foreach_tcp_proto_field                                               \
980   _ (src_port)                                                                \
981   _ (dst_port)
982
983 #define foreach_udp_proto_field                                               \
984   _ (src_port)                                                                \
985   _ (dst_port)
986
987 #define foreach_ip4_proto_field                                               \
988   _ (src_address)                                                             \
989   _ (dst_address)                                                             \
990   _ (tos)                                                                     \
991   _ (length)                                                                  \
992   _ (fragment_id)                                                             \
993   _ (ttl)                                                                     \
994   _ (protocol)                                                                \
995   _ (checksum)
996
997 typedef struct
998 {
999   u16 src_port, dst_port;
1000 } tcpudp_header_t;
1001
1002 #if VPP_API_TEST_BUILTIN == 0
1003 uword
1004 unformat_tcp_mask (unformat_input_t *input, va_list *args)
1005 {
1006   u8 **maskp = va_arg (*args, u8 **);
1007   u8 *mask = 0;
1008   u8 found_something = 0;
1009   tcp_header_t *tcp;
1010
1011 #define _(a) u8 a = 0;
1012   foreach_tcp_proto_field;
1013 #undef _
1014
1015   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1016     {
1017       if (0)
1018         ;
1019 #define _(a) else if (unformat (input, #a)) a = 1;
1020       foreach_tcp_proto_field
1021 #undef _
1022         else break;
1023     }
1024
1025 #define _(a) found_something += a;
1026   foreach_tcp_proto_field;
1027 #undef _
1028
1029   if (found_something == 0)
1030     return 0;
1031
1032   vec_validate (mask, sizeof (*tcp) - 1);
1033
1034   tcp = (tcp_header_t *) mask;
1035
1036 #define _(a)                                                                  \
1037   if (a)                                                                      \
1038     clib_memset (&tcp->a, 0xff, sizeof (tcp->a));
1039   foreach_tcp_proto_field;
1040 #undef _
1041
1042   *maskp = mask;
1043   return 1;
1044 }
1045
1046 uword
1047 unformat_udp_mask (unformat_input_t *input, va_list *args)
1048 {
1049   u8 **maskp = va_arg (*args, u8 **);
1050   u8 *mask = 0;
1051   u8 found_something = 0;
1052   udp_header_t *udp;
1053
1054 #define _(a) u8 a = 0;
1055   foreach_udp_proto_field;
1056 #undef _
1057
1058   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1059     {
1060       if (0)
1061         ;
1062 #define _(a) else if (unformat (input, #a)) a = 1;
1063       foreach_udp_proto_field
1064 #undef _
1065         else break;
1066     }
1067
1068 #define _(a) found_something += a;
1069   foreach_udp_proto_field;
1070 #undef _
1071
1072   if (found_something == 0)
1073     return 0;
1074
1075   vec_validate (mask, sizeof (*udp) - 1);
1076
1077   udp = (udp_header_t *) mask;
1078
1079 #define _(a)                                                                  \
1080   if (a)                                                                      \
1081     clib_memset (&udp->a, 0xff, sizeof (udp->a));
1082   foreach_udp_proto_field;
1083 #undef _
1084
1085   *maskp = mask;
1086   return 1;
1087 }
1088
1089 uword
1090 unformat_l4_mask (unformat_input_t *input, va_list *args)
1091 {
1092   u8 **maskp = va_arg (*args, u8 **);
1093   u16 src_port = 0, dst_port = 0;
1094   tcpudp_header_t *tcpudp;
1095
1096   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1097     {
1098       if (unformat (input, "tcp %U", unformat_tcp_mask, maskp))
1099         return 1;
1100       else if (unformat (input, "udp %U", unformat_udp_mask, maskp))
1101         return 1;
1102       else if (unformat (input, "src_port"))
1103         src_port = 0xFFFF;
1104       else if (unformat (input, "dst_port"))
1105         dst_port = 0xFFFF;
1106       else
1107         return 0;
1108     }
1109
1110   if (!src_port && !dst_port)
1111     return 0;
1112
1113   u8 *mask = 0;
1114   vec_validate (mask, sizeof (tcpudp_header_t) - 1);
1115
1116   tcpudp = (tcpudp_header_t *) mask;
1117   tcpudp->src_port = src_port;
1118   tcpudp->dst_port = dst_port;
1119
1120   *maskp = mask;
1121
1122   return 1;
1123 }
1124
1125 uword
1126 unformat_ip4_mask (unformat_input_t * input, va_list * args)
1127 {
1128   u8 **maskp = va_arg (*args, u8 **);
1129   u8 *mask = 0;
1130   u8 found_something = 0;
1131   ip4_header_t *ip;
1132
1133 #define _(a) u8 a=0;
1134   foreach_ip4_proto_field;
1135 #undef _
1136   u8 version = 0;
1137   u8 hdr_length = 0;
1138
1139
1140   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1141     {
1142       if (unformat (input, "version"))
1143         version = 1;
1144       else if (unformat (input, "hdr_length"))
1145         hdr_length = 1;
1146       else if (unformat (input, "src"))
1147         src_address = 1;
1148       else if (unformat (input, "dst"))
1149         dst_address = 1;
1150       else if (unformat (input, "proto"))
1151         protocol = 1;
1152
1153 #define _(a) else if (unformat (input, #a)) a=1;
1154       foreach_ip4_proto_field
1155 #undef _
1156         else
1157         break;
1158     }
1159
1160 #define _(a) found_something += a;
1161   foreach_ip4_proto_field;
1162 #undef _
1163
1164   if (found_something == 0)
1165     return 0;
1166
1167   vec_validate (mask, sizeof (*ip) - 1);
1168
1169   ip = (ip4_header_t *) mask;
1170
1171 #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
1172   foreach_ip4_proto_field;
1173 #undef _
1174
1175   ip->ip_version_and_header_length = 0;
1176
1177   if (version)
1178     ip->ip_version_and_header_length |= 0xF0;
1179
1180   if (hdr_length)
1181     ip->ip_version_and_header_length |= 0x0F;
1182
1183   *maskp = mask;
1184   return 1;
1185 }
1186
1187 #define foreach_ip6_proto_field                 \
1188 _(src_address)                                  \
1189 _(dst_address)                                  \
1190 _(payload_length)                               \
1191 _(hop_limit)                                    \
1192 _(protocol)
1193
1194 uword
1195 unformat_ip6_mask (unformat_input_t * input, va_list * args)
1196 {
1197   u8 **maskp = va_arg (*args, u8 **);
1198   u8 *mask = 0;
1199   u8 found_something = 0;
1200   ip6_header_t *ip;
1201   u32 ip_version_traffic_class_and_flow_label;
1202
1203 #define _(a) u8 a=0;
1204   foreach_ip6_proto_field;
1205 #undef _
1206   u8 version = 0;
1207   u8 traffic_class = 0;
1208   u8 flow_label = 0;
1209
1210   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1211     {
1212       if (unformat (input, "version"))
1213         version = 1;
1214       else if (unformat (input, "traffic-class"))
1215         traffic_class = 1;
1216       else if (unformat (input, "flow-label"))
1217         flow_label = 1;
1218       else if (unformat (input, "src"))
1219         src_address = 1;
1220       else if (unformat (input, "dst"))
1221         dst_address = 1;
1222       else if (unformat (input, "proto"))
1223         protocol = 1;
1224
1225 #define _(a) else if (unformat (input, #a)) a=1;
1226       foreach_ip6_proto_field
1227 #undef _
1228         else
1229         break;
1230     }
1231
1232 #define _(a) found_something += a;
1233   foreach_ip6_proto_field;
1234 #undef _
1235
1236   if (found_something == 0)
1237     return 0;
1238
1239   vec_validate (mask, sizeof (*ip) - 1);
1240
1241   ip = (ip6_header_t *) mask;
1242
1243 #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
1244   foreach_ip6_proto_field;
1245 #undef _
1246
1247   ip_version_traffic_class_and_flow_label = 0;
1248
1249   if (version)
1250     ip_version_traffic_class_and_flow_label |= 0xF0000000;
1251
1252   if (traffic_class)
1253     ip_version_traffic_class_and_flow_label |= 0x0FF00000;
1254
1255   if (flow_label)
1256     ip_version_traffic_class_and_flow_label |= 0x000FFFFF;
1257
1258   ip->ip_version_traffic_class_and_flow_label =
1259     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
1260
1261   *maskp = mask;
1262   return 1;
1263 }
1264
1265 uword
1266 unformat_l3_mask (unformat_input_t * input, va_list * args)
1267 {
1268   u8 **maskp = va_arg (*args, u8 **);
1269
1270   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1271     {
1272       if (unformat (input, "ip4 %U", unformat_ip4_mask, maskp))
1273         return 1;
1274       else if (unformat (input, "ip6 %U", unformat_ip6_mask, maskp))
1275         return 1;
1276       else
1277         break;
1278     }
1279   return 0;
1280 }
1281
1282 uword
1283 unformat_l2_mask (unformat_input_t * input, va_list * args)
1284 {
1285   u8 **maskp = va_arg (*args, u8 **);
1286   u8 *mask = 0;
1287   u8 src = 0;
1288   u8 dst = 0;
1289   u8 proto = 0;
1290   u8 tag1 = 0;
1291   u8 tag2 = 0;
1292   u8 ignore_tag1 = 0;
1293   u8 ignore_tag2 = 0;
1294   u8 cos1 = 0;
1295   u8 cos2 = 0;
1296   u8 dot1q = 0;
1297   u8 dot1ad = 0;
1298   int len = 14;
1299
1300   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1301     {
1302       if (unformat (input, "src"))
1303         src = 1;
1304       else if (unformat (input, "dst"))
1305         dst = 1;
1306       else if (unformat (input, "proto"))
1307         proto = 1;
1308       else if (unformat (input, "tag1"))
1309         tag1 = 1;
1310       else if (unformat (input, "tag2"))
1311         tag2 = 1;
1312       else if (unformat (input, "ignore-tag1"))
1313         ignore_tag1 = 1;
1314       else if (unformat (input, "ignore-tag2"))
1315         ignore_tag2 = 1;
1316       else if (unformat (input, "cos1"))
1317         cos1 = 1;
1318       else if (unformat (input, "cos2"))
1319         cos2 = 1;
1320       else if (unformat (input, "dot1q"))
1321         dot1q = 1;
1322       else if (unformat (input, "dot1ad"))
1323         dot1ad = 1;
1324       else
1325         break;
1326     }
1327   if ((src + dst + proto + tag1 + tag2 + dot1q + dot1ad +
1328        ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
1329     return 0;
1330
1331   if (tag1 || ignore_tag1 || cos1 || dot1q)
1332     len = 18;
1333   if (tag2 || ignore_tag2 || cos2 || dot1ad)
1334     len = 22;
1335
1336   vec_validate (mask, len - 1);
1337
1338   if (dst)
1339     clib_memset (mask, 0xff, 6);
1340
1341   if (src)
1342     clib_memset (mask + 6, 0xff, 6);
1343
1344   if (tag2 || dot1ad)
1345     {
1346       /* inner vlan tag */
1347       if (tag2)
1348         {
1349           mask[19] = 0xff;
1350           mask[18] = 0x0f;
1351         }
1352       if (cos2)
1353         mask[18] |= 0xe0;
1354       if (proto)
1355         mask[21] = mask[20] = 0xff;
1356       if (tag1)
1357         {
1358           mask[15] = 0xff;
1359           mask[14] = 0x0f;
1360         }
1361       if (cos1)
1362         mask[14] |= 0xe0;
1363       *maskp = mask;
1364       return 1;
1365     }
1366   if (tag1 | dot1q)
1367     {
1368       if (tag1)
1369         {
1370           mask[15] = 0xff;
1371           mask[14] = 0x0f;
1372         }
1373       if (cos1)
1374         mask[14] |= 0xe0;
1375       if (proto)
1376         mask[16] = mask[17] = 0xff;
1377
1378       *maskp = mask;
1379       return 1;
1380     }
1381   if (cos2)
1382     mask[18] |= 0xe0;
1383   if (cos1)
1384     mask[14] |= 0xe0;
1385   if (proto)
1386     mask[12] = mask[13] = 0xff;
1387
1388   *maskp = mask;
1389   return 1;
1390 }
1391
1392 uword
1393 unformat_classify_mask (unformat_input_t * input, va_list * args)
1394 {
1395   u8 **maskp = va_arg (*args, u8 **);
1396   u32 *skipp = va_arg (*args, u32 *);
1397   u32 *matchp = va_arg (*args, u32 *);
1398   u32 match;
1399   u8 *mask = 0;
1400   u8 *l2 = 0;
1401   u8 *l3 = 0;
1402   u8 *l4 = 0;
1403   int i;
1404
1405   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1406     {
1407       if (unformat (input, "hex %U", unformat_hex_string, &mask))
1408         ;
1409       else if (unformat (input, "l2 %U", unformat_l2_mask, &l2))
1410         ;
1411       else if (unformat (input, "l3 %U", unformat_l3_mask, &l3))
1412         ;
1413       else if (unformat (input, "l4 %U", unformat_l4_mask, &l4))
1414         ;
1415       else
1416         break;
1417     }
1418
1419   if (l4 && !l3)
1420     {
1421       vec_free (mask);
1422       vec_free (l2);
1423       vec_free (l4);
1424       return 0;
1425     }
1426
1427   if (mask || l2 || l3 || l4)
1428     {
1429       if (l2 || l3 || l4)
1430         {
1431           /* "With a free Ethernet header in every package" */
1432           if (l2 == 0)
1433             vec_validate (l2, 13);
1434           mask = l2;
1435           if (vec_len (l3))
1436             {
1437               vec_append (mask, l3);
1438               vec_free (l3);
1439             }
1440           if (vec_len (l4))
1441             {
1442               vec_append (mask, l4);
1443               vec_free (l4);
1444             }
1445         }
1446
1447       /* Scan forward looking for the first significant mask octet */
1448       for (i = 0; i < vec_len (mask); i++)
1449         if (mask[i])
1450           break;
1451
1452       /* compute (skip, match) params */
1453       *skipp = i / sizeof (u32x4);
1454       vec_delete (mask, *skipp * sizeof (u32x4), 0);
1455
1456       /* Pad mask to an even multiple of the vector size */
1457       while (vec_len (mask) % sizeof (u32x4))
1458         vec_add1 (mask, 0);
1459
1460       match = vec_len (mask) / sizeof (u32x4);
1461
1462       for (i = match * sizeof (u32x4); i > 0; i -= sizeof (u32x4))
1463         {
1464           u64 *tmp = (u64 *) (mask + (i - sizeof (u32x4)));
1465           if (*tmp || *(tmp + 1))
1466             break;
1467           match--;
1468         }
1469       if (match == 0)
1470         clib_warning ("BUG: match 0");
1471
1472       _vec_len (mask) = match * sizeof (u32x4);
1473
1474       *matchp = match;
1475       *maskp = mask;
1476
1477       return 1;
1478     }
1479
1480   return 0;
1481 }
1482 #endif /* VPP_API_TEST_BUILTIN */
1483
1484 #define foreach_l2_next                         \
1485 _(drop, DROP)                                   \
1486 _(ethernet, ETHERNET_INPUT)                     \
1487 _(ip4, IP4_INPUT)                               \
1488 _(ip6, IP6_INPUT)
1489
1490 uword
1491 unformat_l2_next_index (unformat_input_t * input, va_list * args)
1492 {
1493   u32 *miss_next_indexp = va_arg (*args, u32 *);
1494   u32 next_index = 0;
1495   u32 tmp;
1496
1497 #define _(n,N) \
1498   if (unformat (input, #n)) { next_index = L2_INPUT_CLASSIFY_NEXT_##N; goto out;}
1499   foreach_l2_next;
1500 #undef _
1501
1502   if (unformat (input, "%d", &tmp))
1503     {
1504       next_index = tmp;
1505       goto out;
1506     }
1507
1508   return 0;
1509
1510 out:
1511   *miss_next_indexp = next_index;
1512   return 1;
1513 }
1514
1515 #define foreach_ip_next                         \
1516 _(drop, DROP)                                   \
1517 _(local, LOCAL)                                 \
1518 _(rewrite, REWRITE)
1519
1520 uword
1521 api_unformat_ip_next_index (unformat_input_t * input, va_list * args)
1522 {
1523   u32 *miss_next_indexp = va_arg (*args, u32 *);
1524   u32 next_index = 0;
1525   u32 tmp;
1526
1527 #define _(n,N) \
1528   if (unformat (input, #n)) { next_index = IP_LOOKUP_NEXT_##N; goto out;}
1529   foreach_ip_next;
1530 #undef _
1531
1532   if (unformat (input, "%d", &tmp))
1533     {
1534       next_index = tmp;
1535       goto out;
1536     }
1537
1538   return 0;
1539
1540 out:
1541   *miss_next_indexp = next_index;
1542   return 1;
1543 }
1544
1545 #define foreach_acl_next                        \
1546 _(deny, DENY)
1547
1548 uword
1549 api_unformat_acl_next_index (unformat_input_t * input, va_list * args)
1550 {
1551   u32 *miss_next_indexp = va_arg (*args, u32 *);
1552   u32 next_index = 0;
1553   u32 tmp;
1554
1555 #define _(n,N) \
1556   if (unformat (input, #n)) { next_index = ACL_NEXT_INDEX_##N; goto out;}
1557   foreach_acl_next;
1558 #undef _
1559
1560   if (unformat (input, "permit"))
1561     {
1562       next_index = ~0;
1563       goto out;
1564     }
1565   else if (unformat (input, "%d", &tmp))
1566     {
1567       next_index = tmp;
1568       goto out;
1569     }
1570
1571   return 0;
1572
1573 out:
1574   *miss_next_indexp = next_index;
1575   return 1;
1576 }
1577
1578 uword
1579 unformat_policer_precolor (unformat_input_t * input, va_list * args)
1580 {
1581   u32 *r = va_arg (*args, u32 *);
1582
1583   if (unformat (input, "conform-color"))
1584     *r = POLICE_CONFORM;
1585   else if (unformat (input, "exceed-color"))
1586     *r = POLICE_EXCEED;
1587   else
1588     return 0;
1589
1590   return 1;
1591 }
1592
1593 #if VPP_API_TEST_BUILTIN == 0
1594 uword
1595 unformat_l4_match (unformat_input_t * input, va_list * args)
1596 {
1597   u8 **matchp = va_arg (*args, u8 **);
1598
1599   u8 *proto_header = 0;
1600   int src_port = 0;
1601   int dst_port = 0;
1602
1603   tcpudp_header_t h;
1604
1605   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1606     {
1607       if (unformat (input, "src_port %d", &src_port))
1608         ;
1609       else if (unformat (input, "dst_port %d", &dst_port))
1610         ;
1611       else
1612         return 0;
1613     }
1614
1615   h.src_port = clib_host_to_net_u16 (src_port);
1616   h.dst_port = clib_host_to_net_u16 (dst_port);
1617   vec_validate (proto_header, sizeof (h) - 1);
1618   memcpy (proto_header, &h, sizeof (h));
1619
1620   *matchp = proto_header;
1621
1622   return 1;
1623 }
1624
1625 uword
1626 unformat_ip4_match (unformat_input_t * input, va_list * args)
1627 {
1628   u8 **matchp = va_arg (*args, u8 **);
1629   u8 *match = 0;
1630   ip4_header_t *ip;
1631   int version = 0;
1632   u32 version_val;
1633   int hdr_length = 0;
1634   u32 hdr_length_val;
1635   int src = 0, dst = 0;
1636   ip4_address_t src_val, dst_val;
1637   int proto = 0;
1638   u32 proto_val;
1639   int tos = 0;
1640   u32 tos_val;
1641   int length = 0;
1642   u32 length_val;
1643   int fragment_id = 0;
1644   u32 fragment_id_val;
1645   int ttl = 0;
1646   int ttl_val;
1647   int checksum = 0;
1648   u32 checksum_val;
1649
1650   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1651     {
1652       if (unformat (input, "version %d", &version_val))
1653         version = 1;
1654       else if (unformat (input, "hdr_length %d", &hdr_length_val))
1655         hdr_length = 1;
1656       else if (unformat (input, "src %U", unformat_ip4_address, &src_val))
1657         src = 1;
1658       else if (unformat (input, "dst %U", unformat_ip4_address, &dst_val))
1659         dst = 1;
1660       else if (unformat (input, "proto %d", &proto_val))
1661         proto = 1;
1662       else if (unformat (input, "tos %d", &tos_val))
1663         tos = 1;
1664       else if (unformat (input, "length %d", &length_val))
1665         length = 1;
1666       else if (unformat (input, "fragment_id %d", &fragment_id_val))
1667         fragment_id = 1;
1668       else if (unformat (input, "ttl %d", &ttl_val))
1669         ttl = 1;
1670       else if (unformat (input, "checksum %d", &checksum_val))
1671         checksum = 1;
1672       else
1673         break;
1674     }
1675
1676   if (version + hdr_length + src + dst + proto + tos + length + fragment_id
1677       + ttl + checksum == 0)
1678     return 0;
1679
1680   /*
1681    * Aligned because we use the real comparison functions
1682    */
1683   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
1684
1685   ip = (ip4_header_t *) match;
1686
1687   /* These are realistically matched in practice */
1688   if (src)
1689     ip->src_address.as_u32 = src_val.as_u32;
1690
1691   if (dst)
1692     ip->dst_address.as_u32 = dst_val.as_u32;
1693
1694   if (proto)
1695     ip->protocol = proto_val;
1696
1697
1698   /* These are not, but they're included for completeness */
1699   if (version)
1700     ip->ip_version_and_header_length |= (version_val & 0xF) << 4;
1701
1702   if (hdr_length)
1703     ip->ip_version_and_header_length |= (hdr_length_val & 0xF);
1704
1705   if (tos)
1706     ip->tos = tos_val;
1707
1708   if (length)
1709     ip->length = clib_host_to_net_u16 (length_val);
1710
1711   if (ttl)
1712     ip->ttl = ttl_val;
1713
1714   if (checksum)
1715     ip->checksum = clib_host_to_net_u16 (checksum_val);
1716
1717   *matchp = match;
1718   return 1;
1719 }
1720
1721 uword
1722 unformat_ip6_match (unformat_input_t * input, va_list * args)
1723 {
1724   u8 **matchp = va_arg (*args, u8 **);
1725   u8 *match = 0;
1726   ip6_header_t *ip;
1727   int version = 0;
1728   u32 version_val;
1729   u8 traffic_class = 0;
1730   u32 traffic_class_val = 0;
1731   u8 flow_label = 0;
1732   u8 flow_label_val;
1733   int src = 0, dst = 0;
1734   ip6_address_t src_val, dst_val;
1735   int proto = 0;
1736   u32 proto_val;
1737   int payload_length = 0;
1738   u32 payload_length_val;
1739   int hop_limit = 0;
1740   int hop_limit_val;
1741   u32 ip_version_traffic_class_and_flow_label;
1742
1743   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1744     {
1745       if (unformat (input, "version %d", &version_val))
1746         version = 1;
1747       else if (unformat (input, "traffic_class %d", &traffic_class_val))
1748         traffic_class = 1;
1749       else if (unformat (input, "flow_label %d", &flow_label_val))
1750         flow_label = 1;
1751       else if (unformat (input, "src %U", unformat_ip6_address, &src_val))
1752         src = 1;
1753       else if (unformat (input, "dst %U", unformat_ip6_address, &dst_val))
1754         dst = 1;
1755       else if (unformat (input, "proto %d", &proto_val))
1756         proto = 1;
1757       else if (unformat (input, "payload_length %d", &payload_length_val))
1758         payload_length = 1;
1759       else if (unformat (input, "hop_limit %d", &hop_limit_val))
1760         hop_limit = 1;
1761       else
1762         break;
1763     }
1764
1765   if (version + traffic_class + flow_label + src + dst + proto +
1766       payload_length + hop_limit == 0)
1767     return 0;
1768
1769   /*
1770    * Aligned because we use the real comparison functions
1771    */
1772   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
1773
1774   ip = (ip6_header_t *) match;
1775
1776   if (src)
1777     clib_memcpy (&ip->src_address, &src_val, sizeof (ip->src_address));
1778
1779   if (dst)
1780     clib_memcpy (&ip->dst_address, &dst_val, sizeof (ip->dst_address));
1781
1782   if (proto)
1783     ip->protocol = proto_val;
1784
1785   ip_version_traffic_class_and_flow_label = 0;
1786
1787   if (version)
1788     ip_version_traffic_class_and_flow_label |= (version_val & 0xF) << 28;
1789
1790   if (traffic_class)
1791     ip_version_traffic_class_and_flow_label |=
1792       (traffic_class_val & 0xFF) << 20;
1793
1794   if (flow_label)
1795     ip_version_traffic_class_and_flow_label |= (flow_label_val & 0xFFFFF);
1796
1797   ip->ip_version_traffic_class_and_flow_label =
1798     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
1799
1800   if (payload_length)
1801     ip->payload_length = clib_host_to_net_u16 (payload_length_val);
1802
1803   if (hop_limit)
1804     ip->hop_limit = hop_limit_val;
1805
1806   *matchp = match;
1807   return 1;
1808 }
1809
1810 uword
1811 unformat_l3_match (unformat_input_t * input, va_list * args)
1812 {
1813   u8 **matchp = va_arg (*args, u8 **);
1814
1815   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1816     {
1817       if (unformat (input, "ip4 %U", unformat_ip4_match, matchp))
1818         return 1;
1819       else if (unformat (input, "ip6 %U", unformat_ip6_match, matchp))
1820         return 1;
1821       else
1822         break;
1823     }
1824   return 0;
1825 }
1826
1827 uword
1828 unformat_vlan_tag (unformat_input_t * input, va_list * args)
1829 {
1830   u8 *tagp = va_arg (*args, u8 *);
1831   u32 tag;
1832
1833   if (unformat (input, "%d", &tag))
1834     {
1835       tagp[0] = (tag >> 8) & 0x0F;
1836       tagp[1] = tag & 0xFF;
1837       return 1;
1838     }
1839
1840   return 0;
1841 }
1842
1843 uword
1844 unformat_l2_match (unformat_input_t * input, va_list * args)
1845 {
1846   u8 **matchp = va_arg (*args, u8 **);
1847   u8 *match = 0;
1848   u8 src = 0;
1849   u8 src_val[6];
1850   u8 dst = 0;
1851   u8 dst_val[6];
1852   u8 proto = 0;
1853   u16 proto_val;
1854   u8 tag1 = 0;
1855   u8 tag1_val[2];
1856   u8 tag2 = 0;
1857   u8 tag2_val[2];
1858   int len = 14;
1859   u8 ignore_tag1 = 0;
1860   u8 ignore_tag2 = 0;
1861   u8 cos1 = 0;
1862   u8 cos2 = 0;
1863   u32 cos1_val = 0;
1864   u32 cos2_val = 0;
1865
1866   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1867     {
1868       if (unformat (input, "src %U", unformat_ethernet_address, &src_val))
1869         src = 1;
1870       else
1871         if (unformat (input, "dst %U", unformat_ethernet_address, &dst_val))
1872         dst = 1;
1873       else if (unformat (input, "proto %U",
1874                          unformat_ethernet_type_host_byte_order, &proto_val))
1875         proto = 1;
1876       else if (unformat (input, "tag1 %U", unformat_vlan_tag, tag1_val))
1877         tag1 = 1;
1878       else if (unformat (input, "tag2 %U", unformat_vlan_tag, tag2_val))
1879         tag2 = 1;
1880       else if (unformat (input, "ignore-tag1"))
1881         ignore_tag1 = 1;
1882       else if (unformat (input, "ignore-tag2"))
1883         ignore_tag2 = 1;
1884       else if (unformat (input, "cos1 %d", &cos1_val))
1885         cos1 = 1;
1886       else if (unformat (input, "cos2 %d", &cos2_val))
1887         cos2 = 1;
1888       else
1889         break;
1890     }
1891   if ((src + dst + proto + tag1 + tag2 +
1892        ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
1893     return 0;
1894
1895   if (tag1 || ignore_tag1 || cos1)
1896     len = 18;
1897   if (tag2 || ignore_tag2 || cos2)
1898     len = 22;
1899
1900   vec_validate_aligned (match, len - 1, sizeof (u32x4));
1901
1902   if (dst)
1903     clib_memcpy (match, dst_val, 6);
1904
1905   if (src)
1906     clib_memcpy (match + 6, src_val, 6);
1907
1908   if (tag2)
1909     {
1910       /* inner vlan tag */
1911       match[19] = tag2_val[1];
1912       match[18] = tag2_val[0];
1913       if (cos2)
1914         match[18] |= (cos2_val & 0x7) << 5;
1915       if (proto)
1916         {
1917           match[21] = proto_val & 0xff;
1918           match[20] = proto_val >> 8;
1919         }
1920       if (tag1)
1921         {
1922           match[15] = tag1_val[1];
1923           match[14] = tag1_val[0];
1924         }
1925       if (cos1)
1926         match[14] |= (cos1_val & 0x7) << 5;
1927       *matchp = match;
1928       return 1;
1929     }
1930   if (tag1)
1931     {
1932       match[15] = tag1_val[1];
1933       match[14] = tag1_val[0];
1934       if (proto)
1935         {
1936           match[17] = proto_val & 0xff;
1937           match[16] = proto_val >> 8;
1938         }
1939       if (cos1)
1940         match[14] |= (cos1_val & 0x7) << 5;
1941
1942       *matchp = match;
1943       return 1;
1944     }
1945   if (cos2)
1946     match[18] |= (cos2_val & 0x7) << 5;
1947   if (cos1)
1948     match[14] |= (cos1_val & 0x7) << 5;
1949   if (proto)
1950     {
1951       match[13] = proto_val & 0xff;
1952       match[12] = proto_val >> 8;
1953     }
1954
1955   *matchp = match;
1956   return 1;
1957 }
1958
1959 uword
1960 unformat_qos_source (unformat_input_t * input, va_list * args)
1961 {
1962   int *qs = va_arg (*args, int *);
1963
1964   if (unformat (input, "ip"))
1965     *qs = QOS_SOURCE_IP;
1966   else if (unformat (input, "mpls"))
1967     *qs = QOS_SOURCE_MPLS;
1968   else if (unformat (input, "ext"))
1969     *qs = QOS_SOURCE_EXT;
1970   else if (unformat (input, "vlan"))
1971     *qs = QOS_SOURCE_VLAN;
1972   else
1973     return 0;
1974
1975   return 1;
1976 }
1977 #endif
1978
1979 uword
1980 api_unformat_classify_match (unformat_input_t * input, va_list * args)
1981 {
1982   u8 **matchp = va_arg (*args, u8 **);
1983   u32 skip_n_vectors = va_arg (*args, u32);
1984   u32 match_n_vectors = va_arg (*args, u32);
1985
1986   u8 *match = 0;
1987   u8 *l2 = 0;
1988   u8 *l3 = 0;
1989   u8 *l4 = 0;
1990
1991   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1992     {
1993       if (unformat (input, "hex %U", unformat_hex_string, &match))
1994         ;
1995       else if (unformat (input, "l2 %U", unformat_l2_match, &l2))
1996         ;
1997       else if (unformat (input, "l3 %U", unformat_l3_match, &l3))
1998         ;
1999       else if (unformat (input, "l4 %U", unformat_l4_match, &l4))
2000         ;
2001       else
2002         break;
2003     }
2004
2005   if (l4 && !l3)
2006     {
2007       vec_free (match);
2008       vec_free (l2);
2009       vec_free (l4);
2010       return 0;
2011     }
2012
2013   if (match || l2 || l3 || l4)
2014     {
2015       if (l2 || l3 || l4)
2016         {
2017           /* "Win a free Ethernet header in every packet" */
2018           if (l2 == 0)
2019             vec_validate_aligned (l2, 13, sizeof (u32x4));
2020           match = l2;
2021           if (vec_len (l3))
2022             {
2023               vec_append_aligned (match, l3, sizeof (u32x4));
2024               vec_free (l3);
2025             }
2026           if (vec_len (l4))
2027             {
2028               vec_append_aligned (match, l4, sizeof (u32x4));
2029               vec_free (l4);
2030             }
2031         }
2032
2033       /* Make sure the vector is big enough even if key is all 0's */
2034       vec_validate_aligned
2035         (match, ((match_n_vectors + skip_n_vectors) * sizeof (u32x4)) - 1,
2036          sizeof (u32x4));
2037
2038       /* Set size, include skipped vectors */
2039       _vec_len (match) = (match_n_vectors + skip_n_vectors) * sizeof (u32x4);
2040
2041       *matchp = match;
2042
2043       return 1;
2044     }
2045
2046   return 0;
2047 }
2048
2049 #define foreach_vtr_op                                                        \
2050   _ ("disable", L2_VTR_DISABLED)                                              \
2051   _ ("push-1", L2_VTR_PUSH_1)                                                 \
2052   _ ("push-2", L2_VTR_PUSH_2)                                                 \
2053   _ ("pop-1", L2_VTR_POP_1)                                                   \
2054   _ ("pop-2", L2_VTR_POP_2)                                                   \
2055   _ ("translate-1-1", L2_VTR_TRANSLATE_1_1)                                   \
2056   _ ("translate-1-2", L2_VTR_TRANSLATE_1_2)                                   \
2057   _ ("translate-2-1", L2_VTR_TRANSLATE_2_1)                                   \
2058   _ ("translate-2-2", L2_VTR_TRANSLATE_2_2)
2059
2060 static int
2061 api_show_version (vat_main_t *vam)
2062 {
2063   vl_api_show_version_t *mp;
2064   int ret;
2065
2066   M (SHOW_VERSION, mp);
2067
2068   S (mp);
2069   W (ret);
2070   return ret;
2071 }
2072
2073 static int
2074 api_get_first_msg_id (vat_main_t *vam)
2075 {
2076   vl_api_get_first_msg_id_t *mp;
2077   unformat_input_t *i = vam->input;
2078   u8 *name;
2079   u8 name_set = 0;
2080   int ret;
2081
2082   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2083     {
2084       if (unformat (i, "client %s", &name))
2085         name_set = 1;
2086       else
2087         break;
2088     }
2089
2090   if (name_set == 0)
2091     {
2092       errmsg ("missing client name");
2093       return -99;
2094     }
2095   vec_add1 (name, 0);
2096
2097   if (vec_len (name) > 63)
2098     {
2099       errmsg ("client name too long");
2100       return -99;
2101     }
2102
2103   M (GET_FIRST_MSG_ID, mp);
2104   clib_memcpy (mp->name, name, vec_len (name));
2105   S (mp);
2106   W (ret);
2107   return ret;
2108 }
2109
2110 #define foreach_pbb_vtr_op      \
2111 _("disable",  L2_VTR_DISABLED)  \
2112 _("pop",  L2_VTR_POP_2)         \
2113 _("push",  L2_VTR_PUSH_2)
2114
2115 static int
2116 api_sock_init_shm (vat_main_t * vam)
2117 {
2118 #if VPP_API_TEST_BUILTIN == 0
2119   unformat_input_t *i = vam->input;
2120   vl_api_shm_elem_config_t *config = 0;
2121   u64 size = 64 << 20;
2122   int rv;
2123
2124   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2125     {
2126       if (unformat (i, "size %U", unformat_memory_size, &size))
2127         ;
2128       else
2129         break;
2130     }
2131
2132   /*
2133    * Canned custom ring allocator config.
2134    * Should probably parse all of this
2135    */
2136   vec_validate (config, 6);
2137   config[0].type = VL_API_VLIB_RING;
2138   config[0].size = 256;
2139   config[0].count = 32;
2140
2141   config[1].type = VL_API_VLIB_RING;
2142   config[1].size = 1024;
2143   config[1].count = 16;
2144
2145   config[2].type = VL_API_VLIB_RING;
2146   config[2].size = 4096;
2147   config[2].count = 2;
2148
2149   config[3].type = VL_API_CLIENT_RING;
2150   config[3].size = 256;
2151   config[3].count = 32;
2152
2153   config[4].type = VL_API_CLIENT_RING;
2154   config[4].size = 1024;
2155   config[4].count = 16;
2156
2157   config[5].type = VL_API_CLIENT_RING;
2158   config[5].size = 4096;
2159   config[5].count = 2;
2160
2161   config[6].type = VL_API_QUEUE;
2162   config[6].count = 128;
2163   config[6].size = sizeof (uword);
2164
2165   rv = vl_socket_client_init_shm (config, 1 /* want_pthread */ );
2166   if (!rv)
2167     vam->client_index_invalid = 1;
2168   return rv;
2169 #else
2170   return -99;
2171 #endif
2172 }
2173
2174 static int
2175 q_or_quit (vat_main_t * vam)
2176 {
2177 #if VPP_API_TEST_BUILTIN == 0
2178   longjmp (vam->jump_buf, 1);
2179 #endif
2180   return 0;                     /* not so much */
2181 }
2182
2183 static int
2184 q (vat_main_t * vam)
2185 {
2186   return q_or_quit (vam);
2187 }
2188
2189 static int
2190 quit (vat_main_t * vam)
2191 {
2192   return q_or_quit (vam);
2193 }
2194
2195 static int
2196 comment (vat_main_t * vam)
2197 {
2198   return 0;
2199 }
2200
2201 static int
2202 elog_save (vat_main_t * vam)
2203 {
2204 #if VPP_API_TEST_BUILTIN == 0
2205   elog_main_t *em = &vam->elog_main;
2206   unformat_input_t *i = vam->input;
2207   char *file, *chroot_file;
2208   clib_error_t *error;
2209
2210   if (!unformat (i, "%s", &file))
2211     {
2212       errmsg ("expected file name, got `%U'", format_unformat_error, i);
2213       return 0;
2214     }
2215
2216   /* It's fairly hard to get "../oopsie" through unformat; just in case */
2217   if (strstr (file, "..") || index (file, '/'))
2218     {
2219       errmsg ("illegal characters in filename '%s'", file);
2220       return 0;
2221     }
2222
2223   chroot_file = (char *) format (0, "/tmp/%s%c", file, 0);
2224
2225   vec_free (file);
2226
2227   errmsg ("Saving %wd of %wd events to %s",
2228           elog_n_events_in_buffer (em),
2229           elog_buffer_capacity (em), chroot_file);
2230
2231   error = elog_write_file (em, chroot_file, 1 /* flush ring */ );
2232   vec_free (chroot_file);
2233
2234   if (error)
2235     clib_error_report (error);
2236 #else
2237   errmsg ("Use the vpp event loger...");
2238 #endif
2239
2240   return 0;
2241 }
2242
2243 static int
2244 elog_setup (vat_main_t * vam)
2245 {
2246 #if VPP_API_TEST_BUILTIN == 0
2247   elog_main_t *em = &vam->elog_main;
2248   unformat_input_t *i = vam->input;
2249   u32 nevents = 128 << 10;
2250
2251   (void) unformat (i, "nevents %d", &nevents);
2252
2253   elog_init (em, nevents);
2254   vl_api_set_elog_main (em);
2255   vl_api_set_elog_trace_api_messages (1);
2256   errmsg ("Event logger initialized with %u events", nevents);
2257 #else
2258   errmsg ("Use the vpp event loger...");
2259 #endif
2260   return 0;
2261 }
2262
2263 static int
2264 elog_enable (vat_main_t * vam)
2265 {
2266 #if VPP_API_TEST_BUILTIN == 0
2267   elog_main_t *em = &vam->elog_main;
2268
2269   elog_enable_disable (em, 1 /* enable */ );
2270   vl_api_set_elog_trace_api_messages (1);
2271   errmsg ("Event logger enabled...");
2272 #else
2273   errmsg ("Use the vpp event loger...");
2274 #endif
2275   return 0;
2276 }
2277
2278 static int
2279 elog_disable (vat_main_t * vam)
2280 {
2281 #if VPP_API_TEST_BUILTIN == 0
2282   elog_main_t *em = &vam->elog_main;
2283
2284   elog_enable_disable (em, 0 /* enable */ );
2285   vl_api_set_elog_trace_api_messages (1);
2286   errmsg ("Event logger disabled...");
2287 #else
2288   errmsg ("Use the vpp event loger...");
2289 #endif
2290   return 0;
2291 }
2292
2293 static int
2294 statseg (vat_main_t * vam)
2295 {
2296   ssvm_private_t *ssvmp = &vam->stat_segment;
2297   ssvm_shared_header_t *shared_header = ssvmp->sh;
2298   vlib_counter_t **counters;
2299   u64 thread0_index1_packets;
2300   u64 thread0_index1_bytes;
2301   f64 vector_rate, input_rate;
2302   uword *p;
2303
2304   uword *counter_vector_by_name;
2305   if (vam->stat_segment_lockp == 0)
2306     {
2307       errmsg ("Stat segment not mapped...");
2308       return -99;
2309     }
2310
2311   /* look up "/if/rx for sw_if_index 1 as a test */
2312
2313   clib_spinlock_lock (vam->stat_segment_lockp);
2314
2315   counter_vector_by_name = (uword *) shared_header->opaque[1];
2316
2317   p = hash_get_mem (counter_vector_by_name, "/if/rx");
2318   if (p == 0)
2319     {
2320       clib_spinlock_unlock (vam->stat_segment_lockp);
2321       errmsg ("/if/tx not found?");
2322       return -99;
2323     }
2324
2325   /* Fish per-thread vector of combined counters from shared memory */
2326   counters = (vlib_counter_t **) p[0];
2327
2328   if (vec_len (counters[0]) < 2)
2329     {
2330       clib_spinlock_unlock (vam->stat_segment_lockp);
2331       errmsg ("/if/tx vector length %d", vec_len (counters[0]));
2332       return -99;
2333     }
2334
2335   /* Read thread 0 sw_if_index 1 counter */
2336   thread0_index1_packets = counters[0][1].packets;
2337   thread0_index1_bytes = counters[0][1].bytes;
2338
2339   p = hash_get_mem (counter_vector_by_name, "vector_rate");
2340   if (p == 0)
2341     {
2342       clib_spinlock_unlock (vam->stat_segment_lockp);
2343       errmsg ("vector_rate not found?");
2344       return -99;
2345     }
2346
2347   vector_rate = *(f64 *) (p[0]);
2348   p = hash_get_mem (counter_vector_by_name, "input_rate");
2349   if (p == 0)
2350     {
2351       clib_spinlock_unlock (vam->stat_segment_lockp);
2352       errmsg ("input_rate not found?");
2353       return -99;
2354     }
2355   input_rate = *(f64 *) (p[0]);
2356
2357   clib_spinlock_unlock (vam->stat_segment_lockp);
2358
2359   print (vam->ofp, "vector_rate %.2f input_rate %.2f",
2360          vector_rate, input_rate);
2361   print (vam->ofp, "thread 0 sw_if_index 1 rx pkts %lld, bytes %lld",
2362          thread0_index1_packets, thread0_index1_bytes);
2363
2364   return 0;
2365 }
2366
2367 static int
2368 cmd_cmp (void *a1, void *a2)
2369 {
2370   u8 **c1 = a1;
2371   u8 **c2 = a2;
2372
2373   return strcmp ((char *) (c1[0]), (char *) (c2[0]));
2374 }
2375
2376 static int
2377 help (vat_main_t * vam)
2378 {
2379   u8 **cmds = 0;
2380   u8 *name = 0;
2381   hash_pair_t *p;
2382   unformat_input_t *i = vam->input;
2383   int j;
2384
2385   if (unformat (i, "%s", &name))
2386     {
2387       uword *hs;
2388
2389       vec_add1 (name, 0);
2390
2391       hs = hash_get_mem (vam->help_by_name, name);
2392       if (hs)
2393         print (vam->ofp, "usage: %s %s", name, hs[0]);
2394       else
2395         print (vam->ofp, "No such msg / command '%s'", name);
2396       vec_free (name);
2397       return 0;
2398     }
2399
2400   print (vam->ofp, "Help is available for the following:");
2401
2402     /* *INDENT-OFF* */
2403     hash_foreach_pair (p, vam->function_by_name,
2404     ({
2405       vec_add1 (cmds, (u8 *)(p->key));
2406     }));
2407     /* *INDENT-ON* */
2408
2409   vec_sort_with_function (cmds, cmd_cmp);
2410
2411   for (j = 0; j < vec_len (cmds); j++)
2412     print (vam->ofp, "%s", cmds[j]);
2413
2414   vec_free (cmds);
2415   return 0;
2416 }
2417
2418 static int
2419 set (vat_main_t * vam)
2420 {
2421   u8 *name = 0, *value = 0;
2422   unformat_input_t *i = vam->input;
2423
2424   if (unformat (i, "%s", &name))
2425     {
2426       /* The input buffer is a vector, not a string. */
2427       value = vec_dup (i->buffer);
2428       vec_delete (value, i->index, 0);
2429       /* Almost certainly has a trailing newline */
2430       if (value[vec_len (value) - 1] == '\n')
2431         value[vec_len (value) - 1] = 0;
2432       /* Make sure it's a proper string, one way or the other */
2433       vec_add1 (value, 0);
2434       (void) clib_macro_set_value (&vam->macro_main,
2435                                    (char *) name, (char *) value);
2436     }
2437   else
2438     errmsg ("usage: set <name> <value>");
2439
2440   vec_free (name);
2441   vec_free (value);
2442   return 0;
2443 }
2444
2445 static int
2446 unset (vat_main_t * vam)
2447 {
2448   u8 *name = 0;
2449
2450   if (unformat (vam->input, "%s", &name))
2451     if (clib_macro_unset (&vam->macro_main, (char *) name) == 1)
2452       errmsg ("unset: %s wasn't set", name);
2453   vec_free (name);
2454   return 0;
2455 }
2456
2457 typedef struct
2458 {
2459   u8 *name;
2460   u8 *value;
2461 } macro_sort_t;
2462
2463
2464 static int
2465 macro_sort_cmp (void *a1, void *a2)
2466 {
2467   macro_sort_t *s1 = a1;
2468   macro_sort_t *s2 = a2;
2469
2470   return strcmp ((char *) (s1->name), (char *) (s2->name));
2471 }
2472
2473 static int
2474 dump_macro_table (vat_main_t * vam)
2475 {
2476   macro_sort_t *sort_me = 0, *sm;
2477   int i;
2478   hash_pair_t *p;
2479
2480     /* *INDENT-OFF* */
2481     hash_foreach_pair (p, vam->macro_main.the_value_table_hash,
2482     ({
2483       vec_add2 (sort_me, sm, 1);
2484       sm->name = (u8 *)(p->key);
2485       sm->value = (u8 *) (p->value[0]);
2486     }));
2487     /* *INDENT-ON* */
2488
2489   vec_sort_with_function (sort_me, macro_sort_cmp);
2490
2491   if (vec_len (sort_me))
2492     print (vam->ofp, "%-15s%s", "Name", "Value");
2493   else
2494     print (vam->ofp, "The macro table is empty...");
2495
2496   for (i = 0; i < vec_len (sort_me); i++)
2497     print (vam->ofp, "%-15s%s", sort_me[i].name, sort_me[i].value);
2498   return 0;
2499 }
2500
2501 static int
2502 value_sort_cmp (void *a1, void *a2)
2503 {
2504   name_sort_t *n1 = a1;
2505   name_sort_t *n2 = a2;
2506
2507   if (n1->value < n2->value)
2508     return -1;
2509   if (n1->value > n2->value)
2510     return 1;
2511   return 0;
2512 }
2513
2514
2515 static int
2516 dump_msg_api_table (vat_main_t * vam)
2517 {
2518   api_main_t *am = vlibapi_get_main ();
2519   name_sort_t *nses = 0, *ns;
2520   hash_pair_t *hp;
2521   int i;
2522
2523   /* *INDENT-OFF* */
2524   hash_foreach_pair (hp, am->msg_index_by_name_and_crc,
2525   ({
2526     vec_add2 (nses, ns, 1);
2527     ns->name = (u8 *)(hp->key);
2528     ns->value = (u32) hp->value[0];
2529   }));
2530   /* *INDENT-ON* */
2531
2532   vec_sort_with_function (nses, value_sort_cmp);
2533
2534   for (i = 0; i < vec_len (nses); i++)
2535     print (vam->ofp, " [%d]: %s", nses[i].value, nses[i].name);
2536   vec_free (nses);
2537   return 0;
2538 }
2539
2540 static int
2541 get_msg_id (vat_main_t * vam)
2542 {
2543   u8 *name_and_crc;
2544   u32 message_index;
2545
2546   if (unformat (vam->input, "%s", &name_and_crc))
2547     {
2548       message_index = vl_msg_api_get_msg_index (name_and_crc);
2549       if (message_index == ~0)
2550         {
2551           print (vam->ofp, " '%s' not found", name_and_crc);
2552           return 0;
2553         }
2554       print (vam->ofp, " '%s' has message index %d",
2555              name_and_crc, message_index);
2556       return 0;
2557     }
2558   errmsg ("name_and_crc required...");
2559   return 0;
2560 }
2561
2562 static int
2563 search_node_table (vat_main_t * vam)
2564 {
2565   unformat_input_t *line_input = vam->input;
2566   u8 *node_to_find;
2567   int j;
2568   vlib_node_t *node, *next_node;
2569   uword *p;
2570
2571   if (vam->graph_node_index_by_name == 0)
2572     {
2573       print (vam->ofp, "Node table empty, issue get_node_graph...");
2574       return 0;
2575     }
2576
2577   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2578     {
2579       if (unformat (line_input, "%s", &node_to_find))
2580         {
2581           vec_add1 (node_to_find, 0);
2582           p = hash_get_mem (vam->graph_node_index_by_name, node_to_find);
2583           if (p == 0)
2584             {
2585               print (vam->ofp, "%s not found...", node_to_find);
2586               goto out;
2587             }
2588           node = vam->graph_nodes[0][p[0]];
2589           print (vam->ofp, "[%d] %s", p[0], node->name);
2590           for (j = 0; j < vec_len (node->next_nodes); j++)
2591             {
2592               if (node->next_nodes[j] != ~0)
2593                 {
2594                   next_node = vam->graph_nodes[0][node->next_nodes[j]];
2595                   print (vam->ofp, "  [%d] %s", j, next_node->name);
2596                 }
2597             }
2598         }
2599
2600       else
2601         {
2602           clib_warning ("parse error '%U'", format_unformat_error,
2603                         line_input);
2604           return -99;
2605         }
2606
2607     out:
2608       vec_free (node_to_find);
2609
2610     }
2611
2612   return 0;
2613 }
2614
2615
2616 static int
2617 script (vat_main_t * vam)
2618 {
2619 #if (VPP_API_TEST_BUILTIN==0)
2620   u8 *s = 0;
2621   char *save_current_file;
2622   unformat_input_t save_input;
2623   jmp_buf save_jump_buf;
2624   u32 save_line_number;
2625
2626   FILE *new_fp, *save_ifp;
2627
2628   if (unformat (vam->input, "%s", &s))
2629     {
2630       new_fp = fopen ((char *) s, "r");
2631       if (new_fp == 0)
2632         {
2633           errmsg ("Couldn't open script file %s", s);
2634           vec_free (s);
2635           return -99;
2636         }
2637     }
2638   else
2639     {
2640       errmsg ("Missing script name");
2641       return -99;
2642     }
2643
2644   clib_memcpy (&save_input, &vam->input, sizeof (save_input));
2645   clib_memcpy (&save_jump_buf, &vam->jump_buf, sizeof (save_jump_buf));
2646   save_ifp = vam->ifp;
2647   save_line_number = vam->input_line_number;
2648   save_current_file = (char *) vam->current_file;
2649
2650   vam->input_line_number = 0;
2651   vam->ifp = new_fp;
2652   vam->current_file = s;
2653   do_one_file (vam);
2654
2655   clib_memcpy (&vam->input, &save_input, sizeof (save_input));
2656   clib_memcpy (&vam->jump_buf, &save_jump_buf, sizeof (save_jump_buf));
2657   vam->ifp = save_ifp;
2658   vam->input_line_number = save_line_number;
2659   vam->current_file = (u8 *) save_current_file;
2660   vec_free (s);
2661
2662   return 0;
2663 #else
2664   clib_warning ("use the exec command...");
2665   return -99;
2666 #endif
2667 }
2668
2669 static int
2670 echo (vat_main_t * vam)
2671 {
2672   print (vam->ofp, "%v", vam->input->buffer);
2673   return 0;
2674 }
2675
2676 int exec (vat_main_t *vam) __attribute__ ((weak));
2677 int
2678 exec (vat_main_t *vam)
2679 {
2680   return -1;
2681 }
2682
2683 /* List of API message constructors, CLI names map to api_xxx */
2684 #define foreach_vpe_api_msg                                             \
2685 _(show_version, "")                                                     \
2686 _(get_first_msg_id, "client <name>")                                    \
2687 _(sock_init_shm, "size <nnn>")                                          \
2688 /* List of command functions, CLI names map directly to functions */
2689 #define foreach_cli_function                                    \
2690 _(comment, "usage: comment <ignore-rest-of-line>")              \
2691 _(dump_macro_table, "usage: dump_macro_table ")                 \
2692 _(dump_msg_api_table, "usage: dump_msg_api_table")              \
2693 _(elog_setup, "usage: elog_setup [nevents, default 128K]")      \
2694 _(elog_disable, "usage: elog_disable")                          \
2695 _(elog_enable, "usage: elog_enable")                            \
2696 _(elog_save, "usage: elog_save <filename>")                     \
2697 _(get_msg_id, "usage: get_msg_id name_and_crc")                 \
2698 _(echo, "usage: echo <message>")                                \
2699 _(help, "usage: help")                                          \
2700 _(q, "usage: quit")                                             \
2701 _(quit, "usage: quit")                                          \
2702 _(search_node_table, "usage: search_node_table <name>...")      \
2703 _(set, "usage: set <variable-name> <value>")                    \
2704 _(script, "usage: script <file-name>")                          \
2705 _(statseg, "usage: statseg")                                    \
2706 _(unset, "usage: unset <variable-name>")
2707
2708 #define _(N,n)                                  \
2709     static void vl_api_##n##_t_handler_uni      \
2710     (vl_api_##n##_t * mp)                       \
2711     {                                           \
2712         vat_main_t * vam = &vat_main;           \
2713         if (vam->json_output) {                 \
2714             vl_api_##n##_t_handler_json(mp);    \
2715         } else {                                \
2716             vl_api_##n##_t_handler(mp);         \
2717         }                                       \
2718     }
2719 foreach_vpe_api_reply_msg;
2720 #if VPP_API_TEST_BUILTIN == 0
2721 foreach_standalone_reply_msg;
2722 #endif
2723 #undef _
2724
2725 void
2726 vat_api_hookup (vat_main_t * vam)
2727 {
2728 #define _(N,n)                                                  \
2729     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
2730                            vl_api_##n##_t_handler_uni,          \
2731                            vl_noop_handler,                     \
2732                            vl_api_##n##_t_endian,               \
2733                            vl_api_##n##_t_print,                \
2734                            sizeof(vl_api_##n##_t), 1);
2735   foreach_vpe_api_reply_msg;
2736 #if VPP_API_TEST_BUILTIN == 0
2737   foreach_standalone_reply_msg;
2738 #endif
2739 #undef _
2740
2741 #if (VPP_API_TEST_BUILTIN==0)
2742   vl_msg_api_set_first_available_msg_id (VL_MSG_FIRST_AVAILABLE);
2743
2744   vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
2745
2746   vam->function_by_name = hash_create_string (0, sizeof (uword));
2747
2748   vam->help_by_name = hash_create_string (0, sizeof (uword));
2749 #endif
2750
2751   /* API messages we can send */
2752 #define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
2753   foreach_vpe_api_msg;
2754 #undef _
2755
2756   /* Help strings */
2757 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
2758   foreach_vpe_api_msg;
2759 #undef _
2760
2761   /* CLI functions */
2762 #define _(n,h) hash_set_mem (vam->function_by_name, #n, n);
2763   foreach_cli_function;
2764 #undef _
2765
2766   /* Help strings */
2767 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
2768   foreach_cli_function;
2769 #undef _
2770 }
2771
2772 #if VPP_API_TEST_BUILTIN
2773 static clib_error_t *
2774 vat_api_hookup_shim (vlib_main_t * vm)
2775 {
2776   vat_api_hookup (&vat_main);
2777   return 0;
2778 }
2779
2780 VLIB_API_INIT_FUNCTION (vat_api_hookup_shim);
2781 #endif
2782
2783 /*
2784  * fd.io coding-style-patch-verification: ON
2785  *
2786  * Local Variables:
2787  * eval: (c-set-style "gnu")
2788  * End:
2789  */