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