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