tcp: 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 _(session_rule_add_del_reply)                           \
1915 _(ip_container_proxy_add_del_reply)                     \
1916
1917 #define _(n)                                    \
1918     static void vl_api_##n##_t_handler          \
1919     (vl_api_##n##_t * mp)                       \
1920     {                                           \
1921         vat_main_t * vam = &vat_main;           \
1922         i32 retval = ntohl(mp->retval);         \
1923         if (vam->async_mode) {                  \
1924             vam->async_errors += (retval < 0);  \
1925         } else {                                \
1926             vam->retval = retval;               \
1927             vam->result_ready = 1;              \
1928         }                                       \
1929     }
1930 foreach_standard_reply_retval_handler;
1931 #undef _
1932
1933 #define _(n)                                    \
1934     static void vl_api_##n##_t_handler_json     \
1935     (vl_api_##n##_t * mp)                       \
1936     {                                           \
1937         vat_main_t * vam = &vat_main;           \
1938         vat_json_node_t node;                   \
1939         vat_json_init_object(&node);            \
1940         vat_json_object_add_int(&node, "retval", ntohl(mp->retval));    \
1941         vat_json_print(vam->ofp, &node);        \
1942         vam->retval = ntohl(mp->retval);        \
1943         vam->result_ready = 1;                  \
1944     }
1945 foreach_standard_reply_retval_handler;
1946 #undef _
1947
1948 /*
1949  * Table of message reply handlers, must include boilerplate handlers
1950  * we just generated
1951  */
1952
1953 #define foreach_vpe_api_reply_msg                                       \
1954 _(CREATE_LOOPBACK_REPLY, create_loopback_reply)                         \
1955 _(CREATE_LOOPBACK_INSTANCE_REPLY, create_loopback_instance_reply)       \
1956 _(SW_INTERFACE_DETAILS, sw_interface_details)                           \
1957 _(SW_INTERFACE_SET_FLAGS_REPLY, sw_interface_set_flags_reply)           \
1958 _(CONTROL_PING_REPLY, control_ping_reply)                               \
1959 _(CLI_REPLY, cli_reply)                                                 \
1960 _(CLI_INBAND_REPLY, cli_inband_reply)                                   \
1961 _(SW_INTERFACE_ADD_DEL_ADDRESS_REPLY,                                   \
1962   sw_interface_add_del_address_reply)                                   \
1963 _(SW_INTERFACE_SET_RX_MODE_REPLY, sw_interface_set_rx_mode_reply)       \
1964 _(SW_INTERFACE_SET_RX_PLACEMENT_REPLY, sw_interface_set_rx_placement_reply)     \
1965 _(SW_INTERFACE_RX_PLACEMENT_DETAILS, sw_interface_rx_placement_details) \
1966 _(SW_INTERFACE_SET_TABLE_REPLY, sw_interface_set_table_reply)           \
1967 _(SW_INTERFACE_SET_MPLS_ENABLE_REPLY, sw_interface_set_mpls_enable_reply) \
1968 _(SW_INTERFACE_SET_VPATH_REPLY, sw_interface_set_vpath_reply)           \
1969 _(SW_INTERFACE_SET_L2_XCONNECT_REPLY,                                   \
1970   sw_interface_set_l2_xconnect_reply)                                   \
1971 _(SW_INTERFACE_SET_L2_BRIDGE_REPLY,                                     \
1972   sw_interface_set_l2_bridge_reply)                                     \
1973 _(BRIDGE_DOMAIN_ADD_DEL_REPLY, bridge_domain_add_del_reply)             \
1974 _(BRIDGE_DOMAIN_DETAILS, bridge_domain_details)                         \
1975 _(BRIDGE_DOMAIN_SET_MAC_AGE_REPLY, bridge_domain_set_mac_age_reply)     \
1976 _(L2FIB_ADD_DEL_REPLY, l2fib_add_del_reply)                             \
1977 _(L2FIB_FLUSH_INT_REPLY, l2fib_flush_int_reply)                         \
1978 _(L2FIB_FLUSH_BD_REPLY, l2fib_flush_bd_reply)                           \
1979 _(L2_FLAGS_REPLY, l2_flags_reply)                                       \
1980 _(BRIDGE_FLAGS_REPLY, bridge_flags_reply)                               \
1981 _(VIRTIO_PCI_CREATE_REPLY, virtio_pci_create_reply)                     \
1982 _(VIRTIO_PCI_CREATE_V2_REPLY, virtio_pci_create_v2_reply)               \
1983 _(VIRTIO_PCI_DELETE_REPLY, virtio_pci_delete_reply)                     \
1984 _(SW_INTERFACE_VIRTIO_PCI_DETAILS, sw_interface_virtio_pci_details)     \
1985 _(IP_ROUTE_ADD_DEL_REPLY, ip_route_add_del_reply)                       \
1986 _(IP_TABLE_ADD_DEL_REPLY, ip_table_add_del_reply)                       \
1987 _(IP_TABLE_REPLACE_BEGIN_REPLY, ip_table_replace_begin_reply)           \
1988 _(IP_TABLE_FLUSH_REPLY, ip_table_flush_reply)                           \
1989 _(IP_TABLE_REPLACE_END_REPLY, ip_table_replace_end_reply)               \
1990 _(IP_MROUTE_ADD_DEL_REPLY, ip_mroute_add_del_reply)                     \
1991 _(MPLS_TABLE_ADD_DEL_REPLY, mpls_table_add_del_reply)                   \
1992 _(MPLS_ROUTE_ADD_DEL_REPLY, mpls_route_add_del_reply)                   \
1993 _(MPLS_IP_BIND_UNBIND_REPLY, mpls_ip_bind_unbind_reply)                 \
1994 _(MPLS_TUNNEL_ADD_DEL_REPLY, mpls_tunnel_add_del_reply)                 \
1995 _(SW_INTERFACE_SET_UNNUMBERED_REPLY,                                    \
1996   sw_interface_set_unnumbered_reply)                                    \
1997 _(CREATE_VLAN_SUBIF_REPLY, create_vlan_subif_reply)                     \
1998 _(CREATE_SUBIF_REPLY, create_subif_reply)                               \
1999 _(SET_IP_FLOW_HASH_REPLY, set_ip_flow_hash_reply)                       \
2000 _(SW_INTERFACE_IP6_ENABLE_DISABLE_REPLY,                                \
2001   sw_interface_ip6_enable_disable_reply)                                \
2002 _(L2_PATCH_ADD_DEL_REPLY, l2_patch_add_del_reply)                       \
2003 _(GET_NODE_INDEX_REPLY, get_node_index_reply)                           \
2004 _(ADD_NODE_NEXT_REPLY, add_node_next_reply)                             \
2005 _(L2_FIB_CLEAR_TABLE_REPLY, l2_fib_clear_table_reply)                   \
2006 _(L2_INTERFACE_EFP_FILTER_REPLY, l2_interface_efp_filter_reply)         \
2007 _(L2_INTERFACE_VLAN_TAG_REWRITE_REPLY, l2_interface_vlan_tag_rewrite_reply) \
2008 _(SHOW_VERSION_REPLY, show_version_reply)                               \
2009 _(SHOW_THREADS_REPLY, show_threads_reply)                               \
2010 _(L2_FIB_TABLE_DETAILS, l2_fib_table_details)                           \
2011 _(INTERFACE_NAME_RENUMBER_REPLY, interface_name_renumber_reply)         \
2012 _(WANT_L2_MACS_EVENTS_REPLY, want_l2_macs_events_reply)                 \
2013 _(L2_MACS_EVENT, l2_macs_event)                                         \
2014 _(IP_ADDRESS_DETAILS, ip_address_details)                               \
2015 _(IP_DETAILS, ip_details)                                               \
2016 _(DELETE_LOOPBACK_REPLY, delete_loopback_reply)                         \
2017 _(BD_IP_MAC_ADD_DEL_REPLY, bd_ip_mac_add_del_reply)                     \
2018 _(BD_IP_MAC_FLUSH_REPLY, bd_ip_mac_flush_reply)                         \
2019 _(BD_IP_MAC_DETAILS, bd_ip_mac_details)                                 \
2020 _(WANT_INTERFACE_EVENTS_REPLY, want_interface_events_reply)             \
2021 _(GET_FIRST_MSG_ID_REPLY, get_first_msg_id_reply)                       \
2022 _(GET_NODE_GRAPH_REPLY, get_node_graph_reply)                           \
2023 _(SW_INTERFACE_CLEAR_STATS_REPLY, sw_interface_clear_stats_reply)      \
2024 _(IOAM_ENABLE_REPLY, ioam_enable_reply)                   \
2025 _(IOAM_DISABLE_REPLY, ioam_disable_reply)                     \
2026 _(MPLS_TUNNEL_DETAILS, mpls_tunnel_details)                             \
2027 _(MPLS_TABLE_DETAILS, mpls_table_details)                               \
2028 _(MPLS_ROUTE_DETAILS, mpls_route_details)                               \
2029 _(SW_INTERFACE_SPAN_ENABLE_DISABLE_REPLY, sw_interface_span_enable_disable_reply) \
2030 _(SW_INTERFACE_SPAN_DETAILS, sw_interface_span_details)                 \
2031 _(GET_NEXT_INDEX_REPLY, get_next_index_reply)                           \
2032 _(IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL_REPLY,                         \
2033  ip_source_and_port_range_check_add_del_reply)                          \
2034 _(IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL_REPLY,               \
2035  ip_source_and_port_range_check_interface_add_del_reply)                \
2036 _(DELETE_SUBIF_REPLY, delete_subif_reply)                               \
2037 _(L2_INTERFACE_PBB_TAG_REWRITE_REPLY, l2_interface_pbb_tag_rewrite_reply) \
2038 _(IP_TABLE_DETAILS, ip_table_details)                                   \
2039 _(IP_ROUTE_DETAILS, ip_route_details)                                   \
2040 _(SW_INTERFACE_TAG_ADD_DEL_REPLY, sw_interface_tag_add_del_reply)       \
2041 _(SW_INTERFACE_ADD_DEL_MAC_ADDRESS_REPLY, sw_interface_add_del_mac_address_reply) \
2042 _(L2_XCONNECT_DETAILS, l2_xconnect_details)                             \
2043 _(HW_INTERFACE_SET_MTU_REPLY, hw_interface_set_mtu_reply)               \
2044 _(SW_INTERFACE_GET_TABLE_REPLY, sw_interface_get_table_reply)           \
2045 _(APP_NAMESPACE_ADD_DEL_REPLY, app_namespace_add_del_reply)             \
2046 _(SESSION_RULE_ADD_DEL_REPLY, session_rule_add_del_reply)               \
2047 _(SESSION_RULES_DETAILS, session_rules_details)                         \
2048 _(IP_CONTAINER_PROXY_ADD_DEL_REPLY, ip_container_proxy_add_del_reply)   \
2049
2050 #define foreach_standalone_reply_msg                                    \
2051 _(SW_INTERFACE_EVENT, sw_interface_event)
2052
2053 typedef struct
2054 {
2055   u8 *name;
2056   u32 value;
2057 } name_sort_t;
2058
2059 #define STR_VTR_OP_CASE(op)     \
2060     case L2_VTR_ ## op:         \
2061         return "" # op;
2062
2063 static const char *
2064 str_vtr_op (u32 vtr_op)
2065 {
2066   switch (vtr_op)
2067     {
2068       STR_VTR_OP_CASE (DISABLED);
2069       STR_VTR_OP_CASE (PUSH_1);
2070       STR_VTR_OP_CASE (PUSH_2);
2071       STR_VTR_OP_CASE (POP_1);
2072       STR_VTR_OP_CASE (POP_2);
2073       STR_VTR_OP_CASE (TRANSLATE_1_1);
2074       STR_VTR_OP_CASE (TRANSLATE_1_2);
2075       STR_VTR_OP_CASE (TRANSLATE_2_1);
2076       STR_VTR_OP_CASE (TRANSLATE_2_2);
2077     }
2078
2079   return "UNKNOWN";
2080 }
2081
2082 static int
2083 dump_sub_interface_table (vat_main_t * vam)
2084 {
2085   const sw_interface_subif_t *sub = NULL;
2086
2087   if (vam->json_output)
2088     {
2089       clib_warning
2090         ("JSON output supported only for VPE API calls and dump_stats_table");
2091       return -99;
2092     }
2093
2094   print (vam->ofp,
2095          "%-30s%-12s%-11s%-7s%-5s%-9s%-9s%-6s%-8s%-10s%-10s",
2096          "Interface", "sw_if_index",
2097          "sub id", "dot1ad", "tags", "outer id",
2098          "inner id", "exact", "default", "outer any", "inner any");
2099
2100   vec_foreach (sub, vam->sw_if_subif_table)
2101   {
2102     print (vam->ofp,
2103            "%-30s%-12d%-11d%-7s%-5d%-9d%-9d%-6d%-8d%-10d%-10d",
2104            sub->interface_name,
2105            sub->sw_if_index,
2106            sub->sub_id, sub->sub_dot1ad ? "dot1ad" : "dot1q",
2107            sub->sub_number_of_tags, sub->sub_outer_vlan_id,
2108            sub->sub_inner_vlan_id, sub->sub_exact_match, sub->sub_default,
2109            sub->sub_outer_vlan_id_any, sub->sub_inner_vlan_id_any);
2110     if (sub->vtr_op != L2_VTR_DISABLED)
2111       {
2112         print (vam->ofp,
2113                "  vlan-tag-rewrite - op: %-14s [ dot1q: %d "
2114                "tag1: %d tag2: %d ]",
2115                str_vtr_op (sub->vtr_op), sub->vtr_push_dot1q,
2116                sub->vtr_tag1, sub->vtr_tag2);
2117       }
2118   }
2119
2120   return 0;
2121 }
2122
2123 static int
2124 name_sort_cmp (void *a1, void *a2)
2125 {
2126   name_sort_t *n1 = a1;
2127   name_sort_t *n2 = a2;
2128
2129   return strcmp ((char *) n1->name, (char *) n2->name);
2130 }
2131
2132 static int
2133 dump_interface_table (vat_main_t * vam)
2134 {
2135   hash_pair_t *p;
2136   name_sort_t *nses = 0, *ns;
2137
2138   if (vam->json_output)
2139     {
2140       clib_warning
2141         ("JSON output supported only for VPE API calls and dump_stats_table");
2142       return -99;
2143     }
2144
2145   /* *INDENT-OFF* */
2146   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
2147   ({
2148     vec_add2 (nses, ns, 1);
2149     ns->name = (u8 *)(p->key);
2150     ns->value = (u32) p->value[0];
2151   }));
2152   /* *INDENT-ON* */
2153
2154   vec_sort_with_function (nses, name_sort_cmp);
2155
2156   print (vam->ofp, "%-25s%-15s", "Interface", "sw_if_index");
2157   vec_foreach (ns, nses)
2158   {
2159     print (vam->ofp, "%-25s%-15d", ns->name, ns->value);
2160   }
2161   vec_free (nses);
2162   return 0;
2163 }
2164
2165 static int
2166 dump_ip_table (vat_main_t * vam, int is_ipv6)
2167 {
2168   const ip_details_t *det = NULL;
2169   const ip_address_details_t *address = NULL;
2170   u32 i = ~0;
2171
2172   print (vam->ofp, "%-12s", "sw_if_index");
2173
2174   vec_foreach (det, vam->ip_details_by_sw_if_index[is_ipv6])
2175   {
2176     i++;
2177     if (!det->present)
2178       {
2179         continue;
2180       }
2181     print (vam->ofp, "%-12d", i);
2182     print (vam->ofp, "            %-30s%-13s", "Address", "Prefix length");
2183     if (!det->addr)
2184       {
2185         continue;
2186       }
2187     vec_foreach (address, det->addr)
2188     {
2189       print (vam->ofp,
2190              "            %-30U%-13d",
2191              is_ipv6 ? format_ip6_address : format_ip4_address,
2192              address->ip, address->prefix_length);
2193     }
2194   }
2195
2196   return 0;
2197 }
2198
2199 static int
2200 dump_ipv4_table (vat_main_t * vam)
2201 {
2202   if (vam->json_output)
2203     {
2204       clib_warning
2205         ("JSON output supported only for VPE API calls and dump_stats_table");
2206       return -99;
2207     }
2208
2209   return dump_ip_table (vam, 0);
2210 }
2211
2212 static int
2213 dump_ipv6_table (vat_main_t * vam)
2214 {
2215   if (vam->json_output)
2216     {
2217       clib_warning
2218         ("JSON output supported only for VPE API calls and dump_stats_table");
2219       return -99;
2220     }
2221
2222   return dump_ip_table (vam, 1);
2223 }
2224
2225 /*
2226  * Pass CLI buffers directly in the CLI_INBAND API message,
2227  * instead of an additional shared memory area.
2228  */
2229 static int
2230 exec_inband (vat_main_t * vam)
2231 {
2232   vl_api_cli_inband_t *mp;
2233   unformat_input_t *i = vam->input;
2234   int ret;
2235
2236   if (vec_len (i->buffer) == 0)
2237     return -1;
2238
2239   if (vam->exec_mode == 0 && unformat (i, "mode"))
2240     {
2241       vam->exec_mode = 1;
2242       return 0;
2243     }
2244   if (vam->exec_mode == 1 && (unformat (i, "exit") || unformat (i, "quit")))
2245     {
2246       vam->exec_mode = 0;
2247       return 0;
2248     }
2249
2250   /*
2251    * In order for the CLI command to work, it
2252    * must be a vector ending in \n, not a C-string ending
2253    * in \n\0.
2254    */
2255   M2 (CLI_INBAND, mp, vec_len (vam->input->buffer));
2256   vl_api_vec_to_api_string (vam->input->buffer, &mp->cmd);
2257
2258   S (mp);
2259   W (ret);
2260   /* json responses may or may not include a useful reply... */
2261   if (vec_len (vam->cmd_reply))
2262     print (vam->ofp, "%v", (char *) (vam->cmd_reply));
2263   return ret;
2264 }
2265
2266 int
2267 exec (vat_main_t * vam)
2268 {
2269   return exec_inband (vam);
2270 }
2271
2272 static int
2273 api_create_loopback (vat_main_t * vam)
2274 {
2275   unformat_input_t *i = vam->input;
2276   vl_api_create_loopback_t *mp;
2277   vl_api_create_loopback_instance_t *mp_lbi;
2278   u8 mac_address[6];
2279   u8 mac_set = 0;
2280   u8 is_specified = 0;
2281   u32 user_instance = 0;
2282   int ret;
2283
2284   clib_memset (mac_address, 0, sizeof (mac_address));
2285
2286   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2287     {
2288       if (unformat (i, "mac %U", unformat_ethernet_address, mac_address))
2289         mac_set = 1;
2290       if (unformat (i, "instance %d", &user_instance))
2291         is_specified = 1;
2292       else
2293         break;
2294     }
2295
2296   if (is_specified)
2297     {
2298       M (CREATE_LOOPBACK_INSTANCE, mp_lbi);
2299       mp_lbi->is_specified = is_specified;
2300       if (is_specified)
2301         mp_lbi->user_instance = htonl (user_instance);
2302       if (mac_set)
2303         clib_memcpy (mp_lbi->mac_address, mac_address, sizeof (mac_address));
2304       S (mp_lbi);
2305     }
2306   else
2307     {
2308       /* Construct the API message */
2309       M (CREATE_LOOPBACK, mp);
2310       if (mac_set)
2311         clib_memcpy (mp->mac_address, mac_address, sizeof (mac_address));
2312       S (mp);
2313     }
2314
2315   W (ret);
2316   return ret;
2317 }
2318
2319 static int
2320 api_delete_loopback (vat_main_t * vam)
2321 {
2322   unformat_input_t *i = vam->input;
2323   vl_api_delete_loopback_t *mp;
2324   u32 sw_if_index = ~0;
2325   int ret;
2326
2327   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2328     {
2329       if (unformat (i, "sw_if_index %d", &sw_if_index))
2330         ;
2331       else
2332         break;
2333     }
2334
2335   if (sw_if_index == ~0)
2336     {
2337       errmsg ("missing sw_if_index");
2338       return -99;
2339     }
2340
2341   /* Construct the API message */
2342   M (DELETE_LOOPBACK, mp);
2343   mp->sw_if_index = ntohl (sw_if_index);
2344
2345   S (mp);
2346   W (ret);
2347   return ret;
2348 }
2349
2350 static int
2351 api_want_interface_events (vat_main_t * vam)
2352 {
2353   unformat_input_t *i = vam->input;
2354   vl_api_want_interface_events_t *mp;
2355   int enable = -1;
2356   int ret;
2357
2358   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2359     {
2360       if (unformat (i, "enable"))
2361         enable = 1;
2362       else if (unformat (i, "disable"))
2363         enable = 0;
2364       else
2365         break;
2366     }
2367
2368   if (enable == -1)
2369     {
2370       errmsg ("missing enable|disable");
2371       return -99;
2372     }
2373
2374   M (WANT_INTERFACE_EVENTS, mp);
2375   mp->enable_disable = enable;
2376
2377   vam->interface_event_display = enable;
2378
2379   S (mp);
2380   W (ret);
2381   return ret;
2382 }
2383
2384
2385 /* Note: non-static, called once to set up the initial intfc table */
2386 int
2387 api_sw_interface_dump (vat_main_t * vam)
2388 {
2389   vl_api_sw_interface_dump_t *mp;
2390   vl_api_control_ping_t *mp_ping;
2391   hash_pair_t *p;
2392   name_sort_t *nses = 0, *ns;
2393   sw_interface_subif_t *sub = NULL;
2394   int ret;
2395
2396   /* Toss the old name table */
2397   /* *INDENT-OFF* */
2398   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
2399   ({
2400     vec_add2 (nses, ns, 1);
2401     ns->name = (u8 *)(p->key);
2402     ns->value = (u32) p->value[0];
2403   }));
2404   /* *INDENT-ON* */
2405
2406   hash_free (vam->sw_if_index_by_interface_name);
2407
2408   vec_foreach (ns, nses) vec_free (ns->name);
2409
2410   vec_free (nses);
2411
2412   vec_foreach (sub, vam->sw_if_subif_table)
2413   {
2414     vec_free (sub->interface_name);
2415   }
2416   vec_free (vam->sw_if_subif_table);
2417
2418   /* recreate the interface name hash table */
2419   vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
2420
2421   /*
2422    * Ask for all interface names. Otherwise, the epic catalog of
2423    * name filters becomes ridiculously long, and vat ends up needing
2424    * to be taught about new interface types.
2425    */
2426   M (SW_INTERFACE_DUMP, mp);
2427   S (mp);
2428
2429   /* Use a control ping for synchronization */
2430   MPING (CONTROL_PING, mp_ping);
2431   S (mp_ping);
2432
2433   W (ret);
2434   return ret;
2435 }
2436
2437 static int
2438 api_sw_interface_set_flags (vat_main_t * vam)
2439 {
2440   unformat_input_t *i = vam->input;
2441   vl_api_sw_interface_set_flags_t *mp;
2442   u32 sw_if_index;
2443   u8 sw_if_index_set = 0;
2444   u8 admin_up = 0;
2445   int ret;
2446
2447   /* Parse args required to build the message */
2448   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2449     {
2450       if (unformat (i, "admin-up"))
2451         admin_up = 1;
2452       else if (unformat (i, "admin-down"))
2453         admin_up = 0;
2454       else
2455         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2456         sw_if_index_set = 1;
2457       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2458         sw_if_index_set = 1;
2459       else
2460         break;
2461     }
2462
2463   if (sw_if_index_set == 0)
2464     {
2465       errmsg ("missing interface name or sw_if_index");
2466       return -99;
2467     }
2468
2469   /* Construct the API message */
2470   M (SW_INTERFACE_SET_FLAGS, mp);
2471   mp->sw_if_index = ntohl (sw_if_index);
2472   mp->flags = ntohl ((admin_up) ? IF_STATUS_API_FLAG_ADMIN_UP : 0);
2473
2474   /* send it... */
2475   S (mp);
2476
2477   /* Wait for a reply, return the good/bad news... */
2478   W (ret);
2479   return ret;
2480 }
2481
2482 static int
2483 api_sw_interface_set_rx_mode (vat_main_t * vam)
2484 {
2485   unformat_input_t *i = vam->input;
2486   vl_api_sw_interface_set_rx_mode_t *mp;
2487   u32 sw_if_index;
2488   u8 sw_if_index_set = 0;
2489   int ret;
2490   u8 queue_id_valid = 0;
2491   u32 queue_id;
2492   vnet_hw_if_rx_mode mode = VNET_HW_IF_RX_MODE_UNKNOWN;
2493
2494   /* Parse args required to build the message */
2495   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2496     {
2497       if (unformat (i, "queue %d", &queue_id))
2498         queue_id_valid = 1;
2499       else if (unformat (i, "polling"))
2500         mode = VNET_HW_IF_RX_MODE_POLLING;
2501       else if (unformat (i, "interrupt"))
2502         mode = VNET_HW_IF_RX_MODE_INTERRUPT;
2503       else if (unformat (i, "adaptive"))
2504         mode = VNET_HW_IF_RX_MODE_ADAPTIVE;
2505       else
2506         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2507         sw_if_index_set = 1;
2508       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2509         sw_if_index_set = 1;
2510       else
2511         break;
2512     }
2513
2514   if (sw_if_index_set == 0)
2515     {
2516       errmsg ("missing interface name or sw_if_index");
2517       return -99;
2518     }
2519   if (mode == VNET_HW_IF_RX_MODE_UNKNOWN)
2520     {
2521       errmsg ("missing rx-mode");
2522       return -99;
2523     }
2524
2525   /* Construct the API message */
2526   M (SW_INTERFACE_SET_RX_MODE, mp);
2527   mp->sw_if_index = ntohl (sw_if_index);
2528   mp->mode = (vl_api_rx_mode_t) mode;
2529   mp->queue_id_valid = queue_id_valid;
2530   mp->queue_id = queue_id_valid ? ntohl (queue_id) : ~0;
2531
2532   /* send it... */
2533   S (mp);
2534
2535   /* Wait for a reply, return the good/bad news... */
2536   W (ret);
2537   return ret;
2538 }
2539
2540 static int
2541 api_sw_interface_set_rx_placement (vat_main_t * vam)
2542 {
2543   unformat_input_t *i = vam->input;
2544   vl_api_sw_interface_set_rx_placement_t *mp;
2545   u32 sw_if_index;
2546   u8 sw_if_index_set = 0;
2547   int ret;
2548   u8 is_main = 0;
2549   u32 queue_id, thread_index;
2550
2551   /* Parse args required to build the message */
2552   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2553     {
2554       if (unformat (i, "queue %d", &queue_id))
2555         ;
2556       else if (unformat (i, "main"))
2557         is_main = 1;
2558       else if (unformat (i, "worker %d", &thread_index))
2559         ;
2560       else
2561         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2562         sw_if_index_set = 1;
2563       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2564         sw_if_index_set = 1;
2565       else
2566         break;
2567     }
2568
2569   if (sw_if_index_set == 0)
2570     {
2571       errmsg ("missing interface name or sw_if_index");
2572       return -99;
2573     }
2574
2575   if (is_main)
2576     thread_index = 0;
2577   /* Construct the API message */
2578   M (SW_INTERFACE_SET_RX_PLACEMENT, mp);
2579   mp->sw_if_index = ntohl (sw_if_index);
2580   mp->worker_id = ntohl (thread_index);
2581   mp->queue_id = ntohl (queue_id);
2582   mp->is_main = is_main;
2583
2584   /* send it... */
2585   S (mp);
2586   /* Wait for a reply, return the good/bad news... */
2587   W (ret);
2588   return ret;
2589 }
2590
2591 static void vl_api_sw_interface_rx_placement_details_t_handler
2592   (vl_api_sw_interface_rx_placement_details_t * mp)
2593 {
2594   vat_main_t *vam = &vat_main;
2595   u32 worker_id = ntohl (mp->worker_id);
2596
2597   print (vam->ofp,
2598          "\n%-11d %-11s %-6d %-5d %-9s",
2599          ntohl (mp->sw_if_index), (worker_id == 0) ? "main" : "worker",
2600          worker_id, ntohl (mp->queue_id),
2601          (mp->mode ==
2602           1) ? "polling" : ((mp->mode == 2) ? "interrupt" : "adaptive"));
2603 }
2604
2605 static void vl_api_sw_interface_rx_placement_details_t_handler_json
2606   (vl_api_sw_interface_rx_placement_details_t * mp)
2607 {
2608   vat_main_t *vam = &vat_main;
2609   vat_json_node_t *node = NULL;
2610
2611   if (VAT_JSON_ARRAY != vam->json_tree.type)
2612     {
2613       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
2614       vat_json_init_array (&vam->json_tree);
2615     }
2616   node = vat_json_array_add (&vam->json_tree);
2617
2618   vat_json_init_object (node);
2619   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
2620   vat_json_object_add_uint (node, "worker_id", ntohl (mp->worker_id));
2621   vat_json_object_add_uint (node, "queue_id", ntohl (mp->queue_id));
2622   vat_json_object_add_uint (node, "mode", mp->mode);
2623 }
2624
2625 static int
2626 api_sw_interface_rx_placement_dump (vat_main_t * vam)
2627 {
2628   unformat_input_t *i = vam->input;
2629   vl_api_sw_interface_rx_placement_dump_t *mp;
2630   vl_api_control_ping_t *mp_ping;
2631   int ret;
2632   u32 sw_if_index;
2633   u8 sw_if_index_set = 0;
2634
2635   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2636     {
2637       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2638         sw_if_index_set++;
2639       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2640         sw_if_index_set++;
2641       else
2642         break;
2643     }
2644
2645   print (vam->ofp,
2646          "\n%-11s %-11s %-6s %-5s %-4s",
2647          "sw_if_index", "main/worker", "thread", "queue", "mode");
2648
2649   /* Dump Interface rx placement */
2650   M (SW_INTERFACE_RX_PLACEMENT_DUMP, mp);
2651
2652   if (sw_if_index_set)
2653     mp->sw_if_index = htonl (sw_if_index);
2654   else
2655     mp->sw_if_index = ~0;
2656
2657   S (mp);
2658
2659   /* Use a control ping for synchronization */
2660   MPING (CONTROL_PING, mp_ping);
2661   S (mp_ping);
2662
2663   W (ret);
2664   return ret;
2665 }
2666
2667 static int
2668 api_sw_interface_clear_stats (vat_main_t * vam)
2669 {
2670   unformat_input_t *i = vam->input;
2671   vl_api_sw_interface_clear_stats_t *mp;
2672   u32 sw_if_index;
2673   u8 sw_if_index_set = 0;
2674   int ret;
2675
2676   /* Parse args required to build the message */
2677   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2678     {
2679       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2680         sw_if_index_set = 1;
2681       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2682         sw_if_index_set = 1;
2683       else
2684         break;
2685     }
2686
2687   /* Construct the API message */
2688   M (SW_INTERFACE_CLEAR_STATS, mp);
2689
2690   if (sw_if_index_set == 1)
2691     mp->sw_if_index = ntohl (sw_if_index);
2692   else
2693     mp->sw_if_index = ~0;
2694
2695   /* send it... */
2696   S (mp);
2697
2698   /* Wait for a reply, return the good/bad news... */
2699   W (ret);
2700   return ret;
2701 }
2702
2703 static int
2704 api_sw_interface_add_del_address (vat_main_t * vam)
2705 {
2706   unformat_input_t *i = vam->input;
2707   vl_api_sw_interface_add_del_address_t *mp;
2708   u32 sw_if_index;
2709   u8 sw_if_index_set = 0;
2710   u8 is_add = 1, del_all = 0;
2711   u32 address_length = 0;
2712   u8 v4_address_set = 0;
2713   u8 v6_address_set = 0;
2714   ip4_address_t v4address;
2715   ip6_address_t v6address;
2716   int ret;
2717
2718   /* Parse args required to build the message */
2719   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2720     {
2721       if (unformat (i, "del-all"))
2722         del_all = 1;
2723       else if (unformat (i, "del"))
2724         is_add = 0;
2725       else
2726         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2727         sw_if_index_set = 1;
2728       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2729         sw_if_index_set = 1;
2730       else if (unformat (i, "%U/%d",
2731                          unformat_ip4_address, &v4address, &address_length))
2732         v4_address_set = 1;
2733       else if (unformat (i, "%U/%d",
2734                          unformat_ip6_address, &v6address, &address_length))
2735         v6_address_set = 1;
2736       else
2737         break;
2738     }
2739
2740   if (sw_if_index_set == 0)
2741     {
2742       errmsg ("missing interface name or sw_if_index");
2743       return -99;
2744     }
2745   if (v4_address_set && v6_address_set)
2746     {
2747       errmsg ("both v4 and v6 addresses set");
2748       return -99;
2749     }
2750   if (!v4_address_set && !v6_address_set && !del_all)
2751     {
2752       errmsg ("no addresses set");
2753       return -99;
2754     }
2755
2756   /* Construct the API message */
2757   M (SW_INTERFACE_ADD_DEL_ADDRESS, mp);
2758
2759   mp->sw_if_index = ntohl (sw_if_index);
2760   mp->is_add = is_add;
2761   mp->del_all = del_all;
2762   if (v6_address_set)
2763     {
2764       mp->prefix.address.af = ADDRESS_IP6;
2765       clib_memcpy (mp->prefix.address.un.ip6, &v6address, sizeof (v6address));
2766     }
2767   else
2768     {
2769       mp->prefix.address.af = ADDRESS_IP4;
2770       clib_memcpy (mp->prefix.address.un.ip4, &v4address, sizeof (v4address));
2771     }
2772   mp->prefix.len = address_length;
2773
2774   /* send it... */
2775   S (mp);
2776
2777   /* Wait for a reply, return good/bad news  */
2778   W (ret);
2779   return ret;
2780 }
2781
2782 static int
2783 api_sw_interface_set_mpls_enable (vat_main_t * vam)
2784 {
2785   unformat_input_t *i = vam->input;
2786   vl_api_sw_interface_set_mpls_enable_t *mp;
2787   u32 sw_if_index;
2788   u8 sw_if_index_set = 0;
2789   u8 enable = 1;
2790   int ret;
2791
2792   /* Parse args required to build the message */
2793   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2794     {
2795       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2796         sw_if_index_set = 1;
2797       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2798         sw_if_index_set = 1;
2799       else if (unformat (i, "disable"))
2800         enable = 0;
2801       else if (unformat (i, "dis"))
2802         enable = 0;
2803       else
2804         break;
2805     }
2806
2807   if (sw_if_index_set == 0)
2808     {
2809       errmsg ("missing interface name or sw_if_index");
2810       return -99;
2811     }
2812
2813   /* Construct the API message */
2814   M (SW_INTERFACE_SET_MPLS_ENABLE, mp);
2815
2816   mp->sw_if_index = ntohl (sw_if_index);
2817   mp->enable = enable;
2818
2819   /* send it... */
2820   S (mp);
2821
2822   /* Wait for a reply... */
2823   W (ret);
2824   return ret;
2825 }
2826
2827 static int
2828 api_sw_interface_set_table (vat_main_t * vam)
2829 {
2830   unformat_input_t *i = vam->input;
2831   vl_api_sw_interface_set_table_t *mp;
2832   u32 sw_if_index, vrf_id = 0;
2833   u8 sw_if_index_set = 0;
2834   u8 is_ipv6 = 0;
2835   int ret;
2836
2837   /* Parse args required to build the message */
2838   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2839     {
2840       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2841         sw_if_index_set = 1;
2842       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2843         sw_if_index_set = 1;
2844       else if (unformat (i, "vrf %d", &vrf_id))
2845         ;
2846       else if (unformat (i, "ipv6"))
2847         is_ipv6 = 1;
2848       else
2849         break;
2850     }
2851
2852   if (sw_if_index_set == 0)
2853     {
2854       errmsg ("missing interface name or sw_if_index");
2855       return -99;
2856     }
2857
2858   /* Construct the API message */
2859   M (SW_INTERFACE_SET_TABLE, mp);
2860
2861   mp->sw_if_index = ntohl (sw_if_index);
2862   mp->is_ipv6 = is_ipv6;
2863   mp->vrf_id = ntohl (vrf_id);
2864
2865   /* send it... */
2866   S (mp);
2867
2868   /* Wait for a reply... */
2869   W (ret);
2870   return ret;
2871 }
2872
2873 static void vl_api_sw_interface_get_table_reply_t_handler
2874   (vl_api_sw_interface_get_table_reply_t * mp)
2875 {
2876   vat_main_t *vam = &vat_main;
2877
2878   print (vam->ofp, "%d", ntohl (mp->vrf_id));
2879
2880   vam->retval = ntohl (mp->retval);
2881   vam->result_ready = 1;
2882
2883 }
2884
2885 static void vl_api_sw_interface_get_table_reply_t_handler_json
2886   (vl_api_sw_interface_get_table_reply_t * mp)
2887 {
2888   vat_main_t *vam = &vat_main;
2889   vat_json_node_t node;
2890
2891   vat_json_init_object (&node);
2892   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2893   vat_json_object_add_int (&node, "vrf_id", ntohl (mp->vrf_id));
2894
2895   vat_json_print (vam->ofp, &node);
2896   vat_json_free (&node);
2897
2898   vam->retval = ntohl (mp->retval);
2899   vam->result_ready = 1;
2900 }
2901
2902 static int
2903 api_sw_interface_get_table (vat_main_t * vam)
2904 {
2905   unformat_input_t *i = vam->input;
2906   vl_api_sw_interface_get_table_t *mp;
2907   u32 sw_if_index;
2908   u8 sw_if_index_set = 0;
2909   u8 is_ipv6 = 0;
2910   int ret;
2911
2912   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2913     {
2914       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2915         sw_if_index_set = 1;
2916       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2917         sw_if_index_set = 1;
2918       else if (unformat (i, "ipv6"))
2919         is_ipv6 = 1;
2920       else
2921         break;
2922     }
2923
2924   if (sw_if_index_set == 0)
2925     {
2926       errmsg ("missing interface name or sw_if_index");
2927       return -99;
2928     }
2929
2930   M (SW_INTERFACE_GET_TABLE, mp);
2931   mp->sw_if_index = htonl (sw_if_index);
2932   mp->is_ipv6 = is_ipv6;
2933
2934   S (mp);
2935   W (ret);
2936   return ret;
2937 }
2938
2939 static int
2940 api_sw_interface_set_vpath (vat_main_t * vam)
2941 {
2942   unformat_input_t *i = vam->input;
2943   vl_api_sw_interface_set_vpath_t *mp;
2944   u32 sw_if_index = 0;
2945   u8 sw_if_index_set = 0;
2946   u8 is_enable = 0;
2947   int ret;
2948
2949   /* Parse args required to build the message */
2950   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2951     {
2952       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2953         sw_if_index_set = 1;
2954       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2955         sw_if_index_set = 1;
2956       else if (unformat (i, "enable"))
2957         is_enable = 1;
2958       else if (unformat (i, "disable"))
2959         is_enable = 0;
2960       else
2961         break;
2962     }
2963
2964   if (sw_if_index_set == 0)
2965     {
2966       errmsg ("missing interface name or sw_if_index");
2967       return -99;
2968     }
2969
2970   /* Construct the API message */
2971   M (SW_INTERFACE_SET_VPATH, mp);
2972
2973   mp->sw_if_index = ntohl (sw_if_index);
2974   mp->enable = is_enable;
2975
2976   /* send it... */
2977   S (mp);
2978
2979   /* Wait for a reply... */
2980   W (ret);
2981   return ret;
2982 }
2983
2984 static int
2985 api_sw_interface_set_l2_xconnect (vat_main_t * vam)
2986 {
2987   unformat_input_t *i = vam->input;
2988   vl_api_sw_interface_set_l2_xconnect_t *mp;
2989   u32 rx_sw_if_index;
2990   u8 rx_sw_if_index_set = 0;
2991   u32 tx_sw_if_index;
2992   u8 tx_sw_if_index_set = 0;
2993   u8 enable = 1;
2994   int ret;
2995
2996   /* Parse args required to build the message */
2997   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2998     {
2999       if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index))
3000         rx_sw_if_index_set = 1;
3001       else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
3002         tx_sw_if_index_set = 1;
3003       else if (unformat (i, "rx"))
3004         {
3005           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3006             {
3007               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
3008                             &rx_sw_if_index))
3009                 rx_sw_if_index_set = 1;
3010             }
3011           else
3012             break;
3013         }
3014       else if (unformat (i, "tx"))
3015         {
3016           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3017             {
3018               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
3019                             &tx_sw_if_index))
3020                 tx_sw_if_index_set = 1;
3021             }
3022           else
3023             break;
3024         }
3025       else if (unformat (i, "enable"))
3026         enable = 1;
3027       else if (unformat (i, "disable"))
3028         enable = 0;
3029       else
3030         break;
3031     }
3032
3033   if (rx_sw_if_index_set == 0)
3034     {
3035       errmsg ("missing rx interface name or rx_sw_if_index");
3036       return -99;
3037     }
3038
3039   if (enable && (tx_sw_if_index_set == 0))
3040     {
3041       errmsg ("missing tx interface name or tx_sw_if_index");
3042       return -99;
3043     }
3044
3045   M (SW_INTERFACE_SET_L2_XCONNECT, mp);
3046
3047   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
3048   mp->tx_sw_if_index = ntohl (tx_sw_if_index);
3049   mp->enable = enable;
3050
3051   S (mp);
3052   W (ret);
3053   return ret;
3054 }
3055
3056 static int
3057 api_sw_interface_set_l2_bridge (vat_main_t * vam)
3058 {
3059   unformat_input_t *i = vam->input;
3060   vl_api_sw_interface_set_l2_bridge_t *mp;
3061   vl_api_l2_port_type_t port_type;
3062   u32 rx_sw_if_index;
3063   u8 rx_sw_if_index_set = 0;
3064   u32 bd_id;
3065   u8 bd_id_set = 0;
3066   u32 shg = 0;
3067   u8 enable = 1;
3068   int ret;
3069
3070   port_type = L2_API_PORT_TYPE_NORMAL;
3071
3072   /* Parse args required to build the message */
3073   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3074     {
3075       if (unformat (i, "sw_if_index %d", &rx_sw_if_index))
3076         rx_sw_if_index_set = 1;
3077       else if (unformat (i, "bd_id %d", &bd_id))
3078         bd_id_set = 1;
3079       else
3080         if (unformat
3081             (i, "%U", api_unformat_sw_if_index, vam, &rx_sw_if_index))
3082         rx_sw_if_index_set = 1;
3083       else if (unformat (i, "shg %d", &shg))
3084         ;
3085       else if (unformat (i, "bvi"))
3086         port_type = L2_API_PORT_TYPE_BVI;
3087       else if (unformat (i, "uu-fwd"))
3088         port_type = L2_API_PORT_TYPE_UU_FWD;
3089       else if (unformat (i, "enable"))
3090         enable = 1;
3091       else if (unformat (i, "disable"))
3092         enable = 0;
3093       else
3094         break;
3095     }
3096
3097   if (rx_sw_if_index_set == 0)
3098     {
3099       errmsg ("missing rx interface name or sw_if_index");
3100       return -99;
3101     }
3102
3103   if (enable && (bd_id_set == 0))
3104     {
3105       errmsg ("missing bridge domain");
3106       return -99;
3107     }
3108
3109   M (SW_INTERFACE_SET_L2_BRIDGE, mp);
3110
3111   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
3112   mp->bd_id = ntohl (bd_id);
3113   mp->shg = (u8) shg;
3114   mp->port_type = ntohl (port_type);
3115   mp->enable = enable;
3116
3117   S (mp);
3118   W (ret);
3119   return ret;
3120 }
3121
3122 static int
3123 api_bridge_domain_dump (vat_main_t * vam)
3124 {
3125   unformat_input_t *i = vam->input;
3126   vl_api_bridge_domain_dump_t *mp;
3127   vl_api_control_ping_t *mp_ping;
3128   u32 bd_id = ~0;
3129   int ret;
3130
3131   /* Parse args required to build the message */
3132   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3133     {
3134       if (unformat (i, "bd_id %d", &bd_id))
3135         ;
3136       else
3137         break;
3138     }
3139
3140   M (BRIDGE_DOMAIN_DUMP, mp);
3141   mp->bd_id = ntohl (bd_id);
3142   S (mp);
3143
3144   /* Use a control ping for synchronization */
3145   MPING (CONTROL_PING, mp_ping);
3146   S (mp_ping);
3147
3148   W (ret);
3149   return ret;
3150 }
3151
3152 static int
3153 api_bridge_domain_add_del (vat_main_t * vam)
3154 {
3155   unformat_input_t *i = vam->input;
3156   vl_api_bridge_domain_add_del_t *mp;
3157   u32 bd_id = ~0;
3158   u8 is_add = 1;
3159   u32 flood = 1, forward = 1, learn = 1, uu_flood = 1, arp_term = 0;
3160   u8 *bd_tag = NULL;
3161   u32 mac_age = 0;
3162   int ret;
3163
3164   /* Parse args required to build the message */
3165   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3166     {
3167       if (unformat (i, "bd_id %d", &bd_id))
3168         ;
3169       else if (unformat (i, "flood %d", &flood))
3170         ;
3171       else if (unformat (i, "uu-flood %d", &uu_flood))
3172         ;
3173       else if (unformat (i, "forward %d", &forward))
3174         ;
3175       else if (unformat (i, "learn %d", &learn))
3176         ;
3177       else if (unformat (i, "arp-term %d", &arp_term))
3178         ;
3179       else if (unformat (i, "mac-age %d", &mac_age))
3180         ;
3181       else if (unformat (i, "bd-tag %s", &bd_tag))
3182         ;
3183       else if (unformat (i, "del"))
3184         {
3185           is_add = 0;
3186           flood = uu_flood = forward = learn = 0;
3187         }
3188       else
3189         break;
3190     }
3191
3192   if (bd_id == ~0)
3193     {
3194       errmsg ("missing bridge domain");
3195       ret = -99;
3196       goto done;
3197     }
3198
3199   if (mac_age > 255)
3200     {
3201       errmsg ("mac age must be less than 256 ");
3202       ret = -99;
3203       goto done;
3204     }
3205
3206   if ((bd_tag) && (vec_len (bd_tag) > 63))
3207     {
3208       errmsg ("bd-tag cannot be longer than 63");
3209       ret = -99;
3210       goto done;
3211     }
3212
3213   M (BRIDGE_DOMAIN_ADD_DEL, mp);
3214
3215   mp->bd_id = ntohl (bd_id);
3216   mp->flood = flood;
3217   mp->uu_flood = uu_flood;
3218   mp->forward = forward;
3219   mp->learn = learn;
3220   mp->arp_term = arp_term;
3221   mp->is_add = is_add;
3222   mp->mac_age = (u8) mac_age;
3223   if (bd_tag)
3224     {
3225       clib_memcpy (mp->bd_tag, bd_tag, vec_len (bd_tag));
3226       mp->bd_tag[vec_len (bd_tag)] = 0;
3227     }
3228   S (mp);
3229   W (ret);
3230
3231 done:
3232   vec_free (bd_tag);
3233   return ret;
3234 }
3235
3236 static int
3237 api_l2fib_flush_bd (vat_main_t * vam)
3238 {
3239   unformat_input_t *i = vam->input;
3240   vl_api_l2fib_flush_bd_t *mp;
3241   u32 bd_id = ~0;
3242   int ret;
3243
3244   /* Parse args required to build the message */
3245   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3246     {
3247       if (unformat (i, "bd_id %d", &bd_id));
3248       else
3249         break;
3250     }
3251
3252   if (bd_id == ~0)
3253     {
3254       errmsg ("missing bridge domain");
3255       return -99;
3256     }
3257
3258   M (L2FIB_FLUSH_BD, mp);
3259
3260   mp->bd_id = htonl (bd_id);
3261
3262   S (mp);
3263   W (ret);
3264   return ret;
3265 }
3266
3267 static int
3268 api_l2fib_flush_int (vat_main_t * vam)
3269 {
3270   unformat_input_t *i = vam->input;
3271   vl_api_l2fib_flush_int_t *mp;
3272   u32 sw_if_index = ~0;
3273   int ret;
3274
3275   /* Parse args required to build the message */
3276   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3277     {
3278       if (unformat (i, "sw_if_index %d", &sw_if_index));
3279       else
3280         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index));
3281       else
3282         break;
3283     }
3284
3285   if (sw_if_index == ~0)
3286     {
3287       errmsg ("missing interface name or sw_if_index");
3288       return -99;
3289     }
3290
3291   M (L2FIB_FLUSH_INT, mp);
3292
3293   mp->sw_if_index = ntohl (sw_if_index);
3294
3295   S (mp);
3296   W (ret);
3297   return ret;
3298 }
3299
3300 static int
3301 api_l2fib_add_del (vat_main_t * vam)
3302 {
3303   unformat_input_t *i = vam->input;
3304   vl_api_l2fib_add_del_t *mp;
3305   f64 timeout;
3306   u8 mac[6] = { 0 };
3307   u8 mac_set = 0;
3308   u32 bd_id;
3309   u8 bd_id_set = 0;
3310   u32 sw_if_index = 0;
3311   u8 sw_if_index_set = 0;
3312   u8 is_add = 1;
3313   u8 static_mac = 0;
3314   u8 filter_mac = 0;
3315   u8 bvi_mac = 0;
3316   int count = 1;
3317   f64 before = 0;
3318   int j;
3319
3320   /* Parse args required to build the message */
3321   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3322     {
3323       if (unformat (i, "mac %U", unformat_ethernet_address, mac))
3324         mac_set = 1;
3325       else if (unformat (i, "bd_id %d", &bd_id))
3326         bd_id_set = 1;
3327       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3328         sw_if_index_set = 1;
3329       else if (unformat (i, "sw_if"))
3330         {
3331           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3332             {
3333               if (unformat
3334                   (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3335                 sw_if_index_set = 1;
3336             }
3337           else
3338             break;
3339         }
3340       else if (unformat (i, "static"))
3341         static_mac = 1;
3342       else if (unformat (i, "filter"))
3343         {
3344           filter_mac = 1;
3345           static_mac = 1;
3346         }
3347       else if (unformat (i, "bvi"))
3348         {
3349           bvi_mac = 1;
3350           static_mac = 1;
3351         }
3352       else if (unformat (i, "del"))
3353         is_add = 0;
3354       else if (unformat (i, "count %d", &count))
3355         ;
3356       else
3357         break;
3358     }
3359
3360   if (mac_set == 0)
3361     {
3362       errmsg ("missing mac address");
3363       return -99;
3364     }
3365
3366   if (bd_id_set == 0)
3367     {
3368       errmsg ("missing bridge domain");
3369       return -99;
3370     }
3371
3372   if (is_add && sw_if_index_set == 0 && filter_mac == 0)
3373     {
3374       errmsg ("missing interface name or sw_if_index");
3375       return -99;
3376     }
3377
3378   if (count > 1)
3379     {
3380       /* Turn on async mode */
3381       vam->async_mode = 1;
3382       vam->async_errors = 0;
3383       before = vat_time_now (vam);
3384     }
3385
3386   for (j = 0; j < count; j++)
3387     {
3388       M (L2FIB_ADD_DEL, mp);
3389
3390       clib_memcpy (mp->mac, mac, 6);
3391       mp->bd_id = ntohl (bd_id);
3392       mp->is_add = is_add;
3393       mp->sw_if_index = ntohl (sw_if_index);
3394
3395       if (is_add)
3396         {
3397           mp->static_mac = static_mac;
3398           mp->filter_mac = filter_mac;
3399           mp->bvi_mac = bvi_mac;
3400         }
3401       increment_mac_address (mac);
3402       /* send it... */
3403       S (mp);
3404     }
3405
3406   if (count > 1)
3407     {
3408       vl_api_control_ping_t *mp_ping;
3409       f64 after;
3410
3411       /* Shut off async mode */
3412       vam->async_mode = 0;
3413
3414       MPING (CONTROL_PING, mp_ping);
3415       S (mp_ping);
3416
3417       timeout = vat_time_now (vam) + 1.0;
3418       while (vat_time_now (vam) < timeout)
3419         if (vam->result_ready == 1)
3420           goto out;
3421       vam->retval = -99;
3422
3423     out:
3424       if (vam->retval == -99)
3425         errmsg ("timeout");
3426
3427       if (vam->async_errors > 0)
3428         {
3429           errmsg ("%d asynchronous errors", vam->async_errors);
3430           vam->retval = -98;
3431         }
3432       vam->async_errors = 0;
3433       after = vat_time_now (vam);
3434
3435       print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec",
3436              count, after - before, count / (after - before));
3437     }
3438   else
3439     {
3440       int ret;
3441
3442       /* Wait for a reply... */
3443       W (ret);
3444       return ret;
3445     }
3446   /* Return the good/bad news */
3447   return (vam->retval);
3448 }
3449
3450 static int
3451 api_bridge_domain_set_mac_age (vat_main_t * vam)
3452 {
3453   unformat_input_t *i = vam->input;
3454   vl_api_bridge_domain_set_mac_age_t *mp;
3455   u32 bd_id = ~0;
3456   u32 mac_age = 0;
3457   int ret;
3458
3459   /* Parse args required to build the message */
3460   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3461     {
3462       if (unformat (i, "bd_id %d", &bd_id));
3463       else if (unformat (i, "mac-age %d", &mac_age));
3464       else
3465         break;
3466     }
3467
3468   if (bd_id == ~0)
3469     {
3470       errmsg ("missing bridge domain");
3471       return -99;
3472     }
3473
3474   if (mac_age > 255)
3475     {
3476       errmsg ("mac age must be less than 256 ");
3477       return -99;
3478     }
3479
3480   M (BRIDGE_DOMAIN_SET_MAC_AGE, mp);
3481
3482   mp->bd_id = htonl (bd_id);
3483   mp->mac_age = (u8) mac_age;
3484
3485   S (mp);
3486   W (ret);
3487   return ret;
3488 }
3489
3490 static int
3491 api_l2_flags (vat_main_t * vam)
3492 {
3493   unformat_input_t *i = vam->input;
3494   vl_api_l2_flags_t *mp;
3495   u32 sw_if_index;
3496   u32 flags = 0;
3497   u8 sw_if_index_set = 0;
3498   u8 is_set = 0;
3499   int ret;
3500
3501   /* Parse args required to build the message */
3502   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3503     {
3504       if (unformat (i, "sw_if_index %d", &sw_if_index))
3505         sw_if_index_set = 1;
3506       else if (unformat (i, "sw_if"))
3507         {
3508           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3509             {
3510               if (unformat
3511                   (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3512                 sw_if_index_set = 1;
3513             }
3514           else
3515             break;
3516         }
3517       else if (unformat (i, "learn"))
3518         flags |= L2_LEARN;
3519       else if (unformat (i, "forward"))
3520         flags |= L2_FWD;
3521       else if (unformat (i, "flood"))
3522         flags |= L2_FLOOD;
3523       else if (unformat (i, "uu-flood"))
3524         flags |= L2_UU_FLOOD;
3525       else if (unformat (i, "arp-term"))
3526         flags |= L2_ARP_TERM;
3527       else if (unformat (i, "off"))
3528         is_set = 0;
3529       else if (unformat (i, "disable"))
3530         is_set = 0;
3531       else
3532         break;
3533     }
3534
3535   if (sw_if_index_set == 0)
3536     {
3537       errmsg ("missing interface name or sw_if_index");
3538       return -99;
3539     }
3540
3541   M (L2_FLAGS, mp);
3542
3543   mp->sw_if_index = ntohl (sw_if_index);
3544   mp->feature_bitmap = ntohl (flags);
3545   mp->is_set = is_set;
3546
3547   S (mp);
3548   W (ret);
3549   return ret;
3550 }
3551
3552 static int
3553 api_bridge_flags (vat_main_t * vam)
3554 {
3555   unformat_input_t *i = vam->input;
3556   vl_api_bridge_flags_t *mp;
3557   u32 bd_id;
3558   u8 bd_id_set = 0;
3559   u8 is_set = 1;
3560   bd_flags_t flags = 0;
3561   int ret;
3562
3563   /* Parse args required to build the message */
3564   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3565     {
3566       if (unformat (i, "bd_id %d", &bd_id))
3567         bd_id_set = 1;
3568       else if (unformat (i, "learn"))
3569         flags |= BRIDGE_API_FLAG_LEARN;
3570       else if (unformat (i, "forward"))
3571         flags |= BRIDGE_API_FLAG_FWD;
3572       else if (unformat (i, "flood"))
3573         flags |= BRIDGE_API_FLAG_FLOOD;
3574       else if (unformat (i, "uu-flood"))
3575         flags |= BRIDGE_API_FLAG_UU_FLOOD;
3576       else if (unformat (i, "arp-term"))
3577         flags |= BRIDGE_API_FLAG_ARP_TERM;
3578       else if (unformat (i, "off"))
3579         is_set = 0;
3580       else if (unformat (i, "disable"))
3581         is_set = 0;
3582       else
3583         break;
3584     }
3585
3586   if (bd_id_set == 0)
3587     {
3588       errmsg ("missing bridge domain");
3589       return -99;
3590     }
3591
3592   M (BRIDGE_FLAGS, mp);
3593
3594   mp->bd_id = ntohl (bd_id);
3595   mp->flags = ntohl (flags);
3596   mp->is_set = is_set;
3597
3598   S (mp);
3599   W (ret);
3600   return ret;
3601 }
3602
3603 static int
3604 api_bd_ip_mac_add_del (vat_main_t * vam)
3605 {
3606   vl_api_address_t ip = VL_API_ZERO_ADDRESS;
3607   vl_api_mac_address_t mac = { 0 };
3608   unformat_input_t *i = vam->input;
3609   vl_api_bd_ip_mac_add_del_t *mp;
3610   u32 bd_id;
3611   u8 is_add = 1;
3612   u8 bd_id_set = 0;
3613   u8 ip_set = 0;
3614   u8 mac_set = 0;
3615   int ret;
3616
3617
3618   /* Parse args required to build the message */
3619   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3620     {
3621       if (unformat (i, "bd_id %d", &bd_id))
3622         {
3623           bd_id_set++;
3624         }
3625       else if (unformat (i, "%U", unformat_vl_api_address, &ip))
3626         {
3627           ip_set++;
3628         }
3629       else if (unformat (i, "%U", unformat_vl_api_mac_address, &mac))
3630         {
3631           mac_set++;
3632         }
3633       else if (unformat (i, "del"))
3634         is_add = 0;
3635       else
3636         break;
3637     }
3638
3639   if (bd_id_set == 0)
3640     {
3641       errmsg ("missing bridge domain");
3642       return -99;
3643     }
3644   else if (ip_set == 0)
3645     {
3646       errmsg ("missing IP address");
3647       return -99;
3648     }
3649   else if (mac_set == 0)
3650     {
3651       errmsg ("missing MAC address");
3652       return -99;
3653     }
3654
3655   M (BD_IP_MAC_ADD_DEL, mp);
3656
3657   mp->entry.bd_id = ntohl (bd_id);
3658   mp->is_add = is_add;
3659
3660   clib_memcpy (&mp->entry.ip, &ip, sizeof (ip));
3661   clib_memcpy (&mp->entry.mac, &mac, sizeof (mac));
3662
3663   S (mp);
3664   W (ret);
3665   return ret;
3666 }
3667
3668 static int
3669 api_bd_ip_mac_flush (vat_main_t * vam)
3670 {
3671   unformat_input_t *i = vam->input;
3672   vl_api_bd_ip_mac_flush_t *mp;
3673   u32 bd_id;
3674   u8 bd_id_set = 0;
3675   int ret;
3676
3677   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3678     {
3679       if (unformat (i, "bd_id %d", &bd_id))
3680         {
3681           bd_id_set++;
3682         }
3683       else
3684         break;
3685     }
3686
3687   if (bd_id_set == 0)
3688     {
3689       errmsg ("missing bridge domain");
3690       return -99;
3691     }
3692
3693   M (BD_IP_MAC_FLUSH, mp);
3694
3695   mp->bd_id = ntohl (bd_id);
3696
3697   S (mp);
3698   W (ret);
3699   return ret;
3700 }
3701
3702 static void vl_api_bd_ip_mac_details_t_handler
3703   (vl_api_bd_ip_mac_details_t * mp)
3704 {
3705   vat_main_t *vam = &vat_main;
3706
3707   print (vam->ofp,
3708          "\n%-5d %U %U",
3709          ntohl (mp->entry.bd_id),
3710          format_vl_api_mac_address, mp->entry.mac,
3711          format_vl_api_address, &mp->entry.ip);
3712 }
3713
3714 static void vl_api_bd_ip_mac_details_t_handler_json
3715   (vl_api_bd_ip_mac_details_t * mp)
3716 {
3717   vat_main_t *vam = &vat_main;
3718   vat_json_node_t *node = NULL;
3719
3720   if (VAT_JSON_ARRAY != vam->json_tree.type)
3721     {
3722       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
3723       vat_json_init_array (&vam->json_tree);
3724     }
3725   node = vat_json_array_add (&vam->json_tree);
3726
3727   vat_json_init_object (node);
3728   vat_json_object_add_uint (node, "bd_id", ntohl (mp->entry.bd_id));
3729   vat_json_object_add_string_copy (node, "mac_address",
3730                                    format (0, "%U", format_vl_api_mac_address,
3731                                            &mp->entry.mac));
3732   u8 *ip = 0;
3733
3734   ip = format (0, "%U", format_vl_api_address, &mp->entry.ip);
3735   vat_json_object_add_string_copy (node, "ip_address", ip);
3736   vec_free (ip);
3737 }
3738
3739 static int
3740 api_bd_ip_mac_dump (vat_main_t * vam)
3741 {
3742   unformat_input_t *i = vam->input;
3743   vl_api_bd_ip_mac_dump_t *mp;
3744   vl_api_control_ping_t *mp_ping;
3745   int ret;
3746   u32 bd_id;
3747   u8 bd_id_set = 0;
3748
3749   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3750     {
3751       if (unformat (i, "bd_id %d", &bd_id))
3752         {
3753           bd_id_set++;
3754         }
3755       else
3756         break;
3757     }
3758
3759   print (vam->ofp,
3760          "\n%-5s %-7s %-20s %-30s",
3761          "bd_id", "is_ipv6", "mac_address", "ip_address");
3762
3763   /* Dump Bridge Domain Ip to Mac entries */
3764   M (BD_IP_MAC_DUMP, mp);
3765
3766   if (bd_id_set)
3767     mp->bd_id = htonl (bd_id);
3768   else
3769     mp->bd_id = ~0;
3770
3771   S (mp);
3772
3773   /* Use a control ping for synchronization */
3774   MPING (CONTROL_PING, mp_ping);
3775   S (mp_ping);
3776
3777   W (ret);
3778   return ret;
3779 }
3780
3781 uword
3782 unformat_vlib_pci_addr (unformat_input_t * input, va_list * args)
3783 {
3784   vlib_pci_addr_t *addr = va_arg (*args, vlib_pci_addr_t *);
3785   u32 x[4];
3786
3787   if (!unformat (input, "%x:%x:%x.%x", &x[0], &x[1], &x[2], &x[3]))
3788     return 0;
3789
3790   addr->domain = x[0];
3791   addr->bus = x[1];
3792   addr->slot = x[2];
3793   addr->function = x[3];
3794
3795   return 1;
3796 }
3797
3798 static int
3799 api_virtio_pci_create_v2 (vat_main_t * vam)
3800 {
3801   unformat_input_t *i = vam->input;
3802   vl_api_virtio_pci_create_v2_t *mp;
3803   u8 mac_address[6];
3804   u8 random_mac = 1;
3805   u32 pci_addr = 0;
3806   u64 features = (u64) ~ (0ULL);
3807   u32 virtio_flags = 0;
3808   int ret;
3809
3810   clib_memset (mac_address, 0, sizeof (mac_address));
3811
3812   /* Parse args required to build the message */
3813   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3814     {
3815       if (unformat (i, "hw-addr %U", unformat_ethernet_address, mac_address))
3816         {
3817           random_mac = 0;
3818         }
3819       else if (unformat (i, "pci-addr %U", unformat_vlib_pci_addr, &pci_addr))
3820         ;
3821       else if (unformat (i, "features 0x%llx", &features))
3822         ;
3823       else if (unformat (i, "gso-enabled"))
3824         virtio_flags |= VIRTIO_API_FLAG_GSO;
3825       else if (unformat (i, "csum-offload-enabled"))
3826         virtio_flags |= VIRTIO_API_FLAG_CSUM_OFFLOAD;
3827       else if (unformat (i, "gro-coalesce"))
3828         virtio_flags |= VIRTIO_API_FLAG_GRO_COALESCE;
3829       else if (unformat (i, "packed"))
3830         virtio_flags |= VIRTIO_API_FLAG_PACKED;
3831       else if (unformat (i, "in-order"))
3832         virtio_flags |= VIRTIO_API_FLAG_IN_ORDER;
3833       else if (unformat (i, "buffering"))
3834         virtio_flags |= VIRTIO_API_FLAG_BUFFERING;
3835       else
3836         break;
3837     }
3838
3839   if (pci_addr == 0)
3840     {
3841       errmsg ("pci address must be non zero. ");
3842       return -99;
3843     }
3844
3845   /* Construct the API message */
3846   M (VIRTIO_PCI_CREATE_V2, mp);
3847
3848   mp->use_random_mac = random_mac;
3849
3850   mp->pci_addr.domain = htons (((vlib_pci_addr_t) pci_addr).domain);
3851   mp->pci_addr.bus = ((vlib_pci_addr_t) pci_addr).bus;
3852   mp->pci_addr.slot = ((vlib_pci_addr_t) pci_addr).slot;
3853   mp->pci_addr.function = ((vlib_pci_addr_t) pci_addr).function;
3854
3855   mp->features = clib_host_to_net_u64 (features);
3856   mp->virtio_flags = clib_host_to_net_u32 (virtio_flags);
3857
3858   if (random_mac == 0)
3859     clib_memcpy (mp->mac_address, mac_address, 6);
3860
3861   /* send it... */
3862   S (mp);
3863
3864   /* Wait for a reply... */
3865   W (ret);
3866   return ret;
3867 }
3868
3869 static int
3870 api_virtio_pci_delete (vat_main_t * vam)
3871 {
3872   unformat_input_t *i = vam->input;
3873   vl_api_virtio_pci_delete_t *mp;
3874   u32 sw_if_index = ~0;
3875   u8 sw_if_index_set = 0;
3876   int ret;
3877
3878   /* Parse args required to build the message */
3879   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3880     {
3881       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3882         sw_if_index_set = 1;
3883       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3884         sw_if_index_set = 1;
3885       else
3886         break;
3887     }
3888
3889   if (sw_if_index_set == 0)
3890     {
3891       errmsg ("missing vpp interface name. ");
3892       return -99;
3893     }
3894
3895   /* Construct the API message */
3896   M (VIRTIO_PCI_DELETE, mp);
3897
3898   mp->sw_if_index = htonl (sw_if_index);
3899
3900   /* send it... */
3901   S (mp);
3902
3903   /* Wait for a reply... */
3904   W (ret);
3905   return ret;
3906 }
3907
3908 static int
3909 api_ip_table_add_del (vat_main_t * vam)
3910 {
3911   unformat_input_t *i = vam->input;
3912   vl_api_ip_table_add_del_t *mp;
3913   u32 table_id = ~0;
3914   u8 is_ipv6 = 0;
3915   u8 is_add = 1;
3916   int ret = 0;
3917
3918   /* Parse args required to build the message */
3919   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3920     {
3921       if (unformat (i, "ipv6"))
3922         is_ipv6 = 1;
3923       else if (unformat (i, "del"))
3924         is_add = 0;
3925       else if (unformat (i, "add"))
3926         is_add = 1;
3927       else if (unformat (i, "table %d", &table_id))
3928         ;
3929       else
3930         {
3931           clib_warning ("parse error '%U'", format_unformat_error, i);
3932           return -99;
3933         }
3934     }
3935
3936   if (~0 == table_id)
3937     {
3938       errmsg ("missing table-ID");
3939       return -99;
3940     }
3941
3942   /* Construct the API message */
3943   M (IP_TABLE_ADD_DEL, mp);
3944
3945   mp->table.table_id = ntohl (table_id);
3946   mp->table.is_ip6 = is_ipv6;
3947   mp->is_add = is_add;
3948
3949   /* send it... */
3950   S (mp);
3951
3952   /* Wait for a reply... */
3953   W (ret);
3954
3955   return ret;
3956 }
3957
3958 uword
3959 unformat_fib_path (unformat_input_t * input, va_list * args)
3960 {
3961   vat_main_t *vam = va_arg (*args, vat_main_t *);
3962   vl_api_fib_path_t *path = va_arg (*args, vl_api_fib_path_t *);
3963   u32 weight, preference;
3964   mpls_label_t out_label;
3965
3966   clib_memset (path, 0, sizeof (*path));
3967   path->weight = 1;
3968   path->sw_if_index = ~0;
3969   path->rpf_id = ~0;
3970   path->n_labels = 0;
3971
3972   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3973     {
3974       if (unformat (input, "%U %U",
3975                     unformat_vl_api_ip4_address,
3976                     &path->nh.address.ip4,
3977                     api_unformat_sw_if_index, vam, &path->sw_if_index))
3978         {
3979           path->proto = FIB_API_PATH_NH_PROTO_IP4;
3980         }
3981       else if (unformat (input, "%U %U",
3982                          unformat_vl_api_ip6_address,
3983                          &path->nh.address.ip6,
3984                          api_unformat_sw_if_index, vam, &path->sw_if_index))
3985         {
3986           path->proto = FIB_API_PATH_NH_PROTO_IP6;
3987         }
3988       else if (unformat (input, "weight %u", &weight))
3989         {
3990           path->weight = weight;
3991         }
3992       else if (unformat (input, "preference %u", &preference))
3993         {
3994           path->preference = preference;
3995         }
3996       else if (unformat (input, "%U next-hop-table %d",
3997                          unformat_vl_api_ip4_address,
3998                          &path->nh.address.ip4, &path->table_id))
3999         {
4000           path->proto = FIB_API_PATH_NH_PROTO_IP4;
4001         }
4002       else if (unformat (input, "%U next-hop-table %d",
4003                          unformat_vl_api_ip6_address,
4004                          &path->nh.address.ip6, &path->table_id))
4005         {
4006           path->proto = FIB_API_PATH_NH_PROTO_IP6;
4007         }
4008       else if (unformat (input, "%U",
4009                          unformat_vl_api_ip4_address, &path->nh.address.ip4))
4010         {
4011           /*
4012            * the recursive next-hops are by default in the default table
4013            */
4014           path->table_id = 0;
4015           path->sw_if_index = ~0;
4016           path->proto = FIB_API_PATH_NH_PROTO_IP4;
4017         }
4018       else if (unformat (input, "%U",
4019                          unformat_vl_api_ip6_address, &path->nh.address.ip6))
4020         {
4021           /*
4022            * the recursive next-hops are by default in the default table
4023            */
4024           path->table_id = 0;
4025           path->sw_if_index = ~0;
4026           path->proto = FIB_API_PATH_NH_PROTO_IP6;
4027         }
4028       else if (unformat (input, "resolve-via-host"))
4029         {
4030           path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_HOST;
4031         }
4032       else if (unformat (input, "resolve-via-attached"))
4033         {
4034           path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_ATTACHED;
4035         }
4036       else if (unformat (input, "ip4-lookup-in-table %d", &path->table_id))
4037         {
4038           path->type = FIB_API_PATH_TYPE_LOCAL;
4039           path->sw_if_index = ~0;
4040           path->proto = FIB_API_PATH_NH_PROTO_IP4;
4041         }
4042       else if (unformat (input, "ip6-lookup-in-table %d", &path->table_id))
4043         {
4044           path->type = FIB_API_PATH_TYPE_LOCAL;
4045           path->sw_if_index = ~0;
4046           path->proto = FIB_API_PATH_NH_PROTO_IP6;
4047         }
4048       else if (unformat (input, "sw_if_index %d", &path->sw_if_index))
4049         ;
4050       else if (unformat (input, "via-label %d", &path->nh.via_label))
4051         {
4052           path->proto = FIB_API_PATH_NH_PROTO_MPLS;
4053           path->sw_if_index = ~0;
4054         }
4055       else if (unformat (input, "l2-input-on %d", &path->sw_if_index))
4056         {
4057           path->proto = FIB_API_PATH_NH_PROTO_ETHERNET;
4058           path->type = FIB_API_PATH_TYPE_INTERFACE_RX;
4059         }
4060       else if (unformat (input, "local"))
4061         {
4062           path->type = FIB_API_PATH_TYPE_LOCAL;
4063         }
4064       else if (unformat (input, "out-labels"))
4065         {
4066           while (unformat (input, "%d", &out_label))
4067             {
4068               path->label_stack[path->n_labels].label = out_label;
4069               path->label_stack[path->n_labels].is_uniform = 0;
4070               path->label_stack[path->n_labels].ttl = 64;
4071               path->n_labels++;
4072             }
4073         }
4074       else if (unformat (input, "via"))
4075         {
4076           /* new path, back up and return */
4077           unformat_put_input (input);
4078           unformat_put_input (input);
4079           unformat_put_input (input);
4080           unformat_put_input (input);
4081           break;
4082         }
4083       else
4084         {
4085           return (0);
4086         }
4087     }
4088
4089   path->proto = ntohl (path->proto);
4090   path->type = ntohl (path->type);
4091   path->flags = ntohl (path->flags);
4092   path->table_id = ntohl (path->table_id);
4093   path->sw_if_index = ntohl (path->sw_if_index);
4094
4095   return (1);
4096 }
4097
4098 static int
4099 api_ip_route_add_del (vat_main_t * vam)
4100 {
4101   unformat_input_t *i = vam->input;
4102   vl_api_ip_route_add_del_t *mp;
4103   u32 vrf_id = 0;
4104   u8 is_add = 1;
4105   u8 is_multipath = 0;
4106   u8 prefix_set = 0;
4107   u8 path_count = 0;
4108   vl_api_prefix_t pfx = { };
4109   vl_api_fib_path_t paths[8];
4110   int count = 1;
4111   int j;
4112   f64 before = 0;
4113   u32 random_add_del = 0;
4114   u32 *random_vector = 0;
4115   u32 random_seed = 0xdeaddabe;
4116
4117   /* Parse args required to build the message */
4118   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4119     {
4120       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
4121         prefix_set = 1;
4122       else if (unformat (i, "del"))
4123         is_add = 0;
4124       else if (unformat (i, "add"))
4125         is_add = 1;
4126       else if (unformat (i, "vrf %d", &vrf_id))
4127         ;
4128       else if (unformat (i, "count %d", &count))
4129         ;
4130       else if (unformat (i, "random"))
4131         random_add_del = 1;
4132       else if (unformat (i, "multipath"))
4133         is_multipath = 1;
4134       else if (unformat (i, "seed %d", &random_seed))
4135         ;
4136       else
4137         if (unformat
4138             (i, "via %U", unformat_fib_path, vam, &paths[path_count]))
4139         {
4140           path_count++;
4141           if (8 == path_count)
4142             {
4143               errmsg ("max 8 paths");
4144               return -99;
4145             }
4146         }
4147       else
4148         {
4149           clib_warning ("parse error '%U'", format_unformat_error, i);
4150           return -99;
4151         }
4152     }
4153
4154   if (!path_count)
4155     {
4156       errmsg ("specify a path; via ...");
4157       return -99;
4158     }
4159   if (prefix_set == 0)
4160     {
4161       errmsg ("missing prefix");
4162       return -99;
4163     }
4164
4165   /* Generate a pile of unique, random routes */
4166   if (random_add_del)
4167     {
4168       ip4_address_t *i = (ip4_address_t *) & paths[0].nh.address.ip4;
4169       u32 this_random_address;
4170       uword *random_hash;
4171
4172       random_hash = hash_create (count, sizeof (uword));
4173
4174       hash_set (random_hash, i->as_u32, 1);
4175       for (j = 0; j <= count; j++)
4176         {
4177           do
4178             {
4179               this_random_address = random_u32 (&random_seed);
4180               this_random_address =
4181                 clib_host_to_net_u32 (this_random_address);
4182             }
4183           while (hash_get (random_hash, this_random_address));
4184           vec_add1 (random_vector, this_random_address);
4185           hash_set (random_hash, this_random_address, 1);
4186         }
4187       hash_free (random_hash);
4188       set_ip4_address (&pfx.address, random_vector[0]);
4189     }
4190
4191   if (count > 1)
4192     {
4193       /* Turn on async mode */
4194       vam->async_mode = 1;
4195       vam->async_errors = 0;
4196       before = vat_time_now (vam);
4197     }
4198
4199   for (j = 0; j < count; j++)
4200     {
4201       /* Construct the API message */
4202       M2 (IP_ROUTE_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
4203
4204       mp->is_add = is_add;
4205       mp->is_multipath = is_multipath;
4206
4207       clib_memcpy (&mp->route.prefix, &pfx, sizeof (pfx));
4208       mp->route.table_id = ntohl (vrf_id);
4209       mp->route.n_paths = path_count;
4210
4211       clib_memcpy (&mp->route.paths, &paths, sizeof (paths[0]) * path_count);
4212
4213       if (random_add_del)
4214         set_ip4_address (&pfx.address, random_vector[j + 1]);
4215       else
4216         increment_address (&pfx.address);
4217       /* send it... */
4218       S (mp);
4219       /* If we receive SIGTERM, stop now... */
4220       if (vam->do_exit)
4221         break;
4222     }
4223
4224   /* When testing multiple add/del ops, use a control-ping to sync */
4225   if (count > 1)
4226     {
4227       vl_api_control_ping_t *mp_ping;
4228       f64 after;
4229       f64 timeout;
4230
4231       /* Shut off async mode */
4232       vam->async_mode = 0;
4233
4234       MPING (CONTROL_PING, mp_ping);
4235       S (mp_ping);
4236
4237       timeout = vat_time_now (vam) + 1.0;
4238       while (vat_time_now (vam) < timeout)
4239         if (vam->result_ready == 1)
4240           goto out;
4241       vam->retval = -99;
4242
4243     out:
4244       if (vam->retval == -99)
4245         errmsg ("timeout");
4246
4247       if (vam->async_errors > 0)
4248         {
4249           errmsg ("%d asynchronous errors", vam->async_errors);
4250           vam->retval = -98;
4251         }
4252       vam->async_errors = 0;
4253       after = vat_time_now (vam);
4254
4255       /* slim chance, but we might have eaten SIGTERM on the first iteration */
4256       if (j > 0)
4257         count = j;
4258
4259       print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec",
4260              count, after - before, count / (after - before));
4261     }
4262   else
4263     {
4264       int ret;
4265
4266       /* Wait for a reply... */
4267       W (ret);
4268       return ret;
4269     }
4270
4271   /* Return the good/bad news */
4272   return (vam->retval);
4273 }
4274
4275 static int
4276 api_ip_mroute_add_del (vat_main_t * vam)
4277 {
4278   unformat_input_t *i = vam->input;
4279   u8 path_set = 0, prefix_set = 0, is_add = 1;
4280   vl_api_ip_mroute_add_del_t *mp;
4281   mfib_entry_flags_t eflags = 0;
4282   vl_api_mfib_path_t path;
4283   vl_api_mprefix_t pfx = { };
4284   u32 vrf_id = 0;
4285   int ret;
4286
4287   /* Parse args required to build the message */
4288   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4289     {
4290       if (unformat (i, "%U", unformat_vl_api_mprefix, &pfx))
4291         {
4292           prefix_set = 1;
4293           pfx.grp_address_length = htons (pfx.grp_address_length);
4294         }
4295       else if (unformat (i, "del"))
4296         is_add = 0;
4297       else if (unformat (i, "add"))
4298         is_add = 1;
4299       else if (unformat (i, "vrf %d", &vrf_id))
4300         ;
4301       else if (unformat (i, "%U", unformat_mfib_itf_flags, &path.itf_flags))
4302         path.itf_flags = htonl (path.itf_flags);
4303       else if (unformat (i, "%U", unformat_mfib_entry_flags, &eflags))
4304         ;
4305       else if (unformat (i, "via %U", unformat_fib_path, vam, &path.path))
4306         path_set = 1;
4307       else
4308         {
4309           clib_warning ("parse error '%U'", format_unformat_error, i);
4310           return -99;
4311         }
4312     }
4313
4314   if (prefix_set == 0)
4315     {
4316       errmsg ("missing addresses\n");
4317       return -99;
4318     }
4319   if (path_set == 0)
4320     {
4321       errmsg ("missing path\n");
4322       return -99;
4323     }
4324
4325   /* Construct the API message */
4326   M (IP_MROUTE_ADD_DEL, mp);
4327
4328   mp->is_add = is_add;
4329   mp->is_multipath = 1;
4330
4331   clib_memcpy (&mp->route.prefix, &pfx, sizeof (pfx));
4332   mp->route.table_id = htonl (vrf_id);
4333   mp->route.n_paths = 1;
4334   mp->route.entry_flags = htonl (eflags);
4335
4336   clib_memcpy (&mp->route.paths, &path, sizeof (path));
4337
4338   /* send it... */
4339   S (mp);
4340   /* Wait for a reply... */
4341   W (ret);
4342   return ret;
4343 }
4344
4345 static int
4346 api_mpls_table_add_del (vat_main_t * vam)
4347 {
4348   unformat_input_t *i = vam->input;
4349   vl_api_mpls_table_add_del_t *mp;
4350   u32 table_id = ~0;
4351   u8 is_add = 1;
4352   int ret = 0;
4353
4354   /* Parse args required to build the message */
4355   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4356     {
4357       if (unformat (i, "table %d", &table_id))
4358         ;
4359       else if (unformat (i, "del"))
4360         is_add = 0;
4361       else if (unformat (i, "add"))
4362         is_add = 1;
4363       else
4364         {
4365           clib_warning ("parse error '%U'", format_unformat_error, i);
4366           return -99;
4367         }
4368     }
4369
4370   if (~0 == table_id)
4371     {
4372       errmsg ("missing table-ID");
4373       return -99;
4374     }
4375
4376   /* Construct the API message */
4377   M (MPLS_TABLE_ADD_DEL, mp);
4378
4379   mp->mt_table.mt_table_id = ntohl (table_id);
4380   mp->mt_is_add = is_add;
4381
4382   /* send it... */
4383   S (mp);
4384
4385   /* Wait for a reply... */
4386   W (ret);
4387
4388   return ret;
4389 }
4390
4391 static int
4392 api_mpls_route_add_del (vat_main_t * vam)
4393 {
4394   u8 is_add = 1, path_count = 0, is_multipath = 0, is_eos = 0;
4395   mpls_label_t local_label = MPLS_LABEL_INVALID;
4396   unformat_input_t *i = vam->input;
4397   vl_api_mpls_route_add_del_t *mp;
4398   vl_api_fib_path_t paths[8];
4399   int count = 1, j;
4400   f64 before = 0;
4401
4402   /* Parse args required to build the message */
4403   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4404     {
4405       if (unformat (i, "%d", &local_label))
4406         ;
4407       else if (unformat (i, "eos"))
4408         is_eos = 1;
4409       else if (unformat (i, "non-eos"))
4410         is_eos = 0;
4411       else if (unformat (i, "del"))
4412         is_add = 0;
4413       else if (unformat (i, "add"))
4414         is_add = 1;
4415       else if (unformat (i, "multipath"))
4416         is_multipath = 1;
4417       else if (unformat (i, "count %d", &count))
4418         ;
4419       else
4420         if (unformat
4421             (i, "via %U", unformat_fib_path, vam, &paths[path_count]))
4422         {
4423           path_count++;
4424           if (8 == path_count)
4425             {
4426               errmsg ("max 8 paths");
4427               return -99;
4428             }
4429         }
4430       else
4431         {
4432           clib_warning ("parse error '%U'", format_unformat_error, i);
4433           return -99;
4434         }
4435     }
4436
4437   if (!path_count)
4438     {
4439       errmsg ("specify a path; via ...");
4440       return -99;
4441     }
4442
4443   if (MPLS_LABEL_INVALID == local_label)
4444     {
4445       errmsg ("missing label");
4446       return -99;
4447     }
4448
4449   if (count > 1)
4450     {
4451       /* Turn on async mode */
4452       vam->async_mode = 1;
4453       vam->async_errors = 0;
4454       before = vat_time_now (vam);
4455     }
4456
4457   for (j = 0; j < count; j++)
4458     {
4459       /* Construct the API message */
4460       M2 (MPLS_ROUTE_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
4461
4462       mp->mr_is_add = is_add;
4463       mp->mr_is_multipath = is_multipath;
4464
4465       mp->mr_route.mr_label = local_label;
4466       mp->mr_route.mr_eos = is_eos;
4467       mp->mr_route.mr_table_id = 0;
4468       mp->mr_route.mr_n_paths = path_count;
4469
4470       clib_memcpy (&mp->mr_route.mr_paths, paths,
4471                    sizeof (paths[0]) * path_count);
4472
4473       local_label++;
4474
4475       /* send it... */
4476       S (mp);
4477       /* If we receive SIGTERM, stop now... */
4478       if (vam->do_exit)
4479         break;
4480     }
4481
4482   /* When testing multiple add/del ops, use a control-ping to sync */
4483   if (count > 1)
4484     {
4485       vl_api_control_ping_t *mp_ping;
4486       f64 after;
4487       f64 timeout;
4488
4489       /* Shut off async mode */
4490       vam->async_mode = 0;
4491
4492       MPING (CONTROL_PING, mp_ping);
4493       S (mp_ping);
4494
4495       timeout = vat_time_now (vam) + 1.0;
4496       while (vat_time_now (vam) < timeout)
4497         if (vam->result_ready == 1)
4498           goto out;
4499       vam->retval = -99;
4500
4501     out:
4502       if (vam->retval == -99)
4503         errmsg ("timeout");
4504
4505       if (vam->async_errors > 0)
4506         {
4507           errmsg ("%d asynchronous errors", vam->async_errors);
4508           vam->retval = -98;
4509         }
4510       vam->async_errors = 0;
4511       after = vat_time_now (vam);
4512
4513       /* slim chance, but we might have eaten SIGTERM on the first iteration */
4514       if (j > 0)
4515         count = j;
4516
4517       print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec",
4518              count, after - before, count / (after - before));
4519     }
4520   else
4521     {
4522       int ret;
4523
4524       /* Wait for a reply... */
4525       W (ret);
4526       return ret;
4527     }
4528
4529   /* Return the good/bad news */
4530   return (vam->retval);
4531   return (0);
4532 }
4533
4534 static int
4535 api_mpls_ip_bind_unbind (vat_main_t * vam)
4536 {
4537   unformat_input_t *i = vam->input;
4538   vl_api_mpls_ip_bind_unbind_t *mp;
4539   u32 ip_table_id = 0;
4540   u8 is_bind = 1;
4541   vl_api_prefix_t pfx;
4542   u8 prefix_set = 0;
4543   mpls_label_t local_label = MPLS_LABEL_INVALID;
4544   int ret;
4545
4546   /* Parse args required to build the message */
4547   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4548     {
4549       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
4550         prefix_set = 1;
4551       else if (unformat (i, "%d", &local_label))
4552         ;
4553       else if (unformat (i, "table-id %d", &ip_table_id))
4554         ;
4555       else if (unformat (i, "unbind"))
4556         is_bind = 0;
4557       else if (unformat (i, "bind"))
4558         is_bind = 1;
4559       else
4560         {
4561           clib_warning ("parse error '%U'", format_unformat_error, i);
4562           return -99;
4563         }
4564     }
4565
4566   if (!prefix_set)
4567     {
4568       errmsg ("IP prefix not set");
4569       return -99;
4570     }
4571
4572   if (MPLS_LABEL_INVALID == local_label)
4573     {
4574       errmsg ("missing label");
4575       return -99;
4576     }
4577
4578   /* Construct the API message */
4579   M (MPLS_IP_BIND_UNBIND, mp);
4580
4581   mp->mb_is_bind = is_bind;
4582   mp->mb_ip_table_id = ntohl (ip_table_id);
4583   mp->mb_mpls_table_id = 0;
4584   mp->mb_label = ntohl (local_label);
4585   clib_memcpy (&mp->mb_prefix, &pfx, sizeof (pfx));
4586
4587   /* send it... */
4588   S (mp);
4589
4590   /* Wait for a reply... */
4591   W (ret);
4592   return ret;
4593   return (0);
4594 }
4595
4596 static int
4597 api_mpls_tunnel_add_del (vat_main_t * vam)
4598 {
4599   unformat_input_t *i = vam->input;
4600   vl_api_mpls_tunnel_add_del_t *mp;
4601
4602   vl_api_fib_path_t paths[8];
4603   u32 sw_if_index = ~0;
4604   u8 path_count = 0;
4605   u8 l2_only = 0;
4606   u8 is_add = 1;
4607   int ret;
4608
4609   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4610     {
4611       if (unformat (i, "add"))
4612         is_add = 1;
4613       else
4614         if (unformat
4615             (i, "del %U", api_unformat_sw_if_index, vam, &sw_if_index))
4616         is_add = 0;
4617       else if (unformat (i, "del sw_if_index %d", &sw_if_index))
4618         is_add = 0;
4619       else if (unformat (i, "l2-only"))
4620         l2_only = 1;
4621       else
4622         if (unformat
4623             (i, "via %U", unformat_fib_path, vam, &paths[path_count]))
4624         {
4625           path_count++;
4626           if (8 == path_count)
4627             {
4628               errmsg ("max 8 paths");
4629               return -99;
4630             }
4631         }
4632       else
4633         {
4634           clib_warning ("parse error '%U'", format_unformat_error, i);
4635           return -99;
4636         }
4637     }
4638
4639   M2 (MPLS_TUNNEL_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
4640
4641   mp->mt_is_add = is_add;
4642   mp->mt_tunnel.mt_sw_if_index = ntohl (sw_if_index);
4643   mp->mt_tunnel.mt_l2_only = l2_only;
4644   mp->mt_tunnel.mt_is_multicast = 0;
4645   mp->mt_tunnel.mt_n_paths = path_count;
4646
4647   clib_memcpy (&mp->mt_tunnel.mt_paths, &paths,
4648                sizeof (paths[0]) * path_count);
4649
4650   S (mp);
4651   W (ret);
4652   return ret;
4653 }
4654
4655 static int
4656 api_sw_interface_set_unnumbered (vat_main_t * vam)
4657 {
4658   unformat_input_t *i = vam->input;
4659   vl_api_sw_interface_set_unnumbered_t *mp;
4660   u32 sw_if_index;
4661   u32 unnum_sw_index = ~0;
4662   u8 is_add = 1;
4663   u8 sw_if_index_set = 0;
4664   int ret;
4665
4666   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4667     {
4668       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4669         sw_if_index_set = 1;
4670       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4671         sw_if_index_set = 1;
4672       else if (unformat (i, "unnum_if_index %d", &unnum_sw_index))
4673         ;
4674       else if (unformat (i, "del"))
4675         is_add = 0;
4676       else
4677         {
4678           clib_warning ("parse error '%U'", format_unformat_error, i);
4679           return -99;
4680         }
4681     }
4682
4683   if (sw_if_index_set == 0)
4684     {
4685       errmsg ("missing interface name or sw_if_index");
4686       return -99;
4687     }
4688
4689   M (SW_INTERFACE_SET_UNNUMBERED, mp);
4690
4691   mp->sw_if_index = ntohl (sw_if_index);
4692   mp->unnumbered_sw_if_index = ntohl (unnum_sw_index);
4693   mp->is_add = is_add;
4694
4695   S (mp);
4696   W (ret);
4697   return ret;
4698 }
4699
4700
4701 static int
4702 api_create_vlan_subif (vat_main_t * vam)
4703 {
4704   unformat_input_t *i = vam->input;
4705   vl_api_create_vlan_subif_t *mp;
4706   u32 sw_if_index;
4707   u8 sw_if_index_set = 0;
4708   u32 vlan_id;
4709   u8 vlan_id_set = 0;
4710   int ret;
4711
4712   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4713     {
4714       if (unformat (i, "sw_if_index %d", &sw_if_index))
4715         sw_if_index_set = 1;
4716       else
4717         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4718         sw_if_index_set = 1;
4719       else if (unformat (i, "vlan %d", &vlan_id))
4720         vlan_id_set = 1;
4721       else
4722         {
4723           clib_warning ("parse error '%U'", format_unformat_error, i);
4724           return -99;
4725         }
4726     }
4727
4728   if (sw_if_index_set == 0)
4729     {
4730       errmsg ("missing interface name or sw_if_index");
4731       return -99;
4732     }
4733
4734   if (vlan_id_set == 0)
4735     {
4736       errmsg ("missing vlan_id");
4737       return -99;
4738     }
4739   M (CREATE_VLAN_SUBIF, mp);
4740
4741   mp->sw_if_index = ntohl (sw_if_index);
4742   mp->vlan_id = ntohl (vlan_id);
4743
4744   S (mp);
4745   W (ret);
4746   return ret;
4747 }
4748
4749 #define foreach_create_subif_bit                \
4750 _(no_tags)                                      \
4751 _(one_tag)                                      \
4752 _(two_tags)                                     \
4753 _(dot1ad)                                       \
4754 _(exact_match)                                  \
4755 _(default_sub)                                  \
4756 _(outer_vlan_id_any)                            \
4757 _(inner_vlan_id_any)
4758
4759 #define foreach_create_subif_flag               \
4760 _(0, "no_tags")                                 \
4761 _(1, "one_tag")                                 \
4762 _(2, "two_tags")                                \
4763 _(3, "dot1ad")                                  \
4764 _(4, "exact_match")                             \
4765 _(5, "default_sub")                             \
4766 _(6, "outer_vlan_id_any")                       \
4767 _(7, "inner_vlan_id_any")
4768
4769 static int
4770 api_create_subif (vat_main_t * vam)
4771 {
4772   unformat_input_t *i = vam->input;
4773   vl_api_create_subif_t *mp;
4774   u32 sw_if_index;
4775   u8 sw_if_index_set = 0;
4776   u32 sub_id;
4777   u8 sub_id_set = 0;
4778   u32 __attribute__ ((unused)) no_tags = 0;
4779   u32 __attribute__ ((unused)) one_tag = 0;
4780   u32 __attribute__ ((unused)) two_tags = 0;
4781   u32 __attribute__ ((unused)) dot1ad = 0;
4782   u32 __attribute__ ((unused)) exact_match = 0;
4783   u32 __attribute__ ((unused)) default_sub = 0;
4784   u32 __attribute__ ((unused)) outer_vlan_id_any = 0;
4785   u32 __attribute__ ((unused)) inner_vlan_id_any = 0;
4786   u32 tmp;
4787   u16 outer_vlan_id = 0;
4788   u16 inner_vlan_id = 0;
4789   int ret;
4790
4791   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4792     {
4793       if (unformat (i, "sw_if_index %d", &sw_if_index))
4794         sw_if_index_set = 1;
4795       else
4796         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4797         sw_if_index_set = 1;
4798       else if (unformat (i, "sub_id %d", &sub_id))
4799         sub_id_set = 1;
4800       else if (unformat (i, "outer_vlan_id %d", &tmp))
4801         outer_vlan_id = tmp;
4802       else if (unformat (i, "inner_vlan_id %d", &tmp))
4803         inner_vlan_id = tmp;
4804
4805 #define _(a) else if (unformat (i, #a)) a = 1 ;
4806       foreach_create_subif_bit
4807 #undef _
4808         else
4809         {
4810           clib_warning ("parse error '%U'", format_unformat_error, i);
4811           return -99;
4812         }
4813     }
4814
4815   if (sw_if_index_set == 0)
4816     {
4817       errmsg ("missing interface name or sw_if_index");
4818       return -99;
4819     }
4820
4821   if (sub_id_set == 0)
4822     {
4823       errmsg ("missing sub_id");
4824       return -99;
4825     }
4826   M (CREATE_SUBIF, mp);
4827
4828   mp->sw_if_index = ntohl (sw_if_index);
4829   mp->sub_id = ntohl (sub_id);
4830
4831 #define _(a,b) mp->sub_if_flags |= (1 << a);
4832   foreach_create_subif_flag;
4833 #undef _
4834
4835   mp->outer_vlan_id = ntohs (outer_vlan_id);
4836   mp->inner_vlan_id = ntohs (inner_vlan_id);
4837
4838   S (mp);
4839   W (ret);
4840   return ret;
4841 }
4842
4843 static int
4844 api_ip_table_replace_begin (vat_main_t * vam)
4845 {
4846   unformat_input_t *i = vam->input;
4847   vl_api_ip_table_replace_begin_t *mp;
4848   u32 table_id = 0;
4849   u8 is_ipv6 = 0;
4850
4851   int ret;
4852   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4853     {
4854       if (unformat (i, "table %d", &table_id))
4855         ;
4856       else if (unformat (i, "ipv6"))
4857         is_ipv6 = 1;
4858       else
4859         {
4860           clib_warning ("parse error '%U'", format_unformat_error, i);
4861           return -99;
4862         }
4863     }
4864
4865   M (IP_TABLE_REPLACE_BEGIN, mp);
4866
4867   mp->table.table_id = ntohl (table_id);
4868   mp->table.is_ip6 = is_ipv6;
4869
4870   S (mp);
4871   W (ret);
4872   return ret;
4873 }
4874
4875 static int
4876 api_ip_table_flush (vat_main_t * vam)
4877 {
4878   unformat_input_t *i = vam->input;
4879   vl_api_ip_table_flush_t *mp;
4880   u32 table_id = 0;
4881   u8 is_ipv6 = 0;
4882
4883   int ret;
4884   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4885     {
4886       if (unformat (i, "table %d", &table_id))
4887         ;
4888       else if (unformat (i, "ipv6"))
4889         is_ipv6 = 1;
4890       else
4891         {
4892           clib_warning ("parse error '%U'", format_unformat_error, i);
4893           return -99;
4894         }
4895     }
4896
4897   M (IP_TABLE_FLUSH, mp);
4898
4899   mp->table.table_id = ntohl (table_id);
4900   mp->table.is_ip6 = is_ipv6;
4901
4902   S (mp);
4903   W (ret);
4904   return ret;
4905 }
4906
4907 static int
4908 api_ip_table_replace_end (vat_main_t * vam)
4909 {
4910   unformat_input_t *i = vam->input;
4911   vl_api_ip_table_replace_end_t *mp;
4912   u32 table_id = 0;
4913   u8 is_ipv6 = 0;
4914
4915   int ret;
4916   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4917     {
4918       if (unformat (i, "table %d", &table_id))
4919         ;
4920       else if (unformat (i, "ipv6"))
4921         is_ipv6 = 1;
4922       else
4923         {
4924           clib_warning ("parse error '%U'", format_unformat_error, i);
4925           return -99;
4926         }
4927     }
4928
4929   M (IP_TABLE_REPLACE_END, mp);
4930
4931   mp->table.table_id = ntohl (table_id);
4932   mp->table.is_ip6 = is_ipv6;
4933
4934   S (mp);
4935   W (ret);
4936   return ret;
4937 }
4938
4939 static int
4940 api_set_ip_flow_hash (vat_main_t * vam)
4941 {
4942   unformat_input_t *i = vam->input;
4943   vl_api_set_ip_flow_hash_t *mp;
4944   u32 vrf_id = 0;
4945   u8 is_ipv6 = 0;
4946   u8 vrf_id_set = 0;
4947   u8 src = 0;
4948   u8 dst = 0;
4949   u8 sport = 0;
4950   u8 dport = 0;
4951   u8 proto = 0;
4952   u8 reverse = 0;
4953   int ret;
4954
4955   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4956     {
4957       if (unformat (i, "vrf %d", &vrf_id))
4958         vrf_id_set = 1;
4959       else if (unformat (i, "ipv6"))
4960         is_ipv6 = 1;
4961       else if (unformat (i, "src"))
4962         src = 1;
4963       else if (unformat (i, "dst"))
4964         dst = 1;
4965       else if (unformat (i, "sport"))
4966         sport = 1;
4967       else if (unformat (i, "dport"))
4968         dport = 1;
4969       else if (unformat (i, "proto"))
4970         proto = 1;
4971       else if (unformat (i, "reverse"))
4972         reverse = 1;
4973
4974       else
4975         {
4976           clib_warning ("parse error '%U'", format_unformat_error, i);
4977           return -99;
4978         }
4979     }
4980
4981   if (vrf_id_set == 0)
4982     {
4983       errmsg ("missing vrf id");
4984       return -99;
4985     }
4986
4987   M (SET_IP_FLOW_HASH, mp);
4988   mp->src = src;
4989   mp->dst = dst;
4990   mp->sport = sport;
4991   mp->dport = dport;
4992   mp->proto = proto;
4993   mp->reverse = reverse;
4994   mp->vrf_id = ntohl (vrf_id);
4995   mp->is_ipv6 = is_ipv6;
4996
4997   S (mp);
4998   W (ret);
4999   return ret;
5000 }
5001
5002 static int
5003 api_sw_interface_ip6_enable_disable (vat_main_t * vam)
5004 {
5005   unformat_input_t *i = vam->input;
5006   vl_api_sw_interface_ip6_enable_disable_t *mp;
5007   u32 sw_if_index;
5008   u8 sw_if_index_set = 0;
5009   u8 enable = 0;
5010   int ret;
5011
5012   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5013     {
5014       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5015         sw_if_index_set = 1;
5016       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5017         sw_if_index_set = 1;
5018       else if (unformat (i, "enable"))
5019         enable = 1;
5020       else if (unformat (i, "disable"))
5021         enable = 0;
5022       else
5023         {
5024           clib_warning ("parse error '%U'", format_unformat_error, i);
5025           return -99;
5026         }
5027     }
5028
5029   if (sw_if_index_set == 0)
5030     {
5031       errmsg ("missing interface name or sw_if_index");
5032       return -99;
5033     }
5034
5035   M (SW_INTERFACE_IP6_ENABLE_DISABLE, mp);
5036
5037   mp->sw_if_index = ntohl (sw_if_index);
5038   mp->enable = enable;
5039
5040   S (mp);
5041   W (ret);
5042   return ret;
5043 }
5044
5045
5046 static int
5047 api_l2_patch_add_del (vat_main_t * vam)
5048 {
5049   unformat_input_t *i = vam->input;
5050   vl_api_l2_patch_add_del_t *mp;
5051   u32 rx_sw_if_index;
5052   u8 rx_sw_if_index_set = 0;
5053   u32 tx_sw_if_index;
5054   u8 tx_sw_if_index_set = 0;
5055   u8 is_add = 1;
5056   int ret;
5057
5058   /* Parse args required to build the message */
5059   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5060     {
5061       if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index))
5062         rx_sw_if_index_set = 1;
5063       else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
5064         tx_sw_if_index_set = 1;
5065       else if (unformat (i, "rx"))
5066         {
5067           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5068             {
5069               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
5070                             &rx_sw_if_index))
5071                 rx_sw_if_index_set = 1;
5072             }
5073           else
5074             break;
5075         }
5076       else if (unformat (i, "tx"))
5077         {
5078           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5079             {
5080               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
5081                             &tx_sw_if_index))
5082                 tx_sw_if_index_set = 1;
5083             }
5084           else
5085             break;
5086         }
5087       else if (unformat (i, "del"))
5088         is_add = 0;
5089       else
5090         break;
5091     }
5092
5093   if (rx_sw_if_index_set == 0)
5094     {
5095       errmsg ("missing rx interface name or rx_sw_if_index");
5096       return -99;
5097     }
5098
5099   if (tx_sw_if_index_set == 0)
5100     {
5101       errmsg ("missing tx interface name or tx_sw_if_index");
5102       return -99;
5103     }
5104
5105   M (L2_PATCH_ADD_DEL, mp);
5106
5107   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
5108   mp->tx_sw_if_index = ntohl (tx_sw_if_index);
5109   mp->is_add = is_add;
5110
5111   S (mp);
5112   W (ret);
5113   return ret;
5114 }
5115
5116 u8 is_del;
5117 u8 localsid_addr[16];
5118 u8 end_psp;
5119 u8 behavior;
5120 u32 sw_if_index;
5121 u32 vlan_index;
5122 u32 fib_table;
5123 u8 nh_addr[16];
5124
5125 static int
5126 api_ioam_enable (vat_main_t * vam)
5127 {
5128   unformat_input_t *input = vam->input;
5129   vl_api_ioam_enable_t *mp;
5130   u32 id = 0;
5131   int has_trace_option = 0;
5132   int has_pot_option = 0;
5133   int has_seqno_option = 0;
5134   int has_analyse_option = 0;
5135   int ret;
5136
5137   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5138     {
5139       if (unformat (input, "trace"))
5140         has_trace_option = 1;
5141       else if (unformat (input, "pot"))
5142         has_pot_option = 1;
5143       else if (unformat (input, "seqno"))
5144         has_seqno_option = 1;
5145       else if (unformat (input, "analyse"))
5146         has_analyse_option = 1;
5147       else
5148         break;
5149     }
5150   M (IOAM_ENABLE, mp);
5151   mp->id = htons (id);
5152   mp->seqno = has_seqno_option;
5153   mp->analyse = has_analyse_option;
5154   mp->pot_enable = has_pot_option;
5155   mp->trace_enable = has_trace_option;
5156
5157   S (mp);
5158   W (ret);
5159   return ret;
5160 }
5161
5162
5163 static int
5164 api_ioam_disable (vat_main_t * vam)
5165 {
5166   vl_api_ioam_disable_t *mp;
5167   int ret;
5168
5169   M (IOAM_DISABLE, mp);
5170   S (mp);
5171   W (ret);
5172   return ret;
5173 }
5174
5175 #define foreach_tcp_proto_field                 \
5176 _(src_port)                                     \
5177 _(dst_port)
5178
5179 #define foreach_udp_proto_field                 \
5180 _(src_port)                                     \
5181 _(dst_port)
5182
5183 #define foreach_ip4_proto_field                 \
5184 _(src_address)                                  \
5185 _(dst_address)                                  \
5186 _(tos)                                          \
5187 _(length)                                       \
5188 _(fragment_id)                                  \
5189 _(ttl)                                          \
5190 _(protocol)                                     \
5191 _(checksum)
5192
5193 typedef struct
5194 {
5195   u16 src_port, dst_port;
5196 } tcpudp_header_t;
5197
5198 #if VPP_API_TEST_BUILTIN == 0
5199 uword
5200 unformat_tcp_mask (unformat_input_t * input, va_list * args)
5201 {
5202   u8 **maskp = va_arg (*args, u8 **);
5203   u8 *mask = 0;
5204   u8 found_something = 0;
5205   tcp_header_t *tcp;
5206
5207 #define _(a) u8 a=0;
5208   foreach_tcp_proto_field;
5209 #undef _
5210
5211   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5212     {
5213       if (0);
5214 #define _(a) else if (unformat (input, #a)) a=1;
5215       foreach_tcp_proto_field
5216 #undef _
5217         else
5218         break;
5219     }
5220
5221 #define _(a) found_something += a;
5222   foreach_tcp_proto_field;
5223 #undef _
5224
5225   if (found_something == 0)
5226     return 0;
5227
5228   vec_validate (mask, sizeof (*tcp) - 1);
5229
5230   tcp = (tcp_header_t *) mask;
5231
5232 #define _(a) if (a) clib_memset (&tcp->a, 0xff, sizeof (tcp->a));
5233   foreach_tcp_proto_field;
5234 #undef _
5235
5236   *maskp = mask;
5237   return 1;
5238 }
5239
5240 uword
5241 unformat_udp_mask (unformat_input_t * input, va_list * args)
5242 {
5243   u8 **maskp = va_arg (*args, u8 **);
5244   u8 *mask = 0;
5245   u8 found_something = 0;
5246   udp_header_t *udp;
5247
5248 #define _(a) u8 a=0;
5249   foreach_udp_proto_field;
5250 #undef _
5251
5252   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5253     {
5254       if (0);
5255 #define _(a) else if (unformat (input, #a)) a=1;
5256       foreach_udp_proto_field
5257 #undef _
5258         else
5259         break;
5260     }
5261
5262 #define _(a) found_something += a;
5263   foreach_udp_proto_field;
5264 #undef _
5265
5266   if (found_something == 0)
5267     return 0;
5268
5269   vec_validate (mask, sizeof (*udp) - 1);
5270
5271   udp = (udp_header_t *) mask;
5272
5273 #define _(a) if (a) clib_memset (&udp->a, 0xff, sizeof (udp->a));
5274   foreach_udp_proto_field;
5275 #undef _
5276
5277   *maskp = mask;
5278   return 1;
5279 }
5280
5281 uword
5282 unformat_l4_mask (unformat_input_t * input, va_list * args)
5283 {
5284   u8 **maskp = va_arg (*args, u8 **);
5285   u16 src_port = 0, dst_port = 0;
5286   tcpudp_header_t *tcpudp;
5287
5288   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5289     {
5290       if (unformat (input, "tcp %U", unformat_tcp_mask, maskp))
5291         return 1;
5292       else if (unformat (input, "udp %U", unformat_udp_mask, maskp))
5293         return 1;
5294       else if (unformat (input, "src_port"))
5295         src_port = 0xFFFF;
5296       else if (unformat (input, "dst_port"))
5297         dst_port = 0xFFFF;
5298       else
5299         return 0;
5300     }
5301
5302   if (!src_port && !dst_port)
5303     return 0;
5304
5305   u8 *mask = 0;
5306   vec_validate (mask, sizeof (tcpudp_header_t) - 1);
5307
5308   tcpudp = (tcpudp_header_t *) mask;
5309   tcpudp->src_port = src_port;
5310   tcpudp->dst_port = dst_port;
5311
5312   *maskp = mask;
5313
5314   return 1;
5315 }
5316
5317 uword
5318 unformat_ip4_mask (unformat_input_t * input, va_list * args)
5319 {
5320   u8 **maskp = va_arg (*args, u8 **);
5321   u8 *mask = 0;
5322   u8 found_something = 0;
5323   ip4_header_t *ip;
5324
5325 #define _(a) u8 a=0;
5326   foreach_ip4_proto_field;
5327 #undef _
5328   u8 version = 0;
5329   u8 hdr_length = 0;
5330
5331
5332   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5333     {
5334       if (unformat (input, "version"))
5335         version = 1;
5336       else if (unformat (input, "hdr_length"))
5337         hdr_length = 1;
5338       else if (unformat (input, "src"))
5339         src_address = 1;
5340       else if (unformat (input, "dst"))
5341         dst_address = 1;
5342       else if (unformat (input, "proto"))
5343         protocol = 1;
5344
5345 #define _(a) else if (unformat (input, #a)) a=1;
5346       foreach_ip4_proto_field
5347 #undef _
5348         else
5349         break;
5350     }
5351
5352 #define _(a) found_something += a;
5353   foreach_ip4_proto_field;
5354 #undef _
5355
5356   if (found_something == 0)
5357     return 0;
5358
5359   vec_validate (mask, sizeof (*ip) - 1);
5360
5361   ip = (ip4_header_t *) mask;
5362
5363 #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
5364   foreach_ip4_proto_field;
5365 #undef _
5366
5367   ip->ip_version_and_header_length = 0;
5368
5369   if (version)
5370     ip->ip_version_and_header_length |= 0xF0;
5371
5372   if (hdr_length)
5373     ip->ip_version_and_header_length |= 0x0F;
5374
5375   *maskp = mask;
5376   return 1;
5377 }
5378
5379 #define foreach_ip6_proto_field                 \
5380 _(src_address)                                  \
5381 _(dst_address)                                  \
5382 _(payload_length)                               \
5383 _(hop_limit)                                    \
5384 _(protocol)
5385
5386 uword
5387 unformat_ip6_mask (unformat_input_t * input, va_list * args)
5388 {
5389   u8 **maskp = va_arg (*args, u8 **);
5390   u8 *mask = 0;
5391   u8 found_something = 0;
5392   ip6_header_t *ip;
5393   u32 ip_version_traffic_class_and_flow_label;
5394
5395 #define _(a) u8 a=0;
5396   foreach_ip6_proto_field;
5397 #undef _
5398   u8 version = 0;
5399   u8 traffic_class = 0;
5400   u8 flow_label = 0;
5401
5402   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5403     {
5404       if (unformat (input, "version"))
5405         version = 1;
5406       else if (unformat (input, "traffic-class"))
5407         traffic_class = 1;
5408       else if (unformat (input, "flow-label"))
5409         flow_label = 1;
5410       else if (unformat (input, "src"))
5411         src_address = 1;
5412       else if (unformat (input, "dst"))
5413         dst_address = 1;
5414       else if (unformat (input, "proto"))
5415         protocol = 1;
5416
5417 #define _(a) else if (unformat (input, #a)) a=1;
5418       foreach_ip6_proto_field
5419 #undef _
5420         else
5421         break;
5422     }
5423
5424 #define _(a) found_something += a;
5425   foreach_ip6_proto_field;
5426 #undef _
5427
5428   if (found_something == 0)
5429     return 0;
5430
5431   vec_validate (mask, sizeof (*ip) - 1);
5432
5433   ip = (ip6_header_t *) mask;
5434
5435 #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
5436   foreach_ip6_proto_field;
5437 #undef _
5438
5439   ip_version_traffic_class_and_flow_label = 0;
5440
5441   if (version)
5442     ip_version_traffic_class_and_flow_label |= 0xF0000000;
5443
5444   if (traffic_class)
5445     ip_version_traffic_class_and_flow_label |= 0x0FF00000;
5446
5447   if (flow_label)
5448     ip_version_traffic_class_and_flow_label |= 0x000FFFFF;
5449
5450   ip->ip_version_traffic_class_and_flow_label =
5451     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
5452
5453   *maskp = mask;
5454   return 1;
5455 }
5456
5457 uword
5458 unformat_l3_mask (unformat_input_t * input, va_list * args)
5459 {
5460   u8 **maskp = va_arg (*args, u8 **);
5461
5462   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5463     {
5464       if (unformat (input, "ip4 %U", unformat_ip4_mask, maskp))
5465         return 1;
5466       else if (unformat (input, "ip6 %U", unformat_ip6_mask, maskp))
5467         return 1;
5468       else
5469         break;
5470     }
5471   return 0;
5472 }
5473
5474 uword
5475 unformat_l2_mask (unformat_input_t * input, va_list * args)
5476 {
5477   u8 **maskp = va_arg (*args, u8 **);
5478   u8 *mask = 0;
5479   u8 src = 0;
5480   u8 dst = 0;
5481   u8 proto = 0;
5482   u8 tag1 = 0;
5483   u8 tag2 = 0;
5484   u8 ignore_tag1 = 0;
5485   u8 ignore_tag2 = 0;
5486   u8 cos1 = 0;
5487   u8 cos2 = 0;
5488   u8 dot1q = 0;
5489   u8 dot1ad = 0;
5490   int len = 14;
5491
5492   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5493     {
5494       if (unformat (input, "src"))
5495         src = 1;
5496       else if (unformat (input, "dst"))
5497         dst = 1;
5498       else if (unformat (input, "proto"))
5499         proto = 1;
5500       else if (unformat (input, "tag1"))
5501         tag1 = 1;
5502       else if (unformat (input, "tag2"))
5503         tag2 = 1;
5504       else if (unformat (input, "ignore-tag1"))
5505         ignore_tag1 = 1;
5506       else if (unformat (input, "ignore-tag2"))
5507         ignore_tag2 = 1;
5508       else if (unformat (input, "cos1"))
5509         cos1 = 1;
5510       else if (unformat (input, "cos2"))
5511         cos2 = 1;
5512       else if (unformat (input, "dot1q"))
5513         dot1q = 1;
5514       else if (unformat (input, "dot1ad"))
5515         dot1ad = 1;
5516       else
5517         break;
5518     }
5519   if ((src + dst + proto + tag1 + tag2 + dot1q + dot1ad +
5520        ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
5521     return 0;
5522
5523   if (tag1 || ignore_tag1 || cos1 || dot1q)
5524     len = 18;
5525   if (tag2 || ignore_tag2 || cos2 || dot1ad)
5526     len = 22;
5527
5528   vec_validate (mask, len - 1);
5529
5530   if (dst)
5531     clib_memset (mask, 0xff, 6);
5532
5533   if (src)
5534     clib_memset (mask + 6, 0xff, 6);
5535
5536   if (tag2 || dot1ad)
5537     {
5538       /* inner vlan tag */
5539       if (tag2)
5540         {
5541           mask[19] = 0xff;
5542           mask[18] = 0x0f;
5543         }
5544       if (cos2)
5545         mask[18] |= 0xe0;
5546       if (proto)
5547         mask[21] = mask[20] = 0xff;
5548       if (tag1)
5549         {
5550           mask[15] = 0xff;
5551           mask[14] = 0x0f;
5552         }
5553       if (cos1)
5554         mask[14] |= 0xe0;
5555       *maskp = mask;
5556       return 1;
5557     }
5558   if (tag1 | dot1q)
5559     {
5560       if (tag1)
5561         {
5562           mask[15] = 0xff;
5563           mask[14] = 0x0f;
5564         }
5565       if (cos1)
5566         mask[14] |= 0xe0;
5567       if (proto)
5568         mask[16] = mask[17] = 0xff;
5569
5570       *maskp = mask;
5571       return 1;
5572     }
5573   if (cos2)
5574     mask[18] |= 0xe0;
5575   if (cos1)
5576     mask[14] |= 0xe0;
5577   if (proto)
5578     mask[12] = mask[13] = 0xff;
5579
5580   *maskp = mask;
5581   return 1;
5582 }
5583
5584 uword
5585 unformat_classify_mask (unformat_input_t * input, va_list * args)
5586 {
5587   u8 **maskp = va_arg (*args, u8 **);
5588   u32 *skipp = va_arg (*args, u32 *);
5589   u32 *matchp = va_arg (*args, u32 *);
5590   u32 match;
5591   u8 *mask = 0;
5592   u8 *l2 = 0;
5593   u8 *l3 = 0;
5594   u8 *l4 = 0;
5595   int i;
5596
5597   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5598     {
5599       if (unformat (input, "hex %U", unformat_hex_string, &mask))
5600         ;
5601       else if (unformat (input, "l2 %U", unformat_l2_mask, &l2))
5602         ;
5603       else if (unformat (input, "l3 %U", unformat_l3_mask, &l3))
5604         ;
5605       else if (unformat (input, "l4 %U", unformat_l4_mask, &l4))
5606         ;
5607       else
5608         break;
5609     }
5610
5611   if (l4 && !l3)
5612     {
5613       vec_free (mask);
5614       vec_free (l2);
5615       vec_free (l4);
5616       return 0;
5617     }
5618
5619   if (mask || l2 || l3 || l4)
5620     {
5621       if (l2 || l3 || l4)
5622         {
5623           /* "With a free Ethernet header in every package" */
5624           if (l2 == 0)
5625             vec_validate (l2, 13);
5626           mask = l2;
5627           if (vec_len (l3))
5628             {
5629               vec_append (mask, l3);
5630               vec_free (l3);
5631             }
5632           if (vec_len (l4))
5633             {
5634               vec_append (mask, l4);
5635               vec_free (l4);
5636             }
5637         }
5638
5639       /* Scan forward looking for the first significant mask octet */
5640       for (i = 0; i < vec_len (mask); i++)
5641         if (mask[i])
5642           break;
5643
5644       /* compute (skip, match) params */
5645       *skipp = i / sizeof (u32x4);
5646       vec_delete (mask, *skipp * sizeof (u32x4), 0);
5647
5648       /* Pad mask to an even multiple of the vector size */
5649       while (vec_len (mask) % sizeof (u32x4))
5650         vec_add1 (mask, 0);
5651
5652       match = vec_len (mask) / sizeof (u32x4);
5653
5654       for (i = match * sizeof (u32x4); i > 0; i -= sizeof (u32x4))
5655         {
5656           u64 *tmp = (u64 *) (mask + (i - sizeof (u32x4)));
5657           if (*tmp || *(tmp + 1))
5658             break;
5659           match--;
5660         }
5661       if (match == 0)
5662         clib_warning ("BUG: match 0");
5663
5664       _vec_len (mask) = match * sizeof (u32x4);
5665
5666       *matchp = match;
5667       *maskp = mask;
5668
5669       return 1;
5670     }
5671
5672   return 0;
5673 }
5674 #endif /* VPP_API_TEST_BUILTIN */
5675
5676 #define foreach_l2_next                         \
5677 _(drop, DROP)                                   \
5678 _(ethernet, ETHERNET_INPUT)                     \
5679 _(ip4, IP4_INPUT)                               \
5680 _(ip6, IP6_INPUT)
5681
5682 uword
5683 unformat_l2_next_index (unformat_input_t * input, va_list * args)
5684 {
5685   u32 *miss_next_indexp = va_arg (*args, u32 *);
5686   u32 next_index = 0;
5687   u32 tmp;
5688
5689 #define _(n,N) \
5690   if (unformat (input, #n)) { next_index = L2_INPUT_CLASSIFY_NEXT_##N; goto out;}
5691   foreach_l2_next;
5692 #undef _
5693
5694   if (unformat (input, "%d", &tmp))
5695     {
5696       next_index = tmp;
5697       goto out;
5698     }
5699
5700   return 0;
5701
5702 out:
5703   *miss_next_indexp = next_index;
5704   return 1;
5705 }
5706
5707 #define foreach_ip_next                         \
5708 _(drop, DROP)                                   \
5709 _(local, LOCAL)                                 \
5710 _(rewrite, REWRITE)
5711
5712 uword
5713 api_unformat_ip_next_index (unformat_input_t * input, va_list * args)
5714 {
5715   u32 *miss_next_indexp = va_arg (*args, u32 *);
5716   u32 next_index = 0;
5717   u32 tmp;
5718
5719 #define _(n,N) \
5720   if (unformat (input, #n)) { next_index = IP_LOOKUP_NEXT_##N; goto out;}
5721   foreach_ip_next;
5722 #undef _
5723
5724   if (unformat (input, "%d", &tmp))
5725     {
5726       next_index = tmp;
5727       goto out;
5728     }
5729
5730   return 0;
5731
5732 out:
5733   *miss_next_indexp = next_index;
5734   return 1;
5735 }
5736
5737 #define foreach_acl_next                        \
5738 _(deny, DENY)
5739
5740 uword
5741 api_unformat_acl_next_index (unformat_input_t * input, va_list * args)
5742 {
5743   u32 *miss_next_indexp = va_arg (*args, u32 *);
5744   u32 next_index = 0;
5745   u32 tmp;
5746
5747 #define _(n,N) \
5748   if (unformat (input, #n)) { next_index = ACL_NEXT_INDEX_##N; goto out;}
5749   foreach_acl_next;
5750 #undef _
5751
5752   if (unformat (input, "permit"))
5753     {
5754       next_index = ~0;
5755       goto out;
5756     }
5757   else if (unformat (input, "%d", &tmp))
5758     {
5759       next_index = tmp;
5760       goto out;
5761     }
5762
5763   return 0;
5764
5765 out:
5766   *miss_next_indexp = next_index;
5767   return 1;
5768 }
5769
5770 uword
5771 unformat_policer_precolor (unformat_input_t * input, va_list * args)
5772 {
5773   u32 *r = va_arg (*args, u32 *);
5774
5775   if (unformat (input, "conform-color"))
5776     *r = POLICE_CONFORM;
5777   else if (unformat (input, "exceed-color"))
5778     *r = POLICE_EXCEED;
5779   else
5780     return 0;
5781
5782   return 1;
5783 }
5784
5785 #if VPP_API_TEST_BUILTIN == 0
5786 uword
5787 unformat_l4_match (unformat_input_t * input, va_list * args)
5788 {
5789   u8 **matchp = va_arg (*args, u8 **);
5790
5791   u8 *proto_header = 0;
5792   int src_port = 0;
5793   int dst_port = 0;
5794
5795   tcpudp_header_t h;
5796
5797   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5798     {
5799       if (unformat (input, "src_port %d", &src_port))
5800         ;
5801       else if (unformat (input, "dst_port %d", &dst_port))
5802         ;
5803       else
5804         return 0;
5805     }
5806
5807   h.src_port = clib_host_to_net_u16 (src_port);
5808   h.dst_port = clib_host_to_net_u16 (dst_port);
5809   vec_validate (proto_header, sizeof (h) - 1);
5810   memcpy (proto_header, &h, sizeof (h));
5811
5812   *matchp = proto_header;
5813
5814   return 1;
5815 }
5816
5817 uword
5818 unformat_ip4_match (unformat_input_t * input, va_list * args)
5819 {
5820   u8 **matchp = va_arg (*args, u8 **);
5821   u8 *match = 0;
5822   ip4_header_t *ip;
5823   int version = 0;
5824   u32 version_val;
5825   int hdr_length = 0;
5826   u32 hdr_length_val;
5827   int src = 0, dst = 0;
5828   ip4_address_t src_val, dst_val;
5829   int proto = 0;
5830   u32 proto_val;
5831   int tos = 0;
5832   u32 tos_val;
5833   int length = 0;
5834   u32 length_val;
5835   int fragment_id = 0;
5836   u32 fragment_id_val;
5837   int ttl = 0;
5838   int ttl_val;
5839   int checksum = 0;
5840   u32 checksum_val;
5841
5842   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5843     {
5844       if (unformat (input, "version %d", &version_val))
5845         version = 1;
5846       else if (unformat (input, "hdr_length %d", &hdr_length_val))
5847         hdr_length = 1;
5848       else if (unformat (input, "src %U", unformat_ip4_address, &src_val))
5849         src = 1;
5850       else if (unformat (input, "dst %U", unformat_ip4_address, &dst_val))
5851         dst = 1;
5852       else if (unformat (input, "proto %d", &proto_val))
5853         proto = 1;
5854       else if (unformat (input, "tos %d", &tos_val))
5855         tos = 1;
5856       else if (unformat (input, "length %d", &length_val))
5857         length = 1;
5858       else if (unformat (input, "fragment_id %d", &fragment_id_val))
5859         fragment_id = 1;
5860       else if (unformat (input, "ttl %d", &ttl_val))
5861         ttl = 1;
5862       else if (unformat (input, "checksum %d", &checksum_val))
5863         checksum = 1;
5864       else
5865         break;
5866     }
5867
5868   if (version + hdr_length + src + dst + proto + tos + length + fragment_id
5869       + ttl + checksum == 0)
5870     return 0;
5871
5872   /*
5873    * Aligned because we use the real comparison functions
5874    */
5875   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
5876
5877   ip = (ip4_header_t *) match;
5878
5879   /* These are realistically matched in practice */
5880   if (src)
5881     ip->src_address.as_u32 = src_val.as_u32;
5882
5883   if (dst)
5884     ip->dst_address.as_u32 = dst_val.as_u32;
5885
5886   if (proto)
5887     ip->protocol = proto_val;
5888
5889
5890   /* These are not, but they're included for completeness */
5891   if (version)
5892     ip->ip_version_and_header_length |= (version_val & 0xF) << 4;
5893
5894   if (hdr_length)
5895     ip->ip_version_and_header_length |= (hdr_length_val & 0xF);
5896
5897   if (tos)
5898     ip->tos = tos_val;
5899
5900   if (length)
5901     ip->length = clib_host_to_net_u16 (length_val);
5902
5903   if (ttl)
5904     ip->ttl = ttl_val;
5905
5906   if (checksum)
5907     ip->checksum = clib_host_to_net_u16 (checksum_val);
5908
5909   *matchp = match;
5910   return 1;
5911 }
5912
5913 uword
5914 unformat_ip6_match (unformat_input_t * input, va_list * args)
5915 {
5916   u8 **matchp = va_arg (*args, u8 **);
5917   u8 *match = 0;
5918   ip6_header_t *ip;
5919   int version = 0;
5920   u32 version_val;
5921   u8 traffic_class = 0;
5922   u32 traffic_class_val = 0;
5923   u8 flow_label = 0;
5924   u8 flow_label_val;
5925   int src = 0, dst = 0;
5926   ip6_address_t src_val, dst_val;
5927   int proto = 0;
5928   u32 proto_val;
5929   int payload_length = 0;
5930   u32 payload_length_val;
5931   int hop_limit = 0;
5932   int hop_limit_val;
5933   u32 ip_version_traffic_class_and_flow_label;
5934
5935   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5936     {
5937       if (unformat (input, "version %d", &version_val))
5938         version = 1;
5939       else if (unformat (input, "traffic_class %d", &traffic_class_val))
5940         traffic_class = 1;
5941       else if (unformat (input, "flow_label %d", &flow_label_val))
5942         flow_label = 1;
5943       else if (unformat (input, "src %U", unformat_ip6_address, &src_val))
5944         src = 1;
5945       else if (unformat (input, "dst %U", unformat_ip6_address, &dst_val))
5946         dst = 1;
5947       else if (unformat (input, "proto %d", &proto_val))
5948         proto = 1;
5949       else if (unformat (input, "payload_length %d", &payload_length_val))
5950         payload_length = 1;
5951       else if (unformat (input, "hop_limit %d", &hop_limit_val))
5952         hop_limit = 1;
5953       else
5954         break;
5955     }
5956
5957   if (version + traffic_class + flow_label + src + dst + proto +
5958       payload_length + hop_limit == 0)
5959     return 0;
5960
5961   /*
5962    * Aligned because we use the real comparison functions
5963    */
5964   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
5965
5966   ip = (ip6_header_t *) match;
5967
5968   if (src)
5969     clib_memcpy (&ip->src_address, &src_val, sizeof (ip->src_address));
5970
5971   if (dst)
5972     clib_memcpy (&ip->dst_address, &dst_val, sizeof (ip->dst_address));
5973
5974   if (proto)
5975     ip->protocol = proto_val;
5976
5977   ip_version_traffic_class_and_flow_label = 0;
5978
5979   if (version)
5980     ip_version_traffic_class_and_flow_label |= (version_val & 0xF) << 28;
5981
5982   if (traffic_class)
5983     ip_version_traffic_class_and_flow_label |=
5984       (traffic_class_val & 0xFF) << 20;
5985
5986   if (flow_label)
5987     ip_version_traffic_class_and_flow_label |= (flow_label_val & 0xFFFFF);
5988
5989   ip->ip_version_traffic_class_and_flow_label =
5990     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
5991
5992   if (payload_length)
5993     ip->payload_length = clib_host_to_net_u16 (payload_length_val);
5994
5995   if (hop_limit)
5996     ip->hop_limit = hop_limit_val;
5997
5998   *matchp = match;
5999   return 1;
6000 }
6001
6002 uword
6003 unformat_l3_match (unformat_input_t * input, va_list * args)
6004 {
6005   u8 **matchp = va_arg (*args, u8 **);
6006
6007   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6008     {
6009       if (unformat (input, "ip4 %U", unformat_ip4_match, matchp))
6010         return 1;
6011       else if (unformat (input, "ip6 %U", unformat_ip6_match, matchp))
6012         return 1;
6013       else
6014         break;
6015     }
6016   return 0;
6017 }
6018
6019 uword
6020 unformat_vlan_tag (unformat_input_t * input, va_list * args)
6021 {
6022   u8 *tagp = va_arg (*args, u8 *);
6023   u32 tag;
6024
6025   if (unformat (input, "%d", &tag))
6026     {
6027       tagp[0] = (tag >> 8) & 0x0F;
6028       tagp[1] = tag & 0xFF;
6029       return 1;
6030     }
6031
6032   return 0;
6033 }
6034
6035 uword
6036 unformat_l2_match (unformat_input_t * input, va_list * args)
6037 {
6038   u8 **matchp = va_arg (*args, u8 **);
6039   u8 *match = 0;
6040   u8 src = 0;
6041   u8 src_val[6];
6042   u8 dst = 0;
6043   u8 dst_val[6];
6044   u8 proto = 0;
6045   u16 proto_val;
6046   u8 tag1 = 0;
6047   u8 tag1_val[2];
6048   u8 tag2 = 0;
6049   u8 tag2_val[2];
6050   int len = 14;
6051   u8 ignore_tag1 = 0;
6052   u8 ignore_tag2 = 0;
6053   u8 cos1 = 0;
6054   u8 cos2 = 0;
6055   u32 cos1_val = 0;
6056   u32 cos2_val = 0;
6057
6058   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6059     {
6060       if (unformat (input, "src %U", unformat_ethernet_address, &src_val))
6061         src = 1;
6062       else
6063         if (unformat (input, "dst %U", unformat_ethernet_address, &dst_val))
6064         dst = 1;
6065       else if (unformat (input, "proto %U",
6066                          unformat_ethernet_type_host_byte_order, &proto_val))
6067         proto = 1;
6068       else if (unformat (input, "tag1 %U", unformat_vlan_tag, tag1_val))
6069         tag1 = 1;
6070       else if (unformat (input, "tag2 %U", unformat_vlan_tag, tag2_val))
6071         tag2 = 1;
6072       else if (unformat (input, "ignore-tag1"))
6073         ignore_tag1 = 1;
6074       else if (unformat (input, "ignore-tag2"))
6075         ignore_tag2 = 1;
6076       else if (unformat (input, "cos1 %d", &cos1_val))
6077         cos1 = 1;
6078       else if (unformat (input, "cos2 %d", &cos2_val))
6079         cos2 = 1;
6080       else
6081         break;
6082     }
6083   if ((src + dst + proto + tag1 + tag2 +
6084        ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
6085     return 0;
6086
6087   if (tag1 || ignore_tag1 || cos1)
6088     len = 18;
6089   if (tag2 || ignore_tag2 || cos2)
6090     len = 22;
6091
6092   vec_validate_aligned (match, len - 1, sizeof (u32x4));
6093
6094   if (dst)
6095     clib_memcpy (match, dst_val, 6);
6096
6097   if (src)
6098     clib_memcpy (match + 6, src_val, 6);
6099
6100   if (tag2)
6101     {
6102       /* inner vlan tag */
6103       match[19] = tag2_val[1];
6104       match[18] = tag2_val[0];
6105       if (cos2)
6106         match[18] |= (cos2_val & 0x7) << 5;
6107       if (proto)
6108         {
6109           match[21] = proto_val & 0xff;
6110           match[20] = proto_val >> 8;
6111         }
6112       if (tag1)
6113         {
6114           match[15] = tag1_val[1];
6115           match[14] = tag1_val[0];
6116         }
6117       if (cos1)
6118         match[14] |= (cos1_val & 0x7) << 5;
6119       *matchp = match;
6120       return 1;
6121     }
6122   if (tag1)
6123     {
6124       match[15] = tag1_val[1];
6125       match[14] = tag1_val[0];
6126       if (proto)
6127         {
6128           match[17] = proto_val & 0xff;
6129           match[16] = proto_val >> 8;
6130         }
6131       if (cos1)
6132         match[14] |= (cos1_val & 0x7) << 5;
6133
6134       *matchp = match;
6135       return 1;
6136     }
6137   if (cos2)
6138     match[18] |= (cos2_val & 0x7) << 5;
6139   if (cos1)
6140     match[14] |= (cos1_val & 0x7) << 5;
6141   if (proto)
6142     {
6143       match[13] = proto_val & 0xff;
6144       match[12] = proto_val >> 8;
6145     }
6146
6147   *matchp = match;
6148   return 1;
6149 }
6150
6151 uword
6152 unformat_qos_source (unformat_input_t * input, va_list * args)
6153 {
6154   int *qs = va_arg (*args, int *);
6155
6156   if (unformat (input, "ip"))
6157     *qs = QOS_SOURCE_IP;
6158   else if (unformat (input, "mpls"))
6159     *qs = QOS_SOURCE_MPLS;
6160   else if (unformat (input, "ext"))
6161     *qs = QOS_SOURCE_EXT;
6162   else if (unformat (input, "vlan"))
6163     *qs = QOS_SOURCE_VLAN;
6164   else
6165     return 0;
6166
6167   return 1;
6168 }
6169 #endif
6170
6171 uword
6172 api_unformat_classify_match (unformat_input_t * input, va_list * args)
6173 {
6174   u8 **matchp = va_arg (*args, u8 **);
6175   u32 skip_n_vectors = va_arg (*args, u32);
6176   u32 match_n_vectors = va_arg (*args, u32);
6177
6178   u8 *match = 0;
6179   u8 *l2 = 0;
6180   u8 *l3 = 0;
6181   u8 *l4 = 0;
6182
6183   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6184     {
6185       if (unformat (input, "hex %U", unformat_hex_string, &match))
6186         ;
6187       else if (unformat (input, "l2 %U", unformat_l2_match, &l2))
6188         ;
6189       else if (unformat (input, "l3 %U", unformat_l3_match, &l3))
6190         ;
6191       else if (unformat (input, "l4 %U", unformat_l4_match, &l4))
6192         ;
6193       else
6194         break;
6195     }
6196
6197   if (l4 && !l3)
6198     {
6199       vec_free (match);
6200       vec_free (l2);
6201       vec_free (l4);
6202       return 0;
6203     }
6204
6205   if (match || l2 || l3 || l4)
6206     {
6207       if (l2 || l3 || l4)
6208         {
6209           /* "Win a free Ethernet header in every packet" */
6210           if (l2 == 0)
6211             vec_validate_aligned (l2, 13, sizeof (u32x4));
6212           match = l2;
6213           if (vec_len (l3))
6214             {
6215               vec_append_aligned (match, l3, sizeof (u32x4));
6216               vec_free (l3);
6217             }
6218           if (vec_len (l4))
6219             {
6220               vec_append_aligned (match, l4, sizeof (u32x4));
6221               vec_free (l4);
6222             }
6223         }
6224
6225       /* Make sure the vector is big enough even if key is all 0's */
6226       vec_validate_aligned
6227         (match, ((match_n_vectors + skip_n_vectors) * sizeof (u32x4)) - 1,
6228          sizeof (u32x4));
6229
6230       /* Set size, include skipped vectors */
6231       _vec_len (match) = (match_n_vectors + skip_n_vectors) * sizeof (u32x4);
6232
6233       *matchp = match;
6234
6235       return 1;
6236     }
6237
6238   return 0;
6239 }
6240
6241 static int
6242 api_get_node_index (vat_main_t * vam)
6243 {
6244   unformat_input_t *i = vam->input;
6245   vl_api_get_node_index_t *mp;
6246   u8 *name = 0;
6247   int ret;
6248
6249   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6250     {
6251       if (unformat (i, "node %s", &name))
6252         ;
6253       else
6254         break;
6255     }
6256   if (name == 0)
6257     {
6258       errmsg ("node name required");
6259       return -99;
6260     }
6261   if (vec_len (name) >= ARRAY_LEN (mp->node_name))
6262     {
6263       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
6264       return -99;
6265     }
6266
6267   M (GET_NODE_INDEX, mp);
6268   clib_memcpy (mp->node_name, name, vec_len (name));
6269   vec_free (name);
6270
6271   S (mp);
6272   W (ret);
6273   return ret;
6274 }
6275
6276 static int
6277 api_get_next_index (vat_main_t * vam)
6278 {
6279   unformat_input_t *i = vam->input;
6280   vl_api_get_next_index_t *mp;
6281   u8 *node_name = 0, *next_node_name = 0;
6282   int ret;
6283
6284   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6285     {
6286       if (unformat (i, "node-name %s", &node_name))
6287         ;
6288       else if (unformat (i, "next-node-name %s", &next_node_name))
6289         break;
6290     }
6291
6292   if (node_name == 0)
6293     {
6294       errmsg ("node name required");
6295       return -99;
6296     }
6297   if (vec_len (node_name) >= ARRAY_LEN (mp->node_name))
6298     {
6299       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
6300       return -99;
6301     }
6302
6303   if (next_node_name == 0)
6304     {
6305       errmsg ("next node name required");
6306       return -99;
6307     }
6308   if (vec_len (next_node_name) >= ARRAY_LEN (mp->next_name))
6309     {
6310       errmsg ("next node name too long, max %d", ARRAY_LEN (mp->next_name));
6311       return -99;
6312     }
6313
6314   M (GET_NEXT_INDEX, mp);
6315   clib_memcpy (mp->node_name, node_name, vec_len (node_name));
6316   clib_memcpy (mp->next_name, next_node_name, vec_len (next_node_name));
6317   vec_free (node_name);
6318   vec_free (next_node_name);
6319
6320   S (mp);
6321   W (ret);
6322   return ret;
6323 }
6324
6325 static int
6326 api_add_node_next (vat_main_t * vam)
6327 {
6328   unformat_input_t *i = vam->input;
6329   vl_api_add_node_next_t *mp;
6330   u8 *name = 0;
6331   u8 *next = 0;
6332   int ret;
6333
6334   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6335     {
6336       if (unformat (i, "node %s", &name))
6337         ;
6338       else if (unformat (i, "next %s", &next))
6339         ;
6340       else
6341         break;
6342     }
6343   if (name == 0)
6344     {
6345       errmsg ("node name required");
6346       return -99;
6347     }
6348   if (vec_len (name) >= ARRAY_LEN (mp->node_name))
6349     {
6350       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
6351       return -99;
6352     }
6353   if (next == 0)
6354     {
6355       errmsg ("next node required");
6356       return -99;
6357     }
6358   if (vec_len (next) >= ARRAY_LEN (mp->next_name))
6359     {
6360       errmsg ("next name too long, max %d", ARRAY_LEN (mp->next_name));
6361       return -99;
6362     }
6363
6364   M (ADD_NODE_NEXT, mp);
6365   clib_memcpy (mp->node_name, name, vec_len (name));
6366   clib_memcpy (mp->next_name, next, vec_len (next));
6367   vec_free (name);
6368   vec_free (next);
6369
6370   S (mp);
6371   W (ret);
6372   return ret;
6373 }
6374
6375 static void vl_api_sw_interface_virtio_pci_details_t_handler
6376   (vl_api_sw_interface_virtio_pci_details_t * mp)
6377 {
6378   vat_main_t *vam = &vat_main;
6379
6380   typedef union
6381   {
6382     struct
6383     {
6384       u16 domain;
6385       u8 bus;
6386       u8 slot:5;
6387       u8 function:3;
6388     };
6389     u32 as_u32;
6390   } pci_addr_t;
6391   pci_addr_t addr;
6392
6393   addr.domain = ntohs (mp->pci_addr.domain);
6394   addr.bus = mp->pci_addr.bus;
6395   addr.slot = mp->pci_addr.slot;
6396   addr.function = mp->pci_addr.function;
6397
6398   u8 *pci_addr = format (0, "%04x:%02x:%02x.%x", addr.domain, addr.bus,
6399                          addr.slot, addr.function);
6400
6401   print (vam->ofp,
6402          "\n%-12s %-12d %-12d %-12d %-17U 0x%-08llx",
6403          pci_addr, ntohl (mp->sw_if_index),
6404          ntohs (mp->rx_ring_sz), ntohs (mp->tx_ring_sz),
6405          format_ethernet_address, mp->mac_addr,
6406          clib_net_to_host_u64 (mp->features));
6407   vec_free (pci_addr);
6408 }
6409
6410 static void vl_api_sw_interface_virtio_pci_details_t_handler_json
6411   (vl_api_sw_interface_virtio_pci_details_t * mp)
6412 {
6413   vat_main_t *vam = &vat_main;
6414   vat_json_node_t *node = NULL;
6415   vlib_pci_addr_t pci_addr;
6416
6417   if (VAT_JSON_ARRAY != vam->json_tree.type)
6418     {
6419       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
6420       vat_json_init_array (&vam->json_tree);
6421     }
6422   node = vat_json_array_add (&vam->json_tree);
6423
6424   pci_addr.domain = ntohs (mp->pci_addr.domain);
6425   pci_addr.bus = mp->pci_addr.bus;
6426   pci_addr.slot = mp->pci_addr.slot;
6427   pci_addr.function = mp->pci_addr.function;
6428
6429   vat_json_init_object (node);
6430   vat_json_object_add_uint (node, "pci-addr", pci_addr.as_u32);
6431   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
6432   vat_json_object_add_uint (node, "rx_ring_sz", ntohs (mp->rx_ring_sz));
6433   vat_json_object_add_uint (node, "tx_ring_sz", ntohs (mp->tx_ring_sz));
6434   vat_json_object_add_uint (node, "features",
6435                             clib_net_to_host_u64 (mp->features));
6436   vat_json_object_add_string_copy (node, "mac_addr",
6437                                    format (0, "%U", format_ethernet_address,
6438                                            &mp->mac_addr));
6439 }
6440
6441 static int
6442 api_sw_interface_virtio_pci_dump (vat_main_t * vam)
6443 {
6444   vl_api_sw_interface_virtio_pci_dump_t *mp;
6445   vl_api_control_ping_t *mp_ping;
6446   int ret;
6447
6448   print (vam->ofp,
6449          "\n%-12s %-12s %-12s %-12s %-17s %-08s",
6450          "pci_addr", "sw_if_index", "rx_ring_sz", "tx_ring_sz",
6451          "mac_addr", "features");
6452
6453   /* Get list of tap interfaces */
6454   M (SW_INTERFACE_VIRTIO_PCI_DUMP, mp);
6455   S (mp);
6456
6457   /* Use a control ping for synchronization */
6458   MPING (CONTROL_PING, mp_ping);
6459   S (mp_ping);
6460
6461   W (ret);
6462   return ret;
6463 }
6464
6465 static int
6466 api_l2_fib_clear_table (vat_main_t * vam)
6467 {
6468 //  unformat_input_t * i = vam->input;
6469   vl_api_l2_fib_clear_table_t *mp;
6470   int ret;
6471
6472   M (L2_FIB_CLEAR_TABLE, mp);
6473
6474   S (mp);
6475   W (ret);
6476   return ret;
6477 }
6478
6479 static int
6480 api_l2_interface_efp_filter (vat_main_t * vam)
6481 {
6482   unformat_input_t *i = vam->input;
6483   vl_api_l2_interface_efp_filter_t *mp;
6484   u32 sw_if_index;
6485   u8 enable = 1;
6486   u8 sw_if_index_set = 0;
6487   int ret;
6488
6489   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6490     {
6491       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
6492         sw_if_index_set = 1;
6493       else if (unformat (i, "sw_if_index %d", &sw_if_index))
6494         sw_if_index_set = 1;
6495       else if (unformat (i, "enable"))
6496         enable = 1;
6497       else if (unformat (i, "disable"))
6498         enable = 0;
6499       else
6500         {
6501           clib_warning ("parse error '%U'", format_unformat_error, i);
6502           return -99;
6503         }
6504     }
6505
6506   if (sw_if_index_set == 0)
6507     {
6508       errmsg ("missing sw_if_index");
6509       return -99;
6510     }
6511
6512   M (L2_INTERFACE_EFP_FILTER, mp);
6513
6514   mp->sw_if_index = ntohl (sw_if_index);
6515   mp->enable_disable = enable;
6516
6517   S (mp);
6518   W (ret);
6519   return ret;
6520 }
6521
6522 #define foreach_vtr_op                          \
6523 _("disable",  L2_VTR_DISABLED)                  \
6524 _("push-1",  L2_VTR_PUSH_1)                     \
6525 _("push-2",  L2_VTR_PUSH_2)                     \
6526 _("pop-1",  L2_VTR_POP_1)                       \
6527 _("pop-2",  L2_VTR_POP_2)                       \
6528 _("translate-1-1",  L2_VTR_TRANSLATE_1_1)       \
6529 _("translate-1-2",  L2_VTR_TRANSLATE_1_2)       \
6530 _("translate-2-1",  L2_VTR_TRANSLATE_2_1)       \
6531 _("translate-2-2",  L2_VTR_TRANSLATE_2_2)
6532
6533 static int
6534 api_l2_interface_vlan_tag_rewrite (vat_main_t * vam)
6535 {
6536   unformat_input_t *i = vam->input;
6537   vl_api_l2_interface_vlan_tag_rewrite_t *mp;
6538   u32 sw_if_index;
6539   u8 sw_if_index_set = 0;
6540   u8 vtr_op_set = 0;
6541   u32 vtr_op = 0;
6542   u32 push_dot1q = 1;
6543   u32 tag1 = ~0;
6544   u32 tag2 = ~0;
6545   int ret;
6546
6547   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6548     {
6549       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
6550         sw_if_index_set = 1;
6551       else if (unformat (i, "sw_if_index %d", &sw_if_index))
6552         sw_if_index_set = 1;
6553       else if (unformat (i, "vtr_op %d", &vtr_op))
6554         vtr_op_set = 1;
6555 #define _(n,v) else if (unformat(i, n)) {vtr_op = v; vtr_op_set = 1;}
6556       foreach_vtr_op
6557 #undef _
6558         else if (unformat (i, "push_dot1q %d", &push_dot1q))
6559         ;
6560       else if (unformat (i, "tag1 %d", &tag1))
6561         ;
6562       else if (unformat (i, "tag2 %d", &tag2))
6563         ;
6564       else
6565         {
6566           clib_warning ("parse error '%U'", format_unformat_error, i);
6567           return -99;
6568         }
6569     }
6570
6571   if ((sw_if_index_set == 0) || (vtr_op_set == 0))
6572     {
6573       errmsg ("missing vtr operation or sw_if_index");
6574       return -99;
6575     }
6576
6577   M (L2_INTERFACE_VLAN_TAG_REWRITE, mp);
6578   mp->sw_if_index = ntohl (sw_if_index);
6579   mp->vtr_op = ntohl (vtr_op);
6580   mp->push_dot1q = ntohl (push_dot1q);
6581   mp->tag1 = ntohl (tag1);
6582   mp->tag2 = ntohl (tag2);
6583
6584   S (mp);
6585   W (ret);
6586   return ret;
6587 }
6588
6589 static int
6590 api_show_version (vat_main_t *vam)
6591 {
6592   vl_api_show_version_t *mp;
6593   int ret;
6594
6595   M (SHOW_VERSION, mp);
6596
6597   S (mp);
6598   W (ret);
6599   return ret;
6600 }
6601
6602 static void
6603 vl_api_l2_fib_table_details_t_handler (vl_api_l2_fib_table_details_t *mp)
6604 {
6605   vat_main_t *vam = &vat_main;
6606
6607   print (vam->ofp,
6608          "%3" PRIu32 "    %U    %3" PRIu32 "       %d       %d     %d",
6609          ntohl (mp->bd_id), format_ethernet_address, mp->mac,
6610          ntohl (mp->sw_if_index), mp->static_mac, mp->filter_mac, mp->bvi_mac);
6611 }
6612
6613 static void
6614 vl_api_l2_fib_table_details_t_handler_json (vl_api_l2_fib_table_details_t *mp)
6615 {
6616   vat_main_t *vam = &vat_main;
6617   vat_json_node_t *node = NULL;
6618
6619   if (VAT_JSON_ARRAY != vam->json_tree.type)
6620     {
6621       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
6622       vat_json_init_array (&vam->json_tree);
6623     }
6624   node = vat_json_array_add (&vam->json_tree);
6625
6626   vat_json_init_object (node);
6627   vat_json_object_add_uint (node, "bd_id", ntohl (mp->bd_id));
6628   vat_json_object_add_bytes (node, "mac", mp->mac, 6);
6629   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
6630   vat_json_object_add_uint (node, "static_mac", mp->static_mac);
6631   vat_json_object_add_uint (node, "filter_mac", mp->filter_mac);
6632   vat_json_object_add_uint (node, "bvi_mac", mp->bvi_mac);
6633 }
6634
6635 static int
6636 api_l2_fib_table_dump (vat_main_t *vam)
6637 {
6638   unformat_input_t *i = vam->input;
6639   vl_api_l2_fib_table_dump_t *mp;
6640   vl_api_control_ping_t *mp_ping;
6641   u32 bd_id;
6642   u8 bd_id_set = 0;
6643   int ret;
6644
6645   /* Parse args required to build the message */
6646   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6647     {
6648       if (unformat (i, "bd_id %d", &bd_id))
6649         bd_id_set = 1;
6650       else
6651         break;
6652     }
6653
6654   if (bd_id_set == 0)
6655     {
6656       errmsg ("missing bridge domain");
6657       return -99;
6658     }
6659
6660   print (vam->ofp, "BD-ID     Mac Address      sw-ndx  Static  Filter  BVI");
6661
6662   /* Get list of l2 fib entries */
6663   M (L2_FIB_TABLE_DUMP, mp);
6664
6665   mp->bd_id = ntohl (bd_id);
6666   S (mp);
6667
6668   /* Use a control ping for synchronization */
6669   MPING (CONTROL_PING, mp_ping);
6670   S (mp_ping);
6671
6672   W (ret);
6673   return ret;
6674 }
6675
6676 static int
6677 api_interface_name_renumber (vat_main_t *vam)
6678 {
6679   unformat_input_t *line_input = vam->input;
6680   vl_api_interface_name_renumber_t *mp;
6681   u32 sw_if_index = ~0;
6682   u32 new_show_dev_instance = ~0;
6683   int ret;
6684
6685   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
6686     {
6687       if (unformat (line_input, "%U", api_unformat_sw_if_index, vam,
6688                     &sw_if_index))
6689         ;
6690       else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
6691         ;
6692       else if (unformat (line_input, "new_show_dev_instance %d",
6693                          &new_show_dev_instance))
6694         ;
6695       else
6696         break;
6697     }
6698
6699   if (sw_if_index == ~0)
6700     {
6701       errmsg ("missing interface name or sw_if_index");
6702       return -99;
6703     }
6704
6705   if (new_show_dev_instance == ~0)
6706     {
6707       errmsg ("missing new_show_dev_instance");
6708       return -99;
6709     }
6710
6711   M (INTERFACE_NAME_RENUMBER, mp);
6712
6713   mp->sw_if_index = ntohl (sw_if_index);
6714   mp->new_show_dev_instance = ntohl (new_show_dev_instance);
6715
6716   S (mp);
6717   W (ret);
6718   return ret;
6719 }
6720
6721 static int
6722 api_want_l2_macs_events (vat_main_t *vam)
6723 {
6724   unformat_input_t *line_input = vam->input;
6725   vl_api_want_l2_macs_events_t *mp;
6726   u8 enable_disable = 1;
6727   u32 scan_delay = 0;
6728   u32 max_macs_in_event = 0;
6729   u32 learn_limit = 0;
6730   int ret;
6731
6732   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
6733     {
6734       if (unformat (line_input, "learn-limit %d", &learn_limit))
6735         ;
6736       else if (unformat (line_input, "scan-delay %d", &scan_delay))
6737         ;
6738       else if (unformat (line_input, "max-entries %d", &max_macs_in_event))
6739         ;
6740       else if (unformat (line_input, "disable"))
6741         enable_disable = 0;
6742       else
6743         break;
6744     }
6745
6746   M (WANT_L2_MACS_EVENTS, mp);
6747   mp->enable_disable = enable_disable;
6748   mp->pid = htonl (getpid ());
6749   mp->learn_limit = htonl (learn_limit);
6750   mp->scan_delay = (u8) scan_delay;
6751   mp->max_macs_in_event = (u8) (max_macs_in_event / 10);
6752   S (mp);
6753   W (ret);
6754   return ret;
6755 }
6756
6757 static int
6758 api_ip_address_dump (vat_main_t *vam)
6759 {
6760   unformat_input_t *i = vam->input;
6761   vl_api_ip_address_dump_t *mp;
6762   vl_api_control_ping_t *mp_ping;
6763   u32 sw_if_index = ~0;
6764   u8 sw_if_index_set = 0;
6765   u8 ipv4_set = 0;
6766   u8 ipv6_set = 0;
6767   int ret;
6768
6769   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6770     {
6771       if (unformat (i, "sw_if_index %d", &sw_if_index))
6772         sw_if_index_set = 1;
6773       else if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
6774         sw_if_index_set = 1;
6775       else if (unformat (i, "ipv4"))
6776         ipv4_set = 1;
6777       else if (unformat (i, "ipv6"))
6778         ipv6_set = 1;
6779       else
6780         break;
6781     }
6782
6783   if (ipv4_set && ipv6_set)
6784     {
6785       errmsg ("ipv4 and ipv6 flags cannot be both set");
6786       return -99;
6787     }
6788
6789   if ((!ipv4_set) && (!ipv6_set))
6790     {
6791       errmsg ("no ipv4 nor ipv6 flag set");
6792       return -99;
6793     }
6794
6795   if (sw_if_index_set == 0)
6796     {
6797       errmsg ("missing interface name or sw_if_index");
6798       return -99;
6799     }
6800
6801   vam->current_sw_if_index = sw_if_index;
6802   vam->is_ipv6 = ipv6_set;
6803
6804   M (IP_ADDRESS_DUMP, mp);
6805   mp->sw_if_index = ntohl (sw_if_index);
6806   mp->is_ipv6 = ipv6_set;
6807   S (mp);
6808
6809   /* Use a control ping for synchronization */
6810   MPING (CONTROL_PING, mp_ping);
6811   S (mp_ping);
6812
6813   W (ret);
6814   return ret;
6815 }
6816
6817 static int
6818 api_ip_dump (vat_main_t * vam)
6819 {
6820   vl_api_ip_dump_t *mp;
6821   vl_api_control_ping_t *mp_ping;
6822   unformat_input_t *in = vam->input;
6823   int ipv4_set = 0;
6824   int ipv6_set = 0;
6825   int is_ipv6;
6826   int i;
6827   int ret;
6828
6829   while (unformat_check_input (in) != UNFORMAT_END_OF_INPUT)
6830     {
6831       if (unformat (in, "ipv4"))
6832         ipv4_set = 1;
6833       else if (unformat (in, "ipv6"))
6834         ipv6_set = 1;
6835       else
6836         break;
6837     }
6838
6839   if (ipv4_set && ipv6_set)
6840     {
6841       errmsg ("ipv4 and ipv6 flags cannot be both set");
6842       return -99;
6843     }
6844
6845   if ((!ipv4_set) && (!ipv6_set))
6846     {
6847       errmsg ("no ipv4 nor ipv6 flag set");
6848       return -99;
6849     }
6850
6851   is_ipv6 = ipv6_set;
6852   vam->is_ipv6 = is_ipv6;
6853
6854   /* free old data */
6855   for (i = 0; i < vec_len (vam->ip_details_by_sw_if_index[is_ipv6]); i++)
6856     {
6857       vec_free (vam->ip_details_by_sw_if_index[is_ipv6][i].addr);
6858     }
6859   vec_free (vam->ip_details_by_sw_if_index[is_ipv6]);
6860
6861   M (IP_DUMP, mp);
6862   mp->is_ipv6 = ipv6_set;
6863   S (mp);
6864
6865   /* Use a control ping for synchronization */
6866   MPING (CONTROL_PING, mp_ping);
6867   S (mp_ping);
6868
6869   W (ret);
6870   return ret;
6871 }
6872
6873 static int
6874 api_get_first_msg_id (vat_main_t * vam)
6875 {
6876   vl_api_get_first_msg_id_t *mp;
6877   unformat_input_t *i = vam->input;
6878   u8 *name;
6879   u8 name_set = 0;
6880   int ret;
6881
6882   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6883     {
6884       if (unformat (i, "client %s", &name))
6885         name_set = 1;
6886       else
6887         break;
6888     }
6889
6890   if (name_set == 0)
6891     {
6892       errmsg ("missing client name");
6893       return -99;
6894     }
6895   vec_add1 (name, 0);
6896
6897   if (vec_len (name) > 63)
6898     {
6899       errmsg ("client name too long");
6900       return -99;
6901     }
6902
6903   M (GET_FIRST_MSG_ID, mp);
6904   clib_memcpy (mp->name, name, vec_len (name));
6905   S (mp);
6906   W (ret);
6907   return ret;
6908 }
6909
6910 static int
6911 api_get_node_graph (vat_main_t * vam)
6912 {
6913   vl_api_get_node_graph_t *mp;
6914   int ret;
6915
6916   M (GET_NODE_GRAPH, mp);
6917
6918   /* send it... */
6919   S (mp);
6920   /* Wait for the reply */
6921   W (ret);
6922   return ret;
6923 }
6924
6925 static u8 *
6926 format_fib_api_path_nh_proto (u8 * s, va_list * args)
6927 {
6928   vl_api_fib_path_nh_proto_t proto =
6929     va_arg (*args, vl_api_fib_path_nh_proto_t);
6930
6931   switch (proto)
6932     {
6933     case FIB_API_PATH_NH_PROTO_IP4:
6934       s = format (s, "ip4");
6935       break;
6936     case FIB_API_PATH_NH_PROTO_IP6:
6937       s = format (s, "ip6");
6938       break;
6939     case FIB_API_PATH_NH_PROTO_MPLS:
6940       s = format (s, "mpls");
6941       break;
6942     case FIB_API_PATH_NH_PROTO_BIER:
6943       s = format (s, "bier");
6944       break;
6945     case FIB_API_PATH_NH_PROTO_ETHERNET:
6946       s = format (s, "ethernet");
6947       break;
6948     }
6949
6950   return (s);
6951 }
6952
6953 static u8 *
6954 format_vl_api_ip_address_union (u8 * s, va_list * args)
6955 {
6956   vl_api_address_family_t af = va_arg (*args, int);
6957   const vl_api_address_union_t *u = va_arg (*args, vl_api_address_union_t *);
6958
6959   switch (af)
6960     {
6961     case ADDRESS_IP4:
6962       s = format (s, "%U", format_ip4_address, u->ip4);
6963       break;
6964     case ADDRESS_IP6:
6965       s = format (s, "%U", format_ip6_address, u->ip6);
6966       break;
6967     }
6968   return (s);
6969 }
6970
6971 static u8 *
6972 format_vl_api_fib_path_type (u8 * s, va_list * args)
6973 {
6974   vl_api_fib_path_type_t t = va_arg (*args, vl_api_fib_path_type_t);
6975
6976   switch (t)
6977     {
6978     case FIB_API_PATH_TYPE_NORMAL:
6979       s = format (s, "normal");
6980       break;
6981     case FIB_API_PATH_TYPE_LOCAL:
6982       s = format (s, "local");
6983       break;
6984     case FIB_API_PATH_TYPE_DROP:
6985       s = format (s, "drop");
6986       break;
6987     case FIB_API_PATH_TYPE_UDP_ENCAP:
6988       s = format (s, "udp-encap");
6989       break;
6990     case FIB_API_PATH_TYPE_BIER_IMP:
6991       s = format (s, "bier-imp");
6992       break;
6993     case FIB_API_PATH_TYPE_ICMP_UNREACH:
6994       s = format (s, "unreach");
6995       break;
6996     case FIB_API_PATH_TYPE_ICMP_PROHIBIT:
6997       s = format (s, "prohibit");
6998       break;
6999     case FIB_API_PATH_TYPE_SOURCE_LOOKUP:
7000       s = format (s, "src-lookup");
7001       break;
7002     case FIB_API_PATH_TYPE_DVR:
7003       s = format (s, "dvr");
7004       break;
7005     case FIB_API_PATH_TYPE_INTERFACE_RX:
7006       s = format (s, "interface-rx");
7007       break;
7008     case FIB_API_PATH_TYPE_CLASSIFY:
7009       s = format (s, "classify");
7010       break;
7011     }
7012
7013   return (s);
7014 }
7015
7016 static void
7017 vl_api_fib_path_print (vat_main_t * vam, vl_api_fib_path_t * fp)
7018 {
7019   print (vam->ofp,
7020          "  weight %d, sw_if_index %d, type %U, afi %U, next_hop %U",
7021          ntohl (fp->weight), ntohl (fp->sw_if_index),
7022          format_vl_api_fib_path_type, fp->type,
7023          format_fib_api_path_nh_proto, fp->proto,
7024          format_vl_api_ip_address_union, &fp->nh.address);
7025 }
7026
7027 static void
7028 vl_api_mpls_fib_path_json_print (vat_json_node_t * node,
7029                                  vl_api_fib_path_t * fp)
7030 {
7031   struct in_addr ip4;
7032   struct in6_addr ip6;
7033
7034   vat_json_object_add_uint (node, "weight", ntohl (fp->weight));
7035   vat_json_object_add_uint (node, "sw_if_index", ntohl (fp->sw_if_index));
7036   vat_json_object_add_uint (node, "type", fp->type);
7037   vat_json_object_add_uint (node, "next_hop_proto", fp->proto);
7038   if (fp->proto == FIB_API_PATH_NH_PROTO_IP4)
7039     {
7040       clib_memcpy (&ip4, &fp->nh.address.ip4, sizeof (ip4));
7041       vat_json_object_add_ip4 (node, "next_hop", ip4);
7042     }
7043   else if (fp->proto == FIB_API_PATH_NH_PROTO_IP6)
7044     {
7045       clib_memcpy (&ip6, &fp->nh.address.ip6, sizeof (ip6));
7046       vat_json_object_add_ip6 (node, "next_hop", ip6);
7047     }
7048 }
7049
7050 static void
7051 vl_api_mpls_tunnel_details_t_handler (vl_api_mpls_tunnel_details_t * mp)
7052 {
7053   vat_main_t *vam = &vat_main;
7054   int count = ntohl (mp->mt_tunnel.mt_n_paths);
7055   vl_api_fib_path_t *fp;
7056   i32 i;
7057
7058   print (vam->ofp, "sw_if_index %d via:",
7059          ntohl (mp->mt_tunnel.mt_sw_if_index));
7060   fp = mp->mt_tunnel.mt_paths;
7061   for (i = 0; i < count; i++)
7062     {
7063       vl_api_fib_path_print (vam, fp);
7064       fp++;
7065     }
7066
7067   print (vam->ofp, "");
7068 }
7069
7070 #define vl_api_mpls_tunnel_details_t_endian vl_noop_handler
7071 #define vl_api_mpls_tunnel_details_t_print vl_noop_handler
7072
7073 static void
7074 vl_api_mpls_tunnel_details_t_handler_json (vl_api_mpls_tunnel_details_t * mp)
7075 {
7076   vat_main_t *vam = &vat_main;
7077   vat_json_node_t *node = NULL;
7078   int count = ntohl (mp->mt_tunnel.mt_n_paths);
7079   vl_api_fib_path_t *fp;
7080   i32 i;
7081
7082   if (VAT_JSON_ARRAY != vam->json_tree.type)
7083     {
7084       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
7085       vat_json_init_array (&vam->json_tree);
7086     }
7087   node = vat_json_array_add (&vam->json_tree);
7088
7089   vat_json_init_object (node);
7090   vat_json_object_add_uint (node, "sw_if_index",
7091                             ntohl (mp->mt_tunnel.mt_sw_if_index));
7092
7093   vat_json_object_add_uint (node, "l2_only", mp->mt_tunnel.mt_l2_only);
7094
7095   fp = mp->mt_tunnel.mt_paths;
7096   for (i = 0; i < count; i++)
7097     {
7098       vl_api_mpls_fib_path_json_print (node, fp);
7099       fp++;
7100     }
7101 }
7102
7103 static int
7104 api_mpls_tunnel_dump (vat_main_t * vam)
7105 {
7106   vl_api_mpls_tunnel_dump_t *mp;
7107   vl_api_control_ping_t *mp_ping;
7108   int ret;
7109
7110   M (MPLS_TUNNEL_DUMP, mp);
7111
7112   S (mp);
7113
7114   /* Use a control ping for synchronization */
7115   MPING (CONTROL_PING, mp_ping);
7116   S (mp_ping);
7117
7118   W (ret);
7119   return ret;
7120 }
7121
7122 #define vl_api_mpls_table_details_t_endian vl_noop_handler
7123 #define vl_api_mpls_table_details_t_print vl_noop_handler
7124
7125
7126 static void
7127 vl_api_mpls_table_details_t_handler (vl_api_mpls_table_details_t * mp)
7128 {
7129   vat_main_t *vam = &vat_main;
7130
7131   print (vam->ofp, "table-id %d,", ntohl (mp->mt_table.mt_table_id));
7132 }
7133
7134 static void vl_api_mpls_table_details_t_handler_json
7135   (vl_api_mpls_table_details_t * mp)
7136 {
7137   vat_main_t *vam = &vat_main;
7138   vat_json_node_t *node = NULL;
7139
7140   if (VAT_JSON_ARRAY != vam->json_tree.type)
7141     {
7142       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
7143       vat_json_init_array (&vam->json_tree);
7144     }
7145   node = vat_json_array_add (&vam->json_tree);
7146
7147   vat_json_init_object (node);
7148   vat_json_object_add_uint (node, "table", ntohl (mp->mt_table.mt_table_id));
7149 }
7150
7151 static int
7152 api_mpls_table_dump (vat_main_t * vam)
7153 {
7154   vl_api_mpls_table_dump_t *mp;
7155   vl_api_control_ping_t *mp_ping;
7156   int ret;
7157
7158   M (MPLS_TABLE_DUMP, mp);
7159   S (mp);
7160
7161   /* Use a control ping for synchronization */
7162   MPING (CONTROL_PING, mp_ping);
7163   S (mp_ping);
7164
7165   W (ret);
7166   return ret;
7167 }
7168
7169 #define vl_api_mpls_route_details_t_endian vl_noop_handler
7170 #define vl_api_mpls_route_details_t_print vl_noop_handler
7171
7172 static void
7173 vl_api_mpls_route_details_t_handler (vl_api_mpls_route_details_t * mp)
7174 {
7175   vat_main_t *vam = &vat_main;
7176   int count = (int) clib_net_to_host_u32 (mp->mr_route.mr_n_paths);
7177   vl_api_fib_path_t *fp;
7178   int i;
7179
7180   print (vam->ofp,
7181          "table-id %d, label %u, ess_bit %u",
7182          ntohl (mp->mr_route.mr_table_id),
7183          ntohl (mp->mr_route.mr_label), mp->mr_route.mr_eos);
7184   fp = mp->mr_route.mr_paths;
7185   for (i = 0; i < count; i++)
7186     {
7187       vl_api_fib_path_print (vam, fp);
7188       fp++;
7189     }
7190 }
7191
7192 static void vl_api_mpls_route_details_t_handler_json
7193   (vl_api_mpls_route_details_t * mp)
7194 {
7195   vat_main_t *vam = &vat_main;
7196   int count = (int) clib_host_to_net_u32 (mp->mr_route.mr_n_paths);
7197   vat_json_node_t *node = NULL;
7198   vl_api_fib_path_t *fp;
7199   int i;
7200
7201   if (VAT_JSON_ARRAY != vam->json_tree.type)
7202     {
7203       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
7204       vat_json_init_array (&vam->json_tree);
7205     }
7206   node = vat_json_array_add (&vam->json_tree);
7207
7208   vat_json_init_object (node);
7209   vat_json_object_add_uint (node, "table", ntohl (mp->mr_route.mr_table_id));
7210   vat_json_object_add_uint (node, "s_bit", mp->mr_route.mr_eos);
7211   vat_json_object_add_uint (node, "label", ntohl (mp->mr_route.mr_label));
7212   vat_json_object_add_uint (node, "path_count", count);
7213   fp = mp->mr_route.mr_paths;
7214   for (i = 0; i < count; i++)
7215     {
7216       vl_api_mpls_fib_path_json_print (node, fp);
7217       fp++;
7218     }
7219 }
7220
7221 static int
7222 api_mpls_route_dump (vat_main_t * vam)
7223 {
7224   unformat_input_t *input = vam->input;
7225   vl_api_mpls_route_dump_t *mp;
7226   vl_api_control_ping_t *mp_ping;
7227   u32 table_id;
7228   int ret;
7229
7230   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7231     {
7232       if (unformat (input, "table_id %d", &table_id))
7233         ;
7234       else
7235         break;
7236     }
7237   if (table_id == ~0)
7238     {
7239       errmsg ("missing table id");
7240       return -99;
7241     }
7242
7243   M (MPLS_ROUTE_DUMP, mp);
7244
7245   mp->table.mt_table_id = ntohl (table_id);
7246   S (mp);
7247
7248   /* Use a control ping for synchronization */
7249   MPING (CONTROL_PING, mp_ping);
7250   S (mp_ping);
7251
7252   W (ret);
7253   return ret;
7254 }
7255
7256 #define vl_api_ip_table_details_t_endian vl_noop_handler
7257 #define vl_api_ip_table_details_t_print vl_noop_handler
7258
7259 static void
7260 vl_api_ip_table_details_t_handler (vl_api_ip_table_details_t * mp)
7261 {
7262   vat_main_t *vam = &vat_main;
7263
7264   print (vam->ofp,
7265          "%s; table-id %d, prefix %U/%d",
7266          mp->table.name, ntohl (mp->table.table_id));
7267 }
7268
7269
7270 static void vl_api_ip_table_details_t_handler_json
7271   (vl_api_ip_table_details_t * mp)
7272 {
7273   vat_main_t *vam = &vat_main;
7274   vat_json_node_t *node = NULL;
7275
7276   if (VAT_JSON_ARRAY != vam->json_tree.type)
7277     {
7278       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
7279       vat_json_init_array (&vam->json_tree);
7280     }
7281   node = vat_json_array_add (&vam->json_tree);
7282
7283   vat_json_init_object (node);
7284   vat_json_object_add_uint (node, "table", ntohl (mp->table.table_id));
7285 }
7286
7287 static int
7288 api_ip_table_dump (vat_main_t * vam)
7289 {
7290   vl_api_ip_table_dump_t *mp;
7291   vl_api_control_ping_t *mp_ping;
7292   int ret;
7293
7294   M (IP_TABLE_DUMP, mp);
7295   S (mp);
7296
7297   /* Use a control ping for synchronization */
7298   MPING (CONTROL_PING, mp_ping);
7299   S (mp_ping);
7300
7301   W (ret);
7302   return ret;
7303 }
7304
7305 static int
7306 api_ip_mtable_dump (vat_main_t * vam)
7307 {
7308   vl_api_ip_mtable_dump_t *mp;
7309   vl_api_control_ping_t *mp_ping;
7310   int ret;
7311
7312   M (IP_MTABLE_DUMP, mp);
7313   S (mp);
7314
7315   /* Use a control ping for synchronization */
7316   MPING (CONTROL_PING, mp_ping);
7317   S (mp_ping);
7318
7319   W (ret);
7320   return ret;
7321 }
7322
7323 static int
7324 api_ip_mroute_dump (vat_main_t * vam)
7325 {
7326   unformat_input_t *input = vam->input;
7327   vl_api_control_ping_t *mp_ping;
7328   vl_api_ip_mroute_dump_t *mp;
7329   int ret, is_ip6;
7330   u32 table_id;
7331
7332   is_ip6 = 0;
7333   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7334     {
7335       if (unformat (input, "table_id %d", &table_id))
7336         ;
7337       else if (unformat (input, "ip6"))
7338         is_ip6 = 1;
7339       else if (unformat (input, "ip4"))
7340         is_ip6 = 0;
7341       else
7342         break;
7343     }
7344   if (table_id == ~0)
7345     {
7346       errmsg ("missing table id");
7347       return -99;
7348     }
7349
7350   M (IP_MROUTE_DUMP, mp);
7351   mp->table.table_id = table_id;
7352   mp->table.is_ip6 = is_ip6;
7353   S (mp);
7354
7355   /* Use a control ping for synchronization */
7356   MPING (CONTROL_PING, mp_ping);
7357   S (mp_ping);
7358
7359   W (ret);
7360   return ret;
7361 }
7362
7363 #define vl_api_ip_route_details_t_endian vl_noop_handler
7364 #define vl_api_ip_route_details_t_print vl_noop_handler
7365
7366 static void
7367 vl_api_ip_route_details_t_handler (vl_api_ip_route_details_t * mp)
7368 {
7369   vat_main_t *vam = &vat_main;
7370   u8 count = mp->route.n_paths;
7371   vl_api_fib_path_t *fp;
7372   int i;
7373
7374   print (vam->ofp,
7375          "table-id %d, prefix %U/%d",
7376          ntohl (mp->route.table_id),
7377          format_ip46_address, mp->route.prefix.address, mp->route.prefix.len);
7378   for (i = 0; i < count; i++)
7379     {
7380       fp = &mp->route.paths[i];
7381
7382       vl_api_fib_path_print (vam, fp);
7383       fp++;
7384     }
7385 }
7386
7387 static void vl_api_ip_route_details_t_handler_json
7388   (vl_api_ip_route_details_t * mp)
7389 {
7390   vat_main_t *vam = &vat_main;
7391   u8 count = mp->route.n_paths;
7392   vat_json_node_t *node = NULL;
7393   struct in_addr ip4;
7394   struct in6_addr ip6;
7395   vl_api_fib_path_t *fp;
7396   int i;
7397
7398   if (VAT_JSON_ARRAY != vam->json_tree.type)
7399     {
7400       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
7401       vat_json_init_array (&vam->json_tree);
7402     }
7403   node = vat_json_array_add (&vam->json_tree);
7404
7405   vat_json_init_object (node);
7406   vat_json_object_add_uint (node, "table", ntohl (mp->route.table_id));
7407   if (ADDRESS_IP6 == mp->route.prefix.address.af)
7408     {
7409       clib_memcpy (&ip6, &mp->route.prefix.address.un.ip6, sizeof (ip6));
7410       vat_json_object_add_ip6 (node, "prefix", ip6);
7411     }
7412   else
7413     {
7414       clib_memcpy (&ip4, &mp->route.prefix.address.un.ip4, sizeof (ip4));
7415       vat_json_object_add_ip4 (node, "prefix", ip4);
7416     }
7417   vat_json_object_add_uint (node, "mask_length", mp->route.prefix.len);
7418   vat_json_object_add_uint (node, "path_count", count);
7419   for (i = 0; i < count; i++)
7420     {
7421       fp = &mp->route.paths[i];
7422       vl_api_mpls_fib_path_json_print (node, fp);
7423     }
7424 }
7425
7426 static int
7427 api_ip_route_dump (vat_main_t * vam)
7428 {
7429   unformat_input_t *input = vam->input;
7430   vl_api_ip_route_dump_t *mp;
7431   vl_api_control_ping_t *mp_ping;
7432   u32 table_id;
7433   u8 is_ip6;
7434   int ret;
7435
7436   is_ip6 = 0;
7437   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7438     {
7439       if (unformat (input, "table_id %d", &table_id))
7440         ;
7441       else if (unformat (input, "ip6"))
7442         is_ip6 = 1;
7443       else if (unformat (input, "ip4"))
7444         is_ip6 = 0;
7445       else
7446         break;
7447     }
7448   if (table_id == ~0)
7449     {
7450       errmsg ("missing table id");
7451       return -99;
7452     }
7453
7454   M (IP_ROUTE_DUMP, mp);
7455
7456   mp->table.table_id = table_id;
7457   mp->table.is_ip6 = is_ip6;
7458
7459   S (mp);
7460
7461   /* Use a control ping for synchronization */
7462   MPING (CONTROL_PING, mp_ping);
7463   S (mp_ping);
7464
7465   W (ret);
7466   return ret;
7467 }
7468
7469 static int
7470 api_sw_interface_span_enable_disable (vat_main_t * vam)
7471 {
7472   unformat_input_t *i = vam->input;
7473   vl_api_sw_interface_span_enable_disable_t *mp;
7474   u32 src_sw_if_index = ~0;
7475   u32 dst_sw_if_index = ~0;
7476   u8 state = 3;
7477   int ret;
7478   u8 is_l2 = 0;
7479
7480   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7481     {
7482       if (unformat
7483           (i, "src %U", api_unformat_sw_if_index, vam, &src_sw_if_index))
7484         ;
7485       else if (unformat (i, "src_sw_if_index %d", &src_sw_if_index))
7486         ;
7487       else
7488         if (unformat
7489             (i, "dst %U", api_unformat_sw_if_index, vam, &dst_sw_if_index))
7490         ;
7491       else if (unformat (i, "dst_sw_if_index %d", &dst_sw_if_index))
7492         ;
7493       else if (unformat (i, "disable"))
7494         state = 0;
7495       else if (unformat (i, "rx"))
7496         state = 1;
7497       else if (unformat (i, "tx"))
7498         state = 2;
7499       else if (unformat (i, "both"))
7500         state = 3;
7501       else if (unformat (i, "l2"))
7502         is_l2 = 1;
7503       else
7504         break;
7505     }
7506
7507   M (SW_INTERFACE_SPAN_ENABLE_DISABLE, mp);
7508
7509   mp->sw_if_index_from = htonl (src_sw_if_index);
7510   mp->sw_if_index_to = htonl (dst_sw_if_index);
7511   mp->state = state;
7512   mp->is_l2 = is_l2;
7513
7514   S (mp);
7515   W (ret);
7516   return ret;
7517 }
7518
7519 static void
7520 vl_api_sw_interface_span_details_t_handler (vl_api_sw_interface_span_details_t
7521                                             * mp)
7522 {
7523   vat_main_t *vam = &vat_main;
7524   u8 *sw_if_from_name = 0;
7525   u8 *sw_if_to_name = 0;
7526   u32 sw_if_index_from = ntohl (mp->sw_if_index_from);
7527   u32 sw_if_index_to = ntohl (mp->sw_if_index_to);
7528   char *states[] = { "none", "rx", "tx", "both" };
7529   hash_pair_t *p;
7530
7531   /* *INDENT-OFF* */
7532   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
7533   ({
7534     if ((u32) p->value[0] == sw_if_index_from)
7535       {
7536         sw_if_from_name = (u8 *)(p->key);
7537         if (sw_if_to_name)
7538           break;
7539       }
7540     if ((u32) p->value[0] == sw_if_index_to)
7541       {
7542         sw_if_to_name = (u8 *)(p->key);
7543         if (sw_if_from_name)
7544           break;
7545       }
7546   }));
7547   /* *INDENT-ON* */
7548   print (vam->ofp, "%20s => %20s (%s) %s",
7549          sw_if_from_name, sw_if_to_name, states[mp->state],
7550          mp->is_l2 ? "l2" : "device");
7551 }
7552
7553 static void
7554   vl_api_sw_interface_span_details_t_handler_json
7555   (vl_api_sw_interface_span_details_t * mp)
7556 {
7557   vat_main_t *vam = &vat_main;
7558   vat_json_node_t *node = NULL;
7559   u8 *sw_if_from_name = 0;
7560   u8 *sw_if_to_name = 0;
7561   u32 sw_if_index_from = ntohl (mp->sw_if_index_from);
7562   u32 sw_if_index_to = ntohl (mp->sw_if_index_to);
7563   hash_pair_t *p;
7564
7565   /* *INDENT-OFF* */
7566   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
7567   ({
7568     if ((u32) p->value[0] == sw_if_index_from)
7569       {
7570         sw_if_from_name = (u8 *)(p->key);
7571         if (sw_if_to_name)
7572           break;
7573       }
7574     if ((u32) p->value[0] == sw_if_index_to)
7575       {
7576         sw_if_to_name = (u8 *)(p->key);
7577         if (sw_if_from_name)
7578           break;
7579       }
7580   }));
7581   /* *INDENT-ON* */
7582
7583   if (VAT_JSON_ARRAY != vam->json_tree.type)
7584     {
7585       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
7586       vat_json_init_array (&vam->json_tree);
7587     }
7588   node = vat_json_array_add (&vam->json_tree);
7589
7590   vat_json_init_object (node);
7591   vat_json_object_add_uint (node, "src-if-index", sw_if_index_from);
7592   vat_json_object_add_string_copy (node, "src-if-name", sw_if_from_name);
7593   vat_json_object_add_uint (node, "dst-if-index", sw_if_index_to);
7594   if (0 != sw_if_to_name)
7595     {
7596       vat_json_object_add_string_copy (node, "dst-if-name", sw_if_to_name);
7597     }
7598   vat_json_object_add_uint (node, "state", mp->state);
7599   vat_json_object_add_uint (node, "is-l2", mp->is_l2);
7600 }
7601
7602 static int
7603 api_sw_interface_span_dump (vat_main_t * vam)
7604 {
7605   unformat_input_t *input = vam->input;
7606   vl_api_sw_interface_span_dump_t *mp;
7607   vl_api_control_ping_t *mp_ping;
7608   u8 is_l2 = 0;
7609   int ret;
7610
7611   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7612     {
7613       if (unformat (input, "l2"))
7614         is_l2 = 1;
7615       else
7616         break;
7617     }
7618
7619   M (SW_INTERFACE_SPAN_DUMP, mp);
7620   mp->is_l2 = is_l2;
7621   S (mp);
7622
7623   /* Use a control ping for synchronization */
7624   MPING (CONTROL_PING, mp_ping);
7625   S (mp_ping);
7626
7627   W (ret);
7628   return ret;
7629 }
7630
7631 int
7632 api_ip_source_and_port_range_check_add_del (vat_main_t * vam)
7633 {
7634   unformat_input_t *input = vam->input;
7635   vl_api_ip_source_and_port_range_check_add_del_t *mp;
7636
7637   u16 *low_ports = 0;
7638   u16 *high_ports = 0;
7639   u16 this_low;
7640   u16 this_hi;
7641   vl_api_prefix_t prefix;
7642   u32 tmp, tmp2;
7643   u8 prefix_set = 0;
7644   u32 vrf_id = ~0;
7645   u8 is_add = 1;
7646   int ret;
7647
7648   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7649     {
7650       if (unformat (input, "%U", unformat_vl_api_prefix, &prefix))
7651         prefix_set = 1;
7652       else if (unformat (input, "vrf %d", &vrf_id))
7653         ;
7654       else if (unformat (input, "del"))
7655         is_add = 0;
7656       else if (unformat (input, "port %d", &tmp))
7657         {
7658           if (tmp == 0 || tmp > 65535)
7659             {
7660               errmsg ("port %d out of range", tmp);
7661               return -99;
7662             }
7663           this_low = tmp;
7664           this_hi = this_low + 1;
7665           vec_add1 (low_ports, this_low);
7666           vec_add1 (high_ports, this_hi);
7667         }
7668       else if (unformat (input, "range %d - %d", &tmp, &tmp2))
7669         {
7670           if ((tmp > tmp2) || (tmp == 0) || (tmp2 > 65535))
7671             {
7672               errmsg ("incorrect range parameters");
7673               return -99;
7674             }
7675           this_low = tmp;
7676           /* Note: in debug CLI +1 is added to high before
7677              passing to real fn that does "the work"
7678              (ip_source_and_port_range_check_add_del).
7679              This fn is a wrapper around the binary API fn a
7680              control plane will call, which expects this increment
7681              to have occurred. Hence letting the binary API control
7682              plane fn do the increment for consistency between VAT
7683              and other control planes.
7684            */
7685           this_hi = tmp2;
7686           vec_add1 (low_ports, this_low);
7687           vec_add1 (high_ports, this_hi);
7688         }
7689       else
7690         break;
7691     }
7692
7693   if (prefix_set == 0)
7694     {
7695       errmsg ("<address>/<mask> not specified");
7696       return -99;
7697     }
7698
7699   if (vrf_id == ~0)
7700     {
7701       errmsg ("VRF ID required, not specified");
7702       return -99;
7703     }
7704
7705   if (vrf_id == 0)
7706     {
7707       errmsg
7708         ("VRF ID should not be default. Should be distinct VRF for this purpose.");
7709       return -99;
7710     }
7711
7712   if (vec_len (low_ports) == 0)
7713     {
7714       errmsg ("At least one port or port range required");
7715       return -99;
7716     }
7717
7718   M (IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL, mp);
7719
7720   mp->is_add = is_add;
7721
7722   clib_memcpy (&mp->prefix, &prefix, sizeof (prefix));
7723
7724   mp->number_of_ranges = vec_len (low_ports);
7725
7726   clib_memcpy (mp->low_ports, low_ports, vec_len (low_ports));
7727   vec_free (low_ports);
7728
7729   clib_memcpy (mp->high_ports, high_ports, vec_len (high_ports));
7730   vec_free (high_ports);
7731
7732   mp->vrf_id = ntohl (vrf_id);
7733
7734   S (mp);
7735   W (ret);
7736   return ret;
7737 }
7738
7739 int
7740 api_ip_source_and_port_range_check_interface_add_del (vat_main_t * vam)
7741 {
7742   unformat_input_t *input = vam->input;
7743   vl_api_ip_source_and_port_range_check_interface_add_del_t *mp;
7744   u32 sw_if_index = ~0;
7745   int vrf_set = 0;
7746   u32 tcp_out_vrf_id = ~0, udp_out_vrf_id = ~0;
7747   u32 tcp_in_vrf_id = ~0, udp_in_vrf_id = ~0;
7748   u8 is_add = 1;
7749   int ret;
7750
7751   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7752     {
7753       if (unformat (input, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
7754         ;
7755       else if (unformat (input, "sw_if_index %d", &sw_if_index))
7756         ;
7757       else if (unformat (input, "tcp-out-vrf %d", &tcp_out_vrf_id))
7758         vrf_set = 1;
7759       else if (unformat (input, "udp-out-vrf %d", &udp_out_vrf_id))
7760         vrf_set = 1;
7761       else if (unformat (input, "tcp-in-vrf %d", &tcp_in_vrf_id))
7762         vrf_set = 1;
7763       else if (unformat (input, "udp-in-vrf %d", &udp_in_vrf_id))
7764         vrf_set = 1;
7765       else if (unformat (input, "del"))
7766         is_add = 0;
7767       else
7768         break;
7769     }
7770
7771   if (sw_if_index == ~0)
7772     {
7773       errmsg ("Interface required but not specified");
7774       return -99;
7775     }
7776
7777   if (vrf_set == 0)
7778     {
7779       errmsg ("VRF ID required but not specified");
7780       return -99;
7781     }
7782
7783   if (tcp_out_vrf_id == 0
7784       || udp_out_vrf_id == 0 || tcp_in_vrf_id == 0 || udp_in_vrf_id == 0)
7785     {
7786       errmsg
7787         ("VRF ID should not be default. Should be distinct VRF for this purpose.");
7788       return -99;
7789     }
7790
7791   /* Construct the API message */
7792   M (IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL, mp);
7793
7794   mp->sw_if_index = ntohl (sw_if_index);
7795   mp->is_add = is_add;
7796   mp->tcp_out_vrf_id = ntohl (tcp_out_vrf_id);
7797   mp->udp_out_vrf_id = ntohl (udp_out_vrf_id);
7798   mp->tcp_in_vrf_id = ntohl (tcp_in_vrf_id);
7799   mp->udp_in_vrf_id = ntohl (udp_in_vrf_id);
7800
7801   /* send it... */
7802   S (mp);
7803
7804   /* Wait for a reply... */
7805   W (ret);
7806   return ret;
7807 }
7808
7809 static int
7810 api_delete_subif (vat_main_t * vam)
7811 {
7812   unformat_input_t *i = vam->input;
7813   vl_api_delete_subif_t *mp;
7814   u32 sw_if_index = ~0;
7815   int ret;
7816
7817   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7818     {
7819       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
7820         ;
7821       if (unformat (i, "sw_if_index %d", &sw_if_index))
7822         ;
7823       else
7824         break;
7825     }
7826
7827   if (sw_if_index == ~0)
7828     {
7829       errmsg ("missing sw_if_index");
7830       return -99;
7831     }
7832
7833   /* Construct the API message */
7834   M (DELETE_SUBIF, mp);
7835   mp->sw_if_index = ntohl (sw_if_index);
7836
7837   S (mp);
7838   W (ret);
7839   return ret;
7840 }
7841
7842 #define foreach_pbb_vtr_op      \
7843 _("disable",  L2_VTR_DISABLED)  \
7844 _("pop",  L2_VTR_POP_2)         \
7845 _("push",  L2_VTR_PUSH_2)
7846
7847 static int
7848 api_l2_interface_pbb_tag_rewrite (vat_main_t * vam)
7849 {
7850   unformat_input_t *i = vam->input;
7851   vl_api_l2_interface_pbb_tag_rewrite_t *mp;
7852   u32 sw_if_index = ~0, vtr_op = ~0;
7853   u16 outer_tag = ~0;
7854   u8 dmac[6], smac[6];
7855   u8 dmac_set = 0, smac_set = 0;
7856   u16 vlanid = 0;
7857   u32 sid = ~0;
7858   u32 tmp;
7859   int ret;
7860
7861   /* Shut up coverity */
7862   clib_memset (dmac, 0, sizeof (dmac));
7863   clib_memset (smac, 0, sizeof (smac));
7864
7865   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7866     {
7867       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
7868         ;
7869       else if (unformat (i, "sw_if_index %d", &sw_if_index))
7870         ;
7871       else if (unformat (i, "vtr_op %d", &vtr_op))
7872         ;
7873 #define _(n,v) else if (unformat(i, n)) {vtr_op = v;}
7874       foreach_pbb_vtr_op
7875 #undef _
7876         else if (unformat (i, "translate_pbb_stag"))
7877         {
7878           if (unformat (i, "%d", &tmp))
7879             {
7880               vtr_op = L2_VTR_TRANSLATE_2_1;
7881               outer_tag = tmp;
7882             }
7883           else
7884             {
7885               errmsg
7886                 ("translate_pbb_stag operation requires outer tag definition");
7887               return -99;
7888             }
7889         }
7890       else if (unformat (i, "dmac %U", unformat_ethernet_address, dmac))
7891         dmac_set++;
7892       else if (unformat (i, "smac %U", unformat_ethernet_address, smac))
7893         smac_set++;
7894       else if (unformat (i, "sid %d", &sid))
7895         ;
7896       else if (unformat (i, "vlanid %d", &tmp))
7897         vlanid = tmp;
7898       else
7899         {
7900           clib_warning ("parse error '%U'", format_unformat_error, i);
7901           return -99;
7902         }
7903     }
7904
7905   if ((sw_if_index == ~0) || (vtr_op == ~0))
7906     {
7907       errmsg ("missing sw_if_index or vtr operation");
7908       return -99;
7909     }
7910   if (((vtr_op == L2_VTR_PUSH_2) || (vtr_op == L2_VTR_TRANSLATE_2_2))
7911       && ((dmac_set == 0) || (smac_set == 0) || (sid == ~0)))
7912     {
7913       errmsg
7914         ("push and translate_qinq operations require dmac, smac, sid and optionally vlanid");
7915       return -99;
7916     }
7917
7918   M (L2_INTERFACE_PBB_TAG_REWRITE, mp);
7919   mp->sw_if_index = ntohl (sw_if_index);
7920   mp->vtr_op = ntohl (vtr_op);
7921   mp->outer_tag = ntohs (outer_tag);
7922   clib_memcpy (mp->b_dmac, dmac, sizeof (dmac));
7923   clib_memcpy (mp->b_smac, smac, sizeof (smac));
7924   mp->b_vlanid = ntohs (vlanid);
7925   mp->i_sid = ntohl (sid);
7926
7927   S (mp);
7928   W (ret);
7929   return ret;
7930 }
7931
7932 static int
7933 api_sw_interface_tag_add_del (vat_main_t * vam)
7934 {
7935   unformat_input_t *i = vam->input;
7936   vl_api_sw_interface_tag_add_del_t *mp;
7937   u32 sw_if_index = ~0;
7938   u8 *tag = 0;
7939   u8 enable = 1;
7940   int ret;
7941
7942   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7943     {
7944       if (unformat (i, "tag %s", &tag))
7945         ;
7946       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
7947         ;
7948       else if (unformat (i, "sw_if_index %d", &sw_if_index))
7949         ;
7950       else if (unformat (i, "del"))
7951         enable = 0;
7952       else
7953         break;
7954     }
7955
7956   if (sw_if_index == ~0)
7957     {
7958       errmsg ("missing interface name or sw_if_index");
7959       return -99;
7960     }
7961
7962   if (enable && (tag == 0))
7963     {
7964       errmsg ("no tag specified");
7965       return -99;
7966     }
7967
7968   /* Construct the API message */
7969   M (SW_INTERFACE_TAG_ADD_DEL, mp);
7970   mp->sw_if_index = ntohl (sw_if_index);
7971   mp->is_add = enable;
7972   if (enable)
7973     strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
7974   vec_free (tag);
7975
7976   S (mp);
7977   W (ret);
7978   return ret;
7979 }
7980
7981 static int
7982 api_sw_interface_add_del_mac_address (vat_main_t * vam)
7983 {
7984   unformat_input_t *i = vam->input;
7985   vl_api_mac_address_t mac = { 0 };
7986   vl_api_sw_interface_add_del_mac_address_t *mp;
7987   u32 sw_if_index = ~0;
7988   u8 is_add = 1;
7989   u8 mac_set = 0;
7990   int ret;
7991
7992   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7993     {
7994       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
7995         ;
7996       else if (unformat (i, "sw_if_index %d", &sw_if_index))
7997         ;
7998       else if (unformat (i, "%U", unformat_vl_api_mac_address, &mac))
7999         mac_set++;
8000       else if (unformat (i, "del"))
8001         is_add = 0;
8002       else
8003         break;
8004     }
8005
8006   if (sw_if_index == ~0)
8007     {
8008       errmsg ("missing interface name or sw_if_index");
8009       return -99;
8010     }
8011
8012   if (!mac_set)
8013     {
8014       errmsg ("missing MAC address");
8015       return -99;
8016     }
8017
8018   /* Construct the API message */
8019   M (SW_INTERFACE_ADD_DEL_MAC_ADDRESS, mp);
8020   mp->sw_if_index = ntohl (sw_if_index);
8021   mp->is_add = is_add;
8022   clib_memcpy (&mp->addr, &mac, sizeof (mac));
8023
8024   S (mp);
8025   W (ret);
8026   return ret;
8027 }
8028
8029 static void vl_api_l2_xconnect_details_t_handler
8030   (vl_api_l2_xconnect_details_t * mp)
8031 {
8032   vat_main_t *vam = &vat_main;
8033
8034   print (vam->ofp, "%15d%15d",
8035          ntohl (mp->rx_sw_if_index), ntohl (mp->tx_sw_if_index));
8036 }
8037
8038 static void vl_api_l2_xconnect_details_t_handler_json
8039   (vl_api_l2_xconnect_details_t * mp)
8040 {
8041   vat_main_t *vam = &vat_main;
8042   vat_json_node_t *node = NULL;
8043
8044   if (VAT_JSON_ARRAY != vam->json_tree.type)
8045     {
8046       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
8047       vat_json_init_array (&vam->json_tree);
8048     }
8049   node = vat_json_array_add (&vam->json_tree);
8050
8051   vat_json_init_object (node);
8052   vat_json_object_add_uint (node, "rx_sw_if_index",
8053                             ntohl (mp->rx_sw_if_index));
8054   vat_json_object_add_uint (node, "tx_sw_if_index",
8055                             ntohl (mp->tx_sw_if_index));
8056 }
8057
8058 static int
8059 api_l2_xconnect_dump (vat_main_t * vam)
8060 {
8061   vl_api_l2_xconnect_dump_t *mp;
8062   vl_api_control_ping_t *mp_ping;
8063   int ret;
8064
8065   if (!vam->json_output)
8066     {
8067       print (vam->ofp, "%15s%15s", "rx_sw_if_index", "tx_sw_if_index");
8068     }
8069
8070   M (L2_XCONNECT_DUMP, mp);
8071
8072   S (mp);
8073
8074   /* Use a control ping for synchronization */
8075   MPING (CONTROL_PING, mp_ping);
8076   S (mp_ping);
8077
8078   W (ret);
8079   return ret;
8080 }
8081
8082 static int
8083 api_hw_interface_set_mtu (vat_main_t * vam)
8084 {
8085   unformat_input_t *i = vam->input;
8086   vl_api_hw_interface_set_mtu_t *mp;
8087   u32 sw_if_index = ~0;
8088   u32 mtu = 0;
8089   int ret;
8090
8091   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8092     {
8093       if (unformat (i, "mtu %d", &mtu))
8094         ;
8095       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8096         ;
8097       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8098         ;
8099       else
8100         break;
8101     }
8102
8103   if (sw_if_index == ~0)
8104     {
8105       errmsg ("missing interface name or sw_if_index");
8106       return -99;
8107     }
8108
8109   if (mtu == 0)
8110     {
8111       errmsg ("no mtu specified");
8112       return -99;
8113     }
8114
8115   /* Construct the API message */
8116   M (HW_INTERFACE_SET_MTU, mp);
8117   mp->sw_if_index = ntohl (sw_if_index);
8118   mp->mtu = ntohs ((u16) mtu);
8119
8120   S (mp);
8121   W (ret);
8122   return ret;
8123 }
8124
8125 static void vl_api_app_namespace_add_del_reply_t_handler
8126   (vl_api_app_namespace_add_del_reply_t * mp)
8127 {
8128   vat_main_t *vam = &vat_main;
8129   i32 retval = ntohl (mp->retval);
8130   if (vam->async_mode)
8131     {
8132       vam->async_errors += (retval < 0);
8133     }
8134   else
8135     {
8136       vam->retval = retval;
8137       if (retval == 0)
8138         errmsg ("app ns index %d\n", ntohl (mp->appns_index));
8139       vam->result_ready = 1;
8140     }
8141 }
8142
8143 static void vl_api_app_namespace_add_del_reply_t_handler_json
8144   (vl_api_app_namespace_add_del_reply_t * mp)
8145 {
8146   vat_main_t *vam = &vat_main;
8147   vat_json_node_t node;
8148
8149   vat_json_init_object (&node);
8150   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
8151   vat_json_object_add_uint (&node, "appns_index", ntohl (mp->appns_index));
8152
8153   vat_json_print (vam->ofp, &node);
8154   vat_json_free (&node);
8155
8156   vam->retval = ntohl (mp->retval);
8157   vam->result_ready = 1;
8158 }
8159
8160 static int
8161 api_app_namespace_add_del (vat_main_t * vam)
8162 {
8163   vl_api_app_namespace_add_del_t *mp;
8164   unformat_input_t *i = vam->input;
8165   u8 *ns_id = 0, secret_set = 0, sw_if_index_set = 0;
8166   u32 sw_if_index, ip4_fib_id, ip6_fib_id;
8167   u64 secret;
8168   int ret;
8169
8170   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8171     {
8172       if (unformat (i, "id %_%v%_", &ns_id))
8173         ;
8174       else if (unformat (i, "secret %lu", &secret))
8175         secret_set = 1;
8176       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8177         sw_if_index_set = 1;
8178       else if (unformat (i, "ip4_fib_id %d", &ip4_fib_id))
8179         ;
8180       else if (unformat (i, "ip6_fib_id %d", &ip6_fib_id))
8181         ;
8182       else
8183         break;
8184     }
8185   if (!ns_id || !secret_set || !sw_if_index_set)
8186     {
8187       errmsg ("namespace id, secret and sw_if_index must be set");
8188       return -99;
8189     }
8190   if (vec_len (ns_id) > 64)
8191     {
8192       errmsg ("namespace id too long");
8193       return -99;
8194     }
8195   M (APP_NAMESPACE_ADD_DEL, mp);
8196
8197   vl_api_vec_to_api_string (ns_id, &mp->namespace_id);
8198   mp->secret = clib_host_to_net_u64 (secret);
8199   mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
8200   mp->ip4_fib_id = clib_host_to_net_u32 (ip4_fib_id);
8201   mp->ip6_fib_id = clib_host_to_net_u32 (ip6_fib_id);
8202   vec_free (ns_id);
8203   S (mp);
8204   W (ret);
8205   return ret;
8206 }
8207
8208 static int
8209 api_sock_init_shm (vat_main_t * vam)
8210 {
8211 #if VPP_API_TEST_BUILTIN == 0
8212   unformat_input_t *i = vam->input;
8213   vl_api_shm_elem_config_t *config = 0;
8214   u64 size = 64 << 20;
8215   int rv;
8216
8217   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8218     {
8219       if (unformat (i, "size %U", unformat_memory_size, &size))
8220         ;
8221       else
8222         break;
8223     }
8224
8225   /*
8226    * Canned custom ring allocator config.
8227    * Should probably parse all of this
8228    */
8229   vec_validate (config, 6);
8230   config[0].type = VL_API_VLIB_RING;
8231   config[0].size = 256;
8232   config[0].count = 32;
8233
8234   config[1].type = VL_API_VLIB_RING;
8235   config[1].size = 1024;
8236   config[1].count = 16;
8237
8238   config[2].type = VL_API_VLIB_RING;
8239   config[2].size = 4096;
8240   config[2].count = 2;
8241
8242   config[3].type = VL_API_CLIENT_RING;
8243   config[3].size = 256;
8244   config[3].count = 32;
8245
8246   config[4].type = VL_API_CLIENT_RING;
8247   config[4].size = 1024;
8248   config[4].count = 16;
8249
8250   config[5].type = VL_API_CLIENT_RING;
8251   config[5].size = 4096;
8252   config[5].count = 2;
8253
8254   config[6].type = VL_API_QUEUE;
8255   config[6].count = 128;
8256   config[6].size = sizeof (uword);
8257
8258   rv = vl_socket_client_init_shm (config, 1 /* want_pthread */ );
8259   if (!rv)
8260     vam->client_index_invalid = 1;
8261   return rv;
8262 #else
8263   return -99;
8264 #endif
8265 }
8266
8267 static void
8268 vl_api_session_rules_details_t_handler (vl_api_session_rules_details_t * mp)
8269 {
8270   vat_main_t *vam = &vat_main;
8271   fib_prefix_t lcl, rmt;
8272
8273   ip_prefix_decode (&mp->lcl, &lcl);
8274   ip_prefix_decode (&mp->rmt, &rmt);
8275
8276   if (lcl.fp_proto == FIB_PROTOCOL_IP4)
8277     {
8278       print (vam->ofp,
8279              "appns %u tp %u scope %d %U/%d %d %U/%d %d action: %d tag: %s",
8280              clib_net_to_host_u32 (mp->appns_index), mp->transport_proto,
8281              mp->scope, format_ip4_address, &lcl.fp_addr.ip4, lcl.fp_len,
8282              clib_net_to_host_u16 (mp->lcl_port), format_ip4_address,
8283              &rmt.fp_addr.ip4, rmt.fp_len,
8284              clib_net_to_host_u16 (mp->rmt_port),
8285              clib_net_to_host_u32 (mp->action_index), mp->tag);
8286     }
8287   else
8288     {
8289       print (vam->ofp,
8290              "appns %u tp %u scope %d %U/%d %d %U/%d %d action: %d tag: %s",
8291              clib_net_to_host_u32 (mp->appns_index), mp->transport_proto,
8292              mp->scope, format_ip6_address, &lcl.fp_addr.ip6, lcl.fp_len,
8293              clib_net_to_host_u16 (mp->lcl_port), format_ip6_address,
8294              &rmt.fp_addr.ip6, rmt.fp_len,
8295              clib_net_to_host_u16 (mp->rmt_port),
8296              clib_net_to_host_u32 (mp->action_index), mp->tag);
8297     }
8298 }
8299
8300 static void
8301 vl_api_session_rules_details_t_handler_json (vl_api_session_rules_details_t *
8302                                              mp)
8303 {
8304   vat_main_t *vam = &vat_main;
8305   vat_json_node_t *node = NULL;
8306   struct in6_addr ip6;
8307   struct in_addr ip4;
8308
8309   fib_prefix_t lcl, rmt;
8310
8311   ip_prefix_decode (&mp->lcl, &lcl);
8312   ip_prefix_decode (&mp->rmt, &rmt);
8313
8314   if (VAT_JSON_ARRAY != vam->json_tree.type)
8315     {
8316       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
8317       vat_json_init_array (&vam->json_tree);
8318     }
8319   node = vat_json_array_add (&vam->json_tree);
8320   vat_json_init_object (node);
8321
8322   vat_json_object_add_uint (node, "appns_index",
8323                             clib_net_to_host_u32 (mp->appns_index));
8324   vat_json_object_add_uint (node, "transport_proto", mp->transport_proto);
8325   vat_json_object_add_uint (node, "scope", mp->scope);
8326   vat_json_object_add_uint (node, "action_index",
8327                             clib_net_to_host_u32 (mp->action_index));
8328   vat_json_object_add_uint (node, "lcl_port",
8329                             clib_net_to_host_u16 (mp->lcl_port));
8330   vat_json_object_add_uint (node, "rmt_port",
8331                             clib_net_to_host_u16 (mp->rmt_port));
8332   vat_json_object_add_uint (node, "lcl_plen", lcl.fp_len);
8333   vat_json_object_add_uint (node, "rmt_plen", rmt.fp_len);
8334   vat_json_object_add_string_copy (node, "tag", mp->tag);
8335   if (lcl.fp_proto == FIB_PROTOCOL_IP4)
8336     {
8337       clib_memcpy (&ip4, &lcl.fp_addr.ip4, sizeof (ip4));
8338       vat_json_object_add_ip4 (node, "lcl_ip", ip4);
8339       clib_memcpy (&ip4, &rmt.fp_addr.ip4, sizeof (ip4));
8340       vat_json_object_add_ip4 (node, "rmt_ip", ip4);
8341     }
8342   else
8343     {
8344       clib_memcpy (&ip6, &lcl.fp_addr.ip6, sizeof (ip6));
8345       vat_json_object_add_ip6 (node, "lcl_ip", ip6);
8346       clib_memcpy (&ip6, &rmt.fp_addr.ip6, sizeof (ip6));
8347       vat_json_object_add_ip6 (node, "rmt_ip", ip6);
8348     }
8349 }
8350
8351 static int
8352 api_session_rule_add_del (vat_main_t * vam)
8353 {
8354   vl_api_session_rule_add_del_t *mp;
8355   unformat_input_t *i = vam->input;
8356   u32 proto = ~0, lcl_port, rmt_port, action = 0, lcl_plen, rmt_plen;
8357   u32 appns_index = 0, scope = 0;
8358   ip4_address_t lcl_ip4, rmt_ip4;
8359   ip6_address_t lcl_ip6, rmt_ip6;
8360   u8 is_ip4 = 1, conn_set = 0;
8361   u8 is_add = 1, *tag = 0;
8362   int ret;
8363   fib_prefix_t lcl, rmt;
8364
8365   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8366     {
8367       if (unformat (i, "del"))
8368         is_add = 0;
8369       else if (unformat (i, "add"))
8370         ;
8371       else if (unformat (i, "proto tcp"))
8372         proto = 0;
8373       else if (unformat (i, "proto udp"))
8374         proto = 1;
8375       else if (unformat (i, "appns %d", &appns_index))
8376         ;
8377       else if (unformat (i, "scope %d", &scope))
8378         ;
8379       else if (unformat (i, "tag %_%v%_", &tag))
8380         ;
8381       else
8382         if (unformat
8383             (i, "%U/%d %d %U/%d %d", unformat_ip4_address, &lcl_ip4,
8384              &lcl_plen, &lcl_port, unformat_ip4_address, &rmt_ip4, &rmt_plen,
8385              &rmt_port))
8386         {
8387           is_ip4 = 1;
8388           conn_set = 1;
8389         }
8390       else
8391         if (unformat
8392             (i, "%U/%d %d %U/%d %d", unformat_ip6_address, &lcl_ip6,
8393              &lcl_plen, &lcl_port, unformat_ip6_address, &rmt_ip6, &rmt_plen,
8394              &rmt_port))
8395         {
8396           is_ip4 = 0;
8397           conn_set = 1;
8398         }
8399       else if (unformat (i, "action %d", &action))
8400         ;
8401       else
8402         break;
8403     }
8404   if (proto == ~0 || !conn_set || action == ~0)
8405     {
8406       errmsg ("transport proto, connection and action must be set");
8407       return -99;
8408     }
8409
8410   if (scope > 3)
8411     {
8412       errmsg ("scope should be 0-3");
8413       return -99;
8414     }
8415
8416   M (SESSION_RULE_ADD_DEL, mp);
8417
8418   clib_memset (&lcl, 0, sizeof (lcl));
8419   clib_memset (&rmt, 0, sizeof (rmt));
8420   if (is_ip4)
8421     {
8422       ip_set (&lcl.fp_addr, &lcl_ip4, 1);
8423       ip_set (&rmt.fp_addr, &rmt_ip4, 1);
8424       lcl.fp_len = lcl_plen;
8425       rmt.fp_len = rmt_plen;
8426     }
8427   else
8428     {
8429       ip_set (&lcl.fp_addr, &lcl_ip6, 0);
8430       ip_set (&rmt.fp_addr, &rmt_ip6, 0);
8431       lcl.fp_len = lcl_plen;
8432       rmt.fp_len = rmt_plen;
8433     }
8434
8435
8436   ip_prefix_encode (&lcl, &mp->lcl);
8437   ip_prefix_encode (&rmt, &mp->rmt);
8438   mp->lcl_port = clib_host_to_net_u16 ((u16) lcl_port);
8439   mp->rmt_port = clib_host_to_net_u16 ((u16) rmt_port);
8440   mp->transport_proto =
8441     proto ? TRANSPORT_PROTO_API_UDP : TRANSPORT_PROTO_API_TCP;
8442   mp->action_index = clib_host_to_net_u32 (action);
8443   mp->appns_index = clib_host_to_net_u32 (appns_index);
8444   mp->scope = scope;
8445   mp->is_add = is_add;
8446   if (tag)
8447     {
8448       clib_memcpy (mp->tag, tag, vec_len (tag));
8449       vec_free (tag);
8450     }
8451
8452   S (mp);
8453   W (ret);
8454   return ret;
8455 }
8456
8457 static int
8458 api_session_rules_dump (vat_main_t * vam)
8459 {
8460   vl_api_session_rules_dump_t *mp;
8461   vl_api_control_ping_t *mp_ping;
8462   int ret;
8463
8464   if (!vam->json_output)
8465     {
8466       print (vam->ofp, "%=20s", "Session Rules");
8467     }
8468
8469   M (SESSION_RULES_DUMP, mp);
8470   /* send it... */
8471   S (mp);
8472
8473   /* Use a control ping for synchronization */
8474   MPING (CONTROL_PING, mp_ping);
8475   S (mp_ping);
8476
8477   /* Wait for a reply... */
8478   W (ret);
8479   return ret;
8480 }
8481
8482 static int
8483 api_ip_container_proxy_add_del (vat_main_t * vam)
8484 {
8485   vl_api_ip_container_proxy_add_del_t *mp;
8486   unformat_input_t *i = vam->input;
8487   u32 sw_if_index = ~0;
8488   vl_api_prefix_t pfx = { };
8489   u8 is_add = 1;
8490   int ret;
8491
8492   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8493     {
8494       if (unformat (i, "del"))
8495         is_add = 0;
8496       else if (unformat (i, "add"))
8497         ;
8498       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
8499         ;
8500       else if (unformat (i, "sw_if_index %u", &sw_if_index))
8501         ;
8502       else
8503         break;
8504     }
8505   if (sw_if_index == ~0 || pfx.len == 0)
8506     {
8507       errmsg ("address and sw_if_index must be set");
8508       return -99;
8509     }
8510
8511   M (IP_CONTAINER_PROXY_ADD_DEL, mp);
8512
8513   mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
8514   mp->is_add = is_add;
8515   clib_memcpy (&mp->pfx, &pfx, sizeof (pfx));
8516
8517   S (mp);
8518   W (ret);
8519   return ret;
8520 }
8521
8522 static int
8523 q_or_quit (vat_main_t * vam)
8524 {
8525 #if VPP_API_TEST_BUILTIN == 0
8526   longjmp (vam->jump_buf, 1);
8527 #endif
8528   return 0;                     /* not so much */
8529 }
8530
8531 static int
8532 q (vat_main_t * vam)
8533 {
8534   return q_or_quit (vam);
8535 }
8536
8537 static int
8538 quit (vat_main_t * vam)
8539 {
8540   return q_or_quit (vam);
8541 }
8542
8543 static int
8544 comment (vat_main_t * vam)
8545 {
8546   return 0;
8547 }
8548
8549 static int
8550 elog_save (vat_main_t * vam)
8551 {
8552 #if VPP_API_TEST_BUILTIN == 0
8553   elog_main_t *em = &vam->elog_main;
8554   unformat_input_t *i = vam->input;
8555   char *file, *chroot_file;
8556   clib_error_t *error;
8557
8558   if (!unformat (i, "%s", &file))
8559     {
8560       errmsg ("expected file name, got `%U'", format_unformat_error, i);
8561       return 0;
8562     }
8563
8564   /* It's fairly hard to get "../oopsie" through unformat; just in case */
8565   if (strstr (file, "..") || index (file, '/'))
8566     {
8567       errmsg ("illegal characters in filename '%s'", file);
8568       return 0;
8569     }
8570
8571   chroot_file = (char *) format (0, "/tmp/%s%c", file, 0);
8572
8573   vec_free (file);
8574
8575   errmsg ("Saving %wd of %wd events to %s",
8576           elog_n_events_in_buffer (em),
8577           elog_buffer_capacity (em), chroot_file);
8578
8579   error = elog_write_file (em, chroot_file, 1 /* flush ring */ );
8580   vec_free (chroot_file);
8581
8582   if (error)
8583     clib_error_report (error);
8584 #else
8585   errmsg ("Use the vpp event loger...");
8586 #endif
8587
8588   return 0;
8589 }
8590
8591 static int
8592 elog_setup (vat_main_t * vam)
8593 {
8594 #if VPP_API_TEST_BUILTIN == 0
8595   elog_main_t *em = &vam->elog_main;
8596   unformat_input_t *i = vam->input;
8597   u32 nevents = 128 << 10;
8598
8599   (void) unformat (i, "nevents %d", &nevents);
8600
8601   elog_init (em, nevents);
8602   vl_api_set_elog_main (em);
8603   vl_api_set_elog_trace_api_messages (1);
8604   errmsg ("Event logger initialized with %u events", nevents);
8605 #else
8606   errmsg ("Use the vpp event loger...");
8607 #endif
8608   return 0;
8609 }
8610
8611 static int
8612 elog_enable (vat_main_t * vam)
8613 {
8614 #if VPP_API_TEST_BUILTIN == 0
8615   elog_main_t *em = &vam->elog_main;
8616
8617   elog_enable_disable (em, 1 /* enable */ );
8618   vl_api_set_elog_trace_api_messages (1);
8619   errmsg ("Event logger enabled...");
8620 #else
8621   errmsg ("Use the vpp event loger...");
8622 #endif
8623   return 0;
8624 }
8625
8626 static int
8627 elog_disable (vat_main_t * vam)
8628 {
8629 #if VPP_API_TEST_BUILTIN == 0
8630   elog_main_t *em = &vam->elog_main;
8631
8632   elog_enable_disable (em, 0 /* enable */ );
8633   vl_api_set_elog_trace_api_messages (1);
8634   errmsg ("Event logger disabled...");
8635 #else
8636   errmsg ("Use the vpp event loger...");
8637 #endif
8638   return 0;
8639 }
8640
8641 static int
8642 statseg (vat_main_t * vam)
8643 {
8644   ssvm_private_t *ssvmp = &vam->stat_segment;
8645   ssvm_shared_header_t *shared_header = ssvmp->sh;
8646   vlib_counter_t **counters;
8647   u64 thread0_index1_packets;
8648   u64 thread0_index1_bytes;
8649   f64 vector_rate, input_rate;
8650   uword *p;
8651
8652   uword *counter_vector_by_name;
8653   if (vam->stat_segment_lockp == 0)
8654     {
8655       errmsg ("Stat segment not mapped...");
8656       return -99;
8657     }
8658
8659   /* look up "/if/rx for sw_if_index 1 as a test */
8660
8661   clib_spinlock_lock (vam->stat_segment_lockp);
8662
8663   counter_vector_by_name = (uword *) shared_header->opaque[1];
8664
8665   p = hash_get_mem (counter_vector_by_name, "/if/rx");
8666   if (p == 0)
8667     {
8668       clib_spinlock_unlock (vam->stat_segment_lockp);
8669       errmsg ("/if/tx not found?");
8670       return -99;
8671     }
8672
8673   /* Fish per-thread vector of combined counters from shared memory */
8674   counters = (vlib_counter_t **) p[0];
8675
8676   if (vec_len (counters[0]) < 2)
8677     {
8678       clib_spinlock_unlock (vam->stat_segment_lockp);
8679       errmsg ("/if/tx vector length %d", vec_len (counters[0]));
8680       return -99;
8681     }
8682
8683   /* Read thread 0 sw_if_index 1 counter */
8684   thread0_index1_packets = counters[0][1].packets;
8685   thread0_index1_bytes = counters[0][1].bytes;
8686
8687   p = hash_get_mem (counter_vector_by_name, "vector_rate");
8688   if (p == 0)
8689     {
8690       clib_spinlock_unlock (vam->stat_segment_lockp);
8691       errmsg ("vector_rate not found?");
8692       return -99;
8693     }
8694
8695   vector_rate = *(f64 *) (p[0]);
8696   p = hash_get_mem (counter_vector_by_name, "input_rate");
8697   if (p == 0)
8698     {
8699       clib_spinlock_unlock (vam->stat_segment_lockp);
8700       errmsg ("input_rate not found?");
8701       return -99;
8702     }
8703   input_rate = *(f64 *) (p[0]);
8704
8705   clib_spinlock_unlock (vam->stat_segment_lockp);
8706
8707   print (vam->ofp, "vector_rate %.2f input_rate %.2f",
8708          vector_rate, input_rate);
8709   print (vam->ofp, "thread 0 sw_if_index 1 rx pkts %lld, bytes %lld",
8710          thread0_index1_packets, thread0_index1_bytes);
8711
8712   return 0;
8713 }
8714
8715 static int
8716 cmd_cmp (void *a1, void *a2)
8717 {
8718   u8 **c1 = a1;
8719   u8 **c2 = a2;
8720
8721   return strcmp ((char *) (c1[0]), (char *) (c2[0]));
8722 }
8723
8724 static int
8725 help (vat_main_t * vam)
8726 {
8727   u8 **cmds = 0;
8728   u8 *name = 0;
8729   hash_pair_t *p;
8730   unformat_input_t *i = vam->input;
8731   int j;
8732
8733   if (unformat (i, "%s", &name))
8734     {
8735       uword *hs;
8736
8737       vec_add1 (name, 0);
8738
8739       hs = hash_get_mem (vam->help_by_name, name);
8740       if (hs)
8741         print (vam->ofp, "usage: %s %s", name, hs[0]);
8742       else
8743         print (vam->ofp, "No such msg / command '%s'", name);
8744       vec_free (name);
8745       return 0;
8746     }
8747
8748   print (vam->ofp, "Help is available for the following:");
8749
8750     /* *INDENT-OFF* */
8751     hash_foreach_pair (p, vam->function_by_name,
8752     ({
8753       vec_add1 (cmds, (u8 *)(p->key));
8754     }));
8755     /* *INDENT-ON* */
8756
8757   vec_sort_with_function (cmds, cmd_cmp);
8758
8759   for (j = 0; j < vec_len (cmds); j++)
8760     print (vam->ofp, "%s", cmds[j]);
8761
8762   vec_free (cmds);
8763   return 0;
8764 }
8765
8766 static int
8767 set (vat_main_t * vam)
8768 {
8769   u8 *name = 0, *value = 0;
8770   unformat_input_t *i = vam->input;
8771
8772   if (unformat (i, "%s", &name))
8773     {
8774       /* The input buffer is a vector, not a string. */
8775       value = vec_dup (i->buffer);
8776       vec_delete (value, i->index, 0);
8777       /* Almost certainly has a trailing newline */
8778       if (value[vec_len (value) - 1] == '\n')
8779         value[vec_len (value) - 1] = 0;
8780       /* Make sure it's a proper string, one way or the other */
8781       vec_add1 (value, 0);
8782       (void) clib_macro_set_value (&vam->macro_main,
8783                                    (char *) name, (char *) value);
8784     }
8785   else
8786     errmsg ("usage: set <name> <value>");
8787
8788   vec_free (name);
8789   vec_free (value);
8790   return 0;
8791 }
8792
8793 static int
8794 unset (vat_main_t * vam)
8795 {
8796   u8 *name = 0;
8797
8798   if (unformat (vam->input, "%s", &name))
8799     if (clib_macro_unset (&vam->macro_main, (char *) name) == 1)
8800       errmsg ("unset: %s wasn't set", name);
8801   vec_free (name);
8802   return 0;
8803 }
8804
8805 typedef struct
8806 {
8807   u8 *name;
8808   u8 *value;
8809 } macro_sort_t;
8810
8811
8812 static int
8813 macro_sort_cmp (void *a1, void *a2)
8814 {
8815   macro_sort_t *s1 = a1;
8816   macro_sort_t *s2 = a2;
8817
8818   return strcmp ((char *) (s1->name), (char *) (s2->name));
8819 }
8820
8821 static int
8822 dump_macro_table (vat_main_t * vam)
8823 {
8824   macro_sort_t *sort_me = 0, *sm;
8825   int i;
8826   hash_pair_t *p;
8827
8828     /* *INDENT-OFF* */
8829     hash_foreach_pair (p, vam->macro_main.the_value_table_hash,
8830     ({
8831       vec_add2 (sort_me, sm, 1);
8832       sm->name = (u8 *)(p->key);
8833       sm->value = (u8 *) (p->value[0]);
8834     }));
8835     /* *INDENT-ON* */
8836
8837   vec_sort_with_function (sort_me, macro_sort_cmp);
8838
8839   if (vec_len (sort_me))
8840     print (vam->ofp, "%-15s%s", "Name", "Value");
8841   else
8842     print (vam->ofp, "The macro table is empty...");
8843
8844   for (i = 0; i < vec_len (sort_me); i++)
8845     print (vam->ofp, "%-15s%s", sort_me[i].name, sort_me[i].value);
8846   return 0;
8847 }
8848
8849 static int
8850 dump_node_table (vat_main_t * vam)
8851 {
8852   int i, j;
8853   vlib_node_t *node, *next_node;
8854
8855   if (vec_len (vam->graph_nodes) == 0)
8856     {
8857       print (vam->ofp, "Node table empty, issue get_node_graph...");
8858       return 0;
8859     }
8860
8861   for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
8862     {
8863       node = vam->graph_nodes[0][i];
8864       print (vam->ofp, "[%d] %s", i, node->name);
8865       for (j = 0; j < vec_len (node->next_nodes); j++)
8866         {
8867           if (node->next_nodes[j] != ~0)
8868             {
8869               next_node = vam->graph_nodes[0][node->next_nodes[j]];
8870               print (vam->ofp, "  [%d] %s", j, next_node->name);
8871             }
8872         }
8873     }
8874   return 0;
8875 }
8876
8877 static int
8878 value_sort_cmp (void *a1, void *a2)
8879 {
8880   name_sort_t *n1 = a1;
8881   name_sort_t *n2 = a2;
8882
8883   if (n1->value < n2->value)
8884     return -1;
8885   if (n1->value > n2->value)
8886     return 1;
8887   return 0;
8888 }
8889
8890
8891 static int
8892 dump_msg_api_table (vat_main_t * vam)
8893 {
8894   api_main_t *am = vlibapi_get_main ();
8895   name_sort_t *nses = 0, *ns;
8896   hash_pair_t *hp;
8897   int i;
8898
8899   /* *INDENT-OFF* */
8900   hash_foreach_pair (hp, am->msg_index_by_name_and_crc,
8901   ({
8902     vec_add2 (nses, ns, 1);
8903     ns->name = (u8 *)(hp->key);
8904     ns->value = (u32) hp->value[0];
8905   }));
8906   /* *INDENT-ON* */
8907
8908   vec_sort_with_function (nses, value_sort_cmp);
8909
8910   for (i = 0; i < vec_len (nses); i++)
8911     print (vam->ofp, " [%d]: %s", nses[i].value, nses[i].name);
8912   vec_free (nses);
8913   return 0;
8914 }
8915
8916 static int
8917 get_msg_id (vat_main_t * vam)
8918 {
8919   u8 *name_and_crc;
8920   u32 message_index;
8921
8922   if (unformat (vam->input, "%s", &name_and_crc))
8923     {
8924       message_index = vl_msg_api_get_msg_index (name_and_crc);
8925       if (message_index == ~0)
8926         {
8927           print (vam->ofp, " '%s' not found", name_and_crc);
8928           return 0;
8929         }
8930       print (vam->ofp, " '%s' has message index %d",
8931              name_and_crc, message_index);
8932       return 0;
8933     }
8934   errmsg ("name_and_crc required...");
8935   return 0;
8936 }
8937
8938 static int
8939 search_node_table (vat_main_t * vam)
8940 {
8941   unformat_input_t *line_input = vam->input;
8942   u8 *node_to_find;
8943   int j;
8944   vlib_node_t *node, *next_node;
8945   uword *p;
8946
8947   if (vam->graph_node_index_by_name == 0)
8948     {
8949       print (vam->ofp, "Node table empty, issue get_node_graph...");
8950       return 0;
8951     }
8952
8953   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
8954     {
8955       if (unformat (line_input, "%s", &node_to_find))
8956         {
8957           vec_add1 (node_to_find, 0);
8958           p = hash_get_mem (vam->graph_node_index_by_name, node_to_find);
8959           if (p == 0)
8960             {
8961               print (vam->ofp, "%s not found...", node_to_find);
8962               goto out;
8963             }
8964           node = vam->graph_nodes[0][p[0]];
8965           print (vam->ofp, "[%d] %s", p[0], node->name);
8966           for (j = 0; j < vec_len (node->next_nodes); j++)
8967             {
8968               if (node->next_nodes[j] != ~0)
8969                 {
8970                   next_node = vam->graph_nodes[0][node->next_nodes[j]];
8971                   print (vam->ofp, "  [%d] %s", j, next_node->name);
8972                 }
8973             }
8974         }
8975
8976       else
8977         {
8978           clib_warning ("parse error '%U'", format_unformat_error,
8979                         line_input);
8980           return -99;
8981         }
8982
8983     out:
8984       vec_free (node_to_find);
8985
8986     }
8987
8988   return 0;
8989 }
8990
8991
8992 static int
8993 script (vat_main_t * vam)
8994 {
8995 #if (VPP_API_TEST_BUILTIN==0)
8996   u8 *s = 0;
8997   char *save_current_file;
8998   unformat_input_t save_input;
8999   jmp_buf save_jump_buf;
9000   u32 save_line_number;
9001
9002   FILE *new_fp, *save_ifp;
9003
9004   if (unformat (vam->input, "%s", &s))
9005     {
9006       new_fp = fopen ((char *) s, "r");
9007       if (new_fp == 0)
9008         {
9009           errmsg ("Couldn't open script file %s", s);
9010           vec_free (s);
9011           return -99;
9012         }
9013     }
9014   else
9015     {
9016       errmsg ("Missing script name");
9017       return -99;
9018     }
9019
9020   clib_memcpy (&save_input, &vam->input, sizeof (save_input));
9021   clib_memcpy (&save_jump_buf, &vam->jump_buf, sizeof (save_jump_buf));
9022   save_ifp = vam->ifp;
9023   save_line_number = vam->input_line_number;
9024   save_current_file = (char *) vam->current_file;
9025
9026   vam->input_line_number = 0;
9027   vam->ifp = new_fp;
9028   vam->current_file = s;
9029   do_one_file (vam);
9030
9031   clib_memcpy (&vam->input, &save_input, sizeof (save_input));
9032   clib_memcpy (&vam->jump_buf, &save_jump_buf, sizeof (save_jump_buf));
9033   vam->ifp = save_ifp;
9034   vam->input_line_number = save_line_number;
9035   vam->current_file = (u8 *) save_current_file;
9036   vec_free (s);
9037
9038   return 0;
9039 #else
9040   clib_warning ("use the exec command...");
9041   return -99;
9042 #endif
9043 }
9044
9045 static int
9046 echo (vat_main_t * vam)
9047 {
9048   print (vam->ofp, "%v", vam->input->buffer);
9049   return 0;
9050 }
9051
9052 /* List of API message constructors, CLI names map to api_xxx */
9053 #define foreach_vpe_api_msg                                             \
9054 _(create_loopback,"[mac <mac-addr>] [instance <instance>]")             \
9055 _(sw_interface_dump,"")                                                 \
9056 _(sw_interface_set_flags,                                               \
9057   "<intfc> | sw_if_index <id> admin-up | admin-down link-up | link down") \
9058 _(sw_interface_add_del_address,                                         \
9059   "<intfc> | sw_if_index <id> <ip4-address> | <ip6-address> [del] [del-all] ") \
9060 _(sw_interface_set_rx_mode,                                             \
9061   "<intfc> | sw_if_index <id> [queue <id>] <polling | interrupt | adaptive>") \
9062 _(sw_interface_set_rx_placement,                                        \
9063   "<intfc> | sw_if_index <id> [queue <id>] [worker <id> | main]")       \
9064 _(sw_interface_rx_placement_dump,                                       \
9065   "[<intfc> | sw_if_index <id>]")                                         \
9066 _(sw_interface_set_table,                                               \
9067   "<intfc> | sw_if_index <id> vrf <table-id> [ipv6]")                   \
9068 _(sw_interface_set_mpls_enable,                                         \
9069   "<intfc> | sw_if_index [disable | dis]")                              \
9070 _(sw_interface_set_vpath,                                               \
9071   "<intfc> | sw_if_index <id> enable | disable")                        \
9072 _(sw_interface_set_l2_xconnect,                                         \
9073   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
9074   "enable | disable")                                                   \
9075 _(sw_interface_set_l2_bridge,                                           \
9076   "{<intfc> | sw_if_index <id>} bd_id <bridge-domain-id>\n"             \
9077   "[shg <split-horizon-group>] [bvi]\n"                                 \
9078   "enable | disable")                                                   \
9079 _(bridge_domain_set_mac_age, "bd_id <bridge-domain-id> mac-age 0-255")  \
9080 _(bridge_domain_add_del,                                                \
9081   "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") \
9082 _(bridge_domain_dump, "[bd_id <bridge-domain-id>]\n")                   \
9083 _(l2fib_add_del,                                                        \
9084   "mac <mac-addr> bd_id <bridge-domain-id> [del] | sw_if <intfc> | sw_if_index <id> [static] [filter] [bvi] [count <nn>]\n") \
9085 _(l2fib_flush_bd, "bd_id <bridge-domain-id>")                           \
9086 _(l2fib_flush_int, "<intfc> | sw_if_index <id>")                        \
9087 _(l2_flags,                                                             \
9088   "sw_if <intfc> | sw_if_index <id> [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \
9089 _(bridge_flags,                                                         \
9090   "bd_id <bridge-domain-id> [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \
9091 _(virtio_pci_create_v2,                                                    \
9092   "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]") \
9093 _(virtio_pci_delete,                                                    \
9094   "<vpp-if-name> | sw_if_index <id>")                                   \
9095 _(sw_interface_virtio_pci_dump, "")                                     \
9096 _(ip_table_add_del,                                                     \
9097   "table <n> [ipv6] [add | del]\n")                                     \
9098 _(ip_route_add_del,                                                     \
9099   "<addr>/<mask> via <<addr>|<intfc>|sw_if_index <id>|via-label <n>>\n" \
9100   "[table-id <n>] [<intfc> | sw_if_index <id>] [resolve-attempts <n>]\n"\
9101   "[weight <n>] [drop] [local] [classify <n>]  [out-label <n>]\n"       \
9102   "[multipath] [count <n>] [del]")                                      \
9103 _(ip_mroute_add_del,                                                    \
9104   "<src> <grp>/<mask> [table-id <n>]\n"                                 \
9105   "[<intfc> | sw_if_index <id>] [local] [del]")                         \
9106 _(mpls_table_add_del,                                                   \
9107   "table <n> [add | del]\n")                                            \
9108 _(mpls_route_add_del,                                                   \
9109   "<label> <eos> via <addr | next-hop-table <n> | via-label <n> |\n"    \
9110   "lookup-ip4-table <n> | lookup-in-ip6-table <n> |\n"                  \
9111   "l2-input-on <intfc> | l2-input-on sw_if_index <id>>\n"               \
9112   "[<intfc> | sw_if_index <id>] [resolve-attempts <n>] [weight <n>]\n"  \
9113   "[drop] [local] [classify <n>] [out-label <n>] [multipath]\n"         \
9114   "[count <n>] [del]")                                                  \
9115 _(mpls_ip_bind_unbind,                                                  \
9116   "<label> <addr/len>")                                                 \
9117 _(mpls_tunnel_add_del,                                                  \
9118   "[add | del <intfc | sw_if_index <id>>] via <addr | via-label <n>>\n" \
9119   "[<intfc> | sw_if_index <id> | next-hop-table <id>]\n"                \
9120   "[l2-only]  [out-label <n>]")                                         \
9121 _(sw_interface_set_unnumbered,                                          \
9122   "<intfc> | sw_if_index <id> unnum_if_index <id> [del]")               \
9123 _(create_vlan_subif, "<intfc> | sw_if_index <id> vlan <n>")             \
9124 _(create_subif, "<intfc> | sw_if_index <id> sub_id <n>\n"               \
9125   "[outer_vlan_id <n>][inner_vlan_id <n>]\n"                            \
9126   "[no_tags][one_tag][two_tags][dot1ad][exact_match][default_sub]\n"    \
9127   "[outer_vlan_id_any][inner_vlan_id_any]")                             \
9128 _(ip_table_replace_begin, "table <n> [ipv6]")                           \
9129 _(ip_table_flush, "table <n> [ipv6]")                                   \
9130 _(ip_table_replace_end, "table <n> [ipv6]")                             \
9131 _(set_ip_flow_hash,                                                     \
9132   "vrf <n> [src] [dst] [sport] [dport] [proto] [reverse] [ipv6]")       \
9133 _(sw_interface_ip6_enable_disable,                                      \
9134   "<intfc> | sw_if_index <id> enable | disable")                        \
9135 _(l2_patch_add_del,                                                     \
9136   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
9137   "enable | disable")                                                   \
9138 _(get_node_index, "node <node-name")                                    \
9139 _(add_node_next, "node <node-name> next <next-node-name>")              \
9140 _(l2_fib_clear_table, "")                                               \
9141 _(l2_interface_efp_filter, "sw_if_index <nn> enable | disable")         \
9142 _(l2_interface_vlan_tag_rewrite,                                        \
9143   "<intfc> | sw_if_index <nn> \n"                                       \
9144   "[disable][push-[1|2]][pop-[1|2]][translate-1-[1|2]] \n"              \
9145   "[translate-2-[1|2]] [push_dot1q 0] tag1 <nn> tag2 <nn>")             \
9146 _(show_version, "")                                                     \
9147 _(show_threads, "")                                                     \
9148 _(l2_fib_table_dump, "bd_id <bridge-domain-id>")                        \
9149 _(interface_name_renumber,                                              \
9150   "<intfc> | sw_if_index <nn> new_show_dev_instance <nn>")              \
9151 _(want_l2_macs_events, "[disable] [learn-limit <n>] [scan-delay <n>] [max-entries <n>]") \
9152 _(ip_address_dump, "(ipv4 | ipv6) (<intfc> | sw_if_index <id>)")        \
9153 _(ip_dump, "ipv4 | ipv6")                                               \
9154 _(delete_loopback,"sw_if_index <nn>")                                   \
9155 _(bd_ip_mac_add_del, "bd_id <bridge-domain-id> <ip4/6-addr> <mac-addr> [del]") \
9156 _(bd_ip_mac_flush, "bd_id <bridge-domain-id>")                          \
9157 _(bd_ip_mac_dump, "[bd_id] <bridge-domain-id>")                         \
9158 _(want_interface_events,  "enable|disable")                             \
9159 _(get_first_msg_id, "client <name>")                                    \
9160 _(get_node_graph, " ")                                                  \
9161 _(sw_interface_clear_stats,"<intfc> | sw_if_index <nn>")                \
9162 _(ioam_enable, "[trace] [pow] [ppc <encap|decap>]")                     \
9163 _(ioam_disable, "")                                                     \
9164 _(mpls_tunnel_dump, "tunnel_index <tunnel-id>")                         \
9165 _(mpls_table_dump, "")                                                  \
9166 _(mpls_route_dump, "table-id <ID>")                                     \
9167 _(sw_interface_span_enable_disable, "[l2] [src <intfc> | src_sw_if_index <id>] [disable | [[dst <intfc> | dst_sw_if_index <id>] [both|rx|tx]]]") \
9168 _(sw_interface_span_dump, "[l2]")                                           \
9169 _(get_next_index, "node-name <node-name> next-node-name <node-name>")   \
9170 _(ip_source_and_port_range_check_add_del,                               \
9171   "<ip-addr>/<mask> range <nn>-<nn> vrf <id>")                          \
9172 _(ip_source_and_port_range_check_interface_add_del,                     \
9173   "<intf> | sw_if_index <nn> [tcp-out-vrf <id>] [tcp-in-vrf <id>]"      \
9174   "[udp-in-vrf <id>] [udp-out-vrf <id>]")                               \
9175 _(delete_subif,"<intfc> | sw_if_index <nn>")                            \
9176 _(l2_interface_pbb_tag_rewrite,                                         \
9177   "<intfc> | sw_if_index <nn> \n"                                       \
9178   "[disable | push | pop | translate_pbb_stag <outer_tag>] \n"          \
9179   "dmac <mac> smac <mac> sid <nn> [vlanid <nn>]")                       \
9180 _(ip_table_dump, "")                                                    \
9181 _(ip_route_dump, "table-id [ip4|ip6]")                                  \
9182 _(ip_mtable_dump, "")                                                   \
9183 _(ip_mroute_dump, "table-id [ip4|ip6]")                                 \
9184 _(sw_interface_tag_add_del, "<intfc> | sw_if_index <nn> tag <text>"     \
9185 "[disable]")                                                            \
9186 _(sw_interface_add_del_mac_address, "<intfc> | sw_if_index <nn> "       \
9187   "mac <mac-address> [del]")                                            \
9188 _(l2_xconnect_dump, "")                                                 \
9189 _(hw_interface_set_mtu, "<intfc> | hw_if_index <nn> mtu <nn>")        \
9190 _(sw_interface_get_table, "<intfc> | sw_if_index <id> [ipv6]")          \
9191 _(sock_init_shm, "size <nnn>")                                          \
9192 _(app_namespace_add_del, "[add] id <ns-id> secret <nn> sw_if_index <nn>")\
9193 _(session_rule_add_del, "[add|del] proto <tcp/udp> <lcl-ip>/<plen> "    \
9194   "<lcl-port> <rmt-ip>/<plen> <rmt-port> action <nn>")                  \
9195 _(session_rules_dump, "")                                               \
9196 _(ip_container_proxy_add_del, "[add|del] <address> <sw_if_index>")      \
9197
9198 /* List of command functions, CLI names map directly to functions */
9199 #define foreach_cli_function                                    \
9200 _(comment, "usage: comment <ignore-rest-of-line>")              \
9201 _(dump_interface_table, "usage: dump_interface_table")          \
9202 _(dump_sub_interface_table, "usage: dump_sub_interface_table")  \
9203 _(dump_ipv4_table, "usage: dump_ipv4_table")                    \
9204 _(dump_ipv6_table, "usage: dump_ipv6_table")                    \
9205 _(dump_macro_table, "usage: dump_macro_table ")                 \
9206 _(dump_node_table, "usage: dump_node_table")                    \
9207 _(dump_msg_api_table, "usage: dump_msg_api_table")              \
9208 _(elog_setup, "usage: elog_setup [nevents, default 128K]")      \
9209 _(elog_disable, "usage: elog_disable")                          \
9210 _(elog_enable, "usage: elog_enable")                            \
9211 _(elog_save, "usage: elog_save <filename>")                     \
9212 _(get_msg_id, "usage: get_msg_id name_and_crc")                 \
9213 _(echo, "usage: echo <message>")                                \
9214 _(exec, "usage: exec <vpe-debug-CLI-command>")                  \
9215 _(exec_inband, "usage: exec_inband <vpe-debug-CLI-command>")    \
9216 _(help, "usage: help")                                          \
9217 _(q, "usage: quit")                                             \
9218 _(quit, "usage: quit")                                          \
9219 _(search_node_table, "usage: search_node_table <name>...")      \
9220 _(set, "usage: set <variable-name> <value>")                    \
9221 _(script, "usage: script <file-name>")                          \
9222 _(statseg, "usage: statseg")                                    \
9223 _(unset, "usage: unset <variable-name>")
9224
9225 #define _(N,n)                                  \
9226     static void vl_api_##n##_t_handler_uni      \
9227     (vl_api_##n##_t * mp)                       \
9228     {                                           \
9229         vat_main_t * vam = &vat_main;           \
9230         if (vam->json_output) {                 \
9231             vl_api_##n##_t_handler_json(mp);    \
9232         } else {                                \
9233             vl_api_##n##_t_handler(mp);         \
9234         }                                       \
9235     }
9236 foreach_vpe_api_reply_msg;
9237 #if VPP_API_TEST_BUILTIN == 0
9238 foreach_standalone_reply_msg;
9239 #endif
9240 #undef _
9241
9242 void
9243 vat_api_hookup (vat_main_t * vam)
9244 {
9245 #define _(N,n)                                                  \
9246     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
9247                            vl_api_##n##_t_handler_uni,          \
9248                            vl_noop_handler,                     \
9249                            vl_api_##n##_t_endian,               \
9250                            vl_api_##n##_t_print,                \
9251                            sizeof(vl_api_##n##_t), 1);
9252   foreach_vpe_api_reply_msg;
9253 #if VPP_API_TEST_BUILTIN == 0
9254   foreach_standalone_reply_msg;
9255 #endif
9256 #undef _
9257
9258 #if (VPP_API_TEST_BUILTIN==0)
9259   vl_msg_api_set_first_available_msg_id (VL_MSG_FIRST_AVAILABLE);
9260
9261   vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
9262
9263   vam->function_by_name = hash_create_string (0, sizeof (uword));
9264
9265   vam->help_by_name = hash_create_string (0, sizeof (uword));
9266 #endif
9267
9268   /* API messages we can send */
9269 #define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
9270   foreach_vpe_api_msg;
9271 #undef _
9272
9273   /* Help strings */
9274 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
9275   foreach_vpe_api_msg;
9276 #undef _
9277
9278   /* CLI functions */
9279 #define _(n,h) hash_set_mem (vam->function_by_name, #n, n);
9280   foreach_cli_function;
9281 #undef _
9282
9283   /* Help strings */
9284 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
9285   foreach_cli_function;
9286 #undef _
9287 }
9288
9289 #if VPP_API_TEST_BUILTIN
9290 static clib_error_t *
9291 vat_api_hookup_shim (vlib_main_t * vm)
9292 {
9293   vat_api_hookup (&vat_main);
9294   return 0;
9295 }
9296
9297 VLIB_API_INIT_FUNCTION (vat_api_hookup_shim);
9298 #endif
9299
9300 /*
9301  * fd.io coding-style-patch-verification: ON
9302  *
9303  * Local Variables:
9304  * eval: (c-set-style "gnu")
9305  * End:
9306  */