mpls: 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 increment_mac_address (u8 * mac)
628 {
629   u64 tmp = *((u64 *) mac);
630   tmp = clib_net_to_host_u64 (tmp);
631   tmp += 1 << 16;               /* skip unused (least significant) octets */
632   tmp = clib_host_to_net_u64 (tmp);
633
634   clib_memcpy (mac, &tmp, 6);
635 }
636
637 static void
638 vat_json_object_add_address (vat_json_node_t * node,
639                              const char *str, const vl_api_address_t * addr)
640 {
641   if (ADDRESS_IP6 == addr->af)
642     {
643       struct in6_addr ip6;
644
645       clib_memcpy (&ip6, &addr->un.ip6, sizeof (ip6));
646       vat_json_object_add_ip6 (node, str, ip6);
647     }
648   else
649     {
650       struct in_addr ip4;
651
652       clib_memcpy (&ip4, &addr->un.ip4, sizeof (ip4));
653       vat_json_object_add_ip4 (node, str, ip4);
654     }
655 }
656
657 static void
658 vat_json_object_add_prefix (vat_json_node_t * node,
659                             const vl_api_prefix_t * prefix)
660 {
661   vat_json_object_add_uint (node, "len", prefix->len);
662   vat_json_object_add_address (node, "address", &prefix->address);
663 }
664
665 static void vl_api_create_loopback_reply_t_handler
666   (vl_api_create_loopback_reply_t * mp)
667 {
668   vat_main_t *vam = &vat_main;
669   i32 retval = ntohl (mp->retval);
670
671   vam->retval = retval;
672   vam->regenerate_interface_table = 1;
673   vam->sw_if_index = ntohl (mp->sw_if_index);
674   vam->result_ready = 1;
675 }
676
677 static void vl_api_create_loopback_reply_t_handler_json
678   (vl_api_create_loopback_reply_t * mp)
679 {
680   vat_main_t *vam = &vat_main;
681   vat_json_node_t node;
682
683   vat_json_init_object (&node);
684   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
685   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
686
687   vat_json_print (vam->ofp, &node);
688   vat_json_free (&node);
689   vam->retval = ntohl (mp->retval);
690   vam->result_ready = 1;
691 }
692
693 static void vl_api_create_loopback_instance_reply_t_handler
694   (vl_api_create_loopback_instance_reply_t * mp)
695 {
696   vat_main_t *vam = &vat_main;
697   i32 retval = ntohl (mp->retval);
698
699   vam->retval = retval;
700   vam->regenerate_interface_table = 1;
701   vam->sw_if_index = ntohl (mp->sw_if_index);
702   vam->result_ready = 1;
703 }
704
705 static void vl_api_create_loopback_instance_reply_t_handler_json
706   (vl_api_create_loopback_instance_reply_t * mp)
707 {
708   vat_main_t *vam = &vat_main;
709   vat_json_node_t node;
710
711   vat_json_init_object (&node);
712   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
713   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
714
715   vat_json_print (vam->ofp, &node);
716   vat_json_free (&node);
717   vam->retval = ntohl (mp->retval);
718   vam->result_ready = 1;
719 }
720
721 static void vl_api_create_vlan_subif_reply_t_handler
722   (vl_api_create_vlan_subif_reply_t * mp)
723 {
724   vat_main_t *vam = &vat_main;
725   i32 retval = ntohl (mp->retval);
726
727   vam->retval = retval;
728   vam->regenerate_interface_table = 1;
729   vam->sw_if_index = ntohl (mp->sw_if_index);
730   vam->result_ready = 1;
731 }
732
733 static void vl_api_create_vlan_subif_reply_t_handler_json
734   (vl_api_create_vlan_subif_reply_t * mp)
735 {
736   vat_main_t *vam = &vat_main;
737   vat_json_node_t node;
738
739   vat_json_init_object (&node);
740   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
741   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
742
743   vat_json_print (vam->ofp, &node);
744   vat_json_free (&node);
745
746   vam->retval = ntohl (mp->retval);
747   vam->result_ready = 1;
748 }
749
750 static void vl_api_create_subif_reply_t_handler
751   (vl_api_create_subif_reply_t * mp)
752 {
753   vat_main_t *vam = &vat_main;
754   i32 retval = ntohl (mp->retval);
755
756   vam->retval = retval;
757   vam->regenerate_interface_table = 1;
758   vam->sw_if_index = ntohl (mp->sw_if_index);
759   vam->result_ready = 1;
760 }
761
762 static void vl_api_create_subif_reply_t_handler_json
763   (vl_api_create_subif_reply_t * mp)
764 {
765   vat_main_t *vam = &vat_main;
766   vat_json_node_t node;
767
768   vat_json_init_object (&node);
769   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
770   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
771
772   vat_json_print (vam->ofp, &node);
773   vat_json_free (&node);
774
775   vam->retval = ntohl (mp->retval);
776   vam->result_ready = 1;
777 }
778
779 static void vl_api_interface_name_renumber_reply_t_handler
780   (vl_api_interface_name_renumber_reply_t * mp)
781 {
782   vat_main_t *vam = &vat_main;
783   i32 retval = ntohl (mp->retval);
784
785   vam->retval = retval;
786   vam->regenerate_interface_table = 1;
787   vam->result_ready = 1;
788 }
789
790 static void vl_api_interface_name_renumber_reply_t_handler_json
791   (vl_api_interface_name_renumber_reply_t * mp)
792 {
793   vat_main_t *vam = &vat_main;
794   vat_json_node_t node;
795
796   vat_json_init_object (&node);
797   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
798
799   vat_json_print (vam->ofp, &node);
800   vat_json_free (&node);
801
802   vam->retval = ntohl (mp->retval);
803   vam->result_ready = 1;
804 }
805
806 /*
807  * Special-case: build the interface table, maintain
808  * the next loopback sw_if_index vbl.
809  */
810 static void vl_api_sw_interface_details_t_handler
811   (vl_api_sw_interface_details_t * mp)
812 {
813   vat_main_t *vam = &vat_main;
814   u8 *s = format (0, "%s%c", mp->interface_name, 0);
815
816   hash_set_mem (vam->sw_if_index_by_interface_name, s,
817                 ntohl (mp->sw_if_index));
818
819   /* In sub interface case, fill the sub interface table entry */
820   if (mp->sw_if_index != mp->sup_sw_if_index)
821     {
822       sw_interface_subif_t *sub = NULL;
823
824       vec_add2 (vam->sw_if_subif_table, sub, 1);
825
826       vec_validate (sub->interface_name, strlen ((char *) s) + 1);
827       strncpy ((char *) sub->interface_name, (char *) s,
828                vec_len (sub->interface_name));
829       sub->sw_if_index = ntohl (mp->sw_if_index);
830       sub->sub_id = ntohl (mp->sub_id);
831
832       sub->raw_flags = ntohl (mp->sub_if_flags & SUB_IF_API_FLAG_MASK_VNET);
833
834       sub->sub_number_of_tags = mp->sub_number_of_tags;
835       sub->sub_outer_vlan_id = ntohs (mp->sub_outer_vlan_id);
836       sub->sub_inner_vlan_id = ntohs (mp->sub_inner_vlan_id);
837
838       /* vlan tag rewrite */
839       sub->vtr_op = ntohl (mp->vtr_op);
840       sub->vtr_push_dot1q = ntohl (mp->vtr_push_dot1q);
841       sub->vtr_tag1 = ntohl (mp->vtr_tag1);
842       sub->vtr_tag2 = ntohl (mp->vtr_tag2);
843     }
844 }
845
846 static void vl_api_sw_interface_details_t_handler_json
847   (vl_api_sw_interface_details_t * mp)
848 {
849   vat_main_t *vam = &vat_main;
850   vat_json_node_t *node = NULL;
851
852   if (VAT_JSON_ARRAY != vam->json_tree.type)
853     {
854       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
855       vat_json_init_array (&vam->json_tree);
856     }
857   node = vat_json_array_add (&vam->json_tree);
858
859   vat_json_init_object (node);
860   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
861   vat_json_object_add_uint (node, "sup_sw_if_index",
862                             ntohl (mp->sup_sw_if_index));
863   vat_json_object_add_bytes (node, "l2_address", mp->l2_address,
864                              sizeof (mp->l2_address));
865   vat_json_object_add_string_copy (node, "interface_name",
866                                    mp->interface_name);
867   vat_json_object_add_string_copy (node, "interface_dev_type",
868                                    mp->interface_dev_type);
869   vat_json_object_add_uint (node, "flags", mp->flags);
870   vat_json_object_add_uint (node, "link_duplex", mp->link_duplex);
871   vat_json_object_add_uint (node, "link_speed", mp->link_speed);
872   vat_json_object_add_uint (node, "mtu", ntohs (mp->link_mtu));
873   vat_json_object_add_uint (node, "sub_id", ntohl (mp->sub_id));
874   vat_json_object_add_uint (node, "sub_number_of_tags",
875                             mp->sub_number_of_tags);
876   vat_json_object_add_uint (node, "sub_outer_vlan_id",
877                             ntohs (mp->sub_outer_vlan_id));
878   vat_json_object_add_uint (node, "sub_inner_vlan_id",
879                             ntohs (mp->sub_inner_vlan_id));
880   vat_json_object_add_uint (node, "sub_if_flags", ntohl (mp->sub_if_flags));
881   vat_json_object_add_uint (node, "vtr_op", ntohl (mp->vtr_op));
882   vat_json_object_add_uint (node, "vtr_push_dot1q",
883                             ntohl (mp->vtr_push_dot1q));
884   vat_json_object_add_uint (node, "vtr_tag1", ntohl (mp->vtr_tag1));
885   vat_json_object_add_uint (node, "vtr_tag2", ntohl (mp->vtr_tag2));
886   if (ntohl (mp->sub_if_flags) & SUB_IF_API_FLAG_DOT1AH)
887     {
888       vat_json_object_add_string_copy (node, "pbb_vtr_dmac",
889                                        format (0, "%U",
890                                                format_ethernet_address,
891                                                &mp->b_dmac));
892       vat_json_object_add_string_copy (node, "pbb_vtr_smac",
893                                        format (0, "%U",
894                                                format_ethernet_address,
895                                                &mp->b_smac));
896       vat_json_object_add_uint (node, "pbb_vtr_b_vlanid", mp->b_vlanid);
897       vat_json_object_add_uint (node, "pbb_vtr_i_sid", mp->i_sid);
898     }
899 }
900
901 #if VPP_API_TEST_BUILTIN == 0
902 static void vl_api_sw_interface_event_t_handler
903   (vl_api_sw_interface_event_t * mp)
904 {
905   vat_main_t *vam = &vat_main;
906   if (vam->interface_event_display)
907     errmsg ("interface flags: sw_if_index %d %s %s",
908             ntohl (mp->sw_if_index),
909             ((ntohl (mp->flags)) & IF_STATUS_API_FLAG_ADMIN_UP) ?
910             "admin-up" : "admin-down",
911             ((ntohl (mp->flags)) & IF_STATUS_API_FLAG_LINK_UP) ?
912             "link-up" : "link-down");
913 }
914 #endif
915
916 __clib_unused static void
917 vl_api_sw_interface_event_t_handler_json (vl_api_sw_interface_event_t * mp)
918 {
919   /* JSON output not supported */
920 }
921
922 static void
923 vl_api_cli_reply_t_handler (vl_api_cli_reply_t * mp)
924 {
925   vat_main_t *vam = &vat_main;
926   i32 retval = ntohl (mp->retval);
927
928   vam->retval = retval;
929   vam->shmem_result = uword_to_pointer (mp->reply_in_shmem, u8 *);
930   vam->result_ready = 1;
931 }
932
933 static void
934 vl_api_cli_reply_t_handler_json (vl_api_cli_reply_t * mp)
935 {
936   vat_main_t *vam = &vat_main;
937   vat_json_node_t node;
938   void *oldheap;
939   u8 *reply;
940
941   vat_json_init_object (&node);
942   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
943   vat_json_object_add_uint (&node, "reply_in_shmem",
944                             ntohl (mp->reply_in_shmem));
945   /* Toss the shared-memory original... */
946   oldheap = vl_msg_push_heap ();
947
948   reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
949   vec_free (reply);
950
951   vl_msg_pop_heap (oldheap);
952
953   vat_json_print (vam->ofp, &node);
954   vat_json_free (&node);
955
956   vam->retval = ntohl (mp->retval);
957   vam->result_ready = 1;
958 }
959
960 static void
961 vl_api_cli_inband_reply_t_handler (vl_api_cli_inband_reply_t * mp)
962 {
963   vat_main_t *vam = &vat_main;
964   i32 retval = ntohl (mp->retval);
965
966   vec_reset_length (vam->cmd_reply);
967
968   vam->retval = retval;
969   if (retval == 0)
970     vam->cmd_reply = vl_api_from_api_to_new_vec (mp, &mp->reply);
971   vam->result_ready = 1;
972 }
973
974 static void
975 vl_api_cli_inband_reply_t_handler_json (vl_api_cli_inband_reply_t * mp)
976 {
977   vat_main_t *vam = &vat_main;
978   vat_json_node_t node;
979   u8 *reply = 0;                /* reply vector */
980
981   reply = vl_api_from_api_to_new_vec (mp, &mp->reply);
982   vec_reset_length (vam->cmd_reply);
983
984   vat_json_init_object (&node);
985   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
986   vat_json_object_add_string_copy (&node, "reply", reply);
987
988   vat_json_print (vam->ofp, &node);
989   vat_json_free (&node);
990   vec_free (reply);
991
992   vam->retval = ntohl (mp->retval);
993   vam->result_ready = 1;
994 }
995
996 static void vl_api_get_node_index_reply_t_handler
997   (vl_api_get_node_index_reply_t * mp)
998 {
999   vat_main_t *vam = &vat_main;
1000   i32 retval = ntohl (mp->retval);
1001   if (vam->async_mode)
1002     {
1003       vam->async_errors += (retval < 0);
1004     }
1005   else
1006     {
1007       vam->retval = retval;
1008       if (retval == 0)
1009         errmsg ("node index %d", ntohl (mp->node_index));
1010       vam->result_ready = 1;
1011     }
1012 }
1013
1014 static void vl_api_get_node_index_reply_t_handler_json
1015   (vl_api_get_node_index_reply_t * mp)
1016 {
1017   vat_main_t *vam = &vat_main;
1018   vat_json_node_t node;
1019
1020   vat_json_init_object (&node);
1021   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1022   vat_json_object_add_uint (&node, "node_index", ntohl (mp->node_index));
1023
1024   vat_json_print (vam->ofp, &node);
1025   vat_json_free (&node);
1026
1027   vam->retval = ntohl (mp->retval);
1028   vam->result_ready = 1;
1029 }
1030
1031 static void vl_api_get_next_index_reply_t_handler
1032   (vl_api_get_next_index_reply_t * mp)
1033 {
1034   vat_main_t *vam = &vat_main;
1035   i32 retval = ntohl (mp->retval);
1036   if (vam->async_mode)
1037     {
1038       vam->async_errors += (retval < 0);
1039     }
1040   else
1041     {
1042       vam->retval = retval;
1043       if (retval == 0)
1044         errmsg ("next node index %d", ntohl (mp->next_index));
1045       vam->result_ready = 1;
1046     }
1047 }
1048
1049 static void vl_api_get_next_index_reply_t_handler_json
1050   (vl_api_get_next_index_reply_t * mp)
1051 {
1052   vat_main_t *vam = &vat_main;
1053   vat_json_node_t node;
1054
1055   vat_json_init_object (&node);
1056   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1057   vat_json_object_add_uint (&node, "next_index", ntohl (mp->next_index));
1058
1059   vat_json_print (vam->ofp, &node);
1060   vat_json_free (&node);
1061
1062   vam->retval = ntohl (mp->retval);
1063   vam->result_ready = 1;
1064 }
1065
1066 static void vl_api_add_node_next_reply_t_handler
1067   (vl_api_add_node_next_reply_t * mp)
1068 {
1069   vat_main_t *vam = &vat_main;
1070   i32 retval = ntohl (mp->retval);
1071   if (vam->async_mode)
1072     {
1073       vam->async_errors += (retval < 0);
1074     }
1075   else
1076     {
1077       vam->retval = retval;
1078       if (retval == 0)
1079         errmsg ("next index %d", ntohl (mp->next_index));
1080       vam->result_ready = 1;
1081     }
1082 }
1083
1084 static void vl_api_add_node_next_reply_t_handler_json
1085   (vl_api_add_node_next_reply_t * mp)
1086 {
1087   vat_main_t *vam = &vat_main;
1088   vat_json_node_t node;
1089
1090   vat_json_init_object (&node);
1091   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1092   vat_json_object_add_uint (&node, "next_index", ntohl (mp->next_index));
1093
1094   vat_json_print (vam->ofp, &node);
1095   vat_json_free (&node);
1096
1097   vam->retval = ntohl (mp->retval);
1098   vam->result_ready = 1;
1099 }
1100
1101 static void vl_api_show_version_reply_t_handler
1102   (vl_api_show_version_reply_t * mp)
1103 {
1104   vat_main_t *vam = &vat_main;
1105   i32 retval = ntohl (mp->retval);
1106
1107   if (retval >= 0)
1108     {
1109       errmsg ("        program: %s", mp->program);
1110       errmsg ("        version: %s", mp->version);
1111       errmsg ("     build date: %s", mp->build_date);
1112       errmsg ("build directory: %s", mp->build_directory);
1113     }
1114   vam->retval = retval;
1115   vam->result_ready = 1;
1116 }
1117
1118 static void vl_api_show_version_reply_t_handler_json
1119   (vl_api_show_version_reply_t * mp)
1120 {
1121   vat_main_t *vam = &vat_main;
1122   vat_json_node_t node;
1123
1124   vat_json_init_object (&node);
1125   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1126   vat_json_object_add_string_copy (&node, "program", mp->program);
1127   vat_json_object_add_string_copy (&node, "version", mp->version);
1128   vat_json_object_add_string_copy (&node, "build_date", mp->build_date);
1129   vat_json_object_add_string_copy (&node, "build_directory",
1130                                    mp->build_directory);
1131
1132   vat_json_print (vam->ofp, &node);
1133   vat_json_free (&node);
1134
1135   vam->retval = ntohl (mp->retval);
1136   vam->result_ready = 1;
1137 }
1138
1139 static void vl_api_show_threads_reply_t_handler
1140   (vl_api_show_threads_reply_t * mp)
1141 {
1142   vat_main_t *vam = &vat_main;
1143   i32 retval = ntohl (mp->retval);
1144   int i, count = 0;
1145
1146   if (retval >= 0)
1147     count = ntohl (mp->count);
1148
1149   for (i = 0; i < count; i++)
1150     print (vam->ofp,
1151            "\n%-2d %-11s %-11s %-5d %-6d %-4d %-6d",
1152            ntohl (mp->thread_data[i].id), mp->thread_data[i].name,
1153            mp->thread_data[i].type, ntohl (mp->thread_data[i].pid),
1154            ntohl (mp->thread_data[i].cpu_id), ntohl (mp->thread_data[i].core),
1155            ntohl (mp->thread_data[i].cpu_socket));
1156
1157   vam->retval = retval;
1158   vam->result_ready = 1;
1159 }
1160
1161 static void vl_api_show_threads_reply_t_handler_json
1162   (vl_api_show_threads_reply_t * mp)
1163 {
1164   vat_main_t *vam = &vat_main;
1165   vat_json_node_t node;
1166   vl_api_thread_data_t *td;
1167   i32 retval = ntohl (mp->retval);
1168   int i, count = 0;
1169
1170   if (retval >= 0)
1171     count = ntohl (mp->count);
1172
1173   vat_json_init_object (&node);
1174   vat_json_object_add_int (&node, "retval", retval);
1175   vat_json_object_add_uint (&node, "count", count);
1176
1177   for (i = 0; i < count; i++)
1178     {
1179       td = &mp->thread_data[i];
1180       vat_json_object_add_uint (&node, "id", ntohl (td->id));
1181       vat_json_object_add_string_copy (&node, "name", td->name);
1182       vat_json_object_add_string_copy (&node, "type", td->type);
1183       vat_json_object_add_uint (&node, "pid", ntohl (td->pid));
1184       vat_json_object_add_int (&node, "cpu_id", ntohl (td->cpu_id));
1185       vat_json_object_add_int (&node, "core", ntohl (td->id));
1186       vat_json_object_add_int (&node, "cpu_socket", ntohl (td->cpu_socket));
1187     }
1188
1189   vat_json_print (vam->ofp, &node);
1190   vat_json_free (&node);
1191
1192   vam->retval = retval;
1193   vam->result_ready = 1;
1194 }
1195
1196 static int
1197 api_show_threads (vat_main_t * vam)
1198 {
1199   vl_api_show_threads_t *mp;
1200   int ret;
1201
1202   print (vam->ofp,
1203          "\n%-2s %-11s %-11s %-5s %-6s %-4s %-6s",
1204          "ID", "Name", "Type", "LWP", "cpu_id", "Core", "Socket");
1205
1206   M (SHOW_THREADS, mp);
1207
1208   S (mp);
1209   W (ret);
1210   return ret;
1211 }
1212
1213 static void
1214 vl_api_l2_macs_event_t_handler (vl_api_l2_macs_event_t * mp)
1215 {
1216   u32 n_macs = ntohl (mp->n_macs);
1217   errmsg ("L2MAC event received with pid %d cl-idx %d for %d macs: \n",
1218           ntohl (mp->pid), mp->client_index, n_macs);
1219   int i;
1220   for (i = 0; i < n_macs; i++)
1221     {
1222       vl_api_mac_entry_t *mac = &mp->mac[i];
1223       errmsg (" [%d] sw_if_index %d  mac_addr %U  action %d \n",
1224               i + 1, ntohl (mac->sw_if_index),
1225               format_ethernet_address, mac->mac_addr, mac->action);
1226       if (i == 1000)
1227         break;
1228     }
1229 }
1230
1231 static void
1232 vl_api_l2_macs_event_t_handler_json (vl_api_l2_macs_event_t * mp)
1233 {
1234   /* JSON output not supported */
1235 }
1236
1237 #define vl_api_bridge_domain_details_t_endian vl_noop_handler
1238 #define vl_api_bridge_domain_details_t_print vl_noop_handler
1239
1240 /*
1241  * Special-case: build the bridge domain table, maintain
1242  * the next bd id vbl.
1243  */
1244 static void vl_api_bridge_domain_details_t_handler
1245   (vl_api_bridge_domain_details_t * mp)
1246 {
1247   vat_main_t *vam = &vat_main;
1248   u32 n_sw_ifs = ntohl (mp->n_sw_ifs);
1249   int i;
1250
1251   print (vam->ofp, "\n%-3s %-3s %-3s %-3s %-3s %-6s %-3s",
1252          " ID", "LRN", "FWD", "FLD", "BVI", "UU-FWD", "#IF");
1253
1254   print (vam->ofp, "%3d %3d %3d %3d %3d %6d %3d",
1255          ntohl (mp->bd_id), mp->learn, mp->forward,
1256          mp->flood, ntohl (mp->bvi_sw_if_index),
1257          ntohl (mp->uu_fwd_sw_if_index), n_sw_ifs);
1258
1259   if (n_sw_ifs)
1260     {
1261       vl_api_bridge_domain_sw_if_t *sw_ifs;
1262       print (vam->ofp, "\n\n%s %s  %s", "sw_if_index", "SHG",
1263              "Interface Name");
1264
1265       sw_ifs = mp->sw_if_details;
1266       for (i = 0; i < n_sw_ifs; i++)
1267         {
1268           u8 *sw_if_name = 0;
1269           u32 sw_if_index;
1270           hash_pair_t *p;
1271
1272           sw_if_index = ntohl (sw_ifs->sw_if_index);
1273
1274           /* *INDENT-OFF* */
1275           hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
1276                              ({
1277                                if ((u32) p->value[0] == sw_if_index)
1278                                  {
1279                                    sw_if_name = (u8 *)(p->key);
1280                                    break;
1281                                  }
1282                              }));
1283           /* *INDENT-ON* */
1284           print (vam->ofp, "%7d     %3d  %s", sw_if_index,
1285                  sw_ifs->shg, sw_if_name ? (char *) sw_if_name :
1286                  "sw_if_index not found!");
1287
1288           sw_ifs++;
1289         }
1290     }
1291 }
1292
1293 static void vl_api_bridge_domain_details_t_handler_json
1294   (vl_api_bridge_domain_details_t * mp)
1295 {
1296   vat_main_t *vam = &vat_main;
1297   vat_json_node_t *node, *array = NULL;
1298   u32 n_sw_ifs = ntohl (mp->n_sw_ifs);
1299
1300   if (VAT_JSON_ARRAY != vam->json_tree.type)
1301     {
1302       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
1303       vat_json_init_array (&vam->json_tree);
1304     }
1305   node = vat_json_array_add (&vam->json_tree);
1306
1307   vat_json_init_object (node);
1308   vat_json_object_add_uint (node, "bd_id", ntohl (mp->bd_id));
1309   vat_json_object_add_uint (node, "flood", mp->flood);
1310   vat_json_object_add_uint (node, "forward", mp->forward);
1311   vat_json_object_add_uint (node, "learn", mp->learn);
1312   vat_json_object_add_uint (node, "bvi_sw_if_index",
1313                             ntohl (mp->bvi_sw_if_index));
1314   vat_json_object_add_uint (node, "n_sw_ifs", n_sw_ifs);
1315   array = vat_json_object_add (node, "sw_if");
1316   vat_json_init_array (array);
1317
1318
1319
1320   if (n_sw_ifs)
1321     {
1322       vl_api_bridge_domain_sw_if_t *sw_ifs;
1323       int i;
1324
1325       sw_ifs = mp->sw_if_details;
1326       for (i = 0; i < n_sw_ifs; i++)
1327         {
1328           node = vat_json_array_add (array);
1329           vat_json_init_object (node);
1330           vat_json_object_add_uint (node, "sw_if_index",
1331                                     ntohl (sw_ifs->sw_if_index));
1332           vat_json_object_add_uint (node, "shg", sw_ifs->shg);
1333           sw_ifs++;
1334         }
1335     }
1336 }
1337
1338 static void vl_api_control_ping_reply_t_handler
1339   (vl_api_control_ping_reply_t * mp)
1340 {
1341   vat_main_t *vam = &vat_main;
1342   i32 retval = ntohl (mp->retval);
1343   if (vam->async_mode)
1344     {
1345       vam->async_errors += (retval < 0);
1346     }
1347   else
1348     {
1349       vam->retval = retval;
1350       vam->result_ready = 1;
1351     }
1352   if (vam->socket_client_main)
1353     vam->socket_client_main->control_pings_outstanding--;
1354 }
1355
1356 static void vl_api_control_ping_reply_t_handler_json
1357   (vl_api_control_ping_reply_t * mp)
1358 {
1359   vat_main_t *vam = &vat_main;
1360   i32 retval = ntohl (mp->retval);
1361
1362   if (VAT_JSON_NONE != vam->json_tree.type)
1363     {
1364       vat_json_print (vam->ofp, &vam->json_tree);
1365       vat_json_free (&vam->json_tree);
1366       vam->json_tree.type = VAT_JSON_NONE;
1367     }
1368   else
1369     {
1370       /* just print [] */
1371       vat_json_init_array (&vam->json_tree);
1372       vat_json_print (vam->ofp, &vam->json_tree);
1373       vam->json_tree.type = VAT_JSON_NONE;
1374     }
1375
1376   vam->retval = retval;
1377   vam->result_ready = 1;
1378 }
1379
1380 static void
1381   vl_api_bridge_domain_set_mac_age_reply_t_handler
1382   (vl_api_bridge_domain_set_mac_age_reply_t * mp)
1383 {
1384   vat_main_t *vam = &vat_main;
1385   i32 retval = ntohl (mp->retval);
1386   if (vam->async_mode)
1387     {
1388       vam->async_errors += (retval < 0);
1389     }
1390   else
1391     {
1392       vam->retval = retval;
1393       vam->result_ready = 1;
1394     }
1395 }
1396
1397 static void vl_api_bridge_domain_set_mac_age_reply_t_handler_json
1398   (vl_api_bridge_domain_set_mac_age_reply_t * mp)
1399 {
1400   vat_main_t *vam = &vat_main;
1401   vat_json_node_t node;
1402
1403   vat_json_init_object (&node);
1404   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1405
1406   vat_json_print (vam->ofp, &node);
1407   vat_json_free (&node);
1408
1409   vam->retval = ntohl (mp->retval);
1410   vam->result_ready = 1;
1411 }
1412
1413 static void
1414 vl_api_l2_flags_reply_t_handler (vl_api_l2_flags_reply_t * mp)
1415 {
1416   vat_main_t *vam = &vat_main;
1417   i32 retval = ntohl (mp->retval);
1418   if (vam->async_mode)
1419     {
1420       vam->async_errors += (retval < 0);
1421     }
1422   else
1423     {
1424       vam->retval = retval;
1425       vam->result_ready = 1;
1426     }
1427 }
1428
1429 static void vl_api_l2_flags_reply_t_handler_json
1430   (vl_api_l2_flags_reply_t * mp)
1431 {
1432   vat_main_t *vam = &vat_main;
1433   vat_json_node_t node;
1434
1435   vat_json_init_object (&node);
1436   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1437   vat_json_object_add_uint (&node, "resulting_feature_bitmap",
1438                             ntohl (mp->resulting_feature_bitmap));
1439
1440   vat_json_print (vam->ofp, &node);
1441   vat_json_free (&node);
1442
1443   vam->retval = ntohl (mp->retval);
1444   vam->result_ready = 1;
1445 }
1446
1447 static void vl_api_bridge_flags_reply_t_handler
1448   (vl_api_bridge_flags_reply_t * mp)
1449 {
1450   vat_main_t *vam = &vat_main;
1451   i32 retval = ntohl (mp->retval);
1452   if (vam->async_mode)
1453     {
1454       vam->async_errors += (retval < 0);
1455     }
1456   else
1457     {
1458       vam->retval = retval;
1459       vam->result_ready = 1;
1460     }
1461 }
1462
1463 static void vl_api_bridge_flags_reply_t_handler_json
1464   (vl_api_bridge_flags_reply_t * mp)
1465 {
1466   vat_main_t *vam = &vat_main;
1467   vat_json_node_t node;
1468
1469   vat_json_init_object (&node);
1470   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1471   vat_json_object_add_uint (&node, "resulting_feature_bitmap",
1472                             ntohl (mp->resulting_feature_bitmap));
1473
1474   vat_json_print (vam->ofp, &node);
1475   vat_json_free (&node);
1476
1477   vam->retval = ntohl (mp->retval);
1478   vam->result_ready = 1;
1479 }
1480
1481 static void
1482 vl_api_virtio_pci_create_reply_t_handler (vl_api_virtio_pci_create_reply_t *
1483                                           mp)
1484 {
1485   vat_main_t *vam = &vat_main;
1486   i32 retval = ntohl (mp->retval);
1487   if (vam->async_mode)
1488     {
1489       vam->async_errors += (retval < 0);
1490     }
1491   else
1492     {
1493       vam->retval = retval;
1494       vam->sw_if_index = ntohl (mp->sw_if_index);
1495       vam->result_ready = 1;
1496     }
1497 }
1498
1499 static void vl_api_virtio_pci_create_reply_t_handler_json
1500   (vl_api_virtio_pci_create_reply_t * mp)
1501 {
1502   vat_main_t *vam = &vat_main;
1503   vat_json_node_t node;
1504
1505   vat_json_init_object (&node);
1506   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1507   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1508
1509   vat_json_print (vam->ofp, &node);
1510   vat_json_free (&node);
1511
1512   vam->retval = ntohl (mp->retval);
1513   vam->result_ready = 1;
1514
1515 }
1516
1517 static void
1518   vl_api_virtio_pci_create_v2_reply_t_handler
1519   (vl_api_virtio_pci_create_v2_reply_t * mp)
1520 {
1521   vat_main_t *vam = &vat_main;
1522   i32 retval = ntohl (mp->retval);
1523   if (vam->async_mode)
1524     {
1525       vam->async_errors += (retval < 0);
1526     }
1527   else
1528     {
1529       vam->retval = retval;
1530       vam->sw_if_index = ntohl (mp->sw_if_index);
1531       vam->result_ready = 1;
1532     }
1533 }
1534
1535 static void vl_api_virtio_pci_create_v2_reply_t_handler_json
1536   (vl_api_virtio_pci_create_v2_reply_t * mp)
1537 {
1538   vat_main_t *vam = &vat_main;
1539   vat_json_node_t node;
1540
1541   vat_json_init_object (&node);
1542   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1543   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1544
1545   vat_json_print (vam->ofp, &node);
1546   vat_json_free (&node);
1547
1548   vam->retval = ntohl (mp->retval);
1549   vam->result_ready = 1;
1550 }
1551
1552 static void
1553 vl_api_virtio_pci_delete_reply_t_handler (vl_api_virtio_pci_delete_reply_t *
1554                                           mp)
1555 {
1556   vat_main_t *vam = &vat_main;
1557   i32 retval = ntohl (mp->retval);
1558   if (vam->async_mode)
1559     {
1560       vam->async_errors += (retval < 0);
1561     }
1562   else
1563     {
1564       vam->retval = retval;
1565       vam->result_ready = 1;
1566     }
1567 }
1568
1569 static void vl_api_virtio_pci_delete_reply_t_handler_json
1570   (vl_api_virtio_pci_delete_reply_t * mp)
1571 {
1572   vat_main_t *vam = &vat_main;
1573   vat_json_node_t node;
1574
1575   vat_json_init_object (&node);
1576   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1577
1578   vat_json_print (vam->ofp, &node);
1579   vat_json_free (&node);
1580
1581   vam->retval = ntohl (mp->retval);
1582   vam->result_ready = 1;
1583 }
1584
1585 static void vl_api_ip_address_details_t_handler
1586   (vl_api_ip_address_details_t * mp)
1587 {
1588   vat_main_t *vam = &vat_main;
1589   static ip_address_details_t empty_ip_address_details = { {0} };
1590   ip_address_details_t *address = NULL;
1591   ip_details_t *current_ip_details = NULL;
1592   ip_details_t *details = NULL;
1593
1594   details = vam->ip_details_by_sw_if_index[vam->is_ipv6];
1595
1596   if (!details || vam->current_sw_if_index >= vec_len (details)
1597       || !details[vam->current_sw_if_index].present)
1598     {
1599       errmsg ("ip address details arrived but not stored");
1600       errmsg ("ip_dump should be called first");
1601       return;
1602     }
1603
1604   current_ip_details = vec_elt_at_index (details, vam->current_sw_if_index);
1605
1606 #define addresses (current_ip_details->addr)
1607
1608   vec_validate_init_empty (addresses, vec_len (addresses),
1609                            empty_ip_address_details);
1610
1611   address = vec_elt_at_index (addresses, vec_len (addresses) - 1);
1612
1613   clib_memcpy (&address->ip, &mp->prefix.address.un, sizeof (address->ip));
1614   address->prefix_length = mp->prefix.len;
1615 #undef addresses
1616 }
1617
1618 static void vl_api_ip_address_details_t_handler_json
1619   (vl_api_ip_address_details_t * mp)
1620 {
1621   vat_main_t *vam = &vat_main;
1622   vat_json_node_t *node = NULL;
1623
1624   if (VAT_JSON_ARRAY != vam->json_tree.type)
1625     {
1626       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
1627       vat_json_init_array (&vam->json_tree);
1628     }
1629   node = vat_json_array_add (&vam->json_tree);
1630
1631   vat_json_init_object (node);
1632   vat_json_object_add_prefix (node, &mp->prefix);
1633 }
1634
1635 static void
1636 vl_api_ip_details_t_handler (vl_api_ip_details_t * mp)
1637 {
1638   vat_main_t *vam = &vat_main;
1639   static ip_details_t empty_ip_details = { 0 };
1640   ip_details_t *ip = NULL;
1641   u32 sw_if_index = ~0;
1642
1643   sw_if_index = ntohl (mp->sw_if_index);
1644
1645   vec_validate_init_empty (vam->ip_details_by_sw_if_index[vam->is_ipv6],
1646                            sw_if_index, empty_ip_details);
1647
1648   ip = vec_elt_at_index (vam->ip_details_by_sw_if_index[vam->is_ipv6],
1649                          sw_if_index);
1650
1651   ip->present = 1;
1652 }
1653
1654 static void
1655 vl_api_ip_details_t_handler_json (vl_api_ip_details_t * mp)
1656 {
1657   vat_main_t *vam = &vat_main;
1658
1659   if (VAT_JSON_ARRAY != vam->json_tree.type)
1660     {
1661       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
1662       vat_json_init_array (&vam->json_tree);
1663     }
1664   vat_json_array_add_uint (&vam->json_tree,
1665                            clib_net_to_host_u32 (mp->sw_if_index));
1666 }
1667
1668 static void vl_api_get_first_msg_id_reply_t_handler
1669   (vl_api_get_first_msg_id_reply_t * mp)
1670 {
1671   vat_main_t *vam = &vat_main;
1672   i32 retval = ntohl (mp->retval);
1673
1674   if (vam->async_mode)
1675     {
1676       vam->async_errors += (retval < 0);
1677     }
1678   else
1679     {
1680       vam->retval = retval;
1681       vam->result_ready = 1;
1682     }
1683   if (retval >= 0)
1684     {
1685       errmsg ("first message id %d", ntohs (mp->first_msg_id));
1686     }
1687 }
1688
1689 static void vl_api_get_first_msg_id_reply_t_handler_json
1690   (vl_api_get_first_msg_id_reply_t * mp)
1691 {
1692   vat_main_t *vam = &vat_main;
1693   vat_json_node_t node;
1694
1695   vat_json_init_object (&node);
1696   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1697   vat_json_object_add_uint (&node, "first_msg_id",
1698                             (uint) ntohs (mp->first_msg_id));
1699
1700   vat_json_print (vam->ofp, &node);
1701   vat_json_free (&node);
1702
1703   vam->retval = ntohl (mp->retval);
1704   vam->result_ready = 1;
1705 }
1706
1707 static void vl_api_get_node_graph_reply_t_handler
1708   (vl_api_get_node_graph_reply_t * mp)
1709 {
1710   vat_main_t *vam = &vat_main;
1711   i32 retval = ntohl (mp->retval);
1712   u8 *pvt_copy, *reply;
1713   void *oldheap;
1714   vlib_node_t *node;
1715   int i;
1716
1717   if (vam->async_mode)
1718     {
1719       vam->async_errors += (retval < 0);
1720     }
1721   else
1722     {
1723       vam->retval = retval;
1724       vam->result_ready = 1;
1725     }
1726
1727   /* "Should never happen..." */
1728   if (retval != 0)
1729     return;
1730
1731   reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
1732   pvt_copy = vec_dup (reply);
1733
1734   /* Toss the shared-memory original... */
1735   oldheap = vl_msg_push_heap ();
1736
1737   vec_free (reply);
1738
1739   vl_msg_pop_heap (oldheap);
1740
1741   if (vam->graph_nodes)
1742     {
1743       hash_free (vam->graph_node_index_by_name);
1744
1745       for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
1746         {
1747           node = vam->graph_nodes[0][i];
1748           vec_free (node->name);
1749           vec_free (node->next_nodes);
1750           vec_free (node);
1751         }
1752       vec_free (vam->graph_nodes[0]);
1753       vec_free (vam->graph_nodes);
1754     }
1755
1756   vam->graph_node_index_by_name = hash_create_string (0, sizeof (uword));
1757   vam->graph_nodes = vlib_node_unserialize (pvt_copy);
1758   vec_free (pvt_copy);
1759
1760   for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
1761     {
1762       node = vam->graph_nodes[0][i];
1763       hash_set_mem (vam->graph_node_index_by_name, node->name, i);
1764     }
1765 }
1766
1767 static void vl_api_get_node_graph_reply_t_handler_json
1768   (vl_api_get_node_graph_reply_t * mp)
1769 {
1770   vat_main_t *vam = &vat_main;
1771   void *oldheap;
1772   vat_json_node_t node;
1773   u8 *reply;
1774
1775   /* $$$$ make this real? */
1776   vat_json_init_object (&node);
1777   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1778   vat_json_object_add_uint (&node, "reply_in_shmem", mp->reply_in_shmem);
1779
1780   reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
1781
1782   /* Toss the shared-memory original... */
1783   oldheap = vl_msg_push_heap ();
1784
1785   vec_free (reply);
1786
1787   vl_msg_pop_heap (oldheap);
1788
1789   vat_json_print (vam->ofp, &node);
1790   vat_json_free (&node);
1791
1792   vam->retval = ntohl (mp->retval);
1793   vam->result_ready = 1;
1794 }
1795
1796 /* Format hex dump. */
1797 u8 *
1798 format_hex_bytes (u8 * s, va_list * va)
1799 {
1800   u8 *bytes = va_arg (*va, u8 *);
1801   int n_bytes = va_arg (*va, int);
1802   uword i;
1803
1804   /* Print short or long form depending on byte count. */
1805   uword short_form = n_bytes <= 32;
1806   u32 indent = format_get_indent (s);
1807
1808   if (n_bytes == 0)
1809     return s;
1810
1811   for (i = 0; i < n_bytes; i++)
1812     {
1813       if (!short_form && (i % 32) == 0)
1814         s = format (s, "%08x: ", i);
1815       s = format (s, "%02x", bytes[i]);
1816       if (!short_form && ((i + 1) % 32) == 0 && (i + 1) < n_bytes)
1817         s = format (s, "\n%U", format_white_space, indent);
1818     }
1819
1820   return s;
1821 }
1822
1823 /*
1824  * Generate boilerplate reply handlers, which
1825  * dig the return value out of the xxx_reply_t API message,
1826  * stick it into vam->retval, and set vam->result_ready
1827  *
1828  * Could also do this by pointing N message decode slots at
1829  * a single function, but that could break in subtle ways.
1830  */
1831
1832 #define foreach_standard_reply_retval_handler           \
1833 _(sw_interface_set_flags_reply)                         \
1834 _(sw_interface_add_del_address_reply)                   \
1835 _(sw_interface_set_rx_mode_reply)                       \
1836 _(sw_interface_set_rx_placement_reply)                  \
1837 _(sw_interface_set_table_reply)                         \
1838 _(sw_interface_set_vpath_reply)                         \
1839 _(sw_interface_set_l2_bridge_reply)                     \
1840 _(bridge_domain_add_del_reply)                          \
1841 _(sw_interface_set_l2_xconnect_reply)                   \
1842 _(l2fib_add_del_reply)                                  \
1843 _(l2fib_flush_int_reply)                                \
1844 _(l2fib_flush_bd_reply)                                 \
1845 _(ip_route_add_del_reply)                               \
1846 _(ip_table_add_del_reply)                               \
1847 _(ip_table_replace_begin_reply)                         \
1848 _(ip_table_flush_reply)                                 \
1849 _(ip_table_replace_end_reply)                           \
1850 _(ip_mroute_add_del_reply)                              \
1851 _(sw_interface_set_unnumbered_reply)                    \
1852 _(set_ip_flow_hash_reply)                               \
1853 _(sw_interface_ip6_enable_disable_reply)                \
1854 _(l2_patch_add_del_reply)                               \
1855 _(l2_fib_clear_table_reply)                             \
1856 _(l2_interface_efp_filter_reply)                        \
1857 _(l2_interface_vlan_tag_rewrite_reply)                  \
1858 _(want_l2_macs_events_reply)                            \
1859 _(delete_loopback_reply)                                \
1860 _(bd_ip_mac_add_del_reply)                              \
1861 _(bd_ip_mac_flush_reply)                                \
1862 _(want_interface_events_reply)                          \
1863 _(sw_interface_clear_stats_reply)                       \
1864 _(ioam_enable_reply)                                    \
1865 _(ioam_disable_reply)                                   \
1866 _(ip_source_and_port_range_check_add_del_reply)         \
1867 _(ip_source_and_port_range_check_interface_add_del_reply)\
1868 _(delete_subif_reply)                                   \
1869 _(l2_interface_pbb_tag_rewrite_reply)                   \
1870 _(sw_interface_tag_add_del_reply)                       \
1871 _(sw_interface_add_del_mac_address_reply)               \
1872 _(hw_interface_set_mtu_reply)                           \
1873 _(session_rule_add_del_reply)                           \
1874 _(ip_container_proxy_add_del_reply)                     \
1875
1876 #define _(n)                                    \
1877     static void vl_api_##n##_t_handler          \
1878     (vl_api_##n##_t * mp)                       \
1879     {                                           \
1880         vat_main_t * vam = &vat_main;           \
1881         i32 retval = ntohl(mp->retval);         \
1882         if (vam->async_mode) {                  \
1883             vam->async_errors += (retval < 0);  \
1884         } else {                                \
1885             vam->retval = retval;               \
1886             vam->result_ready = 1;              \
1887         }                                       \
1888     }
1889 foreach_standard_reply_retval_handler;
1890 #undef _
1891
1892 #define _(n)                                    \
1893     static void vl_api_##n##_t_handler_json     \
1894     (vl_api_##n##_t * mp)                       \
1895     {                                           \
1896         vat_main_t * vam = &vat_main;           \
1897         vat_json_node_t node;                   \
1898         vat_json_init_object(&node);            \
1899         vat_json_object_add_int(&node, "retval", ntohl(mp->retval));    \
1900         vat_json_print(vam->ofp, &node);        \
1901         vam->retval = ntohl(mp->retval);        \
1902         vam->result_ready = 1;                  \
1903     }
1904 foreach_standard_reply_retval_handler;
1905 #undef _
1906
1907 /*
1908  * Table of message reply handlers, must include boilerplate handlers
1909  * we just generated
1910  */
1911
1912 #define foreach_vpe_api_reply_msg                                       \
1913 _(CREATE_LOOPBACK_REPLY, create_loopback_reply)                         \
1914 _(CREATE_LOOPBACK_INSTANCE_REPLY, create_loopback_instance_reply)       \
1915 _(SW_INTERFACE_DETAILS, sw_interface_details)                           \
1916 _(SW_INTERFACE_SET_FLAGS_REPLY, sw_interface_set_flags_reply)           \
1917 _(CONTROL_PING_REPLY, control_ping_reply)                               \
1918 _(CLI_REPLY, cli_reply)                                                 \
1919 _(CLI_INBAND_REPLY, cli_inband_reply)                                   \
1920 _(SW_INTERFACE_ADD_DEL_ADDRESS_REPLY,                                   \
1921   sw_interface_add_del_address_reply)                                   \
1922 _(SW_INTERFACE_SET_RX_MODE_REPLY, sw_interface_set_rx_mode_reply)       \
1923 _(SW_INTERFACE_SET_RX_PLACEMENT_REPLY, sw_interface_set_rx_placement_reply)     \
1924 _(SW_INTERFACE_RX_PLACEMENT_DETAILS, sw_interface_rx_placement_details) \
1925 _(SW_INTERFACE_SET_TABLE_REPLY, sw_interface_set_table_reply)           \
1926 _(SW_INTERFACE_SET_VPATH_REPLY, sw_interface_set_vpath_reply)           \
1927 _(SW_INTERFACE_SET_L2_XCONNECT_REPLY,                                   \
1928   sw_interface_set_l2_xconnect_reply)                                   \
1929 _(SW_INTERFACE_SET_L2_BRIDGE_REPLY,                                     \
1930   sw_interface_set_l2_bridge_reply)                                     \
1931 _(BRIDGE_DOMAIN_ADD_DEL_REPLY, bridge_domain_add_del_reply)             \
1932 _(BRIDGE_DOMAIN_DETAILS, bridge_domain_details)                         \
1933 _(BRIDGE_DOMAIN_SET_MAC_AGE_REPLY, bridge_domain_set_mac_age_reply)     \
1934 _(L2FIB_ADD_DEL_REPLY, l2fib_add_del_reply)                             \
1935 _(L2FIB_FLUSH_INT_REPLY, l2fib_flush_int_reply)                         \
1936 _(L2FIB_FLUSH_BD_REPLY, l2fib_flush_bd_reply)                           \
1937 _(L2_FLAGS_REPLY, l2_flags_reply)                                       \
1938 _(BRIDGE_FLAGS_REPLY, bridge_flags_reply)                               \
1939 _(VIRTIO_PCI_CREATE_REPLY, virtio_pci_create_reply)                     \
1940 _(VIRTIO_PCI_CREATE_V2_REPLY, virtio_pci_create_v2_reply)               \
1941 _(VIRTIO_PCI_DELETE_REPLY, virtio_pci_delete_reply)                     \
1942 _(SW_INTERFACE_VIRTIO_PCI_DETAILS, sw_interface_virtio_pci_details)     \
1943 _(IP_ROUTE_ADD_DEL_REPLY, ip_route_add_del_reply)                       \
1944 _(IP_TABLE_ADD_DEL_REPLY, ip_table_add_del_reply)                       \
1945 _(IP_TABLE_REPLACE_BEGIN_REPLY, ip_table_replace_begin_reply)           \
1946 _(IP_TABLE_FLUSH_REPLY, ip_table_flush_reply)                           \
1947 _(IP_TABLE_REPLACE_END_REPLY, ip_table_replace_end_reply)               \
1948 _(IP_MROUTE_ADD_DEL_REPLY, ip_mroute_add_del_reply)                     \
1949 _(SW_INTERFACE_SET_UNNUMBERED_REPLY,                                    \
1950   sw_interface_set_unnumbered_reply)                                    \
1951 _(CREATE_VLAN_SUBIF_REPLY, create_vlan_subif_reply)                     \
1952 _(CREATE_SUBIF_REPLY, create_subif_reply)                               \
1953 _(SET_IP_FLOW_HASH_REPLY, set_ip_flow_hash_reply)                       \
1954 _(SW_INTERFACE_IP6_ENABLE_DISABLE_REPLY,                                \
1955   sw_interface_ip6_enable_disable_reply)                                \
1956 _(L2_PATCH_ADD_DEL_REPLY, l2_patch_add_del_reply)                       \
1957 _(GET_NODE_INDEX_REPLY, get_node_index_reply)                           \
1958 _(ADD_NODE_NEXT_REPLY, add_node_next_reply)                             \
1959 _(L2_FIB_CLEAR_TABLE_REPLY, l2_fib_clear_table_reply)                   \
1960 _(L2_INTERFACE_EFP_FILTER_REPLY, l2_interface_efp_filter_reply)         \
1961 _(L2_INTERFACE_VLAN_TAG_REWRITE_REPLY, l2_interface_vlan_tag_rewrite_reply) \
1962 _(SHOW_VERSION_REPLY, show_version_reply)                               \
1963 _(SHOW_THREADS_REPLY, show_threads_reply)                               \
1964 _(L2_FIB_TABLE_DETAILS, l2_fib_table_details)                           \
1965 _(INTERFACE_NAME_RENUMBER_REPLY, interface_name_renumber_reply)         \
1966 _(WANT_L2_MACS_EVENTS_REPLY, want_l2_macs_events_reply)                 \
1967 _(L2_MACS_EVENT, l2_macs_event)                                         \
1968 _(IP_ADDRESS_DETAILS, ip_address_details)                               \
1969 _(IP_DETAILS, ip_details)                                               \
1970 _(DELETE_LOOPBACK_REPLY, delete_loopback_reply)                         \
1971 _(BD_IP_MAC_ADD_DEL_REPLY, bd_ip_mac_add_del_reply)                     \
1972 _(BD_IP_MAC_FLUSH_REPLY, bd_ip_mac_flush_reply)                         \
1973 _(BD_IP_MAC_DETAILS, bd_ip_mac_details)                                 \
1974 _(WANT_INTERFACE_EVENTS_REPLY, want_interface_events_reply)             \
1975 _(GET_FIRST_MSG_ID_REPLY, get_first_msg_id_reply)                       \
1976 _(GET_NODE_GRAPH_REPLY, get_node_graph_reply)                           \
1977 _(SW_INTERFACE_CLEAR_STATS_REPLY, sw_interface_clear_stats_reply)      \
1978 _(IOAM_ENABLE_REPLY, ioam_enable_reply)                   \
1979 _(IOAM_DISABLE_REPLY, ioam_disable_reply)                     \
1980 _(GET_NEXT_INDEX_REPLY, get_next_index_reply)                           \
1981 _(IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL_REPLY,                         \
1982  ip_source_and_port_range_check_add_del_reply)                          \
1983 _(IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL_REPLY,               \
1984  ip_source_and_port_range_check_interface_add_del_reply)                \
1985 _(DELETE_SUBIF_REPLY, delete_subif_reply)                               \
1986 _(L2_INTERFACE_PBB_TAG_REWRITE_REPLY, l2_interface_pbb_tag_rewrite_reply) \
1987 _(IP_TABLE_DETAILS, ip_table_details)                                   \
1988 _(IP_ROUTE_DETAILS, ip_route_details)                                   \
1989 _(SW_INTERFACE_TAG_ADD_DEL_REPLY, sw_interface_tag_add_del_reply)       \
1990 _(SW_INTERFACE_ADD_DEL_MAC_ADDRESS_REPLY, sw_interface_add_del_mac_address_reply) \
1991 _(L2_XCONNECT_DETAILS, l2_xconnect_details)                             \
1992 _(HW_INTERFACE_SET_MTU_REPLY, hw_interface_set_mtu_reply)               \
1993 _(SW_INTERFACE_GET_TABLE_REPLY, sw_interface_get_table_reply)           \
1994 _(APP_NAMESPACE_ADD_DEL_REPLY, app_namespace_add_del_reply)             \
1995 _(SESSION_RULE_ADD_DEL_REPLY, session_rule_add_del_reply)               \
1996 _(SESSION_RULES_DETAILS, session_rules_details)                         \
1997 _(IP_CONTAINER_PROXY_ADD_DEL_REPLY, ip_container_proxy_add_del_reply)   \
1998
1999 #define foreach_standalone_reply_msg                                    \
2000 _(SW_INTERFACE_EVENT, sw_interface_event)
2001
2002 typedef struct
2003 {
2004   u8 *name;
2005   u32 value;
2006 } name_sort_t;
2007
2008 #define STR_VTR_OP_CASE(op)     \
2009     case L2_VTR_ ## op:         \
2010         return "" # op;
2011
2012 static const char *
2013 str_vtr_op (u32 vtr_op)
2014 {
2015   switch (vtr_op)
2016     {
2017       STR_VTR_OP_CASE (DISABLED);
2018       STR_VTR_OP_CASE (PUSH_1);
2019       STR_VTR_OP_CASE (PUSH_2);
2020       STR_VTR_OP_CASE (POP_1);
2021       STR_VTR_OP_CASE (POP_2);
2022       STR_VTR_OP_CASE (TRANSLATE_1_1);
2023       STR_VTR_OP_CASE (TRANSLATE_1_2);
2024       STR_VTR_OP_CASE (TRANSLATE_2_1);
2025       STR_VTR_OP_CASE (TRANSLATE_2_2);
2026     }
2027
2028   return "UNKNOWN";
2029 }
2030
2031 static int
2032 dump_sub_interface_table (vat_main_t * vam)
2033 {
2034   const sw_interface_subif_t *sub = NULL;
2035
2036   if (vam->json_output)
2037     {
2038       clib_warning
2039         ("JSON output supported only for VPE API calls and dump_stats_table");
2040       return -99;
2041     }
2042
2043   print (vam->ofp,
2044          "%-30s%-12s%-11s%-7s%-5s%-9s%-9s%-6s%-8s%-10s%-10s",
2045          "Interface", "sw_if_index",
2046          "sub id", "dot1ad", "tags", "outer id",
2047          "inner id", "exact", "default", "outer any", "inner any");
2048
2049   vec_foreach (sub, vam->sw_if_subif_table)
2050   {
2051     print (vam->ofp,
2052            "%-30s%-12d%-11d%-7s%-5d%-9d%-9d%-6d%-8d%-10d%-10d",
2053            sub->interface_name,
2054            sub->sw_if_index,
2055            sub->sub_id, sub->sub_dot1ad ? "dot1ad" : "dot1q",
2056            sub->sub_number_of_tags, sub->sub_outer_vlan_id,
2057            sub->sub_inner_vlan_id, sub->sub_exact_match, sub->sub_default,
2058            sub->sub_outer_vlan_id_any, sub->sub_inner_vlan_id_any);
2059     if (sub->vtr_op != L2_VTR_DISABLED)
2060       {
2061         print (vam->ofp,
2062                "  vlan-tag-rewrite - op: %-14s [ dot1q: %d "
2063                "tag1: %d tag2: %d ]",
2064                str_vtr_op (sub->vtr_op), sub->vtr_push_dot1q,
2065                sub->vtr_tag1, sub->vtr_tag2);
2066       }
2067   }
2068
2069   return 0;
2070 }
2071
2072 static int
2073 name_sort_cmp (void *a1, void *a2)
2074 {
2075   name_sort_t *n1 = a1;
2076   name_sort_t *n2 = a2;
2077
2078   return strcmp ((char *) n1->name, (char *) n2->name);
2079 }
2080
2081 static int
2082 dump_interface_table (vat_main_t * vam)
2083 {
2084   hash_pair_t *p;
2085   name_sort_t *nses = 0, *ns;
2086
2087   if (vam->json_output)
2088     {
2089       clib_warning
2090         ("JSON output supported only for VPE API calls and dump_stats_table");
2091       return -99;
2092     }
2093
2094   /* *INDENT-OFF* */
2095   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
2096   ({
2097     vec_add2 (nses, ns, 1);
2098     ns->name = (u8 *)(p->key);
2099     ns->value = (u32) p->value[0];
2100   }));
2101   /* *INDENT-ON* */
2102
2103   vec_sort_with_function (nses, name_sort_cmp);
2104
2105   print (vam->ofp, "%-25s%-15s", "Interface", "sw_if_index");
2106   vec_foreach (ns, nses)
2107   {
2108     print (vam->ofp, "%-25s%-15d", ns->name, ns->value);
2109   }
2110   vec_free (nses);
2111   return 0;
2112 }
2113
2114 static int
2115 dump_ip_table (vat_main_t * vam, int is_ipv6)
2116 {
2117   const ip_details_t *det = NULL;
2118   const ip_address_details_t *address = NULL;
2119   u32 i = ~0;
2120
2121   print (vam->ofp, "%-12s", "sw_if_index");
2122
2123   vec_foreach (det, vam->ip_details_by_sw_if_index[is_ipv6])
2124   {
2125     i++;
2126     if (!det->present)
2127       {
2128         continue;
2129       }
2130     print (vam->ofp, "%-12d", i);
2131     print (vam->ofp, "            %-30s%-13s", "Address", "Prefix length");
2132     if (!det->addr)
2133       {
2134         continue;
2135       }
2136     vec_foreach (address, det->addr)
2137     {
2138       print (vam->ofp,
2139              "            %-30U%-13d",
2140              is_ipv6 ? format_ip6_address : format_ip4_address,
2141              address->ip, address->prefix_length);
2142     }
2143   }
2144
2145   return 0;
2146 }
2147
2148 static int
2149 dump_ipv4_table (vat_main_t * vam)
2150 {
2151   if (vam->json_output)
2152     {
2153       clib_warning
2154         ("JSON output supported only for VPE API calls and dump_stats_table");
2155       return -99;
2156     }
2157
2158   return dump_ip_table (vam, 0);
2159 }
2160
2161 static int
2162 dump_ipv6_table (vat_main_t * vam)
2163 {
2164   if (vam->json_output)
2165     {
2166       clib_warning
2167         ("JSON output supported only for VPE API calls and dump_stats_table");
2168       return -99;
2169     }
2170
2171   return dump_ip_table (vam, 1);
2172 }
2173
2174 /*
2175  * Pass CLI buffers directly in the CLI_INBAND API message,
2176  * instead of an additional shared memory area.
2177  */
2178 static int
2179 exec_inband (vat_main_t * vam)
2180 {
2181   vl_api_cli_inband_t *mp;
2182   unformat_input_t *i = vam->input;
2183   int ret;
2184
2185   if (vec_len (i->buffer) == 0)
2186     return -1;
2187
2188   if (vam->exec_mode == 0 && unformat (i, "mode"))
2189     {
2190       vam->exec_mode = 1;
2191       return 0;
2192     }
2193   if (vam->exec_mode == 1 && (unformat (i, "exit") || unformat (i, "quit")))
2194     {
2195       vam->exec_mode = 0;
2196       return 0;
2197     }
2198
2199   /*
2200    * In order for the CLI command to work, it
2201    * must be a vector ending in \n, not a C-string ending
2202    * in \n\0.
2203    */
2204   M2 (CLI_INBAND, mp, vec_len (vam->input->buffer));
2205   vl_api_vec_to_api_string (vam->input->buffer, &mp->cmd);
2206
2207   S (mp);
2208   W (ret);
2209   /* json responses may or may not include a useful reply... */
2210   if (vec_len (vam->cmd_reply))
2211     print (vam->ofp, "%v", (char *) (vam->cmd_reply));
2212   return ret;
2213 }
2214
2215 int
2216 exec (vat_main_t * vam)
2217 {
2218   return exec_inband (vam);
2219 }
2220
2221 static int
2222 api_create_loopback (vat_main_t * vam)
2223 {
2224   unformat_input_t *i = vam->input;
2225   vl_api_create_loopback_t *mp;
2226   vl_api_create_loopback_instance_t *mp_lbi;
2227   u8 mac_address[6];
2228   u8 mac_set = 0;
2229   u8 is_specified = 0;
2230   u32 user_instance = 0;
2231   int ret;
2232
2233   clib_memset (mac_address, 0, sizeof (mac_address));
2234
2235   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2236     {
2237       if (unformat (i, "mac %U", unformat_ethernet_address, mac_address))
2238         mac_set = 1;
2239       if (unformat (i, "instance %d", &user_instance))
2240         is_specified = 1;
2241       else
2242         break;
2243     }
2244
2245   if (is_specified)
2246     {
2247       M (CREATE_LOOPBACK_INSTANCE, mp_lbi);
2248       mp_lbi->is_specified = is_specified;
2249       if (is_specified)
2250         mp_lbi->user_instance = htonl (user_instance);
2251       if (mac_set)
2252         clib_memcpy (mp_lbi->mac_address, mac_address, sizeof (mac_address));
2253       S (mp_lbi);
2254     }
2255   else
2256     {
2257       /* Construct the API message */
2258       M (CREATE_LOOPBACK, mp);
2259       if (mac_set)
2260         clib_memcpy (mp->mac_address, mac_address, sizeof (mac_address));
2261       S (mp);
2262     }
2263
2264   W (ret);
2265   return ret;
2266 }
2267
2268 static int
2269 api_delete_loopback (vat_main_t * vam)
2270 {
2271   unformat_input_t *i = vam->input;
2272   vl_api_delete_loopback_t *mp;
2273   u32 sw_if_index = ~0;
2274   int ret;
2275
2276   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2277     {
2278       if (unformat (i, "sw_if_index %d", &sw_if_index))
2279         ;
2280       else
2281         break;
2282     }
2283
2284   if (sw_if_index == ~0)
2285     {
2286       errmsg ("missing sw_if_index");
2287       return -99;
2288     }
2289
2290   /* Construct the API message */
2291   M (DELETE_LOOPBACK, mp);
2292   mp->sw_if_index = ntohl (sw_if_index);
2293
2294   S (mp);
2295   W (ret);
2296   return ret;
2297 }
2298
2299 static int
2300 api_want_interface_events (vat_main_t * vam)
2301 {
2302   unformat_input_t *i = vam->input;
2303   vl_api_want_interface_events_t *mp;
2304   int enable = -1;
2305   int ret;
2306
2307   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2308     {
2309       if (unformat (i, "enable"))
2310         enable = 1;
2311       else if (unformat (i, "disable"))
2312         enable = 0;
2313       else
2314         break;
2315     }
2316
2317   if (enable == -1)
2318     {
2319       errmsg ("missing enable|disable");
2320       return -99;
2321     }
2322
2323   M (WANT_INTERFACE_EVENTS, mp);
2324   mp->enable_disable = enable;
2325
2326   vam->interface_event_display = enable;
2327
2328   S (mp);
2329   W (ret);
2330   return ret;
2331 }
2332
2333
2334 /* Note: non-static, called once to set up the initial intfc table */
2335 int
2336 api_sw_interface_dump (vat_main_t * vam)
2337 {
2338   vl_api_sw_interface_dump_t *mp;
2339   vl_api_control_ping_t *mp_ping;
2340   hash_pair_t *p;
2341   name_sort_t *nses = 0, *ns;
2342   sw_interface_subif_t *sub = NULL;
2343   int ret;
2344
2345   /* Toss the old name table */
2346   /* *INDENT-OFF* */
2347   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
2348   ({
2349     vec_add2 (nses, ns, 1);
2350     ns->name = (u8 *)(p->key);
2351     ns->value = (u32) p->value[0];
2352   }));
2353   /* *INDENT-ON* */
2354
2355   hash_free (vam->sw_if_index_by_interface_name);
2356
2357   vec_foreach (ns, nses) vec_free (ns->name);
2358
2359   vec_free (nses);
2360
2361   vec_foreach (sub, vam->sw_if_subif_table)
2362   {
2363     vec_free (sub->interface_name);
2364   }
2365   vec_free (vam->sw_if_subif_table);
2366
2367   /* recreate the interface name hash table */
2368   vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
2369
2370   /*
2371    * Ask for all interface names. Otherwise, the epic catalog of
2372    * name filters becomes ridiculously long, and vat ends up needing
2373    * to be taught about new interface types.
2374    */
2375   M (SW_INTERFACE_DUMP, mp);
2376   S (mp);
2377
2378   /* Use a control ping for synchronization */
2379   MPING (CONTROL_PING, mp_ping);
2380   S (mp_ping);
2381
2382   W (ret);
2383   return ret;
2384 }
2385
2386 static int
2387 api_sw_interface_set_flags (vat_main_t * vam)
2388 {
2389   unformat_input_t *i = vam->input;
2390   vl_api_sw_interface_set_flags_t *mp;
2391   u32 sw_if_index;
2392   u8 sw_if_index_set = 0;
2393   u8 admin_up = 0;
2394   int ret;
2395
2396   /* Parse args required to build the message */
2397   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2398     {
2399       if (unformat (i, "admin-up"))
2400         admin_up = 1;
2401       else if (unformat (i, "admin-down"))
2402         admin_up = 0;
2403       else
2404         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2405         sw_if_index_set = 1;
2406       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2407         sw_if_index_set = 1;
2408       else
2409         break;
2410     }
2411
2412   if (sw_if_index_set == 0)
2413     {
2414       errmsg ("missing interface name or sw_if_index");
2415       return -99;
2416     }
2417
2418   /* Construct the API message */
2419   M (SW_INTERFACE_SET_FLAGS, mp);
2420   mp->sw_if_index = ntohl (sw_if_index);
2421   mp->flags = ntohl ((admin_up) ? IF_STATUS_API_FLAG_ADMIN_UP : 0);
2422
2423   /* send it... */
2424   S (mp);
2425
2426   /* Wait for a reply, return the good/bad news... */
2427   W (ret);
2428   return ret;
2429 }
2430
2431 static int
2432 api_sw_interface_set_rx_mode (vat_main_t * vam)
2433 {
2434   unformat_input_t *i = vam->input;
2435   vl_api_sw_interface_set_rx_mode_t *mp;
2436   u32 sw_if_index;
2437   u8 sw_if_index_set = 0;
2438   int ret;
2439   u8 queue_id_valid = 0;
2440   u32 queue_id;
2441   vnet_hw_if_rx_mode mode = VNET_HW_IF_RX_MODE_UNKNOWN;
2442
2443   /* Parse args required to build the message */
2444   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2445     {
2446       if (unformat (i, "queue %d", &queue_id))
2447         queue_id_valid = 1;
2448       else if (unformat (i, "polling"))
2449         mode = VNET_HW_IF_RX_MODE_POLLING;
2450       else if (unformat (i, "interrupt"))
2451         mode = VNET_HW_IF_RX_MODE_INTERRUPT;
2452       else if (unformat (i, "adaptive"))
2453         mode = VNET_HW_IF_RX_MODE_ADAPTIVE;
2454       else
2455         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2456         sw_if_index_set = 1;
2457       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2458         sw_if_index_set = 1;
2459       else
2460         break;
2461     }
2462
2463   if (sw_if_index_set == 0)
2464     {
2465       errmsg ("missing interface name or sw_if_index");
2466       return -99;
2467     }
2468   if (mode == VNET_HW_IF_RX_MODE_UNKNOWN)
2469     {
2470       errmsg ("missing rx-mode");
2471       return -99;
2472     }
2473
2474   /* Construct the API message */
2475   M (SW_INTERFACE_SET_RX_MODE, mp);
2476   mp->sw_if_index = ntohl (sw_if_index);
2477   mp->mode = (vl_api_rx_mode_t) mode;
2478   mp->queue_id_valid = queue_id_valid;
2479   mp->queue_id = queue_id_valid ? ntohl (queue_id) : ~0;
2480
2481   /* send it... */
2482   S (mp);
2483
2484   /* Wait for a reply, return the good/bad news... */
2485   W (ret);
2486   return ret;
2487 }
2488
2489 static int
2490 api_sw_interface_set_rx_placement (vat_main_t * vam)
2491 {
2492   unformat_input_t *i = vam->input;
2493   vl_api_sw_interface_set_rx_placement_t *mp;
2494   u32 sw_if_index;
2495   u8 sw_if_index_set = 0;
2496   int ret;
2497   u8 is_main = 0;
2498   u32 queue_id, thread_index;
2499
2500   /* Parse args required to build the message */
2501   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2502     {
2503       if (unformat (i, "queue %d", &queue_id))
2504         ;
2505       else if (unformat (i, "main"))
2506         is_main = 1;
2507       else if (unformat (i, "worker %d", &thread_index))
2508         ;
2509       else
2510         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2511         sw_if_index_set = 1;
2512       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2513         sw_if_index_set = 1;
2514       else
2515         break;
2516     }
2517
2518   if (sw_if_index_set == 0)
2519     {
2520       errmsg ("missing interface name or sw_if_index");
2521       return -99;
2522     }
2523
2524   if (is_main)
2525     thread_index = 0;
2526   /* Construct the API message */
2527   M (SW_INTERFACE_SET_RX_PLACEMENT, mp);
2528   mp->sw_if_index = ntohl (sw_if_index);
2529   mp->worker_id = ntohl (thread_index);
2530   mp->queue_id = ntohl (queue_id);
2531   mp->is_main = is_main;
2532
2533   /* send it... */
2534   S (mp);
2535   /* Wait for a reply, return the good/bad news... */
2536   W (ret);
2537   return ret;
2538 }
2539
2540 static void vl_api_sw_interface_rx_placement_details_t_handler
2541   (vl_api_sw_interface_rx_placement_details_t * mp)
2542 {
2543   vat_main_t *vam = &vat_main;
2544   u32 worker_id = ntohl (mp->worker_id);
2545
2546   print (vam->ofp,
2547          "\n%-11d %-11s %-6d %-5d %-9s",
2548          ntohl (mp->sw_if_index), (worker_id == 0) ? "main" : "worker",
2549          worker_id, ntohl (mp->queue_id),
2550          (mp->mode ==
2551           1) ? "polling" : ((mp->mode == 2) ? "interrupt" : "adaptive"));
2552 }
2553
2554 static void vl_api_sw_interface_rx_placement_details_t_handler_json
2555   (vl_api_sw_interface_rx_placement_details_t * mp)
2556 {
2557   vat_main_t *vam = &vat_main;
2558   vat_json_node_t *node = NULL;
2559
2560   if (VAT_JSON_ARRAY != vam->json_tree.type)
2561     {
2562       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
2563       vat_json_init_array (&vam->json_tree);
2564     }
2565   node = vat_json_array_add (&vam->json_tree);
2566
2567   vat_json_init_object (node);
2568   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
2569   vat_json_object_add_uint (node, "worker_id", ntohl (mp->worker_id));
2570   vat_json_object_add_uint (node, "queue_id", ntohl (mp->queue_id));
2571   vat_json_object_add_uint (node, "mode", mp->mode);
2572 }
2573
2574 static int
2575 api_sw_interface_rx_placement_dump (vat_main_t * vam)
2576 {
2577   unformat_input_t *i = vam->input;
2578   vl_api_sw_interface_rx_placement_dump_t *mp;
2579   vl_api_control_ping_t *mp_ping;
2580   int ret;
2581   u32 sw_if_index;
2582   u8 sw_if_index_set = 0;
2583
2584   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2585     {
2586       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2587         sw_if_index_set++;
2588       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2589         sw_if_index_set++;
2590       else
2591         break;
2592     }
2593
2594   print (vam->ofp,
2595          "\n%-11s %-11s %-6s %-5s %-4s",
2596          "sw_if_index", "main/worker", "thread", "queue", "mode");
2597
2598   /* Dump Interface rx placement */
2599   M (SW_INTERFACE_RX_PLACEMENT_DUMP, mp);
2600
2601   if (sw_if_index_set)
2602     mp->sw_if_index = htonl (sw_if_index);
2603   else
2604     mp->sw_if_index = ~0;
2605
2606   S (mp);
2607
2608   /* Use a control ping for synchronization */
2609   MPING (CONTROL_PING, mp_ping);
2610   S (mp_ping);
2611
2612   W (ret);
2613   return ret;
2614 }
2615
2616 static int
2617 api_sw_interface_clear_stats (vat_main_t * vam)
2618 {
2619   unformat_input_t *i = vam->input;
2620   vl_api_sw_interface_clear_stats_t *mp;
2621   u32 sw_if_index;
2622   u8 sw_if_index_set = 0;
2623   int ret;
2624
2625   /* Parse args required to build the message */
2626   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2627     {
2628       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2629         sw_if_index_set = 1;
2630       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2631         sw_if_index_set = 1;
2632       else
2633         break;
2634     }
2635
2636   /* Construct the API message */
2637   M (SW_INTERFACE_CLEAR_STATS, mp);
2638
2639   if (sw_if_index_set == 1)
2640     mp->sw_if_index = ntohl (sw_if_index);
2641   else
2642     mp->sw_if_index = ~0;
2643
2644   /* send it... */
2645   S (mp);
2646
2647   /* Wait for a reply, return the good/bad news... */
2648   W (ret);
2649   return ret;
2650 }
2651
2652 static int
2653 api_sw_interface_add_del_address (vat_main_t * vam)
2654 {
2655   unformat_input_t *i = vam->input;
2656   vl_api_sw_interface_add_del_address_t *mp;
2657   u32 sw_if_index;
2658   u8 sw_if_index_set = 0;
2659   u8 is_add = 1, del_all = 0;
2660   u32 address_length = 0;
2661   u8 v4_address_set = 0;
2662   u8 v6_address_set = 0;
2663   ip4_address_t v4address;
2664   ip6_address_t v6address;
2665   int ret;
2666
2667   /* Parse args required to build the message */
2668   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2669     {
2670       if (unformat (i, "del-all"))
2671         del_all = 1;
2672       else if (unformat (i, "del"))
2673         is_add = 0;
2674       else
2675         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2676         sw_if_index_set = 1;
2677       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2678         sw_if_index_set = 1;
2679       else if (unformat (i, "%U/%d",
2680                          unformat_ip4_address, &v4address, &address_length))
2681         v4_address_set = 1;
2682       else if (unformat (i, "%U/%d",
2683                          unformat_ip6_address, &v6address, &address_length))
2684         v6_address_set = 1;
2685       else
2686         break;
2687     }
2688
2689   if (sw_if_index_set == 0)
2690     {
2691       errmsg ("missing interface name or sw_if_index");
2692       return -99;
2693     }
2694   if (v4_address_set && v6_address_set)
2695     {
2696       errmsg ("both v4 and v6 addresses set");
2697       return -99;
2698     }
2699   if (!v4_address_set && !v6_address_set && !del_all)
2700     {
2701       errmsg ("no addresses set");
2702       return -99;
2703     }
2704
2705   /* Construct the API message */
2706   M (SW_INTERFACE_ADD_DEL_ADDRESS, mp);
2707
2708   mp->sw_if_index = ntohl (sw_if_index);
2709   mp->is_add = is_add;
2710   mp->del_all = del_all;
2711   if (v6_address_set)
2712     {
2713       mp->prefix.address.af = ADDRESS_IP6;
2714       clib_memcpy (mp->prefix.address.un.ip6, &v6address, sizeof (v6address));
2715     }
2716   else
2717     {
2718       mp->prefix.address.af = ADDRESS_IP4;
2719       clib_memcpy (mp->prefix.address.un.ip4, &v4address, sizeof (v4address));
2720     }
2721   mp->prefix.len = address_length;
2722
2723   /* send it... */
2724   S (mp);
2725
2726   /* Wait for a reply, return good/bad news  */
2727   W (ret);
2728   return ret;
2729 }
2730
2731 static int
2732 api_sw_interface_set_table (vat_main_t * vam)
2733 {
2734   unformat_input_t *i = vam->input;
2735   vl_api_sw_interface_set_table_t *mp;
2736   u32 sw_if_index, vrf_id = 0;
2737   u8 sw_if_index_set = 0;
2738   u8 is_ipv6 = 0;
2739   int ret;
2740
2741   /* Parse args required to build the message */
2742   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2743     {
2744       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2745         sw_if_index_set = 1;
2746       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2747         sw_if_index_set = 1;
2748       else if (unformat (i, "vrf %d", &vrf_id))
2749         ;
2750       else if (unformat (i, "ipv6"))
2751         is_ipv6 = 1;
2752       else
2753         break;
2754     }
2755
2756   if (sw_if_index_set == 0)
2757     {
2758       errmsg ("missing interface name or sw_if_index");
2759       return -99;
2760     }
2761
2762   /* Construct the API message */
2763   M (SW_INTERFACE_SET_TABLE, mp);
2764
2765   mp->sw_if_index = ntohl (sw_if_index);
2766   mp->is_ipv6 = is_ipv6;
2767   mp->vrf_id = ntohl (vrf_id);
2768
2769   /* send it... */
2770   S (mp);
2771
2772   /* Wait for a reply... */
2773   W (ret);
2774   return ret;
2775 }
2776
2777 static void vl_api_sw_interface_get_table_reply_t_handler
2778   (vl_api_sw_interface_get_table_reply_t * mp)
2779 {
2780   vat_main_t *vam = &vat_main;
2781
2782   print (vam->ofp, "%d", ntohl (mp->vrf_id));
2783
2784   vam->retval = ntohl (mp->retval);
2785   vam->result_ready = 1;
2786
2787 }
2788
2789 static void vl_api_sw_interface_get_table_reply_t_handler_json
2790   (vl_api_sw_interface_get_table_reply_t * mp)
2791 {
2792   vat_main_t *vam = &vat_main;
2793   vat_json_node_t node;
2794
2795   vat_json_init_object (&node);
2796   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2797   vat_json_object_add_int (&node, "vrf_id", ntohl (mp->vrf_id));
2798
2799   vat_json_print (vam->ofp, &node);
2800   vat_json_free (&node);
2801
2802   vam->retval = ntohl (mp->retval);
2803   vam->result_ready = 1;
2804 }
2805
2806 static int
2807 api_sw_interface_get_table (vat_main_t * vam)
2808 {
2809   unformat_input_t *i = vam->input;
2810   vl_api_sw_interface_get_table_t *mp;
2811   u32 sw_if_index;
2812   u8 sw_if_index_set = 0;
2813   u8 is_ipv6 = 0;
2814   int ret;
2815
2816   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2817     {
2818       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2819         sw_if_index_set = 1;
2820       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2821         sw_if_index_set = 1;
2822       else if (unformat (i, "ipv6"))
2823         is_ipv6 = 1;
2824       else
2825         break;
2826     }
2827
2828   if (sw_if_index_set == 0)
2829     {
2830       errmsg ("missing interface name or sw_if_index");
2831       return -99;
2832     }
2833
2834   M (SW_INTERFACE_GET_TABLE, mp);
2835   mp->sw_if_index = htonl (sw_if_index);
2836   mp->is_ipv6 = is_ipv6;
2837
2838   S (mp);
2839   W (ret);
2840   return ret;
2841 }
2842
2843 static int
2844 api_sw_interface_set_vpath (vat_main_t * vam)
2845 {
2846   unformat_input_t *i = vam->input;
2847   vl_api_sw_interface_set_vpath_t *mp;
2848   u32 sw_if_index = 0;
2849   u8 sw_if_index_set = 0;
2850   u8 is_enable = 0;
2851   int ret;
2852
2853   /* Parse args required to build the message */
2854   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2855     {
2856       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2857         sw_if_index_set = 1;
2858       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2859         sw_if_index_set = 1;
2860       else if (unformat (i, "enable"))
2861         is_enable = 1;
2862       else if (unformat (i, "disable"))
2863         is_enable = 0;
2864       else
2865         break;
2866     }
2867
2868   if (sw_if_index_set == 0)
2869     {
2870       errmsg ("missing interface name or sw_if_index");
2871       return -99;
2872     }
2873
2874   /* Construct the API message */
2875   M (SW_INTERFACE_SET_VPATH, mp);
2876
2877   mp->sw_if_index = ntohl (sw_if_index);
2878   mp->enable = is_enable;
2879
2880   /* send it... */
2881   S (mp);
2882
2883   /* Wait for a reply... */
2884   W (ret);
2885   return ret;
2886 }
2887
2888 static int
2889 api_sw_interface_set_l2_xconnect (vat_main_t * vam)
2890 {
2891   unformat_input_t *i = vam->input;
2892   vl_api_sw_interface_set_l2_xconnect_t *mp;
2893   u32 rx_sw_if_index;
2894   u8 rx_sw_if_index_set = 0;
2895   u32 tx_sw_if_index;
2896   u8 tx_sw_if_index_set = 0;
2897   u8 enable = 1;
2898   int ret;
2899
2900   /* Parse args required to build the message */
2901   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2902     {
2903       if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index))
2904         rx_sw_if_index_set = 1;
2905       else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
2906         tx_sw_if_index_set = 1;
2907       else if (unformat (i, "rx"))
2908         {
2909           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2910             {
2911               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
2912                             &rx_sw_if_index))
2913                 rx_sw_if_index_set = 1;
2914             }
2915           else
2916             break;
2917         }
2918       else if (unformat (i, "tx"))
2919         {
2920           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2921             {
2922               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
2923                             &tx_sw_if_index))
2924                 tx_sw_if_index_set = 1;
2925             }
2926           else
2927             break;
2928         }
2929       else if (unformat (i, "enable"))
2930         enable = 1;
2931       else if (unformat (i, "disable"))
2932         enable = 0;
2933       else
2934         break;
2935     }
2936
2937   if (rx_sw_if_index_set == 0)
2938     {
2939       errmsg ("missing rx interface name or rx_sw_if_index");
2940       return -99;
2941     }
2942
2943   if (enable && (tx_sw_if_index_set == 0))
2944     {
2945       errmsg ("missing tx interface name or tx_sw_if_index");
2946       return -99;
2947     }
2948
2949   M (SW_INTERFACE_SET_L2_XCONNECT, mp);
2950
2951   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
2952   mp->tx_sw_if_index = ntohl (tx_sw_if_index);
2953   mp->enable = enable;
2954
2955   S (mp);
2956   W (ret);
2957   return ret;
2958 }
2959
2960 static int
2961 api_sw_interface_set_l2_bridge (vat_main_t * vam)
2962 {
2963   unformat_input_t *i = vam->input;
2964   vl_api_sw_interface_set_l2_bridge_t *mp;
2965   vl_api_l2_port_type_t port_type;
2966   u32 rx_sw_if_index;
2967   u8 rx_sw_if_index_set = 0;
2968   u32 bd_id;
2969   u8 bd_id_set = 0;
2970   u32 shg = 0;
2971   u8 enable = 1;
2972   int ret;
2973
2974   port_type = L2_API_PORT_TYPE_NORMAL;
2975
2976   /* Parse args required to build the message */
2977   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2978     {
2979       if (unformat (i, "sw_if_index %d", &rx_sw_if_index))
2980         rx_sw_if_index_set = 1;
2981       else if (unformat (i, "bd_id %d", &bd_id))
2982         bd_id_set = 1;
2983       else
2984         if (unformat
2985             (i, "%U", api_unformat_sw_if_index, vam, &rx_sw_if_index))
2986         rx_sw_if_index_set = 1;
2987       else if (unformat (i, "shg %d", &shg))
2988         ;
2989       else if (unformat (i, "bvi"))
2990         port_type = L2_API_PORT_TYPE_BVI;
2991       else if (unformat (i, "uu-fwd"))
2992         port_type = L2_API_PORT_TYPE_UU_FWD;
2993       else if (unformat (i, "enable"))
2994         enable = 1;
2995       else if (unformat (i, "disable"))
2996         enable = 0;
2997       else
2998         break;
2999     }
3000
3001   if (rx_sw_if_index_set == 0)
3002     {
3003       errmsg ("missing rx interface name or sw_if_index");
3004       return -99;
3005     }
3006
3007   if (enable && (bd_id_set == 0))
3008     {
3009       errmsg ("missing bridge domain");
3010       return -99;
3011     }
3012
3013   M (SW_INTERFACE_SET_L2_BRIDGE, mp);
3014
3015   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
3016   mp->bd_id = ntohl (bd_id);
3017   mp->shg = (u8) shg;
3018   mp->port_type = ntohl (port_type);
3019   mp->enable = enable;
3020
3021   S (mp);
3022   W (ret);
3023   return ret;
3024 }
3025
3026 static int
3027 api_bridge_domain_dump (vat_main_t * vam)
3028 {
3029   unformat_input_t *i = vam->input;
3030   vl_api_bridge_domain_dump_t *mp;
3031   vl_api_control_ping_t *mp_ping;
3032   u32 bd_id = ~0;
3033   int ret;
3034
3035   /* Parse args required to build the message */
3036   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3037     {
3038       if (unformat (i, "bd_id %d", &bd_id))
3039         ;
3040       else
3041         break;
3042     }
3043
3044   M (BRIDGE_DOMAIN_DUMP, mp);
3045   mp->bd_id = ntohl (bd_id);
3046   S (mp);
3047
3048   /* Use a control ping for synchronization */
3049   MPING (CONTROL_PING, mp_ping);
3050   S (mp_ping);
3051
3052   W (ret);
3053   return ret;
3054 }
3055
3056 static int
3057 api_bridge_domain_add_del (vat_main_t * vam)
3058 {
3059   unformat_input_t *i = vam->input;
3060   vl_api_bridge_domain_add_del_t *mp;
3061   u32 bd_id = ~0;
3062   u8 is_add = 1;
3063   u32 flood = 1, forward = 1, learn = 1, uu_flood = 1, arp_term = 0;
3064   u8 *bd_tag = NULL;
3065   u32 mac_age = 0;
3066   int ret;
3067
3068   /* Parse args required to build the message */
3069   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3070     {
3071       if (unformat (i, "bd_id %d", &bd_id))
3072         ;
3073       else if (unformat (i, "flood %d", &flood))
3074         ;
3075       else if (unformat (i, "uu-flood %d", &uu_flood))
3076         ;
3077       else if (unformat (i, "forward %d", &forward))
3078         ;
3079       else if (unformat (i, "learn %d", &learn))
3080         ;
3081       else if (unformat (i, "arp-term %d", &arp_term))
3082         ;
3083       else if (unformat (i, "mac-age %d", &mac_age))
3084         ;
3085       else if (unformat (i, "bd-tag %s", &bd_tag))
3086         ;
3087       else if (unformat (i, "del"))
3088         {
3089           is_add = 0;
3090           flood = uu_flood = forward = learn = 0;
3091         }
3092       else
3093         break;
3094     }
3095
3096   if (bd_id == ~0)
3097     {
3098       errmsg ("missing bridge domain");
3099       ret = -99;
3100       goto done;
3101     }
3102
3103   if (mac_age > 255)
3104     {
3105       errmsg ("mac age must be less than 256 ");
3106       ret = -99;
3107       goto done;
3108     }
3109
3110   if ((bd_tag) && (vec_len (bd_tag) > 63))
3111     {
3112       errmsg ("bd-tag cannot be longer than 63");
3113       ret = -99;
3114       goto done;
3115     }
3116
3117   M (BRIDGE_DOMAIN_ADD_DEL, mp);
3118
3119   mp->bd_id = ntohl (bd_id);
3120   mp->flood = flood;
3121   mp->uu_flood = uu_flood;
3122   mp->forward = forward;
3123   mp->learn = learn;
3124   mp->arp_term = arp_term;
3125   mp->is_add = is_add;
3126   mp->mac_age = (u8) mac_age;
3127   if (bd_tag)
3128     {
3129       clib_memcpy (mp->bd_tag, bd_tag, vec_len (bd_tag));
3130       mp->bd_tag[vec_len (bd_tag)] = 0;
3131     }
3132   S (mp);
3133   W (ret);
3134
3135 done:
3136   vec_free (bd_tag);
3137   return ret;
3138 }
3139
3140 static int
3141 api_l2fib_flush_bd (vat_main_t * vam)
3142 {
3143   unformat_input_t *i = vam->input;
3144   vl_api_l2fib_flush_bd_t *mp;
3145   u32 bd_id = ~0;
3146   int ret;
3147
3148   /* Parse args required to build the message */
3149   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3150     {
3151       if (unformat (i, "bd_id %d", &bd_id));
3152       else
3153         break;
3154     }
3155
3156   if (bd_id == ~0)
3157     {
3158       errmsg ("missing bridge domain");
3159       return -99;
3160     }
3161
3162   M (L2FIB_FLUSH_BD, mp);
3163
3164   mp->bd_id = htonl (bd_id);
3165
3166   S (mp);
3167   W (ret);
3168   return ret;
3169 }
3170
3171 static int
3172 api_l2fib_flush_int (vat_main_t * vam)
3173 {
3174   unformat_input_t *i = vam->input;
3175   vl_api_l2fib_flush_int_t *mp;
3176   u32 sw_if_index = ~0;
3177   int ret;
3178
3179   /* Parse args required to build the message */
3180   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3181     {
3182       if (unformat (i, "sw_if_index %d", &sw_if_index));
3183       else
3184         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index));
3185       else
3186         break;
3187     }
3188
3189   if (sw_if_index == ~0)
3190     {
3191       errmsg ("missing interface name or sw_if_index");
3192       return -99;
3193     }
3194
3195   M (L2FIB_FLUSH_INT, mp);
3196
3197   mp->sw_if_index = ntohl (sw_if_index);
3198
3199   S (mp);
3200   W (ret);
3201   return ret;
3202 }
3203
3204 static int
3205 api_l2fib_add_del (vat_main_t * vam)
3206 {
3207   unformat_input_t *i = vam->input;
3208   vl_api_l2fib_add_del_t *mp;
3209   f64 timeout;
3210   u8 mac[6] = { 0 };
3211   u8 mac_set = 0;
3212   u32 bd_id;
3213   u8 bd_id_set = 0;
3214   u32 sw_if_index = 0;
3215   u8 sw_if_index_set = 0;
3216   u8 is_add = 1;
3217   u8 static_mac = 0;
3218   u8 filter_mac = 0;
3219   u8 bvi_mac = 0;
3220   int count = 1;
3221   f64 before = 0;
3222   int j;
3223
3224   /* Parse args required to build the message */
3225   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3226     {
3227       if (unformat (i, "mac %U", unformat_ethernet_address, mac))
3228         mac_set = 1;
3229       else if (unformat (i, "bd_id %d", &bd_id))
3230         bd_id_set = 1;
3231       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3232         sw_if_index_set = 1;
3233       else if (unformat (i, "sw_if"))
3234         {
3235           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3236             {
3237               if (unformat
3238                   (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3239                 sw_if_index_set = 1;
3240             }
3241           else
3242             break;
3243         }
3244       else if (unformat (i, "static"))
3245         static_mac = 1;
3246       else if (unformat (i, "filter"))
3247         {
3248           filter_mac = 1;
3249           static_mac = 1;
3250         }
3251       else if (unformat (i, "bvi"))
3252         {
3253           bvi_mac = 1;
3254           static_mac = 1;
3255         }
3256       else if (unformat (i, "del"))
3257         is_add = 0;
3258       else if (unformat (i, "count %d", &count))
3259         ;
3260       else
3261         break;
3262     }
3263
3264   if (mac_set == 0)
3265     {
3266       errmsg ("missing mac address");
3267       return -99;
3268     }
3269
3270   if (bd_id_set == 0)
3271     {
3272       errmsg ("missing bridge domain");
3273       return -99;
3274     }
3275
3276   if (is_add && sw_if_index_set == 0 && filter_mac == 0)
3277     {
3278       errmsg ("missing interface name or sw_if_index");
3279       return -99;
3280     }
3281
3282   if (count > 1)
3283     {
3284       /* Turn on async mode */
3285       vam->async_mode = 1;
3286       vam->async_errors = 0;
3287       before = vat_time_now (vam);
3288     }
3289
3290   for (j = 0; j < count; j++)
3291     {
3292       M (L2FIB_ADD_DEL, mp);
3293
3294       clib_memcpy (mp->mac, mac, 6);
3295       mp->bd_id = ntohl (bd_id);
3296       mp->is_add = is_add;
3297       mp->sw_if_index = ntohl (sw_if_index);
3298
3299       if (is_add)
3300         {
3301           mp->static_mac = static_mac;
3302           mp->filter_mac = filter_mac;
3303           mp->bvi_mac = bvi_mac;
3304         }
3305       increment_mac_address (mac);
3306       /* send it... */
3307       S (mp);
3308     }
3309
3310   if (count > 1)
3311     {
3312       vl_api_control_ping_t *mp_ping;
3313       f64 after;
3314
3315       /* Shut off async mode */
3316       vam->async_mode = 0;
3317
3318       MPING (CONTROL_PING, mp_ping);
3319       S (mp_ping);
3320
3321       timeout = vat_time_now (vam) + 1.0;
3322       while (vat_time_now (vam) < timeout)
3323         if (vam->result_ready == 1)
3324           goto out;
3325       vam->retval = -99;
3326
3327     out:
3328       if (vam->retval == -99)
3329         errmsg ("timeout");
3330
3331       if (vam->async_errors > 0)
3332         {
3333           errmsg ("%d asynchronous errors", vam->async_errors);
3334           vam->retval = -98;
3335         }
3336       vam->async_errors = 0;
3337       after = vat_time_now (vam);
3338
3339       print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec",
3340              count, after - before, count / (after - before));
3341     }
3342   else
3343     {
3344       int ret;
3345
3346       /* Wait for a reply... */
3347       W (ret);
3348       return ret;
3349     }
3350   /* Return the good/bad news */
3351   return (vam->retval);
3352 }
3353
3354 static int
3355 api_bridge_domain_set_mac_age (vat_main_t * vam)
3356 {
3357   unformat_input_t *i = vam->input;
3358   vl_api_bridge_domain_set_mac_age_t *mp;
3359   u32 bd_id = ~0;
3360   u32 mac_age = 0;
3361   int ret;
3362
3363   /* Parse args required to build the message */
3364   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3365     {
3366       if (unformat (i, "bd_id %d", &bd_id));
3367       else if (unformat (i, "mac-age %d", &mac_age));
3368       else
3369         break;
3370     }
3371
3372   if (bd_id == ~0)
3373     {
3374       errmsg ("missing bridge domain");
3375       return -99;
3376     }
3377
3378   if (mac_age > 255)
3379     {
3380       errmsg ("mac age must be less than 256 ");
3381       return -99;
3382     }
3383
3384   M (BRIDGE_DOMAIN_SET_MAC_AGE, mp);
3385
3386   mp->bd_id = htonl (bd_id);
3387   mp->mac_age = (u8) mac_age;
3388
3389   S (mp);
3390   W (ret);
3391   return ret;
3392 }
3393
3394 static int
3395 api_l2_flags (vat_main_t * vam)
3396 {
3397   unformat_input_t *i = vam->input;
3398   vl_api_l2_flags_t *mp;
3399   u32 sw_if_index;
3400   u32 flags = 0;
3401   u8 sw_if_index_set = 0;
3402   u8 is_set = 0;
3403   int ret;
3404
3405   /* Parse args required to build the message */
3406   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3407     {
3408       if (unformat (i, "sw_if_index %d", &sw_if_index))
3409         sw_if_index_set = 1;
3410       else if (unformat (i, "sw_if"))
3411         {
3412           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3413             {
3414               if (unformat
3415                   (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3416                 sw_if_index_set = 1;
3417             }
3418           else
3419             break;
3420         }
3421       else if (unformat (i, "learn"))
3422         flags |= L2_LEARN;
3423       else if (unformat (i, "forward"))
3424         flags |= L2_FWD;
3425       else if (unformat (i, "flood"))
3426         flags |= L2_FLOOD;
3427       else if (unformat (i, "uu-flood"))
3428         flags |= L2_UU_FLOOD;
3429       else if (unformat (i, "arp-term"))
3430         flags |= L2_ARP_TERM;
3431       else if (unformat (i, "off"))
3432         is_set = 0;
3433       else if (unformat (i, "disable"))
3434         is_set = 0;
3435       else
3436         break;
3437     }
3438
3439   if (sw_if_index_set == 0)
3440     {
3441       errmsg ("missing interface name or sw_if_index");
3442       return -99;
3443     }
3444
3445   M (L2_FLAGS, mp);
3446
3447   mp->sw_if_index = ntohl (sw_if_index);
3448   mp->feature_bitmap = ntohl (flags);
3449   mp->is_set = is_set;
3450
3451   S (mp);
3452   W (ret);
3453   return ret;
3454 }
3455
3456 static int
3457 api_bridge_flags (vat_main_t * vam)
3458 {
3459   unformat_input_t *i = vam->input;
3460   vl_api_bridge_flags_t *mp;
3461   u32 bd_id;
3462   u8 bd_id_set = 0;
3463   u8 is_set = 1;
3464   bd_flags_t flags = 0;
3465   int ret;
3466
3467   /* Parse args required to build the message */
3468   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3469     {
3470       if (unformat (i, "bd_id %d", &bd_id))
3471         bd_id_set = 1;
3472       else if (unformat (i, "learn"))
3473         flags |= BRIDGE_API_FLAG_LEARN;
3474       else if (unformat (i, "forward"))
3475         flags |= BRIDGE_API_FLAG_FWD;
3476       else if (unformat (i, "flood"))
3477         flags |= BRIDGE_API_FLAG_FLOOD;
3478       else if (unformat (i, "uu-flood"))
3479         flags |= BRIDGE_API_FLAG_UU_FLOOD;
3480       else if (unformat (i, "arp-term"))
3481         flags |= BRIDGE_API_FLAG_ARP_TERM;
3482       else if (unformat (i, "off"))
3483         is_set = 0;
3484       else if (unformat (i, "disable"))
3485         is_set = 0;
3486       else
3487         break;
3488     }
3489
3490   if (bd_id_set == 0)
3491     {
3492       errmsg ("missing bridge domain");
3493       return -99;
3494     }
3495
3496   M (BRIDGE_FLAGS, mp);
3497
3498   mp->bd_id = ntohl (bd_id);
3499   mp->flags = ntohl (flags);
3500   mp->is_set = is_set;
3501
3502   S (mp);
3503   W (ret);
3504   return ret;
3505 }
3506
3507 static int
3508 api_bd_ip_mac_add_del (vat_main_t * vam)
3509 {
3510   vl_api_address_t ip = VL_API_ZERO_ADDRESS;
3511   vl_api_mac_address_t mac = { 0 };
3512   unformat_input_t *i = vam->input;
3513   vl_api_bd_ip_mac_add_del_t *mp;
3514   u32 bd_id;
3515   u8 is_add = 1;
3516   u8 bd_id_set = 0;
3517   u8 ip_set = 0;
3518   u8 mac_set = 0;
3519   int ret;
3520
3521
3522   /* Parse args required to build the message */
3523   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3524     {
3525       if (unformat (i, "bd_id %d", &bd_id))
3526         {
3527           bd_id_set++;
3528         }
3529       else if (unformat (i, "%U", unformat_vl_api_address, &ip))
3530         {
3531           ip_set++;
3532         }
3533       else if (unformat (i, "%U", unformat_vl_api_mac_address, &mac))
3534         {
3535           mac_set++;
3536         }
3537       else if (unformat (i, "del"))
3538         is_add = 0;
3539       else
3540         break;
3541     }
3542
3543   if (bd_id_set == 0)
3544     {
3545       errmsg ("missing bridge domain");
3546       return -99;
3547     }
3548   else if (ip_set == 0)
3549     {
3550       errmsg ("missing IP address");
3551       return -99;
3552     }
3553   else if (mac_set == 0)
3554     {
3555       errmsg ("missing MAC address");
3556       return -99;
3557     }
3558
3559   M (BD_IP_MAC_ADD_DEL, mp);
3560
3561   mp->entry.bd_id = ntohl (bd_id);
3562   mp->is_add = is_add;
3563
3564   clib_memcpy (&mp->entry.ip, &ip, sizeof (ip));
3565   clib_memcpy (&mp->entry.mac, &mac, sizeof (mac));
3566
3567   S (mp);
3568   W (ret);
3569   return ret;
3570 }
3571
3572 static int
3573 api_bd_ip_mac_flush (vat_main_t * vam)
3574 {
3575   unformat_input_t *i = vam->input;
3576   vl_api_bd_ip_mac_flush_t *mp;
3577   u32 bd_id;
3578   u8 bd_id_set = 0;
3579   int ret;
3580
3581   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3582     {
3583       if (unformat (i, "bd_id %d", &bd_id))
3584         {
3585           bd_id_set++;
3586         }
3587       else
3588         break;
3589     }
3590
3591   if (bd_id_set == 0)
3592     {
3593       errmsg ("missing bridge domain");
3594       return -99;
3595     }
3596
3597   M (BD_IP_MAC_FLUSH, mp);
3598
3599   mp->bd_id = ntohl (bd_id);
3600
3601   S (mp);
3602   W (ret);
3603   return ret;
3604 }
3605
3606 static void vl_api_bd_ip_mac_details_t_handler
3607   (vl_api_bd_ip_mac_details_t * mp)
3608 {
3609   vat_main_t *vam = &vat_main;
3610
3611   print (vam->ofp,
3612          "\n%-5d %U %U",
3613          ntohl (mp->entry.bd_id),
3614          format_vl_api_mac_address, mp->entry.mac,
3615          format_vl_api_address, &mp->entry.ip);
3616 }
3617
3618 static void vl_api_bd_ip_mac_details_t_handler_json
3619   (vl_api_bd_ip_mac_details_t * mp)
3620 {
3621   vat_main_t *vam = &vat_main;
3622   vat_json_node_t *node = NULL;
3623
3624   if (VAT_JSON_ARRAY != vam->json_tree.type)
3625     {
3626       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
3627       vat_json_init_array (&vam->json_tree);
3628     }
3629   node = vat_json_array_add (&vam->json_tree);
3630
3631   vat_json_init_object (node);
3632   vat_json_object_add_uint (node, "bd_id", ntohl (mp->entry.bd_id));
3633   vat_json_object_add_string_copy (node, "mac_address",
3634                                    format (0, "%U", format_vl_api_mac_address,
3635                                            &mp->entry.mac));
3636   u8 *ip = 0;
3637
3638   ip = format (0, "%U", format_vl_api_address, &mp->entry.ip);
3639   vat_json_object_add_string_copy (node, "ip_address", ip);
3640   vec_free (ip);
3641 }
3642
3643 static int
3644 api_bd_ip_mac_dump (vat_main_t * vam)
3645 {
3646   unformat_input_t *i = vam->input;
3647   vl_api_bd_ip_mac_dump_t *mp;
3648   vl_api_control_ping_t *mp_ping;
3649   int ret;
3650   u32 bd_id;
3651   u8 bd_id_set = 0;
3652
3653   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3654     {
3655       if (unformat (i, "bd_id %d", &bd_id))
3656         {
3657           bd_id_set++;
3658         }
3659       else
3660         break;
3661     }
3662
3663   print (vam->ofp,
3664          "\n%-5s %-7s %-20s %-30s",
3665          "bd_id", "is_ipv6", "mac_address", "ip_address");
3666
3667   /* Dump Bridge Domain Ip to Mac entries */
3668   M (BD_IP_MAC_DUMP, mp);
3669
3670   if (bd_id_set)
3671     mp->bd_id = htonl (bd_id);
3672   else
3673     mp->bd_id = ~0;
3674
3675   S (mp);
3676
3677   /* Use a control ping for synchronization */
3678   MPING (CONTROL_PING, mp_ping);
3679   S (mp_ping);
3680
3681   W (ret);
3682   return ret;
3683 }
3684
3685 uword
3686 unformat_vlib_pci_addr (unformat_input_t * input, va_list * args)
3687 {
3688   vlib_pci_addr_t *addr = va_arg (*args, vlib_pci_addr_t *);
3689   u32 x[4];
3690
3691   if (!unformat (input, "%x:%x:%x.%x", &x[0], &x[1], &x[2], &x[3]))
3692     return 0;
3693
3694   addr->domain = x[0];
3695   addr->bus = x[1];
3696   addr->slot = x[2];
3697   addr->function = x[3];
3698
3699   return 1;
3700 }
3701
3702 static int
3703 api_virtio_pci_create_v2 (vat_main_t * vam)
3704 {
3705   unformat_input_t *i = vam->input;
3706   vl_api_virtio_pci_create_v2_t *mp;
3707   u8 mac_address[6];
3708   u8 random_mac = 1;
3709   u32 pci_addr = 0;
3710   u64 features = (u64) ~ (0ULL);
3711   u32 virtio_flags = 0;
3712   int ret;
3713
3714   clib_memset (mac_address, 0, sizeof (mac_address));
3715
3716   /* Parse args required to build the message */
3717   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3718     {
3719       if (unformat (i, "hw-addr %U", unformat_ethernet_address, mac_address))
3720         {
3721           random_mac = 0;
3722         }
3723       else if (unformat (i, "pci-addr %U", unformat_vlib_pci_addr, &pci_addr))
3724         ;
3725       else if (unformat (i, "features 0x%llx", &features))
3726         ;
3727       else if (unformat (i, "gso-enabled"))
3728         virtio_flags |= VIRTIO_API_FLAG_GSO;
3729       else if (unformat (i, "csum-offload-enabled"))
3730         virtio_flags |= VIRTIO_API_FLAG_CSUM_OFFLOAD;
3731       else if (unformat (i, "gro-coalesce"))
3732         virtio_flags |= VIRTIO_API_FLAG_GRO_COALESCE;
3733       else if (unformat (i, "packed"))
3734         virtio_flags |= VIRTIO_API_FLAG_PACKED;
3735       else if (unformat (i, "in-order"))
3736         virtio_flags |= VIRTIO_API_FLAG_IN_ORDER;
3737       else if (unformat (i, "buffering"))
3738         virtio_flags |= VIRTIO_API_FLAG_BUFFERING;
3739       else
3740         break;
3741     }
3742
3743   if (pci_addr == 0)
3744     {
3745       errmsg ("pci address must be non zero. ");
3746       return -99;
3747     }
3748
3749   /* Construct the API message */
3750   M (VIRTIO_PCI_CREATE_V2, mp);
3751
3752   mp->use_random_mac = random_mac;
3753
3754   mp->pci_addr.domain = htons (((vlib_pci_addr_t) pci_addr).domain);
3755   mp->pci_addr.bus = ((vlib_pci_addr_t) pci_addr).bus;
3756   mp->pci_addr.slot = ((vlib_pci_addr_t) pci_addr).slot;
3757   mp->pci_addr.function = ((vlib_pci_addr_t) pci_addr).function;
3758
3759   mp->features = clib_host_to_net_u64 (features);
3760   mp->virtio_flags = clib_host_to_net_u32 (virtio_flags);
3761
3762   if (random_mac == 0)
3763     clib_memcpy (mp->mac_address, mac_address, 6);
3764
3765   /* send it... */
3766   S (mp);
3767
3768   /* Wait for a reply... */
3769   W (ret);
3770   return ret;
3771 }
3772
3773 static int
3774 api_virtio_pci_delete (vat_main_t * vam)
3775 {
3776   unformat_input_t *i = vam->input;
3777   vl_api_virtio_pci_delete_t *mp;
3778   u32 sw_if_index = ~0;
3779   u8 sw_if_index_set = 0;
3780   int ret;
3781
3782   /* Parse args required to build the message */
3783   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3784     {
3785       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3786         sw_if_index_set = 1;
3787       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3788         sw_if_index_set = 1;
3789       else
3790         break;
3791     }
3792
3793   if (sw_if_index_set == 0)
3794     {
3795       errmsg ("missing vpp interface name. ");
3796       return -99;
3797     }
3798
3799   /* Construct the API message */
3800   M (VIRTIO_PCI_DELETE, mp);
3801
3802   mp->sw_if_index = htonl (sw_if_index);
3803
3804   /* send it... */
3805   S (mp);
3806
3807   /* Wait for a reply... */
3808   W (ret);
3809   return ret;
3810 }
3811
3812 static int
3813 api_ip_table_add_del (vat_main_t * vam)
3814 {
3815   unformat_input_t *i = vam->input;
3816   vl_api_ip_table_add_del_t *mp;
3817   u32 table_id = ~0;
3818   u8 is_ipv6 = 0;
3819   u8 is_add = 1;
3820   int ret = 0;
3821
3822   /* Parse args required to build the message */
3823   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3824     {
3825       if (unformat (i, "ipv6"))
3826         is_ipv6 = 1;
3827       else if (unformat (i, "del"))
3828         is_add = 0;
3829       else if (unformat (i, "add"))
3830         is_add = 1;
3831       else if (unformat (i, "table %d", &table_id))
3832         ;
3833       else
3834         {
3835           clib_warning ("parse error '%U'", format_unformat_error, i);
3836           return -99;
3837         }
3838     }
3839
3840   if (~0 == table_id)
3841     {
3842       errmsg ("missing table-ID");
3843       return -99;
3844     }
3845
3846   /* Construct the API message */
3847   M (IP_TABLE_ADD_DEL, mp);
3848
3849   mp->table.table_id = ntohl (table_id);
3850   mp->table.is_ip6 = is_ipv6;
3851   mp->is_add = is_add;
3852
3853   /* send it... */
3854   S (mp);
3855
3856   /* Wait for a reply... */
3857   W (ret);
3858
3859   return ret;
3860 }
3861
3862 uword
3863 unformat_fib_path (unformat_input_t * input, va_list * args)
3864 {
3865   vat_main_t *vam = va_arg (*args, vat_main_t *);
3866   vl_api_fib_path_t *path = va_arg (*args, vl_api_fib_path_t *);
3867   u32 weight, preference;
3868   mpls_label_t out_label;
3869
3870   clib_memset (path, 0, sizeof (*path));
3871   path->weight = 1;
3872   path->sw_if_index = ~0;
3873   path->rpf_id = ~0;
3874   path->n_labels = 0;
3875
3876   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3877     {
3878       if (unformat (input, "%U %U",
3879                     unformat_vl_api_ip4_address,
3880                     &path->nh.address.ip4,
3881                     api_unformat_sw_if_index, vam, &path->sw_if_index))
3882         {
3883           path->proto = FIB_API_PATH_NH_PROTO_IP4;
3884         }
3885       else if (unformat (input, "%U %U",
3886                          unformat_vl_api_ip6_address,
3887                          &path->nh.address.ip6,
3888                          api_unformat_sw_if_index, vam, &path->sw_if_index))
3889         {
3890           path->proto = FIB_API_PATH_NH_PROTO_IP6;
3891         }
3892       else if (unformat (input, "weight %u", &weight))
3893         {
3894           path->weight = weight;
3895         }
3896       else if (unformat (input, "preference %u", &preference))
3897         {
3898           path->preference = preference;
3899         }
3900       else if (unformat (input, "%U next-hop-table %d",
3901                          unformat_vl_api_ip4_address,
3902                          &path->nh.address.ip4, &path->table_id))
3903         {
3904           path->proto = FIB_API_PATH_NH_PROTO_IP4;
3905         }
3906       else if (unformat (input, "%U next-hop-table %d",
3907                          unformat_vl_api_ip6_address,
3908                          &path->nh.address.ip6, &path->table_id))
3909         {
3910           path->proto = FIB_API_PATH_NH_PROTO_IP6;
3911         }
3912       else if (unformat (input, "%U",
3913                          unformat_vl_api_ip4_address, &path->nh.address.ip4))
3914         {
3915           /*
3916            * the recursive next-hops are by default in the default table
3917            */
3918           path->table_id = 0;
3919           path->sw_if_index = ~0;
3920           path->proto = FIB_API_PATH_NH_PROTO_IP4;
3921         }
3922       else if (unformat (input, "%U",
3923                          unformat_vl_api_ip6_address, &path->nh.address.ip6))
3924         {
3925           /*
3926            * the recursive next-hops are by default in the default table
3927            */
3928           path->table_id = 0;
3929           path->sw_if_index = ~0;
3930           path->proto = FIB_API_PATH_NH_PROTO_IP6;
3931         }
3932       else if (unformat (input, "resolve-via-host"))
3933         {
3934           path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_HOST;
3935         }
3936       else if (unformat (input, "resolve-via-attached"))
3937         {
3938           path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_ATTACHED;
3939         }
3940       else if (unformat (input, "ip4-lookup-in-table %d", &path->table_id))
3941         {
3942           path->type = FIB_API_PATH_TYPE_LOCAL;
3943           path->sw_if_index = ~0;
3944           path->proto = FIB_API_PATH_NH_PROTO_IP4;
3945         }
3946       else if (unformat (input, "ip6-lookup-in-table %d", &path->table_id))
3947         {
3948           path->type = FIB_API_PATH_TYPE_LOCAL;
3949           path->sw_if_index = ~0;
3950           path->proto = FIB_API_PATH_NH_PROTO_IP6;
3951         }
3952       else if (unformat (input, "sw_if_index %d", &path->sw_if_index))
3953         ;
3954       else if (unformat (input, "via-label %d", &path->nh.via_label))
3955         {
3956           path->proto = FIB_API_PATH_NH_PROTO_MPLS;
3957           path->sw_if_index = ~0;
3958         }
3959       else if (unformat (input, "l2-input-on %d", &path->sw_if_index))
3960         {
3961           path->proto = FIB_API_PATH_NH_PROTO_ETHERNET;
3962           path->type = FIB_API_PATH_TYPE_INTERFACE_RX;
3963         }
3964       else if (unformat (input, "local"))
3965         {
3966           path->type = FIB_API_PATH_TYPE_LOCAL;
3967         }
3968       else if (unformat (input, "out-labels"))
3969         {
3970           while (unformat (input, "%d", &out_label))
3971             {
3972               path->label_stack[path->n_labels].label = out_label;
3973               path->label_stack[path->n_labels].is_uniform = 0;
3974               path->label_stack[path->n_labels].ttl = 64;
3975               path->n_labels++;
3976             }
3977         }
3978       else if (unformat (input, "via"))
3979         {
3980           /* new path, back up and return */
3981           unformat_put_input (input);
3982           unformat_put_input (input);
3983           unformat_put_input (input);
3984           unformat_put_input (input);
3985           break;
3986         }
3987       else
3988         {
3989           return (0);
3990         }
3991     }
3992
3993   path->proto = ntohl (path->proto);
3994   path->type = ntohl (path->type);
3995   path->flags = ntohl (path->flags);
3996   path->table_id = ntohl (path->table_id);
3997   path->sw_if_index = ntohl (path->sw_if_index);
3998
3999   return (1);
4000 }
4001
4002 static int
4003 api_ip_route_add_del (vat_main_t * vam)
4004 {
4005   unformat_input_t *i = vam->input;
4006   vl_api_ip_route_add_del_t *mp;
4007   u32 vrf_id = 0;
4008   u8 is_add = 1;
4009   u8 is_multipath = 0;
4010   u8 prefix_set = 0;
4011   u8 path_count = 0;
4012   vl_api_prefix_t pfx = { };
4013   vl_api_fib_path_t paths[8];
4014   int count = 1;
4015   int j;
4016   f64 before = 0;
4017   u32 random_add_del = 0;
4018   u32 *random_vector = 0;
4019   u32 random_seed = 0xdeaddabe;
4020
4021   /* Parse args required to build the message */
4022   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4023     {
4024       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
4025         prefix_set = 1;
4026       else if (unformat (i, "del"))
4027         is_add = 0;
4028       else if (unformat (i, "add"))
4029         is_add = 1;
4030       else if (unformat (i, "vrf %d", &vrf_id))
4031         ;
4032       else if (unformat (i, "count %d", &count))
4033         ;
4034       else if (unformat (i, "random"))
4035         random_add_del = 1;
4036       else if (unformat (i, "multipath"))
4037         is_multipath = 1;
4038       else if (unformat (i, "seed %d", &random_seed))
4039         ;
4040       else
4041         if (unformat
4042             (i, "via %U", unformat_fib_path, vam, &paths[path_count]))
4043         {
4044           path_count++;
4045           if (8 == path_count)
4046             {
4047               errmsg ("max 8 paths");
4048               return -99;
4049             }
4050         }
4051       else
4052         {
4053           clib_warning ("parse error '%U'", format_unformat_error, i);
4054           return -99;
4055         }
4056     }
4057
4058   if (!path_count)
4059     {
4060       errmsg ("specify a path; via ...");
4061       return -99;
4062     }
4063   if (prefix_set == 0)
4064     {
4065       errmsg ("missing prefix");
4066       return -99;
4067     }
4068
4069   /* Generate a pile of unique, random routes */
4070   if (random_add_del)
4071     {
4072       ip4_address_t *i = (ip4_address_t *) & paths[0].nh.address.ip4;
4073       u32 this_random_address;
4074       uword *random_hash;
4075
4076       random_hash = hash_create (count, sizeof (uword));
4077
4078       hash_set (random_hash, i->as_u32, 1);
4079       for (j = 0; j <= count; j++)
4080         {
4081           do
4082             {
4083               this_random_address = random_u32 (&random_seed);
4084               this_random_address =
4085                 clib_host_to_net_u32 (this_random_address);
4086             }
4087           while (hash_get (random_hash, this_random_address));
4088           vec_add1 (random_vector, this_random_address);
4089           hash_set (random_hash, this_random_address, 1);
4090         }
4091       hash_free (random_hash);
4092       set_ip4_address (&pfx.address, random_vector[0]);
4093     }
4094
4095   if (count > 1)
4096     {
4097       /* Turn on async mode */
4098       vam->async_mode = 1;
4099       vam->async_errors = 0;
4100       before = vat_time_now (vam);
4101     }
4102
4103   for (j = 0; j < count; j++)
4104     {
4105       /* Construct the API message */
4106       M2 (IP_ROUTE_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
4107
4108       mp->is_add = is_add;
4109       mp->is_multipath = is_multipath;
4110
4111       clib_memcpy (&mp->route.prefix, &pfx, sizeof (pfx));
4112       mp->route.table_id = ntohl (vrf_id);
4113       mp->route.n_paths = path_count;
4114
4115       clib_memcpy (&mp->route.paths, &paths, sizeof (paths[0]) * path_count);
4116
4117       if (random_add_del)
4118         set_ip4_address (&pfx.address, random_vector[j + 1]);
4119       else
4120         increment_address (&pfx.address);
4121       /* send it... */
4122       S (mp);
4123       /* If we receive SIGTERM, stop now... */
4124       if (vam->do_exit)
4125         break;
4126     }
4127
4128   /* When testing multiple add/del ops, use a control-ping to sync */
4129   if (count > 1)
4130     {
4131       vl_api_control_ping_t *mp_ping;
4132       f64 after;
4133       f64 timeout;
4134
4135       /* Shut off async mode */
4136       vam->async_mode = 0;
4137
4138       MPING (CONTROL_PING, mp_ping);
4139       S (mp_ping);
4140
4141       timeout = vat_time_now (vam) + 1.0;
4142       while (vat_time_now (vam) < timeout)
4143         if (vam->result_ready == 1)
4144           goto out;
4145       vam->retval = -99;
4146
4147     out:
4148       if (vam->retval == -99)
4149         errmsg ("timeout");
4150
4151       if (vam->async_errors > 0)
4152         {
4153           errmsg ("%d asynchronous errors", vam->async_errors);
4154           vam->retval = -98;
4155         }
4156       vam->async_errors = 0;
4157       after = vat_time_now (vam);
4158
4159       /* slim chance, but we might have eaten SIGTERM on the first iteration */
4160       if (j > 0)
4161         count = j;
4162
4163       print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec",
4164              count, after - before, count / (after - before));
4165     }
4166   else
4167     {
4168       int ret;
4169
4170       /* Wait for a reply... */
4171       W (ret);
4172       return ret;
4173     }
4174
4175   /* Return the good/bad news */
4176   return (vam->retval);
4177 }
4178
4179 static int
4180 api_ip_mroute_add_del (vat_main_t * vam)
4181 {
4182   unformat_input_t *i = vam->input;
4183   u8 path_set = 0, prefix_set = 0, is_add = 1;
4184   vl_api_ip_mroute_add_del_t *mp;
4185   mfib_entry_flags_t eflags = 0;
4186   vl_api_mfib_path_t path;
4187   vl_api_mprefix_t pfx = { };
4188   u32 vrf_id = 0;
4189   int ret;
4190
4191   /* Parse args required to build the message */
4192   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4193     {
4194       if (unformat (i, "%U", unformat_vl_api_mprefix, &pfx))
4195         {
4196           prefix_set = 1;
4197           pfx.grp_address_length = htons (pfx.grp_address_length);
4198         }
4199       else if (unformat (i, "del"))
4200         is_add = 0;
4201       else if (unformat (i, "add"))
4202         is_add = 1;
4203       else if (unformat (i, "vrf %d", &vrf_id))
4204         ;
4205       else if (unformat (i, "%U", unformat_mfib_itf_flags, &path.itf_flags))
4206         path.itf_flags = htonl (path.itf_flags);
4207       else if (unformat (i, "%U", unformat_mfib_entry_flags, &eflags))
4208         ;
4209       else if (unformat (i, "via %U", unformat_fib_path, vam, &path.path))
4210         path_set = 1;
4211       else
4212         {
4213           clib_warning ("parse error '%U'", format_unformat_error, i);
4214           return -99;
4215         }
4216     }
4217
4218   if (prefix_set == 0)
4219     {
4220       errmsg ("missing addresses\n");
4221       return -99;
4222     }
4223   if (path_set == 0)
4224     {
4225       errmsg ("missing path\n");
4226       return -99;
4227     }
4228
4229   /* Construct the API message */
4230   M (IP_MROUTE_ADD_DEL, mp);
4231
4232   mp->is_add = is_add;
4233   mp->is_multipath = 1;
4234
4235   clib_memcpy (&mp->route.prefix, &pfx, sizeof (pfx));
4236   mp->route.table_id = htonl (vrf_id);
4237   mp->route.n_paths = 1;
4238   mp->route.entry_flags = htonl (eflags);
4239
4240   clib_memcpy (&mp->route.paths, &path, sizeof (path));
4241
4242   /* send it... */
4243   S (mp);
4244   /* Wait for a reply... */
4245   W (ret);
4246   return ret;
4247 }
4248
4249 static int
4250 api_sw_interface_set_unnumbered (vat_main_t * vam)
4251 {
4252   unformat_input_t *i = vam->input;
4253   vl_api_sw_interface_set_unnumbered_t *mp;
4254   u32 sw_if_index;
4255   u32 unnum_sw_index = ~0;
4256   u8 is_add = 1;
4257   u8 sw_if_index_set = 0;
4258   int ret;
4259
4260   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4261     {
4262       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4263         sw_if_index_set = 1;
4264       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4265         sw_if_index_set = 1;
4266       else if (unformat (i, "unnum_if_index %d", &unnum_sw_index))
4267         ;
4268       else if (unformat (i, "del"))
4269         is_add = 0;
4270       else
4271         {
4272           clib_warning ("parse error '%U'", format_unformat_error, i);
4273           return -99;
4274         }
4275     }
4276
4277   if (sw_if_index_set == 0)
4278     {
4279       errmsg ("missing interface name or sw_if_index");
4280       return -99;
4281     }
4282
4283   M (SW_INTERFACE_SET_UNNUMBERED, mp);
4284
4285   mp->sw_if_index = ntohl (sw_if_index);
4286   mp->unnumbered_sw_if_index = ntohl (unnum_sw_index);
4287   mp->is_add = is_add;
4288
4289   S (mp);
4290   W (ret);
4291   return ret;
4292 }
4293
4294
4295 static int
4296 api_create_vlan_subif (vat_main_t * vam)
4297 {
4298   unformat_input_t *i = vam->input;
4299   vl_api_create_vlan_subif_t *mp;
4300   u32 sw_if_index;
4301   u8 sw_if_index_set = 0;
4302   u32 vlan_id;
4303   u8 vlan_id_set = 0;
4304   int ret;
4305
4306   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4307     {
4308       if (unformat (i, "sw_if_index %d", &sw_if_index))
4309         sw_if_index_set = 1;
4310       else
4311         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4312         sw_if_index_set = 1;
4313       else if (unformat (i, "vlan %d", &vlan_id))
4314         vlan_id_set = 1;
4315       else
4316         {
4317           clib_warning ("parse error '%U'", format_unformat_error, i);
4318           return -99;
4319         }
4320     }
4321
4322   if (sw_if_index_set == 0)
4323     {
4324       errmsg ("missing interface name or sw_if_index");
4325       return -99;
4326     }
4327
4328   if (vlan_id_set == 0)
4329     {
4330       errmsg ("missing vlan_id");
4331       return -99;
4332     }
4333   M (CREATE_VLAN_SUBIF, mp);
4334
4335   mp->sw_if_index = ntohl (sw_if_index);
4336   mp->vlan_id = ntohl (vlan_id);
4337
4338   S (mp);
4339   W (ret);
4340   return ret;
4341 }
4342
4343 #define foreach_create_subif_bit                \
4344 _(no_tags)                                      \
4345 _(one_tag)                                      \
4346 _(two_tags)                                     \
4347 _(dot1ad)                                       \
4348 _(exact_match)                                  \
4349 _(default_sub)                                  \
4350 _(outer_vlan_id_any)                            \
4351 _(inner_vlan_id_any)
4352
4353 #define foreach_create_subif_flag               \
4354 _(0, "no_tags")                                 \
4355 _(1, "one_tag")                                 \
4356 _(2, "two_tags")                                \
4357 _(3, "dot1ad")                                  \
4358 _(4, "exact_match")                             \
4359 _(5, "default_sub")                             \
4360 _(6, "outer_vlan_id_any")                       \
4361 _(7, "inner_vlan_id_any")
4362
4363 static int
4364 api_create_subif (vat_main_t * vam)
4365 {
4366   unformat_input_t *i = vam->input;
4367   vl_api_create_subif_t *mp;
4368   u32 sw_if_index;
4369   u8 sw_if_index_set = 0;
4370   u32 sub_id;
4371   u8 sub_id_set = 0;
4372   u32 __attribute__ ((unused)) no_tags = 0;
4373   u32 __attribute__ ((unused)) one_tag = 0;
4374   u32 __attribute__ ((unused)) two_tags = 0;
4375   u32 __attribute__ ((unused)) dot1ad = 0;
4376   u32 __attribute__ ((unused)) exact_match = 0;
4377   u32 __attribute__ ((unused)) default_sub = 0;
4378   u32 __attribute__ ((unused)) outer_vlan_id_any = 0;
4379   u32 __attribute__ ((unused)) inner_vlan_id_any = 0;
4380   u32 tmp;
4381   u16 outer_vlan_id = 0;
4382   u16 inner_vlan_id = 0;
4383   int ret;
4384
4385   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4386     {
4387       if (unformat (i, "sw_if_index %d", &sw_if_index))
4388         sw_if_index_set = 1;
4389       else
4390         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4391         sw_if_index_set = 1;
4392       else if (unformat (i, "sub_id %d", &sub_id))
4393         sub_id_set = 1;
4394       else if (unformat (i, "outer_vlan_id %d", &tmp))
4395         outer_vlan_id = tmp;
4396       else if (unformat (i, "inner_vlan_id %d", &tmp))
4397         inner_vlan_id = tmp;
4398
4399 #define _(a) else if (unformat (i, #a)) a = 1 ;
4400       foreach_create_subif_bit
4401 #undef _
4402         else
4403         {
4404           clib_warning ("parse error '%U'", format_unformat_error, i);
4405           return -99;
4406         }
4407     }
4408
4409   if (sw_if_index_set == 0)
4410     {
4411       errmsg ("missing interface name or sw_if_index");
4412       return -99;
4413     }
4414
4415   if (sub_id_set == 0)
4416     {
4417       errmsg ("missing sub_id");
4418       return -99;
4419     }
4420   M (CREATE_SUBIF, mp);
4421
4422   mp->sw_if_index = ntohl (sw_if_index);
4423   mp->sub_id = ntohl (sub_id);
4424
4425 #define _(a,b) mp->sub_if_flags |= (1 << a);
4426   foreach_create_subif_flag;
4427 #undef _
4428
4429   mp->outer_vlan_id = ntohs (outer_vlan_id);
4430   mp->inner_vlan_id = ntohs (inner_vlan_id);
4431
4432   S (mp);
4433   W (ret);
4434   return ret;
4435 }
4436
4437 static int
4438 api_ip_table_replace_begin (vat_main_t * vam)
4439 {
4440   unformat_input_t *i = vam->input;
4441   vl_api_ip_table_replace_begin_t *mp;
4442   u32 table_id = 0;
4443   u8 is_ipv6 = 0;
4444
4445   int ret;
4446   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4447     {
4448       if (unformat (i, "table %d", &table_id))
4449         ;
4450       else if (unformat (i, "ipv6"))
4451         is_ipv6 = 1;
4452       else
4453         {
4454           clib_warning ("parse error '%U'", format_unformat_error, i);
4455           return -99;
4456         }
4457     }
4458
4459   M (IP_TABLE_REPLACE_BEGIN, mp);
4460
4461   mp->table.table_id = ntohl (table_id);
4462   mp->table.is_ip6 = is_ipv6;
4463
4464   S (mp);
4465   W (ret);
4466   return ret;
4467 }
4468
4469 static int
4470 api_ip_table_flush (vat_main_t * vam)
4471 {
4472   unformat_input_t *i = vam->input;
4473   vl_api_ip_table_flush_t *mp;
4474   u32 table_id = 0;
4475   u8 is_ipv6 = 0;
4476
4477   int ret;
4478   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4479     {
4480       if (unformat (i, "table %d", &table_id))
4481         ;
4482       else if (unformat (i, "ipv6"))
4483         is_ipv6 = 1;
4484       else
4485         {
4486           clib_warning ("parse error '%U'", format_unformat_error, i);
4487           return -99;
4488         }
4489     }
4490
4491   M (IP_TABLE_FLUSH, mp);
4492
4493   mp->table.table_id = ntohl (table_id);
4494   mp->table.is_ip6 = is_ipv6;
4495
4496   S (mp);
4497   W (ret);
4498   return ret;
4499 }
4500
4501 static int
4502 api_ip_table_replace_end (vat_main_t * vam)
4503 {
4504   unformat_input_t *i = vam->input;
4505   vl_api_ip_table_replace_end_t *mp;
4506   u32 table_id = 0;
4507   u8 is_ipv6 = 0;
4508
4509   int ret;
4510   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4511     {
4512       if (unformat (i, "table %d", &table_id))
4513         ;
4514       else if (unformat (i, "ipv6"))
4515         is_ipv6 = 1;
4516       else
4517         {
4518           clib_warning ("parse error '%U'", format_unformat_error, i);
4519           return -99;
4520         }
4521     }
4522
4523   M (IP_TABLE_REPLACE_END, mp);
4524
4525   mp->table.table_id = ntohl (table_id);
4526   mp->table.is_ip6 = is_ipv6;
4527
4528   S (mp);
4529   W (ret);
4530   return ret;
4531 }
4532
4533 static int
4534 api_set_ip_flow_hash (vat_main_t * vam)
4535 {
4536   unformat_input_t *i = vam->input;
4537   vl_api_set_ip_flow_hash_t *mp;
4538   u32 vrf_id = 0;
4539   u8 is_ipv6 = 0;
4540   u8 vrf_id_set = 0;
4541   u8 src = 0;
4542   u8 dst = 0;
4543   u8 sport = 0;
4544   u8 dport = 0;
4545   u8 proto = 0;
4546   u8 reverse = 0;
4547   int ret;
4548
4549   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4550     {
4551       if (unformat (i, "vrf %d", &vrf_id))
4552         vrf_id_set = 1;
4553       else if (unformat (i, "ipv6"))
4554         is_ipv6 = 1;
4555       else if (unformat (i, "src"))
4556         src = 1;
4557       else if (unformat (i, "dst"))
4558         dst = 1;
4559       else if (unformat (i, "sport"))
4560         sport = 1;
4561       else if (unformat (i, "dport"))
4562         dport = 1;
4563       else if (unformat (i, "proto"))
4564         proto = 1;
4565       else if (unformat (i, "reverse"))
4566         reverse = 1;
4567
4568       else
4569         {
4570           clib_warning ("parse error '%U'", format_unformat_error, i);
4571           return -99;
4572         }
4573     }
4574
4575   if (vrf_id_set == 0)
4576     {
4577       errmsg ("missing vrf id");
4578       return -99;
4579     }
4580
4581   M (SET_IP_FLOW_HASH, mp);
4582   mp->src = src;
4583   mp->dst = dst;
4584   mp->sport = sport;
4585   mp->dport = dport;
4586   mp->proto = proto;
4587   mp->reverse = reverse;
4588   mp->vrf_id = ntohl (vrf_id);
4589   mp->is_ipv6 = is_ipv6;
4590
4591   S (mp);
4592   W (ret);
4593   return ret;
4594 }
4595
4596 static int
4597 api_sw_interface_ip6_enable_disable (vat_main_t * vam)
4598 {
4599   unformat_input_t *i = vam->input;
4600   vl_api_sw_interface_ip6_enable_disable_t *mp;
4601   u32 sw_if_index;
4602   u8 sw_if_index_set = 0;
4603   u8 enable = 0;
4604   int ret;
4605
4606   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4607     {
4608       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4609         sw_if_index_set = 1;
4610       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4611         sw_if_index_set = 1;
4612       else if (unformat (i, "enable"))
4613         enable = 1;
4614       else if (unformat (i, "disable"))
4615         enable = 0;
4616       else
4617         {
4618           clib_warning ("parse error '%U'", format_unformat_error, i);
4619           return -99;
4620         }
4621     }
4622
4623   if (sw_if_index_set == 0)
4624     {
4625       errmsg ("missing interface name or sw_if_index");
4626       return -99;
4627     }
4628
4629   M (SW_INTERFACE_IP6_ENABLE_DISABLE, mp);
4630
4631   mp->sw_if_index = ntohl (sw_if_index);
4632   mp->enable = enable;
4633
4634   S (mp);
4635   W (ret);
4636   return ret;
4637 }
4638
4639
4640 static int
4641 api_l2_patch_add_del (vat_main_t * vam)
4642 {
4643   unformat_input_t *i = vam->input;
4644   vl_api_l2_patch_add_del_t *mp;
4645   u32 rx_sw_if_index;
4646   u8 rx_sw_if_index_set = 0;
4647   u32 tx_sw_if_index;
4648   u8 tx_sw_if_index_set = 0;
4649   u8 is_add = 1;
4650   int ret;
4651
4652   /* Parse args required to build the message */
4653   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4654     {
4655       if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index))
4656         rx_sw_if_index_set = 1;
4657       else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
4658         tx_sw_if_index_set = 1;
4659       else if (unformat (i, "rx"))
4660         {
4661           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4662             {
4663               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
4664                             &rx_sw_if_index))
4665                 rx_sw_if_index_set = 1;
4666             }
4667           else
4668             break;
4669         }
4670       else if (unformat (i, "tx"))
4671         {
4672           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4673             {
4674               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
4675                             &tx_sw_if_index))
4676                 tx_sw_if_index_set = 1;
4677             }
4678           else
4679             break;
4680         }
4681       else if (unformat (i, "del"))
4682         is_add = 0;
4683       else
4684         break;
4685     }
4686
4687   if (rx_sw_if_index_set == 0)
4688     {
4689       errmsg ("missing rx interface name or rx_sw_if_index");
4690       return -99;
4691     }
4692
4693   if (tx_sw_if_index_set == 0)
4694     {
4695       errmsg ("missing tx interface name or tx_sw_if_index");
4696       return -99;
4697     }
4698
4699   M (L2_PATCH_ADD_DEL, mp);
4700
4701   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
4702   mp->tx_sw_if_index = ntohl (tx_sw_if_index);
4703   mp->is_add = is_add;
4704
4705   S (mp);
4706   W (ret);
4707   return ret;
4708 }
4709
4710 u8 is_del;
4711 u8 localsid_addr[16];
4712 u8 end_psp;
4713 u8 behavior;
4714 u32 sw_if_index;
4715 u32 vlan_index;
4716 u32 fib_table;
4717 u8 nh_addr[16];
4718
4719 static int
4720 api_ioam_enable (vat_main_t * vam)
4721 {
4722   unformat_input_t *input = vam->input;
4723   vl_api_ioam_enable_t *mp;
4724   u32 id = 0;
4725   int has_trace_option = 0;
4726   int has_pot_option = 0;
4727   int has_seqno_option = 0;
4728   int has_analyse_option = 0;
4729   int ret;
4730
4731   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
4732     {
4733       if (unformat (input, "trace"))
4734         has_trace_option = 1;
4735       else if (unformat (input, "pot"))
4736         has_pot_option = 1;
4737       else if (unformat (input, "seqno"))
4738         has_seqno_option = 1;
4739       else if (unformat (input, "analyse"))
4740         has_analyse_option = 1;
4741       else
4742         break;
4743     }
4744   M (IOAM_ENABLE, mp);
4745   mp->id = htons (id);
4746   mp->seqno = has_seqno_option;
4747   mp->analyse = has_analyse_option;
4748   mp->pot_enable = has_pot_option;
4749   mp->trace_enable = has_trace_option;
4750
4751   S (mp);
4752   W (ret);
4753   return ret;
4754 }
4755
4756
4757 static int
4758 api_ioam_disable (vat_main_t * vam)
4759 {
4760   vl_api_ioam_disable_t *mp;
4761   int ret;
4762
4763   M (IOAM_DISABLE, mp);
4764   S (mp);
4765   W (ret);
4766   return ret;
4767 }
4768
4769 #define foreach_tcp_proto_field                 \
4770 _(src_port)                                     \
4771 _(dst_port)
4772
4773 #define foreach_udp_proto_field                 \
4774 _(src_port)                                     \
4775 _(dst_port)
4776
4777 #define foreach_ip4_proto_field                 \
4778 _(src_address)                                  \
4779 _(dst_address)                                  \
4780 _(tos)                                          \
4781 _(length)                                       \
4782 _(fragment_id)                                  \
4783 _(ttl)                                          \
4784 _(protocol)                                     \
4785 _(checksum)
4786
4787 typedef struct
4788 {
4789   u16 src_port, dst_port;
4790 } tcpudp_header_t;
4791
4792 #if VPP_API_TEST_BUILTIN == 0
4793 uword
4794 unformat_tcp_mask (unformat_input_t * input, va_list * args)
4795 {
4796   u8 **maskp = va_arg (*args, u8 **);
4797   u8 *mask = 0;
4798   u8 found_something = 0;
4799   tcp_header_t *tcp;
4800
4801 #define _(a) u8 a=0;
4802   foreach_tcp_proto_field;
4803 #undef _
4804
4805   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
4806     {
4807       if (0);
4808 #define _(a) else if (unformat (input, #a)) a=1;
4809       foreach_tcp_proto_field
4810 #undef _
4811         else
4812         break;
4813     }
4814
4815 #define _(a) found_something += a;
4816   foreach_tcp_proto_field;
4817 #undef _
4818
4819   if (found_something == 0)
4820     return 0;
4821
4822   vec_validate (mask, sizeof (*tcp) - 1);
4823
4824   tcp = (tcp_header_t *) mask;
4825
4826 #define _(a) if (a) clib_memset (&tcp->a, 0xff, sizeof (tcp->a));
4827   foreach_tcp_proto_field;
4828 #undef _
4829
4830   *maskp = mask;
4831   return 1;
4832 }
4833
4834 uword
4835 unformat_udp_mask (unformat_input_t * input, va_list * args)
4836 {
4837   u8 **maskp = va_arg (*args, u8 **);
4838   u8 *mask = 0;
4839   u8 found_something = 0;
4840   udp_header_t *udp;
4841
4842 #define _(a) u8 a=0;
4843   foreach_udp_proto_field;
4844 #undef _
4845
4846   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
4847     {
4848       if (0);
4849 #define _(a) else if (unformat (input, #a)) a=1;
4850       foreach_udp_proto_field
4851 #undef _
4852         else
4853         break;
4854     }
4855
4856 #define _(a) found_something += a;
4857   foreach_udp_proto_field;
4858 #undef _
4859
4860   if (found_something == 0)
4861     return 0;
4862
4863   vec_validate (mask, sizeof (*udp) - 1);
4864
4865   udp = (udp_header_t *) mask;
4866
4867 #define _(a) if (a) clib_memset (&udp->a, 0xff, sizeof (udp->a));
4868   foreach_udp_proto_field;
4869 #undef _
4870
4871   *maskp = mask;
4872   return 1;
4873 }
4874
4875 uword
4876 unformat_l4_mask (unformat_input_t * input, va_list * args)
4877 {
4878   u8 **maskp = va_arg (*args, u8 **);
4879   u16 src_port = 0, dst_port = 0;
4880   tcpudp_header_t *tcpudp;
4881
4882   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
4883     {
4884       if (unformat (input, "tcp %U", unformat_tcp_mask, maskp))
4885         return 1;
4886       else if (unformat (input, "udp %U", unformat_udp_mask, maskp))
4887         return 1;
4888       else if (unformat (input, "src_port"))
4889         src_port = 0xFFFF;
4890       else if (unformat (input, "dst_port"))
4891         dst_port = 0xFFFF;
4892       else
4893         return 0;
4894     }
4895
4896   if (!src_port && !dst_port)
4897     return 0;
4898
4899   u8 *mask = 0;
4900   vec_validate (mask, sizeof (tcpudp_header_t) - 1);
4901
4902   tcpudp = (tcpudp_header_t *) mask;
4903   tcpudp->src_port = src_port;
4904   tcpudp->dst_port = dst_port;
4905
4906   *maskp = mask;
4907
4908   return 1;
4909 }
4910
4911 uword
4912 unformat_ip4_mask (unformat_input_t * input, va_list * args)
4913 {
4914   u8 **maskp = va_arg (*args, u8 **);
4915   u8 *mask = 0;
4916   u8 found_something = 0;
4917   ip4_header_t *ip;
4918
4919 #define _(a) u8 a=0;
4920   foreach_ip4_proto_field;
4921 #undef _
4922   u8 version = 0;
4923   u8 hdr_length = 0;
4924
4925
4926   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
4927     {
4928       if (unformat (input, "version"))
4929         version = 1;
4930       else if (unformat (input, "hdr_length"))
4931         hdr_length = 1;
4932       else if (unformat (input, "src"))
4933         src_address = 1;
4934       else if (unformat (input, "dst"))
4935         dst_address = 1;
4936       else if (unformat (input, "proto"))
4937         protocol = 1;
4938
4939 #define _(a) else if (unformat (input, #a)) a=1;
4940       foreach_ip4_proto_field
4941 #undef _
4942         else
4943         break;
4944     }
4945
4946 #define _(a) found_something += a;
4947   foreach_ip4_proto_field;
4948 #undef _
4949
4950   if (found_something == 0)
4951     return 0;
4952
4953   vec_validate (mask, sizeof (*ip) - 1);
4954
4955   ip = (ip4_header_t *) mask;
4956
4957 #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
4958   foreach_ip4_proto_field;
4959 #undef _
4960
4961   ip->ip_version_and_header_length = 0;
4962
4963   if (version)
4964     ip->ip_version_and_header_length |= 0xF0;
4965
4966   if (hdr_length)
4967     ip->ip_version_and_header_length |= 0x0F;
4968
4969   *maskp = mask;
4970   return 1;
4971 }
4972
4973 #define foreach_ip6_proto_field                 \
4974 _(src_address)                                  \
4975 _(dst_address)                                  \
4976 _(payload_length)                               \
4977 _(hop_limit)                                    \
4978 _(protocol)
4979
4980 uword
4981 unformat_ip6_mask (unformat_input_t * input, va_list * args)
4982 {
4983   u8 **maskp = va_arg (*args, u8 **);
4984   u8 *mask = 0;
4985   u8 found_something = 0;
4986   ip6_header_t *ip;
4987   u32 ip_version_traffic_class_and_flow_label;
4988
4989 #define _(a) u8 a=0;
4990   foreach_ip6_proto_field;
4991 #undef _
4992   u8 version = 0;
4993   u8 traffic_class = 0;
4994   u8 flow_label = 0;
4995
4996   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
4997     {
4998       if (unformat (input, "version"))
4999         version = 1;
5000       else if (unformat (input, "traffic-class"))
5001         traffic_class = 1;
5002       else if (unformat (input, "flow-label"))
5003         flow_label = 1;
5004       else if (unformat (input, "src"))
5005         src_address = 1;
5006       else if (unformat (input, "dst"))
5007         dst_address = 1;
5008       else if (unformat (input, "proto"))
5009         protocol = 1;
5010
5011 #define _(a) else if (unformat (input, #a)) a=1;
5012       foreach_ip6_proto_field
5013 #undef _
5014         else
5015         break;
5016     }
5017
5018 #define _(a) found_something += a;
5019   foreach_ip6_proto_field;
5020 #undef _
5021
5022   if (found_something == 0)
5023     return 0;
5024
5025   vec_validate (mask, sizeof (*ip) - 1);
5026
5027   ip = (ip6_header_t *) mask;
5028
5029 #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
5030   foreach_ip6_proto_field;
5031 #undef _
5032
5033   ip_version_traffic_class_and_flow_label = 0;
5034
5035   if (version)
5036     ip_version_traffic_class_and_flow_label |= 0xF0000000;
5037
5038   if (traffic_class)
5039     ip_version_traffic_class_and_flow_label |= 0x0FF00000;
5040
5041   if (flow_label)
5042     ip_version_traffic_class_and_flow_label |= 0x000FFFFF;
5043
5044   ip->ip_version_traffic_class_and_flow_label =
5045     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
5046
5047   *maskp = mask;
5048   return 1;
5049 }
5050
5051 uword
5052 unformat_l3_mask (unformat_input_t * input, va_list * args)
5053 {
5054   u8 **maskp = va_arg (*args, u8 **);
5055
5056   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5057     {
5058       if (unformat (input, "ip4 %U", unformat_ip4_mask, maskp))
5059         return 1;
5060       else if (unformat (input, "ip6 %U", unformat_ip6_mask, maskp))
5061         return 1;
5062       else
5063         break;
5064     }
5065   return 0;
5066 }
5067
5068 uword
5069 unformat_l2_mask (unformat_input_t * input, va_list * args)
5070 {
5071   u8 **maskp = va_arg (*args, u8 **);
5072   u8 *mask = 0;
5073   u8 src = 0;
5074   u8 dst = 0;
5075   u8 proto = 0;
5076   u8 tag1 = 0;
5077   u8 tag2 = 0;
5078   u8 ignore_tag1 = 0;
5079   u8 ignore_tag2 = 0;
5080   u8 cos1 = 0;
5081   u8 cos2 = 0;
5082   u8 dot1q = 0;
5083   u8 dot1ad = 0;
5084   int len = 14;
5085
5086   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5087     {
5088       if (unformat (input, "src"))
5089         src = 1;
5090       else if (unformat (input, "dst"))
5091         dst = 1;
5092       else if (unformat (input, "proto"))
5093         proto = 1;
5094       else if (unformat (input, "tag1"))
5095         tag1 = 1;
5096       else if (unformat (input, "tag2"))
5097         tag2 = 1;
5098       else if (unformat (input, "ignore-tag1"))
5099         ignore_tag1 = 1;
5100       else if (unformat (input, "ignore-tag2"))
5101         ignore_tag2 = 1;
5102       else if (unformat (input, "cos1"))
5103         cos1 = 1;
5104       else if (unformat (input, "cos2"))
5105         cos2 = 1;
5106       else if (unformat (input, "dot1q"))
5107         dot1q = 1;
5108       else if (unformat (input, "dot1ad"))
5109         dot1ad = 1;
5110       else
5111         break;
5112     }
5113   if ((src + dst + proto + tag1 + tag2 + dot1q + dot1ad +
5114        ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
5115     return 0;
5116
5117   if (tag1 || ignore_tag1 || cos1 || dot1q)
5118     len = 18;
5119   if (tag2 || ignore_tag2 || cos2 || dot1ad)
5120     len = 22;
5121
5122   vec_validate (mask, len - 1);
5123
5124   if (dst)
5125     clib_memset (mask, 0xff, 6);
5126
5127   if (src)
5128     clib_memset (mask + 6, 0xff, 6);
5129
5130   if (tag2 || dot1ad)
5131     {
5132       /* inner vlan tag */
5133       if (tag2)
5134         {
5135           mask[19] = 0xff;
5136           mask[18] = 0x0f;
5137         }
5138       if (cos2)
5139         mask[18] |= 0xe0;
5140       if (proto)
5141         mask[21] = mask[20] = 0xff;
5142       if (tag1)
5143         {
5144           mask[15] = 0xff;
5145           mask[14] = 0x0f;
5146         }
5147       if (cos1)
5148         mask[14] |= 0xe0;
5149       *maskp = mask;
5150       return 1;
5151     }
5152   if (tag1 | dot1q)
5153     {
5154       if (tag1)
5155         {
5156           mask[15] = 0xff;
5157           mask[14] = 0x0f;
5158         }
5159       if (cos1)
5160         mask[14] |= 0xe0;
5161       if (proto)
5162         mask[16] = mask[17] = 0xff;
5163
5164       *maskp = mask;
5165       return 1;
5166     }
5167   if (cos2)
5168     mask[18] |= 0xe0;
5169   if (cos1)
5170     mask[14] |= 0xe0;
5171   if (proto)
5172     mask[12] = mask[13] = 0xff;
5173
5174   *maskp = mask;
5175   return 1;
5176 }
5177
5178 uword
5179 unformat_classify_mask (unformat_input_t * input, va_list * args)
5180 {
5181   u8 **maskp = va_arg (*args, u8 **);
5182   u32 *skipp = va_arg (*args, u32 *);
5183   u32 *matchp = va_arg (*args, u32 *);
5184   u32 match;
5185   u8 *mask = 0;
5186   u8 *l2 = 0;
5187   u8 *l3 = 0;
5188   u8 *l4 = 0;
5189   int i;
5190
5191   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5192     {
5193       if (unformat (input, "hex %U", unformat_hex_string, &mask))
5194         ;
5195       else if (unformat (input, "l2 %U", unformat_l2_mask, &l2))
5196         ;
5197       else if (unformat (input, "l3 %U", unformat_l3_mask, &l3))
5198         ;
5199       else if (unformat (input, "l4 %U", unformat_l4_mask, &l4))
5200         ;
5201       else
5202         break;
5203     }
5204
5205   if (l4 && !l3)
5206     {
5207       vec_free (mask);
5208       vec_free (l2);
5209       vec_free (l4);
5210       return 0;
5211     }
5212
5213   if (mask || l2 || l3 || l4)
5214     {
5215       if (l2 || l3 || l4)
5216         {
5217           /* "With a free Ethernet header in every package" */
5218           if (l2 == 0)
5219             vec_validate (l2, 13);
5220           mask = l2;
5221           if (vec_len (l3))
5222             {
5223               vec_append (mask, l3);
5224               vec_free (l3);
5225             }
5226           if (vec_len (l4))
5227             {
5228               vec_append (mask, l4);
5229               vec_free (l4);
5230             }
5231         }
5232
5233       /* Scan forward looking for the first significant mask octet */
5234       for (i = 0; i < vec_len (mask); i++)
5235         if (mask[i])
5236           break;
5237
5238       /* compute (skip, match) params */
5239       *skipp = i / sizeof (u32x4);
5240       vec_delete (mask, *skipp * sizeof (u32x4), 0);
5241
5242       /* Pad mask to an even multiple of the vector size */
5243       while (vec_len (mask) % sizeof (u32x4))
5244         vec_add1 (mask, 0);
5245
5246       match = vec_len (mask) / sizeof (u32x4);
5247
5248       for (i = match * sizeof (u32x4); i > 0; i -= sizeof (u32x4))
5249         {
5250           u64 *tmp = (u64 *) (mask + (i - sizeof (u32x4)));
5251           if (*tmp || *(tmp + 1))
5252             break;
5253           match--;
5254         }
5255       if (match == 0)
5256         clib_warning ("BUG: match 0");
5257
5258       _vec_len (mask) = match * sizeof (u32x4);
5259
5260       *matchp = match;
5261       *maskp = mask;
5262
5263       return 1;
5264     }
5265
5266   return 0;
5267 }
5268 #endif /* VPP_API_TEST_BUILTIN */
5269
5270 #define foreach_l2_next                         \
5271 _(drop, DROP)                                   \
5272 _(ethernet, ETHERNET_INPUT)                     \
5273 _(ip4, IP4_INPUT)                               \
5274 _(ip6, IP6_INPUT)
5275
5276 uword
5277 unformat_l2_next_index (unformat_input_t * input, va_list * args)
5278 {
5279   u32 *miss_next_indexp = va_arg (*args, u32 *);
5280   u32 next_index = 0;
5281   u32 tmp;
5282
5283 #define _(n,N) \
5284   if (unformat (input, #n)) { next_index = L2_INPUT_CLASSIFY_NEXT_##N; goto out;}
5285   foreach_l2_next;
5286 #undef _
5287
5288   if (unformat (input, "%d", &tmp))
5289     {
5290       next_index = tmp;
5291       goto out;
5292     }
5293
5294   return 0;
5295
5296 out:
5297   *miss_next_indexp = next_index;
5298   return 1;
5299 }
5300
5301 #define foreach_ip_next                         \
5302 _(drop, DROP)                                   \
5303 _(local, LOCAL)                                 \
5304 _(rewrite, REWRITE)
5305
5306 uword
5307 api_unformat_ip_next_index (unformat_input_t * input, va_list * args)
5308 {
5309   u32 *miss_next_indexp = va_arg (*args, u32 *);
5310   u32 next_index = 0;
5311   u32 tmp;
5312
5313 #define _(n,N) \
5314   if (unformat (input, #n)) { next_index = IP_LOOKUP_NEXT_##N; goto out;}
5315   foreach_ip_next;
5316 #undef _
5317
5318   if (unformat (input, "%d", &tmp))
5319     {
5320       next_index = tmp;
5321       goto out;
5322     }
5323
5324   return 0;
5325
5326 out:
5327   *miss_next_indexp = next_index;
5328   return 1;
5329 }
5330
5331 #define foreach_acl_next                        \
5332 _(deny, DENY)
5333
5334 uword
5335 api_unformat_acl_next_index (unformat_input_t * input, va_list * args)
5336 {
5337   u32 *miss_next_indexp = va_arg (*args, u32 *);
5338   u32 next_index = 0;
5339   u32 tmp;
5340
5341 #define _(n,N) \
5342   if (unformat (input, #n)) { next_index = ACL_NEXT_INDEX_##N; goto out;}
5343   foreach_acl_next;
5344 #undef _
5345
5346   if (unformat (input, "permit"))
5347     {
5348       next_index = ~0;
5349       goto out;
5350     }
5351   else if (unformat (input, "%d", &tmp))
5352     {
5353       next_index = tmp;
5354       goto out;
5355     }
5356
5357   return 0;
5358
5359 out:
5360   *miss_next_indexp = next_index;
5361   return 1;
5362 }
5363
5364 uword
5365 unformat_policer_precolor (unformat_input_t * input, va_list * args)
5366 {
5367   u32 *r = va_arg (*args, u32 *);
5368
5369   if (unformat (input, "conform-color"))
5370     *r = POLICE_CONFORM;
5371   else if (unformat (input, "exceed-color"))
5372     *r = POLICE_EXCEED;
5373   else
5374     return 0;
5375
5376   return 1;
5377 }
5378
5379 #if VPP_API_TEST_BUILTIN == 0
5380 uword
5381 unformat_l4_match (unformat_input_t * input, va_list * args)
5382 {
5383   u8 **matchp = va_arg (*args, u8 **);
5384
5385   u8 *proto_header = 0;
5386   int src_port = 0;
5387   int dst_port = 0;
5388
5389   tcpudp_header_t h;
5390
5391   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5392     {
5393       if (unformat (input, "src_port %d", &src_port))
5394         ;
5395       else if (unformat (input, "dst_port %d", &dst_port))
5396         ;
5397       else
5398         return 0;
5399     }
5400
5401   h.src_port = clib_host_to_net_u16 (src_port);
5402   h.dst_port = clib_host_to_net_u16 (dst_port);
5403   vec_validate (proto_header, sizeof (h) - 1);
5404   memcpy (proto_header, &h, sizeof (h));
5405
5406   *matchp = proto_header;
5407
5408   return 1;
5409 }
5410
5411 uword
5412 unformat_ip4_match (unformat_input_t * input, va_list * args)
5413 {
5414   u8 **matchp = va_arg (*args, u8 **);
5415   u8 *match = 0;
5416   ip4_header_t *ip;
5417   int version = 0;
5418   u32 version_val;
5419   int hdr_length = 0;
5420   u32 hdr_length_val;
5421   int src = 0, dst = 0;
5422   ip4_address_t src_val, dst_val;
5423   int proto = 0;
5424   u32 proto_val;
5425   int tos = 0;
5426   u32 tos_val;
5427   int length = 0;
5428   u32 length_val;
5429   int fragment_id = 0;
5430   u32 fragment_id_val;
5431   int ttl = 0;
5432   int ttl_val;
5433   int checksum = 0;
5434   u32 checksum_val;
5435
5436   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5437     {
5438       if (unformat (input, "version %d", &version_val))
5439         version = 1;
5440       else if (unformat (input, "hdr_length %d", &hdr_length_val))
5441         hdr_length = 1;
5442       else if (unformat (input, "src %U", unformat_ip4_address, &src_val))
5443         src = 1;
5444       else if (unformat (input, "dst %U", unformat_ip4_address, &dst_val))
5445         dst = 1;
5446       else if (unformat (input, "proto %d", &proto_val))
5447         proto = 1;
5448       else if (unformat (input, "tos %d", &tos_val))
5449         tos = 1;
5450       else if (unformat (input, "length %d", &length_val))
5451         length = 1;
5452       else if (unformat (input, "fragment_id %d", &fragment_id_val))
5453         fragment_id = 1;
5454       else if (unformat (input, "ttl %d", &ttl_val))
5455         ttl = 1;
5456       else if (unformat (input, "checksum %d", &checksum_val))
5457         checksum = 1;
5458       else
5459         break;
5460     }
5461
5462   if (version + hdr_length + src + dst + proto + tos + length + fragment_id
5463       + ttl + checksum == 0)
5464     return 0;
5465
5466   /*
5467    * Aligned because we use the real comparison functions
5468    */
5469   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
5470
5471   ip = (ip4_header_t *) match;
5472
5473   /* These are realistically matched in practice */
5474   if (src)
5475     ip->src_address.as_u32 = src_val.as_u32;
5476
5477   if (dst)
5478     ip->dst_address.as_u32 = dst_val.as_u32;
5479
5480   if (proto)
5481     ip->protocol = proto_val;
5482
5483
5484   /* These are not, but they're included for completeness */
5485   if (version)
5486     ip->ip_version_and_header_length |= (version_val & 0xF) << 4;
5487
5488   if (hdr_length)
5489     ip->ip_version_and_header_length |= (hdr_length_val & 0xF);
5490
5491   if (tos)
5492     ip->tos = tos_val;
5493
5494   if (length)
5495     ip->length = clib_host_to_net_u16 (length_val);
5496
5497   if (ttl)
5498     ip->ttl = ttl_val;
5499
5500   if (checksum)
5501     ip->checksum = clib_host_to_net_u16 (checksum_val);
5502
5503   *matchp = match;
5504   return 1;
5505 }
5506
5507 uword
5508 unformat_ip6_match (unformat_input_t * input, va_list * args)
5509 {
5510   u8 **matchp = va_arg (*args, u8 **);
5511   u8 *match = 0;
5512   ip6_header_t *ip;
5513   int version = 0;
5514   u32 version_val;
5515   u8 traffic_class = 0;
5516   u32 traffic_class_val = 0;
5517   u8 flow_label = 0;
5518   u8 flow_label_val;
5519   int src = 0, dst = 0;
5520   ip6_address_t src_val, dst_val;
5521   int proto = 0;
5522   u32 proto_val;
5523   int payload_length = 0;
5524   u32 payload_length_val;
5525   int hop_limit = 0;
5526   int hop_limit_val;
5527   u32 ip_version_traffic_class_and_flow_label;
5528
5529   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5530     {
5531       if (unformat (input, "version %d", &version_val))
5532         version = 1;
5533       else if (unformat (input, "traffic_class %d", &traffic_class_val))
5534         traffic_class = 1;
5535       else if (unformat (input, "flow_label %d", &flow_label_val))
5536         flow_label = 1;
5537       else if (unformat (input, "src %U", unformat_ip6_address, &src_val))
5538         src = 1;
5539       else if (unformat (input, "dst %U", unformat_ip6_address, &dst_val))
5540         dst = 1;
5541       else if (unformat (input, "proto %d", &proto_val))
5542         proto = 1;
5543       else if (unformat (input, "payload_length %d", &payload_length_val))
5544         payload_length = 1;
5545       else if (unformat (input, "hop_limit %d", &hop_limit_val))
5546         hop_limit = 1;
5547       else
5548         break;
5549     }
5550
5551   if (version + traffic_class + flow_label + src + dst + proto +
5552       payload_length + hop_limit == 0)
5553     return 0;
5554
5555   /*
5556    * Aligned because we use the real comparison functions
5557    */
5558   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
5559
5560   ip = (ip6_header_t *) match;
5561
5562   if (src)
5563     clib_memcpy (&ip->src_address, &src_val, sizeof (ip->src_address));
5564
5565   if (dst)
5566     clib_memcpy (&ip->dst_address, &dst_val, sizeof (ip->dst_address));
5567
5568   if (proto)
5569     ip->protocol = proto_val;
5570
5571   ip_version_traffic_class_and_flow_label = 0;
5572
5573   if (version)
5574     ip_version_traffic_class_and_flow_label |= (version_val & 0xF) << 28;
5575
5576   if (traffic_class)
5577     ip_version_traffic_class_and_flow_label |=
5578       (traffic_class_val & 0xFF) << 20;
5579
5580   if (flow_label)
5581     ip_version_traffic_class_and_flow_label |= (flow_label_val & 0xFFFFF);
5582
5583   ip->ip_version_traffic_class_and_flow_label =
5584     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
5585
5586   if (payload_length)
5587     ip->payload_length = clib_host_to_net_u16 (payload_length_val);
5588
5589   if (hop_limit)
5590     ip->hop_limit = hop_limit_val;
5591
5592   *matchp = match;
5593   return 1;
5594 }
5595
5596 uword
5597 unformat_l3_match (unformat_input_t * input, va_list * args)
5598 {
5599   u8 **matchp = va_arg (*args, u8 **);
5600
5601   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5602     {
5603       if (unformat (input, "ip4 %U", unformat_ip4_match, matchp))
5604         return 1;
5605       else if (unformat (input, "ip6 %U", unformat_ip6_match, matchp))
5606         return 1;
5607       else
5608         break;
5609     }
5610   return 0;
5611 }
5612
5613 uword
5614 unformat_vlan_tag (unformat_input_t * input, va_list * args)
5615 {
5616   u8 *tagp = va_arg (*args, u8 *);
5617   u32 tag;
5618
5619   if (unformat (input, "%d", &tag))
5620     {
5621       tagp[0] = (tag >> 8) & 0x0F;
5622       tagp[1] = tag & 0xFF;
5623       return 1;
5624     }
5625
5626   return 0;
5627 }
5628
5629 uword
5630 unformat_l2_match (unformat_input_t * input, va_list * args)
5631 {
5632   u8 **matchp = va_arg (*args, u8 **);
5633   u8 *match = 0;
5634   u8 src = 0;
5635   u8 src_val[6];
5636   u8 dst = 0;
5637   u8 dst_val[6];
5638   u8 proto = 0;
5639   u16 proto_val;
5640   u8 tag1 = 0;
5641   u8 tag1_val[2];
5642   u8 tag2 = 0;
5643   u8 tag2_val[2];
5644   int len = 14;
5645   u8 ignore_tag1 = 0;
5646   u8 ignore_tag2 = 0;
5647   u8 cos1 = 0;
5648   u8 cos2 = 0;
5649   u32 cos1_val = 0;
5650   u32 cos2_val = 0;
5651
5652   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5653     {
5654       if (unformat (input, "src %U", unformat_ethernet_address, &src_val))
5655         src = 1;
5656       else
5657         if (unformat (input, "dst %U", unformat_ethernet_address, &dst_val))
5658         dst = 1;
5659       else if (unformat (input, "proto %U",
5660                          unformat_ethernet_type_host_byte_order, &proto_val))
5661         proto = 1;
5662       else if (unformat (input, "tag1 %U", unformat_vlan_tag, tag1_val))
5663         tag1 = 1;
5664       else if (unformat (input, "tag2 %U", unformat_vlan_tag, tag2_val))
5665         tag2 = 1;
5666       else if (unformat (input, "ignore-tag1"))
5667         ignore_tag1 = 1;
5668       else if (unformat (input, "ignore-tag2"))
5669         ignore_tag2 = 1;
5670       else if (unformat (input, "cos1 %d", &cos1_val))
5671         cos1 = 1;
5672       else if (unformat (input, "cos2 %d", &cos2_val))
5673         cos2 = 1;
5674       else
5675         break;
5676     }
5677   if ((src + dst + proto + tag1 + tag2 +
5678        ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
5679     return 0;
5680
5681   if (tag1 || ignore_tag1 || cos1)
5682     len = 18;
5683   if (tag2 || ignore_tag2 || cos2)
5684     len = 22;
5685
5686   vec_validate_aligned (match, len - 1, sizeof (u32x4));
5687
5688   if (dst)
5689     clib_memcpy (match, dst_val, 6);
5690
5691   if (src)
5692     clib_memcpy (match + 6, src_val, 6);
5693
5694   if (tag2)
5695     {
5696       /* inner vlan tag */
5697       match[19] = tag2_val[1];
5698       match[18] = tag2_val[0];
5699       if (cos2)
5700         match[18] |= (cos2_val & 0x7) << 5;
5701       if (proto)
5702         {
5703           match[21] = proto_val & 0xff;
5704           match[20] = proto_val >> 8;
5705         }
5706       if (tag1)
5707         {
5708           match[15] = tag1_val[1];
5709           match[14] = tag1_val[0];
5710         }
5711       if (cos1)
5712         match[14] |= (cos1_val & 0x7) << 5;
5713       *matchp = match;
5714       return 1;
5715     }
5716   if (tag1)
5717     {
5718       match[15] = tag1_val[1];
5719       match[14] = tag1_val[0];
5720       if (proto)
5721         {
5722           match[17] = proto_val & 0xff;
5723           match[16] = proto_val >> 8;
5724         }
5725       if (cos1)
5726         match[14] |= (cos1_val & 0x7) << 5;
5727
5728       *matchp = match;
5729       return 1;
5730     }
5731   if (cos2)
5732     match[18] |= (cos2_val & 0x7) << 5;
5733   if (cos1)
5734     match[14] |= (cos1_val & 0x7) << 5;
5735   if (proto)
5736     {
5737       match[13] = proto_val & 0xff;
5738       match[12] = proto_val >> 8;
5739     }
5740
5741   *matchp = match;
5742   return 1;
5743 }
5744
5745 uword
5746 unformat_qos_source (unformat_input_t * input, va_list * args)
5747 {
5748   int *qs = va_arg (*args, int *);
5749
5750   if (unformat (input, "ip"))
5751     *qs = QOS_SOURCE_IP;
5752   else if (unformat (input, "mpls"))
5753     *qs = QOS_SOURCE_MPLS;
5754   else if (unformat (input, "ext"))
5755     *qs = QOS_SOURCE_EXT;
5756   else if (unformat (input, "vlan"))
5757     *qs = QOS_SOURCE_VLAN;
5758   else
5759     return 0;
5760
5761   return 1;
5762 }
5763 #endif
5764
5765 uword
5766 api_unformat_classify_match (unformat_input_t * input, va_list * args)
5767 {
5768   u8 **matchp = va_arg (*args, u8 **);
5769   u32 skip_n_vectors = va_arg (*args, u32);
5770   u32 match_n_vectors = va_arg (*args, u32);
5771
5772   u8 *match = 0;
5773   u8 *l2 = 0;
5774   u8 *l3 = 0;
5775   u8 *l4 = 0;
5776
5777   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5778     {
5779       if (unformat (input, "hex %U", unformat_hex_string, &match))
5780         ;
5781       else if (unformat (input, "l2 %U", unformat_l2_match, &l2))
5782         ;
5783       else if (unformat (input, "l3 %U", unformat_l3_match, &l3))
5784         ;
5785       else if (unformat (input, "l4 %U", unformat_l4_match, &l4))
5786         ;
5787       else
5788         break;
5789     }
5790
5791   if (l4 && !l3)
5792     {
5793       vec_free (match);
5794       vec_free (l2);
5795       vec_free (l4);
5796       return 0;
5797     }
5798
5799   if (match || l2 || l3 || l4)
5800     {
5801       if (l2 || l3 || l4)
5802         {
5803           /* "Win a free Ethernet header in every packet" */
5804           if (l2 == 0)
5805             vec_validate_aligned (l2, 13, sizeof (u32x4));
5806           match = l2;
5807           if (vec_len (l3))
5808             {
5809               vec_append_aligned (match, l3, sizeof (u32x4));
5810               vec_free (l3);
5811             }
5812           if (vec_len (l4))
5813             {
5814               vec_append_aligned (match, l4, sizeof (u32x4));
5815               vec_free (l4);
5816             }
5817         }
5818
5819       /* Make sure the vector is big enough even if key is all 0's */
5820       vec_validate_aligned
5821         (match, ((match_n_vectors + skip_n_vectors) * sizeof (u32x4)) - 1,
5822          sizeof (u32x4));
5823
5824       /* Set size, include skipped vectors */
5825       _vec_len (match) = (match_n_vectors + skip_n_vectors) * sizeof (u32x4);
5826
5827       *matchp = match;
5828
5829       return 1;
5830     }
5831
5832   return 0;
5833 }
5834
5835 static int
5836 api_get_node_index (vat_main_t * vam)
5837 {
5838   unformat_input_t *i = vam->input;
5839   vl_api_get_node_index_t *mp;
5840   u8 *name = 0;
5841   int ret;
5842
5843   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5844     {
5845       if (unformat (i, "node %s", &name))
5846         ;
5847       else
5848         break;
5849     }
5850   if (name == 0)
5851     {
5852       errmsg ("node name required");
5853       return -99;
5854     }
5855   if (vec_len (name) >= ARRAY_LEN (mp->node_name))
5856     {
5857       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
5858       return -99;
5859     }
5860
5861   M (GET_NODE_INDEX, mp);
5862   clib_memcpy (mp->node_name, name, vec_len (name));
5863   vec_free (name);
5864
5865   S (mp);
5866   W (ret);
5867   return ret;
5868 }
5869
5870 static int
5871 api_get_next_index (vat_main_t * vam)
5872 {
5873   unformat_input_t *i = vam->input;
5874   vl_api_get_next_index_t *mp;
5875   u8 *node_name = 0, *next_node_name = 0;
5876   int ret;
5877
5878   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5879     {
5880       if (unformat (i, "node-name %s", &node_name))
5881         ;
5882       else if (unformat (i, "next-node-name %s", &next_node_name))
5883         break;
5884     }
5885
5886   if (node_name == 0)
5887     {
5888       errmsg ("node name required");
5889       return -99;
5890     }
5891   if (vec_len (node_name) >= ARRAY_LEN (mp->node_name))
5892     {
5893       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
5894       return -99;
5895     }
5896
5897   if (next_node_name == 0)
5898     {
5899       errmsg ("next node name required");
5900       return -99;
5901     }
5902   if (vec_len (next_node_name) >= ARRAY_LEN (mp->next_name))
5903     {
5904       errmsg ("next node name too long, max %d", ARRAY_LEN (mp->next_name));
5905       return -99;
5906     }
5907
5908   M (GET_NEXT_INDEX, mp);
5909   clib_memcpy (mp->node_name, node_name, vec_len (node_name));
5910   clib_memcpy (mp->next_name, next_node_name, vec_len (next_node_name));
5911   vec_free (node_name);
5912   vec_free (next_node_name);
5913
5914   S (mp);
5915   W (ret);
5916   return ret;
5917 }
5918
5919 static int
5920 api_add_node_next (vat_main_t * vam)
5921 {
5922   unformat_input_t *i = vam->input;
5923   vl_api_add_node_next_t *mp;
5924   u8 *name = 0;
5925   u8 *next = 0;
5926   int ret;
5927
5928   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5929     {
5930       if (unformat (i, "node %s", &name))
5931         ;
5932       else if (unformat (i, "next %s", &next))
5933         ;
5934       else
5935         break;
5936     }
5937   if (name == 0)
5938     {
5939       errmsg ("node name required");
5940       return -99;
5941     }
5942   if (vec_len (name) >= ARRAY_LEN (mp->node_name))
5943     {
5944       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
5945       return -99;
5946     }
5947   if (next == 0)
5948     {
5949       errmsg ("next node required");
5950       return -99;
5951     }
5952   if (vec_len (next) >= ARRAY_LEN (mp->next_name))
5953     {
5954       errmsg ("next name too long, max %d", ARRAY_LEN (mp->next_name));
5955       return -99;
5956     }
5957
5958   M (ADD_NODE_NEXT, mp);
5959   clib_memcpy (mp->node_name, name, vec_len (name));
5960   clib_memcpy (mp->next_name, next, vec_len (next));
5961   vec_free (name);
5962   vec_free (next);
5963
5964   S (mp);
5965   W (ret);
5966   return ret;
5967 }
5968
5969 static void vl_api_sw_interface_virtio_pci_details_t_handler
5970   (vl_api_sw_interface_virtio_pci_details_t * mp)
5971 {
5972   vat_main_t *vam = &vat_main;
5973
5974   typedef union
5975   {
5976     struct
5977     {
5978       u16 domain;
5979       u8 bus;
5980       u8 slot:5;
5981       u8 function:3;
5982     };
5983     u32 as_u32;
5984   } pci_addr_t;
5985   pci_addr_t addr;
5986
5987   addr.domain = ntohs (mp->pci_addr.domain);
5988   addr.bus = mp->pci_addr.bus;
5989   addr.slot = mp->pci_addr.slot;
5990   addr.function = mp->pci_addr.function;
5991
5992   u8 *pci_addr = format (0, "%04x:%02x:%02x.%x", addr.domain, addr.bus,
5993                          addr.slot, addr.function);
5994
5995   print (vam->ofp,
5996          "\n%-12s %-12d %-12d %-12d %-17U 0x%-08llx",
5997          pci_addr, ntohl (mp->sw_if_index),
5998          ntohs (mp->rx_ring_sz), ntohs (mp->tx_ring_sz),
5999          format_ethernet_address, mp->mac_addr,
6000          clib_net_to_host_u64 (mp->features));
6001   vec_free (pci_addr);
6002 }
6003
6004 static void vl_api_sw_interface_virtio_pci_details_t_handler_json
6005   (vl_api_sw_interface_virtio_pci_details_t * mp)
6006 {
6007   vat_main_t *vam = &vat_main;
6008   vat_json_node_t *node = NULL;
6009   vlib_pci_addr_t pci_addr;
6010
6011   if (VAT_JSON_ARRAY != vam->json_tree.type)
6012     {
6013       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
6014       vat_json_init_array (&vam->json_tree);
6015     }
6016   node = vat_json_array_add (&vam->json_tree);
6017
6018   pci_addr.domain = ntohs (mp->pci_addr.domain);
6019   pci_addr.bus = mp->pci_addr.bus;
6020   pci_addr.slot = mp->pci_addr.slot;
6021   pci_addr.function = mp->pci_addr.function;
6022
6023   vat_json_init_object (node);
6024   vat_json_object_add_uint (node, "pci-addr", pci_addr.as_u32);
6025   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
6026   vat_json_object_add_uint (node, "rx_ring_sz", ntohs (mp->rx_ring_sz));
6027   vat_json_object_add_uint (node, "tx_ring_sz", ntohs (mp->tx_ring_sz));
6028   vat_json_object_add_uint (node, "features",
6029                             clib_net_to_host_u64 (mp->features));
6030   vat_json_object_add_string_copy (node, "mac_addr",
6031                                    format (0, "%U", format_ethernet_address,
6032                                            &mp->mac_addr));
6033 }
6034
6035 static int
6036 api_sw_interface_virtio_pci_dump (vat_main_t * vam)
6037 {
6038   vl_api_sw_interface_virtio_pci_dump_t *mp;
6039   vl_api_control_ping_t *mp_ping;
6040   int ret;
6041
6042   print (vam->ofp,
6043          "\n%-12s %-12s %-12s %-12s %-17s %-08s",
6044          "pci_addr", "sw_if_index", "rx_ring_sz", "tx_ring_sz",
6045          "mac_addr", "features");
6046
6047   /* Get list of tap interfaces */
6048   M (SW_INTERFACE_VIRTIO_PCI_DUMP, mp);
6049   S (mp);
6050
6051   /* Use a control ping for synchronization */
6052   MPING (CONTROL_PING, mp_ping);
6053   S (mp_ping);
6054
6055   W (ret);
6056   return ret;
6057 }
6058
6059 static int
6060 api_l2_fib_clear_table (vat_main_t * vam)
6061 {
6062 //  unformat_input_t * i = vam->input;
6063   vl_api_l2_fib_clear_table_t *mp;
6064   int ret;
6065
6066   M (L2_FIB_CLEAR_TABLE, mp);
6067
6068   S (mp);
6069   W (ret);
6070   return ret;
6071 }
6072
6073 static int
6074 api_l2_interface_efp_filter (vat_main_t * vam)
6075 {
6076   unformat_input_t *i = vam->input;
6077   vl_api_l2_interface_efp_filter_t *mp;
6078   u32 sw_if_index;
6079   u8 enable = 1;
6080   u8 sw_if_index_set = 0;
6081   int ret;
6082
6083   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6084     {
6085       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
6086         sw_if_index_set = 1;
6087       else if (unformat (i, "sw_if_index %d", &sw_if_index))
6088         sw_if_index_set = 1;
6089       else if (unformat (i, "enable"))
6090         enable = 1;
6091       else if (unformat (i, "disable"))
6092         enable = 0;
6093       else
6094         {
6095           clib_warning ("parse error '%U'", format_unformat_error, i);
6096           return -99;
6097         }
6098     }
6099
6100   if (sw_if_index_set == 0)
6101     {
6102       errmsg ("missing sw_if_index");
6103       return -99;
6104     }
6105
6106   M (L2_INTERFACE_EFP_FILTER, mp);
6107
6108   mp->sw_if_index = ntohl (sw_if_index);
6109   mp->enable_disable = enable;
6110
6111   S (mp);
6112   W (ret);
6113   return ret;
6114 }
6115
6116 #define foreach_vtr_op                          \
6117 _("disable",  L2_VTR_DISABLED)                  \
6118 _("push-1",  L2_VTR_PUSH_1)                     \
6119 _("push-2",  L2_VTR_PUSH_2)                     \
6120 _("pop-1",  L2_VTR_POP_1)                       \
6121 _("pop-2",  L2_VTR_POP_2)                       \
6122 _("translate-1-1",  L2_VTR_TRANSLATE_1_1)       \
6123 _("translate-1-2",  L2_VTR_TRANSLATE_1_2)       \
6124 _("translate-2-1",  L2_VTR_TRANSLATE_2_1)       \
6125 _("translate-2-2",  L2_VTR_TRANSLATE_2_2)
6126
6127 static int
6128 api_l2_interface_vlan_tag_rewrite (vat_main_t * vam)
6129 {
6130   unformat_input_t *i = vam->input;
6131   vl_api_l2_interface_vlan_tag_rewrite_t *mp;
6132   u32 sw_if_index;
6133   u8 sw_if_index_set = 0;
6134   u8 vtr_op_set = 0;
6135   u32 vtr_op = 0;
6136   u32 push_dot1q = 1;
6137   u32 tag1 = ~0;
6138   u32 tag2 = ~0;
6139   int ret;
6140
6141   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6142     {
6143       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
6144         sw_if_index_set = 1;
6145       else if (unformat (i, "sw_if_index %d", &sw_if_index))
6146         sw_if_index_set = 1;
6147       else if (unformat (i, "vtr_op %d", &vtr_op))
6148         vtr_op_set = 1;
6149 #define _(n,v) else if (unformat(i, n)) {vtr_op = v; vtr_op_set = 1;}
6150       foreach_vtr_op
6151 #undef _
6152         else if (unformat (i, "push_dot1q %d", &push_dot1q))
6153         ;
6154       else if (unformat (i, "tag1 %d", &tag1))
6155         ;
6156       else if (unformat (i, "tag2 %d", &tag2))
6157         ;
6158       else
6159         {
6160           clib_warning ("parse error '%U'", format_unformat_error, i);
6161           return -99;
6162         }
6163     }
6164
6165   if ((sw_if_index_set == 0) || (vtr_op_set == 0))
6166     {
6167       errmsg ("missing vtr operation or sw_if_index");
6168       return -99;
6169     }
6170
6171   M (L2_INTERFACE_VLAN_TAG_REWRITE, mp);
6172   mp->sw_if_index = ntohl (sw_if_index);
6173   mp->vtr_op = ntohl (vtr_op);
6174   mp->push_dot1q = ntohl (push_dot1q);
6175   mp->tag1 = ntohl (tag1);
6176   mp->tag2 = ntohl (tag2);
6177
6178   S (mp);
6179   W (ret);
6180   return ret;
6181 }
6182
6183 static int
6184 api_show_version (vat_main_t *vam)
6185 {
6186   vl_api_show_version_t *mp;
6187   int ret;
6188
6189   M (SHOW_VERSION, mp);
6190
6191   S (mp);
6192   W (ret);
6193   return ret;
6194 }
6195
6196 static void
6197 vl_api_l2_fib_table_details_t_handler (vl_api_l2_fib_table_details_t *mp)
6198 {
6199   vat_main_t *vam = &vat_main;
6200
6201   print (vam->ofp,
6202          "%3" PRIu32 "    %U    %3" PRIu32 "       %d       %d     %d",
6203          ntohl (mp->bd_id), format_ethernet_address, mp->mac,
6204          ntohl (mp->sw_if_index), mp->static_mac, mp->filter_mac, mp->bvi_mac);
6205 }
6206
6207 static void
6208 vl_api_l2_fib_table_details_t_handler_json (vl_api_l2_fib_table_details_t *mp)
6209 {
6210   vat_main_t *vam = &vat_main;
6211   vat_json_node_t *node = NULL;
6212
6213   if (VAT_JSON_ARRAY != vam->json_tree.type)
6214     {
6215       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
6216       vat_json_init_array (&vam->json_tree);
6217     }
6218   node = vat_json_array_add (&vam->json_tree);
6219
6220   vat_json_init_object (node);
6221   vat_json_object_add_uint (node, "bd_id", ntohl (mp->bd_id));
6222   vat_json_object_add_bytes (node, "mac", mp->mac, 6);
6223   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
6224   vat_json_object_add_uint (node, "static_mac", mp->static_mac);
6225   vat_json_object_add_uint (node, "filter_mac", mp->filter_mac);
6226   vat_json_object_add_uint (node, "bvi_mac", mp->bvi_mac);
6227 }
6228
6229 static int
6230 api_l2_fib_table_dump (vat_main_t *vam)
6231 {
6232   unformat_input_t *i = vam->input;
6233   vl_api_l2_fib_table_dump_t *mp;
6234   vl_api_control_ping_t *mp_ping;
6235   u32 bd_id;
6236   u8 bd_id_set = 0;
6237   int ret;
6238
6239   /* Parse args required to build the message */
6240   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6241     {
6242       if (unformat (i, "bd_id %d", &bd_id))
6243         bd_id_set = 1;
6244       else
6245         break;
6246     }
6247
6248   if (bd_id_set == 0)
6249     {
6250       errmsg ("missing bridge domain");
6251       return -99;
6252     }
6253
6254   print (vam->ofp, "BD-ID     Mac Address      sw-ndx  Static  Filter  BVI");
6255
6256   /* Get list of l2 fib entries */
6257   M (L2_FIB_TABLE_DUMP, mp);
6258
6259   mp->bd_id = ntohl (bd_id);
6260   S (mp);
6261
6262   /* Use a control ping for synchronization */
6263   MPING (CONTROL_PING, mp_ping);
6264   S (mp_ping);
6265
6266   W (ret);
6267   return ret;
6268 }
6269
6270 static int
6271 api_interface_name_renumber (vat_main_t *vam)
6272 {
6273   unformat_input_t *line_input = vam->input;
6274   vl_api_interface_name_renumber_t *mp;
6275   u32 sw_if_index = ~0;
6276   u32 new_show_dev_instance = ~0;
6277   int ret;
6278
6279   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
6280     {
6281       if (unformat (line_input, "%U", api_unformat_sw_if_index, vam,
6282                     &sw_if_index))
6283         ;
6284       else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
6285         ;
6286       else if (unformat (line_input, "new_show_dev_instance %d",
6287                          &new_show_dev_instance))
6288         ;
6289       else
6290         break;
6291     }
6292
6293   if (sw_if_index == ~0)
6294     {
6295       errmsg ("missing interface name or sw_if_index");
6296       return -99;
6297     }
6298
6299   if (new_show_dev_instance == ~0)
6300     {
6301       errmsg ("missing new_show_dev_instance");
6302       return -99;
6303     }
6304
6305   M (INTERFACE_NAME_RENUMBER, mp);
6306
6307   mp->sw_if_index = ntohl (sw_if_index);
6308   mp->new_show_dev_instance = ntohl (new_show_dev_instance);
6309
6310   S (mp);
6311   W (ret);
6312   return ret;
6313 }
6314
6315 static int
6316 api_want_l2_macs_events (vat_main_t *vam)
6317 {
6318   unformat_input_t *line_input = vam->input;
6319   vl_api_want_l2_macs_events_t *mp;
6320   u8 enable_disable = 1;
6321   u32 scan_delay = 0;
6322   u32 max_macs_in_event = 0;
6323   u32 learn_limit = 0;
6324   int ret;
6325
6326   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
6327     {
6328       if (unformat (line_input, "learn-limit %d", &learn_limit))
6329         ;
6330       else if (unformat (line_input, "scan-delay %d", &scan_delay))
6331         ;
6332       else if (unformat (line_input, "max-entries %d", &max_macs_in_event))
6333         ;
6334       else if (unformat (line_input, "disable"))
6335         enable_disable = 0;
6336       else
6337         break;
6338     }
6339
6340   M (WANT_L2_MACS_EVENTS, mp);
6341   mp->enable_disable = enable_disable;
6342   mp->pid = htonl (getpid ());
6343   mp->learn_limit = htonl (learn_limit);
6344   mp->scan_delay = (u8) scan_delay;
6345   mp->max_macs_in_event = (u8) (max_macs_in_event / 10);
6346   S (mp);
6347   W (ret);
6348   return ret;
6349 }
6350
6351 static int
6352 api_ip_address_dump (vat_main_t *vam)
6353 {
6354   unformat_input_t *i = vam->input;
6355   vl_api_ip_address_dump_t *mp;
6356   vl_api_control_ping_t *mp_ping;
6357   u32 sw_if_index = ~0;
6358   u8 sw_if_index_set = 0;
6359   u8 ipv4_set = 0;
6360   u8 ipv6_set = 0;
6361   int ret;
6362
6363   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6364     {
6365       if (unformat (i, "sw_if_index %d", &sw_if_index))
6366         sw_if_index_set = 1;
6367       else if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
6368         sw_if_index_set = 1;
6369       else if (unformat (i, "ipv4"))
6370         ipv4_set = 1;
6371       else if (unformat (i, "ipv6"))
6372         ipv6_set = 1;
6373       else
6374         break;
6375     }
6376
6377   if (ipv4_set && ipv6_set)
6378     {
6379       errmsg ("ipv4 and ipv6 flags cannot be both set");
6380       return -99;
6381     }
6382
6383   if ((!ipv4_set) && (!ipv6_set))
6384     {
6385       errmsg ("no ipv4 nor ipv6 flag set");
6386       return -99;
6387     }
6388
6389   if (sw_if_index_set == 0)
6390     {
6391       errmsg ("missing interface name or sw_if_index");
6392       return -99;
6393     }
6394
6395   vam->current_sw_if_index = sw_if_index;
6396   vam->is_ipv6 = ipv6_set;
6397
6398   M (IP_ADDRESS_DUMP, mp);
6399   mp->sw_if_index = ntohl (sw_if_index);
6400   mp->is_ipv6 = ipv6_set;
6401   S (mp);
6402
6403   /* Use a control ping for synchronization */
6404   MPING (CONTROL_PING, mp_ping);
6405   S (mp_ping);
6406
6407   W (ret);
6408   return ret;
6409 }
6410
6411 static int
6412 api_ip_dump (vat_main_t * vam)
6413 {
6414   vl_api_ip_dump_t *mp;
6415   vl_api_control_ping_t *mp_ping;
6416   unformat_input_t *in = vam->input;
6417   int ipv4_set = 0;
6418   int ipv6_set = 0;
6419   int is_ipv6;
6420   int i;
6421   int ret;
6422
6423   while (unformat_check_input (in) != UNFORMAT_END_OF_INPUT)
6424     {
6425       if (unformat (in, "ipv4"))
6426         ipv4_set = 1;
6427       else if (unformat (in, "ipv6"))
6428         ipv6_set = 1;
6429       else
6430         break;
6431     }
6432
6433   if (ipv4_set && ipv6_set)
6434     {
6435       errmsg ("ipv4 and ipv6 flags cannot be both set");
6436       return -99;
6437     }
6438
6439   if ((!ipv4_set) && (!ipv6_set))
6440     {
6441       errmsg ("no ipv4 nor ipv6 flag set");
6442       return -99;
6443     }
6444
6445   is_ipv6 = ipv6_set;
6446   vam->is_ipv6 = is_ipv6;
6447
6448   /* free old data */
6449   for (i = 0; i < vec_len (vam->ip_details_by_sw_if_index[is_ipv6]); i++)
6450     {
6451       vec_free (vam->ip_details_by_sw_if_index[is_ipv6][i].addr);
6452     }
6453   vec_free (vam->ip_details_by_sw_if_index[is_ipv6]);
6454
6455   M (IP_DUMP, mp);
6456   mp->is_ipv6 = ipv6_set;
6457   S (mp);
6458
6459   /* Use a control ping for synchronization */
6460   MPING (CONTROL_PING, mp_ping);
6461   S (mp_ping);
6462
6463   W (ret);
6464   return ret;
6465 }
6466
6467 static int
6468 api_get_first_msg_id (vat_main_t * vam)
6469 {
6470   vl_api_get_first_msg_id_t *mp;
6471   unformat_input_t *i = vam->input;
6472   u8 *name;
6473   u8 name_set = 0;
6474   int ret;
6475
6476   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6477     {
6478       if (unformat (i, "client %s", &name))
6479         name_set = 1;
6480       else
6481         break;
6482     }
6483
6484   if (name_set == 0)
6485     {
6486       errmsg ("missing client name");
6487       return -99;
6488     }
6489   vec_add1 (name, 0);
6490
6491   if (vec_len (name) > 63)
6492     {
6493       errmsg ("client name too long");
6494       return -99;
6495     }
6496
6497   M (GET_FIRST_MSG_ID, mp);
6498   clib_memcpy (mp->name, name, vec_len (name));
6499   S (mp);
6500   W (ret);
6501   return ret;
6502 }
6503
6504 static int
6505 api_get_node_graph (vat_main_t * vam)
6506 {
6507   vl_api_get_node_graph_t *mp;
6508   int ret;
6509
6510   M (GET_NODE_GRAPH, mp);
6511
6512   /* send it... */
6513   S (mp);
6514   /* Wait for the reply */
6515   W (ret);
6516   return ret;
6517 }
6518
6519 static u8 *
6520 format_fib_api_path_nh_proto (u8 * s, va_list * args)
6521 {
6522   vl_api_fib_path_nh_proto_t proto =
6523     va_arg (*args, vl_api_fib_path_nh_proto_t);
6524
6525   switch (proto)
6526     {
6527     case FIB_API_PATH_NH_PROTO_IP4:
6528       s = format (s, "ip4");
6529       break;
6530     case FIB_API_PATH_NH_PROTO_IP6:
6531       s = format (s, "ip6");
6532       break;
6533     case FIB_API_PATH_NH_PROTO_MPLS:
6534       s = format (s, "mpls");
6535       break;
6536     case FIB_API_PATH_NH_PROTO_BIER:
6537       s = format (s, "bier");
6538       break;
6539     case FIB_API_PATH_NH_PROTO_ETHERNET:
6540       s = format (s, "ethernet");
6541       break;
6542     }
6543
6544   return (s);
6545 }
6546
6547 static u8 *
6548 format_vl_api_ip_address_union (u8 * s, va_list * args)
6549 {
6550   vl_api_address_family_t af = va_arg (*args, int);
6551   const vl_api_address_union_t *u = va_arg (*args, vl_api_address_union_t *);
6552
6553   switch (af)
6554     {
6555     case ADDRESS_IP4:
6556       s = format (s, "%U", format_ip4_address, u->ip4);
6557       break;
6558     case ADDRESS_IP6:
6559       s = format (s, "%U", format_ip6_address, u->ip6);
6560       break;
6561     }
6562   return (s);
6563 }
6564
6565 static u8 *
6566 format_vl_api_fib_path_type (u8 * s, va_list * args)
6567 {
6568   vl_api_fib_path_type_t t = va_arg (*args, vl_api_fib_path_type_t);
6569
6570   switch (t)
6571     {
6572     case FIB_API_PATH_TYPE_NORMAL:
6573       s = format (s, "normal");
6574       break;
6575     case FIB_API_PATH_TYPE_LOCAL:
6576       s = format (s, "local");
6577       break;
6578     case FIB_API_PATH_TYPE_DROP:
6579       s = format (s, "drop");
6580       break;
6581     case FIB_API_PATH_TYPE_UDP_ENCAP:
6582       s = format (s, "udp-encap");
6583       break;
6584     case FIB_API_PATH_TYPE_BIER_IMP:
6585       s = format (s, "bier-imp");
6586       break;
6587     case FIB_API_PATH_TYPE_ICMP_UNREACH:
6588       s = format (s, "unreach");
6589       break;
6590     case FIB_API_PATH_TYPE_ICMP_PROHIBIT:
6591       s = format (s, "prohibit");
6592       break;
6593     case FIB_API_PATH_TYPE_SOURCE_LOOKUP:
6594       s = format (s, "src-lookup");
6595       break;
6596     case FIB_API_PATH_TYPE_DVR:
6597       s = format (s, "dvr");
6598       break;
6599     case FIB_API_PATH_TYPE_INTERFACE_RX:
6600       s = format (s, "interface-rx");
6601       break;
6602     case FIB_API_PATH_TYPE_CLASSIFY:
6603       s = format (s, "classify");
6604       break;
6605     }
6606
6607   return (s);
6608 }
6609
6610 static void
6611 vl_api_fib_path_print (vat_main_t * vam, vl_api_fib_path_t * fp)
6612 {
6613   print (vam->ofp,
6614          "  weight %d, sw_if_index %d, type %U, afi %U, next_hop %U",
6615          ntohl (fp->weight), ntohl (fp->sw_if_index),
6616          format_vl_api_fib_path_type, fp->type,
6617          format_fib_api_path_nh_proto, fp->proto,
6618          format_vl_api_ip_address_union, &fp->nh.address);
6619 }
6620
6621 static void
6622 vl_api_mpls_fib_path_json_print (vat_json_node_t * node,
6623                                  vl_api_fib_path_t * fp)
6624 {
6625   struct in_addr ip4;
6626   struct in6_addr ip6;
6627
6628   vat_json_object_add_uint (node, "weight", ntohl (fp->weight));
6629   vat_json_object_add_uint (node, "sw_if_index", ntohl (fp->sw_if_index));
6630   vat_json_object_add_uint (node, "type", fp->type);
6631   vat_json_object_add_uint (node, "next_hop_proto", fp->proto);
6632   if (fp->proto == FIB_API_PATH_NH_PROTO_IP4)
6633     {
6634       clib_memcpy (&ip4, &fp->nh.address.ip4, sizeof (ip4));
6635       vat_json_object_add_ip4 (node, "next_hop", ip4);
6636     }
6637   else if (fp->proto == FIB_API_PATH_NH_PROTO_IP6)
6638     {
6639       clib_memcpy (&ip6, &fp->nh.address.ip6, sizeof (ip6));
6640       vat_json_object_add_ip6 (node, "next_hop", ip6);
6641     }
6642 }
6643
6644 #define vl_api_ip_table_details_t_endian vl_noop_handler
6645 #define vl_api_ip_table_details_t_print vl_noop_handler
6646
6647 static void
6648 vl_api_ip_table_details_t_handler (vl_api_ip_table_details_t * mp)
6649 {
6650   vat_main_t *vam = &vat_main;
6651
6652   print (vam->ofp,
6653          "%s; table-id %d, prefix %U/%d",
6654          mp->table.name, ntohl (mp->table.table_id));
6655 }
6656
6657
6658 static void vl_api_ip_table_details_t_handler_json
6659   (vl_api_ip_table_details_t * mp)
6660 {
6661   vat_main_t *vam = &vat_main;
6662   vat_json_node_t *node = NULL;
6663
6664   if (VAT_JSON_ARRAY != vam->json_tree.type)
6665     {
6666       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
6667       vat_json_init_array (&vam->json_tree);
6668     }
6669   node = vat_json_array_add (&vam->json_tree);
6670
6671   vat_json_init_object (node);
6672   vat_json_object_add_uint (node, "table", ntohl (mp->table.table_id));
6673 }
6674
6675 static int
6676 api_ip_table_dump (vat_main_t * vam)
6677 {
6678   vl_api_ip_table_dump_t *mp;
6679   vl_api_control_ping_t *mp_ping;
6680   int ret;
6681
6682   M (IP_TABLE_DUMP, mp);
6683   S (mp);
6684
6685   /* Use a control ping for synchronization */
6686   MPING (CONTROL_PING, mp_ping);
6687   S (mp_ping);
6688
6689   W (ret);
6690   return ret;
6691 }
6692
6693 static int
6694 api_ip_mtable_dump (vat_main_t * vam)
6695 {
6696   vl_api_ip_mtable_dump_t *mp;
6697   vl_api_control_ping_t *mp_ping;
6698   int ret;
6699
6700   M (IP_MTABLE_DUMP, mp);
6701   S (mp);
6702
6703   /* Use a control ping for synchronization */
6704   MPING (CONTROL_PING, mp_ping);
6705   S (mp_ping);
6706
6707   W (ret);
6708   return ret;
6709 }
6710
6711 static int
6712 api_ip_mroute_dump (vat_main_t * vam)
6713 {
6714   unformat_input_t *input = vam->input;
6715   vl_api_control_ping_t *mp_ping;
6716   vl_api_ip_mroute_dump_t *mp;
6717   int ret, is_ip6;
6718   u32 table_id;
6719
6720   is_ip6 = 0;
6721   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6722     {
6723       if (unformat (input, "table_id %d", &table_id))
6724         ;
6725       else if (unformat (input, "ip6"))
6726         is_ip6 = 1;
6727       else if (unformat (input, "ip4"))
6728         is_ip6 = 0;
6729       else
6730         break;
6731     }
6732   if (table_id == ~0)
6733     {
6734       errmsg ("missing table id");
6735       return -99;
6736     }
6737
6738   M (IP_MROUTE_DUMP, mp);
6739   mp->table.table_id = table_id;
6740   mp->table.is_ip6 = is_ip6;
6741   S (mp);
6742
6743   /* Use a control ping for synchronization */
6744   MPING (CONTROL_PING, mp_ping);
6745   S (mp_ping);
6746
6747   W (ret);
6748   return ret;
6749 }
6750
6751 #define vl_api_ip_route_details_t_endian vl_noop_handler
6752 #define vl_api_ip_route_details_t_print vl_noop_handler
6753
6754 static void
6755 vl_api_ip_route_details_t_handler (vl_api_ip_route_details_t * mp)
6756 {
6757   vat_main_t *vam = &vat_main;
6758   u8 count = mp->route.n_paths;
6759   vl_api_fib_path_t *fp;
6760   int i;
6761
6762   print (vam->ofp,
6763          "table-id %d, prefix %U/%d",
6764          ntohl (mp->route.table_id),
6765          format_ip46_address, mp->route.prefix.address, mp->route.prefix.len);
6766   for (i = 0; i < count; i++)
6767     {
6768       fp = &mp->route.paths[i];
6769
6770       vl_api_fib_path_print (vam, fp);
6771       fp++;
6772     }
6773 }
6774
6775 static void vl_api_ip_route_details_t_handler_json
6776   (vl_api_ip_route_details_t * mp)
6777 {
6778   vat_main_t *vam = &vat_main;
6779   u8 count = mp->route.n_paths;
6780   vat_json_node_t *node = NULL;
6781   struct in_addr ip4;
6782   struct in6_addr ip6;
6783   vl_api_fib_path_t *fp;
6784   int i;
6785
6786   if (VAT_JSON_ARRAY != vam->json_tree.type)
6787     {
6788       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
6789       vat_json_init_array (&vam->json_tree);
6790     }
6791   node = vat_json_array_add (&vam->json_tree);
6792
6793   vat_json_init_object (node);
6794   vat_json_object_add_uint (node, "table", ntohl (mp->route.table_id));
6795   if (ADDRESS_IP6 == mp->route.prefix.address.af)
6796     {
6797       clib_memcpy (&ip6, &mp->route.prefix.address.un.ip6, sizeof (ip6));
6798       vat_json_object_add_ip6 (node, "prefix", ip6);
6799     }
6800   else
6801     {
6802       clib_memcpy (&ip4, &mp->route.prefix.address.un.ip4, sizeof (ip4));
6803       vat_json_object_add_ip4 (node, "prefix", ip4);
6804     }
6805   vat_json_object_add_uint (node, "mask_length", mp->route.prefix.len);
6806   vat_json_object_add_uint (node, "path_count", count);
6807   for (i = 0; i < count; i++)
6808     {
6809       fp = &mp->route.paths[i];
6810       vl_api_mpls_fib_path_json_print (node, fp);
6811     }
6812 }
6813
6814 static int
6815 api_ip_route_dump (vat_main_t * vam)
6816 {
6817   unformat_input_t *input = vam->input;
6818   vl_api_ip_route_dump_t *mp;
6819   vl_api_control_ping_t *mp_ping;
6820   u32 table_id;
6821   u8 is_ip6;
6822   int ret;
6823
6824   is_ip6 = 0;
6825   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6826     {
6827       if (unformat (input, "table_id %d", &table_id))
6828         ;
6829       else if (unformat (input, "ip6"))
6830         is_ip6 = 1;
6831       else if (unformat (input, "ip4"))
6832         is_ip6 = 0;
6833       else
6834         break;
6835     }
6836   if (table_id == ~0)
6837     {
6838       errmsg ("missing table id");
6839       return -99;
6840     }
6841
6842   M (IP_ROUTE_DUMP, mp);
6843
6844   mp->table.table_id = table_id;
6845   mp->table.is_ip6 = is_ip6;
6846
6847   S (mp);
6848
6849   /* Use a control ping for synchronization */
6850   MPING (CONTROL_PING, mp_ping);
6851   S (mp_ping);
6852
6853   W (ret);
6854   return ret;
6855 }
6856
6857 int
6858 api_ip_source_and_port_range_check_add_del (vat_main_t * vam)
6859 {
6860   unformat_input_t *input = vam->input;
6861   vl_api_ip_source_and_port_range_check_add_del_t *mp;
6862
6863   u16 *low_ports = 0;
6864   u16 *high_ports = 0;
6865   u16 this_low;
6866   u16 this_hi;
6867   vl_api_prefix_t prefix;
6868   u32 tmp, tmp2;
6869   u8 prefix_set = 0;
6870   u32 vrf_id = ~0;
6871   u8 is_add = 1;
6872   int ret;
6873
6874   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6875     {
6876       if (unformat (input, "%U", unformat_vl_api_prefix, &prefix))
6877         prefix_set = 1;
6878       else if (unformat (input, "vrf %d", &vrf_id))
6879         ;
6880       else if (unformat (input, "del"))
6881         is_add = 0;
6882       else if (unformat (input, "port %d", &tmp))
6883         {
6884           if (tmp == 0 || tmp > 65535)
6885             {
6886               errmsg ("port %d out of range", tmp);
6887               return -99;
6888             }
6889           this_low = tmp;
6890           this_hi = this_low + 1;
6891           vec_add1 (low_ports, this_low);
6892           vec_add1 (high_ports, this_hi);
6893         }
6894       else if (unformat (input, "range %d - %d", &tmp, &tmp2))
6895         {
6896           if ((tmp > tmp2) || (tmp == 0) || (tmp2 > 65535))
6897             {
6898               errmsg ("incorrect range parameters");
6899               return -99;
6900             }
6901           this_low = tmp;
6902           /* Note: in debug CLI +1 is added to high before
6903              passing to real fn that does "the work"
6904              (ip_source_and_port_range_check_add_del).
6905              This fn is a wrapper around the binary API fn a
6906              control plane will call, which expects this increment
6907              to have occurred. Hence letting the binary API control
6908              plane fn do the increment for consistency between VAT
6909              and other control planes.
6910            */
6911           this_hi = tmp2;
6912           vec_add1 (low_ports, this_low);
6913           vec_add1 (high_ports, this_hi);
6914         }
6915       else
6916         break;
6917     }
6918
6919   if (prefix_set == 0)
6920     {
6921       errmsg ("<address>/<mask> not specified");
6922       return -99;
6923     }
6924
6925   if (vrf_id == ~0)
6926     {
6927       errmsg ("VRF ID required, not specified");
6928       return -99;
6929     }
6930
6931   if (vrf_id == 0)
6932     {
6933       errmsg
6934         ("VRF ID should not be default. Should be distinct VRF for this purpose.");
6935       return -99;
6936     }
6937
6938   if (vec_len (low_ports) == 0)
6939     {
6940       errmsg ("At least one port or port range required");
6941       return -99;
6942     }
6943
6944   M (IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL, mp);
6945
6946   mp->is_add = is_add;
6947
6948   clib_memcpy (&mp->prefix, &prefix, sizeof (prefix));
6949
6950   mp->number_of_ranges = vec_len (low_ports);
6951
6952   clib_memcpy (mp->low_ports, low_ports, vec_len (low_ports));
6953   vec_free (low_ports);
6954
6955   clib_memcpy (mp->high_ports, high_ports, vec_len (high_ports));
6956   vec_free (high_ports);
6957
6958   mp->vrf_id = ntohl (vrf_id);
6959
6960   S (mp);
6961   W (ret);
6962   return ret;
6963 }
6964
6965 int
6966 api_ip_source_and_port_range_check_interface_add_del (vat_main_t * vam)
6967 {
6968   unformat_input_t *input = vam->input;
6969   vl_api_ip_source_and_port_range_check_interface_add_del_t *mp;
6970   u32 sw_if_index = ~0;
6971   int vrf_set = 0;
6972   u32 tcp_out_vrf_id = ~0, udp_out_vrf_id = ~0;
6973   u32 tcp_in_vrf_id = ~0, udp_in_vrf_id = ~0;
6974   u8 is_add = 1;
6975   int ret;
6976
6977   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6978     {
6979       if (unformat (input, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
6980         ;
6981       else if (unformat (input, "sw_if_index %d", &sw_if_index))
6982         ;
6983       else if (unformat (input, "tcp-out-vrf %d", &tcp_out_vrf_id))
6984         vrf_set = 1;
6985       else if (unformat (input, "udp-out-vrf %d", &udp_out_vrf_id))
6986         vrf_set = 1;
6987       else if (unformat (input, "tcp-in-vrf %d", &tcp_in_vrf_id))
6988         vrf_set = 1;
6989       else if (unformat (input, "udp-in-vrf %d", &udp_in_vrf_id))
6990         vrf_set = 1;
6991       else if (unformat (input, "del"))
6992         is_add = 0;
6993       else
6994         break;
6995     }
6996
6997   if (sw_if_index == ~0)
6998     {
6999       errmsg ("Interface required but not specified");
7000       return -99;
7001     }
7002
7003   if (vrf_set == 0)
7004     {
7005       errmsg ("VRF ID required but not specified");
7006       return -99;
7007     }
7008
7009   if (tcp_out_vrf_id == 0
7010       || udp_out_vrf_id == 0 || tcp_in_vrf_id == 0 || udp_in_vrf_id == 0)
7011     {
7012       errmsg
7013         ("VRF ID should not be default. Should be distinct VRF for this purpose.");
7014       return -99;
7015     }
7016
7017   /* Construct the API message */
7018   M (IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL, mp);
7019
7020   mp->sw_if_index = ntohl (sw_if_index);
7021   mp->is_add = is_add;
7022   mp->tcp_out_vrf_id = ntohl (tcp_out_vrf_id);
7023   mp->udp_out_vrf_id = ntohl (udp_out_vrf_id);
7024   mp->tcp_in_vrf_id = ntohl (tcp_in_vrf_id);
7025   mp->udp_in_vrf_id = ntohl (udp_in_vrf_id);
7026
7027   /* send it... */
7028   S (mp);
7029
7030   /* Wait for a reply... */
7031   W (ret);
7032   return ret;
7033 }
7034
7035 static int
7036 api_delete_subif (vat_main_t * vam)
7037 {
7038   unformat_input_t *i = vam->input;
7039   vl_api_delete_subif_t *mp;
7040   u32 sw_if_index = ~0;
7041   int ret;
7042
7043   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7044     {
7045       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
7046         ;
7047       if (unformat (i, "sw_if_index %d", &sw_if_index))
7048         ;
7049       else
7050         break;
7051     }
7052
7053   if (sw_if_index == ~0)
7054     {
7055       errmsg ("missing sw_if_index");
7056       return -99;
7057     }
7058
7059   /* Construct the API message */
7060   M (DELETE_SUBIF, mp);
7061   mp->sw_if_index = ntohl (sw_if_index);
7062
7063   S (mp);
7064   W (ret);
7065   return ret;
7066 }
7067
7068 #define foreach_pbb_vtr_op      \
7069 _("disable",  L2_VTR_DISABLED)  \
7070 _("pop",  L2_VTR_POP_2)         \
7071 _("push",  L2_VTR_PUSH_2)
7072
7073 static int
7074 api_l2_interface_pbb_tag_rewrite (vat_main_t * vam)
7075 {
7076   unformat_input_t *i = vam->input;
7077   vl_api_l2_interface_pbb_tag_rewrite_t *mp;
7078   u32 sw_if_index = ~0, vtr_op = ~0;
7079   u16 outer_tag = ~0;
7080   u8 dmac[6], smac[6];
7081   u8 dmac_set = 0, smac_set = 0;
7082   u16 vlanid = 0;
7083   u32 sid = ~0;
7084   u32 tmp;
7085   int ret;
7086
7087   /* Shut up coverity */
7088   clib_memset (dmac, 0, sizeof (dmac));
7089   clib_memset (smac, 0, sizeof (smac));
7090
7091   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7092     {
7093       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
7094         ;
7095       else if (unformat (i, "sw_if_index %d", &sw_if_index))
7096         ;
7097       else if (unformat (i, "vtr_op %d", &vtr_op))
7098         ;
7099 #define _(n,v) else if (unformat(i, n)) {vtr_op = v;}
7100       foreach_pbb_vtr_op
7101 #undef _
7102         else if (unformat (i, "translate_pbb_stag"))
7103         {
7104           if (unformat (i, "%d", &tmp))
7105             {
7106               vtr_op = L2_VTR_TRANSLATE_2_1;
7107               outer_tag = tmp;
7108             }
7109           else
7110             {
7111               errmsg
7112                 ("translate_pbb_stag operation requires outer tag definition");
7113               return -99;
7114             }
7115         }
7116       else if (unformat (i, "dmac %U", unformat_ethernet_address, dmac))
7117         dmac_set++;
7118       else if (unformat (i, "smac %U", unformat_ethernet_address, smac))
7119         smac_set++;
7120       else if (unformat (i, "sid %d", &sid))
7121         ;
7122       else if (unformat (i, "vlanid %d", &tmp))
7123         vlanid = tmp;
7124       else
7125         {
7126           clib_warning ("parse error '%U'", format_unformat_error, i);
7127           return -99;
7128         }
7129     }
7130
7131   if ((sw_if_index == ~0) || (vtr_op == ~0))
7132     {
7133       errmsg ("missing sw_if_index or vtr operation");
7134       return -99;
7135     }
7136   if (((vtr_op == L2_VTR_PUSH_2) || (vtr_op == L2_VTR_TRANSLATE_2_2))
7137       && ((dmac_set == 0) || (smac_set == 0) || (sid == ~0)))
7138     {
7139       errmsg
7140         ("push and translate_qinq operations require dmac, smac, sid and optionally vlanid");
7141       return -99;
7142     }
7143
7144   M (L2_INTERFACE_PBB_TAG_REWRITE, mp);
7145   mp->sw_if_index = ntohl (sw_if_index);
7146   mp->vtr_op = ntohl (vtr_op);
7147   mp->outer_tag = ntohs (outer_tag);
7148   clib_memcpy (mp->b_dmac, dmac, sizeof (dmac));
7149   clib_memcpy (mp->b_smac, smac, sizeof (smac));
7150   mp->b_vlanid = ntohs (vlanid);
7151   mp->i_sid = ntohl (sid);
7152
7153   S (mp);
7154   W (ret);
7155   return ret;
7156 }
7157
7158 static int
7159 api_sw_interface_tag_add_del (vat_main_t * vam)
7160 {
7161   unformat_input_t *i = vam->input;
7162   vl_api_sw_interface_tag_add_del_t *mp;
7163   u32 sw_if_index = ~0;
7164   u8 *tag = 0;
7165   u8 enable = 1;
7166   int ret;
7167
7168   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7169     {
7170       if (unformat (i, "tag %s", &tag))
7171         ;
7172       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
7173         ;
7174       else if (unformat (i, "sw_if_index %d", &sw_if_index))
7175         ;
7176       else if (unformat (i, "del"))
7177         enable = 0;
7178       else
7179         break;
7180     }
7181
7182   if (sw_if_index == ~0)
7183     {
7184       errmsg ("missing interface name or sw_if_index");
7185       return -99;
7186     }
7187
7188   if (enable && (tag == 0))
7189     {
7190       errmsg ("no tag specified");
7191       return -99;
7192     }
7193
7194   /* Construct the API message */
7195   M (SW_INTERFACE_TAG_ADD_DEL, mp);
7196   mp->sw_if_index = ntohl (sw_if_index);
7197   mp->is_add = enable;
7198   if (enable)
7199     strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
7200   vec_free (tag);
7201
7202   S (mp);
7203   W (ret);
7204   return ret;
7205 }
7206
7207 static int
7208 api_sw_interface_add_del_mac_address (vat_main_t * vam)
7209 {
7210   unformat_input_t *i = vam->input;
7211   vl_api_mac_address_t mac = { 0 };
7212   vl_api_sw_interface_add_del_mac_address_t *mp;
7213   u32 sw_if_index = ~0;
7214   u8 is_add = 1;
7215   u8 mac_set = 0;
7216   int ret;
7217
7218   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7219     {
7220       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
7221         ;
7222       else if (unformat (i, "sw_if_index %d", &sw_if_index))
7223         ;
7224       else if (unformat (i, "%U", unformat_vl_api_mac_address, &mac))
7225         mac_set++;
7226       else if (unformat (i, "del"))
7227         is_add = 0;
7228       else
7229         break;
7230     }
7231
7232   if (sw_if_index == ~0)
7233     {
7234       errmsg ("missing interface name or sw_if_index");
7235       return -99;
7236     }
7237
7238   if (!mac_set)
7239     {
7240       errmsg ("missing MAC address");
7241       return -99;
7242     }
7243
7244   /* Construct the API message */
7245   M (SW_INTERFACE_ADD_DEL_MAC_ADDRESS, mp);
7246   mp->sw_if_index = ntohl (sw_if_index);
7247   mp->is_add = is_add;
7248   clib_memcpy (&mp->addr, &mac, sizeof (mac));
7249
7250   S (mp);
7251   W (ret);
7252   return ret;
7253 }
7254
7255 static void vl_api_l2_xconnect_details_t_handler
7256   (vl_api_l2_xconnect_details_t * mp)
7257 {
7258   vat_main_t *vam = &vat_main;
7259
7260   print (vam->ofp, "%15d%15d",
7261          ntohl (mp->rx_sw_if_index), ntohl (mp->tx_sw_if_index));
7262 }
7263
7264 static void vl_api_l2_xconnect_details_t_handler_json
7265   (vl_api_l2_xconnect_details_t * mp)
7266 {
7267   vat_main_t *vam = &vat_main;
7268   vat_json_node_t *node = NULL;
7269
7270   if (VAT_JSON_ARRAY != vam->json_tree.type)
7271     {
7272       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
7273       vat_json_init_array (&vam->json_tree);
7274     }
7275   node = vat_json_array_add (&vam->json_tree);
7276
7277   vat_json_init_object (node);
7278   vat_json_object_add_uint (node, "rx_sw_if_index",
7279                             ntohl (mp->rx_sw_if_index));
7280   vat_json_object_add_uint (node, "tx_sw_if_index",
7281                             ntohl (mp->tx_sw_if_index));
7282 }
7283
7284 static int
7285 api_l2_xconnect_dump (vat_main_t * vam)
7286 {
7287   vl_api_l2_xconnect_dump_t *mp;
7288   vl_api_control_ping_t *mp_ping;
7289   int ret;
7290
7291   if (!vam->json_output)
7292     {
7293       print (vam->ofp, "%15s%15s", "rx_sw_if_index", "tx_sw_if_index");
7294     }
7295
7296   M (L2_XCONNECT_DUMP, mp);
7297
7298   S (mp);
7299
7300   /* Use a control ping for synchronization */
7301   MPING (CONTROL_PING, mp_ping);
7302   S (mp_ping);
7303
7304   W (ret);
7305   return ret;
7306 }
7307
7308 static int
7309 api_hw_interface_set_mtu (vat_main_t * vam)
7310 {
7311   unformat_input_t *i = vam->input;
7312   vl_api_hw_interface_set_mtu_t *mp;
7313   u32 sw_if_index = ~0;
7314   u32 mtu = 0;
7315   int ret;
7316
7317   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7318     {
7319       if (unformat (i, "mtu %d", &mtu))
7320         ;
7321       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
7322         ;
7323       else if (unformat (i, "sw_if_index %d", &sw_if_index))
7324         ;
7325       else
7326         break;
7327     }
7328
7329   if (sw_if_index == ~0)
7330     {
7331       errmsg ("missing interface name or sw_if_index");
7332       return -99;
7333     }
7334
7335   if (mtu == 0)
7336     {
7337       errmsg ("no mtu specified");
7338       return -99;
7339     }
7340
7341   /* Construct the API message */
7342   M (HW_INTERFACE_SET_MTU, mp);
7343   mp->sw_if_index = ntohl (sw_if_index);
7344   mp->mtu = ntohs ((u16) mtu);
7345
7346   S (mp);
7347   W (ret);
7348   return ret;
7349 }
7350
7351 static void vl_api_app_namespace_add_del_reply_t_handler
7352   (vl_api_app_namespace_add_del_reply_t * mp)
7353 {
7354   vat_main_t *vam = &vat_main;
7355   i32 retval = ntohl (mp->retval);
7356   if (vam->async_mode)
7357     {
7358       vam->async_errors += (retval < 0);
7359     }
7360   else
7361     {
7362       vam->retval = retval;
7363       if (retval == 0)
7364         errmsg ("app ns index %d\n", ntohl (mp->appns_index));
7365       vam->result_ready = 1;
7366     }
7367 }
7368
7369 static void vl_api_app_namespace_add_del_reply_t_handler_json
7370   (vl_api_app_namespace_add_del_reply_t * mp)
7371 {
7372   vat_main_t *vam = &vat_main;
7373   vat_json_node_t node;
7374
7375   vat_json_init_object (&node);
7376   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
7377   vat_json_object_add_uint (&node, "appns_index", ntohl (mp->appns_index));
7378
7379   vat_json_print (vam->ofp, &node);
7380   vat_json_free (&node);
7381
7382   vam->retval = ntohl (mp->retval);
7383   vam->result_ready = 1;
7384 }
7385
7386 static int
7387 api_app_namespace_add_del (vat_main_t * vam)
7388 {
7389   vl_api_app_namespace_add_del_t *mp;
7390   unformat_input_t *i = vam->input;
7391   u8 *ns_id = 0, secret_set = 0, sw_if_index_set = 0;
7392   u32 sw_if_index, ip4_fib_id, ip6_fib_id;
7393   u64 secret;
7394   int ret;
7395
7396   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7397     {
7398       if (unformat (i, "id %_%v%_", &ns_id))
7399         ;
7400       else if (unformat (i, "secret %lu", &secret))
7401         secret_set = 1;
7402       else if (unformat (i, "sw_if_index %d", &sw_if_index))
7403         sw_if_index_set = 1;
7404       else if (unformat (i, "ip4_fib_id %d", &ip4_fib_id))
7405         ;
7406       else if (unformat (i, "ip6_fib_id %d", &ip6_fib_id))
7407         ;
7408       else
7409         break;
7410     }
7411   if (!ns_id || !secret_set || !sw_if_index_set)
7412     {
7413       errmsg ("namespace id, secret and sw_if_index must be set");
7414       return -99;
7415     }
7416   if (vec_len (ns_id) > 64)
7417     {
7418       errmsg ("namespace id too long");
7419       return -99;
7420     }
7421   M (APP_NAMESPACE_ADD_DEL, mp);
7422
7423   vl_api_vec_to_api_string (ns_id, &mp->namespace_id);
7424   mp->secret = clib_host_to_net_u64 (secret);
7425   mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
7426   mp->ip4_fib_id = clib_host_to_net_u32 (ip4_fib_id);
7427   mp->ip6_fib_id = clib_host_to_net_u32 (ip6_fib_id);
7428   vec_free (ns_id);
7429   S (mp);
7430   W (ret);
7431   return ret;
7432 }
7433
7434 static int
7435 api_sock_init_shm (vat_main_t * vam)
7436 {
7437 #if VPP_API_TEST_BUILTIN == 0
7438   unformat_input_t *i = vam->input;
7439   vl_api_shm_elem_config_t *config = 0;
7440   u64 size = 64 << 20;
7441   int rv;
7442
7443   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7444     {
7445       if (unformat (i, "size %U", unformat_memory_size, &size))
7446         ;
7447       else
7448         break;
7449     }
7450
7451   /*
7452    * Canned custom ring allocator config.
7453    * Should probably parse all of this
7454    */
7455   vec_validate (config, 6);
7456   config[0].type = VL_API_VLIB_RING;
7457   config[0].size = 256;
7458   config[0].count = 32;
7459
7460   config[1].type = VL_API_VLIB_RING;
7461   config[1].size = 1024;
7462   config[1].count = 16;
7463
7464   config[2].type = VL_API_VLIB_RING;
7465   config[2].size = 4096;
7466   config[2].count = 2;
7467
7468   config[3].type = VL_API_CLIENT_RING;
7469   config[3].size = 256;
7470   config[3].count = 32;
7471
7472   config[4].type = VL_API_CLIENT_RING;
7473   config[4].size = 1024;
7474   config[4].count = 16;
7475
7476   config[5].type = VL_API_CLIENT_RING;
7477   config[5].size = 4096;
7478   config[5].count = 2;
7479
7480   config[6].type = VL_API_QUEUE;
7481   config[6].count = 128;
7482   config[6].size = sizeof (uword);
7483
7484   rv = vl_socket_client_init_shm (config, 1 /* want_pthread */ );
7485   if (!rv)
7486     vam->client_index_invalid = 1;
7487   return rv;
7488 #else
7489   return -99;
7490 #endif
7491 }
7492
7493 static void
7494 vl_api_session_rules_details_t_handler (vl_api_session_rules_details_t * mp)
7495 {
7496   vat_main_t *vam = &vat_main;
7497   fib_prefix_t lcl, rmt;
7498
7499   ip_prefix_decode (&mp->lcl, &lcl);
7500   ip_prefix_decode (&mp->rmt, &rmt);
7501
7502   if (lcl.fp_proto == FIB_PROTOCOL_IP4)
7503     {
7504       print (vam->ofp,
7505              "appns %u tp %u scope %d %U/%d %d %U/%d %d action: %d tag: %s",
7506              clib_net_to_host_u32 (mp->appns_index), mp->transport_proto,
7507              mp->scope, format_ip4_address, &lcl.fp_addr.ip4, lcl.fp_len,
7508              clib_net_to_host_u16 (mp->lcl_port), format_ip4_address,
7509              &rmt.fp_addr.ip4, rmt.fp_len,
7510              clib_net_to_host_u16 (mp->rmt_port),
7511              clib_net_to_host_u32 (mp->action_index), mp->tag);
7512     }
7513   else
7514     {
7515       print (vam->ofp,
7516              "appns %u tp %u scope %d %U/%d %d %U/%d %d action: %d tag: %s",
7517              clib_net_to_host_u32 (mp->appns_index), mp->transport_proto,
7518              mp->scope, format_ip6_address, &lcl.fp_addr.ip6, lcl.fp_len,
7519              clib_net_to_host_u16 (mp->lcl_port), format_ip6_address,
7520              &rmt.fp_addr.ip6, rmt.fp_len,
7521              clib_net_to_host_u16 (mp->rmt_port),
7522              clib_net_to_host_u32 (mp->action_index), mp->tag);
7523     }
7524 }
7525
7526 static void
7527 vl_api_session_rules_details_t_handler_json (vl_api_session_rules_details_t *
7528                                              mp)
7529 {
7530   vat_main_t *vam = &vat_main;
7531   vat_json_node_t *node = NULL;
7532   struct in6_addr ip6;
7533   struct in_addr ip4;
7534
7535   fib_prefix_t lcl, rmt;
7536
7537   ip_prefix_decode (&mp->lcl, &lcl);
7538   ip_prefix_decode (&mp->rmt, &rmt);
7539
7540   if (VAT_JSON_ARRAY != vam->json_tree.type)
7541     {
7542       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
7543       vat_json_init_array (&vam->json_tree);
7544     }
7545   node = vat_json_array_add (&vam->json_tree);
7546   vat_json_init_object (node);
7547
7548   vat_json_object_add_uint (node, "appns_index",
7549                             clib_net_to_host_u32 (mp->appns_index));
7550   vat_json_object_add_uint (node, "transport_proto", mp->transport_proto);
7551   vat_json_object_add_uint (node, "scope", mp->scope);
7552   vat_json_object_add_uint (node, "action_index",
7553                             clib_net_to_host_u32 (mp->action_index));
7554   vat_json_object_add_uint (node, "lcl_port",
7555                             clib_net_to_host_u16 (mp->lcl_port));
7556   vat_json_object_add_uint (node, "rmt_port",
7557                             clib_net_to_host_u16 (mp->rmt_port));
7558   vat_json_object_add_uint (node, "lcl_plen", lcl.fp_len);
7559   vat_json_object_add_uint (node, "rmt_plen", rmt.fp_len);
7560   vat_json_object_add_string_copy (node, "tag", mp->tag);
7561   if (lcl.fp_proto == FIB_PROTOCOL_IP4)
7562     {
7563       clib_memcpy (&ip4, &lcl.fp_addr.ip4, sizeof (ip4));
7564       vat_json_object_add_ip4 (node, "lcl_ip", ip4);
7565       clib_memcpy (&ip4, &rmt.fp_addr.ip4, sizeof (ip4));
7566       vat_json_object_add_ip4 (node, "rmt_ip", ip4);
7567     }
7568   else
7569     {
7570       clib_memcpy (&ip6, &lcl.fp_addr.ip6, sizeof (ip6));
7571       vat_json_object_add_ip6 (node, "lcl_ip", ip6);
7572       clib_memcpy (&ip6, &rmt.fp_addr.ip6, sizeof (ip6));
7573       vat_json_object_add_ip6 (node, "rmt_ip", ip6);
7574     }
7575 }
7576
7577 static int
7578 api_session_rule_add_del (vat_main_t * vam)
7579 {
7580   vl_api_session_rule_add_del_t *mp;
7581   unformat_input_t *i = vam->input;
7582   u32 proto = ~0, lcl_port, rmt_port, action = 0, lcl_plen, rmt_plen;
7583   u32 appns_index = 0, scope = 0;
7584   ip4_address_t lcl_ip4, rmt_ip4;
7585   ip6_address_t lcl_ip6, rmt_ip6;
7586   u8 is_ip4 = 1, conn_set = 0;
7587   u8 is_add = 1, *tag = 0;
7588   int ret;
7589   fib_prefix_t lcl, rmt;
7590
7591   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7592     {
7593       if (unformat (i, "del"))
7594         is_add = 0;
7595       else if (unformat (i, "add"))
7596         ;
7597       else if (unformat (i, "proto tcp"))
7598         proto = 0;
7599       else if (unformat (i, "proto udp"))
7600         proto = 1;
7601       else if (unformat (i, "appns %d", &appns_index))
7602         ;
7603       else if (unformat (i, "scope %d", &scope))
7604         ;
7605       else if (unformat (i, "tag %_%v%_", &tag))
7606         ;
7607       else
7608         if (unformat
7609             (i, "%U/%d %d %U/%d %d", unformat_ip4_address, &lcl_ip4,
7610              &lcl_plen, &lcl_port, unformat_ip4_address, &rmt_ip4, &rmt_plen,
7611              &rmt_port))
7612         {
7613           is_ip4 = 1;
7614           conn_set = 1;
7615         }
7616       else
7617         if (unformat
7618             (i, "%U/%d %d %U/%d %d", unformat_ip6_address, &lcl_ip6,
7619              &lcl_plen, &lcl_port, unformat_ip6_address, &rmt_ip6, &rmt_plen,
7620              &rmt_port))
7621         {
7622           is_ip4 = 0;
7623           conn_set = 1;
7624         }
7625       else if (unformat (i, "action %d", &action))
7626         ;
7627       else
7628         break;
7629     }
7630   if (proto == ~0 || !conn_set || action == ~0)
7631     {
7632       errmsg ("transport proto, connection and action must be set");
7633       return -99;
7634     }
7635
7636   if (scope > 3)
7637     {
7638       errmsg ("scope should be 0-3");
7639       return -99;
7640     }
7641
7642   M (SESSION_RULE_ADD_DEL, mp);
7643
7644   clib_memset (&lcl, 0, sizeof (lcl));
7645   clib_memset (&rmt, 0, sizeof (rmt));
7646   if (is_ip4)
7647     {
7648       ip_set (&lcl.fp_addr, &lcl_ip4, 1);
7649       ip_set (&rmt.fp_addr, &rmt_ip4, 1);
7650       lcl.fp_len = lcl_plen;
7651       rmt.fp_len = rmt_plen;
7652     }
7653   else
7654     {
7655       ip_set (&lcl.fp_addr, &lcl_ip6, 0);
7656       ip_set (&rmt.fp_addr, &rmt_ip6, 0);
7657       lcl.fp_len = lcl_plen;
7658       rmt.fp_len = rmt_plen;
7659     }
7660
7661
7662   ip_prefix_encode (&lcl, &mp->lcl);
7663   ip_prefix_encode (&rmt, &mp->rmt);
7664   mp->lcl_port = clib_host_to_net_u16 ((u16) lcl_port);
7665   mp->rmt_port = clib_host_to_net_u16 ((u16) rmt_port);
7666   mp->transport_proto =
7667     proto ? TRANSPORT_PROTO_API_UDP : TRANSPORT_PROTO_API_TCP;
7668   mp->action_index = clib_host_to_net_u32 (action);
7669   mp->appns_index = clib_host_to_net_u32 (appns_index);
7670   mp->scope = scope;
7671   mp->is_add = is_add;
7672   if (tag)
7673     {
7674       clib_memcpy (mp->tag, tag, vec_len (tag));
7675       vec_free (tag);
7676     }
7677
7678   S (mp);
7679   W (ret);
7680   return ret;
7681 }
7682
7683 static int
7684 api_session_rules_dump (vat_main_t * vam)
7685 {
7686   vl_api_session_rules_dump_t *mp;
7687   vl_api_control_ping_t *mp_ping;
7688   int ret;
7689
7690   if (!vam->json_output)
7691     {
7692       print (vam->ofp, "%=20s", "Session Rules");
7693     }
7694
7695   M (SESSION_RULES_DUMP, mp);
7696   /* send it... */
7697   S (mp);
7698
7699   /* Use a control ping for synchronization */
7700   MPING (CONTROL_PING, mp_ping);
7701   S (mp_ping);
7702
7703   /* Wait for a reply... */
7704   W (ret);
7705   return ret;
7706 }
7707
7708 static int
7709 api_ip_container_proxy_add_del (vat_main_t * vam)
7710 {
7711   vl_api_ip_container_proxy_add_del_t *mp;
7712   unformat_input_t *i = vam->input;
7713   u32 sw_if_index = ~0;
7714   vl_api_prefix_t pfx = { };
7715   u8 is_add = 1;
7716   int ret;
7717
7718   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7719     {
7720       if (unformat (i, "del"))
7721         is_add = 0;
7722       else if (unformat (i, "add"))
7723         ;
7724       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
7725         ;
7726       else if (unformat (i, "sw_if_index %u", &sw_if_index))
7727         ;
7728       else
7729         break;
7730     }
7731   if (sw_if_index == ~0 || pfx.len == 0)
7732     {
7733       errmsg ("address and sw_if_index must be set");
7734       return -99;
7735     }
7736
7737   M (IP_CONTAINER_PROXY_ADD_DEL, mp);
7738
7739   mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
7740   mp->is_add = is_add;
7741   clib_memcpy (&mp->pfx, &pfx, sizeof (pfx));
7742
7743   S (mp);
7744   W (ret);
7745   return ret;
7746 }
7747
7748 static int
7749 q_or_quit (vat_main_t * vam)
7750 {
7751 #if VPP_API_TEST_BUILTIN == 0
7752   longjmp (vam->jump_buf, 1);
7753 #endif
7754   return 0;                     /* not so much */
7755 }
7756
7757 static int
7758 q (vat_main_t * vam)
7759 {
7760   return q_or_quit (vam);
7761 }
7762
7763 static int
7764 quit (vat_main_t * vam)
7765 {
7766   return q_or_quit (vam);
7767 }
7768
7769 static int
7770 comment (vat_main_t * vam)
7771 {
7772   return 0;
7773 }
7774
7775 static int
7776 elog_save (vat_main_t * vam)
7777 {
7778 #if VPP_API_TEST_BUILTIN == 0
7779   elog_main_t *em = &vam->elog_main;
7780   unformat_input_t *i = vam->input;
7781   char *file, *chroot_file;
7782   clib_error_t *error;
7783
7784   if (!unformat (i, "%s", &file))
7785     {
7786       errmsg ("expected file name, got `%U'", format_unformat_error, i);
7787       return 0;
7788     }
7789
7790   /* It's fairly hard to get "../oopsie" through unformat; just in case */
7791   if (strstr (file, "..") || index (file, '/'))
7792     {
7793       errmsg ("illegal characters in filename '%s'", file);
7794       return 0;
7795     }
7796
7797   chroot_file = (char *) format (0, "/tmp/%s%c", file, 0);
7798
7799   vec_free (file);
7800
7801   errmsg ("Saving %wd of %wd events to %s",
7802           elog_n_events_in_buffer (em),
7803           elog_buffer_capacity (em), chroot_file);
7804
7805   error = elog_write_file (em, chroot_file, 1 /* flush ring */ );
7806   vec_free (chroot_file);
7807
7808   if (error)
7809     clib_error_report (error);
7810 #else
7811   errmsg ("Use the vpp event loger...");
7812 #endif
7813
7814   return 0;
7815 }
7816
7817 static int
7818 elog_setup (vat_main_t * vam)
7819 {
7820 #if VPP_API_TEST_BUILTIN == 0
7821   elog_main_t *em = &vam->elog_main;
7822   unformat_input_t *i = vam->input;
7823   u32 nevents = 128 << 10;
7824
7825   (void) unformat (i, "nevents %d", &nevents);
7826
7827   elog_init (em, nevents);
7828   vl_api_set_elog_main (em);
7829   vl_api_set_elog_trace_api_messages (1);
7830   errmsg ("Event logger initialized with %u events", nevents);
7831 #else
7832   errmsg ("Use the vpp event loger...");
7833 #endif
7834   return 0;
7835 }
7836
7837 static int
7838 elog_enable (vat_main_t * vam)
7839 {
7840 #if VPP_API_TEST_BUILTIN == 0
7841   elog_main_t *em = &vam->elog_main;
7842
7843   elog_enable_disable (em, 1 /* enable */ );
7844   vl_api_set_elog_trace_api_messages (1);
7845   errmsg ("Event logger enabled...");
7846 #else
7847   errmsg ("Use the vpp event loger...");
7848 #endif
7849   return 0;
7850 }
7851
7852 static int
7853 elog_disable (vat_main_t * vam)
7854 {
7855 #if VPP_API_TEST_BUILTIN == 0
7856   elog_main_t *em = &vam->elog_main;
7857
7858   elog_enable_disable (em, 0 /* enable */ );
7859   vl_api_set_elog_trace_api_messages (1);
7860   errmsg ("Event logger disabled...");
7861 #else
7862   errmsg ("Use the vpp event loger...");
7863 #endif
7864   return 0;
7865 }
7866
7867 static int
7868 statseg (vat_main_t * vam)
7869 {
7870   ssvm_private_t *ssvmp = &vam->stat_segment;
7871   ssvm_shared_header_t *shared_header = ssvmp->sh;
7872   vlib_counter_t **counters;
7873   u64 thread0_index1_packets;
7874   u64 thread0_index1_bytes;
7875   f64 vector_rate, input_rate;
7876   uword *p;
7877
7878   uword *counter_vector_by_name;
7879   if (vam->stat_segment_lockp == 0)
7880     {
7881       errmsg ("Stat segment not mapped...");
7882       return -99;
7883     }
7884
7885   /* look up "/if/rx for sw_if_index 1 as a test */
7886
7887   clib_spinlock_lock (vam->stat_segment_lockp);
7888
7889   counter_vector_by_name = (uword *) shared_header->opaque[1];
7890
7891   p = hash_get_mem (counter_vector_by_name, "/if/rx");
7892   if (p == 0)
7893     {
7894       clib_spinlock_unlock (vam->stat_segment_lockp);
7895       errmsg ("/if/tx not found?");
7896       return -99;
7897     }
7898
7899   /* Fish per-thread vector of combined counters from shared memory */
7900   counters = (vlib_counter_t **) p[0];
7901
7902   if (vec_len (counters[0]) < 2)
7903     {
7904       clib_spinlock_unlock (vam->stat_segment_lockp);
7905       errmsg ("/if/tx vector length %d", vec_len (counters[0]));
7906       return -99;
7907     }
7908
7909   /* Read thread 0 sw_if_index 1 counter */
7910   thread0_index1_packets = counters[0][1].packets;
7911   thread0_index1_bytes = counters[0][1].bytes;
7912
7913   p = hash_get_mem (counter_vector_by_name, "vector_rate");
7914   if (p == 0)
7915     {
7916       clib_spinlock_unlock (vam->stat_segment_lockp);
7917       errmsg ("vector_rate not found?");
7918       return -99;
7919     }
7920
7921   vector_rate = *(f64 *) (p[0]);
7922   p = hash_get_mem (counter_vector_by_name, "input_rate");
7923   if (p == 0)
7924     {
7925       clib_spinlock_unlock (vam->stat_segment_lockp);
7926       errmsg ("input_rate not found?");
7927       return -99;
7928     }
7929   input_rate = *(f64 *) (p[0]);
7930
7931   clib_spinlock_unlock (vam->stat_segment_lockp);
7932
7933   print (vam->ofp, "vector_rate %.2f input_rate %.2f",
7934          vector_rate, input_rate);
7935   print (vam->ofp, "thread 0 sw_if_index 1 rx pkts %lld, bytes %lld",
7936          thread0_index1_packets, thread0_index1_bytes);
7937
7938   return 0;
7939 }
7940
7941 static int
7942 cmd_cmp (void *a1, void *a2)
7943 {
7944   u8 **c1 = a1;
7945   u8 **c2 = a2;
7946
7947   return strcmp ((char *) (c1[0]), (char *) (c2[0]));
7948 }
7949
7950 static int
7951 help (vat_main_t * vam)
7952 {
7953   u8 **cmds = 0;
7954   u8 *name = 0;
7955   hash_pair_t *p;
7956   unformat_input_t *i = vam->input;
7957   int j;
7958
7959   if (unformat (i, "%s", &name))
7960     {
7961       uword *hs;
7962
7963       vec_add1 (name, 0);
7964
7965       hs = hash_get_mem (vam->help_by_name, name);
7966       if (hs)
7967         print (vam->ofp, "usage: %s %s", name, hs[0]);
7968       else
7969         print (vam->ofp, "No such msg / command '%s'", name);
7970       vec_free (name);
7971       return 0;
7972     }
7973
7974   print (vam->ofp, "Help is available for the following:");
7975
7976     /* *INDENT-OFF* */
7977     hash_foreach_pair (p, vam->function_by_name,
7978     ({
7979       vec_add1 (cmds, (u8 *)(p->key));
7980     }));
7981     /* *INDENT-ON* */
7982
7983   vec_sort_with_function (cmds, cmd_cmp);
7984
7985   for (j = 0; j < vec_len (cmds); j++)
7986     print (vam->ofp, "%s", cmds[j]);
7987
7988   vec_free (cmds);
7989   return 0;
7990 }
7991
7992 static int
7993 set (vat_main_t * vam)
7994 {
7995   u8 *name = 0, *value = 0;
7996   unformat_input_t *i = vam->input;
7997
7998   if (unformat (i, "%s", &name))
7999     {
8000       /* The input buffer is a vector, not a string. */
8001       value = vec_dup (i->buffer);
8002       vec_delete (value, i->index, 0);
8003       /* Almost certainly has a trailing newline */
8004       if (value[vec_len (value) - 1] == '\n')
8005         value[vec_len (value) - 1] = 0;
8006       /* Make sure it's a proper string, one way or the other */
8007       vec_add1 (value, 0);
8008       (void) clib_macro_set_value (&vam->macro_main,
8009                                    (char *) name, (char *) value);
8010     }
8011   else
8012     errmsg ("usage: set <name> <value>");
8013
8014   vec_free (name);
8015   vec_free (value);
8016   return 0;
8017 }
8018
8019 static int
8020 unset (vat_main_t * vam)
8021 {
8022   u8 *name = 0;
8023
8024   if (unformat (vam->input, "%s", &name))
8025     if (clib_macro_unset (&vam->macro_main, (char *) name) == 1)
8026       errmsg ("unset: %s wasn't set", name);
8027   vec_free (name);
8028   return 0;
8029 }
8030
8031 typedef struct
8032 {
8033   u8 *name;
8034   u8 *value;
8035 } macro_sort_t;
8036
8037
8038 static int
8039 macro_sort_cmp (void *a1, void *a2)
8040 {
8041   macro_sort_t *s1 = a1;
8042   macro_sort_t *s2 = a2;
8043
8044   return strcmp ((char *) (s1->name), (char *) (s2->name));
8045 }
8046
8047 static int
8048 dump_macro_table (vat_main_t * vam)
8049 {
8050   macro_sort_t *sort_me = 0, *sm;
8051   int i;
8052   hash_pair_t *p;
8053
8054     /* *INDENT-OFF* */
8055     hash_foreach_pair (p, vam->macro_main.the_value_table_hash,
8056     ({
8057       vec_add2 (sort_me, sm, 1);
8058       sm->name = (u8 *)(p->key);
8059       sm->value = (u8 *) (p->value[0]);
8060     }));
8061     /* *INDENT-ON* */
8062
8063   vec_sort_with_function (sort_me, macro_sort_cmp);
8064
8065   if (vec_len (sort_me))
8066     print (vam->ofp, "%-15s%s", "Name", "Value");
8067   else
8068     print (vam->ofp, "The macro table is empty...");
8069
8070   for (i = 0; i < vec_len (sort_me); i++)
8071     print (vam->ofp, "%-15s%s", sort_me[i].name, sort_me[i].value);
8072   return 0;
8073 }
8074
8075 static int
8076 dump_node_table (vat_main_t * vam)
8077 {
8078   int i, j;
8079   vlib_node_t *node, *next_node;
8080
8081   if (vec_len (vam->graph_nodes) == 0)
8082     {
8083       print (vam->ofp, "Node table empty, issue get_node_graph...");
8084       return 0;
8085     }
8086
8087   for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
8088     {
8089       node = vam->graph_nodes[0][i];
8090       print (vam->ofp, "[%d] %s", i, node->name);
8091       for (j = 0; j < vec_len (node->next_nodes); j++)
8092         {
8093           if (node->next_nodes[j] != ~0)
8094             {
8095               next_node = vam->graph_nodes[0][node->next_nodes[j]];
8096               print (vam->ofp, "  [%d] %s", j, next_node->name);
8097             }
8098         }
8099     }
8100   return 0;
8101 }
8102
8103 static int
8104 value_sort_cmp (void *a1, void *a2)
8105 {
8106   name_sort_t *n1 = a1;
8107   name_sort_t *n2 = a2;
8108
8109   if (n1->value < n2->value)
8110     return -1;
8111   if (n1->value > n2->value)
8112     return 1;
8113   return 0;
8114 }
8115
8116
8117 static int
8118 dump_msg_api_table (vat_main_t * vam)
8119 {
8120   api_main_t *am = vlibapi_get_main ();
8121   name_sort_t *nses = 0, *ns;
8122   hash_pair_t *hp;
8123   int i;
8124
8125   /* *INDENT-OFF* */
8126   hash_foreach_pair (hp, am->msg_index_by_name_and_crc,
8127   ({
8128     vec_add2 (nses, ns, 1);
8129     ns->name = (u8 *)(hp->key);
8130     ns->value = (u32) hp->value[0];
8131   }));
8132   /* *INDENT-ON* */
8133
8134   vec_sort_with_function (nses, value_sort_cmp);
8135
8136   for (i = 0; i < vec_len (nses); i++)
8137     print (vam->ofp, " [%d]: %s", nses[i].value, nses[i].name);
8138   vec_free (nses);
8139   return 0;
8140 }
8141
8142 static int
8143 get_msg_id (vat_main_t * vam)
8144 {
8145   u8 *name_and_crc;
8146   u32 message_index;
8147
8148   if (unformat (vam->input, "%s", &name_and_crc))
8149     {
8150       message_index = vl_msg_api_get_msg_index (name_and_crc);
8151       if (message_index == ~0)
8152         {
8153           print (vam->ofp, " '%s' not found", name_and_crc);
8154           return 0;
8155         }
8156       print (vam->ofp, " '%s' has message index %d",
8157              name_and_crc, message_index);
8158       return 0;
8159     }
8160   errmsg ("name_and_crc required...");
8161   return 0;
8162 }
8163
8164 static int
8165 search_node_table (vat_main_t * vam)
8166 {
8167   unformat_input_t *line_input = vam->input;
8168   u8 *node_to_find;
8169   int j;
8170   vlib_node_t *node, *next_node;
8171   uword *p;
8172
8173   if (vam->graph_node_index_by_name == 0)
8174     {
8175       print (vam->ofp, "Node table empty, issue get_node_graph...");
8176       return 0;
8177     }
8178
8179   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
8180     {
8181       if (unformat (line_input, "%s", &node_to_find))
8182         {
8183           vec_add1 (node_to_find, 0);
8184           p = hash_get_mem (vam->graph_node_index_by_name, node_to_find);
8185           if (p == 0)
8186             {
8187               print (vam->ofp, "%s not found...", node_to_find);
8188               goto out;
8189             }
8190           node = vam->graph_nodes[0][p[0]];
8191           print (vam->ofp, "[%d] %s", p[0], node->name);
8192           for (j = 0; j < vec_len (node->next_nodes); j++)
8193             {
8194               if (node->next_nodes[j] != ~0)
8195                 {
8196                   next_node = vam->graph_nodes[0][node->next_nodes[j]];
8197                   print (vam->ofp, "  [%d] %s", j, next_node->name);
8198                 }
8199             }
8200         }
8201
8202       else
8203         {
8204           clib_warning ("parse error '%U'", format_unformat_error,
8205                         line_input);
8206           return -99;
8207         }
8208
8209     out:
8210       vec_free (node_to_find);
8211
8212     }
8213
8214   return 0;
8215 }
8216
8217
8218 static int
8219 script (vat_main_t * vam)
8220 {
8221 #if (VPP_API_TEST_BUILTIN==0)
8222   u8 *s = 0;
8223   char *save_current_file;
8224   unformat_input_t save_input;
8225   jmp_buf save_jump_buf;
8226   u32 save_line_number;
8227
8228   FILE *new_fp, *save_ifp;
8229
8230   if (unformat (vam->input, "%s", &s))
8231     {
8232       new_fp = fopen ((char *) s, "r");
8233       if (new_fp == 0)
8234         {
8235           errmsg ("Couldn't open script file %s", s);
8236           vec_free (s);
8237           return -99;
8238         }
8239     }
8240   else
8241     {
8242       errmsg ("Missing script name");
8243       return -99;
8244     }
8245
8246   clib_memcpy (&save_input, &vam->input, sizeof (save_input));
8247   clib_memcpy (&save_jump_buf, &vam->jump_buf, sizeof (save_jump_buf));
8248   save_ifp = vam->ifp;
8249   save_line_number = vam->input_line_number;
8250   save_current_file = (char *) vam->current_file;
8251
8252   vam->input_line_number = 0;
8253   vam->ifp = new_fp;
8254   vam->current_file = s;
8255   do_one_file (vam);
8256
8257   clib_memcpy (&vam->input, &save_input, sizeof (save_input));
8258   clib_memcpy (&vam->jump_buf, &save_jump_buf, sizeof (save_jump_buf));
8259   vam->ifp = save_ifp;
8260   vam->input_line_number = save_line_number;
8261   vam->current_file = (u8 *) save_current_file;
8262   vec_free (s);
8263
8264   return 0;
8265 #else
8266   clib_warning ("use the exec command...");
8267   return -99;
8268 #endif
8269 }
8270
8271 static int
8272 echo (vat_main_t * vam)
8273 {
8274   print (vam->ofp, "%v", vam->input->buffer);
8275   return 0;
8276 }
8277
8278 /* List of API message constructors, CLI names map to api_xxx */
8279 #define foreach_vpe_api_msg                                             \
8280 _(create_loopback,"[mac <mac-addr>] [instance <instance>]")             \
8281 _(sw_interface_dump,"")                                                 \
8282 _(sw_interface_set_flags,                                               \
8283   "<intfc> | sw_if_index <id> admin-up | admin-down link-up | link down") \
8284 _(sw_interface_add_del_address,                                         \
8285   "<intfc> | sw_if_index <id> <ip4-address> | <ip6-address> [del] [del-all] ") \
8286 _(sw_interface_set_rx_mode,                                             \
8287   "<intfc> | sw_if_index <id> [queue <id>] <polling | interrupt | adaptive>") \
8288 _(sw_interface_set_rx_placement,                                        \
8289   "<intfc> | sw_if_index <id> [queue <id>] [worker <id> | main]")       \
8290 _(sw_interface_rx_placement_dump,                                       \
8291   "[<intfc> | sw_if_index <id>]")                                         \
8292 _(sw_interface_set_table,                                               \
8293   "<intfc> | sw_if_index <id> vrf <table-id> [ipv6]")                   \
8294 _(sw_interface_set_vpath,                                               \
8295   "<intfc> | sw_if_index <id> enable | disable")                        \
8296 _(sw_interface_set_l2_xconnect,                                         \
8297   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
8298   "enable | disable")                                                   \
8299 _(sw_interface_set_l2_bridge,                                           \
8300   "{<intfc> | sw_if_index <id>} bd_id <bridge-domain-id>\n"             \
8301   "[shg <split-horizon-group>] [bvi]\n"                                 \
8302   "enable | disable")                                                   \
8303 _(bridge_domain_set_mac_age, "bd_id <bridge-domain-id> mac-age 0-255")  \
8304 _(bridge_domain_add_del,                                                \
8305   "bd_id <bridge-domain-id> [flood 1|0] [uu-flood 1|0] [forward 1|0] [learn 1|0] [arp-term 1|0] [mac-age 0-255] [bd-tag <text>] [del]\n") \
8306 _(bridge_domain_dump, "[bd_id <bridge-domain-id>]\n")                   \
8307 _(l2fib_add_del,                                                        \
8308   "mac <mac-addr> bd_id <bridge-domain-id> [del] | sw_if <intfc> | sw_if_index <id> [static] [filter] [bvi] [count <nn>]\n") \
8309 _(l2fib_flush_bd, "bd_id <bridge-domain-id>")                           \
8310 _(l2fib_flush_int, "<intfc> | sw_if_index <id>")                        \
8311 _(l2_flags,                                                             \
8312   "sw_if <intfc> | sw_if_index <id> [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \
8313 _(bridge_flags,                                                         \
8314   "bd_id <bridge-domain-id> [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \
8315 _(virtio_pci_create_v2,                                                    \
8316   "pci-addr <pci-address> [use_random_mac | hw-addr <mac-addr>] [features <hex-value>] [gso-enabled [gro-coalesce] | csum-offload-enabled] [packed] [in-order] [buffering]") \
8317 _(virtio_pci_delete,                                                    \
8318   "<vpp-if-name> | sw_if_index <id>")                                   \
8319 _(sw_interface_virtio_pci_dump, "")                                     \
8320 _(ip_table_add_del,                                                     \
8321   "table <n> [ipv6] [add | del]\n")                                     \
8322 _(ip_route_add_del,                                                     \
8323   "<addr>/<mask> via <<addr>|<intfc>|sw_if_index <id>|via-label <n>>\n" \
8324   "[table-id <n>] [<intfc> | sw_if_index <id>] [resolve-attempts <n>]\n"\
8325   "[weight <n>] [drop] [local] [classify <n>]  [out-label <n>]\n"       \
8326   "[multipath] [count <n>] [del]")                                      \
8327 _(ip_mroute_add_del,                                                    \
8328   "<src> <grp>/<mask> [table-id <n>]\n"                                 \
8329   "[<intfc> | sw_if_index <id>] [local] [del]")                         \
8330 _(sw_interface_set_unnumbered,                                          \
8331   "<intfc> | sw_if_index <id> unnum_if_index <id> [del]")               \
8332 _(create_vlan_subif, "<intfc> | sw_if_index <id> vlan <n>")             \
8333 _(create_subif, "<intfc> | sw_if_index <id> sub_id <n>\n"               \
8334   "[outer_vlan_id <n>][inner_vlan_id <n>]\n"                            \
8335   "[no_tags][one_tag][two_tags][dot1ad][exact_match][default_sub]\n"    \
8336   "[outer_vlan_id_any][inner_vlan_id_any]")                             \
8337 _(ip_table_replace_begin, "table <n> [ipv6]")                           \
8338 _(ip_table_flush, "table <n> [ipv6]")                                   \
8339 _(ip_table_replace_end, "table <n> [ipv6]")                             \
8340 _(set_ip_flow_hash,                                                     \
8341   "vrf <n> [src] [dst] [sport] [dport] [proto] [reverse] [ipv6]")       \
8342 _(sw_interface_ip6_enable_disable,                                      \
8343   "<intfc> | sw_if_index <id> enable | disable")                        \
8344 _(l2_patch_add_del,                                                     \
8345   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
8346   "enable | disable")                                                   \
8347 _(get_node_index, "node <node-name")                                    \
8348 _(add_node_next, "node <node-name> next <next-node-name>")              \
8349 _(l2_fib_clear_table, "")                                               \
8350 _(l2_interface_efp_filter, "sw_if_index <nn> enable | disable")         \
8351 _(l2_interface_vlan_tag_rewrite,                                        \
8352   "<intfc> | sw_if_index <nn> \n"                                       \
8353   "[disable][push-[1|2]][pop-[1|2]][translate-1-[1|2]] \n"              \
8354   "[translate-2-[1|2]] [push_dot1q 0] tag1 <nn> tag2 <nn>")             \
8355 _(show_version, "")                                                     \
8356 _(show_threads, "")                                                     \
8357 _(l2_fib_table_dump, "bd_id <bridge-domain-id>")                        \
8358 _(interface_name_renumber,                                              \
8359   "<intfc> | sw_if_index <nn> new_show_dev_instance <nn>")              \
8360 _(want_l2_macs_events, "[disable] [learn-limit <n>] [scan-delay <n>] [max-entries <n>]") \
8361 _(ip_address_dump, "(ipv4 | ipv6) (<intfc> | sw_if_index <id>)")        \
8362 _(ip_dump, "ipv4 | ipv6")                                               \
8363 _(delete_loopback,"sw_if_index <nn>")                                   \
8364 _(bd_ip_mac_add_del, "bd_id <bridge-domain-id> <ip4/6-addr> <mac-addr> [del]") \
8365 _(bd_ip_mac_flush, "bd_id <bridge-domain-id>")                          \
8366 _(bd_ip_mac_dump, "[bd_id] <bridge-domain-id>")                         \
8367 _(want_interface_events,  "enable|disable")                             \
8368 _(get_first_msg_id, "client <name>")                                    \
8369 _(get_node_graph, " ")                                                  \
8370 _(sw_interface_clear_stats,"<intfc> | sw_if_index <nn>")                \
8371 _(ioam_enable, "[trace] [pow] [ppc <encap|decap>]")                     \
8372 _(ioam_disable, "")                                                     \
8373 _(get_next_index, "node-name <node-name> next-node-name <node-name>")   \
8374 _(ip_source_and_port_range_check_add_del,                               \
8375   "<ip-addr>/<mask> range <nn>-<nn> vrf <id>")                          \
8376 _(ip_source_and_port_range_check_interface_add_del,                     \
8377   "<intf> | sw_if_index <nn> [tcp-out-vrf <id>] [tcp-in-vrf <id>]"      \
8378   "[udp-in-vrf <id>] [udp-out-vrf <id>]")                               \
8379 _(delete_subif,"<intfc> | sw_if_index <nn>")                            \
8380 _(l2_interface_pbb_tag_rewrite,                                         \
8381   "<intfc> | sw_if_index <nn> \n"                                       \
8382   "[disable | push | pop | translate_pbb_stag <outer_tag>] \n"          \
8383   "dmac <mac> smac <mac> sid <nn> [vlanid <nn>]")                       \
8384 _(ip_table_dump, "")                                                    \
8385 _(ip_route_dump, "table-id [ip4|ip6]")                                  \
8386 _(ip_mtable_dump, "")                                                   \
8387 _(ip_mroute_dump, "table-id [ip4|ip6]")                                 \
8388 _(sw_interface_tag_add_del, "<intfc> | sw_if_index <nn> tag <text>"     \
8389 "[disable]")                                                            \
8390 _(sw_interface_add_del_mac_address, "<intfc> | sw_if_index <nn> "       \
8391   "mac <mac-address> [del]")                                            \
8392 _(l2_xconnect_dump, "")                                                 \
8393 _(hw_interface_set_mtu, "<intfc> | hw_if_index <nn> mtu <nn>")        \
8394 _(sw_interface_get_table, "<intfc> | sw_if_index <id> [ipv6]")          \
8395 _(sock_init_shm, "size <nnn>")                                          \
8396 _(app_namespace_add_del, "[add] id <ns-id> secret <nn> sw_if_index <nn>")\
8397 _(session_rule_add_del, "[add|del] proto <tcp/udp> <lcl-ip>/<plen> "    \
8398   "<lcl-port> <rmt-ip>/<plen> <rmt-port> action <nn>")                  \
8399 _(session_rules_dump, "")                                               \
8400 _(ip_container_proxy_add_del, "[add|del] <address> <sw_if_index>")      \
8401
8402 /* List of command functions, CLI names map directly to functions */
8403 #define foreach_cli_function                                    \
8404 _(comment, "usage: comment <ignore-rest-of-line>")              \
8405 _(dump_interface_table, "usage: dump_interface_table")          \
8406 _(dump_sub_interface_table, "usage: dump_sub_interface_table")  \
8407 _(dump_ipv4_table, "usage: dump_ipv4_table")                    \
8408 _(dump_ipv6_table, "usage: dump_ipv6_table")                    \
8409 _(dump_macro_table, "usage: dump_macro_table ")                 \
8410 _(dump_node_table, "usage: dump_node_table")                    \
8411 _(dump_msg_api_table, "usage: dump_msg_api_table")              \
8412 _(elog_setup, "usage: elog_setup [nevents, default 128K]")      \
8413 _(elog_disable, "usage: elog_disable")                          \
8414 _(elog_enable, "usage: elog_enable")                            \
8415 _(elog_save, "usage: elog_save <filename>")                     \
8416 _(get_msg_id, "usage: get_msg_id name_and_crc")                 \
8417 _(echo, "usage: echo <message>")                                \
8418 _(exec, "usage: exec <vpe-debug-CLI-command>")                  \
8419 _(exec_inband, "usage: exec_inband <vpe-debug-CLI-command>")    \
8420 _(help, "usage: help")                                          \
8421 _(q, "usage: quit")                                             \
8422 _(quit, "usage: quit")                                          \
8423 _(search_node_table, "usage: search_node_table <name>...")      \
8424 _(set, "usage: set <variable-name> <value>")                    \
8425 _(script, "usage: script <file-name>")                          \
8426 _(statseg, "usage: statseg")                                    \
8427 _(unset, "usage: unset <variable-name>")
8428
8429 #define _(N,n)                                  \
8430     static void vl_api_##n##_t_handler_uni      \
8431     (vl_api_##n##_t * mp)                       \
8432     {                                           \
8433         vat_main_t * vam = &vat_main;           \
8434         if (vam->json_output) {                 \
8435             vl_api_##n##_t_handler_json(mp);    \
8436         } else {                                \
8437             vl_api_##n##_t_handler(mp);         \
8438         }                                       \
8439     }
8440 foreach_vpe_api_reply_msg;
8441 #if VPP_API_TEST_BUILTIN == 0
8442 foreach_standalone_reply_msg;
8443 #endif
8444 #undef _
8445
8446 void
8447 vat_api_hookup (vat_main_t * vam)
8448 {
8449 #define _(N,n)                                                  \
8450     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
8451                            vl_api_##n##_t_handler_uni,          \
8452                            vl_noop_handler,                     \
8453                            vl_api_##n##_t_endian,               \
8454                            vl_api_##n##_t_print,                \
8455                            sizeof(vl_api_##n##_t), 1);
8456   foreach_vpe_api_reply_msg;
8457 #if VPP_API_TEST_BUILTIN == 0
8458   foreach_standalone_reply_msg;
8459 #endif
8460 #undef _
8461
8462 #if (VPP_API_TEST_BUILTIN==0)
8463   vl_msg_api_set_first_available_msg_id (VL_MSG_FIRST_AVAILABLE);
8464
8465   vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
8466
8467   vam->function_by_name = hash_create_string (0, sizeof (uword));
8468
8469   vam->help_by_name = hash_create_string (0, sizeof (uword));
8470 #endif
8471
8472   /* API messages we can send */
8473 #define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
8474   foreach_vpe_api_msg;
8475 #undef _
8476
8477   /* Help strings */
8478 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
8479   foreach_vpe_api_msg;
8480 #undef _
8481
8482   /* CLI functions */
8483 #define _(n,h) hash_set_mem (vam->function_by_name, #n, n);
8484   foreach_cli_function;
8485 #undef _
8486
8487   /* Help strings */
8488 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
8489   foreach_cli_function;
8490 #undef _
8491 }
8492
8493 #if VPP_API_TEST_BUILTIN
8494 static clib_error_t *
8495 vat_api_hookup_shim (vlib_main_t * vm)
8496 {
8497   vat_api_hookup (&vat_main);
8498   return 0;
8499 }
8500
8501 VLIB_API_INIT_FUNCTION (vat_api_hookup_shim);
8502 #endif
8503
8504 /*
8505  * fd.io coding-style-patch-verification: ON
8506  *
8507  * Local Variables:
8508  * eval: (c-set-style "gnu")
8509  * End:
8510  */