l2: api cleanup
[vpp.git] / src / vat / api_format.c
1 /*
2  *------------------------------------------------------------------
3  * api_format.c
4  *
5  * Copyright (c) 2014-2020 Cisco and/or its affiliates.
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at:
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *------------------------------------------------------------------
18  */
19
20 #include <vat/vat.h>
21 #include <vlib/pci/pci.h>
22 #include <vpp/api/types.h>
23 #include <vppinfra/socket.h>
24 #include <vlibapi/api.h>
25 #include <vlibmemory/api.h>
26 #include <vnet/ip/ip.h>
27 #include <vnet/ip-neighbor/ip_neighbor.h>
28 #include <vnet/ip/ip_types_api.h>
29 #include <vnet/l2/l2_input.h>
30 #include <vnet/udp/udp_local.h>
31
32 #include <vpp/api/vpe_msg_enum.h>
33 #include <vnet/l2/l2_classify.h>
34 #include <vnet/l2/l2_vtr.h>
35 #include <vnet/classify/in_out_acl.h>
36 #include <vnet/classify/policer_classify.h>
37 #include <vnet/classify/flow_classify.h>
38 #include <vnet/mpls/mpls.h>
39 #include <vnet/ipsec/ipsec.h>
40 #include <inttypes.h>
41 #include <vnet/ip/ip6_hop_by_hop.h>
42 #include <vnet/ip/ip_source_and_port_range_check.h>
43 #include <vnet/policer/xlate.h>
44 #include <vnet/span/span.h>
45 #include <vnet/policer/policer.h>
46 #include <vnet/policer/police.h>
47 #include <vnet/mfib/mfib_types.h>
48 #include <vnet/bonding/node.h>
49 #include <vnet/qos/qos_types.h>
50 #include <vnet/ethernet/ethernet_types_api.h>
51 #include <vnet/ip/ip_types_api.h>
52 #include "vat/json_format.h"
53 #include <vnet/ip/ip_types_api.h>
54 #include <vnet/ethernet/ethernet_types_api.h>
55
56 #include <inttypes.h>
57 #include <sys/stat.h>
58
59 #define vl_typedefs             /* define message structures */
60 #include <vpp/api/vpe_all_api_h.h>
61 #undef vl_typedefs
62
63 /* declare message handlers for each api */
64
65 #define vl_endianfun            /* define message structures */
66 #include <vpp/api/vpe_all_api_h.h>
67 #undef vl_endianfun
68
69 /* instantiate all the print functions we know about */
70 #if VPP_API_TEST_BUILTIN == 0
71 #define vl_print(handle, ...)
72 #else
73 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
74 #endif
75 #define vl_printfun
76 #include <vpp/api/vpe_all_api_h.h>
77 #undef vl_printfun
78
79 #define __plugin_msg_base 0
80 #include <vlibapi/vat_helper_macros.h>
81
82 void vl_api_set_elog_main (elog_main_t * m);
83 int vl_api_set_elog_trace_api_messages (int enable);
84
85 #if VPP_API_TEST_BUILTIN == 0
86 #include <netdb.h>
87
88 u32
89 vl (void *p)
90 {
91   return vec_len (p);
92 }
93
94 int
95 vat_socket_connect (vat_main_t * vam)
96 {
97   int rv;
98   api_main_t *am = vlibapi_get_main ();
99   vam->socket_client_main = &socket_client_main;
100   if ((rv = vl_socket_client_connect ((char *) vam->socket_name,
101                                       "vpp_api_test",
102                                       0 /* default socket rx, tx buffer */ )))
103     return rv;
104
105   /* vpp expects the client index in network order */
106   vam->my_client_index = htonl (socket_client_main.client_index);
107   am->my_client_index = vam->my_client_index;
108   return 0;
109 }
110 #else /* vpp built-in case, we don't do sockets... */
111 int
112 vat_socket_connect (vat_main_t * vam)
113 {
114   return 0;
115 }
116
117 int
118 vl_socket_client_read (int wait)
119 {
120   return -1;
121 };
122
123 int
124 vl_socket_client_write ()
125 {
126   return -1;
127 };
128
129 void *
130 vl_socket_client_msg_alloc (int nbytes)
131 {
132   return 0;
133 }
134 #endif
135
136
137 f64
138 vat_time_now (vat_main_t * vam)
139 {
140 #if VPP_API_TEST_BUILTIN
141   return vlib_time_now (vam->vlib_main);
142 #else
143   return clib_time_now (&vam->clib_time);
144 #endif
145 }
146
147 void
148 errmsg (char *fmt, ...)
149 {
150   vat_main_t *vam = &vat_main;
151   va_list va;
152   u8 *s;
153
154   va_start (va, fmt);
155   s = va_format (0, fmt, &va);
156   va_end (va);
157
158   vec_add1 (s, 0);
159
160 #if VPP_API_TEST_BUILTIN
161   vlib_cli_output (vam->vlib_main, (char *) s);
162 #else
163   {
164     if (vam->ifp != stdin)
165       fformat (vam->ofp, "%s(%d): \n", vam->current_file,
166                vam->input_line_number);
167     else
168       fformat (vam->ofp, "%s\n", (char *) s);
169     fflush (vam->ofp);
170   }
171 #endif
172
173   vec_free (s);
174 }
175
176 #if VPP_API_TEST_BUILTIN == 0
177 static uword
178 api_unformat_sw_if_index (unformat_input_t * input, va_list * args)
179 {
180   vat_main_t *vam = va_arg (*args, vat_main_t *);
181   u32 *result = va_arg (*args, u32 *);
182   u8 *if_name;
183   uword *p;
184
185   if (!unformat (input, "%s", &if_name))
186     return 0;
187
188   p = hash_get_mem (vam->sw_if_index_by_interface_name, if_name);
189   if (p == 0)
190     return 0;
191   *result = p[0];
192   return 1;
193 }
194
195 /* Parse an IP4 address %d.%d.%d.%d. */
196 uword
197 unformat_ip4_address (unformat_input_t * input, va_list * args)
198 {
199   u8 *result = va_arg (*args, u8 *);
200   unsigned a[4];
201
202   if (!unformat (input, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]))
203     return 0;
204
205   if (a[0] >= 256 || a[1] >= 256 || a[2] >= 256 || a[3] >= 256)
206     return 0;
207
208   result[0] = a[0];
209   result[1] = a[1];
210   result[2] = a[2];
211   result[3] = a[3];
212
213   return 1;
214 }
215
216 uword
217 unformat_ethernet_address (unformat_input_t * input, va_list * args)
218 {
219   u8 *result = va_arg (*args, u8 *);
220   u32 i, a[6];
221
222   if (!unformat (input, "%_%x:%x:%x:%x:%x:%x%_",
223                  &a[0], &a[1], &a[2], &a[3], &a[4], &a[5]))
224     return 0;
225
226   /* Check range. */
227   for (i = 0; i < 6; i++)
228     if (a[i] >= (1 << 8))
229       return 0;
230
231   for (i = 0; i < 6; i++)
232     result[i] = a[i];
233
234   return 1;
235 }
236
237 /* Returns ethernet type as an int in host byte order. */
238 uword
239 unformat_ethernet_type_host_byte_order (unformat_input_t * input,
240                                         va_list * args)
241 {
242   u16 *result = va_arg (*args, u16 *);
243   int type;
244
245   /* Numeric type. */
246   if (unformat (input, "0x%x", &type) || unformat (input, "%d", &type))
247     {
248       if (type >= (1 << 16))
249         return 0;
250       *result = type;
251       return 1;
252     }
253   return 0;
254 }
255
256 /* Parse an IP46 address. */
257 uword
258 unformat_ip46_address (unformat_input_t * input, va_list * args)
259 {
260   ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
261   ip46_type_t type = va_arg (*args, ip46_type_t);
262   if ((type != IP46_TYPE_IP6) &&
263       unformat (input, "%U", unformat_ip4_address, &ip46->ip4))
264     {
265       ip46_address_mask_ip4 (ip46);
266       return 1;
267     }
268   else if ((type != IP46_TYPE_IP4) &&
269            unformat (input, "%U", unformat_ip6_address, &ip46->ip6))
270     {
271       return 1;
272     }
273   return 0;
274 }
275
276 /* Parse an IP6 address. */
277 uword
278 unformat_ip6_address (unformat_input_t * input, va_list * args)
279 {
280   ip6_address_t *result = va_arg (*args, ip6_address_t *);
281   u16 hex_quads[8];
282   uword hex_quad, n_hex_quads, hex_digit, n_hex_digits;
283   uword c, n_colon, double_colon_index;
284
285   n_hex_quads = hex_quad = n_hex_digits = n_colon = 0;
286   double_colon_index = ARRAY_LEN (hex_quads);
287   while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
288     {
289       hex_digit = 16;
290       if (c >= '0' && c <= '9')
291         hex_digit = c - '0';
292       else if (c >= 'a' && c <= 'f')
293         hex_digit = c + 10 - 'a';
294       else if (c >= 'A' && c <= 'F')
295         hex_digit = c + 10 - 'A';
296       else if (c == ':' && n_colon < 2)
297         n_colon++;
298       else
299         {
300           unformat_put_input (input);
301           break;
302         }
303
304       /* Too many hex quads. */
305       if (n_hex_quads >= ARRAY_LEN (hex_quads))
306         return 0;
307
308       if (hex_digit < 16)
309         {
310           hex_quad = (hex_quad << 4) | hex_digit;
311
312           /* Hex quad must fit in 16 bits. */
313           if (n_hex_digits >= 4)
314             return 0;
315
316           n_colon = 0;
317           n_hex_digits++;
318         }
319
320       /* Save position of :: */
321       if (n_colon == 2)
322         {
323           /* More than one :: ? */
324           if (double_colon_index < ARRAY_LEN (hex_quads))
325             return 0;
326           double_colon_index = n_hex_quads;
327         }
328
329       if (n_colon > 0 && n_hex_digits > 0)
330         {
331           hex_quads[n_hex_quads++] = hex_quad;
332           hex_quad = 0;
333           n_hex_digits = 0;
334         }
335     }
336
337   if (n_hex_digits > 0)
338     hex_quads[n_hex_quads++] = hex_quad;
339
340   {
341     word i;
342
343     /* Expand :: to appropriate number of zero hex quads. */
344     if (double_colon_index < ARRAY_LEN (hex_quads))
345       {
346         word n_zero = ARRAY_LEN (hex_quads) - n_hex_quads;
347
348         for (i = n_hex_quads - 1; i >= (signed) double_colon_index; i--)
349           hex_quads[n_zero + i] = hex_quads[i];
350
351         for (i = 0; i < n_zero; i++)
352           hex_quads[double_colon_index + i] = 0;
353
354         n_hex_quads = ARRAY_LEN (hex_quads);
355       }
356
357     /* Too few hex quads given. */
358     if (n_hex_quads < ARRAY_LEN (hex_quads))
359       return 0;
360
361     for (i = 0; i < ARRAY_LEN (hex_quads); i++)
362       result->as_u16[i] = clib_host_to_net_u16 (hex_quads[i]);
363
364     return 1;
365   }
366 }
367
368 uword
369 unformat_ipsec_policy_action (unformat_input_t * input, va_list * args)
370 {
371   u32 *r = va_arg (*args, u32 *);
372
373   if (0);
374 #define _(v,f,s) else if (unformat (input, s)) *r = IPSEC_POLICY_ACTION_##f;
375   foreach_ipsec_policy_action
376 #undef _
377     else
378     return 0;
379   return 1;
380 }
381
382 u8 *
383 format_ipsec_crypto_alg (u8 * s, va_list * args)
384 {
385   u32 i = va_arg (*args, u32);
386   u8 *t = 0;
387
388   switch (i)
389     {
390 #define _(v,f,str) case IPSEC_CRYPTO_ALG_##f: t = (u8 *) str; break;
391       foreach_ipsec_crypto_alg
392 #undef _
393     default:
394       return format (s, "unknown");
395     }
396   return format (s, "%s", t);
397 }
398
399 u8 *
400 format_ipsec_integ_alg (u8 * s, va_list * args)
401 {
402   u32 i = va_arg (*args, u32);
403   u8 *t = 0;
404
405   switch (i)
406     {
407 #define _(v,f,str) case IPSEC_INTEG_ALG_##f: t = (u8 *) str; break;
408       foreach_ipsec_integ_alg
409 #undef _
410     default:
411       return format (s, "unknown");
412     }
413   return format (s, "%s", t);
414 }
415
416 #else /* VPP_API_TEST_BUILTIN == 1 */
417 static uword
418 api_unformat_sw_if_index (unformat_input_t * input, va_list * args)
419 {
420   vat_main_t *vam __clib_unused = va_arg (*args, vat_main_t *);
421   vnet_main_t *vnm = vnet_get_main ();
422   u32 *result = va_arg (*args, u32 *);
423
424   return unformat (input, "%U", unformat_vnet_sw_interface, vnm, result);
425 }
426
427 #endif /* VPP_API_TEST_BUILTIN */
428
429 #if (VPP_API_TEST_BUILTIN==0)
430
431 static const char *mfib_flag_names[] = MFIB_ENTRY_NAMES_SHORT;
432 static const char *mfib_flag_long_names[] = MFIB_ENTRY_NAMES_LONG;
433 static const char *mfib_itf_flag_long_names[] = MFIB_ITF_NAMES_LONG;
434 static const char *mfib_itf_flag_names[] = MFIB_ITF_NAMES_SHORT;
435
436 uword
437 unformat_mfib_itf_flags (unformat_input_t * input, va_list * args)
438 {
439   mfib_itf_flags_t old, *iflags = va_arg (*args, mfib_itf_flags_t *);
440   mfib_itf_attribute_t attr;
441
442   old = *iflags;
443   FOR_EACH_MFIB_ITF_ATTRIBUTE (attr)
444   {
445     if (unformat (input, mfib_itf_flag_long_names[attr]))
446       *iflags |= (1 << attr);
447   }
448   FOR_EACH_MFIB_ITF_ATTRIBUTE (attr)
449   {
450     if (unformat (input, mfib_itf_flag_names[attr]))
451       *iflags |= (1 << attr);
452   }
453
454   return (old == *iflags ? 0 : 1);
455 }
456
457 uword
458 unformat_mfib_entry_flags (unformat_input_t * input, va_list * args)
459 {
460   mfib_entry_flags_t old, *eflags = va_arg (*args, mfib_entry_flags_t *);
461   mfib_entry_attribute_t attr;
462
463   old = *eflags;
464   FOR_EACH_MFIB_ATTRIBUTE (attr)
465   {
466     if (unformat (input, mfib_flag_long_names[attr]))
467       *eflags |= (1 << attr);
468   }
469   FOR_EACH_MFIB_ATTRIBUTE (attr)
470   {
471     if (unformat (input, mfib_flag_names[attr]))
472       *eflags |= (1 << attr);
473   }
474
475   return (old == *eflags ? 0 : 1);
476 }
477
478 u8 *
479 format_ip4_address (u8 * s, va_list * args)
480 {
481   u8 *a = va_arg (*args, u8 *);
482   return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
483 }
484
485 u8 *
486 format_ip6_address (u8 * s, va_list * args)
487 {
488   ip6_address_t *a = va_arg (*args, ip6_address_t *);
489   u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;
490
491   i_max_n_zero = ARRAY_LEN (a->as_u16);
492   max_n_zeros = 0;
493   i_first_zero = i_max_n_zero;
494   n_zeros = 0;
495   for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
496     {
497       u32 is_zero = a->as_u16[i] == 0;
498       if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16))
499         {
500           i_first_zero = i;
501           n_zeros = 0;
502         }
503       n_zeros += is_zero;
504       if ((!is_zero && n_zeros > max_n_zeros)
505           || (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros))
506         {
507           i_max_n_zero = i_first_zero;
508           max_n_zeros = n_zeros;
509           i_first_zero = ARRAY_LEN (a->as_u16);
510           n_zeros = 0;
511         }
512     }
513
514   last_double_colon = 0;
515   for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
516     {
517       if (i == i_max_n_zero && max_n_zeros > 1)
518         {
519           s = format (s, "::");
520           i += max_n_zeros - 1;
521           last_double_colon = 1;
522         }
523       else
524         {
525           s = format (s, "%s%x",
526                       (last_double_colon || i == 0) ? "" : ":",
527                       clib_net_to_host_u16 (a->as_u16[i]));
528           last_double_colon = 0;
529         }
530     }
531
532   return s;
533 }
534
535 /* Format an IP46 address. */
536 u8 *
537 format_ip46_address (u8 * s, va_list * args)
538 {
539   ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
540   ip46_type_t type = va_arg (*args, ip46_type_t);
541   int is_ip4 = 1;
542
543   switch (type)
544     {
545     case IP46_TYPE_ANY:
546       is_ip4 = ip46_address_is_ip4 (ip46);
547       break;
548     case IP46_TYPE_IP4:
549       is_ip4 = 1;
550       break;
551     case IP46_TYPE_IP6:
552       is_ip4 = 0;
553       break;
554     }
555
556   return is_ip4 ?
557     format (s, "%U", format_ip4_address, &ip46->ip4) :
558     format (s, "%U", format_ip6_address, &ip46->ip6);
559 }
560
561 u8 *
562 format_ethernet_address (u8 * s, va_list * args)
563 {
564   u8 *a = va_arg (*args, u8 *);
565
566   return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
567                  a[0], a[1], a[2], a[3], a[4], a[5]);
568 }
569 #endif
570
571 static void
572 increment_v4_address (vl_api_ip4_address_t * i)
573 {
574   ip4_address_t *a = (ip4_address_t *) i;
575   u32 v;
576
577   v = ntohl (a->as_u32) + 1;
578   a->as_u32 = ntohl (v);
579 }
580
581 static void
582 increment_v6_address (vl_api_ip6_address_t * i)
583 {
584   ip6_address_t *a = (ip6_address_t *) i;
585   u64 v0, v1;
586
587   v0 = clib_net_to_host_u64 (a->as_u64[0]);
588   v1 = clib_net_to_host_u64 (a->as_u64[1]);
589
590   v1 += 1;
591   if (v1 == 0)
592     v0 += 1;
593   a->as_u64[0] = clib_net_to_host_u64 (v0);
594   a->as_u64[1] = clib_net_to_host_u64 (v1);
595 }
596
597 static void
598 increment_address (vl_api_address_t * a)
599 {
600   if (a->af == ADDRESS_IP4)
601     increment_v4_address (&a->un.ip4);
602   else if (a->af == ADDRESS_IP6)
603     increment_v6_address (&a->un.ip6);
604 }
605
606 static void
607 set_ip4_address (vl_api_address_t * a, u32 v)
608 {
609   if (a->af == ADDRESS_IP4)
610     {
611       ip4_address_t *i = (ip4_address_t *) & a->un.ip4;
612       i->as_u32 = v;
613     }
614 }
615
616 void
617 ip_set (ip46_address_t * dst, void *src, u8 is_ip4)
618 {
619   if (is_ip4)
620     dst->ip4.as_u32 = ((ip4_address_t *) src)->as_u32;
621   else
622     clib_memcpy_fast (&dst->ip6, (ip6_address_t *) src,
623                       sizeof (ip6_address_t));
624 }
625
626 static void
627 vat_json_object_add_address (vat_json_node_t * node,
628                              const char *str, const vl_api_address_t * addr)
629 {
630   if (ADDRESS_IP6 == addr->af)
631     {
632       struct in6_addr ip6;
633
634       clib_memcpy (&ip6, &addr->un.ip6, sizeof (ip6));
635       vat_json_object_add_ip6 (node, str, ip6);
636     }
637   else
638     {
639       struct in_addr ip4;
640
641       clib_memcpy (&ip4, &addr->un.ip4, sizeof (ip4));
642       vat_json_object_add_ip4 (node, str, ip4);
643     }
644 }
645
646 static void
647 vat_json_object_add_prefix (vat_json_node_t * node,
648                             const vl_api_prefix_t * prefix)
649 {
650   vat_json_object_add_uint (node, "len", prefix->len);
651   vat_json_object_add_address (node, "address", &prefix->address);
652 }
653
654 static void vl_api_create_loopback_reply_t_handler
655   (vl_api_create_loopback_reply_t * mp)
656 {
657   vat_main_t *vam = &vat_main;
658   i32 retval = ntohl (mp->retval);
659
660   vam->retval = retval;
661   vam->regenerate_interface_table = 1;
662   vam->sw_if_index = ntohl (mp->sw_if_index);
663   vam->result_ready = 1;
664 }
665
666 static void vl_api_create_loopback_reply_t_handler_json
667   (vl_api_create_loopback_reply_t * mp)
668 {
669   vat_main_t *vam = &vat_main;
670   vat_json_node_t node;
671
672   vat_json_init_object (&node);
673   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
674   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
675
676   vat_json_print (vam->ofp, &node);
677   vat_json_free (&node);
678   vam->retval = ntohl (mp->retval);
679   vam->result_ready = 1;
680 }
681
682 static void vl_api_create_loopback_instance_reply_t_handler
683   (vl_api_create_loopback_instance_reply_t * mp)
684 {
685   vat_main_t *vam = &vat_main;
686   i32 retval = ntohl (mp->retval);
687
688   vam->retval = retval;
689   vam->regenerate_interface_table = 1;
690   vam->sw_if_index = ntohl (mp->sw_if_index);
691   vam->result_ready = 1;
692 }
693
694 static void vl_api_create_loopback_instance_reply_t_handler_json
695   (vl_api_create_loopback_instance_reply_t * mp)
696 {
697   vat_main_t *vam = &vat_main;
698   vat_json_node_t node;
699
700   vat_json_init_object (&node);
701   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
702   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
703
704   vat_json_print (vam->ofp, &node);
705   vat_json_free (&node);
706   vam->retval = ntohl (mp->retval);
707   vam->result_ready = 1;
708 }
709
710 static void vl_api_create_vlan_subif_reply_t_handler
711   (vl_api_create_vlan_subif_reply_t * mp)
712 {
713   vat_main_t *vam = &vat_main;
714   i32 retval = ntohl (mp->retval);
715
716   vam->retval = retval;
717   vam->regenerate_interface_table = 1;
718   vam->sw_if_index = ntohl (mp->sw_if_index);
719   vam->result_ready = 1;
720 }
721
722 static void vl_api_create_vlan_subif_reply_t_handler_json
723   (vl_api_create_vlan_subif_reply_t * mp)
724 {
725   vat_main_t *vam = &vat_main;
726   vat_json_node_t node;
727
728   vat_json_init_object (&node);
729   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
730   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
731
732   vat_json_print (vam->ofp, &node);
733   vat_json_free (&node);
734
735   vam->retval = ntohl (mp->retval);
736   vam->result_ready = 1;
737 }
738
739 static void vl_api_create_subif_reply_t_handler
740   (vl_api_create_subif_reply_t * mp)
741 {
742   vat_main_t *vam = &vat_main;
743   i32 retval = ntohl (mp->retval);
744
745   vam->retval = retval;
746   vam->regenerate_interface_table = 1;
747   vam->sw_if_index = ntohl (mp->sw_if_index);
748   vam->result_ready = 1;
749 }
750
751 static void vl_api_create_subif_reply_t_handler_json
752   (vl_api_create_subif_reply_t * mp)
753 {
754   vat_main_t *vam = &vat_main;
755   vat_json_node_t node;
756
757   vat_json_init_object (&node);
758   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
759   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
760
761   vat_json_print (vam->ofp, &node);
762   vat_json_free (&node);
763
764   vam->retval = ntohl (mp->retval);
765   vam->result_ready = 1;
766 }
767
768 static void vl_api_interface_name_renumber_reply_t_handler
769   (vl_api_interface_name_renumber_reply_t * mp)
770 {
771   vat_main_t *vam = &vat_main;
772   i32 retval = ntohl (mp->retval);
773
774   vam->retval = retval;
775   vam->regenerate_interface_table = 1;
776   vam->result_ready = 1;
777 }
778
779 static void vl_api_interface_name_renumber_reply_t_handler_json
780   (vl_api_interface_name_renumber_reply_t * mp)
781 {
782   vat_main_t *vam = &vat_main;
783   vat_json_node_t node;
784
785   vat_json_init_object (&node);
786   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
787
788   vat_json_print (vam->ofp, &node);
789   vat_json_free (&node);
790
791   vam->retval = ntohl (mp->retval);
792   vam->result_ready = 1;
793 }
794
795 /*
796  * Special-case: build the interface table, maintain
797  * the next loopback sw_if_index vbl.
798  */
799 static void vl_api_sw_interface_details_t_handler
800   (vl_api_sw_interface_details_t * mp)
801 {
802   vat_main_t *vam = &vat_main;
803   u8 *s = format (0, "%s%c", mp->interface_name, 0);
804
805   hash_set_mem (vam->sw_if_index_by_interface_name, s,
806                 ntohl (mp->sw_if_index));
807
808   /* In sub interface case, fill the sub interface table entry */
809   if (mp->sw_if_index != mp->sup_sw_if_index)
810     {
811       sw_interface_subif_t *sub = NULL;
812
813       vec_add2 (vam->sw_if_subif_table, sub, 1);
814
815       vec_validate (sub->interface_name, strlen ((char *) s) + 1);
816       strncpy ((char *) sub->interface_name, (char *) s,
817                vec_len (sub->interface_name));
818       sub->sw_if_index = ntohl (mp->sw_if_index);
819       sub->sub_id = ntohl (mp->sub_id);
820
821       sub->raw_flags = ntohl (mp->sub_if_flags & SUB_IF_API_FLAG_MASK_VNET);
822
823       sub->sub_number_of_tags = mp->sub_number_of_tags;
824       sub->sub_outer_vlan_id = ntohs (mp->sub_outer_vlan_id);
825       sub->sub_inner_vlan_id = ntohs (mp->sub_inner_vlan_id);
826
827       /* vlan tag rewrite */
828       sub->vtr_op = ntohl (mp->vtr_op);
829       sub->vtr_push_dot1q = ntohl (mp->vtr_push_dot1q);
830       sub->vtr_tag1 = ntohl (mp->vtr_tag1);
831       sub->vtr_tag2 = ntohl (mp->vtr_tag2);
832     }
833 }
834
835 static void vl_api_sw_interface_details_t_handler_json
836   (vl_api_sw_interface_details_t * mp)
837 {
838   vat_main_t *vam = &vat_main;
839   vat_json_node_t *node = NULL;
840
841   if (VAT_JSON_ARRAY != vam->json_tree.type)
842     {
843       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
844       vat_json_init_array (&vam->json_tree);
845     }
846   node = vat_json_array_add (&vam->json_tree);
847
848   vat_json_init_object (node);
849   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
850   vat_json_object_add_uint (node, "sup_sw_if_index",
851                             ntohl (mp->sup_sw_if_index));
852   vat_json_object_add_bytes (node, "l2_address", mp->l2_address,
853                              sizeof (mp->l2_address));
854   vat_json_object_add_string_copy (node, "interface_name",
855                                    mp->interface_name);
856   vat_json_object_add_string_copy (node, "interface_dev_type",
857                                    mp->interface_dev_type);
858   vat_json_object_add_uint (node, "flags", mp->flags);
859   vat_json_object_add_uint (node, "link_duplex", mp->link_duplex);
860   vat_json_object_add_uint (node, "link_speed", mp->link_speed);
861   vat_json_object_add_uint (node, "mtu", ntohs (mp->link_mtu));
862   vat_json_object_add_uint (node, "sub_id", ntohl (mp->sub_id));
863   vat_json_object_add_uint (node, "sub_number_of_tags",
864                             mp->sub_number_of_tags);
865   vat_json_object_add_uint (node, "sub_outer_vlan_id",
866                             ntohs (mp->sub_outer_vlan_id));
867   vat_json_object_add_uint (node, "sub_inner_vlan_id",
868                             ntohs (mp->sub_inner_vlan_id));
869   vat_json_object_add_uint (node, "sub_if_flags", ntohl (mp->sub_if_flags));
870   vat_json_object_add_uint (node, "vtr_op", ntohl (mp->vtr_op));
871   vat_json_object_add_uint (node, "vtr_push_dot1q",
872                             ntohl (mp->vtr_push_dot1q));
873   vat_json_object_add_uint (node, "vtr_tag1", ntohl (mp->vtr_tag1));
874   vat_json_object_add_uint (node, "vtr_tag2", ntohl (mp->vtr_tag2));
875   if (ntohl (mp->sub_if_flags) & SUB_IF_API_FLAG_DOT1AH)
876     {
877       vat_json_object_add_string_copy (node, "pbb_vtr_dmac",
878                                        format (0, "%U",
879                                                format_ethernet_address,
880                                                &mp->b_dmac));
881       vat_json_object_add_string_copy (node, "pbb_vtr_smac",
882                                        format (0, "%U",
883                                                format_ethernet_address,
884                                                &mp->b_smac));
885       vat_json_object_add_uint (node, "pbb_vtr_b_vlanid", mp->b_vlanid);
886       vat_json_object_add_uint (node, "pbb_vtr_i_sid", mp->i_sid);
887     }
888 }
889
890 #if VPP_API_TEST_BUILTIN == 0
891 static void vl_api_sw_interface_event_t_handler
892   (vl_api_sw_interface_event_t * mp)
893 {
894   vat_main_t *vam = &vat_main;
895   if (vam->interface_event_display)
896     errmsg ("interface flags: sw_if_index %d %s %s",
897             ntohl (mp->sw_if_index),
898             ((ntohl (mp->flags)) & IF_STATUS_API_FLAG_ADMIN_UP) ?
899             "admin-up" : "admin-down",
900             ((ntohl (mp->flags)) & IF_STATUS_API_FLAG_LINK_UP) ?
901             "link-up" : "link-down");
902 }
903 #endif
904
905 __clib_unused static void
906 vl_api_sw_interface_event_t_handler_json (vl_api_sw_interface_event_t * mp)
907 {
908   /* JSON output not supported */
909 }
910
911 static void
912 vl_api_cli_reply_t_handler (vl_api_cli_reply_t * mp)
913 {
914   vat_main_t *vam = &vat_main;
915   i32 retval = ntohl (mp->retval);
916
917   vam->retval = retval;
918   vam->shmem_result = uword_to_pointer (mp->reply_in_shmem, u8 *);
919   vam->result_ready = 1;
920 }
921
922 static void
923 vl_api_cli_reply_t_handler_json (vl_api_cli_reply_t * mp)
924 {
925   vat_main_t *vam = &vat_main;
926   vat_json_node_t node;
927   void *oldheap;
928   u8 *reply;
929
930   vat_json_init_object (&node);
931   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
932   vat_json_object_add_uint (&node, "reply_in_shmem",
933                             ntohl (mp->reply_in_shmem));
934   /* Toss the shared-memory original... */
935   oldheap = vl_msg_push_heap ();
936
937   reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
938   vec_free (reply);
939
940   vl_msg_pop_heap (oldheap);
941
942   vat_json_print (vam->ofp, &node);
943   vat_json_free (&node);
944
945   vam->retval = ntohl (mp->retval);
946   vam->result_ready = 1;
947 }
948
949 static void
950 vl_api_cli_inband_reply_t_handler (vl_api_cli_inband_reply_t * mp)
951 {
952   vat_main_t *vam = &vat_main;
953   i32 retval = ntohl (mp->retval);
954
955   vec_reset_length (vam->cmd_reply);
956
957   vam->retval = retval;
958   if (retval == 0)
959     vam->cmd_reply = vl_api_from_api_to_new_vec (mp, &mp->reply);
960   vam->result_ready = 1;
961 }
962
963 static void
964 vl_api_cli_inband_reply_t_handler_json (vl_api_cli_inband_reply_t * mp)
965 {
966   vat_main_t *vam = &vat_main;
967   vat_json_node_t node;
968   u8 *reply = 0;                /* reply vector */
969
970   reply = vl_api_from_api_to_new_vec (mp, &mp->reply);
971   vec_reset_length (vam->cmd_reply);
972
973   vat_json_init_object (&node);
974   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
975   vat_json_object_add_string_copy (&node, "reply", reply);
976
977   vat_json_print (vam->ofp, &node);
978   vat_json_free (&node);
979   vec_free (reply);
980
981   vam->retval = ntohl (mp->retval);
982   vam->result_ready = 1;
983 }
984
985 static void vl_api_get_node_index_reply_t_handler
986   (vl_api_get_node_index_reply_t * mp)
987 {
988   vat_main_t *vam = &vat_main;
989   i32 retval = ntohl (mp->retval);
990   if (vam->async_mode)
991     {
992       vam->async_errors += (retval < 0);
993     }
994   else
995     {
996       vam->retval = retval;
997       if (retval == 0)
998         errmsg ("node index %d", ntohl (mp->node_index));
999       vam->result_ready = 1;
1000     }
1001 }
1002
1003 static void vl_api_get_node_index_reply_t_handler_json
1004   (vl_api_get_node_index_reply_t * mp)
1005 {
1006   vat_main_t *vam = &vat_main;
1007   vat_json_node_t node;
1008
1009   vat_json_init_object (&node);
1010   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1011   vat_json_object_add_uint (&node, "node_index", ntohl (mp->node_index));
1012
1013   vat_json_print (vam->ofp, &node);
1014   vat_json_free (&node);
1015
1016   vam->retval = ntohl (mp->retval);
1017   vam->result_ready = 1;
1018 }
1019
1020 static void vl_api_get_next_index_reply_t_handler
1021   (vl_api_get_next_index_reply_t * mp)
1022 {
1023   vat_main_t *vam = &vat_main;
1024   i32 retval = ntohl (mp->retval);
1025   if (vam->async_mode)
1026     {
1027       vam->async_errors += (retval < 0);
1028     }
1029   else
1030     {
1031       vam->retval = retval;
1032       if (retval == 0)
1033         errmsg ("next node index %d", ntohl (mp->next_index));
1034       vam->result_ready = 1;
1035     }
1036 }
1037
1038 static void vl_api_get_next_index_reply_t_handler_json
1039   (vl_api_get_next_index_reply_t * mp)
1040 {
1041   vat_main_t *vam = &vat_main;
1042   vat_json_node_t node;
1043
1044   vat_json_init_object (&node);
1045   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1046   vat_json_object_add_uint (&node, "next_index", ntohl (mp->next_index));
1047
1048   vat_json_print (vam->ofp, &node);
1049   vat_json_free (&node);
1050
1051   vam->retval = ntohl (mp->retval);
1052   vam->result_ready = 1;
1053 }
1054
1055 static void vl_api_add_node_next_reply_t_handler
1056   (vl_api_add_node_next_reply_t * mp)
1057 {
1058   vat_main_t *vam = &vat_main;
1059   i32 retval = ntohl (mp->retval);
1060   if (vam->async_mode)
1061     {
1062       vam->async_errors += (retval < 0);
1063     }
1064   else
1065     {
1066       vam->retval = retval;
1067       if (retval == 0)
1068         errmsg ("next index %d", ntohl (mp->next_index));
1069       vam->result_ready = 1;
1070     }
1071 }
1072
1073 static void vl_api_add_node_next_reply_t_handler_json
1074   (vl_api_add_node_next_reply_t * mp)
1075 {
1076   vat_main_t *vam = &vat_main;
1077   vat_json_node_t node;
1078
1079   vat_json_init_object (&node);
1080   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1081   vat_json_object_add_uint (&node, "next_index", ntohl (mp->next_index));
1082
1083   vat_json_print (vam->ofp, &node);
1084   vat_json_free (&node);
1085
1086   vam->retval = ntohl (mp->retval);
1087   vam->result_ready = 1;
1088 }
1089
1090 static void vl_api_show_version_reply_t_handler
1091   (vl_api_show_version_reply_t * mp)
1092 {
1093   vat_main_t *vam = &vat_main;
1094   i32 retval = ntohl (mp->retval);
1095
1096   if (retval >= 0)
1097     {
1098       errmsg ("        program: %s", mp->program);
1099       errmsg ("        version: %s", mp->version);
1100       errmsg ("     build date: %s", mp->build_date);
1101       errmsg ("build directory: %s", mp->build_directory);
1102     }
1103   vam->retval = retval;
1104   vam->result_ready = 1;
1105 }
1106
1107 static void vl_api_show_version_reply_t_handler_json
1108   (vl_api_show_version_reply_t * mp)
1109 {
1110   vat_main_t *vam = &vat_main;
1111   vat_json_node_t node;
1112
1113   vat_json_init_object (&node);
1114   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1115   vat_json_object_add_string_copy (&node, "program", mp->program);
1116   vat_json_object_add_string_copy (&node, "version", mp->version);
1117   vat_json_object_add_string_copy (&node, "build_date", mp->build_date);
1118   vat_json_object_add_string_copy (&node, "build_directory",
1119                                    mp->build_directory);
1120
1121   vat_json_print (vam->ofp, &node);
1122   vat_json_free (&node);
1123
1124   vam->retval = ntohl (mp->retval);
1125   vam->result_ready = 1;
1126 }
1127
1128 static void vl_api_show_threads_reply_t_handler
1129   (vl_api_show_threads_reply_t * mp)
1130 {
1131   vat_main_t *vam = &vat_main;
1132   i32 retval = ntohl (mp->retval);
1133   int i, count = 0;
1134
1135   if (retval >= 0)
1136     count = ntohl (mp->count);
1137
1138   for (i = 0; i < count; i++)
1139     print (vam->ofp,
1140            "\n%-2d %-11s %-11s %-5d %-6d %-4d %-6d",
1141            ntohl (mp->thread_data[i].id), mp->thread_data[i].name,
1142            mp->thread_data[i].type, ntohl (mp->thread_data[i].pid),
1143            ntohl (mp->thread_data[i].cpu_id), ntohl (mp->thread_data[i].core),
1144            ntohl (mp->thread_data[i].cpu_socket));
1145
1146   vam->retval = retval;
1147   vam->result_ready = 1;
1148 }
1149
1150 static void vl_api_show_threads_reply_t_handler_json
1151   (vl_api_show_threads_reply_t * mp)
1152 {
1153   vat_main_t *vam = &vat_main;
1154   vat_json_node_t node;
1155   vl_api_thread_data_t *td;
1156   i32 retval = ntohl (mp->retval);
1157   int i, count = 0;
1158
1159   if (retval >= 0)
1160     count = ntohl (mp->count);
1161
1162   vat_json_init_object (&node);
1163   vat_json_object_add_int (&node, "retval", retval);
1164   vat_json_object_add_uint (&node, "count", count);
1165
1166   for (i = 0; i < count; i++)
1167     {
1168       td = &mp->thread_data[i];
1169       vat_json_object_add_uint (&node, "id", ntohl (td->id));
1170       vat_json_object_add_string_copy (&node, "name", td->name);
1171       vat_json_object_add_string_copy (&node, "type", td->type);
1172       vat_json_object_add_uint (&node, "pid", ntohl (td->pid));
1173       vat_json_object_add_int (&node, "cpu_id", ntohl (td->cpu_id));
1174       vat_json_object_add_int (&node, "core", ntohl (td->id));
1175       vat_json_object_add_int (&node, "cpu_socket", ntohl (td->cpu_socket));
1176     }
1177
1178   vat_json_print (vam->ofp, &node);
1179   vat_json_free (&node);
1180
1181   vam->retval = retval;
1182   vam->result_ready = 1;
1183 }
1184
1185 static int
1186 api_show_threads (vat_main_t * vam)
1187 {
1188   vl_api_show_threads_t *mp;
1189   int ret;
1190
1191   print (vam->ofp,
1192          "\n%-2s %-11s %-11s %-5s %-6s %-4s %-6s",
1193          "ID", "Name", "Type", "LWP", "cpu_id", "Core", "Socket");
1194
1195   M (SHOW_THREADS, mp);
1196
1197   S (mp);
1198   W (ret);
1199   return ret;
1200 }
1201
1202 #define vl_api_bridge_domain_details_t_endian vl_noop_handler
1203 #define vl_api_bridge_domain_details_t_print vl_noop_handler
1204
1205 static void vl_api_control_ping_reply_t_handler
1206   (vl_api_control_ping_reply_t * mp)
1207 {
1208   vat_main_t *vam = &vat_main;
1209   i32 retval = ntohl (mp->retval);
1210   if (vam->async_mode)
1211     {
1212       vam->async_errors += (retval < 0);
1213     }
1214   else
1215     {
1216       vam->retval = retval;
1217       vam->result_ready = 1;
1218     }
1219   if (vam->socket_client_main)
1220     vam->socket_client_main->control_pings_outstanding--;
1221 }
1222
1223 static void vl_api_control_ping_reply_t_handler_json
1224   (vl_api_control_ping_reply_t * mp)
1225 {
1226   vat_main_t *vam = &vat_main;
1227   i32 retval = ntohl (mp->retval);
1228
1229   if (VAT_JSON_NONE != vam->json_tree.type)
1230     {
1231       vat_json_print (vam->ofp, &vam->json_tree);
1232       vat_json_free (&vam->json_tree);
1233       vam->json_tree.type = VAT_JSON_NONE;
1234     }
1235   else
1236     {
1237       /* just print [] */
1238       vat_json_init_array (&vam->json_tree);
1239       vat_json_print (vam->ofp, &vam->json_tree);
1240       vam->json_tree.type = VAT_JSON_NONE;
1241     }
1242
1243   vam->retval = retval;
1244   vam->result_ready = 1;
1245 }
1246
1247
1248 static void vl_api_ip_address_details_t_handler
1249   (vl_api_ip_address_details_t * mp)
1250 {
1251   vat_main_t *vam = &vat_main;
1252   static ip_address_details_t empty_ip_address_details = { {0} };
1253   ip_address_details_t *address = NULL;
1254   ip_details_t *current_ip_details = NULL;
1255   ip_details_t *details = NULL;
1256
1257   details = vam->ip_details_by_sw_if_index[vam->is_ipv6];
1258
1259   if (!details || vam->current_sw_if_index >= vec_len (details)
1260       || !details[vam->current_sw_if_index].present)
1261     {
1262       errmsg ("ip address details arrived but not stored");
1263       errmsg ("ip_dump should be called first");
1264       return;
1265     }
1266
1267   current_ip_details = vec_elt_at_index (details, vam->current_sw_if_index);
1268
1269 #define addresses (current_ip_details->addr)
1270
1271   vec_validate_init_empty (addresses, vec_len (addresses),
1272                            empty_ip_address_details);
1273
1274   address = vec_elt_at_index (addresses, vec_len (addresses) - 1);
1275
1276   clib_memcpy (&address->ip, &mp->prefix.address.un, sizeof (address->ip));
1277   address->prefix_length = mp->prefix.len;
1278 #undef addresses
1279 }
1280
1281 static void vl_api_ip_address_details_t_handler_json
1282   (vl_api_ip_address_details_t * mp)
1283 {
1284   vat_main_t *vam = &vat_main;
1285   vat_json_node_t *node = NULL;
1286
1287   if (VAT_JSON_ARRAY != vam->json_tree.type)
1288     {
1289       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
1290       vat_json_init_array (&vam->json_tree);
1291     }
1292   node = vat_json_array_add (&vam->json_tree);
1293
1294   vat_json_init_object (node);
1295   vat_json_object_add_prefix (node, &mp->prefix);
1296 }
1297
1298 static void
1299 vl_api_ip_details_t_handler (vl_api_ip_details_t * mp)
1300 {
1301   vat_main_t *vam = &vat_main;
1302   static ip_details_t empty_ip_details = { 0 };
1303   ip_details_t *ip = NULL;
1304   u32 sw_if_index = ~0;
1305
1306   sw_if_index = ntohl (mp->sw_if_index);
1307
1308   vec_validate_init_empty (vam->ip_details_by_sw_if_index[vam->is_ipv6],
1309                            sw_if_index, empty_ip_details);
1310
1311   ip = vec_elt_at_index (vam->ip_details_by_sw_if_index[vam->is_ipv6],
1312                          sw_if_index);
1313
1314   ip->present = 1;
1315 }
1316
1317 static void
1318 vl_api_ip_details_t_handler_json (vl_api_ip_details_t * mp)
1319 {
1320   vat_main_t *vam = &vat_main;
1321
1322   if (VAT_JSON_ARRAY != vam->json_tree.type)
1323     {
1324       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
1325       vat_json_init_array (&vam->json_tree);
1326     }
1327   vat_json_array_add_uint (&vam->json_tree,
1328                            clib_net_to_host_u32 (mp->sw_if_index));
1329 }
1330
1331 static void vl_api_get_first_msg_id_reply_t_handler
1332   (vl_api_get_first_msg_id_reply_t * mp)
1333 {
1334   vat_main_t *vam = &vat_main;
1335   i32 retval = ntohl (mp->retval);
1336
1337   if (vam->async_mode)
1338     {
1339       vam->async_errors += (retval < 0);
1340     }
1341   else
1342     {
1343       vam->retval = retval;
1344       vam->result_ready = 1;
1345     }
1346   if (retval >= 0)
1347     {
1348       errmsg ("first message id %d", ntohs (mp->first_msg_id));
1349     }
1350 }
1351
1352 static void vl_api_get_first_msg_id_reply_t_handler_json
1353   (vl_api_get_first_msg_id_reply_t * mp)
1354 {
1355   vat_main_t *vam = &vat_main;
1356   vat_json_node_t node;
1357
1358   vat_json_init_object (&node);
1359   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1360   vat_json_object_add_uint (&node, "first_msg_id",
1361                             (uint) ntohs (mp->first_msg_id));
1362
1363   vat_json_print (vam->ofp, &node);
1364   vat_json_free (&node);
1365
1366   vam->retval = ntohl (mp->retval);
1367   vam->result_ready = 1;
1368 }
1369
1370 static void vl_api_get_node_graph_reply_t_handler
1371   (vl_api_get_node_graph_reply_t * mp)
1372 {
1373   vat_main_t *vam = &vat_main;
1374   i32 retval = ntohl (mp->retval);
1375   u8 *pvt_copy, *reply;
1376   void *oldheap;
1377   vlib_node_t *node;
1378   int i;
1379
1380   if (vam->async_mode)
1381     {
1382       vam->async_errors += (retval < 0);
1383     }
1384   else
1385     {
1386       vam->retval = retval;
1387       vam->result_ready = 1;
1388     }
1389
1390   /* "Should never happen..." */
1391   if (retval != 0)
1392     return;
1393
1394   reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
1395   pvt_copy = vec_dup (reply);
1396
1397   /* Toss the shared-memory original... */
1398   oldheap = vl_msg_push_heap ();
1399
1400   vec_free (reply);
1401
1402   vl_msg_pop_heap (oldheap);
1403
1404   if (vam->graph_nodes)
1405     {
1406       hash_free (vam->graph_node_index_by_name);
1407
1408       for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
1409         {
1410           node = vam->graph_nodes[0][i];
1411           vec_free (node->name);
1412           vec_free (node->next_nodes);
1413           vec_free (node);
1414         }
1415       vec_free (vam->graph_nodes[0]);
1416       vec_free (vam->graph_nodes);
1417     }
1418
1419   vam->graph_node_index_by_name = hash_create_string (0, sizeof (uword));
1420   vam->graph_nodes = vlib_node_unserialize (pvt_copy);
1421   vec_free (pvt_copy);
1422
1423   for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
1424     {
1425       node = vam->graph_nodes[0][i];
1426       hash_set_mem (vam->graph_node_index_by_name, node->name, i);
1427     }
1428 }
1429
1430 static void vl_api_get_node_graph_reply_t_handler_json
1431   (vl_api_get_node_graph_reply_t * mp)
1432 {
1433   vat_main_t *vam = &vat_main;
1434   void *oldheap;
1435   vat_json_node_t node;
1436   u8 *reply;
1437
1438   /* $$$$ make this real? */
1439   vat_json_init_object (&node);
1440   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1441   vat_json_object_add_uint (&node, "reply_in_shmem", mp->reply_in_shmem);
1442
1443   reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
1444
1445   /* Toss the shared-memory original... */
1446   oldheap = vl_msg_push_heap ();
1447
1448   vec_free (reply);
1449
1450   vl_msg_pop_heap (oldheap);
1451
1452   vat_json_print (vam->ofp, &node);
1453   vat_json_free (&node);
1454
1455   vam->retval = ntohl (mp->retval);
1456   vam->result_ready = 1;
1457 }
1458
1459 /* Format hex dump. */
1460 u8 *
1461 format_hex_bytes (u8 * s, va_list * va)
1462 {
1463   u8 *bytes = va_arg (*va, u8 *);
1464   int n_bytes = va_arg (*va, int);
1465   uword i;
1466
1467   /* Print short or long form depending on byte count. */
1468   uword short_form = n_bytes <= 32;
1469   u32 indent = format_get_indent (s);
1470
1471   if (n_bytes == 0)
1472     return s;
1473
1474   for (i = 0; i < n_bytes; i++)
1475     {
1476       if (!short_form && (i % 32) == 0)
1477         s = format (s, "%08x: ", i);
1478       s = format (s, "%02x", bytes[i]);
1479       if (!short_form && ((i + 1) % 32) == 0 && (i + 1) < n_bytes)
1480         s = format (s, "\n%U", format_white_space, indent);
1481     }
1482
1483   return s;
1484 }
1485
1486 /*
1487  * Generate boilerplate reply handlers, which
1488  * dig the return value out of the xxx_reply_t API message,
1489  * stick it into vam->retval, and set vam->result_ready
1490  *
1491  * Could also do this by pointing N message decode slots at
1492  * a single function, but that could break in subtle ways.
1493  */
1494
1495 #define foreach_standard_reply_retval_handler           \
1496 _(sw_interface_set_flags_reply)                         \
1497 _(sw_interface_add_del_address_reply)                   \
1498 _(sw_interface_set_rx_placement_reply)                  \
1499 _(sw_interface_set_table_reply)                         \
1500 _(ip_route_add_del_reply)                               \
1501 _(ip_table_add_del_reply)                               \
1502 _(ip_table_replace_begin_reply)                         \
1503 _(ip_table_flush_reply)                                 \
1504 _(ip_table_replace_end_reply)                           \
1505 _(ip_mroute_add_del_reply)                              \
1506 _(sw_interface_set_unnumbered_reply)                    \
1507 _(set_ip_flow_hash_reply)                               \
1508 _(sw_interface_ip6_enable_disable_reply)                \
1509 _(delete_loopback_reply)                                \
1510 _(want_interface_events_reply)                          \
1511 _(sw_interface_clear_stats_reply)                       \
1512 _(ioam_enable_reply)                                    \
1513 _(ioam_disable_reply)                                   \
1514 _(ip_source_and_port_range_check_add_del_reply)         \
1515 _(ip_source_and_port_range_check_interface_add_del_reply)\
1516 _(delete_subif_reply)                                   \
1517 _(sw_interface_tag_add_del_reply)                       \
1518 _(sw_interface_add_del_mac_address_reply)               \
1519 _(hw_interface_set_mtu_reply)                           \
1520 _(session_rule_add_del_reply)                           \
1521 _(ip_container_proxy_add_del_reply)                     \
1522
1523 #define _(n)                                    \
1524     static void vl_api_##n##_t_handler          \
1525     (vl_api_##n##_t * mp)                       \
1526     {                                           \
1527         vat_main_t * vam = &vat_main;           \
1528         i32 retval = ntohl(mp->retval);         \
1529         if (vam->async_mode) {                  \
1530             vam->async_errors += (retval < 0);  \
1531         } else {                                \
1532             vam->retval = retval;               \
1533             vam->result_ready = 1;              \
1534         }                                       \
1535     }
1536 foreach_standard_reply_retval_handler;
1537 #undef _
1538
1539 #define _(n)                                    \
1540     static void vl_api_##n##_t_handler_json     \
1541     (vl_api_##n##_t * mp)                       \
1542     {                                           \
1543         vat_main_t * vam = &vat_main;           \
1544         vat_json_node_t node;                   \
1545         vat_json_init_object(&node);            \
1546         vat_json_object_add_int(&node, "retval", ntohl(mp->retval));    \
1547         vat_json_print(vam->ofp, &node);        \
1548         vam->retval = ntohl(mp->retval);        \
1549         vam->result_ready = 1;                  \
1550     }
1551 foreach_standard_reply_retval_handler;
1552 #undef _
1553
1554 /*
1555  * Table of message reply handlers, must include boilerplate handlers
1556  * we just generated
1557  */
1558
1559 #define foreach_vpe_api_reply_msg                                       \
1560 _(CREATE_LOOPBACK_REPLY, create_loopback_reply)                         \
1561 _(CREATE_LOOPBACK_INSTANCE_REPLY, create_loopback_instance_reply)       \
1562 _(SW_INTERFACE_DETAILS, sw_interface_details)                           \
1563 _(SW_INTERFACE_SET_FLAGS_REPLY, sw_interface_set_flags_reply)           \
1564 _(CONTROL_PING_REPLY, control_ping_reply)                               \
1565 _(CLI_REPLY, cli_reply)                                                 \
1566 _(CLI_INBAND_REPLY, cli_inband_reply)                                   \
1567 _(SW_INTERFACE_ADD_DEL_ADDRESS_REPLY,                                   \
1568   sw_interface_add_del_address_reply)                                   \
1569 _(SW_INTERFACE_SET_RX_PLACEMENT_REPLY, sw_interface_set_rx_placement_reply)     \
1570 _(SW_INTERFACE_RX_PLACEMENT_DETAILS, sw_interface_rx_placement_details) \
1571 _(SW_INTERFACE_SET_TABLE_REPLY, sw_interface_set_table_reply)           \
1572 _(IP_ROUTE_ADD_DEL_REPLY, ip_route_add_del_reply)                       \
1573 _(IP_TABLE_ADD_DEL_REPLY, ip_table_add_del_reply)                       \
1574 _(IP_TABLE_REPLACE_BEGIN_REPLY, ip_table_replace_begin_reply)           \
1575 _(IP_TABLE_FLUSH_REPLY, ip_table_flush_reply)                           \
1576 _(IP_TABLE_REPLACE_END_REPLY, ip_table_replace_end_reply)               \
1577 _(IP_MROUTE_ADD_DEL_REPLY, ip_mroute_add_del_reply)                     \
1578 _(SW_INTERFACE_SET_UNNUMBERED_REPLY,                                    \
1579   sw_interface_set_unnumbered_reply)                                    \
1580 _(CREATE_VLAN_SUBIF_REPLY, create_vlan_subif_reply)                     \
1581 _(CREATE_SUBIF_REPLY, create_subif_reply)                               \
1582 _(SET_IP_FLOW_HASH_REPLY, set_ip_flow_hash_reply)                       \
1583 _(SW_INTERFACE_IP6_ENABLE_DISABLE_REPLY,                                \
1584   sw_interface_ip6_enable_disable_reply)                                \
1585 _(GET_NODE_INDEX_REPLY, get_node_index_reply)                           \
1586 _(ADD_NODE_NEXT_REPLY, add_node_next_reply)                             \
1587 _(SHOW_VERSION_REPLY, show_version_reply)                               \
1588 _(SHOW_THREADS_REPLY, show_threads_reply)                               \
1589 _(INTERFACE_NAME_RENUMBER_REPLY, interface_name_renumber_reply)         \
1590 _(IP_ADDRESS_DETAILS, ip_address_details)                               \
1591 _(IP_DETAILS, ip_details)                                               \
1592 _(DELETE_LOOPBACK_REPLY, delete_loopback_reply)                         \
1593 _(WANT_INTERFACE_EVENTS_REPLY, want_interface_events_reply)             \
1594 _(GET_FIRST_MSG_ID_REPLY, get_first_msg_id_reply)                       \
1595 _(GET_NODE_GRAPH_REPLY, get_node_graph_reply)                           \
1596 _(SW_INTERFACE_CLEAR_STATS_REPLY, sw_interface_clear_stats_reply)      \
1597 _(IOAM_ENABLE_REPLY, ioam_enable_reply)                   \
1598 _(IOAM_DISABLE_REPLY, ioam_disable_reply)                     \
1599 _(GET_NEXT_INDEX_REPLY, get_next_index_reply)                           \
1600 _(IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL_REPLY,                         \
1601  ip_source_and_port_range_check_add_del_reply)                          \
1602 _(IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL_REPLY,               \
1603  ip_source_and_port_range_check_interface_add_del_reply)                \
1604 _(DELETE_SUBIF_REPLY, delete_subif_reply)                               \
1605 _(IP_TABLE_DETAILS, ip_table_details)                                   \
1606 _(IP_ROUTE_DETAILS, ip_route_details)                                   \
1607 _(SW_INTERFACE_TAG_ADD_DEL_REPLY, sw_interface_tag_add_del_reply)       \
1608 _(SW_INTERFACE_ADD_DEL_MAC_ADDRESS_REPLY, sw_interface_add_del_mac_address_reply) \
1609 _(HW_INTERFACE_SET_MTU_REPLY, hw_interface_set_mtu_reply)               \
1610 _(SW_INTERFACE_GET_TABLE_REPLY, sw_interface_get_table_reply)           \
1611 _(APP_NAMESPACE_ADD_DEL_REPLY, app_namespace_add_del_reply)             \
1612 _(SESSION_RULE_ADD_DEL_REPLY, session_rule_add_del_reply)               \
1613 _(SESSION_RULES_DETAILS, session_rules_details)                         \
1614 _(IP_CONTAINER_PROXY_ADD_DEL_REPLY, ip_container_proxy_add_del_reply)   \
1615
1616 #define foreach_standalone_reply_msg                                    \
1617 _(SW_INTERFACE_EVENT, sw_interface_event)
1618
1619 typedef struct
1620 {
1621   u8 *name;
1622   u32 value;
1623 } name_sort_t;
1624
1625 #define STR_VTR_OP_CASE(op)     \
1626     case L2_VTR_ ## op:         \
1627         return "" # op;
1628
1629 static const char *
1630 str_vtr_op (u32 vtr_op)
1631 {
1632   switch (vtr_op)
1633     {
1634       STR_VTR_OP_CASE (DISABLED);
1635       STR_VTR_OP_CASE (PUSH_1);
1636       STR_VTR_OP_CASE (PUSH_2);
1637       STR_VTR_OP_CASE (POP_1);
1638       STR_VTR_OP_CASE (POP_2);
1639       STR_VTR_OP_CASE (TRANSLATE_1_1);
1640       STR_VTR_OP_CASE (TRANSLATE_1_2);
1641       STR_VTR_OP_CASE (TRANSLATE_2_1);
1642       STR_VTR_OP_CASE (TRANSLATE_2_2);
1643     }
1644
1645   return "UNKNOWN";
1646 }
1647
1648 static int
1649 dump_sub_interface_table (vat_main_t * vam)
1650 {
1651   const sw_interface_subif_t *sub = NULL;
1652
1653   if (vam->json_output)
1654     {
1655       clib_warning
1656         ("JSON output supported only for VPE API calls and dump_stats_table");
1657       return -99;
1658     }
1659
1660   print (vam->ofp,
1661          "%-30s%-12s%-11s%-7s%-5s%-9s%-9s%-6s%-8s%-10s%-10s",
1662          "Interface", "sw_if_index",
1663          "sub id", "dot1ad", "tags", "outer id",
1664          "inner id", "exact", "default", "outer any", "inner any");
1665
1666   vec_foreach (sub, vam->sw_if_subif_table)
1667   {
1668     print (vam->ofp,
1669            "%-30s%-12d%-11d%-7s%-5d%-9d%-9d%-6d%-8d%-10d%-10d",
1670            sub->interface_name,
1671            sub->sw_if_index,
1672            sub->sub_id, sub->sub_dot1ad ? "dot1ad" : "dot1q",
1673            sub->sub_number_of_tags, sub->sub_outer_vlan_id,
1674            sub->sub_inner_vlan_id, sub->sub_exact_match, sub->sub_default,
1675            sub->sub_outer_vlan_id_any, sub->sub_inner_vlan_id_any);
1676     if (sub->vtr_op != L2_VTR_DISABLED)
1677       {
1678         print (vam->ofp,
1679                "  vlan-tag-rewrite - op: %-14s [ dot1q: %d "
1680                "tag1: %d tag2: %d ]",
1681                str_vtr_op (sub->vtr_op), sub->vtr_push_dot1q,
1682                sub->vtr_tag1, sub->vtr_tag2);
1683       }
1684   }
1685
1686   return 0;
1687 }
1688
1689 static int
1690 name_sort_cmp (void *a1, void *a2)
1691 {
1692   name_sort_t *n1 = a1;
1693   name_sort_t *n2 = a2;
1694
1695   return strcmp ((char *) n1->name, (char *) n2->name);
1696 }
1697
1698 static int
1699 dump_interface_table (vat_main_t * vam)
1700 {
1701   hash_pair_t *p;
1702   name_sort_t *nses = 0, *ns;
1703
1704   if (vam->json_output)
1705     {
1706       clib_warning
1707         ("JSON output supported only for VPE API calls and dump_stats_table");
1708       return -99;
1709     }
1710
1711   /* *INDENT-OFF* */
1712   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
1713   ({
1714     vec_add2 (nses, ns, 1);
1715     ns->name = (u8 *)(p->key);
1716     ns->value = (u32) p->value[0];
1717   }));
1718   /* *INDENT-ON* */
1719
1720   vec_sort_with_function (nses, name_sort_cmp);
1721
1722   print (vam->ofp, "%-25s%-15s", "Interface", "sw_if_index");
1723   vec_foreach (ns, nses)
1724   {
1725     print (vam->ofp, "%-25s%-15d", ns->name, ns->value);
1726   }
1727   vec_free (nses);
1728   return 0;
1729 }
1730
1731 static int
1732 dump_ip_table (vat_main_t * vam, int is_ipv6)
1733 {
1734   const ip_details_t *det = NULL;
1735   const ip_address_details_t *address = NULL;
1736   u32 i = ~0;
1737
1738   print (vam->ofp, "%-12s", "sw_if_index");
1739
1740   vec_foreach (det, vam->ip_details_by_sw_if_index[is_ipv6])
1741   {
1742     i++;
1743     if (!det->present)
1744       {
1745         continue;
1746       }
1747     print (vam->ofp, "%-12d", i);
1748     print (vam->ofp, "            %-30s%-13s", "Address", "Prefix length");
1749     if (!det->addr)
1750       {
1751         continue;
1752       }
1753     vec_foreach (address, det->addr)
1754     {
1755       print (vam->ofp,
1756              "            %-30U%-13d",
1757              is_ipv6 ? format_ip6_address : format_ip4_address,
1758              address->ip, address->prefix_length);
1759     }
1760   }
1761
1762   return 0;
1763 }
1764
1765 static int
1766 dump_ipv4_table (vat_main_t * vam)
1767 {
1768   if (vam->json_output)
1769     {
1770       clib_warning
1771         ("JSON output supported only for VPE API calls and dump_stats_table");
1772       return -99;
1773     }
1774
1775   return dump_ip_table (vam, 0);
1776 }
1777
1778 static int
1779 dump_ipv6_table (vat_main_t * vam)
1780 {
1781   if (vam->json_output)
1782     {
1783       clib_warning
1784         ("JSON output supported only for VPE API calls and dump_stats_table");
1785       return -99;
1786     }
1787
1788   return dump_ip_table (vam, 1);
1789 }
1790
1791 /*
1792  * Pass CLI buffers directly in the CLI_INBAND API message,
1793  * instead of an additional shared memory area.
1794  */
1795 static int
1796 exec_inband (vat_main_t * vam)
1797 {
1798   vl_api_cli_inband_t *mp;
1799   unformat_input_t *i = vam->input;
1800   int ret;
1801
1802   if (vec_len (i->buffer) == 0)
1803     return -1;
1804
1805   if (vam->exec_mode == 0 && unformat (i, "mode"))
1806     {
1807       vam->exec_mode = 1;
1808       return 0;
1809     }
1810   if (vam->exec_mode == 1 && (unformat (i, "exit") || unformat (i, "quit")))
1811     {
1812       vam->exec_mode = 0;
1813       return 0;
1814     }
1815
1816   /*
1817    * In order for the CLI command to work, it
1818    * must be a vector ending in \n, not a C-string ending
1819    * in \n\0.
1820    */
1821   M2 (CLI_INBAND, mp, vec_len (vam->input->buffer));
1822   vl_api_vec_to_api_string (vam->input->buffer, &mp->cmd);
1823
1824   S (mp);
1825   W (ret);
1826   /* json responses may or may not include a useful reply... */
1827   if (vec_len (vam->cmd_reply))
1828     print (vam->ofp, "%v", (char *) (vam->cmd_reply));
1829   return ret;
1830 }
1831
1832 int
1833 exec (vat_main_t * vam)
1834 {
1835   return exec_inband (vam);
1836 }
1837
1838 static int
1839 api_create_loopback (vat_main_t * vam)
1840 {
1841   unformat_input_t *i = vam->input;
1842   vl_api_create_loopback_t *mp;
1843   vl_api_create_loopback_instance_t *mp_lbi;
1844   u8 mac_address[6];
1845   u8 mac_set = 0;
1846   u8 is_specified = 0;
1847   u32 user_instance = 0;
1848   int ret;
1849
1850   clib_memset (mac_address, 0, sizeof (mac_address));
1851
1852   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1853     {
1854       if (unformat (i, "mac %U", unformat_ethernet_address, mac_address))
1855         mac_set = 1;
1856       if (unformat (i, "instance %d", &user_instance))
1857         is_specified = 1;
1858       else
1859         break;
1860     }
1861
1862   if (is_specified)
1863     {
1864       M (CREATE_LOOPBACK_INSTANCE, mp_lbi);
1865       mp_lbi->is_specified = is_specified;
1866       if (is_specified)
1867         mp_lbi->user_instance = htonl (user_instance);
1868       if (mac_set)
1869         clib_memcpy (mp_lbi->mac_address, mac_address, sizeof (mac_address));
1870       S (mp_lbi);
1871     }
1872   else
1873     {
1874       /* Construct the API message */
1875       M (CREATE_LOOPBACK, mp);
1876       if (mac_set)
1877         clib_memcpy (mp->mac_address, mac_address, sizeof (mac_address));
1878       S (mp);
1879     }
1880
1881   W (ret);
1882   return ret;
1883 }
1884
1885 static int
1886 api_delete_loopback (vat_main_t * vam)
1887 {
1888   unformat_input_t *i = vam->input;
1889   vl_api_delete_loopback_t *mp;
1890   u32 sw_if_index = ~0;
1891   int ret;
1892
1893   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1894     {
1895       if (unformat (i, "sw_if_index %d", &sw_if_index))
1896         ;
1897       else
1898         break;
1899     }
1900
1901   if (sw_if_index == ~0)
1902     {
1903       errmsg ("missing sw_if_index");
1904       return -99;
1905     }
1906
1907   /* Construct the API message */
1908   M (DELETE_LOOPBACK, mp);
1909   mp->sw_if_index = ntohl (sw_if_index);
1910
1911   S (mp);
1912   W (ret);
1913   return ret;
1914 }
1915
1916 static int
1917 api_want_interface_events (vat_main_t * vam)
1918 {
1919   unformat_input_t *i = vam->input;
1920   vl_api_want_interface_events_t *mp;
1921   int enable = -1;
1922   int ret;
1923
1924   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1925     {
1926       if (unformat (i, "enable"))
1927         enable = 1;
1928       else if (unformat (i, "disable"))
1929         enable = 0;
1930       else
1931         break;
1932     }
1933
1934   if (enable == -1)
1935     {
1936       errmsg ("missing enable|disable");
1937       return -99;
1938     }
1939
1940   M (WANT_INTERFACE_EVENTS, mp);
1941   mp->enable_disable = enable;
1942
1943   vam->interface_event_display = enable;
1944
1945   S (mp);
1946   W (ret);
1947   return ret;
1948 }
1949
1950
1951 /* Note: non-static, called once to set up the initial intfc table */
1952 int
1953 api_sw_interface_dump (vat_main_t * vam)
1954 {
1955   vl_api_sw_interface_dump_t *mp;
1956   vl_api_control_ping_t *mp_ping;
1957   hash_pair_t *p;
1958   name_sort_t *nses = 0, *ns;
1959   sw_interface_subif_t *sub = NULL;
1960   int ret;
1961
1962   /* Toss the old name table */
1963   /* *INDENT-OFF* */
1964   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
1965   ({
1966     vec_add2 (nses, ns, 1);
1967     ns->name = (u8 *)(p->key);
1968     ns->value = (u32) p->value[0];
1969   }));
1970   /* *INDENT-ON* */
1971
1972   hash_free (vam->sw_if_index_by_interface_name);
1973
1974   vec_foreach (ns, nses) vec_free (ns->name);
1975
1976   vec_free (nses);
1977
1978   vec_foreach (sub, vam->sw_if_subif_table)
1979   {
1980     vec_free (sub->interface_name);
1981   }
1982   vec_free (vam->sw_if_subif_table);
1983
1984   /* recreate the interface name hash table */
1985   vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
1986
1987   /*
1988    * Ask for all interface names. Otherwise, the epic catalog of
1989    * name filters becomes ridiculously long, and vat ends up needing
1990    * to be taught about new interface types.
1991    */
1992   M (SW_INTERFACE_DUMP, mp);
1993   S (mp);
1994
1995   /* Use a control ping for synchronization */
1996   MPING (CONTROL_PING, mp_ping);
1997   S (mp_ping);
1998
1999   W (ret);
2000   return ret;
2001 }
2002
2003 static int
2004 api_sw_interface_set_flags (vat_main_t * vam)
2005 {
2006   unformat_input_t *i = vam->input;
2007   vl_api_sw_interface_set_flags_t *mp;
2008   u32 sw_if_index;
2009   u8 sw_if_index_set = 0;
2010   u8 admin_up = 0;
2011   int ret;
2012
2013   /* Parse args required to build the message */
2014   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2015     {
2016       if (unformat (i, "admin-up"))
2017         admin_up = 1;
2018       else if (unformat (i, "admin-down"))
2019         admin_up = 0;
2020       else
2021         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2022         sw_if_index_set = 1;
2023       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2024         sw_if_index_set = 1;
2025       else
2026         break;
2027     }
2028
2029   if (sw_if_index_set == 0)
2030     {
2031       errmsg ("missing interface name or sw_if_index");
2032       return -99;
2033     }
2034
2035   /* Construct the API message */
2036   M (SW_INTERFACE_SET_FLAGS, mp);
2037   mp->sw_if_index = ntohl (sw_if_index);
2038   mp->flags = ntohl ((admin_up) ? IF_STATUS_API_FLAG_ADMIN_UP : 0);
2039
2040   /* send it... */
2041   S (mp);
2042
2043   /* Wait for a reply, return the good/bad news... */
2044   W (ret);
2045   return ret;
2046 }
2047
2048 static int
2049 api_sw_interface_set_rx_placement (vat_main_t * vam)
2050 {
2051   unformat_input_t *i = vam->input;
2052   vl_api_sw_interface_set_rx_placement_t *mp;
2053   u32 sw_if_index;
2054   u8 sw_if_index_set = 0;
2055   int ret;
2056   u8 is_main = 0;
2057   u32 queue_id, thread_index;
2058
2059   /* Parse args required to build the message */
2060   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2061     {
2062       if (unformat (i, "queue %d", &queue_id))
2063         ;
2064       else if (unformat (i, "main"))
2065         is_main = 1;
2066       else if (unformat (i, "worker %d", &thread_index))
2067         ;
2068       else
2069         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2070         sw_if_index_set = 1;
2071       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2072         sw_if_index_set = 1;
2073       else
2074         break;
2075     }
2076
2077   if (sw_if_index_set == 0)
2078     {
2079       errmsg ("missing interface name or sw_if_index");
2080       return -99;
2081     }
2082
2083   if (is_main)
2084     thread_index = 0;
2085   /* Construct the API message */
2086   M (SW_INTERFACE_SET_RX_PLACEMENT, mp);
2087   mp->sw_if_index = ntohl (sw_if_index);
2088   mp->worker_id = ntohl (thread_index);
2089   mp->queue_id = ntohl (queue_id);
2090   mp->is_main = is_main;
2091
2092   /* send it... */
2093   S (mp);
2094   /* Wait for a reply, return the good/bad news... */
2095   W (ret);
2096   return ret;
2097 }
2098
2099 static void vl_api_sw_interface_rx_placement_details_t_handler
2100   (vl_api_sw_interface_rx_placement_details_t * mp)
2101 {
2102   vat_main_t *vam = &vat_main;
2103   u32 worker_id = ntohl (mp->worker_id);
2104
2105   print (vam->ofp,
2106          "\n%-11d %-11s %-6d %-5d %-9s",
2107          ntohl (mp->sw_if_index), (worker_id == 0) ? "main" : "worker",
2108          worker_id, ntohl (mp->queue_id),
2109          (mp->mode ==
2110           1) ? "polling" : ((mp->mode == 2) ? "interrupt" : "adaptive"));
2111 }
2112
2113 static void vl_api_sw_interface_rx_placement_details_t_handler_json
2114   (vl_api_sw_interface_rx_placement_details_t * mp)
2115 {
2116   vat_main_t *vam = &vat_main;
2117   vat_json_node_t *node = NULL;
2118
2119   if (VAT_JSON_ARRAY != vam->json_tree.type)
2120     {
2121       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
2122       vat_json_init_array (&vam->json_tree);
2123     }
2124   node = vat_json_array_add (&vam->json_tree);
2125
2126   vat_json_init_object (node);
2127   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
2128   vat_json_object_add_uint (node, "worker_id", ntohl (mp->worker_id));
2129   vat_json_object_add_uint (node, "queue_id", ntohl (mp->queue_id));
2130   vat_json_object_add_uint (node, "mode", mp->mode);
2131 }
2132
2133 static int
2134 api_sw_interface_rx_placement_dump (vat_main_t * vam)
2135 {
2136   unformat_input_t *i = vam->input;
2137   vl_api_sw_interface_rx_placement_dump_t *mp;
2138   vl_api_control_ping_t *mp_ping;
2139   int ret;
2140   u32 sw_if_index;
2141   u8 sw_if_index_set = 0;
2142
2143   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2144     {
2145       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2146         sw_if_index_set++;
2147       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2148         sw_if_index_set++;
2149       else
2150         break;
2151     }
2152
2153   print (vam->ofp,
2154          "\n%-11s %-11s %-6s %-5s %-4s",
2155          "sw_if_index", "main/worker", "thread", "queue", "mode");
2156
2157   /* Dump Interface rx placement */
2158   M (SW_INTERFACE_RX_PLACEMENT_DUMP, mp);
2159
2160   if (sw_if_index_set)
2161     mp->sw_if_index = htonl (sw_if_index);
2162   else
2163     mp->sw_if_index = ~0;
2164
2165   S (mp);
2166
2167   /* Use a control ping for synchronization */
2168   MPING (CONTROL_PING, mp_ping);
2169   S (mp_ping);
2170
2171   W (ret);
2172   return ret;
2173 }
2174
2175 static int
2176 api_sw_interface_clear_stats (vat_main_t * vam)
2177 {
2178   unformat_input_t *i = vam->input;
2179   vl_api_sw_interface_clear_stats_t *mp;
2180   u32 sw_if_index;
2181   u8 sw_if_index_set = 0;
2182   int ret;
2183
2184   /* Parse args required to build the message */
2185   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2186     {
2187       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2188         sw_if_index_set = 1;
2189       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2190         sw_if_index_set = 1;
2191       else
2192         break;
2193     }
2194
2195   /* Construct the API message */
2196   M (SW_INTERFACE_CLEAR_STATS, mp);
2197
2198   if (sw_if_index_set == 1)
2199     mp->sw_if_index = ntohl (sw_if_index);
2200   else
2201     mp->sw_if_index = ~0;
2202
2203   /* send it... */
2204   S (mp);
2205
2206   /* Wait for a reply, return the good/bad news... */
2207   W (ret);
2208   return ret;
2209 }
2210
2211 static int
2212 api_sw_interface_add_del_address (vat_main_t * vam)
2213 {
2214   unformat_input_t *i = vam->input;
2215   vl_api_sw_interface_add_del_address_t *mp;
2216   u32 sw_if_index;
2217   u8 sw_if_index_set = 0;
2218   u8 is_add = 1, del_all = 0;
2219   u32 address_length = 0;
2220   u8 v4_address_set = 0;
2221   u8 v6_address_set = 0;
2222   ip4_address_t v4address;
2223   ip6_address_t v6address;
2224   int ret;
2225
2226   /* Parse args required to build the message */
2227   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2228     {
2229       if (unformat (i, "del-all"))
2230         del_all = 1;
2231       else if (unformat (i, "del"))
2232         is_add = 0;
2233       else
2234         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2235         sw_if_index_set = 1;
2236       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2237         sw_if_index_set = 1;
2238       else if (unformat (i, "%U/%d",
2239                          unformat_ip4_address, &v4address, &address_length))
2240         v4_address_set = 1;
2241       else if (unformat (i, "%U/%d",
2242                          unformat_ip6_address, &v6address, &address_length))
2243         v6_address_set = 1;
2244       else
2245         break;
2246     }
2247
2248   if (sw_if_index_set == 0)
2249     {
2250       errmsg ("missing interface name or sw_if_index");
2251       return -99;
2252     }
2253   if (v4_address_set && v6_address_set)
2254     {
2255       errmsg ("both v4 and v6 addresses set");
2256       return -99;
2257     }
2258   if (!v4_address_set && !v6_address_set && !del_all)
2259     {
2260       errmsg ("no addresses set");
2261       return -99;
2262     }
2263
2264   /* Construct the API message */
2265   M (SW_INTERFACE_ADD_DEL_ADDRESS, mp);
2266
2267   mp->sw_if_index = ntohl (sw_if_index);
2268   mp->is_add = is_add;
2269   mp->del_all = del_all;
2270   if (v6_address_set)
2271     {
2272       mp->prefix.address.af = ADDRESS_IP6;
2273       clib_memcpy (mp->prefix.address.un.ip6, &v6address, sizeof (v6address));
2274     }
2275   else
2276     {
2277       mp->prefix.address.af = ADDRESS_IP4;
2278       clib_memcpy (mp->prefix.address.un.ip4, &v4address, sizeof (v4address));
2279     }
2280   mp->prefix.len = address_length;
2281
2282   /* send it... */
2283   S (mp);
2284
2285   /* Wait for a reply, return good/bad news  */
2286   W (ret);
2287   return ret;
2288 }
2289
2290 static int
2291 api_sw_interface_set_table (vat_main_t * vam)
2292 {
2293   unformat_input_t *i = vam->input;
2294   vl_api_sw_interface_set_table_t *mp;
2295   u32 sw_if_index, vrf_id = 0;
2296   u8 sw_if_index_set = 0;
2297   u8 is_ipv6 = 0;
2298   int ret;
2299
2300   /* Parse args required to build the message */
2301   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2302     {
2303       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2304         sw_if_index_set = 1;
2305       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2306         sw_if_index_set = 1;
2307       else if (unformat (i, "vrf %d", &vrf_id))
2308         ;
2309       else if (unformat (i, "ipv6"))
2310         is_ipv6 = 1;
2311       else
2312         break;
2313     }
2314
2315   if (sw_if_index_set == 0)
2316     {
2317       errmsg ("missing interface name or sw_if_index");
2318       return -99;
2319     }
2320
2321   /* Construct the API message */
2322   M (SW_INTERFACE_SET_TABLE, mp);
2323
2324   mp->sw_if_index = ntohl (sw_if_index);
2325   mp->is_ipv6 = is_ipv6;
2326   mp->vrf_id = ntohl (vrf_id);
2327
2328   /* send it... */
2329   S (mp);
2330
2331   /* Wait for a reply... */
2332   W (ret);
2333   return ret;
2334 }
2335
2336 static void vl_api_sw_interface_get_table_reply_t_handler
2337   (vl_api_sw_interface_get_table_reply_t * mp)
2338 {
2339   vat_main_t *vam = &vat_main;
2340
2341   print (vam->ofp, "%d", ntohl (mp->vrf_id));
2342
2343   vam->retval = ntohl (mp->retval);
2344   vam->result_ready = 1;
2345
2346 }
2347
2348 static void vl_api_sw_interface_get_table_reply_t_handler_json
2349   (vl_api_sw_interface_get_table_reply_t * mp)
2350 {
2351   vat_main_t *vam = &vat_main;
2352   vat_json_node_t node;
2353
2354   vat_json_init_object (&node);
2355   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2356   vat_json_object_add_int (&node, "vrf_id", ntohl (mp->vrf_id));
2357
2358   vat_json_print (vam->ofp, &node);
2359   vat_json_free (&node);
2360
2361   vam->retval = ntohl (mp->retval);
2362   vam->result_ready = 1;
2363 }
2364
2365 static int
2366 api_sw_interface_get_table (vat_main_t * vam)
2367 {
2368   unformat_input_t *i = vam->input;
2369   vl_api_sw_interface_get_table_t *mp;
2370   u32 sw_if_index;
2371   u8 sw_if_index_set = 0;
2372   u8 is_ipv6 = 0;
2373   int ret;
2374
2375   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2376     {
2377       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2378         sw_if_index_set = 1;
2379       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2380         sw_if_index_set = 1;
2381       else if (unformat (i, "ipv6"))
2382         is_ipv6 = 1;
2383       else
2384         break;
2385     }
2386
2387   if (sw_if_index_set == 0)
2388     {
2389       errmsg ("missing interface name or sw_if_index");
2390       return -99;
2391     }
2392
2393   M (SW_INTERFACE_GET_TABLE, mp);
2394   mp->sw_if_index = htonl (sw_if_index);
2395   mp->is_ipv6 = is_ipv6;
2396
2397   S (mp);
2398   W (ret);
2399   return ret;
2400 }
2401
2402 uword
2403 unformat_vlib_pci_addr (unformat_input_t *input, va_list *args)
2404 {
2405   vlib_pci_addr_t *addr = va_arg (*args, vlib_pci_addr_t *);
2406   u32 x[4];
2407
2408   if (!unformat (input, "%x:%x:%x.%x", &x[0], &x[1], &x[2], &x[3]))
2409     return 0;
2410
2411   addr->domain = x[0];
2412   addr->bus = x[1];
2413   addr->slot = x[2];
2414   addr->function = x[3];
2415
2416   return 1;
2417 }
2418
2419 static int
2420 api_ip_table_add_del (vat_main_t *vam)
2421 {
2422   unformat_input_t *i = vam->input;
2423   vl_api_ip_table_add_del_t *mp;
2424   u32 table_id = ~0;
2425   u8 is_ipv6 = 0;
2426   u8 is_add = 1;
2427   int ret = 0;
2428
2429   /* Parse args required to build the message */
2430   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2431     {
2432       if (unformat (i, "ipv6"))
2433         is_ipv6 = 1;
2434       else if (unformat (i, "del"))
2435         is_add = 0;
2436       else if (unformat (i, "add"))
2437         is_add = 1;
2438       else if (unformat (i, "table %d", &table_id))
2439         ;
2440       else
2441         {
2442           clib_warning ("parse error '%U'", format_unformat_error, i);
2443           return -99;
2444         }
2445     }
2446
2447   if (~0 == table_id)
2448     {
2449       errmsg ("missing table-ID");
2450       return -99;
2451     }
2452
2453   /* Construct the API message */
2454   M (IP_TABLE_ADD_DEL, mp);
2455
2456   mp->table.table_id = ntohl (table_id);
2457   mp->table.is_ip6 = is_ipv6;
2458   mp->is_add = is_add;
2459
2460   /* send it... */
2461   S (mp);
2462
2463   /* Wait for a reply... */
2464   W (ret);
2465
2466   return ret;
2467 }
2468
2469 uword
2470 unformat_fib_path (unformat_input_t *input, va_list *args)
2471 {
2472   vat_main_t *vam = va_arg (*args, vat_main_t *);
2473   vl_api_fib_path_t *path = va_arg (*args, vl_api_fib_path_t *);
2474   u32 weight, preference;
2475   mpls_label_t out_label;
2476
2477   clib_memset (path, 0, sizeof (*path));
2478   path->weight = 1;
2479   path->sw_if_index = ~0;
2480   path->rpf_id = ~0;
2481   path->n_labels = 0;
2482
2483   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2484     {
2485       if (unformat (input, "%U %U", unformat_vl_api_ip4_address,
2486                     &path->nh.address.ip4, api_unformat_sw_if_index, vam,
2487                     &path->sw_if_index))
2488         {
2489           path->proto = FIB_API_PATH_NH_PROTO_IP4;
2490         }
2491       else if (unformat (input, "%U %U",
2492                          unformat_vl_api_ip6_address,
2493                          &path->nh.address.ip6,
2494                          api_unformat_sw_if_index, vam, &path->sw_if_index))
2495         {
2496           path->proto = FIB_API_PATH_NH_PROTO_IP6;
2497         }
2498       else if (unformat (input, "weight %u", &weight))
2499         {
2500           path->weight = weight;
2501         }
2502       else if (unformat (input, "preference %u", &preference))
2503         {
2504           path->preference = preference;
2505         }
2506       else if (unformat (input, "%U next-hop-table %d",
2507                          unformat_vl_api_ip4_address,
2508                          &path->nh.address.ip4, &path->table_id))
2509         {
2510           path->proto = FIB_API_PATH_NH_PROTO_IP4;
2511         }
2512       else if (unformat (input, "%U next-hop-table %d",
2513                          unformat_vl_api_ip6_address,
2514                          &path->nh.address.ip6, &path->table_id))
2515         {
2516           path->proto = FIB_API_PATH_NH_PROTO_IP6;
2517         }
2518       else if (unformat (input, "%U",
2519                          unformat_vl_api_ip4_address, &path->nh.address.ip4))
2520         {
2521           /*
2522            * the recursive next-hops are by default in the default table
2523            */
2524           path->table_id = 0;
2525           path->sw_if_index = ~0;
2526           path->proto = FIB_API_PATH_NH_PROTO_IP4;
2527         }
2528       else if (unformat (input, "%U",
2529                          unformat_vl_api_ip6_address, &path->nh.address.ip6))
2530         {
2531           /*
2532            * the recursive next-hops are by default in the default table
2533            */
2534           path->table_id = 0;
2535           path->sw_if_index = ~0;
2536           path->proto = FIB_API_PATH_NH_PROTO_IP6;
2537         }
2538       else if (unformat (input, "resolve-via-host"))
2539         {
2540           path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_HOST;
2541         }
2542       else if (unformat (input, "resolve-via-attached"))
2543         {
2544           path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_ATTACHED;
2545         }
2546       else if (unformat (input, "ip4-lookup-in-table %d", &path->table_id))
2547         {
2548           path->type = FIB_API_PATH_TYPE_LOCAL;
2549           path->sw_if_index = ~0;
2550           path->proto = FIB_API_PATH_NH_PROTO_IP4;
2551         }
2552       else if (unformat (input, "ip6-lookup-in-table %d", &path->table_id))
2553         {
2554           path->type = FIB_API_PATH_TYPE_LOCAL;
2555           path->sw_if_index = ~0;
2556           path->proto = FIB_API_PATH_NH_PROTO_IP6;
2557         }
2558       else if (unformat (input, "sw_if_index %d", &path->sw_if_index))
2559         ;
2560       else if (unformat (input, "via-label %d", &path->nh.via_label))
2561         {
2562           path->proto = FIB_API_PATH_NH_PROTO_MPLS;
2563           path->sw_if_index = ~0;
2564         }
2565       else if (unformat (input, "l2-input-on %d", &path->sw_if_index))
2566         {
2567           path->proto = FIB_API_PATH_NH_PROTO_ETHERNET;
2568           path->type = FIB_API_PATH_TYPE_INTERFACE_RX;
2569         }
2570       else if (unformat (input, "local"))
2571         {
2572           path->type = FIB_API_PATH_TYPE_LOCAL;
2573         }
2574       else if (unformat (input, "out-labels"))
2575         {
2576           while (unformat (input, "%d", &out_label))
2577             {
2578               path->label_stack[path->n_labels].label = out_label;
2579               path->label_stack[path->n_labels].is_uniform = 0;
2580               path->label_stack[path->n_labels].ttl = 64;
2581               path->n_labels++;
2582             }
2583         }
2584       else if (unformat (input, "via"))
2585         {
2586           /* new path, back up and return */
2587           unformat_put_input (input);
2588           unformat_put_input (input);
2589           unformat_put_input (input);
2590           unformat_put_input (input);
2591           break;
2592         }
2593       else
2594         {
2595           return (0);
2596         }
2597     }
2598
2599   path->proto = ntohl (path->proto);
2600   path->type = ntohl (path->type);
2601   path->flags = ntohl (path->flags);
2602   path->table_id = ntohl (path->table_id);
2603   path->sw_if_index = ntohl (path->sw_if_index);
2604
2605   return (1);
2606 }
2607
2608 static int
2609 api_ip_route_add_del (vat_main_t * vam)
2610 {
2611   unformat_input_t *i = vam->input;
2612   vl_api_ip_route_add_del_t *mp;
2613   u32 vrf_id = 0;
2614   u8 is_add = 1;
2615   u8 is_multipath = 0;
2616   u8 prefix_set = 0;
2617   u8 path_count = 0;
2618   vl_api_prefix_t pfx = { };
2619   vl_api_fib_path_t paths[8];
2620   int count = 1;
2621   int j;
2622   f64 before = 0;
2623   u32 random_add_del = 0;
2624   u32 *random_vector = 0;
2625   u32 random_seed = 0xdeaddabe;
2626
2627   /* Parse args required to build the message */
2628   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2629     {
2630       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
2631         prefix_set = 1;
2632       else if (unformat (i, "del"))
2633         is_add = 0;
2634       else if (unformat (i, "add"))
2635         is_add = 1;
2636       else if (unformat (i, "vrf %d", &vrf_id))
2637         ;
2638       else if (unformat (i, "count %d", &count))
2639         ;
2640       else if (unformat (i, "random"))
2641         random_add_del = 1;
2642       else if (unformat (i, "multipath"))
2643         is_multipath = 1;
2644       else if (unformat (i, "seed %d", &random_seed))
2645         ;
2646       else
2647         if (unformat
2648             (i, "via %U", unformat_fib_path, vam, &paths[path_count]))
2649         {
2650           path_count++;
2651           if (8 == path_count)
2652             {
2653               errmsg ("max 8 paths");
2654               return -99;
2655             }
2656         }
2657       else
2658         {
2659           clib_warning ("parse error '%U'", format_unformat_error, i);
2660           return -99;
2661         }
2662     }
2663
2664   if (!path_count)
2665     {
2666       errmsg ("specify a path; via ...");
2667       return -99;
2668     }
2669   if (prefix_set == 0)
2670     {
2671       errmsg ("missing prefix");
2672       return -99;
2673     }
2674
2675   /* Generate a pile of unique, random routes */
2676   if (random_add_del)
2677     {
2678       ip4_address_t *i = (ip4_address_t *) & paths[0].nh.address.ip4;
2679       u32 this_random_address;
2680       uword *random_hash;
2681
2682       random_hash = hash_create (count, sizeof (uword));
2683
2684       hash_set (random_hash, i->as_u32, 1);
2685       for (j = 0; j <= count; j++)
2686         {
2687           do
2688             {
2689               this_random_address = random_u32 (&random_seed);
2690               this_random_address =
2691                 clib_host_to_net_u32 (this_random_address);
2692             }
2693           while (hash_get (random_hash, this_random_address));
2694           vec_add1 (random_vector, this_random_address);
2695           hash_set (random_hash, this_random_address, 1);
2696         }
2697       hash_free (random_hash);
2698       set_ip4_address (&pfx.address, random_vector[0]);
2699     }
2700
2701   if (count > 1)
2702     {
2703       /* Turn on async mode */
2704       vam->async_mode = 1;
2705       vam->async_errors = 0;
2706       before = vat_time_now (vam);
2707     }
2708
2709   for (j = 0; j < count; j++)
2710     {
2711       /* Construct the API message */
2712       M2 (IP_ROUTE_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
2713
2714       mp->is_add = is_add;
2715       mp->is_multipath = is_multipath;
2716
2717       clib_memcpy (&mp->route.prefix, &pfx, sizeof (pfx));
2718       mp->route.table_id = ntohl (vrf_id);
2719       mp->route.n_paths = path_count;
2720
2721       clib_memcpy (&mp->route.paths, &paths, sizeof (paths[0]) * path_count);
2722
2723       if (random_add_del)
2724         set_ip4_address (&pfx.address, random_vector[j + 1]);
2725       else
2726         increment_address (&pfx.address);
2727       /* send it... */
2728       S (mp);
2729       /* If we receive SIGTERM, stop now... */
2730       if (vam->do_exit)
2731         break;
2732     }
2733
2734   /* When testing multiple add/del ops, use a control-ping to sync */
2735   if (count > 1)
2736     {
2737       vl_api_control_ping_t *mp_ping;
2738       f64 after;
2739       f64 timeout;
2740
2741       /* Shut off async mode */
2742       vam->async_mode = 0;
2743
2744       MPING (CONTROL_PING, mp_ping);
2745       S (mp_ping);
2746
2747       timeout = vat_time_now (vam) + 1.0;
2748       while (vat_time_now (vam) < timeout)
2749         if (vam->result_ready == 1)
2750           goto out;
2751       vam->retval = -99;
2752
2753     out:
2754       if (vam->retval == -99)
2755         errmsg ("timeout");
2756
2757       if (vam->async_errors > 0)
2758         {
2759           errmsg ("%d asynchronous errors", vam->async_errors);
2760           vam->retval = -98;
2761         }
2762       vam->async_errors = 0;
2763       after = vat_time_now (vam);
2764
2765       /* slim chance, but we might have eaten SIGTERM on the first iteration */
2766       if (j > 0)
2767         count = j;
2768
2769       print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec",
2770              count, after - before, count / (after - before));
2771     }
2772   else
2773     {
2774       int ret;
2775
2776       /* Wait for a reply... */
2777       W (ret);
2778       return ret;
2779     }
2780
2781   /* Return the good/bad news */
2782   return (vam->retval);
2783 }
2784
2785 static int
2786 api_ip_mroute_add_del (vat_main_t * vam)
2787 {
2788   unformat_input_t *i = vam->input;
2789   u8 path_set = 0, prefix_set = 0, is_add = 1;
2790   vl_api_ip_mroute_add_del_t *mp;
2791   mfib_entry_flags_t eflags = 0;
2792   vl_api_mfib_path_t path;
2793   vl_api_mprefix_t pfx = { };
2794   u32 vrf_id = 0;
2795   int ret;
2796
2797   /* Parse args required to build the message */
2798   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2799     {
2800       if (unformat (i, "%U", unformat_vl_api_mprefix, &pfx))
2801         {
2802           prefix_set = 1;
2803           pfx.grp_address_length = htons (pfx.grp_address_length);
2804         }
2805       else if (unformat (i, "del"))
2806         is_add = 0;
2807       else if (unformat (i, "add"))
2808         is_add = 1;
2809       else if (unformat (i, "vrf %d", &vrf_id))
2810         ;
2811       else if (unformat (i, "%U", unformat_mfib_itf_flags, &path.itf_flags))
2812         path.itf_flags = htonl (path.itf_flags);
2813       else if (unformat (i, "%U", unformat_mfib_entry_flags, &eflags))
2814         ;
2815       else if (unformat (i, "via %U", unformat_fib_path, vam, &path.path))
2816         path_set = 1;
2817       else
2818         {
2819           clib_warning ("parse error '%U'", format_unformat_error, i);
2820           return -99;
2821         }
2822     }
2823
2824   if (prefix_set == 0)
2825     {
2826       errmsg ("missing addresses\n");
2827       return -99;
2828     }
2829   if (path_set == 0)
2830     {
2831       errmsg ("missing path\n");
2832       return -99;
2833     }
2834
2835   /* Construct the API message */
2836   M (IP_MROUTE_ADD_DEL, mp);
2837
2838   mp->is_add = is_add;
2839   mp->is_multipath = 1;
2840
2841   clib_memcpy (&mp->route.prefix, &pfx, sizeof (pfx));
2842   mp->route.table_id = htonl (vrf_id);
2843   mp->route.n_paths = 1;
2844   mp->route.entry_flags = htonl (eflags);
2845
2846   clib_memcpy (&mp->route.paths, &path, sizeof (path));
2847
2848   /* send it... */
2849   S (mp);
2850   /* Wait for a reply... */
2851   W (ret);
2852   return ret;
2853 }
2854
2855 static int
2856 api_sw_interface_set_unnumbered (vat_main_t * vam)
2857 {
2858   unformat_input_t *i = vam->input;
2859   vl_api_sw_interface_set_unnumbered_t *mp;
2860   u32 sw_if_index;
2861   u32 unnum_sw_index = ~0;
2862   u8 is_add = 1;
2863   u8 sw_if_index_set = 0;
2864   int ret;
2865
2866   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2867     {
2868       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2869         sw_if_index_set = 1;
2870       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2871         sw_if_index_set = 1;
2872       else if (unformat (i, "unnum_if_index %d", &unnum_sw_index))
2873         ;
2874       else if (unformat (i, "del"))
2875         is_add = 0;
2876       else
2877         {
2878           clib_warning ("parse error '%U'", format_unformat_error, i);
2879           return -99;
2880         }
2881     }
2882
2883   if (sw_if_index_set == 0)
2884     {
2885       errmsg ("missing interface name or sw_if_index");
2886       return -99;
2887     }
2888
2889   M (SW_INTERFACE_SET_UNNUMBERED, mp);
2890
2891   mp->sw_if_index = ntohl (sw_if_index);
2892   mp->unnumbered_sw_if_index = ntohl (unnum_sw_index);
2893   mp->is_add = is_add;
2894
2895   S (mp);
2896   W (ret);
2897   return ret;
2898 }
2899
2900
2901 static int
2902 api_create_vlan_subif (vat_main_t * vam)
2903 {
2904   unformat_input_t *i = vam->input;
2905   vl_api_create_vlan_subif_t *mp;
2906   u32 sw_if_index;
2907   u8 sw_if_index_set = 0;
2908   u32 vlan_id;
2909   u8 vlan_id_set = 0;
2910   int ret;
2911
2912   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2913     {
2914       if (unformat (i, "sw_if_index %d", &sw_if_index))
2915         sw_if_index_set = 1;
2916       else
2917         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2918         sw_if_index_set = 1;
2919       else if (unformat (i, "vlan %d", &vlan_id))
2920         vlan_id_set = 1;
2921       else
2922         {
2923           clib_warning ("parse error '%U'", format_unformat_error, i);
2924           return -99;
2925         }
2926     }
2927
2928   if (sw_if_index_set == 0)
2929     {
2930       errmsg ("missing interface name or sw_if_index");
2931       return -99;
2932     }
2933
2934   if (vlan_id_set == 0)
2935     {
2936       errmsg ("missing vlan_id");
2937       return -99;
2938     }
2939   M (CREATE_VLAN_SUBIF, mp);
2940
2941   mp->sw_if_index = ntohl (sw_if_index);
2942   mp->vlan_id = ntohl (vlan_id);
2943
2944   S (mp);
2945   W (ret);
2946   return ret;
2947 }
2948
2949 #define foreach_create_subif_bit                \
2950 _(no_tags)                                      \
2951 _(one_tag)                                      \
2952 _(two_tags)                                     \
2953 _(dot1ad)                                       \
2954 _(exact_match)                                  \
2955 _(default_sub)                                  \
2956 _(outer_vlan_id_any)                            \
2957 _(inner_vlan_id_any)
2958
2959 #define foreach_create_subif_flag               \
2960 _(0, "no_tags")                                 \
2961 _(1, "one_tag")                                 \
2962 _(2, "two_tags")                                \
2963 _(3, "dot1ad")                                  \
2964 _(4, "exact_match")                             \
2965 _(5, "default_sub")                             \
2966 _(6, "outer_vlan_id_any")                       \
2967 _(7, "inner_vlan_id_any")
2968
2969 static int
2970 api_create_subif (vat_main_t * vam)
2971 {
2972   unformat_input_t *i = vam->input;
2973   vl_api_create_subif_t *mp;
2974   u32 sw_if_index;
2975   u8 sw_if_index_set = 0;
2976   u32 sub_id;
2977   u8 sub_id_set = 0;
2978   u32 __attribute__ ((unused)) no_tags = 0;
2979   u32 __attribute__ ((unused)) one_tag = 0;
2980   u32 __attribute__ ((unused)) two_tags = 0;
2981   u32 __attribute__ ((unused)) dot1ad = 0;
2982   u32 __attribute__ ((unused)) exact_match = 0;
2983   u32 __attribute__ ((unused)) default_sub = 0;
2984   u32 __attribute__ ((unused)) outer_vlan_id_any = 0;
2985   u32 __attribute__ ((unused)) inner_vlan_id_any = 0;
2986   u32 tmp;
2987   u16 outer_vlan_id = 0;
2988   u16 inner_vlan_id = 0;
2989   int ret;
2990
2991   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2992     {
2993       if (unformat (i, "sw_if_index %d", &sw_if_index))
2994         sw_if_index_set = 1;
2995       else
2996         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2997         sw_if_index_set = 1;
2998       else if (unformat (i, "sub_id %d", &sub_id))
2999         sub_id_set = 1;
3000       else if (unformat (i, "outer_vlan_id %d", &tmp))
3001         outer_vlan_id = tmp;
3002       else if (unformat (i, "inner_vlan_id %d", &tmp))
3003         inner_vlan_id = tmp;
3004
3005 #define _(a) else if (unformat (i, #a)) a = 1 ;
3006       foreach_create_subif_bit
3007 #undef _
3008         else
3009         {
3010           clib_warning ("parse error '%U'", format_unformat_error, i);
3011           return -99;
3012         }
3013     }
3014
3015   if (sw_if_index_set == 0)
3016     {
3017       errmsg ("missing interface name or sw_if_index");
3018       return -99;
3019     }
3020
3021   if (sub_id_set == 0)
3022     {
3023       errmsg ("missing sub_id");
3024       return -99;
3025     }
3026   M (CREATE_SUBIF, mp);
3027
3028   mp->sw_if_index = ntohl (sw_if_index);
3029   mp->sub_id = ntohl (sub_id);
3030
3031 #define _(a,b) mp->sub_if_flags |= (1 << a);
3032   foreach_create_subif_flag;
3033 #undef _
3034
3035   mp->outer_vlan_id = ntohs (outer_vlan_id);
3036   mp->inner_vlan_id = ntohs (inner_vlan_id);
3037
3038   S (mp);
3039   W (ret);
3040   return ret;
3041 }
3042
3043 static int
3044 api_ip_table_replace_begin (vat_main_t * vam)
3045 {
3046   unformat_input_t *i = vam->input;
3047   vl_api_ip_table_replace_begin_t *mp;
3048   u32 table_id = 0;
3049   u8 is_ipv6 = 0;
3050
3051   int ret;
3052   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3053     {
3054       if (unformat (i, "table %d", &table_id))
3055         ;
3056       else if (unformat (i, "ipv6"))
3057         is_ipv6 = 1;
3058       else
3059         {
3060           clib_warning ("parse error '%U'", format_unformat_error, i);
3061           return -99;
3062         }
3063     }
3064
3065   M (IP_TABLE_REPLACE_BEGIN, mp);
3066
3067   mp->table.table_id = ntohl (table_id);
3068   mp->table.is_ip6 = is_ipv6;
3069
3070   S (mp);
3071   W (ret);
3072   return ret;
3073 }
3074
3075 static int
3076 api_ip_table_flush (vat_main_t * vam)
3077 {
3078   unformat_input_t *i = vam->input;
3079   vl_api_ip_table_flush_t *mp;
3080   u32 table_id = 0;
3081   u8 is_ipv6 = 0;
3082
3083   int ret;
3084   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3085     {
3086       if (unformat (i, "table %d", &table_id))
3087         ;
3088       else if (unformat (i, "ipv6"))
3089         is_ipv6 = 1;
3090       else
3091         {
3092           clib_warning ("parse error '%U'", format_unformat_error, i);
3093           return -99;
3094         }
3095     }
3096
3097   M (IP_TABLE_FLUSH, mp);
3098
3099   mp->table.table_id = ntohl (table_id);
3100   mp->table.is_ip6 = is_ipv6;
3101
3102   S (mp);
3103   W (ret);
3104   return ret;
3105 }
3106
3107 static int
3108 api_ip_table_replace_end (vat_main_t * vam)
3109 {
3110   unformat_input_t *i = vam->input;
3111   vl_api_ip_table_replace_end_t *mp;
3112   u32 table_id = 0;
3113   u8 is_ipv6 = 0;
3114
3115   int ret;
3116   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3117     {
3118       if (unformat (i, "table %d", &table_id))
3119         ;
3120       else if (unformat (i, "ipv6"))
3121         is_ipv6 = 1;
3122       else
3123         {
3124           clib_warning ("parse error '%U'", format_unformat_error, i);
3125           return -99;
3126         }
3127     }
3128
3129   M (IP_TABLE_REPLACE_END, mp);
3130
3131   mp->table.table_id = ntohl (table_id);
3132   mp->table.is_ip6 = is_ipv6;
3133
3134   S (mp);
3135   W (ret);
3136   return ret;
3137 }
3138
3139 static int
3140 api_set_ip_flow_hash (vat_main_t * vam)
3141 {
3142   unformat_input_t *i = vam->input;
3143   vl_api_set_ip_flow_hash_t *mp;
3144   u32 vrf_id = 0;
3145   u8 is_ipv6 = 0;
3146   u8 vrf_id_set = 0;
3147   u8 src = 0;
3148   u8 dst = 0;
3149   u8 sport = 0;
3150   u8 dport = 0;
3151   u8 proto = 0;
3152   u8 reverse = 0;
3153   int ret;
3154
3155   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3156     {
3157       if (unformat (i, "vrf %d", &vrf_id))
3158         vrf_id_set = 1;
3159       else if (unformat (i, "ipv6"))
3160         is_ipv6 = 1;
3161       else if (unformat (i, "src"))
3162         src = 1;
3163       else if (unformat (i, "dst"))
3164         dst = 1;
3165       else if (unformat (i, "sport"))
3166         sport = 1;
3167       else if (unformat (i, "dport"))
3168         dport = 1;
3169       else if (unformat (i, "proto"))
3170         proto = 1;
3171       else if (unformat (i, "reverse"))
3172         reverse = 1;
3173
3174       else
3175         {
3176           clib_warning ("parse error '%U'", format_unformat_error, i);
3177           return -99;
3178         }
3179     }
3180
3181   if (vrf_id_set == 0)
3182     {
3183       errmsg ("missing vrf id");
3184       return -99;
3185     }
3186
3187   M (SET_IP_FLOW_HASH, mp);
3188   mp->src = src;
3189   mp->dst = dst;
3190   mp->sport = sport;
3191   mp->dport = dport;
3192   mp->proto = proto;
3193   mp->reverse = reverse;
3194   mp->vrf_id = ntohl (vrf_id);
3195   mp->is_ipv6 = is_ipv6;
3196
3197   S (mp);
3198   W (ret);
3199   return ret;
3200 }
3201
3202 static int
3203 api_sw_interface_ip6_enable_disable (vat_main_t * vam)
3204 {
3205   unformat_input_t *i = vam->input;
3206   vl_api_sw_interface_ip6_enable_disable_t *mp;
3207   u32 sw_if_index;
3208   u8 sw_if_index_set = 0;
3209   u8 enable = 0;
3210   int ret;
3211
3212   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3213     {
3214       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3215         sw_if_index_set = 1;
3216       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3217         sw_if_index_set = 1;
3218       else if (unformat (i, "enable"))
3219         enable = 1;
3220       else if (unformat (i, "disable"))
3221         enable = 0;
3222       else
3223         {
3224           clib_warning ("parse error '%U'", format_unformat_error, i);
3225           return -99;
3226         }
3227     }
3228
3229   if (sw_if_index_set == 0)
3230     {
3231       errmsg ("missing interface name or sw_if_index");
3232       return -99;
3233     }
3234
3235   M (SW_INTERFACE_IP6_ENABLE_DISABLE, mp);
3236
3237   mp->sw_if_index = ntohl (sw_if_index);
3238   mp->enable = enable;
3239
3240   S (mp);
3241   W (ret);
3242   return ret;
3243 }
3244
3245 u8 is_del;
3246 u8 localsid_addr[16];
3247 u8 end_psp;
3248 u8 behavior;
3249 u32 sw_if_index;
3250 u32 vlan_index;
3251 u32 fib_table;
3252 u8 nh_addr[16];
3253
3254 static int
3255 api_ioam_enable (vat_main_t * vam)
3256 {
3257   unformat_input_t *input = vam->input;
3258   vl_api_ioam_enable_t *mp;
3259   u32 id = 0;
3260   int has_trace_option = 0;
3261   int has_pot_option = 0;
3262   int has_seqno_option = 0;
3263   int has_analyse_option = 0;
3264   int ret;
3265
3266   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3267     {
3268       if (unformat (input, "trace"))
3269         has_trace_option = 1;
3270       else if (unformat (input, "pot"))
3271         has_pot_option = 1;
3272       else if (unformat (input, "seqno"))
3273         has_seqno_option = 1;
3274       else if (unformat (input, "analyse"))
3275         has_analyse_option = 1;
3276       else
3277         break;
3278     }
3279   M (IOAM_ENABLE, mp);
3280   mp->id = htons (id);
3281   mp->seqno = has_seqno_option;
3282   mp->analyse = has_analyse_option;
3283   mp->pot_enable = has_pot_option;
3284   mp->trace_enable = has_trace_option;
3285
3286   S (mp);
3287   W (ret);
3288   return ret;
3289 }
3290
3291
3292 static int
3293 api_ioam_disable (vat_main_t * vam)
3294 {
3295   vl_api_ioam_disable_t *mp;
3296   int ret;
3297
3298   M (IOAM_DISABLE, mp);
3299   S (mp);
3300   W (ret);
3301   return ret;
3302 }
3303
3304 #define foreach_tcp_proto_field                 \
3305 _(src_port)                                     \
3306 _(dst_port)
3307
3308 #define foreach_udp_proto_field                 \
3309 _(src_port)                                     \
3310 _(dst_port)
3311
3312 #define foreach_ip4_proto_field                 \
3313 _(src_address)                                  \
3314 _(dst_address)                                  \
3315 _(tos)                                          \
3316 _(length)                                       \
3317 _(fragment_id)                                  \
3318 _(ttl)                                          \
3319 _(protocol)                                     \
3320 _(checksum)
3321
3322 typedef struct
3323 {
3324   u16 src_port, dst_port;
3325 } tcpudp_header_t;
3326
3327 #if VPP_API_TEST_BUILTIN == 0
3328 uword
3329 unformat_tcp_mask (unformat_input_t * input, va_list * args)
3330 {
3331   u8 **maskp = va_arg (*args, u8 **);
3332   u8 *mask = 0;
3333   u8 found_something = 0;
3334   tcp_header_t *tcp;
3335
3336 #define _(a) u8 a=0;
3337   foreach_tcp_proto_field;
3338 #undef _
3339
3340   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3341     {
3342       if (0);
3343 #define _(a) else if (unformat (input, #a)) a=1;
3344       foreach_tcp_proto_field
3345 #undef _
3346         else
3347         break;
3348     }
3349
3350 #define _(a) found_something += a;
3351   foreach_tcp_proto_field;
3352 #undef _
3353
3354   if (found_something == 0)
3355     return 0;
3356
3357   vec_validate (mask, sizeof (*tcp) - 1);
3358
3359   tcp = (tcp_header_t *) mask;
3360
3361 #define _(a) if (a) clib_memset (&tcp->a, 0xff, sizeof (tcp->a));
3362   foreach_tcp_proto_field;
3363 #undef _
3364
3365   *maskp = mask;
3366   return 1;
3367 }
3368
3369 uword
3370 unformat_udp_mask (unformat_input_t * input, va_list * args)
3371 {
3372   u8 **maskp = va_arg (*args, u8 **);
3373   u8 *mask = 0;
3374   u8 found_something = 0;
3375   udp_header_t *udp;
3376
3377 #define _(a) u8 a=0;
3378   foreach_udp_proto_field;
3379 #undef _
3380
3381   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3382     {
3383       if (0);
3384 #define _(a) else if (unformat (input, #a)) a=1;
3385       foreach_udp_proto_field
3386 #undef _
3387         else
3388         break;
3389     }
3390
3391 #define _(a) found_something += a;
3392   foreach_udp_proto_field;
3393 #undef _
3394
3395   if (found_something == 0)
3396     return 0;
3397
3398   vec_validate (mask, sizeof (*udp) - 1);
3399
3400   udp = (udp_header_t *) mask;
3401
3402 #define _(a) if (a) clib_memset (&udp->a, 0xff, sizeof (udp->a));
3403   foreach_udp_proto_field;
3404 #undef _
3405
3406   *maskp = mask;
3407   return 1;
3408 }
3409
3410 uword
3411 unformat_l4_mask (unformat_input_t * input, va_list * args)
3412 {
3413   u8 **maskp = va_arg (*args, u8 **);
3414   u16 src_port = 0, dst_port = 0;
3415   tcpudp_header_t *tcpudp;
3416
3417   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3418     {
3419       if (unformat (input, "tcp %U", unformat_tcp_mask, maskp))
3420         return 1;
3421       else if (unformat (input, "udp %U", unformat_udp_mask, maskp))
3422         return 1;
3423       else if (unformat (input, "src_port"))
3424         src_port = 0xFFFF;
3425       else if (unformat (input, "dst_port"))
3426         dst_port = 0xFFFF;
3427       else
3428         return 0;
3429     }
3430
3431   if (!src_port && !dst_port)
3432     return 0;
3433
3434   u8 *mask = 0;
3435   vec_validate (mask, sizeof (tcpudp_header_t) - 1);
3436
3437   tcpudp = (tcpudp_header_t *) mask;
3438   tcpudp->src_port = src_port;
3439   tcpudp->dst_port = dst_port;
3440
3441   *maskp = mask;
3442
3443   return 1;
3444 }
3445
3446 uword
3447 unformat_ip4_mask (unformat_input_t * input, va_list * args)
3448 {
3449   u8 **maskp = va_arg (*args, u8 **);
3450   u8 *mask = 0;
3451   u8 found_something = 0;
3452   ip4_header_t *ip;
3453
3454 #define _(a) u8 a=0;
3455   foreach_ip4_proto_field;
3456 #undef _
3457   u8 version = 0;
3458   u8 hdr_length = 0;
3459
3460
3461   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3462     {
3463       if (unformat (input, "version"))
3464         version = 1;
3465       else if (unformat (input, "hdr_length"))
3466         hdr_length = 1;
3467       else if (unformat (input, "src"))
3468         src_address = 1;
3469       else if (unformat (input, "dst"))
3470         dst_address = 1;
3471       else if (unformat (input, "proto"))
3472         protocol = 1;
3473
3474 #define _(a) else if (unformat (input, #a)) a=1;
3475       foreach_ip4_proto_field
3476 #undef _
3477         else
3478         break;
3479     }
3480
3481 #define _(a) found_something += a;
3482   foreach_ip4_proto_field;
3483 #undef _
3484
3485   if (found_something == 0)
3486     return 0;
3487
3488   vec_validate (mask, sizeof (*ip) - 1);
3489
3490   ip = (ip4_header_t *) mask;
3491
3492 #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
3493   foreach_ip4_proto_field;
3494 #undef _
3495
3496   ip->ip_version_and_header_length = 0;
3497
3498   if (version)
3499     ip->ip_version_and_header_length |= 0xF0;
3500
3501   if (hdr_length)
3502     ip->ip_version_and_header_length |= 0x0F;
3503
3504   *maskp = mask;
3505   return 1;
3506 }
3507
3508 #define foreach_ip6_proto_field                 \
3509 _(src_address)                                  \
3510 _(dst_address)                                  \
3511 _(payload_length)                               \
3512 _(hop_limit)                                    \
3513 _(protocol)
3514
3515 uword
3516 unformat_ip6_mask (unformat_input_t * input, va_list * args)
3517 {
3518   u8 **maskp = va_arg (*args, u8 **);
3519   u8 *mask = 0;
3520   u8 found_something = 0;
3521   ip6_header_t *ip;
3522   u32 ip_version_traffic_class_and_flow_label;
3523
3524 #define _(a) u8 a=0;
3525   foreach_ip6_proto_field;
3526 #undef _
3527   u8 version = 0;
3528   u8 traffic_class = 0;
3529   u8 flow_label = 0;
3530
3531   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3532     {
3533       if (unformat (input, "version"))
3534         version = 1;
3535       else if (unformat (input, "traffic-class"))
3536         traffic_class = 1;
3537       else if (unformat (input, "flow-label"))
3538         flow_label = 1;
3539       else if (unformat (input, "src"))
3540         src_address = 1;
3541       else if (unformat (input, "dst"))
3542         dst_address = 1;
3543       else if (unformat (input, "proto"))
3544         protocol = 1;
3545
3546 #define _(a) else if (unformat (input, #a)) a=1;
3547       foreach_ip6_proto_field
3548 #undef _
3549         else
3550         break;
3551     }
3552
3553 #define _(a) found_something += a;
3554   foreach_ip6_proto_field;
3555 #undef _
3556
3557   if (found_something == 0)
3558     return 0;
3559
3560   vec_validate (mask, sizeof (*ip) - 1);
3561
3562   ip = (ip6_header_t *) mask;
3563
3564 #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
3565   foreach_ip6_proto_field;
3566 #undef _
3567
3568   ip_version_traffic_class_and_flow_label = 0;
3569
3570   if (version)
3571     ip_version_traffic_class_and_flow_label |= 0xF0000000;
3572
3573   if (traffic_class)
3574     ip_version_traffic_class_and_flow_label |= 0x0FF00000;
3575
3576   if (flow_label)
3577     ip_version_traffic_class_and_flow_label |= 0x000FFFFF;
3578
3579   ip->ip_version_traffic_class_and_flow_label =
3580     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
3581
3582   *maskp = mask;
3583   return 1;
3584 }
3585
3586 uword
3587 unformat_l3_mask (unformat_input_t * input, va_list * args)
3588 {
3589   u8 **maskp = va_arg (*args, u8 **);
3590
3591   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3592     {
3593       if (unformat (input, "ip4 %U", unformat_ip4_mask, maskp))
3594         return 1;
3595       else if (unformat (input, "ip6 %U", unformat_ip6_mask, maskp))
3596         return 1;
3597       else
3598         break;
3599     }
3600   return 0;
3601 }
3602
3603 uword
3604 unformat_l2_mask (unformat_input_t * input, va_list * args)
3605 {
3606   u8 **maskp = va_arg (*args, u8 **);
3607   u8 *mask = 0;
3608   u8 src = 0;
3609   u8 dst = 0;
3610   u8 proto = 0;
3611   u8 tag1 = 0;
3612   u8 tag2 = 0;
3613   u8 ignore_tag1 = 0;
3614   u8 ignore_tag2 = 0;
3615   u8 cos1 = 0;
3616   u8 cos2 = 0;
3617   u8 dot1q = 0;
3618   u8 dot1ad = 0;
3619   int len = 14;
3620
3621   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3622     {
3623       if (unformat (input, "src"))
3624         src = 1;
3625       else if (unformat (input, "dst"))
3626         dst = 1;
3627       else if (unformat (input, "proto"))
3628         proto = 1;
3629       else if (unformat (input, "tag1"))
3630         tag1 = 1;
3631       else if (unformat (input, "tag2"))
3632         tag2 = 1;
3633       else if (unformat (input, "ignore-tag1"))
3634         ignore_tag1 = 1;
3635       else if (unformat (input, "ignore-tag2"))
3636         ignore_tag2 = 1;
3637       else if (unformat (input, "cos1"))
3638         cos1 = 1;
3639       else if (unformat (input, "cos2"))
3640         cos2 = 1;
3641       else if (unformat (input, "dot1q"))
3642         dot1q = 1;
3643       else if (unformat (input, "dot1ad"))
3644         dot1ad = 1;
3645       else
3646         break;
3647     }
3648   if ((src + dst + proto + tag1 + tag2 + dot1q + dot1ad +
3649        ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
3650     return 0;
3651
3652   if (tag1 || ignore_tag1 || cos1 || dot1q)
3653     len = 18;
3654   if (tag2 || ignore_tag2 || cos2 || dot1ad)
3655     len = 22;
3656
3657   vec_validate (mask, len - 1);
3658
3659   if (dst)
3660     clib_memset (mask, 0xff, 6);
3661
3662   if (src)
3663     clib_memset (mask + 6, 0xff, 6);
3664
3665   if (tag2 || dot1ad)
3666     {
3667       /* inner vlan tag */
3668       if (tag2)
3669         {
3670           mask[19] = 0xff;
3671           mask[18] = 0x0f;
3672         }
3673       if (cos2)
3674         mask[18] |= 0xe0;
3675       if (proto)
3676         mask[21] = mask[20] = 0xff;
3677       if (tag1)
3678         {
3679           mask[15] = 0xff;
3680           mask[14] = 0x0f;
3681         }
3682       if (cos1)
3683         mask[14] |= 0xe0;
3684       *maskp = mask;
3685       return 1;
3686     }
3687   if (tag1 | dot1q)
3688     {
3689       if (tag1)
3690         {
3691           mask[15] = 0xff;
3692           mask[14] = 0x0f;
3693         }
3694       if (cos1)
3695         mask[14] |= 0xe0;
3696       if (proto)
3697         mask[16] = mask[17] = 0xff;
3698
3699       *maskp = mask;
3700       return 1;
3701     }
3702   if (cos2)
3703     mask[18] |= 0xe0;
3704   if (cos1)
3705     mask[14] |= 0xe0;
3706   if (proto)
3707     mask[12] = mask[13] = 0xff;
3708
3709   *maskp = mask;
3710   return 1;
3711 }
3712
3713 uword
3714 unformat_classify_mask (unformat_input_t * input, va_list * args)
3715 {
3716   u8 **maskp = va_arg (*args, u8 **);
3717   u32 *skipp = va_arg (*args, u32 *);
3718   u32 *matchp = va_arg (*args, u32 *);
3719   u32 match;
3720   u8 *mask = 0;
3721   u8 *l2 = 0;
3722   u8 *l3 = 0;
3723   u8 *l4 = 0;
3724   int i;
3725
3726   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3727     {
3728       if (unformat (input, "hex %U", unformat_hex_string, &mask))
3729         ;
3730       else if (unformat (input, "l2 %U", unformat_l2_mask, &l2))
3731         ;
3732       else if (unformat (input, "l3 %U", unformat_l3_mask, &l3))
3733         ;
3734       else if (unformat (input, "l4 %U", unformat_l4_mask, &l4))
3735         ;
3736       else
3737         break;
3738     }
3739
3740   if (l4 && !l3)
3741     {
3742       vec_free (mask);
3743       vec_free (l2);
3744       vec_free (l4);
3745       return 0;
3746     }
3747
3748   if (mask || l2 || l3 || l4)
3749     {
3750       if (l2 || l3 || l4)
3751         {
3752           /* "With a free Ethernet header in every package" */
3753           if (l2 == 0)
3754             vec_validate (l2, 13);
3755           mask = l2;
3756           if (vec_len (l3))
3757             {
3758               vec_append (mask, l3);
3759               vec_free (l3);
3760             }
3761           if (vec_len (l4))
3762             {
3763               vec_append (mask, l4);
3764               vec_free (l4);
3765             }
3766         }
3767
3768       /* Scan forward looking for the first significant mask octet */
3769       for (i = 0; i < vec_len (mask); i++)
3770         if (mask[i])
3771           break;
3772
3773       /* compute (skip, match) params */
3774       *skipp = i / sizeof (u32x4);
3775       vec_delete (mask, *skipp * sizeof (u32x4), 0);
3776
3777       /* Pad mask to an even multiple of the vector size */
3778       while (vec_len (mask) % sizeof (u32x4))
3779         vec_add1 (mask, 0);
3780
3781       match = vec_len (mask) / sizeof (u32x4);
3782
3783       for (i = match * sizeof (u32x4); i > 0; i -= sizeof (u32x4))
3784         {
3785           u64 *tmp = (u64 *) (mask + (i - sizeof (u32x4)));
3786           if (*tmp || *(tmp + 1))
3787             break;
3788           match--;
3789         }
3790       if (match == 0)
3791         clib_warning ("BUG: match 0");
3792
3793       _vec_len (mask) = match * sizeof (u32x4);
3794
3795       *matchp = match;
3796       *maskp = mask;
3797
3798       return 1;
3799     }
3800
3801   return 0;
3802 }
3803 #endif /* VPP_API_TEST_BUILTIN */
3804
3805 #define foreach_l2_next                         \
3806 _(drop, DROP)                                   \
3807 _(ethernet, ETHERNET_INPUT)                     \
3808 _(ip4, IP4_INPUT)                               \
3809 _(ip6, IP6_INPUT)
3810
3811 uword
3812 unformat_l2_next_index (unformat_input_t * input, va_list * args)
3813 {
3814   u32 *miss_next_indexp = va_arg (*args, u32 *);
3815   u32 next_index = 0;
3816   u32 tmp;
3817
3818 #define _(n,N) \
3819   if (unformat (input, #n)) { next_index = L2_INPUT_CLASSIFY_NEXT_##N; goto out;}
3820   foreach_l2_next;
3821 #undef _
3822
3823   if (unformat (input, "%d", &tmp))
3824     {
3825       next_index = tmp;
3826       goto out;
3827     }
3828
3829   return 0;
3830
3831 out:
3832   *miss_next_indexp = next_index;
3833   return 1;
3834 }
3835
3836 #define foreach_ip_next                         \
3837 _(drop, DROP)                                   \
3838 _(local, LOCAL)                                 \
3839 _(rewrite, REWRITE)
3840
3841 uword
3842 api_unformat_ip_next_index (unformat_input_t * input, va_list * args)
3843 {
3844   u32 *miss_next_indexp = va_arg (*args, u32 *);
3845   u32 next_index = 0;
3846   u32 tmp;
3847
3848 #define _(n,N) \
3849   if (unformat (input, #n)) { next_index = IP_LOOKUP_NEXT_##N; goto out;}
3850   foreach_ip_next;
3851 #undef _
3852
3853   if (unformat (input, "%d", &tmp))
3854     {
3855       next_index = tmp;
3856       goto out;
3857     }
3858
3859   return 0;
3860
3861 out:
3862   *miss_next_indexp = next_index;
3863   return 1;
3864 }
3865
3866 #define foreach_acl_next                        \
3867 _(deny, DENY)
3868
3869 uword
3870 api_unformat_acl_next_index (unformat_input_t * input, va_list * args)
3871 {
3872   u32 *miss_next_indexp = va_arg (*args, u32 *);
3873   u32 next_index = 0;
3874   u32 tmp;
3875
3876 #define _(n,N) \
3877   if (unformat (input, #n)) { next_index = ACL_NEXT_INDEX_##N; goto out;}
3878   foreach_acl_next;
3879 #undef _
3880
3881   if (unformat (input, "permit"))
3882     {
3883       next_index = ~0;
3884       goto out;
3885     }
3886   else if (unformat (input, "%d", &tmp))
3887     {
3888       next_index = tmp;
3889       goto out;
3890     }
3891
3892   return 0;
3893
3894 out:
3895   *miss_next_indexp = next_index;
3896   return 1;
3897 }
3898
3899 uword
3900 unformat_policer_precolor (unformat_input_t * input, va_list * args)
3901 {
3902   u32 *r = va_arg (*args, u32 *);
3903
3904   if (unformat (input, "conform-color"))
3905     *r = POLICE_CONFORM;
3906   else if (unformat (input, "exceed-color"))
3907     *r = POLICE_EXCEED;
3908   else
3909     return 0;
3910
3911   return 1;
3912 }
3913
3914 #if VPP_API_TEST_BUILTIN == 0
3915 uword
3916 unformat_l4_match (unformat_input_t * input, va_list * args)
3917 {
3918   u8 **matchp = va_arg (*args, u8 **);
3919
3920   u8 *proto_header = 0;
3921   int src_port = 0;
3922   int dst_port = 0;
3923
3924   tcpudp_header_t h;
3925
3926   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3927     {
3928       if (unformat (input, "src_port %d", &src_port))
3929         ;
3930       else if (unformat (input, "dst_port %d", &dst_port))
3931         ;
3932       else
3933         return 0;
3934     }
3935
3936   h.src_port = clib_host_to_net_u16 (src_port);
3937   h.dst_port = clib_host_to_net_u16 (dst_port);
3938   vec_validate (proto_header, sizeof (h) - 1);
3939   memcpy (proto_header, &h, sizeof (h));
3940
3941   *matchp = proto_header;
3942
3943   return 1;
3944 }
3945
3946 uword
3947 unformat_ip4_match (unformat_input_t * input, va_list * args)
3948 {
3949   u8 **matchp = va_arg (*args, u8 **);
3950   u8 *match = 0;
3951   ip4_header_t *ip;
3952   int version = 0;
3953   u32 version_val;
3954   int hdr_length = 0;
3955   u32 hdr_length_val;
3956   int src = 0, dst = 0;
3957   ip4_address_t src_val, dst_val;
3958   int proto = 0;
3959   u32 proto_val;
3960   int tos = 0;
3961   u32 tos_val;
3962   int length = 0;
3963   u32 length_val;
3964   int fragment_id = 0;
3965   u32 fragment_id_val;
3966   int ttl = 0;
3967   int ttl_val;
3968   int checksum = 0;
3969   u32 checksum_val;
3970
3971   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3972     {
3973       if (unformat (input, "version %d", &version_val))
3974         version = 1;
3975       else if (unformat (input, "hdr_length %d", &hdr_length_val))
3976         hdr_length = 1;
3977       else if (unformat (input, "src %U", unformat_ip4_address, &src_val))
3978         src = 1;
3979       else if (unformat (input, "dst %U", unformat_ip4_address, &dst_val))
3980         dst = 1;
3981       else if (unformat (input, "proto %d", &proto_val))
3982         proto = 1;
3983       else if (unformat (input, "tos %d", &tos_val))
3984         tos = 1;
3985       else if (unformat (input, "length %d", &length_val))
3986         length = 1;
3987       else if (unformat (input, "fragment_id %d", &fragment_id_val))
3988         fragment_id = 1;
3989       else if (unformat (input, "ttl %d", &ttl_val))
3990         ttl = 1;
3991       else if (unformat (input, "checksum %d", &checksum_val))
3992         checksum = 1;
3993       else
3994         break;
3995     }
3996
3997   if (version + hdr_length + src + dst + proto + tos + length + fragment_id
3998       + ttl + checksum == 0)
3999     return 0;
4000
4001   /*
4002    * Aligned because we use the real comparison functions
4003    */
4004   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
4005
4006   ip = (ip4_header_t *) match;
4007
4008   /* These are realistically matched in practice */
4009   if (src)
4010     ip->src_address.as_u32 = src_val.as_u32;
4011
4012   if (dst)
4013     ip->dst_address.as_u32 = dst_val.as_u32;
4014
4015   if (proto)
4016     ip->protocol = proto_val;
4017
4018
4019   /* These are not, but they're included for completeness */
4020   if (version)
4021     ip->ip_version_and_header_length |= (version_val & 0xF) << 4;
4022
4023   if (hdr_length)
4024     ip->ip_version_and_header_length |= (hdr_length_val & 0xF);
4025
4026   if (tos)
4027     ip->tos = tos_val;
4028
4029   if (length)
4030     ip->length = clib_host_to_net_u16 (length_val);
4031
4032   if (ttl)
4033     ip->ttl = ttl_val;
4034
4035   if (checksum)
4036     ip->checksum = clib_host_to_net_u16 (checksum_val);
4037
4038   *matchp = match;
4039   return 1;
4040 }
4041
4042 uword
4043 unformat_ip6_match (unformat_input_t * input, va_list * args)
4044 {
4045   u8 **matchp = va_arg (*args, u8 **);
4046   u8 *match = 0;
4047   ip6_header_t *ip;
4048   int version = 0;
4049   u32 version_val;
4050   u8 traffic_class = 0;
4051   u32 traffic_class_val = 0;
4052   u8 flow_label = 0;
4053   u8 flow_label_val;
4054   int src = 0, dst = 0;
4055   ip6_address_t src_val, dst_val;
4056   int proto = 0;
4057   u32 proto_val;
4058   int payload_length = 0;
4059   u32 payload_length_val;
4060   int hop_limit = 0;
4061   int hop_limit_val;
4062   u32 ip_version_traffic_class_and_flow_label;
4063
4064   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
4065     {
4066       if (unformat (input, "version %d", &version_val))
4067         version = 1;
4068       else if (unformat (input, "traffic_class %d", &traffic_class_val))
4069         traffic_class = 1;
4070       else if (unformat (input, "flow_label %d", &flow_label_val))
4071         flow_label = 1;
4072       else if (unformat (input, "src %U", unformat_ip6_address, &src_val))
4073         src = 1;
4074       else if (unformat (input, "dst %U", unformat_ip6_address, &dst_val))
4075         dst = 1;
4076       else if (unformat (input, "proto %d", &proto_val))
4077         proto = 1;
4078       else if (unformat (input, "payload_length %d", &payload_length_val))
4079         payload_length = 1;
4080       else if (unformat (input, "hop_limit %d", &hop_limit_val))
4081         hop_limit = 1;
4082       else
4083         break;
4084     }
4085
4086   if (version + traffic_class + flow_label + src + dst + proto +
4087       payload_length + hop_limit == 0)
4088     return 0;
4089
4090   /*
4091    * Aligned because we use the real comparison functions
4092    */
4093   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
4094
4095   ip = (ip6_header_t *) match;
4096
4097   if (src)
4098     clib_memcpy (&ip->src_address, &src_val, sizeof (ip->src_address));
4099
4100   if (dst)
4101     clib_memcpy (&ip->dst_address, &dst_val, sizeof (ip->dst_address));
4102
4103   if (proto)
4104     ip->protocol = proto_val;
4105
4106   ip_version_traffic_class_and_flow_label = 0;
4107
4108   if (version)
4109     ip_version_traffic_class_and_flow_label |= (version_val & 0xF) << 28;
4110
4111   if (traffic_class)
4112     ip_version_traffic_class_and_flow_label |=
4113       (traffic_class_val & 0xFF) << 20;
4114
4115   if (flow_label)
4116     ip_version_traffic_class_and_flow_label |= (flow_label_val & 0xFFFFF);
4117
4118   ip->ip_version_traffic_class_and_flow_label =
4119     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
4120
4121   if (payload_length)
4122     ip->payload_length = clib_host_to_net_u16 (payload_length_val);
4123
4124   if (hop_limit)
4125     ip->hop_limit = hop_limit_val;
4126
4127   *matchp = match;
4128   return 1;
4129 }
4130
4131 uword
4132 unformat_l3_match (unformat_input_t * input, va_list * args)
4133 {
4134   u8 **matchp = va_arg (*args, u8 **);
4135
4136   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
4137     {
4138       if (unformat (input, "ip4 %U", unformat_ip4_match, matchp))
4139         return 1;
4140       else if (unformat (input, "ip6 %U", unformat_ip6_match, matchp))
4141         return 1;
4142       else
4143         break;
4144     }
4145   return 0;
4146 }
4147
4148 uword
4149 unformat_vlan_tag (unformat_input_t * input, va_list * args)
4150 {
4151   u8 *tagp = va_arg (*args, u8 *);
4152   u32 tag;
4153
4154   if (unformat (input, "%d", &tag))
4155     {
4156       tagp[0] = (tag >> 8) & 0x0F;
4157       tagp[1] = tag & 0xFF;
4158       return 1;
4159     }
4160
4161   return 0;
4162 }
4163
4164 uword
4165 unformat_l2_match (unformat_input_t * input, va_list * args)
4166 {
4167   u8 **matchp = va_arg (*args, u8 **);
4168   u8 *match = 0;
4169   u8 src = 0;
4170   u8 src_val[6];
4171   u8 dst = 0;
4172   u8 dst_val[6];
4173   u8 proto = 0;
4174   u16 proto_val;
4175   u8 tag1 = 0;
4176   u8 tag1_val[2];
4177   u8 tag2 = 0;
4178   u8 tag2_val[2];
4179   int len = 14;
4180   u8 ignore_tag1 = 0;
4181   u8 ignore_tag2 = 0;
4182   u8 cos1 = 0;
4183   u8 cos2 = 0;
4184   u32 cos1_val = 0;
4185   u32 cos2_val = 0;
4186
4187   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
4188     {
4189       if (unformat (input, "src %U", unformat_ethernet_address, &src_val))
4190         src = 1;
4191       else
4192         if (unformat (input, "dst %U", unformat_ethernet_address, &dst_val))
4193         dst = 1;
4194       else if (unformat (input, "proto %U",
4195                          unformat_ethernet_type_host_byte_order, &proto_val))
4196         proto = 1;
4197       else if (unformat (input, "tag1 %U", unformat_vlan_tag, tag1_val))
4198         tag1 = 1;
4199       else if (unformat (input, "tag2 %U", unformat_vlan_tag, tag2_val))
4200         tag2 = 1;
4201       else if (unformat (input, "ignore-tag1"))
4202         ignore_tag1 = 1;
4203       else if (unformat (input, "ignore-tag2"))
4204         ignore_tag2 = 1;
4205       else if (unformat (input, "cos1 %d", &cos1_val))
4206         cos1 = 1;
4207       else if (unformat (input, "cos2 %d", &cos2_val))
4208         cos2 = 1;
4209       else
4210         break;
4211     }
4212   if ((src + dst + proto + tag1 + tag2 +
4213        ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
4214     return 0;
4215
4216   if (tag1 || ignore_tag1 || cos1)
4217     len = 18;
4218   if (tag2 || ignore_tag2 || cos2)
4219     len = 22;
4220
4221   vec_validate_aligned (match, len - 1, sizeof (u32x4));
4222
4223   if (dst)
4224     clib_memcpy (match, dst_val, 6);
4225
4226   if (src)
4227     clib_memcpy (match + 6, src_val, 6);
4228
4229   if (tag2)
4230     {
4231       /* inner vlan tag */
4232       match[19] = tag2_val[1];
4233       match[18] = tag2_val[0];
4234       if (cos2)
4235         match[18] |= (cos2_val & 0x7) << 5;
4236       if (proto)
4237         {
4238           match[21] = proto_val & 0xff;
4239           match[20] = proto_val >> 8;
4240         }
4241       if (tag1)
4242         {
4243           match[15] = tag1_val[1];
4244           match[14] = tag1_val[0];
4245         }
4246       if (cos1)
4247         match[14] |= (cos1_val & 0x7) << 5;
4248       *matchp = match;
4249       return 1;
4250     }
4251   if (tag1)
4252     {
4253       match[15] = tag1_val[1];
4254       match[14] = tag1_val[0];
4255       if (proto)
4256         {
4257           match[17] = proto_val & 0xff;
4258           match[16] = proto_val >> 8;
4259         }
4260       if (cos1)
4261         match[14] |= (cos1_val & 0x7) << 5;
4262
4263       *matchp = match;
4264       return 1;
4265     }
4266   if (cos2)
4267     match[18] |= (cos2_val & 0x7) << 5;
4268   if (cos1)
4269     match[14] |= (cos1_val & 0x7) << 5;
4270   if (proto)
4271     {
4272       match[13] = proto_val & 0xff;
4273       match[12] = proto_val >> 8;
4274     }
4275
4276   *matchp = match;
4277   return 1;
4278 }
4279
4280 uword
4281 unformat_qos_source (unformat_input_t * input, va_list * args)
4282 {
4283   int *qs = va_arg (*args, int *);
4284
4285   if (unformat (input, "ip"))
4286     *qs = QOS_SOURCE_IP;
4287   else if (unformat (input, "mpls"))
4288     *qs = QOS_SOURCE_MPLS;
4289   else if (unformat (input, "ext"))
4290     *qs = QOS_SOURCE_EXT;
4291   else if (unformat (input, "vlan"))
4292     *qs = QOS_SOURCE_VLAN;
4293   else
4294     return 0;
4295
4296   return 1;
4297 }
4298 #endif
4299
4300 uword
4301 api_unformat_classify_match (unformat_input_t * input, va_list * args)
4302 {
4303   u8 **matchp = va_arg (*args, u8 **);
4304   u32 skip_n_vectors = va_arg (*args, u32);
4305   u32 match_n_vectors = va_arg (*args, u32);
4306
4307   u8 *match = 0;
4308   u8 *l2 = 0;
4309   u8 *l3 = 0;
4310   u8 *l4 = 0;
4311
4312   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
4313     {
4314       if (unformat (input, "hex %U", unformat_hex_string, &match))
4315         ;
4316       else if (unformat (input, "l2 %U", unformat_l2_match, &l2))
4317         ;
4318       else if (unformat (input, "l3 %U", unformat_l3_match, &l3))
4319         ;
4320       else if (unformat (input, "l4 %U", unformat_l4_match, &l4))
4321         ;
4322       else
4323         break;
4324     }
4325
4326   if (l4 && !l3)
4327     {
4328       vec_free (match);
4329       vec_free (l2);
4330       vec_free (l4);
4331       return 0;
4332     }
4333
4334   if (match || l2 || l3 || l4)
4335     {
4336       if (l2 || l3 || l4)
4337         {
4338           /* "Win a free Ethernet header in every packet" */
4339           if (l2 == 0)
4340             vec_validate_aligned (l2, 13, sizeof (u32x4));
4341           match = l2;
4342           if (vec_len (l3))
4343             {
4344               vec_append_aligned (match, l3, sizeof (u32x4));
4345               vec_free (l3);
4346             }
4347           if (vec_len (l4))
4348             {
4349               vec_append_aligned (match, l4, sizeof (u32x4));
4350               vec_free (l4);
4351             }
4352         }
4353
4354       /* Make sure the vector is big enough even if key is all 0's */
4355       vec_validate_aligned
4356         (match, ((match_n_vectors + skip_n_vectors) * sizeof (u32x4)) - 1,
4357          sizeof (u32x4));
4358
4359       /* Set size, include skipped vectors */
4360       _vec_len (match) = (match_n_vectors + skip_n_vectors) * sizeof (u32x4);
4361
4362       *matchp = match;
4363
4364       return 1;
4365     }
4366
4367   return 0;
4368 }
4369
4370 static int
4371 api_get_node_index (vat_main_t * vam)
4372 {
4373   unformat_input_t *i = vam->input;
4374   vl_api_get_node_index_t *mp;
4375   u8 *name = 0;
4376   int ret;
4377
4378   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4379     {
4380       if (unformat (i, "node %s", &name))
4381         ;
4382       else
4383         break;
4384     }
4385   if (name == 0)
4386     {
4387       errmsg ("node name required");
4388       return -99;
4389     }
4390   if (vec_len (name) >= ARRAY_LEN (mp->node_name))
4391     {
4392       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
4393       return -99;
4394     }
4395
4396   M (GET_NODE_INDEX, mp);
4397   clib_memcpy (mp->node_name, name, vec_len (name));
4398   vec_free (name);
4399
4400   S (mp);
4401   W (ret);
4402   return ret;
4403 }
4404
4405 static int
4406 api_get_next_index (vat_main_t * vam)
4407 {
4408   unformat_input_t *i = vam->input;
4409   vl_api_get_next_index_t *mp;
4410   u8 *node_name = 0, *next_node_name = 0;
4411   int ret;
4412
4413   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4414     {
4415       if (unformat (i, "node-name %s", &node_name))
4416         ;
4417       else if (unformat (i, "next-node-name %s", &next_node_name))
4418         break;
4419     }
4420
4421   if (node_name == 0)
4422     {
4423       errmsg ("node name required");
4424       return -99;
4425     }
4426   if (vec_len (node_name) >= ARRAY_LEN (mp->node_name))
4427     {
4428       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
4429       return -99;
4430     }
4431
4432   if (next_node_name == 0)
4433     {
4434       errmsg ("next node name required");
4435       return -99;
4436     }
4437   if (vec_len (next_node_name) >= ARRAY_LEN (mp->next_name))
4438     {
4439       errmsg ("next node name too long, max %d", ARRAY_LEN (mp->next_name));
4440       return -99;
4441     }
4442
4443   M (GET_NEXT_INDEX, mp);
4444   clib_memcpy (mp->node_name, node_name, vec_len (node_name));
4445   clib_memcpy (mp->next_name, next_node_name, vec_len (next_node_name));
4446   vec_free (node_name);
4447   vec_free (next_node_name);
4448
4449   S (mp);
4450   W (ret);
4451   return ret;
4452 }
4453
4454 static int
4455 api_add_node_next (vat_main_t * vam)
4456 {
4457   unformat_input_t *i = vam->input;
4458   vl_api_add_node_next_t *mp;
4459   u8 *name = 0;
4460   u8 *next = 0;
4461   int ret;
4462
4463   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4464     {
4465       if (unformat (i, "node %s", &name))
4466         ;
4467       else if (unformat (i, "next %s", &next))
4468         ;
4469       else
4470         break;
4471     }
4472   if (name == 0)
4473     {
4474       errmsg ("node name required");
4475       return -99;
4476     }
4477   if (vec_len (name) >= ARRAY_LEN (mp->node_name))
4478     {
4479       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
4480       return -99;
4481     }
4482   if (next == 0)
4483     {
4484       errmsg ("next node required");
4485       return -99;
4486     }
4487   if (vec_len (next) >= ARRAY_LEN (mp->next_name))
4488     {
4489       errmsg ("next name too long, max %d", ARRAY_LEN (mp->next_name));
4490       return -99;
4491     }
4492
4493   M (ADD_NODE_NEXT, mp);
4494   clib_memcpy (mp->node_name, name, vec_len (name));
4495   clib_memcpy (mp->next_name, next, vec_len (next));
4496   vec_free (name);
4497   vec_free (next);
4498
4499   S (mp);
4500   W (ret);
4501   return ret;
4502 }
4503
4504 #define foreach_vtr_op                          \
4505 _("disable",  L2_VTR_DISABLED)                  \
4506 _("push-1",  L2_VTR_PUSH_1)                     \
4507 _("push-2",  L2_VTR_PUSH_2)                     \
4508 _("pop-1",  L2_VTR_POP_1)                       \
4509 _("pop-2",  L2_VTR_POP_2)                       \
4510 _("translate-1-1",  L2_VTR_TRANSLATE_1_1)       \
4511 _("translate-1-2",  L2_VTR_TRANSLATE_1_2)       \
4512 _("translate-2-1",  L2_VTR_TRANSLATE_2_1)       \
4513 _("translate-2-2",  L2_VTR_TRANSLATE_2_2)
4514
4515 static int
4516 api_show_version (vat_main_t *vam)
4517 {
4518   vl_api_show_version_t *mp;
4519   int ret;
4520
4521   M (SHOW_VERSION, mp);
4522
4523   S (mp);
4524   W (ret);
4525   return ret;
4526 }
4527
4528 static int
4529 api_interface_name_renumber (vat_main_t *vam)
4530 {
4531   unformat_input_t *line_input = vam->input;
4532   vl_api_interface_name_renumber_t *mp;
4533   u32 sw_if_index = ~0;
4534   u32 new_show_dev_instance = ~0;
4535   int ret;
4536
4537   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
4538     {
4539       if (unformat (line_input, "%U", api_unformat_sw_if_index, vam,
4540                     &sw_if_index))
4541         ;
4542       else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
4543         ;
4544       else if (unformat (line_input, "new_show_dev_instance %d",
4545                          &new_show_dev_instance))
4546         ;
4547       else
4548         break;
4549     }
4550
4551   if (sw_if_index == ~0)
4552     {
4553       errmsg ("missing interface name or sw_if_index");
4554       return -99;
4555     }
4556
4557   if (new_show_dev_instance == ~0)
4558     {
4559       errmsg ("missing new_show_dev_instance");
4560       return -99;
4561     }
4562
4563   M (INTERFACE_NAME_RENUMBER, mp);
4564
4565   mp->sw_if_index = ntohl (sw_if_index);
4566   mp->new_show_dev_instance = ntohl (new_show_dev_instance);
4567
4568   S (mp);
4569   W (ret);
4570   return ret;
4571 }
4572
4573 static int
4574 api_ip_address_dump (vat_main_t *vam)
4575 {
4576   unformat_input_t *i = vam->input;
4577   vl_api_ip_address_dump_t *mp;
4578   vl_api_control_ping_t *mp_ping;
4579   u32 sw_if_index = ~0;
4580   u8 sw_if_index_set = 0;
4581   u8 ipv4_set = 0;
4582   u8 ipv6_set = 0;
4583   int ret;
4584
4585   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4586     {
4587       if (unformat (i, "sw_if_index %d", &sw_if_index))
4588         sw_if_index_set = 1;
4589       else if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4590         sw_if_index_set = 1;
4591       else if (unformat (i, "ipv4"))
4592         ipv4_set = 1;
4593       else if (unformat (i, "ipv6"))
4594         ipv6_set = 1;
4595       else
4596         break;
4597     }
4598
4599   if (ipv4_set && ipv6_set)
4600     {
4601       errmsg ("ipv4 and ipv6 flags cannot be both set");
4602       return -99;
4603     }
4604
4605   if ((!ipv4_set) && (!ipv6_set))
4606     {
4607       errmsg ("no ipv4 nor ipv6 flag set");
4608       return -99;
4609     }
4610
4611   if (sw_if_index_set == 0)
4612     {
4613       errmsg ("missing interface name or sw_if_index");
4614       return -99;
4615     }
4616
4617   vam->current_sw_if_index = sw_if_index;
4618   vam->is_ipv6 = ipv6_set;
4619
4620   M (IP_ADDRESS_DUMP, mp);
4621   mp->sw_if_index = ntohl (sw_if_index);
4622   mp->is_ipv6 = ipv6_set;
4623   S (mp);
4624
4625   /* Use a control ping for synchronization */
4626   MPING (CONTROL_PING, mp_ping);
4627   S (mp_ping);
4628
4629   W (ret);
4630   return ret;
4631 }
4632
4633 static int
4634 api_ip_dump (vat_main_t * vam)
4635 {
4636   vl_api_ip_dump_t *mp;
4637   vl_api_control_ping_t *mp_ping;
4638   unformat_input_t *in = vam->input;
4639   int ipv4_set = 0;
4640   int ipv6_set = 0;
4641   int is_ipv6;
4642   int i;
4643   int ret;
4644
4645   while (unformat_check_input (in) != UNFORMAT_END_OF_INPUT)
4646     {
4647       if (unformat (in, "ipv4"))
4648         ipv4_set = 1;
4649       else if (unformat (in, "ipv6"))
4650         ipv6_set = 1;
4651       else
4652         break;
4653     }
4654
4655   if (ipv4_set && ipv6_set)
4656     {
4657       errmsg ("ipv4 and ipv6 flags cannot be both set");
4658       return -99;
4659     }
4660
4661   if ((!ipv4_set) && (!ipv6_set))
4662     {
4663       errmsg ("no ipv4 nor ipv6 flag set");
4664       return -99;
4665     }
4666
4667   is_ipv6 = ipv6_set;
4668   vam->is_ipv6 = is_ipv6;
4669
4670   /* free old data */
4671   for (i = 0; i < vec_len (vam->ip_details_by_sw_if_index[is_ipv6]); i++)
4672     {
4673       vec_free (vam->ip_details_by_sw_if_index[is_ipv6][i].addr);
4674     }
4675   vec_free (vam->ip_details_by_sw_if_index[is_ipv6]);
4676
4677   M (IP_DUMP, mp);
4678   mp->is_ipv6 = ipv6_set;
4679   S (mp);
4680
4681   /* Use a control ping for synchronization */
4682   MPING (CONTROL_PING, mp_ping);
4683   S (mp_ping);
4684
4685   W (ret);
4686   return ret;
4687 }
4688
4689 static int
4690 api_get_first_msg_id (vat_main_t * vam)
4691 {
4692   vl_api_get_first_msg_id_t *mp;
4693   unformat_input_t *i = vam->input;
4694   u8 *name;
4695   u8 name_set = 0;
4696   int ret;
4697
4698   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4699     {
4700       if (unformat (i, "client %s", &name))
4701         name_set = 1;
4702       else
4703         break;
4704     }
4705
4706   if (name_set == 0)
4707     {
4708       errmsg ("missing client name");
4709       return -99;
4710     }
4711   vec_add1 (name, 0);
4712
4713   if (vec_len (name) > 63)
4714     {
4715       errmsg ("client name too long");
4716       return -99;
4717     }
4718
4719   M (GET_FIRST_MSG_ID, mp);
4720   clib_memcpy (mp->name, name, vec_len (name));
4721   S (mp);
4722   W (ret);
4723   return ret;
4724 }
4725
4726 static int
4727 api_get_node_graph (vat_main_t * vam)
4728 {
4729   vl_api_get_node_graph_t *mp;
4730   int ret;
4731
4732   M (GET_NODE_GRAPH, mp);
4733
4734   /* send it... */
4735   S (mp);
4736   /* Wait for the reply */
4737   W (ret);
4738   return ret;
4739 }
4740
4741 static u8 *
4742 format_fib_api_path_nh_proto (u8 * s, va_list * args)
4743 {
4744   vl_api_fib_path_nh_proto_t proto =
4745     va_arg (*args, vl_api_fib_path_nh_proto_t);
4746
4747   switch (proto)
4748     {
4749     case FIB_API_PATH_NH_PROTO_IP4:
4750       s = format (s, "ip4");
4751       break;
4752     case FIB_API_PATH_NH_PROTO_IP6:
4753       s = format (s, "ip6");
4754       break;
4755     case FIB_API_PATH_NH_PROTO_MPLS:
4756       s = format (s, "mpls");
4757       break;
4758     case FIB_API_PATH_NH_PROTO_BIER:
4759       s = format (s, "bier");
4760       break;
4761     case FIB_API_PATH_NH_PROTO_ETHERNET:
4762       s = format (s, "ethernet");
4763       break;
4764     }
4765
4766   return (s);
4767 }
4768
4769 static u8 *
4770 format_vl_api_ip_address_union (u8 * s, va_list * args)
4771 {
4772   vl_api_address_family_t af = va_arg (*args, int);
4773   const vl_api_address_union_t *u = va_arg (*args, vl_api_address_union_t *);
4774
4775   switch (af)
4776     {
4777     case ADDRESS_IP4:
4778       s = format (s, "%U", format_ip4_address, u->ip4);
4779       break;
4780     case ADDRESS_IP6:
4781       s = format (s, "%U", format_ip6_address, u->ip6);
4782       break;
4783     }
4784   return (s);
4785 }
4786
4787 static u8 *
4788 format_vl_api_fib_path_type (u8 * s, va_list * args)
4789 {
4790   vl_api_fib_path_type_t t = va_arg (*args, vl_api_fib_path_type_t);
4791
4792   switch (t)
4793     {
4794     case FIB_API_PATH_TYPE_NORMAL:
4795       s = format (s, "normal");
4796       break;
4797     case FIB_API_PATH_TYPE_LOCAL:
4798       s = format (s, "local");
4799       break;
4800     case FIB_API_PATH_TYPE_DROP:
4801       s = format (s, "drop");
4802       break;
4803     case FIB_API_PATH_TYPE_UDP_ENCAP:
4804       s = format (s, "udp-encap");
4805       break;
4806     case FIB_API_PATH_TYPE_BIER_IMP:
4807       s = format (s, "bier-imp");
4808       break;
4809     case FIB_API_PATH_TYPE_ICMP_UNREACH:
4810       s = format (s, "unreach");
4811       break;
4812     case FIB_API_PATH_TYPE_ICMP_PROHIBIT:
4813       s = format (s, "prohibit");
4814       break;
4815     case FIB_API_PATH_TYPE_SOURCE_LOOKUP:
4816       s = format (s, "src-lookup");
4817       break;
4818     case FIB_API_PATH_TYPE_DVR:
4819       s = format (s, "dvr");
4820       break;
4821     case FIB_API_PATH_TYPE_INTERFACE_RX:
4822       s = format (s, "interface-rx");
4823       break;
4824     case FIB_API_PATH_TYPE_CLASSIFY:
4825       s = format (s, "classify");
4826       break;
4827     }
4828
4829   return (s);
4830 }
4831
4832 static void
4833 vl_api_fib_path_print (vat_main_t * vam, vl_api_fib_path_t * fp)
4834 {
4835   print (vam->ofp,
4836          "  weight %d, sw_if_index %d, type %U, afi %U, next_hop %U",
4837          ntohl (fp->weight), ntohl (fp->sw_if_index),
4838          format_vl_api_fib_path_type, fp->type,
4839          format_fib_api_path_nh_proto, fp->proto,
4840          format_vl_api_ip_address_union, &fp->nh.address);
4841 }
4842
4843 static void
4844 vl_api_mpls_fib_path_json_print (vat_json_node_t * node,
4845                                  vl_api_fib_path_t * fp)
4846 {
4847   struct in_addr ip4;
4848   struct in6_addr ip6;
4849
4850   vat_json_object_add_uint (node, "weight", ntohl (fp->weight));
4851   vat_json_object_add_uint (node, "sw_if_index", ntohl (fp->sw_if_index));
4852   vat_json_object_add_uint (node, "type", fp->type);
4853   vat_json_object_add_uint (node, "next_hop_proto", fp->proto);
4854   if (fp->proto == FIB_API_PATH_NH_PROTO_IP4)
4855     {
4856       clib_memcpy (&ip4, &fp->nh.address.ip4, sizeof (ip4));
4857       vat_json_object_add_ip4 (node, "next_hop", ip4);
4858     }
4859   else if (fp->proto == FIB_API_PATH_NH_PROTO_IP6)
4860     {
4861       clib_memcpy (&ip6, &fp->nh.address.ip6, sizeof (ip6));
4862       vat_json_object_add_ip6 (node, "next_hop", ip6);
4863     }
4864 }
4865
4866 #define vl_api_ip_table_details_t_endian vl_noop_handler
4867 #define vl_api_ip_table_details_t_print vl_noop_handler
4868
4869 static void
4870 vl_api_ip_table_details_t_handler (vl_api_ip_table_details_t * mp)
4871 {
4872   vat_main_t *vam = &vat_main;
4873
4874   print (vam->ofp,
4875          "%s; table-id %d, prefix %U/%d",
4876          mp->table.name, ntohl (mp->table.table_id));
4877 }
4878
4879
4880 static void vl_api_ip_table_details_t_handler_json
4881   (vl_api_ip_table_details_t * mp)
4882 {
4883   vat_main_t *vam = &vat_main;
4884   vat_json_node_t *node = NULL;
4885
4886   if (VAT_JSON_ARRAY != vam->json_tree.type)
4887     {
4888       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
4889       vat_json_init_array (&vam->json_tree);
4890     }
4891   node = vat_json_array_add (&vam->json_tree);
4892
4893   vat_json_init_object (node);
4894   vat_json_object_add_uint (node, "table", ntohl (mp->table.table_id));
4895 }
4896
4897 static int
4898 api_ip_table_dump (vat_main_t * vam)
4899 {
4900   vl_api_ip_table_dump_t *mp;
4901   vl_api_control_ping_t *mp_ping;
4902   int ret;
4903
4904   M (IP_TABLE_DUMP, mp);
4905   S (mp);
4906
4907   /* Use a control ping for synchronization */
4908   MPING (CONTROL_PING, mp_ping);
4909   S (mp_ping);
4910
4911   W (ret);
4912   return ret;
4913 }
4914
4915 static int
4916 api_ip_mtable_dump (vat_main_t * vam)
4917 {
4918   vl_api_ip_mtable_dump_t *mp;
4919   vl_api_control_ping_t *mp_ping;
4920   int ret;
4921
4922   M (IP_MTABLE_DUMP, mp);
4923   S (mp);
4924
4925   /* Use a control ping for synchronization */
4926   MPING (CONTROL_PING, mp_ping);
4927   S (mp_ping);
4928
4929   W (ret);
4930   return ret;
4931 }
4932
4933 static int
4934 api_ip_mroute_dump (vat_main_t * vam)
4935 {
4936   unformat_input_t *input = vam->input;
4937   vl_api_control_ping_t *mp_ping;
4938   vl_api_ip_mroute_dump_t *mp;
4939   int ret, is_ip6;
4940   u32 table_id;
4941
4942   is_ip6 = 0;
4943   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
4944     {
4945       if (unformat (input, "table_id %d", &table_id))
4946         ;
4947       else if (unformat (input, "ip6"))
4948         is_ip6 = 1;
4949       else if (unformat (input, "ip4"))
4950         is_ip6 = 0;
4951       else
4952         break;
4953     }
4954   if (table_id == ~0)
4955     {
4956       errmsg ("missing table id");
4957       return -99;
4958     }
4959
4960   M (IP_MROUTE_DUMP, mp);
4961   mp->table.table_id = table_id;
4962   mp->table.is_ip6 = is_ip6;
4963   S (mp);
4964
4965   /* Use a control ping for synchronization */
4966   MPING (CONTROL_PING, mp_ping);
4967   S (mp_ping);
4968
4969   W (ret);
4970   return ret;
4971 }
4972
4973 #define vl_api_ip_route_details_t_endian vl_noop_handler
4974 #define vl_api_ip_route_details_t_print vl_noop_handler
4975
4976 static void
4977 vl_api_ip_route_details_t_handler (vl_api_ip_route_details_t * mp)
4978 {
4979   vat_main_t *vam = &vat_main;
4980   u8 count = mp->route.n_paths;
4981   vl_api_fib_path_t *fp;
4982   int i;
4983
4984   print (vam->ofp,
4985          "table-id %d, prefix %U/%d",
4986          ntohl (mp->route.table_id),
4987          format_ip46_address, mp->route.prefix.address, mp->route.prefix.len);
4988   for (i = 0; i < count; i++)
4989     {
4990       fp = &mp->route.paths[i];
4991
4992       vl_api_fib_path_print (vam, fp);
4993       fp++;
4994     }
4995 }
4996
4997 static void vl_api_ip_route_details_t_handler_json
4998   (vl_api_ip_route_details_t * mp)
4999 {
5000   vat_main_t *vam = &vat_main;
5001   u8 count = mp->route.n_paths;
5002   vat_json_node_t *node = NULL;
5003   struct in_addr ip4;
5004   struct in6_addr ip6;
5005   vl_api_fib_path_t *fp;
5006   int i;
5007
5008   if (VAT_JSON_ARRAY != vam->json_tree.type)
5009     {
5010       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
5011       vat_json_init_array (&vam->json_tree);
5012     }
5013   node = vat_json_array_add (&vam->json_tree);
5014
5015   vat_json_init_object (node);
5016   vat_json_object_add_uint (node, "table", ntohl (mp->route.table_id));
5017   if (ADDRESS_IP6 == mp->route.prefix.address.af)
5018     {
5019       clib_memcpy (&ip6, &mp->route.prefix.address.un.ip6, sizeof (ip6));
5020       vat_json_object_add_ip6 (node, "prefix", ip6);
5021     }
5022   else
5023     {
5024       clib_memcpy (&ip4, &mp->route.prefix.address.un.ip4, sizeof (ip4));
5025       vat_json_object_add_ip4 (node, "prefix", ip4);
5026     }
5027   vat_json_object_add_uint (node, "mask_length", mp->route.prefix.len);
5028   vat_json_object_add_uint (node, "path_count", count);
5029   for (i = 0; i < count; i++)
5030     {
5031       fp = &mp->route.paths[i];
5032       vl_api_mpls_fib_path_json_print (node, fp);
5033     }
5034 }
5035
5036 static int
5037 api_ip_route_dump (vat_main_t * vam)
5038 {
5039   unformat_input_t *input = vam->input;
5040   vl_api_ip_route_dump_t *mp;
5041   vl_api_control_ping_t *mp_ping;
5042   u32 table_id;
5043   u8 is_ip6;
5044   int ret;
5045
5046   is_ip6 = 0;
5047   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5048     {
5049       if (unformat (input, "table_id %d", &table_id))
5050         ;
5051       else if (unformat (input, "ip6"))
5052         is_ip6 = 1;
5053       else if (unformat (input, "ip4"))
5054         is_ip6 = 0;
5055       else
5056         break;
5057     }
5058   if (table_id == ~0)
5059     {
5060       errmsg ("missing table id");
5061       return -99;
5062     }
5063
5064   M (IP_ROUTE_DUMP, mp);
5065
5066   mp->table.table_id = table_id;
5067   mp->table.is_ip6 = is_ip6;
5068
5069   S (mp);
5070
5071   /* Use a control ping for synchronization */
5072   MPING (CONTROL_PING, mp_ping);
5073   S (mp_ping);
5074
5075   W (ret);
5076   return ret;
5077 }
5078
5079 int
5080 api_ip_source_and_port_range_check_add_del (vat_main_t * vam)
5081 {
5082   unformat_input_t *input = vam->input;
5083   vl_api_ip_source_and_port_range_check_add_del_t *mp;
5084
5085   u16 *low_ports = 0;
5086   u16 *high_ports = 0;
5087   u16 this_low;
5088   u16 this_hi;
5089   vl_api_prefix_t prefix;
5090   u32 tmp, tmp2;
5091   u8 prefix_set = 0;
5092   u32 vrf_id = ~0;
5093   u8 is_add = 1;
5094   int ret;
5095
5096   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5097     {
5098       if (unformat (input, "%U", unformat_vl_api_prefix, &prefix))
5099         prefix_set = 1;
5100       else if (unformat (input, "vrf %d", &vrf_id))
5101         ;
5102       else if (unformat (input, "del"))
5103         is_add = 0;
5104       else if (unformat (input, "port %d", &tmp))
5105         {
5106           if (tmp == 0 || tmp > 65535)
5107             {
5108               errmsg ("port %d out of range", tmp);
5109               return -99;
5110             }
5111           this_low = tmp;
5112           this_hi = this_low + 1;
5113           vec_add1 (low_ports, this_low);
5114           vec_add1 (high_ports, this_hi);
5115         }
5116       else if (unformat (input, "range %d - %d", &tmp, &tmp2))
5117         {
5118           if ((tmp > tmp2) || (tmp == 0) || (tmp2 > 65535))
5119             {
5120               errmsg ("incorrect range parameters");
5121               return -99;
5122             }
5123           this_low = tmp;
5124           /* Note: in debug CLI +1 is added to high before
5125              passing to real fn that does "the work"
5126              (ip_source_and_port_range_check_add_del).
5127              This fn is a wrapper around the binary API fn a
5128              control plane will call, which expects this increment
5129              to have occurred. Hence letting the binary API control
5130              plane fn do the increment for consistency between VAT
5131              and other control planes.
5132            */
5133           this_hi = tmp2;
5134           vec_add1 (low_ports, this_low);
5135           vec_add1 (high_ports, this_hi);
5136         }
5137       else
5138         break;
5139     }
5140
5141   if (prefix_set == 0)
5142     {
5143       errmsg ("<address>/<mask> not specified");
5144       return -99;
5145     }
5146
5147   if (vrf_id == ~0)
5148     {
5149       errmsg ("VRF ID required, not specified");
5150       return -99;
5151     }
5152
5153   if (vrf_id == 0)
5154     {
5155       errmsg
5156         ("VRF ID should not be default. Should be distinct VRF for this purpose.");
5157       return -99;
5158     }
5159
5160   if (vec_len (low_ports) == 0)
5161     {
5162       errmsg ("At least one port or port range required");
5163       return -99;
5164     }
5165
5166   M (IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL, mp);
5167
5168   mp->is_add = is_add;
5169
5170   clib_memcpy (&mp->prefix, &prefix, sizeof (prefix));
5171
5172   mp->number_of_ranges = vec_len (low_ports);
5173
5174   clib_memcpy (mp->low_ports, low_ports, vec_len (low_ports));
5175   vec_free (low_ports);
5176
5177   clib_memcpy (mp->high_ports, high_ports, vec_len (high_ports));
5178   vec_free (high_ports);
5179
5180   mp->vrf_id = ntohl (vrf_id);
5181
5182   S (mp);
5183   W (ret);
5184   return ret;
5185 }
5186
5187 int
5188 api_ip_source_and_port_range_check_interface_add_del (vat_main_t * vam)
5189 {
5190   unformat_input_t *input = vam->input;
5191   vl_api_ip_source_and_port_range_check_interface_add_del_t *mp;
5192   u32 sw_if_index = ~0;
5193   int vrf_set = 0;
5194   u32 tcp_out_vrf_id = ~0, udp_out_vrf_id = ~0;
5195   u32 tcp_in_vrf_id = ~0, udp_in_vrf_id = ~0;
5196   u8 is_add = 1;
5197   int ret;
5198
5199   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5200     {
5201       if (unformat (input, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5202         ;
5203       else if (unformat (input, "sw_if_index %d", &sw_if_index))
5204         ;
5205       else if (unformat (input, "tcp-out-vrf %d", &tcp_out_vrf_id))
5206         vrf_set = 1;
5207       else if (unformat (input, "udp-out-vrf %d", &udp_out_vrf_id))
5208         vrf_set = 1;
5209       else if (unformat (input, "tcp-in-vrf %d", &tcp_in_vrf_id))
5210         vrf_set = 1;
5211       else if (unformat (input, "udp-in-vrf %d", &udp_in_vrf_id))
5212         vrf_set = 1;
5213       else if (unformat (input, "del"))
5214         is_add = 0;
5215       else
5216         break;
5217     }
5218
5219   if (sw_if_index == ~0)
5220     {
5221       errmsg ("Interface required but not specified");
5222       return -99;
5223     }
5224
5225   if (vrf_set == 0)
5226     {
5227       errmsg ("VRF ID required but not specified");
5228       return -99;
5229     }
5230
5231   if (tcp_out_vrf_id == 0
5232       || udp_out_vrf_id == 0 || tcp_in_vrf_id == 0 || udp_in_vrf_id == 0)
5233     {
5234       errmsg
5235         ("VRF ID should not be default. Should be distinct VRF for this purpose.");
5236       return -99;
5237     }
5238
5239   /* Construct the API message */
5240   M (IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL, mp);
5241
5242   mp->sw_if_index = ntohl (sw_if_index);
5243   mp->is_add = is_add;
5244   mp->tcp_out_vrf_id = ntohl (tcp_out_vrf_id);
5245   mp->udp_out_vrf_id = ntohl (udp_out_vrf_id);
5246   mp->tcp_in_vrf_id = ntohl (tcp_in_vrf_id);
5247   mp->udp_in_vrf_id = ntohl (udp_in_vrf_id);
5248
5249   /* send it... */
5250   S (mp);
5251
5252   /* Wait for a reply... */
5253   W (ret);
5254   return ret;
5255 }
5256
5257 static int
5258 api_delete_subif (vat_main_t * vam)
5259 {
5260   unformat_input_t *i = vam->input;
5261   vl_api_delete_subif_t *mp;
5262   u32 sw_if_index = ~0;
5263   int ret;
5264
5265   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5266     {
5267       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5268         ;
5269       if (unformat (i, "sw_if_index %d", &sw_if_index))
5270         ;
5271       else
5272         break;
5273     }
5274
5275   if (sw_if_index == ~0)
5276     {
5277       errmsg ("missing sw_if_index");
5278       return -99;
5279     }
5280
5281   /* Construct the API message */
5282   M (DELETE_SUBIF, mp);
5283   mp->sw_if_index = ntohl (sw_if_index);
5284
5285   S (mp);
5286   W (ret);
5287   return ret;
5288 }
5289
5290 #define foreach_pbb_vtr_op      \
5291 _("disable",  L2_VTR_DISABLED)  \
5292 _("pop",  L2_VTR_POP_2)         \
5293 _("push",  L2_VTR_PUSH_2)
5294
5295
5296 static int
5297 api_sw_interface_tag_add_del (vat_main_t * vam)
5298 {
5299   unformat_input_t *i = vam->input;
5300   vl_api_sw_interface_tag_add_del_t *mp;
5301   u32 sw_if_index = ~0;
5302   u8 *tag = 0;
5303   u8 enable = 1;
5304   int ret;
5305
5306   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5307     {
5308       if (unformat (i, "tag %s", &tag))
5309         ;
5310       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5311         ;
5312       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5313         ;
5314       else if (unformat (i, "del"))
5315         enable = 0;
5316       else
5317         break;
5318     }
5319
5320   if (sw_if_index == ~0)
5321     {
5322       errmsg ("missing interface name or sw_if_index");
5323       return -99;
5324     }
5325
5326   if (enable && (tag == 0))
5327     {
5328       errmsg ("no tag specified");
5329       return -99;
5330     }
5331
5332   /* Construct the API message */
5333   M (SW_INTERFACE_TAG_ADD_DEL, mp);
5334   mp->sw_if_index = ntohl (sw_if_index);
5335   mp->is_add = enable;
5336   if (enable)
5337     strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
5338   vec_free (tag);
5339
5340   S (mp);
5341   W (ret);
5342   return ret;
5343 }
5344
5345 static int
5346 api_sw_interface_add_del_mac_address (vat_main_t * vam)
5347 {
5348   unformat_input_t *i = vam->input;
5349   vl_api_mac_address_t mac = { 0 };
5350   vl_api_sw_interface_add_del_mac_address_t *mp;
5351   u32 sw_if_index = ~0;
5352   u8 is_add = 1;
5353   u8 mac_set = 0;
5354   int ret;
5355
5356   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5357     {
5358       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5359         ;
5360       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5361         ;
5362       else if (unformat (i, "%U", unformat_vl_api_mac_address, &mac))
5363         mac_set++;
5364       else if (unformat (i, "del"))
5365         is_add = 0;
5366       else
5367         break;
5368     }
5369
5370   if (sw_if_index == ~0)
5371     {
5372       errmsg ("missing interface name or sw_if_index");
5373       return -99;
5374     }
5375
5376   if (!mac_set)
5377     {
5378       errmsg ("missing MAC address");
5379       return -99;
5380     }
5381
5382   /* Construct the API message */
5383   M (SW_INTERFACE_ADD_DEL_MAC_ADDRESS, mp);
5384   mp->sw_if_index = ntohl (sw_if_index);
5385   mp->is_add = is_add;
5386   clib_memcpy (&mp->addr, &mac, sizeof (mac));
5387
5388   S (mp);
5389   W (ret);
5390   return ret;
5391 }
5392
5393 static int
5394 api_hw_interface_set_mtu (vat_main_t * vam)
5395 {
5396   unformat_input_t *i = vam->input;
5397   vl_api_hw_interface_set_mtu_t *mp;
5398   u32 sw_if_index = ~0;
5399   u32 mtu = 0;
5400   int ret;
5401
5402   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5403     {
5404       if (unformat (i, "mtu %d", &mtu))
5405         ;
5406       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5407         ;
5408       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5409         ;
5410       else
5411         break;
5412     }
5413
5414   if (sw_if_index == ~0)
5415     {
5416       errmsg ("missing interface name or sw_if_index");
5417       return -99;
5418     }
5419
5420   if (mtu == 0)
5421     {
5422       errmsg ("no mtu specified");
5423       return -99;
5424     }
5425
5426   /* Construct the API message */
5427   M (HW_INTERFACE_SET_MTU, mp);
5428   mp->sw_if_index = ntohl (sw_if_index);
5429   mp->mtu = ntohs ((u16) mtu);
5430
5431   S (mp);
5432   W (ret);
5433   return ret;
5434 }
5435
5436 static void vl_api_app_namespace_add_del_reply_t_handler
5437   (vl_api_app_namespace_add_del_reply_t * mp)
5438 {
5439   vat_main_t *vam = &vat_main;
5440   i32 retval = ntohl (mp->retval);
5441   if (vam->async_mode)
5442     {
5443       vam->async_errors += (retval < 0);
5444     }
5445   else
5446     {
5447       vam->retval = retval;
5448       if (retval == 0)
5449         errmsg ("app ns index %d\n", ntohl (mp->appns_index));
5450       vam->result_ready = 1;
5451     }
5452 }
5453
5454 static void vl_api_app_namespace_add_del_reply_t_handler_json
5455   (vl_api_app_namespace_add_del_reply_t * mp)
5456 {
5457   vat_main_t *vam = &vat_main;
5458   vat_json_node_t node;
5459
5460   vat_json_init_object (&node);
5461   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
5462   vat_json_object_add_uint (&node, "appns_index", ntohl (mp->appns_index));
5463
5464   vat_json_print (vam->ofp, &node);
5465   vat_json_free (&node);
5466
5467   vam->retval = ntohl (mp->retval);
5468   vam->result_ready = 1;
5469 }
5470
5471 static int
5472 api_app_namespace_add_del (vat_main_t * vam)
5473 {
5474   vl_api_app_namespace_add_del_t *mp;
5475   unformat_input_t *i = vam->input;
5476   u8 *ns_id = 0, secret_set = 0, sw_if_index_set = 0;
5477   u32 sw_if_index, ip4_fib_id, ip6_fib_id;
5478   u64 secret;
5479   int ret;
5480
5481   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5482     {
5483       if (unformat (i, "id %_%v%_", &ns_id))
5484         ;
5485       else if (unformat (i, "secret %lu", &secret))
5486         secret_set = 1;
5487       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5488         sw_if_index_set = 1;
5489       else if (unformat (i, "ip4_fib_id %d", &ip4_fib_id))
5490         ;
5491       else if (unformat (i, "ip6_fib_id %d", &ip6_fib_id))
5492         ;
5493       else
5494         break;
5495     }
5496   if (!ns_id || !secret_set || !sw_if_index_set)
5497     {
5498       errmsg ("namespace id, secret and sw_if_index must be set");
5499       return -99;
5500     }
5501   if (vec_len (ns_id) > 64)
5502     {
5503       errmsg ("namespace id too long");
5504       return -99;
5505     }
5506   M (APP_NAMESPACE_ADD_DEL, mp);
5507
5508   vl_api_vec_to_api_string (ns_id, &mp->namespace_id);
5509   mp->secret = clib_host_to_net_u64 (secret);
5510   mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
5511   mp->ip4_fib_id = clib_host_to_net_u32 (ip4_fib_id);
5512   mp->ip6_fib_id = clib_host_to_net_u32 (ip6_fib_id);
5513   vec_free (ns_id);
5514   S (mp);
5515   W (ret);
5516   return ret;
5517 }
5518
5519 static int
5520 api_sock_init_shm (vat_main_t * vam)
5521 {
5522 #if VPP_API_TEST_BUILTIN == 0
5523   unformat_input_t *i = vam->input;
5524   vl_api_shm_elem_config_t *config = 0;
5525   u64 size = 64 << 20;
5526   int rv;
5527
5528   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5529     {
5530       if (unformat (i, "size %U", unformat_memory_size, &size))
5531         ;
5532       else
5533         break;
5534     }
5535
5536   /*
5537    * Canned custom ring allocator config.
5538    * Should probably parse all of this
5539    */
5540   vec_validate (config, 6);
5541   config[0].type = VL_API_VLIB_RING;
5542   config[0].size = 256;
5543   config[0].count = 32;
5544
5545   config[1].type = VL_API_VLIB_RING;
5546   config[1].size = 1024;
5547   config[1].count = 16;
5548
5549   config[2].type = VL_API_VLIB_RING;
5550   config[2].size = 4096;
5551   config[2].count = 2;
5552
5553   config[3].type = VL_API_CLIENT_RING;
5554   config[3].size = 256;
5555   config[3].count = 32;
5556
5557   config[4].type = VL_API_CLIENT_RING;
5558   config[4].size = 1024;
5559   config[4].count = 16;
5560
5561   config[5].type = VL_API_CLIENT_RING;
5562   config[5].size = 4096;
5563   config[5].count = 2;
5564
5565   config[6].type = VL_API_QUEUE;
5566   config[6].count = 128;
5567   config[6].size = sizeof (uword);
5568
5569   rv = vl_socket_client_init_shm (config, 1 /* want_pthread */ );
5570   if (!rv)
5571     vam->client_index_invalid = 1;
5572   return rv;
5573 #else
5574   return -99;
5575 #endif
5576 }
5577
5578 static void
5579 vl_api_session_rules_details_t_handler (vl_api_session_rules_details_t * mp)
5580 {
5581   vat_main_t *vam = &vat_main;
5582   fib_prefix_t lcl, rmt;
5583
5584   ip_prefix_decode (&mp->lcl, &lcl);
5585   ip_prefix_decode (&mp->rmt, &rmt);
5586
5587   if (lcl.fp_proto == FIB_PROTOCOL_IP4)
5588     {
5589       print (vam->ofp,
5590              "appns %u tp %u scope %d %U/%d %d %U/%d %d action: %d tag: %s",
5591              clib_net_to_host_u32 (mp->appns_index), mp->transport_proto,
5592              mp->scope, format_ip4_address, &lcl.fp_addr.ip4, lcl.fp_len,
5593              clib_net_to_host_u16 (mp->lcl_port), format_ip4_address,
5594              &rmt.fp_addr.ip4, rmt.fp_len,
5595              clib_net_to_host_u16 (mp->rmt_port),
5596              clib_net_to_host_u32 (mp->action_index), mp->tag);
5597     }
5598   else
5599     {
5600       print (vam->ofp,
5601              "appns %u tp %u scope %d %U/%d %d %U/%d %d action: %d tag: %s",
5602              clib_net_to_host_u32 (mp->appns_index), mp->transport_proto,
5603              mp->scope, format_ip6_address, &lcl.fp_addr.ip6, lcl.fp_len,
5604              clib_net_to_host_u16 (mp->lcl_port), format_ip6_address,
5605              &rmt.fp_addr.ip6, rmt.fp_len,
5606              clib_net_to_host_u16 (mp->rmt_port),
5607              clib_net_to_host_u32 (mp->action_index), mp->tag);
5608     }
5609 }
5610
5611 static void
5612 vl_api_session_rules_details_t_handler_json (vl_api_session_rules_details_t *
5613                                              mp)
5614 {
5615   vat_main_t *vam = &vat_main;
5616   vat_json_node_t *node = NULL;
5617   struct in6_addr ip6;
5618   struct in_addr ip4;
5619
5620   fib_prefix_t lcl, rmt;
5621
5622   ip_prefix_decode (&mp->lcl, &lcl);
5623   ip_prefix_decode (&mp->rmt, &rmt);
5624
5625   if (VAT_JSON_ARRAY != vam->json_tree.type)
5626     {
5627       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
5628       vat_json_init_array (&vam->json_tree);
5629     }
5630   node = vat_json_array_add (&vam->json_tree);
5631   vat_json_init_object (node);
5632
5633   vat_json_object_add_uint (node, "appns_index",
5634                             clib_net_to_host_u32 (mp->appns_index));
5635   vat_json_object_add_uint (node, "transport_proto", mp->transport_proto);
5636   vat_json_object_add_uint (node, "scope", mp->scope);
5637   vat_json_object_add_uint (node, "action_index",
5638                             clib_net_to_host_u32 (mp->action_index));
5639   vat_json_object_add_uint (node, "lcl_port",
5640                             clib_net_to_host_u16 (mp->lcl_port));
5641   vat_json_object_add_uint (node, "rmt_port",
5642                             clib_net_to_host_u16 (mp->rmt_port));
5643   vat_json_object_add_uint (node, "lcl_plen", lcl.fp_len);
5644   vat_json_object_add_uint (node, "rmt_plen", rmt.fp_len);
5645   vat_json_object_add_string_copy (node, "tag", mp->tag);
5646   if (lcl.fp_proto == FIB_PROTOCOL_IP4)
5647     {
5648       clib_memcpy (&ip4, &lcl.fp_addr.ip4, sizeof (ip4));
5649       vat_json_object_add_ip4 (node, "lcl_ip", ip4);
5650       clib_memcpy (&ip4, &rmt.fp_addr.ip4, sizeof (ip4));
5651       vat_json_object_add_ip4 (node, "rmt_ip", ip4);
5652     }
5653   else
5654     {
5655       clib_memcpy (&ip6, &lcl.fp_addr.ip6, sizeof (ip6));
5656       vat_json_object_add_ip6 (node, "lcl_ip", ip6);
5657       clib_memcpy (&ip6, &rmt.fp_addr.ip6, sizeof (ip6));
5658       vat_json_object_add_ip6 (node, "rmt_ip", ip6);
5659     }
5660 }
5661
5662 static int
5663 api_session_rule_add_del (vat_main_t * vam)
5664 {
5665   vl_api_session_rule_add_del_t *mp;
5666   unformat_input_t *i = vam->input;
5667   u32 proto = ~0, lcl_port, rmt_port, action = 0, lcl_plen, rmt_plen;
5668   u32 appns_index = 0, scope = 0;
5669   ip4_address_t lcl_ip4, rmt_ip4;
5670   ip6_address_t lcl_ip6, rmt_ip6;
5671   u8 is_ip4 = 1, conn_set = 0;
5672   u8 is_add = 1, *tag = 0;
5673   int ret;
5674   fib_prefix_t lcl, rmt;
5675
5676   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5677     {
5678       if (unformat (i, "del"))
5679         is_add = 0;
5680       else if (unformat (i, "add"))
5681         ;
5682       else if (unformat (i, "proto tcp"))
5683         proto = 0;
5684       else if (unformat (i, "proto udp"))
5685         proto = 1;
5686       else if (unformat (i, "appns %d", &appns_index))
5687         ;
5688       else if (unformat (i, "scope %d", &scope))
5689         ;
5690       else if (unformat (i, "tag %_%v%_", &tag))
5691         ;
5692       else
5693         if (unformat
5694             (i, "%U/%d %d %U/%d %d", unformat_ip4_address, &lcl_ip4,
5695              &lcl_plen, &lcl_port, unformat_ip4_address, &rmt_ip4, &rmt_plen,
5696              &rmt_port))
5697         {
5698           is_ip4 = 1;
5699           conn_set = 1;
5700         }
5701       else
5702         if (unformat
5703             (i, "%U/%d %d %U/%d %d", unformat_ip6_address, &lcl_ip6,
5704              &lcl_plen, &lcl_port, unformat_ip6_address, &rmt_ip6, &rmt_plen,
5705              &rmt_port))
5706         {
5707           is_ip4 = 0;
5708           conn_set = 1;
5709         }
5710       else if (unformat (i, "action %d", &action))
5711         ;
5712       else
5713         break;
5714     }
5715   if (proto == ~0 || !conn_set || action == ~0)
5716     {
5717       errmsg ("transport proto, connection and action must be set");
5718       return -99;
5719     }
5720
5721   if (scope > 3)
5722     {
5723       errmsg ("scope should be 0-3");
5724       return -99;
5725     }
5726
5727   M (SESSION_RULE_ADD_DEL, mp);
5728
5729   clib_memset (&lcl, 0, sizeof (lcl));
5730   clib_memset (&rmt, 0, sizeof (rmt));
5731   if (is_ip4)
5732     {
5733       ip_set (&lcl.fp_addr, &lcl_ip4, 1);
5734       ip_set (&rmt.fp_addr, &rmt_ip4, 1);
5735       lcl.fp_len = lcl_plen;
5736       rmt.fp_len = rmt_plen;
5737     }
5738   else
5739     {
5740       ip_set (&lcl.fp_addr, &lcl_ip6, 0);
5741       ip_set (&rmt.fp_addr, &rmt_ip6, 0);
5742       lcl.fp_len = lcl_plen;
5743       rmt.fp_len = rmt_plen;
5744     }
5745
5746
5747   ip_prefix_encode (&lcl, &mp->lcl);
5748   ip_prefix_encode (&rmt, &mp->rmt);
5749   mp->lcl_port = clib_host_to_net_u16 ((u16) lcl_port);
5750   mp->rmt_port = clib_host_to_net_u16 ((u16) rmt_port);
5751   mp->transport_proto =
5752     proto ? TRANSPORT_PROTO_API_UDP : TRANSPORT_PROTO_API_TCP;
5753   mp->action_index = clib_host_to_net_u32 (action);
5754   mp->appns_index = clib_host_to_net_u32 (appns_index);
5755   mp->scope = scope;
5756   mp->is_add = is_add;
5757   if (tag)
5758     {
5759       clib_memcpy (mp->tag, tag, vec_len (tag));
5760       vec_free (tag);
5761     }
5762
5763   S (mp);
5764   W (ret);
5765   return ret;
5766 }
5767
5768 static int
5769 api_session_rules_dump (vat_main_t * vam)
5770 {
5771   vl_api_session_rules_dump_t *mp;
5772   vl_api_control_ping_t *mp_ping;
5773   int ret;
5774
5775   if (!vam->json_output)
5776     {
5777       print (vam->ofp, "%=20s", "Session Rules");
5778     }
5779
5780   M (SESSION_RULES_DUMP, mp);
5781   /* send it... */
5782   S (mp);
5783
5784   /* Use a control ping for synchronization */
5785   MPING (CONTROL_PING, mp_ping);
5786   S (mp_ping);
5787
5788   /* Wait for a reply... */
5789   W (ret);
5790   return ret;
5791 }
5792
5793 static int
5794 api_ip_container_proxy_add_del (vat_main_t * vam)
5795 {
5796   vl_api_ip_container_proxy_add_del_t *mp;
5797   unformat_input_t *i = vam->input;
5798   u32 sw_if_index = ~0;
5799   vl_api_prefix_t pfx = { };
5800   u8 is_add = 1;
5801   int ret;
5802
5803   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5804     {
5805       if (unformat (i, "del"))
5806         is_add = 0;
5807       else if (unformat (i, "add"))
5808         ;
5809       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
5810         ;
5811       else if (unformat (i, "sw_if_index %u", &sw_if_index))
5812         ;
5813       else
5814         break;
5815     }
5816   if (sw_if_index == ~0 || pfx.len == 0)
5817     {
5818       errmsg ("address and sw_if_index must be set");
5819       return -99;
5820     }
5821
5822   M (IP_CONTAINER_PROXY_ADD_DEL, mp);
5823
5824   mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
5825   mp->is_add = is_add;
5826   clib_memcpy (&mp->pfx, &pfx, sizeof (pfx));
5827
5828   S (mp);
5829   W (ret);
5830   return ret;
5831 }
5832
5833 static int
5834 q_or_quit (vat_main_t * vam)
5835 {
5836 #if VPP_API_TEST_BUILTIN == 0
5837   longjmp (vam->jump_buf, 1);
5838 #endif
5839   return 0;                     /* not so much */
5840 }
5841
5842 static int
5843 q (vat_main_t * vam)
5844 {
5845   return q_or_quit (vam);
5846 }
5847
5848 static int
5849 quit (vat_main_t * vam)
5850 {
5851   return q_or_quit (vam);
5852 }
5853
5854 static int
5855 comment (vat_main_t * vam)
5856 {
5857   return 0;
5858 }
5859
5860 static int
5861 elog_save (vat_main_t * vam)
5862 {
5863 #if VPP_API_TEST_BUILTIN == 0
5864   elog_main_t *em = &vam->elog_main;
5865   unformat_input_t *i = vam->input;
5866   char *file, *chroot_file;
5867   clib_error_t *error;
5868
5869   if (!unformat (i, "%s", &file))
5870     {
5871       errmsg ("expected file name, got `%U'", format_unformat_error, i);
5872       return 0;
5873     }
5874
5875   /* It's fairly hard to get "../oopsie" through unformat; just in case */
5876   if (strstr (file, "..") || index (file, '/'))
5877     {
5878       errmsg ("illegal characters in filename '%s'", file);
5879       return 0;
5880     }
5881
5882   chroot_file = (char *) format (0, "/tmp/%s%c", file, 0);
5883
5884   vec_free (file);
5885
5886   errmsg ("Saving %wd of %wd events to %s",
5887           elog_n_events_in_buffer (em),
5888           elog_buffer_capacity (em), chroot_file);
5889
5890   error = elog_write_file (em, chroot_file, 1 /* flush ring */ );
5891   vec_free (chroot_file);
5892
5893   if (error)
5894     clib_error_report (error);
5895 #else
5896   errmsg ("Use the vpp event loger...");
5897 #endif
5898
5899   return 0;
5900 }
5901
5902 static int
5903 elog_setup (vat_main_t * vam)
5904 {
5905 #if VPP_API_TEST_BUILTIN == 0
5906   elog_main_t *em = &vam->elog_main;
5907   unformat_input_t *i = vam->input;
5908   u32 nevents = 128 << 10;
5909
5910   (void) unformat (i, "nevents %d", &nevents);
5911
5912   elog_init (em, nevents);
5913   vl_api_set_elog_main (em);
5914   vl_api_set_elog_trace_api_messages (1);
5915   errmsg ("Event logger initialized with %u events", nevents);
5916 #else
5917   errmsg ("Use the vpp event loger...");
5918 #endif
5919   return 0;
5920 }
5921
5922 static int
5923 elog_enable (vat_main_t * vam)
5924 {
5925 #if VPP_API_TEST_BUILTIN == 0
5926   elog_main_t *em = &vam->elog_main;
5927
5928   elog_enable_disable (em, 1 /* enable */ );
5929   vl_api_set_elog_trace_api_messages (1);
5930   errmsg ("Event logger enabled...");
5931 #else
5932   errmsg ("Use the vpp event loger...");
5933 #endif
5934   return 0;
5935 }
5936
5937 static int
5938 elog_disable (vat_main_t * vam)
5939 {
5940 #if VPP_API_TEST_BUILTIN == 0
5941   elog_main_t *em = &vam->elog_main;
5942
5943   elog_enable_disable (em, 0 /* enable */ );
5944   vl_api_set_elog_trace_api_messages (1);
5945   errmsg ("Event logger disabled...");
5946 #else
5947   errmsg ("Use the vpp event loger...");
5948 #endif
5949   return 0;
5950 }
5951
5952 static int
5953 statseg (vat_main_t * vam)
5954 {
5955   ssvm_private_t *ssvmp = &vam->stat_segment;
5956   ssvm_shared_header_t *shared_header = ssvmp->sh;
5957   vlib_counter_t **counters;
5958   u64 thread0_index1_packets;
5959   u64 thread0_index1_bytes;
5960   f64 vector_rate, input_rate;
5961   uword *p;
5962
5963   uword *counter_vector_by_name;
5964   if (vam->stat_segment_lockp == 0)
5965     {
5966       errmsg ("Stat segment not mapped...");
5967       return -99;
5968     }
5969
5970   /* look up "/if/rx for sw_if_index 1 as a test */
5971
5972   clib_spinlock_lock (vam->stat_segment_lockp);
5973
5974   counter_vector_by_name = (uword *) shared_header->opaque[1];
5975
5976   p = hash_get_mem (counter_vector_by_name, "/if/rx");
5977   if (p == 0)
5978     {
5979       clib_spinlock_unlock (vam->stat_segment_lockp);
5980       errmsg ("/if/tx not found?");
5981       return -99;
5982     }
5983
5984   /* Fish per-thread vector of combined counters from shared memory */
5985   counters = (vlib_counter_t **) p[0];
5986
5987   if (vec_len (counters[0]) < 2)
5988     {
5989       clib_spinlock_unlock (vam->stat_segment_lockp);
5990       errmsg ("/if/tx vector length %d", vec_len (counters[0]));
5991       return -99;
5992     }
5993
5994   /* Read thread 0 sw_if_index 1 counter */
5995   thread0_index1_packets = counters[0][1].packets;
5996   thread0_index1_bytes = counters[0][1].bytes;
5997
5998   p = hash_get_mem (counter_vector_by_name, "vector_rate");
5999   if (p == 0)
6000     {
6001       clib_spinlock_unlock (vam->stat_segment_lockp);
6002       errmsg ("vector_rate not found?");
6003       return -99;
6004     }
6005
6006   vector_rate = *(f64 *) (p[0]);
6007   p = hash_get_mem (counter_vector_by_name, "input_rate");
6008   if (p == 0)
6009     {
6010       clib_spinlock_unlock (vam->stat_segment_lockp);
6011       errmsg ("input_rate not found?");
6012       return -99;
6013     }
6014   input_rate = *(f64 *) (p[0]);
6015
6016   clib_spinlock_unlock (vam->stat_segment_lockp);
6017
6018   print (vam->ofp, "vector_rate %.2f input_rate %.2f",
6019          vector_rate, input_rate);
6020   print (vam->ofp, "thread 0 sw_if_index 1 rx pkts %lld, bytes %lld",
6021          thread0_index1_packets, thread0_index1_bytes);
6022
6023   return 0;
6024 }
6025
6026 static int
6027 cmd_cmp (void *a1, void *a2)
6028 {
6029   u8 **c1 = a1;
6030   u8 **c2 = a2;
6031
6032   return strcmp ((char *) (c1[0]), (char *) (c2[0]));
6033 }
6034
6035 static int
6036 help (vat_main_t * vam)
6037 {
6038   u8 **cmds = 0;
6039   u8 *name = 0;
6040   hash_pair_t *p;
6041   unformat_input_t *i = vam->input;
6042   int j;
6043
6044   if (unformat (i, "%s", &name))
6045     {
6046       uword *hs;
6047
6048       vec_add1 (name, 0);
6049
6050       hs = hash_get_mem (vam->help_by_name, name);
6051       if (hs)
6052         print (vam->ofp, "usage: %s %s", name, hs[0]);
6053       else
6054         print (vam->ofp, "No such msg / command '%s'", name);
6055       vec_free (name);
6056       return 0;
6057     }
6058
6059   print (vam->ofp, "Help is available for the following:");
6060
6061     /* *INDENT-OFF* */
6062     hash_foreach_pair (p, vam->function_by_name,
6063     ({
6064       vec_add1 (cmds, (u8 *)(p->key));
6065     }));
6066     /* *INDENT-ON* */
6067
6068   vec_sort_with_function (cmds, cmd_cmp);
6069
6070   for (j = 0; j < vec_len (cmds); j++)
6071     print (vam->ofp, "%s", cmds[j]);
6072
6073   vec_free (cmds);
6074   return 0;
6075 }
6076
6077 static int
6078 set (vat_main_t * vam)
6079 {
6080   u8 *name = 0, *value = 0;
6081   unformat_input_t *i = vam->input;
6082
6083   if (unformat (i, "%s", &name))
6084     {
6085       /* The input buffer is a vector, not a string. */
6086       value = vec_dup (i->buffer);
6087       vec_delete (value, i->index, 0);
6088       /* Almost certainly has a trailing newline */
6089       if (value[vec_len (value) - 1] == '\n')
6090         value[vec_len (value) - 1] = 0;
6091       /* Make sure it's a proper string, one way or the other */
6092       vec_add1 (value, 0);
6093       (void) clib_macro_set_value (&vam->macro_main,
6094                                    (char *) name, (char *) value);
6095     }
6096   else
6097     errmsg ("usage: set <name> <value>");
6098
6099   vec_free (name);
6100   vec_free (value);
6101   return 0;
6102 }
6103
6104 static int
6105 unset (vat_main_t * vam)
6106 {
6107   u8 *name = 0;
6108
6109   if (unformat (vam->input, "%s", &name))
6110     if (clib_macro_unset (&vam->macro_main, (char *) name) == 1)
6111       errmsg ("unset: %s wasn't set", name);
6112   vec_free (name);
6113   return 0;
6114 }
6115
6116 typedef struct
6117 {
6118   u8 *name;
6119   u8 *value;
6120 } macro_sort_t;
6121
6122
6123 static int
6124 macro_sort_cmp (void *a1, void *a2)
6125 {
6126   macro_sort_t *s1 = a1;
6127   macro_sort_t *s2 = a2;
6128
6129   return strcmp ((char *) (s1->name), (char *) (s2->name));
6130 }
6131
6132 static int
6133 dump_macro_table (vat_main_t * vam)
6134 {
6135   macro_sort_t *sort_me = 0, *sm;
6136   int i;
6137   hash_pair_t *p;
6138
6139     /* *INDENT-OFF* */
6140     hash_foreach_pair (p, vam->macro_main.the_value_table_hash,
6141     ({
6142       vec_add2 (sort_me, sm, 1);
6143       sm->name = (u8 *)(p->key);
6144       sm->value = (u8 *) (p->value[0]);
6145     }));
6146     /* *INDENT-ON* */
6147
6148   vec_sort_with_function (sort_me, macro_sort_cmp);
6149
6150   if (vec_len (sort_me))
6151     print (vam->ofp, "%-15s%s", "Name", "Value");
6152   else
6153     print (vam->ofp, "The macro table is empty...");
6154
6155   for (i = 0; i < vec_len (sort_me); i++)
6156     print (vam->ofp, "%-15s%s", sort_me[i].name, sort_me[i].value);
6157   return 0;
6158 }
6159
6160 static int
6161 dump_node_table (vat_main_t * vam)
6162 {
6163   int i, j;
6164   vlib_node_t *node, *next_node;
6165
6166   if (vec_len (vam->graph_nodes) == 0)
6167     {
6168       print (vam->ofp, "Node table empty, issue get_node_graph...");
6169       return 0;
6170     }
6171
6172   for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
6173     {
6174       node = vam->graph_nodes[0][i];
6175       print (vam->ofp, "[%d] %s", i, node->name);
6176       for (j = 0; j < vec_len (node->next_nodes); j++)
6177         {
6178           if (node->next_nodes[j] != ~0)
6179             {
6180               next_node = vam->graph_nodes[0][node->next_nodes[j]];
6181               print (vam->ofp, "  [%d] %s", j, next_node->name);
6182             }
6183         }
6184     }
6185   return 0;
6186 }
6187
6188 static int
6189 value_sort_cmp (void *a1, void *a2)
6190 {
6191   name_sort_t *n1 = a1;
6192   name_sort_t *n2 = a2;
6193
6194   if (n1->value < n2->value)
6195     return -1;
6196   if (n1->value > n2->value)
6197     return 1;
6198   return 0;
6199 }
6200
6201
6202 static int
6203 dump_msg_api_table (vat_main_t * vam)
6204 {
6205   api_main_t *am = vlibapi_get_main ();
6206   name_sort_t *nses = 0, *ns;
6207   hash_pair_t *hp;
6208   int i;
6209
6210   /* *INDENT-OFF* */
6211   hash_foreach_pair (hp, am->msg_index_by_name_and_crc,
6212   ({
6213     vec_add2 (nses, ns, 1);
6214     ns->name = (u8 *)(hp->key);
6215     ns->value = (u32) hp->value[0];
6216   }));
6217   /* *INDENT-ON* */
6218
6219   vec_sort_with_function (nses, value_sort_cmp);
6220
6221   for (i = 0; i < vec_len (nses); i++)
6222     print (vam->ofp, " [%d]: %s", nses[i].value, nses[i].name);
6223   vec_free (nses);
6224   return 0;
6225 }
6226
6227 static int
6228 get_msg_id (vat_main_t * vam)
6229 {
6230   u8 *name_and_crc;
6231   u32 message_index;
6232
6233   if (unformat (vam->input, "%s", &name_and_crc))
6234     {
6235       message_index = vl_msg_api_get_msg_index (name_and_crc);
6236       if (message_index == ~0)
6237         {
6238           print (vam->ofp, " '%s' not found", name_and_crc);
6239           return 0;
6240         }
6241       print (vam->ofp, " '%s' has message index %d",
6242              name_and_crc, message_index);
6243       return 0;
6244     }
6245   errmsg ("name_and_crc required...");
6246   return 0;
6247 }
6248
6249 static int
6250 search_node_table (vat_main_t * vam)
6251 {
6252   unformat_input_t *line_input = vam->input;
6253   u8 *node_to_find;
6254   int j;
6255   vlib_node_t *node, *next_node;
6256   uword *p;
6257
6258   if (vam->graph_node_index_by_name == 0)
6259     {
6260       print (vam->ofp, "Node table empty, issue get_node_graph...");
6261       return 0;
6262     }
6263
6264   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
6265     {
6266       if (unformat (line_input, "%s", &node_to_find))
6267         {
6268           vec_add1 (node_to_find, 0);
6269           p = hash_get_mem (vam->graph_node_index_by_name, node_to_find);
6270           if (p == 0)
6271             {
6272               print (vam->ofp, "%s not found...", node_to_find);
6273               goto out;
6274             }
6275           node = vam->graph_nodes[0][p[0]];
6276           print (vam->ofp, "[%d] %s", p[0], node->name);
6277           for (j = 0; j < vec_len (node->next_nodes); j++)
6278             {
6279               if (node->next_nodes[j] != ~0)
6280                 {
6281                   next_node = vam->graph_nodes[0][node->next_nodes[j]];
6282                   print (vam->ofp, "  [%d] %s", j, next_node->name);
6283                 }
6284             }
6285         }
6286
6287       else
6288         {
6289           clib_warning ("parse error '%U'", format_unformat_error,
6290                         line_input);
6291           return -99;
6292         }
6293
6294     out:
6295       vec_free (node_to_find);
6296
6297     }
6298
6299   return 0;
6300 }
6301
6302
6303 static int
6304 script (vat_main_t * vam)
6305 {
6306 #if (VPP_API_TEST_BUILTIN==0)
6307   u8 *s = 0;
6308   char *save_current_file;
6309   unformat_input_t save_input;
6310   jmp_buf save_jump_buf;
6311   u32 save_line_number;
6312
6313   FILE *new_fp, *save_ifp;
6314
6315   if (unformat (vam->input, "%s", &s))
6316     {
6317       new_fp = fopen ((char *) s, "r");
6318       if (new_fp == 0)
6319         {
6320           errmsg ("Couldn't open script file %s", s);
6321           vec_free (s);
6322           return -99;
6323         }
6324     }
6325   else
6326     {
6327       errmsg ("Missing script name");
6328       return -99;
6329     }
6330
6331   clib_memcpy (&save_input, &vam->input, sizeof (save_input));
6332   clib_memcpy (&save_jump_buf, &vam->jump_buf, sizeof (save_jump_buf));
6333   save_ifp = vam->ifp;
6334   save_line_number = vam->input_line_number;
6335   save_current_file = (char *) vam->current_file;
6336
6337   vam->input_line_number = 0;
6338   vam->ifp = new_fp;
6339   vam->current_file = s;
6340   do_one_file (vam);
6341
6342   clib_memcpy (&vam->input, &save_input, sizeof (save_input));
6343   clib_memcpy (&vam->jump_buf, &save_jump_buf, sizeof (save_jump_buf));
6344   vam->ifp = save_ifp;
6345   vam->input_line_number = save_line_number;
6346   vam->current_file = (u8 *) save_current_file;
6347   vec_free (s);
6348
6349   return 0;
6350 #else
6351   clib_warning ("use the exec command...");
6352   return -99;
6353 #endif
6354 }
6355
6356 static int
6357 echo (vat_main_t * vam)
6358 {
6359   print (vam->ofp, "%v", vam->input->buffer);
6360   return 0;
6361 }
6362
6363 /* List of API message constructors, CLI names map to api_xxx */
6364 #define foreach_vpe_api_msg                                             \
6365 _(create_loopback,"[mac <mac-addr>] [instance <instance>]")             \
6366 _(sw_interface_dump,"")                                                 \
6367 _(sw_interface_set_flags,                                               \
6368   "<intfc> | sw_if_index <id> admin-up | admin-down link-up | link down") \
6369 _(sw_interface_add_del_address,                                         \
6370   "<intfc> | sw_if_index <id> <ip4-address> | <ip6-address> [del] [del-all] ") \
6371 _(sw_interface_set_rx_placement,                                        \
6372   "<intfc> | sw_if_index <id> [queue <id>] [worker <id> | main]")       \
6373 _(sw_interface_rx_placement_dump,                                       \
6374   "[<intfc> | sw_if_index <id>]")                                         \
6375 _(sw_interface_set_table,                                               \
6376   "<intfc> | sw_if_index <id> vrf <table-id> [ipv6]")                   \
6377 _(ip_table_add_del,                                                     \
6378   "table <n> [ipv6] [add | del]\n")                                     \
6379 _(ip_route_add_del,                                                     \
6380   "<addr>/<mask> via <<addr>|<intfc>|sw_if_index <id>|via-label <n>>\n" \
6381   "[table-id <n>] [<intfc> | sw_if_index <id>] [resolve-attempts <n>]\n"\
6382   "[weight <n>] [drop] [local] [classify <n>]  [out-label <n>]\n"       \
6383   "[multipath] [count <n>] [del]")                                      \
6384 _(ip_mroute_add_del,                                                    \
6385   "<src> <grp>/<mask> [table-id <n>]\n"                                 \
6386   "[<intfc> | sw_if_index <id>] [local] [del]")                         \
6387 _(sw_interface_set_unnumbered,                                          \
6388   "<intfc> | sw_if_index <id> unnum_if_index <id> [del]")               \
6389 _(create_vlan_subif, "<intfc> | sw_if_index <id> vlan <n>")             \
6390 _(create_subif, "<intfc> | sw_if_index <id> sub_id <n>\n"               \
6391   "[outer_vlan_id <n>][inner_vlan_id <n>]\n"                            \
6392   "[no_tags][one_tag][two_tags][dot1ad][exact_match][default_sub]\n"    \
6393   "[outer_vlan_id_any][inner_vlan_id_any]")                             \
6394 _(ip_table_replace_begin, "table <n> [ipv6]")                           \
6395 _(ip_table_flush, "table <n> [ipv6]")                                   \
6396 _(ip_table_replace_end, "table <n> [ipv6]")                             \
6397 _(set_ip_flow_hash,                                                     \
6398   "vrf <n> [src] [dst] [sport] [dport] [proto] [reverse] [ipv6]")       \
6399 _(sw_interface_ip6_enable_disable,                                      \
6400   "<intfc> | sw_if_index <id> enable | disable")                        \
6401 _(get_node_index, "node <node-name")                                    \
6402 _(add_node_next, "node <node-name> next <next-node-name>")              \
6403 _(show_version, "")                                                     \
6404 _(show_threads, "")                                                     \
6405 _(interface_name_renumber,                                              \
6406   "<intfc> | sw_if_index <nn> new_show_dev_instance <nn>")              \
6407 _(ip_address_dump, "(ipv4 | ipv6) (<intfc> | sw_if_index <id>)")        \
6408 _(ip_dump, "ipv4 | ipv6")                                               \
6409 _(delete_loopback,"sw_if_index <nn>")                                   \
6410 _(want_interface_events,  "enable|disable")                             \
6411 _(get_first_msg_id, "client <name>")                                    \
6412 _(get_node_graph, " ")                                                  \
6413 _(sw_interface_clear_stats,"<intfc> | sw_if_index <nn>")                \
6414 _(ioam_enable, "[trace] [pow] [ppc <encap|decap>]")                     \
6415 _(ioam_disable, "")                                                     \
6416 _(get_next_index, "node-name <node-name> next-node-name <node-name>")   \
6417 _(ip_source_and_port_range_check_add_del,                               \
6418   "<ip-addr>/<mask> range <nn>-<nn> vrf <id>")                          \
6419 _(ip_source_and_port_range_check_interface_add_del,                     \
6420   "<intf> | sw_if_index <nn> [tcp-out-vrf <id>] [tcp-in-vrf <id>]"      \
6421   "[udp-in-vrf <id>] [udp-out-vrf <id>]")                               \
6422 _(delete_subif,"<intfc> | sw_if_index <nn>")                            \
6423 _(ip_table_dump, "")                                                    \
6424 _(ip_route_dump, "table-id [ip4|ip6]")                                  \
6425 _(ip_mtable_dump, "")                                                   \
6426 _(ip_mroute_dump, "table-id [ip4|ip6]")                                 \
6427 _(sw_interface_tag_add_del, "<intfc> | sw_if_index <nn> tag <text>"     \
6428 "[disable]")                                                            \
6429 _(sw_interface_add_del_mac_address, "<intfc> | sw_if_index <nn> "       \
6430   "mac <mac-address> [del]")                                            \
6431 _(hw_interface_set_mtu, "<intfc> | hw_if_index <nn> mtu <nn>")        \
6432 _(sw_interface_get_table, "<intfc> | sw_if_index <id> [ipv6]")          \
6433 _(sock_init_shm, "size <nnn>")                                          \
6434 _(app_namespace_add_del, "[add] id <ns-id> secret <nn> sw_if_index <nn>")\
6435 _(session_rule_add_del, "[add|del] proto <tcp/udp> <lcl-ip>/<plen> "    \
6436   "<lcl-port> <rmt-ip>/<plen> <rmt-port> action <nn>")                  \
6437 _(session_rules_dump, "")                                               \
6438 _(ip_container_proxy_add_del, "[add|del] <address> <sw_if_index>")      \
6439
6440 /* List of command functions, CLI names map directly to functions */
6441 #define foreach_cli_function                                    \
6442 _(comment, "usage: comment <ignore-rest-of-line>")              \
6443 _(dump_interface_table, "usage: dump_interface_table")          \
6444 _(dump_sub_interface_table, "usage: dump_sub_interface_table")  \
6445 _(dump_ipv4_table, "usage: dump_ipv4_table")                    \
6446 _(dump_ipv6_table, "usage: dump_ipv6_table")                    \
6447 _(dump_macro_table, "usage: dump_macro_table ")                 \
6448 _(dump_node_table, "usage: dump_node_table")                    \
6449 _(dump_msg_api_table, "usage: dump_msg_api_table")              \
6450 _(elog_setup, "usage: elog_setup [nevents, default 128K]")      \
6451 _(elog_disable, "usage: elog_disable")                          \
6452 _(elog_enable, "usage: elog_enable")                            \
6453 _(elog_save, "usage: elog_save <filename>")                     \
6454 _(get_msg_id, "usage: get_msg_id name_and_crc")                 \
6455 _(echo, "usage: echo <message>")                                \
6456 _(exec, "usage: exec <vpe-debug-CLI-command>")                  \
6457 _(exec_inband, "usage: exec_inband <vpe-debug-CLI-command>")    \
6458 _(help, "usage: help")                                          \
6459 _(q, "usage: quit")                                             \
6460 _(quit, "usage: quit")                                          \
6461 _(search_node_table, "usage: search_node_table <name>...")      \
6462 _(set, "usage: set <variable-name> <value>")                    \
6463 _(script, "usage: script <file-name>")                          \
6464 _(statseg, "usage: statseg")                                    \
6465 _(unset, "usage: unset <variable-name>")
6466
6467 #define _(N,n)                                  \
6468     static void vl_api_##n##_t_handler_uni      \
6469     (vl_api_##n##_t * mp)                       \
6470     {                                           \
6471         vat_main_t * vam = &vat_main;           \
6472         if (vam->json_output) {                 \
6473             vl_api_##n##_t_handler_json(mp);    \
6474         } else {                                \
6475             vl_api_##n##_t_handler(mp);         \
6476         }                                       \
6477     }
6478 foreach_vpe_api_reply_msg;
6479 #if VPP_API_TEST_BUILTIN == 0
6480 foreach_standalone_reply_msg;
6481 #endif
6482 #undef _
6483
6484 void
6485 vat_api_hookup (vat_main_t * vam)
6486 {
6487 #define _(N,n)                                                  \
6488     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
6489                            vl_api_##n##_t_handler_uni,          \
6490                            vl_noop_handler,                     \
6491                            vl_api_##n##_t_endian,               \
6492                            vl_api_##n##_t_print,                \
6493                            sizeof(vl_api_##n##_t), 1);
6494   foreach_vpe_api_reply_msg;
6495 #if VPP_API_TEST_BUILTIN == 0
6496   foreach_standalone_reply_msg;
6497 #endif
6498 #undef _
6499
6500 #if (VPP_API_TEST_BUILTIN==0)
6501   vl_msg_api_set_first_available_msg_id (VL_MSG_FIRST_AVAILABLE);
6502
6503   vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
6504
6505   vam->function_by_name = hash_create_string (0, sizeof (uword));
6506
6507   vam->help_by_name = hash_create_string (0, sizeof (uword));
6508 #endif
6509
6510   /* API messages we can send */
6511 #define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
6512   foreach_vpe_api_msg;
6513 #undef _
6514
6515   /* Help strings */
6516 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
6517   foreach_vpe_api_msg;
6518 #undef _
6519
6520   /* CLI functions */
6521 #define _(n,h) hash_set_mem (vam->function_by_name, #n, n);
6522   foreach_cli_function;
6523 #undef _
6524
6525   /* Help strings */
6526 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
6527   foreach_cli_function;
6528 #undef _
6529 }
6530
6531 #if VPP_API_TEST_BUILTIN
6532 static clib_error_t *
6533 vat_api_hookup_shim (vlib_main_t * vm)
6534 {
6535   vat_api_hookup (&vat_main);
6536   return 0;
6537 }
6538
6539 VLIB_API_INIT_FUNCTION (vat_api_hookup_shim);
6540 #endif
6541
6542 /*
6543  * fd.io coding-style-patch-verification: ON
6544  *
6545  * Local Variables:
6546  * eval: (c-set-style "gnu")
6547  * End:
6548  */