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