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