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