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