ethernet: 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 uword
430 unformat_ipsec_api_crypto_alg (unformat_input_t * input, va_list * args)
431 {
432   u32 *r = va_arg (*args, u32 *);
433
434   if (0);
435 #define _(v,f,s) else if (unformat (input, s)) *r = IPSEC_API_CRYPTO_ALG_##f;
436   foreach_ipsec_crypto_alg
437 #undef _
438     else
439     return 0;
440   return 1;
441 }
442
443 uword
444 unformat_ipsec_api_integ_alg (unformat_input_t * input, va_list * args)
445 {
446   u32 *r = va_arg (*args, u32 *);
447
448   if (0);
449 #define _(v,f,s) else if (unformat (input, s)) *r = IPSEC_API_INTEG_ALG_##f;
450   foreach_ipsec_integ_alg
451 #undef _
452     else
453     return 0;
454   return 1;
455 }
456
457 #if (VPP_API_TEST_BUILTIN==0)
458
459 static const char *mfib_flag_names[] = MFIB_ENTRY_NAMES_SHORT;
460 static const char *mfib_flag_long_names[] = MFIB_ENTRY_NAMES_LONG;
461 static const char *mfib_itf_flag_long_names[] = MFIB_ITF_NAMES_LONG;
462 static const char *mfib_itf_flag_names[] = MFIB_ITF_NAMES_SHORT;
463
464 uword
465 unformat_mfib_itf_flags (unformat_input_t * input, va_list * args)
466 {
467   mfib_itf_flags_t old, *iflags = va_arg (*args, mfib_itf_flags_t *);
468   mfib_itf_attribute_t attr;
469
470   old = *iflags;
471   FOR_EACH_MFIB_ITF_ATTRIBUTE (attr)
472   {
473     if (unformat (input, mfib_itf_flag_long_names[attr]))
474       *iflags |= (1 << attr);
475   }
476   FOR_EACH_MFIB_ITF_ATTRIBUTE (attr)
477   {
478     if (unformat (input, mfib_itf_flag_names[attr]))
479       *iflags |= (1 << attr);
480   }
481
482   return (old == *iflags ? 0 : 1);
483 }
484
485 uword
486 unformat_mfib_entry_flags (unformat_input_t * input, va_list * args)
487 {
488   mfib_entry_flags_t old, *eflags = va_arg (*args, mfib_entry_flags_t *);
489   mfib_entry_attribute_t attr;
490
491   old = *eflags;
492   FOR_EACH_MFIB_ATTRIBUTE (attr)
493   {
494     if (unformat (input, mfib_flag_long_names[attr]))
495       *eflags |= (1 << attr);
496   }
497   FOR_EACH_MFIB_ATTRIBUTE (attr)
498   {
499     if (unformat (input, mfib_flag_names[attr]))
500       *eflags |= (1 << attr);
501   }
502
503   return (old == *eflags ? 0 : 1);
504 }
505
506 u8 *
507 format_ip4_address (u8 * s, va_list * args)
508 {
509   u8 *a = va_arg (*args, u8 *);
510   return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
511 }
512
513 u8 *
514 format_ip6_address (u8 * s, va_list * args)
515 {
516   ip6_address_t *a = va_arg (*args, ip6_address_t *);
517   u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;
518
519   i_max_n_zero = ARRAY_LEN (a->as_u16);
520   max_n_zeros = 0;
521   i_first_zero = i_max_n_zero;
522   n_zeros = 0;
523   for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
524     {
525       u32 is_zero = a->as_u16[i] == 0;
526       if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16))
527         {
528           i_first_zero = i;
529           n_zeros = 0;
530         }
531       n_zeros += is_zero;
532       if ((!is_zero && n_zeros > max_n_zeros)
533           || (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros))
534         {
535           i_max_n_zero = i_first_zero;
536           max_n_zeros = n_zeros;
537           i_first_zero = ARRAY_LEN (a->as_u16);
538           n_zeros = 0;
539         }
540     }
541
542   last_double_colon = 0;
543   for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
544     {
545       if (i == i_max_n_zero && max_n_zeros > 1)
546         {
547           s = format (s, "::");
548           i += max_n_zeros - 1;
549           last_double_colon = 1;
550         }
551       else
552         {
553           s = format (s, "%s%x",
554                       (last_double_colon || i == 0) ? "" : ":",
555                       clib_net_to_host_u16 (a->as_u16[i]));
556           last_double_colon = 0;
557         }
558     }
559
560   return s;
561 }
562
563 /* Format an IP46 address. */
564 u8 *
565 format_ip46_address (u8 * s, va_list * args)
566 {
567   ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
568   ip46_type_t type = va_arg (*args, ip46_type_t);
569   int is_ip4 = 1;
570
571   switch (type)
572     {
573     case IP46_TYPE_ANY:
574       is_ip4 = ip46_address_is_ip4 (ip46);
575       break;
576     case IP46_TYPE_IP4:
577       is_ip4 = 1;
578       break;
579     case IP46_TYPE_IP6:
580       is_ip4 = 0;
581       break;
582     }
583
584   return is_ip4 ?
585     format (s, "%U", format_ip4_address, &ip46->ip4) :
586     format (s, "%U", format_ip6_address, &ip46->ip6);
587 }
588
589 u8 *
590 format_ethernet_address (u8 * s, va_list * args)
591 {
592   u8 *a = va_arg (*args, u8 *);
593
594   return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
595                  a[0], a[1], a[2], a[3], a[4], a[5]);
596 }
597 #endif
598
599 static void
600 increment_v4_address (vl_api_ip4_address_t * i)
601 {
602   ip4_address_t *a = (ip4_address_t *) i;
603   u32 v;
604
605   v = ntohl (a->as_u32) + 1;
606   a->as_u32 = ntohl (v);
607 }
608
609 static void
610 increment_v6_address (vl_api_ip6_address_t * i)
611 {
612   ip6_address_t *a = (ip6_address_t *) i;
613   u64 v0, v1;
614
615   v0 = clib_net_to_host_u64 (a->as_u64[0]);
616   v1 = clib_net_to_host_u64 (a->as_u64[1]);
617
618   v1 += 1;
619   if (v1 == 0)
620     v0 += 1;
621   a->as_u64[0] = clib_net_to_host_u64 (v0);
622   a->as_u64[1] = clib_net_to_host_u64 (v1);
623 }
624
625 static void
626 increment_address (vl_api_address_t * a)
627 {
628   if (a->af == ADDRESS_IP4)
629     increment_v4_address (&a->un.ip4);
630   else if (a->af == ADDRESS_IP6)
631     increment_v6_address (&a->un.ip6);
632 }
633
634 static void
635 set_ip4_address (vl_api_address_t * a, u32 v)
636 {
637   if (a->af == ADDRESS_IP4)
638     {
639       ip4_address_t *i = (ip4_address_t *) & a->un.ip4;
640       i->as_u32 = v;
641     }
642 }
643
644 void
645 ip_set (ip46_address_t * dst, void *src, u8 is_ip4)
646 {
647   if (is_ip4)
648     dst->ip4.as_u32 = ((ip4_address_t *) src)->as_u32;
649   else
650     clib_memcpy_fast (&dst->ip6, (ip6_address_t *) src,
651                       sizeof (ip6_address_t));
652 }
653
654 static void
655 increment_mac_address (u8 * mac)
656 {
657   u64 tmp = *((u64 *) mac);
658   tmp = clib_net_to_host_u64 (tmp);
659   tmp += 1 << 16;               /* skip unused (least significant) octets */
660   tmp = clib_host_to_net_u64 (tmp);
661
662   clib_memcpy (mac, &tmp, 6);
663 }
664
665 static void
666 vat_json_object_add_address (vat_json_node_t * node,
667                              const char *str, const vl_api_address_t * addr)
668 {
669   if (ADDRESS_IP6 == addr->af)
670     {
671       struct in6_addr ip6;
672
673       clib_memcpy (&ip6, &addr->un.ip6, sizeof (ip6));
674       vat_json_object_add_ip6 (node, str, ip6);
675     }
676   else
677     {
678       struct in_addr ip4;
679
680       clib_memcpy (&ip4, &addr->un.ip4, sizeof (ip4));
681       vat_json_object_add_ip4 (node, str, ip4);
682     }
683 }
684
685 static void
686 vat_json_object_add_prefix (vat_json_node_t * node,
687                             const vl_api_prefix_t * prefix)
688 {
689   vat_json_object_add_uint (node, "len", prefix->len);
690   vat_json_object_add_address (node, "address", &prefix->address);
691 }
692
693 static void vl_api_create_loopback_reply_t_handler
694   (vl_api_create_loopback_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_reply_t_handler_json
706   (vl_api_create_loopback_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_loopback_instance_reply_t_handler
722   (vl_api_create_loopback_instance_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_loopback_instance_reply_t_handler_json
734   (vl_api_create_loopback_instance_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   vam->retval = ntohl (mp->retval);
746   vam->result_ready = 1;
747 }
748
749 static void vl_api_af_packet_create_reply_t_handler
750   (vl_api_af_packet_create_reply_t * mp)
751 {
752   vat_main_t *vam = &vat_main;
753   i32 retval = ntohl (mp->retval);
754
755   vam->retval = retval;
756   vam->regenerate_interface_table = 1;
757   vam->sw_if_index = ntohl (mp->sw_if_index);
758   vam->result_ready = 1;
759 }
760
761 static void vl_api_af_packet_create_reply_t_handler_json
762   (vl_api_af_packet_create_reply_t * mp)
763 {
764   vat_main_t *vam = &vat_main;
765   vat_json_node_t node;
766
767   vat_json_init_object (&node);
768   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
769   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
770
771   vat_json_print (vam->ofp, &node);
772   vat_json_free (&node);
773
774   vam->retval = ntohl (mp->retval);
775   vam->result_ready = 1;
776 }
777
778 static void vl_api_create_vlan_subif_reply_t_handler
779   (vl_api_create_vlan_subif_reply_t * mp)
780 {
781   vat_main_t *vam = &vat_main;
782   i32 retval = ntohl (mp->retval);
783
784   vam->retval = retval;
785   vam->regenerate_interface_table = 1;
786   vam->sw_if_index = ntohl (mp->sw_if_index);
787   vam->result_ready = 1;
788 }
789
790 static void vl_api_create_vlan_subif_reply_t_handler_json
791   (vl_api_create_vlan_subif_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   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
799
800   vat_json_print (vam->ofp, &node);
801   vat_json_free (&node);
802
803   vam->retval = ntohl (mp->retval);
804   vam->result_ready = 1;
805 }
806
807 static void vl_api_create_subif_reply_t_handler
808   (vl_api_create_subif_reply_t * mp)
809 {
810   vat_main_t *vam = &vat_main;
811   i32 retval = ntohl (mp->retval);
812
813   vam->retval = retval;
814   vam->regenerate_interface_table = 1;
815   vam->sw_if_index = ntohl (mp->sw_if_index);
816   vam->result_ready = 1;
817 }
818
819 static void vl_api_create_subif_reply_t_handler_json
820   (vl_api_create_subif_reply_t * mp)
821 {
822   vat_main_t *vam = &vat_main;
823   vat_json_node_t node;
824
825   vat_json_init_object (&node);
826   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
827   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
828
829   vat_json_print (vam->ofp, &node);
830   vat_json_free (&node);
831
832   vam->retval = ntohl (mp->retval);
833   vam->result_ready = 1;
834 }
835
836 static void vl_api_interface_name_renumber_reply_t_handler
837   (vl_api_interface_name_renumber_reply_t * mp)
838 {
839   vat_main_t *vam = &vat_main;
840   i32 retval = ntohl (mp->retval);
841
842   vam->retval = retval;
843   vam->regenerate_interface_table = 1;
844   vam->result_ready = 1;
845 }
846
847 static void vl_api_interface_name_renumber_reply_t_handler_json
848   (vl_api_interface_name_renumber_reply_t * mp)
849 {
850   vat_main_t *vam = &vat_main;
851   vat_json_node_t node;
852
853   vat_json_init_object (&node);
854   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
855
856   vat_json_print (vam->ofp, &node);
857   vat_json_free (&node);
858
859   vam->retval = ntohl (mp->retval);
860   vam->result_ready = 1;
861 }
862
863 /*
864  * Special-case: build the interface table, maintain
865  * the next loopback sw_if_index vbl.
866  */
867 static void vl_api_sw_interface_details_t_handler
868   (vl_api_sw_interface_details_t * mp)
869 {
870   vat_main_t *vam = &vat_main;
871   u8 *s = format (0, "%s%c", mp->interface_name, 0);
872
873   hash_set_mem (vam->sw_if_index_by_interface_name, s,
874                 ntohl (mp->sw_if_index));
875
876   /* In sub interface case, fill the sub interface table entry */
877   if (mp->sw_if_index != mp->sup_sw_if_index)
878     {
879       sw_interface_subif_t *sub = NULL;
880
881       vec_add2 (vam->sw_if_subif_table, sub, 1);
882
883       vec_validate (sub->interface_name, strlen ((char *) s) + 1);
884       strncpy ((char *) sub->interface_name, (char *) s,
885                vec_len (sub->interface_name));
886       sub->sw_if_index = ntohl (mp->sw_if_index);
887       sub->sub_id = ntohl (mp->sub_id);
888
889       sub->raw_flags = ntohl (mp->sub_if_flags & SUB_IF_API_FLAG_MASK_VNET);
890
891       sub->sub_number_of_tags = mp->sub_number_of_tags;
892       sub->sub_outer_vlan_id = ntohs (mp->sub_outer_vlan_id);
893       sub->sub_inner_vlan_id = ntohs (mp->sub_inner_vlan_id);
894
895       /* vlan tag rewrite */
896       sub->vtr_op = ntohl (mp->vtr_op);
897       sub->vtr_push_dot1q = ntohl (mp->vtr_push_dot1q);
898       sub->vtr_tag1 = ntohl (mp->vtr_tag1);
899       sub->vtr_tag2 = ntohl (mp->vtr_tag2);
900     }
901 }
902
903 static void vl_api_sw_interface_details_t_handler_json
904   (vl_api_sw_interface_details_t * mp)
905 {
906   vat_main_t *vam = &vat_main;
907   vat_json_node_t *node = NULL;
908
909   if (VAT_JSON_ARRAY != vam->json_tree.type)
910     {
911       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
912       vat_json_init_array (&vam->json_tree);
913     }
914   node = vat_json_array_add (&vam->json_tree);
915
916   vat_json_init_object (node);
917   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
918   vat_json_object_add_uint (node, "sup_sw_if_index",
919                             ntohl (mp->sup_sw_if_index));
920   vat_json_object_add_bytes (node, "l2_address", mp->l2_address,
921                              sizeof (mp->l2_address));
922   vat_json_object_add_string_copy (node, "interface_name",
923                                    mp->interface_name);
924   vat_json_object_add_string_copy (node, "interface_dev_type",
925                                    mp->interface_dev_type);
926   vat_json_object_add_uint (node, "flags", mp->flags);
927   vat_json_object_add_uint (node, "link_duplex", mp->link_duplex);
928   vat_json_object_add_uint (node, "link_speed", mp->link_speed);
929   vat_json_object_add_uint (node, "mtu", ntohs (mp->link_mtu));
930   vat_json_object_add_uint (node, "sub_id", ntohl (mp->sub_id));
931   vat_json_object_add_uint (node, "sub_number_of_tags",
932                             mp->sub_number_of_tags);
933   vat_json_object_add_uint (node, "sub_outer_vlan_id",
934                             ntohs (mp->sub_outer_vlan_id));
935   vat_json_object_add_uint (node, "sub_inner_vlan_id",
936                             ntohs (mp->sub_inner_vlan_id));
937   vat_json_object_add_uint (node, "sub_if_flags", ntohl (mp->sub_if_flags));
938   vat_json_object_add_uint (node, "vtr_op", ntohl (mp->vtr_op));
939   vat_json_object_add_uint (node, "vtr_push_dot1q",
940                             ntohl (mp->vtr_push_dot1q));
941   vat_json_object_add_uint (node, "vtr_tag1", ntohl (mp->vtr_tag1));
942   vat_json_object_add_uint (node, "vtr_tag2", ntohl (mp->vtr_tag2));
943   if (ntohl (mp->sub_if_flags) & SUB_IF_API_FLAG_DOT1AH)
944     {
945       vat_json_object_add_string_copy (node, "pbb_vtr_dmac",
946                                        format (0, "%U",
947                                                format_ethernet_address,
948                                                &mp->b_dmac));
949       vat_json_object_add_string_copy (node, "pbb_vtr_smac",
950                                        format (0, "%U",
951                                                format_ethernet_address,
952                                                &mp->b_smac));
953       vat_json_object_add_uint (node, "pbb_vtr_b_vlanid", mp->b_vlanid);
954       vat_json_object_add_uint (node, "pbb_vtr_i_sid", mp->i_sid);
955     }
956 }
957
958 #if VPP_API_TEST_BUILTIN == 0
959 static void vl_api_sw_interface_event_t_handler
960   (vl_api_sw_interface_event_t * mp)
961 {
962   vat_main_t *vam = &vat_main;
963   if (vam->interface_event_display)
964     errmsg ("interface flags: sw_if_index %d %s %s",
965             ntohl (mp->sw_if_index),
966             ((ntohl (mp->flags)) & IF_STATUS_API_FLAG_ADMIN_UP) ?
967             "admin-up" : "admin-down",
968             ((ntohl (mp->flags)) & IF_STATUS_API_FLAG_LINK_UP) ?
969             "link-up" : "link-down");
970 }
971 #endif
972
973 __clib_unused static void
974 vl_api_sw_interface_event_t_handler_json (vl_api_sw_interface_event_t * mp)
975 {
976   /* JSON output not supported */
977 }
978
979 static void
980 vl_api_cli_reply_t_handler (vl_api_cli_reply_t * mp)
981 {
982   vat_main_t *vam = &vat_main;
983   i32 retval = ntohl (mp->retval);
984
985   vam->retval = retval;
986   vam->shmem_result = uword_to_pointer (mp->reply_in_shmem, u8 *);
987   vam->result_ready = 1;
988 }
989
990 static void
991 vl_api_cli_reply_t_handler_json (vl_api_cli_reply_t * mp)
992 {
993   vat_main_t *vam = &vat_main;
994   vat_json_node_t node;
995   void *oldheap;
996   u8 *reply;
997
998   vat_json_init_object (&node);
999   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1000   vat_json_object_add_uint (&node, "reply_in_shmem",
1001                             ntohl (mp->reply_in_shmem));
1002   /* Toss the shared-memory original... */
1003   oldheap = vl_msg_push_heap ();
1004
1005   reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
1006   vec_free (reply);
1007
1008   vl_msg_pop_heap (oldheap);
1009
1010   vat_json_print (vam->ofp, &node);
1011   vat_json_free (&node);
1012
1013   vam->retval = ntohl (mp->retval);
1014   vam->result_ready = 1;
1015 }
1016
1017 static void
1018 vl_api_cli_inband_reply_t_handler (vl_api_cli_inband_reply_t * mp)
1019 {
1020   vat_main_t *vam = &vat_main;
1021   i32 retval = ntohl (mp->retval);
1022
1023   vec_reset_length (vam->cmd_reply);
1024
1025   vam->retval = retval;
1026   if (retval == 0)
1027     vam->cmd_reply = vl_api_from_api_to_new_vec (mp, &mp->reply);
1028   vam->result_ready = 1;
1029 }
1030
1031 static void
1032 vl_api_cli_inband_reply_t_handler_json (vl_api_cli_inband_reply_t * mp)
1033 {
1034   vat_main_t *vam = &vat_main;
1035   vat_json_node_t node;
1036   u8 *reply = 0;                /* reply vector */
1037
1038   reply = vl_api_from_api_to_new_vec (mp, &mp->reply);
1039   vec_reset_length (vam->cmd_reply);
1040
1041   vat_json_init_object (&node);
1042   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1043   vat_json_object_add_string_copy (&node, "reply", reply);
1044
1045   vat_json_print (vam->ofp, &node);
1046   vat_json_free (&node);
1047   vec_free (reply);
1048
1049   vam->retval = ntohl (mp->retval);
1050   vam->result_ready = 1;
1051 }
1052
1053 static void vl_api_get_node_index_reply_t_handler
1054   (vl_api_get_node_index_reply_t * mp)
1055 {
1056   vat_main_t *vam = &vat_main;
1057   i32 retval = ntohl (mp->retval);
1058   if (vam->async_mode)
1059     {
1060       vam->async_errors += (retval < 0);
1061     }
1062   else
1063     {
1064       vam->retval = retval;
1065       if (retval == 0)
1066         errmsg ("node index %d", ntohl (mp->node_index));
1067       vam->result_ready = 1;
1068     }
1069 }
1070
1071 static void vl_api_get_node_index_reply_t_handler_json
1072   (vl_api_get_node_index_reply_t * mp)
1073 {
1074   vat_main_t *vam = &vat_main;
1075   vat_json_node_t node;
1076
1077   vat_json_init_object (&node);
1078   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1079   vat_json_object_add_uint (&node, "node_index", ntohl (mp->node_index));
1080
1081   vat_json_print (vam->ofp, &node);
1082   vat_json_free (&node);
1083
1084   vam->retval = ntohl (mp->retval);
1085   vam->result_ready = 1;
1086 }
1087
1088 static void vl_api_get_next_index_reply_t_handler
1089   (vl_api_get_next_index_reply_t * mp)
1090 {
1091   vat_main_t *vam = &vat_main;
1092   i32 retval = ntohl (mp->retval);
1093   if (vam->async_mode)
1094     {
1095       vam->async_errors += (retval < 0);
1096     }
1097   else
1098     {
1099       vam->retval = retval;
1100       if (retval == 0)
1101         errmsg ("next node index %d", ntohl (mp->next_index));
1102       vam->result_ready = 1;
1103     }
1104 }
1105
1106 static void vl_api_get_next_index_reply_t_handler_json
1107   (vl_api_get_next_index_reply_t * mp)
1108 {
1109   vat_main_t *vam = &vat_main;
1110   vat_json_node_t node;
1111
1112   vat_json_init_object (&node);
1113   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1114   vat_json_object_add_uint (&node, "next_index", ntohl (mp->next_index));
1115
1116   vat_json_print (vam->ofp, &node);
1117   vat_json_free (&node);
1118
1119   vam->retval = ntohl (mp->retval);
1120   vam->result_ready = 1;
1121 }
1122
1123 static void vl_api_add_node_next_reply_t_handler
1124   (vl_api_add_node_next_reply_t * mp)
1125 {
1126   vat_main_t *vam = &vat_main;
1127   i32 retval = ntohl (mp->retval);
1128   if (vam->async_mode)
1129     {
1130       vam->async_errors += (retval < 0);
1131     }
1132   else
1133     {
1134       vam->retval = retval;
1135       if (retval == 0)
1136         errmsg ("next index %d", ntohl (mp->next_index));
1137       vam->result_ready = 1;
1138     }
1139 }
1140
1141 static void vl_api_add_node_next_reply_t_handler_json
1142   (vl_api_add_node_next_reply_t * mp)
1143 {
1144   vat_main_t *vam = &vat_main;
1145   vat_json_node_t node;
1146
1147   vat_json_init_object (&node);
1148   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1149   vat_json_object_add_uint (&node, "next_index", ntohl (mp->next_index));
1150
1151   vat_json_print (vam->ofp, &node);
1152   vat_json_free (&node);
1153
1154   vam->retval = ntohl (mp->retval);
1155   vam->result_ready = 1;
1156 }
1157
1158 static void vl_api_show_version_reply_t_handler
1159   (vl_api_show_version_reply_t * mp)
1160 {
1161   vat_main_t *vam = &vat_main;
1162   i32 retval = ntohl (mp->retval);
1163
1164   if (retval >= 0)
1165     {
1166       errmsg ("        program: %s", mp->program);
1167       errmsg ("        version: %s", mp->version);
1168       errmsg ("     build date: %s", mp->build_date);
1169       errmsg ("build directory: %s", mp->build_directory);
1170     }
1171   vam->retval = retval;
1172   vam->result_ready = 1;
1173 }
1174
1175 static void vl_api_show_version_reply_t_handler_json
1176   (vl_api_show_version_reply_t * mp)
1177 {
1178   vat_main_t *vam = &vat_main;
1179   vat_json_node_t node;
1180
1181   vat_json_init_object (&node);
1182   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1183   vat_json_object_add_string_copy (&node, "program", mp->program);
1184   vat_json_object_add_string_copy (&node, "version", mp->version);
1185   vat_json_object_add_string_copy (&node, "build_date", mp->build_date);
1186   vat_json_object_add_string_copy (&node, "build_directory",
1187                                    mp->build_directory);
1188
1189   vat_json_print (vam->ofp, &node);
1190   vat_json_free (&node);
1191
1192   vam->retval = ntohl (mp->retval);
1193   vam->result_ready = 1;
1194 }
1195
1196 static void vl_api_show_threads_reply_t_handler
1197   (vl_api_show_threads_reply_t * mp)
1198 {
1199   vat_main_t *vam = &vat_main;
1200   i32 retval = ntohl (mp->retval);
1201   int i, count = 0;
1202
1203   if (retval >= 0)
1204     count = ntohl (mp->count);
1205
1206   for (i = 0; i < count; i++)
1207     print (vam->ofp,
1208            "\n%-2d %-11s %-11s %-5d %-6d %-4d %-6d",
1209            ntohl (mp->thread_data[i].id), mp->thread_data[i].name,
1210            mp->thread_data[i].type, ntohl (mp->thread_data[i].pid),
1211            ntohl (mp->thread_data[i].cpu_id), ntohl (mp->thread_data[i].core),
1212            ntohl (mp->thread_data[i].cpu_socket));
1213
1214   vam->retval = retval;
1215   vam->result_ready = 1;
1216 }
1217
1218 static void vl_api_show_threads_reply_t_handler_json
1219   (vl_api_show_threads_reply_t * mp)
1220 {
1221   vat_main_t *vam = &vat_main;
1222   vat_json_node_t node;
1223   vl_api_thread_data_t *td;
1224   i32 retval = ntohl (mp->retval);
1225   int i, count = 0;
1226
1227   if (retval >= 0)
1228     count = ntohl (mp->count);
1229
1230   vat_json_init_object (&node);
1231   vat_json_object_add_int (&node, "retval", retval);
1232   vat_json_object_add_uint (&node, "count", count);
1233
1234   for (i = 0; i < count; i++)
1235     {
1236       td = &mp->thread_data[i];
1237       vat_json_object_add_uint (&node, "id", ntohl (td->id));
1238       vat_json_object_add_string_copy (&node, "name", td->name);
1239       vat_json_object_add_string_copy (&node, "type", td->type);
1240       vat_json_object_add_uint (&node, "pid", ntohl (td->pid));
1241       vat_json_object_add_int (&node, "cpu_id", ntohl (td->cpu_id));
1242       vat_json_object_add_int (&node, "core", ntohl (td->id));
1243       vat_json_object_add_int (&node, "cpu_socket", ntohl (td->cpu_socket));
1244     }
1245
1246   vat_json_print (vam->ofp, &node);
1247   vat_json_free (&node);
1248
1249   vam->retval = retval;
1250   vam->result_ready = 1;
1251 }
1252
1253 static int
1254 api_show_threads (vat_main_t * vam)
1255 {
1256   vl_api_show_threads_t *mp;
1257   int ret;
1258
1259   print (vam->ofp,
1260          "\n%-2s %-11s %-11s %-5s %-6s %-4s %-6s",
1261          "ID", "Name", "Type", "LWP", "cpu_id", "Core", "Socket");
1262
1263   M (SHOW_THREADS, mp);
1264
1265   S (mp);
1266   W (ret);
1267   return ret;
1268 }
1269
1270 static void
1271 vl_api_l2_macs_event_t_handler (vl_api_l2_macs_event_t * mp)
1272 {
1273   u32 n_macs = ntohl (mp->n_macs);
1274   errmsg ("L2MAC event received with pid %d cl-idx %d for %d macs: \n",
1275           ntohl (mp->pid), mp->client_index, n_macs);
1276   int i;
1277   for (i = 0; i < n_macs; i++)
1278     {
1279       vl_api_mac_entry_t *mac = &mp->mac[i];
1280       errmsg (" [%d] sw_if_index %d  mac_addr %U  action %d \n",
1281               i + 1, ntohl (mac->sw_if_index),
1282               format_ethernet_address, mac->mac_addr, mac->action);
1283       if (i == 1000)
1284         break;
1285     }
1286 }
1287
1288 static void
1289 vl_api_l2_macs_event_t_handler_json (vl_api_l2_macs_event_t * mp)
1290 {
1291   /* JSON output not supported */
1292 }
1293
1294 #define vl_api_bridge_domain_details_t_endian vl_noop_handler
1295 #define vl_api_bridge_domain_details_t_print vl_noop_handler
1296
1297 /*
1298  * Special-case: build the bridge domain table, maintain
1299  * the next bd id vbl.
1300  */
1301 static void vl_api_bridge_domain_details_t_handler
1302   (vl_api_bridge_domain_details_t * mp)
1303 {
1304   vat_main_t *vam = &vat_main;
1305   u32 n_sw_ifs = ntohl (mp->n_sw_ifs);
1306   int i;
1307
1308   print (vam->ofp, "\n%-3s %-3s %-3s %-3s %-3s %-6s %-3s",
1309          " ID", "LRN", "FWD", "FLD", "BVI", "UU-FWD", "#IF");
1310
1311   print (vam->ofp, "%3d %3d %3d %3d %3d %6d %3d",
1312          ntohl (mp->bd_id), mp->learn, mp->forward,
1313          mp->flood, ntohl (mp->bvi_sw_if_index),
1314          ntohl (mp->uu_fwd_sw_if_index), n_sw_ifs);
1315
1316   if (n_sw_ifs)
1317     {
1318       vl_api_bridge_domain_sw_if_t *sw_ifs;
1319       print (vam->ofp, "\n\n%s %s  %s", "sw_if_index", "SHG",
1320              "Interface Name");
1321
1322       sw_ifs = mp->sw_if_details;
1323       for (i = 0; i < n_sw_ifs; i++)
1324         {
1325           u8 *sw_if_name = 0;
1326           u32 sw_if_index;
1327           hash_pair_t *p;
1328
1329           sw_if_index = ntohl (sw_ifs->sw_if_index);
1330
1331           /* *INDENT-OFF* */
1332           hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
1333                              ({
1334                                if ((u32) p->value[0] == sw_if_index)
1335                                  {
1336                                    sw_if_name = (u8 *)(p->key);
1337                                    break;
1338                                  }
1339                              }));
1340           /* *INDENT-ON* */
1341           print (vam->ofp, "%7d     %3d  %s", sw_if_index,
1342                  sw_ifs->shg, sw_if_name ? (char *) sw_if_name :
1343                  "sw_if_index not found!");
1344
1345           sw_ifs++;
1346         }
1347     }
1348 }
1349
1350 static void vl_api_bridge_domain_details_t_handler_json
1351   (vl_api_bridge_domain_details_t * mp)
1352 {
1353   vat_main_t *vam = &vat_main;
1354   vat_json_node_t *node, *array = NULL;
1355   u32 n_sw_ifs = ntohl (mp->n_sw_ifs);
1356
1357   if (VAT_JSON_ARRAY != vam->json_tree.type)
1358     {
1359       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
1360       vat_json_init_array (&vam->json_tree);
1361     }
1362   node = vat_json_array_add (&vam->json_tree);
1363
1364   vat_json_init_object (node);
1365   vat_json_object_add_uint (node, "bd_id", ntohl (mp->bd_id));
1366   vat_json_object_add_uint (node, "flood", mp->flood);
1367   vat_json_object_add_uint (node, "forward", mp->forward);
1368   vat_json_object_add_uint (node, "learn", mp->learn);
1369   vat_json_object_add_uint (node, "bvi_sw_if_index",
1370                             ntohl (mp->bvi_sw_if_index));
1371   vat_json_object_add_uint (node, "n_sw_ifs", n_sw_ifs);
1372   array = vat_json_object_add (node, "sw_if");
1373   vat_json_init_array (array);
1374
1375
1376
1377   if (n_sw_ifs)
1378     {
1379       vl_api_bridge_domain_sw_if_t *sw_ifs;
1380       int i;
1381
1382       sw_ifs = mp->sw_if_details;
1383       for (i = 0; i < n_sw_ifs; i++)
1384         {
1385           node = vat_json_array_add (array);
1386           vat_json_init_object (node);
1387           vat_json_object_add_uint (node, "sw_if_index",
1388                                     ntohl (sw_ifs->sw_if_index));
1389           vat_json_object_add_uint (node, "shg", sw_ifs->shg);
1390           sw_ifs++;
1391         }
1392     }
1393 }
1394
1395 static void vl_api_control_ping_reply_t_handler
1396   (vl_api_control_ping_reply_t * mp)
1397 {
1398   vat_main_t *vam = &vat_main;
1399   i32 retval = ntohl (mp->retval);
1400   if (vam->async_mode)
1401     {
1402       vam->async_errors += (retval < 0);
1403     }
1404   else
1405     {
1406       vam->retval = retval;
1407       vam->result_ready = 1;
1408     }
1409   if (vam->socket_client_main)
1410     vam->socket_client_main->control_pings_outstanding--;
1411 }
1412
1413 static void vl_api_control_ping_reply_t_handler_json
1414   (vl_api_control_ping_reply_t * mp)
1415 {
1416   vat_main_t *vam = &vat_main;
1417   i32 retval = ntohl (mp->retval);
1418
1419   if (VAT_JSON_NONE != vam->json_tree.type)
1420     {
1421       vat_json_print (vam->ofp, &vam->json_tree);
1422       vat_json_free (&vam->json_tree);
1423       vam->json_tree.type = VAT_JSON_NONE;
1424     }
1425   else
1426     {
1427       /* just print [] */
1428       vat_json_init_array (&vam->json_tree);
1429       vat_json_print (vam->ofp, &vam->json_tree);
1430       vam->json_tree.type = VAT_JSON_NONE;
1431     }
1432
1433   vam->retval = retval;
1434   vam->result_ready = 1;
1435 }
1436
1437 static void
1438   vl_api_bridge_domain_set_mac_age_reply_t_handler
1439   (vl_api_bridge_domain_set_mac_age_reply_t * mp)
1440 {
1441   vat_main_t *vam = &vat_main;
1442   i32 retval = ntohl (mp->retval);
1443   if (vam->async_mode)
1444     {
1445       vam->async_errors += (retval < 0);
1446     }
1447   else
1448     {
1449       vam->retval = retval;
1450       vam->result_ready = 1;
1451     }
1452 }
1453
1454 static void vl_api_bridge_domain_set_mac_age_reply_t_handler_json
1455   (vl_api_bridge_domain_set_mac_age_reply_t * mp)
1456 {
1457   vat_main_t *vam = &vat_main;
1458   vat_json_node_t node;
1459
1460   vat_json_init_object (&node);
1461   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1462
1463   vat_json_print (vam->ofp, &node);
1464   vat_json_free (&node);
1465
1466   vam->retval = ntohl (mp->retval);
1467   vam->result_ready = 1;
1468 }
1469
1470 static void
1471 vl_api_l2_flags_reply_t_handler (vl_api_l2_flags_reply_t * mp)
1472 {
1473   vat_main_t *vam = &vat_main;
1474   i32 retval = ntohl (mp->retval);
1475   if (vam->async_mode)
1476     {
1477       vam->async_errors += (retval < 0);
1478     }
1479   else
1480     {
1481       vam->retval = retval;
1482       vam->result_ready = 1;
1483     }
1484 }
1485
1486 static void vl_api_l2_flags_reply_t_handler_json
1487   (vl_api_l2_flags_reply_t * mp)
1488 {
1489   vat_main_t *vam = &vat_main;
1490   vat_json_node_t node;
1491
1492   vat_json_init_object (&node);
1493   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1494   vat_json_object_add_uint (&node, "resulting_feature_bitmap",
1495                             ntohl (mp->resulting_feature_bitmap));
1496
1497   vat_json_print (vam->ofp, &node);
1498   vat_json_free (&node);
1499
1500   vam->retval = ntohl (mp->retval);
1501   vam->result_ready = 1;
1502 }
1503
1504 static void vl_api_bridge_flags_reply_t_handler
1505   (vl_api_bridge_flags_reply_t * mp)
1506 {
1507   vat_main_t *vam = &vat_main;
1508   i32 retval = ntohl (mp->retval);
1509   if (vam->async_mode)
1510     {
1511       vam->async_errors += (retval < 0);
1512     }
1513   else
1514     {
1515       vam->retval = retval;
1516       vam->result_ready = 1;
1517     }
1518 }
1519
1520 static void vl_api_bridge_flags_reply_t_handler_json
1521   (vl_api_bridge_flags_reply_t * mp)
1522 {
1523   vat_main_t *vam = &vat_main;
1524   vat_json_node_t node;
1525
1526   vat_json_init_object (&node);
1527   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1528   vat_json_object_add_uint (&node, "resulting_feature_bitmap",
1529                             ntohl (mp->resulting_feature_bitmap));
1530
1531   vat_json_print (vam->ofp, &node);
1532   vat_json_free (&node);
1533
1534   vam->retval = ntohl (mp->retval);
1535   vam->result_ready = 1;
1536 }
1537
1538 static void
1539 vl_api_tap_create_v2_reply_t_handler (vl_api_tap_create_v2_reply_t * mp)
1540 {
1541   vat_main_t *vam = &vat_main;
1542   i32 retval = ntohl (mp->retval);
1543   if (vam->async_mode)
1544     {
1545       vam->async_errors += (retval < 0);
1546     }
1547   else
1548     {
1549       vam->retval = retval;
1550       vam->sw_if_index = ntohl (mp->sw_if_index);
1551       vam->result_ready = 1;
1552     }
1553
1554 }
1555
1556 static void vl_api_tap_create_v2_reply_t_handler_json
1557   (vl_api_tap_create_v2_reply_t * mp)
1558 {
1559   vat_main_t *vam = &vat_main;
1560   vat_json_node_t node;
1561
1562   vat_json_init_object (&node);
1563   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1564   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1565
1566   vat_json_print (vam->ofp, &node);
1567   vat_json_free (&node);
1568
1569   vam->retval = ntohl (mp->retval);
1570   vam->result_ready = 1;
1571
1572 }
1573
1574 static void
1575 vl_api_tap_delete_v2_reply_t_handler (vl_api_tap_delete_v2_reply_t * mp)
1576 {
1577   vat_main_t *vam = &vat_main;
1578   i32 retval = ntohl (mp->retval);
1579   if (vam->async_mode)
1580     {
1581       vam->async_errors += (retval < 0);
1582     }
1583   else
1584     {
1585       vam->retval = retval;
1586       vam->result_ready = 1;
1587     }
1588 }
1589
1590 static void vl_api_tap_delete_v2_reply_t_handler_json
1591   (vl_api_tap_delete_v2_reply_t * mp)
1592 {
1593   vat_main_t *vam = &vat_main;
1594   vat_json_node_t node;
1595
1596   vat_json_init_object (&node);
1597   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1598
1599   vat_json_print (vam->ofp, &node);
1600   vat_json_free (&node);
1601
1602   vam->retval = ntohl (mp->retval);
1603   vam->result_ready = 1;
1604 }
1605
1606 static void
1607 vl_api_virtio_pci_create_reply_t_handler (vl_api_virtio_pci_create_reply_t *
1608                                           mp)
1609 {
1610   vat_main_t *vam = &vat_main;
1611   i32 retval = ntohl (mp->retval);
1612   if (vam->async_mode)
1613     {
1614       vam->async_errors += (retval < 0);
1615     }
1616   else
1617     {
1618       vam->retval = retval;
1619       vam->sw_if_index = ntohl (mp->sw_if_index);
1620       vam->result_ready = 1;
1621     }
1622 }
1623
1624 static void vl_api_virtio_pci_create_reply_t_handler_json
1625   (vl_api_virtio_pci_create_reply_t * mp)
1626 {
1627   vat_main_t *vam = &vat_main;
1628   vat_json_node_t node;
1629
1630   vat_json_init_object (&node);
1631   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1632   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1633
1634   vat_json_print (vam->ofp, &node);
1635   vat_json_free (&node);
1636
1637   vam->retval = ntohl (mp->retval);
1638   vam->result_ready = 1;
1639
1640 }
1641
1642 static void
1643   vl_api_virtio_pci_create_v2_reply_t_handler
1644   (vl_api_virtio_pci_create_v2_reply_t * mp)
1645 {
1646   vat_main_t *vam = &vat_main;
1647   i32 retval = ntohl (mp->retval);
1648   if (vam->async_mode)
1649     {
1650       vam->async_errors += (retval < 0);
1651     }
1652   else
1653     {
1654       vam->retval = retval;
1655       vam->sw_if_index = ntohl (mp->sw_if_index);
1656       vam->result_ready = 1;
1657     }
1658 }
1659
1660 static void vl_api_virtio_pci_create_v2_reply_t_handler_json
1661   (vl_api_virtio_pci_create_v2_reply_t * mp)
1662 {
1663   vat_main_t *vam = &vat_main;
1664   vat_json_node_t node;
1665
1666   vat_json_init_object (&node);
1667   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1668   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1669
1670   vat_json_print (vam->ofp, &node);
1671   vat_json_free (&node);
1672
1673   vam->retval = ntohl (mp->retval);
1674   vam->result_ready = 1;
1675 }
1676
1677 static void
1678 vl_api_virtio_pci_delete_reply_t_handler (vl_api_virtio_pci_delete_reply_t *
1679                                           mp)
1680 {
1681   vat_main_t *vam = &vat_main;
1682   i32 retval = ntohl (mp->retval);
1683   if (vam->async_mode)
1684     {
1685       vam->async_errors += (retval < 0);
1686     }
1687   else
1688     {
1689       vam->retval = retval;
1690       vam->result_ready = 1;
1691     }
1692 }
1693
1694 static void vl_api_virtio_pci_delete_reply_t_handler_json
1695   (vl_api_virtio_pci_delete_reply_t * mp)
1696 {
1697   vat_main_t *vam = &vat_main;
1698   vat_json_node_t node;
1699
1700   vat_json_init_object (&node);
1701   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1702
1703   vat_json_print (vam->ofp, &node);
1704   vat_json_free (&node);
1705
1706   vam->retval = ntohl (mp->retval);
1707   vam->result_ready = 1;
1708 }
1709
1710 static void
1711 vl_api_bond_create_reply_t_handler (vl_api_bond_create_reply_t * mp)
1712 {
1713   vat_main_t *vam = &vat_main;
1714   i32 retval = ntohl (mp->retval);
1715
1716   if (vam->async_mode)
1717     {
1718       vam->async_errors += (retval < 0);
1719     }
1720   else
1721     {
1722       vam->retval = retval;
1723       vam->sw_if_index = ntohl (mp->sw_if_index);
1724       vam->result_ready = 1;
1725     }
1726 }
1727
1728 static void vl_api_bond_create_reply_t_handler_json
1729   (vl_api_bond_create_reply_t * mp)
1730 {
1731   vat_main_t *vam = &vat_main;
1732   vat_json_node_t node;
1733
1734   vat_json_init_object (&node);
1735   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1736   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1737
1738   vat_json_print (vam->ofp, &node);
1739   vat_json_free (&node);
1740
1741   vam->retval = ntohl (mp->retval);
1742   vam->result_ready = 1;
1743 }
1744
1745 static void
1746 vl_api_bond_create2_reply_t_handler (vl_api_bond_create2_reply_t * mp)
1747 {
1748   vat_main_t *vam = &vat_main;
1749   i32 retval = ntohl (mp->retval);
1750
1751   if (vam->async_mode)
1752     {
1753       vam->async_errors += (retval < 0);
1754     }
1755   else
1756     {
1757       vam->retval = retval;
1758       vam->sw_if_index = ntohl (mp->sw_if_index);
1759       vam->result_ready = 1;
1760     }
1761 }
1762
1763 static void vl_api_bond_create2_reply_t_handler_json
1764   (vl_api_bond_create2_reply_t * mp)
1765 {
1766   vat_main_t *vam = &vat_main;
1767   vat_json_node_t node;
1768
1769   vat_json_init_object (&node);
1770   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1771   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1772
1773   vat_json_print (vam->ofp, &node);
1774   vat_json_free (&node);
1775
1776   vam->retval = ntohl (mp->retval);
1777   vam->result_ready = 1;
1778 }
1779
1780 static void
1781 vl_api_bond_delete_reply_t_handler (vl_api_bond_delete_reply_t * mp)
1782 {
1783   vat_main_t *vam = &vat_main;
1784   i32 retval = ntohl (mp->retval);
1785
1786   if (vam->async_mode)
1787     {
1788       vam->async_errors += (retval < 0);
1789     }
1790   else
1791     {
1792       vam->retval = retval;
1793       vam->result_ready = 1;
1794     }
1795 }
1796
1797 static void vl_api_bond_delete_reply_t_handler_json
1798   (vl_api_bond_delete_reply_t * mp)
1799 {
1800   vat_main_t *vam = &vat_main;
1801   vat_json_node_t node;
1802
1803   vat_json_init_object (&node);
1804   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1805
1806   vat_json_print (vam->ofp, &node);
1807   vat_json_free (&node);
1808
1809   vam->retval = ntohl (mp->retval);
1810   vam->result_ready = 1;
1811 }
1812
1813 static void
1814 vl_api_bond_add_member_reply_t_handler (vl_api_bond_add_member_reply_t * mp)
1815 {
1816   vat_main_t *vam = &vat_main;
1817   i32 retval = ntohl (mp->retval);
1818
1819   if (vam->async_mode)
1820     {
1821       vam->async_errors += (retval < 0);
1822     }
1823   else
1824     {
1825       vam->retval = retval;
1826       vam->result_ready = 1;
1827     }
1828 }
1829
1830 static void vl_api_bond_add_member_reply_t_handler_json
1831   (vl_api_bond_add_member_reply_t * mp)
1832 {
1833   vat_main_t *vam = &vat_main;
1834   vat_json_node_t node;
1835
1836   vat_json_init_object (&node);
1837   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1838
1839   vat_json_print (vam->ofp, &node);
1840   vat_json_free (&node);
1841
1842   vam->retval = ntohl (mp->retval);
1843   vam->result_ready = 1;
1844 }
1845
1846 static void
1847 vl_api_bond_detach_member_reply_t_handler (vl_api_bond_detach_member_reply_t *
1848                                            mp)
1849 {
1850   vat_main_t *vam = &vat_main;
1851   i32 retval = ntohl (mp->retval);
1852
1853   if (vam->async_mode)
1854     {
1855       vam->async_errors += (retval < 0);
1856     }
1857   else
1858     {
1859       vam->retval = retval;
1860       vam->result_ready = 1;
1861     }
1862 }
1863
1864 static void vl_api_bond_detach_member_reply_t_handler_json
1865   (vl_api_bond_detach_member_reply_t * mp)
1866 {
1867   vat_main_t *vam = &vat_main;
1868   vat_json_node_t node;
1869
1870   vat_json_init_object (&node);
1871   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1872
1873   vat_json_print (vam->ofp, &node);
1874   vat_json_free (&node);
1875
1876   vam->retval = ntohl (mp->retval);
1877   vam->result_ready = 1;
1878 }
1879
1880 static int
1881 api_sw_interface_set_bond_weight (vat_main_t * vam)
1882 {
1883   unformat_input_t *i = vam->input;
1884   vl_api_sw_interface_set_bond_weight_t *mp;
1885   u32 sw_if_index = ~0;
1886   u32 weight = 0;
1887   u8 weight_enter = 0;
1888   int ret;
1889
1890   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1891     {
1892       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
1893         ;
1894       else if (unformat (i, "sw_if_index %d", &sw_if_index))
1895         ;
1896       else if (unformat (i, "weight %u", &weight))
1897         weight_enter = 1;
1898       else
1899         break;
1900     }
1901
1902   if (sw_if_index == ~0)
1903     {
1904       errmsg ("missing interface name or sw_if_index");
1905       return -99;
1906     }
1907   if (weight_enter == 0)
1908     {
1909       errmsg ("missing valid weight");
1910       return -99;
1911     }
1912
1913   /* Construct the API message */
1914   M (SW_INTERFACE_SET_BOND_WEIGHT, mp);
1915   mp->sw_if_index = ntohl (sw_if_index);
1916   mp->weight = ntohl (weight);
1917
1918   S (mp);
1919   W (ret);
1920   return ret;
1921 }
1922
1923 static void vl_api_sw_bond_interface_details_t_handler
1924   (vl_api_sw_bond_interface_details_t * mp)
1925 {
1926   vat_main_t *vam = &vat_main;
1927
1928   print (vam->ofp,
1929          "%-16s %-12d %-12U %-13U %-14u %-14u",
1930          mp->interface_name, ntohl (mp->sw_if_index),
1931          format_bond_mode, ntohl (mp->mode), format_bond_load_balance,
1932          ntohl (mp->lb), ntohl (mp->active_members), ntohl (mp->members));
1933 }
1934
1935 static void vl_api_sw_bond_interface_details_t_handler_json
1936   (vl_api_sw_bond_interface_details_t * mp)
1937 {
1938   vat_main_t *vam = &vat_main;
1939   vat_json_node_t *node = NULL;
1940
1941   if (VAT_JSON_ARRAY != vam->json_tree.type)
1942     {
1943       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
1944       vat_json_init_array (&vam->json_tree);
1945     }
1946   node = vat_json_array_add (&vam->json_tree);
1947
1948   vat_json_init_object (node);
1949   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
1950   vat_json_object_add_string_copy (node, "interface_name",
1951                                    mp->interface_name);
1952   vat_json_object_add_uint (node, "mode", ntohl (mp->mode));
1953   vat_json_object_add_uint (node, "load_balance", ntohl (mp->lb));
1954   vat_json_object_add_uint (node, "active_members",
1955                             ntohl (mp->active_members));
1956   vat_json_object_add_uint (node, "members", ntohl (mp->members));
1957 }
1958
1959 static int
1960 api_sw_bond_interface_dump (vat_main_t * vam)
1961 {
1962   unformat_input_t *i = vam->input;
1963   vl_api_sw_bond_interface_dump_t *mp;
1964   vl_api_control_ping_t *mp_ping;
1965   int ret;
1966   u32 sw_if_index = ~0;
1967
1968   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1969     {
1970       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
1971         ;
1972       else if (unformat (i, "sw_if_index %d", &sw_if_index))
1973         ;
1974       else
1975         break;
1976     }
1977
1978   print (vam->ofp,
1979          "\n%-16s %-12s %-12s %-13s %-14s %-14s",
1980          "interface name", "sw_if_index", "mode", "load balance",
1981          "active members", "members");
1982
1983   /* Get list of bond interfaces */
1984   M (SW_BOND_INTERFACE_DUMP, mp);
1985   mp->sw_if_index = ntohl (sw_if_index);
1986   S (mp);
1987
1988   /* Use a control ping for synchronization */
1989   MPING (CONTROL_PING, mp_ping);
1990   S (mp_ping);
1991
1992   W (ret);
1993   return ret;
1994 }
1995
1996 static void vl_api_sw_member_interface_details_t_handler
1997   (vl_api_sw_member_interface_details_t * mp)
1998 {
1999   vat_main_t *vam = &vat_main;
2000
2001   print (vam->ofp,
2002          "%-25s %-12d %-7d %-12d %-10d %-10d", mp->interface_name,
2003          ntohl (mp->sw_if_index), mp->is_passive, mp->is_long_timeout,
2004          ntohl (mp->weight), mp->is_local_numa);
2005 }
2006
2007 static void vl_api_sw_member_interface_details_t_handler_json
2008   (vl_api_sw_member_interface_details_t * mp)
2009 {
2010   vat_main_t *vam = &vat_main;
2011   vat_json_node_t *node = NULL;
2012
2013   if (VAT_JSON_ARRAY != vam->json_tree.type)
2014     {
2015       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
2016       vat_json_init_array (&vam->json_tree);
2017     }
2018   node = vat_json_array_add (&vam->json_tree);
2019
2020   vat_json_init_object (node);
2021   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
2022   vat_json_object_add_string_copy (node, "interface_name",
2023                                    mp->interface_name);
2024   vat_json_object_add_uint (node, "passive", mp->is_passive);
2025   vat_json_object_add_uint (node, "long_timeout", mp->is_long_timeout);
2026   vat_json_object_add_uint (node, "weight", ntohl (mp->weight));
2027   vat_json_object_add_uint (node, "is_local_numa", mp->is_local_numa);
2028 }
2029
2030 static int
2031 api_sw_member_interface_dump (vat_main_t * vam)
2032 {
2033   unformat_input_t *i = vam->input;
2034   vl_api_sw_member_interface_dump_t *mp;
2035   vl_api_control_ping_t *mp_ping;
2036   u32 sw_if_index = ~0;
2037   u8 sw_if_index_set = 0;
2038   int ret;
2039
2040   /* Parse args required to build the message */
2041   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2042     {
2043       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2044         sw_if_index_set = 1;
2045       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2046         sw_if_index_set = 1;
2047       else
2048         break;
2049     }
2050
2051   if (sw_if_index_set == 0)
2052     {
2053       errmsg ("missing vpp interface name. ");
2054       return -99;
2055     }
2056
2057   print (vam->ofp,
2058          "\n%-25s %-12s %-7s %-12s %-10s %-10s",
2059          "member interface name", "sw_if_index", "passive", "long_timeout",
2060          "weight", "local numa");
2061
2062   /* Get list of bond interfaces */
2063   M (SW_MEMBER_INTERFACE_DUMP, mp);
2064   mp->sw_if_index = ntohl (sw_if_index);
2065   S (mp);
2066
2067   /* Use a control ping for synchronization */
2068   MPING (CONTROL_PING, mp_ping);
2069   S (mp_ping);
2070
2071   W (ret);
2072   return ret;
2073 }
2074
2075 static void vl_api_mpls_tunnel_add_del_reply_t_handler
2076   (vl_api_mpls_tunnel_add_del_reply_t * mp)
2077 {
2078   vat_main_t *vam = &vat_main;
2079   i32 retval = ntohl (mp->retval);
2080   if (vam->async_mode)
2081     {
2082       vam->async_errors += (retval < 0);
2083     }
2084   else
2085     {
2086       vam->retval = retval;
2087       vam->sw_if_index = ntohl (mp->sw_if_index);
2088       vam->result_ready = 1;
2089     }
2090   vam->regenerate_interface_table = 1;
2091 }
2092
2093 static void vl_api_mpls_tunnel_add_del_reply_t_handler_json
2094   (vl_api_mpls_tunnel_add_del_reply_t * mp)
2095 {
2096   vat_main_t *vam = &vat_main;
2097   vat_json_node_t node;
2098
2099   vat_json_init_object (&node);
2100   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2101   vat_json_object_add_uint (&node, "tunnel_sw_if_index",
2102                             ntohl (mp->sw_if_index));
2103
2104   vat_json_print (vam->ofp, &node);
2105   vat_json_free (&node);
2106
2107   vam->retval = ntohl (mp->retval);
2108   vam->result_ready = 1;
2109 }
2110
2111 static void vl_api_create_vhost_user_if_reply_t_handler
2112   (vl_api_create_vhost_user_if_reply_t * mp)
2113 {
2114   vat_main_t *vam = &vat_main;
2115   i32 retval = ntohl (mp->retval);
2116   if (vam->async_mode)
2117     {
2118       vam->async_errors += (retval < 0);
2119     }
2120   else
2121     {
2122       vam->retval = retval;
2123       vam->sw_if_index = ntohl (mp->sw_if_index);
2124       vam->result_ready = 1;
2125     }
2126   vam->regenerate_interface_table = 1;
2127 }
2128
2129 static void vl_api_create_vhost_user_if_reply_t_handler_json
2130   (vl_api_create_vhost_user_if_reply_t * mp)
2131 {
2132   vat_main_t *vam = &vat_main;
2133   vat_json_node_t node;
2134
2135   vat_json_init_object (&node);
2136   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2137   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
2138
2139   vat_json_print (vam->ofp, &node);
2140   vat_json_free (&node);
2141
2142   vam->retval = ntohl (mp->retval);
2143   vam->result_ready = 1;
2144 }
2145
2146 static void vl_api_create_vhost_user_if_v2_reply_t_handler
2147   (vl_api_create_vhost_user_if_v2_reply_t * mp)
2148 {
2149   vat_main_t *vam = &vat_main;
2150   i32 retval = ntohl (mp->retval);
2151   if (vam->async_mode)
2152     {
2153       vam->async_errors += (retval < 0);
2154     }
2155   else
2156     {
2157       vam->retval = retval;
2158       vam->sw_if_index = ntohl (mp->sw_if_index);
2159       vam->result_ready = 1;
2160     }
2161   vam->regenerate_interface_table = 1;
2162 }
2163
2164 static void vl_api_create_vhost_user_if_v2_reply_t_handler_json
2165   (vl_api_create_vhost_user_if_v2_reply_t * mp)
2166 {
2167   vat_main_t *vam = &vat_main;
2168   vat_json_node_t node;
2169
2170   vat_json_init_object (&node);
2171   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2172   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
2173
2174   vat_json_print (vam->ofp, &node);
2175   vat_json_free (&node);
2176
2177   vam->retval = ntohl (mp->retval);
2178   vam->result_ready = 1;
2179 }
2180
2181 static void vl_api_ip_address_details_t_handler
2182   (vl_api_ip_address_details_t * mp)
2183 {
2184   vat_main_t *vam = &vat_main;
2185   static ip_address_details_t empty_ip_address_details = { {0} };
2186   ip_address_details_t *address = NULL;
2187   ip_details_t *current_ip_details = NULL;
2188   ip_details_t *details = NULL;
2189
2190   details = vam->ip_details_by_sw_if_index[vam->is_ipv6];
2191
2192   if (!details || vam->current_sw_if_index >= vec_len (details)
2193       || !details[vam->current_sw_if_index].present)
2194     {
2195       errmsg ("ip address details arrived but not stored");
2196       errmsg ("ip_dump should be called first");
2197       return;
2198     }
2199
2200   current_ip_details = vec_elt_at_index (details, vam->current_sw_if_index);
2201
2202 #define addresses (current_ip_details->addr)
2203
2204   vec_validate_init_empty (addresses, vec_len (addresses),
2205                            empty_ip_address_details);
2206
2207   address = vec_elt_at_index (addresses, vec_len (addresses) - 1);
2208
2209   clib_memcpy (&address->ip, &mp->prefix.address.un, sizeof (address->ip));
2210   address->prefix_length = mp->prefix.len;
2211 #undef addresses
2212 }
2213
2214 static void vl_api_ip_address_details_t_handler_json
2215   (vl_api_ip_address_details_t * mp)
2216 {
2217   vat_main_t *vam = &vat_main;
2218   vat_json_node_t *node = NULL;
2219
2220   if (VAT_JSON_ARRAY != vam->json_tree.type)
2221     {
2222       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
2223       vat_json_init_array (&vam->json_tree);
2224     }
2225   node = vat_json_array_add (&vam->json_tree);
2226
2227   vat_json_init_object (node);
2228   vat_json_object_add_prefix (node, &mp->prefix);
2229 }
2230
2231 static void
2232 vl_api_ip_details_t_handler (vl_api_ip_details_t * mp)
2233 {
2234   vat_main_t *vam = &vat_main;
2235   static ip_details_t empty_ip_details = { 0 };
2236   ip_details_t *ip = NULL;
2237   u32 sw_if_index = ~0;
2238
2239   sw_if_index = ntohl (mp->sw_if_index);
2240
2241   vec_validate_init_empty (vam->ip_details_by_sw_if_index[vam->is_ipv6],
2242                            sw_if_index, empty_ip_details);
2243
2244   ip = vec_elt_at_index (vam->ip_details_by_sw_if_index[vam->is_ipv6],
2245                          sw_if_index);
2246
2247   ip->present = 1;
2248 }
2249
2250 static void
2251 vl_api_ip_details_t_handler_json (vl_api_ip_details_t * mp)
2252 {
2253   vat_main_t *vam = &vat_main;
2254
2255   if (VAT_JSON_ARRAY != vam->json_tree.type)
2256     {
2257       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
2258       vat_json_init_array (&vam->json_tree);
2259     }
2260   vat_json_array_add_uint (&vam->json_tree,
2261                            clib_net_to_host_u32 (mp->sw_if_index));
2262 }
2263
2264 static void vl_api_get_first_msg_id_reply_t_handler
2265   (vl_api_get_first_msg_id_reply_t * mp)
2266 {
2267   vat_main_t *vam = &vat_main;
2268   i32 retval = ntohl (mp->retval);
2269
2270   if (vam->async_mode)
2271     {
2272       vam->async_errors += (retval < 0);
2273     }
2274   else
2275     {
2276       vam->retval = retval;
2277       vam->result_ready = 1;
2278     }
2279   if (retval >= 0)
2280     {
2281       errmsg ("first message id %d", ntohs (mp->first_msg_id));
2282     }
2283 }
2284
2285 static void vl_api_get_first_msg_id_reply_t_handler_json
2286   (vl_api_get_first_msg_id_reply_t * mp)
2287 {
2288   vat_main_t *vam = &vat_main;
2289   vat_json_node_t node;
2290
2291   vat_json_init_object (&node);
2292   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2293   vat_json_object_add_uint (&node, "first_msg_id",
2294                             (uint) ntohs (mp->first_msg_id));
2295
2296   vat_json_print (vam->ofp, &node);
2297   vat_json_free (&node);
2298
2299   vam->retval = ntohl (mp->retval);
2300   vam->result_ready = 1;
2301 }
2302
2303 static void vl_api_get_node_graph_reply_t_handler
2304   (vl_api_get_node_graph_reply_t * mp)
2305 {
2306   vat_main_t *vam = &vat_main;
2307   i32 retval = ntohl (mp->retval);
2308   u8 *pvt_copy, *reply;
2309   void *oldheap;
2310   vlib_node_t *node;
2311   int i;
2312
2313   if (vam->async_mode)
2314     {
2315       vam->async_errors += (retval < 0);
2316     }
2317   else
2318     {
2319       vam->retval = retval;
2320       vam->result_ready = 1;
2321     }
2322
2323   /* "Should never happen..." */
2324   if (retval != 0)
2325     return;
2326
2327   reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
2328   pvt_copy = vec_dup (reply);
2329
2330   /* Toss the shared-memory original... */
2331   oldheap = vl_msg_push_heap ();
2332
2333   vec_free (reply);
2334
2335   vl_msg_pop_heap (oldheap);
2336
2337   if (vam->graph_nodes)
2338     {
2339       hash_free (vam->graph_node_index_by_name);
2340
2341       for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
2342         {
2343           node = vam->graph_nodes[0][i];
2344           vec_free (node->name);
2345           vec_free (node->next_nodes);
2346           vec_free (node);
2347         }
2348       vec_free (vam->graph_nodes[0]);
2349       vec_free (vam->graph_nodes);
2350     }
2351
2352   vam->graph_node_index_by_name = hash_create_string (0, sizeof (uword));
2353   vam->graph_nodes = vlib_node_unserialize (pvt_copy);
2354   vec_free (pvt_copy);
2355
2356   for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
2357     {
2358       node = vam->graph_nodes[0][i];
2359       hash_set_mem (vam->graph_node_index_by_name, node->name, i);
2360     }
2361 }
2362
2363 static void vl_api_get_node_graph_reply_t_handler_json
2364   (vl_api_get_node_graph_reply_t * mp)
2365 {
2366   vat_main_t *vam = &vat_main;
2367   void *oldheap;
2368   vat_json_node_t node;
2369   u8 *reply;
2370
2371   /* $$$$ make this real? */
2372   vat_json_init_object (&node);
2373   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2374   vat_json_object_add_uint (&node, "reply_in_shmem", mp->reply_in_shmem);
2375
2376   reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
2377
2378   /* Toss the shared-memory original... */
2379   oldheap = vl_msg_push_heap ();
2380
2381   vec_free (reply);
2382
2383   vl_msg_pop_heap (oldheap);
2384
2385   vat_json_print (vam->ofp, &node);
2386   vat_json_free (&node);
2387
2388   vam->retval = ntohl (mp->retval);
2389   vam->result_ready = 1;
2390 }
2391
2392 /* Format hex dump. */
2393 u8 *
2394 format_hex_bytes (u8 * s, va_list * va)
2395 {
2396   u8 *bytes = va_arg (*va, u8 *);
2397   int n_bytes = va_arg (*va, int);
2398   uword i;
2399
2400   /* Print short or long form depending on byte count. */
2401   uword short_form = n_bytes <= 32;
2402   u32 indent = format_get_indent (s);
2403
2404   if (n_bytes == 0)
2405     return s;
2406
2407   for (i = 0; i < n_bytes; i++)
2408     {
2409       if (!short_form && (i % 32) == 0)
2410         s = format (s, "%08x: ", i);
2411       s = format (s, "%02x", bytes[i]);
2412       if (!short_form && ((i + 1) % 32) == 0 && (i + 1) < n_bytes)
2413         s = format (s, "\n%U", format_white_space, indent);
2414     }
2415
2416   return s;
2417 }
2418
2419 /*
2420  * Generate boilerplate reply handlers, which
2421  * dig the return value out of the xxx_reply_t API message,
2422  * stick it into vam->retval, and set vam->result_ready
2423  *
2424  * Could also do this by pointing N message decode slots at
2425  * a single function, but that could break in subtle ways.
2426  */
2427
2428 #define foreach_standard_reply_retval_handler           \
2429 _(sw_interface_set_flags_reply)                         \
2430 _(sw_interface_add_del_address_reply)                   \
2431 _(sw_interface_set_rx_mode_reply)                       \
2432 _(sw_interface_set_rx_placement_reply)                  \
2433 _(sw_interface_set_table_reply)                         \
2434 _(sw_interface_set_mpls_enable_reply)                   \
2435 _(sw_interface_set_vpath_reply)                         \
2436 _(sw_interface_set_l2_bridge_reply)                     \
2437 _(sw_interface_set_bond_weight_reply)                   \
2438 _(bridge_domain_add_del_reply)                          \
2439 _(sw_interface_set_l2_xconnect_reply)                   \
2440 _(l2fib_add_del_reply)                                  \
2441 _(l2fib_flush_int_reply)                                \
2442 _(l2fib_flush_bd_reply)                                 \
2443 _(ip_route_add_del_reply)                               \
2444 _(ip_table_add_del_reply)                               \
2445 _(ip_table_replace_begin_reply)                         \
2446 _(ip_table_flush_reply)                                 \
2447 _(ip_table_replace_end_reply)                           \
2448 _(ip_mroute_add_del_reply)                              \
2449 _(mpls_route_add_del_reply)                             \
2450 _(mpls_table_add_del_reply)                             \
2451 _(mpls_ip_bind_unbind_reply)                            \
2452 _(sw_interface_set_unnumbered_reply)                    \
2453 _(set_ip_flow_hash_reply)                               \
2454 _(sw_interface_ip6_enable_disable_reply)                \
2455 _(l2_patch_add_del_reply)                               \
2456 _(sr_mpls_policy_add_reply)                             \
2457 _(sr_mpls_policy_mod_reply)                             \
2458 _(sr_mpls_policy_del_reply)                             \
2459 _(sr_policy_add_reply)                                  \
2460 _(sr_policy_mod_reply)                                  \
2461 _(sr_policy_del_reply)                                  \
2462 _(sr_localsid_add_del_reply)                            \
2463 _(sr_steering_add_del_reply)                            \
2464 _(l2_fib_clear_table_reply)                             \
2465 _(l2_interface_efp_filter_reply)                        \
2466 _(l2_interface_vlan_tag_rewrite_reply)                  \
2467 _(modify_vhost_user_if_reply)                           \
2468 _(modify_vhost_user_if_v2_reply)                        \
2469 _(delete_vhost_user_if_reply)                           \
2470 _(want_l2_macs_events_reply)                            \
2471 _(ipsec_spd_add_del_reply)                              \
2472 _(ipsec_interface_add_del_spd_reply)                    \
2473 _(ipsec_spd_entry_add_del_reply)                        \
2474 _(ipsec_sad_entry_add_del_reply)                        \
2475 _(delete_loopback_reply)                                \
2476 _(bd_ip_mac_add_del_reply)                              \
2477 _(bd_ip_mac_flush_reply)                                \
2478 _(want_interface_events_reply)                          \
2479 _(sw_interface_clear_stats_reply)                       \
2480 _(ioam_enable_reply)                                    \
2481 _(ioam_disable_reply)                                   \
2482 _(af_packet_delete_reply)                               \
2483 _(sw_interface_span_enable_disable_reply)               \
2484 _(ip_source_and_port_range_check_add_del_reply)         \
2485 _(ip_source_and_port_range_check_interface_add_del_reply)\
2486 _(delete_subif_reply)                                   \
2487 _(l2_interface_pbb_tag_rewrite_reply)                   \
2488 _(set_punt_reply)                                       \
2489 _(sw_interface_tag_add_del_reply)                       \
2490 _(sw_interface_add_del_mac_address_reply)               \
2491 _(hw_interface_set_mtu_reply)                           \
2492 _(tcp_configure_src_addresses_reply)                    \
2493 _(session_rule_add_del_reply)                           \
2494 _(ip_container_proxy_add_del_reply)                     \
2495 _(qos_record_enable_disable_reply)                      \
2496
2497 #define _(n)                                    \
2498     static void vl_api_##n##_t_handler          \
2499     (vl_api_##n##_t * mp)                       \
2500     {                                           \
2501         vat_main_t * vam = &vat_main;           \
2502         i32 retval = ntohl(mp->retval);         \
2503         if (vam->async_mode) {                  \
2504             vam->async_errors += (retval < 0);  \
2505         } else {                                \
2506             vam->retval = retval;               \
2507             vam->result_ready = 1;              \
2508         }                                       \
2509     }
2510 foreach_standard_reply_retval_handler;
2511 #undef _
2512
2513 #define _(n)                                    \
2514     static void vl_api_##n##_t_handler_json     \
2515     (vl_api_##n##_t * mp)                       \
2516     {                                           \
2517         vat_main_t * vam = &vat_main;           \
2518         vat_json_node_t node;                   \
2519         vat_json_init_object(&node);            \
2520         vat_json_object_add_int(&node, "retval", ntohl(mp->retval));    \
2521         vat_json_print(vam->ofp, &node);        \
2522         vam->retval = ntohl(mp->retval);        \
2523         vam->result_ready = 1;                  \
2524     }
2525 foreach_standard_reply_retval_handler;
2526 #undef _
2527
2528 /*
2529  * Table of message reply handlers, must include boilerplate handlers
2530  * we just generated
2531  */
2532
2533 #define foreach_vpe_api_reply_msg                                       \
2534 _(CREATE_LOOPBACK_REPLY, create_loopback_reply)                         \
2535 _(CREATE_LOOPBACK_INSTANCE_REPLY, create_loopback_instance_reply)       \
2536 _(SW_INTERFACE_DETAILS, sw_interface_details)                           \
2537 _(SW_INTERFACE_SET_FLAGS_REPLY, sw_interface_set_flags_reply)           \
2538 _(CONTROL_PING_REPLY, control_ping_reply)                               \
2539 _(CLI_REPLY, cli_reply)                                                 \
2540 _(CLI_INBAND_REPLY, cli_inband_reply)                                   \
2541 _(SW_INTERFACE_ADD_DEL_ADDRESS_REPLY,                                   \
2542   sw_interface_add_del_address_reply)                                   \
2543 _(SW_INTERFACE_SET_RX_MODE_REPLY, sw_interface_set_rx_mode_reply)       \
2544 _(SW_INTERFACE_SET_RX_PLACEMENT_REPLY, sw_interface_set_rx_placement_reply)     \
2545 _(SW_INTERFACE_RX_PLACEMENT_DETAILS, sw_interface_rx_placement_details) \
2546 _(SW_INTERFACE_SET_TABLE_REPLY, sw_interface_set_table_reply)           \
2547 _(SW_INTERFACE_SET_MPLS_ENABLE_REPLY, sw_interface_set_mpls_enable_reply) \
2548 _(SW_INTERFACE_SET_VPATH_REPLY, sw_interface_set_vpath_reply)           \
2549 _(SW_INTERFACE_SET_L2_XCONNECT_REPLY,                                   \
2550   sw_interface_set_l2_xconnect_reply)                                   \
2551 _(SW_INTERFACE_SET_L2_BRIDGE_REPLY,                                     \
2552   sw_interface_set_l2_bridge_reply)                                     \
2553 _(BRIDGE_DOMAIN_ADD_DEL_REPLY, bridge_domain_add_del_reply)             \
2554 _(BRIDGE_DOMAIN_DETAILS, bridge_domain_details)                         \
2555 _(BRIDGE_DOMAIN_SET_MAC_AGE_REPLY, bridge_domain_set_mac_age_reply)     \
2556 _(L2FIB_ADD_DEL_REPLY, l2fib_add_del_reply)                             \
2557 _(L2FIB_FLUSH_INT_REPLY, l2fib_flush_int_reply)                         \
2558 _(L2FIB_FLUSH_BD_REPLY, l2fib_flush_bd_reply)                           \
2559 _(L2_FLAGS_REPLY, l2_flags_reply)                                       \
2560 _(BRIDGE_FLAGS_REPLY, bridge_flags_reply)                               \
2561 _(TAP_CREATE_V2_REPLY, tap_create_v2_reply)                             \
2562 _(TAP_DELETE_V2_REPLY, tap_delete_v2_reply)                             \
2563 _(SW_INTERFACE_TAP_V2_DETAILS, sw_interface_tap_v2_details)             \
2564 _(VIRTIO_PCI_CREATE_REPLY, virtio_pci_create_reply)                     \
2565 _(VIRTIO_PCI_CREATE_V2_REPLY, virtio_pci_create_v2_reply)               \
2566 _(VIRTIO_PCI_DELETE_REPLY, virtio_pci_delete_reply)                     \
2567 _(SW_INTERFACE_VIRTIO_PCI_DETAILS, sw_interface_virtio_pci_details)     \
2568 _(BOND_CREATE_REPLY, bond_create_reply)                                 \
2569 _(BOND_CREATE2_REPLY, bond_create2_reply)                               \
2570 _(BOND_DELETE_REPLY, bond_delete_reply)                                 \
2571 _(BOND_ADD_MEMBER_REPLY, bond_add_member_reply)                         \
2572 _(BOND_DETACH_MEMBER_REPLY, bond_detach_member_reply)                   \
2573 _(SW_INTERFACE_SET_BOND_WEIGHT_REPLY, sw_interface_set_bond_weight_reply) \
2574 _(SW_BOND_INTERFACE_DETAILS, sw_bond_interface_details)                 \
2575 _(SW_MEMBER_INTERFACE_DETAILS, sw_member_interface_details)               \
2576 _(IP_ROUTE_ADD_DEL_REPLY, ip_route_add_del_reply)                       \
2577 _(IP_TABLE_ADD_DEL_REPLY, ip_table_add_del_reply)                       \
2578 _(IP_TABLE_REPLACE_BEGIN_REPLY, ip_table_replace_begin_reply)           \
2579 _(IP_TABLE_FLUSH_REPLY, ip_table_flush_reply)                           \
2580 _(IP_TABLE_REPLACE_END_REPLY, ip_table_replace_end_reply)               \
2581 _(IP_MROUTE_ADD_DEL_REPLY, ip_mroute_add_del_reply)                     \
2582 _(MPLS_TABLE_ADD_DEL_REPLY, mpls_table_add_del_reply)                   \
2583 _(MPLS_ROUTE_ADD_DEL_REPLY, mpls_route_add_del_reply)                   \
2584 _(MPLS_IP_BIND_UNBIND_REPLY, mpls_ip_bind_unbind_reply)                 \
2585 _(MPLS_TUNNEL_ADD_DEL_REPLY, mpls_tunnel_add_del_reply)                 \
2586 _(SW_INTERFACE_SET_UNNUMBERED_REPLY,                                    \
2587   sw_interface_set_unnumbered_reply)                                    \
2588 _(CREATE_VLAN_SUBIF_REPLY, create_vlan_subif_reply)                     \
2589 _(CREATE_SUBIF_REPLY, create_subif_reply)                               \
2590 _(SET_IP_FLOW_HASH_REPLY, set_ip_flow_hash_reply)                       \
2591 _(SW_INTERFACE_IP6_ENABLE_DISABLE_REPLY,                                \
2592   sw_interface_ip6_enable_disable_reply)                                \
2593 _(L2_PATCH_ADD_DEL_REPLY, l2_patch_add_del_reply)                       \
2594 _(SR_MPLS_POLICY_ADD_REPLY, sr_mpls_policy_add_reply)                   \
2595 _(SR_MPLS_POLICY_MOD_REPLY, sr_mpls_policy_mod_reply)                   \
2596 _(SR_MPLS_POLICY_DEL_REPLY, sr_mpls_policy_del_reply)                   \
2597 _(SR_POLICY_ADD_REPLY, sr_policy_add_reply)                             \
2598 _(SR_POLICY_MOD_REPLY, sr_policy_mod_reply)                             \
2599 _(SR_POLICY_DEL_REPLY, sr_policy_del_reply)                             \
2600 _(SR_LOCALSID_ADD_DEL_REPLY, sr_localsid_add_del_reply)                 \
2601 _(SR_STEERING_ADD_DEL_REPLY, sr_steering_add_del_reply)                 \
2602 _(GET_NODE_INDEX_REPLY, get_node_index_reply)                           \
2603 _(ADD_NODE_NEXT_REPLY, add_node_next_reply)                             \
2604 _(L2_FIB_CLEAR_TABLE_REPLY, l2_fib_clear_table_reply)                   \
2605 _(L2_INTERFACE_EFP_FILTER_REPLY, l2_interface_efp_filter_reply)         \
2606 _(L2_INTERFACE_VLAN_TAG_REWRITE_REPLY, l2_interface_vlan_tag_rewrite_reply) \
2607 _(SW_INTERFACE_VHOST_USER_DETAILS, sw_interface_vhost_user_details)     \
2608 _(CREATE_VHOST_USER_IF_REPLY, create_vhost_user_if_reply)               \
2609 _(MODIFY_VHOST_USER_IF_REPLY, modify_vhost_user_if_reply)               \
2610 _(CREATE_VHOST_USER_IF_V2_REPLY, create_vhost_user_if_v2_reply)         \
2611 _(MODIFY_VHOST_USER_IF_V2_REPLY, modify_vhost_user_if_v2_reply)         \
2612 _(DELETE_VHOST_USER_IF_REPLY, delete_vhost_user_if_reply)               \
2613 _(SHOW_VERSION_REPLY, show_version_reply)                               \
2614 _(SHOW_THREADS_REPLY, show_threads_reply)                               \
2615 _(L2_FIB_TABLE_DETAILS, l2_fib_table_details)                           \
2616 _(INTERFACE_NAME_RENUMBER_REPLY, interface_name_renumber_reply)         \
2617 _(WANT_L2_MACS_EVENTS_REPLY, want_l2_macs_events_reply)                 \
2618 _(L2_MACS_EVENT, l2_macs_event)                                         \
2619 _(IP_ADDRESS_DETAILS, ip_address_details)                               \
2620 _(IP_DETAILS, ip_details)                                               \
2621 _(IPSEC_SPD_ADD_DEL_REPLY, ipsec_spd_add_del_reply)                     \
2622 _(IPSEC_INTERFACE_ADD_DEL_SPD_REPLY, ipsec_interface_add_del_spd_reply) \
2623 _(IPSEC_SPD_ENTRY_ADD_DEL_REPLY, ipsec_spd_entry_add_del_reply)         \
2624 _(IPSEC_SAD_ENTRY_ADD_DEL_REPLY, ipsec_sad_entry_add_del_reply)         \
2625 _(IPSEC_SA_DETAILS, ipsec_sa_details)                                   \
2626 _(DELETE_LOOPBACK_REPLY, delete_loopback_reply)                         \
2627 _(BD_IP_MAC_ADD_DEL_REPLY, bd_ip_mac_add_del_reply)                     \
2628 _(BD_IP_MAC_FLUSH_REPLY, bd_ip_mac_flush_reply)                         \
2629 _(BD_IP_MAC_DETAILS, bd_ip_mac_details)                                 \
2630 _(WANT_INTERFACE_EVENTS_REPLY, want_interface_events_reply)             \
2631 _(GET_FIRST_MSG_ID_REPLY, get_first_msg_id_reply)                       \
2632 _(GET_NODE_GRAPH_REPLY, get_node_graph_reply)                           \
2633 _(SW_INTERFACE_CLEAR_STATS_REPLY, sw_interface_clear_stats_reply)      \
2634 _(IOAM_ENABLE_REPLY, ioam_enable_reply)                   \
2635 _(IOAM_DISABLE_REPLY, ioam_disable_reply)                     \
2636 _(AF_PACKET_CREATE_REPLY, af_packet_create_reply)                       \
2637 _(AF_PACKET_DELETE_REPLY, af_packet_delete_reply)                       \
2638 _(AF_PACKET_DETAILS, af_packet_details)                                 \
2639 _(MPLS_TUNNEL_DETAILS, mpls_tunnel_details)                             \
2640 _(MPLS_TABLE_DETAILS, mpls_table_details)                               \
2641 _(MPLS_ROUTE_DETAILS, mpls_route_details)                               \
2642 _(SW_INTERFACE_SPAN_ENABLE_DISABLE_REPLY, sw_interface_span_enable_disable_reply) \
2643 _(SW_INTERFACE_SPAN_DETAILS, sw_interface_span_details)                 \
2644 _(GET_NEXT_INDEX_REPLY, get_next_index_reply)                           \
2645 _(IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL_REPLY,                         \
2646  ip_source_and_port_range_check_add_del_reply)                          \
2647 _(IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL_REPLY,               \
2648  ip_source_and_port_range_check_interface_add_del_reply)                \
2649 _(DELETE_SUBIF_REPLY, delete_subif_reply)                               \
2650 _(L2_INTERFACE_PBB_TAG_REWRITE_REPLY, l2_interface_pbb_tag_rewrite_reply) \
2651 _(SET_PUNT_REPLY, set_punt_reply)                                       \
2652 _(IP_TABLE_DETAILS, ip_table_details)                                   \
2653 _(IP_ROUTE_DETAILS, ip_route_details)                                   \
2654 _(SW_INTERFACE_TAG_ADD_DEL_REPLY, sw_interface_tag_add_del_reply)       \
2655 _(SW_INTERFACE_ADD_DEL_MAC_ADDRESS_REPLY, sw_interface_add_del_mac_address_reply) \
2656 _(L2_XCONNECT_DETAILS, l2_xconnect_details)                             \
2657 _(HW_INTERFACE_SET_MTU_REPLY, hw_interface_set_mtu_reply)               \
2658 _(SW_INTERFACE_GET_TABLE_REPLY, sw_interface_get_table_reply)           \
2659 _(TCP_CONFIGURE_SRC_ADDRESSES_REPLY, tcp_configure_src_addresses_reply) \
2660 _(APP_NAMESPACE_ADD_DEL_REPLY, app_namespace_add_del_reply)             \
2661 _(SESSION_RULE_ADD_DEL_REPLY, session_rule_add_del_reply)               \
2662 _(SESSION_RULES_DETAILS, session_rules_details)                         \
2663 _(IP_CONTAINER_PROXY_ADD_DEL_REPLY, ip_container_proxy_add_del_reply)   \
2664 _(QOS_RECORD_ENABLE_DISABLE_REPLY, qos_record_enable_disable_reply)             \
2665
2666 #define foreach_standalone_reply_msg                                    \
2667 _(SW_INTERFACE_EVENT, sw_interface_event)
2668
2669 typedef struct
2670 {
2671   u8 *name;
2672   u32 value;
2673 } name_sort_t;
2674
2675 #define STR_VTR_OP_CASE(op)     \
2676     case L2_VTR_ ## op:         \
2677         return "" # op;
2678
2679 static const char *
2680 str_vtr_op (u32 vtr_op)
2681 {
2682   switch (vtr_op)
2683     {
2684       STR_VTR_OP_CASE (DISABLED);
2685       STR_VTR_OP_CASE (PUSH_1);
2686       STR_VTR_OP_CASE (PUSH_2);
2687       STR_VTR_OP_CASE (POP_1);
2688       STR_VTR_OP_CASE (POP_2);
2689       STR_VTR_OP_CASE (TRANSLATE_1_1);
2690       STR_VTR_OP_CASE (TRANSLATE_1_2);
2691       STR_VTR_OP_CASE (TRANSLATE_2_1);
2692       STR_VTR_OP_CASE (TRANSLATE_2_2);
2693     }
2694
2695   return "UNKNOWN";
2696 }
2697
2698 static int
2699 dump_sub_interface_table (vat_main_t * vam)
2700 {
2701   const sw_interface_subif_t *sub = NULL;
2702
2703   if (vam->json_output)
2704     {
2705       clib_warning
2706         ("JSON output supported only for VPE API calls and dump_stats_table");
2707       return -99;
2708     }
2709
2710   print (vam->ofp,
2711          "%-30s%-12s%-11s%-7s%-5s%-9s%-9s%-6s%-8s%-10s%-10s",
2712          "Interface", "sw_if_index",
2713          "sub id", "dot1ad", "tags", "outer id",
2714          "inner id", "exact", "default", "outer any", "inner any");
2715
2716   vec_foreach (sub, vam->sw_if_subif_table)
2717   {
2718     print (vam->ofp,
2719            "%-30s%-12d%-11d%-7s%-5d%-9d%-9d%-6d%-8d%-10d%-10d",
2720            sub->interface_name,
2721            sub->sw_if_index,
2722            sub->sub_id, sub->sub_dot1ad ? "dot1ad" : "dot1q",
2723            sub->sub_number_of_tags, sub->sub_outer_vlan_id,
2724            sub->sub_inner_vlan_id, sub->sub_exact_match, sub->sub_default,
2725            sub->sub_outer_vlan_id_any, sub->sub_inner_vlan_id_any);
2726     if (sub->vtr_op != L2_VTR_DISABLED)
2727       {
2728         print (vam->ofp,
2729                "  vlan-tag-rewrite - op: %-14s [ dot1q: %d "
2730                "tag1: %d tag2: %d ]",
2731                str_vtr_op (sub->vtr_op), sub->vtr_push_dot1q,
2732                sub->vtr_tag1, sub->vtr_tag2);
2733       }
2734   }
2735
2736   return 0;
2737 }
2738
2739 static int
2740 name_sort_cmp (void *a1, void *a2)
2741 {
2742   name_sort_t *n1 = a1;
2743   name_sort_t *n2 = a2;
2744
2745   return strcmp ((char *) n1->name, (char *) n2->name);
2746 }
2747
2748 static int
2749 dump_interface_table (vat_main_t * vam)
2750 {
2751   hash_pair_t *p;
2752   name_sort_t *nses = 0, *ns;
2753
2754   if (vam->json_output)
2755     {
2756       clib_warning
2757         ("JSON output supported only for VPE API calls and dump_stats_table");
2758       return -99;
2759     }
2760
2761   /* *INDENT-OFF* */
2762   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
2763   ({
2764     vec_add2 (nses, ns, 1);
2765     ns->name = (u8 *)(p->key);
2766     ns->value = (u32) p->value[0];
2767   }));
2768   /* *INDENT-ON* */
2769
2770   vec_sort_with_function (nses, name_sort_cmp);
2771
2772   print (vam->ofp, "%-25s%-15s", "Interface", "sw_if_index");
2773   vec_foreach (ns, nses)
2774   {
2775     print (vam->ofp, "%-25s%-15d", ns->name, ns->value);
2776   }
2777   vec_free (nses);
2778   return 0;
2779 }
2780
2781 static int
2782 dump_ip_table (vat_main_t * vam, int is_ipv6)
2783 {
2784   const ip_details_t *det = NULL;
2785   const ip_address_details_t *address = NULL;
2786   u32 i = ~0;
2787
2788   print (vam->ofp, "%-12s", "sw_if_index");
2789
2790   vec_foreach (det, vam->ip_details_by_sw_if_index[is_ipv6])
2791   {
2792     i++;
2793     if (!det->present)
2794       {
2795         continue;
2796       }
2797     print (vam->ofp, "%-12d", i);
2798     print (vam->ofp, "            %-30s%-13s", "Address", "Prefix length");
2799     if (!det->addr)
2800       {
2801         continue;
2802       }
2803     vec_foreach (address, det->addr)
2804     {
2805       print (vam->ofp,
2806              "            %-30U%-13d",
2807              is_ipv6 ? format_ip6_address : format_ip4_address,
2808              address->ip, address->prefix_length);
2809     }
2810   }
2811
2812   return 0;
2813 }
2814
2815 static int
2816 dump_ipv4_table (vat_main_t * vam)
2817 {
2818   if (vam->json_output)
2819     {
2820       clib_warning
2821         ("JSON output supported only for VPE API calls and dump_stats_table");
2822       return -99;
2823     }
2824
2825   return dump_ip_table (vam, 0);
2826 }
2827
2828 static int
2829 dump_ipv6_table (vat_main_t * vam)
2830 {
2831   if (vam->json_output)
2832     {
2833       clib_warning
2834         ("JSON output supported only for VPE API calls and dump_stats_table");
2835       return -99;
2836     }
2837
2838   return dump_ip_table (vam, 1);
2839 }
2840
2841 /*
2842  * Pass CLI buffers directly in the CLI_INBAND API message,
2843  * instead of an additional shared memory area.
2844  */
2845 static int
2846 exec_inband (vat_main_t * vam)
2847 {
2848   vl_api_cli_inband_t *mp;
2849   unformat_input_t *i = vam->input;
2850   int ret;
2851
2852   if (vec_len (i->buffer) == 0)
2853     return -1;
2854
2855   if (vam->exec_mode == 0 && unformat (i, "mode"))
2856     {
2857       vam->exec_mode = 1;
2858       return 0;
2859     }
2860   if (vam->exec_mode == 1 && (unformat (i, "exit") || unformat (i, "quit")))
2861     {
2862       vam->exec_mode = 0;
2863       return 0;
2864     }
2865
2866   /*
2867    * In order for the CLI command to work, it
2868    * must be a vector ending in \n, not a C-string ending
2869    * in \n\0.
2870    */
2871   M2 (CLI_INBAND, mp, vec_len (vam->input->buffer));
2872   vl_api_vec_to_api_string (vam->input->buffer, &mp->cmd);
2873
2874   S (mp);
2875   W (ret);
2876   /* json responses may or may not include a useful reply... */
2877   if (vec_len (vam->cmd_reply))
2878     print (vam->ofp, "%v", (char *) (vam->cmd_reply));
2879   return ret;
2880 }
2881
2882 int
2883 exec (vat_main_t * vam)
2884 {
2885   return exec_inband (vam);
2886 }
2887
2888 static int
2889 api_create_loopback (vat_main_t * vam)
2890 {
2891   unformat_input_t *i = vam->input;
2892   vl_api_create_loopback_t *mp;
2893   vl_api_create_loopback_instance_t *mp_lbi;
2894   u8 mac_address[6];
2895   u8 mac_set = 0;
2896   u8 is_specified = 0;
2897   u32 user_instance = 0;
2898   int ret;
2899
2900   clib_memset (mac_address, 0, sizeof (mac_address));
2901
2902   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2903     {
2904       if (unformat (i, "mac %U", unformat_ethernet_address, mac_address))
2905         mac_set = 1;
2906       if (unformat (i, "instance %d", &user_instance))
2907         is_specified = 1;
2908       else
2909         break;
2910     }
2911
2912   if (is_specified)
2913     {
2914       M (CREATE_LOOPBACK_INSTANCE, mp_lbi);
2915       mp_lbi->is_specified = is_specified;
2916       if (is_specified)
2917         mp_lbi->user_instance = htonl (user_instance);
2918       if (mac_set)
2919         clib_memcpy (mp_lbi->mac_address, mac_address, sizeof (mac_address));
2920       S (mp_lbi);
2921     }
2922   else
2923     {
2924       /* Construct the API message */
2925       M (CREATE_LOOPBACK, mp);
2926       if (mac_set)
2927         clib_memcpy (mp->mac_address, mac_address, sizeof (mac_address));
2928       S (mp);
2929     }
2930
2931   W (ret);
2932   return ret;
2933 }
2934
2935 static int
2936 api_delete_loopback (vat_main_t * vam)
2937 {
2938   unformat_input_t *i = vam->input;
2939   vl_api_delete_loopback_t *mp;
2940   u32 sw_if_index = ~0;
2941   int ret;
2942
2943   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2944     {
2945       if (unformat (i, "sw_if_index %d", &sw_if_index))
2946         ;
2947       else
2948         break;
2949     }
2950
2951   if (sw_if_index == ~0)
2952     {
2953       errmsg ("missing sw_if_index");
2954       return -99;
2955     }
2956
2957   /* Construct the API message */
2958   M (DELETE_LOOPBACK, mp);
2959   mp->sw_if_index = ntohl (sw_if_index);
2960
2961   S (mp);
2962   W (ret);
2963   return ret;
2964 }
2965
2966 static int
2967 api_want_interface_events (vat_main_t * vam)
2968 {
2969   unformat_input_t *i = vam->input;
2970   vl_api_want_interface_events_t *mp;
2971   int enable = -1;
2972   int ret;
2973
2974   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2975     {
2976       if (unformat (i, "enable"))
2977         enable = 1;
2978       else if (unformat (i, "disable"))
2979         enable = 0;
2980       else
2981         break;
2982     }
2983
2984   if (enable == -1)
2985     {
2986       errmsg ("missing enable|disable");
2987       return -99;
2988     }
2989
2990   M (WANT_INTERFACE_EVENTS, mp);
2991   mp->enable_disable = enable;
2992
2993   vam->interface_event_display = enable;
2994
2995   S (mp);
2996   W (ret);
2997   return ret;
2998 }
2999
3000
3001 /* Note: non-static, called once to set up the initial intfc table */
3002 int
3003 api_sw_interface_dump (vat_main_t * vam)
3004 {
3005   vl_api_sw_interface_dump_t *mp;
3006   vl_api_control_ping_t *mp_ping;
3007   hash_pair_t *p;
3008   name_sort_t *nses = 0, *ns;
3009   sw_interface_subif_t *sub = NULL;
3010   int ret;
3011
3012   /* Toss the old name table */
3013   /* *INDENT-OFF* */
3014   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
3015   ({
3016     vec_add2 (nses, ns, 1);
3017     ns->name = (u8 *)(p->key);
3018     ns->value = (u32) p->value[0];
3019   }));
3020   /* *INDENT-ON* */
3021
3022   hash_free (vam->sw_if_index_by_interface_name);
3023
3024   vec_foreach (ns, nses) vec_free (ns->name);
3025
3026   vec_free (nses);
3027
3028   vec_foreach (sub, vam->sw_if_subif_table)
3029   {
3030     vec_free (sub->interface_name);
3031   }
3032   vec_free (vam->sw_if_subif_table);
3033
3034   /* recreate the interface name hash table */
3035   vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
3036
3037   /*
3038    * Ask for all interface names. Otherwise, the epic catalog of
3039    * name filters becomes ridiculously long, and vat ends up needing
3040    * to be taught about new interface types.
3041    */
3042   M (SW_INTERFACE_DUMP, mp);
3043   S (mp);
3044
3045   /* Use a control ping for synchronization */
3046   MPING (CONTROL_PING, mp_ping);
3047   S (mp_ping);
3048
3049   W (ret);
3050   return ret;
3051 }
3052
3053 static int
3054 api_sw_interface_set_flags (vat_main_t * vam)
3055 {
3056   unformat_input_t *i = vam->input;
3057   vl_api_sw_interface_set_flags_t *mp;
3058   u32 sw_if_index;
3059   u8 sw_if_index_set = 0;
3060   u8 admin_up = 0;
3061   int ret;
3062
3063   /* Parse args required to build the message */
3064   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3065     {
3066       if (unformat (i, "admin-up"))
3067         admin_up = 1;
3068       else if (unformat (i, "admin-down"))
3069         admin_up = 0;
3070       else
3071         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3072         sw_if_index_set = 1;
3073       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3074         sw_if_index_set = 1;
3075       else
3076         break;
3077     }
3078
3079   if (sw_if_index_set == 0)
3080     {
3081       errmsg ("missing interface name or sw_if_index");
3082       return -99;
3083     }
3084
3085   /* Construct the API message */
3086   M (SW_INTERFACE_SET_FLAGS, mp);
3087   mp->sw_if_index = ntohl (sw_if_index);
3088   mp->flags = ntohl ((admin_up) ? IF_STATUS_API_FLAG_ADMIN_UP : 0);
3089
3090   /* send it... */
3091   S (mp);
3092
3093   /* Wait for a reply, return the good/bad news... */
3094   W (ret);
3095   return ret;
3096 }
3097
3098 static int
3099 api_sw_interface_set_rx_mode (vat_main_t * vam)
3100 {
3101   unformat_input_t *i = vam->input;
3102   vl_api_sw_interface_set_rx_mode_t *mp;
3103   u32 sw_if_index;
3104   u8 sw_if_index_set = 0;
3105   int ret;
3106   u8 queue_id_valid = 0;
3107   u32 queue_id;
3108   vnet_hw_if_rx_mode mode = VNET_HW_IF_RX_MODE_UNKNOWN;
3109
3110   /* Parse args required to build the message */
3111   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3112     {
3113       if (unformat (i, "queue %d", &queue_id))
3114         queue_id_valid = 1;
3115       else if (unformat (i, "polling"))
3116         mode = VNET_HW_IF_RX_MODE_POLLING;
3117       else if (unformat (i, "interrupt"))
3118         mode = VNET_HW_IF_RX_MODE_INTERRUPT;
3119       else if (unformat (i, "adaptive"))
3120         mode = VNET_HW_IF_RX_MODE_ADAPTIVE;
3121       else
3122         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3123         sw_if_index_set = 1;
3124       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3125         sw_if_index_set = 1;
3126       else
3127         break;
3128     }
3129
3130   if (sw_if_index_set == 0)
3131     {
3132       errmsg ("missing interface name or sw_if_index");
3133       return -99;
3134     }
3135   if (mode == VNET_HW_IF_RX_MODE_UNKNOWN)
3136     {
3137       errmsg ("missing rx-mode");
3138       return -99;
3139     }
3140
3141   /* Construct the API message */
3142   M (SW_INTERFACE_SET_RX_MODE, mp);
3143   mp->sw_if_index = ntohl (sw_if_index);
3144   mp->mode = (vl_api_rx_mode_t) mode;
3145   mp->queue_id_valid = queue_id_valid;
3146   mp->queue_id = queue_id_valid ? ntohl (queue_id) : ~0;
3147
3148   /* send it... */
3149   S (mp);
3150
3151   /* Wait for a reply, return the good/bad news... */
3152   W (ret);
3153   return ret;
3154 }
3155
3156 static int
3157 api_sw_interface_set_rx_placement (vat_main_t * vam)
3158 {
3159   unformat_input_t *i = vam->input;
3160   vl_api_sw_interface_set_rx_placement_t *mp;
3161   u32 sw_if_index;
3162   u8 sw_if_index_set = 0;
3163   int ret;
3164   u8 is_main = 0;
3165   u32 queue_id, thread_index;
3166
3167   /* Parse args required to build the message */
3168   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3169     {
3170       if (unformat (i, "queue %d", &queue_id))
3171         ;
3172       else if (unformat (i, "main"))
3173         is_main = 1;
3174       else if (unformat (i, "worker %d", &thread_index))
3175         ;
3176       else
3177         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3178         sw_if_index_set = 1;
3179       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3180         sw_if_index_set = 1;
3181       else
3182         break;
3183     }
3184
3185   if (sw_if_index_set == 0)
3186     {
3187       errmsg ("missing interface name or sw_if_index");
3188       return -99;
3189     }
3190
3191   if (is_main)
3192     thread_index = 0;
3193   /* Construct the API message */
3194   M (SW_INTERFACE_SET_RX_PLACEMENT, mp);
3195   mp->sw_if_index = ntohl (sw_if_index);
3196   mp->worker_id = ntohl (thread_index);
3197   mp->queue_id = ntohl (queue_id);
3198   mp->is_main = is_main;
3199
3200   /* send it... */
3201   S (mp);
3202   /* Wait for a reply, return the good/bad news... */
3203   W (ret);
3204   return ret;
3205 }
3206
3207 static void vl_api_sw_interface_rx_placement_details_t_handler
3208   (vl_api_sw_interface_rx_placement_details_t * mp)
3209 {
3210   vat_main_t *vam = &vat_main;
3211   u32 worker_id = ntohl (mp->worker_id);
3212
3213   print (vam->ofp,
3214          "\n%-11d %-11s %-6d %-5d %-9s",
3215          ntohl (mp->sw_if_index), (worker_id == 0) ? "main" : "worker",
3216          worker_id, ntohl (mp->queue_id),
3217          (mp->mode ==
3218           1) ? "polling" : ((mp->mode == 2) ? "interrupt" : "adaptive"));
3219 }
3220
3221 static void vl_api_sw_interface_rx_placement_details_t_handler_json
3222   (vl_api_sw_interface_rx_placement_details_t * mp)
3223 {
3224   vat_main_t *vam = &vat_main;
3225   vat_json_node_t *node = NULL;
3226
3227   if (VAT_JSON_ARRAY != vam->json_tree.type)
3228     {
3229       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
3230       vat_json_init_array (&vam->json_tree);
3231     }
3232   node = vat_json_array_add (&vam->json_tree);
3233
3234   vat_json_init_object (node);
3235   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
3236   vat_json_object_add_uint (node, "worker_id", ntohl (mp->worker_id));
3237   vat_json_object_add_uint (node, "queue_id", ntohl (mp->queue_id));
3238   vat_json_object_add_uint (node, "mode", mp->mode);
3239 }
3240
3241 static int
3242 api_sw_interface_rx_placement_dump (vat_main_t * vam)
3243 {
3244   unformat_input_t *i = vam->input;
3245   vl_api_sw_interface_rx_placement_dump_t *mp;
3246   vl_api_control_ping_t *mp_ping;
3247   int ret;
3248   u32 sw_if_index;
3249   u8 sw_if_index_set = 0;
3250
3251   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3252     {
3253       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3254         sw_if_index_set++;
3255       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3256         sw_if_index_set++;
3257       else
3258         break;
3259     }
3260
3261   print (vam->ofp,
3262          "\n%-11s %-11s %-6s %-5s %-4s",
3263          "sw_if_index", "main/worker", "thread", "queue", "mode");
3264
3265   /* Dump Interface rx placement */
3266   M (SW_INTERFACE_RX_PLACEMENT_DUMP, mp);
3267
3268   if (sw_if_index_set)
3269     mp->sw_if_index = htonl (sw_if_index);
3270   else
3271     mp->sw_if_index = ~0;
3272
3273   S (mp);
3274
3275   /* Use a control ping for synchronization */
3276   MPING (CONTROL_PING, mp_ping);
3277   S (mp_ping);
3278
3279   W (ret);
3280   return ret;
3281 }
3282
3283 static int
3284 api_sw_interface_clear_stats (vat_main_t * vam)
3285 {
3286   unformat_input_t *i = vam->input;
3287   vl_api_sw_interface_clear_stats_t *mp;
3288   u32 sw_if_index;
3289   u8 sw_if_index_set = 0;
3290   int ret;
3291
3292   /* Parse args required to build the message */
3293   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3294     {
3295       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3296         sw_if_index_set = 1;
3297       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3298         sw_if_index_set = 1;
3299       else
3300         break;
3301     }
3302
3303   /* Construct the API message */
3304   M (SW_INTERFACE_CLEAR_STATS, mp);
3305
3306   if (sw_if_index_set == 1)
3307     mp->sw_if_index = ntohl (sw_if_index);
3308   else
3309     mp->sw_if_index = ~0;
3310
3311   /* send it... */
3312   S (mp);
3313
3314   /* Wait for a reply, return the good/bad news... */
3315   W (ret);
3316   return ret;
3317 }
3318
3319 static int
3320 api_sw_interface_add_del_address (vat_main_t * vam)
3321 {
3322   unformat_input_t *i = vam->input;
3323   vl_api_sw_interface_add_del_address_t *mp;
3324   u32 sw_if_index;
3325   u8 sw_if_index_set = 0;
3326   u8 is_add = 1, del_all = 0;
3327   u32 address_length = 0;
3328   u8 v4_address_set = 0;
3329   u8 v6_address_set = 0;
3330   ip4_address_t v4address;
3331   ip6_address_t v6address;
3332   int ret;
3333
3334   /* Parse args required to build the message */
3335   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3336     {
3337       if (unformat (i, "del-all"))
3338         del_all = 1;
3339       else if (unformat (i, "del"))
3340         is_add = 0;
3341       else
3342         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3343         sw_if_index_set = 1;
3344       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3345         sw_if_index_set = 1;
3346       else if (unformat (i, "%U/%d",
3347                          unformat_ip4_address, &v4address, &address_length))
3348         v4_address_set = 1;
3349       else if (unformat (i, "%U/%d",
3350                          unformat_ip6_address, &v6address, &address_length))
3351         v6_address_set = 1;
3352       else
3353         break;
3354     }
3355
3356   if (sw_if_index_set == 0)
3357     {
3358       errmsg ("missing interface name or sw_if_index");
3359       return -99;
3360     }
3361   if (v4_address_set && v6_address_set)
3362     {
3363       errmsg ("both v4 and v6 addresses set");
3364       return -99;
3365     }
3366   if (!v4_address_set && !v6_address_set && !del_all)
3367     {
3368       errmsg ("no addresses set");
3369       return -99;
3370     }
3371
3372   /* Construct the API message */
3373   M (SW_INTERFACE_ADD_DEL_ADDRESS, mp);
3374
3375   mp->sw_if_index = ntohl (sw_if_index);
3376   mp->is_add = is_add;
3377   mp->del_all = del_all;
3378   if (v6_address_set)
3379     {
3380       mp->prefix.address.af = ADDRESS_IP6;
3381       clib_memcpy (mp->prefix.address.un.ip6, &v6address, sizeof (v6address));
3382     }
3383   else
3384     {
3385       mp->prefix.address.af = ADDRESS_IP4;
3386       clib_memcpy (mp->prefix.address.un.ip4, &v4address, sizeof (v4address));
3387     }
3388   mp->prefix.len = address_length;
3389
3390   /* send it... */
3391   S (mp);
3392
3393   /* Wait for a reply, return good/bad news  */
3394   W (ret);
3395   return ret;
3396 }
3397
3398 static int
3399 api_sw_interface_set_mpls_enable (vat_main_t * vam)
3400 {
3401   unformat_input_t *i = vam->input;
3402   vl_api_sw_interface_set_mpls_enable_t *mp;
3403   u32 sw_if_index;
3404   u8 sw_if_index_set = 0;
3405   u8 enable = 1;
3406   int ret;
3407
3408   /* Parse args required to build the message */
3409   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3410     {
3411       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3412         sw_if_index_set = 1;
3413       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3414         sw_if_index_set = 1;
3415       else if (unformat (i, "disable"))
3416         enable = 0;
3417       else if (unformat (i, "dis"))
3418         enable = 0;
3419       else
3420         break;
3421     }
3422
3423   if (sw_if_index_set == 0)
3424     {
3425       errmsg ("missing interface name or sw_if_index");
3426       return -99;
3427     }
3428
3429   /* Construct the API message */
3430   M (SW_INTERFACE_SET_MPLS_ENABLE, mp);
3431
3432   mp->sw_if_index = ntohl (sw_if_index);
3433   mp->enable = enable;
3434
3435   /* send it... */
3436   S (mp);
3437
3438   /* Wait for a reply... */
3439   W (ret);
3440   return ret;
3441 }
3442
3443 static int
3444 api_sw_interface_set_table (vat_main_t * vam)
3445 {
3446   unformat_input_t *i = vam->input;
3447   vl_api_sw_interface_set_table_t *mp;
3448   u32 sw_if_index, vrf_id = 0;
3449   u8 sw_if_index_set = 0;
3450   u8 is_ipv6 = 0;
3451   int ret;
3452
3453   /* Parse args required to build the message */
3454   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3455     {
3456       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3457         sw_if_index_set = 1;
3458       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3459         sw_if_index_set = 1;
3460       else if (unformat (i, "vrf %d", &vrf_id))
3461         ;
3462       else if (unformat (i, "ipv6"))
3463         is_ipv6 = 1;
3464       else
3465         break;
3466     }
3467
3468   if (sw_if_index_set == 0)
3469     {
3470       errmsg ("missing interface name or sw_if_index");
3471       return -99;
3472     }
3473
3474   /* Construct the API message */
3475   M (SW_INTERFACE_SET_TABLE, mp);
3476
3477   mp->sw_if_index = ntohl (sw_if_index);
3478   mp->is_ipv6 = is_ipv6;
3479   mp->vrf_id = ntohl (vrf_id);
3480
3481   /* send it... */
3482   S (mp);
3483
3484   /* Wait for a reply... */
3485   W (ret);
3486   return ret;
3487 }
3488
3489 static void vl_api_sw_interface_get_table_reply_t_handler
3490   (vl_api_sw_interface_get_table_reply_t * mp)
3491 {
3492   vat_main_t *vam = &vat_main;
3493
3494   print (vam->ofp, "%d", ntohl (mp->vrf_id));
3495
3496   vam->retval = ntohl (mp->retval);
3497   vam->result_ready = 1;
3498
3499 }
3500
3501 static void vl_api_sw_interface_get_table_reply_t_handler_json
3502   (vl_api_sw_interface_get_table_reply_t * mp)
3503 {
3504   vat_main_t *vam = &vat_main;
3505   vat_json_node_t node;
3506
3507   vat_json_init_object (&node);
3508   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
3509   vat_json_object_add_int (&node, "vrf_id", ntohl (mp->vrf_id));
3510
3511   vat_json_print (vam->ofp, &node);
3512   vat_json_free (&node);
3513
3514   vam->retval = ntohl (mp->retval);
3515   vam->result_ready = 1;
3516 }
3517
3518 static int
3519 api_sw_interface_get_table (vat_main_t * vam)
3520 {
3521   unformat_input_t *i = vam->input;
3522   vl_api_sw_interface_get_table_t *mp;
3523   u32 sw_if_index;
3524   u8 sw_if_index_set = 0;
3525   u8 is_ipv6 = 0;
3526   int ret;
3527
3528   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3529     {
3530       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3531         sw_if_index_set = 1;
3532       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3533         sw_if_index_set = 1;
3534       else if (unformat (i, "ipv6"))
3535         is_ipv6 = 1;
3536       else
3537         break;
3538     }
3539
3540   if (sw_if_index_set == 0)
3541     {
3542       errmsg ("missing interface name or sw_if_index");
3543       return -99;
3544     }
3545
3546   M (SW_INTERFACE_GET_TABLE, mp);
3547   mp->sw_if_index = htonl (sw_if_index);
3548   mp->is_ipv6 = is_ipv6;
3549
3550   S (mp);
3551   W (ret);
3552   return ret;
3553 }
3554
3555 static int
3556 api_sw_interface_set_vpath (vat_main_t * vam)
3557 {
3558   unformat_input_t *i = vam->input;
3559   vl_api_sw_interface_set_vpath_t *mp;
3560   u32 sw_if_index = 0;
3561   u8 sw_if_index_set = 0;
3562   u8 is_enable = 0;
3563   int ret;
3564
3565   /* Parse args required to build the message */
3566   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3567     {
3568       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3569         sw_if_index_set = 1;
3570       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3571         sw_if_index_set = 1;
3572       else if (unformat (i, "enable"))
3573         is_enable = 1;
3574       else if (unformat (i, "disable"))
3575         is_enable = 0;
3576       else
3577         break;
3578     }
3579
3580   if (sw_if_index_set == 0)
3581     {
3582       errmsg ("missing interface name or sw_if_index");
3583       return -99;
3584     }
3585
3586   /* Construct the API message */
3587   M (SW_INTERFACE_SET_VPATH, mp);
3588
3589   mp->sw_if_index = ntohl (sw_if_index);
3590   mp->enable = is_enable;
3591
3592   /* send it... */
3593   S (mp);
3594
3595   /* Wait for a reply... */
3596   W (ret);
3597   return ret;
3598 }
3599
3600 static int
3601 api_sw_interface_set_l2_xconnect (vat_main_t * vam)
3602 {
3603   unformat_input_t *i = vam->input;
3604   vl_api_sw_interface_set_l2_xconnect_t *mp;
3605   u32 rx_sw_if_index;
3606   u8 rx_sw_if_index_set = 0;
3607   u32 tx_sw_if_index;
3608   u8 tx_sw_if_index_set = 0;
3609   u8 enable = 1;
3610   int ret;
3611
3612   /* Parse args required to build the message */
3613   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3614     {
3615       if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index))
3616         rx_sw_if_index_set = 1;
3617       else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
3618         tx_sw_if_index_set = 1;
3619       else if (unformat (i, "rx"))
3620         {
3621           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3622             {
3623               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
3624                             &rx_sw_if_index))
3625                 rx_sw_if_index_set = 1;
3626             }
3627           else
3628             break;
3629         }
3630       else if (unformat (i, "tx"))
3631         {
3632           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3633             {
3634               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
3635                             &tx_sw_if_index))
3636                 tx_sw_if_index_set = 1;
3637             }
3638           else
3639             break;
3640         }
3641       else if (unformat (i, "enable"))
3642         enable = 1;
3643       else if (unformat (i, "disable"))
3644         enable = 0;
3645       else
3646         break;
3647     }
3648
3649   if (rx_sw_if_index_set == 0)
3650     {
3651       errmsg ("missing rx interface name or rx_sw_if_index");
3652       return -99;
3653     }
3654
3655   if (enable && (tx_sw_if_index_set == 0))
3656     {
3657       errmsg ("missing tx interface name or tx_sw_if_index");
3658       return -99;
3659     }
3660
3661   M (SW_INTERFACE_SET_L2_XCONNECT, mp);
3662
3663   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
3664   mp->tx_sw_if_index = ntohl (tx_sw_if_index);
3665   mp->enable = enable;
3666
3667   S (mp);
3668   W (ret);
3669   return ret;
3670 }
3671
3672 static int
3673 api_sw_interface_set_l2_bridge (vat_main_t * vam)
3674 {
3675   unformat_input_t *i = vam->input;
3676   vl_api_sw_interface_set_l2_bridge_t *mp;
3677   vl_api_l2_port_type_t port_type;
3678   u32 rx_sw_if_index;
3679   u8 rx_sw_if_index_set = 0;
3680   u32 bd_id;
3681   u8 bd_id_set = 0;
3682   u32 shg = 0;
3683   u8 enable = 1;
3684   int ret;
3685
3686   port_type = L2_API_PORT_TYPE_NORMAL;
3687
3688   /* Parse args required to build the message */
3689   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3690     {
3691       if (unformat (i, "sw_if_index %d", &rx_sw_if_index))
3692         rx_sw_if_index_set = 1;
3693       else if (unformat (i, "bd_id %d", &bd_id))
3694         bd_id_set = 1;
3695       else
3696         if (unformat
3697             (i, "%U", api_unformat_sw_if_index, vam, &rx_sw_if_index))
3698         rx_sw_if_index_set = 1;
3699       else if (unformat (i, "shg %d", &shg))
3700         ;
3701       else if (unformat (i, "bvi"))
3702         port_type = L2_API_PORT_TYPE_BVI;
3703       else if (unformat (i, "uu-fwd"))
3704         port_type = L2_API_PORT_TYPE_UU_FWD;
3705       else if (unformat (i, "enable"))
3706         enable = 1;
3707       else if (unformat (i, "disable"))
3708         enable = 0;
3709       else
3710         break;
3711     }
3712
3713   if (rx_sw_if_index_set == 0)
3714     {
3715       errmsg ("missing rx interface name or sw_if_index");
3716       return -99;
3717     }
3718
3719   if (enable && (bd_id_set == 0))
3720     {
3721       errmsg ("missing bridge domain");
3722       return -99;
3723     }
3724
3725   M (SW_INTERFACE_SET_L2_BRIDGE, mp);
3726
3727   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
3728   mp->bd_id = ntohl (bd_id);
3729   mp->shg = (u8) shg;
3730   mp->port_type = ntohl (port_type);
3731   mp->enable = enable;
3732
3733   S (mp);
3734   W (ret);
3735   return ret;
3736 }
3737
3738 static int
3739 api_bridge_domain_dump (vat_main_t * vam)
3740 {
3741   unformat_input_t *i = vam->input;
3742   vl_api_bridge_domain_dump_t *mp;
3743   vl_api_control_ping_t *mp_ping;
3744   u32 bd_id = ~0;
3745   int ret;
3746
3747   /* Parse args required to build the message */
3748   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3749     {
3750       if (unformat (i, "bd_id %d", &bd_id))
3751         ;
3752       else
3753         break;
3754     }
3755
3756   M (BRIDGE_DOMAIN_DUMP, mp);
3757   mp->bd_id = ntohl (bd_id);
3758   S (mp);
3759
3760   /* Use a control ping for synchronization */
3761   MPING (CONTROL_PING, mp_ping);
3762   S (mp_ping);
3763
3764   W (ret);
3765   return ret;
3766 }
3767
3768 static int
3769 api_bridge_domain_add_del (vat_main_t * vam)
3770 {
3771   unformat_input_t *i = vam->input;
3772   vl_api_bridge_domain_add_del_t *mp;
3773   u32 bd_id = ~0;
3774   u8 is_add = 1;
3775   u32 flood = 1, forward = 1, learn = 1, uu_flood = 1, arp_term = 0;
3776   u8 *bd_tag = NULL;
3777   u32 mac_age = 0;
3778   int ret;
3779
3780   /* Parse args required to build the message */
3781   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3782     {
3783       if (unformat (i, "bd_id %d", &bd_id))
3784         ;
3785       else if (unformat (i, "flood %d", &flood))
3786         ;
3787       else if (unformat (i, "uu-flood %d", &uu_flood))
3788         ;
3789       else if (unformat (i, "forward %d", &forward))
3790         ;
3791       else if (unformat (i, "learn %d", &learn))
3792         ;
3793       else if (unformat (i, "arp-term %d", &arp_term))
3794         ;
3795       else if (unformat (i, "mac-age %d", &mac_age))
3796         ;
3797       else if (unformat (i, "bd-tag %s", &bd_tag))
3798         ;
3799       else if (unformat (i, "del"))
3800         {
3801           is_add = 0;
3802           flood = uu_flood = forward = learn = 0;
3803         }
3804       else
3805         break;
3806     }
3807
3808   if (bd_id == ~0)
3809     {
3810       errmsg ("missing bridge domain");
3811       ret = -99;
3812       goto done;
3813     }
3814
3815   if (mac_age > 255)
3816     {
3817       errmsg ("mac age must be less than 256 ");
3818       ret = -99;
3819       goto done;
3820     }
3821
3822   if ((bd_tag) && (vec_len (bd_tag) > 63))
3823     {
3824       errmsg ("bd-tag cannot be longer than 63");
3825       ret = -99;
3826       goto done;
3827     }
3828
3829   M (BRIDGE_DOMAIN_ADD_DEL, mp);
3830
3831   mp->bd_id = ntohl (bd_id);
3832   mp->flood = flood;
3833   mp->uu_flood = uu_flood;
3834   mp->forward = forward;
3835   mp->learn = learn;
3836   mp->arp_term = arp_term;
3837   mp->is_add = is_add;
3838   mp->mac_age = (u8) mac_age;
3839   if (bd_tag)
3840     {
3841       clib_memcpy (mp->bd_tag, bd_tag, vec_len (bd_tag));
3842       mp->bd_tag[vec_len (bd_tag)] = 0;
3843     }
3844   S (mp);
3845   W (ret);
3846
3847 done:
3848   vec_free (bd_tag);
3849   return ret;
3850 }
3851
3852 static int
3853 api_l2fib_flush_bd (vat_main_t * vam)
3854 {
3855   unformat_input_t *i = vam->input;
3856   vl_api_l2fib_flush_bd_t *mp;
3857   u32 bd_id = ~0;
3858   int ret;
3859
3860   /* Parse args required to build the message */
3861   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3862     {
3863       if (unformat (i, "bd_id %d", &bd_id));
3864       else
3865         break;
3866     }
3867
3868   if (bd_id == ~0)
3869     {
3870       errmsg ("missing bridge domain");
3871       return -99;
3872     }
3873
3874   M (L2FIB_FLUSH_BD, mp);
3875
3876   mp->bd_id = htonl (bd_id);
3877
3878   S (mp);
3879   W (ret);
3880   return ret;
3881 }
3882
3883 static int
3884 api_l2fib_flush_int (vat_main_t * vam)
3885 {
3886   unformat_input_t *i = vam->input;
3887   vl_api_l2fib_flush_int_t *mp;
3888   u32 sw_if_index = ~0;
3889   int ret;
3890
3891   /* Parse args required to build the message */
3892   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3893     {
3894       if (unformat (i, "sw_if_index %d", &sw_if_index));
3895       else
3896         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index));
3897       else
3898         break;
3899     }
3900
3901   if (sw_if_index == ~0)
3902     {
3903       errmsg ("missing interface name or sw_if_index");
3904       return -99;
3905     }
3906
3907   M (L2FIB_FLUSH_INT, mp);
3908
3909   mp->sw_if_index = ntohl (sw_if_index);
3910
3911   S (mp);
3912   W (ret);
3913   return ret;
3914 }
3915
3916 static int
3917 api_l2fib_add_del (vat_main_t * vam)
3918 {
3919   unformat_input_t *i = vam->input;
3920   vl_api_l2fib_add_del_t *mp;
3921   f64 timeout;
3922   u8 mac[6] = { 0 };
3923   u8 mac_set = 0;
3924   u32 bd_id;
3925   u8 bd_id_set = 0;
3926   u32 sw_if_index = 0;
3927   u8 sw_if_index_set = 0;
3928   u8 is_add = 1;
3929   u8 static_mac = 0;
3930   u8 filter_mac = 0;
3931   u8 bvi_mac = 0;
3932   int count = 1;
3933   f64 before = 0;
3934   int j;
3935
3936   /* Parse args required to build the message */
3937   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3938     {
3939       if (unformat (i, "mac %U", unformat_ethernet_address, mac))
3940         mac_set = 1;
3941       else if (unformat (i, "bd_id %d", &bd_id))
3942         bd_id_set = 1;
3943       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3944         sw_if_index_set = 1;
3945       else if (unformat (i, "sw_if"))
3946         {
3947           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3948             {
3949               if (unformat
3950                   (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3951                 sw_if_index_set = 1;
3952             }
3953           else
3954             break;
3955         }
3956       else if (unformat (i, "static"))
3957         static_mac = 1;
3958       else if (unformat (i, "filter"))
3959         {
3960           filter_mac = 1;
3961           static_mac = 1;
3962         }
3963       else if (unformat (i, "bvi"))
3964         {
3965           bvi_mac = 1;
3966           static_mac = 1;
3967         }
3968       else if (unformat (i, "del"))
3969         is_add = 0;
3970       else if (unformat (i, "count %d", &count))
3971         ;
3972       else
3973         break;
3974     }
3975
3976   if (mac_set == 0)
3977     {
3978       errmsg ("missing mac address");
3979       return -99;
3980     }
3981
3982   if (bd_id_set == 0)
3983     {
3984       errmsg ("missing bridge domain");
3985       return -99;
3986     }
3987
3988   if (is_add && sw_if_index_set == 0 && filter_mac == 0)
3989     {
3990       errmsg ("missing interface name or sw_if_index");
3991       return -99;
3992     }
3993
3994   if (count > 1)
3995     {
3996       /* Turn on async mode */
3997       vam->async_mode = 1;
3998       vam->async_errors = 0;
3999       before = vat_time_now (vam);
4000     }
4001
4002   for (j = 0; j < count; j++)
4003     {
4004       M (L2FIB_ADD_DEL, mp);
4005
4006       clib_memcpy (mp->mac, mac, 6);
4007       mp->bd_id = ntohl (bd_id);
4008       mp->is_add = is_add;
4009       mp->sw_if_index = ntohl (sw_if_index);
4010
4011       if (is_add)
4012         {
4013           mp->static_mac = static_mac;
4014           mp->filter_mac = filter_mac;
4015           mp->bvi_mac = bvi_mac;
4016         }
4017       increment_mac_address (mac);
4018       /* send it... */
4019       S (mp);
4020     }
4021
4022   if (count > 1)
4023     {
4024       vl_api_control_ping_t *mp_ping;
4025       f64 after;
4026
4027       /* Shut off async mode */
4028       vam->async_mode = 0;
4029
4030       MPING (CONTROL_PING, mp_ping);
4031       S (mp_ping);
4032
4033       timeout = vat_time_now (vam) + 1.0;
4034       while (vat_time_now (vam) < timeout)
4035         if (vam->result_ready == 1)
4036           goto out;
4037       vam->retval = -99;
4038
4039     out:
4040       if (vam->retval == -99)
4041         errmsg ("timeout");
4042
4043       if (vam->async_errors > 0)
4044         {
4045           errmsg ("%d asynchronous errors", vam->async_errors);
4046           vam->retval = -98;
4047         }
4048       vam->async_errors = 0;
4049       after = vat_time_now (vam);
4050
4051       print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec",
4052              count, after - before, count / (after - before));
4053     }
4054   else
4055     {
4056       int ret;
4057
4058       /* Wait for a reply... */
4059       W (ret);
4060       return ret;
4061     }
4062   /* Return the good/bad news */
4063   return (vam->retval);
4064 }
4065
4066 static int
4067 api_bridge_domain_set_mac_age (vat_main_t * vam)
4068 {
4069   unformat_input_t *i = vam->input;
4070   vl_api_bridge_domain_set_mac_age_t *mp;
4071   u32 bd_id = ~0;
4072   u32 mac_age = 0;
4073   int ret;
4074
4075   /* Parse args required to build the message */
4076   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4077     {
4078       if (unformat (i, "bd_id %d", &bd_id));
4079       else if (unformat (i, "mac-age %d", &mac_age));
4080       else
4081         break;
4082     }
4083
4084   if (bd_id == ~0)
4085     {
4086       errmsg ("missing bridge domain");
4087       return -99;
4088     }
4089
4090   if (mac_age > 255)
4091     {
4092       errmsg ("mac age must be less than 256 ");
4093       return -99;
4094     }
4095
4096   M (BRIDGE_DOMAIN_SET_MAC_AGE, mp);
4097
4098   mp->bd_id = htonl (bd_id);
4099   mp->mac_age = (u8) mac_age;
4100
4101   S (mp);
4102   W (ret);
4103   return ret;
4104 }
4105
4106 static int
4107 api_l2_flags (vat_main_t * vam)
4108 {
4109   unformat_input_t *i = vam->input;
4110   vl_api_l2_flags_t *mp;
4111   u32 sw_if_index;
4112   u32 flags = 0;
4113   u8 sw_if_index_set = 0;
4114   u8 is_set = 0;
4115   int ret;
4116
4117   /* Parse args required to build the message */
4118   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4119     {
4120       if (unformat (i, "sw_if_index %d", &sw_if_index))
4121         sw_if_index_set = 1;
4122       else if (unformat (i, "sw_if"))
4123         {
4124           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4125             {
4126               if (unformat
4127                   (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4128                 sw_if_index_set = 1;
4129             }
4130           else
4131             break;
4132         }
4133       else if (unformat (i, "learn"))
4134         flags |= L2_LEARN;
4135       else if (unformat (i, "forward"))
4136         flags |= L2_FWD;
4137       else if (unformat (i, "flood"))
4138         flags |= L2_FLOOD;
4139       else if (unformat (i, "uu-flood"))
4140         flags |= L2_UU_FLOOD;
4141       else if (unformat (i, "arp-term"))
4142         flags |= L2_ARP_TERM;
4143       else if (unformat (i, "off"))
4144         is_set = 0;
4145       else if (unformat (i, "disable"))
4146         is_set = 0;
4147       else
4148         break;
4149     }
4150
4151   if (sw_if_index_set == 0)
4152     {
4153       errmsg ("missing interface name or sw_if_index");
4154       return -99;
4155     }
4156
4157   M (L2_FLAGS, mp);
4158
4159   mp->sw_if_index = ntohl (sw_if_index);
4160   mp->feature_bitmap = ntohl (flags);
4161   mp->is_set = is_set;
4162
4163   S (mp);
4164   W (ret);
4165   return ret;
4166 }
4167
4168 static int
4169 api_bridge_flags (vat_main_t * vam)
4170 {
4171   unformat_input_t *i = vam->input;
4172   vl_api_bridge_flags_t *mp;
4173   u32 bd_id;
4174   u8 bd_id_set = 0;
4175   u8 is_set = 1;
4176   bd_flags_t flags = 0;
4177   int ret;
4178
4179   /* Parse args required to build the message */
4180   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4181     {
4182       if (unformat (i, "bd_id %d", &bd_id))
4183         bd_id_set = 1;
4184       else if (unformat (i, "learn"))
4185         flags |= BRIDGE_API_FLAG_LEARN;
4186       else if (unformat (i, "forward"))
4187         flags |= BRIDGE_API_FLAG_FWD;
4188       else if (unformat (i, "flood"))
4189         flags |= BRIDGE_API_FLAG_FLOOD;
4190       else if (unformat (i, "uu-flood"))
4191         flags |= BRIDGE_API_FLAG_UU_FLOOD;
4192       else if (unformat (i, "arp-term"))
4193         flags |= BRIDGE_API_FLAG_ARP_TERM;
4194       else if (unformat (i, "off"))
4195         is_set = 0;
4196       else if (unformat (i, "disable"))
4197         is_set = 0;
4198       else
4199         break;
4200     }
4201
4202   if (bd_id_set == 0)
4203     {
4204       errmsg ("missing bridge domain");
4205       return -99;
4206     }
4207
4208   M (BRIDGE_FLAGS, mp);
4209
4210   mp->bd_id = ntohl (bd_id);
4211   mp->flags = ntohl (flags);
4212   mp->is_set = is_set;
4213
4214   S (mp);
4215   W (ret);
4216   return ret;
4217 }
4218
4219 static int
4220 api_bd_ip_mac_add_del (vat_main_t * vam)
4221 {
4222   vl_api_address_t ip = VL_API_ZERO_ADDRESS;
4223   vl_api_mac_address_t mac = { 0 };
4224   unformat_input_t *i = vam->input;
4225   vl_api_bd_ip_mac_add_del_t *mp;
4226   u32 bd_id;
4227   u8 is_add = 1;
4228   u8 bd_id_set = 0;
4229   u8 ip_set = 0;
4230   u8 mac_set = 0;
4231   int ret;
4232
4233
4234   /* Parse args required to build the message */
4235   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4236     {
4237       if (unformat (i, "bd_id %d", &bd_id))
4238         {
4239           bd_id_set++;
4240         }
4241       else if (unformat (i, "%U", unformat_vl_api_address, &ip))
4242         {
4243           ip_set++;
4244         }
4245       else if (unformat (i, "%U", unformat_vl_api_mac_address, &mac))
4246         {
4247           mac_set++;
4248         }
4249       else if (unformat (i, "del"))
4250         is_add = 0;
4251       else
4252         break;
4253     }
4254
4255   if (bd_id_set == 0)
4256     {
4257       errmsg ("missing bridge domain");
4258       return -99;
4259     }
4260   else if (ip_set == 0)
4261     {
4262       errmsg ("missing IP address");
4263       return -99;
4264     }
4265   else if (mac_set == 0)
4266     {
4267       errmsg ("missing MAC address");
4268       return -99;
4269     }
4270
4271   M (BD_IP_MAC_ADD_DEL, mp);
4272
4273   mp->entry.bd_id = ntohl (bd_id);
4274   mp->is_add = is_add;
4275
4276   clib_memcpy (&mp->entry.ip, &ip, sizeof (ip));
4277   clib_memcpy (&mp->entry.mac, &mac, sizeof (mac));
4278
4279   S (mp);
4280   W (ret);
4281   return ret;
4282 }
4283
4284 static int
4285 api_bd_ip_mac_flush (vat_main_t * vam)
4286 {
4287   unformat_input_t *i = vam->input;
4288   vl_api_bd_ip_mac_flush_t *mp;
4289   u32 bd_id;
4290   u8 bd_id_set = 0;
4291   int ret;
4292
4293   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4294     {
4295       if (unformat (i, "bd_id %d", &bd_id))
4296         {
4297           bd_id_set++;
4298         }
4299       else
4300         break;
4301     }
4302
4303   if (bd_id_set == 0)
4304     {
4305       errmsg ("missing bridge domain");
4306       return -99;
4307     }
4308
4309   M (BD_IP_MAC_FLUSH, mp);
4310
4311   mp->bd_id = ntohl (bd_id);
4312
4313   S (mp);
4314   W (ret);
4315   return ret;
4316 }
4317
4318 static void vl_api_bd_ip_mac_details_t_handler
4319   (vl_api_bd_ip_mac_details_t * mp)
4320 {
4321   vat_main_t *vam = &vat_main;
4322
4323   print (vam->ofp,
4324          "\n%-5d %U %U",
4325          ntohl (mp->entry.bd_id),
4326          format_vl_api_mac_address, mp->entry.mac,
4327          format_vl_api_address, &mp->entry.ip);
4328 }
4329
4330 static void vl_api_bd_ip_mac_details_t_handler_json
4331   (vl_api_bd_ip_mac_details_t * mp)
4332 {
4333   vat_main_t *vam = &vat_main;
4334   vat_json_node_t *node = NULL;
4335
4336   if (VAT_JSON_ARRAY != vam->json_tree.type)
4337     {
4338       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
4339       vat_json_init_array (&vam->json_tree);
4340     }
4341   node = vat_json_array_add (&vam->json_tree);
4342
4343   vat_json_init_object (node);
4344   vat_json_object_add_uint (node, "bd_id", ntohl (mp->entry.bd_id));
4345   vat_json_object_add_string_copy (node, "mac_address",
4346                                    format (0, "%U", format_vl_api_mac_address,
4347                                            &mp->entry.mac));
4348   u8 *ip = 0;
4349
4350   ip = format (0, "%U", format_vl_api_address, &mp->entry.ip);
4351   vat_json_object_add_string_copy (node, "ip_address", ip);
4352   vec_free (ip);
4353 }
4354
4355 static int
4356 api_bd_ip_mac_dump (vat_main_t * vam)
4357 {
4358   unformat_input_t *i = vam->input;
4359   vl_api_bd_ip_mac_dump_t *mp;
4360   vl_api_control_ping_t *mp_ping;
4361   int ret;
4362   u32 bd_id;
4363   u8 bd_id_set = 0;
4364
4365   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4366     {
4367       if (unformat (i, "bd_id %d", &bd_id))
4368         {
4369           bd_id_set++;
4370         }
4371       else
4372         break;
4373     }
4374
4375   print (vam->ofp,
4376          "\n%-5s %-7s %-20s %-30s",
4377          "bd_id", "is_ipv6", "mac_address", "ip_address");
4378
4379   /* Dump Bridge Domain Ip to Mac entries */
4380   M (BD_IP_MAC_DUMP, mp);
4381
4382   if (bd_id_set)
4383     mp->bd_id = htonl (bd_id);
4384   else
4385     mp->bd_id = ~0;
4386
4387   S (mp);
4388
4389   /* Use a control ping for synchronization */
4390   MPING (CONTROL_PING, mp_ping);
4391   S (mp_ping);
4392
4393   W (ret);
4394   return ret;
4395 }
4396
4397 static int
4398 api_tap_create_v2 (vat_main_t * vam)
4399 {
4400   unformat_input_t *i = vam->input;
4401   vl_api_tap_create_v2_t *mp;
4402   u8 mac_address[6];
4403   u8 random_mac = 1;
4404   u32 id = ~0;
4405   u32 num_rx_queues = 0;
4406   u8 *host_if_name = 0;
4407   u8 host_if_name_set = 0;
4408   u8 *host_ns = 0;
4409   u8 host_ns_set = 0;
4410   u8 host_mac_addr[6];
4411   u8 host_mac_addr_set = 0;
4412   u8 *host_bridge = 0;
4413   u8 host_bridge_set = 0;
4414   u8 host_ip4_prefix_set = 0;
4415   u8 host_ip6_prefix_set = 0;
4416   ip4_address_t host_ip4_addr;
4417   ip4_address_t host_ip4_gw;
4418   u8 host_ip4_gw_set = 0;
4419   u32 host_ip4_prefix_len = 0;
4420   ip6_address_t host_ip6_addr;
4421   ip6_address_t host_ip6_gw;
4422   u8 host_ip6_gw_set = 0;
4423   u32 host_ip6_prefix_len = 0;
4424   u32 host_mtu_size = 0;
4425   u8 host_mtu_set = 0;
4426   u32 tap_flags = 0;
4427   int ret;
4428   u32 rx_ring_sz = 0, tx_ring_sz = 0;
4429
4430   clib_memset (mac_address, 0, sizeof (mac_address));
4431
4432   /* Parse args required to build the message */
4433   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4434     {
4435       if (unformat (i, "id %u", &id))
4436         ;
4437       else
4438         if (unformat
4439             (i, "hw-addr %U", unformat_ethernet_address, mac_address))
4440         random_mac = 0;
4441       else if (unformat (i, "host-if-name %s", &host_if_name))
4442         host_if_name_set = 1;
4443       else if (unformat (i, "num-rx-queues %u", &num_rx_queues))
4444         ;
4445       else if (unformat (i, "host-ns %s", &host_ns))
4446         host_ns_set = 1;
4447       else if (unformat (i, "host-mac-addr %U", unformat_ethernet_address,
4448                          host_mac_addr))
4449         host_mac_addr_set = 1;
4450       else if (unformat (i, "host-bridge %s", &host_bridge))
4451         host_bridge_set = 1;
4452       else if (unformat (i, "host-ip4-addr %U/%u", unformat_ip4_address,
4453                          &host_ip4_addr, &host_ip4_prefix_len))
4454         host_ip4_prefix_set = 1;
4455       else if (unformat (i, "host-ip6-addr %U/%u", unformat_ip6_address,
4456                          &host_ip6_addr, &host_ip6_prefix_len))
4457         host_ip6_prefix_set = 1;
4458       else if (unformat (i, "host-ip4-gw %U", unformat_ip4_address,
4459                          &host_ip4_gw))
4460         host_ip4_gw_set = 1;
4461       else if (unformat (i, "host-ip6-gw %U", unformat_ip6_address,
4462                          &host_ip6_gw))
4463         host_ip6_gw_set = 1;
4464       else if (unformat (i, "rx-ring-size %u", &rx_ring_sz))
4465         ;
4466       else if (unformat (i, "tx-ring-size %u", &tx_ring_sz))
4467         ;
4468       else if (unformat (i, "host-mtu-size %u", &host_mtu_size))
4469         host_mtu_set = 1;
4470       else if (unformat (i, "no-gso"))
4471         tap_flags &= ~TAP_API_FLAG_GSO;
4472       else if (unformat (i, "gso"))
4473         tap_flags |= TAP_API_FLAG_GSO;
4474       else if (unformat (i, "csum-offload"))
4475         tap_flags |= TAP_API_FLAG_CSUM_OFFLOAD;
4476       else if (unformat (i, "persist"))
4477         tap_flags |= TAP_API_FLAG_PERSIST;
4478       else if (unformat (i, "attach"))
4479         tap_flags |= TAP_API_FLAG_ATTACH;
4480       else if (unformat (i, "tun"))
4481         tap_flags |= TAP_API_FLAG_TUN;
4482       else if (unformat (i, "gro-coalesce"))
4483         tap_flags |= TAP_API_FLAG_GRO_COALESCE;
4484       else if (unformat (i, "packed"))
4485         tap_flags |= TAP_API_FLAG_PACKED;
4486       else if (unformat (i, "in-order"))
4487         tap_flags |= TAP_API_FLAG_IN_ORDER;
4488       else
4489         break;
4490     }
4491
4492   if (vec_len (host_if_name) > 63)
4493     {
4494       errmsg ("tap name too long. ");
4495       return -99;
4496     }
4497   if (vec_len (host_ns) > 63)
4498     {
4499       errmsg ("host name space too long. ");
4500       return -99;
4501     }
4502   if (vec_len (host_bridge) > 63)
4503     {
4504       errmsg ("host bridge name too long. ");
4505       return -99;
4506     }
4507   if (host_ip4_prefix_len > 32)
4508     {
4509       errmsg ("host ip4 prefix length not valid. ");
4510       return -99;
4511     }
4512   if (host_ip6_prefix_len > 128)
4513     {
4514       errmsg ("host ip6 prefix length not valid. ");
4515       return -99;
4516     }
4517   if (!is_pow2 (rx_ring_sz))
4518     {
4519       errmsg ("rx ring size must be power of 2. ");
4520       return -99;
4521     }
4522   if (rx_ring_sz > 32768)
4523     {
4524       errmsg ("rx ring size must be 32768 or lower. ");
4525       return -99;
4526     }
4527   if (!is_pow2 (tx_ring_sz))
4528     {
4529       errmsg ("tx ring size must be power of 2. ");
4530       return -99;
4531     }
4532   if (tx_ring_sz > 32768)
4533     {
4534       errmsg ("tx ring size must be 32768 or lower. ");
4535       return -99;
4536     }
4537   if (host_mtu_set && (host_mtu_size < 64 || host_mtu_size > 65355))
4538     {
4539       errmsg ("host MTU size must be in between 64 and 65355. ");
4540       return -99;
4541     }
4542
4543   /* Construct the API message */
4544   M (TAP_CREATE_V2, mp);
4545
4546   mp->id = ntohl (id);
4547   mp->use_random_mac = random_mac;
4548   mp->num_rx_queues = (u8) num_rx_queues;
4549   mp->tx_ring_sz = ntohs (tx_ring_sz);
4550   mp->rx_ring_sz = ntohs (rx_ring_sz);
4551   mp->host_mtu_set = host_mtu_set;
4552   mp->host_mtu_size = ntohl (host_mtu_size);
4553   mp->host_mac_addr_set = host_mac_addr_set;
4554   mp->host_ip4_prefix_set = host_ip4_prefix_set;
4555   mp->host_ip6_prefix_set = host_ip6_prefix_set;
4556   mp->host_ip4_gw_set = host_ip4_gw_set;
4557   mp->host_ip6_gw_set = host_ip6_gw_set;
4558   mp->tap_flags = ntohl (tap_flags);
4559   mp->host_namespace_set = host_ns_set;
4560   mp->host_if_name_set = host_if_name_set;
4561   mp->host_bridge_set = host_bridge_set;
4562
4563   if (random_mac == 0)
4564     clib_memcpy (mp->mac_address, mac_address, 6);
4565   if (host_mac_addr_set)
4566     clib_memcpy (mp->host_mac_addr, host_mac_addr, 6);
4567   if (host_if_name_set)
4568     clib_memcpy (mp->host_if_name, host_if_name, vec_len (host_if_name));
4569   if (host_ns_set)
4570     clib_memcpy (mp->host_namespace, host_ns, vec_len (host_ns));
4571   if (host_bridge_set)
4572     clib_memcpy (mp->host_bridge, host_bridge, vec_len (host_bridge));
4573   if (host_ip4_prefix_set)
4574     {
4575       clib_memcpy (mp->host_ip4_prefix.address, &host_ip4_addr, 4);
4576       mp->host_ip4_prefix.len = (u8) host_ip4_prefix_len;
4577     }
4578   if (host_ip6_prefix_set)
4579     {
4580       clib_memcpy (mp->host_ip6_prefix.address, &host_ip6_addr, 16);
4581       mp->host_ip6_prefix.len = (u8) host_ip6_prefix_len;
4582     }
4583   if (host_ip4_gw_set)
4584     clib_memcpy (mp->host_ip4_gw, &host_ip4_gw, 4);
4585   if (host_ip6_gw_set)
4586     clib_memcpy (mp->host_ip6_gw, &host_ip6_gw, 16);
4587
4588   vec_free (host_ns);
4589   vec_free (host_if_name);
4590   vec_free (host_bridge);
4591
4592   /* send it... */
4593   S (mp);
4594
4595   /* Wait for a reply... */
4596   W (ret);
4597   return ret;
4598 }
4599
4600 static int
4601 api_tap_delete_v2 (vat_main_t * vam)
4602 {
4603   unformat_input_t *i = vam->input;
4604   vl_api_tap_delete_v2_t *mp;
4605   u32 sw_if_index = ~0;
4606   u8 sw_if_index_set = 0;
4607   int ret;
4608
4609   /* Parse args required to build the message */
4610   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4611     {
4612       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4613         sw_if_index_set = 1;
4614       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4615         sw_if_index_set = 1;
4616       else
4617         break;
4618     }
4619
4620   if (sw_if_index_set == 0)
4621     {
4622       errmsg ("missing vpp interface name. ");
4623       return -99;
4624     }
4625
4626   /* Construct the API message */
4627   M (TAP_DELETE_V2, mp);
4628
4629   mp->sw_if_index = ntohl (sw_if_index);
4630
4631   /* send it... */
4632   S (mp);
4633
4634   /* Wait for a reply... */
4635   W (ret);
4636   return ret;
4637 }
4638
4639 uword
4640 unformat_vlib_pci_addr (unformat_input_t * input, va_list * args)
4641 {
4642   vlib_pci_addr_t *addr = va_arg (*args, vlib_pci_addr_t *);
4643   u32 x[4];
4644
4645   if (!unformat (input, "%x:%x:%x.%x", &x[0], &x[1], &x[2], &x[3]))
4646     return 0;
4647
4648   addr->domain = x[0];
4649   addr->bus = x[1];
4650   addr->slot = x[2];
4651   addr->function = x[3];
4652
4653   return 1;
4654 }
4655
4656 static int
4657 api_virtio_pci_create_v2 (vat_main_t * vam)
4658 {
4659   unformat_input_t *i = vam->input;
4660   vl_api_virtio_pci_create_v2_t *mp;
4661   u8 mac_address[6];
4662   u8 random_mac = 1;
4663   u32 pci_addr = 0;
4664   u64 features = (u64) ~ (0ULL);
4665   u32 virtio_flags = 0;
4666   int ret;
4667
4668   clib_memset (mac_address, 0, sizeof (mac_address));
4669
4670   /* Parse args required to build the message */
4671   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4672     {
4673       if (unformat (i, "hw-addr %U", unformat_ethernet_address, mac_address))
4674         {
4675           random_mac = 0;
4676         }
4677       else if (unformat (i, "pci-addr %U", unformat_vlib_pci_addr, &pci_addr))
4678         ;
4679       else if (unformat (i, "features 0x%llx", &features))
4680         ;
4681       else if (unformat (i, "gso-enabled"))
4682         virtio_flags |= VIRTIO_API_FLAG_GSO;
4683       else if (unformat (i, "csum-offload-enabled"))
4684         virtio_flags |= VIRTIO_API_FLAG_CSUM_OFFLOAD;
4685       else if (unformat (i, "gro-coalesce"))
4686         virtio_flags |= VIRTIO_API_FLAG_GRO_COALESCE;
4687       else if (unformat (i, "packed"))
4688         virtio_flags |= VIRTIO_API_FLAG_PACKED;
4689       else if (unformat (i, "in-order"))
4690         virtio_flags |= VIRTIO_API_FLAG_IN_ORDER;
4691       else if (unformat (i, "buffering"))
4692         virtio_flags |= VIRTIO_API_FLAG_BUFFERING;
4693       else
4694         break;
4695     }
4696
4697   if (pci_addr == 0)
4698     {
4699       errmsg ("pci address must be non zero. ");
4700       return -99;
4701     }
4702
4703   /* Construct the API message */
4704   M (VIRTIO_PCI_CREATE_V2, mp);
4705
4706   mp->use_random_mac = random_mac;
4707
4708   mp->pci_addr.domain = htons (((vlib_pci_addr_t) pci_addr).domain);
4709   mp->pci_addr.bus = ((vlib_pci_addr_t) pci_addr).bus;
4710   mp->pci_addr.slot = ((vlib_pci_addr_t) pci_addr).slot;
4711   mp->pci_addr.function = ((vlib_pci_addr_t) pci_addr).function;
4712
4713   mp->features = clib_host_to_net_u64 (features);
4714   mp->virtio_flags = clib_host_to_net_u32 (virtio_flags);
4715
4716   if (random_mac == 0)
4717     clib_memcpy (mp->mac_address, mac_address, 6);
4718
4719   /* send it... */
4720   S (mp);
4721
4722   /* Wait for a reply... */
4723   W (ret);
4724   return ret;
4725 }
4726
4727 static int
4728 api_virtio_pci_delete (vat_main_t * vam)
4729 {
4730   unformat_input_t *i = vam->input;
4731   vl_api_virtio_pci_delete_t *mp;
4732   u32 sw_if_index = ~0;
4733   u8 sw_if_index_set = 0;
4734   int ret;
4735
4736   /* Parse args required to build the message */
4737   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4738     {
4739       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4740         sw_if_index_set = 1;
4741       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4742         sw_if_index_set = 1;
4743       else
4744         break;
4745     }
4746
4747   if (sw_if_index_set == 0)
4748     {
4749       errmsg ("missing vpp interface name. ");
4750       return -99;
4751     }
4752
4753   /* Construct the API message */
4754   M (VIRTIO_PCI_DELETE, mp);
4755
4756   mp->sw_if_index = htonl (sw_if_index);
4757
4758   /* send it... */
4759   S (mp);
4760
4761   /* Wait for a reply... */
4762   W (ret);
4763   return ret;
4764 }
4765
4766 static int
4767 api_bond_create (vat_main_t * vam)
4768 {
4769   unformat_input_t *i = vam->input;
4770   vl_api_bond_create_t *mp;
4771   u8 mac_address[6];
4772   u8 custom_mac = 0;
4773   int ret;
4774   u8 mode;
4775   u8 lb;
4776   u8 mode_is_set = 0;
4777   u32 id = ~0;
4778   u8 numa_only = 0;
4779
4780   clib_memset (mac_address, 0, sizeof (mac_address));
4781   lb = BOND_LB_L2;
4782
4783   /* Parse args required to build the message */
4784   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4785     {
4786       if (unformat (i, "mode %U", unformat_bond_mode, &mode))
4787         mode_is_set = 1;
4788       else if (((mode == BOND_MODE_LACP) || (mode == BOND_MODE_XOR))
4789                && unformat (i, "lb %U", unformat_bond_load_balance, &lb))
4790         ;
4791       else if (unformat (i, "hw-addr %U", unformat_ethernet_address,
4792                          mac_address))
4793         custom_mac = 1;
4794       else if (unformat (i, "numa-only"))
4795         numa_only = 1;
4796       else if (unformat (i, "id %u", &id))
4797         ;
4798       else
4799         break;
4800     }
4801
4802   if (mode_is_set == 0)
4803     {
4804       errmsg ("Missing bond mode. ");
4805       return -99;
4806     }
4807
4808   /* Construct the API message */
4809   M (BOND_CREATE, mp);
4810
4811   mp->use_custom_mac = custom_mac;
4812
4813   mp->mode = htonl (mode);
4814   mp->lb = htonl (lb);
4815   mp->id = htonl (id);
4816   mp->numa_only = numa_only;
4817
4818   if (custom_mac)
4819     clib_memcpy (mp->mac_address, mac_address, 6);
4820
4821   /* send it... */
4822   S (mp);
4823
4824   /* Wait for a reply... */
4825   W (ret);
4826   return ret;
4827 }
4828
4829 static int
4830 api_bond_create2 (vat_main_t * vam)
4831 {
4832   unformat_input_t *i = vam->input;
4833   vl_api_bond_create2_t *mp;
4834   u8 mac_address[6];
4835   u8 custom_mac = 0;
4836   int ret;
4837   u8 mode;
4838   u8 lb;
4839   u8 mode_is_set = 0;
4840   u32 id = ~0;
4841   u8 numa_only = 0;
4842   u8 gso = 0;
4843
4844   clib_memset (mac_address, 0, sizeof (mac_address));
4845   lb = BOND_LB_L2;
4846
4847   /* Parse args required to build the message */
4848   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4849     {
4850       if (unformat (i, "mode %U", unformat_bond_mode, &mode))
4851         mode_is_set = 1;
4852       else if (((mode == BOND_MODE_LACP) || (mode == BOND_MODE_XOR))
4853                && unformat (i, "lb %U", unformat_bond_load_balance, &lb))
4854         ;
4855       else if (unformat (i, "hw-addr %U", unformat_ethernet_address,
4856                          mac_address))
4857         custom_mac = 1;
4858       else if (unformat (i, "numa-only"))
4859         numa_only = 1;
4860       else if (unformat (i, "gso"))
4861         gso = 1;
4862       else if (unformat (i, "id %u", &id))
4863         ;
4864       else
4865         break;
4866     }
4867
4868   if (mode_is_set == 0)
4869     {
4870       errmsg ("Missing bond mode. ");
4871       return -99;
4872     }
4873
4874   /* Construct the API message */
4875   M (BOND_CREATE2, mp);
4876
4877   mp->use_custom_mac = custom_mac;
4878
4879   mp->mode = htonl (mode);
4880   mp->lb = htonl (lb);
4881   mp->id = htonl (id);
4882   mp->numa_only = numa_only;
4883   mp->enable_gso = gso;
4884
4885   if (custom_mac)
4886     clib_memcpy (mp->mac_address, mac_address, 6);
4887
4888   /* send it... */
4889   S (mp);
4890
4891   /* Wait for a reply... */
4892   W (ret);
4893   return ret;
4894 }
4895
4896 static int
4897 api_bond_delete (vat_main_t * vam)
4898 {
4899   unformat_input_t *i = vam->input;
4900   vl_api_bond_delete_t *mp;
4901   u32 sw_if_index = ~0;
4902   u8 sw_if_index_set = 0;
4903   int ret;
4904
4905   /* Parse args required to build the message */
4906   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4907     {
4908       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4909         sw_if_index_set = 1;
4910       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4911         sw_if_index_set = 1;
4912       else
4913         break;
4914     }
4915
4916   if (sw_if_index_set == 0)
4917     {
4918       errmsg ("missing vpp interface name. ");
4919       return -99;
4920     }
4921
4922   /* Construct the API message */
4923   M (BOND_DELETE, mp);
4924
4925   mp->sw_if_index = ntohl (sw_if_index);
4926
4927   /* send it... */
4928   S (mp);
4929
4930   /* Wait for a reply... */
4931   W (ret);
4932   return ret;
4933 }
4934
4935 static int
4936 api_bond_add_member (vat_main_t * vam)
4937 {
4938   unformat_input_t *i = vam->input;
4939   vl_api_bond_add_member_t *mp;
4940   u32 bond_sw_if_index;
4941   int ret;
4942   u8 is_passive;
4943   u8 is_long_timeout;
4944   u32 bond_sw_if_index_is_set = 0;
4945   u32 sw_if_index;
4946   u8 sw_if_index_is_set = 0;
4947
4948   /* Parse args required to build the message */
4949   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4950     {
4951       if (unformat (i, "sw_if_index %d", &sw_if_index))
4952         sw_if_index_is_set = 1;
4953       else if (unformat (i, "bond %u", &bond_sw_if_index))
4954         bond_sw_if_index_is_set = 1;
4955       else if (unformat (i, "passive %d", &is_passive))
4956         ;
4957       else if (unformat (i, "long-timeout %d", &is_long_timeout))
4958         ;
4959       else
4960         break;
4961     }
4962
4963   if (bond_sw_if_index_is_set == 0)
4964     {
4965       errmsg ("Missing bond sw_if_index. ");
4966       return -99;
4967     }
4968   if (sw_if_index_is_set == 0)
4969     {
4970       errmsg ("Missing member sw_if_index. ");
4971       return -99;
4972     }
4973
4974   /* Construct the API message */
4975   M (BOND_ADD_MEMBER, mp);
4976
4977   mp->bond_sw_if_index = ntohl (bond_sw_if_index);
4978   mp->sw_if_index = ntohl (sw_if_index);
4979   mp->is_long_timeout = is_long_timeout;
4980   mp->is_passive = is_passive;
4981
4982   /* send it... */
4983   S (mp);
4984
4985   /* Wait for a reply... */
4986   W (ret);
4987   return ret;
4988 }
4989
4990 static int
4991 api_bond_detach_member (vat_main_t * vam)
4992 {
4993   unformat_input_t *i = vam->input;
4994   vl_api_bond_detach_member_t *mp;
4995   u32 sw_if_index = ~0;
4996   u8 sw_if_index_set = 0;
4997   int ret;
4998
4999   /* Parse args required to build the message */
5000   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5001     {
5002       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5003         sw_if_index_set = 1;
5004       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5005         sw_if_index_set = 1;
5006       else
5007         break;
5008     }
5009
5010   if (sw_if_index_set == 0)
5011     {
5012       errmsg ("missing vpp interface name. ");
5013       return -99;
5014     }
5015
5016   /* Construct the API message */
5017   M (BOND_DETACH_MEMBER, mp);
5018
5019   mp->sw_if_index = ntohl (sw_if_index);
5020
5021   /* send it... */
5022   S (mp);
5023
5024   /* Wait for a reply... */
5025   W (ret);
5026   return ret;
5027 }
5028
5029 static int
5030 api_ip_table_add_del (vat_main_t * vam)
5031 {
5032   unformat_input_t *i = vam->input;
5033   vl_api_ip_table_add_del_t *mp;
5034   u32 table_id = ~0;
5035   u8 is_ipv6 = 0;
5036   u8 is_add = 1;
5037   int ret = 0;
5038
5039   /* Parse args required to build the message */
5040   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5041     {
5042       if (unformat (i, "ipv6"))
5043         is_ipv6 = 1;
5044       else if (unformat (i, "del"))
5045         is_add = 0;
5046       else if (unformat (i, "add"))
5047         is_add = 1;
5048       else if (unformat (i, "table %d", &table_id))
5049         ;
5050       else
5051         {
5052           clib_warning ("parse error '%U'", format_unformat_error, i);
5053           return -99;
5054         }
5055     }
5056
5057   if (~0 == table_id)
5058     {
5059       errmsg ("missing table-ID");
5060       return -99;
5061     }
5062
5063   /* Construct the API message */
5064   M (IP_TABLE_ADD_DEL, mp);
5065
5066   mp->table.table_id = ntohl (table_id);
5067   mp->table.is_ip6 = is_ipv6;
5068   mp->is_add = is_add;
5069
5070   /* send it... */
5071   S (mp);
5072
5073   /* Wait for a reply... */
5074   W (ret);
5075
5076   return ret;
5077 }
5078
5079 uword
5080 unformat_fib_path (unformat_input_t * input, va_list * args)
5081 {
5082   vat_main_t *vam = va_arg (*args, vat_main_t *);
5083   vl_api_fib_path_t *path = va_arg (*args, vl_api_fib_path_t *);
5084   u32 weight, preference;
5085   mpls_label_t out_label;
5086
5087   clib_memset (path, 0, sizeof (*path));
5088   path->weight = 1;
5089   path->sw_if_index = ~0;
5090   path->rpf_id = ~0;
5091   path->n_labels = 0;
5092
5093   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5094     {
5095       if (unformat (input, "%U %U",
5096                     unformat_vl_api_ip4_address,
5097                     &path->nh.address.ip4,
5098                     api_unformat_sw_if_index, vam, &path->sw_if_index))
5099         {
5100           path->proto = FIB_API_PATH_NH_PROTO_IP4;
5101         }
5102       else if (unformat (input, "%U %U",
5103                          unformat_vl_api_ip6_address,
5104                          &path->nh.address.ip6,
5105                          api_unformat_sw_if_index, vam, &path->sw_if_index))
5106         {
5107           path->proto = FIB_API_PATH_NH_PROTO_IP6;
5108         }
5109       else if (unformat (input, "weight %u", &weight))
5110         {
5111           path->weight = weight;
5112         }
5113       else if (unformat (input, "preference %u", &preference))
5114         {
5115           path->preference = preference;
5116         }
5117       else if (unformat (input, "%U next-hop-table %d",
5118                          unformat_vl_api_ip4_address,
5119                          &path->nh.address.ip4, &path->table_id))
5120         {
5121           path->proto = FIB_API_PATH_NH_PROTO_IP4;
5122         }
5123       else if (unformat (input, "%U next-hop-table %d",
5124                          unformat_vl_api_ip6_address,
5125                          &path->nh.address.ip6, &path->table_id))
5126         {
5127           path->proto = FIB_API_PATH_NH_PROTO_IP6;
5128         }
5129       else if (unformat (input, "%U",
5130                          unformat_vl_api_ip4_address, &path->nh.address.ip4))
5131         {
5132           /*
5133            * the recursive next-hops are by default in the default table
5134            */
5135           path->table_id = 0;
5136           path->sw_if_index = ~0;
5137           path->proto = FIB_API_PATH_NH_PROTO_IP4;
5138         }
5139       else if (unformat (input, "%U",
5140                          unformat_vl_api_ip6_address, &path->nh.address.ip6))
5141         {
5142           /*
5143            * the recursive next-hops are by default in the default table
5144            */
5145           path->table_id = 0;
5146           path->sw_if_index = ~0;
5147           path->proto = FIB_API_PATH_NH_PROTO_IP6;
5148         }
5149       else if (unformat (input, "resolve-via-host"))
5150         {
5151           path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_HOST;
5152         }
5153       else if (unformat (input, "resolve-via-attached"))
5154         {
5155           path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_ATTACHED;
5156         }
5157       else if (unformat (input, "ip4-lookup-in-table %d", &path->table_id))
5158         {
5159           path->type = FIB_API_PATH_TYPE_LOCAL;
5160           path->sw_if_index = ~0;
5161           path->proto = FIB_API_PATH_NH_PROTO_IP4;
5162         }
5163       else if (unformat (input, "ip6-lookup-in-table %d", &path->table_id))
5164         {
5165           path->type = FIB_API_PATH_TYPE_LOCAL;
5166           path->sw_if_index = ~0;
5167           path->proto = FIB_API_PATH_NH_PROTO_IP6;
5168         }
5169       else if (unformat (input, "sw_if_index %d", &path->sw_if_index))
5170         ;
5171       else if (unformat (input, "via-label %d", &path->nh.via_label))
5172         {
5173           path->proto = FIB_API_PATH_NH_PROTO_MPLS;
5174           path->sw_if_index = ~0;
5175         }
5176       else if (unformat (input, "l2-input-on %d", &path->sw_if_index))
5177         {
5178           path->proto = FIB_API_PATH_NH_PROTO_ETHERNET;
5179           path->type = FIB_API_PATH_TYPE_INTERFACE_RX;
5180         }
5181       else if (unformat (input, "local"))
5182         {
5183           path->type = FIB_API_PATH_TYPE_LOCAL;
5184         }
5185       else if (unformat (input, "out-labels"))
5186         {
5187           while (unformat (input, "%d", &out_label))
5188             {
5189               path->label_stack[path->n_labels].label = out_label;
5190               path->label_stack[path->n_labels].is_uniform = 0;
5191               path->label_stack[path->n_labels].ttl = 64;
5192               path->n_labels++;
5193             }
5194         }
5195       else if (unformat (input, "via"))
5196         {
5197           /* new path, back up and return */
5198           unformat_put_input (input);
5199           unformat_put_input (input);
5200           unformat_put_input (input);
5201           unformat_put_input (input);
5202           break;
5203         }
5204       else
5205         {
5206           return (0);
5207         }
5208     }
5209
5210   path->proto = ntohl (path->proto);
5211   path->type = ntohl (path->type);
5212   path->flags = ntohl (path->flags);
5213   path->table_id = ntohl (path->table_id);
5214   path->sw_if_index = ntohl (path->sw_if_index);
5215
5216   return (1);
5217 }
5218
5219 static int
5220 api_ip_route_add_del (vat_main_t * vam)
5221 {
5222   unformat_input_t *i = vam->input;
5223   vl_api_ip_route_add_del_t *mp;
5224   u32 vrf_id = 0;
5225   u8 is_add = 1;
5226   u8 is_multipath = 0;
5227   u8 prefix_set = 0;
5228   u8 path_count = 0;
5229   vl_api_prefix_t pfx = { };
5230   vl_api_fib_path_t paths[8];
5231   int count = 1;
5232   int j;
5233   f64 before = 0;
5234   u32 random_add_del = 0;
5235   u32 *random_vector = 0;
5236   u32 random_seed = 0xdeaddabe;
5237
5238   /* Parse args required to build the message */
5239   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5240     {
5241       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
5242         prefix_set = 1;
5243       else if (unformat (i, "del"))
5244         is_add = 0;
5245       else if (unformat (i, "add"))
5246         is_add = 1;
5247       else if (unformat (i, "vrf %d", &vrf_id))
5248         ;
5249       else if (unformat (i, "count %d", &count))
5250         ;
5251       else if (unformat (i, "random"))
5252         random_add_del = 1;
5253       else if (unformat (i, "multipath"))
5254         is_multipath = 1;
5255       else if (unformat (i, "seed %d", &random_seed))
5256         ;
5257       else
5258         if (unformat
5259             (i, "via %U", unformat_fib_path, vam, &paths[path_count]))
5260         {
5261           path_count++;
5262           if (8 == path_count)
5263             {
5264               errmsg ("max 8 paths");
5265               return -99;
5266             }
5267         }
5268       else
5269         {
5270           clib_warning ("parse error '%U'", format_unformat_error, i);
5271           return -99;
5272         }
5273     }
5274
5275   if (!path_count)
5276     {
5277       errmsg ("specify a path; via ...");
5278       return -99;
5279     }
5280   if (prefix_set == 0)
5281     {
5282       errmsg ("missing prefix");
5283       return -99;
5284     }
5285
5286   /* Generate a pile of unique, random routes */
5287   if (random_add_del)
5288     {
5289       ip4_address_t *i = (ip4_address_t *) & paths[0].nh.address.ip4;
5290       u32 this_random_address;
5291       uword *random_hash;
5292
5293       random_hash = hash_create (count, sizeof (uword));
5294
5295       hash_set (random_hash, i->as_u32, 1);
5296       for (j = 0; j <= count; j++)
5297         {
5298           do
5299             {
5300               this_random_address = random_u32 (&random_seed);
5301               this_random_address =
5302                 clib_host_to_net_u32 (this_random_address);
5303             }
5304           while (hash_get (random_hash, this_random_address));
5305           vec_add1 (random_vector, this_random_address);
5306           hash_set (random_hash, this_random_address, 1);
5307         }
5308       hash_free (random_hash);
5309       set_ip4_address (&pfx.address, random_vector[0]);
5310     }
5311
5312   if (count > 1)
5313     {
5314       /* Turn on async mode */
5315       vam->async_mode = 1;
5316       vam->async_errors = 0;
5317       before = vat_time_now (vam);
5318     }
5319
5320   for (j = 0; j < count; j++)
5321     {
5322       /* Construct the API message */
5323       M2 (IP_ROUTE_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
5324
5325       mp->is_add = is_add;
5326       mp->is_multipath = is_multipath;
5327
5328       clib_memcpy (&mp->route.prefix, &pfx, sizeof (pfx));
5329       mp->route.table_id = ntohl (vrf_id);
5330       mp->route.n_paths = path_count;
5331
5332       clib_memcpy (&mp->route.paths, &paths, sizeof (paths[0]) * path_count);
5333
5334       if (random_add_del)
5335         set_ip4_address (&pfx.address, random_vector[j + 1]);
5336       else
5337         increment_address (&pfx.address);
5338       /* send it... */
5339       S (mp);
5340       /* If we receive SIGTERM, stop now... */
5341       if (vam->do_exit)
5342         break;
5343     }
5344
5345   /* When testing multiple add/del ops, use a control-ping to sync */
5346   if (count > 1)
5347     {
5348       vl_api_control_ping_t *mp_ping;
5349       f64 after;
5350       f64 timeout;
5351
5352       /* Shut off async mode */
5353       vam->async_mode = 0;
5354
5355       MPING (CONTROL_PING, mp_ping);
5356       S (mp_ping);
5357
5358       timeout = vat_time_now (vam) + 1.0;
5359       while (vat_time_now (vam) < timeout)
5360         if (vam->result_ready == 1)
5361           goto out;
5362       vam->retval = -99;
5363
5364     out:
5365       if (vam->retval == -99)
5366         errmsg ("timeout");
5367
5368       if (vam->async_errors > 0)
5369         {
5370           errmsg ("%d asynchronous errors", vam->async_errors);
5371           vam->retval = -98;
5372         }
5373       vam->async_errors = 0;
5374       after = vat_time_now (vam);
5375
5376       /* slim chance, but we might have eaten SIGTERM on the first iteration */
5377       if (j > 0)
5378         count = j;
5379
5380       print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec",
5381              count, after - before, count / (after - before));
5382     }
5383   else
5384     {
5385       int ret;
5386
5387       /* Wait for a reply... */
5388       W (ret);
5389       return ret;
5390     }
5391
5392   /* Return the good/bad news */
5393   return (vam->retval);
5394 }
5395
5396 static int
5397 api_ip_mroute_add_del (vat_main_t * vam)
5398 {
5399   unformat_input_t *i = vam->input;
5400   u8 path_set = 0, prefix_set = 0, is_add = 1;
5401   vl_api_ip_mroute_add_del_t *mp;
5402   mfib_entry_flags_t eflags = 0;
5403   vl_api_mfib_path_t path;
5404   vl_api_mprefix_t pfx = { };
5405   u32 vrf_id = 0;
5406   int ret;
5407
5408   /* Parse args required to build the message */
5409   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5410     {
5411       if (unformat (i, "%U", unformat_vl_api_mprefix, &pfx))
5412         {
5413           prefix_set = 1;
5414           pfx.grp_address_length = htons (pfx.grp_address_length);
5415         }
5416       else if (unformat (i, "del"))
5417         is_add = 0;
5418       else if (unformat (i, "add"))
5419         is_add = 1;
5420       else if (unformat (i, "vrf %d", &vrf_id))
5421         ;
5422       else if (unformat (i, "%U", unformat_mfib_itf_flags, &path.itf_flags))
5423         path.itf_flags = htonl (path.itf_flags);
5424       else if (unformat (i, "%U", unformat_mfib_entry_flags, &eflags))
5425         ;
5426       else if (unformat (i, "via %U", unformat_fib_path, vam, &path.path))
5427         path_set = 1;
5428       else
5429         {
5430           clib_warning ("parse error '%U'", format_unformat_error, i);
5431           return -99;
5432         }
5433     }
5434
5435   if (prefix_set == 0)
5436     {
5437       errmsg ("missing addresses\n");
5438       return -99;
5439     }
5440   if (path_set == 0)
5441     {
5442       errmsg ("missing path\n");
5443       return -99;
5444     }
5445
5446   /* Construct the API message */
5447   M (IP_MROUTE_ADD_DEL, mp);
5448
5449   mp->is_add = is_add;
5450   mp->is_multipath = 1;
5451
5452   clib_memcpy (&mp->route.prefix, &pfx, sizeof (pfx));
5453   mp->route.table_id = htonl (vrf_id);
5454   mp->route.n_paths = 1;
5455   mp->route.entry_flags = htonl (eflags);
5456
5457   clib_memcpy (&mp->route.paths, &path, sizeof (path));
5458
5459   /* send it... */
5460   S (mp);
5461   /* Wait for a reply... */
5462   W (ret);
5463   return ret;
5464 }
5465
5466 static int
5467 api_mpls_table_add_del (vat_main_t * vam)
5468 {
5469   unformat_input_t *i = vam->input;
5470   vl_api_mpls_table_add_del_t *mp;
5471   u32 table_id = ~0;
5472   u8 is_add = 1;
5473   int ret = 0;
5474
5475   /* Parse args required to build the message */
5476   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5477     {
5478       if (unformat (i, "table %d", &table_id))
5479         ;
5480       else if (unformat (i, "del"))
5481         is_add = 0;
5482       else if (unformat (i, "add"))
5483         is_add = 1;
5484       else
5485         {
5486           clib_warning ("parse error '%U'", format_unformat_error, i);
5487           return -99;
5488         }
5489     }
5490
5491   if (~0 == table_id)
5492     {
5493       errmsg ("missing table-ID");
5494       return -99;
5495     }
5496
5497   /* Construct the API message */
5498   M (MPLS_TABLE_ADD_DEL, mp);
5499
5500   mp->mt_table.mt_table_id = ntohl (table_id);
5501   mp->mt_is_add = is_add;
5502
5503   /* send it... */
5504   S (mp);
5505
5506   /* Wait for a reply... */
5507   W (ret);
5508
5509   return ret;
5510 }
5511
5512 static int
5513 api_mpls_route_add_del (vat_main_t * vam)
5514 {
5515   u8 is_add = 1, path_count = 0, is_multipath = 0, is_eos = 0;
5516   mpls_label_t local_label = MPLS_LABEL_INVALID;
5517   unformat_input_t *i = vam->input;
5518   vl_api_mpls_route_add_del_t *mp;
5519   vl_api_fib_path_t paths[8];
5520   int count = 1, j;
5521   f64 before = 0;
5522
5523   /* Parse args required to build the message */
5524   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5525     {
5526       if (unformat (i, "%d", &local_label))
5527         ;
5528       else if (unformat (i, "eos"))
5529         is_eos = 1;
5530       else if (unformat (i, "non-eos"))
5531         is_eos = 0;
5532       else if (unformat (i, "del"))
5533         is_add = 0;
5534       else if (unformat (i, "add"))
5535         is_add = 1;
5536       else if (unformat (i, "multipath"))
5537         is_multipath = 1;
5538       else if (unformat (i, "count %d", &count))
5539         ;
5540       else
5541         if (unformat
5542             (i, "via %U", unformat_fib_path, vam, &paths[path_count]))
5543         {
5544           path_count++;
5545           if (8 == path_count)
5546             {
5547               errmsg ("max 8 paths");
5548               return -99;
5549             }
5550         }
5551       else
5552         {
5553           clib_warning ("parse error '%U'", format_unformat_error, i);
5554           return -99;
5555         }
5556     }
5557
5558   if (!path_count)
5559     {
5560       errmsg ("specify a path; via ...");
5561       return -99;
5562     }
5563
5564   if (MPLS_LABEL_INVALID == local_label)
5565     {
5566       errmsg ("missing label");
5567       return -99;
5568     }
5569
5570   if (count > 1)
5571     {
5572       /* Turn on async mode */
5573       vam->async_mode = 1;
5574       vam->async_errors = 0;
5575       before = vat_time_now (vam);
5576     }
5577
5578   for (j = 0; j < count; j++)
5579     {
5580       /* Construct the API message */
5581       M2 (MPLS_ROUTE_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
5582
5583       mp->mr_is_add = is_add;
5584       mp->mr_is_multipath = is_multipath;
5585
5586       mp->mr_route.mr_label = local_label;
5587       mp->mr_route.mr_eos = is_eos;
5588       mp->mr_route.mr_table_id = 0;
5589       mp->mr_route.mr_n_paths = path_count;
5590
5591       clib_memcpy (&mp->mr_route.mr_paths, paths,
5592                    sizeof (paths[0]) * path_count);
5593
5594       local_label++;
5595
5596       /* send it... */
5597       S (mp);
5598       /* If we receive SIGTERM, stop now... */
5599       if (vam->do_exit)
5600         break;
5601     }
5602
5603   /* When testing multiple add/del ops, use a control-ping to sync */
5604   if (count > 1)
5605     {
5606       vl_api_control_ping_t *mp_ping;
5607       f64 after;
5608       f64 timeout;
5609
5610       /* Shut off async mode */
5611       vam->async_mode = 0;
5612
5613       MPING (CONTROL_PING, mp_ping);
5614       S (mp_ping);
5615
5616       timeout = vat_time_now (vam) + 1.0;
5617       while (vat_time_now (vam) < timeout)
5618         if (vam->result_ready == 1)
5619           goto out;
5620       vam->retval = -99;
5621
5622     out:
5623       if (vam->retval == -99)
5624         errmsg ("timeout");
5625
5626       if (vam->async_errors > 0)
5627         {
5628           errmsg ("%d asynchronous errors", vam->async_errors);
5629           vam->retval = -98;
5630         }
5631       vam->async_errors = 0;
5632       after = vat_time_now (vam);
5633
5634       /* slim chance, but we might have eaten SIGTERM on the first iteration */
5635       if (j > 0)
5636         count = j;
5637
5638       print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec",
5639              count, after - before, count / (after - before));
5640     }
5641   else
5642     {
5643       int ret;
5644
5645       /* Wait for a reply... */
5646       W (ret);
5647       return ret;
5648     }
5649
5650   /* Return the good/bad news */
5651   return (vam->retval);
5652   return (0);
5653 }
5654
5655 static int
5656 api_mpls_ip_bind_unbind (vat_main_t * vam)
5657 {
5658   unformat_input_t *i = vam->input;
5659   vl_api_mpls_ip_bind_unbind_t *mp;
5660   u32 ip_table_id = 0;
5661   u8 is_bind = 1;
5662   vl_api_prefix_t pfx;
5663   u8 prefix_set = 0;
5664   mpls_label_t local_label = MPLS_LABEL_INVALID;
5665   int ret;
5666
5667   /* Parse args required to build the message */
5668   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5669     {
5670       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
5671         prefix_set = 1;
5672       else if (unformat (i, "%d", &local_label))
5673         ;
5674       else if (unformat (i, "table-id %d", &ip_table_id))
5675         ;
5676       else if (unformat (i, "unbind"))
5677         is_bind = 0;
5678       else if (unformat (i, "bind"))
5679         is_bind = 1;
5680       else
5681         {
5682           clib_warning ("parse error '%U'", format_unformat_error, i);
5683           return -99;
5684         }
5685     }
5686
5687   if (!prefix_set)
5688     {
5689       errmsg ("IP prefix not set");
5690       return -99;
5691     }
5692
5693   if (MPLS_LABEL_INVALID == local_label)
5694     {
5695       errmsg ("missing label");
5696       return -99;
5697     }
5698
5699   /* Construct the API message */
5700   M (MPLS_IP_BIND_UNBIND, mp);
5701
5702   mp->mb_is_bind = is_bind;
5703   mp->mb_ip_table_id = ntohl (ip_table_id);
5704   mp->mb_mpls_table_id = 0;
5705   mp->mb_label = ntohl (local_label);
5706   clib_memcpy (&mp->mb_prefix, &pfx, sizeof (pfx));
5707
5708   /* send it... */
5709   S (mp);
5710
5711   /* Wait for a reply... */
5712   W (ret);
5713   return ret;
5714   return (0);
5715 }
5716
5717 static int
5718 api_sr_mpls_policy_add (vat_main_t * vam)
5719 {
5720   unformat_input_t *i = vam->input;
5721   vl_api_sr_mpls_policy_add_t *mp;
5722   u32 bsid = 0;
5723   u32 weight = 1;
5724   u8 type = 0;
5725   u8 n_segments = 0;
5726   u32 sid;
5727   u32 *segments = NULL;
5728   int ret;
5729
5730   /* Parse args required to build the message */
5731   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5732     {
5733       if (unformat (i, "bsid %d", &bsid))
5734         ;
5735       else if (unformat (i, "weight %d", &weight))
5736         ;
5737       else if (unformat (i, "spray"))
5738         type = 1;
5739       else if (unformat (i, "next %d", &sid))
5740         {
5741           n_segments += 1;
5742           vec_add1 (segments, htonl (sid));
5743         }
5744       else
5745         {
5746           clib_warning ("parse error '%U'", format_unformat_error, i);
5747           return -99;
5748         }
5749     }
5750
5751   if (bsid == 0)
5752     {
5753       errmsg ("bsid not set");
5754       return -99;
5755     }
5756
5757   if (n_segments == 0)
5758     {
5759       errmsg ("no sid in segment stack");
5760       return -99;
5761     }
5762
5763   /* Construct the API message */
5764   M2 (SR_MPLS_POLICY_ADD, mp, sizeof (u32) * n_segments);
5765
5766   mp->bsid = htonl (bsid);
5767   mp->weight = htonl (weight);
5768   mp->is_spray = type;
5769   mp->n_segments = n_segments;
5770   memcpy (mp->segments, segments, sizeof (u32) * n_segments);
5771   vec_free (segments);
5772
5773   /* send it... */
5774   S (mp);
5775
5776   /* Wait for a reply... */
5777   W (ret);
5778   return ret;
5779 }
5780
5781 static int
5782 api_sr_mpls_policy_del (vat_main_t * vam)
5783 {
5784   unformat_input_t *i = vam->input;
5785   vl_api_sr_mpls_policy_del_t *mp;
5786   u32 bsid = 0;
5787   int ret;
5788
5789   /* Parse args required to build the message */
5790   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5791     {
5792       if (unformat (i, "bsid %d", &bsid))
5793         ;
5794       else
5795         {
5796           clib_warning ("parse error '%U'", format_unformat_error, i);
5797           return -99;
5798         }
5799     }
5800
5801   if (bsid == 0)
5802     {
5803       errmsg ("bsid not set");
5804       return -99;
5805     }
5806
5807   /* Construct the API message */
5808   M (SR_MPLS_POLICY_DEL, mp);
5809
5810   mp->bsid = htonl (bsid);
5811
5812   /* send it... */
5813   S (mp);
5814
5815   /* Wait for a reply... */
5816   W (ret);
5817   return ret;
5818 }
5819
5820 static int
5821 api_mpls_tunnel_add_del (vat_main_t * vam)
5822 {
5823   unformat_input_t *i = vam->input;
5824   vl_api_mpls_tunnel_add_del_t *mp;
5825
5826   vl_api_fib_path_t paths[8];
5827   u32 sw_if_index = ~0;
5828   u8 path_count = 0;
5829   u8 l2_only = 0;
5830   u8 is_add = 1;
5831   int ret;
5832
5833   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5834     {
5835       if (unformat (i, "add"))
5836         is_add = 1;
5837       else
5838         if (unformat
5839             (i, "del %U", api_unformat_sw_if_index, vam, &sw_if_index))
5840         is_add = 0;
5841       else if (unformat (i, "del sw_if_index %d", &sw_if_index))
5842         is_add = 0;
5843       else if (unformat (i, "l2-only"))
5844         l2_only = 1;
5845       else
5846         if (unformat
5847             (i, "via %U", unformat_fib_path, vam, &paths[path_count]))
5848         {
5849           path_count++;
5850           if (8 == path_count)
5851             {
5852               errmsg ("max 8 paths");
5853               return -99;
5854             }
5855         }
5856       else
5857         {
5858           clib_warning ("parse error '%U'", format_unformat_error, i);
5859           return -99;
5860         }
5861     }
5862
5863   M2 (MPLS_TUNNEL_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
5864
5865   mp->mt_is_add = is_add;
5866   mp->mt_tunnel.mt_sw_if_index = ntohl (sw_if_index);
5867   mp->mt_tunnel.mt_l2_only = l2_only;
5868   mp->mt_tunnel.mt_is_multicast = 0;
5869   mp->mt_tunnel.mt_n_paths = path_count;
5870
5871   clib_memcpy (&mp->mt_tunnel.mt_paths, &paths,
5872                sizeof (paths[0]) * path_count);
5873
5874   S (mp);
5875   W (ret);
5876   return ret;
5877 }
5878
5879 static int
5880 api_sw_interface_set_unnumbered (vat_main_t * vam)
5881 {
5882   unformat_input_t *i = vam->input;
5883   vl_api_sw_interface_set_unnumbered_t *mp;
5884   u32 sw_if_index;
5885   u32 unnum_sw_index = ~0;
5886   u8 is_add = 1;
5887   u8 sw_if_index_set = 0;
5888   int ret;
5889
5890   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5891     {
5892       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5893         sw_if_index_set = 1;
5894       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5895         sw_if_index_set = 1;
5896       else if (unformat (i, "unnum_if_index %d", &unnum_sw_index))
5897         ;
5898       else if (unformat (i, "del"))
5899         is_add = 0;
5900       else
5901         {
5902           clib_warning ("parse error '%U'", format_unformat_error, i);
5903           return -99;
5904         }
5905     }
5906
5907   if (sw_if_index_set == 0)
5908     {
5909       errmsg ("missing interface name or sw_if_index");
5910       return -99;
5911     }
5912
5913   M (SW_INTERFACE_SET_UNNUMBERED, mp);
5914
5915   mp->sw_if_index = ntohl (sw_if_index);
5916   mp->unnumbered_sw_if_index = ntohl (unnum_sw_index);
5917   mp->is_add = is_add;
5918
5919   S (mp);
5920   W (ret);
5921   return ret;
5922 }
5923
5924
5925 static int
5926 api_create_vlan_subif (vat_main_t * vam)
5927 {
5928   unformat_input_t *i = vam->input;
5929   vl_api_create_vlan_subif_t *mp;
5930   u32 sw_if_index;
5931   u8 sw_if_index_set = 0;
5932   u32 vlan_id;
5933   u8 vlan_id_set = 0;
5934   int ret;
5935
5936   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5937     {
5938       if (unformat (i, "sw_if_index %d", &sw_if_index))
5939         sw_if_index_set = 1;
5940       else
5941         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5942         sw_if_index_set = 1;
5943       else if (unformat (i, "vlan %d", &vlan_id))
5944         vlan_id_set = 1;
5945       else
5946         {
5947           clib_warning ("parse error '%U'", format_unformat_error, i);
5948           return -99;
5949         }
5950     }
5951
5952   if (sw_if_index_set == 0)
5953     {
5954       errmsg ("missing interface name or sw_if_index");
5955       return -99;
5956     }
5957
5958   if (vlan_id_set == 0)
5959     {
5960       errmsg ("missing vlan_id");
5961       return -99;
5962     }
5963   M (CREATE_VLAN_SUBIF, mp);
5964
5965   mp->sw_if_index = ntohl (sw_if_index);
5966   mp->vlan_id = ntohl (vlan_id);
5967
5968   S (mp);
5969   W (ret);
5970   return ret;
5971 }
5972
5973 #define foreach_create_subif_bit                \
5974 _(no_tags)                                      \
5975 _(one_tag)                                      \
5976 _(two_tags)                                     \
5977 _(dot1ad)                                       \
5978 _(exact_match)                                  \
5979 _(default_sub)                                  \
5980 _(outer_vlan_id_any)                            \
5981 _(inner_vlan_id_any)
5982
5983 #define foreach_create_subif_flag               \
5984 _(0, "no_tags")                                 \
5985 _(1, "one_tag")                                 \
5986 _(2, "two_tags")                                \
5987 _(3, "dot1ad")                                  \
5988 _(4, "exact_match")                             \
5989 _(5, "default_sub")                             \
5990 _(6, "outer_vlan_id_any")                       \
5991 _(7, "inner_vlan_id_any")
5992
5993 static int
5994 api_create_subif (vat_main_t * vam)
5995 {
5996   unformat_input_t *i = vam->input;
5997   vl_api_create_subif_t *mp;
5998   u32 sw_if_index;
5999   u8 sw_if_index_set = 0;
6000   u32 sub_id;
6001   u8 sub_id_set = 0;
6002   u32 __attribute__ ((unused)) no_tags = 0;
6003   u32 __attribute__ ((unused)) one_tag = 0;
6004   u32 __attribute__ ((unused)) two_tags = 0;
6005   u32 __attribute__ ((unused)) dot1ad = 0;
6006   u32 __attribute__ ((unused)) exact_match = 0;
6007   u32 __attribute__ ((unused)) default_sub = 0;
6008   u32 __attribute__ ((unused)) outer_vlan_id_any = 0;
6009   u32 __attribute__ ((unused)) inner_vlan_id_any = 0;
6010   u32 tmp;
6011   u16 outer_vlan_id = 0;
6012   u16 inner_vlan_id = 0;
6013   int ret;
6014
6015   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6016     {
6017       if (unformat (i, "sw_if_index %d", &sw_if_index))
6018         sw_if_index_set = 1;
6019       else
6020         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
6021         sw_if_index_set = 1;
6022       else if (unformat (i, "sub_id %d", &sub_id))
6023         sub_id_set = 1;
6024       else if (unformat (i, "outer_vlan_id %d", &tmp))
6025         outer_vlan_id = tmp;
6026       else if (unformat (i, "inner_vlan_id %d", &tmp))
6027         inner_vlan_id = tmp;
6028
6029 #define _(a) else if (unformat (i, #a)) a = 1 ;
6030       foreach_create_subif_bit
6031 #undef _
6032         else
6033         {
6034           clib_warning ("parse error '%U'", format_unformat_error, i);
6035           return -99;
6036         }
6037     }
6038
6039   if (sw_if_index_set == 0)
6040     {
6041       errmsg ("missing interface name or sw_if_index");
6042       return -99;
6043     }
6044
6045   if (sub_id_set == 0)
6046     {
6047       errmsg ("missing sub_id");
6048       return -99;
6049     }
6050   M (CREATE_SUBIF, mp);
6051
6052   mp->sw_if_index = ntohl (sw_if_index);
6053   mp->sub_id = ntohl (sub_id);
6054
6055 #define _(a,b) mp->sub_if_flags |= (1 << a);
6056   foreach_create_subif_flag;
6057 #undef _
6058
6059   mp->outer_vlan_id = ntohs (outer_vlan_id);
6060   mp->inner_vlan_id = ntohs (inner_vlan_id);
6061
6062   S (mp);
6063   W (ret);
6064   return ret;
6065 }
6066
6067 static int
6068 api_ip_table_replace_begin (vat_main_t * vam)
6069 {
6070   unformat_input_t *i = vam->input;
6071   vl_api_ip_table_replace_begin_t *mp;
6072   u32 table_id = 0;
6073   u8 is_ipv6 = 0;
6074
6075   int ret;
6076   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6077     {
6078       if (unformat (i, "table %d", &table_id))
6079         ;
6080       else if (unformat (i, "ipv6"))
6081         is_ipv6 = 1;
6082       else
6083         {
6084           clib_warning ("parse error '%U'", format_unformat_error, i);
6085           return -99;
6086         }
6087     }
6088
6089   M (IP_TABLE_REPLACE_BEGIN, mp);
6090
6091   mp->table.table_id = ntohl (table_id);
6092   mp->table.is_ip6 = is_ipv6;
6093
6094   S (mp);
6095   W (ret);
6096   return ret;
6097 }
6098
6099 static int
6100 api_ip_table_flush (vat_main_t * vam)
6101 {
6102   unformat_input_t *i = vam->input;
6103   vl_api_ip_table_flush_t *mp;
6104   u32 table_id = 0;
6105   u8 is_ipv6 = 0;
6106
6107   int ret;
6108   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6109     {
6110       if (unformat (i, "table %d", &table_id))
6111         ;
6112       else if (unformat (i, "ipv6"))
6113         is_ipv6 = 1;
6114       else
6115         {
6116           clib_warning ("parse error '%U'", format_unformat_error, i);
6117           return -99;
6118         }
6119     }
6120
6121   M (IP_TABLE_FLUSH, mp);
6122
6123   mp->table.table_id = ntohl (table_id);
6124   mp->table.is_ip6 = is_ipv6;
6125
6126   S (mp);
6127   W (ret);
6128   return ret;
6129 }
6130
6131 static int
6132 api_ip_table_replace_end (vat_main_t * vam)
6133 {
6134   unformat_input_t *i = vam->input;
6135   vl_api_ip_table_replace_end_t *mp;
6136   u32 table_id = 0;
6137   u8 is_ipv6 = 0;
6138
6139   int ret;
6140   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6141     {
6142       if (unformat (i, "table %d", &table_id))
6143         ;
6144       else if (unformat (i, "ipv6"))
6145         is_ipv6 = 1;
6146       else
6147         {
6148           clib_warning ("parse error '%U'", format_unformat_error, i);
6149           return -99;
6150         }
6151     }
6152
6153   M (IP_TABLE_REPLACE_END, mp);
6154
6155   mp->table.table_id = ntohl (table_id);
6156   mp->table.is_ip6 = is_ipv6;
6157
6158   S (mp);
6159   W (ret);
6160   return ret;
6161 }
6162
6163 static int
6164 api_set_ip_flow_hash (vat_main_t * vam)
6165 {
6166   unformat_input_t *i = vam->input;
6167   vl_api_set_ip_flow_hash_t *mp;
6168   u32 vrf_id = 0;
6169   u8 is_ipv6 = 0;
6170   u8 vrf_id_set = 0;
6171   u8 src = 0;
6172   u8 dst = 0;
6173   u8 sport = 0;
6174   u8 dport = 0;
6175   u8 proto = 0;
6176   u8 reverse = 0;
6177   int ret;
6178
6179   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6180     {
6181       if (unformat (i, "vrf %d", &vrf_id))
6182         vrf_id_set = 1;
6183       else if (unformat (i, "ipv6"))
6184         is_ipv6 = 1;
6185       else if (unformat (i, "src"))
6186         src = 1;
6187       else if (unformat (i, "dst"))
6188         dst = 1;
6189       else if (unformat (i, "sport"))
6190         sport = 1;
6191       else if (unformat (i, "dport"))
6192         dport = 1;
6193       else if (unformat (i, "proto"))
6194         proto = 1;
6195       else if (unformat (i, "reverse"))
6196         reverse = 1;
6197
6198       else
6199         {
6200           clib_warning ("parse error '%U'", format_unformat_error, i);
6201           return -99;
6202         }
6203     }
6204
6205   if (vrf_id_set == 0)
6206     {
6207       errmsg ("missing vrf id");
6208       return -99;
6209     }
6210
6211   M (SET_IP_FLOW_HASH, mp);
6212   mp->src = src;
6213   mp->dst = dst;
6214   mp->sport = sport;
6215   mp->dport = dport;
6216   mp->proto = proto;
6217   mp->reverse = reverse;
6218   mp->vrf_id = ntohl (vrf_id);
6219   mp->is_ipv6 = is_ipv6;
6220
6221   S (mp);
6222   W (ret);
6223   return ret;
6224 }
6225
6226 static int
6227 api_sw_interface_ip6_enable_disable (vat_main_t * vam)
6228 {
6229   unformat_input_t *i = vam->input;
6230   vl_api_sw_interface_ip6_enable_disable_t *mp;
6231   u32 sw_if_index;
6232   u8 sw_if_index_set = 0;
6233   u8 enable = 0;
6234   int ret;
6235
6236   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6237     {
6238       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
6239         sw_if_index_set = 1;
6240       else if (unformat (i, "sw_if_index %d", &sw_if_index))
6241         sw_if_index_set = 1;
6242       else if (unformat (i, "enable"))
6243         enable = 1;
6244       else if (unformat (i, "disable"))
6245         enable = 0;
6246       else
6247         {
6248           clib_warning ("parse error '%U'", format_unformat_error, i);
6249           return -99;
6250         }
6251     }
6252
6253   if (sw_if_index_set == 0)
6254     {
6255       errmsg ("missing interface name or sw_if_index");
6256       return -99;
6257     }
6258
6259   M (SW_INTERFACE_IP6_ENABLE_DISABLE, mp);
6260
6261   mp->sw_if_index = ntohl (sw_if_index);
6262   mp->enable = enable;
6263
6264   S (mp);
6265   W (ret);
6266   return ret;
6267 }
6268
6269
6270 static int
6271 api_l2_patch_add_del (vat_main_t * vam)
6272 {
6273   unformat_input_t *i = vam->input;
6274   vl_api_l2_patch_add_del_t *mp;
6275   u32 rx_sw_if_index;
6276   u8 rx_sw_if_index_set = 0;
6277   u32 tx_sw_if_index;
6278   u8 tx_sw_if_index_set = 0;
6279   u8 is_add = 1;
6280   int ret;
6281
6282   /* Parse args required to build the message */
6283   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6284     {
6285       if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index))
6286         rx_sw_if_index_set = 1;
6287       else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
6288         tx_sw_if_index_set = 1;
6289       else if (unformat (i, "rx"))
6290         {
6291           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6292             {
6293               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
6294                             &rx_sw_if_index))
6295                 rx_sw_if_index_set = 1;
6296             }
6297           else
6298             break;
6299         }
6300       else if (unformat (i, "tx"))
6301         {
6302           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6303             {
6304               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
6305                             &tx_sw_if_index))
6306                 tx_sw_if_index_set = 1;
6307             }
6308           else
6309             break;
6310         }
6311       else if (unformat (i, "del"))
6312         is_add = 0;
6313       else
6314         break;
6315     }
6316
6317   if (rx_sw_if_index_set == 0)
6318     {
6319       errmsg ("missing rx interface name or rx_sw_if_index");
6320       return -99;
6321     }
6322
6323   if (tx_sw_if_index_set == 0)
6324     {
6325       errmsg ("missing tx interface name or tx_sw_if_index");
6326       return -99;
6327     }
6328
6329   M (L2_PATCH_ADD_DEL, mp);
6330
6331   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
6332   mp->tx_sw_if_index = ntohl (tx_sw_if_index);
6333   mp->is_add = is_add;
6334
6335   S (mp);
6336   W (ret);
6337   return ret;
6338 }
6339
6340 u8 is_del;
6341 u8 localsid_addr[16];
6342 u8 end_psp;
6343 u8 behavior;
6344 u32 sw_if_index;
6345 u32 vlan_index;
6346 u32 fib_table;
6347 u8 nh_addr[16];
6348
6349 static int
6350 api_sr_localsid_add_del (vat_main_t * vam)
6351 {
6352   unformat_input_t *i = vam->input;
6353   vl_api_sr_localsid_add_del_t *mp;
6354
6355   u8 is_del;
6356   ip6_address_t localsid;
6357   u8 end_psp = 0;
6358   u8 behavior = ~0;
6359   u32 sw_if_index;
6360   u32 fib_table = ~(u32) 0;
6361   ip46_address_t nh_addr;
6362   clib_memset (&nh_addr, 0, sizeof (ip46_address_t));
6363
6364   bool nexthop_set = 0;
6365
6366   int ret;
6367
6368   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6369     {
6370       if (unformat (i, "del"))
6371         is_del = 1;
6372       else if (unformat (i, "address %U", unformat_ip6_address, &localsid));
6373       else if (unformat (i, "next-hop %U", unformat_ip46_address, &nh_addr))
6374         nexthop_set = 1;
6375       else if (unformat (i, "behavior %u", &behavior));
6376       else if (unformat (i, "sw_if_index %u", &sw_if_index));
6377       else if (unformat (i, "fib-table %u", &fib_table));
6378       else if (unformat (i, "end.psp %u", &behavior));
6379       else
6380         break;
6381     }
6382
6383   M (SR_LOCALSID_ADD_DEL, mp);
6384
6385   clib_memcpy (mp->localsid, &localsid, sizeof (mp->localsid));
6386
6387   if (nexthop_set)
6388     {
6389       clib_memcpy (&mp->nh_addr.un, &nh_addr, sizeof (mp->nh_addr.un));
6390     }
6391   mp->behavior = behavior;
6392   mp->sw_if_index = ntohl (sw_if_index);
6393   mp->fib_table = ntohl (fib_table);
6394   mp->end_psp = end_psp;
6395   mp->is_del = is_del;
6396
6397   S (mp);
6398   W (ret);
6399   return ret;
6400 }
6401
6402 static int
6403 api_ioam_enable (vat_main_t * vam)
6404 {
6405   unformat_input_t *input = vam->input;
6406   vl_api_ioam_enable_t *mp;
6407   u32 id = 0;
6408   int has_trace_option = 0;
6409   int has_pot_option = 0;
6410   int has_seqno_option = 0;
6411   int has_analyse_option = 0;
6412   int ret;
6413
6414   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6415     {
6416       if (unformat (input, "trace"))
6417         has_trace_option = 1;
6418       else if (unformat (input, "pot"))
6419         has_pot_option = 1;
6420       else if (unformat (input, "seqno"))
6421         has_seqno_option = 1;
6422       else if (unformat (input, "analyse"))
6423         has_analyse_option = 1;
6424       else
6425         break;
6426     }
6427   M (IOAM_ENABLE, mp);
6428   mp->id = htons (id);
6429   mp->seqno = has_seqno_option;
6430   mp->analyse = has_analyse_option;
6431   mp->pot_enable = has_pot_option;
6432   mp->trace_enable = has_trace_option;
6433
6434   S (mp);
6435   W (ret);
6436   return ret;
6437 }
6438
6439
6440 static int
6441 api_ioam_disable (vat_main_t * vam)
6442 {
6443   vl_api_ioam_disable_t *mp;
6444   int ret;
6445
6446   M (IOAM_DISABLE, mp);
6447   S (mp);
6448   W (ret);
6449   return ret;
6450 }
6451
6452 #define foreach_tcp_proto_field                 \
6453 _(src_port)                                     \
6454 _(dst_port)
6455
6456 #define foreach_udp_proto_field                 \
6457 _(src_port)                                     \
6458 _(dst_port)
6459
6460 #define foreach_ip4_proto_field                 \
6461 _(src_address)                                  \
6462 _(dst_address)                                  \
6463 _(tos)                                          \
6464 _(length)                                       \
6465 _(fragment_id)                                  \
6466 _(ttl)                                          \
6467 _(protocol)                                     \
6468 _(checksum)
6469
6470 typedef struct
6471 {
6472   u16 src_port, dst_port;
6473 } tcpudp_header_t;
6474
6475 #if VPP_API_TEST_BUILTIN == 0
6476 uword
6477 unformat_tcp_mask (unformat_input_t * input, va_list * args)
6478 {
6479   u8 **maskp = va_arg (*args, u8 **);
6480   u8 *mask = 0;
6481   u8 found_something = 0;
6482   tcp_header_t *tcp;
6483
6484 #define _(a) u8 a=0;
6485   foreach_tcp_proto_field;
6486 #undef _
6487
6488   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6489     {
6490       if (0);
6491 #define _(a) else if (unformat (input, #a)) a=1;
6492       foreach_tcp_proto_field
6493 #undef _
6494         else
6495         break;
6496     }
6497
6498 #define _(a) found_something += a;
6499   foreach_tcp_proto_field;
6500 #undef _
6501
6502   if (found_something == 0)
6503     return 0;
6504
6505   vec_validate (mask, sizeof (*tcp) - 1);
6506
6507   tcp = (tcp_header_t *) mask;
6508
6509 #define _(a) if (a) clib_memset (&tcp->a, 0xff, sizeof (tcp->a));
6510   foreach_tcp_proto_field;
6511 #undef _
6512
6513   *maskp = mask;
6514   return 1;
6515 }
6516
6517 uword
6518 unformat_udp_mask (unformat_input_t * input, va_list * args)
6519 {
6520   u8 **maskp = va_arg (*args, u8 **);
6521   u8 *mask = 0;
6522   u8 found_something = 0;
6523   udp_header_t *udp;
6524
6525 #define _(a) u8 a=0;
6526   foreach_udp_proto_field;
6527 #undef _
6528
6529   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6530     {
6531       if (0);
6532 #define _(a) else if (unformat (input, #a)) a=1;
6533       foreach_udp_proto_field
6534 #undef _
6535         else
6536         break;
6537     }
6538
6539 #define _(a) found_something += a;
6540   foreach_udp_proto_field;
6541 #undef _
6542
6543   if (found_something == 0)
6544     return 0;
6545
6546   vec_validate (mask, sizeof (*udp) - 1);
6547
6548   udp = (udp_header_t *) mask;
6549
6550 #define _(a) if (a) clib_memset (&udp->a, 0xff, sizeof (udp->a));
6551   foreach_udp_proto_field;
6552 #undef _
6553
6554   *maskp = mask;
6555   return 1;
6556 }
6557
6558 uword
6559 unformat_l4_mask (unformat_input_t * input, va_list * args)
6560 {
6561   u8 **maskp = va_arg (*args, u8 **);
6562   u16 src_port = 0, dst_port = 0;
6563   tcpudp_header_t *tcpudp;
6564
6565   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6566     {
6567       if (unformat (input, "tcp %U", unformat_tcp_mask, maskp))
6568         return 1;
6569       else if (unformat (input, "udp %U", unformat_udp_mask, maskp))
6570         return 1;
6571       else if (unformat (input, "src_port"))
6572         src_port = 0xFFFF;
6573       else if (unformat (input, "dst_port"))
6574         dst_port = 0xFFFF;
6575       else
6576         return 0;
6577     }
6578
6579   if (!src_port && !dst_port)
6580     return 0;
6581
6582   u8 *mask = 0;
6583   vec_validate (mask, sizeof (tcpudp_header_t) - 1);
6584
6585   tcpudp = (tcpudp_header_t *) mask;
6586   tcpudp->src_port = src_port;
6587   tcpudp->dst_port = dst_port;
6588
6589   *maskp = mask;
6590
6591   return 1;
6592 }
6593
6594 uword
6595 unformat_ip4_mask (unformat_input_t * input, va_list * args)
6596 {
6597   u8 **maskp = va_arg (*args, u8 **);
6598   u8 *mask = 0;
6599   u8 found_something = 0;
6600   ip4_header_t *ip;
6601
6602 #define _(a) u8 a=0;
6603   foreach_ip4_proto_field;
6604 #undef _
6605   u8 version = 0;
6606   u8 hdr_length = 0;
6607
6608
6609   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6610     {
6611       if (unformat (input, "version"))
6612         version = 1;
6613       else if (unformat (input, "hdr_length"))
6614         hdr_length = 1;
6615       else if (unformat (input, "src"))
6616         src_address = 1;
6617       else if (unformat (input, "dst"))
6618         dst_address = 1;
6619       else if (unformat (input, "proto"))
6620         protocol = 1;
6621
6622 #define _(a) else if (unformat (input, #a)) a=1;
6623       foreach_ip4_proto_field
6624 #undef _
6625         else
6626         break;
6627     }
6628
6629 #define _(a) found_something += a;
6630   foreach_ip4_proto_field;
6631 #undef _
6632
6633   if (found_something == 0)
6634     return 0;
6635
6636   vec_validate (mask, sizeof (*ip) - 1);
6637
6638   ip = (ip4_header_t *) mask;
6639
6640 #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
6641   foreach_ip4_proto_field;
6642 #undef _
6643
6644   ip->ip_version_and_header_length = 0;
6645
6646   if (version)
6647     ip->ip_version_and_header_length |= 0xF0;
6648
6649   if (hdr_length)
6650     ip->ip_version_and_header_length |= 0x0F;
6651
6652   *maskp = mask;
6653   return 1;
6654 }
6655
6656 #define foreach_ip6_proto_field                 \
6657 _(src_address)                                  \
6658 _(dst_address)                                  \
6659 _(payload_length)                               \
6660 _(hop_limit)                                    \
6661 _(protocol)
6662
6663 uword
6664 unformat_ip6_mask (unformat_input_t * input, va_list * args)
6665 {
6666   u8 **maskp = va_arg (*args, u8 **);
6667   u8 *mask = 0;
6668   u8 found_something = 0;
6669   ip6_header_t *ip;
6670   u32 ip_version_traffic_class_and_flow_label;
6671
6672 #define _(a) u8 a=0;
6673   foreach_ip6_proto_field;
6674 #undef _
6675   u8 version = 0;
6676   u8 traffic_class = 0;
6677   u8 flow_label = 0;
6678
6679   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6680     {
6681       if (unformat (input, "version"))
6682         version = 1;
6683       else if (unformat (input, "traffic-class"))
6684         traffic_class = 1;
6685       else if (unformat (input, "flow-label"))
6686         flow_label = 1;
6687       else if (unformat (input, "src"))
6688         src_address = 1;
6689       else if (unformat (input, "dst"))
6690         dst_address = 1;
6691       else if (unformat (input, "proto"))
6692         protocol = 1;
6693
6694 #define _(a) else if (unformat (input, #a)) a=1;
6695       foreach_ip6_proto_field
6696 #undef _
6697         else
6698         break;
6699     }
6700
6701 #define _(a) found_something += a;
6702   foreach_ip6_proto_field;
6703 #undef _
6704
6705   if (found_something == 0)
6706     return 0;
6707
6708   vec_validate (mask, sizeof (*ip) - 1);
6709
6710   ip = (ip6_header_t *) mask;
6711
6712 #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
6713   foreach_ip6_proto_field;
6714 #undef _
6715
6716   ip_version_traffic_class_and_flow_label = 0;
6717
6718   if (version)
6719     ip_version_traffic_class_and_flow_label |= 0xF0000000;
6720
6721   if (traffic_class)
6722     ip_version_traffic_class_and_flow_label |= 0x0FF00000;
6723
6724   if (flow_label)
6725     ip_version_traffic_class_and_flow_label |= 0x000FFFFF;
6726
6727   ip->ip_version_traffic_class_and_flow_label =
6728     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
6729
6730   *maskp = mask;
6731   return 1;
6732 }
6733
6734 uword
6735 unformat_l3_mask (unformat_input_t * input, va_list * args)
6736 {
6737   u8 **maskp = va_arg (*args, u8 **);
6738
6739   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6740     {
6741       if (unformat (input, "ip4 %U", unformat_ip4_mask, maskp))
6742         return 1;
6743       else if (unformat (input, "ip6 %U", unformat_ip6_mask, maskp))
6744         return 1;
6745       else
6746         break;
6747     }
6748   return 0;
6749 }
6750
6751 uword
6752 unformat_l2_mask (unformat_input_t * input, va_list * args)
6753 {
6754   u8 **maskp = va_arg (*args, u8 **);
6755   u8 *mask = 0;
6756   u8 src = 0;
6757   u8 dst = 0;
6758   u8 proto = 0;
6759   u8 tag1 = 0;
6760   u8 tag2 = 0;
6761   u8 ignore_tag1 = 0;
6762   u8 ignore_tag2 = 0;
6763   u8 cos1 = 0;
6764   u8 cos2 = 0;
6765   u8 dot1q = 0;
6766   u8 dot1ad = 0;
6767   int len = 14;
6768
6769   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6770     {
6771       if (unformat (input, "src"))
6772         src = 1;
6773       else if (unformat (input, "dst"))
6774         dst = 1;
6775       else if (unformat (input, "proto"))
6776         proto = 1;
6777       else if (unformat (input, "tag1"))
6778         tag1 = 1;
6779       else if (unformat (input, "tag2"))
6780         tag2 = 1;
6781       else if (unformat (input, "ignore-tag1"))
6782         ignore_tag1 = 1;
6783       else if (unformat (input, "ignore-tag2"))
6784         ignore_tag2 = 1;
6785       else if (unformat (input, "cos1"))
6786         cos1 = 1;
6787       else if (unformat (input, "cos2"))
6788         cos2 = 1;
6789       else if (unformat (input, "dot1q"))
6790         dot1q = 1;
6791       else if (unformat (input, "dot1ad"))
6792         dot1ad = 1;
6793       else
6794         break;
6795     }
6796   if ((src + dst + proto + tag1 + tag2 + dot1q + dot1ad +
6797        ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
6798     return 0;
6799
6800   if (tag1 || ignore_tag1 || cos1 || dot1q)
6801     len = 18;
6802   if (tag2 || ignore_tag2 || cos2 || dot1ad)
6803     len = 22;
6804
6805   vec_validate (mask, len - 1);
6806
6807   if (dst)
6808     clib_memset (mask, 0xff, 6);
6809
6810   if (src)
6811     clib_memset (mask + 6, 0xff, 6);
6812
6813   if (tag2 || dot1ad)
6814     {
6815       /* inner vlan tag */
6816       if (tag2)
6817         {
6818           mask[19] = 0xff;
6819           mask[18] = 0x0f;
6820         }
6821       if (cos2)
6822         mask[18] |= 0xe0;
6823       if (proto)
6824         mask[21] = mask[20] = 0xff;
6825       if (tag1)
6826         {
6827           mask[15] = 0xff;
6828           mask[14] = 0x0f;
6829         }
6830       if (cos1)
6831         mask[14] |= 0xe0;
6832       *maskp = mask;
6833       return 1;
6834     }
6835   if (tag1 | dot1q)
6836     {
6837       if (tag1)
6838         {
6839           mask[15] = 0xff;
6840           mask[14] = 0x0f;
6841         }
6842       if (cos1)
6843         mask[14] |= 0xe0;
6844       if (proto)
6845         mask[16] = mask[17] = 0xff;
6846
6847       *maskp = mask;
6848       return 1;
6849     }
6850   if (cos2)
6851     mask[18] |= 0xe0;
6852   if (cos1)
6853     mask[14] |= 0xe0;
6854   if (proto)
6855     mask[12] = mask[13] = 0xff;
6856
6857   *maskp = mask;
6858   return 1;
6859 }
6860
6861 uword
6862 unformat_classify_mask (unformat_input_t * input, va_list * args)
6863 {
6864   u8 **maskp = va_arg (*args, u8 **);
6865   u32 *skipp = va_arg (*args, u32 *);
6866   u32 *matchp = va_arg (*args, u32 *);
6867   u32 match;
6868   u8 *mask = 0;
6869   u8 *l2 = 0;
6870   u8 *l3 = 0;
6871   u8 *l4 = 0;
6872   int i;
6873
6874   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6875     {
6876       if (unformat (input, "hex %U", unformat_hex_string, &mask))
6877         ;
6878       else if (unformat (input, "l2 %U", unformat_l2_mask, &l2))
6879         ;
6880       else if (unformat (input, "l3 %U", unformat_l3_mask, &l3))
6881         ;
6882       else if (unformat (input, "l4 %U", unformat_l4_mask, &l4))
6883         ;
6884       else
6885         break;
6886     }
6887
6888   if (l4 && !l3)
6889     {
6890       vec_free (mask);
6891       vec_free (l2);
6892       vec_free (l4);
6893       return 0;
6894     }
6895
6896   if (mask || l2 || l3 || l4)
6897     {
6898       if (l2 || l3 || l4)
6899         {
6900           /* "With a free Ethernet header in every package" */
6901           if (l2 == 0)
6902             vec_validate (l2, 13);
6903           mask = l2;
6904           if (vec_len (l3))
6905             {
6906               vec_append (mask, l3);
6907               vec_free (l3);
6908             }
6909           if (vec_len (l4))
6910             {
6911               vec_append (mask, l4);
6912               vec_free (l4);
6913             }
6914         }
6915
6916       /* Scan forward looking for the first significant mask octet */
6917       for (i = 0; i < vec_len (mask); i++)
6918         if (mask[i])
6919           break;
6920
6921       /* compute (skip, match) params */
6922       *skipp = i / sizeof (u32x4);
6923       vec_delete (mask, *skipp * sizeof (u32x4), 0);
6924
6925       /* Pad mask to an even multiple of the vector size */
6926       while (vec_len (mask) % sizeof (u32x4))
6927         vec_add1 (mask, 0);
6928
6929       match = vec_len (mask) / sizeof (u32x4);
6930
6931       for (i = match * sizeof (u32x4); i > 0; i -= sizeof (u32x4))
6932         {
6933           u64 *tmp = (u64 *) (mask + (i - sizeof (u32x4)));
6934           if (*tmp || *(tmp + 1))
6935             break;
6936           match--;
6937         }
6938       if (match == 0)
6939         clib_warning ("BUG: match 0");
6940
6941       _vec_len (mask) = match * sizeof (u32x4);
6942
6943       *matchp = match;
6944       *maskp = mask;
6945
6946       return 1;
6947     }
6948
6949   return 0;
6950 }
6951 #endif /* VPP_API_TEST_BUILTIN */
6952
6953 #define foreach_l2_next                         \
6954 _(drop, DROP)                                   \
6955 _(ethernet, ETHERNET_INPUT)                     \
6956 _(ip4, IP4_INPUT)                               \
6957 _(ip6, IP6_INPUT)
6958
6959 uword
6960 unformat_l2_next_index (unformat_input_t * input, va_list * args)
6961 {
6962   u32 *miss_next_indexp = va_arg (*args, u32 *);
6963   u32 next_index = 0;
6964   u32 tmp;
6965
6966 #define _(n,N) \
6967   if (unformat (input, #n)) { next_index = L2_INPUT_CLASSIFY_NEXT_##N; goto out;}
6968   foreach_l2_next;
6969 #undef _
6970
6971   if (unformat (input, "%d", &tmp))
6972     {
6973       next_index = tmp;
6974       goto out;
6975     }
6976
6977   return 0;
6978
6979 out:
6980   *miss_next_indexp = next_index;
6981   return 1;
6982 }
6983
6984 #define foreach_ip_next                         \
6985 _(drop, DROP)                                   \
6986 _(local, LOCAL)                                 \
6987 _(rewrite, REWRITE)
6988
6989 uword
6990 api_unformat_ip_next_index (unformat_input_t * input, va_list * args)
6991 {
6992   u32 *miss_next_indexp = va_arg (*args, u32 *);
6993   u32 next_index = 0;
6994   u32 tmp;
6995
6996 #define _(n,N) \
6997   if (unformat (input, #n)) { next_index = IP_LOOKUP_NEXT_##N; goto out;}
6998   foreach_ip_next;
6999 #undef _
7000
7001   if (unformat (input, "%d", &tmp))
7002     {
7003       next_index = tmp;
7004       goto out;
7005     }
7006
7007   return 0;
7008
7009 out:
7010   *miss_next_indexp = next_index;
7011   return 1;
7012 }
7013
7014 #define foreach_acl_next                        \
7015 _(deny, DENY)
7016
7017 uword
7018 api_unformat_acl_next_index (unformat_input_t * input, va_list * args)
7019 {
7020   u32 *miss_next_indexp = va_arg (*args, u32 *);
7021   u32 next_index = 0;
7022   u32 tmp;
7023
7024 #define _(n,N) \
7025   if (unformat (input, #n)) { next_index = ACL_NEXT_INDEX_##N; goto out;}
7026   foreach_acl_next;
7027 #undef _
7028
7029   if (unformat (input, "permit"))
7030     {
7031       next_index = ~0;
7032       goto out;
7033     }
7034   else if (unformat (input, "%d", &tmp))
7035     {
7036       next_index = tmp;
7037       goto out;
7038     }
7039
7040   return 0;
7041
7042 out:
7043   *miss_next_indexp = next_index;
7044   return 1;
7045 }
7046
7047 uword
7048 unformat_policer_precolor (unformat_input_t * input, va_list * args)
7049 {
7050   u32 *r = va_arg (*args, u32 *);
7051
7052   if (unformat (input, "conform-color"))
7053     *r = POLICE_CONFORM;
7054   else if (unformat (input, "exceed-color"))
7055     *r = POLICE_EXCEED;
7056   else
7057     return 0;
7058
7059   return 1;
7060 }
7061
7062 #if VPP_API_TEST_BUILTIN == 0
7063 uword
7064 unformat_l4_match (unformat_input_t * input, va_list * args)
7065 {
7066   u8 **matchp = va_arg (*args, u8 **);
7067
7068   u8 *proto_header = 0;
7069   int src_port = 0;
7070   int dst_port = 0;
7071
7072   tcpudp_header_t h;
7073
7074   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7075     {
7076       if (unformat (input, "src_port %d", &src_port))
7077         ;
7078       else if (unformat (input, "dst_port %d", &dst_port))
7079         ;
7080       else
7081         return 0;
7082     }
7083
7084   h.src_port = clib_host_to_net_u16 (src_port);
7085   h.dst_port = clib_host_to_net_u16 (dst_port);
7086   vec_validate (proto_header, sizeof (h) - 1);
7087   memcpy (proto_header, &h, sizeof (h));
7088
7089   *matchp = proto_header;
7090
7091   return 1;
7092 }
7093
7094 uword
7095 unformat_ip4_match (unformat_input_t * input, va_list * args)
7096 {
7097   u8 **matchp = va_arg (*args, u8 **);
7098   u8 *match = 0;
7099   ip4_header_t *ip;
7100   int version = 0;
7101   u32 version_val;
7102   int hdr_length = 0;
7103   u32 hdr_length_val;
7104   int src = 0, dst = 0;
7105   ip4_address_t src_val, dst_val;
7106   int proto = 0;
7107   u32 proto_val;
7108   int tos = 0;
7109   u32 tos_val;
7110   int length = 0;
7111   u32 length_val;
7112   int fragment_id = 0;
7113   u32 fragment_id_val;
7114   int ttl = 0;
7115   int ttl_val;
7116   int checksum = 0;
7117   u32 checksum_val;
7118
7119   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7120     {
7121       if (unformat (input, "version %d", &version_val))
7122         version = 1;
7123       else if (unformat (input, "hdr_length %d", &hdr_length_val))
7124         hdr_length = 1;
7125       else if (unformat (input, "src %U", unformat_ip4_address, &src_val))
7126         src = 1;
7127       else if (unformat (input, "dst %U", unformat_ip4_address, &dst_val))
7128         dst = 1;
7129       else if (unformat (input, "proto %d", &proto_val))
7130         proto = 1;
7131       else if (unformat (input, "tos %d", &tos_val))
7132         tos = 1;
7133       else if (unformat (input, "length %d", &length_val))
7134         length = 1;
7135       else if (unformat (input, "fragment_id %d", &fragment_id_val))
7136         fragment_id = 1;
7137       else if (unformat (input, "ttl %d", &ttl_val))
7138         ttl = 1;
7139       else if (unformat (input, "checksum %d", &checksum_val))
7140         checksum = 1;
7141       else
7142         break;
7143     }
7144
7145   if (version + hdr_length + src + dst + proto + tos + length + fragment_id
7146       + ttl + checksum == 0)
7147     return 0;
7148
7149   /*
7150    * Aligned because we use the real comparison functions
7151    */
7152   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
7153
7154   ip = (ip4_header_t *) match;
7155
7156   /* These are realistically matched in practice */
7157   if (src)
7158     ip->src_address.as_u32 = src_val.as_u32;
7159
7160   if (dst)
7161     ip->dst_address.as_u32 = dst_val.as_u32;
7162
7163   if (proto)
7164     ip->protocol = proto_val;
7165
7166
7167   /* These are not, but they're included for completeness */
7168   if (version)
7169     ip->ip_version_and_header_length |= (version_val & 0xF) << 4;
7170
7171   if (hdr_length)
7172     ip->ip_version_and_header_length |= (hdr_length_val & 0xF);
7173
7174   if (tos)
7175     ip->tos = tos_val;
7176
7177   if (length)
7178     ip->length = clib_host_to_net_u16 (length_val);
7179
7180   if (ttl)
7181     ip->ttl = ttl_val;
7182
7183   if (checksum)
7184     ip->checksum = clib_host_to_net_u16 (checksum_val);
7185
7186   *matchp = match;
7187   return 1;
7188 }
7189
7190 uword
7191 unformat_ip6_match (unformat_input_t * input, va_list * args)
7192 {
7193   u8 **matchp = va_arg (*args, u8 **);
7194   u8 *match = 0;
7195   ip6_header_t *ip;
7196   int version = 0;
7197   u32 version_val;
7198   u8 traffic_class = 0;
7199   u32 traffic_class_val = 0;
7200   u8 flow_label = 0;
7201   u8 flow_label_val;
7202   int src = 0, dst = 0;
7203   ip6_address_t src_val, dst_val;
7204   int proto = 0;
7205   u32 proto_val;
7206   int payload_length = 0;
7207   u32 payload_length_val;
7208   int hop_limit = 0;
7209   int hop_limit_val;
7210   u32 ip_version_traffic_class_and_flow_label;
7211
7212   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7213     {
7214       if (unformat (input, "version %d", &version_val))
7215         version = 1;
7216       else if (unformat (input, "traffic_class %d", &traffic_class_val))
7217         traffic_class = 1;
7218       else if (unformat (input, "flow_label %d", &flow_label_val))
7219         flow_label = 1;
7220       else if (unformat (input, "src %U", unformat_ip6_address, &src_val))
7221         src = 1;
7222       else if (unformat (input, "dst %U", unformat_ip6_address, &dst_val))
7223         dst = 1;
7224       else if (unformat (input, "proto %d", &proto_val))
7225         proto = 1;
7226       else if (unformat (input, "payload_length %d", &payload_length_val))
7227         payload_length = 1;
7228       else if (unformat (input, "hop_limit %d", &hop_limit_val))
7229         hop_limit = 1;
7230       else
7231         break;
7232     }
7233
7234   if (version + traffic_class + flow_label + src + dst + proto +
7235       payload_length + hop_limit == 0)
7236     return 0;
7237
7238   /*
7239    * Aligned because we use the real comparison functions
7240    */
7241   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
7242
7243   ip = (ip6_header_t *) match;
7244
7245   if (src)
7246     clib_memcpy (&ip->src_address, &src_val, sizeof (ip->src_address));
7247
7248   if (dst)
7249     clib_memcpy (&ip->dst_address, &dst_val, sizeof (ip->dst_address));
7250
7251   if (proto)
7252     ip->protocol = proto_val;
7253
7254   ip_version_traffic_class_and_flow_label = 0;
7255
7256   if (version)
7257     ip_version_traffic_class_and_flow_label |= (version_val & 0xF) << 28;
7258
7259   if (traffic_class)
7260     ip_version_traffic_class_and_flow_label |=
7261       (traffic_class_val & 0xFF) << 20;
7262
7263   if (flow_label)
7264     ip_version_traffic_class_and_flow_label |= (flow_label_val & 0xFFFFF);
7265
7266   ip->ip_version_traffic_class_and_flow_label =
7267     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
7268
7269   if (payload_length)
7270     ip->payload_length = clib_host_to_net_u16 (payload_length_val);
7271
7272   if (hop_limit)
7273     ip->hop_limit = hop_limit_val;
7274
7275   *matchp = match;
7276   return 1;
7277 }
7278
7279 uword
7280 unformat_l3_match (unformat_input_t * input, va_list * args)
7281 {
7282   u8 **matchp = va_arg (*args, u8 **);
7283
7284   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7285     {
7286       if (unformat (input, "ip4 %U", unformat_ip4_match, matchp))
7287         return 1;
7288       else if (unformat (input, "ip6 %U", unformat_ip6_match, matchp))
7289         return 1;
7290       else
7291         break;
7292     }
7293   return 0;
7294 }
7295
7296 uword
7297 unformat_vlan_tag (unformat_input_t * input, va_list * args)
7298 {
7299   u8 *tagp = va_arg (*args, u8 *);
7300   u32 tag;
7301
7302   if (unformat (input, "%d", &tag))
7303     {
7304       tagp[0] = (tag >> 8) & 0x0F;
7305       tagp[1] = tag & 0xFF;
7306       return 1;
7307     }
7308
7309   return 0;
7310 }
7311
7312 uword
7313 unformat_l2_match (unformat_input_t * input, va_list * args)
7314 {
7315   u8 **matchp = va_arg (*args, u8 **);
7316   u8 *match = 0;
7317   u8 src = 0;
7318   u8 src_val[6];
7319   u8 dst = 0;
7320   u8 dst_val[6];
7321   u8 proto = 0;
7322   u16 proto_val;
7323   u8 tag1 = 0;
7324   u8 tag1_val[2];
7325   u8 tag2 = 0;
7326   u8 tag2_val[2];
7327   int len = 14;
7328   u8 ignore_tag1 = 0;
7329   u8 ignore_tag2 = 0;
7330   u8 cos1 = 0;
7331   u8 cos2 = 0;
7332   u32 cos1_val = 0;
7333   u32 cos2_val = 0;
7334
7335   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7336     {
7337       if (unformat (input, "src %U", unformat_ethernet_address, &src_val))
7338         src = 1;
7339       else
7340         if (unformat (input, "dst %U", unformat_ethernet_address, &dst_val))
7341         dst = 1;
7342       else if (unformat (input, "proto %U",
7343                          unformat_ethernet_type_host_byte_order, &proto_val))
7344         proto = 1;
7345       else if (unformat (input, "tag1 %U", unformat_vlan_tag, tag1_val))
7346         tag1 = 1;
7347       else if (unformat (input, "tag2 %U", unformat_vlan_tag, tag2_val))
7348         tag2 = 1;
7349       else if (unformat (input, "ignore-tag1"))
7350         ignore_tag1 = 1;
7351       else if (unformat (input, "ignore-tag2"))
7352         ignore_tag2 = 1;
7353       else if (unformat (input, "cos1 %d", &cos1_val))
7354         cos1 = 1;
7355       else if (unformat (input, "cos2 %d", &cos2_val))
7356         cos2 = 1;
7357       else
7358         break;
7359     }
7360   if ((src + dst + proto + tag1 + tag2 +
7361        ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
7362     return 0;
7363
7364   if (tag1 || ignore_tag1 || cos1)
7365     len = 18;
7366   if (tag2 || ignore_tag2 || cos2)
7367     len = 22;
7368
7369   vec_validate_aligned (match, len - 1, sizeof (u32x4));
7370
7371   if (dst)
7372     clib_memcpy (match, dst_val, 6);
7373
7374   if (src)
7375     clib_memcpy (match + 6, src_val, 6);
7376
7377   if (tag2)
7378     {
7379       /* inner vlan tag */
7380       match[19] = tag2_val[1];
7381       match[18] = tag2_val[0];
7382       if (cos2)
7383         match[18] |= (cos2_val & 0x7) << 5;
7384       if (proto)
7385         {
7386           match[21] = proto_val & 0xff;
7387           match[20] = proto_val >> 8;
7388         }
7389       if (tag1)
7390         {
7391           match[15] = tag1_val[1];
7392           match[14] = tag1_val[0];
7393         }
7394       if (cos1)
7395         match[14] |= (cos1_val & 0x7) << 5;
7396       *matchp = match;
7397       return 1;
7398     }
7399   if (tag1)
7400     {
7401       match[15] = tag1_val[1];
7402       match[14] = tag1_val[0];
7403       if (proto)
7404         {
7405           match[17] = proto_val & 0xff;
7406           match[16] = proto_val >> 8;
7407         }
7408       if (cos1)
7409         match[14] |= (cos1_val & 0x7) << 5;
7410
7411       *matchp = match;
7412       return 1;
7413     }
7414   if (cos2)
7415     match[18] |= (cos2_val & 0x7) << 5;
7416   if (cos1)
7417     match[14] |= (cos1_val & 0x7) << 5;
7418   if (proto)
7419     {
7420       match[13] = proto_val & 0xff;
7421       match[12] = proto_val >> 8;
7422     }
7423
7424   *matchp = match;
7425   return 1;
7426 }
7427
7428 uword
7429 unformat_qos_source (unformat_input_t * input, va_list * args)
7430 {
7431   int *qs = va_arg (*args, int *);
7432
7433   if (unformat (input, "ip"))
7434     *qs = QOS_SOURCE_IP;
7435   else if (unformat (input, "mpls"))
7436     *qs = QOS_SOURCE_MPLS;
7437   else if (unformat (input, "ext"))
7438     *qs = QOS_SOURCE_EXT;
7439   else if (unformat (input, "vlan"))
7440     *qs = QOS_SOURCE_VLAN;
7441   else
7442     return 0;
7443
7444   return 1;
7445 }
7446 #endif
7447
7448 uword
7449 api_unformat_classify_match (unformat_input_t * input, va_list * args)
7450 {
7451   u8 **matchp = va_arg (*args, u8 **);
7452   u32 skip_n_vectors = va_arg (*args, u32);
7453   u32 match_n_vectors = va_arg (*args, u32);
7454
7455   u8 *match = 0;
7456   u8 *l2 = 0;
7457   u8 *l3 = 0;
7458   u8 *l4 = 0;
7459
7460   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7461     {
7462       if (unformat (input, "hex %U", unformat_hex_string, &match))
7463         ;
7464       else if (unformat (input, "l2 %U", unformat_l2_match, &l2))
7465         ;
7466       else if (unformat (input, "l3 %U", unformat_l3_match, &l3))
7467         ;
7468       else if (unformat (input, "l4 %U", unformat_l4_match, &l4))
7469         ;
7470       else
7471         break;
7472     }
7473
7474   if (l4 && !l3)
7475     {
7476       vec_free (match);
7477       vec_free (l2);
7478       vec_free (l4);
7479       return 0;
7480     }
7481
7482   if (match || l2 || l3 || l4)
7483     {
7484       if (l2 || l3 || l4)
7485         {
7486           /* "Win a free Ethernet header in every packet" */
7487           if (l2 == 0)
7488             vec_validate_aligned (l2, 13, sizeof (u32x4));
7489           match = l2;
7490           if (vec_len (l3))
7491             {
7492               vec_append_aligned (match, l3, sizeof (u32x4));
7493               vec_free (l3);
7494             }
7495           if (vec_len (l4))
7496             {
7497               vec_append_aligned (match, l4, sizeof (u32x4));
7498               vec_free (l4);
7499             }
7500         }
7501
7502       /* Make sure the vector is big enough even if key is all 0's */
7503       vec_validate_aligned
7504         (match, ((match_n_vectors + skip_n_vectors) * sizeof (u32x4)) - 1,
7505          sizeof (u32x4));
7506
7507       /* Set size, include skipped vectors */
7508       _vec_len (match) = (match_n_vectors + skip_n_vectors) * sizeof (u32x4);
7509
7510       *matchp = match;
7511
7512       return 1;
7513     }
7514
7515   return 0;
7516 }
7517
7518 static int
7519 api_get_node_index (vat_main_t * vam)
7520 {
7521   unformat_input_t *i = vam->input;
7522   vl_api_get_node_index_t *mp;
7523   u8 *name = 0;
7524   int ret;
7525
7526   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7527     {
7528       if (unformat (i, "node %s", &name))
7529         ;
7530       else
7531         break;
7532     }
7533   if (name == 0)
7534     {
7535       errmsg ("node name required");
7536       return -99;
7537     }
7538   if (vec_len (name) >= ARRAY_LEN (mp->node_name))
7539     {
7540       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
7541       return -99;
7542     }
7543
7544   M (GET_NODE_INDEX, mp);
7545   clib_memcpy (mp->node_name, name, vec_len (name));
7546   vec_free (name);
7547
7548   S (mp);
7549   W (ret);
7550   return ret;
7551 }
7552
7553 static int
7554 api_get_next_index (vat_main_t * vam)
7555 {
7556   unformat_input_t *i = vam->input;
7557   vl_api_get_next_index_t *mp;
7558   u8 *node_name = 0, *next_node_name = 0;
7559   int ret;
7560
7561   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7562     {
7563       if (unformat (i, "node-name %s", &node_name))
7564         ;
7565       else if (unformat (i, "next-node-name %s", &next_node_name))
7566         break;
7567     }
7568
7569   if (node_name == 0)
7570     {
7571       errmsg ("node name required");
7572       return -99;
7573     }
7574   if (vec_len (node_name) >= ARRAY_LEN (mp->node_name))
7575     {
7576       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
7577       return -99;
7578     }
7579
7580   if (next_node_name == 0)
7581     {
7582       errmsg ("next node name required");
7583       return -99;
7584     }
7585   if (vec_len (next_node_name) >= ARRAY_LEN (mp->next_name))
7586     {
7587       errmsg ("next node name too long, max %d", ARRAY_LEN (mp->next_name));
7588       return -99;
7589     }
7590
7591   M (GET_NEXT_INDEX, mp);
7592   clib_memcpy (mp->node_name, node_name, vec_len (node_name));
7593   clib_memcpy (mp->next_name, next_node_name, vec_len (next_node_name));
7594   vec_free (node_name);
7595   vec_free (next_node_name);
7596
7597   S (mp);
7598   W (ret);
7599   return ret;
7600 }
7601
7602 static int
7603 api_add_node_next (vat_main_t * vam)
7604 {
7605   unformat_input_t *i = vam->input;
7606   vl_api_add_node_next_t *mp;
7607   u8 *name = 0;
7608   u8 *next = 0;
7609   int ret;
7610
7611   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7612     {
7613       if (unformat (i, "node %s", &name))
7614         ;
7615       else if (unformat (i, "next %s", &next))
7616         ;
7617       else
7618         break;
7619     }
7620   if (name == 0)
7621     {
7622       errmsg ("node name required");
7623       return -99;
7624     }
7625   if (vec_len (name) >= ARRAY_LEN (mp->node_name))
7626     {
7627       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
7628       return -99;
7629     }
7630   if (next == 0)
7631     {
7632       errmsg ("next node required");
7633       return -99;
7634     }
7635   if (vec_len (next) >= ARRAY_LEN (mp->next_name))
7636     {
7637       errmsg ("next name too long, max %d", ARRAY_LEN (mp->next_name));
7638       return -99;
7639     }
7640
7641   M (ADD_NODE_NEXT, mp);
7642   clib_memcpy (mp->node_name, name, vec_len (name));
7643   clib_memcpy (mp->next_name, next, vec_len (next));
7644   vec_free (name);
7645   vec_free (next);
7646
7647   S (mp);
7648   W (ret);
7649   return ret;
7650 }
7651
7652 static void vl_api_sw_interface_tap_v2_details_t_handler
7653   (vl_api_sw_interface_tap_v2_details_t * mp)
7654 {
7655   vat_main_t *vam = &vat_main;
7656
7657   u8 *ip4 =
7658     format (0, "%U/%d", format_ip4_address, mp->host_ip4_prefix.address,
7659             mp->host_ip4_prefix.len);
7660   u8 *ip6 =
7661     format (0, "%U/%d", format_ip6_address, mp->host_ip6_prefix.address,
7662             mp->host_ip6_prefix.len);
7663
7664   print (vam->ofp,
7665          "\n%-16s %-12d %-5d %-12d %-12d %-14U %-30s %-20s %-20s %-30s 0x%-08x",
7666          mp->dev_name, ntohl (mp->sw_if_index), ntohl (mp->id),
7667          ntohs (mp->rx_ring_sz), ntohs (mp->tx_ring_sz),
7668          format_ethernet_address, mp->host_mac_addr, mp->host_namespace,
7669          mp->host_bridge, ip4, ip6, ntohl (mp->tap_flags));
7670
7671   vec_free (ip4);
7672   vec_free (ip6);
7673 }
7674
7675 static void vl_api_sw_interface_tap_v2_details_t_handler_json
7676   (vl_api_sw_interface_tap_v2_details_t * mp)
7677 {
7678   vat_main_t *vam = &vat_main;
7679   vat_json_node_t *node = NULL;
7680
7681   if (VAT_JSON_ARRAY != vam->json_tree.type)
7682     {
7683       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
7684       vat_json_init_array (&vam->json_tree);
7685     }
7686   node = vat_json_array_add (&vam->json_tree);
7687
7688   vat_json_init_object (node);
7689   vat_json_object_add_uint (node, "id", ntohl (mp->id));
7690   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
7691   vat_json_object_add_uint (node, "tap_flags", ntohl (mp->tap_flags));
7692   vat_json_object_add_string_copy (node, "dev_name", mp->dev_name);
7693   vat_json_object_add_uint (node, "rx_ring_sz", ntohs (mp->rx_ring_sz));
7694   vat_json_object_add_uint (node, "tx_ring_sz", ntohs (mp->tx_ring_sz));
7695   vat_json_object_add_string_copy (node, "host_mac_addr",
7696                                    format (0, "%U", format_ethernet_address,
7697                                            &mp->host_mac_addr));
7698   vat_json_object_add_string_copy (node, "host_namespace",
7699                                    mp->host_namespace);
7700   vat_json_object_add_string_copy (node, "host_bridge", mp->host_bridge);
7701   vat_json_object_add_string_copy (node, "host_ip4_addr",
7702                                    format (0, "%U/%d", format_ip4_address,
7703                                            mp->host_ip4_prefix.address,
7704                                            mp->host_ip4_prefix.len));
7705   vat_json_object_add_string_copy (node, "host_ip6_prefix",
7706                                    format (0, "%U/%d", format_ip6_address,
7707                                            mp->host_ip6_prefix.address,
7708                                            mp->host_ip6_prefix.len));
7709
7710 }
7711
7712 static int
7713 api_sw_interface_tap_v2_dump (vat_main_t * vam)
7714 {
7715   vl_api_sw_interface_tap_v2_dump_t *mp;
7716   vl_api_control_ping_t *mp_ping;
7717   int ret;
7718
7719   print (vam->ofp,
7720          "\n%-16s %-12s %-5s %-12s %-12s %-14s %-30s %-20s %-20s %-30s",
7721          "dev_name", "sw_if_index", "id", "rx_ring_sz", "tx_ring_sz",
7722          "host_mac_addr", "host_namespace", "host_bridge", "host_ip4_addr",
7723          "host_ip6_addr");
7724
7725   /* Get list of tap interfaces */
7726   M (SW_INTERFACE_TAP_V2_DUMP, mp);
7727   S (mp);
7728
7729   /* Use a control ping for synchronization */
7730   MPING (CONTROL_PING, mp_ping);
7731   S (mp_ping);
7732
7733   W (ret);
7734   return ret;
7735 }
7736
7737 static void vl_api_sw_interface_virtio_pci_details_t_handler
7738   (vl_api_sw_interface_virtio_pci_details_t * mp)
7739 {
7740   vat_main_t *vam = &vat_main;
7741
7742   typedef union
7743   {
7744     struct
7745     {
7746       u16 domain;
7747       u8 bus;
7748       u8 slot:5;
7749       u8 function:3;
7750     };
7751     u32 as_u32;
7752   } pci_addr_t;
7753   pci_addr_t addr;
7754
7755   addr.domain = ntohs (mp->pci_addr.domain);
7756   addr.bus = mp->pci_addr.bus;
7757   addr.slot = mp->pci_addr.slot;
7758   addr.function = mp->pci_addr.function;
7759
7760   u8 *pci_addr = format (0, "%04x:%02x:%02x.%x", addr.domain, addr.bus,
7761                          addr.slot, addr.function);
7762
7763   print (vam->ofp,
7764          "\n%-12s %-12d %-12d %-12d %-17U 0x%-08llx",
7765          pci_addr, ntohl (mp->sw_if_index),
7766          ntohs (mp->rx_ring_sz), ntohs (mp->tx_ring_sz),
7767          format_ethernet_address, mp->mac_addr,
7768          clib_net_to_host_u64 (mp->features));
7769   vec_free (pci_addr);
7770 }
7771
7772 static void vl_api_sw_interface_virtio_pci_details_t_handler_json
7773   (vl_api_sw_interface_virtio_pci_details_t * mp)
7774 {
7775   vat_main_t *vam = &vat_main;
7776   vat_json_node_t *node = NULL;
7777   vlib_pci_addr_t pci_addr;
7778
7779   if (VAT_JSON_ARRAY != vam->json_tree.type)
7780     {
7781       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
7782       vat_json_init_array (&vam->json_tree);
7783     }
7784   node = vat_json_array_add (&vam->json_tree);
7785
7786   pci_addr.domain = ntohs (mp->pci_addr.domain);
7787   pci_addr.bus = mp->pci_addr.bus;
7788   pci_addr.slot = mp->pci_addr.slot;
7789   pci_addr.function = mp->pci_addr.function;
7790
7791   vat_json_init_object (node);
7792   vat_json_object_add_uint (node, "pci-addr", pci_addr.as_u32);
7793   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
7794   vat_json_object_add_uint (node, "rx_ring_sz", ntohs (mp->rx_ring_sz));
7795   vat_json_object_add_uint (node, "tx_ring_sz", ntohs (mp->tx_ring_sz));
7796   vat_json_object_add_uint (node, "features",
7797                             clib_net_to_host_u64 (mp->features));
7798   vat_json_object_add_string_copy (node, "mac_addr",
7799                                    format (0, "%U", format_ethernet_address,
7800                                            &mp->mac_addr));
7801 }
7802
7803 static int
7804 api_sw_interface_virtio_pci_dump (vat_main_t * vam)
7805 {
7806   vl_api_sw_interface_virtio_pci_dump_t *mp;
7807   vl_api_control_ping_t *mp_ping;
7808   int ret;
7809
7810   print (vam->ofp,
7811          "\n%-12s %-12s %-12s %-12s %-17s %-08s",
7812          "pci_addr", "sw_if_index", "rx_ring_sz", "tx_ring_sz",
7813          "mac_addr", "features");
7814
7815   /* Get list of tap interfaces */
7816   M (SW_INTERFACE_VIRTIO_PCI_DUMP, mp);
7817   S (mp);
7818
7819   /* Use a control ping for synchronization */
7820   MPING (CONTROL_PING, mp_ping);
7821   S (mp_ping);
7822
7823   W (ret);
7824   return ret;
7825 }
7826
7827 static int
7828 api_l2_fib_clear_table (vat_main_t * vam)
7829 {
7830 //  unformat_input_t * i = vam->input;
7831   vl_api_l2_fib_clear_table_t *mp;
7832   int ret;
7833
7834   M (L2_FIB_CLEAR_TABLE, mp);
7835
7836   S (mp);
7837   W (ret);
7838   return ret;
7839 }
7840
7841 static int
7842 api_l2_interface_efp_filter (vat_main_t * vam)
7843 {
7844   unformat_input_t *i = vam->input;
7845   vl_api_l2_interface_efp_filter_t *mp;
7846   u32 sw_if_index;
7847   u8 enable = 1;
7848   u8 sw_if_index_set = 0;
7849   int ret;
7850
7851   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7852     {
7853       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
7854         sw_if_index_set = 1;
7855       else if (unformat (i, "sw_if_index %d", &sw_if_index))
7856         sw_if_index_set = 1;
7857       else if (unformat (i, "enable"))
7858         enable = 1;
7859       else if (unformat (i, "disable"))
7860         enable = 0;
7861       else
7862         {
7863           clib_warning ("parse error '%U'", format_unformat_error, i);
7864           return -99;
7865         }
7866     }
7867
7868   if (sw_if_index_set == 0)
7869     {
7870       errmsg ("missing sw_if_index");
7871       return -99;
7872     }
7873
7874   M (L2_INTERFACE_EFP_FILTER, mp);
7875
7876   mp->sw_if_index = ntohl (sw_if_index);
7877   mp->enable_disable = enable;
7878
7879   S (mp);
7880   W (ret);
7881   return ret;
7882 }
7883
7884 #define foreach_vtr_op                          \
7885 _("disable",  L2_VTR_DISABLED)                  \
7886 _("push-1",  L2_VTR_PUSH_1)                     \
7887 _("push-2",  L2_VTR_PUSH_2)                     \
7888 _("pop-1",  L2_VTR_POP_1)                       \
7889 _("pop-2",  L2_VTR_POP_2)                       \
7890 _("translate-1-1",  L2_VTR_TRANSLATE_1_1)       \
7891 _("translate-1-2",  L2_VTR_TRANSLATE_1_2)       \
7892 _("translate-2-1",  L2_VTR_TRANSLATE_2_1)       \
7893 _("translate-2-2",  L2_VTR_TRANSLATE_2_2)
7894
7895 static int
7896 api_l2_interface_vlan_tag_rewrite (vat_main_t * vam)
7897 {
7898   unformat_input_t *i = vam->input;
7899   vl_api_l2_interface_vlan_tag_rewrite_t *mp;
7900   u32 sw_if_index;
7901   u8 sw_if_index_set = 0;
7902   u8 vtr_op_set = 0;
7903   u32 vtr_op = 0;
7904   u32 push_dot1q = 1;
7905   u32 tag1 = ~0;
7906   u32 tag2 = ~0;
7907   int ret;
7908
7909   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7910     {
7911       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
7912         sw_if_index_set = 1;
7913       else if (unformat (i, "sw_if_index %d", &sw_if_index))
7914         sw_if_index_set = 1;
7915       else if (unformat (i, "vtr_op %d", &vtr_op))
7916         vtr_op_set = 1;
7917 #define _(n,v) else if (unformat(i, n)) {vtr_op = v; vtr_op_set = 1;}
7918       foreach_vtr_op
7919 #undef _
7920         else if (unformat (i, "push_dot1q %d", &push_dot1q))
7921         ;
7922       else if (unformat (i, "tag1 %d", &tag1))
7923         ;
7924       else if (unformat (i, "tag2 %d", &tag2))
7925         ;
7926       else
7927         {
7928           clib_warning ("parse error '%U'", format_unformat_error, i);
7929           return -99;
7930         }
7931     }
7932
7933   if ((sw_if_index_set == 0) || (vtr_op_set == 0))
7934     {
7935       errmsg ("missing vtr operation or sw_if_index");
7936       return -99;
7937     }
7938
7939   M (L2_INTERFACE_VLAN_TAG_REWRITE, mp);
7940   mp->sw_if_index = ntohl (sw_if_index);
7941   mp->vtr_op = ntohl (vtr_op);
7942   mp->push_dot1q = ntohl (push_dot1q);
7943   mp->tag1 = ntohl (tag1);
7944   mp->tag2 = ntohl (tag2);
7945
7946   S (mp);
7947   W (ret);
7948   return ret;
7949 }
7950
7951 static int
7952 api_create_vhost_user_if (vat_main_t * vam)
7953 {
7954   unformat_input_t *i = vam->input;
7955   vl_api_create_vhost_user_if_t *mp;
7956   u8 *file_name;
7957   u8 is_server = 0;
7958   u8 file_name_set = 0;
7959   u32 custom_dev_instance = ~0;
7960   u8 hwaddr[6];
7961   u8 use_custom_mac = 0;
7962   u8 disable_mrg_rxbuf = 0;
7963   u8 disable_indirect_desc = 0;
7964   u8 *tag = 0;
7965   u8 enable_gso = 0;
7966   u8 enable_packed = 0;
7967   int ret;
7968
7969   /* Shut up coverity */
7970   clib_memset (hwaddr, 0, sizeof (hwaddr));
7971
7972   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7973     {
7974       if (unformat (i, "socket %s", &file_name))
7975         {
7976           file_name_set = 1;
7977         }
7978       else if (unformat (i, "renumber %" PRIu32, &custom_dev_instance))
7979         ;
7980       else if (unformat (i, "mac %U", unformat_ethernet_address, hwaddr))
7981         use_custom_mac = 1;
7982       else if (unformat (i, "server"))
7983         is_server = 1;
7984       else if (unformat (i, "disable_mrg_rxbuf"))
7985         disable_mrg_rxbuf = 1;
7986       else if (unformat (i, "disable_indirect_desc"))
7987         disable_indirect_desc = 1;
7988       else if (unformat (i, "gso"))
7989         enable_gso = 1;
7990       else if (unformat (i, "packed"))
7991         enable_packed = 1;
7992       else if (unformat (i, "tag %s", &tag))
7993         ;
7994       else
7995         break;
7996     }
7997
7998   if (file_name_set == 0)
7999     {
8000       errmsg ("missing socket file name");
8001       return -99;
8002     }
8003
8004   if (vec_len (file_name) > 255)
8005     {
8006       errmsg ("socket file name too long");
8007       return -99;
8008     }
8009   vec_add1 (file_name, 0);
8010
8011   M (CREATE_VHOST_USER_IF, mp);
8012
8013   mp->is_server = is_server;
8014   mp->disable_mrg_rxbuf = disable_mrg_rxbuf;
8015   mp->disable_indirect_desc = disable_indirect_desc;
8016   mp->enable_gso = enable_gso;
8017   mp->enable_packed = enable_packed;
8018   mp->custom_dev_instance = ntohl (custom_dev_instance);
8019   clib_memcpy (mp->sock_filename, file_name, vec_len (file_name));
8020   vec_free (file_name);
8021   if (custom_dev_instance != ~0)
8022     mp->renumber = 1;
8023
8024   mp->use_custom_mac = use_custom_mac;
8025   clib_memcpy (mp->mac_address, hwaddr, 6);
8026   if (tag)
8027     strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
8028   vec_free (tag);
8029
8030   S (mp);
8031   W (ret);
8032   return ret;
8033 }
8034
8035 static int
8036 api_modify_vhost_user_if (vat_main_t * vam)
8037 {
8038   unformat_input_t *i = vam->input;
8039   vl_api_modify_vhost_user_if_t *mp;
8040   u8 *file_name;
8041   u8 is_server = 0;
8042   u8 file_name_set = 0;
8043   u32 custom_dev_instance = ~0;
8044   u8 sw_if_index_set = 0;
8045   u32 sw_if_index = (u32) ~ 0;
8046   u8 enable_gso = 0;
8047   u8 enable_packed = 0;
8048   int ret;
8049
8050   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8051     {
8052       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8053         sw_if_index_set = 1;
8054       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8055         sw_if_index_set = 1;
8056       else if (unformat (i, "socket %s", &file_name))
8057         {
8058           file_name_set = 1;
8059         }
8060       else if (unformat (i, "renumber %" PRIu32, &custom_dev_instance))
8061         ;
8062       else if (unformat (i, "server"))
8063         is_server = 1;
8064       else if (unformat (i, "gso"))
8065         enable_gso = 1;
8066       else if (unformat (i, "packed"))
8067         enable_packed = 1;
8068       else
8069         break;
8070     }
8071
8072   if (sw_if_index_set == 0)
8073     {
8074       errmsg ("missing sw_if_index or interface name");
8075       return -99;
8076     }
8077
8078   if (file_name_set == 0)
8079     {
8080       errmsg ("missing socket file name");
8081       return -99;
8082     }
8083
8084   if (vec_len (file_name) > 255)
8085     {
8086       errmsg ("socket file name too long");
8087       return -99;
8088     }
8089   vec_add1 (file_name, 0);
8090
8091   M (MODIFY_VHOST_USER_IF, mp);
8092
8093   mp->sw_if_index = ntohl (sw_if_index);
8094   mp->is_server = is_server;
8095   mp->enable_gso = enable_gso;
8096   mp->enable_packed = enable_packed;
8097   mp->custom_dev_instance = ntohl (custom_dev_instance);
8098   clib_memcpy (mp->sock_filename, file_name, vec_len (file_name));
8099   vec_free (file_name);
8100   if (custom_dev_instance != ~0)
8101     mp->renumber = 1;
8102
8103   S (mp);
8104   W (ret);
8105   return ret;
8106 }
8107
8108 static int
8109 api_create_vhost_user_if_v2 (vat_main_t * vam)
8110 {
8111   unformat_input_t *i = vam->input;
8112   vl_api_create_vhost_user_if_v2_t *mp;
8113   u8 *file_name;
8114   u8 is_server = 0;
8115   u8 file_name_set = 0;
8116   u32 custom_dev_instance = ~0;
8117   u8 hwaddr[6];
8118   u8 use_custom_mac = 0;
8119   u8 disable_mrg_rxbuf = 0;
8120   u8 disable_indirect_desc = 0;
8121   u8 *tag = 0;
8122   u8 enable_gso = 0;
8123   u8 enable_packed = 0;
8124   u8 enable_event_idx = 0;
8125   int ret;
8126
8127   /* Shut up coverity */
8128   clib_memset (hwaddr, 0, sizeof (hwaddr));
8129
8130   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8131     {
8132       if (unformat (i, "socket %s", &file_name))
8133         {
8134           file_name_set = 1;
8135         }
8136       else if (unformat (i, "renumber %" PRIu32, &custom_dev_instance))
8137         ;
8138       else if (unformat (i, "mac %U", unformat_ethernet_address, hwaddr))
8139         use_custom_mac = 1;
8140       else if (unformat (i, "server"))
8141         is_server = 1;
8142       else if (unformat (i, "disable_mrg_rxbuf"))
8143         disable_mrg_rxbuf = 1;
8144       else if (unformat (i, "disable_indirect_desc"))
8145         disable_indirect_desc = 1;
8146       else if (unformat (i, "gso"))
8147         enable_gso = 1;
8148       else if (unformat (i, "packed"))
8149         enable_packed = 1;
8150       else if (unformat (i, "event-idx"))
8151         enable_event_idx = 1;
8152       else if (unformat (i, "tag %s", &tag))
8153         ;
8154       else
8155         break;
8156     }
8157
8158   if (file_name_set == 0)
8159     {
8160       errmsg ("missing socket file name");
8161       return -99;
8162     }
8163
8164   if (vec_len (file_name) > 255)
8165     {
8166       errmsg ("socket file name too long");
8167       return -99;
8168     }
8169   vec_add1 (file_name, 0);
8170
8171   M (CREATE_VHOST_USER_IF_V2, mp);
8172
8173   mp->is_server = is_server;
8174   mp->disable_mrg_rxbuf = disable_mrg_rxbuf;
8175   mp->disable_indirect_desc = disable_indirect_desc;
8176   mp->enable_gso = enable_gso;
8177   mp->enable_packed = enable_packed;
8178   mp->enable_event_idx = enable_event_idx;
8179   mp->custom_dev_instance = ntohl (custom_dev_instance);
8180   clib_memcpy (mp->sock_filename, file_name, vec_len (file_name));
8181   vec_free (file_name);
8182   if (custom_dev_instance != ~0)
8183     mp->renumber = 1;
8184
8185   mp->use_custom_mac = use_custom_mac;
8186   clib_memcpy (mp->mac_address, hwaddr, 6);
8187   if (tag)
8188     strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
8189   vec_free (tag);
8190
8191   S (mp);
8192   W (ret);
8193   return ret;
8194 }
8195
8196 static int
8197 api_modify_vhost_user_if_v2 (vat_main_t * vam)
8198 {
8199   unformat_input_t *i = vam->input;
8200   vl_api_modify_vhost_user_if_v2_t *mp;
8201   u8 *file_name;
8202   u8 is_server = 0;
8203   u8 file_name_set = 0;
8204   u32 custom_dev_instance = ~0;
8205   u8 sw_if_index_set = 0;
8206   u32 sw_if_index = (u32) ~ 0;
8207   u8 enable_gso = 0;
8208   u8 enable_packed = 0;
8209   u8 enable_event_idx = 0;
8210   int ret;
8211
8212   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8213     {
8214       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8215         sw_if_index_set = 1;
8216       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8217         sw_if_index_set = 1;
8218       else if (unformat (i, "socket %s", &file_name))
8219         {
8220           file_name_set = 1;
8221         }
8222       else if (unformat (i, "renumber %" PRIu32, &custom_dev_instance))
8223         ;
8224       else if (unformat (i, "server"))
8225         is_server = 1;
8226       else if (unformat (i, "gso"))
8227         enable_gso = 1;
8228       else if (unformat (i, "packed"))
8229         enable_packed = 1;
8230       else if (unformat (i, "event-idx"))
8231         enable_event_idx = 1;
8232       else
8233         break;
8234     }
8235
8236   if (sw_if_index_set == 0)
8237     {
8238       errmsg ("missing sw_if_index or interface name");
8239       return -99;
8240     }
8241
8242   if (file_name_set == 0)
8243     {
8244       errmsg ("missing socket file name");
8245       return -99;
8246     }
8247
8248   if (vec_len (file_name) > 255)
8249     {
8250       errmsg ("socket file name too long");
8251       return -99;
8252     }
8253   vec_add1 (file_name, 0);
8254
8255   M (MODIFY_VHOST_USER_IF_V2, mp);
8256
8257   mp->sw_if_index = ntohl (sw_if_index);
8258   mp->is_server = is_server;
8259   mp->enable_gso = enable_gso;
8260   mp->enable_packed = enable_packed;
8261   mp->enable_event_idx = enable_event_idx;
8262   mp->custom_dev_instance = ntohl (custom_dev_instance);
8263   clib_memcpy (mp->sock_filename, file_name, vec_len (file_name));
8264   vec_free (file_name);
8265   if (custom_dev_instance != ~0)
8266     mp->renumber = 1;
8267
8268   S (mp);
8269   W (ret);
8270   return ret;
8271 }
8272
8273 static int
8274 api_delete_vhost_user_if (vat_main_t * vam)
8275 {
8276   unformat_input_t *i = vam->input;
8277   vl_api_delete_vhost_user_if_t *mp;
8278   u32 sw_if_index = ~0;
8279   u8 sw_if_index_set = 0;
8280   int ret;
8281
8282   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8283     {
8284       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8285         sw_if_index_set = 1;
8286       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8287         sw_if_index_set = 1;
8288       else
8289         break;
8290     }
8291
8292   if (sw_if_index_set == 0)
8293     {
8294       errmsg ("missing sw_if_index or interface name");
8295       return -99;
8296     }
8297
8298
8299   M (DELETE_VHOST_USER_IF, mp);
8300
8301   mp->sw_if_index = ntohl (sw_if_index);
8302
8303   S (mp);
8304   W (ret);
8305   return ret;
8306 }
8307
8308 static void vl_api_sw_interface_vhost_user_details_t_handler
8309   (vl_api_sw_interface_vhost_user_details_t * mp)
8310 {
8311   vat_main_t *vam = &vat_main;
8312   u64 features;
8313
8314   features =
8315     clib_net_to_host_u32 (mp->features_first_32) | ((u64)
8316                                                     clib_net_to_host_u32
8317                                                     (mp->features_last_32) <<
8318                                                     32);
8319
8320   print (vam->ofp, "%-25s %3" PRIu32 " %6" PRIu32 " %16llx %6d %7d %s",
8321          (char *) mp->interface_name, ntohl (mp->sw_if_index),
8322          ntohl (mp->virtio_net_hdr_sz), features, mp->is_server,
8323          ntohl (mp->num_regions), (char *) mp->sock_filename);
8324   print (vam->ofp, "    Status: '%s'", strerror (ntohl (mp->sock_errno)));
8325 }
8326
8327 static void vl_api_sw_interface_vhost_user_details_t_handler_json
8328   (vl_api_sw_interface_vhost_user_details_t * mp)
8329 {
8330   vat_main_t *vam = &vat_main;
8331   vat_json_node_t *node = NULL;
8332
8333   if (VAT_JSON_ARRAY != vam->json_tree.type)
8334     {
8335       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
8336       vat_json_init_array (&vam->json_tree);
8337     }
8338   node = vat_json_array_add (&vam->json_tree);
8339
8340   vat_json_init_object (node);
8341   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
8342   vat_json_object_add_string_copy (node, "interface_name",
8343                                    mp->interface_name);
8344   vat_json_object_add_uint (node, "virtio_net_hdr_sz",
8345                             ntohl (mp->virtio_net_hdr_sz));
8346   vat_json_object_add_uint (node, "features_first_32",
8347                             clib_net_to_host_u32 (mp->features_first_32));
8348   vat_json_object_add_uint (node, "features_last_32",
8349                             clib_net_to_host_u32 (mp->features_last_32));
8350   vat_json_object_add_uint (node, "is_server", mp->is_server);
8351   vat_json_object_add_string_copy (node, "sock_filename", mp->sock_filename);
8352   vat_json_object_add_uint (node, "num_regions", ntohl (mp->num_regions));
8353   vat_json_object_add_uint (node, "sock_errno", ntohl (mp->sock_errno));
8354 }
8355
8356 static int
8357 api_sw_interface_vhost_user_dump (vat_main_t * vam)
8358 {
8359   unformat_input_t *i = vam->input;
8360   vl_api_sw_interface_vhost_user_dump_t *mp;
8361   vl_api_control_ping_t *mp_ping;
8362   int ret;
8363   u32 sw_if_index = ~0;
8364
8365   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8366     {
8367       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8368         ;
8369       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8370         ;
8371       else
8372         break;
8373     }
8374
8375   print (vam->ofp, "Interface name            idx hdr_sz         features "
8376                    "server regions filename");
8377
8378   /* Get list of vhost-user interfaces */
8379   M (SW_INTERFACE_VHOST_USER_DUMP, mp);
8380   mp->sw_if_index = ntohl (sw_if_index);
8381   S (mp);
8382
8383   /* Use a control ping for synchronization */
8384   MPING (CONTROL_PING, mp_ping);
8385   S (mp_ping);
8386
8387   W (ret);
8388   return ret;
8389 }
8390
8391 static int
8392 api_show_version (vat_main_t * vam)
8393 {
8394   vl_api_show_version_t *mp;
8395   int ret;
8396
8397   M (SHOW_VERSION, mp);
8398
8399   S (mp);
8400   W (ret);
8401   return ret;
8402 }
8403
8404 static void vl_api_l2_fib_table_details_t_handler
8405   (vl_api_l2_fib_table_details_t * mp)
8406 {
8407   vat_main_t *vam = &vat_main;
8408
8409   print (vam->ofp, "%3" PRIu32 "    %U    %3" PRIu32
8410          "       %d       %d     %d",
8411          ntohl (mp->bd_id), format_ethernet_address, mp->mac,
8412          ntohl (mp->sw_if_index), mp->static_mac, mp->filter_mac,
8413          mp->bvi_mac);
8414 }
8415
8416 static void vl_api_l2_fib_table_details_t_handler_json
8417   (vl_api_l2_fib_table_details_t * mp)
8418 {
8419   vat_main_t *vam = &vat_main;
8420   vat_json_node_t *node = NULL;
8421
8422   if (VAT_JSON_ARRAY != vam->json_tree.type)
8423     {
8424       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
8425       vat_json_init_array (&vam->json_tree);
8426     }
8427   node = vat_json_array_add (&vam->json_tree);
8428
8429   vat_json_init_object (node);
8430   vat_json_object_add_uint (node, "bd_id", ntohl (mp->bd_id));
8431   vat_json_object_add_bytes (node, "mac", mp->mac, 6);
8432   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
8433   vat_json_object_add_uint (node, "static_mac", mp->static_mac);
8434   vat_json_object_add_uint (node, "filter_mac", mp->filter_mac);
8435   vat_json_object_add_uint (node, "bvi_mac", mp->bvi_mac);
8436 }
8437
8438 static int
8439 api_l2_fib_table_dump (vat_main_t * vam)
8440 {
8441   unformat_input_t *i = vam->input;
8442   vl_api_l2_fib_table_dump_t *mp;
8443   vl_api_control_ping_t *mp_ping;
8444   u32 bd_id;
8445   u8 bd_id_set = 0;
8446   int ret;
8447
8448   /* Parse args required to build the message */
8449   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8450     {
8451       if (unformat (i, "bd_id %d", &bd_id))
8452         bd_id_set = 1;
8453       else
8454         break;
8455     }
8456
8457   if (bd_id_set == 0)
8458     {
8459       errmsg ("missing bridge domain");
8460       return -99;
8461     }
8462
8463   print (vam->ofp, "BD-ID     Mac Address      sw-ndx  Static  Filter  BVI");
8464
8465   /* Get list of l2 fib entries */
8466   M (L2_FIB_TABLE_DUMP, mp);
8467
8468   mp->bd_id = ntohl (bd_id);
8469   S (mp);
8470
8471   /* Use a control ping for synchronization */
8472   MPING (CONTROL_PING, mp_ping);
8473   S (mp_ping);
8474
8475   W (ret);
8476   return ret;
8477 }
8478
8479
8480 static int
8481 api_interface_name_renumber (vat_main_t * vam)
8482 {
8483   unformat_input_t *line_input = vam->input;
8484   vl_api_interface_name_renumber_t *mp;
8485   u32 sw_if_index = ~0;
8486   u32 new_show_dev_instance = ~0;
8487   int ret;
8488
8489   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
8490     {
8491       if (unformat (line_input, "%U", api_unformat_sw_if_index, vam,
8492                     &sw_if_index))
8493         ;
8494       else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
8495         ;
8496       else if (unformat (line_input, "new_show_dev_instance %d",
8497                          &new_show_dev_instance))
8498         ;
8499       else
8500         break;
8501     }
8502
8503   if (sw_if_index == ~0)
8504     {
8505       errmsg ("missing interface name or sw_if_index");
8506       return -99;
8507     }
8508
8509   if (new_show_dev_instance == ~0)
8510     {
8511       errmsg ("missing new_show_dev_instance");
8512       return -99;
8513     }
8514
8515   M (INTERFACE_NAME_RENUMBER, mp);
8516
8517   mp->sw_if_index = ntohl (sw_if_index);
8518   mp->new_show_dev_instance = ntohl (new_show_dev_instance);
8519
8520   S (mp);
8521   W (ret);
8522   return ret;
8523 }
8524
8525 static int
8526 api_want_l2_macs_events (vat_main_t * vam)
8527 {
8528   unformat_input_t *line_input = vam->input;
8529   vl_api_want_l2_macs_events_t *mp;
8530   u8 enable_disable = 1;
8531   u32 scan_delay = 0;
8532   u32 max_macs_in_event = 0;
8533   u32 learn_limit = 0;
8534   int ret;
8535
8536   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
8537     {
8538       if (unformat (line_input, "learn-limit %d", &learn_limit))
8539         ;
8540       else if (unformat (line_input, "scan-delay %d", &scan_delay))
8541         ;
8542       else if (unformat (line_input, "max-entries %d", &max_macs_in_event))
8543         ;
8544       else if (unformat (line_input, "disable"))
8545         enable_disable = 0;
8546       else
8547         break;
8548     }
8549
8550   M (WANT_L2_MACS_EVENTS, mp);
8551   mp->enable_disable = enable_disable;
8552   mp->pid = htonl (getpid ());
8553   mp->learn_limit = htonl (learn_limit);
8554   mp->scan_delay = (u8) scan_delay;
8555   mp->max_macs_in_event = (u8) (max_macs_in_event / 10);
8556   S (mp);
8557   W (ret);
8558   return ret;
8559 }
8560
8561 static int
8562 api_ip_address_dump (vat_main_t * vam)
8563 {
8564   unformat_input_t *i = vam->input;
8565   vl_api_ip_address_dump_t *mp;
8566   vl_api_control_ping_t *mp_ping;
8567   u32 sw_if_index = ~0;
8568   u8 sw_if_index_set = 0;
8569   u8 ipv4_set = 0;
8570   u8 ipv6_set = 0;
8571   int ret;
8572
8573   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8574     {
8575       if (unformat (i, "sw_if_index %d", &sw_if_index))
8576         sw_if_index_set = 1;
8577       else
8578         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8579         sw_if_index_set = 1;
8580       else if (unformat (i, "ipv4"))
8581         ipv4_set = 1;
8582       else if (unformat (i, "ipv6"))
8583         ipv6_set = 1;
8584       else
8585         break;
8586     }
8587
8588   if (ipv4_set && ipv6_set)
8589     {
8590       errmsg ("ipv4 and ipv6 flags cannot be both set");
8591       return -99;
8592     }
8593
8594   if ((!ipv4_set) && (!ipv6_set))
8595     {
8596       errmsg ("no ipv4 nor ipv6 flag set");
8597       return -99;
8598     }
8599
8600   if (sw_if_index_set == 0)
8601     {
8602       errmsg ("missing interface name or sw_if_index");
8603       return -99;
8604     }
8605
8606   vam->current_sw_if_index = sw_if_index;
8607   vam->is_ipv6 = ipv6_set;
8608
8609   M (IP_ADDRESS_DUMP, mp);
8610   mp->sw_if_index = ntohl (sw_if_index);
8611   mp->is_ipv6 = ipv6_set;
8612   S (mp);
8613
8614   /* Use a control ping for synchronization */
8615   MPING (CONTROL_PING, mp_ping);
8616   S (mp_ping);
8617
8618   W (ret);
8619   return ret;
8620 }
8621
8622 static int
8623 api_ip_dump (vat_main_t * vam)
8624 {
8625   vl_api_ip_dump_t *mp;
8626   vl_api_control_ping_t *mp_ping;
8627   unformat_input_t *in = vam->input;
8628   int ipv4_set = 0;
8629   int ipv6_set = 0;
8630   int is_ipv6;
8631   int i;
8632   int ret;
8633
8634   while (unformat_check_input (in) != UNFORMAT_END_OF_INPUT)
8635     {
8636       if (unformat (in, "ipv4"))
8637         ipv4_set = 1;
8638       else if (unformat (in, "ipv6"))
8639         ipv6_set = 1;
8640       else
8641         break;
8642     }
8643
8644   if (ipv4_set && ipv6_set)
8645     {
8646       errmsg ("ipv4 and ipv6 flags cannot be both set");
8647       return -99;
8648     }
8649
8650   if ((!ipv4_set) && (!ipv6_set))
8651     {
8652       errmsg ("no ipv4 nor ipv6 flag set");
8653       return -99;
8654     }
8655
8656   is_ipv6 = ipv6_set;
8657   vam->is_ipv6 = is_ipv6;
8658
8659   /* free old data */
8660   for (i = 0; i < vec_len (vam->ip_details_by_sw_if_index[is_ipv6]); i++)
8661     {
8662       vec_free (vam->ip_details_by_sw_if_index[is_ipv6][i].addr);
8663     }
8664   vec_free (vam->ip_details_by_sw_if_index[is_ipv6]);
8665
8666   M (IP_DUMP, mp);
8667   mp->is_ipv6 = ipv6_set;
8668   S (mp);
8669
8670   /* Use a control ping for synchronization */
8671   MPING (CONTROL_PING, mp_ping);
8672   S (mp_ping);
8673
8674   W (ret);
8675   return ret;
8676 }
8677
8678 static int
8679 api_ipsec_spd_add_del (vat_main_t * vam)
8680 {
8681   unformat_input_t *i = vam->input;
8682   vl_api_ipsec_spd_add_del_t *mp;
8683   u32 spd_id = ~0;
8684   u8 is_add = 1;
8685   int ret;
8686
8687   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8688     {
8689       if (unformat (i, "spd_id %d", &spd_id))
8690         ;
8691       else if (unformat (i, "del"))
8692         is_add = 0;
8693       else
8694         {
8695           clib_warning ("parse error '%U'", format_unformat_error, i);
8696           return -99;
8697         }
8698     }
8699   if (spd_id == ~0)
8700     {
8701       errmsg ("spd_id must be set");
8702       return -99;
8703     }
8704
8705   M (IPSEC_SPD_ADD_DEL, mp);
8706
8707   mp->spd_id = ntohl (spd_id);
8708   mp->is_add = is_add;
8709
8710   S (mp);
8711   W (ret);
8712   return ret;
8713 }
8714
8715 static int
8716 api_ipsec_interface_add_del_spd (vat_main_t * vam)
8717 {
8718   unformat_input_t *i = vam->input;
8719   vl_api_ipsec_interface_add_del_spd_t *mp;
8720   u32 sw_if_index;
8721   u8 sw_if_index_set = 0;
8722   u32 spd_id = (u32) ~ 0;
8723   u8 is_add = 1;
8724   int ret;
8725
8726   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8727     {
8728       if (unformat (i, "del"))
8729         is_add = 0;
8730       else if (unformat (i, "spd_id %d", &spd_id))
8731         ;
8732       else
8733         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8734         sw_if_index_set = 1;
8735       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8736         sw_if_index_set = 1;
8737       else
8738         {
8739           clib_warning ("parse error '%U'", format_unformat_error, i);
8740           return -99;
8741         }
8742
8743     }
8744
8745   if (spd_id == (u32) ~ 0)
8746     {
8747       errmsg ("spd_id must be set");
8748       return -99;
8749     }
8750
8751   if (sw_if_index_set == 0)
8752     {
8753       errmsg ("missing interface name or sw_if_index");
8754       return -99;
8755     }
8756
8757   M (IPSEC_INTERFACE_ADD_DEL_SPD, mp);
8758
8759   mp->spd_id = ntohl (spd_id);
8760   mp->sw_if_index = ntohl (sw_if_index);
8761   mp->is_add = is_add;
8762
8763   S (mp);
8764   W (ret);
8765   return ret;
8766 }
8767
8768 static int
8769 api_ipsec_spd_entry_add_del (vat_main_t * vam)
8770 {
8771   unformat_input_t *i = vam->input;
8772   vl_api_ipsec_spd_entry_add_del_t *mp;
8773   u8 is_add = 1, is_outbound = 0;
8774   u32 spd_id = 0, sa_id = 0, protocol = 0, policy = 0;
8775   i32 priority = 0;
8776   u32 rport_start = 0, rport_stop = (u32) ~ 0;
8777   u32 lport_start = 0, lport_stop = (u32) ~ 0;
8778   vl_api_address_t laddr_start = { }, laddr_stop =
8779   {
8780   }, raddr_start =
8781   {
8782   }, raddr_stop =
8783   {
8784   };
8785   int ret;
8786
8787   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8788     {
8789       if (unformat (i, "del"))
8790         is_add = 0;
8791       if (unformat (i, "outbound"))
8792         is_outbound = 1;
8793       if (unformat (i, "inbound"))
8794         is_outbound = 0;
8795       else if (unformat (i, "spd_id %d", &spd_id))
8796         ;
8797       else if (unformat (i, "sa_id %d", &sa_id))
8798         ;
8799       else if (unformat (i, "priority %d", &priority))
8800         ;
8801       else if (unformat (i, "protocol %d", &protocol))
8802         ;
8803       else if (unformat (i, "lport_start %d", &lport_start))
8804         ;
8805       else if (unformat (i, "lport_stop %d", &lport_stop))
8806         ;
8807       else if (unformat (i, "rport_start %d", &rport_start))
8808         ;
8809       else if (unformat (i, "rport_stop %d", &rport_stop))
8810         ;
8811       else if (unformat (i, "laddr_start %U",
8812                          unformat_vl_api_address, &laddr_start))
8813         ;
8814       else if (unformat (i, "laddr_stop %U", unformat_vl_api_address,
8815                          &laddr_stop))
8816         ;
8817       else if (unformat (i, "raddr_start %U", unformat_vl_api_address,
8818                          &raddr_start))
8819         ;
8820       else if (unformat (i, "raddr_stop %U", unformat_vl_api_address,
8821                          &raddr_stop))
8822         ;
8823       else
8824         if (unformat (i, "action %U", unformat_ipsec_policy_action, &policy))
8825         {
8826           if (policy == IPSEC_POLICY_ACTION_RESOLVE)
8827             {
8828               clib_warning ("unsupported action: 'resolve'");
8829               return -99;
8830             }
8831         }
8832       else
8833         {
8834           clib_warning ("parse error '%U'", format_unformat_error, i);
8835           return -99;
8836         }
8837
8838     }
8839
8840   M (IPSEC_SPD_ENTRY_ADD_DEL, mp);
8841
8842   mp->is_add = is_add;
8843
8844   mp->entry.spd_id = ntohl (spd_id);
8845   mp->entry.priority = ntohl (priority);
8846   mp->entry.is_outbound = is_outbound;
8847
8848   clib_memcpy (&mp->entry.remote_address_start, &raddr_start,
8849                sizeof (vl_api_address_t));
8850   clib_memcpy (&mp->entry.remote_address_stop, &raddr_stop,
8851                sizeof (vl_api_address_t));
8852   clib_memcpy (&mp->entry.local_address_start, &laddr_start,
8853                sizeof (vl_api_address_t));
8854   clib_memcpy (&mp->entry.local_address_stop, &laddr_stop,
8855                sizeof (vl_api_address_t));
8856
8857   mp->entry.protocol = (u8) protocol;
8858   mp->entry.local_port_start = ntohs ((u16) lport_start);
8859   mp->entry.local_port_stop = ntohs ((u16) lport_stop);
8860   mp->entry.remote_port_start = ntohs ((u16) rport_start);
8861   mp->entry.remote_port_stop = ntohs ((u16) rport_stop);
8862   mp->entry.policy = (u8) policy;
8863   mp->entry.sa_id = ntohl (sa_id);
8864
8865   S (mp);
8866   W (ret);
8867   return ret;
8868 }
8869
8870 static int
8871 api_ipsec_sad_entry_add_del (vat_main_t * vam)
8872 {
8873   unformat_input_t *i = vam->input;
8874   vl_api_ipsec_sad_entry_add_del_t *mp;
8875   u32 sad_id = 0, spi = 0;
8876   u8 *ck = 0, *ik = 0;
8877   u8 is_add = 1;
8878
8879   vl_api_ipsec_crypto_alg_t crypto_alg = IPSEC_API_CRYPTO_ALG_NONE;
8880   vl_api_ipsec_integ_alg_t integ_alg = IPSEC_API_INTEG_ALG_NONE;
8881   vl_api_ipsec_sad_flags_t flags = IPSEC_API_SAD_FLAG_NONE;
8882   vl_api_ipsec_proto_t protocol = IPSEC_API_PROTO_AH;
8883   vl_api_address_t tun_src, tun_dst;
8884   int ret;
8885
8886   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8887     {
8888       if (unformat (i, "del"))
8889         is_add = 0;
8890       else if (unformat (i, "sad_id %d", &sad_id))
8891         ;
8892       else if (unformat (i, "spi %d", &spi))
8893         ;
8894       else if (unformat (i, "esp"))
8895         protocol = IPSEC_API_PROTO_ESP;
8896       else
8897         if (unformat (i, "tunnel_src %U", unformat_vl_api_address, &tun_src))
8898         {
8899           flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL;
8900           if (ADDRESS_IP6 == tun_src.af)
8901             flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL_V6;
8902         }
8903       else
8904         if (unformat (i, "tunnel_dst %U", unformat_vl_api_address, &tun_dst))
8905         {
8906           flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL;
8907           if (ADDRESS_IP6 == tun_src.af)
8908             flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL_V6;
8909         }
8910       else
8911         if (unformat (i, "crypto_alg %U",
8912                       unformat_ipsec_api_crypto_alg, &crypto_alg))
8913         ;
8914       else if (unformat (i, "crypto_key %U", unformat_hex_string, &ck))
8915         ;
8916       else if (unformat (i, "integ_alg %U",
8917                          unformat_ipsec_api_integ_alg, &integ_alg))
8918         ;
8919       else if (unformat (i, "integ_key %U", unformat_hex_string, &ik))
8920         ;
8921       else
8922         {
8923           clib_warning ("parse error '%U'", format_unformat_error, i);
8924           return -99;
8925         }
8926
8927     }
8928
8929   M (IPSEC_SAD_ENTRY_ADD_DEL, mp);
8930
8931   mp->is_add = is_add;
8932   mp->entry.sad_id = ntohl (sad_id);
8933   mp->entry.protocol = protocol;
8934   mp->entry.spi = ntohl (spi);
8935   mp->entry.flags = flags;
8936
8937   mp->entry.crypto_algorithm = crypto_alg;
8938   mp->entry.integrity_algorithm = integ_alg;
8939   mp->entry.crypto_key.length = vec_len (ck);
8940   mp->entry.integrity_key.length = vec_len (ik);
8941
8942   if (mp->entry.crypto_key.length > sizeof (mp->entry.crypto_key.data))
8943     mp->entry.crypto_key.length = sizeof (mp->entry.crypto_key.data);
8944
8945   if (mp->entry.integrity_key.length > sizeof (mp->entry.integrity_key.data))
8946     mp->entry.integrity_key.length = sizeof (mp->entry.integrity_key.data);
8947
8948   if (ck)
8949     clib_memcpy (mp->entry.crypto_key.data, ck, mp->entry.crypto_key.length);
8950   if (ik)
8951     clib_memcpy (mp->entry.integrity_key.data, ik,
8952                  mp->entry.integrity_key.length);
8953
8954   if (flags & IPSEC_API_SAD_FLAG_IS_TUNNEL)
8955     {
8956       clib_memcpy (&mp->entry.tunnel_src, &tun_src,
8957                    sizeof (mp->entry.tunnel_src));
8958       clib_memcpy (&mp->entry.tunnel_dst, &tun_dst,
8959                    sizeof (mp->entry.tunnel_dst));
8960     }
8961
8962   S (mp);
8963   W (ret);
8964   return ret;
8965 }
8966
8967 static void
8968 vl_api_ipsec_sa_details_t_handler (vl_api_ipsec_sa_details_t * mp)
8969 {
8970   vat_main_t *vam = &vat_main;
8971
8972   print (vam->ofp, "sa_id %u sw_if_index %u spi %u proto %u crypto_alg %u "
8973          "crypto_key %U integ_alg %u integ_key %U flags %x "
8974          "tunnel_src_addr %U tunnel_dst_addr %U "
8975          "salt %u seq_outbound %lu last_seq_inbound %lu "
8976          "replay_window %lu stat_index %u\n",
8977          ntohl (mp->entry.sad_id),
8978          ntohl (mp->sw_if_index),
8979          ntohl (mp->entry.spi),
8980          ntohl (mp->entry.protocol),
8981          ntohl (mp->entry.crypto_algorithm),
8982          format_hex_bytes, mp->entry.crypto_key.data,
8983          mp->entry.crypto_key.length, ntohl (mp->entry.integrity_algorithm),
8984          format_hex_bytes, mp->entry.integrity_key.data,
8985          mp->entry.integrity_key.length, ntohl (mp->entry.flags),
8986          format_vl_api_address, &mp->entry.tunnel_src, format_vl_api_address,
8987          &mp->entry.tunnel_dst, ntohl (mp->salt),
8988          clib_net_to_host_u64 (mp->seq_outbound),
8989          clib_net_to_host_u64 (mp->last_seq_inbound),
8990          clib_net_to_host_u64 (mp->replay_window), ntohl (mp->stat_index));
8991 }
8992
8993 #define vl_api_ipsec_sa_details_t_endian vl_noop_handler
8994 #define vl_api_ipsec_sa_details_t_print vl_noop_handler
8995
8996 static void vl_api_ipsec_sa_details_t_handler_json
8997   (vl_api_ipsec_sa_details_t * mp)
8998 {
8999   vat_main_t *vam = &vat_main;
9000   vat_json_node_t *node = NULL;
9001   vl_api_ipsec_sad_flags_t flags;
9002
9003   if (VAT_JSON_ARRAY != vam->json_tree.type)
9004     {
9005       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9006       vat_json_init_array (&vam->json_tree);
9007     }
9008   node = vat_json_array_add (&vam->json_tree);
9009
9010   vat_json_init_object (node);
9011   vat_json_object_add_uint (node, "sa_id", ntohl (mp->entry.sad_id));
9012   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
9013   vat_json_object_add_uint (node, "spi", ntohl (mp->entry.spi));
9014   vat_json_object_add_uint (node, "proto", ntohl (mp->entry.protocol));
9015   vat_json_object_add_uint (node, "crypto_alg",
9016                             ntohl (mp->entry.crypto_algorithm));
9017   vat_json_object_add_uint (node, "integ_alg",
9018                             ntohl (mp->entry.integrity_algorithm));
9019   flags = ntohl (mp->entry.flags);
9020   vat_json_object_add_uint (node, "use_esn",
9021                             ! !(flags & IPSEC_API_SAD_FLAG_USE_ESN));
9022   vat_json_object_add_uint (node, "use_anti_replay",
9023                             ! !(flags & IPSEC_API_SAD_FLAG_USE_ANTI_REPLAY));
9024   vat_json_object_add_uint (node, "is_tunnel",
9025                             ! !(flags & IPSEC_API_SAD_FLAG_IS_TUNNEL));
9026   vat_json_object_add_uint (node, "is_tunnel_ip6",
9027                             ! !(flags & IPSEC_API_SAD_FLAG_IS_TUNNEL_V6));
9028   vat_json_object_add_uint (node, "udp_encap",
9029                             ! !(flags & IPSEC_API_SAD_FLAG_UDP_ENCAP));
9030   vat_json_object_add_bytes (node, "crypto_key", mp->entry.crypto_key.data,
9031                              mp->entry.crypto_key.length);
9032   vat_json_object_add_bytes (node, "integ_key", mp->entry.integrity_key.data,
9033                              mp->entry.integrity_key.length);
9034   vat_json_object_add_address (node, "src", &mp->entry.tunnel_src);
9035   vat_json_object_add_address (node, "dst", &mp->entry.tunnel_dst);
9036   vat_json_object_add_uint (node, "replay_window",
9037                             clib_net_to_host_u64 (mp->replay_window));
9038   vat_json_object_add_uint (node, "stat_index", ntohl (mp->stat_index));
9039 }
9040
9041 static int
9042 api_ipsec_sa_dump (vat_main_t * vam)
9043 {
9044   unformat_input_t *i = vam->input;
9045   vl_api_ipsec_sa_dump_t *mp;
9046   vl_api_control_ping_t *mp_ping;
9047   u32 sa_id = ~0;
9048   int ret;
9049
9050   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9051     {
9052       if (unformat (i, "sa_id %d", &sa_id))
9053         ;
9054       else
9055         {
9056           clib_warning ("parse error '%U'", format_unformat_error, i);
9057           return -99;
9058         }
9059     }
9060
9061   M (IPSEC_SA_DUMP, mp);
9062
9063   mp->sa_id = ntohl (sa_id);
9064
9065   S (mp);
9066
9067   /* Use a control ping for synchronization */
9068   M (CONTROL_PING, mp_ping);
9069   S (mp_ping);
9070
9071   W (ret);
9072   return ret;
9073 }
9074
9075 static int
9076 api_get_first_msg_id (vat_main_t * vam)
9077 {
9078   vl_api_get_first_msg_id_t *mp;
9079   unformat_input_t *i = vam->input;
9080   u8 *name;
9081   u8 name_set = 0;
9082   int ret;
9083
9084   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9085     {
9086       if (unformat (i, "client %s", &name))
9087         name_set = 1;
9088       else
9089         break;
9090     }
9091
9092   if (name_set == 0)
9093     {
9094       errmsg ("missing client name");
9095       return -99;
9096     }
9097   vec_add1 (name, 0);
9098
9099   if (vec_len (name) > 63)
9100     {
9101       errmsg ("client name too long");
9102       return -99;
9103     }
9104
9105   M (GET_FIRST_MSG_ID, mp);
9106   clib_memcpy (mp->name, name, vec_len (name));
9107   S (mp);
9108   W (ret);
9109   return ret;
9110 }
9111
9112 static int
9113 api_get_node_graph (vat_main_t * vam)
9114 {
9115   vl_api_get_node_graph_t *mp;
9116   int ret;
9117
9118   M (GET_NODE_GRAPH, mp);
9119
9120   /* send it... */
9121   S (mp);
9122   /* Wait for the reply */
9123   W (ret);
9124   return ret;
9125 }
9126
9127 static int
9128 api_af_packet_create (vat_main_t * vam)
9129 {
9130   unformat_input_t *i = vam->input;
9131   vl_api_af_packet_create_t *mp;
9132   u8 *host_if_name = 0;
9133   u8 hw_addr[6];
9134   u8 random_hw_addr = 1;
9135   int ret;
9136
9137   clib_memset (hw_addr, 0, sizeof (hw_addr));
9138
9139   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9140     {
9141       if (unformat (i, "name %s", &host_if_name))
9142         vec_add1 (host_if_name, 0);
9143       else if (unformat (i, "hw_addr %U", unformat_ethernet_address, hw_addr))
9144         random_hw_addr = 0;
9145       else
9146         break;
9147     }
9148
9149   if (!vec_len (host_if_name))
9150     {
9151       errmsg ("host-interface name must be specified");
9152       return -99;
9153     }
9154
9155   if (vec_len (host_if_name) > 64)
9156     {
9157       errmsg ("host-interface name too long");
9158       return -99;
9159     }
9160
9161   M (AF_PACKET_CREATE, mp);
9162
9163   clib_memcpy (mp->host_if_name, host_if_name, vec_len (host_if_name));
9164   clib_memcpy (mp->hw_addr, hw_addr, 6);
9165   mp->use_random_hw_addr = random_hw_addr;
9166   vec_free (host_if_name);
9167
9168   S (mp);
9169
9170   /* *INDENT-OFF* */
9171   W2 (ret,
9172       ({
9173         if (ret == 0)
9174           fprintf (vam->ofp ? vam->ofp : stderr,
9175                    " new sw_if_index = %d\n", vam->sw_if_index);
9176       }));
9177   /* *INDENT-ON* */
9178   return ret;
9179 }
9180
9181 static int
9182 api_af_packet_delete (vat_main_t * vam)
9183 {
9184   unformat_input_t *i = vam->input;
9185   vl_api_af_packet_delete_t *mp;
9186   u8 *host_if_name = 0;
9187   int ret;
9188
9189   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9190     {
9191       if (unformat (i, "name %s", &host_if_name))
9192         vec_add1 (host_if_name, 0);
9193       else
9194         break;
9195     }
9196
9197   if (!vec_len (host_if_name))
9198     {
9199       errmsg ("host-interface name must be specified");
9200       return -99;
9201     }
9202
9203   if (vec_len (host_if_name) > 64)
9204     {
9205       errmsg ("host-interface name too long");
9206       return -99;
9207     }
9208
9209   M (AF_PACKET_DELETE, mp);
9210
9211   clib_memcpy (mp->host_if_name, host_if_name, vec_len (host_if_name));
9212   vec_free (host_if_name);
9213
9214   S (mp);
9215   W (ret);
9216   return ret;
9217 }
9218
9219 static void vl_api_af_packet_details_t_handler
9220   (vl_api_af_packet_details_t * mp)
9221 {
9222   vat_main_t *vam = &vat_main;
9223
9224   print (vam->ofp, "%-16s %d",
9225          mp->host_if_name, clib_net_to_host_u32 (mp->sw_if_index));
9226 }
9227
9228 static void vl_api_af_packet_details_t_handler_json
9229   (vl_api_af_packet_details_t * mp)
9230 {
9231   vat_main_t *vam = &vat_main;
9232   vat_json_node_t *node = NULL;
9233
9234   if (VAT_JSON_ARRAY != vam->json_tree.type)
9235     {
9236       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9237       vat_json_init_array (&vam->json_tree);
9238     }
9239   node = vat_json_array_add (&vam->json_tree);
9240
9241   vat_json_init_object (node);
9242   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
9243   vat_json_object_add_string_copy (node, "dev_name", mp->host_if_name);
9244 }
9245
9246 static int
9247 api_af_packet_dump (vat_main_t * vam)
9248 {
9249   vl_api_af_packet_dump_t *mp;
9250   vl_api_control_ping_t *mp_ping;
9251   int ret;
9252
9253   print (vam->ofp, "\n%-16s %s", "dev_name", "sw_if_index");
9254   /* Get list of tap interfaces */
9255   M (AF_PACKET_DUMP, mp);
9256   S (mp);
9257
9258   /* Use a control ping for synchronization */
9259   MPING (CONTROL_PING, mp_ping);
9260   S (mp_ping);
9261
9262   W (ret);
9263   return ret;
9264 }
9265
9266 static u8 *
9267 format_fib_api_path_nh_proto (u8 * s, va_list * args)
9268 {
9269   vl_api_fib_path_nh_proto_t proto =
9270     va_arg (*args, vl_api_fib_path_nh_proto_t);
9271
9272   switch (proto)
9273     {
9274     case FIB_API_PATH_NH_PROTO_IP4:
9275       s = format (s, "ip4");
9276       break;
9277     case FIB_API_PATH_NH_PROTO_IP6:
9278       s = format (s, "ip6");
9279       break;
9280     case FIB_API_PATH_NH_PROTO_MPLS:
9281       s = format (s, "mpls");
9282       break;
9283     case FIB_API_PATH_NH_PROTO_BIER:
9284       s = format (s, "bier");
9285       break;
9286     case FIB_API_PATH_NH_PROTO_ETHERNET:
9287       s = format (s, "ethernet");
9288       break;
9289     }
9290
9291   return (s);
9292 }
9293
9294 static u8 *
9295 format_vl_api_ip_address_union (u8 * s, va_list * args)
9296 {
9297   vl_api_address_family_t af = va_arg (*args, int);
9298   const vl_api_address_union_t *u = va_arg (*args, vl_api_address_union_t *);
9299
9300   switch (af)
9301     {
9302     case ADDRESS_IP4:
9303       s = format (s, "%U", format_ip4_address, u->ip4);
9304       break;
9305     case ADDRESS_IP6:
9306       s = format (s, "%U", format_ip6_address, u->ip6);
9307       break;
9308     }
9309   return (s);
9310 }
9311
9312 static u8 *
9313 format_vl_api_fib_path_type (u8 * s, va_list * args)
9314 {
9315   vl_api_fib_path_type_t t = va_arg (*args, vl_api_fib_path_type_t);
9316
9317   switch (t)
9318     {
9319     case FIB_API_PATH_TYPE_NORMAL:
9320       s = format (s, "normal");
9321       break;
9322     case FIB_API_PATH_TYPE_LOCAL:
9323       s = format (s, "local");
9324       break;
9325     case FIB_API_PATH_TYPE_DROP:
9326       s = format (s, "drop");
9327       break;
9328     case FIB_API_PATH_TYPE_UDP_ENCAP:
9329       s = format (s, "udp-encap");
9330       break;
9331     case FIB_API_PATH_TYPE_BIER_IMP:
9332       s = format (s, "bier-imp");
9333       break;
9334     case FIB_API_PATH_TYPE_ICMP_UNREACH:
9335       s = format (s, "unreach");
9336       break;
9337     case FIB_API_PATH_TYPE_ICMP_PROHIBIT:
9338       s = format (s, "prohibit");
9339       break;
9340     case FIB_API_PATH_TYPE_SOURCE_LOOKUP:
9341       s = format (s, "src-lookup");
9342       break;
9343     case FIB_API_PATH_TYPE_DVR:
9344       s = format (s, "dvr");
9345       break;
9346     case FIB_API_PATH_TYPE_INTERFACE_RX:
9347       s = format (s, "interface-rx");
9348       break;
9349     case FIB_API_PATH_TYPE_CLASSIFY:
9350       s = format (s, "classify");
9351       break;
9352     }
9353
9354   return (s);
9355 }
9356
9357 static void
9358 vl_api_fib_path_print (vat_main_t * vam, vl_api_fib_path_t * fp)
9359 {
9360   print (vam->ofp,
9361          "  weight %d, sw_if_index %d, type %U, afi %U, next_hop %U",
9362          ntohl (fp->weight), ntohl (fp->sw_if_index),
9363          format_vl_api_fib_path_type, fp->type,
9364          format_fib_api_path_nh_proto, fp->proto,
9365          format_vl_api_ip_address_union, &fp->nh.address);
9366 }
9367
9368 static void
9369 vl_api_mpls_fib_path_json_print (vat_json_node_t * node,
9370                                  vl_api_fib_path_t * fp)
9371 {
9372   struct in_addr ip4;
9373   struct in6_addr ip6;
9374
9375   vat_json_object_add_uint (node, "weight", ntohl (fp->weight));
9376   vat_json_object_add_uint (node, "sw_if_index", ntohl (fp->sw_if_index));
9377   vat_json_object_add_uint (node, "type", fp->type);
9378   vat_json_object_add_uint (node, "next_hop_proto", fp->proto);
9379   if (fp->proto == FIB_API_PATH_NH_PROTO_IP4)
9380     {
9381       clib_memcpy (&ip4, &fp->nh.address.ip4, sizeof (ip4));
9382       vat_json_object_add_ip4 (node, "next_hop", ip4);
9383     }
9384   else if (fp->proto == FIB_API_PATH_NH_PROTO_IP6)
9385     {
9386       clib_memcpy (&ip6, &fp->nh.address.ip6, sizeof (ip6));
9387       vat_json_object_add_ip6 (node, "next_hop", ip6);
9388     }
9389 }
9390
9391 static void
9392 vl_api_mpls_tunnel_details_t_handler (vl_api_mpls_tunnel_details_t * mp)
9393 {
9394   vat_main_t *vam = &vat_main;
9395   int count = ntohl (mp->mt_tunnel.mt_n_paths);
9396   vl_api_fib_path_t *fp;
9397   i32 i;
9398
9399   print (vam->ofp, "sw_if_index %d via:",
9400          ntohl (mp->mt_tunnel.mt_sw_if_index));
9401   fp = mp->mt_tunnel.mt_paths;
9402   for (i = 0; i < count; i++)
9403     {
9404       vl_api_fib_path_print (vam, fp);
9405       fp++;
9406     }
9407
9408   print (vam->ofp, "");
9409 }
9410
9411 #define vl_api_mpls_tunnel_details_t_endian vl_noop_handler
9412 #define vl_api_mpls_tunnel_details_t_print vl_noop_handler
9413
9414 static void
9415 vl_api_mpls_tunnel_details_t_handler_json (vl_api_mpls_tunnel_details_t * mp)
9416 {
9417   vat_main_t *vam = &vat_main;
9418   vat_json_node_t *node = NULL;
9419   int count = ntohl (mp->mt_tunnel.mt_n_paths);
9420   vl_api_fib_path_t *fp;
9421   i32 i;
9422
9423   if (VAT_JSON_ARRAY != vam->json_tree.type)
9424     {
9425       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9426       vat_json_init_array (&vam->json_tree);
9427     }
9428   node = vat_json_array_add (&vam->json_tree);
9429
9430   vat_json_init_object (node);
9431   vat_json_object_add_uint (node, "sw_if_index",
9432                             ntohl (mp->mt_tunnel.mt_sw_if_index));
9433
9434   vat_json_object_add_uint (node, "l2_only", mp->mt_tunnel.mt_l2_only);
9435
9436   fp = mp->mt_tunnel.mt_paths;
9437   for (i = 0; i < count; i++)
9438     {
9439       vl_api_mpls_fib_path_json_print (node, fp);
9440       fp++;
9441     }
9442 }
9443
9444 static int
9445 api_mpls_tunnel_dump (vat_main_t * vam)
9446 {
9447   vl_api_mpls_tunnel_dump_t *mp;
9448   vl_api_control_ping_t *mp_ping;
9449   int ret;
9450
9451   M (MPLS_TUNNEL_DUMP, mp);
9452
9453   S (mp);
9454
9455   /* Use a control ping for synchronization */
9456   MPING (CONTROL_PING, mp_ping);
9457   S (mp_ping);
9458
9459   W (ret);
9460   return ret;
9461 }
9462
9463 #define vl_api_mpls_table_details_t_endian vl_noop_handler
9464 #define vl_api_mpls_table_details_t_print vl_noop_handler
9465
9466
9467 static void
9468 vl_api_mpls_table_details_t_handler (vl_api_mpls_table_details_t * mp)
9469 {
9470   vat_main_t *vam = &vat_main;
9471
9472   print (vam->ofp, "table-id %d,", ntohl (mp->mt_table.mt_table_id));
9473 }
9474
9475 static void vl_api_mpls_table_details_t_handler_json
9476   (vl_api_mpls_table_details_t * mp)
9477 {
9478   vat_main_t *vam = &vat_main;
9479   vat_json_node_t *node = NULL;
9480
9481   if (VAT_JSON_ARRAY != vam->json_tree.type)
9482     {
9483       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9484       vat_json_init_array (&vam->json_tree);
9485     }
9486   node = vat_json_array_add (&vam->json_tree);
9487
9488   vat_json_init_object (node);
9489   vat_json_object_add_uint (node, "table", ntohl (mp->mt_table.mt_table_id));
9490 }
9491
9492 static int
9493 api_mpls_table_dump (vat_main_t * vam)
9494 {
9495   vl_api_mpls_table_dump_t *mp;
9496   vl_api_control_ping_t *mp_ping;
9497   int ret;
9498
9499   M (MPLS_TABLE_DUMP, mp);
9500   S (mp);
9501
9502   /* Use a control ping for synchronization */
9503   MPING (CONTROL_PING, mp_ping);
9504   S (mp_ping);
9505
9506   W (ret);
9507   return ret;
9508 }
9509
9510 #define vl_api_mpls_route_details_t_endian vl_noop_handler
9511 #define vl_api_mpls_route_details_t_print vl_noop_handler
9512
9513 static void
9514 vl_api_mpls_route_details_t_handler (vl_api_mpls_route_details_t * mp)
9515 {
9516   vat_main_t *vam = &vat_main;
9517   int count = (int) clib_net_to_host_u32 (mp->mr_route.mr_n_paths);
9518   vl_api_fib_path_t *fp;
9519   int i;
9520
9521   print (vam->ofp,
9522          "table-id %d, label %u, ess_bit %u",
9523          ntohl (mp->mr_route.mr_table_id),
9524          ntohl (mp->mr_route.mr_label), mp->mr_route.mr_eos);
9525   fp = mp->mr_route.mr_paths;
9526   for (i = 0; i < count; i++)
9527     {
9528       vl_api_fib_path_print (vam, fp);
9529       fp++;
9530     }
9531 }
9532
9533 static void vl_api_mpls_route_details_t_handler_json
9534   (vl_api_mpls_route_details_t * mp)
9535 {
9536   vat_main_t *vam = &vat_main;
9537   int count = (int) clib_host_to_net_u32 (mp->mr_route.mr_n_paths);
9538   vat_json_node_t *node = NULL;
9539   vl_api_fib_path_t *fp;
9540   int i;
9541
9542   if (VAT_JSON_ARRAY != vam->json_tree.type)
9543     {
9544       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9545       vat_json_init_array (&vam->json_tree);
9546     }
9547   node = vat_json_array_add (&vam->json_tree);
9548
9549   vat_json_init_object (node);
9550   vat_json_object_add_uint (node, "table", ntohl (mp->mr_route.mr_table_id));
9551   vat_json_object_add_uint (node, "s_bit", mp->mr_route.mr_eos);
9552   vat_json_object_add_uint (node, "label", ntohl (mp->mr_route.mr_label));
9553   vat_json_object_add_uint (node, "path_count", count);
9554   fp = mp->mr_route.mr_paths;
9555   for (i = 0; i < count; i++)
9556     {
9557       vl_api_mpls_fib_path_json_print (node, fp);
9558       fp++;
9559     }
9560 }
9561
9562 static int
9563 api_mpls_route_dump (vat_main_t * vam)
9564 {
9565   unformat_input_t *input = vam->input;
9566   vl_api_mpls_route_dump_t *mp;
9567   vl_api_control_ping_t *mp_ping;
9568   u32 table_id;
9569   int ret;
9570
9571   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
9572     {
9573       if (unformat (input, "table_id %d", &table_id))
9574         ;
9575       else
9576         break;
9577     }
9578   if (table_id == ~0)
9579     {
9580       errmsg ("missing table id");
9581       return -99;
9582     }
9583
9584   M (MPLS_ROUTE_DUMP, mp);
9585
9586   mp->table.mt_table_id = ntohl (table_id);
9587   S (mp);
9588
9589   /* Use a control ping for synchronization */
9590   MPING (CONTROL_PING, mp_ping);
9591   S (mp_ping);
9592
9593   W (ret);
9594   return ret;
9595 }
9596
9597 #define vl_api_ip_table_details_t_endian vl_noop_handler
9598 #define vl_api_ip_table_details_t_print vl_noop_handler
9599
9600 static void
9601 vl_api_ip_table_details_t_handler (vl_api_ip_table_details_t * mp)
9602 {
9603   vat_main_t *vam = &vat_main;
9604
9605   print (vam->ofp,
9606          "%s; table-id %d, prefix %U/%d",
9607          mp->table.name, ntohl (mp->table.table_id));
9608 }
9609
9610
9611 static void vl_api_ip_table_details_t_handler_json
9612   (vl_api_ip_table_details_t * mp)
9613 {
9614   vat_main_t *vam = &vat_main;
9615   vat_json_node_t *node = NULL;
9616
9617   if (VAT_JSON_ARRAY != vam->json_tree.type)
9618     {
9619       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9620       vat_json_init_array (&vam->json_tree);
9621     }
9622   node = vat_json_array_add (&vam->json_tree);
9623
9624   vat_json_init_object (node);
9625   vat_json_object_add_uint (node, "table", ntohl (mp->table.table_id));
9626 }
9627
9628 static int
9629 api_ip_table_dump (vat_main_t * vam)
9630 {
9631   vl_api_ip_table_dump_t *mp;
9632   vl_api_control_ping_t *mp_ping;
9633   int ret;
9634
9635   M (IP_TABLE_DUMP, mp);
9636   S (mp);
9637
9638   /* Use a control ping for synchronization */
9639   MPING (CONTROL_PING, mp_ping);
9640   S (mp_ping);
9641
9642   W (ret);
9643   return ret;
9644 }
9645
9646 static int
9647 api_ip_mtable_dump (vat_main_t * vam)
9648 {
9649   vl_api_ip_mtable_dump_t *mp;
9650   vl_api_control_ping_t *mp_ping;
9651   int ret;
9652
9653   M (IP_MTABLE_DUMP, mp);
9654   S (mp);
9655
9656   /* Use a control ping for synchronization */
9657   MPING (CONTROL_PING, mp_ping);
9658   S (mp_ping);
9659
9660   W (ret);
9661   return ret;
9662 }
9663
9664 static int
9665 api_ip_mroute_dump (vat_main_t * vam)
9666 {
9667   unformat_input_t *input = vam->input;
9668   vl_api_control_ping_t *mp_ping;
9669   vl_api_ip_mroute_dump_t *mp;
9670   int ret, is_ip6;
9671   u32 table_id;
9672
9673   is_ip6 = 0;
9674   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
9675     {
9676       if (unformat (input, "table_id %d", &table_id))
9677         ;
9678       else if (unformat (input, "ip6"))
9679         is_ip6 = 1;
9680       else if (unformat (input, "ip4"))
9681         is_ip6 = 0;
9682       else
9683         break;
9684     }
9685   if (table_id == ~0)
9686     {
9687       errmsg ("missing table id");
9688       return -99;
9689     }
9690
9691   M (IP_MROUTE_DUMP, mp);
9692   mp->table.table_id = table_id;
9693   mp->table.is_ip6 = is_ip6;
9694   S (mp);
9695
9696   /* Use a control ping for synchronization */
9697   MPING (CONTROL_PING, mp_ping);
9698   S (mp_ping);
9699
9700   W (ret);
9701   return ret;
9702 }
9703
9704 #define vl_api_ip_route_details_t_endian vl_noop_handler
9705 #define vl_api_ip_route_details_t_print vl_noop_handler
9706
9707 static void
9708 vl_api_ip_route_details_t_handler (vl_api_ip_route_details_t * mp)
9709 {
9710   vat_main_t *vam = &vat_main;
9711   u8 count = mp->route.n_paths;
9712   vl_api_fib_path_t *fp;
9713   int i;
9714
9715   print (vam->ofp,
9716          "table-id %d, prefix %U/%d",
9717          ntohl (mp->route.table_id),
9718          format_ip46_address, mp->route.prefix.address, mp->route.prefix.len);
9719   for (i = 0; i < count; i++)
9720     {
9721       fp = &mp->route.paths[i];
9722
9723       vl_api_fib_path_print (vam, fp);
9724       fp++;
9725     }
9726 }
9727
9728 static void vl_api_ip_route_details_t_handler_json
9729   (vl_api_ip_route_details_t * mp)
9730 {
9731   vat_main_t *vam = &vat_main;
9732   u8 count = mp->route.n_paths;
9733   vat_json_node_t *node = NULL;
9734   struct in_addr ip4;
9735   struct in6_addr ip6;
9736   vl_api_fib_path_t *fp;
9737   int i;
9738
9739   if (VAT_JSON_ARRAY != vam->json_tree.type)
9740     {
9741       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9742       vat_json_init_array (&vam->json_tree);
9743     }
9744   node = vat_json_array_add (&vam->json_tree);
9745
9746   vat_json_init_object (node);
9747   vat_json_object_add_uint (node, "table", ntohl (mp->route.table_id));
9748   if (ADDRESS_IP6 == mp->route.prefix.address.af)
9749     {
9750       clib_memcpy (&ip6, &mp->route.prefix.address.un.ip6, sizeof (ip6));
9751       vat_json_object_add_ip6 (node, "prefix", ip6);
9752     }
9753   else
9754     {
9755       clib_memcpy (&ip4, &mp->route.prefix.address.un.ip4, sizeof (ip4));
9756       vat_json_object_add_ip4 (node, "prefix", ip4);
9757     }
9758   vat_json_object_add_uint (node, "mask_length", mp->route.prefix.len);
9759   vat_json_object_add_uint (node, "path_count", count);
9760   for (i = 0; i < count; i++)
9761     {
9762       fp = &mp->route.paths[i];
9763       vl_api_mpls_fib_path_json_print (node, fp);
9764     }
9765 }
9766
9767 static int
9768 api_ip_route_dump (vat_main_t * vam)
9769 {
9770   unformat_input_t *input = vam->input;
9771   vl_api_ip_route_dump_t *mp;
9772   vl_api_control_ping_t *mp_ping;
9773   u32 table_id;
9774   u8 is_ip6;
9775   int ret;
9776
9777   is_ip6 = 0;
9778   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
9779     {
9780       if (unformat (input, "table_id %d", &table_id))
9781         ;
9782       else if (unformat (input, "ip6"))
9783         is_ip6 = 1;
9784       else if (unformat (input, "ip4"))
9785         is_ip6 = 0;
9786       else
9787         break;
9788     }
9789   if (table_id == ~0)
9790     {
9791       errmsg ("missing table id");
9792       return -99;
9793     }
9794
9795   M (IP_ROUTE_DUMP, mp);
9796
9797   mp->table.table_id = table_id;
9798   mp->table.is_ip6 = is_ip6;
9799
9800   S (mp);
9801
9802   /* Use a control ping for synchronization */
9803   MPING (CONTROL_PING, mp_ping);
9804   S (mp_ping);
9805
9806   W (ret);
9807   return ret;
9808 }
9809
9810 static int
9811 api_sw_interface_span_enable_disable (vat_main_t * vam)
9812 {
9813   unformat_input_t *i = vam->input;
9814   vl_api_sw_interface_span_enable_disable_t *mp;
9815   u32 src_sw_if_index = ~0;
9816   u32 dst_sw_if_index = ~0;
9817   u8 state = 3;
9818   int ret;
9819   u8 is_l2 = 0;
9820
9821   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9822     {
9823       if (unformat
9824           (i, "src %U", api_unformat_sw_if_index, vam, &src_sw_if_index))
9825         ;
9826       else if (unformat (i, "src_sw_if_index %d", &src_sw_if_index))
9827         ;
9828       else
9829         if (unformat
9830             (i, "dst %U", api_unformat_sw_if_index, vam, &dst_sw_if_index))
9831         ;
9832       else if (unformat (i, "dst_sw_if_index %d", &dst_sw_if_index))
9833         ;
9834       else if (unformat (i, "disable"))
9835         state = 0;
9836       else if (unformat (i, "rx"))
9837         state = 1;
9838       else if (unformat (i, "tx"))
9839         state = 2;
9840       else if (unformat (i, "both"))
9841         state = 3;
9842       else if (unformat (i, "l2"))
9843         is_l2 = 1;
9844       else
9845         break;
9846     }
9847
9848   M (SW_INTERFACE_SPAN_ENABLE_DISABLE, mp);
9849
9850   mp->sw_if_index_from = htonl (src_sw_if_index);
9851   mp->sw_if_index_to = htonl (dst_sw_if_index);
9852   mp->state = state;
9853   mp->is_l2 = is_l2;
9854
9855   S (mp);
9856   W (ret);
9857   return ret;
9858 }
9859
9860 static void
9861 vl_api_sw_interface_span_details_t_handler (vl_api_sw_interface_span_details_t
9862                                             * mp)
9863 {
9864   vat_main_t *vam = &vat_main;
9865   u8 *sw_if_from_name = 0;
9866   u8 *sw_if_to_name = 0;
9867   u32 sw_if_index_from = ntohl (mp->sw_if_index_from);
9868   u32 sw_if_index_to = ntohl (mp->sw_if_index_to);
9869   char *states[] = { "none", "rx", "tx", "both" };
9870   hash_pair_t *p;
9871
9872   /* *INDENT-OFF* */
9873   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
9874   ({
9875     if ((u32) p->value[0] == sw_if_index_from)
9876       {
9877         sw_if_from_name = (u8 *)(p->key);
9878         if (sw_if_to_name)
9879           break;
9880       }
9881     if ((u32) p->value[0] == sw_if_index_to)
9882       {
9883         sw_if_to_name = (u8 *)(p->key);
9884         if (sw_if_from_name)
9885           break;
9886       }
9887   }));
9888   /* *INDENT-ON* */
9889   print (vam->ofp, "%20s => %20s (%s) %s",
9890          sw_if_from_name, sw_if_to_name, states[mp->state],
9891          mp->is_l2 ? "l2" : "device");
9892 }
9893
9894 static void
9895   vl_api_sw_interface_span_details_t_handler_json
9896   (vl_api_sw_interface_span_details_t * mp)
9897 {
9898   vat_main_t *vam = &vat_main;
9899   vat_json_node_t *node = NULL;
9900   u8 *sw_if_from_name = 0;
9901   u8 *sw_if_to_name = 0;
9902   u32 sw_if_index_from = ntohl (mp->sw_if_index_from);
9903   u32 sw_if_index_to = ntohl (mp->sw_if_index_to);
9904   hash_pair_t *p;
9905
9906   /* *INDENT-OFF* */
9907   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
9908   ({
9909     if ((u32) p->value[0] == sw_if_index_from)
9910       {
9911         sw_if_from_name = (u8 *)(p->key);
9912         if (sw_if_to_name)
9913           break;
9914       }
9915     if ((u32) p->value[0] == sw_if_index_to)
9916       {
9917         sw_if_to_name = (u8 *)(p->key);
9918         if (sw_if_from_name)
9919           break;
9920       }
9921   }));
9922   /* *INDENT-ON* */
9923
9924   if (VAT_JSON_ARRAY != vam->json_tree.type)
9925     {
9926       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9927       vat_json_init_array (&vam->json_tree);
9928     }
9929   node = vat_json_array_add (&vam->json_tree);
9930
9931   vat_json_init_object (node);
9932   vat_json_object_add_uint (node, "src-if-index", sw_if_index_from);
9933   vat_json_object_add_string_copy (node, "src-if-name", sw_if_from_name);
9934   vat_json_object_add_uint (node, "dst-if-index", sw_if_index_to);
9935   if (0 != sw_if_to_name)
9936     {
9937       vat_json_object_add_string_copy (node, "dst-if-name", sw_if_to_name);
9938     }
9939   vat_json_object_add_uint (node, "state", mp->state);
9940   vat_json_object_add_uint (node, "is-l2", mp->is_l2);
9941 }
9942
9943 static int
9944 api_sw_interface_span_dump (vat_main_t * vam)
9945 {
9946   unformat_input_t *input = vam->input;
9947   vl_api_sw_interface_span_dump_t *mp;
9948   vl_api_control_ping_t *mp_ping;
9949   u8 is_l2 = 0;
9950   int ret;
9951
9952   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
9953     {
9954       if (unformat (input, "l2"))
9955         is_l2 = 1;
9956       else
9957         break;
9958     }
9959
9960   M (SW_INTERFACE_SPAN_DUMP, mp);
9961   mp->is_l2 = is_l2;
9962   S (mp);
9963
9964   /* Use a control ping for synchronization */
9965   MPING (CONTROL_PING, mp_ping);
9966   S (mp_ping);
9967
9968   W (ret);
9969   return ret;
9970 }
9971
9972 int
9973 api_ip_source_and_port_range_check_add_del (vat_main_t * vam)
9974 {
9975   unformat_input_t *input = vam->input;
9976   vl_api_ip_source_and_port_range_check_add_del_t *mp;
9977
9978   u16 *low_ports = 0;
9979   u16 *high_ports = 0;
9980   u16 this_low;
9981   u16 this_hi;
9982   vl_api_prefix_t prefix;
9983   u32 tmp, tmp2;
9984   u8 prefix_set = 0;
9985   u32 vrf_id = ~0;
9986   u8 is_add = 1;
9987   int ret;
9988
9989   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
9990     {
9991       if (unformat (input, "%U", unformat_vl_api_prefix, &prefix))
9992         prefix_set = 1;
9993       else if (unformat (input, "vrf %d", &vrf_id))
9994         ;
9995       else if (unformat (input, "del"))
9996         is_add = 0;
9997       else if (unformat (input, "port %d", &tmp))
9998         {
9999           if (tmp == 0 || tmp > 65535)
10000             {
10001               errmsg ("port %d out of range", tmp);
10002               return -99;
10003             }
10004           this_low = tmp;
10005           this_hi = this_low + 1;
10006           vec_add1 (low_ports, this_low);
10007           vec_add1 (high_ports, this_hi);
10008         }
10009       else if (unformat (input, "range %d - %d", &tmp, &tmp2))
10010         {
10011           if ((tmp > tmp2) || (tmp == 0) || (tmp2 > 65535))
10012             {
10013               errmsg ("incorrect range parameters");
10014               return -99;
10015             }
10016           this_low = tmp;
10017           /* Note: in debug CLI +1 is added to high before
10018              passing to real fn that does "the work"
10019              (ip_source_and_port_range_check_add_del).
10020              This fn is a wrapper around the binary API fn a
10021              control plane will call, which expects this increment
10022              to have occurred. Hence letting the binary API control
10023              plane fn do the increment for consistency between VAT
10024              and other control planes.
10025            */
10026           this_hi = tmp2;
10027           vec_add1 (low_ports, this_low);
10028           vec_add1 (high_ports, this_hi);
10029         }
10030       else
10031         break;
10032     }
10033
10034   if (prefix_set == 0)
10035     {
10036       errmsg ("<address>/<mask> not specified");
10037       return -99;
10038     }
10039
10040   if (vrf_id == ~0)
10041     {
10042       errmsg ("VRF ID required, not specified");
10043       return -99;
10044     }
10045
10046   if (vrf_id == 0)
10047     {
10048       errmsg
10049         ("VRF ID should not be default. Should be distinct VRF for this purpose.");
10050       return -99;
10051     }
10052
10053   if (vec_len (low_ports) == 0)
10054     {
10055       errmsg ("At least one port or port range required");
10056       return -99;
10057     }
10058
10059   M (IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL, mp);
10060
10061   mp->is_add = is_add;
10062
10063   clib_memcpy (&mp->prefix, &prefix, sizeof (prefix));
10064
10065   mp->number_of_ranges = vec_len (low_ports);
10066
10067   clib_memcpy (mp->low_ports, low_ports, vec_len (low_ports));
10068   vec_free (low_ports);
10069
10070   clib_memcpy (mp->high_ports, high_ports, vec_len (high_ports));
10071   vec_free (high_ports);
10072
10073   mp->vrf_id = ntohl (vrf_id);
10074
10075   S (mp);
10076   W (ret);
10077   return ret;
10078 }
10079
10080 int
10081 api_ip_source_and_port_range_check_interface_add_del (vat_main_t * vam)
10082 {
10083   unformat_input_t *input = vam->input;
10084   vl_api_ip_source_and_port_range_check_interface_add_del_t *mp;
10085   u32 sw_if_index = ~0;
10086   int vrf_set = 0;
10087   u32 tcp_out_vrf_id = ~0, udp_out_vrf_id = ~0;
10088   u32 tcp_in_vrf_id = ~0, udp_in_vrf_id = ~0;
10089   u8 is_add = 1;
10090   int ret;
10091
10092   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
10093     {
10094       if (unformat (input, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10095         ;
10096       else if (unformat (input, "sw_if_index %d", &sw_if_index))
10097         ;
10098       else if (unformat (input, "tcp-out-vrf %d", &tcp_out_vrf_id))
10099         vrf_set = 1;
10100       else if (unformat (input, "udp-out-vrf %d", &udp_out_vrf_id))
10101         vrf_set = 1;
10102       else if (unformat (input, "tcp-in-vrf %d", &tcp_in_vrf_id))
10103         vrf_set = 1;
10104       else if (unformat (input, "udp-in-vrf %d", &udp_in_vrf_id))
10105         vrf_set = 1;
10106       else if (unformat (input, "del"))
10107         is_add = 0;
10108       else
10109         break;
10110     }
10111
10112   if (sw_if_index == ~0)
10113     {
10114       errmsg ("Interface required but not specified");
10115       return -99;
10116     }
10117
10118   if (vrf_set == 0)
10119     {
10120       errmsg ("VRF ID required but not specified");
10121       return -99;
10122     }
10123
10124   if (tcp_out_vrf_id == 0
10125       || udp_out_vrf_id == 0 || tcp_in_vrf_id == 0 || udp_in_vrf_id == 0)
10126     {
10127       errmsg
10128         ("VRF ID should not be default. Should be distinct VRF for this purpose.");
10129       return -99;
10130     }
10131
10132   /* Construct the API message */
10133   M (IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL, mp);
10134
10135   mp->sw_if_index = ntohl (sw_if_index);
10136   mp->is_add = is_add;
10137   mp->tcp_out_vrf_id = ntohl (tcp_out_vrf_id);
10138   mp->udp_out_vrf_id = ntohl (udp_out_vrf_id);
10139   mp->tcp_in_vrf_id = ntohl (tcp_in_vrf_id);
10140   mp->udp_in_vrf_id = ntohl (udp_in_vrf_id);
10141
10142   /* send it... */
10143   S (mp);
10144
10145   /* Wait for a reply... */
10146   W (ret);
10147   return ret;
10148 }
10149
10150 static int
10151 api_set_punt (vat_main_t * vam)
10152 {
10153   unformat_input_t *i = vam->input;
10154   vl_api_address_family_t af;
10155   vl_api_set_punt_t *mp;
10156   u32 protocol = ~0;
10157   u32 port = ~0;
10158   int is_add = 1;
10159   int ret;
10160
10161   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10162     {
10163       if (unformat (i, "%U", unformat_vl_api_address_family, &af))
10164         ;
10165       else if (unformat (i, "protocol %d", &protocol))
10166         ;
10167       else if (unformat (i, "port %d", &port))
10168         ;
10169       else if (unformat (i, "del"))
10170         is_add = 0;
10171       else
10172         {
10173           clib_warning ("parse error '%U'", format_unformat_error, i);
10174           return -99;
10175         }
10176     }
10177
10178   M (SET_PUNT, mp);
10179
10180   mp->is_add = (u8) is_add;
10181   mp->punt.type = PUNT_API_TYPE_L4;
10182   mp->punt.punt.l4.af = af;
10183   mp->punt.punt.l4.protocol = (u8) protocol;
10184   mp->punt.punt.l4.port = htons ((u16) port);
10185
10186   S (mp);
10187   W (ret);
10188   return ret;
10189 }
10190
10191 static int
10192 api_delete_subif (vat_main_t * vam)
10193 {
10194   unformat_input_t *i = vam->input;
10195   vl_api_delete_subif_t *mp;
10196   u32 sw_if_index = ~0;
10197   int ret;
10198
10199   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10200     {
10201       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10202         ;
10203       if (unformat (i, "sw_if_index %d", &sw_if_index))
10204         ;
10205       else
10206         break;
10207     }
10208
10209   if (sw_if_index == ~0)
10210     {
10211       errmsg ("missing sw_if_index");
10212       return -99;
10213     }
10214
10215   /* Construct the API message */
10216   M (DELETE_SUBIF, mp);
10217   mp->sw_if_index = ntohl (sw_if_index);
10218
10219   S (mp);
10220   W (ret);
10221   return ret;
10222 }
10223
10224 #define foreach_pbb_vtr_op      \
10225 _("disable",  L2_VTR_DISABLED)  \
10226 _("pop",  L2_VTR_POP_2)         \
10227 _("push",  L2_VTR_PUSH_2)
10228
10229 static int
10230 api_l2_interface_pbb_tag_rewrite (vat_main_t * vam)
10231 {
10232   unformat_input_t *i = vam->input;
10233   vl_api_l2_interface_pbb_tag_rewrite_t *mp;
10234   u32 sw_if_index = ~0, vtr_op = ~0;
10235   u16 outer_tag = ~0;
10236   u8 dmac[6], smac[6];
10237   u8 dmac_set = 0, smac_set = 0;
10238   u16 vlanid = 0;
10239   u32 sid = ~0;
10240   u32 tmp;
10241   int ret;
10242
10243   /* Shut up coverity */
10244   clib_memset (dmac, 0, sizeof (dmac));
10245   clib_memset (smac, 0, sizeof (smac));
10246
10247   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10248     {
10249       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10250         ;
10251       else if (unformat (i, "sw_if_index %d", &sw_if_index))
10252         ;
10253       else if (unformat (i, "vtr_op %d", &vtr_op))
10254         ;
10255 #define _(n,v) else if (unformat(i, n)) {vtr_op = v;}
10256       foreach_pbb_vtr_op
10257 #undef _
10258         else if (unformat (i, "translate_pbb_stag"))
10259         {
10260           if (unformat (i, "%d", &tmp))
10261             {
10262               vtr_op = L2_VTR_TRANSLATE_2_1;
10263               outer_tag = tmp;
10264             }
10265           else
10266             {
10267               errmsg
10268                 ("translate_pbb_stag operation requires outer tag definition");
10269               return -99;
10270             }
10271         }
10272       else if (unformat (i, "dmac %U", unformat_ethernet_address, dmac))
10273         dmac_set++;
10274       else if (unformat (i, "smac %U", unformat_ethernet_address, smac))
10275         smac_set++;
10276       else if (unformat (i, "sid %d", &sid))
10277         ;
10278       else if (unformat (i, "vlanid %d", &tmp))
10279         vlanid = tmp;
10280       else
10281         {
10282           clib_warning ("parse error '%U'", format_unformat_error, i);
10283           return -99;
10284         }
10285     }
10286
10287   if ((sw_if_index == ~0) || (vtr_op == ~0))
10288     {
10289       errmsg ("missing sw_if_index or vtr operation");
10290       return -99;
10291     }
10292   if (((vtr_op == L2_VTR_PUSH_2) || (vtr_op == L2_VTR_TRANSLATE_2_2))
10293       && ((dmac_set == 0) || (smac_set == 0) || (sid == ~0)))
10294     {
10295       errmsg
10296         ("push and translate_qinq operations require dmac, smac, sid and optionally vlanid");
10297       return -99;
10298     }
10299
10300   M (L2_INTERFACE_PBB_TAG_REWRITE, mp);
10301   mp->sw_if_index = ntohl (sw_if_index);
10302   mp->vtr_op = ntohl (vtr_op);
10303   mp->outer_tag = ntohs (outer_tag);
10304   clib_memcpy (mp->b_dmac, dmac, sizeof (dmac));
10305   clib_memcpy (mp->b_smac, smac, sizeof (smac));
10306   mp->b_vlanid = ntohs (vlanid);
10307   mp->i_sid = ntohl (sid);
10308
10309   S (mp);
10310   W (ret);
10311   return ret;
10312 }
10313
10314 static int
10315 api_sw_interface_tag_add_del (vat_main_t * vam)
10316 {
10317   unformat_input_t *i = vam->input;
10318   vl_api_sw_interface_tag_add_del_t *mp;
10319   u32 sw_if_index = ~0;
10320   u8 *tag = 0;
10321   u8 enable = 1;
10322   int ret;
10323
10324   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10325     {
10326       if (unformat (i, "tag %s", &tag))
10327         ;
10328       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10329         ;
10330       else if (unformat (i, "sw_if_index %d", &sw_if_index))
10331         ;
10332       else if (unformat (i, "del"))
10333         enable = 0;
10334       else
10335         break;
10336     }
10337
10338   if (sw_if_index == ~0)
10339     {
10340       errmsg ("missing interface name or sw_if_index");
10341       return -99;
10342     }
10343
10344   if (enable && (tag == 0))
10345     {
10346       errmsg ("no tag specified");
10347       return -99;
10348     }
10349
10350   /* Construct the API message */
10351   M (SW_INTERFACE_TAG_ADD_DEL, mp);
10352   mp->sw_if_index = ntohl (sw_if_index);
10353   mp->is_add = enable;
10354   if (enable)
10355     strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
10356   vec_free (tag);
10357
10358   S (mp);
10359   W (ret);
10360   return ret;
10361 }
10362
10363 static int
10364 api_sw_interface_add_del_mac_address (vat_main_t * vam)
10365 {
10366   unformat_input_t *i = vam->input;
10367   vl_api_mac_address_t mac = { 0 };
10368   vl_api_sw_interface_add_del_mac_address_t *mp;
10369   u32 sw_if_index = ~0;
10370   u8 is_add = 1;
10371   u8 mac_set = 0;
10372   int ret;
10373
10374   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10375     {
10376       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10377         ;
10378       else if (unformat (i, "sw_if_index %d", &sw_if_index))
10379         ;
10380       else if (unformat (i, "%U", unformat_vl_api_mac_address, &mac))
10381         mac_set++;
10382       else if (unformat (i, "del"))
10383         is_add = 0;
10384       else
10385         break;
10386     }
10387
10388   if (sw_if_index == ~0)
10389     {
10390       errmsg ("missing interface name or sw_if_index");
10391       return -99;
10392     }
10393
10394   if (!mac_set)
10395     {
10396       errmsg ("missing MAC address");
10397       return -99;
10398     }
10399
10400   /* Construct the API message */
10401   M (SW_INTERFACE_ADD_DEL_MAC_ADDRESS, mp);
10402   mp->sw_if_index = ntohl (sw_if_index);
10403   mp->is_add = is_add;
10404   clib_memcpy (&mp->addr, &mac, sizeof (mac));
10405
10406   S (mp);
10407   W (ret);
10408   return ret;
10409 }
10410
10411 static void vl_api_l2_xconnect_details_t_handler
10412   (vl_api_l2_xconnect_details_t * mp)
10413 {
10414   vat_main_t *vam = &vat_main;
10415
10416   print (vam->ofp, "%15d%15d",
10417          ntohl (mp->rx_sw_if_index), ntohl (mp->tx_sw_if_index));
10418 }
10419
10420 static void vl_api_l2_xconnect_details_t_handler_json
10421   (vl_api_l2_xconnect_details_t * mp)
10422 {
10423   vat_main_t *vam = &vat_main;
10424   vat_json_node_t *node = NULL;
10425
10426   if (VAT_JSON_ARRAY != vam->json_tree.type)
10427     {
10428       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
10429       vat_json_init_array (&vam->json_tree);
10430     }
10431   node = vat_json_array_add (&vam->json_tree);
10432
10433   vat_json_init_object (node);
10434   vat_json_object_add_uint (node, "rx_sw_if_index",
10435                             ntohl (mp->rx_sw_if_index));
10436   vat_json_object_add_uint (node, "tx_sw_if_index",
10437                             ntohl (mp->tx_sw_if_index));
10438 }
10439
10440 static int
10441 api_l2_xconnect_dump (vat_main_t * vam)
10442 {
10443   vl_api_l2_xconnect_dump_t *mp;
10444   vl_api_control_ping_t *mp_ping;
10445   int ret;
10446
10447   if (!vam->json_output)
10448     {
10449       print (vam->ofp, "%15s%15s", "rx_sw_if_index", "tx_sw_if_index");
10450     }
10451
10452   M (L2_XCONNECT_DUMP, mp);
10453
10454   S (mp);
10455
10456   /* Use a control ping for synchronization */
10457   MPING (CONTROL_PING, mp_ping);
10458   S (mp_ping);
10459
10460   W (ret);
10461   return ret;
10462 }
10463
10464 static int
10465 api_hw_interface_set_mtu (vat_main_t * vam)
10466 {
10467   unformat_input_t *i = vam->input;
10468   vl_api_hw_interface_set_mtu_t *mp;
10469   u32 sw_if_index = ~0;
10470   u32 mtu = 0;
10471   int ret;
10472
10473   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10474     {
10475       if (unformat (i, "mtu %d", &mtu))
10476         ;
10477       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10478         ;
10479       else if (unformat (i, "sw_if_index %d", &sw_if_index))
10480         ;
10481       else
10482         break;
10483     }
10484
10485   if (sw_if_index == ~0)
10486     {
10487       errmsg ("missing interface name or sw_if_index");
10488       return -99;
10489     }
10490
10491   if (mtu == 0)
10492     {
10493       errmsg ("no mtu specified");
10494       return -99;
10495     }
10496
10497   /* Construct the API message */
10498   M (HW_INTERFACE_SET_MTU, mp);
10499   mp->sw_if_index = ntohl (sw_if_index);
10500   mp->mtu = ntohs ((u16) mtu);
10501
10502   S (mp);
10503   W (ret);
10504   return ret;
10505 }
10506
10507 static int
10508 api_tcp_configure_src_addresses (vat_main_t * vam)
10509 {
10510   vl_api_tcp_configure_src_addresses_t *mp;
10511   unformat_input_t *i = vam->input;
10512   vl_api_address_t first, last;
10513   u8 range_set = 0;
10514   u32 vrf_id = 0;
10515   int ret;
10516
10517   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10518     {
10519       if (unformat (i, "%U - %U",
10520                     unformat_vl_api_address, &first,
10521                     unformat_vl_api_address, &last))
10522         {
10523           if (range_set)
10524             {
10525               errmsg ("one range per message (range already set)");
10526               return -99;
10527             }
10528           range_set = 1;
10529         }
10530       else if (unformat (i, "vrf %d", &vrf_id))
10531         ;
10532       else
10533         break;
10534     }
10535
10536   if (range_set == 0)
10537     {
10538       errmsg ("address range not set");
10539       return -99;
10540     }
10541
10542   M (TCP_CONFIGURE_SRC_ADDRESSES, mp);
10543
10544   mp->vrf_id = ntohl (vrf_id);
10545   clib_memcpy (&mp->first_address, &first, sizeof (first));
10546   clib_memcpy (&mp->last_address, &last, sizeof (last));
10547
10548   S (mp);
10549   W (ret);
10550   return ret;
10551 }
10552
10553 static void vl_api_app_namespace_add_del_reply_t_handler
10554   (vl_api_app_namespace_add_del_reply_t * mp)
10555 {
10556   vat_main_t *vam = &vat_main;
10557   i32 retval = ntohl (mp->retval);
10558   if (vam->async_mode)
10559     {
10560       vam->async_errors += (retval < 0);
10561     }
10562   else
10563     {
10564       vam->retval = retval;
10565       if (retval == 0)
10566         errmsg ("app ns index %d\n", ntohl (mp->appns_index));
10567       vam->result_ready = 1;
10568     }
10569 }
10570
10571 static void vl_api_app_namespace_add_del_reply_t_handler_json
10572   (vl_api_app_namespace_add_del_reply_t * mp)
10573 {
10574   vat_main_t *vam = &vat_main;
10575   vat_json_node_t node;
10576
10577   vat_json_init_object (&node);
10578   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
10579   vat_json_object_add_uint (&node, "appns_index", ntohl (mp->appns_index));
10580
10581   vat_json_print (vam->ofp, &node);
10582   vat_json_free (&node);
10583
10584   vam->retval = ntohl (mp->retval);
10585   vam->result_ready = 1;
10586 }
10587
10588 static int
10589 api_app_namespace_add_del (vat_main_t * vam)
10590 {
10591   vl_api_app_namespace_add_del_t *mp;
10592   unformat_input_t *i = vam->input;
10593   u8 *ns_id = 0, secret_set = 0, sw_if_index_set = 0;
10594   u32 sw_if_index, ip4_fib_id, ip6_fib_id;
10595   u64 secret;
10596   int ret;
10597
10598   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10599     {
10600       if (unformat (i, "id %_%v%_", &ns_id))
10601         ;
10602       else if (unformat (i, "secret %lu", &secret))
10603         secret_set = 1;
10604       else if (unformat (i, "sw_if_index %d", &sw_if_index))
10605         sw_if_index_set = 1;
10606       else if (unformat (i, "ip4_fib_id %d", &ip4_fib_id))
10607         ;
10608       else if (unformat (i, "ip6_fib_id %d", &ip6_fib_id))
10609         ;
10610       else
10611         break;
10612     }
10613   if (!ns_id || !secret_set || !sw_if_index_set)
10614     {
10615       errmsg ("namespace id, secret and sw_if_index must be set");
10616       return -99;
10617     }
10618   if (vec_len (ns_id) > 64)
10619     {
10620       errmsg ("namespace id too long");
10621       return -99;
10622     }
10623   M (APP_NAMESPACE_ADD_DEL, mp);
10624
10625   vl_api_vec_to_api_string (ns_id, &mp->namespace_id);
10626   mp->secret = clib_host_to_net_u64 (secret);
10627   mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
10628   mp->ip4_fib_id = clib_host_to_net_u32 (ip4_fib_id);
10629   mp->ip6_fib_id = clib_host_to_net_u32 (ip6_fib_id);
10630   vec_free (ns_id);
10631   S (mp);
10632   W (ret);
10633   return ret;
10634 }
10635
10636 static int
10637 api_sock_init_shm (vat_main_t * vam)
10638 {
10639 #if VPP_API_TEST_BUILTIN == 0
10640   unformat_input_t *i = vam->input;
10641   vl_api_shm_elem_config_t *config = 0;
10642   u64 size = 64 << 20;
10643   int rv;
10644
10645   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10646     {
10647       if (unformat (i, "size %U", unformat_memory_size, &size))
10648         ;
10649       else
10650         break;
10651     }
10652
10653   /*
10654    * Canned custom ring allocator config.
10655    * Should probably parse all of this
10656    */
10657   vec_validate (config, 6);
10658   config[0].type = VL_API_VLIB_RING;
10659   config[0].size = 256;
10660   config[0].count = 32;
10661
10662   config[1].type = VL_API_VLIB_RING;
10663   config[1].size = 1024;
10664   config[1].count = 16;
10665
10666   config[2].type = VL_API_VLIB_RING;
10667   config[2].size = 4096;
10668   config[2].count = 2;
10669
10670   config[3].type = VL_API_CLIENT_RING;
10671   config[3].size = 256;
10672   config[3].count = 32;
10673
10674   config[4].type = VL_API_CLIENT_RING;
10675   config[4].size = 1024;
10676   config[4].count = 16;
10677
10678   config[5].type = VL_API_CLIENT_RING;
10679   config[5].size = 4096;
10680   config[5].count = 2;
10681
10682   config[6].type = VL_API_QUEUE;
10683   config[6].count = 128;
10684   config[6].size = sizeof (uword);
10685
10686   rv = vl_socket_client_init_shm (config, 1 /* want_pthread */ );
10687   if (!rv)
10688     vam->client_index_invalid = 1;
10689   return rv;
10690 #else
10691   return -99;
10692 #endif
10693 }
10694
10695 static void
10696 vl_api_session_rules_details_t_handler (vl_api_session_rules_details_t * mp)
10697 {
10698   vat_main_t *vam = &vat_main;
10699   fib_prefix_t lcl, rmt;
10700
10701   ip_prefix_decode (&mp->lcl, &lcl);
10702   ip_prefix_decode (&mp->rmt, &rmt);
10703
10704   if (lcl.fp_proto == FIB_PROTOCOL_IP4)
10705     {
10706       print (vam->ofp,
10707              "appns %u tp %u scope %d %U/%d %d %U/%d %d action: %d tag: %s",
10708              clib_net_to_host_u32 (mp->appns_index), mp->transport_proto,
10709              mp->scope, format_ip4_address, &lcl.fp_addr.ip4, lcl.fp_len,
10710              clib_net_to_host_u16 (mp->lcl_port), format_ip4_address,
10711              &rmt.fp_addr.ip4, rmt.fp_len,
10712              clib_net_to_host_u16 (mp->rmt_port),
10713              clib_net_to_host_u32 (mp->action_index), mp->tag);
10714     }
10715   else
10716     {
10717       print (vam->ofp,
10718              "appns %u tp %u scope %d %U/%d %d %U/%d %d action: %d tag: %s",
10719              clib_net_to_host_u32 (mp->appns_index), mp->transport_proto,
10720              mp->scope, format_ip6_address, &lcl.fp_addr.ip6, lcl.fp_len,
10721              clib_net_to_host_u16 (mp->lcl_port), format_ip6_address,
10722              &rmt.fp_addr.ip6, rmt.fp_len,
10723              clib_net_to_host_u16 (mp->rmt_port),
10724              clib_net_to_host_u32 (mp->action_index), mp->tag);
10725     }
10726 }
10727
10728 static void
10729 vl_api_session_rules_details_t_handler_json (vl_api_session_rules_details_t *
10730                                              mp)
10731 {
10732   vat_main_t *vam = &vat_main;
10733   vat_json_node_t *node = NULL;
10734   struct in6_addr ip6;
10735   struct in_addr ip4;
10736
10737   fib_prefix_t lcl, rmt;
10738
10739   ip_prefix_decode (&mp->lcl, &lcl);
10740   ip_prefix_decode (&mp->rmt, &rmt);
10741
10742   if (VAT_JSON_ARRAY != vam->json_tree.type)
10743     {
10744       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
10745       vat_json_init_array (&vam->json_tree);
10746     }
10747   node = vat_json_array_add (&vam->json_tree);
10748   vat_json_init_object (node);
10749
10750   vat_json_object_add_uint (node, "appns_index",
10751                             clib_net_to_host_u32 (mp->appns_index));
10752   vat_json_object_add_uint (node, "transport_proto", mp->transport_proto);
10753   vat_json_object_add_uint (node, "scope", mp->scope);
10754   vat_json_object_add_uint (node, "action_index",
10755                             clib_net_to_host_u32 (mp->action_index));
10756   vat_json_object_add_uint (node, "lcl_port",
10757                             clib_net_to_host_u16 (mp->lcl_port));
10758   vat_json_object_add_uint (node, "rmt_port",
10759                             clib_net_to_host_u16 (mp->rmt_port));
10760   vat_json_object_add_uint (node, "lcl_plen", lcl.fp_len);
10761   vat_json_object_add_uint (node, "rmt_plen", rmt.fp_len);
10762   vat_json_object_add_string_copy (node, "tag", mp->tag);
10763   if (lcl.fp_proto == FIB_PROTOCOL_IP4)
10764     {
10765       clib_memcpy (&ip4, &lcl.fp_addr.ip4, sizeof (ip4));
10766       vat_json_object_add_ip4 (node, "lcl_ip", ip4);
10767       clib_memcpy (&ip4, &rmt.fp_addr.ip4, sizeof (ip4));
10768       vat_json_object_add_ip4 (node, "rmt_ip", ip4);
10769     }
10770   else
10771     {
10772       clib_memcpy (&ip6, &lcl.fp_addr.ip6, sizeof (ip6));
10773       vat_json_object_add_ip6 (node, "lcl_ip", ip6);
10774       clib_memcpy (&ip6, &rmt.fp_addr.ip6, sizeof (ip6));
10775       vat_json_object_add_ip6 (node, "rmt_ip", ip6);
10776     }
10777 }
10778
10779 static int
10780 api_session_rule_add_del (vat_main_t * vam)
10781 {
10782   vl_api_session_rule_add_del_t *mp;
10783   unformat_input_t *i = vam->input;
10784   u32 proto = ~0, lcl_port, rmt_port, action = 0, lcl_plen, rmt_plen;
10785   u32 appns_index = 0, scope = 0;
10786   ip4_address_t lcl_ip4, rmt_ip4;
10787   ip6_address_t lcl_ip6, rmt_ip6;
10788   u8 is_ip4 = 1, conn_set = 0;
10789   u8 is_add = 1, *tag = 0;
10790   int ret;
10791   fib_prefix_t lcl, rmt;
10792
10793   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10794     {
10795       if (unformat (i, "del"))
10796         is_add = 0;
10797       else if (unformat (i, "add"))
10798         ;
10799       else if (unformat (i, "proto tcp"))
10800         proto = 0;
10801       else if (unformat (i, "proto udp"))
10802         proto = 1;
10803       else if (unformat (i, "appns %d", &appns_index))
10804         ;
10805       else if (unformat (i, "scope %d", &scope))
10806         ;
10807       else if (unformat (i, "tag %_%v%_", &tag))
10808         ;
10809       else
10810         if (unformat
10811             (i, "%U/%d %d %U/%d %d", unformat_ip4_address, &lcl_ip4,
10812              &lcl_plen, &lcl_port, unformat_ip4_address, &rmt_ip4, &rmt_plen,
10813              &rmt_port))
10814         {
10815           is_ip4 = 1;
10816           conn_set = 1;
10817         }
10818       else
10819         if (unformat
10820             (i, "%U/%d %d %U/%d %d", unformat_ip6_address, &lcl_ip6,
10821              &lcl_plen, &lcl_port, unformat_ip6_address, &rmt_ip6, &rmt_plen,
10822              &rmt_port))
10823         {
10824           is_ip4 = 0;
10825           conn_set = 1;
10826         }
10827       else if (unformat (i, "action %d", &action))
10828         ;
10829       else
10830         break;
10831     }
10832   if (proto == ~0 || !conn_set || action == ~0)
10833     {
10834       errmsg ("transport proto, connection and action must be set");
10835       return -99;
10836     }
10837
10838   if (scope > 3)
10839     {
10840       errmsg ("scope should be 0-3");
10841       return -99;
10842     }
10843
10844   M (SESSION_RULE_ADD_DEL, mp);
10845
10846   clib_memset (&lcl, 0, sizeof (lcl));
10847   clib_memset (&rmt, 0, sizeof (rmt));
10848   if (is_ip4)
10849     {
10850       ip_set (&lcl.fp_addr, &lcl_ip4, 1);
10851       ip_set (&rmt.fp_addr, &rmt_ip4, 1);
10852       lcl.fp_len = lcl_plen;
10853       rmt.fp_len = rmt_plen;
10854     }
10855   else
10856     {
10857       ip_set (&lcl.fp_addr, &lcl_ip6, 0);
10858       ip_set (&rmt.fp_addr, &rmt_ip6, 0);
10859       lcl.fp_len = lcl_plen;
10860       rmt.fp_len = rmt_plen;
10861     }
10862
10863
10864   ip_prefix_encode (&lcl, &mp->lcl);
10865   ip_prefix_encode (&rmt, &mp->rmt);
10866   mp->lcl_port = clib_host_to_net_u16 ((u16) lcl_port);
10867   mp->rmt_port = clib_host_to_net_u16 ((u16) rmt_port);
10868   mp->transport_proto =
10869     proto ? TRANSPORT_PROTO_API_UDP : TRANSPORT_PROTO_API_TCP;
10870   mp->action_index = clib_host_to_net_u32 (action);
10871   mp->appns_index = clib_host_to_net_u32 (appns_index);
10872   mp->scope = scope;
10873   mp->is_add = is_add;
10874   if (tag)
10875     {
10876       clib_memcpy (mp->tag, tag, vec_len (tag));
10877       vec_free (tag);
10878     }
10879
10880   S (mp);
10881   W (ret);
10882   return ret;
10883 }
10884
10885 static int
10886 api_session_rules_dump (vat_main_t * vam)
10887 {
10888   vl_api_session_rules_dump_t *mp;
10889   vl_api_control_ping_t *mp_ping;
10890   int ret;
10891
10892   if (!vam->json_output)
10893     {
10894       print (vam->ofp, "%=20s", "Session Rules");
10895     }
10896
10897   M (SESSION_RULES_DUMP, mp);
10898   /* send it... */
10899   S (mp);
10900
10901   /* Use a control ping for synchronization */
10902   MPING (CONTROL_PING, mp_ping);
10903   S (mp_ping);
10904
10905   /* Wait for a reply... */
10906   W (ret);
10907   return ret;
10908 }
10909
10910 static int
10911 api_ip_container_proxy_add_del (vat_main_t * vam)
10912 {
10913   vl_api_ip_container_proxy_add_del_t *mp;
10914   unformat_input_t *i = vam->input;
10915   u32 sw_if_index = ~0;
10916   vl_api_prefix_t pfx = { };
10917   u8 is_add = 1;
10918   int ret;
10919
10920   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10921     {
10922       if (unformat (i, "del"))
10923         is_add = 0;
10924       else if (unformat (i, "add"))
10925         ;
10926       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
10927         ;
10928       else if (unformat (i, "sw_if_index %u", &sw_if_index))
10929         ;
10930       else
10931         break;
10932     }
10933   if (sw_if_index == ~0 || pfx.len == 0)
10934     {
10935       errmsg ("address and sw_if_index must be set");
10936       return -99;
10937     }
10938
10939   M (IP_CONTAINER_PROXY_ADD_DEL, mp);
10940
10941   mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
10942   mp->is_add = is_add;
10943   clib_memcpy (&mp->pfx, &pfx, sizeof (pfx));
10944
10945   S (mp);
10946   W (ret);
10947   return ret;
10948 }
10949
10950 static int
10951 api_qos_record_enable_disable (vat_main_t * vam)
10952 {
10953   unformat_input_t *i = vam->input;
10954   vl_api_qos_record_enable_disable_t *mp;
10955   u32 sw_if_index, qs = 0xff;
10956   u8 sw_if_index_set = 0;
10957   u8 enable = 1;
10958   int ret;
10959
10960   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10961     {
10962       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10963         sw_if_index_set = 1;
10964       else if (unformat (i, "sw_if_index %d", &sw_if_index))
10965         sw_if_index_set = 1;
10966       else if (unformat (i, "%U", unformat_qos_source, &qs))
10967         ;
10968       else if (unformat (i, "disable"))
10969         enable = 0;
10970       else
10971         {
10972           clib_warning ("parse error '%U'", format_unformat_error, i);
10973           return -99;
10974         }
10975     }
10976
10977   if (sw_if_index_set == 0)
10978     {
10979       errmsg ("missing interface name or sw_if_index");
10980       return -99;
10981     }
10982   if (qs == 0xff)
10983     {
10984       errmsg ("input location must be specified");
10985       return -99;
10986     }
10987
10988   M (QOS_RECORD_ENABLE_DISABLE, mp);
10989
10990   mp->record.sw_if_index = ntohl (sw_if_index);
10991   mp->record.input_source = qs;
10992   mp->enable = enable;
10993
10994   S (mp);
10995   W (ret);
10996   return ret;
10997 }
10998
10999
11000 static int
11001 q_or_quit (vat_main_t * vam)
11002 {
11003 #if VPP_API_TEST_BUILTIN == 0
11004   longjmp (vam->jump_buf, 1);
11005 #endif
11006   return 0;                     /* not so much */
11007 }
11008
11009 static int
11010 q (vat_main_t * vam)
11011 {
11012   return q_or_quit (vam);
11013 }
11014
11015 static int
11016 quit (vat_main_t * vam)
11017 {
11018   return q_or_quit (vam);
11019 }
11020
11021 static int
11022 comment (vat_main_t * vam)
11023 {
11024   return 0;
11025 }
11026
11027 static int
11028 elog_save (vat_main_t * vam)
11029 {
11030 #if VPP_API_TEST_BUILTIN == 0
11031   elog_main_t *em = &vam->elog_main;
11032   unformat_input_t *i = vam->input;
11033   char *file, *chroot_file;
11034   clib_error_t *error;
11035
11036   if (!unformat (i, "%s", &file))
11037     {
11038       errmsg ("expected file name, got `%U'", format_unformat_error, i);
11039       return 0;
11040     }
11041
11042   /* It's fairly hard to get "../oopsie" through unformat; just in case */
11043   if (strstr (file, "..") || index (file, '/'))
11044     {
11045       errmsg ("illegal characters in filename '%s'", file);
11046       return 0;
11047     }
11048
11049   chroot_file = (char *) format (0, "/tmp/%s%c", file, 0);
11050
11051   vec_free (file);
11052
11053   errmsg ("Saving %wd of %wd events to %s",
11054           elog_n_events_in_buffer (em),
11055           elog_buffer_capacity (em), chroot_file);
11056
11057   error = elog_write_file (em, chroot_file, 1 /* flush ring */ );
11058   vec_free (chroot_file);
11059
11060   if (error)
11061     clib_error_report (error);
11062 #else
11063   errmsg ("Use the vpp event loger...");
11064 #endif
11065
11066   return 0;
11067 }
11068
11069 static int
11070 elog_setup (vat_main_t * vam)
11071 {
11072 #if VPP_API_TEST_BUILTIN == 0
11073   elog_main_t *em = &vam->elog_main;
11074   unformat_input_t *i = vam->input;
11075   u32 nevents = 128 << 10;
11076
11077   (void) unformat (i, "nevents %d", &nevents);
11078
11079   elog_init (em, nevents);
11080   vl_api_set_elog_main (em);
11081   vl_api_set_elog_trace_api_messages (1);
11082   errmsg ("Event logger initialized with %u events", nevents);
11083 #else
11084   errmsg ("Use the vpp event loger...");
11085 #endif
11086   return 0;
11087 }
11088
11089 static int
11090 elog_enable (vat_main_t * vam)
11091 {
11092 #if VPP_API_TEST_BUILTIN == 0
11093   elog_main_t *em = &vam->elog_main;
11094
11095   elog_enable_disable (em, 1 /* enable */ );
11096   vl_api_set_elog_trace_api_messages (1);
11097   errmsg ("Event logger enabled...");
11098 #else
11099   errmsg ("Use the vpp event loger...");
11100 #endif
11101   return 0;
11102 }
11103
11104 static int
11105 elog_disable (vat_main_t * vam)
11106 {
11107 #if VPP_API_TEST_BUILTIN == 0
11108   elog_main_t *em = &vam->elog_main;
11109
11110   elog_enable_disable (em, 0 /* enable */ );
11111   vl_api_set_elog_trace_api_messages (1);
11112   errmsg ("Event logger disabled...");
11113 #else
11114   errmsg ("Use the vpp event loger...");
11115 #endif
11116   return 0;
11117 }
11118
11119 static int
11120 statseg (vat_main_t * vam)
11121 {
11122   ssvm_private_t *ssvmp = &vam->stat_segment;
11123   ssvm_shared_header_t *shared_header = ssvmp->sh;
11124   vlib_counter_t **counters;
11125   u64 thread0_index1_packets;
11126   u64 thread0_index1_bytes;
11127   f64 vector_rate, input_rate;
11128   uword *p;
11129
11130   uword *counter_vector_by_name;
11131   if (vam->stat_segment_lockp == 0)
11132     {
11133       errmsg ("Stat segment not mapped...");
11134       return -99;
11135     }
11136
11137   /* look up "/if/rx for sw_if_index 1 as a test */
11138
11139   clib_spinlock_lock (vam->stat_segment_lockp);
11140
11141   counter_vector_by_name = (uword *) shared_header->opaque[1];
11142
11143   p = hash_get_mem (counter_vector_by_name, "/if/rx");
11144   if (p == 0)
11145     {
11146       clib_spinlock_unlock (vam->stat_segment_lockp);
11147       errmsg ("/if/tx not found?");
11148       return -99;
11149     }
11150
11151   /* Fish per-thread vector of combined counters from shared memory */
11152   counters = (vlib_counter_t **) p[0];
11153
11154   if (vec_len (counters[0]) < 2)
11155     {
11156       clib_spinlock_unlock (vam->stat_segment_lockp);
11157       errmsg ("/if/tx vector length %d", vec_len (counters[0]));
11158       return -99;
11159     }
11160
11161   /* Read thread 0 sw_if_index 1 counter */
11162   thread0_index1_packets = counters[0][1].packets;
11163   thread0_index1_bytes = counters[0][1].bytes;
11164
11165   p = hash_get_mem (counter_vector_by_name, "vector_rate");
11166   if (p == 0)
11167     {
11168       clib_spinlock_unlock (vam->stat_segment_lockp);
11169       errmsg ("vector_rate not found?");
11170       return -99;
11171     }
11172
11173   vector_rate = *(f64 *) (p[0]);
11174   p = hash_get_mem (counter_vector_by_name, "input_rate");
11175   if (p == 0)
11176     {
11177       clib_spinlock_unlock (vam->stat_segment_lockp);
11178       errmsg ("input_rate not found?");
11179       return -99;
11180     }
11181   input_rate = *(f64 *) (p[0]);
11182
11183   clib_spinlock_unlock (vam->stat_segment_lockp);
11184
11185   print (vam->ofp, "vector_rate %.2f input_rate %.2f",
11186          vector_rate, input_rate);
11187   print (vam->ofp, "thread 0 sw_if_index 1 rx pkts %lld, bytes %lld",
11188          thread0_index1_packets, thread0_index1_bytes);
11189
11190   return 0;
11191 }
11192
11193 static int
11194 cmd_cmp (void *a1, void *a2)
11195 {
11196   u8 **c1 = a1;
11197   u8 **c2 = a2;
11198
11199   return strcmp ((char *) (c1[0]), (char *) (c2[0]));
11200 }
11201
11202 static int
11203 help (vat_main_t * vam)
11204 {
11205   u8 **cmds = 0;
11206   u8 *name = 0;
11207   hash_pair_t *p;
11208   unformat_input_t *i = vam->input;
11209   int j;
11210
11211   if (unformat (i, "%s", &name))
11212     {
11213       uword *hs;
11214
11215       vec_add1 (name, 0);
11216
11217       hs = hash_get_mem (vam->help_by_name, name);
11218       if (hs)
11219         print (vam->ofp, "usage: %s %s", name, hs[0]);
11220       else
11221         print (vam->ofp, "No such msg / command '%s'", name);
11222       vec_free (name);
11223       return 0;
11224     }
11225
11226   print (vam->ofp, "Help is available for the following:");
11227
11228     /* *INDENT-OFF* */
11229     hash_foreach_pair (p, vam->function_by_name,
11230     ({
11231       vec_add1 (cmds, (u8 *)(p->key));
11232     }));
11233     /* *INDENT-ON* */
11234
11235   vec_sort_with_function (cmds, cmd_cmp);
11236
11237   for (j = 0; j < vec_len (cmds); j++)
11238     print (vam->ofp, "%s", cmds[j]);
11239
11240   vec_free (cmds);
11241   return 0;
11242 }
11243
11244 static int
11245 set (vat_main_t * vam)
11246 {
11247   u8 *name = 0, *value = 0;
11248   unformat_input_t *i = vam->input;
11249
11250   if (unformat (i, "%s", &name))
11251     {
11252       /* The input buffer is a vector, not a string. */
11253       value = vec_dup (i->buffer);
11254       vec_delete (value, i->index, 0);
11255       /* Almost certainly has a trailing newline */
11256       if (value[vec_len (value) - 1] == '\n')
11257         value[vec_len (value) - 1] = 0;
11258       /* Make sure it's a proper string, one way or the other */
11259       vec_add1 (value, 0);
11260       (void) clib_macro_set_value (&vam->macro_main,
11261                                    (char *) name, (char *) value);
11262     }
11263   else
11264     errmsg ("usage: set <name> <value>");
11265
11266   vec_free (name);
11267   vec_free (value);
11268   return 0;
11269 }
11270
11271 static int
11272 unset (vat_main_t * vam)
11273 {
11274   u8 *name = 0;
11275
11276   if (unformat (vam->input, "%s", &name))
11277     if (clib_macro_unset (&vam->macro_main, (char *) name) == 1)
11278       errmsg ("unset: %s wasn't set", name);
11279   vec_free (name);
11280   return 0;
11281 }
11282
11283 typedef struct
11284 {
11285   u8 *name;
11286   u8 *value;
11287 } macro_sort_t;
11288
11289
11290 static int
11291 macro_sort_cmp (void *a1, void *a2)
11292 {
11293   macro_sort_t *s1 = a1;
11294   macro_sort_t *s2 = a2;
11295
11296   return strcmp ((char *) (s1->name), (char *) (s2->name));
11297 }
11298
11299 static int
11300 dump_macro_table (vat_main_t * vam)
11301 {
11302   macro_sort_t *sort_me = 0, *sm;
11303   int i;
11304   hash_pair_t *p;
11305
11306     /* *INDENT-OFF* */
11307     hash_foreach_pair (p, vam->macro_main.the_value_table_hash,
11308     ({
11309       vec_add2 (sort_me, sm, 1);
11310       sm->name = (u8 *)(p->key);
11311       sm->value = (u8 *) (p->value[0]);
11312     }));
11313     /* *INDENT-ON* */
11314
11315   vec_sort_with_function (sort_me, macro_sort_cmp);
11316
11317   if (vec_len (sort_me))
11318     print (vam->ofp, "%-15s%s", "Name", "Value");
11319   else
11320     print (vam->ofp, "The macro table is empty...");
11321
11322   for (i = 0; i < vec_len (sort_me); i++)
11323     print (vam->ofp, "%-15s%s", sort_me[i].name, sort_me[i].value);
11324   return 0;
11325 }
11326
11327 static int
11328 dump_node_table (vat_main_t * vam)
11329 {
11330   int i, j;
11331   vlib_node_t *node, *next_node;
11332
11333   if (vec_len (vam->graph_nodes) == 0)
11334     {
11335       print (vam->ofp, "Node table empty, issue get_node_graph...");
11336       return 0;
11337     }
11338
11339   for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
11340     {
11341       node = vam->graph_nodes[0][i];
11342       print (vam->ofp, "[%d] %s", i, node->name);
11343       for (j = 0; j < vec_len (node->next_nodes); j++)
11344         {
11345           if (node->next_nodes[j] != ~0)
11346             {
11347               next_node = vam->graph_nodes[0][node->next_nodes[j]];
11348               print (vam->ofp, "  [%d] %s", j, next_node->name);
11349             }
11350         }
11351     }
11352   return 0;
11353 }
11354
11355 static int
11356 value_sort_cmp (void *a1, void *a2)
11357 {
11358   name_sort_t *n1 = a1;
11359   name_sort_t *n2 = a2;
11360
11361   if (n1->value < n2->value)
11362     return -1;
11363   if (n1->value > n2->value)
11364     return 1;
11365   return 0;
11366 }
11367
11368
11369 static int
11370 dump_msg_api_table (vat_main_t * vam)
11371 {
11372   api_main_t *am = vlibapi_get_main ();
11373   name_sort_t *nses = 0, *ns;
11374   hash_pair_t *hp;
11375   int i;
11376
11377   /* *INDENT-OFF* */
11378   hash_foreach_pair (hp, am->msg_index_by_name_and_crc,
11379   ({
11380     vec_add2 (nses, ns, 1);
11381     ns->name = (u8 *)(hp->key);
11382     ns->value = (u32) hp->value[0];
11383   }));
11384   /* *INDENT-ON* */
11385
11386   vec_sort_with_function (nses, value_sort_cmp);
11387
11388   for (i = 0; i < vec_len (nses); i++)
11389     print (vam->ofp, " [%d]: %s", nses[i].value, nses[i].name);
11390   vec_free (nses);
11391   return 0;
11392 }
11393
11394 static int
11395 get_msg_id (vat_main_t * vam)
11396 {
11397   u8 *name_and_crc;
11398   u32 message_index;
11399
11400   if (unformat (vam->input, "%s", &name_and_crc))
11401     {
11402       message_index = vl_msg_api_get_msg_index (name_and_crc);
11403       if (message_index == ~0)
11404         {
11405           print (vam->ofp, " '%s' not found", name_and_crc);
11406           return 0;
11407         }
11408       print (vam->ofp, " '%s' has message index %d",
11409              name_and_crc, message_index);
11410       return 0;
11411     }
11412   errmsg ("name_and_crc required...");
11413   return 0;
11414 }
11415
11416 static int
11417 search_node_table (vat_main_t * vam)
11418 {
11419   unformat_input_t *line_input = vam->input;
11420   u8 *node_to_find;
11421   int j;
11422   vlib_node_t *node, *next_node;
11423   uword *p;
11424
11425   if (vam->graph_node_index_by_name == 0)
11426     {
11427       print (vam->ofp, "Node table empty, issue get_node_graph...");
11428       return 0;
11429     }
11430
11431   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
11432     {
11433       if (unformat (line_input, "%s", &node_to_find))
11434         {
11435           vec_add1 (node_to_find, 0);
11436           p = hash_get_mem (vam->graph_node_index_by_name, node_to_find);
11437           if (p == 0)
11438             {
11439               print (vam->ofp, "%s not found...", node_to_find);
11440               goto out;
11441             }
11442           node = vam->graph_nodes[0][p[0]];
11443           print (vam->ofp, "[%d] %s", p[0], node->name);
11444           for (j = 0; j < vec_len (node->next_nodes); j++)
11445             {
11446               if (node->next_nodes[j] != ~0)
11447                 {
11448                   next_node = vam->graph_nodes[0][node->next_nodes[j]];
11449                   print (vam->ofp, "  [%d] %s", j, next_node->name);
11450                 }
11451             }
11452         }
11453
11454       else
11455         {
11456           clib_warning ("parse error '%U'", format_unformat_error,
11457                         line_input);
11458           return -99;
11459         }
11460
11461     out:
11462       vec_free (node_to_find);
11463
11464     }
11465
11466   return 0;
11467 }
11468
11469
11470 static int
11471 script (vat_main_t * vam)
11472 {
11473 #if (VPP_API_TEST_BUILTIN==0)
11474   u8 *s = 0;
11475   char *save_current_file;
11476   unformat_input_t save_input;
11477   jmp_buf save_jump_buf;
11478   u32 save_line_number;
11479
11480   FILE *new_fp, *save_ifp;
11481
11482   if (unformat (vam->input, "%s", &s))
11483     {
11484       new_fp = fopen ((char *) s, "r");
11485       if (new_fp == 0)
11486         {
11487           errmsg ("Couldn't open script file %s", s);
11488           vec_free (s);
11489           return -99;
11490         }
11491     }
11492   else
11493     {
11494       errmsg ("Missing script name");
11495       return -99;
11496     }
11497
11498   clib_memcpy (&save_input, &vam->input, sizeof (save_input));
11499   clib_memcpy (&save_jump_buf, &vam->jump_buf, sizeof (save_jump_buf));
11500   save_ifp = vam->ifp;
11501   save_line_number = vam->input_line_number;
11502   save_current_file = (char *) vam->current_file;
11503
11504   vam->input_line_number = 0;
11505   vam->ifp = new_fp;
11506   vam->current_file = s;
11507   do_one_file (vam);
11508
11509   clib_memcpy (&vam->input, &save_input, sizeof (save_input));
11510   clib_memcpy (&vam->jump_buf, &save_jump_buf, sizeof (save_jump_buf));
11511   vam->ifp = save_ifp;
11512   vam->input_line_number = save_line_number;
11513   vam->current_file = (u8 *) save_current_file;
11514   vec_free (s);
11515
11516   return 0;
11517 #else
11518   clib_warning ("use the exec command...");
11519   return -99;
11520 #endif
11521 }
11522
11523 static int
11524 echo (vat_main_t * vam)
11525 {
11526   print (vam->ofp, "%v", vam->input->buffer);
11527   return 0;
11528 }
11529
11530 /* List of API message constructors, CLI names map to api_xxx */
11531 #define foreach_vpe_api_msg                                             \
11532 _(create_loopback,"[mac <mac-addr>] [instance <instance>]")             \
11533 _(sw_interface_dump,"")                                                 \
11534 _(sw_interface_set_flags,                                               \
11535   "<intfc> | sw_if_index <id> admin-up | admin-down link-up | link down") \
11536 _(sw_interface_add_del_address,                                         \
11537   "<intfc> | sw_if_index <id> <ip4-address> | <ip6-address> [del] [del-all] ") \
11538 _(sw_interface_set_rx_mode,                                             \
11539   "<intfc> | sw_if_index <id> [queue <id>] <polling | interrupt | adaptive>") \
11540 _(sw_interface_set_rx_placement,                                        \
11541   "<intfc> | sw_if_index <id> [queue <id>] [worker <id> | main]")       \
11542 _(sw_interface_rx_placement_dump,                                       \
11543   "[<intfc> | sw_if_index <id>]")                                         \
11544 _(sw_interface_set_table,                                               \
11545   "<intfc> | sw_if_index <id> vrf <table-id> [ipv6]")                   \
11546 _(sw_interface_set_mpls_enable,                                         \
11547   "<intfc> | sw_if_index [disable | dis]")                              \
11548 _(sw_interface_set_vpath,                                               \
11549   "<intfc> | sw_if_index <id> enable | disable")                        \
11550 _(sw_interface_set_l2_xconnect,                                         \
11551   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
11552   "enable | disable")                                                   \
11553 _(sw_interface_set_l2_bridge,                                           \
11554   "{<intfc> | sw_if_index <id>} bd_id <bridge-domain-id>\n"             \
11555   "[shg <split-horizon-group>] [bvi]\n"                                 \
11556   "enable | disable")                                                   \
11557 _(bridge_domain_set_mac_age, "bd_id <bridge-domain-id> mac-age 0-255")  \
11558 _(bridge_domain_add_del,                                                \
11559   "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") \
11560 _(bridge_domain_dump, "[bd_id <bridge-domain-id>]\n")                   \
11561 _(l2fib_add_del,                                                        \
11562   "mac <mac-addr> bd_id <bridge-domain-id> [del] | sw_if <intfc> | sw_if_index <id> [static] [filter] [bvi] [count <nn>]\n") \
11563 _(l2fib_flush_bd, "bd_id <bridge-domain-id>")                           \
11564 _(l2fib_flush_int, "<intfc> | sw_if_index <id>")                        \
11565 _(l2_flags,                                                             \
11566   "sw_if <intfc> | sw_if_index <id> [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \
11567 _(bridge_flags,                                                         \
11568   "bd_id <bridge-domain-id> [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \
11569 _(tap_create_v2,                                                        \
11570   "id <num> [hw-addr <mac-addr>] [host-if-name <name>] [host-ns <name>] [num-rx-queues <num>] [rx-ring-size <num>] [tx-ring-size <num>] [host-bridge <name>] [host-mac-addr <mac-addr>] [host-ip4-addr <ip4addr/mask>] [host-ip6-addr <ip6addr/mask>] [host-mtu-size <mtu>] [gso | no-gso | csum-offload | gro-coalesce] [persist] [attach] [tun] [packed] [in-order]") \
11571 _(tap_delete_v2,                                                        \
11572   "<vpp-if-name> | sw_if_index <id>")                                   \
11573 _(sw_interface_tap_v2_dump, "")                                         \
11574 _(virtio_pci_create_v2,                                                    \
11575   "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]") \
11576 _(virtio_pci_delete,                                                    \
11577   "<vpp-if-name> | sw_if_index <id>")                                   \
11578 _(sw_interface_virtio_pci_dump, "")                                     \
11579 _(bond_create,                                                          \
11580   "[hw-addr <mac-addr>] {round-robin | active-backup | "                \
11581   "broadcast | {lacp | xor} [load-balance { l2 | l23 | l34 }]} "        \
11582   "[id <if-id>]")                                                       \
11583 _(bond_create2,                                                         \
11584   "[hw-addr <mac-addr>] {mode round-robin | active-backup | "           \
11585   "broadcast | {lacp | xor} [load-balance { l2 | l23 | l34 }]} "        \
11586   "[id <if-id>] [gso]")                                                 \
11587 _(bond_delete,                                                          \
11588   "<vpp-if-name> | sw_if_index <id>")                                   \
11589 _(bond_add_member,                                                      \
11590   "sw_if_index <n> bond <sw_if_index> [is_passive] [is_long_timeout]")  \
11591 _(bond_detach_member,                                                   \
11592   "sw_if_index <n>")                                                    \
11593  _(sw_interface_set_bond_weight, "<intfc> | sw_if_index <nn> weight <value>") \
11594  _(sw_bond_interface_dump, "<intfc> | sw_if_index <nn>")                \
11595  _(sw_member_interface_dump,                                            \
11596   "<vpp-if-name> | sw_if_index <id>")                                   \
11597 _(ip_table_add_del,                                                     \
11598   "table <n> [ipv6] [add | del]\n")                                     \
11599 _(ip_route_add_del,                                                     \
11600   "<addr>/<mask> via <<addr>|<intfc>|sw_if_index <id>|via-label <n>>\n" \
11601   "[table-id <n>] [<intfc> | sw_if_index <id>] [resolve-attempts <n>]\n"\
11602   "[weight <n>] [drop] [local] [classify <n>]  [out-label <n>]\n"       \
11603   "[multipath] [count <n>] [del]")                                      \
11604 _(ip_mroute_add_del,                                                    \
11605   "<src> <grp>/<mask> [table-id <n>]\n"                                 \
11606   "[<intfc> | sw_if_index <id>] [local] [del]")                         \
11607 _(mpls_table_add_del,                                                   \
11608   "table <n> [add | del]\n")                                            \
11609 _(mpls_route_add_del,                                                   \
11610   "<label> <eos> via <addr | next-hop-table <n> | via-label <n> |\n"    \
11611   "lookup-ip4-table <n> | lookup-in-ip6-table <n> |\n"                  \
11612   "l2-input-on <intfc> | l2-input-on sw_if_index <id>>\n"               \
11613   "[<intfc> | sw_if_index <id>] [resolve-attempts <n>] [weight <n>]\n"  \
11614   "[drop] [local] [classify <n>] [out-label <n>] [multipath]\n"         \
11615   "[count <n>] [del]")                                                  \
11616 _(mpls_ip_bind_unbind,                                                  \
11617   "<label> <addr/len>")                                                 \
11618 _(mpls_tunnel_add_del,                                                  \
11619   "[add | del <intfc | sw_if_index <id>>] via <addr | via-label <n>>\n" \
11620   "[<intfc> | sw_if_index <id> | next-hop-table <id>]\n"                \
11621   "[l2-only]  [out-label <n>]")                                         \
11622 _(sr_mpls_policy_add,                                                   \
11623   "bsid <id> [weight <n>] [spray] next <sid> [next <sid>]")             \
11624 _(sr_mpls_policy_del,                                                   \
11625   "bsid <id>")                                                          \
11626 _(sw_interface_set_unnumbered,                                          \
11627   "<intfc> | sw_if_index <id> unnum_if_index <id> [del]")               \
11628 _(create_vlan_subif, "<intfc> | sw_if_index <id> vlan <n>")             \
11629 _(create_subif, "<intfc> | sw_if_index <id> sub_id <n>\n"               \
11630   "[outer_vlan_id <n>][inner_vlan_id <n>]\n"                            \
11631   "[no_tags][one_tag][two_tags][dot1ad][exact_match][default_sub]\n"    \
11632   "[outer_vlan_id_any][inner_vlan_id_any]")                             \
11633 _(ip_table_replace_begin, "table <n> [ipv6]")                           \
11634 _(ip_table_flush, "table <n> [ipv6]")                                   \
11635 _(ip_table_replace_end, "table <n> [ipv6]")                             \
11636 _(set_ip_flow_hash,                                                     \
11637   "vrf <n> [src] [dst] [sport] [dport] [proto] [reverse] [ipv6]")       \
11638 _(sw_interface_ip6_enable_disable,                                      \
11639   "<intfc> | sw_if_index <id> enable | disable")                        \
11640 _(l2_patch_add_del,                                                     \
11641   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
11642   "enable | disable")                                                   \
11643 _(sr_localsid_add_del,                                                  \
11644   "(del) address <addr> next_hop <addr> behavior <beh>\n"               \
11645   "fib-table <num> (end.psp) sw_if_index <num>")                        \
11646 _(get_node_index, "node <node-name")                                    \
11647 _(add_node_next, "node <node-name> next <next-node-name>")              \
11648 _(l2_fib_clear_table, "")                                               \
11649 _(l2_interface_efp_filter, "sw_if_index <nn> enable | disable")         \
11650 _(l2_interface_vlan_tag_rewrite,                                        \
11651   "<intfc> | sw_if_index <nn> \n"                                       \
11652   "[disable][push-[1|2]][pop-[1|2]][translate-1-[1|2]] \n"              \
11653   "[translate-2-[1|2]] [push_dot1q 0] tag1 <nn> tag2 <nn>")             \
11654 _(create_vhost_user_if,                                                 \
11655         "socket <filename> [server] [renumber <dev_instance>] "         \
11656         "[disable_mrg_rxbuf] [disable_indirect_desc] [gso] "            \
11657         "[mac <mac_address>] [packed]")                                 \
11658 _(modify_vhost_user_if,                                                 \
11659         "<intfc> | sw_if_index <nn> socket <filename>\n"                \
11660         "[server] [renumber <dev_instance>] [gso] [packed]")            \
11661 _(create_vhost_user_if_v2,                                              \
11662         "socket <filename> [server] [renumber <dev_instance>] "         \
11663         "[disable_mrg_rxbuf] [disable_indirect_desc] [gso] "            \
11664         "[mac <mac_address>] [packed] [event-idx]")                     \
11665 _(modify_vhost_user_if_v2,                                              \
11666         "<intfc> | sw_if_index <nn> socket <filename>\n"                \
11667         "[server] [renumber <dev_instance>] [gso] [packed] [event-idx]")\
11668 _(delete_vhost_user_if, "<intfc> | sw_if_index <nn>")                   \
11669 _(sw_interface_vhost_user_dump, "<intfc> | sw_if_index <nn>")           \
11670 _(show_version, "")                                                     \
11671 _(show_threads, "")                                                     \
11672 _(l2_fib_table_dump, "bd_id <bridge-domain-id>")                        \
11673 _(interface_name_renumber,                                              \
11674   "<intfc> | sw_if_index <nn> new_show_dev_instance <nn>")              \
11675 _(want_l2_macs_events, "[disable] [learn-limit <n>] [scan-delay <n>] [max-entries <n>]") \
11676 _(ip_address_dump, "(ipv4 | ipv6) (<intfc> | sw_if_index <id>)")        \
11677 _(ip_dump, "ipv4 | ipv6")                                               \
11678 _(ipsec_spd_add_del, "spd_id <n> [del]")                                \
11679 _(ipsec_interface_add_del_spd, "(<intfc> | sw_if_index <id>)\n"         \
11680   "  spid_id <n> ")                                                     \
11681 _(ipsec_sad_entry_add_del, "sad_id <n> spi <n> crypto_alg <alg>\n"      \
11682   "  crypto_key <hex> tunnel_src <ip4|ip6> tunnel_dst <ip4|ip6>\n"      \
11683   "  integ_alg <alg> integ_key <hex>")                                  \
11684 _(ipsec_spd_entry_add_del, "spd_id <n> priority <n> action <action>\n"  \
11685   "  (inbound|outbound) [sa_id <n>] laddr_start <ip4|ip6>\n"            \
11686   "  laddr_stop <ip4|ip6> raddr_start <ip4|ip6> raddr_stop <ip4|ip6>\n" \
11687   "  [lport_start <n> lport_stop <n>] [rport_start <n> rport_stop <n>]" ) \
11688 _(ipsec_sa_dump, "[sa_id <n>]")                                         \
11689 _(delete_loopback,"sw_if_index <nn>")                                   \
11690 _(bd_ip_mac_add_del, "bd_id <bridge-domain-id> <ip4/6-addr> <mac-addr> [del]") \
11691 _(bd_ip_mac_flush, "bd_id <bridge-domain-id>")                          \
11692 _(bd_ip_mac_dump, "[bd_id] <bridge-domain-id>")                         \
11693 _(want_interface_events,  "enable|disable")                             \
11694 _(get_first_msg_id, "client <name>")                                    \
11695 _(get_node_graph, " ")                                                  \
11696 _(sw_interface_clear_stats,"<intfc> | sw_if_index <nn>")                \
11697 _(ioam_enable, "[trace] [pow] [ppc <encap|decap>]")                     \
11698 _(ioam_disable, "")                                                     \
11699 _(af_packet_create, "name <host interface name> [hw_addr <mac>]")       \
11700 _(af_packet_delete, "name <host interface name>")                       \
11701 _(af_packet_dump, "")                                                   \
11702 _(mpls_tunnel_dump, "tunnel_index <tunnel-id>")                         \
11703 _(mpls_table_dump, "")                                                  \
11704 _(mpls_route_dump, "table-id <ID>")                                     \
11705 _(sw_interface_span_enable_disable, "[l2] [src <intfc> | src_sw_if_index <id>] [disable | [[dst <intfc> | dst_sw_if_index <id>] [both|rx|tx]]]") \
11706 _(sw_interface_span_dump, "[l2]")                                           \
11707 _(get_next_index, "node-name <node-name> next-node-name <node-name>")   \
11708 _(ip_source_and_port_range_check_add_del,                               \
11709   "<ip-addr>/<mask> range <nn>-<nn> vrf <id>")                          \
11710 _(ip_source_and_port_range_check_interface_add_del,                     \
11711   "<intf> | sw_if_index <nn> [tcp-out-vrf <id>] [tcp-in-vrf <id>]"      \
11712   "[udp-in-vrf <id>] [udp-out-vrf <id>]")                               \
11713 _(delete_subif,"<intfc> | sw_if_index <nn>")                            \
11714 _(l2_interface_pbb_tag_rewrite,                                         \
11715   "<intfc> | sw_if_index <nn> \n"                                       \
11716   "[disable | push | pop | translate_pbb_stag <outer_tag>] \n"          \
11717   "dmac <mac> smac <mac> sid <nn> [vlanid <nn>]")                       \
11718 _(set_punt, "protocol <l4-protocol> [ip <ver>] [port <l4-port>] [del]")     \
11719 _(ip_table_dump, "")                                                    \
11720 _(ip_route_dump, "table-id [ip4|ip6]")                                  \
11721 _(ip_mtable_dump, "")                                                   \
11722 _(ip_mroute_dump, "table-id [ip4|ip6]")                                 \
11723 _(sw_interface_tag_add_del, "<intfc> | sw_if_index <nn> tag <text>"     \
11724 "[disable]")                                                            \
11725 _(sw_interface_add_del_mac_address, "<intfc> | sw_if_index <nn> "       \
11726   "mac <mac-address> [del]")                                            \
11727 _(l2_xconnect_dump, "")                                                 \
11728 _(hw_interface_set_mtu, "<intfc> | hw_if_index <nn> mtu <nn>")        \
11729 _(sw_interface_get_table, "<intfc> | sw_if_index <id> [ipv6]")          \
11730 _(tcp_configure_src_addresses, "<ip4|6>first-<ip4|6>last [vrf <id>]")   \
11731 _(sock_init_shm, "size <nnn>")                                          \
11732 _(app_namespace_add_del, "[add] id <ns-id> secret <nn> sw_if_index <nn>")\
11733 _(session_rule_add_del, "[add|del] proto <tcp/udp> <lcl-ip>/<plen> "    \
11734   "<lcl-port> <rmt-ip>/<plen> <rmt-port> action <nn>")                  \
11735 _(session_rules_dump, "")                                               \
11736 _(ip_container_proxy_add_del, "[add|del] <address> <sw_if_index>")      \
11737 _(qos_record_enable_disable, "<record-source> <intfc> | sw_if_index <id> [disable]")
11738
11739 /* List of command functions, CLI names map directly to functions */
11740 #define foreach_cli_function                                    \
11741 _(comment, "usage: comment <ignore-rest-of-line>")              \
11742 _(dump_interface_table, "usage: dump_interface_table")          \
11743 _(dump_sub_interface_table, "usage: dump_sub_interface_table")  \
11744 _(dump_ipv4_table, "usage: dump_ipv4_table")                    \
11745 _(dump_ipv6_table, "usage: dump_ipv6_table")                    \
11746 _(dump_macro_table, "usage: dump_macro_table ")                 \
11747 _(dump_node_table, "usage: dump_node_table")                    \
11748 _(dump_msg_api_table, "usage: dump_msg_api_table")              \
11749 _(elog_setup, "usage: elog_setup [nevents, default 128K]")      \
11750 _(elog_disable, "usage: elog_disable")                          \
11751 _(elog_enable, "usage: elog_enable")                            \
11752 _(elog_save, "usage: elog_save <filename>")                     \
11753 _(get_msg_id, "usage: get_msg_id name_and_crc")                 \
11754 _(echo, "usage: echo <message>")                                \
11755 _(exec, "usage: exec <vpe-debug-CLI-command>")                  \
11756 _(exec_inband, "usage: exec_inband <vpe-debug-CLI-command>")    \
11757 _(help, "usage: help")                                          \
11758 _(q, "usage: quit")                                             \
11759 _(quit, "usage: quit")                                          \
11760 _(search_node_table, "usage: search_node_table <name>...")      \
11761 _(set, "usage: set <variable-name> <value>")                    \
11762 _(script, "usage: script <file-name>")                          \
11763 _(statseg, "usage: statseg")                                    \
11764 _(unset, "usage: unset <variable-name>")
11765
11766 #define _(N,n)                                  \
11767     static void vl_api_##n##_t_handler_uni      \
11768     (vl_api_##n##_t * mp)                       \
11769     {                                           \
11770         vat_main_t * vam = &vat_main;           \
11771         if (vam->json_output) {                 \
11772             vl_api_##n##_t_handler_json(mp);    \
11773         } else {                                \
11774             vl_api_##n##_t_handler(mp);         \
11775         }                                       \
11776     }
11777 foreach_vpe_api_reply_msg;
11778 #if VPP_API_TEST_BUILTIN == 0
11779 foreach_standalone_reply_msg;
11780 #endif
11781 #undef _
11782
11783 void
11784 vat_api_hookup (vat_main_t * vam)
11785 {
11786 #define _(N,n)                                                  \
11787     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
11788                            vl_api_##n##_t_handler_uni,          \
11789                            vl_noop_handler,                     \
11790                            vl_api_##n##_t_endian,               \
11791                            vl_api_##n##_t_print,                \
11792                            sizeof(vl_api_##n##_t), 1);
11793   foreach_vpe_api_reply_msg;
11794 #if VPP_API_TEST_BUILTIN == 0
11795   foreach_standalone_reply_msg;
11796 #endif
11797 #undef _
11798
11799 #if (VPP_API_TEST_BUILTIN==0)
11800   vl_msg_api_set_first_available_msg_id (VL_MSG_FIRST_AVAILABLE);
11801
11802   vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
11803
11804   vam->function_by_name = hash_create_string (0, sizeof (uword));
11805
11806   vam->help_by_name = hash_create_string (0, sizeof (uword));
11807 #endif
11808
11809   /* API messages we can send */
11810 #define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
11811   foreach_vpe_api_msg;
11812 #undef _
11813
11814   /* Help strings */
11815 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
11816   foreach_vpe_api_msg;
11817 #undef _
11818
11819   /* CLI functions */
11820 #define _(n,h) hash_set_mem (vam->function_by_name, #n, n);
11821   foreach_cli_function;
11822 #undef _
11823
11824   /* Help strings */
11825 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
11826   foreach_cli_function;
11827 #undef _
11828 }
11829
11830 #if VPP_API_TEST_BUILTIN
11831 static clib_error_t *
11832 vat_api_hookup_shim (vlib_main_t * vm)
11833 {
11834   vat_api_hookup (&vat_main);
11835   return 0;
11836 }
11837
11838 VLIB_API_INIT_FUNCTION (vat_api_hookup_shim);
11839 #endif
11840
11841 /*
11842  * fd.io coding-style-patch-verification: ON
11843  *
11844  * Local Variables:
11845  * eval: (c-set-style "gnu")
11846  * End:
11847  */