ipsec: 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_af_packet_create_reply_t_handler
722   (vl_api_af_packet_create_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_af_packet_create_reply_t_handler_json
734   (vl_api_af_packet_create_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_vlan_subif_reply_t_handler
751   (vl_api_create_vlan_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_vlan_subif_reply_t_handler_json
763   (vl_api_create_vlan_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_create_subif_reply_t_handler
780   (vl_api_create_subif_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->sw_if_index = ntohl (mp->sw_if_index);
788   vam->result_ready = 1;
789 }
790
791 static void vl_api_create_subif_reply_t_handler_json
792   (vl_api_create_subif_reply_t * mp)
793 {
794   vat_main_t *vam = &vat_main;
795   vat_json_node_t node;
796
797   vat_json_init_object (&node);
798   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
799   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
800
801   vat_json_print (vam->ofp, &node);
802   vat_json_free (&node);
803
804   vam->retval = ntohl (mp->retval);
805   vam->result_ready = 1;
806 }
807
808 static void vl_api_interface_name_renumber_reply_t_handler
809   (vl_api_interface_name_renumber_reply_t * mp)
810 {
811   vat_main_t *vam = &vat_main;
812   i32 retval = ntohl (mp->retval);
813
814   vam->retval = retval;
815   vam->regenerate_interface_table = 1;
816   vam->result_ready = 1;
817 }
818
819 static void vl_api_interface_name_renumber_reply_t_handler_json
820   (vl_api_interface_name_renumber_reply_t * mp)
821 {
822   vat_main_t *vam = &vat_main;
823   vat_json_node_t node;
824
825   vat_json_init_object (&node);
826   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
827
828   vat_json_print (vam->ofp, &node);
829   vat_json_free (&node);
830
831   vam->retval = ntohl (mp->retval);
832   vam->result_ready = 1;
833 }
834
835 /*
836  * Special-case: build the interface table, maintain
837  * the next loopback sw_if_index vbl.
838  */
839 static void vl_api_sw_interface_details_t_handler
840   (vl_api_sw_interface_details_t * mp)
841 {
842   vat_main_t *vam = &vat_main;
843   u8 *s = format (0, "%s%c", mp->interface_name, 0);
844
845   hash_set_mem (vam->sw_if_index_by_interface_name, s,
846                 ntohl (mp->sw_if_index));
847
848   /* In sub interface case, fill the sub interface table entry */
849   if (mp->sw_if_index != mp->sup_sw_if_index)
850     {
851       sw_interface_subif_t *sub = NULL;
852
853       vec_add2 (vam->sw_if_subif_table, sub, 1);
854
855       vec_validate (sub->interface_name, strlen ((char *) s) + 1);
856       strncpy ((char *) sub->interface_name, (char *) s,
857                vec_len (sub->interface_name));
858       sub->sw_if_index = ntohl (mp->sw_if_index);
859       sub->sub_id = ntohl (mp->sub_id);
860
861       sub->raw_flags = ntohl (mp->sub_if_flags & SUB_IF_API_FLAG_MASK_VNET);
862
863       sub->sub_number_of_tags = mp->sub_number_of_tags;
864       sub->sub_outer_vlan_id = ntohs (mp->sub_outer_vlan_id);
865       sub->sub_inner_vlan_id = ntohs (mp->sub_inner_vlan_id);
866
867       /* vlan tag rewrite */
868       sub->vtr_op = ntohl (mp->vtr_op);
869       sub->vtr_push_dot1q = ntohl (mp->vtr_push_dot1q);
870       sub->vtr_tag1 = ntohl (mp->vtr_tag1);
871       sub->vtr_tag2 = ntohl (mp->vtr_tag2);
872     }
873 }
874
875 static void vl_api_sw_interface_details_t_handler_json
876   (vl_api_sw_interface_details_t * mp)
877 {
878   vat_main_t *vam = &vat_main;
879   vat_json_node_t *node = NULL;
880
881   if (VAT_JSON_ARRAY != vam->json_tree.type)
882     {
883       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
884       vat_json_init_array (&vam->json_tree);
885     }
886   node = vat_json_array_add (&vam->json_tree);
887
888   vat_json_init_object (node);
889   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
890   vat_json_object_add_uint (node, "sup_sw_if_index",
891                             ntohl (mp->sup_sw_if_index));
892   vat_json_object_add_bytes (node, "l2_address", mp->l2_address,
893                              sizeof (mp->l2_address));
894   vat_json_object_add_string_copy (node, "interface_name",
895                                    mp->interface_name);
896   vat_json_object_add_string_copy (node, "interface_dev_type",
897                                    mp->interface_dev_type);
898   vat_json_object_add_uint (node, "flags", mp->flags);
899   vat_json_object_add_uint (node, "link_duplex", mp->link_duplex);
900   vat_json_object_add_uint (node, "link_speed", mp->link_speed);
901   vat_json_object_add_uint (node, "mtu", ntohs (mp->link_mtu));
902   vat_json_object_add_uint (node, "sub_id", ntohl (mp->sub_id));
903   vat_json_object_add_uint (node, "sub_number_of_tags",
904                             mp->sub_number_of_tags);
905   vat_json_object_add_uint (node, "sub_outer_vlan_id",
906                             ntohs (mp->sub_outer_vlan_id));
907   vat_json_object_add_uint (node, "sub_inner_vlan_id",
908                             ntohs (mp->sub_inner_vlan_id));
909   vat_json_object_add_uint (node, "sub_if_flags", ntohl (mp->sub_if_flags));
910   vat_json_object_add_uint (node, "vtr_op", ntohl (mp->vtr_op));
911   vat_json_object_add_uint (node, "vtr_push_dot1q",
912                             ntohl (mp->vtr_push_dot1q));
913   vat_json_object_add_uint (node, "vtr_tag1", ntohl (mp->vtr_tag1));
914   vat_json_object_add_uint (node, "vtr_tag2", ntohl (mp->vtr_tag2));
915   if (ntohl (mp->sub_if_flags) & SUB_IF_API_FLAG_DOT1AH)
916     {
917       vat_json_object_add_string_copy (node, "pbb_vtr_dmac",
918                                        format (0, "%U",
919                                                format_ethernet_address,
920                                                &mp->b_dmac));
921       vat_json_object_add_string_copy (node, "pbb_vtr_smac",
922                                        format (0, "%U",
923                                                format_ethernet_address,
924                                                &mp->b_smac));
925       vat_json_object_add_uint (node, "pbb_vtr_b_vlanid", mp->b_vlanid);
926       vat_json_object_add_uint (node, "pbb_vtr_i_sid", mp->i_sid);
927     }
928 }
929
930 #if VPP_API_TEST_BUILTIN == 0
931 static void vl_api_sw_interface_event_t_handler
932   (vl_api_sw_interface_event_t * mp)
933 {
934   vat_main_t *vam = &vat_main;
935   if (vam->interface_event_display)
936     errmsg ("interface flags: sw_if_index %d %s %s",
937             ntohl (mp->sw_if_index),
938             ((ntohl (mp->flags)) & IF_STATUS_API_FLAG_ADMIN_UP) ?
939             "admin-up" : "admin-down",
940             ((ntohl (mp->flags)) & IF_STATUS_API_FLAG_LINK_UP) ?
941             "link-up" : "link-down");
942 }
943 #endif
944
945 __clib_unused static void
946 vl_api_sw_interface_event_t_handler_json (vl_api_sw_interface_event_t * mp)
947 {
948   /* JSON output not supported */
949 }
950
951 static void
952 vl_api_cli_reply_t_handler (vl_api_cli_reply_t * mp)
953 {
954   vat_main_t *vam = &vat_main;
955   i32 retval = ntohl (mp->retval);
956
957   vam->retval = retval;
958   vam->shmem_result = uword_to_pointer (mp->reply_in_shmem, u8 *);
959   vam->result_ready = 1;
960 }
961
962 static void
963 vl_api_cli_reply_t_handler_json (vl_api_cli_reply_t * mp)
964 {
965   vat_main_t *vam = &vat_main;
966   vat_json_node_t node;
967   void *oldheap;
968   u8 *reply;
969
970   vat_json_init_object (&node);
971   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
972   vat_json_object_add_uint (&node, "reply_in_shmem",
973                             ntohl (mp->reply_in_shmem));
974   /* Toss the shared-memory original... */
975   oldheap = vl_msg_push_heap ();
976
977   reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
978   vec_free (reply);
979
980   vl_msg_pop_heap (oldheap);
981
982   vat_json_print (vam->ofp, &node);
983   vat_json_free (&node);
984
985   vam->retval = ntohl (mp->retval);
986   vam->result_ready = 1;
987 }
988
989 static void
990 vl_api_cli_inband_reply_t_handler (vl_api_cli_inband_reply_t * mp)
991 {
992   vat_main_t *vam = &vat_main;
993   i32 retval = ntohl (mp->retval);
994
995   vec_reset_length (vam->cmd_reply);
996
997   vam->retval = retval;
998   if (retval == 0)
999     vam->cmd_reply = vl_api_from_api_to_new_vec (mp, &mp->reply);
1000   vam->result_ready = 1;
1001 }
1002
1003 static void
1004 vl_api_cli_inband_reply_t_handler_json (vl_api_cli_inband_reply_t * mp)
1005 {
1006   vat_main_t *vam = &vat_main;
1007   vat_json_node_t node;
1008   u8 *reply = 0;                /* reply vector */
1009
1010   reply = vl_api_from_api_to_new_vec (mp, &mp->reply);
1011   vec_reset_length (vam->cmd_reply);
1012
1013   vat_json_init_object (&node);
1014   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1015   vat_json_object_add_string_copy (&node, "reply", reply);
1016
1017   vat_json_print (vam->ofp, &node);
1018   vat_json_free (&node);
1019   vec_free (reply);
1020
1021   vam->retval = ntohl (mp->retval);
1022   vam->result_ready = 1;
1023 }
1024
1025 static void vl_api_get_node_index_reply_t_handler
1026   (vl_api_get_node_index_reply_t * mp)
1027 {
1028   vat_main_t *vam = &vat_main;
1029   i32 retval = ntohl (mp->retval);
1030   if (vam->async_mode)
1031     {
1032       vam->async_errors += (retval < 0);
1033     }
1034   else
1035     {
1036       vam->retval = retval;
1037       if (retval == 0)
1038         errmsg ("node index %d", ntohl (mp->node_index));
1039       vam->result_ready = 1;
1040     }
1041 }
1042
1043 static void vl_api_get_node_index_reply_t_handler_json
1044   (vl_api_get_node_index_reply_t * mp)
1045 {
1046   vat_main_t *vam = &vat_main;
1047   vat_json_node_t node;
1048
1049   vat_json_init_object (&node);
1050   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1051   vat_json_object_add_uint (&node, "node_index", ntohl (mp->node_index));
1052
1053   vat_json_print (vam->ofp, &node);
1054   vat_json_free (&node);
1055
1056   vam->retval = ntohl (mp->retval);
1057   vam->result_ready = 1;
1058 }
1059
1060 static void vl_api_get_next_index_reply_t_handler
1061   (vl_api_get_next_index_reply_t * mp)
1062 {
1063   vat_main_t *vam = &vat_main;
1064   i32 retval = ntohl (mp->retval);
1065   if (vam->async_mode)
1066     {
1067       vam->async_errors += (retval < 0);
1068     }
1069   else
1070     {
1071       vam->retval = retval;
1072       if (retval == 0)
1073         errmsg ("next node index %d", ntohl (mp->next_index));
1074       vam->result_ready = 1;
1075     }
1076 }
1077
1078 static void vl_api_get_next_index_reply_t_handler_json
1079   (vl_api_get_next_index_reply_t * mp)
1080 {
1081   vat_main_t *vam = &vat_main;
1082   vat_json_node_t node;
1083
1084   vat_json_init_object (&node);
1085   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1086   vat_json_object_add_uint (&node, "next_index", ntohl (mp->next_index));
1087
1088   vat_json_print (vam->ofp, &node);
1089   vat_json_free (&node);
1090
1091   vam->retval = ntohl (mp->retval);
1092   vam->result_ready = 1;
1093 }
1094
1095 static void vl_api_add_node_next_reply_t_handler
1096   (vl_api_add_node_next_reply_t * mp)
1097 {
1098   vat_main_t *vam = &vat_main;
1099   i32 retval = ntohl (mp->retval);
1100   if (vam->async_mode)
1101     {
1102       vam->async_errors += (retval < 0);
1103     }
1104   else
1105     {
1106       vam->retval = retval;
1107       if (retval == 0)
1108         errmsg ("next index %d", ntohl (mp->next_index));
1109       vam->result_ready = 1;
1110     }
1111 }
1112
1113 static void vl_api_add_node_next_reply_t_handler_json
1114   (vl_api_add_node_next_reply_t * mp)
1115 {
1116   vat_main_t *vam = &vat_main;
1117   vat_json_node_t node;
1118
1119   vat_json_init_object (&node);
1120   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1121   vat_json_object_add_uint (&node, "next_index", ntohl (mp->next_index));
1122
1123   vat_json_print (vam->ofp, &node);
1124   vat_json_free (&node);
1125
1126   vam->retval = ntohl (mp->retval);
1127   vam->result_ready = 1;
1128 }
1129
1130 static void vl_api_show_version_reply_t_handler
1131   (vl_api_show_version_reply_t * mp)
1132 {
1133   vat_main_t *vam = &vat_main;
1134   i32 retval = ntohl (mp->retval);
1135
1136   if (retval >= 0)
1137     {
1138       errmsg ("        program: %s", mp->program);
1139       errmsg ("        version: %s", mp->version);
1140       errmsg ("     build date: %s", mp->build_date);
1141       errmsg ("build directory: %s", mp->build_directory);
1142     }
1143   vam->retval = retval;
1144   vam->result_ready = 1;
1145 }
1146
1147 static void vl_api_show_version_reply_t_handler_json
1148   (vl_api_show_version_reply_t * mp)
1149 {
1150   vat_main_t *vam = &vat_main;
1151   vat_json_node_t node;
1152
1153   vat_json_init_object (&node);
1154   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1155   vat_json_object_add_string_copy (&node, "program", mp->program);
1156   vat_json_object_add_string_copy (&node, "version", mp->version);
1157   vat_json_object_add_string_copy (&node, "build_date", mp->build_date);
1158   vat_json_object_add_string_copy (&node, "build_directory",
1159                                    mp->build_directory);
1160
1161   vat_json_print (vam->ofp, &node);
1162   vat_json_free (&node);
1163
1164   vam->retval = ntohl (mp->retval);
1165   vam->result_ready = 1;
1166 }
1167
1168 static void vl_api_show_threads_reply_t_handler
1169   (vl_api_show_threads_reply_t * mp)
1170 {
1171   vat_main_t *vam = &vat_main;
1172   i32 retval = ntohl (mp->retval);
1173   int i, count = 0;
1174
1175   if (retval >= 0)
1176     count = ntohl (mp->count);
1177
1178   for (i = 0; i < count; i++)
1179     print (vam->ofp,
1180            "\n%-2d %-11s %-11s %-5d %-6d %-4d %-6d",
1181            ntohl (mp->thread_data[i].id), mp->thread_data[i].name,
1182            mp->thread_data[i].type, ntohl (mp->thread_data[i].pid),
1183            ntohl (mp->thread_data[i].cpu_id), ntohl (mp->thread_data[i].core),
1184            ntohl (mp->thread_data[i].cpu_socket));
1185
1186   vam->retval = retval;
1187   vam->result_ready = 1;
1188 }
1189
1190 static void vl_api_show_threads_reply_t_handler_json
1191   (vl_api_show_threads_reply_t * mp)
1192 {
1193   vat_main_t *vam = &vat_main;
1194   vat_json_node_t node;
1195   vl_api_thread_data_t *td;
1196   i32 retval = ntohl (mp->retval);
1197   int i, count = 0;
1198
1199   if (retval >= 0)
1200     count = ntohl (mp->count);
1201
1202   vat_json_init_object (&node);
1203   vat_json_object_add_int (&node, "retval", retval);
1204   vat_json_object_add_uint (&node, "count", count);
1205
1206   for (i = 0; i < count; i++)
1207     {
1208       td = &mp->thread_data[i];
1209       vat_json_object_add_uint (&node, "id", ntohl (td->id));
1210       vat_json_object_add_string_copy (&node, "name", td->name);
1211       vat_json_object_add_string_copy (&node, "type", td->type);
1212       vat_json_object_add_uint (&node, "pid", ntohl (td->pid));
1213       vat_json_object_add_int (&node, "cpu_id", ntohl (td->cpu_id));
1214       vat_json_object_add_int (&node, "core", ntohl (td->id));
1215       vat_json_object_add_int (&node, "cpu_socket", ntohl (td->cpu_socket));
1216     }
1217
1218   vat_json_print (vam->ofp, &node);
1219   vat_json_free (&node);
1220
1221   vam->retval = retval;
1222   vam->result_ready = 1;
1223 }
1224
1225 static int
1226 api_show_threads (vat_main_t * vam)
1227 {
1228   vl_api_show_threads_t *mp;
1229   int ret;
1230
1231   print (vam->ofp,
1232          "\n%-2s %-11s %-11s %-5s %-6s %-4s %-6s",
1233          "ID", "Name", "Type", "LWP", "cpu_id", "Core", "Socket");
1234
1235   M (SHOW_THREADS, mp);
1236
1237   S (mp);
1238   W (ret);
1239   return ret;
1240 }
1241
1242 static void
1243 vl_api_l2_macs_event_t_handler (vl_api_l2_macs_event_t * mp)
1244 {
1245   u32 n_macs = ntohl (mp->n_macs);
1246   errmsg ("L2MAC event received with pid %d cl-idx %d for %d macs: \n",
1247           ntohl (mp->pid), mp->client_index, n_macs);
1248   int i;
1249   for (i = 0; i < n_macs; i++)
1250     {
1251       vl_api_mac_entry_t *mac = &mp->mac[i];
1252       errmsg (" [%d] sw_if_index %d  mac_addr %U  action %d \n",
1253               i + 1, ntohl (mac->sw_if_index),
1254               format_ethernet_address, mac->mac_addr, mac->action);
1255       if (i == 1000)
1256         break;
1257     }
1258 }
1259
1260 static void
1261 vl_api_l2_macs_event_t_handler_json (vl_api_l2_macs_event_t * mp)
1262 {
1263   /* JSON output not supported */
1264 }
1265
1266 #define vl_api_bridge_domain_details_t_endian vl_noop_handler
1267 #define vl_api_bridge_domain_details_t_print vl_noop_handler
1268
1269 /*
1270  * Special-case: build the bridge domain table, maintain
1271  * the next bd id vbl.
1272  */
1273 static void vl_api_bridge_domain_details_t_handler
1274   (vl_api_bridge_domain_details_t * mp)
1275 {
1276   vat_main_t *vam = &vat_main;
1277   u32 n_sw_ifs = ntohl (mp->n_sw_ifs);
1278   int i;
1279
1280   print (vam->ofp, "\n%-3s %-3s %-3s %-3s %-3s %-6s %-3s",
1281          " ID", "LRN", "FWD", "FLD", "BVI", "UU-FWD", "#IF");
1282
1283   print (vam->ofp, "%3d %3d %3d %3d %3d %6d %3d",
1284          ntohl (mp->bd_id), mp->learn, mp->forward,
1285          mp->flood, ntohl (mp->bvi_sw_if_index),
1286          ntohl (mp->uu_fwd_sw_if_index), n_sw_ifs);
1287
1288   if (n_sw_ifs)
1289     {
1290       vl_api_bridge_domain_sw_if_t *sw_ifs;
1291       print (vam->ofp, "\n\n%s %s  %s", "sw_if_index", "SHG",
1292              "Interface Name");
1293
1294       sw_ifs = mp->sw_if_details;
1295       for (i = 0; i < n_sw_ifs; i++)
1296         {
1297           u8 *sw_if_name = 0;
1298           u32 sw_if_index;
1299           hash_pair_t *p;
1300
1301           sw_if_index = ntohl (sw_ifs->sw_if_index);
1302
1303           /* *INDENT-OFF* */
1304           hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
1305                              ({
1306                                if ((u32) p->value[0] == sw_if_index)
1307                                  {
1308                                    sw_if_name = (u8 *)(p->key);
1309                                    break;
1310                                  }
1311                              }));
1312           /* *INDENT-ON* */
1313           print (vam->ofp, "%7d     %3d  %s", sw_if_index,
1314                  sw_ifs->shg, sw_if_name ? (char *) sw_if_name :
1315                  "sw_if_index not found!");
1316
1317           sw_ifs++;
1318         }
1319     }
1320 }
1321
1322 static void vl_api_bridge_domain_details_t_handler_json
1323   (vl_api_bridge_domain_details_t * mp)
1324 {
1325   vat_main_t *vam = &vat_main;
1326   vat_json_node_t *node, *array = NULL;
1327   u32 n_sw_ifs = ntohl (mp->n_sw_ifs);
1328
1329   if (VAT_JSON_ARRAY != vam->json_tree.type)
1330     {
1331       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
1332       vat_json_init_array (&vam->json_tree);
1333     }
1334   node = vat_json_array_add (&vam->json_tree);
1335
1336   vat_json_init_object (node);
1337   vat_json_object_add_uint (node, "bd_id", ntohl (mp->bd_id));
1338   vat_json_object_add_uint (node, "flood", mp->flood);
1339   vat_json_object_add_uint (node, "forward", mp->forward);
1340   vat_json_object_add_uint (node, "learn", mp->learn);
1341   vat_json_object_add_uint (node, "bvi_sw_if_index",
1342                             ntohl (mp->bvi_sw_if_index));
1343   vat_json_object_add_uint (node, "n_sw_ifs", n_sw_ifs);
1344   array = vat_json_object_add (node, "sw_if");
1345   vat_json_init_array (array);
1346
1347
1348
1349   if (n_sw_ifs)
1350     {
1351       vl_api_bridge_domain_sw_if_t *sw_ifs;
1352       int i;
1353
1354       sw_ifs = mp->sw_if_details;
1355       for (i = 0; i < n_sw_ifs; i++)
1356         {
1357           node = vat_json_array_add (array);
1358           vat_json_init_object (node);
1359           vat_json_object_add_uint (node, "sw_if_index",
1360                                     ntohl (sw_ifs->sw_if_index));
1361           vat_json_object_add_uint (node, "shg", sw_ifs->shg);
1362           sw_ifs++;
1363         }
1364     }
1365 }
1366
1367 static void vl_api_control_ping_reply_t_handler
1368   (vl_api_control_ping_reply_t * mp)
1369 {
1370   vat_main_t *vam = &vat_main;
1371   i32 retval = ntohl (mp->retval);
1372   if (vam->async_mode)
1373     {
1374       vam->async_errors += (retval < 0);
1375     }
1376   else
1377     {
1378       vam->retval = retval;
1379       vam->result_ready = 1;
1380     }
1381   if (vam->socket_client_main)
1382     vam->socket_client_main->control_pings_outstanding--;
1383 }
1384
1385 static void vl_api_control_ping_reply_t_handler_json
1386   (vl_api_control_ping_reply_t * mp)
1387 {
1388   vat_main_t *vam = &vat_main;
1389   i32 retval = ntohl (mp->retval);
1390
1391   if (VAT_JSON_NONE != vam->json_tree.type)
1392     {
1393       vat_json_print (vam->ofp, &vam->json_tree);
1394       vat_json_free (&vam->json_tree);
1395       vam->json_tree.type = VAT_JSON_NONE;
1396     }
1397   else
1398     {
1399       /* just print [] */
1400       vat_json_init_array (&vam->json_tree);
1401       vat_json_print (vam->ofp, &vam->json_tree);
1402       vam->json_tree.type = VAT_JSON_NONE;
1403     }
1404
1405   vam->retval = retval;
1406   vam->result_ready = 1;
1407 }
1408
1409 static void
1410   vl_api_bridge_domain_set_mac_age_reply_t_handler
1411   (vl_api_bridge_domain_set_mac_age_reply_t * mp)
1412 {
1413   vat_main_t *vam = &vat_main;
1414   i32 retval = ntohl (mp->retval);
1415   if (vam->async_mode)
1416     {
1417       vam->async_errors += (retval < 0);
1418     }
1419   else
1420     {
1421       vam->retval = retval;
1422       vam->result_ready = 1;
1423     }
1424 }
1425
1426 static void vl_api_bridge_domain_set_mac_age_reply_t_handler_json
1427   (vl_api_bridge_domain_set_mac_age_reply_t * mp)
1428 {
1429   vat_main_t *vam = &vat_main;
1430   vat_json_node_t node;
1431
1432   vat_json_init_object (&node);
1433   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1434
1435   vat_json_print (vam->ofp, &node);
1436   vat_json_free (&node);
1437
1438   vam->retval = ntohl (mp->retval);
1439   vam->result_ready = 1;
1440 }
1441
1442 static void
1443 vl_api_l2_flags_reply_t_handler (vl_api_l2_flags_reply_t * mp)
1444 {
1445   vat_main_t *vam = &vat_main;
1446   i32 retval = ntohl (mp->retval);
1447   if (vam->async_mode)
1448     {
1449       vam->async_errors += (retval < 0);
1450     }
1451   else
1452     {
1453       vam->retval = retval;
1454       vam->result_ready = 1;
1455     }
1456 }
1457
1458 static void vl_api_l2_flags_reply_t_handler_json
1459   (vl_api_l2_flags_reply_t * mp)
1460 {
1461   vat_main_t *vam = &vat_main;
1462   vat_json_node_t node;
1463
1464   vat_json_init_object (&node);
1465   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1466   vat_json_object_add_uint (&node, "resulting_feature_bitmap",
1467                             ntohl (mp->resulting_feature_bitmap));
1468
1469   vat_json_print (vam->ofp, &node);
1470   vat_json_free (&node);
1471
1472   vam->retval = ntohl (mp->retval);
1473   vam->result_ready = 1;
1474 }
1475
1476 static void vl_api_bridge_flags_reply_t_handler
1477   (vl_api_bridge_flags_reply_t * mp)
1478 {
1479   vat_main_t *vam = &vat_main;
1480   i32 retval = ntohl (mp->retval);
1481   if (vam->async_mode)
1482     {
1483       vam->async_errors += (retval < 0);
1484     }
1485   else
1486     {
1487       vam->retval = retval;
1488       vam->result_ready = 1;
1489     }
1490 }
1491
1492 static void vl_api_bridge_flags_reply_t_handler_json
1493   (vl_api_bridge_flags_reply_t * mp)
1494 {
1495   vat_main_t *vam = &vat_main;
1496   vat_json_node_t node;
1497
1498   vat_json_init_object (&node);
1499   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1500   vat_json_object_add_uint (&node, "resulting_feature_bitmap",
1501                             ntohl (mp->resulting_feature_bitmap));
1502
1503   vat_json_print (vam->ofp, &node);
1504   vat_json_free (&node);
1505
1506   vam->retval = ntohl (mp->retval);
1507   vam->result_ready = 1;
1508 }
1509
1510 static void
1511 vl_api_tap_create_v2_reply_t_handler (vl_api_tap_create_v2_reply_t * mp)
1512 {
1513   vat_main_t *vam = &vat_main;
1514   i32 retval = ntohl (mp->retval);
1515   if (vam->async_mode)
1516     {
1517       vam->async_errors += (retval < 0);
1518     }
1519   else
1520     {
1521       vam->retval = retval;
1522       vam->sw_if_index = ntohl (mp->sw_if_index);
1523       vam->result_ready = 1;
1524     }
1525
1526 }
1527
1528 static void vl_api_tap_create_v2_reply_t_handler_json
1529   (vl_api_tap_create_v2_reply_t * mp)
1530 {
1531   vat_main_t *vam = &vat_main;
1532   vat_json_node_t node;
1533
1534   vat_json_init_object (&node);
1535   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1536   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1537
1538   vat_json_print (vam->ofp, &node);
1539   vat_json_free (&node);
1540
1541   vam->retval = ntohl (mp->retval);
1542   vam->result_ready = 1;
1543
1544 }
1545
1546 static void
1547 vl_api_tap_delete_v2_reply_t_handler (vl_api_tap_delete_v2_reply_t * mp)
1548 {
1549   vat_main_t *vam = &vat_main;
1550   i32 retval = ntohl (mp->retval);
1551   if (vam->async_mode)
1552     {
1553       vam->async_errors += (retval < 0);
1554     }
1555   else
1556     {
1557       vam->retval = retval;
1558       vam->result_ready = 1;
1559     }
1560 }
1561
1562 static void vl_api_tap_delete_v2_reply_t_handler_json
1563   (vl_api_tap_delete_v2_reply_t * mp)
1564 {
1565   vat_main_t *vam = &vat_main;
1566   vat_json_node_t node;
1567
1568   vat_json_init_object (&node);
1569   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1570
1571   vat_json_print (vam->ofp, &node);
1572   vat_json_free (&node);
1573
1574   vam->retval = ntohl (mp->retval);
1575   vam->result_ready = 1;
1576 }
1577
1578 static void
1579 vl_api_virtio_pci_create_reply_t_handler (vl_api_virtio_pci_create_reply_t *
1580                                           mp)
1581 {
1582   vat_main_t *vam = &vat_main;
1583   i32 retval = ntohl (mp->retval);
1584   if (vam->async_mode)
1585     {
1586       vam->async_errors += (retval < 0);
1587     }
1588   else
1589     {
1590       vam->retval = retval;
1591       vam->sw_if_index = ntohl (mp->sw_if_index);
1592       vam->result_ready = 1;
1593     }
1594 }
1595
1596 static void vl_api_virtio_pci_create_reply_t_handler_json
1597   (vl_api_virtio_pci_create_reply_t * mp)
1598 {
1599   vat_main_t *vam = &vat_main;
1600   vat_json_node_t node;
1601
1602   vat_json_init_object (&node);
1603   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1604   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1605
1606   vat_json_print (vam->ofp, &node);
1607   vat_json_free (&node);
1608
1609   vam->retval = ntohl (mp->retval);
1610   vam->result_ready = 1;
1611
1612 }
1613
1614 static void
1615   vl_api_virtio_pci_create_v2_reply_t_handler
1616   (vl_api_virtio_pci_create_v2_reply_t * mp)
1617 {
1618   vat_main_t *vam = &vat_main;
1619   i32 retval = ntohl (mp->retval);
1620   if (vam->async_mode)
1621     {
1622       vam->async_errors += (retval < 0);
1623     }
1624   else
1625     {
1626       vam->retval = retval;
1627       vam->sw_if_index = ntohl (mp->sw_if_index);
1628       vam->result_ready = 1;
1629     }
1630 }
1631
1632 static void vl_api_virtio_pci_create_v2_reply_t_handler_json
1633   (vl_api_virtio_pci_create_v2_reply_t * mp)
1634 {
1635   vat_main_t *vam = &vat_main;
1636   vat_json_node_t node;
1637
1638   vat_json_init_object (&node);
1639   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1640   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1641
1642   vat_json_print (vam->ofp, &node);
1643   vat_json_free (&node);
1644
1645   vam->retval = ntohl (mp->retval);
1646   vam->result_ready = 1;
1647 }
1648
1649 static void
1650 vl_api_virtio_pci_delete_reply_t_handler (vl_api_virtio_pci_delete_reply_t *
1651                                           mp)
1652 {
1653   vat_main_t *vam = &vat_main;
1654   i32 retval = ntohl (mp->retval);
1655   if (vam->async_mode)
1656     {
1657       vam->async_errors += (retval < 0);
1658     }
1659   else
1660     {
1661       vam->retval = retval;
1662       vam->result_ready = 1;
1663     }
1664 }
1665
1666 static void vl_api_virtio_pci_delete_reply_t_handler_json
1667   (vl_api_virtio_pci_delete_reply_t * mp)
1668 {
1669   vat_main_t *vam = &vat_main;
1670   vat_json_node_t node;
1671
1672   vat_json_init_object (&node);
1673   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1674
1675   vat_json_print (vam->ofp, &node);
1676   vat_json_free (&node);
1677
1678   vam->retval = ntohl (mp->retval);
1679   vam->result_ready = 1;
1680 }
1681
1682 static void
1683 vl_api_bond_create_reply_t_handler (vl_api_bond_create_reply_t * mp)
1684 {
1685   vat_main_t *vam = &vat_main;
1686   i32 retval = ntohl (mp->retval);
1687
1688   if (vam->async_mode)
1689     {
1690       vam->async_errors += (retval < 0);
1691     }
1692   else
1693     {
1694       vam->retval = retval;
1695       vam->sw_if_index = ntohl (mp->sw_if_index);
1696       vam->result_ready = 1;
1697     }
1698 }
1699
1700 static void vl_api_bond_create_reply_t_handler_json
1701   (vl_api_bond_create_reply_t * mp)
1702 {
1703   vat_main_t *vam = &vat_main;
1704   vat_json_node_t node;
1705
1706   vat_json_init_object (&node);
1707   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1708   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1709
1710   vat_json_print (vam->ofp, &node);
1711   vat_json_free (&node);
1712
1713   vam->retval = ntohl (mp->retval);
1714   vam->result_ready = 1;
1715 }
1716
1717 static void
1718 vl_api_bond_create2_reply_t_handler (vl_api_bond_create2_reply_t * mp)
1719 {
1720   vat_main_t *vam = &vat_main;
1721   i32 retval = ntohl (mp->retval);
1722
1723   if (vam->async_mode)
1724     {
1725       vam->async_errors += (retval < 0);
1726     }
1727   else
1728     {
1729       vam->retval = retval;
1730       vam->sw_if_index = ntohl (mp->sw_if_index);
1731       vam->result_ready = 1;
1732     }
1733 }
1734
1735 static void vl_api_bond_create2_reply_t_handler_json
1736   (vl_api_bond_create2_reply_t * mp)
1737 {
1738   vat_main_t *vam = &vat_main;
1739   vat_json_node_t node;
1740
1741   vat_json_init_object (&node);
1742   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1743   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1744
1745   vat_json_print (vam->ofp, &node);
1746   vat_json_free (&node);
1747
1748   vam->retval = ntohl (mp->retval);
1749   vam->result_ready = 1;
1750 }
1751
1752 static void
1753 vl_api_bond_delete_reply_t_handler (vl_api_bond_delete_reply_t * mp)
1754 {
1755   vat_main_t *vam = &vat_main;
1756   i32 retval = ntohl (mp->retval);
1757
1758   if (vam->async_mode)
1759     {
1760       vam->async_errors += (retval < 0);
1761     }
1762   else
1763     {
1764       vam->retval = retval;
1765       vam->result_ready = 1;
1766     }
1767 }
1768
1769 static void vl_api_bond_delete_reply_t_handler_json
1770   (vl_api_bond_delete_reply_t * mp)
1771 {
1772   vat_main_t *vam = &vat_main;
1773   vat_json_node_t node;
1774
1775   vat_json_init_object (&node);
1776   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1777
1778   vat_json_print (vam->ofp, &node);
1779   vat_json_free (&node);
1780
1781   vam->retval = ntohl (mp->retval);
1782   vam->result_ready = 1;
1783 }
1784
1785 static void
1786 vl_api_bond_add_member_reply_t_handler (vl_api_bond_add_member_reply_t * mp)
1787 {
1788   vat_main_t *vam = &vat_main;
1789   i32 retval = ntohl (mp->retval);
1790
1791   if (vam->async_mode)
1792     {
1793       vam->async_errors += (retval < 0);
1794     }
1795   else
1796     {
1797       vam->retval = retval;
1798       vam->result_ready = 1;
1799     }
1800 }
1801
1802 static void vl_api_bond_add_member_reply_t_handler_json
1803   (vl_api_bond_add_member_reply_t * mp)
1804 {
1805   vat_main_t *vam = &vat_main;
1806   vat_json_node_t node;
1807
1808   vat_json_init_object (&node);
1809   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1810
1811   vat_json_print (vam->ofp, &node);
1812   vat_json_free (&node);
1813
1814   vam->retval = ntohl (mp->retval);
1815   vam->result_ready = 1;
1816 }
1817
1818 static void
1819 vl_api_bond_detach_member_reply_t_handler (vl_api_bond_detach_member_reply_t *
1820                                            mp)
1821 {
1822   vat_main_t *vam = &vat_main;
1823   i32 retval = ntohl (mp->retval);
1824
1825   if (vam->async_mode)
1826     {
1827       vam->async_errors += (retval < 0);
1828     }
1829   else
1830     {
1831       vam->retval = retval;
1832       vam->result_ready = 1;
1833     }
1834 }
1835
1836 static void vl_api_bond_detach_member_reply_t_handler_json
1837   (vl_api_bond_detach_member_reply_t * mp)
1838 {
1839   vat_main_t *vam = &vat_main;
1840   vat_json_node_t node;
1841
1842   vat_json_init_object (&node);
1843   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1844
1845   vat_json_print (vam->ofp, &node);
1846   vat_json_free (&node);
1847
1848   vam->retval = ntohl (mp->retval);
1849   vam->result_ready = 1;
1850 }
1851
1852 static int
1853 api_sw_interface_set_bond_weight (vat_main_t * vam)
1854 {
1855   unformat_input_t *i = vam->input;
1856   vl_api_sw_interface_set_bond_weight_t *mp;
1857   u32 sw_if_index = ~0;
1858   u32 weight = 0;
1859   u8 weight_enter = 0;
1860   int ret;
1861
1862   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1863     {
1864       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
1865         ;
1866       else if (unformat (i, "sw_if_index %d", &sw_if_index))
1867         ;
1868       else if (unformat (i, "weight %u", &weight))
1869         weight_enter = 1;
1870       else
1871         break;
1872     }
1873
1874   if (sw_if_index == ~0)
1875     {
1876       errmsg ("missing interface name or sw_if_index");
1877       return -99;
1878     }
1879   if (weight_enter == 0)
1880     {
1881       errmsg ("missing valid weight");
1882       return -99;
1883     }
1884
1885   /* Construct the API message */
1886   M (SW_INTERFACE_SET_BOND_WEIGHT, mp);
1887   mp->sw_if_index = ntohl (sw_if_index);
1888   mp->weight = ntohl (weight);
1889
1890   S (mp);
1891   W (ret);
1892   return ret;
1893 }
1894
1895 static void vl_api_sw_bond_interface_details_t_handler
1896   (vl_api_sw_bond_interface_details_t * mp)
1897 {
1898   vat_main_t *vam = &vat_main;
1899
1900   print (vam->ofp,
1901          "%-16s %-12d %-12U %-13U %-14u %-14u",
1902          mp->interface_name, ntohl (mp->sw_if_index),
1903          format_bond_mode, ntohl (mp->mode), format_bond_load_balance,
1904          ntohl (mp->lb), ntohl (mp->active_members), ntohl (mp->members));
1905 }
1906
1907 static void vl_api_sw_bond_interface_details_t_handler_json
1908   (vl_api_sw_bond_interface_details_t * mp)
1909 {
1910   vat_main_t *vam = &vat_main;
1911   vat_json_node_t *node = NULL;
1912
1913   if (VAT_JSON_ARRAY != vam->json_tree.type)
1914     {
1915       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
1916       vat_json_init_array (&vam->json_tree);
1917     }
1918   node = vat_json_array_add (&vam->json_tree);
1919
1920   vat_json_init_object (node);
1921   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
1922   vat_json_object_add_string_copy (node, "interface_name",
1923                                    mp->interface_name);
1924   vat_json_object_add_uint (node, "mode", ntohl (mp->mode));
1925   vat_json_object_add_uint (node, "load_balance", ntohl (mp->lb));
1926   vat_json_object_add_uint (node, "active_members",
1927                             ntohl (mp->active_members));
1928   vat_json_object_add_uint (node, "members", ntohl (mp->members));
1929 }
1930
1931 static int
1932 api_sw_bond_interface_dump (vat_main_t * vam)
1933 {
1934   unformat_input_t *i = vam->input;
1935   vl_api_sw_bond_interface_dump_t *mp;
1936   vl_api_control_ping_t *mp_ping;
1937   int ret;
1938   u32 sw_if_index = ~0;
1939
1940   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1941     {
1942       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
1943         ;
1944       else if (unformat (i, "sw_if_index %d", &sw_if_index))
1945         ;
1946       else
1947         break;
1948     }
1949
1950   print (vam->ofp,
1951          "\n%-16s %-12s %-12s %-13s %-14s %-14s",
1952          "interface name", "sw_if_index", "mode", "load balance",
1953          "active members", "members");
1954
1955   /* Get list of bond interfaces */
1956   M (SW_BOND_INTERFACE_DUMP, mp);
1957   mp->sw_if_index = ntohl (sw_if_index);
1958   S (mp);
1959
1960   /* Use a control ping for synchronization */
1961   MPING (CONTROL_PING, mp_ping);
1962   S (mp_ping);
1963
1964   W (ret);
1965   return ret;
1966 }
1967
1968 static void vl_api_sw_member_interface_details_t_handler
1969   (vl_api_sw_member_interface_details_t * mp)
1970 {
1971   vat_main_t *vam = &vat_main;
1972
1973   print (vam->ofp,
1974          "%-25s %-12d %-7d %-12d %-10d %-10d", mp->interface_name,
1975          ntohl (mp->sw_if_index), mp->is_passive, mp->is_long_timeout,
1976          ntohl (mp->weight), mp->is_local_numa);
1977 }
1978
1979 static void vl_api_sw_member_interface_details_t_handler_json
1980   (vl_api_sw_member_interface_details_t * mp)
1981 {
1982   vat_main_t *vam = &vat_main;
1983   vat_json_node_t *node = NULL;
1984
1985   if (VAT_JSON_ARRAY != vam->json_tree.type)
1986     {
1987       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
1988       vat_json_init_array (&vam->json_tree);
1989     }
1990   node = vat_json_array_add (&vam->json_tree);
1991
1992   vat_json_init_object (node);
1993   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
1994   vat_json_object_add_string_copy (node, "interface_name",
1995                                    mp->interface_name);
1996   vat_json_object_add_uint (node, "passive", mp->is_passive);
1997   vat_json_object_add_uint (node, "long_timeout", mp->is_long_timeout);
1998   vat_json_object_add_uint (node, "weight", ntohl (mp->weight));
1999   vat_json_object_add_uint (node, "is_local_numa", mp->is_local_numa);
2000 }
2001
2002 static int
2003 api_sw_member_interface_dump (vat_main_t * vam)
2004 {
2005   unformat_input_t *i = vam->input;
2006   vl_api_sw_member_interface_dump_t *mp;
2007   vl_api_control_ping_t *mp_ping;
2008   u32 sw_if_index = ~0;
2009   u8 sw_if_index_set = 0;
2010   int ret;
2011
2012   /* Parse args required to build the message */
2013   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2014     {
2015       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2016         sw_if_index_set = 1;
2017       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2018         sw_if_index_set = 1;
2019       else
2020         break;
2021     }
2022
2023   if (sw_if_index_set == 0)
2024     {
2025       errmsg ("missing vpp interface name. ");
2026       return -99;
2027     }
2028
2029   print (vam->ofp,
2030          "\n%-25s %-12s %-7s %-12s %-10s %-10s",
2031          "member interface name", "sw_if_index", "passive", "long_timeout",
2032          "weight", "local numa");
2033
2034   /* Get list of bond interfaces */
2035   M (SW_MEMBER_INTERFACE_DUMP, mp);
2036   mp->sw_if_index = ntohl (sw_if_index);
2037   S (mp);
2038
2039   /* Use a control ping for synchronization */
2040   MPING (CONTROL_PING, mp_ping);
2041   S (mp_ping);
2042
2043   W (ret);
2044   return ret;
2045 }
2046
2047 static void vl_api_mpls_tunnel_add_del_reply_t_handler
2048   (vl_api_mpls_tunnel_add_del_reply_t * mp)
2049 {
2050   vat_main_t *vam = &vat_main;
2051   i32 retval = ntohl (mp->retval);
2052   if (vam->async_mode)
2053     {
2054       vam->async_errors += (retval < 0);
2055     }
2056   else
2057     {
2058       vam->retval = retval;
2059       vam->sw_if_index = ntohl (mp->sw_if_index);
2060       vam->result_ready = 1;
2061     }
2062   vam->regenerate_interface_table = 1;
2063 }
2064
2065 static void vl_api_mpls_tunnel_add_del_reply_t_handler_json
2066   (vl_api_mpls_tunnel_add_del_reply_t * mp)
2067 {
2068   vat_main_t *vam = &vat_main;
2069   vat_json_node_t node;
2070
2071   vat_json_init_object (&node);
2072   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2073   vat_json_object_add_uint (&node, "tunnel_sw_if_index",
2074                             ntohl (mp->sw_if_index));
2075
2076   vat_json_print (vam->ofp, &node);
2077   vat_json_free (&node);
2078
2079   vam->retval = ntohl (mp->retval);
2080   vam->result_ready = 1;
2081 }
2082
2083 static void vl_api_create_vhost_user_if_reply_t_handler
2084   (vl_api_create_vhost_user_if_reply_t * mp)
2085 {
2086   vat_main_t *vam = &vat_main;
2087   i32 retval = ntohl (mp->retval);
2088   if (vam->async_mode)
2089     {
2090       vam->async_errors += (retval < 0);
2091     }
2092   else
2093     {
2094       vam->retval = retval;
2095       vam->sw_if_index = ntohl (mp->sw_if_index);
2096       vam->result_ready = 1;
2097     }
2098   vam->regenerate_interface_table = 1;
2099 }
2100
2101 static void vl_api_create_vhost_user_if_reply_t_handler_json
2102   (vl_api_create_vhost_user_if_reply_t * mp)
2103 {
2104   vat_main_t *vam = &vat_main;
2105   vat_json_node_t node;
2106
2107   vat_json_init_object (&node);
2108   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2109   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
2110
2111   vat_json_print (vam->ofp, &node);
2112   vat_json_free (&node);
2113
2114   vam->retval = ntohl (mp->retval);
2115   vam->result_ready = 1;
2116 }
2117
2118 static void vl_api_create_vhost_user_if_v2_reply_t_handler
2119   (vl_api_create_vhost_user_if_v2_reply_t * mp)
2120 {
2121   vat_main_t *vam = &vat_main;
2122   i32 retval = ntohl (mp->retval);
2123   if (vam->async_mode)
2124     {
2125       vam->async_errors += (retval < 0);
2126     }
2127   else
2128     {
2129       vam->retval = retval;
2130       vam->sw_if_index = ntohl (mp->sw_if_index);
2131       vam->result_ready = 1;
2132     }
2133   vam->regenerate_interface_table = 1;
2134 }
2135
2136 static void vl_api_create_vhost_user_if_v2_reply_t_handler_json
2137   (vl_api_create_vhost_user_if_v2_reply_t * mp)
2138 {
2139   vat_main_t *vam = &vat_main;
2140   vat_json_node_t node;
2141
2142   vat_json_init_object (&node);
2143   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2144   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
2145
2146   vat_json_print (vam->ofp, &node);
2147   vat_json_free (&node);
2148
2149   vam->retval = ntohl (mp->retval);
2150   vam->result_ready = 1;
2151 }
2152
2153 static void vl_api_ip_address_details_t_handler
2154   (vl_api_ip_address_details_t * mp)
2155 {
2156   vat_main_t *vam = &vat_main;
2157   static ip_address_details_t empty_ip_address_details = { {0} };
2158   ip_address_details_t *address = NULL;
2159   ip_details_t *current_ip_details = NULL;
2160   ip_details_t *details = NULL;
2161
2162   details = vam->ip_details_by_sw_if_index[vam->is_ipv6];
2163
2164   if (!details || vam->current_sw_if_index >= vec_len (details)
2165       || !details[vam->current_sw_if_index].present)
2166     {
2167       errmsg ("ip address details arrived but not stored");
2168       errmsg ("ip_dump should be called first");
2169       return;
2170     }
2171
2172   current_ip_details = vec_elt_at_index (details, vam->current_sw_if_index);
2173
2174 #define addresses (current_ip_details->addr)
2175
2176   vec_validate_init_empty (addresses, vec_len (addresses),
2177                            empty_ip_address_details);
2178
2179   address = vec_elt_at_index (addresses, vec_len (addresses) - 1);
2180
2181   clib_memcpy (&address->ip, &mp->prefix.address.un, sizeof (address->ip));
2182   address->prefix_length = mp->prefix.len;
2183 #undef addresses
2184 }
2185
2186 static void vl_api_ip_address_details_t_handler_json
2187   (vl_api_ip_address_details_t * mp)
2188 {
2189   vat_main_t *vam = &vat_main;
2190   vat_json_node_t *node = NULL;
2191
2192   if (VAT_JSON_ARRAY != vam->json_tree.type)
2193     {
2194       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
2195       vat_json_init_array (&vam->json_tree);
2196     }
2197   node = vat_json_array_add (&vam->json_tree);
2198
2199   vat_json_init_object (node);
2200   vat_json_object_add_prefix (node, &mp->prefix);
2201 }
2202
2203 static void
2204 vl_api_ip_details_t_handler (vl_api_ip_details_t * mp)
2205 {
2206   vat_main_t *vam = &vat_main;
2207   static ip_details_t empty_ip_details = { 0 };
2208   ip_details_t *ip = NULL;
2209   u32 sw_if_index = ~0;
2210
2211   sw_if_index = ntohl (mp->sw_if_index);
2212
2213   vec_validate_init_empty (vam->ip_details_by_sw_if_index[vam->is_ipv6],
2214                            sw_if_index, empty_ip_details);
2215
2216   ip = vec_elt_at_index (vam->ip_details_by_sw_if_index[vam->is_ipv6],
2217                          sw_if_index);
2218
2219   ip->present = 1;
2220 }
2221
2222 static void
2223 vl_api_ip_details_t_handler_json (vl_api_ip_details_t * mp)
2224 {
2225   vat_main_t *vam = &vat_main;
2226
2227   if (VAT_JSON_ARRAY != vam->json_tree.type)
2228     {
2229       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
2230       vat_json_init_array (&vam->json_tree);
2231     }
2232   vat_json_array_add_uint (&vam->json_tree,
2233                            clib_net_to_host_u32 (mp->sw_if_index));
2234 }
2235
2236 static void vl_api_get_first_msg_id_reply_t_handler
2237   (vl_api_get_first_msg_id_reply_t * mp)
2238 {
2239   vat_main_t *vam = &vat_main;
2240   i32 retval = ntohl (mp->retval);
2241
2242   if (vam->async_mode)
2243     {
2244       vam->async_errors += (retval < 0);
2245     }
2246   else
2247     {
2248       vam->retval = retval;
2249       vam->result_ready = 1;
2250     }
2251   if (retval >= 0)
2252     {
2253       errmsg ("first message id %d", ntohs (mp->first_msg_id));
2254     }
2255 }
2256
2257 static void vl_api_get_first_msg_id_reply_t_handler_json
2258   (vl_api_get_first_msg_id_reply_t * mp)
2259 {
2260   vat_main_t *vam = &vat_main;
2261   vat_json_node_t node;
2262
2263   vat_json_init_object (&node);
2264   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2265   vat_json_object_add_uint (&node, "first_msg_id",
2266                             (uint) ntohs (mp->first_msg_id));
2267
2268   vat_json_print (vam->ofp, &node);
2269   vat_json_free (&node);
2270
2271   vam->retval = ntohl (mp->retval);
2272   vam->result_ready = 1;
2273 }
2274
2275 static void vl_api_get_node_graph_reply_t_handler
2276   (vl_api_get_node_graph_reply_t * mp)
2277 {
2278   vat_main_t *vam = &vat_main;
2279   i32 retval = ntohl (mp->retval);
2280   u8 *pvt_copy, *reply;
2281   void *oldheap;
2282   vlib_node_t *node;
2283   int i;
2284
2285   if (vam->async_mode)
2286     {
2287       vam->async_errors += (retval < 0);
2288     }
2289   else
2290     {
2291       vam->retval = retval;
2292       vam->result_ready = 1;
2293     }
2294
2295   /* "Should never happen..." */
2296   if (retval != 0)
2297     return;
2298
2299   reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
2300   pvt_copy = vec_dup (reply);
2301
2302   /* Toss the shared-memory original... */
2303   oldheap = vl_msg_push_heap ();
2304
2305   vec_free (reply);
2306
2307   vl_msg_pop_heap (oldheap);
2308
2309   if (vam->graph_nodes)
2310     {
2311       hash_free (vam->graph_node_index_by_name);
2312
2313       for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
2314         {
2315           node = vam->graph_nodes[0][i];
2316           vec_free (node->name);
2317           vec_free (node->next_nodes);
2318           vec_free (node);
2319         }
2320       vec_free (vam->graph_nodes[0]);
2321       vec_free (vam->graph_nodes);
2322     }
2323
2324   vam->graph_node_index_by_name = hash_create_string (0, sizeof (uword));
2325   vam->graph_nodes = vlib_node_unserialize (pvt_copy);
2326   vec_free (pvt_copy);
2327
2328   for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
2329     {
2330       node = vam->graph_nodes[0][i];
2331       hash_set_mem (vam->graph_node_index_by_name, node->name, i);
2332     }
2333 }
2334
2335 static void vl_api_get_node_graph_reply_t_handler_json
2336   (vl_api_get_node_graph_reply_t * mp)
2337 {
2338   vat_main_t *vam = &vat_main;
2339   void *oldheap;
2340   vat_json_node_t node;
2341   u8 *reply;
2342
2343   /* $$$$ make this real? */
2344   vat_json_init_object (&node);
2345   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2346   vat_json_object_add_uint (&node, "reply_in_shmem", mp->reply_in_shmem);
2347
2348   reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
2349
2350   /* Toss the shared-memory original... */
2351   oldheap = vl_msg_push_heap ();
2352
2353   vec_free (reply);
2354
2355   vl_msg_pop_heap (oldheap);
2356
2357   vat_json_print (vam->ofp, &node);
2358   vat_json_free (&node);
2359
2360   vam->retval = ntohl (mp->retval);
2361   vam->result_ready = 1;
2362 }
2363
2364 /* Format hex dump. */
2365 u8 *
2366 format_hex_bytes (u8 * s, va_list * va)
2367 {
2368   u8 *bytes = va_arg (*va, u8 *);
2369   int n_bytes = va_arg (*va, int);
2370   uword i;
2371
2372   /* Print short or long form depending on byte count. */
2373   uword short_form = n_bytes <= 32;
2374   u32 indent = format_get_indent (s);
2375
2376   if (n_bytes == 0)
2377     return s;
2378
2379   for (i = 0; i < n_bytes; i++)
2380     {
2381       if (!short_form && (i % 32) == 0)
2382         s = format (s, "%08x: ", i);
2383       s = format (s, "%02x", bytes[i]);
2384       if (!short_form && ((i + 1) % 32) == 0 && (i + 1) < n_bytes)
2385         s = format (s, "\n%U", format_white_space, indent);
2386     }
2387
2388   return s;
2389 }
2390
2391 /*
2392  * Generate boilerplate reply handlers, which
2393  * dig the return value out of the xxx_reply_t API message,
2394  * stick it into vam->retval, and set vam->result_ready
2395  *
2396  * Could also do this by pointing N message decode slots at
2397  * a single function, but that could break in subtle ways.
2398  */
2399
2400 #define foreach_standard_reply_retval_handler           \
2401 _(sw_interface_set_flags_reply)                         \
2402 _(sw_interface_add_del_address_reply)                   \
2403 _(sw_interface_set_rx_mode_reply)                       \
2404 _(sw_interface_set_rx_placement_reply)                  \
2405 _(sw_interface_set_table_reply)                         \
2406 _(sw_interface_set_mpls_enable_reply)                   \
2407 _(sw_interface_set_vpath_reply)                         \
2408 _(sw_interface_set_l2_bridge_reply)                     \
2409 _(sw_interface_set_bond_weight_reply)                   \
2410 _(bridge_domain_add_del_reply)                          \
2411 _(sw_interface_set_l2_xconnect_reply)                   \
2412 _(l2fib_add_del_reply)                                  \
2413 _(l2fib_flush_int_reply)                                \
2414 _(l2fib_flush_bd_reply)                                 \
2415 _(ip_route_add_del_reply)                               \
2416 _(ip_table_add_del_reply)                               \
2417 _(ip_table_replace_begin_reply)                         \
2418 _(ip_table_flush_reply)                                 \
2419 _(ip_table_replace_end_reply)                           \
2420 _(ip_mroute_add_del_reply)                              \
2421 _(mpls_route_add_del_reply)                             \
2422 _(mpls_table_add_del_reply)                             \
2423 _(mpls_ip_bind_unbind_reply)                            \
2424 _(sw_interface_set_unnumbered_reply)                    \
2425 _(set_ip_flow_hash_reply)                               \
2426 _(sw_interface_ip6_enable_disable_reply)                \
2427 _(l2_patch_add_del_reply)                               \
2428 _(sr_mpls_policy_add_reply)                             \
2429 _(sr_mpls_policy_mod_reply)                             \
2430 _(sr_mpls_policy_del_reply)                             \
2431 _(sr_policy_add_reply)                                  \
2432 _(sr_policy_mod_reply)                                  \
2433 _(sr_policy_del_reply)                                  \
2434 _(sr_localsid_add_del_reply)                            \
2435 _(sr_steering_add_del_reply)                            \
2436 _(l2_fib_clear_table_reply)                             \
2437 _(l2_interface_efp_filter_reply)                        \
2438 _(l2_interface_vlan_tag_rewrite_reply)                  \
2439 _(modify_vhost_user_if_reply)                           \
2440 _(modify_vhost_user_if_v2_reply)                        \
2441 _(delete_vhost_user_if_reply)                           \
2442 _(want_l2_macs_events_reply)                            \
2443 _(delete_loopback_reply)                                \
2444 _(bd_ip_mac_add_del_reply)                              \
2445 _(bd_ip_mac_flush_reply)                                \
2446 _(want_interface_events_reply)                          \
2447 _(sw_interface_clear_stats_reply)                       \
2448 _(ioam_enable_reply)                                    \
2449 _(ioam_disable_reply)                                   \
2450 _(af_packet_delete_reply)                               \
2451 _(sw_interface_span_enable_disable_reply)               \
2452 _(ip_source_and_port_range_check_add_del_reply)         \
2453 _(ip_source_and_port_range_check_interface_add_del_reply)\
2454 _(delete_subif_reply)                                   \
2455 _(l2_interface_pbb_tag_rewrite_reply)                   \
2456 _(set_punt_reply)                                       \
2457 _(sw_interface_tag_add_del_reply)                       \
2458 _(sw_interface_add_del_mac_address_reply)               \
2459 _(hw_interface_set_mtu_reply)                           \
2460 _(tcp_configure_src_addresses_reply)                    \
2461 _(session_rule_add_del_reply)                           \
2462 _(ip_container_proxy_add_del_reply)                     \
2463 _(qos_record_enable_disable_reply)                      \
2464
2465 #define _(n)                                    \
2466     static void vl_api_##n##_t_handler          \
2467     (vl_api_##n##_t * mp)                       \
2468     {                                           \
2469         vat_main_t * vam = &vat_main;           \
2470         i32 retval = ntohl(mp->retval);         \
2471         if (vam->async_mode) {                  \
2472             vam->async_errors += (retval < 0);  \
2473         } else {                                \
2474             vam->retval = retval;               \
2475             vam->result_ready = 1;              \
2476         }                                       \
2477     }
2478 foreach_standard_reply_retval_handler;
2479 #undef _
2480
2481 #define _(n)                                    \
2482     static void vl_api_##n##_t_handler_json     \
2483     (vl_api_##n##_t * mp)                       \
2484     {                                           \
2485         vat_main_t * vam = &vat_main;           \
2486         vat_json_node_t node;                   \
2487         vat_json_init_object(&node);            \
2488         vat_json_object_add_int(&node, "retval", ntohl(mp->retval));    \
2489         vat_json_print(vam->ofp, &node);        \
2490         vam->retval = ntohl(mp->retval);        \
2491         vam->result_ready = 1;                  \
2492     }
2493 foreach_standard_reply_retval_handler;
2494 #undef _
2495
2496 /*
2497  * Table of message reply handlers, must include boilerplate handlers
2498  * we just generated
2499  */
2500
2501 #define foreach_vpe_api_reply_msg                                       \
2502 _(CREATE_LOOPBACK_REPLY, create_loopback_reply)                         \
2503 _(CREATE_LOOPBACK_INSTANCE_REPLY, create_loopback_instance_reply)       \
2504 _(SW_INTERFACE_DETAILS, sw_interface_details)                           \
2505 _(SW_INTERFACE_SET_FLAGS_REPLY, sw_interface_set_flags_reply)           \
2506 _(CONTROL_PING_REPLY, control_ping_reply)                               \
2507 _(CLI_REPLY, cli_reply)                                                 \
2508 _(CLI_INBAND_REPLY, cli_inband_reply)                                   \
2509 _(SW_INTERFACE_ADD_DEL_ADDRESS_REPLY,                                   \
2510   sw_interface_add_del_address_reply)                                   \
2511 _(SW_INTERFACE_SET_RX_MODE_REPLY, sw_interface_set_rx_mode_reply)       \
2512 _(SW_INTERFACE_SET_RX_PLACEMENT_REPLY, sw_interface_set_rx_placement_reply)     \
2513 _(SW_INTERFACE_RX_PLACEMENT_DETAILS, sw_interface_rx_placement_details) \
2514 _(SW_INTERFACE_SET_TABLE_REPLY, sw_interface_set_table_reply)           \
2515 _(SW_INTERFACE_SET_MPLS_ENABLE_REPLY, sw_interface_set_mpls_enable_reply) \
2516 _(SW_INTERFACE_SET_VPATH_REPLY, sw_interface_set_vpath_reply)           \
2517 _(SW_INTERFACE_SET_L2_XCONNECT_REPLY,                                   \
2518   sw_interface_set_l2_xconnect_reply)                                   \
2519 _(SW_INTERFACE_SET_L2_BRIDGE_REPLY,                                     \
2520   sw_interface_set_l2_bridge_reply)                                     \
2521 _(BRIDGE_DOMAIN_ADD_DEL_REPLY, bridge_domain_add_del_reply)             \
2522 _(BRIDGE_DOMAIN_DETAILS, bridge_domain_details)                         \
2523 _(BRIDGE_DOMAIN_SET_MAC_AGE_REPLY, bridge_domain_set_mac_age_reply)     \
2524 _(L2FIB_ADD_DEL_REPLY, l2fib_add_del_reply)                             \
2525 _(L2FIB_FLUSH_INT_REPLY, l2fib_flush_int_reply)                         \
2526 _(L2FIB_FLUSH_BD_REPLY, l2fib_flush_bd_reply)                           \
2527 _(L2_FLAGS_REPLY, l2_flags_reply)                                       \
2528 _(BRIDGE_FLAGS_REPLY, bridge_flags_reply)                               \
2529 _(TAP_CREATE_V2_REPLY, tap_create_v2_reply)                             \
2530 _(TAP_DELETE_V2_REPLY, tap_delete_v2_reply)                             \
2531 _(SW_INTERFACE_TAP_V2_DETAILS, sw_interface_tap_v2_details)             \
2532 _(VIRTIO_PCI_CREATE_REPLY, virtio_pci_create_reply)                     \
2533 _(VIRTIO_PCI_CREATE_V2_REPLY, virtio_pci_create_v2_reply)               \
2534 _(VIRTIO_PCI_DELETE_REPLY, virtio_pci_delete_reply)                     \
2535 _(SW_INTERFACE_VIRTIO_PCI_DETAILS, sw_interface_virtio_pci_details)     \
2536 _(BOND_CREATE_REPLY, bond_create_reply)                                 \
2537 _(BOND_CREATE2_REPLY, bond_create2_reply)                               \
2538 _(BOND_DELETE_REPLY, bond_delete_reply)                                 \
2539 _(BOND_ADD_MEMBER_REPLY, bond_add_member_reply)                         \
2540 _(BOND_DETACH_MEMBER_REPLY, bond_detach_member_reply)                   \
2541 _(SW_INTERFACE_SET_BOND_WEIGHT_REPLY, sw_interface_set_bond_weight_reply) \
2542 _(SW_BOND_INTERFACE_DETAILS, sw_bond_interface_details)                 \
2543 _(SW_MEMBER_INTERFACE_DETAILS, sw_member_interface_details)               \
2544 _(IP_ROUTE_ADD_DEL_REPLY, ip_route_add_del_reply)                       \
2545 _(IP_TABLE_ADD_DEL_REPLY, ip_table_add_del_reply)                       \
2546 _(IP_TABLE_REPLACE_BEGIN_REPLY, ip_table_replace_begin_reply)           \
2547 _(IP_TABLE_FLUSH_REPLY, ip_table_flush_reply)                           \
2548 _(IP_TABLE_REPLACE_END_REPLY, ip_table_replace_end_reply)               \
2549 _(IP_MROUTE_ADD_DEL_REPLY, ip_mroute_add_del_reply)                     \
2550 _(MPLS_TABLE_ADD_DEL_REPLY, mpls_table_add_del_reply)                   \
2551 _(MPLS_ROUTE_ADD_DEL_REPLY, mpls_route_add_del_reply)                   \
2552 _(MPLS_IP_BIND_UNBIND_REPLY, mpls_ip_bind_unbind_reply)                 \
2553 _(MPLS_TUNNEL_ADD_DEL_REPLY, mpls_tunnel_add_del_reply)                 \
2554 _(SW_INTERFACE_SET_UNNUMBERED_REPLY,                                    \
2555   sw_interface_set_unnumbered_reply)                                    \
2556 _(CREATE_VLAN_SUBIF_REPLY, create_vlan_subif_reply)                     \
2557 _(CREATE_SUBIF_REPLY, create_subif_reply)                               \
2558 _(SET_IP_FLOW_HASH_REPLY, set_ip_flow_hash_reply)                       \
2559 _(SW_INTERFACE_IP6_ENABLE_DISABLE_REPLY,                                \
2560   sw_interface_ip6_enable_disable_reply)                                \
2561 _(L2_PATCH_ADD_DEL_REPLY, l2_patch_add_del_reply)                       \
2562 _(SR_MPLS_POLICY_ADD_REPLY, sr_mpls_policy_add_reply)                   \
2563 _(SR_MPLS_POLICY_MOD_REPLY, sr_mpls_policy_mod_reply)                   \
2564 _(SR_MPLS_POLICY_DEL_REPLY, sr_mpls_policy_del_reply)                   \
2565 _(SR_POLICY_ADD_REPLY, sr_policy_add_reply)                             \
2566 _(SR_POLICY_MOD_REPLY, sr_policy_mod_reply)                             \
2567 _(SR_POLICY_DEL_REPLY, sr_policy_del_reply)                             \
2568 _(SR_LOCALSID_ADD_DEL_REPLY, sr_localsid_add_del_reply)                 \
2569 _(SR_STEERING_ADD_DEL_REPLY, sr_steering_add_del_reply)                 \
2570 _(GET_NODE_INDEX_REPLY, get_node_index_reply)                           \
2571 _(ADD_NODE_NEXT_REPLY, add_node_next_reply)                             \
2572 _(L2_FIB_CLEAR_TABLE_REPLY, l2_fib_clear_table_reply)                   \
2573 _(L2_INTERFACE_EFP_FILTER_REPLY, l2_interface_efp_filter_reply)         \
2574 _(L2_INTERFACE_VLAN_TAG_REWRITE_REPLY, l2_interface_vlan_tag_rewrite_reply) \
2575 _(SW_INTERFACE_VHOST_USER_DETAILS, sw_interface_vhost_user_details)     \
2576 _(CREATE_VHOST_USER_IF_REPLY, create_vhost_user_if_reply)               \
2577 _(MODIFY_VHOST_USER_IF_REPLY, modify_vhost_user_if_reply)               \
2578 _(CREATE_VHOST_USER_IF_V2_REPLY, create_vhost_user_if_v2_reply)         \
2579 _(MODIFY_VHOST_USER_IF_V2_REPLY, modify_vhost_user_if_v2_reply)         \
2580 _(DELETE_VHOST_USER_IF_REPLY, delete_vhost_user_if_reply)               \
2581 _(SHOW_VERSION_REPLY, show_version_reply)                               \
2582 _(SHOW_THREADS_REPLY, show_threads_reply)                               \
2583 _(L2_FIB_TABLE_DETAILS, l2_fib_table_details)                           \
2584 _(INTERFACE_NAME_RENUMBER_REPLY, interface_name_renumber_reply)         \
2585 _(WANT_L2_MACS_EVENTS_REPLY, want_l2_macs_events_reply)                 \
2586 _(L2_MACS_EVENT, l2_macs_event)                                         \
2587 _(IP_ADDRESS_DETAILS, ip_address_details)                               \
2588 _(IP_DETAILS, ip_details)                                               \
2589 _(DELETE_LOOPBACK_REPLY, delete_loopback_reply)                         \
2590 _(BD_IP_MAC_ADD_DEL_REPLY, bd_ip_mac_add_del_reply)                     \
2591 _(BD_IP_MAC_FLUSH_REPLY, bd_ip_mac_flush_reply)                         \
2592 _(BD_IP_MAC_DETAILS, bd_ip_mac_details)                                 \
2593 _(WANT_INTERFACE_EVENTS_REPLY, want_interface_events_reply)             \
2594 _(GET_FIRST_MSG_ID_REPLY, get_first_msg_id_reply)                       \
2595 _(GET_NODE_GRAPH_REPLY, get_node_graph_reply)                           \
2596 _(SW_INTERFACE_CLEAR_STATS_REPLY, sw_interface_clear_stats_reply)      \
2597 _(IOAM_ENABLE_REPLY, ioam_enable_reply)                   \
2598 _(IOAM_DISABLE_REPLY, ioam_disable_reply)                     \
2599 _(AF_PACKET_CREATE_REPLY, af_packet_create_reply)                       \
2600 _(AF_PACKET_DELETE_REPLY, af_packet_delete_reply)                       \
2601 _(AF_PACKET_DETAILS, af_packet_details)                                 \
2602 _(MPLS_TUNNEL_DETAILS, mpls_tunnel_details)                             \
2603 _(MPLS_TABLE_DETAILS, mpls_table_details)                               \
2604 _(MPLS_ROUTE_DETAILS, mpls_route_details)                               \
2605 _(SW_INTERFACE_SPAN_ENABLE_DISABLE_REPLY, sw_interface_span_enable_disable_reply) \
2606 _(SW_INTERFACE_SPAN_DETAILS, sw_interface_span_details)                 \
2607 _(GET_NEXT_INDEX_REPLY, get_next_index_reply)                           \
2608 _(IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL_REPLY,                         \
2609  ip_source_and_port_range_check_add_del_reply)                          \
2610 _(IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL_REPLY,               \
2611  ip_source_and_port_range_check_interface_add_del_reply)                \
2612 _(DELETE_SUBIF_REPLY, delete_subif_reply)                               \
2613 _(L2_INTERFACE_PBB_TAG_REWRITE_REPLY, l2_interface_pbb_tag_rewrite_reply) \
2614 _(SET_PUNT_REPLY, set_punt_reply)                                       \
2615 _(IP_TABLE_DETAILS, ip_table_details)                                   \
2616 _(IP_ROUTE_DETAILS, ip_route_details)                                   \
2617 _(SW_INTERFACE_TAG_ADD_DEL_REPLY, sw_interface_tag_add_del_reply)       \
2618 _(SW_INTERFACE_ADD_DEL_MAC_ADDRESS_REPLY, sw_interface_add_del_mac_address_reply) \
2619 _(L2_XCONNECT_DETAILS, l2_xconnect_details)                             \
2620 _(HW_INTERFACE_SET_MTU_REPLY, hw_interface_set_mtu_reply)               \
2621 _(SW_INTERFACE_GET_TABLE_REPLY, sw_interface_get_table_reply)           \
2622 _(TCP_CONFIGURE_SRC_ADDRESSES_REPLY, tcp_configure_src_addresses_reply) \
2623 _(APP_NAMESPACE_ADD_DEL_REPLY, app_namespace_add_del_reply)             \
2624 _(SESSION_RULE_ADD_DEL_REPLY, session_rule_add_del_reply)               \
2625 _(SESSION_RULES_DETAILS, session_rules_details)                         \
2626 _(IP_CONTAINER_PROXY_ADD_DEL_REPLY, ip_container_proxy_add_del_reply)   \
2627 _(QOS_RECORD_ENABLE_DISABLE_REPLY, qos_record_enable_disable_reply)             \
2628
2629 #define foreach_standalone_reply_msg                                    \
2630 _(SW_INTERFACE_EVENT, sw_interface_event)
2631
2632 typedef struct
2633 {
2634   u8 *name;
2635   u32 value;
2636 } name_sort_t;
2637
2638 #define STR_VTR_OP_CASE(op)     \
2639     case L2_VTR_ ## op:         \
2640         return "" # op;
2641
2642 static const char *
2643 str_vtr_op (u32 vtr_op)
2644 {
2645   switch (vtr_op)
2646     {
2647       STR_VTR_OP_CASE (DISABLED);
2648       STR_VTR_OP_CASE (PUSH_1);
2649       STR_VTR_OP_CASE (PUSH_2);
2650       STR_VTR_OP_CASE (POP_1);
2651       STR_VTR_OP_CASE (POP_2);
2652       STR_VTR_OP_CASE (TRANSLATE_1_1);
2653       STR_VTR_OP_CASE (TRANSLATE_1_2);
2654       STR_VTR_OP_CASE (TRANSLATE_2_1);
2655       STR_VTR_OP_CASE (TRANSLATE_2_2);
2656     }
2657
2658   return "UNKNOWN";
2659 }
2660
2661 static int
2662 dump_sub_interface_table (vat_main_t * vam)
2663 {
2664   const sw_interface_subif_t *sub = NULL;
2665
2666   if (vam->json_output)
2667     {
2668       clib_warning
2669         ("JSON output supported only for VPE API calls and dump_stats_table");
2670       return -99;
2671     }
2672
2673   print (vam->ofp,
2674          "%-30s%-12s%-11s%-7s%-5s%-9s%-9s%-6s%-8s%-10s%-10s",
2675          "Interface", "sw_if_index",
2676          "sub id", "dot1ad", "tags", "outer id",
2677          "inner id", "exact", "default", "outer any", "inner any");
2678
2679   vec_foreach (sub, vam->sw_if_subif_table)
2680   {
2681     print (vam->ofp,
2682            "%-30s%-12d%-11d%-7s%-5d%-9d%-9d%-6d%-8d%-10d%-10d",
2683            sub->interface_name,
2684            sub->sw_if_index,
2685            sub->sub_id, sub->sub_dot1ad ? "dot1ad" : "dot1q",
2686            sub->sub_number_of_tags, sub->sub_outer_vlan_id,
2687            sub->sub_inner_vlan_id, sub->sub_exact_match, sub->sub_default,
2688            sub->sub_outer_vlan_id_any, sub->sub_inner_vlan_id_any);
2689     if (sub->vtr_op != L2_VTR_DISABLED)
2690       {
2691         print (vam->ofp,
2692                "  vlan-tag-rewrite - op: %-14s [ dot1q: %d "
2693                "tag1: %d tag2: %d ]",
2694                str_vtr_op (sub->vtr_op), sub->vtr_push_dot1q,
2695                sub->vtr_tag1, sub->vtr_tag2);
2696       }
2697   }
2698
2699   return 0;
2700 }
2701
2702 static int
2703 name_sort_cmp (void *a1, void *a2)
2704 {
2705   name_sort_t *n1 = a1;
2706   name_sort_t *n2 = a2;
2707
2708   return strcmp ((char *) n1->name, (char *) n2->name);
2709 }
2710
2711 static int
2712 dump_interface_table (vat_main_t * vam)
2713 {
2714   hash_pair_t *p;
2715   name_sort_t *nses = 0, *ns;
2716
2717   if (vam->json_output)
2718     {
2719       clib_warning
2720         ("JSON output supported only for VPE API calls and dump_stats_table");
2721       return -99;
2722     }
2723
2724   /* *INDENT-OFF* */
2725   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
2726   ({
2727     vec_add2 (nses, ns, 1);
2728     ns->name = (u8 *)(p->key);
2729     ns->value = (u32) p->value[0];
2730   }));
2731   /* *INDENT-ON* */
2732
2733   vec_sort_with_function (nses, name_sort_cmp);
2734
2735   print (vam->ofp, "%-25s%-15s", "Interface", "sw_if_index");
2736   vec_foreach (ns, nses)
2737   {
2738     print (vam->ofp, "%-25s%-15d", ns->name, ns->value);
2739   }
2740   vec_free (nses);
2741   return 0;
2742 }
2743
2744 static int
2745 dump_ip_table (vat_main_t * vam, int is_ipv6)
2746 {
2747   const ip_details_t *det = NULL;
2748   const ip_address_details_t *address = NULL;
2749   u32 i = ~0;
2750
2751   print (vam->ofp, "%-12s", "sw_if_index");
2752
2753   vec_foreach (det, vam->ip_details_by_sw_if_index[is_ipv6])
2754   {
2755     i++;
2756     if (!det->present)
2757       {
2758         continue;
2759       }
2760     print (vam->ofp, "%-12d", i);
2761     print (vam->ofp, "            %-30s%-13s", "Address", "Prefix length");
2762     if (!det->addr)
2763       {
2764         continue;
2765       }
2766     vec_foreach (address, det->addr)
2767     {
2768       print (vam->ofp,
2769              "            %-30U%-13d",
2770              is_ipv6 ? format_ip6_address : format_ip4_address,
2771              address->ip, address->prefix_length);
2772     }
2773   }
2774
2775   return 0;
2776 }
2777
2778 static int
2779 dump_ipv4_table (vat_main_t * vam)
2780 {
2781   if (vam->json_output)
2782     {
2783       clib_warning
2784         ("JSON output supported only for VPE API calls and dump_stats_table");
2785       return -99;
2786     }
2787
2788   return dump_ip_table (vam, 0);
2789 }
2790
2791 static int
2792 dump_ipv6_table (vat_main_t * vam)
2793 {
2794   if (vam->json_output)
2795     {
2796       clib_warning
2797         ("JSON output supported only for VPE API calls and dump_stats_table");
2798       return -99;
2799     }
2800
2801   return dump_ip_table (vam, 1);
2802 }
2803
2804 /*
2805  * Pass CLI buffers directly in the CLI_INBAND API message,
2806  * instead of an additional shared memory area.
2807  */
2808 static int
2809 exec_inband (vat_main_t * vam)
2810 {
2811   vl_api_cli_inband_t *mp;
2812   unformat_input_t *i = vam->input;
2813   int ret;
2814
2815   if (vec_len (i->buffer) == 0)
2816     return -1;
2817
2818   if (vam->exec_mode == 0 && unformat (i, "mode"))
2819     {
2820       vam->exec_mode = 1;
2821       return 0;
2822     }
2823   if (vam->exec_mode == 1 && (unformat (i, "exit") || unformat (i, "quit")))
2824     {
2825       vam->exec_mode = 0;
2826       return 0;
2827     }
2828
2829   /*
2830    * In order for the CLI command to work, it
2831    * must be a vector ending in \n, not a C-string ending
2832    * in \n\0.
2833    */
2834   M2 (CLI_INBAND, mp, vec_len (vam->input->buffer));
2835   vl_api_vec_to_api_string (vam->input->buffer, &mp->cmd);
2836
2837   S (mp);
2838   W (ret);
2839   /* json responses may or may not include a useful reply... */
2840   if (vec_len (vam->cmd_reply))
2841     print (vam->ofp, "%v", (char *) (vam->cmd_reply));
2842   return ret;
2843 }
2844
2845 int
2846 exec (vat_main_t * vam)
2847 {
2848   return exec_inband (vam);
2849 }
2850
2851 static int
2852 api_create_loopback (vat_main_t * vam)
2853 {
2854   unformat_input_t *i = vam->input;
2855   vl_api_create_loopback_t *mp;
2856   vl_api_create_loopback_instance_t *mp_lbi;
2857   u8 mac_address[6];
2858   u8 mac_set = 0;
2859   u8 is_specified = 0;
2860   u32 user_instance = 0;
2861   int ret;
2862
2863   clib_memset (mac_address, 0, sizeof (mac_address));
2864
2865   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2866     {
2867       if (unformat (i, "mac %U", unformat_ethernet_address, mac_address))
2868         mac_set = 1;
2869       if (unformat (i, "instance %d", &user_instance))
2870         is_specified = 1;
2871       else
2872         break;
2873     }
2874
2875   if (is_specified)
2876     {
2877       M (CREATE_LOOPBACK_INSTANCE, mp_lbi);
2878       mp_lbi->is_specified = is_specified;
2879       if (is_specified)
2880         mp_lbi->user_instance = htonl (user_instance);
2881       if (mac_set)
2882         clib_memcpy (mp_lbi->mac_address, mac_address, sizeof (mac_address));
2883       S (mp_lbi);
2884     }
2885   else
2886     {
2887       /* Construct the API message */
2888       M (CREATE_LOOPBACK, mp);
2889       if (mac_set)
2890         clib_memcpy (mp->mac_address, mac_address, sizeof (mac_address));
2891       S (mp);
2892     }
2893
2894   W (ret);
2895   return ret;
2896 }
2897
2898 static int
2899 api_delete_loopback (vat_main_t * vam)
2900 {
2901   unformat_input_t *i = vam->input;
2902   vl_api_delete_loopback_t *mp;
2903   u32 sw_if_index = ~0;
2904   int ret;
2905
2906   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2907     {
2908       if (unformat (i, "sw_if_index %d", &sw_if_index))
2909         ;
2910       else
2911         break;
2912     }
2913
2914   if (sw_if_index == ~0)
2915     {
2916       errmsg ("missing sw_if_index");
2917       return -99;
2918     }
2919
2920   /* Construct the API message */
2921   M (DELETE_LOOPBACK, mp);
2922   mp->sw_if_index = ntohl (sw_if_index);
2923
2924   S (mp);
2925   W (ret);
2926   return ret;
2927 }
2928
2929 static int
2930 api_want_interface_events (vat_main_t * vam)
2931 {
2932   unformat_input_t *i = vam->input;
2933   vl_api_want_interface_events_t *mp;
2934   int enable = -1;
2935   int ret;
2936
2937   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2938     {
2939       if (unformat (i, "enable"))
2940         enable = 1;
2941       else if (unformat (i, "disable"))
2942         enable = 0;
2943       else
2944         break;
2945     }
2946
2947   if (enable == -1)
2948     {
2949       errmsg ("missing enable|disable");
2950       return -99;
2951     }
2952
2953   M (WANT_INTERFACE_EVENTS, mp);
2954   mp->enable_disable = enable;
2955
2956   vam->interface_event_display = enable;
2957
2958   S (mp);
2959   W (ret);
2960   return ret;
2961 }
2962
2963
2964 /* Note: non-static, called once to set up the initial intfc table */
2965 int
2966 api_sw_interface_dump (vat_main_t * vam)
2967 {
2968   vl_api_sw_interface_dump_t *mp;
2969   vl_api_control_ping_t *mp_ping;
2970   hash_pair_t *p;
2971   name_sort_t *nses = 0, *ns;
2972   sw_interface_subif_t *sub = NULL;
2973   int ret;
2974
2975   /* Toss the old name table */
2976   /* *INDENT-OFF* */
2977   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
2978   ({
2979     vec_add2 (nses, ns, 1);
2980     ns->name = (u8 *)(p->key);
2981     ns->value = (u32) p->value[0];
2982   }));
2983   /* *INDENT-ON* */
2984
2985   hash_free (vam->sw_if_index_by_interface_name);
2986
2987   vec_foreach (ns, nses) vec_free (ns->name);
2988
2989   vec_free (nses);
2990
2991   vec_foreach (sub, vam->sw_if_subif_table)
2992   {
2993     vec_free (sub->interface_name);
2994   }
2995   vec_free (vam->sw_if_subif_table);
2996
2997   /* recreate the interface name hash table */
2998   vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
2999
3000   /*
3001    * Ask for all interface names. Otherwise, the epic catalog of
3002    * name filters becomes ridiculously long, and vat ends up needing
3003    * to be taught about new interface types.
3004    */
3005   M (SW_INTERFACE_DUMP, mp);
3006   S (mp);
3007
3008   /* Use a control ping for synchronization */
3009   MPING (CONTROL_PING, mp_ping);
3010   S (mp_ping);
3011
3012   W (ret);
3013   return ret;
3014 }
3015
3016 static int
3017 api_sw_interface_set_flags (vat_main_t * vam)
3018 {
3019   unformat_input_t *i = vam->input;
3020   vl_api_sw_interface_set_flags_t *mp;
3021   u32 sw_if_index;
3022   u8 sw_if_index_set = 0;
3023   u8 admin_up = 0;
3024   int ret;
3025
3026   /* Parse args required to build the message */
3027   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3028     {
3029       if (unformat (i, "admin-up"))
3030         admin_up = 1;
3031       else if (unformat (i, "admin-down"))
3032         admin_up = 0;
3033       else
3034         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3035         sw_if_index_set = 1;
3036       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3037         sw_if_index_set = 1;
3038       else
3039         break;
3040     }
3041
3042   if (sw_if_index_set == 0)
3043     {
3044       errmsg ("missing interface name or sw_if_index");
3045       return -99;
3046     }
3047
3048   /* Construct the API message */
3049   M (SW_INTERFACE_SET_FLAGS, mp);
3050   mp->sw_if_index = ntohl (sw_if_index);
3051   mp->flags = ntohl ((admin_up) ? IF_STATUS_API_FLAG_ADMIN_UP : 0);
3052
3053   /* send it... */
3054   S (mp);
3055
3056   /* Wait for a reply, return the good/bad news... */
3057   W (ret);
3058   return ret;
3059 }
3060
3061 static int
3062 api_sw_interface_set_rx_mode (vat_main_t * vam)
3063 {
3064   unformat_input_t *i = vam->input;
3065   vl_api_sw_interface_set_rx_mode_t *mp;
3066   u32 sw_if_index;
3067   u8 sw_if_index_set = 0;
3068   int ret;
3069   u8 queue_id_valid = 0;
3070   u32 queue_id;
3071   vnet_hw_if_rx_mode mode = VNET_HW_IF_RX_MODE_UNKNOWN;
3072
3073   /* Parse args required to build the message */
3074   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3075     {
3076       if (unformat (i, "queue %d", &queue_id))
3077         queue_id_valid = 1;
3078       else if (unformat (i, "polling"))
3079         mode = VNET_HW_IF_RX_MODE_POLLING;
3080       else if (unformat (i, "interrupt"))
3081         mode = VNET_HW_IF_RX_MODE_INTERRUPT;
3082       else if (unformat (i, "adaptive"))
3083         mode = VNET_HW_IF_RX_MODE_ADAPTIVE;
3084       else
3085         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3086         sw_if_index_set = 1;
3087       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3088         sw_if_index_set = 1;
3089       else
3090         break;
3091     }
3092
3093   if (sw_if_index_set == 0)
3094     {
3095       errmsg ("missing interface name or sw_if_index");
3096       return -99;
3097     }
3098   if (mode == VNET_HW_IF_RX_MODE_UNKNOWN)
3099     {
3100       errmsg ("missing rx-mode");
3101       return -99;
3102     }
3103
3104   /* Construct the API message */
3105   M (SW_INTERFACE_SET_RX_MODE, mp);
3106   mp->sw_if_index = ntohl (sw_if_index);
3107   mp->mode = (vl_api_rx_mode_t) mode;
3108   mp->queue_id_valid = queue_id_valid;
3109   mp->queue_id = queue_id_valid ? ntohl (queue_id) : ~0;
3110
3111   /* send it... */
3112   S (mp);
3113
3114   /* Wait for a reply, return the good/bad news... */
3115   W (ret);
3116   return ret;
3117 }
3118
3119 static int
3120 api_sw_interface_set_rx_placement (vat_main_t * vam)
3121 {
3122   unformat_input_t *i = vam->input;
3123   vl_api_sw_interface_set_rx_placement_t *mp;
3124   u32 sw_if_index;
3125   u8 sw_if_index_set = 0;
3126   int ret;
3127   u8 is_main = 0;
3128   u32 queue_id, thread_index;
3129
3130   /* Parse args required to build the message */
3131   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3132     {
3133       if (unformat (i, "queue %d", &queue_id))
3134         ;
3135       else if (unformat (i, "main"))
3136         is_main = 1;
3137       else if (unformat (i, "worker %d", &thread_index))
3138         ;
3139       else
3140         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3141         sw_if_index_set = 1;
3142       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3143         sw_if_index_set = 1;
3144       else
3145         break;
3146     }
3147
3148   if (sw_if_index_set == 0)
3149     {
3150       errmsg ("missing interface name or sw_if_index");
3151       return -99;
3152     }
3153
3154   if (is_main)
3155     thread_index = 0;
3156   /* Construct the API message */
3157   M (SW_INTERFACE_SET_RX_PLACEMENT, mp);
3158   mp->sw_if_index = ntohl (sw_if_index);
3159   mp->worker_id = ntohl (thread_index);
3160   mp->queue_id = ntohl (queue_id);
3161   mp->is_main = is_main;
3162
3163   /* send it... */
3164   S (mp);
3165   /* Wait for a reply, return the good/bad news... */
3166   W (ret);
3167   return ret;
3168 }
3169
3170 static void vl_api_sw_interface_rx_placement_details_t_handler
3171   (vl_api_sw_interface_rx_placement_details_t * mp)
3172 {
3173   vat_main_t *vam = &vat_main;
3174   u32 worker_id = ntohl (mp->worker_id);
3175
3176   print (vam->ofp,
3177          "\n%-11d %-11s %-6d %-5d %-9s",
3178          ntohl (mp->sw_if_index), (worker_id == 0) ? "main" : "worker",
3179          worker_id, ntohl (mp->queue_id),
3180          (mp->mode ==
3181           1) ? "polling" : ((mp->mode == 2) ? "interrupt" : "adaptive"));
3182 }
3183
3184 static void vl_api_sw_interface_rx_placement_details_t_handler_json
3185   (vl_api_sw_interface_rx_placement_details_t * mp)
3186 {
3187   vat_main_t *vam = &vat_main;
3188   vat_json_node_t *node = NULL;
3189
3190   if (VAT_JSON_ARRAY != vam->json_tree.type)
3191     {
3192       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
3193       vat_json_init_array (&vam->json_tree);
3194     }
3195   node = vat_json_array_add (&vam->json_tree);
3196
3197   vat_json_init_object (node);
3198   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
3199   vat_json_object_add_uint (node, "worker_id", ntohl (mp->worker_id));
3200   vat_json_object_add_uint (node, "queue_id", ntohl (mp->queue_id));
3201   vat_json_object_add_uint (node, "mode", mp->mode);
3202 }
3203
3204 static int
3205 api_sw_interface_rx_placement_dump (vat_main_t * vam)
3206 {
3207   unformat_input_t *i = vam->input;
3208   vl_api_sw_interface_rx_placement_dump_t *mp;
3209   vl_api_control_ping_t *mp_ping;
3210   int ret;
3211   u32 sw_if_index;
3212   u8 sw_if_index_set = 0;
3213
3214   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3215     {
3216       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3217         sw_if_index_set++;
3218       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3219         sw_if_index_set++;
3220       else
3221         break;
3222     }
3223
3224   print (vam->ofp,
3225          "\n%-11s %-11s %-6s %-5s %-4s",
3226          "sw_if_index", "main/worker", "thread", "queue", "mode");
3227
3228   /* Dump Interface rx placement */
3229   M (SW_INTERFACE_RX_PLACEMENT_DUMP, mp);
3230
3231   if (sw_if_index_set)
3232     mp->sw_if_index = htonl (sw_if_index);
3233   else
3234     mp->sw_if_index = ~0;
3235
3236   S (mp);
3237
3238   /* Use a control ping for synchronization */
3239   MPING (CONTROL_PING, mp_ping);
3240   S (mp_ping);
3241
3242   W (ret);
3243   return ret;
3244 }
3245
3246 static int
3247 api_sw_interface_clear_stats (vat_main_t * vam)
3248 {
3249   unformat_input_t *i = vam->input;
3250   vl_api_sw_interface_clear_stats_t *mp;
3251   u32 sw_if_index;
3252   u8 sw_if_index_set = 0;
3253   int ret;
3254
3255   /* Parse args required to build the message */
3256   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3257     {
3258       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3259         sw_if_index_set = 1;
3260       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3261         sw_if_index_set = 1;
3262       else
3263         break;
3264     }
3265
3266   /* Construct the API message */
3267   M (SW_INTERFACE_CLEAR_STATS, mp);
3268
3269   if (sw_if_index_set == 1)
3270     mp->sw_if_index = ntohl (sw_if_index);
3271   else
3272     mp->sw_if_index = ~0;
3273
3274   /* send it... */
3275   S (mp);
3276
3277   /* Wait for a reply, return the good/bad news... */
3278   W (ret);
3279   return ret;
3280 }
3281
3282 static int
3283 api_sw_interface_add_del_address (vat_main_t * vam)
3284 {
3285   unformat_input_t *i = vam->input;
3286   vl_api_sw_interface_add_del_address_t *mp;
3287   u32 sw_if_index;
3288   u8 sw_if_index_set = 0;
3289   u8 is_add = 1, del_all = 0;
3290   u32 address_length = 0;
3291   u8 v4_address_set = 0;
3292   u8 v6_address_set = 0;
3293   ip4_address_t v4address;
3294   ip6_address_t v6address;
3295   int ret;
3296
3297   /* Parse args required to build the message */
3298   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3299     {
3300       if (unformat (i, "del-all"))
3301         del_all = 1;
3302       else if (unformat (i, "del"))
3303         is_add = 0;
3304       else
3305         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3306         sw_if_index_set = 1;
3307       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3308         sw_if_index_set = 1;
3309       else if (unformat (i, "%U/%d",
3310                          unformat_ip4_address, &v4address, &address_length))
3311         v4_address_set = 1;
3312       else if (unformat (i, "%U/%d",
3313                          unformat_ip6_address, &v6address, &address_length))
3314         v6_address_set = 1;
3315       else
3316         break;
3317     }
3318
3319   if (sw_if_index_set == 0)
3320     {
3321       errmsg ("missing interface name or sw_if_index");
3322       return -99;
3323     }
3324   if (v4_address_set && v6_address_set)
3325     {
3326       errmsg ("both v4 and v6 addresses set");
3327       return -99;
3328     }
3329   if (!v4_address_set && !v6_address_set && !del_all)
3330     {
3331       errmsg ("no addresses set");
3332       return -99;
3333     }
3334
3335   /* Construct the API message */
3336   M (SW_INTERFACE_ADD_DEL_ADDRESS, mp);
3337
3338   mp->sw_if_index = ntohl (sw_if_index);
3339   mp->is_add = is_add;
3340   mp->del_all = del_all;
3341   if (v6_address_set)
3342     {
3343       mp->prefix.address.af = ADDRESS_IP6;
3344       clib_memcpy (mp->prefix.address.un.ip6, &v6address, sizeof (v6address));
3345     }
3346   else
3347     {
3348       mp->prefix.address.af = ADDRESS_IP4;
3349       clib_memcpy (mp->prefix.address.un.ip4, &v4address, sizeof (v4address));
3350     }
3351   mp->prefix.len = address_length;
3352
3353   /* send it... */
3354   S (mp);
3355
3356   /* Wait for a reply, return good/bad news  */
3357   W (ret);
3358   return ret;
3359 }
3360
3361 static int
3362 api_sw_interface_set_mpls_enable (vat_main_t * vam)
3363 {
3364   unformat_input_t *i = vam->input;
3365   vl_api_sw_interface_set_mpls_enable_t *mp;
3366   u32 sw_if_index;
3367   u8 sw_if_index_set = 0;
3368   u8 enable = 1;
3369   int ret;
3370
3371   /* Parse args required to build the message */
3372   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3373     {
3374       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3375         sw_if_index_set = 1;
3376       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3377         sw_if_index_set = 1;
3378       else if (unformat (i, "disable"))
3379         enable = 0;
3380       else if (unformat (i, "dis"))
3381         enable = 0;
3382       else
3383         break;
3384     }
3385
3386   if (sw_if_index_set == 0)
3387     {
3388       errmsg ("missing interface name or sw_if_index");
3389       return -99;
3390     }
3391
3392   /* Construct the API message */
3393   M (SW_INTERFACE_SET_MPLS_ENABLE, mp);
3394
3395   mp->sw_if_index = ntohl (sw_if_index);
3396   mp->enable = enable;
3397
3398   /* send it... */
3399   S (mp);
3400
3401   /* Wait for a reply... */
3402   W (ret);
3403   return ret;
3404 }
3405
3406 static int
3407 api_sw_interface_set_table (vat_main_t * vam)
3408 {
3409   unformat_input_t *i = vam->input;
3410   vl_api_sw_interface_set_table_t *mp;
3411   u32 sw_if_index, vrf_id = 0;
3412   u8 sw_if_index_set = 0;
3413   u8 is_ipv6 = 0;
3414   int ret;
3415
3416   /* Parse args required to build the message */
3417   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3418     {
3419       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3420         sw_if_index_set = 1;
3421       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3422         sw_if_index_set = 1;
3423       else if (unformat (i, "vrf %d", &vrf_id))
3424         ;
3425       else if (unformat (i, "ipv6"))
3426         is_ipv6 = 1;
3427       else
3428         break;
3429     }
3430
3431   if (sw_if_index_set == 0)
3432     {
3433       errmsg ("missing interface name or sw_if_index");
3434       return -99;
3435     }
3436
3437   /* Construct the API message */
3438   M (SW_INTERFACE_SET_TABLE, mp);
3439
3440   mp->sw_if_index = ntohl (sw_if_index);
3441   mp->is_ipv6 = is_ipv6;
3442   mp->vrf_id = ntohl (vrf_id);
3443
3444   /* send it... */
3445   S (mp);
3446
3447   /* Wait for a reply... */
3448   W (ret);
3449   return ret;
3450 }
3451
3452 static void vl_api_sw_interface_get_table_reply_t_handler
3453   (vl_api_sw_interface_get_table_reply_t * mp)
3454 {
3455   vat_main_t *vam = &vat_main;
3456
3457   print (vam->ofp, "%d", ntohl (mp->vrf_id));
3458
3459   vam->retval = ntohl (mp->retval);
3460   vam->result_ready = 1;
3461
3462 }
3463
3464 static void vl_api_sw_interface_get_table_reply_t_handler_json
3465   (vl_api_sw_interface_get_table_reply_t * mp)
3466 {
3467   vat_main_t *vam = &vat_main;
3468   vat_json_node_t node;
3469
3470   vat_json_init_object (&node);
3471   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
3472   vat_json_object_add_int (&node, "vrf_id", ntohl (mp->vrf_id));
3473
3474   vat_json_print (vam->ofp, &node);
3475   vat_json_free (&node);
3476
3477   vam->retval = ntohl (mp->retval);
3478   vam->result_ready = 1;
3479 }
3480
3481 static int
3482 api_sw_interface_get_table (vat_main_t * vam)
3483 {
3484   unformat_input_t *i = vam->input;
3485   vl_api_sw_interface_get_table_t *mp;
3486   u32 sw_if_index;
3487   u8 sw_if_index_set = 0;
3488   u8 is_ipv6 = 0;
3489   int ret;
3490
3491   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3492     {
3493       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3494         sw_if_index_set = 1;
3495       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3496         sw_if_index_set = 1;
3497       else if (unformat (i, "ipv6"))
3498         is_ipv6 = 1;
3499       else
3500         break;
3501     }
3502
3503   if (sw_if_index_set == 0)
3504     {
3505       errmsg ("missing interface name or sw_if_index");
3506       return -99;
3507     }
3508
3509   M (SW_INTERFACE_GET_TABLE, mp);
3510   mp->sw_if_index = htonl (sw_if_index);
3511   mp->is_ipv6 = is_ipv6;
3512
3513   S (mp);
3514   W (ret);
3515   return ret;
3516 }
3517
3518 static int
3519 api_sw_interface_set_vpath (vat_main_t * vam)
3520 {
3521   unformat_input_t *i = vam->input;
3522   vl_api_sw_interface_set_vpath_t *mp;
3523   u32 sw_if_index = 0;
3524   u8 sw_if_index_set = 0;
3525   u8 is_enable = 0;
3526   int ret;
3527
3528   /* Parse args required to build the message */
3529   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3530     {
3531       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3532         sw_if_index_set = 1;
3533       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3534         sw_if_index_set = 1;
3535       else if (unformat (i, "enable"))
3536         is_enable = 1;
3537       else if (unformat (i, "disable"))
3538         is_enable = 0;
3539       else
3540         break;
3541     }
3542
3543   if (sw_if_index_set == 0)
3544     {
3545       errmsg ("missing interface name or sw_if_index");
3546       return -99;
3547     }
3548
3549   /* Construct the API message */
3550   M (SW_INTERFACE_SET_VPATH, mp);
3551
3552   mp->sw_if_index = ntohl (sw_if_index);
3553   mp->enable = is_enable;
3554
3555   /* send it... */
3556   S (mp);
3557
3558   /* Wait for a reply... */
3559   W (ret);
3560   return ret;
3561 }
3562
3563 static int
3564 api_sw_interface_set_l2_xconnect (vat_main_t * vam)
3565 {
3566   unformat_input_t *i = vam->input;
3567   vl_api_sw_interface_set_l2_xconnect_t *mp;
3568   u32 rx_sw_if_index;
3569   u8 rx_sw_if_index_set = 0;
3570   u32 tx_sw_if_index;
3571   u8 tx_sw_if_index_set = 0;
3572   u8 enable = 1;
3573   int ret;
3574
3575   /* Parse args required to build the message */
3576   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3577     {
3578       if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index))
3579         rx_sw_if_index_set = 1;
3580       else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
3581         tx_sw_if_index_set = 1;
3582       else if (unformat (i, "rx"))
3583         {
3584           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3585             {
3586               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
3587                             &rx_sw_if_index))
3588                 rx_sw_if_index_set = 1;
3589             }
3590           else
3591             break;
3592         }
3593       else if (unformat (i, "tx"))
3594         {
3595           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3596             {
3597               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
3598                             &tx_sw_if_index))
3599                 tx_sw_if_index_set = 1;
3600             }
3601           else
3602             break;
3603         }
3604       else if (unformat (i, "enable"))
3605         enable = 1;
3606       else if (unformat (i, "disable"))
3607         enable = 0;
3608       else
3609         break;
3610     }
3611
3612   if (rx_sw_if_index_set == 0)
3613     {
3614       errmsg ("missing rx interface name or rx_sw_if_index");
3615       return -99;
3616     }
3617
3618   if (enable && (tx_sw_if_index_set == 0))
3619     {
3620       errmsg ("missing tx interface name or tx_sw_if_index");
3621       return -99;
3622     }
3623
3624   M (SW_INTERFACE_SET_L2_XCONNECT, mp);
3625
3626   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
3627   mp->tx_sw_if_index = ntohl (tx_sw_if_index);
3628   mp->enable = enable;
3629
3630   S (mp);
3631   W (ret);
3632   return ret;
3633 }
3634
3635 static int
3636 api_sw_interface_set_l2_bridge (vat_main_t * vam)
3637 {
3638   unformat_input_t *i = vam->input;
3639   vl_api_sw_interface_set_l2_bridge_t *mp;
3640   vl_api_l2_port_type_t port_type;
3641   u32 rx_sw_if_index;
3642   u8 rx_sw_if_index_set = 0;
3643   u32 bd_id;
3644   u8 bd_id_set = 0;
3645   u32 shg = 0;
3646   u8 enable = 1;
3647   int ret;
3648
3649   port_type = L2_API_PORT_TYPE_NORMAL;
3650
3651   /* Parse args required to build the message */
3652   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3653     {
3654       if (unformat (i, "sw_if_index %d", &rx_sw_if_index))
3655         rx_sw_if_index_set = 1;
3656       else if (unformat (i, "bd_id %d", &bd_id))
3657         bd_id_set = 1;
3658       else
3659         if (unformat
3660             (i, "%U", api_unformat_sw_if_index, vam, &rx_sw_if_index))
3661         rx_sw_if_index_set = 1;
3662       else if (unformat (i, "shg %d", &shg))
3663         ;
3664       else if (unformat (i, "bvi"))
3665         port_type = L2_API_PORT_TYPE_BVI;
3666       else if (unformat (i, "uu-fwd"))
3667         port_type = L2_API_PORT_TYPE_UU_FWD;
3668       else if (unformat (i, "enable"))
3669         enable = 1;
3670       else if (unformat (i, "disable"))
3671         enable = 0;
3672       else
3673         break;
3674     }
3675
3676   if (rx_sw_if_index_set == 0)
3677     {
3678       errmsg ("missing rx interface name or sw_if_index");
3679       return -99;
3680     }
3681
3682   if (enable && (bd_id_set == 0))
3683     {
3684       errmsg ("missing bridge domain");
3685       return -99;
3686     }
3687
3688   M (SW_INTERFACE_SET_L2_BRIDGE, mp);
3689
3690   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
3691   mp->bd_id = ntohl (bd_id);
3692   mp->shg = (u8) shg;
3693   mp->port_type = ntohl (port_type);
3694   mp->enable = enable;
3695
3696   S (mp);
3697   W (ret);
3698   return ret;
3699 }
3700
3701 static int
3702 api_bridge_domain_dump (vat_main_t * vam)
3703 {
3704   unformat_input_t *i = vam->input;
3705   vl_api_bridge_domain_dump_t *mp;
3706   vl_api_control_ping_t *mp_ping;
3707   u32 bd_id = ~0;
3708   int ret;
3709
3710   /* Parse args required to build the message */
3711   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3712     {
3713       if (unformat (i, "bd_id %d", &bd_id))
3714         ;
3715       else
3716         break;
3717     }
3718
3719   M (BRIDGE_DOMAIN_DUMP, mp);
3720   mp->bd_id = ntohl (bd_id);
3721   S (mp);
3722
3723   /* Use a control ping for synchronization */
3724   MPING (CONTROL_PING, mp_ping);
3725   S (mp_ping);
3726
3727   W (ret);
3728   return ret;
3729 }
3730
3731 static int
3732 api_bridge_domain_add_del (vat_main_t * vam)
3733 {
3734   unformat_input_t *i = vam->input;
3735   vl_api_bridge_domain_add_del_t *mp;
3736   u32 bd_id = ~0;
3737   u8 is_add = 1;
3738   u32 flood = 1, forward = 1, learn = 1, uu_flood = 1, arp_term = 0;
3739   u8 *bd_tag = NULL;
3740   u32 mac_age = 0;
3741   int ret;
3742
3743   /* Parse args required to build the message */
3744   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3745     {
3746       if (unformat (i, "bd_id %d", &bd_id))
3747         ;
3748       else if (unformat (i, "flood %d", &flood))
3749         ;
3750       else if (unformat (i, "uu-flood %d", &uu_flood))
3751         ;
3752       else if (unformat (i, "forward %d", &forward))
3753         ;
3754       else if (unformat (i, "learn %d", &learn))
3755         ;
3756       else if (unformat (i, "arp-term %d", &arp_term))
3757         ;
3758       else if (unformat (i, "mac-age %d", &mac_age))
3759         ;
3760       else if (unformat (i, "bd-tag %s", &bd_tag))
3761         ;
3762       else if (unformat (i, "del"))
3763         {
3764           is_add = 0;
3765           flood = uu_flood = forward = learn = 0;
3766         }
3767       else
3768         break;
3769     }
3770
3771   if (bd_id == ~0)
3772     {
3773       errmsg ("missing bridge domain");
3774       ret = -99;
3775       goto done;
3776     }
3777
3778   if (mac_age > 255)
3779     {
3780       errmsg ("mac age must be less than 256 ");
3781       ret = -99;
3782       goto done;
3783     }
3784
3785   if ((bd_tag) && (vec_len (bd_tag) > 63))
3786     {
3787       errmsg ("bd-tag cannot be longer than 63");
3788       ret = -99;
3789       goto done;
3790     }
3791
3792   M (BRIDGE_DOMAIN_ADD_DEL, mp);
3793
3794   mp->bd_id = ntohl (bd_id);
3795   mp->flood = flood;
3796   mp->uu_flood = uu_flood;
3797   mp->forward = forward;
3798   mp->learn = learn;
3799   mp->arp_term = arp_term;
3800   mp->is_add = is_add;
3801   mp->mac_age = (u8) mac_age;
3802   if (bd_tag)
3803     {
3804       clib_memcpy (mp->bd_tag, bd_tag, vec_len (bd_tag));
3805       mp->bd_tag[vec_len (bd_tag)] = 0;
3806     }
3807   S (mp);
3808   W (ret);
3809
3810 done:
3811   vec_free (bd_tag);
3812   return ret;
3813 }
3814
3815 static int
3816 api_l2fib_flush_bd (vat_main_t * vam)
3817 {
3818   unformat_input_t *i = vam->input;
3819   vl_api_l2fib_flush_bd_t *mp;
3820   u32 bd_id = ~0;
3821   int ret;
3822
3823   /* Parse args required to build the message */
3824   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3825     {
3826       if (unformat (i, "bd_id %d", &bd_id));
3827       else
3828         break;
3829     }
3830
3831   if (bd_id == ~0)
3832     {
3833       errmsg ("missing bridge domain");
3834       return -99;
3835     }
3836
3837   M (L2FIB_FLUSH_BD, mp);
3838
3839   mp->bd_id = htonl (bd_id);
3840
3841   S (mp);
3842   W (ret);
3843   return ret;
3844 }
3845
3846 static int
3847 api_l2fib_flush_int (vat_main_t * vam)
3848 {
3849   unformat_input_t *i = vam->input;
3850   vl_api_l2fib_flush_int_t *mp;
3851   u32 sw_if_index = ~0;
3852   int ret;
3853
3854   /* Parse args required to build the message */
3855   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3856     {
3857       if (unformat (i, "sw_if_index %d", &sw_if_index));
3858       else
3859         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index));
3860       else
3861         break;
3862     }
3863
3864   if (sw_if_index == ~0)
3865     {
3866       errmsg ("missing interface name or sw_if_index");
3867       return -99;
3868     }
3869
3870   M (L2FIB_FLUSH_INT, mp);
3871
3872   mp->sw_if_index = ntohl (sw_if_index);
3873
3874   S (mp);
3875   W (ret);
3876   return ret;
3877 }
3878
3879 static int
3880 api_l2fib_add_del (vat_main_t * vam)
3881 {
3882   unformat_input_t *i = vam->input;
3883   vl_api_l2fib_add_del_t *mp;
3884   f64 timeout;
3885   u8 mac[6] = { 0 };
3886   u8 mac_set = 0;
3887   u32 bd_id;
3888   u8 bd_id_set = 0;
3889   u32 sw_if_index = 0;
3890   u8 sw_if_index_set = 0;
3891   u8 is_add = 1;
3892   u8 static_mac = 0;
3893   u8 filter_mac = 0;
3894   u8 bvi_mac = 0;
3895   int count = 1;
3896   f64 before = 0;
3897   int j;
3898
3899   /* Parse args required to build the message */
3900   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3901     {
3902       if (unformat (i, "mac %U", unformat_ethernet_address, mac))
3903         mac_set = 1;
3904       else if (unformat (i, "bd_id %d", &bd_id))
3905         bd_id_set = 1;
3906       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3907         sw_if_index_set = 1;
3908       else if (unformat (i, "sw_if"))
3909         {
3910           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3911             {
3912               if (unformat
3913                   (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3914                 sw_if_index_set = 1;
3915             }
3916           else
3917             break;
3918         }
3919       else if (unformat (i, "static"))
3920         static_mac = 1;
3921       else if (unformat (i, "filter"))
3922         {
3923           filter_mac = 1;
3924           static_mac = 1;
3925         }
3926       else if (unformat (i, "bvi"))
3927         {
3928           bvi_mac = 1;
3929           static_mac = 1;
3930         }
3931       else if (unformat (i, "del"))
3932         is_add = 0;
3933       else if (unformat (i, "count %d", &count))
3934         ;
3935       else
3936         break;
3937     }
3938
3939   if (mac_set == 0)
3940     {
3941       errmsg ("missing mac address");
3942       return -99;
3943     }
3944
3945   if (bd_id_set == 0)
3946     {
3947       errmsg ("missing bridge domain");
3948       return -99;
3949     }
3950
3951   if (is_add && sw_if_index_set == 0 && filter_mac == 0)
3952     {
3953       errmsg ("missing interface name or sw_if_index");
3954       return -99;
3955     }
3956
3957   if (count > 1)
3958     {
3959       /* Turn on async mode */
3960       vam->async_mode = 1;
3961       vam->async_errors = 0;
3962       before = vat_time_now (vam);
3963     }
3964
3965   for (j = 0; j < count; j++)
3966     {
3967       M (L2FIB_ADD_DEL, mp);
3968
3969       clib_memcpy (mp->mac, mac, 6);
3970       mp->bd_id = ntohl (bd_id);
3971       mp->is_add = is_add;
3972       mp->sw_if_index = ntohl (sw_if_index);
3973
3974       if (is_add)
3975         {
3976           mp->static_mac = static_mac;
3977           mp->filter_mac = filter_mac;
3978           mp->bvi_mac = bvi_mac;
3979         }
3980       increment_mac_address (mac);
3981       /* send it... */
3982       S (mp);
3983     }
3984
3985   if (count > 1)
3986     {
3987       vl_api_control_ping_t *mp_ping;
3988       f64 after;
3989
3990       /* Shut off async mode */
3991       vam->async_mode = 0;
3992
3993       MPING (CONTROL_PING, mp_ping);
3994       S (mp_ping);
3995
3996       timeout = vat_time_now (vam) + 1.0;
3997       while (vat_time_now (vam) < timeout)
3998         if (vam->result_ready == 1)
3999           goto out;
4000       vam->retval = -99;
4001
4002     out:
4003       if (vam->retval == -99)
4004         errmsg ("timeout");
4005
4006       if (vam->async_errors > 0)
4007         {
4008           errmsg ("%d asynchronous errors", vam->async_errors);
4009           vam->retval = -98;
4010         }
4011       vam->async_errors = 0;
4012       after = vat_time_now (vam);
4013
4014       print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec",
4015              count, after - before, count / (after - before));
4016     }
4017   else
4018     {
4019       int ret;
4020
4021       /* Wait for a reply... */
4022       W (ret);
4023       return ret;
4024     }
4025   /* Return the good/bad news */
4026   return (vam->retval);
4027 }
4028
4029 static int
4030 api_bridge_domain_set_mac_age (vat_main_t * vam)
4031 {
4032   unformat_input_t *i = vam->input;
4033   vl_api_bridge_domain_set_mac_age_t *mp;
4034   u32 bd_id = ~0;
4035   u32 mac_age = 0;
4036   int ret;
4037
4038   /* Parse args required to build the message */
4039   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4040     {
4041       if (unformat (i, "bd_id %d", &bd_id));
4042       else if (unformat (i, "mac-age %d", &mac_age));
4043       else
4044         break;
4045     }
4046
4047   if (bd_id == ~0)
4048     {
4049       errmsg ("missing bridge domain");
4050       return -99;
4051     }
4052
4053   if (mac_age > 255)
4054     {
4055       errmsg ("mac age must be less than 256 ");
4056       return -99;
4057     }
4058
4059   M (BRIDGE_DOMAIN_SET_MAC_AGE, mp);
4060
4061   mp->bd_id = htonl (bd_id);
4062   mp->mac_age = (u8) mac_age;
4063
4064   S (mp);
4065   W (ret);
4066   return ret;
4067 }
4068
4069 static int
4070 api_l2_flags (vat_main_t * vam)
4071 {
4072   unformat_input_t *i = vam->input;
4073   vl_api_l2_flags_t *mp;
4074   u32 sw_if_index;
4075   u32 flags = 0;
4076   u8 sw_if_index_set = 0;
4077   u8 is_set = 0;
4078   int ret;
4079
4080   /* Parse args required to build the message */
4081   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4082     {
4083       if (unformat (i, "sw_if_index %d", &sw_if_index))
4084         sw_if_index_set = 1;
4085       else if (unformat (i, "sw_if"))
4086         {
4087           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4088             {
4089               if (unformat
4090                   (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4091                 sw_if_index_set = 1;
4092             }
4093           else
4094             break;
4095         }
4096       else if (unformat (i, "learn"))
4097         flags |= L2_LEARN;
4098       else if (unformat (i, "forward"))
4099         flags |= L2_FWD;
4100       else if (unformat (i, "flood"))
4101         flags |= L2_FLOOD;
4102       else if (unformat (i, "uu-flood"))
4103         flags |= L2_UU_FLOOD;
4104       else if (unformat (i, "arp-term"))
4105         flags |= L2_ARP_TERM;
4106       else if (unformat (i, "off"))
4107         is_set = 0;
4108       else if (unformat (i, "disable"))
4109         is_set = 0;
4110       else
4111         break;
4112     }
4113
4114   if (sw_if_index_set == 0)
4115     {
4116       errmsg ("missing interface name or sw_if_index");
4117       return -99;
4118     }
4119
4120   M (L2_FLAGS, mp);
4121
4122   mp->sw_if_index = ntohl (sw_if_index);
4123   mp->feature_bitmap = ntohl (flags);
4124   mp->is_set = is_set;
4125
4126   S (mp);
4127   W (ret);
4128   return ret;
4129 }
4130
4131 static int
4132 api_bridge_flags (vat_main_t * vam)
4133 {
4134   unformat_input_t *i = vam->input;
4135   vl_api_bridge_flags_t *mp;
4136   u32 bd_id;
4137   u8 bd_id_set = 0;
4138   u8 is_set = 1;
4139   bd_flags_t flags = 0;
4140   int ret;
4141
4142   /* Parse args required to build the message */
4143   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4144     {
4145       if (unformat (i, "bd_id %d", &bd_id))
4146         bd_id_set = 1;
4147       else if (unformat (i, "learn"))
4148         flags |= BRIDGE_API_FLAG_LEARN;
4149       else if (unformat (i, "forward"))
4150         flags |= BRIDGE_API_FLAG_FWD;
4151       else if (unformat (i, "flood"))
4152         flags |= BRIDGE_API_FLAG_FLOOD;
4153       else if (unformat (i, "uu-flood"))
4154         flags |= BRIDGE_API_FLAG_UU_FLOOD;
4155       else if (unformat (i, "arp-term"))
4156         flags |= BRIDGE_API_FLAG_ARP_TERM;
4157       else if (unformat (i, "off"))
4158         is_set = 0;
4159       else if (unformat (i, "disable"))
4160         is_set = 0;
4161       else
4162         break;
4163     }
4164
4165   if (bd_id_set == 0)
4166     {
4167       errmsg ("missing bridge domain");
4168       return -99;
4169     }
4170
4171   M (BRIDGE_FLAGS, mp);
4172
4173   mp->bd_id = ntohl (bd_id);
4174   mp->flags = ntohl (flags);
4175   mp->is_set = is_set;
4176
4177   S (mp);
4178   W (ret);
4179   return ret;
4180 }
4181
4182 static int
4183 api_bd_ip_mac_add_del (vat_main_t * vam)
4184 {
4185   vl_api_address_t ip = VL_API_ZERO_ADDRESS;
4186   vl_api_mac_address_t mac = { 0 };
4187   unformat_input_t *i = vam->input;
4188   vl_api_bd_ip_mac_add_del_t *mp;
4189   u32 bd_id;
4190   u8 is_add = 1;
4191   u8 bd_id_set = 0;
4192   u8 ip_set = 0;
4193   u8 mac_set = 0;
4194   int ret;
4195
4196
4197   /* Parse args required to build the message */
4198   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4199     {
4200       if (unformat (i, "bd_id %d", &bd_id))
4201         {
4202           bd_id_set++;
4203         }
4204       else if (unformat (i, "%U", unformat_vl_api_address, &ip))
4205         {
4206           ip_set++;
4207         }
4208       else if (unformat (i, "%U", unformat_vl_api_mac_address, &mac))
4209         {
4210           mac_set++;
4211         }
4212       else if (unformat (i, "del"))
4213         is_add = 0;
4214       else
4215         break;
4216     }
4217
4218   if (bd_id_set == 0)
4219     {
4220       errmsg ("missing bridge domain");
4221       return -99;
4222     }
4223   else if (ip_set == 0)
4224     {
4225       errmsg ("missing IP address");
4226       return -99;
4227     }
4228   else if (mac_set == 0)
4229     {
4230       errmsg ("missing MAC address");
4231       return -99;
4232     }
4233
4234   M (BD_IP_MAC_ADD_DEL, mp);
4235
4236   mp->entry.bd_id = ntohl (bd_id);
4237   mp->is_add = is_add;
4238
4239   clib_memcpy (&mp->entry.ip, &ip, sizeof (ip));
4240   clib_memcpy (&mp->entry.mac, &mac, sizeof (mac));
4241
4242   S (mp);
4243   W (ret);
4244   return ret;
4245 }
4246
4247 static int
4248 api_bd_ip_mac_flush (vat_main_t * vam)
4249 {
4250   unformat_input_t *i = vam->input;
4251   vl_api_bd_ip_mac_flush_t *mp;
4252   u32 bd_id;
4253   u8 bd_id_set = 0;
4254   int ret;
4255
4256   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4257     {
4258       if (unformat (i, "bd_id %d", &bd_id))
4259         {
4260           bd_id_set++;
4261         }
4262       else
4263         break;
4264     }
4265
4266   if (bd_id_set == 0)
4267     {
4268       errmsg ("missing bridge domain");
4269       return -99;
4270     }
4271
4272   M (BD_IP_MAC_FLUSH, mp);
4273
4274   mp->bd_id = ntohl (bd_id);
4275
4276   S (mp);
4277   W (ret);
4278   return ret;
4279 }
4280
4281 static void vl_api_bd_ip_mac_details_t_handler
4282   (vl_api_bd_ip_mac_details_t * mp)
4283 {
4284   vat_main_t *vam = &vat_main;
4285
4286   print (vam->ofp,
4287          "\n%-5d %U %U",
4288          ntohl (mp->entry.bd_id),
4289          format_vl_api_mac_address, mp->entry.mac,
4290          format_vl_api_address, &mp->entry.ip);
4291 }
4292
4293 static void vl_api_bd_ip_mac_details_t_handler_json
4294   (vl_api_bd_ip_mac_details_t * mp)
4295 {
4296   vat_main_t *vam = &vat_main;
4297   vat_json_node_t *node = NULL;
4298
4299   if (VAT_JSON_ARRAY != vam->json_tree.type)
4300     {
4301       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
4302       vat_json_init_array (&vam->json_tree);
4303     }
4304   node = vat_json_array_add (&vam->json_tree);
4305
4306   vat_json_init_object (node);
4307   vat_json_object_add_uint (node, "bd_id", ntohl (mp->entry.bd_id));
4308   vat_json_object_add_string_copy (node, "mac_address",
4309                                    format (0, "%U", format_vl_api_mac_address,
4310                                            &mp->entry.mac));
4311   u8 *ip = 0;
4312
4313   ip = format (0, "%U", format_vl_api_address, &mp->entry.ip);
4314   vat_json_object_add_string_copy (node, "ip_address", ip);
4315   vec_free (ip);
4316 }
4317
4318 static int
4319 api_bd_ip_mac_dump (vat_main_t * vam)
4320 {
4321   unformat_input_t *i = vam->input;
4322   vl_api_bd_ip_mac_dump_t *mp;
4323   vl_api_control_ping_t *mp_ping;
4324   int ret;
4325   u32 bd_id;
4326   u8 bd_id_set = 0;
4327
4328   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4329     {
4330       if (unformat (i, "bd_id %d", &bd_id))
4331         {
4332           bd_id_set++;
4333         }
4334       else
4335         break;
4336     }
4337
4338   print (vam->ofp,
4339          "\n%-5s %-7s %-20s %-30s",
4340          "bd_id", "is_ipv6", "mac_address", "ip_address");
4341
4342   /* Dump Bridge Domain Ip to Mac entries */
4343   M (BD_IP_MAC_DUMP, mp);
4344
4345   if (bd_id_set)
4346     mp->bd_id = htonl (bd_id);
4347   else
4348     mp->bd_id = ~0;
4349
4350   S (mp);
4351
4352   /* Use a control ping for synchronization */
4353   MPING (CONTROL_PING, mp_ping);
4354   S (mp_ping);
4355
4356   W (ret);
4357   return ret;
4358 }
4359
4360 static int
4361 api_tap_create_v2 (vat_main_t * vam)
4362 {
4363   unformat_input_t *i = vam->input;
4364   vl_api_tap_create_v2_t *mp;
4365   u8 mac_address[6];
4366   u8 random_mac = 1;
4367   u32 id = ~0;
4368   u32 num_rx_queues = 0;
4369   u8 *host_if_name = 0;
4370   u8 host_if_name_set = 0;
4371   u8 *host_ns = 0;
4372   u8 host_ns_set = 0;
4373   u8 host_mac_addr[6];
4374   u8 host_mac_addr_set = 0;
4375   u8 *host_bridge = 0;
4376   u8 host_bridge_set = 0;
4377   u8 host_ip4_prefix_set = 0;
4378   u8 host_ip6_prefix_set = 0;
4379   ip4_address_t host_ip4_addr;
4380   ip4_address_t host_ip4_gw;
4381   u8 host_ip4_gw_set = 0;
4382   u32 host_ip4_prefix_len = 0;
4383   ip6_address_t host_ip6_addr;
4384   ip6_address_t host_ip6_gw;
4385   u8 host_ip6_gw_set = 0;
4386   u32 host_ip6_prefix_len = 0;
4387   u32 host_mtu_size = 0;
4388   u8 host_mtu_set = 0;
4389   u32 tap_flags = 0;
4390   int ret;
4391   u32 rx_ring_sz = 0, tx_ring_sz = 0;
4392
4393   clib_memset (mac_address, 0, sizeof (mac_address));
4394
4395   /* Parse args required to build the message */
4396   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4397     {
4398       if (unformat (i, "id %u", &id))
4399         ;
4400       else
4401         if (unformat
4402             (i, "hw-addr %U", unformat_ethernet_address, mac_address))
4403         random_mac = 0;
4404       else if (unformat (i, "host-if-name %s", &host_if_name))
4405         host_if_name_set = 1;
4406       else if (unformat (i, "num-rx-queues %u", &num_rx_queues))
4407         ;
4408       else if (unformat (i, "host-ns %s", &host_ns))
4409         host_ns_set = 1;
4410       else if (unformat (i, "host-mac-addr %U", unformat_ethernet_address,
4411                          host_mac_addr))
4412         host_mac_addr_set = 1;
4413       else if (unformat (i, "host-bridge %s", &host_bridge))
4414         host_bridge_set = 1;
4415       else if (unformat (i, "host-ip4-addr %U/%u", unformat_ip4_address,
4416                          &host_ip4_addr, &host_ip4_prefix_len))
4417         host_ip4_prefix_set = 1;
4418       else if (unformat (i, "host-ip6-addr %U/%u", unformat_ip6_address,
4419                          &host_ip6_addr, &host_ip6_prefix_len))
4420         host_ip6_prefix_set = 1;
4421       else if (unformat (i, "host-ip4-gw %U", unformat_ip4_address,
4422                          &host_ip4_gw))
4423         host_ip4_gw_set = 1;
4424       else if (unformat (i, "host-ip6-gw %U", unformat_ip6_address,
4425                          &host_ip6_gw))
4426         host_ip6_gw_set = 1;
4427       else if (unformat (i, "rx-ring-size %u", &rx_ring_sz))
4428         ;
4429       else if (unformat (i, "tx-ring-size %u", &tx_ring_sz))
4430         ;
4431       else if (unformat (i, "host-mtu-size %u", &host_mtu_size))
4432         host_mtu_set = 1;
4433       else if (unformat (i, "no-gso"))
4434         tap_flags &= ~TAP_API_FLAG_GSO;
4435       else if (unformat (i, "gso"))
4436         tap_flags |= TAP_API_FLAG_GSO;
4437       else if (unformat (i, "csum-offload"))
4438         tap_flags |= TAP_API_FLAG_CSUM_OFFLOAD;
4439       else if (unformat (i, "persist"))
4440         tap_flags |= TAP_API_FLAG_PERSIST;
4441       else if (unformat (i, "attach"))
4442         tap_flags |= TAP_API_FLAG_ATTACH;
4443       else if (unformat (i, "tun"))
4444         tap_flags |= TAP_API_FLAG_TUN;
4445       else if (unformat (i, "gro-coalesce"))
4446         tap_flags |= TAP_API_FLAG_GRO_COALESCE;
4447       else if (unformat (i, "packed"))
4448         tap_flags |= TAP_API_FLAG_PACKED;
4449       else if (unformat (i, "in-order"))
4450         tap_flags |= TAP_API_FLAG_IN_ORDER;
4451       else
4452         break;
4453     }
4454
4455   if (vec_len (host_if_name) > 63)
4456     {
4457       errmsg ("tap name too long. ");
4458       return -99;
4459     }
4460   if (vec_len (host_ns) > 63)
4461     {
4462       errmsg ("host name space too long. ");
4463       return -99;
4464     }
4465   if (vec_len (host_bridge) > 63)
4466     {
4467       errmsg ("host bridge name too long. ");
4468       return -99;
4469     }
4470   if (host_ip4_prefix_len > 32)
4471     {
4472       errmsg ("host ip4 prefix length not valid. ");
4473       return -99;
4474     }
4475   if (host_ip6_prefix_len > 128)
4476     {
4477       errmsg ("host ip6 prefix length not valid. ");
4478       return -99;
4479     }
4480   if (!is_pow2 (rx_ring_sz))
4481     {
4482       errmsg ("rx ring size must be power of 2. ");
4483       return -99;
4484     }
4485   if (rx_ring_sz > 32768)
4486     {
4487       errmsg ("rx ring size must be 32768 or lower. ");
4488       return -99;
4489     }
4490   if (!is_pow2 (tx_ring_sz))
4491     {
4492       errmsg ("tx ring size must be power of 2. ");
4493       return -99;
4494     }
4495   if (tx_ring_sz > 32768)
4496     {
4497       errmsg ("tx ring size must be 32768 or lower. ");
4498       return -99;
4499     }
4500   if (host_mtu_set && (host_mtu_size < 64 || host_mtu_size > 65355))
4501     {
4502       errmsg ("host MTU size must be in between 64 and 65355. ");
4503       return -99;
4504     }
4505
4506   /* Construct the API message */
4507   M (TAP_CREATE_V2, mp);
4508
4509   mp->id = ntohl (id);
4510   mp->use_random_mac = random_mac;
4511   mp->num_rx_queues = (u8) num_rx_queues;
4512   mp->tx_ring_sz = ntohs (tx_ring_sz);
4513   mp->rx_ring_sz = ntohs (rx_ring_sz);
4514   mp->host_mtu_set = host_mtu_set;
4515   mp->host_mtu_size = ntohl (host_mtu_size);
4516   mp->host_mac_addr_set = host_mac_addr_set;
4517   mp->host_ip4_prefix_set = host_ip4_prefix_set;
4518   mp->host_ip6_prefix_set = host_ip6_prefix_set;
4519   mp->host_ip4_gw_set = host_ip4_gw_set;
4520   mp->host_ip6_gw_set = host_ip6_gw_set;
4521   mp->tap_flags = ntohl (tap_flags);
4522   mp->host_namespace_set = host_ns_set;
4523   mp->host_if_name_set = host_if_name_set;
4524   mp->host_bridge_set = host_bridge_set;
4525
4526   if (random_mac == 0)
4527     clib_memcpy (mp->mac_address, mac_address, 6);
4528   if (host_mac_addr_set)
4529     clib_memcpy (mp->host_mac_addr, host_mac_addr, 6);
4530   if (host_if_name_set)
4531     clib_memcpy (mp->host_if_name, host_if_name, vec_len (host_if_name));
4532   if (host_ns_set)
4533     clib_memcpy (mp->host_namespace, host_ns, vec_len (host_ns));
4534   if (host_bridge_set)
4535     clib_memcpy (mp->host_bridge, host_bridge, vec_len (host_bridge));
4536   if (host_ip4_prefix_set)
4537     {
4538       clib_memcpy (mp->host_ip4_prefix.address, &host_ip4_addr, 4);
4539       mp->host_ip4_prefix.len = (u8) host_ip4_prefix_len;
4540     }
4541   if (host_ip6_prefix_set)
4542     {
4543       clib_memcpy (mp->host_ip6_prefix.address, &host_ip6_addr, 16);
4544       mp->host_ip6_prefix.len = (u8) host_ip6_prefix_len;
4545     }
4546   if (host_ip4_gw_set)
4547     clib_memcpy (mp->host_ip4_gw, &host_ip4_gw, 4);
4548   if (host_ip6_gw_set)
4549     clib_memcpy (mp->host_ip6_gw, &host_ip6_gw, 16);
4550
4551   vec_free (host_ns);
4552   vec_free (host_if_name);
4553   vec_free (host_bridge);
4554
4555   /* send it... */
4556   S (mp);
4557
4558   /* Wait for a reply... */
4559   W (ret);
4560   return ret;
4561 }
4562
4563 static int
4564 api_tap_delete_v2 (vat_main_t * vam)
4565 {
4566   unformat_input_t *i = vam->input;
4567   vl_api_tap_delete_v2_t *mp;
4568   u32 sw_if_index = ~0;
4569   u8 sw_if_index_set = 0;
4570   int ret;
4571
4572   /* Parse args required to build the message */
4573   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4574     {
4575       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4576         sw_if_index_set = 1;
4577       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4578         sw_if_index_set = 1;
4579       else
4580         break;
4581     }
4582
4583   if (sw_if_index_set == 0)
4584     {
4585       errmsg ("missing vpp interface name. ");
4586       return -99;
4587     }
4588
4589   /* Construct the API message */
4590   M (TAP_DELETE_V2, mp);
4591
4592   mp->sw_if_index = ntohl (sw_if_index);
4593
4594   /* send it... */
4595   S (mp);
4596
4597   /* Wait for a reply... */
4598   W (ret);
4599   return ret;
4600 }
4601
4602 uword
4603 unformat_vlib_pci_addr (unformat_input_t * input, va_list * args)
4604 {
4605   vlib_pci_addr_t *addr = va_arg (*args, vlib_pci_addr_t *);
4606   u32 x[4];
4607
4608   if (!unformat (input, "%x:%x:%x.%x", &x[0], &x[1], &x[2], &x[3]))
4609     return 0;
4610
4611   addr->domain = x[0];
4612   addr->bus = x[1];
4613   addr->slot = x[2];
4614   addr->function = x[3];
4615
4616   return 1;
4617 }
4618
4619 static int
4620 api_virtio_pci_create_v2 (vat_main_t * vam)
4621 {
4622   unformat_input_t *i = vam->input;
4623   vl_api_virtio_pci_create_v2_t *mp;
4624   u8 mac_address[6];
4625   u8 random_mac = 1;
4626   u32 pci_addr = 0;
4627   u64 features = (u64) ~ (0ULL);
4628   u32 virtio_flags = 0;
4629   int ret;
4630
4631   clib_memset (mac_address, 0, sizeof (mac_address));
4632
4633   /* Parse args required to build the message */
4634   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4635     {
4636       if (unformat (i, "hw-addr %U", unformat_ethernet_address, mac_address))
4637         {
4638           random_mac = 0;
4639         }
4640       else if (unformat (i, "pci-addr %U", unformat_vlib_pci_addr, &pci_addr))
4641         ;
4642       else if (unformat (i, "features 0x%llx", &features))
4643         ;
4644       else if (unformat (i, "gso-enabled"))
4645         virtio_flags |= VIRTIO_API_FLAG_GSO;
4646       else if (unformat (i, "csum-offload-enabled"))
4647         virtio_flags |= VIRTIO_API_FLAG_CSUM_OFFLOAD;
4648       else if (unformat (i, "gro-coalesce"))
4649         virtio_flags |= VIRTIO_API_FLAG_GRO_COALESCE;
4650       else if (unformat (i, "packed"))
4651         virtio_flags |= VIRTIO_API_FLAG_PACKED;
4652       else if (unformat (i, "in-order"))
4653         virtio_flags |= VIRTIO_API_FLAG_IN_ORDER;
4654       else if (unformat (i, "buffering"))
4655         virtio_flags |= VIRTIO_API_FLAG_BUFFERING;
4656       else
4657         break;
4658     }
4659
4660   if (pci_addr == 0)
4661     {
4662       errmsg ("pci address must be non zero. ");
4663       return -99;
4664     }
4665
4666   /* Construct the API message */
4667   M (VIRTIO_PCI_CREATE_V2, mp);
4668
4669   mp->use_random_mac = random_mac;
4670
4671   mp->pci_addr.domain = htons (((vlib_pci_addr_t) pci_addr).domain);
4672   mp->pci_addr.bus = ((vlib_pci_addr_t) pci_addr).bus;
4673   mp->pci_addr.slot = ((vlib_pci_addr_t) pci_addr).slot;
4674   mp->pci_addr.function = ((vlib_pci_addr_t) pci_addr).function;
4675
4676   mp->features = clib_host_to_net_u64 (features);
4677   mp->virtio_flags = clib_host_to_net_u32 (virtio_flags);
4678
4679   if (random_mac == 0)
4680     clib_memcpy (mp->mac_address, mac_address, 6);
4681
4682   /* send it... */
4683   S (mp);
4684
4685   /* Wait for a reply... */
4686   W (ret);
4687   return ret;
4688 }
4689
4690 static int
4691 api_virtio_pci_delete (vat_main_t * vam)
4692 {
4693   unformat_input_t *i = vam->input;
4694   vl_api_virtio_pci_delete_t *mp;
4695   u32 sw_if_index = ~0;
4696   u8 sw_if_index_set = 0;
4697   int ret;
4698
4699   /* Parse args required to build the message */
4700   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4701     {
4702       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4703         sw_if_index_set = 1;
4704       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4705         sw_if_index_set = 1;
4706       else
4707         break;
4708     }
4709
4710   if (sw_if_index_set == 0)
4711     {
4712       errmsg ("missing vpp interface name. ");
4713       return -99;
4714     }
4715
4716   /* Construct the API message */
4717   M (VIRTIO_PCI_DELETE, mp);
4718
4719   mp->sw_if_index = htonl (sw_if_index);
4720
4721   /* send it... */
4722   S (mp);
4723
4724   /* Wait for a reply... */
4725   W (ret);
4726   return ret;
4727 }
4728
4729 static int
4730 api_bond_create (vat_main_t * vam)
4731 {
4732   unformat_input_t *i = vam->input;
4733   vl_api_bond_create_t *mp;
4734   u8 mac_address[6];
4735   u8 custom_mac = 0;
4736   int ret;
4737   u8 mode;
4738   u8 lb;
4739   u8 mode_is_set = 0;
4740   u32 id = ~0;
4741   u8 numa_only = 0;
4742
4743   clib_memset (mac_address, 0, sizeof (mac_address));
4744   lb = BOND_LB_L2;
4745
4746   /* Parse args required to build the message */
4747   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4748     {
4749       if (unformat (i, "mode %U", unformat_bond_mode, &mode))
4750         mode_is_set = 1;
4751       else if (((mode == BOND_MODE_LACP) || (mode == BOND_MODE_XOR))
4752                && unformat (i, "lb %U", unformat_bond_load_balance, &lb))
4753         ;
4754       else if (unformat (i, "hw-addr %U", unformat_ethernet_address,
4755                          mac_address))
4756         custom_mac = 1;
4757       else if (unformat (i, "numa-only"))
4758         numa_only = 1;
4759       else if (unformat (i, "id %u", &id))
4760         ;
4761       else
4762         break;
4763     }
4764
4765   if (mode_is_set == 0)
4766     {
4767       errmsg ("Missing bond mode. ");
4768       return -99;
4769     }
4770
4771   /* Construct the API message */
4772   M (BOND_CREATE, mp);
4773
4774   mp->use_custom_mac = custom_mac;
4775
4776   mp->mode = htonl (mode);
4777   mp->lb = htonl (lb);
4778   mp->id = htonl (id);
4779   mp->numa_only = numa_only;
4780
4781   if (custom_mac)
4782     clib_memcpy (mp->mac_address, mac_address, 6);
4783
4784   /* send it... */
4785   S (mp);
4786
4787   /* Wait for a reply... */
4788   W (ret);
4789   return ret;
4790 }
4791
4792 static int
4793 api_bond_create2 (vat_main_t * vam)
4794 {
4795   unformat_input_t *i = vam->input;
4796   vl_api_bond_create2_t *mp;
4797   u8 mac_address[6];
4798   u8 custom_mac = 0;
4799   int ret;
4800   u8 mode;
4801   u8 lb;
4802   u8 mode_is_set = 0;
4803   u32 id = ~0;
4804   u8 numa_only = 0;
4805   u8 gso = 0;
4806
4807   clib_memset (mac_address, 0, sizeof (mac_address));
4808   lb = BOND_LB_L2;
4809
4810   /* Parse args required to build the message */
4811   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4812     {
4813       if (unformat (i, "mode %U", unformat_bond_mode, &mode))
4814         mode_is_set = 1;
4815       else if (((mode == BOND_MODE_LACP) || (mode == BOND_MODE_XOR))
4816                && unformat (i, "lb %U", unformat_bond_load_balance, &lb))
4817         ;
4818       else if (unformat (i, "hw-addr %U", unformat_ethernet_address,
4819                          mac_address))
4820         custom_mac = 1;
4821       else if (unformat (i, "numa-only"))
4822         numa_only = 1;
4823       else if (unformat (i, "gso"))
4824         gso = 1;
4825       else if (unformat (i, "id %u", &id))
4826         ;
4827       else
4828         break;
4829     }
4830
4831   if (mode_is_set == 0)
4832     {
4833       errmsg ("Missing bond mode. ");
4834       return -99;
4835     }
4836
4837   /* Construct the API message */
4838   M (BOND_CREATE2, mp);
4839
4840   mp->use_custom_mac = custom_mac;
4841
4842   mp->mode = htonl (mode);
4843   mp->lb = htonl (lb);
4844   mp->id = htonl (id);
4845   mp->numa_only = numa_only;
4846   mp->enable_gso = gso;
4847
4848   if (custom_mac)
4849     clib_memcpy (mp->mac_address, mac_address, 6);
4850
4851   /* send it... */
4852   S (mp);
4853
4854   /* Wait for a reply... */
4855   W (ret);
4856   return ret;
4857 }
4858
4859 static int
4860 api_bond_delete (vat_main_t * vam)
4861 {
4862   unformat_input_t *i = vam->input;
4863   vl_api_bond_delete_t *mp;
4864   u32 sw_if_index = ~0;
4865   u8 sw_if_index_set = 0;
4866   int ret;
4867
4868   /* Parse args required to build the message */
4869   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4870     {
4871       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4872         sw_if_index_set = 1;
4873       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4874         sw_if_index_set = 1;
4875       else
4876         break;
4877     }
4878
4879   if (sw_if_index_set == 0)
4880     {
4881       errmsg ("missing vpp interface name. ");
4882       return -99;
4883     }
4884
4885   /* Construct the API message */
4886   M (BOND_DELETE, mp);
4887
4888   mp->sw_if_index = ntohl (sw_if_index);
4889
4890   /* send it... */
4891   S (mp);
4892
4893   /* Wait for a reply... */
4894   W (ret);
4895   return ret;
4896 }
4897
4898 static int
4899 api_bond_add_member (vat_main_t * vam)
4900 {
4901   unformat_input_t *i = vam->input;
4902   vl_api_bond_add_member_t *mp;
4903   u32 bond_sw_if_index;
4904   int ret;
4905   u8 is_passive;
4906   u8 is_long_timeout;
4907   u32 bond_sw_if_index_is_set = 0;
4908   u32 sw_if_index;
4909   u8 sw_if_index_is_set = 0;
4910
4911   /* Parse args required to build the message */
4912   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4913     {
4914       if (unformat (i, "sw_if_index %d", &sw_if_index))
4915         sw_if_index_is_set = 1;
4916       else if (unformat (i, "bond %u", &bond_sw_if_index))
4917         bond_sw_if_index_is_set = 1;
4918       else if (unformat (i, "passive %d", &is_passive))
4919         ;
4920       else if (unformat (i, "long-timeout %d", &is_long_timeout))
4921         ;
4922       else
4923         break;
4924     }
4925
4926   if (bond_sw_if_index_is_set == 0)
4927     {
4928       errmsg ("Missing bond sw_if_index. ");
4929       return -99;
4930     }
4931   if (sw_if_index_is_set == 0)
4932     {
4933       errmsg ("Missing member sw_if_index. ");
4934       return -99;
4935     }
4936
4937   /* Construct the API message */
4938   M (BOND_ADD_MEMBER, mp);
4939
4940   mp->bond_sw_if_index = ntohl (bond_sw_if_index);
4941   mp->sw_if_index = ntohl (sw_if_index);
4942   mp->is_long_timeout = is_long_timeout;
4943   mp->is_passive = is_passive;
4944
4945   /* send it... */
4946   S (mp);
4947
4948   /* Wait for a reply... */
4949   W (ret);
4950   return ret;
4951 }
4952
4953 static int
4954 api_bond_detach_member (vat_main_t * vam)
4955 {
4956   unformat_input_t *i = vam->input;
4957   vl_api_bond_detach_member_t *mp;
4958   u32 sw_if_index = ~0;
4959   u8 sw_if_index_set = 0;
4960   int ret;
4961
4962   /* Parse args required to build the message */
4963   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4964     {
4965       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4966         sw_if_index_set = 1;
4967       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4968         sw_if_index_set = 1;
4969       else
4970         break;
4971     }
4972
4973   if (sw_if_index_set == 0)
4974     {
4975       errmsg ("missing vpp interface name. ");
4976       return -99;
4977     }
4978
4979   /* Construct the API message */
4980   M (BOND_DETACH_MEMBER, mp);
4981
4982   mp->sw_if_index = ntohl (sw_if_index);
4983
4984   /* send it... */
4985   S (mp);
4986
4987   /* Wait for a reply... */
4988   W (ret);
4989   return ret;
4990 }
4991
4992 static int
4993 api_ip_table_add_del (vat_main_t * vam)
4994 {
4995   unformat_input_t *i = vam->input;
4996   vl_api_ip_table_add_del_t *mp;
4997   u32 table_id = ~0;
4998   u8 is_ipv6 = 0;
4999   u8 is_add = 1;
5000   int ret = 0;
5001
5002   /* Parse args required to build the message */
5003   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5004     {
5005       if (unformat (i, "ipv6"))
5006         is_ipv6 = 1;
5007       else if (unformat (i, "del"))
5008         is_add = 0;
5009       else if (unformat (i, "add"))
5010         is_add = 1;
5011       else if (unformat (i, "table %d", &table_id))
5012         ;
5013       else
5014         {
5015           clib_warning ("parse error '%U'", format_unformat_error, i);
5016           return -99;
5017         }
5018     }
5019
5020   if (~0 == table_id)
5021     {
5022       errmsg ("missing table-ID");
5023       return -99;
5024     }
5025
5026   /* Construct the API message */
5027   M (IP_TABLE_ADD_DEL, mp);
5028
5029   mp->table.table_id = ntohl (table_id);
5030   mp->table.is_ip6 = is_ipv6;
5031   mp->is_add = is_add;
5032
5033   /* send it... */
5034   S (mp);
5035
5036   /* Wait for a reply... */
5037   W (ret);
5038
5039   return ret;
5040 }
5041
5042 uword
5043 unformat_fib_path (unformat_input_t * input, va_list * args)
5044 {
5045   vat_main_t *vam = va_arg (*args, vat_main_t *);
5046   vl_api_fib_path_t *path = va_arg (*args, vl_api_fib_path_t *);
5047   u32 weight, preference;
5048   mpls_label_t out_label;
5049
5050   clib_memset (path, 0, sizeof (*path));
5051   path->weight = 1;
5052   path->sw_if_index = ~0;
5053   path->rpf_id = ~0;
5054   path->n_labels = 0;
5055
5056   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5057     {
5058       if (unformat (input, "%U %U",
5059                     unformat_vl_api_ip4_address,
5060                     &path->nh.address.ip4,
5061                     api_unformat_sw_if_index, vam, &path->sw_if_index))
5062         {
5063           path->proto = FIB_API_PATH_NH_PROTO_IP4;
5064         }
5065       else if (unformat (input, "%U %U",
5066                          unformat_vl_api_ip6_address,
5067                          &path->nh.address.ip6,
5068                          api_unformat_sw_if_index, vam, &path->sw_if_index))
5069         {
5070           path->proto = FIB_API_PATH_NH_PROTO_IP6;
5071         }
5072       else if (unformat (input, "weight %u", &weight))
5073         {
5074           path->weight = weight;
5075         }
5076       else if (unformat (input, "preference %u", &preference))
5077         {
5078           path->preference = preference;
5079         }
5080       else if (unformat (input, "%U next-hop-table %d",
5081                          unformat_vl_api_ip4_address,
5082                          &path->nh.address.ip4, &path->table_id))
5083         {
5084           path->proto = FIB_API_PATH_NH_PROTO_IP4;
5085         }
5086       else if (unformat (input, "%U next-hop-table %d",
5087                          unformat_vl_api_ip6_address,
5088                          &path->nh.address.ip6, &path->table_id))
5089         {
5090           path->proto = FIB_API_PATH_NH_PROTO_IP6;
5091         }
5092       else if (unformat (input, "%U",
5093                          unformat_vl_api_ip4_address, &path->nh.address.ip4))
5094         {
5095           /*
5096            * the recursive next-hops are by default in the default table
5097            */
5098           path->table_id = 0;
5099           path->sw_if_index = ~0;
5100           path->proto = FIB_API_PATH_NH_PROTO_IP4;
5101         }
5102       else if (unformat (input, "%U",
5103                          unformat_vl_api_ip6_address, &path->nh.address.ip6))
5104         {
5105           /*
5106            * the recursive next-hops are by default in the default table
5107            */
5108           path->table_id = 0;
5109           path->sw_if_index = ~0;
5110           path->proto = FIB_API_PATH_NH_PROTO_IP6;
5111         }
5112       else if (unformat (input, "resolve-via-host"))
5113         {
5114           path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_HOST;
5115         }
5116       else if (unformat (input, "resolve-via-attached"))
5117         {
5118           path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_ATTACHED;
5119         }
5120       else if (unformat (input, "ip4-lookup-in-table %d", &path->table_id))
5121         {
5122           path->type = FIB_API_PATH_TYPE_LOCAL;
5123           path->sw_if_index = ~0;
5124           path->proto = FIB_API_PATH_NH_PROTO_IP4;
5125         }
5126       else if (unformat (input, "ip6-lookup-in-table %d", &path->table_id))
5127         {
5128           path->type = FIB_API_PATH_TYPE_LOCAL;
5129           path->sw_if_index = ~0;
5130           path->proto = FIB_API_PATH_NH_PROTO_IP6;
5131         }
5132       else if (unformat (input, "sw_if_index %d", &path->sw_if_index))
5133         ;
5134       else if (unformat (input, "via-label %d", &path->nh.via_label))
5135         {
5136           path->proto = FIB_API_PATH_NH_PROTO_MPLS;
5137           path->sw_if_index = ~0;
5138         }
5139       else if (unformat (input, "l2-input-on %d", &path->sw_if_index))
5140         {
5141           path->proto = FIB_API_PATH_NH_PROTO_ETHERNET;
5142           path->type = FIB_API_PATH_TYPE_INTERFACE_RX;
5143         }
5144       else if (unformat (input, "local"))
5145         {
5146           path->type = FIB_API_PATH_TYPE_LOCAL;
5147         }
5148       else if (unformat (input, "out-labels"))
5149         {
5150           while (unformat (input, "%d", &out_label))
5151             {
5152               path->label_stack[path->n_labels].label = out_label;
5153               path->label_stack[path->n_labels].is_uniform = 0;
5154               path->label_stack[path->n_labels].ttl = 64;
5155               path->n_labels++;
5156             }
5157         }
5158       else if (unformat (input, "via"))
5159         {
5160           /* new path, back up and return */
5161           unformat_put_input (input);
5162           unformat_put_input (input);
5163           unformat_put_input (input);
5164           unformat_put_input (input);
5165           break;
5166         }
5167       else
5168         {
5169           return (0);
5170         }
5171     }
5172
5173   path->proto = ntohl (path->proto);
5174   path->type = ntohl (path->type);
5175   path->flags = ntohl (path->flags);
5176   path->table_id = ntohl (path->table_id);
5177   path->sw_if_index = ntohl (path->sw_if_index);
5178
5179   return (1);
5180 }
5181
5182 static int
5183 api_ip_route_add_del (vat_main_t * vam)
5184 {
5185   unformat_input_t *i = vam->input;
5186   vl_api_ip_route_add_del_t *mp;
5187   u32 vrf_id = 0;
5188   u8 is_add = 1;
5189   u8 is_multipath = 0;
5190   u8 prefix_set = 0;
5191   u8 path_count = 0;
5192   vl_api_prefix_t pfx = { };
5193   vl_api_fib_path_t paths[8];
5194   int count = 1;
5195   int j;
5196   f64 before = 0;
5197   u32 random_add_del = 0;
5198   u32 *random_vector = 0;
5199   u32 random_seed = 0xdeaddabe;
5200
5201   /* Parse args required to build the message */
5202   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5203     {
5204       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
5205         prefix_set = 1;
5206       else if (unformat (i, "del"))
5207         is_add = 0;
5208       else if (unformat (i, "add"))
5209         is_add = 1;
5210       else if (unformat (i, "vrf %d", &vrf_id))
5211         ;
5212       else if (unformat (i, "count %d", &count))
5213         ;
5214       else if (unformat (i, "random"))
5215         random_add_del = 1;
5216       else if (unformat (i, "multipath"))
5217         is_multipath = 1;
5218       else if (unformat (i, "seed %d", &random_seed))
5219         ;
5220       else
5221         if (unformat
5222             (i, "via %U", unformat_fib_path, vam, &paths[path_count]))
5223         {
5224           path_count++;
5225           if (8 == path_count)
5226             {
5227               errmsg ("max 8 paths");
5228               return -99;
5229             }
5230         }
5231       else
5232         {
5233           clib_warning ("parse error '%U'", format_unformat_error, i);
5234           return -99;
5235         }
5236     }
5237
5238   if (!path_count)
5239     {
5240       errmsg ("specify a path; via ...");
5241       return -99;
5242     }
5243   if (prefix_set == 0)
5244     {
5245       errmsg ("missing prefix");
5246       return -99;
5247     }
5248
5249   /* Generate a pile of unique, random routes */
5250   if (random_add_del)
5251     {
5252       ip4_address_t *i = (ip4_address_t *) & paths[0].nh.address.ip4;
5253       u32 this_random_address;
5254       uword *random_hash;
5255
5256       random_hash = hash_create (count, sizeof (uword));
5257
5258       hash_set (random_hash, i->as_u32, 1);
5259       for (j = 0; j <= count; j++)
5260         {
5261           do
5262             {
5263               this_random_address = random_u32 (&random_seed);
5264               this_random_address =
5265                 clib_host_to_net_u32 (this_random_address);
5266             }
5267           while (hash_get (random_hash, this_random_address));
5268           vec_add1 (random_vector, this_random_address);
5269           hash_set (random_hash, this_random_address, 1);
5270         }
5271       hash_free (random_hash);
5272       set_ip4_address (&pfx.address, random_vector[0]);
5273     }
5274
5275   if (count > 1)
5276     {
5277       /* Turn on async mode */
5278       vam->async_mode = 1;
5279       vam->async_errors = 0;
5280       before = vat_time_now (vam);
5281     }
5282
5283   for (j = 0; j < count; j++)
5284     {
5285       /* Construct the API message */
5286       M2 (IP_ROUTE_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
5287
5288       mp->is_add = is_add;
5289       mp->is_multipath = is_multipath;
5290
5291       clib_memcpy (&mp->route.prefix, &pfx, sizeof (pfx));
5292       mp->route.table_id = ntohl (vrf_id);
5293       mp->route.n_paths = path_count;
5294
5295       clib_memcpy (&mp->route.paths, &paths, sizeof (paths[0]) * path_count);
5296
5297       if (random_add_del)
5298         set_ip4_address (&pfx.address, random_vector[j + 1]);
5299       else
5300         increment_address (&pfx.address);
5301       /* send it... */
5302       S (mp);
5303       /* If we receive SIGTERM, stop now... */
5304       if (vam->do_exit)
5305         break;
5306     }
5307
5308   /* When testing multiple add/del ops, use a control-ping to sync */
5309   if (count > 1)
5310     {
5311       vl_api_control_ping_t *mp_ping;
5312       f64 after;
5313       f64 timeout;
5314
5315       /* Shut off async mode */
5316       vam->async_mode = 0;
5317
5318       MPING (CONTROL_PING, mp_ping);
5319       S (mp_ping);
5320
5321       timeout = vat_time_now (vam) + 1.0;
5322       while (vat_time_now (vam) < timeout)
5323         if (vam->result_ready == 1)
5324           goto out;
5325       vam->retval = -99;
5326
5327     out:
5328       if (vam->retval == -99)
5329         errmsg ("timeout");
5330
5331       if (vam->async_errors > 0)
5332         {
5333           errmsg ("%d asynchronous errors", vam->async_errors);
5334           vam->retval = -98;
5335         }
5336       vam->async_errors = 0;
5337       after = vat_time_now (vam);
5338
5339       /* slim chance, but we might have eaten SIGTERM on the first iteration */
5340       if (j > 0)
5341         count = j;
5342
5343       print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec",
5344              count, after - before, count / (after - before));
5345     }
5346   else
5347     {
5348       int ret;
5349
5350       /* Wait for a reply... */
5351       W (ret);
5352       return ret;
5353     }
5354
5355   /* Return the good/bad news */
5356   return (vam->retval);
5357 }
5358
5359 static int
5360 api_ip_mroute_add_del (vat_main_t * vam)
5361 {
5362   unformat_input_t *i = vam->input;
5363   u8 path_set = 0, prefix_set = 0, is_add = 1;
5364   vl_api_ip_mroute_add_del_t *mp;
5365   mfib_entry_flags_t eflags = 0;
5366   vl_api_mfib_path_t path;
5367   vl_api_mprefix_t pfx = { };
5368   u32 vrf_id = 0;
5369   int ret;
5370
5371   /* Parse args required to build the message */
5372   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5373     {
5374       if (unformat (i, "%U", unformat_vl_api_mprefix, &pfx))
5375         {
5376           prefix_set = 1;
5377           pfx.grp_address_length = htons (pfx.grp_address_length);
5378         }
5379       else if (unformat (i, "del"))
5380         is_add = 0;
5381       else if (unformat (i, "add"))
5382         is_add = 1;
5383       else if (unformat (i, "vrf %d", &vrf_id))
5384         ;
5385       else if (unformat (i, "%U", unformat_mfib_itf_flags, &path.itf_flags))
5386         path.itf_flags = htonl (path.itf_flags);
5387       else if (unformat (i, "%U", unformat_mfib_entry_flags, &eflags))
5388         ;
5389       else if (unformat (i, "via %U", unformat_fib_path, vam, &path.path))
5390         path_set = 1;
5391       else
5392         {
5393           clib_warning ("parse error '%U'", format_unformat_error, i);
5394           return -99;
5395         }
5396     }
5397
5398   if (prefix_set == 0)
5399     {
5400       errmsg ("missing addresses\n");
5401       return -99;
5402     }
5403   if (path_set == 0)
5404     {
5405       errmsg ("missing path\n");
5406       return -99;
5407     }
5408
5409   /* Construct the API message */
5410   M (IP_MROUTE_ADD_DEL, mp);
5411
5412   mp->is_add = is_add;
5413   mp->is_multipath = 1;
5414
5415   clib_memcpy (&mp->route.prefix, &pfx, sizeof (pfx));
5416   mp->route.table_id = htonl (vrf_id);
5417   mp->route.n_paths = 1;
5418   mp->route.entry_flags = htonl (eflags);
5419
5420   clib_memcpy (&mp->route.paths, &path, sizeof (path));
5421
5422   /* send it... */
5423   S (mp);
5424   /* Wait for a reply... */
5425   W (ret);
5426   return ret;
5427 }
5428
5429 static int
5430 api_mpls_table_add_del (vat_main_t * vam)
5431 {
5432   unformat_input_t *i = vam->input;
5433   vl_api_mpls_table_add_del_t *mp;
5434   u32 table_id = ~0;
5435   u8 is_add = 1;
5436   int ret = 0;
5437
5438   /* Parse args required to build the message */
5439   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5440     {
5441       if (unformat (i, "table %d", &table_id))
5442         ;
5443       else if (unformat (i, "del"))
5444         is_add = 0;
5445       else if (unformat (i, "add"))
5446         is_add = 1;
5447       else
5448         {
5449           clib_warning ("parse error '%U'", format_unformat_error, i);
5450           return -99;
5451         }
5452     }
5453
5454   if (~0 == table_id)
5455     {
5456       errmsg ("missing table-ID");
5457       return -99;
5458     }
5459
5460   /* Construct the API message */
5461   M (MPLS_TABLE_ADD_DEL, mp);
5462
5463   mp->mt_table.mt_table_id = ntohl (table_id);
5464   mp->mt_is_add = is_add;
5465
5466   /* send it... */
5467   S (mp);
5468
5469   /* Wait for a reply... */
5470   W (ret);
5471
5472   return ret;
5473 }
5474
5475 static int
5476 api_mpls_route_add_del (vat_main_t * vam)
5477 {
5478   u8 is_add = 1, path_count = 0, is_multipath = 0, is_eos = 0;
5479   mpls_label_t local_label = MPLS_LABEL_INVALID;
5480   unformat_input_t *i = vam->input;
5481   vl_api_mpls_route_add_del_t *mp;
5482   vl_api_fib_path_t paths[8];
5483   int count = 1, j;
5484   f64 before = 0;
5485
5486   /* Parse args required to build the message */
5487   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5488     {
5489       if (unformat (i, "%d", &local_label))
5490         ;
5491       else if (unformat (i, "eos"))
5492         is_eos = 1;
5493       else if (unformat (i, "non-eos"))
5494         is_eos = 0;
5495       else if (unformat (i, "del"))
5496         is_add = 0;
5497       else if (unformat (i, "add"))
5498         is_add = 1;
5499       else if (unformat (i, "multipath"))
5500         is_multipath = 1;
5501       else if (unformat (i, "count %d", &count))
5502         ;
5503       else
5504         if (unformat
5505             (i, "via %U", unformat_fib_path, vam, &paths[path_count]))
5506         {
5507           path_count++;
5508           if (8 == path_count)
5509             {
5510               errmsg ("max 8 paths");
5511               return -99;
5512             }
5513         }
5514       else
5515         {
5516           clib_warning ("parse error '%U'", format_unformat_error, i);
5517           return -99;
5518         }
5519     }
5520
5521   if (!path_count)
5522     {
5523       errmsg ("specify a path; via ...");
5524       return -99;
5525     }
5526
5527   if (MPLS_LABEL_INVALID == local_label)
5528     {
5529       errmsg ("missing label");
5530       return -99;
5531     }
5532
5533   if (count > 1)
5534     {
5535       /* Turn on async mode */
5536       vam->async_mode = 1;
5537       vam->async_errors = 0;
5538       before = vat_time_now (vam);
5539     }
5540
5541   for (j = 0; j < count; j++)
5542     {
5543       /* Construct the API message */
5544       M2 (MPLS_ROUTE_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
5545
5546       mp->mr_is_add = is_add;
5547       mp->mr_is_multipath = is_multipath;
5548
5549       mp->mr_route.mr_label = local_label;
5550       mp->mr_route.mr_eos = is_eos;
5551       mp->mr_route.mr_table_id = 0;
5552       mp->mr_route.mr_n_paths = path_count;
5553
5554       clib_memcpy (&mp->mr_route.mr_paths, paths,
5555                    sizeof (paths[0]) * path_count);
5556
5557       local_label++;
5558
5559       /* send it... */
5560       S (mp);
5561       /* If we receive SIGTERM, stop now... */
5562       if (vam->do_exit)
5563         break;
5564     }
5565
5566   /* When testing multiple add/del ops, use a control-ping to sync */
5567   if (count > 1)
5568     {
5569       vl_api_control_ping_t *mp_ping;
5570       f64 after;
5571       f64 timeout;
5572
5573       /* Shut off async mode */
5574       vam->async_mode = 0;
5575
5576       MPING (CONTROL_PING, mp_ping);
5577       S (mp_ping);
5578
5579       timeout = vat_time_now (vam) + 1.0;
5580       while (vat_time_now (vam) < timeout)
5581         if (vam->result_ready == 1)
5582           goto out;
5583       vam->retval = -99;
5584
5585     out:
5586       if (vam->retval == -99)
5587         errmsg ("timeout");
5588
5589       if (vam->async_errors > 0)
5590         {
5591           errmsg ("%d asynchronous errors", vam->async_errors);
5592           vam->retval = -98;
5593         }
5594       vam->async_errors = 0;
5595       after = vat_time_now (vam);
5596
5597       /* slim chance, but we might have eaten SIGTERM on the first iteration */
5598       if (j > 0)
5599         count = j;
5600
5601       print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec",
5602              count, after - before, count / (after - before));
5603     }
5604   else
5605     {
5606       int ret;
5607
5608       /* Wait for a reply... */
5609       W (ret);
5610       return ret;
5611     }
5612
5613   /* Return the good/bad news */
5614   return (vam->retval);
5615   return (0);
5616 }
5617
5618 static int
5619 api_mpls_ip_bind_unbind (vat_main_t * vam)
5620 {
5621   unformat_input_t *i = vam->input;
5622   vl_api_mpls_ip_bind_unbind_t *mp;
5623   u32 ip_table_id = 0;
5624   u8 is_bind = 1;
5625   vl_api_prefix_t pfx;
5626   u8 prefix_set = 0;
5627   mpls_label_t local_label = MPLS_LABEL_INVALID;
5628   int ret;
5629
5630   /* Parse args required to build the message */
5631   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5632     {
5633       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
5634         prefix_set = 1;
5635       else if (unformat (i, "%d", &local_label))
5636         ;
5637       else if (unformat (i, "table-id %d", &ip_table_id))
5638         ;
5639       else if (unformat (i, "unbind"))
5640         is_bind = 0;
5641       else if (unformat (i, "bind"))
5642         is_bind = 1;
5643       else
5644         {
5645           clib_warning ("parse error '%U'", format_unformat_error, i);
5646           return -99;
5647         }
5648     }
5649
5650   if (!prefix_set)
5651     {
5652       errmsg ("IP prefix not set");
5653       return -99;
5654     }
5655
5656   if (MPLS_LABEL_INVALID == local_label)
5657     {
5658       errmsg ("missing label");
5659       return -99;
5660     }
5661
5662   /* Construct the API message */
5663   M (MPLS_IP_BIND_UNBIND, mp);
5664
5665   mp->mb_is_bind = is_bind;
5666   mp->mb_ip_table_id = ntohl (ip_table_id);
5667   mp->mb_mpls_table_id = 0;
5668   mp->mb_label = ntohl (local_label);
5669   clib_memcpy (&mp->mb_prefix, &pfx, sizeof (pfx));
5670
5671   /* send it... */
5672   S (mp);
5673
5674   /* Wait for a reply... */
5675   W (ret);
5676   return ret;
5677   return (0);
5678 }
5679
5680 static int
5681 api_sr_mpls_policy_add (vat_main_t * vam)
5682 {
5683   unformat_input_t *i = vam->input;
5684   vl_api_sr_mpls_policy_add_t *mp;
5685   u32 bsid = 0;
5686   u32 weight = 1;
5687   u8 type = 0;
5688   u8 n_segments = 0;
5689   u32 sid;
5690   u32 *segments = NULL;
5691   int ret;
5692
5693   /* Parse args required to build the message */
5694   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5695     {
5696       if (unformat (i, "bsid %d", &bsid))
5697         ;
5698       else if (unformat (i, "weight %d", &weight))
5699         ;
5700       else if (unformat (i, "spray"))
5701         type = 1;
5702       else if (unformat (i, "next %d", &sid))
5703         {
5704           n_segments += 1;
5705           vec_add1 (segments, htonl (sid));
5706         }
5707       else
5708         {
5709           clib_warning ("parse error '%U'", format_unformat_error, i);
5710           return -99;
5711         }
5712     }
5713
5714   if (bsid == 0)
5715     {
5716       errmsg ("bsid not set");
5717       return -99;
5718     }
5719
5720   if (n_segments == 0)
5721     {
5722       errmsg ("no sid in segment stack");
5723       return -99;
5724     }
5725
5726   /* Construct the API message */
5727   M2 (SR_MPLS_POLICY_ADD, mp, sizeof (u32) * n_segments);
5728
5729   mp->bsid = htonl (bsid);
5730   mp->weight = htonl (weight);
5731   mp->is_spray = type;
5732   mp->n_segments = n_segments;
5733   memcpy (mp->segments, segments, sizeof (u32) * n_segments);
5734   vec_free (segments);
5735
5736   /* send it... */
5737   S (mp);
5738
5739   /* Wait for a reply... */
5740   W (ret);
5741   return ret;
5742 }
5743
5744 static int
5745 api_sr_mpls_policy_del (vat_main_t * vam)
5746 {
5747   unformat_input_t *i = vam->input;
5748   vl_api_sr_mpls_policy_del_t *mp;
5749   u32 bsid = 0;
5750   int ret;
5751
5752   /* Parse args required to build the message */
5753   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5754     {
5755       if (unformat (i, "bsid %d", &bsid))
5756         ;
5757       else
5758         {
5759           clib_warning ("parse error '%U'", format_unformat_error, i);
5760           return -99;
5761         }
5762     }
5763
5764   if (bsid == 0)
5765     {
5766       errmsg ("bsid not set");
5767       return -99;
5768     }
5769
5770   /* Construct the API message */
5771   M (SR_MPLS_POLICY_DEL, mp);
5772
5773   mp->bsid = htonl (bsid);
5774
5775   /* send it... */
5776   S (mp);
5777
5778   /* Wait for a reply... */
5779   W (ret);
5780   return ret;
5781 }
5782
5783 static int
5784 api_mpls_tunnel_add_del (vat_main_t * vam)
5785 {
5786   unformat_input_t *i = vam->input;
5787   vl_api_mpls_tunnel_add_del_t *mp;
5788
5789   vl_api_fib_path_t paths[8];
5790   u32 sw_if_index = ~0;
5791   u8 path_count = 0;
5792   u8 l2_only = 0;
5793   u8 is_add = 1;
5794   int ret;
5795
5796   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5797     {
5798       if (unformat (i, "add"))
5799         is_add = 1;
5800       else
5801         if (unformat
5802             (i, "del %U", api_unformat_sw_if_index, vam, &sw_if_index))
5803         is_add = 0;
5804       else if (unformat (i, "del sw_if_index %d", &sw_if_index))
5805         is_add = 0;
5806       else if (unformat (i, "l2-only"))
5807         l2_only = 1;
5808       else
5809         if (unformat
5810             (i, "via %U", unformat_fib_path, vam, &paths[path_count]))
5811         {
5812           path_count++;
5813           if (8 == path_count)
5814             {
5815               errmsg ("max 8 paths");
5816               return -99;
5817             }
5818         }
5819       else
5820         {
5821           clib_warning ("parse error '%U'", format_unformat_error, i);
5822           return -99;
5823         }
5824     }
5825
5826   M2 (MPLS_TUNNEL_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
5827
5828   mp->mt_is_add = is_add;
5829   mp->mt_tunnel.mt_sw_if_index = ntohl (sw_if_index);
5830   mp->mt_tunnel.mt_l2_only = l2_only;
5831   mp->mt_tunnel.mt_is_multicast = 0;
5832   mp->mt_tunnel.mt_n_paths = path_count;
5833
5834   clib_memcpy (&mp->mt_tunnel.mt_paths, &paths,
5835                sizeof (paths[0]) * path_count);
5836
5837   S (mp);
5838   W (ret);
5839   return ret;
5840 }
5841
5842 static int
5843 api_sw_interface_set_unnumbered (vat_main_t * vam)
5844 {
5845   unformat_input_t *i = vam->input;
5846   vl_api_sw_interface_set_unnumbered_t *mp;
5847   u32 sw_if_index;
5848   u32 unnum_sw_index = ~0;
5849   u8 is_add = 1;
5850   u8 sw_if_index_set = 0;
5851   int ret;
5852
5853   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5854     {
5855       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5856         sw_if_index_set = 1;
5857       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5858         sw_if_index_set = 1;
5859       else if (unformat (i, "unnum_if_index %d", &unnum_sw_index))
5860         ;
5861       else if (unformat (i, "del"))
5862         is_add = 0;
5863       else
5864         {
5865           clib_warning ("parse error '%U'", format_unformat_error, i);
5866           return -99;
5867         }
5868     }
5869
5870   if (sw_if_index_set == 0)
5871     {
5872       errmsg ("missing interface name or sw_if_index");
5873       return -99;
5874     }
5875
5876   M (SW_INTERFACE_SET_UNNUMBERED, mp);
5877
5878   mp->sw_if_index = ntohl (sw_if_index);
5879   mp->unnumbered_sw_if_index = ntohl (unnum_sw_index);
5880   mp->is_add = is_add;
5881
5882   S (mp);
5883   W (ret);
5884   return ret;
5885 }
5886
5887
5888 static int
5889 api_create_vlan_subif (vat_main_t * vam)
5890 {
5891   unformat_input_t *i = vam->input;
5892   vl_api_create_vlan_subif_t *mp;
5893   u32 sw_if_index;
5894   u8 sw_if_index_set = 0;
5895   u32 vlan_id;
5896   u8 vlan_id_set = 0;
5897   int ret;
5898
5899   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5900     {
5901       if (unformat (i, "sw_if_index %d", &sw_if_index))
5902         sw_if_index_set = 1;
5903       else
5904         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5905         sw_if_index_set = 1;
5906       else if (unformat (i, "vlan %d", &vlan_id))
5907         vlan_id_set = 1;
5908       else
5909         {
5910           clib_warning ("parse error '%U'", format_unformat_error, i);
5911           return -99;
5912         }
5913     }
5914
5915   if (sw_if_index_set == 0)
5916     {
5917       errmsg ("missing interface name or sw_if_index");
5918       return -99;
5919     }
5920
5921   if (vlan_id_set == 0)
5922     {
5923       errmsg ("missing vlan_id");
5924       return -99;
5925     }
5926   M (CREATE_VLAN_SUBIF, mp);
5927
5928   mp->sw_if_index = ntohl (sw_if_index);
5929   mp->vlan_id = ntohl (vlan_id);
5930
5931   S (mp);
5932   W (ret);
5933   return ret;
5934 }
5935
5936 #define foreach_create_subif_bit                \
5937 _(no_tags)                                      \
5938 _(one_tag)                                      \
5939 _(two_tags)                                     \
5940 _(dot1ad)                                       \
5941 _(exact_match)                                  \
5942 _(default_sub)                                  \
5943 _(outer_vlan_id_any)                            \
5944 _(inner_vlan_id_any)
5945
5946 #define foreach_create_subif_flag               \
5947 _(0, "no_tags")                                 \
5948 _(1, "one_tag")                                 \
5949 _(2, "two_tags")                                \
5950 _(3, "dot1ad")                                  \
5951 _(4, "exact_match")                             \
5952 _(5, "default_sub")                             \
5953 _(6, "outer_vlan_id_any")                       \
5954 _(7, "inner_vlan_id_any")
5955
5956 static int
5957 api_create_subif (vat_main_t * vam)
5958 {
5959   unformat_input_t *i = vam->input;
5960   vl_api_create_subif_t *mp;
5961   u32 sw_if_index;
5962   u8 sw_if_index_set = 0;
5963   u32 sub_id;
5964   u8 sub_id_set = 0;
5965   u32 __attribute__ ((unused)) no_tags = 0;
5966   u32 __attribute__ ((unused)) one_tag = 0;
5967   u32 __attribute__ ((unused)) two_tags = 0;
5968   u32 __attribute__ ((unused)) dot1ad = 0;
5969   u32 __attribute__ ((unused)) exact_match = 0;
5970   u32 __attribute__ ((unused)) default_sub = 0;
5971   u32 __attribute__ ((unused)) outer_vlan_id_any = 0;
5972   u32 __attribute__ ((unused)) inner_vlan_id_any = 0;
5973   u32 tmp;
5974   u16 outer_vlan_id = 0;
5975   u16 inner_vlan_id = 0;
5976   int ret;
5977
5978   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5979     {
5980       if (unformat (i, "sw_if_index %d", &sw_if_index))
5981         sw_if_index_set = 1;
5982       else
5983         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5984         sw_if_index_set = 1;
5985       else if (unformat (i, "sub_id %d", &sub_id))
5986         sub_id_set = 1;
5987       else if (unformat (i, "outer_vlan_id %d", &tmp))
5988         outer_vlan_id = tmp;
5989       else if (unformat (i, "inner_vlan_id %d", &tmp))
5990         inner_vlan_id = tmp;
5991
5992 #define _(a) else if (unformat (i, #a)) a = 1 ;
5993       foreach_create_subif_bit
5994 #undef _
5995         else
5996         {
5997           clib_warning ("parse error '%U'", format_unformat_error, i);
5998           return -99;
5999         }
6000     }
6001
6002   if (sw_if_index_set == 0)
6003     {
6004       errmsg ("missing interface name or sw_if_index");
6005       return -99;
6006     }
6007
6008   if (sub_id_set == 0)
6009     {
6010       errmsg ("missing sub_id");
6011       return -99;
6012     }
6013   M (CREATE_SUBIF, mp);
6014
6015   mp->sw_if_index = ntohl (sw_if_index);
6016   mp->sub_id = ntohl (sub_id);
6017
6018 #define _(a,b) mp->sub_if_flags |= (1 << a);
6019   foreach_create_subif_flag;
6020 #undef _
6021
6022   mp->outer_vlan_id = ntohs (outer_vlan_id);
6023   mp->inner_vlan_id = ntohs (inner_vlan_id);
6024
6025   S (mp);
6026   W (ret);
6027   return ret;
6028 }
6029
6030 static int
6031 api_ip_table_replace_begin (vat_main_t * vam)
6032 {
6033   unformat_input_t *i = vam->input;
6034   vl_api_ip_table_replace_begin_t *mp;
6035   u32 table_id = 0;
6036   u8 is_ipv6 = 0;
6037
6038   int ret;
6039   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6040     {
6041       if (unformat (i, "table %d", &table_id))
6042         ;
6043       else if (unformat (i, "ipv6"))
6044         is_ipv6 = 1;
6045       else
6046         {
6047           clib_warning ("parse error '%U'", format_unformat_error, i);
6048           return -99;
6049         }
6050     }
6051
6052   M (IP_TABLE_REPLACE_BEGIN, mp);
6053
6054   mp->table.table_id = ntohl (table_id);
6055   mp->table.is_ip6 = is_ipv6;
6056
6057   S (mp);
6058   W (ret);
6059   return ret;
6060 }
6061
6062 static int
6063 api_ip_table_flush (vat_main_t * vam)
6064 {
6065   unformat_input_t *i = vam->input;
6066   vl_api_ip_table_flush_t *mp;
6067   u32 table_id = 0;
6068   u8 is_ipv6 = 0;
6069
6070   int ret;
6071   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6072     {
6073       if (unformat (i, "table %d", &table_id))
6074         ;
6075       else if (unformat (i, "ipv6"))
6076         is_ipv6 = 1;
6077       else
6078         {
6079           clib_warning ("parse error '%U'", format_unformat_error, i);
6080           return -99;
6081         }
6082     }
6083
6084   M (IP_TABLE_FLUSH, mp);
6085
6086   mp->table.table_id = ntohl (table_id);
6087   mp->table.is_ip6 = is_ipv6;
6088
6089   S (mp);
6090   W (ret);
6091   return ret;
6092 }
6093
6094 static int
6095 api_ip_table_replace_end (vat_main_t * vam)
6096 {
6097   unformat_input_t *i = vam->input;
6098   vl_api_ip_table_replace_end_t *mp;
6099   u32 table_id = 0;
6100   u8 is_ipv6 = 0;
6101
6102   int ret;
6103   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6104     {
6105       if (unformat (i, "table %d", &table_id))
6106         ;
6107       else if (unformat (i, "ipv6"))
6108         is_ipv6 = 1;
6109       else
6110         {
6111           clib_warning ("parse error '%U'", format_unformat_error, i);
6112           return -99;
6113         }
6114     }
6115
6116   M (IP_TABLE_REPLACE_END, mp);
6117
6118   mp->table.table_id = ntohl (table_id);
6119   mp->table.is_ip6 = is_ipv6;
6120
6121   S (mp);
6122   W (ret);
6123   return ret;
6124 }
6125
6126 static int
6127 api_set_ip_flow_hash (vat_main_t * vam)
6128 {
6129   unformat_input_t *i = vam->input;
6130   vl_api_set_ip_flow_hash_t *mp;
6131   u32 vrf_id = 0;
6132   u8 is_ipv6 = 0;
6133   u8 vrf_id_set = 0;
6134   u8 src = 0;
6135   u8 dst = 0;
6136   u8 sport = 0;
6137   u8 dport = 0;
6138   u8 proto = 0;
6139   u8 reverse = 0;
6140   int ret;
6141
6142   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6143     {
6144       if (unformat (i, "vrf %d", &vrf_id))
6145         vrf_id_set = 1;
6146       else if (unformat (i, "ipv6"))
6147         is_ipv6 = 1;
6148       else if (unformat (i, "src"))
6149         src = 1;
6150       else if (unformat (i, "dst"))
6151         dst = 1;
6152       else if (unformat (i, "sport"))
6153         sport = 1;
6154       else if (unformat (i, "dport"))
6155         dport = 1;
6156       else if (unformat (i, "proto"))
6157         proto = 1;
6158       else if (unformat (i, "reverse"))
6159         reverse = 1;
6160
6161       else
6162         {
6163           clib_warning ("parse error '%U'", format_unformat_error, i);
6164           return -99;
6165         }
6166     }
6167
6168   if (vrf_id_set == 0)
6169     {
6170       errmsg ("missing vrf id");
6171       return -99;
6172     }
6173
6174   M (SET_IP_FLOW_HASH, mp);
6175   mp->src = src;
6176   mp->dst = dst;
6177   mp->sport = sport;
6178   mp->dport = dport;
6179   mp->proto = proto;
6180   mp->reverse = reverse;
6181   mp->vrf_id = ntohl (vrf_id);
6182   mp->is_ipv6 = is_ipv6;
6183
6184   S (mp);
6185   W (ret);
6186   return ret;
6187 }
6188
6189 static int
6190 api_sw_interface_ip6_enable_disable (vat_main_t * vam)
6191 {
6192   unformat_input_t *i = vam->input;
6193   vl_api_sw_interface_ip6_enable_disable_t *mp;
6194   u32 sw_if_index;
6195   u8 sw_if_index_set = 0;
6196   u8 enable = 0;
6197   int ret;
6198
6199   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6200     {
6201       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
6202         sw_if_index_set = 1;
6203       else if (unformat (i, "sw_if_index %d", &sw_if_index))
6204         sw_if_index_set = 1;
6205       else if (unformat (i, "enable"))
6206         enable = 1;
6207       else if (unformat (i, "disable"))
6208         enable = 0;
6209       else
6210         {
6211           clib_warning ("parse error '%U'", format_unformat_error, i);
6212           return -99;
6213         }
6214     }
6215
6216   if (sw_if_index_set == 0)
6217     {
6218       errmsg ("missing interface name or sw_if_index");
6219       return -99;
6220     }
6221
6222   M (SW_INTERFACE_IP6_ENABLE_DISABLE, mp);
6223
6224   mp->sw_if_index = ntohl (sw_if_index);
6225   mp->enable = enable;
6226
6227   S (mp);
6228   W (ret);
6229   return ret;
6230 }
6231
6232
6233 static int
6234 api_l2_patch_add_del (vat_main_t * vam)
6235 {
6236   unformat_input_t *i = vam->input;
6237   vl_api_l2_patch_add_del_t *mp;
6238   u32 rx_sw_if_index;
6239   u8 rx_sw_if_index_set = 0;
6240   u32 tx_sw_if_index;
6241   u8 tx_sw_if_index_set = 0;
6242   u8 is_add = 1;
6243   int ret;
6244
6245   /* Parse args required to build the message */
6246   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6247     {
6248       if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index))
6249         rx_sw_if_index_set = 1;
6250       else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
6251         tx_sw_if_index_set = 1;
6252       else if (unformat (i, "rx"))
6253         {
6254           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6255             {
6256               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
6257                             &rx_sw_if_index))
6258                 rx_sw_if_index_set = 1;
6259             }
6260           else
6261             break;
6262         }
6263       else if (unformat (i, "tx"))
6264         {
6265           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6266             {
6267               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
6268                             &tx_sw_if_index))
6269                 tx_sw_if_index_set = 1;
6270             }
6271           else
6272             break;
6273         }
6274       else if (unformat (i, "del"))
6275         is_add = 0;
6276       else
6277         break;
6278     }
6279
6280   if (rx_sw_if_index_set == 0)
6281     {
6282       errmsg ("missing rx interface name or rx_sw_if_index");
6283       return -99;
6284     }
6285
6286   if (tx_sw_if_index_set == 0)
6287     {
6288       errmsg ("missing tx interface name or tx_sw_if_index");
6289       return -99;
6290     }
6291
6292   M (L2_PATCH_ADD_DEL, mp);
6293
6294   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
6295   mp->tx_sw_if_index = ntohl (tx_sw_if_index);
6296   mp->is_add = is_add;
6297
6298   S (mp);
6299   W (ret);
6300   return ret;
6301 }
6302
6303 u8 is_del;
6304 u8 localsid_addr[16];
6305 u8 end_psp;
6306 u8 behavior;
6307 u32 sw_if_index;
6308 u32 vlan_index;
6309 u32 fib_table;
6310 u8 nh_addr[16];
6311
6312 static int
6313 api_sr_localsid_add_del (vat_main_t * vam)
6314 {
6315   unformat_input_t *i = vam->input;
6316   vl_api_sr_localsid_add_del_t *mp;
6317
6318   u8 is_del;
6319   ip6_address_t localsid;
6320   u8 end_psp = 0;
6321   u8 behavior = ~0;
6322   u32 sw_if_index;
6323   u32 fib_table = ~(u32) 0;
6324   ip46_address_t nh_addr;
6325   clib_memset (&nh_addr, 0, sizeof (ip46_address_t));
6326
6327   bool nexthop_set = 0;
6328
6329   int ret;
6330
6331   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6332     {
6333       if (unformat (i, "del"))
6334         is_del = 1;
6335       else if (unformat (i, "address %U", unformat_ip6_address, &localsid));
6336       else if (unformat (i, "next-hop %U", unformat_ip46_address, &nh_addr))
6337         nexthop_set = 1;
6338       else if (unformat (i, "behavior %u", &behavior));
6339       else if (unformat (i, "sw_if_index %u", &sw_if_index));
6340       else if (unformat (i, "fib-table %u", &fib_table));
6341       else if (unformat (i, "end.psp %u", &behavior));
6342       else
6343         break;
6344     }
6345
6346   M (SR_LOCALSID_ADD_DEL, mp);
6347
6348   clib_memcpy (mp->localsid, &localsid, sizeof (mp->localsid));
6349
6350   if (nexthop_set)
6351     {
6352       clib_memcpy (&mp->nh_addr.un, &nh_addr, sizeof (mp->nh_addr.un));
6353     }
6354   mp->behavior = behavior;
6355   mp->sw_if_index = ntohl (sw_if_index);
6356   mp->fib_table = ntohl (fib_table);
6357   mp->end_psp = end_psp;
6358   mp->is_del = is_del;
6359
6360   S (mp);
6361   W (ret);
6362   return ret;
6363 }
6364
6365 static int
6366 api_ioam_enable (vat_main_t * vam)
6367 {
6368   unformat_input_t *input = vam->input;
6369   vl_api_ioam_enable_t *mp;
6370   u32 id = 0;
6371   int has_trace_option = 0;
6372   int has_pot_option = 0;
6373   int has_seqno_option = 0;
6374   int has_analyse_option = 0;
6375   int ret;
6376
6377   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6378     {
6379       if (unformat (input, "trace"))
6380         has_trace_option = 1;
6381       else if (unformat (input, "pot"))
6382         has_pot_option = 1;
6383       else if (unformat (input, "seqno"))
6384         has_seqno_option = 1;
6385       else if (unformat (input, "analyse"))
6386         has_analyse_option = 1;
6387       else
6388         break;
6389     }
6390   M (IOAM_ENABLE, mp);
6391   mp->id = htons (id);
6392   mp->seqno = has_seqno_option;
6393   mp->analyse = has_analyse_option;
6394   mp->pot_enable = has_pot_option;
6395   mp->trace_enable = has_trace_option;
6396
6397   S (mp);
6398   W (ret);
6399   return ret;
6400 }
6401
6402
6403 static int
6404 api_ioam_disable (vat_main_t * vam)
6405 {
6406   vl_api_ioam_disable_t *mp;
6407   int ret;
6408
6409   M (IOAM_DISABLE, mp);
6410   S (mp);
6411   W (ret);
6412   return ret;
6413 }
6414
6415 #define foreach_tcp_proto_field                 \
6416 _(src_port)                                     \
6417 _(dst_port)
6418
6419 #define foreach_udp_proto_field                 \
6420 _(src_port)                                     \
6421 _(dst_port)
6422
6423 #define foreach_ip4_proto_field                 \
6424 _(src_address)                                  \
6425 _(dst_address)                                  \
6426 _(tos)                                          \
6427 _(length)                                       \
6428 _(fragment_id)                                  \
6429 _(ttl)                                          \
6430 _(protocol)                                     \
6431 _(checksum)
6432
6433 typedef struct
6434 {
6435   u16 src_port, dst_port;
6436 } tcpudp_header_t;
6437
6438 #if VPP_API_TEST_BUILTIN == 0
6439 uword
6440 unformat_tcp_mask (unformat_input_t * input, va_list * args)
6441 {
6442   u8 **maskp = va_arg (*args, u8 **);
6443   u8 *mask = 0;
6444   u8 found_something = 0;
6445   tcp_header_t *tcp;
6446
6447 #define _(a) u8 a=0;
6448   foreach_tcp_proto_field;
6449 #undef _
6450
6451   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6452     {
6453       if (0);
6454 #define _(a) else if (unformat (input, #a)) a=1;
6455       foreach_tcp_proto_field
6456 #undef _
6457         else
6458         break;
6459     }
6460
6461 #define _(a) found_something += a;
6462   foreach_tcp_proto_field;
6463 #undef _
6464
6465   if (found_something == 0)
6466     return 0;
6467
6468   vec_validate (mask, sizeof (*tcp) - 1);
6469
6470   tcp = (tcp_header_t *) mask;
6471
6472 #define _(a) if (a) clib_memset (&tcp->a, 0xff, sizeof (tcp->a));
6473   foreach_tcp_proto_field;
6474 #undef _
6475
6476   *maskp = mask;
6477   return 1;
6478 }
6479
6480 uword
6481 unformat_udp_mask (unformat_input_t * input, va_list * args)
6482 {
6483   u8 **maskp = va_arg (*args, u8 **);
6484   u8 *mask = 0;
6485   u8 found_something = 0;
6486   udp_header_t *udp;
6487
6488 #define _(a) u8 a=0;
6489   foreach_udp_proto_field;
6490 #undef _
6491
6492   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6493     {
6494       if (0);
6495 #define _(a) else if (unformat (input, #a)) a=1;
6496       foreach_udp_proto_field
6497 #undef _
6498         else
6499         break;
6500     }
6501
6502 #define _(a) found_something += a;
6503   foreach_udp_proto_field;
6504 #undef _
6505
6506   if (found_something == 0)
6507     return 0;
6508
6509   vec_validate (mask, sizeof (*udp) - 1);
6510
6511   udp = (udp_header_t *) mask;
6512
6513 #define _(a) if (a) clib_memset (&udp->a, 0xff, sizeof (udp->a));
6514   foreach_udp_proto_field;
6515 #undef _
6516
6517   *maskp = mask;
6518   return 1;
6519 }
6520
6521 uword
6522 unformat_l4_mask (unformat_input_t * input, va_list * args)
6523 {
6524   u8 **maskp = va_arg (*args, u8 **);
6525   u16 src_port = 0, dst_port = 0;
6526   tcpudp_header_t *tcpudp;
6527
6528   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6529     {
6530       if (unformat (input, "tcp %U", unformat_tcp_mask, maskp))
6531         return 1;
6532       else if (unformat (input, "udp %U", unformat_udp_mask, maskp))
6533         return 1;
6534       else if (unformat (input, "src_port"))
6535         src_port = 0xFFFF;
6536       else if (unformat (input, "dst_port"))
6537         dst_port = 0xFFFF;
6538       else
6539         return 0;
6540     }
6541
6542   if (!src_port && !dst_port)
6543     return 0;
6544
6545   u8 *mask = 0;
6546   vec_validate (mask, sizeof (tcpudp_header_t) - 1);
6547
6548   tcpudp = (tcpudp_header_t *) mask;
6549   tcpudp->src_port = src_port;
6550   tcpudp->dst_port = dst_port;
6551
6552   *maskp = mask;
6553
6554   return 1;
6555 }
6556
6557 uword
6558 unformat_ip4_mask (unformat_input_t * input, va_list * args)
6559 {
6560   u8 **maskp = va_arg (*args, u8 **);
6561   u8 *mask = 0;
6562   u8 found_something = 0;
6563   ip4_header_t *ip;
6564
6565 #define _(a) u8 a=0;
6566   foreach_ip4_proto_field;
6567 #undef _
6568   u8 version = 0;
6569   u8 hdr_length = 0;
6570
6571
6572   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6573     {
6574       if (unformat (input, "version"))
6575         version = 1;
6576       else if (unformat (input, "hdr_length"))
6577         hdr_length = 1;
6578       else if (unformat (input, "src"))
6579         src_address = 1;
6580       else if (unformat (input, "dst"))
6581         dst_address = 1;
6582       else if (unformat (input, "proto"))
6583         protocol = 1;
6584
6585 #define _(a) else if (unformat (input, #a)) a=1;
6586       foreach_ip4_proto_field
6587 #undef _
6588         else
6589         break;
6590     }
6591
6592 #define _(a) found_something += a;
6593   foreach_ip4_proto_field;
6594 #undef _
6595
6596   if (found_something == 0)
6597     return 0;
6598
6599   vec_validate (mask, sizeof (*ip) - 1);
6600
6601   ip = (ip4_header_t *) mask;
6602
6603 #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
6604   foreach_ip4_proto_field;
6605 #undef _
6606
6607   ip->ip_version_and_header_length = 0;
6608
6609   if (version)
6610     ip->ip_version_and_header_length |= 0xF0;
6611
6612   if (hdr_length)
6613     ip->ip_version_and_header_length |= 0x0F;
6614
6615   *maskp = mask;
6616   return 1;
6617 }
6618
6619 #define foreach_ip6_proto_field                 \
6620 _(src_address)                                  \
6621 _(dst_address)                                  \
6622 _(payload_length)                               \
6623 _(hop_limit)                                    \
6624 _(protocol)
6625
6626 uword
6627 unformat_ip6_mask (unformat_input_t * input, va_list * args)
6628 {
6629   u8 **maskp = va_arg (*args, u8 **);
6630   u8 *mask = 0;
6631   u8 found_something = 0;
6632   ip6_header_t *ip;
6633   u32 ip_version_traffic_class_and_flow_label;
6634
6635 #define _(a) u8 a=0;
6636   foreach_ip6_proto_field;
6637 #undef _
6638   u8 version = 0;
6639   u8 traffic_class = 0;
6640   u8 flow_label = 0;
6641
6642   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6643     {
6644       if (unformat (input, "version"))
6645         version = 1;
6646       else if (unformat (input, "traffic-class"))
6647         traffic_class = 1;
6648       else if (unformat (input, "flow-label"))
6649         flow_label = 1;
6650       else if (unformat (input, "src"))
6651         src_address = 1;
6652       else if (unformat (input, "dst"))
6653         dst_address = 1;
6654       else if (unformat (input, "proto"))
6655         protocol = 1;
6656
6657 #define _(a) else if (unformat (input, #a)) a=1;
6658       foreach_ip6_proto_field
6659 #undef _
6660         else
6661         break;
6662     }
6663
6664 #define _(a) found_something += a;
6665   foreach_ip6_proto_field;
6666 #undef _
6667
6668   if (found_something == 0)
6669     return 0;
6670
6671   vec_validate (mask, sizeof (*ip) - 1);
6672
6673   ip = (ip6_header_t *) mask;
6674
6675 #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
6676   foreach_ip6_proto_field;
6677 #undef _
6678
6679   ip_version_traffic_class_and_flow_label = 0;
6680
6681   if (version)
6682     ip_version_traffic_class_and_flow_label |= 0xF0000000;
6683
6684   if (traffic_class)
6685     ip_version_traffic_class_and_flow_label |= 0x0FF00000;
6686
6687   if (flow_label)
6688     ip_version_traffic_class_and_flow_label |= 0x000FFFFF;
6689
6690   ip->ip_version_traffic_class_and_flow_label =
6691     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
6692
6693   *maskp = mask;
6694   return 1;
6695 }
6696
6697 uword
6698 unformat_l3_mask (unformat_input_t * input, va_list * args)
6699 {
6700   u8 **maskp = va_arg (*args, u8 **);
6701
6702   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6703     {
6704       if (unformat (input, "ip4 %U", unformat_ip4_mask, maskp))
6705         return 1;
6706       else if (unformat (input, "ip6 %U", unformat_ip6_mask, maskp))
6707         return 1;
6708       else
6709         break;
6710     }
6711   return 0;
6712 }
6713
6714 uword
6715 unformat_l2_mask (unformat_input_t * input, va_list * args)
6716 {
6717   u8 **maskp = va_arg (*args, u8 **);
6718   u8 *mask = 0;
6719   u8 src = 0;
6720   u8 dst = 0;
6721   u8 proto = 0;
6722   u8 tag1 = 0;
6723   u8 tag2 = 0;
6724   u8 ignore_tag1 = 0;
6725   u8 ignore_tag2 = 0;
6726   u8 cos1 = 0;
6727   u8 cos2 = 0;
6728   u8 dot1q = 0;
6729   u8 dot1ad = 0;
6730   int len = 14;
6731
6732   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6733     {
6734       if (unformat (input, "src"))
6735         src = 1;
6736       else if (unformat (input, "dst"))
6737         dst = 1;
6738       else if (unformat (input, "proto"))
6739         proto = 1;
6740       else if (unformat (input, "tag1"))
6741         tag1 = 1;
6742       else if (unformat (input, "tag2"))
6743         tag2 = 1;
6744       else if (unformat (input, "ignore-tag1"))
6745         ignore_tag1 = 1;
6746       else if (unformat (input, "ignore-tag2"))
6747         ignore_tag2 = 1;
6748       else if (unformat (input, "cos1"))
6749         cos1 = 1;
6750       else if (unformat (input, "cos2"))
6751         cos2 = 1;
6752       else if (unformat (input, "dot1q"))
6753         dot1q = 1;
6754       else if (unformat (input, "dot1ad"))
6755         dot1ad = 1;
6756       else
6757         break;
6758     }
6759   if ((src + dst + proto + tag1 + tag2 + dot1q + dot1ad +
6760        ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
6761     return 0;
6762
6763   if (tag1 || ignore_tag1 || cos1 || dot1q)
6764     len = 18;
6765   if (tag2 || ignore_tag2 || cos2 || dot1ad)
6766     len = 22;
6767
6768   vec_validate (mask, len - 1);
6769
6770   if (dst)
6771     clib_memset (mask, 0xff, 6);
6772
6773   if (src)
6774     clib_memset (mask + 6, 0xff, 6);
6775
6776   if (tag2 || dot1ad)
6777     {
6778       /* inner vlan tag */
6779       if (tag2)
6780         {
6781           mask[19] = 0xff;
6782           mask[18] = 0x0f;
6783         }
6784       if (cos2)
6785         mask[18] |= 0xe0;
6786       if (proto)
6787         mask[21] = mask[20] = 0xff;
6788       if (tag1)
6789         {
6790           mask[15] = 0xff;
6791           mask[14] = 0x0f;
6792         }
6793       if (cos1)
6794         mask[14] |= 0xe0;
6795       *maskp = mask;
6796       return 1;
6797     }
6798   if (tag1 | dot1q)
6799     {
6800       if (tag1)
6801         {
6802           mask[15] = 0xff;
6803           mask[14] = 0x0f;
6804         }
6805       if (cos1)
6806         mask[14] |= 0xe0;
6807       if (proto)
6808         mask[16] = mask[17] = 0xff;
6809
6810       *maskp = mask;
6811       return 1;
6812     }
6813   if (cos2)
6814     mask[18] |= 0xe0;
6815   if (cos1)
6816     mask[14] |= 0xe0;
6817   if (proto)
6818     mask[12] = mask[13] = 0xff;
6819
6820   *maskp = mask;
6821   return 1;
6822 }
6823
6824 uword
6825 unformat_classify_mask (unformat_input_t * input, va_list * args)
6826 {
6827   u8 **maskp = va_arg (*args, u8 **);
6828   u32 *skipp = va_arg (*args, u32 *);
6829   u32 *matchp = va_arg (*args, u32 *);
6830   u32 match;
6831   u8 *mask = 0;
6832   u8 *l2 = 0;
6833   u8 *l3 = 0;
6834   u8 *l4 = 0;
6835   int i;
6836
6837   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6838     {
6839       if (unformat (input, "hex %U", unformat_hex_string, &mask))
6840         ;
6841       else if (unformat (input, "l2 %U", unformat_l2_mask, &l2))
6842         ;
6843       else if (unformat (input, "l3 %U", unformat_l3_mask, &l3))
6844         ;
6845       else if (unformat (input, "l4 %U", unformat_l4_mask, &l4))
6846         ;
6847       else
6848         break;
6849     }
6850
6851   if (l4 && !l3)
6852     {
6853       vec_free (mask);
6854       vec_free (l2);
6855       vec_free (l4);
6856       return 0;
6857     }
6858
6859   if (mask || l2 || l3 || l4)
6860     {
6861       if (l2 || l3 || l4)
6862         {
6863           /* "With a free Ethernet header in every package" */
6864           if (l2 == 0)
6865             vec_validate (l2, 13);
6866           mask = l2;
6867           if (vec_len (l3))
6868             {
6869               vec_append (mask, l3);
6870               vec_free (l3);
6871             }
6872           if (vec_len (l4))
6873             {
6874               vec_append (mask, l4);
6875               vec_free (l4);
6876             }
6877         }
6878
6879       /* Scan forward looking for the first significant mask octet */
6880       for (i = 0; i < vec_len (mask); i++)
6881         if (mask[i])
6882           break;
6883
6884       /* compute (skip, match) params */
6885       *skipp = i / sizeof (u32x4);
6886       vec_delete (mask, *skipp * sizeof (u32x4), 0);
6887
6888       /* Pad mask to an even multiple of the vector size */
6889       while (vec_len (mask) % sizeof (u32x4))
6890         vec_add1 (mask, 0);
6891
6892       match = vec_len (mask) / sizeof (u32x4);
6893
6894       for (i = match * sizeof (u32x4); i > 0; i -= sizeof (u32x4))
6895         {
6896           u64 *tmp = (u64 *) (mask + (i - sizeof (u32x4)));
6897           if (*tmp || *(tmp + 1))
6898             break;
6899           match--;
6900         }
6901       if (match == 0)
6902         clib_warning ("BUG: match 0");
6903
6904       _vec_len (mask) = match * sizeof (u32x4);
6905
6906       *matchp = match;
6907       *maskp = mask;
6908
6909       return 1;
6910     }
6911
6912   return 0;
6913 }
6914 #endif /* VPP_API_TEST_BUILTIN */
6915
6916 #define foreach_l2_next                         \
6917 _(drop, DROP)                                   \
6918 _(ethernet, ETHERNET_INPUT)                     \
6919 _(ip4, IP4_INPUT)                               \
6920 _(ip6, IP6_INPUT)
6921
6922 uword
6923 unformat_l2_next_index (unformat_input_t * input, va_list * args)
6924 {
6925   u32 *miss_next_indexp = va_arg (*args, u32 *);
6926   u32 next_index = 0;
6927   u32 tmp;
6928
6929 #define _(n,N) \
6930   if (unformat (input, #n)) { next_index = L2_INPUT_CLASSIFY_NEXT_##N; goto out;}
6931   foreach_l2_next;
6932 #undef _
6933
6934   if (unformat (input, "%d", &tmp))
6935     {
6936       next_index = tmp;
6937       goto out;
6938     }
6939
6940   return 0;
6941
6942 out:
6943   *miss_next_indexp = next_index;
6944   return 1;
6945 }
6946
6947 #define foreach_ip_next                         \
6948 _(drop, DROP)                                   \
6949 _(local, LOCAL)                                 \
6950 _(rewrite, REWRITE)
6951
6952 uword
6953 api_unformat_ip_next_index (unformat_input_t * input, va_list * args)
6954 {
6955   u32 *miss_next_indexp = va_arg (*args, u32 *);
6956   u32 next_index = 0;
6957   u32 tmp;
6958
6959 #define _(n,N) \
6960   if (unformat (input, #n)) { next_index = IP_LOOKUP_NEXT_##N; goto out;}
6961   foreach_ip_next;
6962 #undef _
6963
6964   if (unformat (input, "%d", &tmp))
6965     {
6966       next_index = tmp;
6967       goto out;
6968     }
6969
6970   return 0;
6971
6972 out:
6973   *miss_next_indexp = next_index;
6974   return 1;
6975 }
6976
6977 #define foreach_acl_next                        \
6978 _(deny, DENY)
6979
6980 uword
6981 api_unformat_acl_next_index (unformat_input_t * input, va_list * args)
6982 {
6983   u32 *miss_next_indexp = va_arg (*args, u32 *);
6984   u32 next_index = 0;
6985   u32 tmp;
6986
6987 #define _(n,N) \
6988   if (unformat (input, #n)) { next_index = ACL_NEXT_INDEX_##N; goto out;}
6989   foreach_acl_next;
6990 #undef _
6991
6992   if (unformat (input, "permit"))
6993     {
6994       next_index = ~0;
6995       goto out;
6996     }
6997   else if (unformat (input, "%d", &tmp))
6998     {
6999       next_index = tmp;
7000       goto out;
7001     }
7002
7003   return 0;
7004
7005 out:
7006   *miss_next_indexp = next_index;
7007   return 1;
7008 }
7009
7010 uword
7011 unformat_policer_precolor (unformat_input_t * input, va_list * args)
7012 {
7013   u32 *r = va_arg (*args, u32 *);
7014
7015   if (unformat (input, "conform-color"))
7016     *r = POLICE_CONFORM;
7017   else if (unformat (input, "exceed-color"))
7018     *r = POLICE_EXCEED;
7019   else
7020     return 0;
7021
7022   return 1;
7023 }
7024
7025 #if VPP_API_TEST_BUILTIN == 0
7026 uword
7027 unformat_l4_match (unformat_input_t * input, va_list * args)
7028 {
7029   u8 **matchp = va_arg (*args, u8 **);
7030
7031   u8 *proto_header = 0;
7032   int src_port = 0;
7033   int dst_port = 0;
7034
7035   tcpudp_header_t h;
7036
7037   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7038     {
7039       if (unformat (input, "src_port %d", &src_port))
7040         ;
7041       else if (unformat (input, "dst_port %d", &dst_port))
7042         ;
7043       else
7044         return 0;
7045     }
7046
7047   h.src_port = clib_host_to_net_u16 (src_port);
7048   h.dst_port = clib_host_to_net_u16 (dst_port);
7049   vec_validate (proto_header, sizeof (h) - 1);
7050   memcpy (proto_header, &h, sizeof (h));
7051
7052   *matchp = proto_header;
7053
7054   return 1;
7055 }
7056
7057 uword
7058 unformat_ip4_match (unformat_input_t * input, va_list * args)
7059 {
7060   u8 **matchp = va_arg (*args, u8 **);
7061   u8 *match = 0;
7062   ip4_header_t *ip;
7063   int version = 0;
7064   u32 version_val;
7065   int hdr_length = 0;
7066   u32 hdr_length_val;
7067   int src = 0, dst = 0;
7068   ip4_address_t src_val, dst_val;
7069   int proto = 0;
7070   u32 proto_val;
7071   int tos = 0;
7072   u32 tos_val;
7073   int length = 0;
7074   u32 length_val;
7075   int fragment_id = 0;
7076   u32 fragment_id_val;
7077   int ttl = 0;
7078   int ttl_val;
7079   int checksum = 0;
7080   u32 checksum_val;
7081
7082   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7083     {
7084       if (unformat (input, "version %d", &version_val))
7085         version = 1;
7086       else if (unformat (input, "hdr_length %d", &hdr_length_val))
7087         hdr_length = 1;
7088       else if (unformat (input, "src %U", unformat_ip4_address, &src_val))
7089         src = 1;
7090       else if (unformat (input, "dst %U", unformat_ip4_address, &dst_val))
7091         dst = 1;
7092       else if (unformat (input, "proto %d", &proto_val))
7093         proto = 1;
7094       else if (unformat (input, "tos %d", &tos_val))
7095         tos = 1;
7096       else if (unformat (input, "length %d", &length_val))
7097         length = 1;
7098       else if (unformat (input, "fragment_id %d", &fragment_id_val))
7099         fragment_id = 1;
7100       else if (unformat (input, "ttl %d", &ttl_val))
7101         ttl = 1;
7102       else if (unformat (input, "checksum %d", &checksum_val))
7103         checksum = 1;
7104       else
7105         break;
7106     }
7107
7108   if (version + hdr_length + src + dst + proto + tos + length + fragment_id
7109       + ttl + checksum == 0)
7110     return 0;
7111
7112   /*
7113    * Aligned because we use the real comparison functions
7114    */
7115   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
7116
7117   ip = (ip4_header_t *) match;
7118
7119   /* These are realistically matched in practice */
7120   if (src)
7121     ip->src_address.as_u32 = src_val.as_u32;
7122
7123   if (dst)
7124     ip->dst_address.as_u32 = dst_val.as_u32;
7125
7126   if (proto)
7127     ip->protocol = proto_val;
7128
7129
7130   /* These are not, but they're included for completeness */
7131   if (version)
7132     ip->ip_version_and_header_length |= (version_val & 0xF) << 4;
7133
7134   if (hdr_length)
7135     ip->ip_version_and_header_length |= (hdr_length_val & 0xF);
7136
7137   if (tos)
7138     ip->tos = tos_val;
7139
7140   if (length)
7141     ip->length = clib_host_to_net_u16 (length_val);
7142
7143   if (ttl)
7144     ip->ttl = ttl_val;
7145
7146   if (checksum)
7147     ip->checksum = clib_host_to_net_u16 (checksum_val);
7148
7149   *matchp = match;
7150   return 1;
7151 }
7152
7153 uword
7154 unformat_ip6_match (unformat_input_t * input, va_list * args)
7155 {
7156   u8 **matchp = va_arg (*args, u8 **);
7157   u8 *match = 0;
7158   ip6_header_t *ip;
7159   int version = 0;
7160   u32 version_val;
7161   u8 traffic_class = 0;
7162   u32 traffic_class_val = 0;
7163   u8 flow_label = 0;
7164   u8 flow_label_val;
7165   int src = 0, dst = 0;
7166   ip6_address_t src_val, dst_val;
7167   int proto = 0;
7168   u32 proto_val;
7169   int payload_length = 0;
7170   u32 payload_length_val;
7171   int hop_limit = 0;
7172   int hop_limit_val;
7173   u32 ip_version_traffic_class_and_flow_label;
7174
7175   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7176     {
7177       if (unformat (input, "version %d", &version_val))
7178         version = 1;
7179       else if (unformat (input, "traffic_class %d", &traffic_class_val))
7180         traffic_class = 1;
7181       else if (unformat (input, "flow_label %d", &flow_label_val))
7182         flow_label = 1;
7183       else if (unformat (input, "src %U", unformat_ip6_address, &src_val))
7184         src = 1;
7185       else if (unformat (input, "dst %U", unformat_ip6_address, &dst_val))
7186         dst = 1;
7187       else if (unformat (input, "proto %d", &proto_val))
7188         proto = 1;
7189       else if (unformat (input, "payload_length %d", &payload_length_val))
7190         payload_length = 1;
7191       else if (unformat (input, "hop_limit %d", &hop_limit_val))
7192         hop_limit = 1;
7193       else
7194         break;
7195     }
7196
7197   if (version + traffic_class + flow_label + src + dst + proto +
7198       payload_length + hop_limit == 0)
7199     return 0;
7200
7201   /*
7202    * Aligned because we use the real comparison functions
7203    */
7204   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
7205
7206   ip = (ip6_header_t *) match;
7207
7208   if (src)
7209     clib_memcpy (&ip->src_address, &src_val, sizeof (ip->src_address));
7210
7211   if (dst)
7212     clib_memcpy (&ip->dst_address, &dst_val, sizeof (ip->dst_address));
7213
7214   if (proto)
7215     ip->protocol = proto_val;
7216
7217   ip_version_traffic_class_and_flow_label = 0;
7218
7219   if (version)
7220     ip_version_traffic_class_and_flow_label |= (version_val & 0xF) << 28;
7221
7222   if (traffic_class)
7223     ip_version_traffic_class_and_flow_label |=
7224       (traffic_class_val & 0xFF) << 20;
7225
7226   if (flow_label)
7227     ip_version_traffic_class_and_flow_label |= (flow_label_val & 0xFFFFF);
7228
7229   ip->ip_version_traffic_class_and_flow_label =
7230     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
7231
7232   if (payload_length)
7233     ip->payload_length = clib_host_to_net_u16 (payload_length_val);
7234
7235   if (hop_limit)
7236     ip->hop_limit = hop_limit_val;
7237
7238   *matchp = match;
7239   return 1;
7240 }
7241
7242 uword
7243 unformat_l3_match (unformat_input_t * input, va_list * args)
7244 {
7245   u8 **matchp = va_arg (*args, u8 **);
7246
7247   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7248     {
7249       if (unformat (input, "ip4 %U", unformat_ip4_match, matchp))
7250         return 1;
7251       else if (unformat (input, "ip6 %U", unformat_ip6_match, matchp))
7252         return 1;
7253       else
7254         break;
7255     }
7256   return 0;
7257 }
7258
7259 uword
7260 unformat_vlan_tag (unformat_input_t * input, va_list * args)
7261 {
7262   u8 *tagp = va_arg (*args, u8 *);
7263   u32 tag;
7264
7265   if (unformat (input, "%d", &tag))
7266     {
7267       tagp[0] = (tag >> 8) & 0x0F;
7268       tagp[1] = tag & 0xFF;
7269       return 1;
7270     }
7271
7272   return 0;
7273 }
7274
7275 uword
7276 unformat_l2_match (unformat_input_t * input, va_list * args)
7277 {
7278   u8 **matchp = va_arg (*args, u8 **);
7279   u8 *match = 0;
7280   u8 src = 0;
7281   u8 src_val[6];
7282   u8 dst = 0;
7283   u8 dst_val[6];
7284   u8 proto = 0;
7285   u16 proto_val;
7286   u8 tag1 = 0;
7287   u8 tag1_val[2];
7288   u8 tag2 = 0;
7289   u8 tag2_val[2];
7290   int len = 14;
7291   u8 ignore_tag1 = 0;
7292   u8 ignore_tag2 = 0;
7293   u8 cos1 = 0;
7294   u8 cos2 = 0;
7295   u32 cos1_val = 0;
7296   u32 cos2_val = 0;
7297
7298   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7299     {
7300       if (unformat (input, "src %U", unformat_ethernet_address, &src_val))
7301         src = 1;
7302       else
7303         if (unformat (input, "dst %U", unformat_ethernet_address, &dst_val))
7304         dst = 1;
7305       else if (unformat (input, "proto %U",
7306                          unformat_ethernet_type_host_byte_order, &proto_val))
7307         proto = 1;
7308       else if (unformat (input, "tag1 %U", unformat_vlan_tag, tag1_val))
7309         tag1 = 1;
7310       else if (unformat (input, "tag2 %U", unformat_vlan_tag, tag2_val))
7311         tag2 = 1;
7312       else if (unformat (input, "ignore-tag1"))
7313         ignore_tag1 = 1;
7314       else if (unformat (input, "ignore-tag2"))
7315         ignore_tag2 = 1;
7316       else if (unformat (input, "cos1 %d", &cos1_val))
7317         cos1 = 1;
7318       else if (unformat (input, "cos2 %d", &cos2_val))
7319         cos2 = 1;
7320       else
7321         break;
7322     }
7323   if ((src + dst + proto + tag1 + tag2 +
7324        ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
7325     return 0;
7326
7327   if (tag1 || ignore_tag1 || cos1)
7328     len = 18;
7329   if (tag2 || ignore_tag2 || cos2)
7330     len = 22;
7331
7332   vec_validate_aligned (match, len - 1, sizeof (u32x4));
7333
7334   if (dst)
7335     clib_memcpy (match, dst_val, 6);
7336
7337   if (src)
7338     clib_memcpy (match + 6, src_val, 6);
7339
7340   if (tag2)
7341     {
7342       /* inner vlan tag */
7343       match[19] = tag2_val[1];
7344       match[18] = tag2_val[0];
7345       if (cos2)
7346         match[18] |= (cos2_val & 0x7) << 5;
7347       if (proto)
7348         {
7349           match[21] = proto_val & 0xff;
7350           match[20] = proto_val >> 8;
7351         }
7352       if (tag1)
7353         {
7354           match[15] = tag1_val[1];
7355           match[14] = tag1_val[0];
7356         }
7357       if (cos1)
7358         match[14] |= (cos1_val & 0x7) << 5;
7359       *matchp = match;
7360       return 1;
7361     }
7362   if (tag1)
7363     {
7364       match[15] = tag1_val[1];
7365       match[14] = tag1_val[0];
7366       if (proto)
7367         {
7368           match[17] = proto_val & 0xff;
7369           match[16] = proto_val >> 8;
7370         }
7371       if (cos1)
7372         match[14] |= (cos1_val & 0x7) << 5;
7373
7374       *matchp = match;
7375       return 1;
7376     }
7377   if (cos2)
7378     match[18] |= (cos2_val & 0x7) << 5;
7379   if (cos1)
7380     match[14] |= (cos1_val & 0x7) << 5;
7381   if (proto)
7382     {
7383       match[13] = proto_val & 0xff;
7384       match[12] = proto_val >> 8;
7385     }
7386
7387   *matchp = match;
7388   return 1;
7389 }
7390
7391 uword
7392 unformat_qos_source (unformat_input_t * input, va_list * args)
7393 {
7394   int *qs = va_arg (*args, int *);
7395
7396   if (unformat (input, "ip"))
7397     *qs = QOS_SOURCE_IP;
7398   else if (unformat (input, "mpls"))
7399     *qs = QOS_SOURCE_MPLS;
7400   else if (unformat (input, "ext"))
7401     *qs = QOS_SOURCE_EXT;
7402   else if (unformat (input, "vlan"))
7403     *qs = QOS_SOURCE_VLAN;
7404   else
7405     return 0;
7406
7407   return 1;
7408 }
7409 #endif
7410
7411 uword
7412 api_unformat_classify_match (unformat_input_t * input, va_list * args)
7413 {
7414   u8 **matchp = va_arg (*args, u8 **);
7415   u32 skip_n_vectors = va_arg (*args, u32);
7416   u32 match_n_vectors = va_arg (*args, u32);
7417
7418   u8 *match = 0;
7419   u8 *l2 = 0;
7420   u8 *l3 = 0;
7421   u8 *l4 = 0;
7422
7423   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7424     {
7425       if (unformat (input, "hex %U", unformat_hex_string, &match))
7426         ;
7427       else if (unformat (input, "l2 %U", unformat_l2_match, &l2))
7428         ;
7429       else if (unformat (input, "l3 %U", unformat_l3_match, &l3))
7430         ;
7431       else if (unformat (input, "l4 %U", unformat_l4_match, &l4))
7432         ;
7433       else
7434         break;
7435     }
7436
7437   if (l4 && !l3)
7438     {
7439       vec_free (match);
7440       vec_free (l2);
7441       vec_free (l4);
7442       return 0;
7443     }
7444
7445   if (match || l2 || l3 || l4)
7446     {
7447       if (l2 || l3 || l4)
7448         {
7449           /* "Win a free Ethernet header in every packet" */
7450           if (l2 == 0)
7451             vec_validate_aligned (l2, 13, sizeof (u32x4));
7452           match = l2;
7453           if (vec_len (l3))
7454             {
7455               vec_append_aligned (match, l3, sizeof (u32x4));
7456               vec_free (l3);
7457             }
7458           if (vec_len (l4))
7459             {
7460               vec_append_aligned (match, l4, sizeof (u32x4));
7461               vec_free (l4);
7462             }
7463         }
7464
7465       /* Make sure the vector is big enough even if key is all 0's */
7466       vec_validate_aligned
7467         (match, ((match_n_vectors + skip_n_vectors) * sizeof (u32x4)) - 1,
7468          sizeof (u32x4));
7469
7470       /* Set size, include skipped vectors */
7471       _vec_len (match) = (match_n_vectors + skip_n_vectors) * sizeof (u32x4);
7472
7473       *matchp = match;
7474
7475       return 1;
7476     }
7477
7478   return 0;
7479 }
7480
7481 static int
7482 api_get_node_index (vat_main_t * vam)
7483 {
7484   unformat_input_t *i = vam->input;
7485   vl_api_get_node_index_t *mp;
7486   u8 *name = 0;
7487   int ret;
7488
7489   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7490     {
7491       if (unformat (i, "node %s", &name))
7492         ;
7493       else
7494         break;
7495     }
7496   if (name == 0)
7497     {
7498       errmsg ("node name required");
7499       return -99;
7500     }
7501   if (vec_len (name) >= ARRAY_LEN (mp->node_name))
7502     {
7503       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
7504       return -99;
7505     }
7506
7507   M (GET_NODE_INDEX, mp);
7508   clib_memcpy (mp->node_name, name, vec_len (name));
7509   vec_free (name);
7510
7511   S (mp);
7512   W (ret);
7513   return ret;
7514 }
7515
7516 static int
7517 api_get_next_index (vat_main_t * vam)
7518 {
7519   unformat_input_t *i = vam->input;
7520   vl_api_get_next_index_t *mp;
7521   u8 *node_name = 0, *next_node_name = 0;
7522   int ret;
7523
7524   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7525     {
7526       if (unformat (i, "node-name %s", &node_name))
7527         ;
7528       else if (unformat (i, "next-node-name %s", &next_node_name))
7529         break;
7530     }
7531
7532   if (node_name == 0)
7533     {
7534       errmsg ("node name required");
7535       return -99;
7536     }
7537   if (vec_len (node_name) >= ARRAY_LEN (mp->node_name))
7538     {
7539       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
7540       return -99;
7541     }
7542
7543   if (next_node_name == 0)
7544     {
7545       errmsg ("next node name required");
7546       return -99;
7547     }
7548   if (vec_len (next_node_name) >= ARRAY_LEN (mp->next_name))
7549     {
7550       errmsg ("next node name too long, max %d", ARRAY_LEN (mp->next_name));
7551       return -99;
7552     }
7553
7554   M (GET_NEXT_INDEX, mp);
7555   clib_memcpy (mp->node_name, node_name, vec_len (node_name));
7556   clib_memcpy (mp->next_name, next_node_name, vec_len (next_node_name));
7557   vec_free (node_name);
7558   vec_free (next_node_name);
7559
7560   S (mp);
7561   W (ret);
7562   return ret;
7563 }
7564
7565 static int
7566 api_add_node_next (vat_main_t * vam)
7567 {
7568   unformat_input_t *i = vam->input;
7569   vl_api_add_node_next_t *mp;
7570   u8 *name = 0;
7571   u8 *next = 0;
7572   int ret;
7573
7574   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7575     {
7576       if (unformat (i, "node %s", &name))
7577         ;
7578       else if (unformat (i, "next %s", &next))
7579         ;
7580       else
7581         break;
7582     }
7583   if (name == 0)
7584     {
7585       errmsg ("node name required");
7586       return -99;
7587     }
7588   if (vec_len (name) >= ARRAY_LEN (mp->node_name))
7589     {
7590       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
7591       return -99;
7592     }
7593   if (next == 0)
7594     {
7595       errmsg ("next node required");
7596       return -99;
7597     }
7598   if (vec_len (next) >= ARRAY_LEN (mp->next_name))
7599     {
7600       errmsg ("next name too long, max %d", ARRAY_LEN (mp->next_name));
7601       return -99;
7602     }
7603
7604   M (ADD_NODE_NEXT, mp);
7605   clib_memcpy (mp->node_name, name, vec_len (name));
7606   clib_memcpy (mp->next_name, next, vec_len (next));
7607   vec_free (name);
7608   vec_free (next);
7609
7610   S (mp);
7611   W (ret);
7612   return ret;
7613 }
7614
7615 static void vl_api_sw_interface_tap_v2_details_t_handler
7616   (vl_api_sw_interface_tap_v2_details_t * mp)
7617 {
7618   vat_main_t *vam = &vat_main;
7619
7620   u8 *ip4 =
7621     format (0, "%U/%d", format_ip4_address, mp->host_ip4_prefix.address,
7622             mp->host_ip4_prefix.len);
7623   u8 *ip6 =
7624     format (0, "%U/%d", format_ip6_address, mp->host_ip6_prefix.address,
7625             mp->host_ip6_prefix.len);
7626
7627   print (vam->ofp,
7628          "\n%-16s %-12d %-5d %-12d %-12d %-14U %-30s %-20s %-20s %-30s 0x%-08x",
7629          mp->dev_name, ntohl (mp->sw_if_index), ntohl (mp->id),
7630          ntohs (mp->rx_ring_sz), ntohs (mp->tx_ring_sz),
7631          format_ethernet_address, mp->host_mac_addr, mp->host_namespace,
7632          mp->host_bridge, ip4, ip6, ntohl (mp->tap_flags));
7633
7634   vec_free (ip4);
7635   vec_free (ip6);
7636 }
7637
7638 static void vl_api_sw_interface_tap_v2_details_t_handler_json
7639   (vl_api_sw_interface_tap_v2_details_t * mp)
7640 {
7641   vat_main_t *vam = &vat_main;
7642   vat_json_node_t *node = NULL;
7643
7644   if (VAT_JSON_ARRAY != vam->json_tree.type)
7645     {
7646       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
7647       vat_json_init_array (&vam->json_tree);
7648     }
7649   node = vat_json_array_add (&vam->json_tree);
7650
7651   vat_json_init_object (node);
7652   vat_json_object_add_uint (node, "id", ntohl (mp->id));
7653   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
7654   vat_json_object_add_uint (node, "tap_flags", ntohl (mp->tap_flags));
7655   vat_json_object_add_string_copy (node, "dev_name", mp->dev_name);
7656   vat_json_object_add_uint (node, "rx_ring_sz", ntohs (mp->rx_ring_sz));
7657   vat_json_object_add_uint (node, "tx_ring_sz", ntohs (mp->tx_ring_sz));
7658   vat_json_object_add_string_copy (node, "host_mac_addr",
7659                                    format (0, "%U", format_ethernet_address,
7660                                            &mp->host_mac_addr));
7661   vat_json_object_add_string_copy (node, "host_namespace",
7662                                    mp->host_namespace);
7663   vat_json_object_add_string_copy (node, "host_bridge", mp->host_bridge);
7664   vat_json_object_add_string_copy (node, "host_ip4_addr",
7665                                    format (0, "%U/%d", format_ip4_address,
7666                                            mp->host_ip4_prefix.address,
7667                                            mp->host_ip4_prefix.len));
7668   vat_json_object_add_string_copy (node, "host_ip6_prefix",
7669                                    format (0, "%U/%d", format_ip6_address,
7670                                            mp->host_ip6_prefix.address,
7671                                            mp->host_ip6_prefix.len));
7672
7673 }
7674
7675 static int
7676 api_sw_interface_tap_v2_dump (vat_main_t * vam)
7677 {
7678   vl_api_sw_interface_tap_v2_dump_t *mp;
7679   vl_api_control_ping_t *mp_ping;
7680   int ret;
7681
7682   print (vam->ofp,
7683          "\n%-16s %-12s %-5s %-12s %-12s %-14s %-30s %-20s %-20s %-30s",
7684          "dev_name", "sw_if_index", "id", "rx_ring_sz", "tx_ring_sz",
7685          "host_mac_addr", "host_namespace", "host_bridge", "host_ip4_addr",
7686          "host_ip6_addr");
7687
7688   /* Get list of tap interfaces */
7689   M (SW_INTERFACE_TAP_V2_DUMP, mp);
7690   S (mp);
7691
7692   /* Use a control ping for synchronization */
7693   MPING (CONTROL_PING, mp_ping);
7694   S (mp_ping);
7695
7696   W (ret);
7697   return ret;
7698 }
7699
7700 static void vl_api_sw_interface_virtio_pci_details_t_handler
7701   (vl_api_sw_interface_virtio_pci_details_t * mp)
7702 {
7703   vat_main_t *vam = &vat_main;
7704
7705   typedef union
7706   {
7707     struct
7708     {
7709       u16 domain;
7710       u8 bus;
7711       u8 slot:5;
7712       u8 function:3;
7713     };
7714     u32 as_u32;
7715   } pci_addr_t;
7716   pci_addr_t addr;
7717
7718   addr.domain = ntohs (mp->pci_addr.domain);
7719   addr.bus = mp->pci_addr.bus;
7720   addr.slot = mp->pci_addr.slot;
7721   addr.function = mp->pci_addr.function;
7722
7723   u8 *pci_addr = format (0, "%04x:%02x:%02x.%x", addr.domain, addr.bus,
7724                          addr.slot, addr.function);
7725
7726   print (vam->ofp,
7727          "\n%-12s %-12d %-12d %-12d %-17U 0x%-08llx",
7728          pci_addr, ntohl (mp->sw_if_index),
7729          ntohs (mp->rx_ring_sz), ntohs (mp->tx_ring_sz),
7730          format_ethernet_address, mp->mac_addr,
7731          clib_net_to_host_u64 (mp->features));
7732   vec_free (pci_addr);
7733 }
7734
7735 static void vl_api_sw_interface_virtio_pci_details_t_handler_json
7736   (vl_api_sw_interface_virtio_pci_details_t * mp)
7737 {
7738   vat_main_t *vam = &vat_main;
7739   vat_json_node_t *node = NULL;
7740   vlib_pci_addr_t pci_addr;
7741
7742   if (VAT_JSON_ARRAY != vam->json_tree.type)
7743     {
7744       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
7745       vat_json_init_array (&vam->json_tree);
7746     }
7747   node = vat_json_array_add (&vam->json_tree);
7748
7749   pci_addr.domain = ntohs (mp->pci_addr.domain);
7750   pci_addr.bus = mp->pci_addr.bus;
7751   pci_addr.slot = mp->pci_addr.slot;
7752   pci_addr.function = mp->pci_addr.function;
7753
7754   vat_json_init_object (node);
7755   vat_json_object_add_uint (node, "pci-addr", pci_addr.as_u32);
7756   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
7757   vat_json_object_add_uint (node, "rx_ring_sz", ntohs (mp->rx_ring_sz));
7758   vat_json_object_add_uint (node, "tx_ring_sz", ntohs (mp->tx_ring_sz));
7759   vat_json_object_add_uint (node, "features",
7760                             clib_net_to_host_u64 (mp->features));
7761   vat_json_object_add_string_copy (node, "mac_addr",
7762                                    format (0, "%U", format_ethernet_address,
7763                                            &mp->mac_addr));
7764 }
7765
7766 static int
7767 api_sw_interface_virtio_pci_dump (vat_main_t * vam)
7768 {
7769   vl_api_sw_interface_virtio_pci_dump_t *mp;
7770   vl_api_control_ping_t *mp_ping;
7771   int ret;
7772
7773   print (vam->ofp,
7774          "\n%-12s %-12s %-12s %-12s %-17s %-08s",
7775          "pci_addr", "sw_if_index", "rx_ring_sz", "tx_ring_sz",
7776          "mac_addr", "features");
7777
7778   /* Get list of tap interfaces */
7779   M (SW_INTERFACE_VIRTIO_PCI_DUMP, mp);
7780   S (mp);
7781
7782   /* Use a control ping for synchronization */
7783   MPING (CONTROL_PING, mp_ping);
7784   S (mp_ping);
7785
7786   W (ret);
7787   return ret;
7788 }
7789
7790 static int
7791 api_l2_fib_clear_table (vat_main_t * vam)
7792 {
7793 //  unformat_input_t * i = vam->input;
7794   vl_api_l2_fib_clear_table_t *mp;
7795   int ret;
7796
7797   M (L2_FIB_CLEAR_TABLE, mp);
7798
7799   S (mp);
7800   W (ret);
7801   return ret;
7802 }
7803
7804 static int
7805 api_l2_interface_efp_filter (vat_main_t * vam)
7806 {
7807   unformat_input_t *i = vam->input;
7808   vl_api_l2_interface_efp_filter_t *mp;
7809   u32 sw_if_index;
7810   u8 enable = 1;
7811   u8 sw_if_index_set = 0;
7812   int ret;
7813
7814   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7815     {
7816       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
7817         sw_if_index_set = 1;
7818       else if (unformat (i, "sw_if_index %d", &sw_if_index))
7819         sw_if_index_set = 1;
7820       else if (unformat (i, "enable"))
7821         enable = 1;
7822       else if (unformat (i, "disable"))
7823         enable = 0;
7824       else
7825         {
7826           clib_warning ("parse error '%U'", format_unformat_error, i);
7827           return -99;
7828         }
7829     }
7830
7831   if (sw_if_index_set == 0)
7832     {
7833       errmsg ("missing sw_if_index");
7834       return -99;
7835     }
7836
7837   M (L2_INTERFACE_EFP_FILTER, mp);
7838
7839   mp->sw_if_index = ntohl (sw_if_index);
7840   mp->enable_disable = enable;
7841
7842   S (mp);
7843   W (ret);
7844   return ret;
7845 }
7846
7847 #define foreach_vtr_op                          \
7848 _("disable",  L2_VTR_DISABLED)                  \
7849 _("push-1",  L2_VTR_PUSH_1)                     \
7850 _("push-2",  L2_VTR_PUSH_2)                     \
7851 _("pop-1",  L2_VTR_POP_1)                       \
7852 _("pop-2",  L2_VTR_POP_2)                       \
7853 _("translate-1-1",  L2_VTR_TRANSLATE_1_1)       \
7854 _("translate-1-2",  L2_VTR_TRANSLATE_1_2)       \
7855 _("translate-2-1",  L2_VTR_TRANSLATE_2_1)       \
7856 _("translate-2-2",  L2_VTR_TRANSLATE_2_2)
7857
7858 static int
7859 api_l2_interface_vlan_tag_rewrite (vat_main_t * vam)
7860 {
7861   unformat_input_t *i = vam->input;
7862   vl_api_l2_interface_vlan_tag_rewrite_t *mp;
7863   u32 sw_if_index;
7864   u8 sw_if_index_set = 0;
7865   u8 vtr_op_set = 0;
7866   u32 vtr_op = 0;
7867   u32 push_dot1q = 1;
7868   u32 tag1 = ~0;
7869   u32 tag2 = ~0;
7870   int ret;
7871
7872   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7873     {
7874       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
7875         sw_if_index_set = 1;
7876       else if (unformat (i, "sw_if_index %d", &sw_if_index))
7877         sw_if_index_set = 1;
7878       else if (unformat (i, "vtr_op %d", &vtr_op))
7879         vtr_op_set = 1;
7880 #define _(n,v) else if (unformat(i, n)) {vtr_op = v; vtr_op_set = 1;}
7881       foreach_vtr_op
7882 #undef _
7883         else if (unformat (i, "push_dot1q %d", &push_dot1q))
7884         ;
7885       else if (unformat (i, "tag1 %d", &tag1))
7886         ;
7887       else if (unformat (i, "tag2 %d", &tag2))
7888         ;
7889       else
7890         {
7891           clib_warning ("parse error '%U'", format_unformat_error, i);
7892           return -99;
7893         }
7894     }
7895
7896   if ((sw_if_index_set == 0) || (vtr_op_set == 0))
7897     {
7898       errmsg ("missing vtr operation or sw_if_index");
7899       return -99;
7900     }
7901
7902   M (L2_INTERFACE_VLAN_TAG_REWRITE, mp);
7903   mp->sw_if_index = ntohl (sw_if_index);
7904   mp->vtr_op = ntohl (vtr_op);
7905   mp->push_dot1q = ntohl (push_dot1q);
7906   mp->tag1 = ntohl (tag1);
7907   mp->tag2 = ntohl (tag2);
7908
7909   S (mp);
7910   W (ret);
7911   return ret;
7912 }
7913
7914 static int
7915 api_create_vhost_user_if (vat_main_t * vam)
7916 {
7917   unformat_input_t *i = vam->input;
7918   vl_api_create_vhost_user_if_t *mp;
7919   u8 *file_name;
7920   u8 is_server = 0;
7921   u8 file_name_set = 0;
7922   u32 custom_dev_instance = ~0;
7923   u8 hwaddr[6];
7924   u8 use_custom_mac = 0;
7925   u8 disable_mrg_rxbuf = 0;
7926   u8 disable_indirect_desc = 0;
7927   u8 *tag = 0;
7928   u8 enable_gso = 0;
7929   u8 enable_packed = 0;
7930   int ret;
7931
7932   /* Shut up coverity */
7933   clib_memset (hwaddr, 0, sizeof (hwaddr));
7934
7935   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7936     {
7937       if (unformat (i, "socket %s", &file_name))
7938         {
7939           file_name_set = 1;
7940         }
7941       else if (unformat (i, "renumber %" PRIu32, &custom_dev_instance))
7942         ;
7943       else if (unformat (i, "mac %U", unformat_ethernet_address, hwaddr))
7944         use_custom_mac = 1;
7945       else if (unformat (i, "server"))
7946         is_server = 1;
7947       else if (unformat (i, "disable_mrg_rxbuf"))
7948         disable_mrg_rxbuf = 1;
7949       else if (unformat (i, "disable_indirect_desc"))
7950         disable_indirect_desc = 1;
7951       else if (unformat (i, "gso"))
7952         enable_gso = 1;
7953       else if (unformat (i, "packed"))
7954         enable_packed = 1;
7955       else if (unformat (i, "tag %s", &tag))
7956         ;
7957       else
7958         break;
7959     }
7960
7961   if (file_name_set == 0)
7962     {
7963       errmsg ("missing socket file name");
7964       return -99;
7965     }
7966
7967   if (vec_len (file_name) > 255)
7968     {
7969       errmsg ("socket file name too long");
7970       return -99;
7971     }
7972   vec_add1 (file_name, 0);
7973
7974   M (CREATE_VHOST_USER_IF, mp);
7975
7976   mp->is_server = is_server;
7977   mp->disable_mrg_rxbuf = disable_mrg_rxbuf;
7978   mp->disable_indirect_desc = disable_indirect_desc;
7979   mp->enable_gso = enable_gso;
7980   mp->enable_packed = enable_packed;
7981   mp->custom_dev_instance = ntohl (custom_dev_instance);
7982   clib_memcpy (mp->sock_filename, file_name, vec_len (file_name));
7983   vec_free (file_name);
7984   if (custom_dev_instance != ~0)
7985     mp->renumber = 1;
7986
7987   mp->use_custom_mac = use_custom_mac;
7988   clib_memcpy (mp->mac_address, hwaddr, 6);
7989   if (tag)
7990     strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
7991   vec_free (tag);
7992
7993   S (mp);
7994   W (ret);
7995   return ret;
7996 }
7997
7998 static int
7999 api_modify_vhost_user_if (vat_main_t * vam)
8000 {
8001   unformat_input_t *i = vam->input;
8002   vl_api_modify_vhost_user_if_t *mp;
8003   u8 *file_name;
8004   u8 is_server = 0;
8005   u8 file_name_set = 0;
8006   u32 custom_dev_instance = ~0;
8007   u8 sw_if_index_set = 0;
8008   u32 sw_if_index = (u32) ~ 0;
8009   u8 enable_gso = 0;
8010   u8 enable_packed = 0;
8011   int ret;
8012
8013   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8014     {
8015       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8016         sw_if_index_set = 1;
8017       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8018         sw_if_index_set = 1;
8019       else if (unformat (i, "socket %s", &file_name))
8020         {
8021           file_name_set = 1;
8022         }
8023       else if (unformat (i, "renumber %" PRIu32, &custom_dev_instance))
8024         ;
8025       else if (unformat (i, "server"))
8026         is_server = 1;
8027       else if (unformat (i, "gso"))
8028         enable_gso = 1;
8029       else if (unformat (i, "packed"))
8030         enable_packed = 1;
8031       else
8032         break;
8033     }
8034
8035   if (sw_if_index_set == 0)
8036     {
8037       errmsg ("missing sw_if_index or interface name");
8038       return -99;
8039     }
8040
8041   if (file_name_set == 0)
8042     {
8043       errmsg ("missing socket file name");
8044       return -99;
8045     }
8046
8047   if (vec_len (file_name) > 255)
8048     {
8049       errmsg ("socket file name too long");
8050       return -99;
8051     }
8052   vec_add1 (file_name, 0);
8053
8054   M (MODIFY_VHOST_USER_IF, mp);
8055
8056   mp->sw_if_index = ntohl (sw_if_index);
8057   mp->is_server = is_server;
8058   mp->enable_gso = enable_gso;
8059   mp->enable_packed = enable_packed;
8060   mp->custom_dev_instance = ntohl (custom_dev_instance);
8061   clib_memcpy (mp->sock_filename, file_name, vec_len (file_name));
8062   vec_free (file_name);
8063   if (custom_dev_instance != ~0)
8064     mp->renumber = 1;
8065
8066   S (mp);
8067   W (ret);
8068   return ret;
8069 }
8070
8071 static int
8072 api_create_vhost_user_if_v2 (vat_main_t * vam)
8073 {
8074   unformat_input_t *i = vam->input;
8075   vl_api_create_vhost_user_if_v2_t *mp;
8076   u8 *file_name;
8077   u8 is_server = 0;
8078   u8 file_name_set = 0;
8079   u32 custom_dev_instance = ~0;
8080   u8 hwaddr[6];
8081   u8 use_custom_mac = 0;
8082   u8 disable_mrg_rxbuf = 0;
8083   u8 disable_indirect_desc = 0;
8084   u8 *tag = 0;
8085   u8 enable_gso = 0;
8086   u8 enable_packed = 0;
8087   u8 enable_event_idx = 0;
8088   int ret;
8089
8090   /* Shut up coverity */
8091   clib_memset (hwaddr, 0, sizeof (hwaddr));
8092
8093   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8094     {
8095       if (unformat (i, "socket %s", &file_name))
8096         {
8097           file_name_set = 1;
8098         }
8099       else if (unformat (i, "renumber %" PRIu32, &custom_dev_instance))
8100         ;
8101       else if (unformat (i, "mac %U", unformat_ethernet_address, hwaddr))
8102         use_custom_mac = 1;
8103       else if (unformat (i, "server"))
8104         is_server = 1;
8105       else if (unformat (i, "disable_mrg_rxbuf"))
8106         disable_mrg_rxbuf = 1;
8107       else if (unformat (i, "disable_indirect_desc"))
8108         disable_indirect_desc = 1;
8109       else if (unformat (i, "gso"))
8110         enable_gso = 1;
8111       else if (unformat (i, "packed"))
8112         enable_packed = 1;
8113       else if (unformat (i, "event-idx"))
8114         enable_event_idx = 1;
8115       else if (unformat (i, "tag %s", &tag))
8116         ;
8117       else
8118         break;
8119     }
8120
8121   if (file_name_set == 0)
8122     {
8123       errmsg ("missing socket file name");
8124       return -99;
8125     }
8126
8127   if (vec_len (file_name) > 255)
8128     {
8129       errmsg ("socket file name too long");
8130       return -99;
8131     }
8132   vec_add1 (file_name, 0);
8133
8134   M (CREATE_VHOST_USER_IF_V2, mp);
8135
8136   mp->is_server = is_server;
8137   mp->disable_mrg_rxbuf = disable_mrg_rxbuf;
8138   mp->disable_indirect_desc = disable_indirect_desc;
8139   mp->enable_gso = enable_gso;
8140   mp->enable_packed = enable_packed;
8141   mp->enable_event_idx = enable_event_idx;
8142   mp->custom_dev_instance = ntohl (custom_dev_instance);
8143   clib_memcpy (mp->sock_filename, file_name, vec_len (file_name));
8144   vec_free (file_name);
8145   if (custom_dev_instance != ~0)
8146     mp->renumber = 1;
8147
8148   mp->use_custom_mac = use_custom_mac;
8149   clib_memcpy (mp->mac_address, hwaddr, 6);
8150   if (tag)
8151     strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
8152   vec_free (tag);
8153
8154   S (mp);
8155   W (ret);
8156   return ret;
8157 }
8158
8159 static int
8160 api_modify_vhost_user_if_v2 (vat_main_t * vam)
8161 {
8162   unformat_input_t *i = vam->input;
8163   vl_api_modify_vhost_user_if_v2_t *mp;
8164   u8 *file_name;
8165   u8 is_server = 0;
8166   u8 file_name_set = 0;
8167   u32 custom_dev_instance = ~0;
8168   u8 sw_if_index_set = 0;
8169   u32 sw_if_index = (u32) ~ 0;
8170   u8 enable_gso = 0;
8171   u8 enable_packed = 0;
8172   u8 enable_event_idx = 0;
8173   int ret;
8174
8175   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8176     {
8177       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8178         sw_if_index_set = 1;
8179       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8180         sw_if_index_set = 1;
8181       else if (unformat (i, "socket %s", &file_name))
8182         {
8183           file_name_set = 1;
8184         }
8185       else if (unformat (i, "renumber %" PRIu32, &custom_dev_instance))
8186         ;
8187       else if (unformat (i, "server"))
8188         is_server = 1;
8189       else if (unformat (i, "gso"))
8190         enable_gso = 1;
8191       else if (unformat (i, "packed"))
8192         enable_packed = 1;
8193       else if (unformat (i, "event-idx"))
8194         enable_event_idx = 1;
8195       else
8196         break;
8197     }
8198
8199   if (sw_if_index_set == 0)
8200     {
8201       errmsg ("missing sw_if_index or interface name");
8202       return -99;
8203     }
8204
8205   if (file_name_set == 0)
8206     {
8207       errmsg ("missing socket file name");
8208       return -99;
8209     }
8210
8211   if (vec_len (file_name) > 255)
8212     {
8213       errmsg ("socket file name too long");
8214       return -99;
8215     }
8216   vec_add1 (file_name, 0);
8217
8218   M (MODIFY_VHOST_USER_IF_V2, mp);
8219
8220   mp->sw_if_index = ntohl (sw_if_index);
8221   mp->is_server = is_server;
8222   mp->enable_gso = enable_gso;
8223   mp->enable_packed = enable_packed;
8224   mp->enable_event_idx = enable_event_idx;
8225   mp->custom_dev_instance = ntohl (custom_dev_instance);
8226   clib_memcpy (mp->sock_filename, file_name, vec_len (file_name));
8227   vec_free (file_name);
8228   if (custom_dev_instance != ~0)
8229     mp->renumber = 1;
8230
8231   S (mp);
8232   W (ret);
8233   return ret;
8234 }
8235
8236 static int
8237 api_delete_vhost_user_if (vat_main_t * vam)
8238 {
8239   unformat_input_t *i = vam->input;
8240   vl_api_delete_vhost_user_if_t *mp;
8241   u32 sw_if_index = ~0;
8242   u8 sw_if_index_set = 0;
8243   int ret;
8244
8245   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8246     {
8247       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8248         sw_if_index_set = 1;
8249       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8250         sw_if_index_set = 1;
8251       else
8252         break;
8253     }
8254
8255   if (sw_if_index_set == 0)
8256     {
8257       errmsg ("missing sw_if_index or interface name");
8258       return -99;
8259     }
8260
8261
8262   M (DELETE_VHOST_USER_IF, mp);
8263
8264   mp->sw_if_index = ntohl (sw_if_index);
8265
8266   S (mp);
8267   W (ret);
8268   return ret;
8269 }
8270
8271 static void vl_api_sw_interface_vhost_user_details_t_handler
8272   (vl_api_sw_interface_vhost_user_details_t * mp)
8273 {
8274   vat_main_t *vam = &vat_main;
8275   u64 features;
8276
8277   features =
8278     clib_net_to_host_u32 (mp->features_first_32) | ((u64)
8279                                                     clib_net_to_host_u32
8280                                                     (mp->features_last_32) <<
8281                                                     32);
8282
8283   print (vam->ofp, "%-25s %3" PRIu32 " %6" PRIu32 " %16llx %6d %7d %s",
8284          (char *) mp->interface_name, ntohl (mp->sw_if_index),
8285          ntohl (mp->virtio_net_hdr_sz), features, mp->is_server,
8286          ntohl (mp->num_regions), (char *) mp->sock_filename);
8287   print (vam->ofp, "    Status: '%s'", strerror (ntohl (mp->sock_errno)));
8288 }
8289
8290 static void vl_api_sw_interface_vhost_user_details_t_handler_json
8291   (vl_api_sw_interface_vhost_user_details_t * mp)
8292 {
8293   vat_main_t *vam = &vat_main;
8294   vat_json_node_t *node = NULL;
8295
8296   if (VAT_JSON_ARRAY != vam->json_tree.type)
8297     {
8298       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
8299       vat_json_init_array (&vam->json_tree);
8300     }
8301   node = vat_json_array_add (&vam->json_tree);
8302
8303   vat_json_init_object (node);
8304   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
8305   vat_json_object_add_string_copy (node, "interface_name",
8306                                    mp->interface_name);
8307   vat_json_object_add_uint (node, "virtio_net_hdr_sz",
8308                             ntohl (mp->virtio_net_hdr_sz));
8309   vat_json_object_add_uint (node, "features_first_32",
8310                             clib_net_to_host_u32 (mp->features_first_32));
8311   vat_json_object_add_uint (node, "features_last_32",
8312                             clib_net_to_host_u32 (mp->features_last_32));
8313   vat_json_object_add_uint (node, "is_server", mp->is_server);
8314   vat_json_object_add_string_copy (node, "sock_filename", mp->sock_filename);
8315   vat_json_object_add_uint (node, "num_regions", ntohl (mp->num_regions));
8316   vat_json_object_add_uint (node, "sock_errno", ntohl (mp->sock_errno));
8317 }
8318
8319 static int
8320 api_sw_interface_vhost_user_dump (vat_main_t * vam)
8321 {
8322   unformat_input_t *i = vam->input;
8323   vl_api_sw_interface_vhost_user_dump_t *mp;
8324   vl_api_control_ping_t *mp_ping;
8325   int ret;
8326   u32 sw_if_index = ~0;
8327
8328   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8329     {
8330       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8331         ;
8332       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8333         ;
8334       else
8335         break;
8336     }
8337
8338   print (vam->ofp, "Interface name            idx hdr_sz         features "
8339                    "server regions filename");
8340
8341   /* Get list of vhost-user interfaces */
8342   M (SW_INTERFACE_VHOST_USER_DUMP, mp);
8343   mp->sw_if_index = ntohl (sw_if_index);
8344   S (mp);
8345
8346   /* Use a control ping for synchronization */
8347   MPING (CONTROL_PING, mp_ping);
8348   S (mp_ping);
8349
8350   W (ret);
8351   return ret;
8352 }
8353
8354 static int
8355 api_show_version (vat_main_t * vam)
8356 {
8357   vl_api_show_version_t *mp;
8358   int ret;
8359
8360   M (SHOW_VERSION, mp);
8361
8362   S (mp);
8363   W (ret);
8364   return ret;
8365 }
8366
8367 static void vl_api_l2_fib_table_details_t_handler
8368   (vl_api_l2_fib_table_details_t * mp)
8369 {
8370   vat_main_t *vam = &vat_main;
8371
8372   print (vam->ofp, "%3" PRIu32 "    %U    %3" PRIu32
8373          "       %d       %d     %d",
8374          ntohl (mp->bd_id), format_ethernet_address, mp->mac,
8375          ntohl (mp->sw_if_index), mp->static_mac, mp->filter_mac,
8376          mp->bvi_mac);
8377 }
8378
8379 static void vl_api_l2_fib_table_details_t_handler_json
8380   (vl_api_l2_fib_table_details_t * mp)
8381 {
8382   vat_main_t *vam = &vat_main;
8383   vat_json_node_t *node = NULL;
8384
8385   if (VAT_JSON_ARRAY != vam->json_tree.type)
8386     {
8387       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
8388       vat_json_init_array (&vam->json_tree);
8389     }
8390   node = vat_json_array_add (&vam->json_tree);
8391
8392   vat_json_init_object (node);
8393   vat_json_object_add_uint (node, "bd_id", ntohl (mp->bd_id));
8394   vat_json_object_add_bytes (node, "mac", mp->mac, 6);
8395   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
8396   vat_json_object_add_uint (node, "static_mac", mp->static_mac);
8397   vat_json_object_add_uint (node, "filter_mac", mp->filter_mac);
8398   vat_json_object_add_uint (node, "bvi_mac", mp->bvi_mac);
8399 }
8400
8401 static int
8402 api_l2_fib_table_dump (vat_main_t * vam)
8403 {
8404   unformat_input_t *i = vam->input;
8405   vl_api_l2_fib_table_dump_t *mp;
8406   vl_api_control_ping_t *mp_ping;
8407   u32 bd_id;
8408   u8 bd_id_set = 0;
8409   int ret;
8410
8411   /* Parse args required to build the message */
8412   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8413     {
8414       if (unformat (i, "bd_id %d", &bd_id))
8415         bd_id_set = 1;
8416       else
8417         break;
8418     }
8419
8420   if (bd_id_set == 0)
8421     {
8422       errmsg ("missing bridge domain");
8423       return -99;
8424     }
8425
8426   print (vam->ofp, "BD-ID     Mac Address      sw-ndx  Static  Filter  BVI");
8427
8428   /* Get list of l2 fib entries */
8429   M (L2_FIB_TABLE_DUMP, mp);
8430
8431   mp->bd_id = ntohl (bd_id);
8432   S (mp);
8433
8434   /* Use a control ping for synchronization */
8435   MPING (CONTROL_PING, mp_ping);
8436   S (mp_ping);
8437
8438   W (ret);
8439   return ret;
8440 }
8441
8442
8443 static int
8444 api_interface_name_renumber (vat_main_t * vam)
8445 {
8446   unformat_input_t *line_input = vam->input;
8447   vl_api_interface_name_renumber_t *mp;
8448   u32 sw_if_index = ~0;
8449   u32 new_show_dev_instance = ~0;
8450   int ret;
8451
8452   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
8453     {
8454       if (unformat (line_input, "%U", api_unformat_sw_if_index, vam,
8455                     &sw_if_index))
8456         ;
8457       else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
8458         ;
8459       else if (unformat (line_input, "new_show_dev_instance %d",
8460                          &new_show_dev_instance))
8461         ;
8462       else
8463         break;
8464     }
8465
8466   if (sw_if_index == ~0)
8467     {
8468       errmsg ("missing interface name or sw_if_index");
8469       return -99;
8470     }
8471
8472   if (new_show_dev_instance == ~0)
8473     {
8474       errmsg ("missing new_show_dev_instance");
8475       return -99;
8476     }
8477
8478   M (INTERFACE_NAME_RENUMBER, mp);
8479
8480   mp->sw_if_index = ntohl (sw_if_index);
8481   mp->new_show_dev_instance = ntohl (new_show_dev_instance);
8482
8483   S (mp);
8484   W (ret);
8485   return ret;
8486 }
8487
8488 static int
8489 api_want_l2_macs_events (vat_main_t * vam)
8490 {
8491   unformat_input_t *line_input = vam->input;
8492   vl_api_want_l2_macs_events_t *mp;
8493   u8 enable_disable = 1;
8494   u32 scan_delay = 0;
8495   u32 max_macs_in_event = 0;
8496   u32 learn_limit = 0;
8497   int ret;
8498
8499   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
8500     {
8501       if (unformat (line_input, "learn-limit %d", &learn_limit))
8502         ;
8503       else if (unformat (line_input, "scan-delay %d", &scan_delay))
8504         ;
8505       else if (unformat (line_input, "max-entries %d", &max_macs_in_event))
8506         ;
8507       else if (unformat (line_input, "disable"))
8508         enable_disable = 0;
8509       else
8510         break;
8511     }
8512
8513   M (WANT_L2_MACS_EVENTS, mp);
8514   mp->enable_disable = enable_disable;
8515   mp->pid = htonl (getpid ());
8516   mp->learn_limit = htonl (learn_limit);
8517   mp->scan_delay = (u8) scan_delay;
8518   mp->max_macs_in_event = (u8) (max_macs_in_event / 10);
8519   S (mp);
8520   W (ret);
8521   return ret;
8522 }
8523
8524 static int
8525 api_ip_address_dump (vat_main_t * vam)
8526 {
8527   unformat_input_t *i = vam->input;
8528   vl_api_ip_address_dump_t *mp;
8529   vl_api_control_ping_t *mp_ping;
8530   u32 sw_if_index = ~0;
8531   u8 sw_if_index_set = 0;
8532   u8 ipv4_set = 0;
8533   u8 ipv6_set = 0;
8534   int ret;
8535
8536   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8537     {
8538       if (unformat (i, "sw_if_index %d", &sw_if_index))
8539         sw_if_index_set = 1;
8540       else
8541         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8542         sw_if_index_set = 1;
8543       else if (unformat (i, "ipv4"))
8544         ipv4_set = 1;
8545       else if (unformat (i, "ipv6"))
8546         ipv6_set = 1;
8547       else
8548         break;
8549     }
8550
8551   if (ipv4_set && ipv6_set)
8552     {
8553       errmsg ("ipv4 and ipv6 flags cannot be both set");
8554       return -99;
8555     }
8556
8557   if ((!ipv4_set) && (!ipv6_set))
8558     {
8559       errmsg ("no ipv4 nor ipv6 flag set");
8560       return -99;
8561     }
8562
8563   if (sw_if_index_set == 0)
8564     {
8565       errmsg ("missing interface name or sw_if_index");
8566       return -99;
8567     }
8568
8569   vam->current_sw_if_index = sw_if_index;
8570   vam->is_ipv6 = ipv6_set;
8571
8572   M (IP_ADDRESS_DUMP, mp);
8573   mp->sw_if_index = ntohl (sw_if_index);
8574   mp->is_ipv6 = ipv6_set;
8575   S (mp);
8576
8577   /* Use a control ping for synchronization */
8578   MPING (CONTROL_PING, mp_ping);
8579   S (mp_ping);
8580
8581   W (ret);
8582   return ret;
8583 }
8584
8585 static int
8586 api_ip_dump (vat_main_t * vam)
8587 {
8588   vl_api_ip_dump_t *mp;
8589   vl_api_control_ping_t *mp_ping;
8590   unformat_input_t *in = vam->input;
8591   int ipv4_set = 0;
8592   int ipv6_set = 0;
8593   int is_ipv6;
8594   int i;
8595   int ret;
8596
8597   while (unformat_check_input (in) != UNFORMAT_END_OF_INPUT)
8598     {
8599       if (unformat (in, "ipv4"))
8600         ipv4_set = 1;
8601       else if (unformat (in, "ipv6"))
8602         ipv6_set = 1;
8603       else
8604         break;
8605     }
8606
8607   if (ipv4_set && ipv6_set)
8608     {
8609       errmsg ("ipv4 and ipv6 flags cannot be both set");
8610       return -99;
8611     }
8612
8613   if ((!ipv4_set) && (!ipv6_set))
8614     {
8615       errmsg ("no ipv4 nor ipv6 flag set");
8616       return -99;
8617     }
8618
8619   is_ipv6 = ipv6_set;
8620   vam->is_ipv6 = is_ipv6;
8621
8622   /* free old data */
8623   for (i = 0; i < vec_len (vam->ip_details_by_sw_if_index[is_ipv6]); i++)
8624     {
8625       vec_free (vam->ip_details_by_sw_if_index[is_ipv6][i].addr);
8626     }
8627   vec_free (vam->ip_details_by_sw_if_index[is_ipv6]);
8628
8629   M (IP_DUMP, mp);
8630   mp->is_ipv6 = ipv6_set;
8631   S (mp);
8632
8633   /* Use a control ping for synchronization */
8634   MPING (CONTROL_PING, mp_ping);
8635   S (mp_ping);
8636
8637   W (ret);
8638   return ret;
8639 }
8640
8641 static int
8642 api_get_first_msg_id (vat_main_t * vam)
8643 {
8644   vl_api_get_first_msg_id_t *mp;
8645   unformat_input_t *i = vam->input;
8646   u8 *name;
8647   u8 name_set = 0;
8648   int ret;
8649
8650   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8651     {
8652       if (unformat (i, "client %s", &name))
8653         name_set = 1;
8654       else
8655         break;
8656     }
8657
8658   if (name_set == 0)
8659     {
8660       errmsg ("missing client name");
8661       return -99;
8662     }
8663   vec_add1 (name, 0);
8664
8665   if (vec_len (name) > 63)
8666     {
8667       errmsg ("client name too long");
8668       return -99;
8669     }
8670
8671   M (GET_FIRST_MSG_ID, mp);
8672   clib_memcpy (mp->name, name, vec_len (name));
8673   S (mp);
8674   W (ret);
8675   return ret;
8676 }
8677
8678 static int
8679 api_get_node_graph (vat_main_t * vam)
8680 {
8681   vl_api_get_node_graph_t *mp;
8682   int ret;
8683
8684   M (GET_NODE_GRAPH, mp);
8685
8686   /* send it... */
8687   S (mp);
8688   /* Wait for the reply */
8689   W (ret);
8690   return ret;
8691 }
8692
8693 static int
8694 api_af_packet_create (vat_main_t * vam)
8695 {
8696   unformat_input_t *i = vam->input;
8697   vl_api_af_packet_create_t *mp;
8698   u8 *host_if_name = 0;
8699   u8 hw_addr[6];
8700   u8 random_hw_addr = 1;
8701   int ret;
8702
8703   clib_memset (hw_addr, 0, sizeof (hw_addr));
8704
8705   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8706     {
8707       if (unformat (i, "name %s", &host_if_name))
8708         vec_add1 (host_if_name, 0);
8709       else if (unformat (i, "hw_addr %U", unformat_ethernet_address, hw_addr))
8710         random_hw_addr = 0;
8711       else
8712         break;
8713     }
8714
8715   if (!vec_len (host_if_name))
8716     {
8717       errmsg ("host-interface name must be specified");
8718       return -99;
8719     }
8720
8721   if (vec_len (host_if_name) > 64)
8722     {
8723       errmsg ("host-interface name too long");
8724       return -99;
8725     }
8726
8727   M (AF_PACKET_CREATE, mp);
8728
8729   clib_memcpy (mp->host_if_name, host_if_name, vec_len (host_if_name));
8730   clib_memcpy (mp->hw_addr, hw_addr, 6);
8731   mp->use_random_hw_addr = random_hw_addr;
8732   vec_free (host_if_name);
8733
8734   S (mp);
8735
8736   /* *INDENT-OFF* */
8737   W2 (ret,
8738       ({
8739         if (ret == 0)
8740           fprintf (vam->ofp ? vam->ofp : stderr,
8741                    " new sw_if_index = %d\n", vam->sw_if_index);
8742       }));
8743   /* *INDENT-ON* */
8744   return ret;
8745 }
8746
8747 static int
8748 api_af_packet_delete (vat_main_t * vam)
8749 {
8750   unformat_input_t *i = vam->input;
8751   vl_api_af_packet_delete_t *mp;
8752   u8 *host_if_name = 0;
8753   int ret;
8754
8755   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8756     {
8757       if (unformat (i, "name %s", &host_if_name))
8758         vec_add1 (host_if_name, 0);
8759       else
8760         break;
8761     }
8762
8763   if (!vec_len (host_if_name))
8764     {
8765       errmsg ("host-interface name must be specified");
8766       return -99;
8767     }
8768
8769   if (vec_len (host_if_name) > 64)
8770     {
8771       errmsg ("host-interface name too long");
8772       return -99;
8773     }
8774
8775   M (AF_PACKET_DELETE, mp);
8776
8777   clib_memcpy (mp->host_if_name, host_if_name, vec_len (host_if_name));
8778   vec_free (host_if_name);
8779
8780   S (mp);
8781   W (ret);
8782   return ret;
8783 }
8784
8785 static void vl_api_af_packet_details_t_handler
8786   (vl_api_af_packet_details_t * mp)
8787 {
8788   vat_main_t *vam = &vat_main;
8789
8790   print (vam->ofp, "%-16s %d",
8791          mp->host_if_name, clib_net_to_host_u32 (mp->sw_if_index));
8792 }
8793
8794 static void vl_api_af_packet_details_t_handler_json
8795   (vl_api_af_packet_details_t * mp)
8796 {
8797   vat_main_t *vam = &vat_main;
8798   vat_json_node_t *node = NULL;
8799
8800   if (VAT_JSON_ARRAY != vam->json_tree.type)
8801     {
8802       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
8803       vat_json_init_array (&vam->json_tree);
8804     }
8805   node = vat_json_array_add (&vam->json_tree);
8806
8807   vat_json_init_object (node);
8808   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
8809   vat_json_object_add_string_copy (node, "dev_name", mp->host_if_name);
8810 }
8811
8812 static int
8813 api_af_packet_dump (vat_main_t * vam)
8814 {
8815   vl_api_af_packet_dump_t *mp;
8816   vl_api_control_ping_t *mp_ping;
8817   int ret;
8818
8819   print (vam->ofp, "\n%-16s %s", "dev_name", "sw_if_index");
8820   /* Get list of tap interfaces */
8821   M (AF_PACKET_DUMP, mp);
8822   S (mp);
8823
8824   /* Use a control ping for synchronization */
8825   MPING (CONTROL_PING, mp_ping);
8826   S (mp_ping);
8827
8828   W (ret);
8829   return ret;
8830 }
8831
8832 static u8 *
8833 format_fib_api_path_nh_proto (u8 * s, va_list * args)
8834 {
8835   vl_api_fib_path_nh_proto_t proto =
8836     va_arg (*args, vl_api_fib_path_nh_proto_t);
8837
8838   switch (proto)
8839     {
8840     case FIB_API_PATH_NH_PROTO_IP4:
8841       s = format (s, "ip4");
8842       break;
8843     case FIB_API_PATH_NH_PROTO_IP6:
8844       s = format (s, "ip6");
8845       break;
8846     case FIB_API_PATH_NH_PROTO_MPLS:
8847       s = format (s, "mpls");
8848       break;
8849     case FIB_API_PATH_NH_PROTO_BIER:
8850       s = format (s, "bier");
8851       break;
8852     case FIB_API_PATH_NH_PROTO_ETHERNET:
8853       s = format (s, "ethernet");
8854       break;
8855     }
8856
8857   return (s);
8858 }
8859
8860 static u8 *
8861 format_vl_api_ip_address_union (u8 * s, va_list * args)
8862 {
8863   vl_api_address_family_t af = va_arg (*args, int);
8864   const vl_api_address_union_t *u = va_arg (*args, vl_api_address_union_t *);
8865
8866   switch (af)
8867     {
8868     case ADDRESS_IP4:
8869       s = format (s, "%U", format_ip4_address, u->ip4);
8870       break;
8871     case ADDRESS_IP6:
8872       s = format (s, "%U", format_ip6_address, u->ip6);
8873       break;
8874     }
8875   return (s);
8876 }
8877
8878 static u8 *
8879 format_vl_api_fib_path_type (u8 * s, va_list * args)
8880 {
8881   vl_api_fib_path_type_t t = va_arg (*args, vl_api_fib_path_type_t);
8882
8883   switch (t)
8884     {
8885     case FIB_API_PATH_TYPE_NORMAL:
8886       s = format (s, "normal");
8887       break;
8888     case FIB_API_PATH_TYPE_LOCAL:
8889       s = format (s, "local");
8890       break;
8891     case FIB_API_PATH_TYPE_DROP:
8892       s = format (s, "drop");
8893       break;
8894     case FIB_API_PATH_TYPE_UDP_ENCAP:
8895       s = format (s, "udp-encap");
8896       break;
8897     case FIB_API_PATH_TYPE_BIER_IMP:
8898       s = format (s, "bier-imp");
8899       break;
8900     case FIB_API_PATH_TYPE_ICMP_UNREACH:
8901       s = format (s, "unreach");
8902       break;
8903     case FIB_API_PATH_TYPE_ICMP_PROHIBIT:
8904       s = format (s, "prohibit");
8905       break;
8906     case FIB_API_PATH_TYPE_SOURCE_LOOKUP:
8907       s = format (s, "src-lookup");
8908       break;
8909     case FIB_API_PATH_TYPE_DVR:
8910       s = format (s, "dvr");
8911       break;
8912     case FIB_API_PATH_TYPE_INTERFACE_RX:
8913       s = format (s, "interface-rx");
8914       break;
8915     case FIB_API_PATH_TYPE_CLASSIFY:
8916       s = format (s, "classify");
8917       break;
8918     }
8919
8920   return (s);
8921 }
8922
8923 static void
8924 vl_api_fib_path_print (vat_main_t * vam, vl_api_fib_path_t * fp)
8925 {
8926   print (vam->ofp,
8927          "  weight %d, sw_if_index %d, type %U, afi %U, next_hop %U",
8928          ntohl (fp->weight), ntohl (fp->sw_if_index),
8929          format_vl_api_fib_path_type, fp->type,
8930          format_fib_api_path_nh_proto, fp->proto,
8931          format_vl_api_ip_address_union, &fp->nh.address);
8932 }
8933
8934 static void
8935 vl_api_mpls_fib_path_json_print (vat_json_node_t * node,
8936                                  vl_api_fib_path_t * fp)
8937 {
8938   struct in_addr ip4;
8939   struct in6_addr ip6;
8940
8941   vat_json_object_add_uint (node, "weight", ntohl (fp->weight));
8942   vat_json_object_add_uint (node, "sw_if_index", ntohl (fp->sw_if_index));
8943   vat_json_object_add_uint (node, "type", fp->type);
8944   vat_json_object_add_uint (node, "next_hop_proto", fp->proto);
8945   if (fp->proto == FIB_API_PATH_NH_PROTO_IP4)
8946     {
8947       clib_memcpy (&ip4, &fp->nh.address.ip4, sizeof (ip4));
8948       vat_json_object_add_ip4 (node, "next_hop", ip4);
8949     }
8950   else if (fp->proto == FIB_API_PATH_NH_PROTO_IP6)
8951     {
8952       clib_memcpy (&ip6, &fp->nh.address.ip6, sizeof (ip6));
8953       vat_json_object_add_ip6 (node, "next_hop", ip6);
8954     }
8955 }
8956
8957 static void
8958 vl_api_mpls_tunnel_details_t_handler (vl_api_mpls_tunnel_details_t * mp)
8959 {
8960   vat_main_t *vam = &vat_main;
8961   int count = ntohl (mp->mt_tunnel.mt_n_paths);
8962   vl_api_fib_path_t *fp;
8963   i32 i;
8964
8965   print (vam->ofp, "sw_if_index %d via:",
8966          ntohl (mp->mt_tunnel.mt_sw_if_index));
8967   fp = mp->mt_tunnel.mt_paths;
8968   for (i = 0; i < count; i++)
8969     {
8970       vl_api_fib_path_print (vam, fp);
8971       fp++;
8972     }
8973
8974   print (vam->ofp, "");
8975 }
8976
8977 #define vl_api_mpls_tunnel_details_t_endian vl_noop_handler
8978 #define vl_api_mpls_tunnel_details_t_print vl_noop_handler
8979
8980 static void
8981 vl_api_mpls_tunnel_details_t_handler_json (vl_api_mpls_tunnel_details_t * mp)
8982 {
8983   vat_main_t *vam = &vat_main;
8984   vat_json_node_t *node = NULL;
8985   int count = ntohl (mp->mt_tunnel.mt_n_paths);
8986   vl_api_fib_path_t *fp;
8987   i32 i;
8988
8989   if (VAT_JSON_ARRAY != vam->json_tree.type)
8990     {
8991       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
8992       vat_json_init_array (&vam->json_tree);
8993     }
8994   node = vat_json_array_add (&vam->json_tree);
8995
8996   vat_json_init_object (node);
8997   vat_json_object_add_uint (node, "sw_if_index",
8998                             ntohl (mp->mt_tunnel.mt_sw_if_index));
8999
9000   vat_json_object_add_uint (node, "l2_only", mp->mt_tunnel.mt_l2_only);
9001
9002   fp = mp->mt_tunnel.mt_paths;
9003   for (i = 0; i < count; i++)
9004     {
9005       vl_api_mpls_fib_path_json_print (node, fp);
9006       fp++;
9007     }
9008 }
9009
9010 static int
9011 api_mpls_tunnel_dump (vat_main_t * vam)
9012 {
9013   vl_api_mpls_tunnel_dump_t *mp;
9014   vl_api_control_ping_t *mp_ping;
9015   int ret;
9016
9017   M (MPLS_TUNNEL_DUMP, mp);
9018
9019   S (mp);
9020
9021   /* Use a control ping for synchronization */
9022   MPING (CONTROL_PING, mp_ping);
9023   S (mp_ping);
9024
9025   W (ret);
9026   return ret;
9027 }
9028
9029 #define vl_api_mpls_table_details_t_endian vl_noop_handler
9030 #define vl_api_mpls_table_details_t_print vl_noop_handler
9031
9032
9033 static void
9034 vl_api_mpls_table_details_t_handler (vl_api_mpls_table_details_t * mp)
9035 {
9036   vat_main_t *vam = &vat_main;
9037
9038   print (vam->ofp, "table-id %d,", ntohl (mp->mt_table.mt_table_id));
9039 }
9040
9041 static void vl_api_mpls_table_details_t_handler_json
9042   (vl_api_mpls_table_details_t * mp)
9043 {
9044   vat_main_t *vam = &vat_main;
9045   vat_json_node_t *node = NULL;
9046
9047   if (VAT_JSON_ARRAY != vam->json_tree.type)
9048     {
9049       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9050       vat_json_init_array (&vam->json_tree);
9051     }
9052   node = vat_json_array_add (&vam->json_tree);
9053
9054   vat_json_init_object (node);
9055   vat_json_object_add_uint (node, "table", ntohl (mp->mt_table.mt_table_id));
9056 }
9057
9058 static int
9059 api_mpls_table_dump (vat_main_t * vam)
9060 {
9061   vl_api_mpls_table_dump_t *mp;
9062   vl_api_control_ping_t *mp_ping;
9063   int ret;
9064
9065   M (MPLS_TABLE_DUMP, mp);
9066   S (mp);
9067
9068   /* Use a control ping for synchronization */
9069   MPING (CONTROL_PING, mp_ping);
9070   S (mp_ping);
9071
9072   W (ret);
9073   return ret;
9074 }
9075
9076 #define vl_api_mpls_route_details_t_endian vl_noop_handler
9077 #define vl_api_mpls_route_details_t_print vl_noop_handler
9078
9079 static void
9080 vl_api_mpls_route_details_t_handler (vl_api_mpls_route_details_t * mp)
9081 {
9082   vat_main_t *vam = &vat_main;
9083   int count = (int) clib_net_to_host_u32 (mp->mr_route.mr_n_paths);
9084   vl_api_fib_path_t *fp;
9085   int i;
9086
9087   print (vam->ofp,
9088          "table-id %d, label %u, ess_bit %u",
9089          ntohl (mp->mr_route.mr_table_id),
9090          ntohl (mp->mr_route.mr_label), mp->mr_route.mr_eos);
9091   fp = mp->mr_route.mr_paths;
9092   for (i = 0; i < count; i++)
9093     {
9094       vl_api_fib_path_print (vam, fp);
9095       fp++;
9096     }
9097 }
9098
9099 static void vl_api_mpls_route_details_t_handler_json
9100   (vl_api_mpls_route_details_t * mp)
9101 {
9102   vat_main_t *vam = &vat_main;
9103   int count = (int) clib_host_to_net_u32 (mp->mr_route.mr_n_paths);
9104   vat_json_node_t *node = NULL;
9105   vl_api_fib_path_t *fp;
9106   int i;
9107
9108   if (VAT_JSON_ARRAY != vam->json_tree.type)
9109     {
9110       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9111       vat_json_init_array (&vam->json_tree);
9112     }
9113   node = vat_json_array_add (&vam->json_tree);
9114
9115   vat_json_init_object (node);
9116   vat_json_object_add_uint (node, "table", ntohl (mp->mr_route.mr_table_id));
9117   vat_json_object_add_uint (node, "s_bit", mp->mr_route.mr_eos);
9118   vat_json_object_add_uint (node, "label", ntohl (mp->mr_route.mr_label));
9119   vat_json_object_add_uint (node, "path_count", count);
9120   fp = mp->mr_route.mr_paths;
9121   for (i = 0; i < count; i++)
9122     {
9123       vl_api_mpls_fib_path_json_print (node, fp);
9124       fp++;
9125     }
9126 }
9127
9128 static int
9129 api_mpls_route_dump (vat_main_t * vam)
9130 {
9131   unformat_input_t *input = vam->input;
9132   vl_api_mpls_route_dump_t *mp;
9133   vl_api_control_ping_t *mp_ping;
9134   u32 table_id;
9135   int ret;
9136
9137   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
9138     {
9139       if (unformat (input, "table_id %d", &table_id))
9140         ;
9141       else
9142         break;
9143     }
9144   if (table_id == ~0)
9145     {
9146       errmsg ("missing table id");
9147       return -99;
9148     }
9149
9150   M (MPLS_ROUTE_DUMP, mp);
9151
9152   mp->table.mt_table_id = ntohl (table_id);
9153   S (mp);
9154
9155   /* Use a control ping for synchronization */
9156   MPING (CONTROL_PING, mp_ping);
9157   S (mp_ping);
9158
9159   W (ret);
9160   return ret;
9161 }
9162
9163 #define vl_api_ip_table_details_t_endian vl_noop_handler
9164 #define vl_api_ip_table_details_t_print vl_noop_handler
9165
9166 static void
9167 vl_api_ip_table_details_t_handler (vl_api_ip_table_details_t * mp)
9168 {
9169   vat_main_t *vam = &vat_main;
9170
9171   print (vam->ofp,
9172          "%s; table-id %d, prefix %U/%d",
9173          mp->table.name, ntohl (mp->table.table_id));
9174 }
9175
9176
9177 static void vl_api_ip_table_details_t_handler_json
9178   (vl_api_ip_table_details_t * mp)
9179 {
9180   vat_main_t *vam = &vat_main;
9181   vat_json_node_t *node = NULL;
9182
9183   if (VAT_JSON_ARRAY != vam->json_tree.type)
9184     {
9185       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9186       vat_json_init_array (&vam->json_tree);
9187     }
9188   node = vat_json_array_add (&vam->json_tree);
9189
9190   vat_json_init_object (node);
9191   vat_json_object_add_uint (node, "table", ntohl (mp->table.table_id));
9192 }
9193
9194 static int
9195 api_ip_table_dump (vat_main_t * vam)
9196 {
9197   vl_api_ip_table_dump_t *mp;
9198   vl_api_control_ping_t *mp_ping;
9199   int ret;
9200
9201   M (IP_TABLE_DUMP, mp);
9202   S (mp);
9203
9204   /* Use a control ping for synchronization */
9205   MPING (CONTROL_PING, mp_ping);
9206   S (mp_ping);
9207
9208   W (ret);
9209   return ret;
9210 }
9211
9212 static int
9213 api_ip_mtable_dump (vat_main_t * vam)
9214 {
9215   vl_api_ip_mtable_dump_t *mp;
9216   vl_api_control_ping_t *mp_ping;
9217   int ret;
9218
9219   M (IP_MTABLE_DUMP, mp);
9220   S (mp);
9221
9222   /* Use a control ping for synchronization */
9223   MPING (CONTROL_PING, mp_ping);
9224   S (mp_ping);
9225
9226   W (ret);
9227   return ret;
9228 }
9229
9230 static int
9231 api_ip_mroute_dump (vat_main_t * vam)
9232 {
9233   unformat_input_t *input = vam->input;
9234   vl_api_control_ping_t *mp_ping;
9235   vl_api_ip_mroute_dump_t *mp;
9236   int ret, is_ip6;
9237   u32 table_id;
9238
9239   is_ip6 = 0;
9240   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
9241     {
9242       if (unformat (input, "table_id %d", &table_id))
9243         ;
9244       else if (unformat (input, "ip6"))
9245         is_ip6 = 1;
9246       else if (unformat (input, "ip4"))
9247         is_ip6 = 0;
9248       else
9249         break;
9250     }
9251   if (table_id == ~0)
9252     {
9253       errmsg ("missing table id");
9254       return -99;
9255     }
9256
9257   M (IP_MROUTE_DUMP, mp);
9258   mp->table.table_id = table_id;
9259   mp->table.is_ip6 = is_ip6;
9260   S (mp);
9261
9262   /* Use a control ping for synchronization */
9263   MPING (CONTROL_PING, mp_ping);
9264   S (mp_ping);
9265
9266   W (ret);
9267   return ret;
9268 }
9269
9270 #define vl_api_ip_route_details_t_endian vl_noop_handler
9271 #define vl_api_ip_route_details_t_print vl_noop_handler
9272
9273 static void
9274 vl_api_ip_route_details_t_handler (vl_api_ip_route_details_t * mp)
9275 {
9276   vat_main_t *vam = &vat_main;
9277   u8 count = mp->route.n_paths;
9278   vl_api_fib_path_t *fp;
9279   int i;
9280
9281   print (vam->ofp,
9282          "table-id %d, prefix %U/%d",
9283          ntohl (mp->route.table_id),
9284          format_ip46_address, mp->route.prefix.address, mp->route.prefix.len);
9285   for (i = 0; i < count; i++)
9286     {
9287       fp = &mp->route.paths[i];
9288
9289       vl_api_fib_path_print (vam, fp);
9290       fp++;
9291     }
9292 }
9293
9294 static void vl_api_ip_route_details_t_handler_json
9295   (vl_api_ip_route_details_t * mp)
9296 {
9297   vat_main_t *vam = &vat_main;
9298   u8 count = mp->route.n_paths;
9299   vat_json_node_t *node = NULL;
9300   struct in_addr ip4;
9301   struct in6_addr ip6;
9302   vl_api_fib_path_t *fp;
9303   int i;
9304
9305   if (VAT_JSON_ARRAY != vam->json_tree.type)
9306     {
9307       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9308       vat_json_init_array (&vam->json_tree);
9309     }
9310   node = vat_json_array_add (&vam->json_tree);
9311
9312   vat_json_init_object (node);
9313   vat_json_object_add_uint (node, "table", ntohl (mp->route.table_id));
9314   if (ADDRESS_IP6 == mp->route.prefix.address.af)
9315     {
9316       clib_memcpy (&ip6, &mp->route.prefix.address.un.ip6, sizeof (ip6));
9317       vat_json_object_add_ip6 (node, "prefix", ip6);
9318     }
9319   else
9320     {
9321       clib_memcpy (&ip4, &mp->route.prefix.address.un.ip4, sizeof (ip4));
9322       vat_json_object_add_ip4 (node, "prefix", ip4);
9323     }
9324   vat_json_object_add_uint (node, "mask_length", mp->route.prefix.len);
9325   vat_json_object_add_uint (node, "path_count", count);
9326   for (i = 0; i < count; i++)
9327     {
9328       fp = &mp->route.paths[i];
9329       vl_api_mpls_fib_path_json_print (node, fp);
9330     }
9331 }
9332
9333 static int
9334 api_ip_route_dump (vat_main_t * vam)
9335 {
9336   unformat_input_t *input = vam->input;
9337   vl_api_ip_route_dump_t *mp;
9338   vl_api_control_ping_t *mp_ping;
9339   u32 table_id;
9340   u8 is_ip6;
9341   int ret;
9342
9343   is_ip6 = 0;
9344   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
9345     {
9346       if (unformat (input, "table_id %d", &table_id))
9347         ;
9348       else if (unformat (input, "ip6"))
9349         is_ip6 = 1;
9350       else if (unformat (input, "ip4"))
9351         is_ip6 = 0;
9352       else
9353         break;
9354     }
9355   if (table_id == ~0)
9356     {
9357       errmsg ("missing table id");
9358       return -99;
9359     }
9360
9361   M (IP_ROUTE_DUMP, mp);
9362
9363   mp->table.table_id = table_id;
9364   mp->table.is_ip6 = is_ip6;
9365
9366   S (mp);
9367
9368   /* Use a control ping for synchronization */
9369   MPING (CONTROL_PING, mp_ping);
9370   S (mp_ping);
9371
9372   W (ret);
9373   return ret;
9374 }
9375
9376 static int
9377 api_sw_interface_span_enable_disable (vat_main_t * vam)
9378 {
9379   unformat_input_t *i = vam->input;
9380   vl_api_sw_interface_span_enable_disable_t *mp;
9381   u32 src_sw_if_index = ~0;
9382   u32 dst_sw_if_index = ~0;
9383   u8 state = 3;
9384   int ret;
9385   u8 is_l2 = 0;
9386
9387   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9388     {
9389       if (unformat
9390           (i, "src %U", api_unformat_sw_if_index, vam, &src_sw_if_index))
9391         ;
9392       else if (unformat (i, "src_sw_if_index %d", &src_sw_if_index))
9393         ;
9394       else
9395         if (unformat
9396             (i, "dst %U", api_unformat_sw_if_index, vam, &dst_sw_if_index))
9397         ;
9398       else if (unformat (i, "dst_sw_if_index %d", &dst_sw_if_index))
9399         ;
9400       else if (unformat (i, "disable"))
9401         state = 0;
9402       else if (unformat (i, "rx"))
9403         state = 1;
9404       else if (unformat (i, "tx"))
9405         state = 2;
9406       else if (unformat (i, "both"))
9407         state = 3;
9408       else if (unformat (i, "l2"))
9409         is_l2 = 1;
9410       else
9411         break;
9412     }
9413
9414   M (SW_INTERFACE_SPAN_ENABLE_DISABLE, mp);
9415
9416   mp->sw_if_index_from = htonl (src_sw_if_index);
9417   mp->sw_if_index_to = htonl (dst_sw_if_index);
9418   mp->state = state;
9419   mp->is_l2 = is_l2;
9420
9421   S (mp);
9422   W (ret);
9423   return ret;
9424 }
9425
9426 static void
9427 vl_api_sw_interface_span_details_t_handler (vl_api_sw_interface_span_details_t
9428                                             * mp)
9429 {
9430   vat_main_t *vam = &vat_main;
9431   u8 *sw_if_from_name = 0;
9432   u8 *sw_if_to_name = 0;
9433   u32 sw_if_index_from = ntohl (mp->sw_if_index_from);
9434   u32 sw_if_index_to = ntohl (mp->sw_if_index_to);
9435   char *states[] = { "none", "rx", "tx", "both" };
9436   hash_pair_t *p;
9437
9438   /* *INDENT-OFF* */
9439   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
9440   ({
9441     if ((u32) p->value[0] == sw_if_index_from)
9442       {
9443         sw_if_from_name = (u8 *)(p->key);
9444         if (sw_if_to_name)
9445           break;
9446       }
9447     if ((u32) p->value[0] == sw_if_index_to)
9448       {
9449         sw_if_to_name = (u8 *)(p->key);
9450         if (sw_if_from_name)
9451           break;
9452       }
9453   }));
9454   /* *INDENT-ON* */
9455   print (vam->ofp, "%20s => %20s (%s) %s",
9456          sw_if_from_name, sw_if_to_name, states[mp->state],
9457          mp->is_l2 ? "l2" : "device");
9458 }
9459
9460 static void
9461   vl_api_sw_interface_span_details_t_handler_json
9462   (vl_api_sw_interface_span_details_t * mp)
9463 {
9464   vat_main_t *vam = &vat_main;
9465   vat_json_node_t *node = NULL;
9466   u8 *sw_if_from_name = 0;
9467   u8 *sw_if_to_name = 0;
9468   u32 sw_if_index_from = ntohl (mp->sw_if_index_from);
9469   u32 sw_if_index_to = ntohl (mp->sw_if_index_to);
9470   hash_pair_t *p;
9471
9472   /* *INDENT-OFF* */
9473   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
9474   ({
9475     if ((u32) p->value[0] == sw_if_index_from)
9476       {
9477         sw_if_from_name = (u8 *)(p->key);
9478         if (sw_if_to_name)
9479           break;
9480       }
9481     if ((u32) p->value[0] == sw_if_index_to)
9482       {
9483         sw_if_to_name = (u8 *)(p->key);
9484         if (sw_if_from_name)
9485           break;
9486       }
9487   }));
9488   /* *INDENT-ON* */
9489
9490   if (VAT_JSON_ARRAY != vam->json_tree.type)
9491     {
9492       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9493       vat_json_init_array (&vam->json_tree);
9494     }
9495   node = vat_json_array_add (&vam->json_tree);
9496
9497   vat_json_init_object (node);
9498   vat_json_object_add_uint (node, "src-if-index", sw_if_index_from);
9499   vat_json_object_add_string_copy (node, "src-if-name", sw_if_from_name);
9500   vat_json_object_add_uint (node, "dst-if-index", sw_if_index_to);
9501   if (0 != sw_if_to_name)
9502     {
9503       vat_json_object_add_string_copy (node, "dst-if-name", sw_if_to_name);
9504     }
9505   vat_json_object_add_uint (node, "state", mp->state);
9506   vat_json_object_add_uint (node, "is-l2", mp->is_l2);
9507 }
9508
9509 static int
9510 api_sw_interface_span_dump (vat_main_t * vam)
9511 {
9512   unformat_input_t *input = vam->input;
9513   vl_api_sw_interface_span_dump_t *mp;
9514   vl_api_control_ping_t *mp_ping;
9515   u8 is_l2 = 0;
9516   int ret;
9517
9518   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
9519     {
9520       if (unformat (input, "l2"))
9521         is_l2 = 1;
9522       else
9523         break;
9524     }
9525
9526   M (SW_INTERFACE_SPAN_DUMP, mp);
9527   mp->is_l2 = is_l2;
9528   S (mp);
9529
9530   /* Use a control ping for synchronization */
9531   MPING (CONTROL_PING, mp_ping);
9532   S (mp_ping);
9533
9534   W (ret);
9535   return ret;
9536 }
9537
9538 int
9539 api_ip_source_and_port_range_check_add_del (vat_main_t * vam)
9540 {
9541   unformat_input_t *input = vam->input;
9542   vl_api_ip_source_and_port_range_check_add_del_t *mp;
9543
9544   u16 *low_ports = 0;
9545   u16 *high_ports = 0;
9546   u16 this_low;
9547   u16 this_hi;
9548   vl_api_prefix_t prefix;
9549   u32 tmp, tmp2;
9550   u8 prefix_set = 0;
9551   u32 vrf_id = ~0;
9552   u8 is_add = 1;
9553   int ret;
9554
9555   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
9556     {
9557       if (unformat (input, "%U", unformat_vl_api_prefix, &prefix))
9558         prefix_set = 1;
9559       else if (unformat (input, "vrf %d", &vrf_id))
9560         ;
9561       else if (unformat (input, "del"))
9562         is_add = 0;
9563       else if (unformat (input, "port %d", &tmp))
9564         {
9565           if (tmp == 0 || tmp > 65535)
9566             {
9567               errmsg ("port %d out of range", tmp);
9568               return -99;
9569             }
9570           this_low = tmp;
9571           this_hi = this_low + 1;
9572           vec_add1 (low_ports, this_low);
9573           vec_add1 (high_ports, this_hi);
9574         }
9575       else if (unformat (input, "range %d - %d", &tmp, &tmp2))
9576         {
9577           if ((tmp > tmp2) || (tmp == 0) || (tmp2 > 65535))
9578             {
9579               errmsg ("incorrect range parameters");
9580               return -99;
9581             }
9582           this_low = tmp;
9583           /* Note: in debug CLI +1 is added to high before
9584              passing to real fn that does "the work"
9585              (ip_source_and_port_range_check_add_del).
9586              This fn is a wrapper around the binary API fn a
9587              control plane will call, which expects this increment
9588              to have occurred. Hence letting the binary API control
9589              plane fn do the increment for consistency between VAT
9590              and other control planes.
9591            */
9592           this_hi = tmp2;
9593           vec_add1 (low_ports, this_low);
9594           vec_add1 (high_ports, this_hi);
9595         }
9596       else
9597         break;
9598     }
9599
9600   if (prefix_set == 0)
9601     {
9602       errmsg ("<address>/<mask> not specified");
9603       return -99;
9604     }
9605
9606   if (vrf_id == ~0)
9607     {
9608       errmsg ("VRF ID required, not specified");
9609       return -99;
9610     }
9611
9612   if (vrf_id == 0)
9613     {
9614       errmsg
9615         ("VRF ID should not be default. Should be distinct VRF for this purpose.");
9616       return -99;
9617     }
9618
9619   if (vec_len (low_ports) == 0)
9620     {
9621       errmsg ("At least one port or port range required");
9622       return -99;
9623     }
9624
9625   M (IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL, mp);
9626
9627   mp->is_add = is_add;
9628
9629   clib_memcpy (&mp->prefix, &prefix, sizeof (prefix));
9630
9631   mp->number_of_ranges = vec_len (low_ports);
9632
9633   clib_memcpy (mp->low_ports, low_ports, vec_len (low_ports));
9634   vec_free (low_ports);
9635
9636   clib_memcpy (mp->high_ports, high_ports, vec_len (high_ports));
9637   vec_free (high_ports);
9638
9639   mp->vrf_id = ntohl (vrf_id);
9640
9641   S (mp);
9642   W (ret);
9643   return ret;
9644 }
9645
9646 int
9647 api_ip_source_and_port_range_check_interface_add_del (vat_main_t * vam)
9648 {
9649   unformat_input_t *input = vam->input;
9650   vl_api_ip_source_and_port_range_check_interface_add_del_t *mp;
9651   u32 sw_if_index = ~0;
9652   int vrf_set = 0;
9653   u32 tcp_out_vrf_id = ~0, udp_out_vrf_id = ~0;
9654   u32 tcp_in_vrf_id = ~0, udp_in_vrf_id = ~0;
9655   u8 is_add = 1;
9656   int ret;
9657
9658   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
9659     {
9660       if (unformat (input, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
9661         ;
9662       else if (unformat (input, "sw_if_index %d", &sw_if_index))
9663         ;
9664       else if (unformat (input, "tcp-out-vrf %d", &tcp_out_vrf_id))
9665         vrf_set = 1;
9666       else if (unformat (input, "udp-out-vrf %d", &udp_out_vrf_id))
9667         vrf_set = 1;
9668       else if (unformat (input, "tcp-in-vrf %d", &tcp_in_vrf_id))
9669         vrf_set = 1;
9670       else if (unformat (input, "udp-in-vrf %d", &udp_in_vrf_id))
9671         vrf_set = 1;
9672       else if (unformat (input, "del"))
9673         is_add = 0;
9674       else
9675         break;
9676     }
9677
9678   if (sw_if_index == ~0)
9679     {
9680       errmsg ("Interface required but not specified");
9681       return -99;
9682     }
9683
9684   if (vrf_set == 0)
9685     {
9686       errmsg ("VRF ID required but not specified");
9687       return -99;
9688     }
9689
9690   if (tcp_out_vrf_id == 0
9691       || udp_out_vrf_id == 0 || tcp_in_vrf_id == 0 || udp_in_vrf_id == 0)
9692     {
9693       errmsg
9694         ("VRF ID should not be default. Should be distinct VRF for this purpose.");
9695       return -99;
9696     }
9697
9698   /* Construct the API message */
9699   M (IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL, mp);
9700
9701   mp->sw_if_index = ntohl (sw_if_index);
9702   mp->is_add = is_add;
9703   mp->tcp_out_vrf_id = ntohl (tcp_out_vrf_id);
9704   mp->udp_out_vrf_id = ntohl (udp_out_vrf_id);
9705   mp->tcp_in_vrf_id = ntohl (tcp_in_vrf_id);
9706   mp->udp_in_vrf_id = ntohl (udp_in_vrf_id);
9707
9708   /* send it... */
9709   S (mp);
9710
9711   /* Wait for a reply... */
9712   W (ret);
9713   return ret;
9714 }
9715
9716 static int
9717 api_set_punt (vat_main_t * vam)
9718 {
9719   unformat_input_t *i = vam->input;
9720   vl_api_address_family_t af;
9721   vl_api_set_punt_t *mp;
9722   u32 protocol = ~0;
9723   u32 port = ~0;
9724   int is_add = 1;
9725   int ret;
9726
9727   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9728     {
9729       if (unformat (i, "%U", unformat_vl_api_address_family, &af))
9730         ;
9731       else if (unformat (i, "protocol %d", &protocol))
9732         ;
9733       else if (unformat (i, "port %d", &port))
9734         ;
9735       else if (unformat (i, "del"))
9736         is_add = 0;
9737       else
9738         {
9739           clib_warning ("parse error '%U'", format_unformat_error, i);
9740           return -99;
9741         }
9742     }
9743
9744   M (SET_PUNT, mp);
9745
9746   mp->is_add = (u8) is_add;
9747   mp->punt.type = PUNT_API_TYPE_L4;
9748   mp->punt.punt.l4.af = af;
9749   mp->punt.punt.l4.protocol = (u8) protocol;
9750   mp->punt.punt.l4.port = htons ((u16) port);
9751
9752   S (mp);
9753   W (ret);
9754   return ret;
9755 }
9756
9757 static int
9758 api_delete_subif (vat_main_t * vam)
9759 {
9760   unformat_input_t *i = vam->input;
9761   vl_api_delete_subif_t *mp;
9762   u32 sw_if_index = ~0;
9763   int ret;
9764
9765   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9766     {
9767       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
9768         ;
9769       if (unformat (i, "sw_if_index %d", &sw_if_index))
9770         ;
9771       else
9772         break;
9773     }
9774
9775   if (sw_if_index == ~0)
9776     {
9777       errmsg ("missing sw_if_index");
9778       return -99;
9779     }
9780
9781   /* Construct the API message */
9782   M (DELETE_SUBIF, mp);
9783   mp->sw_if_index = ntohl (sw_if_index);
9784
9785   S (mp);
9786   W (ret);
9787   return ret;
9788 }
9789
9790 #define foreach_pbb_vtr_op      \
9791 _("disable",  L2_VTR_DISABLED)  \
9792 _("pop",  L2_VTR_POP_2)         \
9793 _("push",  L2_VTR_PUSH_2)
9794
9795 static int
9796 api_l2_interface_pbb_tag_rewrite (vat_main_t * vam)
9797 {
9798   unformat_input_t *i = vam->input;
9799   vl_api_l2_interface_pbb_tag_rewrite_t *mp;
9800   u32 sw_if_index = ~0, vtr_op = ~0;
9801   u16 outer_tag = ~0;
9802   u8 dmac[6], smac[6];
9803   u8 dmac_set = 0, smac_set = 0;
9804   u16 vlanid = 0;
9805   u32 sid = ~0;
9806   u32 tmp;
9807   int ret;
9808
9809   /* Shut up coverity */
9810   clib_memset (dmac, 0, sizeof (dmac));
9811   clib_memset (smac, 0, sizeof (smac));
9812
9813   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9814     {
9815       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
9816         ;
9817       else if (unformat (i, "sw_if_index %d", &sw_if_index))
9818         ;
9819       else if (unformat (i, "vtr_op %d", &vtr_op))
9820         ;
9821 #define _(n,v) else if (unformat(i, n)) {vtr_op = v;}
9822       foreach_pbb_vtr_op
9823 #undef _
9824         else if (unformat (i, "translate_pbb_stag"))
9825         {
9826           if (unformat (i, "%d", &tmp))
9827             {
9828               vtr_op = L2_VTR_TRANSLATE_2_1;
9829               outer_tag = tmp;
9830             }
9831           else
9832             {
9833               errmsg
9834                 ("translate_pbb_stag operation requires outer tag definition");
9835               return -99;
9836             }
9837         }
9838       else if (unformat (i, "dmac %U", unformat_ethernet_address, dmac))
9839         dmac_set++;
9840       else if (unformat (i, "smac %U", unformat_ethernet_address, smac))
9841         smac_set++;
9842       else if (unformat (i, "sid %d", &sid))
9843         ;
9844       else if (unformat (i, "vlanid %d", &tmp))
9845         vlanid = tmp;
9846       else
9847         {
9848           clib_warning ("parse error '%U'", format_unformat_error, i);
9849           return -99;
9850         }
9851     }
9852
9853   if ((sw_if_index == ~0) || (vtr_op == ~0))
9854     {
9855       errmsg ("missing sw_if_index or vtr operation");
9856       return -99;
9857     }
9858   if (((vtr_op == L2_VTR_PUSH_2) || (vtr_op == L2_VTR_TRANSLATE_2_2))
9859       && ((dmac_set == 0) || (smac_set == 0) || (sid == ~0)))
9860     {
9861       errmsg
9862         ("push and translate_qinq operations require dmac, smac, sid and optionally vlanid");
9863       return -99;
9864     }
9865
9866   M (L2_INTERFACE_PBB_TAG_REWRITE, mp);
9867   mp->sw_if_index = ntohl (sw_if_index);
9868   mp->vtr_op = ntohl (vtr_op);
9869   mp->outer_tag = ntohs (outer_tag);
9870   clib_memcpy (mp->b_dmac, dmac, sizeof (dmac));
9871   clib_memcpy (mp->b_smac, smac, sizeof (smac));
9872   mp->b_vlanid = ntohs (vlanid);
9873   mp->i_sid = ntohl (sid);
9874
9875   S (mp);
9876   W (ret);
9877   return ret;
9878 }
9879
9880 static int
9881 api_sw_interface_tag_add_del (vat_main_t * vam)
9882 {
9883   unformat_input_t *i = vam->input;
9884   vl_api_sw_interface_tag_add_del_t *mp;
9885   u32 sw_if_index = ~0;
9886   u8 *tag = 0;
9887   u8 enable = 1;
9888   int ret;
9889
9890   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9891     {
9892       if (unformat (i, "tag %s", &tag))
9893         ;
9894       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
9895         ;
9896       else if (unformat (i, "sw_if_index %d", &sw_if_index))
9897         ;
9898       else if (unformat (i, "del"))
9899         enable = 0;
9900       else
9901         break;
9902     }
9903
9904   if (sw_if_index == ~0)
9905     {
9906       errmsg ("missing interface name or sw_if_index");
9907       return -99;
9908     }
9909
9910   if (enable && (tag == 0))
9911     {
9912       errmsg ("no tag specified");
9913       return -99;
9914     }
9915
9916   /* Construct the API message */
9917   M (SW_INTERFACE_TAG_ADD_DEL, mp);
9918   mp->sw_if_index = ntohl (sw_if_index);
9919   mp->is_add = enable;
9920   if (enable)
9921     strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
9922   vec_free (tag);
9923
9924   S (mp);
9925   W (ret);
9926   return ret;
9927 }
9928
9929 static int
9930 api_sw_interface_add_del_mac_address (vat_main_t * vam)
9931 {
9932   unformat_input_t *i = vam->input;
9933   vl_api_mac_address_t mac = { 0 };
9934   vl_api_sw_interface_add_del_mac_address_t *mp;
9935   u32 sw_if_index = ~0;
9936   u8 is_add = 1;
9937   u8 mac_set = 0;
9938   int ret;
9939
9940   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9941     {
9942       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
9943         ;
9944       else if (unformat (i, "sw_if_index %d", &sw_if_index))
9945         ;
9946       else if (unformat (i, "%U", unformat_vl_api_mac_address, &mac))
9947         mac_set++;
9948       else if (unformat (i, "del"))
9949         is_add = 0;
9950       else
9951         break;
9952     }
9953
9954   if (sw_if_index == ~0)
9955     {
9956       errmsg ("missing interface name or sw_if_index");
9957       return -99;
9958     }
9959
9960   if (!mac_set)
9961     {
9962       errmsg ("missing MAC address");
9963       return -99;
9964     }
9965
9966   /* Construct the API message */
9967   M (SW_INTERFACE_ADD_DEL_MAC_ADDRESS, mp);
9968   mp->sw_if_index = ntohl (sw_if_index);
9969   mp->is_add = is_add;
9970   clib_memcpy (&mp->addr, &mac, sizeof (mac));
9971
9972   S (mp);
9973   W (ret);
9974   return ret;
9975 }
9976
9977 static void vl_api_l2_xconnect_details_t_handler
9978   (vl_api_l2_xconnect_details_t * mp)
9979 {
9980   vat_main_t *vam = &vat_main;
9981
9982   print (vam->ofp, "%15d%15d",
9983          ntohl (mp->rx_sw_if_index), ntohl (mp->tx_sw_if_index));
9984 }
9985
9986 static void vl_api_l2_xconnect_details_t_handler_json
9987   (vl_api_l2_xconnect_details_t * mp)
9988 {
9989   vat_main_t *vam = &vat_main;
9990   vat_json_node_t *node = NULL;
9991
9992   if (VAT_JSON_ARRAY != vam->json_tree.type)
9993     {
9994       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9995       vat_json_init_array (&vam->json_tree);
9996     }
9997   node = vat_json_array_add (&vam->json_tree);
9998
9999   vat_json_init_object (node);
10000   vat_json_object_add_uint (node, "rx_sw_if_index",
10001                             ntohl (mp->rx_sw_if_index));
10002   vat_json_object_add_uint (node, "tx_sw_if_index",
10003                             ntohl (mp->tx_sw_if_index));
10004 }
10005
10006 static int
10007 api_l2_xconnect_dump (vat_main_t * vam)
10008 {
10009   vl_api_l2_xconnect_dump_t *mp;
10010   vl_api_control_ping_t *mp_ping;
10011   int ret;
10012
10013   if (!vam->json_output)
10014     {
10015       print (vam->ofp, "%15s%15s", "rx_sw_if_index", "tx_sw_if_index");
10016     }
10017
10018   M (L2_XCONNECT_DUMP, mp);
10019
10020   S (mp);
10021
10022   /* Use a control ping for synchronization */
10023   MPING (CONTROL_PING, mp_ping);
10024   S (mp_ping);
10025
10026   W (ret);
10027   return ret;
10028 }
10029
10030 static int
10031 api_hw_interface_set_mtu (vat_main_t * vam)
10032 {
10033   unformat_input_t *i = vam->input;
10034   vl_api_hw_interface_set_mtu_t *mp;
10035   u32 sw_if_index = ~0;
10036   u32 mtu = 0;
10037   int ret;
10038
10039   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10040     {
10041       if (unformat (i, "mtu %d", &mtu))
10042         ;
10043       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10044         ;
10045       else if (unformat (i, "sw_if_index %d", &sw_if_index))
10046         ;
10047       else
10048         break;
10049     }
10050
10051   if (sw_if_index == ~0)
10052     {
10053       errmsg ("missing interface name or sw_if_index");
10054       return -99;
10055     }
10056
10057   if (mtu == 0)
10058     {
10059       errmsg ("no mtu specified");
10060       return -99;
10061     }
10062
10063   /* Construct the API message */
10064   M (HW_INTERFACE_SET_MTU, mp);
10065   mp->sw_if_index = ntohl (sw_if_index);
10066   mp->mtu = ntohs ((u16) mtu);
10067
10068   S (mp);
10069   W (ret);
10070   return ret;
10071 }
10072
10073 static int
10074 api_tcp_configure_src_addresses (vat_main_t * vam)
10075 {
10076   vl_api_tcp_configure_src_addresses_t *mp;
10077   unformat_input_t *i = vam->input;
10078   vl_api_address_t first, last;
10079   u8 range_set = 0;
10080   u32 vrf_id = 0;
10081   int ret;
10082
10083   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10084     {
10085       if (unformat (i, "%U - %U",
10086                     unformat_vl_api_address, &first,
10087                     unformat_vl_api_address, &last))
10088         {
10089           if (range_set)
10090             {
10091               errmsg ("one range per message (range already set)");
10092               return -99;
10093             }
10094           range_set = 1;
10095         }
10096       else if (unformat (i, "vrf %d", &vrf_id))
10097         ;
10098       else
10099         break;
10100     }
10101
10102   if (range_set == 0)
10103     {
10104       errmsg ("address range not set");
10105       return -99;
10106     }
10107
10108   M (TCP_CONFIGURE_SRC_ADDRESSES, mp);
10109
10110   mp->vrf_id = ntohl (vrf_id);
10111   clib_memcpy (&mp->first_address, &first, sizeof (first));
10112   clib_memcpy (&mp->last_address, &last, sizeof (last));
10113
10114   S (mp);
10115   W (ret);
10116   return ret;
10117 }
10118
10119 static void vl_api_app_namespace_add_del_reply_t_handler
10120   (vl_api_app_namespace_add_del_reply_t * mp)
10121 {
10122   vat_main_t *vam = &vat_main;
10123   i32 retval = ntohl (mp->retval);
10124   if (vam->async_mode)
10125     {
10126       vam->async_errors += (retval < 0);
10127     }
10128   else
10129     {
10130       vam->retval = retval;
10131       if (retval == 0)
10132         errmsg ("app ns index %d\n", ntohl (mp->appns_index));
10133       vam->result_ready = 1;
10134     }
10135 }
10136
10137 static void vl_api_app_namespace_add_del_reply_t_handler_json
10138   (vl_api_app_namespace_add_del_reply_t * mp)
10139 {
10140   vat_main_t *vam = &vat_main;
10141   vat_json_node_t node;
10142
10143   vat_json_init_object (&node);
10144   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
10145   vat_json_object_add_uint (&node, "appns_index", ntohl (mp->appns_index));
10146
10147   vat_json_print (vam->ofp, &node);
10148   vat_json_free (&node);
10149
10150   vam->retval = ntohl (mp->retval);
10151   vam->result_ready = 1;
10152 }
10153
10154 static int
10155 api_app_namespace_add_del (vat_main_t * vam)
10156 {
10157   vl_api_app_namespace_add_del_t *mp;
10158   unformat_input_t *i = vam->input;
10159   u8 *ns_id = 0, secret_set = 0, sw_if_index_set = 0;
10160   u32 sw_if_index, ip4_fib_id, ip6_fib_id;
10161   u64 secret;
10162   int ret;
10163
10164   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10165     {
10166       if (unformat (i, "id %_%v%_", &ns_id))
10167         ;
10168       else if (unformat (i, "secret %lu", &secret))
10169         secret_set = 1;
10170       else if (unformat (i, "sw_if_index %d", &sw_if_index))
10171         sw_if_index_set = 1;
10172       else if (unformat (i, "ip4_fib_id %d", &ip4_fib_id))
10173         ;
10174       else if (unformat (i, "ip6_fib_id %d", &ip6_fib_id))
10175         ;
10176       else
10177         break;
10178     }
10179   if (!ns_id || !secret_set || !sw_if_index_set)
10180     {
10181       errmsg ("namespace id, secret and sw_if_index must be set");
10182       return -99;
10183     }
10184   if (vec_len (ns_id) > 64)
10185     {
10186       errmsg ("namespace id too long");
10187       return -99;
10188     }
10189   M (APP_NAMESPACE_ADD_DEL, mp);
10190
10191   vl_api_vec_to_api_string (ns_id, &mp->namespace_id);
10192   mp->secret = clib_host_to_net_u64 (secret);
10193   mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
10194   mp->ip4_fib_id = clib_host_to_net_u32 (ip4_fib_id);
10195   mp->ip6_fib_id = clib_host_to_net_u32 (ip6_fib_id);
10196   vec_free (ns_id);
10197   S (mp);
10198   W (ret);
10199   return ret;
10200 }
10201
10202 static int
10203 api_sock_init_shm (vat_main_t * vam)
10204 {
10205 #if VPP_API_TEST_BUILTIN == 0
10206   unformat_input_t *i = vam->input;
10207   vl_api_shm_elem_config_t *config = 0;
10208   u64 size = 64 << 20;
10209   int rv;
10210
10211   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10212     {
10213       if (unformat (i, "size %U", unformat_memory_size, &size))
10214         ;
10215       else
10216         break;
10217     }
10218
10219   /*
10220    * Canned custom ring allocator config.
10221    * Should probably parse all of this
10222    */
10223   vec_validate (config, 6);
10224   config[0].type = VL_API_VLIB_RING;
10225   config[0].size = 256;
10226   config[0].count = 32;
10227
10228   config[1].type = VL_API_VLIB_RING;
10229   config[1].size = 1024;
10230   config[1].count = 16;
10231
10232   config[2].type = VL_API_VLIB_RING;
10233   config[2].size = 4096;
10234   config[2].count = 2;
10235
10236   config[3].type = VL_API_CLIENT_RING;
10237   config[3].size = 256;
10238   config[3].count = 32;
10239
10240   config[4].type = VL_API_CLIENT_RING;
10241   config[4].size = 1024;
10242   config[4].count = 16;
10243
10244   config[5].type = VL_API_CLIENT_RING;
10245   config[5].size = 4096;
10246   config[5].count = 2;
10247
10248   config[6].type = VL_API_QUEUE;
10249   config[6].count = 128;
10250   config[6].size = sizeof (uword);
10251
10252   rv = vl_socket_client_init_shm (config, 1 /* want_pthread */ );
10253   if (!rv)
10254     vam->client_index_invalid = 1;
10255   return rv;
10256 #else
10257   return -99;
10258 #endif
10259 }
10260
10261 static void
10262 vl_api_session_rules_details_t_handler (vl_api_session_rules_details_t * mp)
10263 {
10264   vat_main_t *vam = &vat_main;
10265   fib_prefix_t lcl, rmt;
10266
10267   ip_prefix_decode (&mp->lcl, &lcl);
10268   ip_prefix_decode (&mp->rmt, &rmt);
10269
10270   if (lcl.fp_proto == FIB_PROTOCOL_IP4)
10271     {
10272       print (vam->ofp,
10273              "appns %u tp %u scope %d %U/%d %d %U/%d %d action: %d tag: %s",
10274              clib_net_to_host_u32 (mp->appns_index), mp->transport_proto,
10275              mp->scope, format_ip4_address, &lcl.fp_addr.ip4, lcl.fp_len,
10276              clib_net_to_host_u16 (mp->lcl_port), format_ip4_address,
10277              &rmt.fp_addr.ip4, rmt.fp_len,
10278              clib_net_to_host_u16 (mp->rmt_port),
10279              clib_net_to_host_u32 (mp->action_index), mp->tag);
10280     }
10281   else
10282     {
10283       print (vam->ofp,
10284              "appns %u tp %u scope %d %U/%d %d %U/%d %d action: %d tag: %s",
10285              clib_net_to_host_u32 (mp->appns_index), mp->transport_proto,
10286              mp->scope, format_ip6_address, &lcl.fp_addr.ip6, lcl.fp_len,
10287              clib_net_to_host_u16 (mp->lcl_port), format_ip6_address,
10288              &rmt.fp_addr.ip6, rmt.fp_len,
10289              clib_net_to_host_u16 (mp->rmt_port),
10290              clib_net_to_host_u32 (mp->action_index), mp->tag);
10291     }
10292 }
10293
10294 static void
10295 vl_api_session_rules_details_t_handler_json (vl_api_session_rules_details_t *
10296                                              mp)
10297 {
10298   vat_main_t *vam = &vat_main;
10299   vat_json_node_t *node = NULL;
10300   struct in6_addr ip6;
10301   struct in_addr ip4;
10302
10303   fib_prefix_t lcl, rmt;
10304
10305   ip_prefix_decode (&mp->lcl, &lcl);
10306   ip_prefix_decode (&mp->rmt, &rmt);
10307
10308   if (VAT_JSON_ARRAY != vam->json_tree.type)
10309     {
10310       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
10311       vat_json_init_array (&vam->json_tree);
10312     }
10313   node = vat_json_array_add (&vam->json_tree);
10314   vat_json_init_object (node);
10315
10316   vat_json_object_add_uint (node, "appns_index",
10317                             clib_net_to_host_u32 (mp->appns_index));
10318   vat_json_object_add_uint (node, "transport_proto", mp->transport_proto);
10319   vat_json_object_add_uint (node, "scope", mp->scope);
10320   vat_json_object_add_uint (node, "action_index",
10321                             clib_net_to_host_u32 (mp->action_index));
10322   vat_json_object_add_uint (node, "lcl_port",
10323                             clib_net_to_host_u16 (mp->lcl_port));
10324   vat_json_object_add_uint (node, "rmt_port",
10325                             clib_net_to_host_u16 (mp->rmt_port));
10326   vat_json_object_add_uint (node, "lcl_plen", lcl.fp_len);
10327   vat_json_object_add_uint (node, "rmt_plen", rmt.fp_len);
10328   vat_json_object_add_string_copy (node, "tag", mp->tag);
10329   if (lcl.fp_proto == FIB_PROTOCOL_IP4)
10330     {
10331       clib_memcpy (&ip4, &lcl.fp_addr.ip4, sizeof (ip4));
10332       vat_json_object_add_ip4 (node, "lcl_ip", ip4);
10333       clib_memcpy (&ip4, &rmt.fp_addr.ip4, sizeof (ip4));
10334       vat_json_object_add_ip4 (node, "rmt_ip", ip4);
10335     }
10336   else
10337     {
10338       clib_memcpy (&ip6, &lcl.fp_addr.ip6, sizeof (ip6));
10339       vat_json_object_add_ip6 (node, "lcl_ip", ip6);
10340       clib_memcpy (&ip6, &rmt.fp_addr.ip6, sizeof (ip6));
10341       vat_json_object_add_ip6 (node, "rmt_ip", ip6);
10342     }
10343 }
10344
10345 static int
10346 api_session_rule_add_del (vat_main_t * vam)
10347 {
10348   vl_api_session_rule_add_del_t *mp;
10349   unformat_input_t *i = vam->input;
10350   u32 proto = ~0, lcl_port, rmt_port, action = 0, lcl_plen, rmt_plen;
10351   u32 appns_index = 0, scope = 0;
10352   ip4_address_t lcl_ip4, rmt_ip4;
10353   ip6_address_t lcl_ip6, rmt_ip6;
10354   u8 is_ip4 = 1, conn_set = 0;
10355   u8 is_add = 1, *tag = 0;
10356   int ret;
10357   fib_prefix_t lcl, rmt;
10358
10359   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10360     {
10361       if (unformat (i, "del"))
10362         is_add = 0;
10363       else if (unformat (i, "add"))
10364         ;
10365       else if (unformat (i, "proto tcp"))
10366         proto = 0;
10367       else if (unformat (i, "proto udp"))
10368         proto = 1;
10369       else if (unformat (i, "appns %d", &appns_index))
10370         ;
10371       else if (unformat (i, "scope %d", &scope))
10372         ;
10373       else if (unformat (i, "tag %_%v%_", &tag))
10374         ;
10375       else
10376         if (unformat
10377             (i, "%U/%d %d %U/%d %d", unformat_ip4_address, &lcl_ip4,
10378              &lcl_plen, &lcl_port, unformat_ip4_address, &rmt_ip4, &rmt_plen,
10379              &rmt_port))
10380         {
10381           is_ip4 = 1;
10382           conn_set = 1;
10383         }
10384       else
10385         if (unformat
10386             (i, "%U/%d %d %U/%d %d", unformat_ip6_address, &lcl_ip6,
10387              &lcl_plen, &lcl_port, unformat_ip6_address, &rmt_ip6, &rmt_plen,
10388              &rmt_port))
10389         {
10390           is_ip4 = 0;
10391           conn_set = 1;
10392         }
10393       else if (unformat (i, "action %d", &action))
10394         ;
10395       else
10396         break;
10397     }
10398   if (proto == ~0 || !conn_set || action == ~0)
10399     {
10400       errmsg ("transport proto, connection and action must be set");
10401       return -99;
10402     }
10403
10404   if (scope > 3)
10405     {
10406       errmsg ("scope should be 0-3");
10407       return -99;
10408     }
10409
10410   M (SESSION_RULE_ADD_DEL, mp);
10411
10412   clib_memset (&lcl, 0, sizeof (lcl));
10413   clib_memset (&rmt, 0, sizeof (rmt));
10414   if (is_ip4)
10415     {
10416       ip_set (&lcl.fp_addr, &lcl_ip4, 1);
10417       ip_set (&rmt.fp_addr, &rmt_ip4, 1);
10418       lcl.fp_len = lcl_plen;
10419       rmt.fp_len = rmt_plen;
10420     }
10421   else
10422     {
10423       ip_set (&lcl.fp_addr, &lcl_ip6, 0);
10424       ip_set (&rmt.fp_addr, &rmt_ip6, 0);
10425       lcl.fp_len = lcl_plen;
10426       rmt.fp_len = rmt_plen;
10427     }
10428
10429
10430   ip_prefix_encode (&lcl, &mp->lcl);
10431   ip_prefix_encode (&rmt, &mp->rmt);
10432   mp->lcl_port = clib_host_to_net_u16 ((u16) lcl_port);
10433   mp->rmt_port = clib_host_to_net_u16 ((u16) rmt_port);
10434   mp->transport_proto =
10435     proto ? TRANSPORT_PROTO_API_UDP : TRANSPORT_PROTO_API_TCP;
10436   mp->action_index = clib_host_to_net_u32 (action);
10437   mp->appns_index = clib_host_to_net_u32 (appns_index);
10438   mp->scope = scope;
10439   mp->is_add = is_add;
10440   if (tag)
10441     {
10442       clib_memcpy (mp->tag, tag, vec_len (tag));
10443       vec_free (tag);
10444     }
10445
10446   S (mp);
10447   W (ret);
10448   return ret;
10449 }
10450
10451 static int
10452 api_session_rules_dump (vat_main_t * vam)
10453 {
10454   vl_api_session_rules_dump_t *mp;
10455   vl_api_control_ping_t *mp_ping;
10456   int ret;
10457
10458   if (!vam->json_output)
10459     {
10460       print (vam->ofp, "%=20s", "Session Rules");
10461     }
10462
10463   M (SESSION_RULES_DUMP, mp);
10464   /* send it... */
10465   S (mp);
10466
10467   /* Use a control ping for synchronization */
10468   MPING (CONTROL_PING, mp_ping);
10469   S (mp_ping);
10470
10471   /* Wait for a reply... */
10472   W (ret);
10473   return ret;
10474 }
10475
10476 static int
10477 api_ip_container_proxy_add_del (vat_main_t * vam)
10478 {
10479   vl_api_ip_container_proxy_add_del_t *mp;
10480   unformat_input_t *i = vam->input;
10481   u32 sw_if_index = ~0;
10482   vl_api_prefix_t pfx = { };
10483   u8 is_add = 1;
10484   int ret;
10485
10486   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10487     {
10488       if (unformat (i, "del"))
10489         is_add = 0;
10490       else if (unformat (i, "add"))
10491         ;
10492       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
10493         ;
10494       else if (unformat (i, "sw_if_index %u", &sw_if_index))
10495         ;
10496       else
10497         break;
10498     }
10499   if (sw_if_index == ~0 || pfx.len == 0)
10500     {
10501       errmsg ("address and sw_if_index must be set");
10502       return -99;
10503     }
10504
10505   M (IP_CONTAINER_PROXY_ADD_DEL, mp);
10506
10507   mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
10508   mp->is_add = is_add;
10509   clib_memcpy (&mp->pfx, &pfx, sizeof (pfx));
10510
10511   S (mp);
10512   W (ret);
10513   return ret;
10514 }
10515
10516 static int
10517 api_qos_record_enable_disable (vat_main_t * vam)
10518 {
10519   unformat_input_t *i = vam->input;
10520   vl_api_qos_record_enable_disable_t *mp;
10521   u32 sw_if_index, qs = 0xff;
10522   u8 sw_if_index_set = 0;
10523   u8 enable = 1;
10524   int ret;
10525
10526   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10527     {
10528       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10529         sw_if_index_set = 1;
10530       else if (unformat (i, "sw_if_index %d", &sw_if_index))
10531         sw_if_index_set = 1;
10532       else if (unformat (i, "%U", unformat_qos_source, &qs))
10533         ;
10534       else if (unformat (i, "disable"))
10535         enable = 0;
10536       else
10537         {
10538           clib_warning ("parse error '%U'", format_unformat_error, i);
10539           return -99;
10540         }
10541     }
10542
10543   if (sw_if_index_set == 0)
10544     {
10545       errmsg ("missing interface name or sw_if_index");
10546       return -99;
10547     }
10548   if (qs == 0xff)
10549     {
10550       errmsg ("input location must be specified");
10551       return -99;
10552     }
10553
10554   M (QOS_RECORD_ENABLE_DISABLE, mp);
10555
10556   mp->record.sw_if_index = ntohl (sw_if_index);
10557   mp->record.input_source = qs;
10558   mp->enable = enable;
10559
10560   S (mp);
10561   W (ret);
10562   return ret;
10563 }
10564
10565
10566 static int
10567 q_or_quit (vat_main_t * vam)
10568 {
10569 #if VPP_API_TEST_BUILTIN == 0
10570   longjmp (vam->jump_buf, 1);
10571 #endif
10572   return 0;                     /* not so much */
10573 }
10574
10575 static int
10576 q (vat_main_t * vam)
10577 {
10578   return q_or_quit (vam);
10579 }
10580
10581 static int
10582 quit (vat_main_t * vam)
10583 {
10584   return q_or_quit (vam);
10585 }
10586
10587 static int
10588 comment (vat_main_t * vam)
10589 {
10590   return 0;
10591 }
10592
10593 static int
10594 elog_save (vat_main_t * vam)
10595 {
10596 #if VPP_API_TEST_BUILTIN == 0
10597   elog_main_t *em = &vam->elog_main;
10598   unformat_input_t *i = vam->input;
10599   char *file, *chroot_file;
10600   clib_error_t *error;
10601
10602   if (!unformat (i, "%s", &file))
10603     {
10604       errmsg ("expected file name, got `%U'", format_unformat_error, i);
10605       return 0;
10606     }
10607
10608   /* It's fairly hard to get "../oopsie" through unformat; just in case */
10609   if (strstr (file, "..") || index (file, '/'))
10610     {
10611       errmsg ("illegal characters in filename '%s'", file);
10612       return 0;
10613     }
10614
10615   chroot_file = (char *) format (0, "/tmp/%s%c", file, 0);
10616
10617   vec_free (file);
10618
10619   errmsg ("Saving %wd of %wd events to %s",
10620           elog_n_events_in_buffer (em),
10621           elog_buffer_capacity (em), chroot_file);
10622
10623   error = elog_write_file (em, chroot_file, 1 /* flush ring */ );
10624   vec_free (chroot_file);
10625
10626   if (error)
10627     clib_error_report (error);
10628 #else
10629   errmsg ("Use the vpp event loger...");
10630 #endif
10631
10632   return 0;
10633 }
10634
10635 static int
10636 elog_setup (vat_main_t * vam)
10637 {
10638 #if VPP_API_TEST_BUILTIN == 0
10639   elog_main_t *em = &vam->elog_main;
10640   unformat_input_t *i = vam->input;
10641   u32 nevents = 128 << 10;
10642
10643   (void) unformat (i, "nevents %d", &nevents);
10644
10645   elog_init (em, nevents);
10646   vl_api_set_elog_main (em);
10647   vl_api_set_elog_trace_api_messages (1);
10648   errmsg ("Event logger initialized with %u events", nevents);
10649 #else
10650   errmsg ("Use the vpp event loger...");
10651 #endif
10652   return 0;
10653 }
10654
10655 static int
10656 elog_enable (vat_main_t * vam)
10657 {
10658 #if VPP_API_TEST_BUILTIN == 0
10659   elog_main_t *em = &vam->elog_main;
10660
10661   elog_enable_disable (em, 1 /* enable */ );
10662   vl_api_set_elog_trace_api_messages (1);
10663   errmsg ("Event logger enabled...");
10664 #else
10665   errmsg ("Use the vpp event loger...");
10666 #endif
10667   return 0;
10668 }
10669
10670 static int
10671 elog_disable (vat_main_t * vam)
10672 {
10673 #if VPP_API_TEST_BUILTIN == 0
10674   elog_main_t *em = &vam->elog_main;
10675
10676   elog_enable_disable (em, 0 /* enable */ );
10677   vl_api_set_elog_trace_api_messages (1);
10678   errmsg ("Event logger disabled...");
10679 #else
10680   errmsg ("Use the vpp event loger...");
10681 #endif
10682   return 0;
10683 }
10684
10685 static int
10686 statseg (vat_main_t * vam)
10687 {
10688   ssvm_private_t *ssvmp = &vam->stat_segment;
10689   ssvm_shared_header_t *shared_header = ssvmp->sh;
10690   vlib_counter_t **counters;
10691   u64 thread0_index1_packets;
10692   u64 thread0_index1_bytes;
10693   f64 vector_rate, input_rate;
10694   uword *p;
10695
10696   uword *counter_vector_by_name;
10697   if (vam->stat_segment_lockp == 0)
10698     {
10699       errmsg ("Stat segment not mapped...");
10700       return -99;
10701     }
10702
10703   /* look up "/if/rx for sw_if_index 1 as a test */
10704
10705   clib_spinlock_lock (vam->stat_segment_lockp);
10706
10707   counter_vector_by_name = (uword *) shared_header->opaque[1];
10708
10709   p = hash_get_mem (counter_vector_by_name, "/if/rx");
10710   if (p == 0)
10711     {
10712       clib_spinlock_unlock (vam->stat_segment_lockp);
10713       errmsg ("/if/tx not found?");
10714       return -99;
10715     }
10716
10717   /* Fish per-thread vector of combined counters from shared memory */
10718   counters = (vlib_counter_t **) p[0];
10719
10720   if (vec_len (counters[0]) < 2)
10721     {
10722       clib_spinlock_unlock (vam->stat_segment_lockp);
10723       errmsg ("/if/tx vector length %d", vec_len (counters[0]));
10724       return -99;
10725     }
10726
10727   /* Read thread 0 sw_if_index 1 counter */
10728   thread0_index1_packets = counters[0][1].packets;
10729   thread0_index1_bytes = counters[0][1].bytes;
10730
10731   p = hash_get_mem (counter_vector_by_name, "vector_rate");
10732   if (p == 0)
10733     {
10734       clib_spinlock_unlock (vam->stat_segment_lockp);
10735       errmsg ("vector_rate not found?");
10736       return -99;
10737     }
10738
10739   vector_rate = *(f64 *) (p[0]);
10740   p = hash_get_mem (counter_vector_by_name, "input_rate");
10741   if (p == 0)
10742     {
10743       clib_spinlock_unlock (vam->stat_segment_lockp);
10744       errmsg ("input_rate not found?");
10745       return -99;
10746     }
10747   input_rate = *(f64 *) (p[0]);
10748
10749   clib_spinlock_unlock (vam->stat_segment_lockp);
10750
10751   print (vam->ofp, "vector_rate %.2f input_rate %.2f",
10752          vector_rate, input_rate);
10753   print (vam->ofp, "thread 0 sw_if_index 1 rx pkts %lld, bytes %lld",
10754          thread0_index1_packets, thread0_index1_bytes);
10755
10756   return 0;
10757 }
10758
10759 static int
10760 cmd_cmp (void *a1, void *a2)
10761 {
10762   u8 **c1 = a1;
10763   u8 **c2 = a2;
10764
10765   return strcmp ((char *) (c1[0]), (char *) (c2[0]));
10766 }
10767
10768 static int
10769 help (vat_main_t * vam)
10770 {
10771   u8 **cmds = 0;
10772   u8 *name = 0;
10773   hash_pair_t *p;
10774   unformat_input_t *i = vam->input;
10775   int j;
10776
10777   if (unformat (i, "%s", &name))
10778     {
10779       uword *hs;
10780
10781       vec_add1 (name, 0);
10782
10783       hs = hash_get_mem (vam->help_by_name, name);
10784       if (hs)
10785         print (vam->ofp, "usage: %s %s", name, hs[0]);
10786       else
10787         print (vam->ofp, "No such msg / command '%s'", name);
10788       vec_free (name);
10789       return 0;
10790     }
10791
10792   print (vam->ofp, "Help is available for the following:");
10793
10794     /* *INDENT-OFF* */
10795     hash_foreach_pair (p, vam->function_by_name,
10796     ({
10797       vec_add1 (cmds, (u8 *)(p->key));
10798     }));
10799     /* *INDENT-ON* */
10800
10801   vec_sort_with_function (cmds, cmd_cmp);
10802
10803   for (j = 0; j < vec_len (cmds); j++)
10804     print (vam->ofp, "%s", cmds[j]);
10805
10806   vec_free (cmds);
10807   return 0;
10808 }
10809
10810 static int
10811 set (vat_main_t * vam)
10812 {
10813   u8 *name = 0, *value = 0;
10814   unformat_input_t *i = vam->input;
10815
10816   if (unformat (i, "%s", &name))
10817     {
10818       /* The input buffer is a vector, not a string. */
10819       value = vec_dup (i->buffer);
10820       vec_delete (value, i->index, 0);
10821       /* Almost certainly has a trailing newline */
10822       if (value[vec_len (value) - 1] == '\n')
10823         value[vec_len (value) - 1] = 0;
10824       /* Make sure it's a proper string, one way or the other */
10825       vec_add1 (value, 0);
10826       (void) clib_macro_set_value (&vam->macro_main,
10827                                    (char *) name, (char *) value);
10828     }
10829   else
10830     errmsg ("usage: set <name> <value>");
10831
10832   vec_free (name);
10833   vec_free (value);
10834   return 0;
10835 }
10836
10837 static int
10838 unset (vat_main_t * vam)
10839 {
10840   u8 *name = 0;
10841
10842   if (unformat (vam->input, "%s", &name))
10843     if (clib_macro_unset (&vam->macro_main, (char *) name) == 1)
10844       errmsg ("unset: %s wasn't set", name);
10845   vec_free (name);
10846   return 0;
10847 }
10848
10849 typedef struct
10850 {
10851   u8 *name;
10852   u8 *value;
10853 } macro_sort_t;
10854
10855
10856 static int
10857 macro_sort_cmp (void *a1, void *a2)
10858 {
10859   macro_sort_t *s1 = a1;
10860   macro_sort_t *s2 = a2;
10861
10862   return strcmp ((char *) (s1->name), (char *) (s2->name));
10863 }
10864
10865 static int
10866 dump_macro_table (vat_main_t * vam)
10867 {
10868   macro_sort_t *sort_me = 0, *sm;
10869   int i;
10870   hash_pair_t *p;
10871
10872     /* *INDENT-OFF* */
10873     hash_foreach_pair (p, vam->macro_main.the_value_table_hash,
10874     ({
10875       vec_add2 (sort_me, sm, 1);
10876       sm->name = (u8 *)(p->key);
10877       sm->value = (u8 *) (p->value[0]);
10878     }));
10879     /* *INDENT-ON* */
10880
10881   vec_sort_with_function (sort_me, macro_sort_cmp);
10882
10883   if (vec_len (sort_me))
10884     print (vam->ofp, "%-15s%s", "Name", "Value");
10885   else
10886     print (vam->ofp, "The macro table is empty...");
10887
10888   for (i = 0; i < vec_len (sort_me); i++)
10889     print (vam->ofp, "%-15s%s", sort_me[i].name, sort_me[i].value);
10890   return 0;
10891 }
10892
10893 static int
10894 dump_node_table (vat_main_t * vam)
10895 {
10896   int i, j;
10897   vlib_node_t *node, *next_node;
10898
10899   if (vec_len (vam->graph_nodes) == 0)
10900     {
10901       print (vam->ofp, "Node table empty, issue get_node_graph...");
10902       return 0;
10903     }
10904
10905   for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
10906     {
10907       node = vam->graph_nodes[0][i];
10908       print (vam->ofp, "[%d] %s", i, node->name);
10909       for (j = 0; j < vec_len (node->next_nodes); j++)
10910         {
10911           if (node->next_nodes[j] != ~0)
10912             {
10913               next_node = vam->graph_nodes[0][node->next_nodes[j]];
10914               print (vam->ofp, "  [%d] %s", j, next_node->name);
10915             }
10916         }
10917     }
10918   return 0;
10919 }
10920
10921 static int
10922 value_sort_cmp (void *a1, void *a2)
10923 {
10924   name_sort_t *n1 = a1;
10925   name_sort_t *n2 = a2;
10926
10927   if (n1->value < n2->value)
10928     return -1;
10929   if (n1->value > n2->value)
10930     return 1;
10931   return 0;
10932 }
10933
10934
10935 static int
10936 dump_msg_api_table (vat_main_t * vam)
10937 {
10938   api_main_t *am = vlibapi_get_main ();
10939   name_sort_t *nses = 0, *ns;
10940   hash_pair_t *hp;
10941   int i;
10942
10943   /* *INDENT-OFF* */
10944   hash_foreach_pair (hp, am->msg_index_by_name_and_crc,
10945   ({
10946     vec_add2 (nses, ns, 1);
10947     ns->name = (u8 *)(hp->key);
10948     ns->value = (u32) hp->value[0];
10949   }));
10950   /* *INDENT-ON* */
10951
10952   vec_sort_with_function (nses, value_sort_cmp);
10953
10954   for (i = 0; i < vec_len (nses); i++)
10955     print (vam->ofp, " [%d]: %s", nses[i].value, nses[i].name);
10956   vec_free (nses);
10957   return 0;
10958 }
10959
10960 static int
10961 get_msg_id (vat_main_t * vam)
10962 {
10963   u8 *name_and_crc;
10964   u32 message_index;
10965
10966   if (unformat (vam->input, "%s", &name_and_crc))
10967     {
10968       message_index = vl_msg_api_get_msg_index (name_and_crc);
10969       if (message_index == ~0)
10970         {
10971           print (vam->ofp, " '%s' not found", name_and_crc);
10972           return 0;
10973         }
10974       print (vam->ofp, " '%s' has message index %d",
10975              name_and_crc, message_index);
10976       return 0;
10977     }
10978   errmsg ("name_and_crc required...");
10979   return 0;
10980 }
10981
10982 static int
10983 search_node_table (vat_main_t * vam)
10984 {
10985   unformat_input_t *line_input = vam->input;
10986   u8 *node_to_find;
10987   int j;
10988   vlib_node_t *node, *next_node;
10989   uword *p;
10990
10991   if (vam->graph_node_index_by_name == 0)
10992     {
10993       print (vam->ofp, "Node table empty, issue get_node_graph...");
10994       return 0;
10995     }
10996
10997   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
10998     {
10999       if (unformat (line_input, "%s", &node_to_find))
11000         {
11001           vec_add1 (node_to_find, 0);
11002           p = hash_get_mem (vam->graph_node_index_by_name, node_to_find);
11003           if (p == 0)
11004             {
11005               print (vam->ofp, "%s not found...", node_to_find);
11006               goto out;
11007             }
11008           node = vam->graph_nodes[0][p[0]];
11009           print (vam->ofp, "[%d] %s", p[0], node->name);
11010           for (j = 0; j < vec_len (node->next_nodes); j++)
11011             {
11012               if (node->next_nodes[j] != ~0)
11013                 {
11014                   next_node = vam->graph_nodes[0][node->next_nodes[j]];
11015                   print (vam->ofp, "  [%d] %s", j, next_node->name);
11016                 }
11017             }
11018         }
11019
11020       else
11021         {
11022           clib_warning ("parse error '%U'", format_unformat_error,
11023                         line_input);
11024           return -99;
11025         }
11026
11027     out:
11028       vec_free (node_to_find);
11029
11030     }
11031
11032   return 0;
11033 }
11034
11035
11036 static int
11037 script (vat_main_t * vam)
11038 {
11039 #if (VPP_API_TEST_BUILTIN==0)
11040   u8 *s = 0;
11041   char *save_current_file;
11042   unformat_input_t save_input;
11043   jmp_buf save_jump_buf;
11044   u32 save_line_number;
11045
11046   FILE *new_fp, *save_ifp;
11047
11048   if (unformat (vam->input, "%s", &s))
11049     {
11050       new_fp = fopen ((char *) s, "r");
11051       if (new_fp == 0)
11052         {
11053           errmsg ("Couldn't open script file %s", s);
11054           vec_free (s);
11055           return -99;
11056         }
11057     }
11058   else
11059     {
11060       errmsg ("Missing script name");
11061       return -99;
11062     }
11063
11064   clib_memcpy (&save_input, &vam->input, sizeof (save_input));
11065   clib_memcpy (&save_jump_buf, &vam->jump_buf, sizeof (save_jump_buf));
11066   save_ifp = vam->ifp;
11067   save_line_number = vam->input_line_number;
11068   save_current_file = (char *) vam->current_file;
11069
11070   vam->input_line_number = 0;
11071   vam->ifp = new_fp;
11072   vam->current_file = s;
11073   do_one_file (vam);
11074
11075   clib_memcpy (&vam->input, &save_input, sizeof (save_input));
11076   clib_memcpy (&vam->jump_buf, &save_jump_buf, sizeof (save_jump_buf));
11077   vam->ifp = save_ifp;
11078   vam->input_line_number = save_line_number;
11079   vam->current_file = (u8 *) save_current_file;
11080   vec_free (s);
11081
11082   return 0;
11083 #else
11084   clib_warning ("use the exec command...");
11085   return -99;
11086 #endif
11087 }
11088
11089 static int
11090 echo (vat_main_t * vam)
11091 {
11092   print (vam->ofp, "%v", vam->input->buffer);
11093   return 0;
11094 }
11095
11096 /* List of API message constructors, CLI names map to api_xxx */
11097 #define foreach_vpe_api_msg                                             \
11098 _(create_loopback,"[mac <mac-addr>] [instance <instance>]")             \
11099 _(sw_interface_dump,"")                                                 \
11100 _(sw_interface_set_flags,                                               \
11101   "<intfc> | sw_if_index <id> admin-up | admin-down link-up | link down") \
11102 _(sw_interface_add_del_address,                                         \
11103   "<intfc> | sw_if_index <id> <ip4-address> | <ip6-address> [del] [del-all] ") \
11104 _(sw_interface_set_rx_mode,                                             \
11105   "<intfc> | sw_if_index <id> [queue <id>] <polling | interrupt | adaptive>") \
11106 _(sw_interface_set_rx_placement,                                        \
11107   "<intfc> | sw_if_index <id> [queue <id>] [worker <id> | main]")       \
11108 _(sw_interface_rx_placement_dump,                                       \
11109   "[<intfc> | sw_if_index <id>]")                                         \
11110 _(sw_interface_set_table,                                               \
11111   "<intfc> | sw_if_index <id> vrf <table-id> [ipv6]")                   \
11112 _(sw_interface_set_mpls_enable,                                         \
11113   "<intfc> | sw_if_index [disable | dis]")                              \
11114 _(sw_interface_set_vpath,                                               \
11115   "<intfc> | sw_if_index <id> enable | disable")                        \
11116 _(sw_interface_set_l2_xconnect,                                         \
11117   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
11118   "enable | disable")                                                   \
11119 _(sw_interface_set_l2_bridge,                                           \
11120   "{<intfc> | sw_if_index <id>} bd_id <bridge-domain-id>\n"             \
11121   "[shg <split-horizon-group>] [bvi]\n"                                 \
11122   "enable | disable")                                                   \
11123 _(bridge_domain_set_mac_age, "bd_id <bridge-domain-id> mac-age 0-255")  \
11124 _(bridge_domain_add_del,                                                \
11125   "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") \
11126 _(bridge_domain_dump, "[bd_id <bridge-domain-id>]\n")                   \
11127 _(l2fib_add_del,                                                        \
11128   "mac <mac-addr> bd_id <bridge-domain-id> [del] | sw_if <intfc> | sw_if_index <id> [static] [filter] [bvi] [count <nn>]\n") \
11129 _(l2fib_flush_bd, "bd_id <bridge-domain-id>")                           \
11130 _(l2fib_flush_int, "<intfc> | sw_if_index <id>")                        \
11131 _(l2_flags,                                                             \
11132   "sw_if <intfc> | sw_if_index <id> [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \
11133 _(bridge_flags,                                                         \
11134   "bd_id <bridge-domain-id> [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \
11135 _(tap_create_v2,                                                        \
11136   "id <num> [hw-addr <mac-addr>] [host-if-name <name>] [host-ns <name>] [num-rx-queues <num>] [rx-ring-size <num>] [tx-ring-size <num>] [host-bridge <name>] [host-mac-addr <mac-addr>] [host-ip4-addr <ip4addr/mask>] [host-ip6-addr <ip6addr/mask>] [host-mtu-size <mtu>] [gso | no-gso | csum-offload | gro-coalesce] [persist] [attach] [tun] [packed] [in-order]") \
11137 _(tap_delete_v2,                                                        \
11138   "<vpp-if-name> | sw_if_index <id>")                                   \
11139 _(sw_interface_tap_v2_dump, "")                                         \
11140 _(virtio_pci_create_v2,                                                    \
11141   "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]") \
11142 _(virtio_pci_delete,                                                    \
11143   "<vpp-if-name> | sw_if_index <id>")                                   \
11144 _(sw_interface_virtio_pci_dump, "")                                     \
11145 _(bond_create,                                                          \
11146   "[hw-addr <mac-addr>] {round-robin | active-backup | "                \
11147   "broadcast | {lacp | xor} [load-balance { l2 | l23 | l34 }]} "        \
11148   "[id <if-id>]")                                                       \
11149 _(bond_create2,                                                         \
11150   "[hw-addr <mac-addr>] {mode round-robin | active-backup | "           \
11151   "broadcast | {lacp | xor} [load-balance { l2 | l23 | l34 }]} "        \
11152   "[id <if-id>] [gso]")                                                 \
11153 _(bond_delete,                                                          \
11154   "<vpp-if-name> | sw_if_index <id>")                                   \
11155 _(bond_add_member,                                                      \
11156   "sw_if_index <n> bond <sw_if_index> [is_passive] [is_long_timeout]")  \
11157 _(bond_detach_member,                                                   \
11158   "sw_if_index <n>")                                                    \
11159  _(sw_interface_set_bond_weight, "<intfc> | sw_if_index <nn> weight <value>") \
11160  _(sw_bond_interface_dump, "<intfc> | sw_if_index <nn>")                \
11161  _(sw_member_interface_dump,                                            \
11162   "<vpp-if-name> | sw_if_index <id>")                                   \
11163 _(ip_table_add_del,                                                     \
11164   "table <n> [ipv6] [add | del]\n")                                     \
11165 _(ip_route_add_del,                                                     \
11166   "<addr>/<mask> via <<addr>|<intfc>|sw_if_index <id>|via-label <n>>\n" \
11167   "[table-id <n>] [<intfc> | sw_if_index <id>] [resolve-attempts <n>]\n"\
11168   "[weight <n>] [drop] [local] [classify <n>]  [out-label <n>]\n"       \
11169   "[multipath] [count <n>] [del]")                                      \
11170 _(ip_mroute_add_del,                                                    \
11171   "<src> <grp>/<mask> [table-id <n>]\n"                                 \
11172   "[<intfc> | sw_if_index <id>] [local] [del]")                         \
11173 _(mpls_table_add_del,                                                   \
11174   "table <n> [add | del]\n")                                            \
11175 _(mpls_route_add_del,                                                   \
11176   "<label> <eos> via <addr | next-hop-table <n> | via-label <n> |\n"    \
11177   "lookup-ip4-table <n> | lookup-in-ip6-table <n> |\n"                  \
11178   "l2-input-on <intfc> | l2-input-on sw_if_index <id>>\n"               \
11179   "[<intfc> | sw_if_index <id>] [resolve-attempts <n>] [weight <n>]\n"  \
11180   "[drop] [local] [classify <n>] [out-label <n>] [multipath]\n"         \
11181   "[count <n>] [del]")                                                  \
11182 _(mpls_ip_bind_unbind,                                                  \
11183   "<label> <addr/len>")                                                 \
11184 _(mpls_tunnel_add_del,                                                  \
11185   "[add | del <intfc | sw_if_index <id>>] via <addr | via-label <n>>\n" \
11186   "[<intfc> | sw_if_index <id> | next-hop-table <id>]\n"                \
11187   "[l2-only]  [out-label <n>]")                                         \
11188 _(sr_mpls_policy_add,                                                   \
11189   "bsid <id> [weight <n>] [spray] next <sid> [next <sid>]")             \
11190 _(sr_mpls_policy_del,                                                   \
11191   "bsid <id>")                                                          \
11192 _(sw_interface_set_unnumbered,                                          \
11193   "<intfc> | sw_if_index <id> unnum_if_index <id> [del]")               \
11194 _(create_vlan_subif, "<intfc> | sw_if_index <id> vlan <n>")             \
11195 _(create_subif, "<intfc> | sw_if_index <id> sub_id <n>\n"               \
11196   "[outer_vlan_id <n>][inner_vlan_id <n>]\n"                            \
11197   "[no_tags][one_tag][two_tags][dot1ad][exact_match][default_sub]\n"    \
11198   "[outer_vlan_id_any][inner_vlan_id_any]")                             \
11199 _(ip_table_replace_begin, "table <n> [ipv6]")                           \
11200 _(ip_table_flush, "table <n> [ipv6]")                                   \
11201 _(ip_table_replace_end, "table <n> [ipv6]")                             \
11202 _(set_ip_flow_hash,                                                     \
11203   "vrf <n> [src] [dst] [sport] [dport] [proto] [reverse] [ipv6]")       \
11204 _(sw_interface_ip6_enable_disable,                                      \
11205   "<intfc> | sw_if_index <id> enable | disable")                        \
11206 _(l2_patch_add_del,                                                     \
11207   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
11208   "enable | disable")                                                   \
11209 _(sr_localsid_add_del,                                                  \
11210   "(del) address <addr> next_hop <addr> behavior <beh>\n"               \
11211   "fib-table <num> (end.psp) sw_if_index <num>")                        \
11212 _(get_node_index, "node <node-name")                                    \
11213 _(add_node_next, "node <node-name> next <next-node-name>")              \
11214 _(l2_fib_clear_table, "")                                               \
11215 _(l2_interface_efp_filter, "sw_if_index <nn> enable | disable")         \
11216 _(l2_interface_vlan_tag_rewrite,                                        \
11217   "<intfc> | sw_if_index <nn> \n"                                       \
11218   "[disable][push-[1|2]][pop-[1|2]][translate-1-[1|2]] \n"              \
11219   "[translate-2-[1|2]] [push_dot1q 0] tag1 <nn> tag2 <nn>")             \
11220 _(create_vhost_user_if,                                                 \
11221         "socket <filename> [server] [renumber <dev_instance>] "         \
11222         "[disable_mrg_rxbuf] [disable_indirect_desc] [gso] "            \
11223         "[mac <mac_address>] [packed]")                                 \
11224 _(modify_vhost_user_if,                                                 \
11225         "<intfc> | sw_if_index <nn> socket <filename>\n"                \
11226         "[server] [renumber <dev_instance>] [gso] [packed]")            \
11227 _(create_vhost_user_if_v2,                                              \
11228         "socket <filename> [server] [renumber <dev_instance>] "         \
11229         "[disable_mrg_rxbuf] [disable_indirect_desc] [gso] "            \
11230         "[mac <mac_address>] [packed] [event-idx]")                     \
11231 _(modify_vhost_user_if_v2,                                              \
11232         "<intfc> | sw_if_index <nn> socket <filename>\n"                \
11233         "[server] [renumber <dev_instance>] [gso] [packed] [event-idx]")\
11234 _(delete_vhost_user_if, "<intfc> | sw_if_index <nn>")                   \
11235 _(sw_interface_vhost_user_dump, "<intfc> | sw_if_index <nn>")           \
11236 _(show_version, "")                                                     \
11237 _(show_threads, "")                                                     \
11238 _(l2_fib_table_dump, "bd_id <bridge-domain-id>")                        \
11239 _(interface_name_renumber,                                              \
11240   "<intfc> | sw_if_index <nn> new_show_dev_instance <nn>")              \
11241 _(want_l2_macs_events, "[disable] [learn-limit <n>] [scan-delay <n>] [max-entries <n>]") \
11242 _(ip_address_dump, "(ipv4 | ipv6) (<intfc> | sw_if_index <id>)")        \
11243 _(ip_dump, "ipv4 | ipv6")                                               \
11244 _(delete_loopback,"sw_if_index <nn>")                                   \
11245 _(bd_ip_mac_add_del, "bd_id <bridge-domain-id> <ip4/6-addr> <mac-addr> [del]") \
11246 _(bd_ip_mac_flush, "bd_id <bridge-domain-id>")                          \
11247 _(bd_ip_mac_dump, "[bd_id] <bridge-domain-id>")                         \
11248 _(want_interface_events,  "enable|disable")                             \
11249 _(get_first_msg_id, "client <name>")                                    \
11250 _(get_node_graph, " ")                                                  \
11251 _(sw_interface_clear_stats,"<intfc> | sw_if_index <nn>")                \
11252 _(ioam_enable, "[trace] [pow] [ppc <encap|decap>]")                     \
11253 _(ioam_disable, "")                                                     \
11254 _(af_packet_create, "name <host interface name> [hw_addr <mac>]")       \
11255 _(af_packet_delete, "name <host interface name>")                       \
11256 _(af_packet_dump, "")                                                   \
11257 _(mpls_tunnel_dump, "tunnel_index <tunnel-id>")                         \
11258 _(mpls_table_dump, "")                                                  \
11259 _(mpls_route_dump, "table-id <ID>")                                     \
11260 _(sw_interface_span_enable_disable, "[l2] [src <intfc> | src_sw_if_index <id>] [disable | [[dst <intfc> | dst_sw_if_index <id>] [both|rx|tx]]]") \
11261 _(sw_interface_span_dump, "[l2]")                                           \
11262 _(get_next_index, "node-name <node-name> next-node-name <node-name>")   \
11263 _(ip_source_and_port_range_check_add_del,                               \
11264   "<ip-addr>/<mask> range <nn>-<nn> vrf <id>")                          \
11265 _(ip_source_and_port_range_check_interface_add_del,                     \
11266   "<intf> | sw_if_index <nn> [tcp-out-vrf <id>] [tcp-in-vrf <id>]"      \
11267   "[udp-in-vrf <id>] [udp-out-vrf <id>]")                               \
11268 _(delete_subif,"<intfc> | sw_if_index <nn>")                            \
11269 _(l2_interface_pbb_tag_rewrite,                                         \
11270   "<intfc> | sw_if_index <nn> \n"                                       \
11271   "[disable | push | pop | translate_pbb_stag <outer_tag>] \n"          \
11272   "dmac <mac> smac <mac> sid <nn> [vlanid <nn>]")                       \
11273 _(set_punt, "protocol <l4-protocol> [ip <ver>] [port <l4-port>] [del]")     \
11274 _(ip_table_dump, "")                                                    \
11275 _(ip_route_dump, "table-id [ip4|ip6]")                                  \
11276 _(ip_mtable_dump, "")                                                   \
11277 _(ip_mroute_dump, "table-id [ip4|ip6]")                                 \
11278 _(sw_interface_tag_add_del, "<intfc> | sw_if_index <nn> tag <text>"     \
11279 "[disable]")                                                            \
11280 _(sw_interface_add_del_mac_address, "<intfc> | sw_if_index <nn> "       \
11281   "mac <mac-address> [del]")                                            \
11282 _(l2_xconnect_dump, "")                                                 \
11283 _(hw_interface_set_mtu, "<intfc> | hw_if_index <nn> mtu <nn>")        \
11284 _(sw_interface_get_table, "<intfc> | sw_if_index <id> [ipv6]")          \
11285 _(tcp_configure_src_addresses, "<ip4|6>first-<ip4|6>last [vrf <id>]")   \
11286 _(sock_init_shm, "size <nnn>")                                          \
11287 _(app_namespace_add_del, "[add] id <ns-id> secret <nn> sw_if_index <nn>")\
11288 _(session_rule_add_del, "[add|del] proto <tcp/udp> <lcl-ip>/<plen> "    \
11289   "<lcl-port> <rmt-ip>/<plen> <rmt-port> action <nn>")                  \
11290 _(session_rules_dump, "")                                               \
11291 _(ip_container_proxy_add_del, "[add|del] <address> <sw_if_index>")      \
11292 _(qos_record_enable_disable, "<record-source> <intfc> | sw_if_index <id> [disable]")
11293
11294 /* List of command functions, CLI names map directly to functions */
11295 #define foreach_cli_function                                    \
11296 _(comment, "usage: comment <ignore-rest-of-line>")              \
11297 _(dump_interface_table, "usage: dump_interface_table")          \
11298 _(dump_sub_interface_table, "usage: dump_sub_interface_table")  \
11299 _(dump_ipv4_table, "usage: dump_ipv4_table")                    \
11300 _(dump_ipv6_table, "usage: dump_ipv6_table")                    \
11301 _(dump_macro_table, "usage: dump_macro_table ")                 \
11302 _(dump_node_table, "usage: dump_node_table")                    \
11303 _(dump_msg_api_table, "usage: dump_msg_api_table")              \
11304 _(elog_setup, "usage: elog_setup [nevents, default 128K]")      \
11305 _(elog_disable, "usage: elog_disable")                          \
11306 _(elog_enable, "usage: elog_enable")                            \
11307 _(elog_save, "usage: elog_save <filename>")                     \
11308 _(get_msg_id, "usage: get_msg_id name_and_crc")                 \
11309 _(echo, "usage: echo <message>")                                \
11310 _(exec, "usage: exec <vpe-debug-CLI-command>")                  \
11311 _(exec_inband, "usage: exec_inband <vpe-debug-CLI-command>")    \
11312 _(help, "usage: help")                                          \
11313 _(q, "usage: quit")                                             \
11314 _(quit, "usage: quit")                                          \
11315 _(search_node_table, "usage: search_node_table <name>...")      \
11316 _(set, "usage: set <variable-name> <value>")                    \
11317 _(script, "usage: script <file-name>")                          \
11318 _(statseg, "usage: statseg")                                    \
11319 _(unset, "usage: unset <variable-name>")
11320
11321 #define _(N,n)                                  \
11322     static void vl_api_##n##_t_handler_uni      \
11323     (vl_api_##n##_t * mp)                       \
11324     {                                           \
11325         vat_main_t * vam = &vat_main;           \
11326         if (vam->json_output) {                 \
11327             vl_api_##n##_t_handler_json(mp);    \
11328         } else {                                \
11329             vl_api_##n##_t_handler(mp);         \
11330         }                                       \
11331     }
11332 foreach_vpe_api_reply_msg;
11333 #if VPP_API_TEST_BUILTIN == 0
11334 foreach_standalone_reply_msg;
11335 #endif
11336 #undef _
11337
11338 void
11339 vat_api_hookup (vat_main_t * vam)
11340 {
11341 #define _(N,n)                                                  \
11342     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
11343                            vl_api_##n##_t_handler_uni,          \
11344                            vl_noop_handler,                     \
11345                            vl_api_##n##_t_endian,               \
11346                            vl_api_##n##_t_print,                \
11347                            sizeof(vl_api_##n##_t), 1);
11348   foreach_vpe_api_reply_msg;
11349 #if VPP_API_TEST_BUILTIN == 0
11350   foreach_standalone_reply_msg;
11351 #endif
11352 #undef _
11353
11354 #if (VPP_API_TEST_BUILTIN==0)
11355   vl_msg_api_set_first_available_msg_id (VL_MSG_FIRST_AVAILABLE);
11356
11357   vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
11358
11359   vam->function_by_name = hash_create_string (0, sizeof (uword));
11360
11361   vam->help_by_name = hash_create_string (0, sizeof (uword));
11362 #endif
11363
11364   /* API messages we can send */
11365 #define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
11366   foreach_vpe_api_msg;
11367 #undef _
11368
11369   /* Help strings */
11370 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
11371   foreach_vpe_api_msg;
11372 #undef _
11373
11374   /* CLI functions */
11375 #define _(n,h) hash_set_mem (vam->function_by_name, #n, n);
11376   foreach_cli_function;
11377 #undef _
11378
11379   /* Help strings */
11380 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
11381   foreach_cli_function;
11382 #undef _
11383 }
11384
11385 #if VPP_API_TEST_BUILTIN
11386 static clib_error_t *
11387 vat_api_hookup_shim (vlib_main_t * vm)
11388 {
11389   vat_api_hookup (&vat_main);
11390   return 0;
11391 }
11392
11393 VLIB_API_INIT_FUNCTION (vat_api_hookup_shim);
11394 #endif
11395
11396 /*
11397  * fd.io coding-style-patch-verification: ON
11398  *
11399  * Local Variables:
11400  * eval: (c-set-style "gnu")
11401  * End:
11402  */