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