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