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