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