virtio: 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_create_vlan_subif_reply_t_handler
722   (vl_api_create_vlan_subif_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_create_vlan_subif_reply_t_handler_json
734   (vl_api_create_vlan_subif_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_subif_reply_t_handler
751   (vl_api_create_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_subif_reply_t_handler_json
763   (vl_api_create_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_interface_name_renumber_reply_t_handler
780   (vl_api_interface_name_renumber_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->result_ready = 1;
788 }
789
790 static void vl_api_interface_name_renumber_reply_t_handler_json
791   (vl_api_interface_name_renumber_reply_t * mp)
792 {
793   vat_main_t *vam = &vat_main;
794   vat_json_node_t node;
795
796   vat_json_init_object (&node);
797   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
798
799   vat_json_print (vam->ofp, &node);
800   vat_json_free (&node);
801
802   vam->retval = ntohl (mp->retval);
803   vam->result_ready = 1;
804 }
805
806 /*
807  * Special-case: build the interface table, maintain
808  * the next loopback sw_if_index vbl.
809  */
810 static void vl_api_sw_interface_details_t_handler
811   (vl_api_sw_interface_details_t * mp)
812 {
813   vat_main_t *vam = &vat_main;
814   u8 *s = format (0, "%s%c", mp->interface_name, 0);
815
816   hash_set_mem (vam->sw_if_index_by_interface_name, s,
817                 ntohl (mp->sw_if_index));
818
819   /* In sub interface case, fill the sub interface table entry */
820   if (mp->sw_if_index != mp->sup_sw_if_index)
821     {
822       sw_interface_subif_t *sub = NULL;
823
824       vec_add2 (vam->sw_if_subif_table, sub, 1);
825
826       vec_validate (sub->interface_name, strlen ((char *) s) + 1);
827       strncpy ((char *) sub->interface_name, (char *) s,
828                vec_len (sub->interface_name));
829       sub->sw_if_index = ntohl (mp->sw_if_index);
830       sub->sub_id = ntohl (mp->sub_id);
831
832       sub->raw_flags = ntohl (mp->sub_if_flags & SUB_IF_API_FLAG_MASK_VNET);
833
834       sub->sub_number_of_tags = mp->sub_number_of_tags;
835       sub->sub_outer_vlan_id = ntohs (mp->sub_outer_vlan_id);
836       sub->sub_inner_vlan_id = ntohs (mp->sub_inner_vlan_id);
837
838       /* vlan tag rewrite */
839       sub->vtr_op = ntohl (mp->vtr_op);
840       sub->vtr_push_dot1q = ntohl (mp->vtr_push_dot1q);
841       sub->vtr_tag1 = ntohl (mp->vtr_tag1);
842       sub->vtr_tag2 = ntohl (mp->vtr_tag2);
843     }
844 }
845
846 static void vl_api_sw_interface_details_t_handler_json
847   (vl_api_sw_interface_details_t * mp)
848 {
849   vat_main_t *vam = &vat_main;
850   vat_json_node_t *node = NULL;
851
852   if (VAT_JSON_ARRAY != vam->json_tree.type)
853     {
854       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
855       vat_json_init_array (&vam->json_tree);
856     }
857   node = vat_json_array_add (&vam->json_tree);
858
859   vat_json_init_object (node);
860   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
861   vat_json_object_add_uint (node, "sup_sw_if_index",
862                             ntohl (mp->sup_sw_if_index));
863   vat_json_object_add_bytes (node, "l2_address", mp->l2_address,
864                              sizeof (mp->l2_address));
865   vat_json_object_add_string_copy (node, "interface_name",
866                                    mp->interface_name);
867   vat_json_object_add_string_copy (node, "interface_dev_type",
868                                    mp->interface_dev_type);
869   vat_json_object_add_uint (node, "flags", mp->flags);
870   vat_json_object_add_uint (node, "link_duplex", mp->link_duplex);
871   vat_json_object_add_uint (node, "link_speed", mp->link_speed);
872   vat_json_object_add_uint (node, "mtu", ntohs (mp->link_mtu));
873   vat_json_object_add_uint (node, "sub_id", ntohl (mp->sub_id));
874   vat_json_object_add_uint (node, "sub_number_of_tags",
875                             mp->sub_number_of_tags);
876   vat_json_object_add_uint (node, "sub_outer_vlan_id",
877                             ntohs (mp->sub_outer_vlan_id));
878   vat_json_object_add_uint (node, "sub_inner_vlan_id",
879                             ntohs (mp->sub_inner_vlan_id));
880   vat_json_object_add_uint (node, "sub_if_flags", ntohl (mp->sub_if_flags));
881   vat_json_object_add_uint (node, "vtr_op", ntohl (mp->vtr_op));
882   vat_json_object_add_uint (node, "vtr_push_dot1q",
883                             ntohl (mp->vtr_push_dot1q));
884   vat_json_object_add_uint (node, "vtr_tag1", ntohl (mp->vtr_tag1));
885   vat_json_object_add_uint (node, "vtr_tag2", ntohl (mp->vtr_tag2));
886   if (ntohl (mp->sub_if_flags) & SUB_IF_API_FLAG_DOT1AH)
887     {
888       vat_json_object_add_string_copy (node, "pbb_vtr_dmac",
889                                        format (0, "%U",
890                                                format_ethernet_address,
891                                                &mp->b_dmac));
892       vat_json_object_add_string_copy (node, "pbb_vtr_smac",
893                                        format (0, "%U",
894                                                format_ethernet_address,
895                                                &mp->b_smac));
896       vat_json_object_add_uint (node, "pbb_vtr_b_vlanid", mp->b_vlanid);
897       vat_json_object_add_uint (node, "pbb_vtr_i_sid", mp->i_sid);
898     }
899 }
900
901 #if VPP_API_TEST_BUILTIN == 0
902 static void vl_api_sw_interface_event_t_handler
903   (vl_api_sw_interface_event_t * mp)
904 {
905   vat_main_t *vam = &vat_main;
906   if (vam->interface_event_display)
907     errmsg ("interface flags: sw_if_index %d %s %s",
908             ntohl (mp->sw_if_index),
909             ((ntohl (mp->flags)) & IF_STATUS_API_FLAG_ADMIN_UP) ?
910             "admin-up" : "admin-down",
911             ((ntohl (mp->flags)) & IF_STATUS_API_FLAG_LINK_UP) ?
912             "link-up" : "link-down");
913 }
914 #endif
915
916 __clib_unused static void
917 vl_api_sw_interface_event_t_handler_json (vl_api_sw_interface_event_t * mp)
918 {
919   /* JSON output not supported */
920 }
921
922 static void
923 vl_api_cli_reply_t_handler (vl_api_cli_reply_t * mp)
924 {
925   vat_main_t *vam = &vat_main;
926   i32 retval = ntohl (mp->retval);
927
928   vam->retval = retval;
929   vam->shmem_result = uword_to_pointer (mp->reply_in_shmem, u8 *);
930   vam->result_ready = 1;
931 }
932
933 static void
934 vl_api_cli_reply_t_handler_json (vl_api_cli_reply_t * mp)
935 {
936   vat_main_t *vam = &vat_main;
937   vat_json_node_t node;
938   void *oldheap;
939   u8 *reply;
940
941   vat_json_init_object (&node);
942   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
943   vat_json_object_add_uint (&node, "reply_in_shmem",
944                             ntohl (mp->reply_in_shmem));
945   /* Toss the shared-memory original... */
946   oldheap = vl_msg_push_heap ();
947
948   reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
949   vec_free (reply);
950
951   vl_msg_pop_heap (oldheap);
952
953   vat_json_print (vam->ofp, &node);
954   vat_json_free (&node);
955
956   vam->retval = ntohl (mp->retval);
957   vam->result_ready = 1;
958 }
959
960 static void
961 vl_api_cli_inband_reply_t_handler (vl_api_cli_inband_reply_t * mp)
962 {
963   vat_main_t *vam = &vat_main;
964   i32 retval = ntohl (mp->retval);
965
966   vec_reset_length (vam->cmd_reply);
967
968   vam->retval = retval;
969   if (retval == 0)
970     vam->cmd_reply = vl_api_from_api_to_new_vec (mp, &mp->reply);
971   vam->result_ready = 1;
972 }
973
974 static void
975 vl_api_cli_inband_reply_t_handler_json (vl_api_cli_inband_reply_t * mp)
976 {
977   vat_main_t *vam = &vat_main;
978   vat_json_node_t node;
979   u8 *reply = 0;                /* reply vector */
980
981   reply = vl_api_from_api_to_new_vec (mp, &mp->reply);
982   vec_reset_length (vam->cmd_reply);
983
984   vat_json_init_object (&node);
985   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
986   vat_json_object_add_string_copy (&node, "reply", reply);
987
988   vat_json_print (vam->ofp, &node);
989   vat_json_free (&node);
990   vec_free (reply);
991
992   vam->retval = ntohl (mp->retval);
993   vam->result_ready = 1;
994 }
995
996 static void vl_api_get_node_index_reply_t_handler
997   (vl_api_get_node_index_reply_t * mp)
998 {
999   vat_main_t *vam = &vat_main;
1000   i32 retval = ntohl (mp->retval);
1001   if (vam->async_mode)
1002     {
1003       vam->async_errors += (retval < 0);
1004     }
1005   else
1006     {
1007       vam->retval = retval;
1008       if (retval == 0)
1009         errmsg ("node index %d", ntohl (mp->node_index));
1010       vam->result_ready = 1;
1011     }
1012 }
1013
1014 static void vl_api_get_node_index_reply_t_handler_json
1015   (vl_api_get_node_index_reply_t * mp)
1016 {
1017   vat_main_t *vam = &vat_main;
1018   vat_json_node_t node;
1019
1020   vat_json_init_object (&node);
1021   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1022   vat_json_object_add_uint (&node, "node_index", ntohl (mp->node_index));
1023
1024   vat_json_print (vam->ofp, &node);
1025   vat_json_free (&node);
1026
1027   vam->retval = ntohl (mp->retval);
1028   vam->result_ready = 1;
1029 }
1030
1031 static void vl_api_get_next_index_reply_t_handler
1032   (vl_api_get_next_index_reply_t * mp)
1033 {
1034   vat_main_t *vam = &vat_main;
1035   i32 retval = ntohl (mp->retval);
1036   if (vam->async_mode)
1037     {
1038       vam->async_errors += (retval < 0);
1039     }
1040   else
1041     {
1042       vam->retval = retval;
1043       if (retval == 0)
1044         errmsg ("next node index %d", ntohl (mp->next_index));
1045       vam->result_ready = 1;
1046     }
1047 }
1048
1049 static void vl_api_get_next_index_reply_t_handler_json
1050   (vl_api_get_next_index_reply_t * mp)
1051 {
1052   vat_main_t *vam = &vat_main;
1053   vat_json_node_t node;
1054
1055   vat_json_init_object (&node);
1056   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1057   vat_json_object_add_uint (&node, "next_index", ntohl (mp->next_index));
1058
1059   vat_json_print (vam->ofp, &node);
1060   vat_json_free (&node);
1061
1062   vam->retval = ntohl (mp->retval);
1063   vam->result_ready = 1;
1064 }
1065
1066 static void vl_api_add_node_next_reply_t_handler
1067   (vl_api_add_node_next_reply_t * mp)
1068 {
1069   vat_main_t *vam = &vat_main;
1070   i32 retval = ntohl (mp->retval);
1071   if (vam->async_mode)
1072     {
1073       vam->async_errors += (retval < 0);
1074     }
1075   else
1076     {
1077       vam->retval = retval;
1078       if (retval == 0)
1079         errmsg ("next index %d", ntohl (mp->next_index));
1080       vam->result_ready = 1;
1081     }
1082 }
1083
1084 static void vl_api_add_node_next_reply_t_handler_json
1085   (vl_api_add_node_next_reply_t * mp)
1086 {
1087   vat_main_t *vam = &vat_main;
1088   vat_json_node_t node;
1089
1090   vat_json_init_object (&node);
1091   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1092   vat_json_object_add_uint (&node, "next_index", ntohl (mp->next_index));
1093
1094   vat_json_print (vam->ofp, &node);
1095   vat_json_free (&node);
1096
1097   vam->retval = ntohl (mp->retval);
1098   vam->result_ready = 1;
1099 }
1100
1101 static void vl_api_show_version_reply_t_handler
1102   (vl_api_show_version_reply_t * mp)
1103 {
1104   vat_main_t *vam = &vat_main;
1105   i32 retval = ntohl (mp->retval);
1106
1107   if (retval >= 0)
1108     {
1109       errmsg ("        program: %s", mp->program);
1110       errmsg ("        version: %s", mp->version);
1111       errmsg ("     build date: %s", mp->build_date);
1112       errmsg ("build directory: %s", mp->build_directory);
1113     }
1114   vam->retval = retval;
1115   vam->result_ready = 1;
1116 }
1117
1118 static void vl_api_show_version_reply_t_handler_json
1119   (vl_api_show_version_reply_t * mp)
1120 {
1121   vat_main_t *vam = &vat_main;
1122   vat_json_node_t node;
1123
1124   vat_json_init_object (&node);
1125   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1126   vat_json_object_add_string_copy (&node, "program", mp->program);
1127   vat_json_object_add_string_copy (&node, "version", mp->version);
1128   vat_json_object_add_string_copy (&node, "build_date", mp->build_date);
1129   vat_json_object_add_string_copy (&node, "build_directory",
1130                                    mp->build_directory);
1131
1132   vat_json_print (vam->ofp, &node);
1133   vat_json_free (&node);
1134
1135   vam->retval = ntohl (mp->retval);
1136   vam->result_ready = 1;
1137 }
1138
1139 static void vl_api_show_threads_reply_t_handler
1140   (vl_api_show_threads_reply_t * mp)
1141 {
1142   vat_main_t *vam = &vat_main;
1143   i32 retval = ntohl (mp->retval);
1144   int i, count = 0;
1145
1146   if (retval >= 0)
1147     count = ntohl (mp->count);
1148
1149   for (i = 0; i < count; i++)
1150     print (vam->ofp,
1151            "\n%-2d %-11s %-11s %-5d %-6d %-4d %-6d",
1152            ntohl (mp->thread_data[i].id), mp->thread_data[i].name,
1153            mp->thread_data[i].type, ntohl (mp->thread_data[i].pid),
1154            ntohl (mp->thread_data[i].cpu_id), ntohl (mp->thread_data[i].core),
1155            ntohl (mp->thread_data[i].cpu_socket));
1156
1157   vam->retval = retval;
1158   vam->result_ready = 1;
1159 }
1160
1161 static void vl_api_show_threads_reply_t_handler_json
1162   (vl_api_show_threads_reply_t * mp)
1163 {
1164   vat_main_t *vam = &vat_main;
1165   vat_json_node_t node;
1166   vl_api_thread_data_t *td;
1167   i32 retval = ntohl (mp->retval);
1168   int i, count = 0;
1169
1170   if (retval >= 0)
1171     count = ntohl (mp->count);
1172
1173   vat_json_init_object (&node);
1174   vat_json_object_add_int (&node, "retval", retval);
1175   vat_json_object_add_uint (&node, "count", count);
1176
1177   for (i = 0; i < count; i++)
1178     {
1179       td = &mp->thread_data[i];
1180       vat_json_object_add_uint (&node, "id", ntohl (td->id));
1181       vat_json_object_add_string_copy (&node, "name", td->name);
1182       vat_json_object_add_string_copy (&node, "type", td->type);
1183       vat_json_object_add_uint (&node, "pid", ntohl (td->pid));
1184       vat_json_object_add_int (&node, "cpu_id", ntohl (td->cpu_id));
1185       vat_json_object_add_int (&node, "core", ntohl (td->id));
1186       vat_json_object_add_int (&node, "cpu_socket", ntohl (td->cpu_socket));
1187     }
1188
1189   vat_json_print (vam->ofp, &node);
1190   vat_json_free (&node);
1191
1192   vam->retval = retval;
1193   vam->result_ready = 1;
1194 }
1195
1196 static int
1197 api_show_threads (vat_main_t * vam)
1198 {
1199   vl_api_show_threads_t *mp;
1200   int ret;
1201
1202   print (vam->ofp,
1203          "\n%-2s %-11s %-11s %-5s %-6s %-4s %-6s",
1204          "ID", "Name", "Type", "LWP", "cpu_id", "Core", "Socket");
1205
1206   M (SHOW_THREADS, mp);
1207
1208   S (mp);
1209   W (ret);
1210   return ret;
1211 }
1212
1213 static void
1214 vl_api_l2_macs_event_t_handler (vl_api_l2_macs_event_t * mp)
1215 {
1216   u32 n_macs = ntohl (mp->n_macs);
1217   errmsg ("L2MAC event received with pid %d cl-idx %d for %d macs: \n",
1218           ntohl (mp->pid), mp->client_index, n_macs);
1219   int i;
1220   for (i = 0; i < n_macs; i++)
1221     {
1222       vl_api_mac_entry_t *mac = &mp->mac[i];
1223       errmsg (" [%d] sw_if_index %d  mac_addr %U  action %d \n",
1224               i + 1, ntohl (mac->sw_if_index),
1225               format_ethernet_address, mac->mac_addr, mac->action);
1226       if (i == 1000)
1227         break;
1228     }
1229 }
1230
1231 static void
1232 vl_api_l2_macs_event_t_handler_json (vl_api_l2_macs_event_t * mp)
1233 {
1234   /* JSON output not supported */
1235 }
1236
1237 #define vl_api_bridge_domain_details_t_endian vl_noop_handler
1238 #define vl_api_bridge_domain_details_t_print vl_noop_handler
1239
1240 /*
1241  * Special-case: build the bridge domain table, maintain
1242  * the next bd id vbl.
1243  */
1244 static void vl_api_bridge_domain_details_t_handler
1245   (vl_api_bridge_domain_details_t * mp)
1246 {
1247   vat_main_t *vam = &vat_main;
1248   u32 n_sw_ifs = ntohl (mp->n_sw_ifs);
1249   int i;
1250
1251   print (vam->ofp, "\n%-3s %-3s %-3s %-3s %-3s %-6s %-3s",
1252          " ID", "LRN", "FWD", "FLD", "BVI", "UU-FWD", "#IF");
1253
1254   print (vam->ofp, "%3d %3d %3d %3d %3d %6d %3d",
1255          ntohl (mp->bd_id), mp->learn, mp->forward,
1256          mp->flood, ntohl (mp->bvi_sw_if_index),
1257          ntohl (mp->uu_fwd_sw_if_index), n_sw_ifs);
1258
1259   if (n_sw_ifs)
1260     {
1261       vl_api_bridge_domain_sw_if_t *sw_ifs;
1262       print (vam->ofp, "\n\n%s %s  %s", "sw_if_index", "SHG",
1263              "Interface Name");
1264
1265       sw_ifs = mp->sw_if_details;
1266       for (i = 0; i < n_sw_ifs; i++)
1267         {
1268           u8 *sw_if_name = 0;
1269           u32 sw_if_index;
1270           hash_pair_t *p;
1271
1272           sw_if_index = ntohl (sw_ifs->sw_if_index);
1273
1274           /* *INDENT-OFF* */
1275           hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
1276                              ({
1277                                if ((u32) p->value[0] == sw_if_index)
1278                                  {
1279                                    sw_if_name = (u8 *)(p->key);
1280                                    break;
1281                                  }
1282                              }));
1283           /* *INDENT-ON* */
1284           print (vam->ofp, "%7d     %3d  %s", sw_if_index,
1285                  sw_ifs->shg, sw_if_name ? (char *) sw_if_name :
1286                  "sw_if_index not found!");
1287
1288           sw_ifs++;
1289         }
1290     }
1291 }
1292
1293 static void vl_api_bridge_domain_details_t_handler_json
1294   (vl_api_bridge_domain_details_t * mp)
1295 {
1296   vat_main_t *vam = &vat_main;
1297   vat_json_node_t *node, *array = NULL;
1298   u32 n_sw_ifs = ntohl (mp->n_sw_ifs);
1299
1300   if (VAT_JSON_ARRAY != vam->json_tree.type)
1301     {
1302       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
1303       vat_json_init_array (&vam->json_tree);
1304     }
1305   node = vat_json_array_add (&vam->json_tree);
1306
1307   vat_json_init_object (node);
1308   vat_json_object_add_uint (node, "bd_id", ntohl (mp->bd_id));
1309   vat_json_object_add_uint (node, "flood", mp->flood);
1310   vat_json_object_add_uint (node, "forward", mp->forward);
1311   vat_json_object_add_uint (node, "learn", mp->learn);
1312   vat_json_object_add_uint (node, "bvi_sw_if_index",
1313                             ntohl (mp->bvi_sw_if_index));
1314   vat_json_object_add_uint (node, "n_sw_ifs", n_sw_ifs);
1315   array = vat_json_object_add (node, "sw_if");
1316   vat_json_init_array (array);
1317
1318
1319
1320   if (n_sw_ifs)
1321     {
1322       vl_api_bridge_domain_sw_if_t *sw_ifs;
1323       int i;
1324
1325       sw_ifs = mp->sw_if_details;
1326       for (i = 0; i < n_sw_ifs; i++)
1327         {
1328           node = vat_json_array_add (array);
1329           vat_json_init_object (node);
1330           vat_json_object_add_uint (node, "sw_if_index",
1331                                     ntohl (sw_ifs->sw_if_index));
1332           vat_json_object_add_uint (node, "shg", sw_ifs->shg);
1333           sw_ifs++;
1334         }
1335     }
1336 }
1337
1338 static void vl_api_control_ping_reply_t_handler
1339   (vl_api_control_ping_reply_t * mp)
1340 {
1341   vat_main_t *vam = &vat_main;
1342   i32 retval = ntohl (mp->retval);
1343   if (vam->async_mode)
1344     {
1345       vam->async_errors += (retval < 0);
1346     }
1347   else
1348     {
1349       vam->retval = retval;
1350       vam->result_ready = 1;
1351     }
1352   if (vam->socket_client_main)
1353     vam->socket_client_main->control_pings_outstanding--;
1354 }
1355
1356 static void vl_api_control_ping_reply_t_handler_json
1357   (vl_api_control_ping_reply_t * mp)
1358 {
1359   vat_main_t *vam = &vat_main;
1360   i32 retval = ntohl (mp->retval);
1361
1362   if (VAT_JSON_NONE != vam->json_tree.type)
1363     {
1364       vat_json_print (vam->ofp, &vam->json_tree);
1365       vat_json_free (&vam->json_tree);
1366       vam->json_tree.type = VAT_JSON_NONE;
1367     }
1368   else
1369     {
1370       /* just print [] */
1371       vat_json_init_array (&vam->json_tree);
1372       vat_json_print (vam->ofp, &vam->json_tree);
1373       vam->json_tree.type = VAT_JSON_NONE;
1374     }
1375
1376   vam->retval = retval;
1377   vam->result_ready = 1;
1378 }
1379
1380 static void
1381   vl_api_bridge_domain_set_mac_age_reply_t_handler
1382   (vl_api_bridge_domain_set_mac_age_reply_t * mp)
1383 {
1384   vat_main_t *vam = &vat_main;
1385   i32 retval = ntohl (mp->retval);
1386   if (vam->async_mode)
1387     {
1388       vam->async_errors += (retval < 0);
1389     }
1390   else
1391     {
1392       vam->retval = retval;
1393       vam->result_ready = 1;
1394     }
1395 }
1396
1397 static void vl_api_bridge_domain_set_mac_age_reply_t_handler_json
1398   (vl_api_bridge_domain_set_mac_age_reply_t * mp)
1399 {
1400   vat_main_t *vam = &vat_main;
1401   vat_json_node_t node;
1402
1403   vat_json_init_object (&node);
1404   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1405
1406   vat_json_print (vam->ofp, &node);
1407   vat_json_free (&node);
1408
1409   vam->retval = ntohl (mp->retval);
1410   vam->result_ready = 1;
1411 }
1412
1413 static void
1414 vl_api_l2_flags_reply_t_handler (vl_api_l2_flags_reply_t * mp)
1415 {
1416   vat_main_t *vam = &vat_main;
1417   i32 retval = ntohl (mp->retval);
1418   if (vam->async_mode)
1419     {
1420       vam->async_errors += (retval < 0);
1421     }
1422   else
1423     {
1424       vam->retval = retval;
1425       vam->result_ready = 1;
1426     }
1427 }
1428
1429 static void vl_api_l2_flags_reply_t_handler_json
1430   (vl_api_l2_flags_reply_t * mp)
1431 {
1432   vat_main_t *vam = &vat_main;
1433   vat_json_node_t node;
1434
1435   vat_json_init_object (&node);
1436   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1437   vat_json_object_add_uint (&node, "resulting_feature_bitmap",
1438                             ntohl (mp->resulting_feature_bitmap));
1439
1440   vat_json_print (vam->ofp, &node);
1441   vat_json_free (&node);
1442
1443   vam->retval = ntohl (mp->retval);
1444   vam->result_ready = 1;
1445 }
1446
1447 static void vl_api_bridge_flags_reply_t_handler
1448   (vl_api_bridge_flags_reply_t * mp)
1449 {
1450   vat_main_t *vam = &vat_main;
1451   i32 retval = ntohl (mp->retval);
1452   if (vam->async_mode)
1453     {
1454       vam->async_errors += (retval < 0);
1455     }
1456   else
1457     {
1458       vam->retval = retval;
1459       vam->result_ready = 1;
1460     }
1461 }
1462
1463 static void vl_api_bridge_flags_reply_t_handler_json
1464   (vl_api_bridge_flags_reply_t * mp)
1465 {
1466   vat_main_t *vam = &vat_main;
1467   vat_json_node_t node;
1468
1469   vat_json_init_object (&node);
1470   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1471   vat_json_object_add_uint (&node, "resulting_feature_bitmap",
1472                             ntohl (mp->resulting_feature_bitmap));
1473
1474   vat_json_print (vam->ofp, &node);
1475   vat_json_free (&node);
1476
1477   vam->retval = ntohl (mp->retval);
1478   vam->result_ready = 1;
1479 }
1480
1481 static void vl_api_ip_address_details_t_handler
1482   (vl_api_ip_address_details_t * mp)
1483 {
1484   vat_main_t *vam = &vat_main;
1485   static ip_address_details_t empty_ip_address_details = { {0} };
1486   ip_address_details_t *address = NULL;
1487   ip_details_t *current_ip_details = NULL;
1488   ip_details_t *details = NULL;
1489
1490   details = vam->ip_details_by_sw_if_index[vam->is_ipv6];
1491
1492   if (!details || vam->current_sw_if_index >= vec_len (details)
1493       || !details[vam->current_sw_if_index].present)
1494     {
1495       errmsg ("ip address details arrived but not stored");
1496       errmsg ("ip_dump should be called first");
1497       return;
1498     }
1499
1500   current_ip_details = vec_elt_at_index (details, vam->current_sw_if_index);
1501
1502 #define addresses (current_ip_details->addr)
1503
1504   vec_validate_init_empty (addresses, vec_len (addresses),
1505                            empty_ip_address_details);
1506
1507   address = vec_elt_at_index (addresses, vec_len (addresses) - 1);
1508
1509   clib_memcpy (&address->ip, &mp->prefix.address.un, sizeof (address->ip));
1510   address->prefix_length = mp->prefix.len;
1511 #undef addresses
1512 }
1513
1514 static void vl_api_ip_address_details_t_handler_json
1515   (vl_api_ip_address_details_t * mp)
1516 {
1517   vat_main_t *vam = &vat_main;
1518   vat_json_node_t *node = NULL;
1519
1520   if (VAT_JSON_ARRAY != vam->json_tree.type)
1521     {
1522       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
1523       vat_json_init_array (&vam->json_tree);
1524     }
1525   node = vat_json_array_add (&vam->json_tree);
1526
1527   vat_json_init_object (node);
1528   vat_json_object_add_prefix (node, &mp->prefix);
1529 }
1530
1531 static void
1532 vl_api_ip_details_t_handler (vl_api_ip_details_t * mp)
1533 {
1534   vat_main_t *vam = &vat_main;
1535   static ip_details_t empty_ip_details = { 0 };
1536   ip_details_t *ip = NULL;
1537   u32 sw_if_index = ~0;
1538
1539   sw_if_index = ntohl (mp->sw_if_index);
1540
1541   vec_validate_init_empty (vam->ip_details_by_sw_if_index[vam->is_ipv6],
1542                            sw_if_index, empty_ip_details);
1543
1544   ip = vec_elt_at_index (vam->ip_details_by_sw_if_index[vam->is_ipv6],
1545                          sw_if_index);
1546
1547   ip->present = 1;
1548 }
1549
1550 static void
1551 vl_api_ip_details_t_handler_json (vl_api_ip_details_t * mp)
1552 {
1553   vat_main_t *vam = &vat_main;
1554
1555   if (VAT_JSON_ARRAY != vam->json_tree.type)
1556     {
1557       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
1558       vat_json_init_array (&vam->json_tree);
1559     }
1560   vat_json_array_add_uint (&vam->json_tree,
1561                            clib_net_to_host_u32 (mp->sw_if_index));
1562 }
1563
1564 static void vl_api_get_first_msg_id_reply_t_handler
1565   (vl_api_get_first_msg_id_reply_t * mp)
1566 {
1567   vat_main_t *vam = &vat_main;
1568   i32 retval = ntohl (mp->retval);
1569
1570   if (vam->async_mode)
1571     {
1572       vam->async_errors += (retval < 0);
1573     }
1574   else
1575     {
1576       vam->retval = retval;
1577       vam->result_ready = 1;
1578     }
1579   if (retval >= 0)
1580     {
1581       errmsg ("first message id %d", ntohs (mp->first_msg_id));
1582     }
1583 }
1584
1585 static void vl_api_get_first_msg_id_reply_t_handler_json
1586   (vl_api_get_first_msg_id_reply_t * mp)
1587 {
1588   vat_main_t *vam = &vat_main;
1589   vat_json_node_t node;
1590
1591   vat_json_init_object (&node);
1592   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1593   vat_json_object_add_uint (&node, "first_msg_id",
1594                             (uint) ntohs (mp->first_msg_id));
1595
1596   vat_json_print (vam->ofp, &node);
1597   vat_json_free (&node);
1598
1599   vam->retval = ntohl (mp->retval);
1600   vam->result_ready = 1;
1601 }
1602
1603 static void vl_api_get_node_graph_reply_t_handler
1604   (vl_api_get_node_graph_reply_t * mp)
1605 {
1606   vat_main_t *vam = &vat_main;
1607   i32 retval = ntohl (mp->retval);
1608   u8 *pvt_copy, *reply;
1609   void *oldheap;
1610   vlib_node_t *node;
1611   int i;
1612
1613   if (vam->async_mode)
1614     {
1615       vam->async_errors += (retval < 0);
1616     }
1617   else
1618     {
1619       vam->retval = retval;
1620       vam->result_ready = 1;
1621     }
1622
1623   /* "Should never happen..." */
1624   if (retval != 0)
1625     return;
1626
1627   reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
1628   pvt_copy = vec_dup (reply);
1629
1630   /* Toss the shared-memory original... */
1631   oldheap = vl_msg_push_heap ();
1632
1633   vec_free (reply);
1634
1635   vl_msg_pop_heap (oldheap);
1636
1637   if (vam->graph_nodes)
1638     {
1639       hash_free (vam->graph_node_index_by_name);
1640
1641       for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
1642         {
1643           node = vam->graph_nodes[0][i];
1644           vec_free (node->name);
1645           vec_free (node->next_nodes);
1646           vec_free (node);
1647         }
1648       vec_free (vam->graph_nodes[0]);
1649       vec_free (vam->graph_nodes);
1650     }
1651
1652   vam->graph_node_index_by_name = hash_create_string (0, sizeof (uword));
1653   vam->graph_nodes = vlib_node_unserialize (pvt_copy);
1654   vec_free (pvt_copy);
1655
1656   for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
1657     {
1658       node = vam->graph_nodes[0][i];
1659       hash_set_mem (vam->graph_node_index_by_name, node->name, i);
1660     }
1661 }
1662
1663 static void vl_api_get_node_graph_reply_t_handler_json
1664   (vl_api_get_node_graph_reply_t * mp)
1665 {
1666   vat_main_t *vam = &vat_main;
1667   void *oldheap;
1668   vat_json_node_t node;
1669   u8 *reply;
1670
1671   /* $$$$ make this real? */
1672   vat_json_init_object (&node);
1673   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1674   vat_json_object_add_uint (&node, "reply_in_shmem", mp->reply_in_shmem);
1675
1676   reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
1677
1678   /* Toss the shared-memory original... */
1679   oldheap = vl_msg_push_heap ();
1680
1681   vec_free (reply);
1682
1683   vl_msg_pop_heap (oldheap);
1684
1685   vat_json_print (vam->ofp, &node);
1686   vat_json_free (&node);
1687
1688   vam->retval = ntohl (mp->retval);
1689   vam->result_ready = 1;
1690 }
1691
1692 /* Format hex dump. */
1693 u8 *
1694 format_hex_bytes (u8 * s, va_list * va)
1695 {
1696   u8 *bytes = va_arg (*va, u8 *);
1697   int n_bytes = va_arg (*va, int);
1698   uword i;
1699
1700   /* Print short or long form depending on byte count. */
1701   uword short_form = n_bytes <= 32;
1702   u32 indent = format_get_indent (s);
1703
1704   if (n_bytes == 0)
1705     return s;
1706
1707   for (i = 0; i < n_bytes; i++)
1708     {
1709       if (!short_form && (i % 32) == 0)
1710         s = format (s, "%08x: ", i);
1711       s = format (s, "%02x", bytes[i]);
1712       if (!short_form && ((i + 1) % 32) == 0 && (i + 1) < n_bytes)
1713         s = format (s, "\n%U", format_white_space, indent);
1714     }
1715
1716   return s;
1717 }
1718
1719 /*
1720  * Generate boilerplate reply handlers, which
1721  * dig the return value out of the xxx_reply_t API message,
1722  * stick it into vam->retval, and set vam->result_ready
1723  *
1724  * Could also do this by pointing N message decode slots at
1725  * a single function, but that could break in subtle ways.
1726  */
1727
1728 #define foreach_standard_reply_retval_handler           \
1729 _(sw_interface_set_flags_reply)                         \
1730 _(sw_interface_add_del_address_reply)                   \
1731 _(sw_interface_set_rx_mode_reply)                       \
1732 _(sw_interface_set_rx_placement_reply)                  \
1733 _(sw_interface_set_table_reply)                         \
1734 _(sw_interface_set_vpath_reply)                         \
1735 _(sw_interface_set_l2_bridge_reply)                     \
1736 _(bridge_domain_add_del_reply)                          \
1737 _(sw_interface_set_l2_xconnect_reply)                   \
1738 _(l2fib_add_del_reply)                                  \
1739 _(l2fib_flush_int_reply)                                \
1740 _(l2fib_flush_bd_reply)                                 \
1741 _(ip_route_add_del_reply)                               \
1742 _(ip_table_add_del_reply)                               \
1743 _(ip_table_replace_begin_reply)                         \
1744 _(ip_table_flush_reply)                                 \
1745 _(ip_table_replace_end_reply)                           \
1746 _(ip_mroute_add_del_reply)                              \
1747 _(sw_interface_set_unnumbered_reply)                    \
1748 _(set_ip_flow_hash_reply)                               \
1749 _(sw_interface_ip6_enable_disable_reply)                \
1750 _(l2_patch_add_del_reply)                               \
1751 _(l2_fib_clear_table_reply)                             \
1752 _(l2_interface_efp_filter_reply)                        \
1753 _(l2_interface_vlan_tag_rewrite_reply)                  \
1754 _(want_l2_macs_events_reply)                            \
1755 _(delete_loopback_reply)                                \
1756 _(bd_ip_mac_add_del_reply)                              \
1757 _(bd_ip_mac_flush_reply)                                \
1758 _(want_interface_events_reply)                          \
1759 _(sw_interface_clear_stats_reply)                       \
1760 _(ioam_enable_reply)                                    \
1761 _(ioam_disable_reply)                                   \
1762 _(ip_source_and_port_range_check_add_del_reply)         \
1763 _(ip_source_and_port_range_check_interface_add_del_reply)\
1764 _(delete_subif_reply)                                   \
1765 _(l2_interface_pbb_tag_rewrite_reply)                   \
1766 _(sw_interface_tag_add_del_reply)                       \
1767 _(sw_interface_add_del_mac_address_reply)               \
1768 _(hw_interface_set_mtu_reply)                           \
1769 _(session_rule_add_del_reply)                           \
1770 _(ip_container_proxy_add_del_reply)                     \
1771
1772 #define _(n)                                    \
1773     static void vl_api_##n##_t_handler          \
1774     (vl_api_##n##_t * mp)                       \
1775     {                                           \
1776         vat_main_t * vam = &vat_main;           \
1777         i32 retval = ntohl(mp->retval);         \
1778         if (vam->async_mode) {                  \
1779             vam->async_errors += (retval < 0);  \
1780         } else {                                \
1781             vam->retval = retval;               \
1782             vam->result_ready = 1;              \
1783         }                                       \
1784     }
1785 foreach_standard_reply_retval_handler;
1786 #undef _
1787
1788 #define _(n)                                    \
1789     static void vl_api_##n##_t_handler_json     \
1790     (vl_api_##n##_t * mp)                       \
1791     {                                           \
1792         vat_main_t * vam = &vat_main;           \
1793         vat_json_node_t node;                   \
1794         vat_json_init_object(&node);            \
1795         vat_json_object_add_int(&node, "retval", ntohl(mp->retval));    \
1796         vat_json_print(vam->ofp, &node);        \
1797         vam->retval = ntohl(mp->retval);        \
1798         vam->result_ready = 1;                  \
1799     }
1800 foreach_standard_reply_retval_handler;
1801 #undef _
1802
1803 /*
1804  * Table of message reply handlers, must include boilerplate handlers
1805  * we just generated
1806  */
1807
1808 #define foreach_vpe_api_reply_msg                                       \
1809 _(CREATE_LOOPBACK_REPLY, create_loopback_reply)                         \
1810 _(CREATE_LOOPBACK_INSTANCE_REPLY, create_loopback_instance_reply)       \
1811 _(SW_INTERFACE_DETAILS, sw_interface_details)                           \
1812 _(SW_INTERFACE_SET_FLAGS_REPLY, sw_interface_set_flags_reply)           \
1813 _(CONTROL_PING_REPLY, control_ping_reply)                               \
1814 _(CLI_REPLY, cli_reply)                                                 \
1815 _(CLI_INBAND_REPLY, cli_inband_reply)                                   \
1816 _(SW_INTERFACE_ADD_DEL_ADDRESS_REPLY,                                   \
1817   sw_interface_add_del_address_reply)                                   \
1818 _(SW_INTERFACE_SET_RX_MODE_REPLY, sw_interface_set_rx_mode_reply)       \
1819 _(SW_INTERFACE_SET_RX_PLACEMENT_REPLY, sw_interface_set_rx_placement_reply)     \
1820 _(SW_INTERFACE_RX_PLACEMENT_DETAILS, sw_interface_rx_placement_details) \
1821 _(SW_INTERFACE_SET_TABLE_REPLY, sw_interface_set_table_reply)           \
1822 _(SW_INTERFACE_SET_VPATH_REPLY, sw_interface_set_vpath_reply)           \
1823 _(SW_INTERFACE_SET_L2_XCONNECT_REPLY,                                   \
1824   sw_interface_set_l2_xconnect_reply)                                   \
1825 _(SW_INTERFACE_SET_L2_BRIDGE_REPLY,                                     \
1826   sw_interface_set_l2_bridge_reply)                                     \
1827 _(BRIDGE_DOMAIN_ADD_DEL_REPLY, bridge_domain_add_del_reply)             \
1828 _(BRIDGE_DOMAIN_DETAILS, bridge_domain_details)                         \
1829 _(BRIDGE_DOMAIN_SET_MAC_AGE_REPLY, bridge_domain_set_mac_age_reply)     \
1830 _(L2FIB_ADD_DEL_REPLY, l2fib_add_del_reply)                             \
1831 _(L2FIB_FLUSH_INT_REPLY, l2fib_flush_int_reply)                         \
1832 _(L2FIB_FLUSH_BD_REPLY, l2fib_flush_bd_reply)                           \
1833 _(L2_FLAGS_REPLY, l2_flags_reply)                                       \
1834 _(BRIDGE_FLAGS_REPLY, bridge_flags_reply)                               \
1835 _(IP_ROUTE_ADD_DEL_REPLY, ip_route_add_del_reply)                       \
1836 _(IP_TABLE_ADD_DEL_REPLY, ip_table_add_del_reply)                       \
1837 _(IP_TABLE_REPLACE_BEGIN_REPLY, ip_table_replace_begin_reply)           \
1838 _(IP_TABLE_FLUSH_REPLY, ip_table_flush_reply)                           \
1839 _(IP_TABLE_REPLACE_END_REPLY, ip_table_replace_end_reply)               \
1840 _(IP_MROUTE_ADD_DEL_REPLY, ip_mroute_add_del_reply)                     \
1841 _(SW_INTERFACE_SET_UNNUMBERED_REPLY,                                    \
1842   sw_interface_set_unnumbered_reply)                                    \
1843 _(CREATE_VLAN_SUBIF_REPLY, create_vlan_subif_reply)                     \
1844 _(CREATE_SUBIF_REPLY, create_subif_reply)                               \
1845 _(SET_IP_FLOW_HASH_REPLY, set_ip_flow_hash_reply)                       \
1846 _(SW_INTERFACE_IP6_ENABLE_DISABLE_REPLY,                                \
1847   sw_interface_ip6_enable_disable_reply)                                \
1848 _(L2_PATCH_ADD_DEL_REPLY, l2_patch_add_del_reply)                       \
1849 _(GET_NODE_INDEX_REPLY, get_node_index_reply)                           \
1850 _(ADD_NODE_NEXT_REPLY, add_node_next_reply)                             \
1851 _(L2_FIB_CLEAR_TABLE_REPLY, l2_fib_clear_table_reply)                   \
1852 _(L2_INTERFACE_EFP_FILTER_REPLY, l2_interface_efp_filter_reply)         \
1853 _(L2_INTERFACE_VLAN_TAG_REWRITE_REPLY, l2_interface_vlan_tag_rewrite_reply) \
1854 _(SHOW_VERSION_REPLY, show_version_reply)                               \
1855 _(SHOW_THREADS_REPLY, show_threads_reply)                               \
1856 _(L2_FIB_TABLE_DETAILS, l2_fib_table_details)                           \
1857 _(INTERFACE_NAME_RENUMBER_REPLY, interface_name_renumber_reply)         \
1858 _(WANT_L2_MACS_EVENTS_REPLY, want_l2_macs_events_reply)                 \
1859 _(L2_MACS_EVENT, l2_macs_event)                                         \
1860 _(IP_ADDRESS_DETAILS, ip_address_details)                               \
1861 _(IP_DETAILS, ip_details)                                               \
1862 _(DELETE_LOOPBACK_REPLY, delete_loopback_reply)                         \
1863 _(BD_IP_MAC_ADD_DEL_REPLY, bd_ip_mac_add_del_reply)                     \
1864 _(BD_IP_MAC_FLUSH_REPLY, bd_ip_mac_flush_reply)                         \
1865 _(BD_IP_MAC_DETAILS, bd_ip_mac_details)                                 \
1866 _(WANT_INTERFACE_EVENTS_REPLY, want_interface_events_reply)             \
1867 _(GET_FIRST_MSG_ID_REPLY, get_first_msg_id_reply)                       \
1868 _(GET_NODE_GRAPH_REPLY, get_node_graph_reply)                           \
1869 _(SW_INTERFACE_CLEAR_STATS_REPLY, sw_interface_clear_stats_reply)      \
1870 _(IOAM_ENABLE_REPLY, ioam_enable_reply)                   \
1871 _(IOAM_DISABLE_REPLY, ioam_disable_reply)                     \
1872 _(GET_NEXT_INDEX_REPLY, get_next_index_reply)                           \
1873 _(IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL_REPLY,                         \
1874  ip_source_and_port_range_check_add_del_reply)                          \
1875 _(IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL_REPLY,               \
1876  ip_source_and_port_range_check_interface_add_del_reply)                \
1877 _(DELETE_SUBIF_REPLY, delete_subif_reply)                               \
1878 _(L2_INTERFACE_PBB_TAG_REWRITE_REPLY, l2_interface_pbb_tag_rewrite_reply) \
1879 _(IP_TABLE_DETAILS, ip_table_details)                                   \
1880 _(IP_ROUTE_DETAILS, ip_route_details)                                   \
1881 _(SW_INTERFACE_TAG_ADD_DEL_REPLY, sw_interface_tag_add_del_reply)       \
1882 _(SW_INTERFACE_ADD_DEL_MAC_ADDRESS_REPLY, sw_interface_add_del_mac_address_reply) \
1883 _(L2_XCONNECT_DETAILS, l2_xconnect_details)                             \
1884 _(HW_INTERFACE_SET_MTU_REPLY, hw_interface_set_mtu_reply)               \
1885 _(SW_INTERFACE_GET_TABLE_REPLY, sw_interface_get_table_reply)           \
1886 _(APP_NAMESPACE_ADD_DEL_REPLY, app_namespace_add_del_reply)             \
1887 _(SESSION_RULE_ADD_DEL_REPLY, session_rule_add_del_reply)               \
1888 _(SESSION_RULES_DETAILS, session_rules_details)                         \
1889 _(IP_CONTAINER_PROXY_ADD_DEL_REPLY, ip_container_proxy_add_del_reply)   \
1890
1891 #define foreach_standalone_reply_msg                                    \
1892 _(SW_INTERFACE_EVENT, sw_interface_event)
1893
1894 typedef struct
1895 {
1896   u8 *name;
1897   u32 value;
1898 } name_sort_t;
1899
1900 #define STR_VTR_OP_CASE(op)     \
1901     case L2_VTR_ ## op:         \
1902         return "" # op;
1903
1904 static const char *
1905 str_vtr_op (u32 vtr_op)
1906 {
1907   switch (vtr_op)
1908     {
1909       STR_VTR_OP_CASE (DISABLED);
1910       STR_VTR_OP_CASE (PUSH_1);
1911       STR_VTR_OP_CASE (PUSH_2);
1912       STR_VTR_OP_CASE (POP_1);
1913       STR_VTR_OP_CASE (POP_2);
1914       STR_VTR_OP_CASE (TRANSLATE_1_1);
1915       STR_VTR_OP_CASE (TRANSLATE_1_2);
1916       STR_VTR_OP_CASE (TRANSLATE_2_1);
1917       STR_VTR_OP_CASE (TRANSLATE_2_2);
1918     }
1919
1920   return "UNKNOWN";
1921 }
1922
1923 static int
1924 dump_sub_interface_table (vat_main_t * vam)
1925 {
1926   const sw_interface_subif_t *sub = NULL;
1927
1928   if (vam->json_output)
1929     {
1930       clib_warning
1931         ("JSON output supported only for VPE API calls and dump_stats_table");
1932       return -99;
1933     }
1934
1935   print (vam->ofp,
1936          "%-30s%-12s%-11s%-7s%-5s%-9s%-9s%-6s%-8s%-10s%-10s",
1937          "Interface", "sw_if_index",
1938          "sub id", "dot1ad", "tags", "outer id",
1939          "inner id", "exact", "default", "outer any", "inner any");
1940
1941   vec_foreach (sub, vam->sw_if_subif_table)
1942   {
1943     print (vam->ofp,
1944            "%-30s%-12d%-11d%-7s%-5d%-9d%-9d%-6d%-8d%-10d%-10d",
1945            sub->interface_name,
1946            sub->sw_if_index,
1947            sub->sub_id, sub->sub_dot1ad ? "dot1ad" : "dot1q",
1948            sub->sub_number_of_tags, sub->sub_outer_vlan_id,
1949            sub->sub_inner_vlan_id, sub->sub_exact_match, sub->sub_default,
1950            sub->sub_outer_vlan_id_any, sub->sub_inner_vlan_id_any);
1951     if (sub->vtr_op != L2_VTR_DISABLED)
1952       {
1953         print (vam->ofp,
1954                "  vlan-tag-rewrite - op: %-14s [ dot1q: %d "
1955                "tag1: %d tag2: %d ]",
1956                str_vtr_op (sub->vtr_op), sub->vtr_push_dot1q,
1957                sub->vtr_tag1, sub->vtr_tag2);
1958       }
1959   }
1960
1961   return 0;
1962 }
1963
1964 static int
1965 name_sort_cmp (void *a1, void *a2)
1966 {
1967   name_sort_t *n1 = a1;
1968   name_sort_t *n2 = a2;
1969
1970   return strcmp ((char *) n1->name, (char *) n2->name);
1971 }
1972
1973 static int
1974 dump_interface_table (vat_main_t * vam)
1975 {
1976   hash_pair_t *p;
1977   name_sort_t *nses = 0, *ns;
1978
1979   if (vam->json_output)
1980     {
1981       clib_warning
1982         ("JSON output supported only for VPE API calls and dump_stats_table");
1983       return -99;
1984     }
1985
1986   /* *INDENT-OFF* */
1987   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
1988   ({
1989     vec_add2 (nses, ns, 1);
1990     ns->name = (u8 *)(p->key);
1991     ns->value = (u32) p->value[0];
1992   }));
1993   /* *INDENT-ON* */
1994
1995   vec_sort_with_function (nses, name_sort_cmp);
1996
1997   print (vam->ofp, "%-25s%-15s", "Interface", "sw_if_index");
1998   vec_foreach (ns, nses)
1999   {
2000     print (vam->ofp, "%-25s%-15d", ns->name, ns->value);
2001   }
2002   vec_free (nses);
2003   return 0;
2004 }
2005
2006 static int
2007 dump_ip_table (vat_main_t * vam, int is_ipv6)
2008 {
2009   const ip_details_t *det = NULL;
2010   const ip_address_details_t *address = NULL;
2011   u32 i = ~0;
2012
2013   print (vam->ofp, "%-12s", "sw_if_index");
2014
2015   vec_foreach (det, vam->ip_details_by_sw_if_index[is_ipv6])
2016   {
2017     i++;
2018     if (!det->present)
2019       {
2020         continue;
2021       }
2022     print (vam->ofp, "%-12d", i);
2023     print (vam->ofp, "            %-30s%-13s", "Address", "Prefix length");
2024     if (!det->addr)
2025       {
2026         continue;
2027       }
2028     vec_foreach (address, det->addr)
2029     {
2030       print (vam->ofp,
2031              "            %-30U%-13d",
2032              is_ipv6 ? format_ip6_address : format_ip4_address,
2033              address->ip, address->prefix_length);
2034     }
2035   }
2036
2037   return 0;
2038 }
2039
2040 static int
2041 dump_ipv4_table (vat_main_t * vam)
2042 {
2043   if (vam->json_output)
2044     {
2045       clib_warning
2046         ("JSON output supported only for VPE API calls and dump_stats_table");
2047       return -99;
2048     }
2049
2050   return dump_ip_table (vam, 0);
2051 }
2052
2053 static int
2054 dump_ipv6_table (vat_main_t * vam)
2055 {
2056   if (vam->json_output)
2057     {
2058       clib_warning
2059         ("JSON output supported only for VPE API calls and dump_stats_table");
2060       return -99;
2061     }
2062
2063   return dump_ip_table (vam, 1);
2064 }
2065
2066 /*
2067  * Pass CLI buffers directly in the CLI_INBAND API message,
2068  * instead of an additional shared memory area.
2069  */
2070 static int
2071 exec_inband (vat_main_t * vam)
2072 {
2073   vl_api_cli_inband_t *mp;
2074   unformat_input_t *i = vam->input;
2075   int ret;
2076
2077   if (vec_len (i->buffer) == 0)
2078     return -1;
2079
2080   if (vam->exec_mode == 0 && unformat (i, "mode"))
2081     {
2082       vam->exec_mode = 1;
2083       return 0;
2084     }
2085   if (vam->exec_mode == 1 && (unformat (i, "exit") || unformat (i, "quit")))
2086     {
2087       vam->exec_mode = 0;
2088       return 0;
2089     }
2090
2091   /*
2092    * In order for the CLI command to work, it
2093    * must be a vector ending in \n, not a C-string ending
2094    * in \n\0.
2095    */
2096   M2 (CLI_INBAND, mp, vec_len (vam->input->buffer));
2097   vl_api_vec_to_api_string (vam->input->buffer, &mp->cmd);
2098
2099   S (mp);
2100   W (ret);
2101   /* json responses may or may not include a useful reply... */
2102   if (vec_len (vam->cmd_reply))
2103     print (vam->ofp, "%v", (char *) (vam->cmd_reply));
2104   return ret;
2105 }
2106
2107 int
2108 exec (vat_main_t * vam)
2109 {
2110   return exec_inband (vam);
2111 }
2112
2113 static int
2114 api_create_loopback (vat_main_t * vam)
2115 {
2116   unformat_input_t *i = vam->input;
2117   vl_api_create_loopback_t *mp;
2118   vl_api_create_loopback_instance_t *mp_lbi;
2119   u8 mac_address[6];
2120   u8 mac_set = 0;
2121   u8 is_specified = 0;
2122   u32 user_instance = 0;
2123   int ret;
2124
2125   clib_memset (mac_address, 0, sizeof (mac_address));
2126
2127   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2128     {
2129       if (unformat (i, "mac %U", unformat_ethernet_address, mac_address))
2130         mac_set = 1;
2131       if (unformat (i, "instance %d", &user_instance))
2132         is_specified = 1;
2133       else
2134         break;
2135     }
2136
2137   if (is_specified)
2138     {
2139       M (CREATE_LOOPBACK_INSTANCE, mp_lbi);
2140       mp_lbi->is_specified = is_specified;
2141       if (is_specified)
2142         mp_lbi->user_instance = htonl (user_instance);
2143       if (mac_set)
2144         clib_memcpy (mp_lbi->mac_address, mac_address, sizeof (mac_address));
2145       S (mp_lbi);
2146     }
2147   else
2148     {
2149       /* Construct the API message */
2150       M (CREATE_LOOPBACK, mp);
2151       if (mac_set)
2152         clib_memcpy (mp->mac_address, mac_address, sizeof (mac_address));
2153       S (mp);
2154     }
2155
2156   W (ret);
2157   return ret;
2158 }
2159
2160 static int
2161 api_delete_loopback (vat_main_t * vam)
2162 {
2163   unformat_input_t *i = vam->input;
2164   vl_api_delete_loopback_t *mp;
2165   u32 sw_if_index = ~0;
2166   int ret;
2167
2168   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2169     {
2170       if (unformat (i, "sw_if_index %d", &sw_if_index))
2171         ;
2172       else
2173         break;
2174     }
2175
2176   if (sw_if_index == ~0)
2177     {
2178       errmsg ("missing sw_if_index");
2179       return -99;
2180     }
2181
2182   /* Construct the API message */
2183   M (DELETE_LOOPBACK, mp);
2184   mp->sw_if_index = ntohl (sw_if_index);
2185
2186   S (mp);
2187   W (ret);
2188   return ret;
2189 }
2190
2191 static int
2192 api_want_interface_events (vat_main_t * vam)
2193 {
2194   unformat_input_t *i = vam->input;
2195   vl_api_want_interface_events_t *mp;
2196   int enable = -1;
2197   int ret;
2198
2199   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2200     {
2201       if (unformat (i, "enable"))
2202         enable = 1;
2203       else if (unformat (i, "disable"))
2204         enable = 0;
2205       else
2206         break;
2207     }
2208
2209   if (enable == -1)
2210     {
2211       errmsg ("missing enable|disable");
2212       return -99;
2213     }
2214
2215   M (WANT_INTERFACE_EVENTS, mp);
2216   mp->enable_disable = enable;
2217
2218   vam->interface_event_display = enable;
2219
2220   S (mp);
2221   W (ret);
2222   return ret;
2223 }
2224
2225
2226 /* Note: non-static, called once to set up the initial intfc table */
2227 int
2228 api_sw_interface_dump (vat_main_t * vam)
2229 {
2230   vl_api_sw_interface_dump_t *mp;
2231   vl_api_control_ping_t *mp_ping;
2232   hash_pair_t *p;
2233   name_sort_t *nses = 0, *ns;
2234   sw_interface_subif_t *sub = NULL;
2235   int ret;
2236
2237   /* Toss the old name table */
2238   /* *INDENT-OFF* */
2239   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
2240   ({
2241     vec_add2 (nses, ns, 1);
2242     ns->name = (u8 *)(p->key);
2243     ns->value = (u32) p->value[0];
2244   }));
2245   /* *INDENT-ON* */
2246
2247   hash_free (vam->sw_if_index_by_interface_name);
2248
2249   vec_foreach (ns, nses) vec_free (ns->name);
2250
2251   vec_free (nses);
2252
2253   vec_foreach (sub, vam->sw_if_subif_table)
2254   {
2255     vec_free (sub->interface_name);
2256   }
2257   vec_free (vam->sw_if_subif_table);
2258
2259   /* recreate the interface name hash table */
2260   vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
2261
2262   /*
2263    * Ask for all interface names. Otherwise, the epic catalog of
2264    * name filters becomes ridiculously long, and vat ends up needing
2265    * to be taught about new interface types.
2266    */
2267   M (SW_INTERFACE_DUMP, mp);
2268   S (mp);
2269
2270   /* Use a control ping for synchronization */
2271   MPING (CONTROL_PING, mp_ping);
2272   S (mp_ping);
2273
2274   W (ret);
2275   return ret;
2276 }
2277
2278 static int
2279 api_sw_interface_set_flags (vat_main_t * vam)
2280 {
2281   unformat_input_t *i = vam->input;
2282   vl_api_sw_interface_set_flags_t *mp;
2283   u32 sw_if_index;
2284   u8 sw_if_index_set = 0;
2285   u8 admin_up = 0;
2286   int ret;
2287
2288   /* Parse args required to build the message */
2289   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2290     {
2291       if (unformat (i, "admin-up"))
2292         admin_up = 1;
2293       else if (unformat (i, "admin-down"))
2294         admin_up = 0;
2295       else
2296         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2297         sw_if_index_set = 1;
2298       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2299         sw_if_index_set = 1;
2300       else
2301         break;
2302     }
2303
2304   if (sw_if_index_set == 0)
2305     {
2306       errmsg ("missing interface name or sw_if_index");
2307       return -99;
2308     }
2309
2310   /* Construct the API message */
2311   M (SW_INTERFACE_SET_FLAGS, mp);
2312   mp->sw_if_index = ntohl (sw_if_index);
2313   mp->flags = ntohl ((admin_up) ? IF_STATUS_API_FLAG_ADMIN_UP : 0);
2314
2315   /* send it... */
2316   S (mp);
2317
2318   /* Wait for a reply, return the good/bad news... */
2319   W (ret);
2320   return ret;
2321 }
2322
2323 static int
2324 api_sw_interface_set_rx_mode (vat_main_t * vam)
2325 {
2326   unformat_input_t *i = vam->input;
2327   vl_api_sw_interface_set_rx_mode_t *mp;
2328   u32 sw_if_index;
2329   u8 sw_if_index_set = 0;
2330   int ret;
2331   u8 queue_id_valid = 0;
2332   u32 queue_id;
2333   vnet_hw_if_rx_mode mode = VNET_HW_IF_RX_MODE_UNKNOWN;
2334
2335   /* Parse args required to build the message */
2336   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2337     {
2338       if (unformat (i, "queue %d", &queue_id))
2339         queue_id_valid = 1;
2340       else if (unformat (i, "polling"))
2341         mode = VNET_HW_IF_RX_MODE_POLLING;
2342       else if (unformat (i, "interrupt"))
2343         mode = VNET_HW_IF_RX_MODE_INTERRUPT;
2344       else if (unformat (i, "adaptive"))
2345         mode = VNET_HW_IF_RX_MODE_ADAPTIVE;
2346       else
2347         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2348         sw_if_index_set = 1;
2349       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2350         sw_if_index_set = 1;
2351       else
2352         break;
2353     }
2354
2355   if (sw_if_index_set == 0)
2356     {
2357       errmsg ("missing interface name or sw_if_index");
2358       return -99;
2359     }
2360   if (mode == VNET_HW_IF_RX_MODE_UNKNOWN)
2361     {
2362       errmsg ("missing rx-mode");
2363       return -99;
2364     }
2365
2366   /* Construct the API message */
2367   M (SW_INTERFACE_SET_RX_MODE, mp);
2368   mp->sw_if_index = ntohl (sw_if_index);
2369   mp->mode = (vl_api_rx_mode_t) mode;
2370   mp->queue_id_valid = queue_id_valid;
2371   mp->queue_id = queue_id_valid ? ntohl (queue_id) : ~0;
2372
2373   /* send it... */
2374   S (mp);
2375
2376   /* Wait for a reply, return the good/bad news... */
2377   W (ret);
2378   return ret;
2379 }
2380
2381 static int
2382 api_sw_interface_set_rx_placement (vat_main_t * vam)
2383 {
2384   unformat_input_t *i = vam->input;
2385   vl_api_sw_interface_set_rx_placement_t *mp;
2386   u32 sw_if_index;
2387   u8 sw_if_index_set = 0;
2388   int ret;
2389   u8 is_main = 0;
2390   u32 queue_id, thread_index;
2391
2392   /* Parse args required to build the message */
2393   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2394     {
2395       if (unformat (i, "queue %d", &queue_id))
2396         ;
2397       else if (unformat (i, "main"))
2398         is_main = 1;
2399       else if (unformat (i, "worker %d", &thread_index))
2400         ;
2401       else
2402         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2403         sw_if_index_set = 1;
2404       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2405         sw_if_index_set = 1;
2406       else
2407         break;
2408     }
2409
2410   if (sw_if_index_set == 0)
2411     {
2412       errmsg ("missing interface name or sw_if_index");
2413       return -99;
2414     }
2415
2416   if (is_main)
2417     thread_index = 0;
2418   /* Construct the API message */
2419   M (SW_INTERFACE_SET_RX_PLACEMENT, mp);
2420   mp->sw_if_index = ntohl (sw_if_index);
2421   mp->worker_id = ntohl (thread_index);
2422   mp->queue_id = ntohl (queue_id);
2423   mp->is_main = is_main;
2424
2425   /* send it... */
2426   S (mp);
2427   /* Wait for a reply, return the good/bad news... */
2428   W (ret);
2429   return ret;
2430 }
2431
2432 static void vl_api_sw_interface_rx_placement_details_t_handler
2433   (vl_api_sw_interface_rx_placement_details_t * mp)
2434 {
2435   vat_main_t *vam = &vat_main;
2436   u32 worker_id = ntohl (mp->worker_id);
2437
2438   print (vam->ofp,
2439          "\n%-11d %-11s %-6d %-5d %-9s",
2440          ntohl (mp->sw_if_index), (worker_id == 0) ? "main" : "worker",
2441          worker_id, ntohl (mp->queue_id),
2442          (mp->mode ==
2443           1) ? "polling" : ((mp->mode == 2) ? "interrupt" : "adaptive"));
2444 }
2445
2446 static void vl_api_sw_interface_rx_placement_details_t_handler_json
2447   (vl_api_sw_interface_rx_placement_details_t * mp)
2448 {
2449   vat_main_t *vam = &vat_main;
2450   vat_json_node_t *node = NULL;
2451
2452   if (VAT_JSON_ARRAY != vam->json_tree.type)
2453     {
2454       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
2455       vat_json_init_array (&vam->json_tree);
2456     }
2457   node = vat_json_array_add (&vam->json_tree);
2458
2459   vat_json_init_object (node);
2460   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
2461   vat_json_object_add_uint (node, "worker_id", ntohl (mp->worker_id));
2462   vat_json_object_add_uint (node, "queue_id", ntohl (mp->queue_id));
2463   vat_json_object_add_uint (node, "mode", mp->mode);
2464 }
2465
2466 static int
2467 api_sw_interface_rx_placement_dump (vat_main_t * vam)
2468 {
2469   unformat_input_t *i = vam->input;
2470   vl_api_sw_interface_rx_placement_dump_t *mp;
2471   vl_api_control_ping_t *mp_ping;
2472   int ret;
2473   u32 sw_if_index;
2474   u8 sw_if_index_set = 0;
2475
2476   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2477     {
2478       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2479         sw_if_index_set++;
2480       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2481         sw_if_index_set++;
2482       else
2483         break;
2484     }
2485
2486   print (vam->ofp,
2487          "\n%-11s %-11s %-6s %-5s %-4s",
2488          "sw_if_index", "main/worker", "thread", "queue", "mode");
2489
2490   /* Dump Interface rx placement */
2491   M (SW_INTERFACE_RX_PLACEMENT_DUMP, mp);
2492
2493   if (sw_if_index_set)
2494     mp->sw_if_index = htonl (sw_if_index);
2495   else
2496     mp->sw_if_index = ~0;
2497
2498   S (mp);
2499
2500   /* Use a control ping for synchronization */
2501   MPING (CONTROL_PING, mp_ping);
2502   S (mp_ping);
2503
2504   W (ret);
2505   return ret;
2506 }
2507
2508 static int
2509 api_sw_interface_clear_stats (vat_main_t * vam)
2510 {
2511   unformat_input_t *i = vam->input;
2512   vl_api_sw_interface_clear_stats_t *mp;
2513   u32 sw_if_index;
2514   u8 sw_if_index_set = 0;
2515   int ret;
2516
2517   /* Parse args required to build the message */
2518   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2519     {
2520       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2521         sw_if_index_set = 1;
2522       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2523         sw_if_index_set = 1;
2524       else
2525         break;
2526     }
2527
2528   /* Construct the API message */
2529   M (SW_INTERFACE_CLEAR_STATS, mp);
2530
2531   if (sw_if_index_set == 1)
2532     mp->sw_if_index = ntohl (sw_if_index);
2533   else
2534     mp->sw_if_index = ~0;
2535
2536   /* send it... */
2537   S (mp);
2538
2539   /* Wait for a reply, return the good/bad news... */
2540   W (ret);
2541   return ret;
2542 }
2543
2544 static int
2545 api_sw_interface_add_del_address (vat_main_t * vam)
2546 {
2547   unformat_input_t *i = vam->input;
2548   vl_api_sw_interface_add_del_address_t *mp;
2549   u32 sw_if_index;
2550   u8 sw_if_index_set = 0;
2551   u8 is_add = 1, del_all = 0;
2552   u32 address_length = 0;
2553   u8 v4_address_set = 0;
2554   u8 v6_address_set = 0;
2555   ip4_address_t v4address;
2556   ip6_address_t v6address;
2557   int ret;
2558
2559   /* Parse args required to build the message */
2560   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2561     {
2562       if (unformat (i, "del-all"))
2563         del_all = 1;
2564       else if (unformat (i, "del"))
2565         is_add = 0;
2566       else
2567         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2568         sw_if_index_set = 1;
2569       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2570         sw_if_index_set = 1;
2571       else if (unformat (i, "%U/%d",
2572                          unformat_ip4_address, &v4address, &address_length))
2573         v4_address_set = 1;
2574       else if (unformat (i, "%U/%d",
2575                          unformat_ip6_address, &v6address, &address_length))
2576         v6_address_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   if (v4_address_set && v6_address_set)
2587     {
2588       errmsg ("both v4 and v6 addresses set");
2589       return -99;
2590     }
2591   if (!v4_address_set && !v6_address_set && !del_all)
2592     {
2593       errmsg ("no addresses set");
2594       return -99;
2595     }
2596
2597   /* Construct the API message */
2598   M (SW_INTERFACE_ADD_DEL_ADDRESS, mp);
2599
2600   mp->sw_if_index = ntohl (sw_if_index);
2601   mp->is_add = is_add;
2602   mp->del_all = del_all;
2603   if (v6_address_set)
2604     {
2605       mp->prefix.address.af = ADDRESS_IP6;
2606       clib_memcpy (mp->prefix.address.un.ip6, &v6address, sizeof (v6address));
2607     }
2608   else
2609     {
2610       mp->prefix.address.af = ADDRESS_IP4;
2611       clib_memcpy (mp->prefix.address.un.ip4, &v4address, sizeof (v4address));
2612     }
2613   mp->prefix.len = address_length;
2614
2615   /* send it... */
2616   S (mp);
2617
2618   /* Wait for a reply, return good/bad news  */
2619   W (ret);
2620   return ret;
2621 }
2622
2623 static int
2624 api_sw_interface_set_table (vat_main_t * vam)
2625 {
2626   unformat_input_t *i = vam->input;
2627   vl_api_sw_interface_set_table_t *mp;
2628   u32 sw_if_index, vrf_id = 0;
2629   u8 sw_if_index_set = 0;
2630   u8 is_ipv6 = 0;
2631   int ret;
2632
2633   /* Parse args required to build the message */
2634   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2635     {
2636       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2637         sw_if_index_set = 1;
2638       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2639         sw_if_index_set = 1;
2640       else if (unformat (i, "vrf %d", &vrf_id))
2641         ;
2642       else if (unformat (i, "ipv6"))
2643         is_ipv6 = 1;
2644       else
2645         break;
2646     }
2647
2648   if (sw_if_index_set == 0)
2649     {
2650       errmsg ("missing interface name or sw_if_index");
2651       return -99;
2652     }
2653
2654   /* Construct the API message */
2655   M (SW_INTERFACE_SET_TABLE, mp);
2656
2657   mp->sw_if_index = ntohl (sw_if_index);
2658   mp->is_ipv6 = is_ipv6;
2659   mp->vrf_id = ntohl (vrf_id);
2660
2661   /* send it... */
2662   S (mp);
2663
2664   /* Wait for a reply... */
2665   W (ret);
2666   return ret;
2667 }
2668
2669 static void vl_api_sw_interface_get_table_reply_t_handler
2670   (vl_api_sw_interface_get_table_reply_t * mp)
2671 {
2672   vat_main_t *vam = &vat_main;
2673
2674   print (vam->ofp, "%d", ntohl (mp->vrf_id));
2675
2676   vam->retval = ntohl (mp->retval);
2677   vam->result_ready = 1;
2678
2679 }
2680
2681 static void vl_api_sw_interface_get_table_reply_t_handler_json
2682   (vl_api_sw_interface_get_table_reply_t * mp)
2683 {
2684   vat_main_t *vam = &vat_main;
2685   vat_json_node_t node;
2686
2687   vat_json_init_object (&node);
2688   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2689   vat_json_object_add_int (&node, "vrf_id", ntohl (mp->vrf_id));
2690
2691   vat_json_print (vam->ofp, &node);
2692   vat_json_free (&node);
2693
2694   vam->retval = ntohl (mp->retval);
2695   vam->result_ready = 1;
2696 }
2697
2698 static int
2699 api_sw_interface_get_table (vat_main_t * vam)
2700 {
2701   unformat_input_t *i = vam->input;
2702   vl_api_sw_interface_get_table_t *mp;
2703   u32 sw_if_index;
2704   u8 sw_if_index_set = 0;
2705   u8 is_ipv6 = 0;
2706   int ret;
2707
2708   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2709     {
2710       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2711         sw_if_index_set = 1;
2712       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2713         sw_if_index_set = 1;
2714       else if (unformat (i, "ipv6"))
2715         is_ipv6 = 1;
2716       else
2717         break;
2718     }
2719
2720   if (sw_if_index_set == 0)
2721     {
2722       errmsg ("missing interface name or sw_if_index");
2723       return -99;
2724     }
2725
2726   M (SW_INTERFACE_GET_TABLE, mp);
2727   mp->sw_if_index = htonl (sw_if_index);
2728   mp->is_ipv6 = is_ipv6;
2729
2730   S (mp);
2731   W (ret);
2732   return ret;
2733 }
2734
2735 static int
2736 api_sw_interface_set_vpath (vat_main_t * vam)
2737 {
2738   unformat_input_t *i = vam->input;
2739   vl_api_sw_interface_set_vpath_t *mp;
2740   u32 sw_if_index = 0;
2741   u8 sw_if_index_set = 0;
2742   u8 is_enable = 0;
2743   int ret;
2744
2745   /* Parse args required to build the message */
2746   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2747     {
2748       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2749         sw_if_index_set = 1;
2750       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2751         sw_if_index_set = 1;
2752       else if (unformat (i, "enable"))
2753         is_enable = 1;
2754       else if (unformat (i, "disable"))
2755         is_enable = 0;
2756       else
2757         break;
2758     }
2759
2760   if (sw_if_index_set == 0)
2761     {
2762       errmsg ("missing interface name or sw_if_index");
2763       return -99;
2764     }
2765
2766   /* Construct the API message */
2767   M (SW_INTERFACE_SET_VPATH, mp);
2768
2769   mp->sw_if_index = ntohl (sw_if_index);
2770   mp->enable = is_enable;
2771
2772   /* send it... */
2773   S (mp);
2774
2775   /* Wait for a reply... */
2776   W (ret);
2777   return ret;
2778 }
2779
2780 static int
2781 api_sw_interface_set_l2_xconnect (vat_main_t * vam)
2782 {
2783   unformat_input_t *i = vam->input;
2784   vl_api_sw_interface_set_l2_xconnect_t *mp;
2785   u32 rx_sw_if_index;
2786   u8 rx_sw_if_index_set = 0;
2787   u32 tx_sw_if_index;
2788   u8 tx_sw_if_index_set = 0;
2789   u8 enable = 1;
2790   int ret;
2791
2792   /* Parse args required to build the message */
2793   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2794     {
2795       if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index))
2796         rx_sw_if_index_set = 1;
2797       else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
2798         tx_sw_if_index_set = 1;
2799       else if (unformat (i, "rx"))
2800         {
2801           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2802             {
2803               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
2804                             &rx_sw_if_index))
2805                 rx_sw_if_index_set = 1;
2806             }
2807           else
2808             break;
2809         }
2810       else if (unformat (i, "tx"))
2811         {
2812           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2813             {
2814               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
2815                             &tx_sw_if_index))
2816                 tx_sw_if_index_set = 1;
2817             }
2818           else
2819             break;
2820         }
2821       else if (unformat (i, "enable"))
2822         enable = 1;
2823       else if (unformat (i, "disable"))
2824         enable = 0;
2825       else
2826         break;
2827     }
2828
2829   if (rx_sw_if_index_set == 0)
2830     {
2831       errmsg ("missing rx interface name or rx_sw_if_index");
2832       return -99;
2833     }
2834
2835   if (enable && (tx_sw_if_index_set == 0))
2836     {
2837       errmsg ("missing tx interface name or tx_sw_if_index");
2838       return -99;
2839     }
2840
2841   M (SW_INTERFACE_SET_L2_XCONNECT, mp);
2842
2843   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
2844   mp->tx_sw_if_index = ntohl (tx_sw_if_index);
2845   mp->enable = enable;
2846
2847   S (mp);
2848   W (ret);
2849   return ret;
2850 }
2851
2852 static int
2853 api_sw_interface_set_l2_bridge (vat_main_t * vam)
2854 {
2855   unformat_input_t *i = vam->input;
2856   vl_api_sw_interface_set_l2_bridge_t *mp;
2857   vl_api_l2_port_type_t port_type;
2858   u32 rx_sw_if_index;
2859   u8 rx_sw_if_index_set = 0;
2860   u32 bd_id;
2861   u8 bd_id_set = 0;
2862   u32 shg = 0;
2863   u8 enable = 1;
2864   int ret;
2865
2866   port_type = L2_API_PORT_TYPE_NORMAL;
2867
2868   /* Parse args required to build the message */
2869   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2870     {
2871       if (unformat (i, "sw_if_index %d", &rx_sw_if_index))
2872         rx_sw_if_index_set = 1;
2873       else if (unformat (i, "bd_id %d", &bd_id))
2874         bd_id_set = 1;
2875       else
2876         if (unformat
2877             (i, "%U", api_unformat_sw_if_index, vam, &rx_sw_if_index))
2878         rx_sw_if_index_set = 1;
2879       else if (unformat (i, "shg %d", &shg))
2880         ;
2881       else if (unformat (i, "bvi"))
2882         port_type = L2_API_PORT_TYPE_BVI;
2883       else if (unformat (i, "uu-fwd"))
2884         port_type = L2_API_PORT_TYPE_UU_FWD;
2885       else if (unformat (i, "enable"))
2886         enable = 1;
2887       else if (unformat (i, "disable"))
2888         enable = 0;
2889       else
2890         break;
2891     }
2892
2893   if (rx_sw_if_index_set == 0)
2894     {
2895       errmsg ("missing rx interface name or sw_if_index");
2896       return -99;
2897     }
2898
2899   if (enable && (bd_id_set == 0))
2900     {
2901       errmsg ("missing bridge domain");
2902       return -99;
2903     }
2904
2905   M (SW_INTERFACE_SET_L2_BRIDGE, mp);
2906
2907   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
2908   mp->bd_id = ntohl (bd_id);
2909   mp->shg = (u8) shg;
2910   mp->port_type = ntohl (port_type);
2911   mp->enable = enable;
2912
2913   S (mp);
2914   W (ret);
2915   return ret;
2916 }
2917
2918 static int
2919 api_bridge_domain_dump (vat_main_t * vam)
2920 {
2921   unformat_input_t *i = vam->input;
2922   vl_api_bridge_domain_dump_t *mp;
2923   vl_api_control_ping_t *mp_ping;
2924   u32 bd_id = ~0;
2925   int ret;
2926
2927   /* Parse args required to build the message */
2928   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2929     {
2930       if (unformat (i, "bd_id %d", &bd_id))
2931         ;
2932       else
2933         break;
2934     }
2935
2936   M (BRIDGE_DOMAIN_DUMP, mp);
2937   mp->bd_id = ntohl (bd_id);
2938   S (mp);
2939
2940   /* Use a control ping for synchronization */
2941   MPING (CONTROL_PING, mp_ping);
2942   S (mp_ping);
2943
2944   W (ret);
2945   return ret;
2946 }
2947
2948 static int
2949 api_bridge_domain_add_del (vat_main_t * vam)
2950 {
2951   unformat_input_t *i = vam->input;
2952   vl_api_bridge_domain_add_del_t *mp;
2953   u32 bd_id = ~0;
2954   u8 is_add = 1;
2955   u32 flood = 1, forward = 1, learn = 1, uu_flood = 1, arp_term = 0;
2956   u8 *bd_tag = NULL;
2957   u32 mac_age = 0;
2958   int ret;
2959
2960   /* Parse args required to build the message */
2961   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2962     {
2963       if (unformat (i, "bd_id %d", &bd_id))
2964         ;
2965       else if (unformat (i, "flood %d", &flood))
2966         ;
2967       else if (unformat (i, "uu-flood %d", &uu_flood))
2968         ;
2969       else if (unformat (i, "forward %d", &forward))
2970         ;
2971       else if (unformat (i, "learn %d", &learn))
2972         ;
2973       else if (unformat (i, "arp-term %d", &arp_term))
2974         ;
2975       else if (unformat (i, "mac-age %d", &mac_age))
2976         ;
2977       else if (unformat (i, "bd-tag %s", &bd_tag))
2978         ;
2979       else if (unformat (i, "del"))
2980         {
2981           is_add = 0;
2982           flood = uu_flood = forward = learn = 0;
2983         }
2984       else
2985         break;
2986     }
2987
2988   if (bd_id == ~0)
2989     {
2990       errmsg ("missing bridge domain");
2991       ret = -99;
2992       goto done;
2993     }
2994
2995   if (mac_age > 255)
2996     {
2997       errmsg ("mac age must be less than 256 ");
2998       ret = -99;
2999       goto done;
3000     }
3001
3002   if ((bd_tag) && (vec_len (bd_tag) > 63))
3003     {
3004       errmsg ("bd-tag cannot be longer than 63");
3005       ret = -99;
3006       goto done;
3007     }
3008
3009   M (BRIDGE_DOMAIN_ADD_DEL, mp);
3010
3011   mp->bd_id = ntohl (bd_id);
3012   mp->flood = flood;
3013   mp->uu_flood = uu_flood;
3014   mp->forward = forward;
3015   mp->learn = learn;
3016   mp->arp_term = arp_term;
3017   mp->is_add = is_add;
3018   mp->mac_age = (u8) mac_age;
3019   if (bd_tag)
3020     {
3021       clib_memcpy (mp->bd_tag, bd_tag, vec_len (bd_tag));
3022       mp->bd_tag[vec_len (bd_tag)] = 0;
3023     }
3024   S (mp);
3025   W (ret);
3026
3027 done:
3028   vec_free (bd_tag);
3029   return ret;
3030 }
3031
3032 static int
3033 api_l2fib_flush_bd (vat_main_t * vam)
3034 {
3035   unformat_input_t *i = vam->input;
3036   vl_api_l2fib_flush_bd_t *mp;
3037   u32 bd_id = ~0;
3038   int ret;
3039
3040   /* Parse args required to build the message */
3041   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3042     {
3043       if (unformat (i, "bd_id %d", &bd_id));
3044       else
3045         break;
3046     }
3047
3048   if (bd_id == ~0)
3049     {
3050       errmsg ("missing bridge domain");
3051       return -99;
3052     }
3053
3054   M (L2FIB_FLUSH_BD, mp);
3055
3056   mp->bd_id = htonl (bd_id);
3057
3058   S (mp);
3059   W (ret);
3060   return ret;
3061 }
3062
3063 static int
3064 api_l2fib_flush_int (vat_main_t * vam)
3065 {
3066   unformat_input_t *i = vam->input;
3067   vl_api_l2fib_flush_int_t *mp;
3068   u32 sw_if_index = ~0;
3069   int ret;
3070
3071   /* Parse args required to build the message */
3072   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3073     {
3074       if (unformat (i, "sw_if_index %d", &sw_if_index));
3075       else
3076         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index));
3077       else
3078         break;
3079     }
3080
3081   if (sw_if_index == ~0)
3082     {
3083       errmsg ("missing interface name or sw_if_index");
3084       return -99;
3085     }
3086
3087   M (L2FIB_FLUSH_INT, mp);
3088
3089   mp->sw_if_index = ntohl (sw_if_index);
3090
3091   S (mp);
3092   W (ret);
3093   return ret;
3094 }
3095
3096 static int
3097 api_l2fib_add_del (vat_main_t * vam)
3098 {
3099   unformat_input_t *i = vam->input;
3100   vl_api_l2fib_add_del_t *mp;
3101   f64 timeout;
3102   u8 mac[6] = { 0 };
3103   u8 mac_set = 0;
3104   u32 bd_id;
3105   u8 bd_id_set = 0;
3106   u32 sw_if_index = 0;
3107   u8 sw_if_index_set = 0;
3108   u8 is_add = 1;
3109   u8 static_mac = 0;
3110   u8 filter_mac = 0;
3111   u8 bvi_mac = 0;
3112   int count = 1;
3113   f64 before = 0;
3114   int j;
3115
3116   /* Parse args required to build the message */
3117   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3118     {
3119       if (unformat (i, "mac %U", unformat_ethernet_address, mac))
3120         mac_set = 1;
3121       else if (unformat (i, "bd_id %d", &bd_id))
3122         bd_id_set = 1;
3123       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3124         sw_if_index_set = 1;
3125       else if (unformat (i, "sw_if"))
3126         {
3127           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3128             {
3129               if (unformat
3130                   (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3131                 sw_if_index_set = 1;
3132             }
3133           else
3134             break;
3135         }
3136       else if (unformat (i, "static"))
3137         static_mac = 1;
3138       else if (unformat (i, "filter"))
3139         {
3140           filter_mac = 1;
3141           static_mac = 1;
3142         }
3143       else if (unformat (i, "bvi"))
3144         {
3145           bvi_mac = 1;
3146           static_mac = 1;
3147         }
3148       else if (unformat (i, "del"))
3149         is_add = 0;
3150       else if (unformat (i, "count %d", &count))
3151         ;
3152       else
3153         break;
3154     }
3155
3156   if (mac_set == 0)
3157     {
3158       errmsg ("missing mac address");
3159       return -99;
3160     }
3161
3162   if (bd_id_set == 0)
3163     {
3164       errmsg ("missing bridge domain");
3165       return -99;
3166     }
3167
3168   if (is_add && sw_if_index_set == 0 && filter_mac == 0)
3169     {
3170       errmsg ("missing interface name or sw_if_index");
3171       return -99;
3172     }
3173
3174   if (count > 1)
3175     {
3176       /* Turn on async mode */
3177       vam->async_mode = 1;
3178       vam->async_errors = 0;
3179       before = vat_time_now (vam);
3180     }
3181
3182   for (j = 0; j < count; j++)
3183     {
3184       M (L2FIB_ADD_DEL, mp);
3185
3186       clib_memcpy (mp->mac, mac, 6);
3187       mp->bd_id = ntohl (bd_id);
3188       mp->is_add = is_add;
3189       mp->sw_if_index = ntohl (sw_if_index);
3190
3191       if (is_add)
3192         {
3193           mp->static_mac = static_mac;
3194           mp->filter_mac = filter_mac;
3195           mp->bvi_mac = bvi_mac;
3196         }
3197       increment_mac_address (mac);
3198       /* send it... */
3199       S (mp);
3200     }
3201
3202   if (count > 1)
3203     {
3204       vl_api_control_ping_t *mp_ping;
3205       f64 after;
3206
3207       /* Shut off async mode */
3208       vam->async_mode = 0;
3209
3210       MPING (CONTROL_PING, mp_ping);
3211       S (mp_ping);
3212
3213       timeout = vat_time_now (vam) + 1.0;
3214       while (vat_time_now (vam) < timeout)
3215         if (vam->result_ready == 1)
3216           goto out;
3217       vam->retval = -99;
3218
3219     out:
3220       if (vam->retval == -99)
3221         errmsg ("timeout");
3222
3223       if (vam->async_errors > 0)
3224         {
3225           errmsg ("%d asynchronous errors", vam->async_errors);
3226           vam->retval = -98;
3227         }
3228       vam->async_errors = 0;
3229       after = vat_time_now (vam);
3230
3231       print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec",
3232              count, after - before, count / (after - before));
3233     }
3234   else
3235     {
3236       int ret;
3237
3238       /* Wait for a reply... */
3239       W (ret);
3240       return ret;
3241     }
3242   /* Return the good/bad news */
3243   return (vam->retval);
3244 }
3245
3246 static int
3247 api_bridge_domain_set_mac_age (vat_main_t * vam)
3248 {
3249   unformat_input_t *i = vam->input;
3250   vl_api_bridge_domain_set_mac_age_t *mp;
3251   u32 bd_id = ~0;
3252   u32 mac_age = 0;
3253   int ret;
3254
3255   /* Parse args required to build the message */
3256   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3257     {
3258       if (unformat (i, "bd_id %d", &bd_id));
3259       else if (unformat (i, "mac-age %d", &mac_age));
3260       else
3261         break;
3262     }
3263
3264   if (bd_id == ~0)
3265     {
3266       errmsg ("missing bridge domain");
3267       return -99;
3268     }
3269
3270   if (mac_age > 255)
3271     {
3272       errmsg ("mac age must be less than 256 ");
3273       return -99;
3274     }
3275
3276   M (BRIDGE_DOMAIN_SET_MAC_AGE, mp);
3277
3278   mp->bd_id = htonl (bd_id);
3279   mp->mac_age = (u8) mac_age;
3280
3281   S (mp);
3282   W (ret);
3283   return ret;
3284 }
3285
3286 static int
3287 api_l2_flags (vat_main_t * vam)
3288 {
3289   unformat_input_t *i = vam->input;
3290   vl_api_l2_flags_t *mp;
3291   u32 sw_if_index;
3292   u32 flags = 0;
3293   u8 sw_if_index_set = 0;
3294   u8 is_set = 0;
3295   int ret;
3296
3297   /* Parse args required to build the message */
3298   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3299     {
3300       if (unformat (i, "sw_if_index %d", &sw_if_index))
3301         sw_if_index_set = 1;
3302       else if (unformat (i, "sw_if"))
3303         {
3304           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3305             {
3306               if (unformat
3307                   (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3308                 sw_if_index_set = 1;
3309             }
3310           else
3311             break;
3312         }
3313       else if (unformat (i, "learn"))
3314         flags |= L2_LEARN;
3315       else if (unformat (i, "forward"))
3316         flags |= L2_FWD;
3317       else if (unformat (i, "flood"))
3318         flags |= L2_FLOOD;
3319       else if (unformat (i, "uu-flood"))
3320         flags |= L2_UU_FLOOD;
3321       else if (unformat (i, "arp-term"))
3322         flags |= L2_ARP_TERM;
3323       else if (unformat (i, "off"))
3324         is_set = 0;
3325       else if (unformat (i, "disable"))
3326         is_set = 0;
3327       else
3328         break;
3329     }
3330
3331   if (sw_if_index_set == 0)
3332     {
3333       errmsg ("missing interface name or sw_if_index");
3334       return -99;
3335     }
3336
3337   M (L2_FLAGS, mp);
3338
3339   mp->sw_if_index = ntohl (sw_if_index);
3340   mp->feature_bitmap = ntohl (flags);
3341   mp->is_set = is_set;
3342
3343   S (mp);
3344   W (ret);
3345   return ret;
3346 }
3347
3348 static int
3349 api_bridge_flags (vat_main_t * vam)
3350 {
3351   unformat_input_t *i = vam->input;
3352   vl_api_bridge_flags_t *mp;
3353   u32 bd_id;
3354   u8 bd_id_set = 0;
3355   u8 is_set = 1;
3356   bd_flags_t flags = 0;
3357   int ret;
3358
3359   /* Parse args required to build the message */
3360   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3361     {
3362       if (unformat (i, "bd_id %d", &bd_id))
3363         bd_id_set = 1;
3364       else if (unformat (i, "learn"))
3365         flags |= BRIDGE_API_FLAG_LEARN;
3366       else if (unformat (i, "forward"))
3367         flags |= BRIDGE_API_FLAG_FWD;
3368       else if (unformat (i, "flood"))
3369         flags |= BRIDGE_API_FLAG_FLOOD;
3370       else if (unformat (i, "uu-flood"))
3371         flags |= BRIDGE_API_FLAG_UU_FLOOD;
3372       else if (unformat (i, "arp-term"))
3373         flags |= BRIDGE_API_FLAG_ARP_TERM;
3374       else if (unformat (i, "off"))
3375         is_set = 0;
3376       else if (unformat (i, "disable"))
3377         is_set = 0;
3378       else
3379         break;
3380     }
3381
3382   if (bd_id_set == 0)
3383     {
3384       errmsg ("missing bridge domain");
3385       return -99;
3386     }
3387
3388   M (BRIDGE_FLAGS, mp);
3389
3390   mp->bd_id = ntohl (bd_id);
3391   mp->flags = ntohl (flags);
3392   mp->is_set = is_set;
3393
3394   S (mp);
3395   W (ret);
3396   return ret;
3397 }
3398
3399 static int
3400 api_bd_ip_mac_add_del (vat_main_t * vam)
3401 {
3402   vl_api_address_t ip = VL_API_ZERO_ADDRESS;
3403   vl_api_mac_address_t mac = { 0 };
3404   unformat_input_t *i = vam->input;
3405   vl_api_bd_ip_mac_add_del_t *mp;
3406   u32 bd_id;
3407   u8 is_add = 1;
3408   u8 bd_id_set = 0;
3409   u8 ip_set = 0;
3410   u8 mac_set = 0;
3411   int ret;
3412
3413
3414   /* Parse args required to build the message */
3415   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3416     {
3417       if (unformat (i, "bd_id %d", &bd_id))
3418         {
3419           bd_id_set++;
3420         }
3421       else if (unformat (i, "%U", unformat_vl_api_address, &ip))
3422         {
3423           ip_set++;
3424         }
3425       else if (unformat (i, "%U", unformat_vl_api_mac_address, &mac))
3426         {
3427           mac_set++;
3428         }
3429       else if (unformat (i, "del"))
3430         is_add = 0;
3431       else
3432         break;
3433     }
3434
3435   if (bd_id_set == 0)
3436     {
3437       errmsg ("missing bridge domain");
3438       return -99;
3439     }
3440   else if (ip_set == 0)
3441     {
3442       errmsg ("missing IP address");
3443       return -99;
3444     }
3445   else if (mac_set == 0)
3446     {
3447       errmsg ("missing MAC address");
3448       return -99;
3449     }
3450
3451   M (BD_IP_MAC_ADD_DEL, mp);
3452
3453   mp->entry.bd_id = ntohl (bd_id);
3454   mp->is_add = is_add;
3455
3456   clib_memcpy (&mp->entry.ip, &ip, sizeof (ip));
3457   clib_memcpy (&mp->entry.mac, &mac, sizeof (mac));
3458
3459   S (mp);
3460   W (ret);
3461   return ret;
3462 }
3463
3464 static int
3465 api_bd_ip_mac_flush (vat_main_t * vam)
3466 {
3467   unformat_input_t *i = vam->input;
3468   vl_api_bd_ip_mac_flush_t *mp;
3469   u32 bd_id;
3470   u8 bd_id_set = 0;
3471   int ret;
3472
3473   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3474     {
3475       if (unformat (i, "bd_id %d", &bd_id))
3476         {
3477           bd_id_set++;
3478         }
3479       else
3480         break;
3481     }
3482
3483   if (bd_id_set == 0)
3484     {
3485       errmsg ("missing bridge domain");
3486       return -99;
3487     }
3488
3489   M (BD_IP_MAC_FLUSH, mp);
3490
3491   mp->bd_id = ntohl (bd_id);
3492
3493   S (mp);
3494   W (ret);
3495   return ret;
3496 }
3497
3498 static void vl_api_bd_ip_mac_details_t_handler
3499   (vl_api_bd_ip_mac_details_t * mp)
3500 {
3501   vat_main_t *vam = &vat_main;
3502
3503   print (vam->ofp,
3504          "\n%-5d %U %U",
3505          ntohl (mp->entry.bd_id),
3506          format_vl_api_mac_address, mp->entry.mac,
3507          format_vl_api_address, &mp->entry.ip);
3508 }
3509
3510 static void vl_api_bd_ip_mac_details_t_handler_json
3511   (vl_api_bd_ip_mac_details_t * mp)
3512 {
3513   vat_main_t *vam = &vat_main;
3514   vat_json_node_t *node = NULL;
3515
3516   if (VAT_JSON_ARRAY != vam->json_tree.type)
3517     {
3518       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
3519       vat_json_init_array (&vam->json_tree);
3520     }
3521   node = vat_json_array_add (&vam->json_tree);
3522
3523   vat_json_init_object (node);
3524   vat_json_object_add_uint (node, "bd_id", ntohl (mp->entry.bd_id));
3525   vat_json_object_add_string_copy (node, "mac_address",
3526                                    format (0, "%U", format_vl_api_mac_address,
3527                                            &mp->entry.mac));
3528   u8 *ip = 0;
3529
3530   ip = format (0, "%U", format_vl_api_address, &mp->entry.ip);
3531   vat_json_object_add_string_copy (node, "ip_address", ip);
3532   vec_free (ip);
3533 }
3534
3535 static int
3536 api_bd_ip_mac_dump (vat_main_t * vam)
3537 {
3538   unformat_input_t *i = vam->input;
3539   vl_api_bd_ip_mac_dump_t *mp;
3540   vl_api_control_ping_t *mp_ping;
3541   int ret;
3542   u32 bd_id;
3543   u8 bd_id_set = 0;
3544
3545   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3546     {
3547       if (unformat (i, "bd_id %d", &bd_id))
3548         {
3549           bd_id_set++;
3550         }
3551       else
3552         break;
3553     }
3554
3555   print (vam->ofp,
3556          "\n%-5s %-7s %-20s %-30s",
3557          "bd_id", "is_ipv6", "mac_address", "ip_address");
3558
3559   /* Dump Bridge Domain Ip to Mac entries */
3560   M (BD_IP_MAC_DUMP, mp);
3561
3562   if (bd_id_set)
3563     mp->bd_id = htonl (bd_id);
3564   else
3565     mp->bd_id = ~0;
3566
3567   S (mp);
3568
3569   /* Use a control ping for synchronization */
3570   MPING (CONTROL_PING, mp_ping);
3571   S (mp_ping);
3572
3573   W (ret);
3574   return ret;
3575 }
3576
3577 uword
3578 unformat_vlib_pci_addr (unformat_input_t * input, va_list * args)
3579 {
3580   vlib_pci_addr_t *addr = va_arg (*args, vlib_pci_addr_t *);
3581   u32 x[4];
3582
3583   if (!unformat (input, "%x:%x:%x.%x", &x[0], &x[1], &x[2], &x[3]))
3584     return 0;
3585
3586   addr->domain = x[0];
3587   addr->bus = x[1];
3588   addr->slot = x[2];
3589   addr->function = x[3];
3590
3591   return 1;
3592 }
3593
3594 static int
3595 api_ip_table_add_del (vat_main_t * vam)
3596 {
3597   unformat_input_t *i = vam->input;
3598   vl_api_ip_table_add_del_t *mp;
3599   u32 table_id = ~0;
3600   u8 is_ipv6 = 0;
3601   u8 is_add = 1;
3602   int ret = 0;
3603
3604   /* Parse args required to build the message */
3605   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3606     {
3607       if (unformat (i, "ipv6"))
3608         is_ipv6 = 1;
3609       else if (unformat (i, "del"))
3610         is_add = 0;
3611       else if (unformat (i, "add"))
3612         is_add = 1;
3613       else if (unformat (i, "table %d", &table_id))
3614         ;
3615       else
3616         {
3617           clib_warning ("parse error '%U'", format_unformat_error, i);
3618           return -99;
3619         }
3620     }
3621
3622   if (~0 == table_id)
3623     {
3624       errmsg ("missing table-ID");
3625       return -99;
3626     }
3627
3628   /* Construct the API message */
3629   M (IP_TABLE_ADD_DEL, mp);
3630
3631   mp->table.table_id = ntohl (table_id);
3632   mp->table.is_ip6 = is_ipv6;
3633   mp->is_add = is_add;
3634
3635   /* send it... */
3636   S (mp);
3637
3638   /* Wait for a reply... */
3639   W (ret);
3640
3641   return ret;
3642 }
3643
3644 uword
3645 unformat_fib_path (unformat_input_t * input, va_list * args)
3646 {
3647   vat_main_t *vam = va_arg (*args, vat_main_t *);
3648   vl_api_fib_path_t *path = va_arg (*args, vl_api_fib_path_t *);
3649   u32 weight, preference;
3650   mpls_label_t out_label;
3651
3652   clib_memset (path, 0, sizeof (*path));
3653   path->weight = 1;
3654   path->sw_if_index = ~0;
3655   path->rpf_id = ~0;
3656   path->n_labels = 0;
3657
3658   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3659     {
3660       if (unformat (input, "%U %U",
3661                     unformat_vl_api_ip4_address,
3662                     &path->nh.address.ip4,
3663                     api_unformat_sw_if_index, vam, &path->sw_if_index))
3664         {
3665           path->proto = FIB_API_PATH_NH_PROTO_IP4;
3666         }
3667       else if (unformat (input, "%U %U",
3668                          unformat_vl_api_ip6_address,
3669                          &path->nh.address.ip6,
3670                          api_unformat_sw_if_index, vam, &path->sw_if_index))
3671         {
3672           path->proto = FIB_API_PATH_NH_PROTO_IP6;
3673         }
3674       else if (unformat (input, "weight %u", &weight))
3675         {
3676           path->weight = weight;
3677         }
3678       else if (unformat (input, "preference %u", &preference))
3679         {
3680           path->preference = preference;
3681         }
3682       else if (unformat (input, "%U next-hop-table %d",
3683                          unformat_vl_api_ip4_address,
3684                          &path->nh.address.ip4, &path->table_id))
3685         {
3686           path->proto = FIB_API_PATH_NH_PROTO_IP4;
3687         }
3688       else if (unformat (input, "%U next-hop-table %d",
3689                          unformat_vl_api_ip6_address,
3690                          &path->nh.address.ip6, &path->table_id))
3691         {
3692           path->proto = FIB_API_PATH_NH_PROTO_IP6;
3693         }
3694       else if (unformat (input, "%U",
3695                          unformat_vl_api_ip4_address, &path->nh.address.ip4))
3696         {
3697           /*
3698            * the recursive next-hops are by default in the default table
3699            */
3700           path->table_id = 0;
3701           path->sw_if_index = ~0;
3702           path->proto = FIB_API_PATH_NH_PROTO_IP4;
3703         }
3704       else if (unformat (input, "%U",
3705                          unformat_vl_api_ip6_address, &path->nh.address.ip6))
3706         {
3707           /*
3708            * the recursive next-hops are by default in the default table
3709            */
3710           path->table_id = 0;
3711           path->sw_if_index = ~0;
3712           path->proto = FIB_API_PATH_NH_PROTO_IP6;
3713         }
3714       else if (unformat (input, "resolve-via-host"))
3715         {
3716           path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_HOST;
3717         }
3718       else if (unformat (input, "resolve-via-attached"))
3719         {
3720           path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_ATTACHED;
3721         }
3722       else if (unformat (input, "ip4-lookup-in-table %d", &path->table_id))
3723         {
3724           path->type = FIB_API_PATH_TYPE_LOCAL;
3725           path->sw_if_index = ~0;
3726           path->proto = FIB_API_PATH_NH_PROTO_IP4;
3727         }
3728       else if (unformat (input, "ip6-lookup-in-table %d", &path->table_id))
3729         {
3730           path->type = FIB_API_PATH_TYPE_LOCAL;
3731           path->sw_if_index = ~0;
3732           path->proto = FIB_API_PATH_NH_PROTO_IP6;
3733         }
3734       else if (unformat (input, "sw_if_index %d", &path->sw_if_index))
3735         ;
3736       else if (unformat (input, "via-label %d", &path->nh.via_label))
3737         {
3738           path->proto = FIB_API_PATH_NH_PROTO_MPLS;
3739           path->sw_if_index = ~0;
3740         }
3741       else if (unformat (input, "l2-input-on %d", &path->sw_if_index))
3742         {
3743           path->proto = FIB_API_PATH_NH_PROTO_ETHERNET;
3744           path->type = FIB_API_PATH_TYPE_INTERFACE_RX;
3745         }
3746       else if (unformat (input, "local"))
3747         {
3748           path->type = FIB_API_PATH_TYPE_LOCAL;
3749         }
3750       else if (unformat (input, "out-labels"))
3751         {
3752           while (unformat (input, "%d", &out_label))
3753             {
3754               path->label_stack[path->n_labels].label = out_label;
3755               path->label_stack[path->n_labels].is_uniform = 0;
3756               path->label_stack[path->n_labels].ttl = 64;
3757               path->n_labels++;
3758             }
3759         }
3760       else if (unformat (input, "via"))
3761         {
3762           /* new path, back up and return */
3763           unformat_put_input (input);
3764           unformat_put_input (input);
3765           unformat_put_input (input);
3766           unformat_put_input (input);
3767           break;
3768         }
3769       else
3770         {
3771           return (0);
3772         }
3773     }
3774
3775   path->proto = ntohl (path->proto);
3776   path->type = ntohl (path->type);
3777   path->flags = ntohl (path->flags);
3778   path->table_id = ntohl (path->table_id);
3779   path->sw_if_index = ntohl (path->sw_if_index);
3780
3781   return (1);
3782 }
3783
3784 static int
3785 api_ip_route_add_del (vat_main_t * vam)
3786 {
3787   unformat_input_t *i = vam->input;
3788   vl_api_ip_route_add_del_t *mp;
3789   u32 vrf_id = 0;
3790   u8 is_add = 1;
3791   u8 is_multipath = 0;
3792   u8 prefix_set = 0;
3793   u8 path_count = 0;
3794   vl_api_prefix_t pfx = { };
3795   vl_api_fib_path_t paths[8];
3796   int count = 1;
3797   int j;
3798   f64 before = 0;
3799   u32 random_add_del = 0;
3800   u32 *random_vector = 0;
3801   u32 random_seed = 0xdeaddabe;
3802
3803   /* Parse args required to build the message */
3804   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3805     {
3806       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
3807         prefix_set = 1;
3808       else if (unformat (i, "del"))
3809         is_add = 0;
3810       else if (unformat (i, "add"))
3811         is_add = 1;
3812       else if (unformat (i, "vrf %d", &vrf_id))
3813         ;
3814       else if (unformat (i, "count %d", &count))
3815         ;
3816       else if (unformat (i, "random"))
3817         random_add_del = 1;
3818       else if (unformat (i, "multipath"))
3819         is_multipath = 1;
3820       else if (unformat (i, "seed %d", &random_seed))
3821         ;
3822       else
3823         if (unformat
3824             (i, "via %U", unformat_fib_path, vam, &paths[path_count]))
3825         {
3826           path_count++;
3827           if (8 == path_count)
3828             {
3829               errmsg ("max 8 paths");
3830               return -99;
3831             }
3832         }
3833       else
3834         {
3835           clib_warning ("parse error '%U'", format_unformat_error, i);
3836           return -99;
3837         }
3838     }
3839
3840   if (!path_count)
3841     {
3842       errmsg ("specify a path; via ...");
3843       return -99;
3844     }
3845   if (prefix_set == 0)
3846     {
3847       errmsg ("missing prefix");
3848       return -99;
3849     }
3850
3851   /* Generate a pile of unique, random routes */
3852   if (random_add_del)
3853     {
3854       ip4_address_t *i = (ip4_address_t *) & paths[0].nh.address.ip4;
3855       u32 this_random_address;
3856       uword *random_hash;
3857
3858       random_hash = hash_create (count, sizeof (uword));
3859
3860       hash_set (random_hash, i->as_u32, 1);
3861       for (j = 0; j <= count; j++)
3862         {
3863           do
3864             {
3865               this_random_address = random_u32 (&random_seed);
3866               this_random_address =
3867                 clib_host_to_net_u32 (this_random_address);
3868             }
3869           while (hash_get (random_hash, this_random_address));
3870           vec_add1 (random_vector, this_random_address);
3871           hash_set (random_hash, this_random_address, 1);
3872         }
3873       hash_free (random_hash);
3874       set_ip4_address (&pfx.address, random_vector[0]);
3875     }
3876
3877   if (count > 1)
3878     {
3879       /* Turn on async mode */
3880       vam->async_mode = 1;
3881       vam->async_errors = 0;
3882       before = vat_time_now (vam);
3883     }
3884
3885   for (j = 0; j < count; j++)
3886     {
3887       /* Construct the API message */
3888       M2 (IP_ROUTE_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
3889
3890       mp->is_add = is_add;
3891       mp->is_multipath = is_multipath;
3892
3893       clib_memcpy (&mp->route.prefix, &pfx, sizeof (pfx));
3894       mp->route.table_id = ntohl (vrf_id);
3895       mp->route.n_paths = path_count;
3896
3897       clib_memcpy (&mp->route.paths, &paths, sizeof (paths[0]) * path_count);
3898
3899       if (random_add_del)
3900         set_ip4_address (&pfx.address, random_vector[j + 1]);
3901       else
3902         increment_address (&pfx.address);
3903       /* send it... */
3904       S (mp);
3905       /* If we receive SIGTERM, stop now... */
3906       if (vam->do_exit)
3907         break;
3908     }
3909
3910   /* When testing multiple add/del ops, use a control-ping to sync */
3911   if (count > 1)
3912     {
3913       vl_api_control_ping_t *mp_ping;
3914       f64 after;
3915       f64 timeout;
3916
3917       /* Shut off async mode */
3918       vam->async_mode = 0;
3919
3920       MPING (CONTROL_PING, mp_ping);
3921       S (mp_ping);
3922
3923       timeout = vat_time_now (vam) + 1.0;
3924       while (vat_time_now (vam) < timeout)
3925         if (vam->result_ready == 1)
3926           goto out;
3927       vam->retval = -99;
3928
3929     out:
3930       if (vam->retval == -99)
3931         errmsg ("timeout");
3932
3933       if (vam->async_errors > 0)
3934         {
3935           errmsg ("%d asynchronous errors", vam->async_errors);
3936           vam->retval = -98;
3937         }
3938       vam->async_errors = 0;
3939       after = vat_time_now (vam);
3940
3941       /* slim chance, but we might have eaten SIGTERM on the first iteration */
3942       if (j > 0)
3943         count = j;
3944
3945       print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec",
3946              count, after - before, count / (after - before));
3947     }
3948   else
3949     {
3950       int ret;
3951
3952       /* Wait for a reply... */
3953       W (ret);
3954       return ret;
3955     }
3956
3957   /* Return the good/bad news */
3958   return (vam->retval);
3959 }
3960
3961 static int
3962 api_ip_mroute_add_del (vat_main_t * vam)
3963 {
3964   unformat_input_t *i = vam->input;
3965   u8 path_set = 0, prefix_set = 0, is_add = 1;
3966   vl_api_ip_mroute_add_del_t *mp;
3967   mfib_entry_flags_t eflags = 0;
3968   vl_api_mfib_path_t path;
3969   vl_api_mprefix_t pfx = { };
3970   u32 vrf_id = 0;
3971   int ret;
3972
3973   /* Parse args required to build the message */
3974   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3975     {
3976       if (unformat (i, "%U", unformat_vl_api_mprefix, &pfx))
3977         {
3978           prefix_set = 1;
3979           pfx.grp_address_length = htons (pfx.grp_address_length);
3980         }
3981       else if (unformat (i, "del"))
3982         is_add = 0;
3983       else if (unformat (i, "add"))
3984         is_add = 1;
3985       else if (unformat (i, "vrf %d", &vrf_id))
3986         ;
3987       else if (unformat (i, "%U", unformat_mfib_itf_flags, &path.itf_flags))
3988         path.itf_flags = htonl (path.itf_flags);
3989       else if (unformat (i, "%U", unformat_mfib_entry_flags, &eflags))
3990         ;
3991       else if (unformat (i, "via %U", unformat_fib_path, vam, &path.path))
3992         path_set = 1;
3993       else
3994         {
3995           clib_warning ("parse error '%U'", format_unformat_error, i);
3996           return -99;
3997         }
3998     }
3999
4000   if (prefix_set == 0)
4001     {
4002       errmsg ("missing addresses\n");
4003       return -99;
4004     }
4005   if (path_set == 0)
4006     {
4007       errmsg ("missing path\n");
4008       return -99;
4009     }
4010
4011   /* Construct the API message */
4012   M (IP_MROUTE_ADD_DEL, mp);
4013
4014   mp->is_add = is_add;
4015   mp->is_multipath = 1;
4016
4017   clib_memcpy (&mp->route.prefix, &pfx, sizeof (pfx));
4018   mp->route.table_id = htonl (vrf_id);
4019   mp->route.n_paths = 1;
4020   mp->route.entry_flags = htonl (eflags);
4021
4022   clib_memcpy (&mp->route.paths, &path, sizeof (path));
4023
4024   /* send it... */
4025   S (mp);
4026   /* Wait for a reply... */
4027   W (ret);
4028   return ret;
4029 }
4030
4031 static int
4032 api_sw_interface_set_unnumbered (vat_main_t * vam)
4033 {
4034   unformat_input_t *i = vam->input;
4035   vl_api_sw_interface_set_unnumbered_t *mp;
4036   u32 sw_if_index;
4037   u32 unnum_sw_index = ~0;
4038   u8 is_add = 1;
4039   u8 sw_if_index_set = 0;
4040   int ret;
4041
4042   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4043     {
4044       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4045         sw_if_index_set = 1;
4046       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4047         sw_if_index_set = 1;
4048       else if (unformat (i, "unnum_if_index %d", &unnum_sw_index))
4049         ;
4050       else if (unformat (i, "del"))
4051         is_add = 0;
4052       else
4053         {
4054           clib_warning ("parse error '%U'", format_unformat_error, i);
4055           return -99;
4056         }
4057     }
4058
4059   if (sw_if_index_set == 0)
4060     {
4061       errmsg ("missing interface name or sw_if_index");
4062       return -99;
4063     }
4064
4065   M (SW_INTERFACE_SET_UNNUMBERED, mp);
4066
4067   mp->sw_if_index = ntohl (sw_if_index);
4068   mp->unnumbered_sw_if_index = ntohl (unnum_sw_index);
4069   mp->is_add = is_add;
4070
4071   S (mp);
4072   W (ret);
4073   return ret;
4074 }
4075
4076
4077 static int
4078 api_create_vlan_subif (vat_main_t * vam)
4079 {
4080   unformat_input_t *i = vam->input;
4081   vl_api_create_vlan_subif_t *mp;
4082   u32 sw_if_index;
4083   u8 sw_if_index_set = 0;
4084   u32 vlan_id;
4085   u8 vlan_id_set = 0;
4086   int ret;
4087
4088   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4089     {
4090       if (unformat (i, "sw_if_index %d", &sw_if_index))
4091         sw_if_index_set = 1;
4092       else
4093         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4094         sw_if_index_set = 1;
4095       else if (unformat (i, "vlan %d", &vlan_id))
4096         vlan_id_set = 1;
4097       else
4098         {
4099           clib_warning ("parse error '%U'", format_unformat_error, i);
4100           return -99;
4101         }
4102     }
4103
4104   if (sw_if_index_set == 0)
4105     {
4106       errmsg ("missing interface name or sw_if_index");
4107       return -99;
4108     }
4109
4110   if (vlan_id_set == 0)
4111     {
4112       errmsg ("missing vlan_id");
4113       return -99;
4114     }
4115   M (CREATE_VLAN_SUBIF, mp);
4116
4117   mp->sw_if_index = ntohl (sw_if_index);
4118   mp->vlan_id = ntohl (vlan_id);
4119
4120   S (mp);
4121   W (ret);
4122   return ret;
4123 }
4124
4125 #define foreach_create_subif_bit                \
4126 _(no_tags)                                      \
4127 _(one_tag)                                      \
4128 _(two_tags)                                     \
4129 _(dot1ad)                                       \
4130 _(exact_match)                                  \
4131 _(default_sub)                                  \
4132 _(outer_vlan_id_any)                            \
4133 _(inner_vlan_id_any)
4134
4135 #define foreach_create_subif_flag               \
4136 _(0, "no_tags")                                 \
4137 _(1, "one_tag")                                 \
4138 _(2, "two_tags")                                \
4139 _(3, "dot1ad")                                  \
4140 _(4, "exact_match")                             \
4141 _(5, "default_sub")                             \
4142 _(6, "outer_vlan_id_any")                       \
4143 _(7, "inner_vlan_id_any")
4144
4145 static int
4146 api_create_subif (vat_main_t * vam)
4147 {
4148   unformat_input_t *i = vam->input;
4149   vl_api_create_subif_t *mp;
4150   u32 sw_if_index;
4151   u8 sw_if_index_set = 0;
4152   u32 sub_id;
4153   u8 sub_id_set = 0;
4154   u32 __attribute__ ((unused)) no_tags = 0;
4155   u32 __attribute__ ((unused)) one_tag = 0;
4156   u32 __attribute__ ((unused)) two_tags = 0;
4157   u32 __attribute__ ((unused)) dot1ad = 0;
4158   u32 __attribute__ ((unused)) exact_match = 0;
4159   u32 __attribute__ ((unused)) default_sub = 0;
4160   u32 __attribute__ ((unused)) outer_vlan_id_any = 0;
4161   u32 __attribute__ ((unused)) inner_vlan_id_any = 0;
4162   u32 tmp;
4163   u16 outer_vlan_id = 0;
4164   u16 inner_vlan_id = 0;
4165   int ret;
4166
4167   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4168     {
4169       if (unformat (i, "sw_if_index %d", &sw_if_index))
4170         sw_if_index_set = 1;
4171       else
4172         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4173         sw_if_index_set = 1;
4174       else if (unformat (i, "sub_id %d", &sub_id))
4175         sub_id_set = 1;
4176       else if (unformat (i, "outer_vlan_id %d", &tmp))
4177         outer_vlan_id = tmp;
4178       else if (unformat (i, "inner_vlan_id %d", &tmp))
4179         inner_vlan_id = tmp;
4180
4181 #define _(a) else if (unformat (i, #a)) a = 1 ;
4182       foreach_create_subif_bit
4183 #undef _
4184         else
4185         {
4186           clib_warning ("parse error '%U'", format_unformat_error, i);
4187           return -99;
4188         }
4189     }
4190
4191   if (sw_if_index_set == 0)
4192     {
4193       errmsg ("missing interface name or sw_if_index");
4194       return -99;
4195     }
4196
4197   if (sub_id_set == 0)
4198     {
4199       errmsg ("missing sub_id");
4200       return -99;
4201     }
4202   M (CREATE_SUBIF, mp);
4203
4204   mp->sw_if_index = ntohl (sw_if_index);
4205   mp->sub_id = ntohl (sub_id);
4206
4207 #define _(a,b) mp->sub_if_flags |= (1 << a);
4208   foreach_create_subif_flag;
4209 #undef _
4210
4211   mp->outer_vlan_id = ntohs (outer_vlan_id);
4212   mp->inner_vlan_id = ntohs (inner_vlan_id);
4213
4214   S (mp);
4215   W (ret);
4216   return ret;
4217 }
4218
4219 static int
4220 api_ip_table_replace_begin (vat_main_t * vam)
4221 {
4222   unformat_input_t *i = vam->input;
4223   vl_api_ip_table_replace_begin_t *mp;
4224   u32 table_id = 0;
4225   u8 is_ipv6 = 0;
4226
4227   int ret;
4228   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4229     {
4230       if (unformat (i, "table %d", &table_id))
4231         ;
4232       else if (unformat (i, "ipv6"))
4233         is_ipv6 = 1;
4234       else
4235         {
4236           clib_warning ("parse error '%U'", format_unformat_error, i);
4237           return -99;
4238         }
4239     }
4240
4241   M (IP_TABLE_REPLACE_BEGIN, mp);
4242
4243   mp->table.table_id = ntohl (table_id);
4244   mp->table.is_ip6 = is_ipv6;
4245
4246   S (mp);
4247   W (ret);
4248   return ret;
4249 }
4250
4251 static int
4252 api_ip_table_flush (vat_main_t * vam)
4253 {
4254   unformat_input_t *i = vam->input;
4255   vl_api_ip_table_flush_t *mp;
4256   u32 table_id = 0;
4257   u8 is_ipv6 = 0;
4258
4259   int ret;
4260   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4261     {
4262       if (unformat (i, "table %d", &table_id))
4263         ;
4264       else if (unformat (i, "ipv6"))
4265         is_ipv6 = 1;
4266       else
4267         {
4268           clib_warning ("parse error '%U'", format_unformat_error, i);
4269           return -99;
4270         }
4271     }
4272
4273   M (IP_TABLE_FLUSH, mp);
4274
4275   mp->table.table_id = ntohl (table_id);
4276   mp->table.is_ip6 = is_ipv6;
4277
4278   S (mp);
4279   W (ret);
4280   return ret;
4281 }
4282
4283 static int
4284 api_ip_table_replace_end (vat_main_t * vam)
4285 {
4286   unformat_input_t *i = vam->input;
4287   vl_api_ip_table_replace_end_t *mp;
4288   u32 table_id = 0;
4289   u8 is_ipv6 = 0;
4290
4291   int ret;
4292   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4293     {
4294       if (unformat (i, "table %d", &table_id))
4295         ;
4296       else if (unformat (i, "ipv6"))
4297         is_ipv6 = 1;
4298       else
4299         {
4300           clib_warning ("parse error '%U'", format_unformat_error, i);
4301           return -99;
4302         }
4303     }
4304
4305   M (IP_TABLE_REPLACE_END, mp);
4306
4307   mp->table.table_id = ntohl (table_id);
4308   mp->table.is_ip6 = is_ipv6;
4309
4310   S (mp);
4311   W (ret);
4312   return ret;
4313 }
4314
4315 static int
4316 api_set_ip_flow_hash (vat_main_t * vam)
4317 {
4318   unformat_input_t *i = vam->input;
4319   vl_api_set_ip_flow_hash_t *mp;
4320   u32 vrf_id = 0;
4321   u8 is_ipv6 = 0;
4322   u8 vrf_id_set = 0;
4323   u8 src = 0;
4324   u8 dst = 0;
4325   u8 sport = 0;
4326   u8 dport = 0;
4327   u8 proto = 0;
4328   u8 reverse = 0;
4329   int ret;
4330
4331   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4332     {
4333       if (unformat (i, "vrf %d", &vrf_id))
4334         vrf_id_set = 1;
4335       else if (unformat (i, "ipv6"))
4336         is_ipv6 = 1;
4337       else if (unformat (i, "src"))
4338         src = 1;
4339       else if (unformat (i, "dst"))
4340         dst = 1;
4341       else if (unformat (i, "sport"))
4342         sport = 1;
4343       else if (unformat (i, "dport"))
4344         dport = 1;
4345       else if (unformat (i, "proto"))
4346         proto = 1;
4347       else if (unformat (i, "reverse"))
4348         reverse = 1;
4349
4350       else
4351         {
4352           clib_warning ("parse error '%U'", format_unformat_error, i);
4353           return -99;
4354         }
4355     }
4356
4357   if (vrf_id_set == 0)
4358     {
4359       errmsg ("missing vrf id");
4360       return -99;
4361     }
4362
4363   M (SET_IP_FLOW_HASH, mp);
4364   mp->src = src;
4365   mp->dst = dst;
4366   mp->sport = sport;
4367   mp->dport = dport;
4368   mp->proto = proto;
4369   mp->reverse = reverse;
4370   mp->vrf_id = ntohl (vrf_id);
4371   mp->is_ipv6 = is_ipv6;
4372
4373   S (mp);
4374   W (ret);
4375   return ret;
4376 }
4377
4378 static int
4379 api_sw_interface_ip6_enable_disable (vat_main_t * vam)
4380 {
4381   unformat_input_t *i = vam->input;
4382   vl_api_sw_interface_ip6_enable_disable_t *mp;
4383   u32 sw_if_index;
4384   u8 sw_if_index_set = 0;
4385   u8 enable = 0;
4386   int ret;
4387
4388   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4389     {
4390       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4391         sw_if_index_set = 1;
4392       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4393         sw_if_index_set = 1;
4394       else if (unformat (i, "enable"))
4395         enable = 1;
4396       else if (unformat (i, "disable"))
4397         enable = 0;
4398       else
4399         {
4400           clib_warning ("parse error '%U'", format_unformat_error, i);
4401           return -99;
4402         }
4403     }
4404
4405   if (sw_if_index_set == 0)
4406     {
4407       errmsg ("missing interface name or sw_if_index");
4408       return -99;
4409     }
4410
4411   M (SW_INTERFACE_IP6_ENABLE_DISABLE, mp);
4412
4413   mp->sw_if_index = ntohl (sw_if_index);
4414   mp->enable = enable;
4415
4416   S (mp);
4417   W (ret);
4418   return ret;
4419 }
4420
4421
4422 static int
4423 api_l2_patch_add_del (vat_main_t * vam)
4424 {
4425   unformat_input_t *i = vam->input;
4426   vl_api_l2_patch_add_del_t *mp;
4427   u32 rx_sw_if_index;
4428   u8 rx_sw_if_index_set = 0;
4429   u32 tx_sw_if_index;
4430   u8 tx_sw_if_index_set = 0;
4431   u8 is_add = 1;
4432   int ret;
4433
4434   /* Parse args required to build the message */
4435   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4436     {
4437       if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index))
4438         rx_sw_if_index_set = 1;
4439       else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
4440         tx_sw_if_index_set = 1;
4441       else if (unformat (i, "rx"))
4442         {
4443           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4444             {
4445               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
4446                             &rx_sw_if_index))
4447                 rx_sw_if_index_set = 1;
4448             }
4449           else
4450             break;
4451         }
4452       else if (unformat (i, "tx"))
4453         {
4454           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4455             {
4456               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
4457                             &tx_sw_if_index))
4458                 tx_sw_if_index_set = 1;
4459             }
4460           else
4461             break;
4462         }
4463       else if (unformat (i, "del"))
4464         is_add = 0;
4465       else
4466         break;
4467     }
4468
4469   if (rx_sw_if_index_set == 0)
4470     {
4471       errmsg ("missing rx interface name or rx_sw_if_index");
4472       return -99;
4473     }
4474
4475   if (tx_sw_if_index_set == 0)
4476     {
4477       errmsg ("missing tx interface name or tx_sw_if_index");
4478       return -99;
4479     }
4480
4481   M (L2_PATCH_ADD_DEL, mp);
4482
4483   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
4484   mp->tx_sw_if_index = ntohl (tx_sw_if_index);
4485   mp->is_add = is_add;
4486
4487   S (mp);
4488   W (ret);
4489   return ret;
4490 }
4491
4492 u8 is_del;
4493 u8 localsid_addr[16];
4494 u8 end_psp;
4495 u8 behavior;
4496 u32 sw_if_index;
4497 u32 vlan_index;
4498 u32 fib_table;
4499 u8 nh_addr[16];
4500
4501 static int
4502 api_ioam_enable (vat_main_t * vam)
4503 {
4504   unformat_input_t *input = vam->input;
4505   vl_api_ioam_enable_t *mp;
4506   u32 id = 0;
4507   int has_trace_option = 0;
4508   int has_pot_option = 0;
4509   int has_seqno_option = 0;
4510   int has_analyse_option = 0;
4511   int ret;
4512
4513   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
4514     {
4515       if (unformat (input, "trace"))
4516         has_trace_option = 1;
4517       else if (unformat (input, "pot"))
4518         has_pot_option = 1;
4519       else if (unformat (input, "seqno"))
4520         has_seqno_option = 1;
4521       else if (unformat (input, "analyse"))
4522         has_analyse_option = 1;
4523       else
4524         break;
4525     }
4526   M (IOAM_ENABLE, mp);
4527   mp->id = htons (id);
4528   mp->seqno = has_seqno_option;
4529   mp->analyse = has_analyse_option;
4530   mp->pot_enable = has_pot_option;
4531   mp->trace_enable = has_trace_option;
4532
4533   S (mp);
4534   W (ret);
4535   return ret;
4536 }
4537
4538
4539 static int
4540 api_ioam_disable (vat_main_t * vam)
4541 {
4542   vl_api_ioam_disable_t *mp;
4543   int ret;
4544
4545   M (IOAM_DISABLE, mp);
4546   S (mp);
4547   W (ret);
4548   return ret;
4549 }
4550
4551 #define foreach_tcp_proto_field                 \
4552 _(src_port)                                     \
4553 _(dst_port)
4554
4555 #define foreach_udp_proto_field                 \
4556 _(src_port)                                     \
4557 _(dst_port)
4558
4559 #define foreach_ip4_proto_field                 \
4560 _(src_address)                                  \
4561 _(dst_address)                                  \
4562 _(tos)                                          \
4563 _(length)                                       \
4564 _(fragment_id)                                  \
4565 _(ttl)                                          \
4566 _(protocol)                                     \
4567 _(checksum)
4568
4569 typedef struct
4570 {
4571   u16 src_port, dst_port;
4572 } tcpudp_header_t;
4573
4574 #if VPP_API_TEST_BUILTIN == 0
4575 uword
4576 unformat_tcp_mask (unformat_input_t * input, va_list * args)
4577 {
4578   u8 **maskp = va_arg (*args, u8 **);
4579   u8 *mask = 0;
4580   u8 found_something = 0;
4581   tcp_header_t *tcp;
4582
4583 #define _(a) u8 a=0;
4584   foreach_tcp_proto_field;
4585 #undef _
4586
4587   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
4588     {
4589       if (0);
4590 #define _(a) else if (unformat (input, #a)) a=1;
4591       foreach_tcp_proto_field
4592 #undef _
4593         else
4594         break;
4595     }
4596
4597 #define _(a) found_something += a;
4598   foreach_tcp_proto_field;
4599 #undef _
4600
4601   if (found_something == 0)
4602     return 0;
4603
4604   vec_validate (mask, sizeof (*tcp) - 1);
4605
4606   tcp = (tcp_header_t *) mask;
4607
4608 #define _(a) if (a) clib_memset (&tcp->a, 0xff, sizeof (tcp->a));
4609   foreach_tcp_proto_field;
4610 #undef _
4611
4612   *maskp = mask;
4613   return 1;
4614 }
4615
4616 uword
4617 unformat_udp_mask (unformat_input_t * input, va_list * args)
4618 {
4619   u8 **maskp = va_arg (*args, u8 **);
4620   u8 *mask = 0;
4621   u8 found_something = 0;
4622   udp_header_t *udp;
4623
4624 #define _(a) u8 a=0;
4625   foreach_udp_proto_field;
4626 #undef _
4627
4628   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
4629     {
4630       if (0);
4631 #define _(a) else if (unformat (input, #a)) a=1;
4632       foreach_udp_proto_field
4633 #undef _
4634         else
4635         break;
4636     }
4637
4638 #define _(a) found_something += a;
4639   foreach_udp_proto_field;
4640 #undef _
4641
4642   if (found_something == 0)
4643     return 0;
4644
4645   vec_validate (mask, sizeof (*udp) - 1);
4646
4647   udp = (udp_header_t *) mask;
4648
4649 #define _(a) if (a) clib_memset (&udp->a, 0xff, sizeof (udp->a));
4650   foreach_udp_proto_field;
4651 #undef _
4652
4653   *maskp = mask;
4654   return 1;
4655 }
4656
4657 uword
4658 unformat_l4_mask (unformat_input_t * input, va_list * args)
4659 {
4660   u8 **maskp = va_arg (*args, u8 **);
4661   u16 src_port = 0, dst_port = 0;
4662   tcpudp_header_t *tcpudp;
4663
4664   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
4665     {
4666       if (unformat (input, "tcp %U", unformat_tcp_mask, maskp))
4667         return 1;
4668       else if (unformat (input, "udp %U", unformat_udp_mask, maskp))
4669         return 1;
4670       else if (unformat (input, "src_port"))
4671         src_port = 0xFFFF;
4672       else if (unformat (input, "dst_port"))
4673         dst_port = 0xFFFF;
4674       else
4675         return 0;
4676     }
4677
4678   if (!src_port && !dst_port)
4679     return 0;
4680
4681   u8 *mask = 0;
4682   vec_validate (mask, sizeof (tcpudp_header_t) - 1);
4683
4684   tcpudp = (tcpudp_header_t *) mask;
4685   tcpudp->src_port = src_port;
4686   tcpudp->dst_port = dst_port;
4687
4688   *maskp = mask;
4689
4690   return 1;
4691 }
4692
4693 uword
4694 unformat_ip4_mask (unformat_input_t * input, va_list * args)
4695 {
4696   u8 **maskp = va_arg (*args, u8 **);
4697   u8 *mask = 0;
4698   u8 found_something = 0;
4699   ip4_header_t *ip;
4700
4701 #define _(a) u8 a=0;
4702   foreach_ip4_proto_field;
4703 #undef _
4704   u8 version = 0;
4705   u8 hdr_length = 0;
4706
4707
4708   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
4709     {
4710       if (unformat (input, "version"))
4711         version = 1;
4712       else if (unformat (input, "hdr_length"))
4713         hdr_length = 1;
4714       else if (unformat (input, "src"))
4715         src_address = 1;
4716       else if (unformat (input, "dst"))
4717         dst_address = 1;
4718       else if (unformat (input, "proto"))
4719         protocol = 1;
4720
4721 #define _(a) else if (unformat (input, #a)) a=1;
4722       foreach_ip4_proto_field
4723 #undef _
4724         else
4725         break;
4726     }
4727
4728 #define _(a) found_something += a;
4729   foreach_ip4_proto_field;
4730 #undef _
4731
4732   if (found_something == 0)
4733     return 0;
4734
4735   vec_validate (mask, sizeof (*ip) - 1);
4736
4737   ip = (ip4_header_t *) mask;
4738
4739 #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
4740   foreach_ip4_proto_field;
4741 #undef _
4742
4743   ip->ip_version_and_header_length = 0;
4744
4745   if (version)
4746     ip->ip_version_and_header_length |= 0xF0;
4747
4748   if (hdr_length)
4749     ip->ip_version_and_header_length |= 0x0F;
4750
4751   *maskp = mask;
4752   return 1;
4753 }
4754
4755 #define foreach_ip6_proto_field                 \
4756 _(src_address)                                  \
4757 _(dst_address)                                  \
4758 _(payload_length)                               \
4759 _(hop_limit)                                    \
4760 _(protocol)
4761
4762 uword
4763 unformat_ip6_mask (unformat_input_t * input, va_list * args)
4764 {
4765   u8 **maskp = va_arg (*args, u8 **);
4766   u8 *mask = 0;
4767   u8 found_something = 0;
4768   ip6_header_t *ip;
4769   u32 ip_version_traffic_class_and_flow_label;
4770
4771 #define _(a) u8 a=0;
4772   foreach_ip6_proto_field;
4773 #undef _
4774   u8 version = 0;
4775   u8 traffic_class = 0;
4776   u8 flow_label = 0;
4777
4778   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
4779     {
4780       if (unformat (input, "version"))
4781         version = 1;
4782       else if (unformat (input, "traffic-class"))
4783         traffic_class = 1;
4784       else if (unformat (input, "flow-label"))
4785         flow_label = 1;
4786       else if (unformat (input, "src"))
4787         src_address = 1;
4788       else if (unformat (input, "dst"))
4789         dst_address = 1;
4790       else if (unformat (input, "proto"))
4791         protocol = 1;
4792
4793 #define _(a) else if (unformat (input, #a)) a=1;
4794       foreach_ip6_proto_field
4795 #undef _
4796         else
4797         break;
4798     }
4799
4800 #define _(a) found_something += a;
4801   foreach_ip6_proto_field;
4802 #undef _
4803
4804   if (found_something == 0)
4805     return 0;
4806
4807   vec_validate (mask, sizeof (*ip) - 1);
4808
4809   ip = (ip6_header_t *) mask;
4810
4811 #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
4812   foreach_ip6_proto_field;
4813 #undef _
4814
4815   ip_version_traffic_class_and_flow_label = 0;
4816
4817   if (version)
4818     ip_version_traffic_class_and_flow_label |= 0xF0000000;
4819
4820   if (traffic_class)
4821     ip_version_traffic_class_and_flow_label |= 0x0FF00000;
4822
4823   if (flow_label)
4824     ip_version_traffic_class_and_flow_label |= 0x000FFFFF;
4825
4826   ip->ip_version_traffic_class_and_flow_label =
4827     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
4828
4829   *maskp = mask;
4830   return 1;
4831 }
4832
4833 uword
4834 unformat_l3_mask (unformat_input_t * input, va_list * args)
4835 {
4836   u8 **maskp = va_arg (*args, u8 **);
4837
4838   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
4839     {
4840       if (unformat (input, "ip4 %U", unformat_ip4_mask, maskp))
4841         return 1;
4842       else if (unformat (input, "ip6 %U", unformat_ip6_mask, maskp))
4843         return 1;
4844       else
4845         break;
4846     }
4847   return 0;
4848 }
4849
4850 uword
4851 unformat_l2_mask (unformat_input_t * input, va_list * args)
4852 {
4853   u8 **maskp = va_arg (*args, u8 **);
4854   u8 *mask = 0;
4855   u8 src = 0;
4856   u8 dst = 0;
4857   u8 proto = 0;
4858   u8 tag1 = 0;
4859   u8 tag2 = 0;
4860   u8 ignore_tag1 = 0;
4861   u8 ignore_tag2 = 0;
4862   u8 cos1 = 0;
4863   u8 cos2 = 0;
4864   u8 dot1q = 0;
4865   u8 dot1ad = 0;
4866   int len = 14;
4867
4868   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
4869     {
4870       if (unformat (input, "src"))
4871         src = 1;
4872       else if (unformat (input, "dst"))
4873         dst = 1;
4874       else if (unformat (input, "proto"))
4875         proto = 1;
4876       else if (unformat (input, "tag1"))
4877         tag1 = 1;
4878       else if (unformat (input, "tag2"))
4879         tag2 = 1;
4880       else if (unformat (input, "ignore-tag1"))
4881         ignore_tag1 = 1;
4882       else if (unformat (input, "ignore-tag2"))
4883         ignore_tag2 = 1;
4884       else if (unformat (input, "cos1"))
4885         cos1 = 1;
4886       else if (unformat (input, "cos2"))
4887         cos2 = 1;
4888       else if (unformat (input, "dot1q"))
4889         dot1q = 1;
4890       else if (unformat (input, "dot1ad"))
4891         dot1ad = 1;
4892       else
4893         break;
4894     }
4895   if ((src + dst + proto + tag1 + tag2 + dot1q + dot1ad +
4896        ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
4897     return 0;
4898
4899   if (tag1 || ignore_tag1 || cos1 || dot1q)
4900     len = 18;
4901   if (tag2 || ignore_tag2 || cos2 || dot1ad)
4902     len = 22;
4903
4904   vec_validate (mask, len - 1);
4905
4906   if (dst)
4907     clib_memset (mask, 0xff, 6);
4908
4909   if (src)
4910     clib_memset (mask + 6, 0xff, 6);
4911
4912   if (tag2 || dot1ad)
4913     {
4914       /* inner vlan tag */
4915       if (tag2)
4916         {
4917           mask[19] = 0xff;
4918           mask[18] = 0x0f;
4919         }
4920       if (cos2)
4921         mask[18] |= 0xe0;
4922       if (proto)
4923         mask[21] = mask[20] = 0xff;
4924       if (tag1)
4925         {
4926           mask[15] = 0xff;
4927           mask[14] = 0x0f;
4928         }
4929       if (cos1)
4930         mask[14] |= 0xe0;
4931       *maskp = mask;
4932       return 1;
4933     }
4934   if (tag1 | dot1q)
4935     {
4936       if (tag1)
4937         {
4938           mask[15] = 0xff;
4939           mask[14] = 0x0f;
4940         }
4941       if (cos1)
4942         mask[14] |= 0xe0;
4943       if (proto)
4944         mask[16] = mask[17] = 0xff;
4945
4946       *maskp = mask;
4947       return 1;
4948     }
4949   if (cos2)
4950     mask[18] |= 0xe0;
4951   if (cos1)
4952     mask[14] |= 0xe0;
4953   if (proto)
4954     mask[12] = mask[13] = 0xff;
4955
4956   *maskp = mask;
4957   return 1;
4958 }
4959
4960 uword
4961 unformat_classify_mask (unformat_input_t * input, va_list * args)
4962 {
4963   u8 **maskp = va_arg (*args, u8 **);
4964   u32 *skipp = va_arg (*args, u32 *);
4965   u32 *matchp = va_arg (*args, u32 *);
4966   u32 match;
4967   u8 *mask = 0;
4968   u8 *l2 = 0;
4969   u8 *l3 = 0;
4970   u8 *l4 = 0;
4971   int i;
4972
4973   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
4974     {
4975       if (unformat (input, "hex %U", unformat_hex_string, &mask))
4976         ;
4977       else if (unformat (input, "l2 %U", unformat_l2_mask, &l2))
4978         ;
4979       else if (unformat (input, "l3 %U", unformat_l3_mask, &l3))
4980         ;
4981       else if (unformat (input, "l4 %U", unformat_l4_mask, &l4))
4982         ;
4983       else
4984         break;
4985     }
4986
4987   if (l4 && !l3)
4988     {
4989       vec_free (mask);
4990       vec_free (l2);
4991       vec_free (l4);
4992       return 0;
4993     }
4994
4995   if (mask || l2 || l3 || l4)
4996     {
4997       if (l2 || l3 || l4)
4998         {
4999           /* "With a free Ethernet header in every package" */
5000           if (l2 == 0)
5001             vec_validate (l2, 13);
5002           mask = l2;
5003           if (vec_len (l3))
5004             {
5005               vec_append (mask, l3);
5006               vec_free (l3);
5007             }
5008           if (vec_len (l4))
5009             {
5010               vec_append (mask, l4);
5011               vec_free (l4);
5012             }
5013         }
5014
5015       /* Scan forward looking for the first significant mask octet */
5016       for (i = 0; i < vec_len (mask); i++)
5017         if (mask[i])
5018           break;
5019
5020       /* compute (skip, match) params */
5021       *skipp = i / sizeof (u32x4);
5022       vec_delete (mask, *skipp * sizeof (u32x4), 0);
5023
5024       /* Pad mask to an even multiple of the vector size */
5025       while (vec_len (mask) % sizeof (u32x4))
5026         vec_add1 (mask, 0);
5027
5028       match = vec_len (mask) / sizeof (u32x4);
5029
5030       for (i = match * sizeof (u32x4); i > 0; i -= sizeof (u32x4))
5031         {
5032           u64 *tmp = (u64 *) (mask + (i - sizeof (u32x4)));
5033           if (*tmp || *(tmp + 1))
5034             break;
5035           match--;
5036         }
5037       if (match == 0)
5038         clib_warning ("BUG: match 0");
5039
5040       _vec_len (mask) = match * sizeof (u32x4);
5041
5042       *matchp = match;
5043       *maskp = mask;
5044
5045       return 1;
5046     }
5047
5048   return 0;
5049 }
5050 #endif /* VPP_API_TEST_BUILTIN */
5051
5052 #define foreach_l2_next                         \
5053 _(drop, DROP)                                   \
5054 _(ethernet, ETHERNET_INPUT)                     \
5055 _(ip4, IP4_INPUT)                               \
5056 _(ip6, IP6_INPUT)
5057
5058 uword
5059 unformat_l2_next_index (unformat_input_t * input, va_list * args)
5060 {
5061   u32 *miss_next_indexp = va_arg (*args, u32 *);
5062   u32 next_index = 0;
5063   u32 tmp;
5064
5065 #define _(n,N) \
5066   if (unformat (input, #n)) { next_index = L2_INPUT_CLASSIFY_NEXT_##N; goto out;}
5067   foreach_l2_next;
5068 #undef _
5069
5070   if (unformat (input, "%d", &tmp))
5071     {
5072       next_index = tmp;
5073       goto out;
5074     }
5075
5076   return 0;
5077
5078 out:
5079   *miss_next_indexp = next_index;
5080   return 1;
5081 }
5082
5083 #define foreach_ip_next                         \
5084 _(drop, DROP)                                   \
5085 _(local, LOCAL)                                 \
5086 _(rewrite, REWRITE)
5087
5088 uword
5089 api_unformat_ip_next_index (unformat_input_t * input, va_list * args)
5090 {
5091   u32 *miss_next_indexp = va_arg (*args, u32 *);
5092   u32 next_index = 0;
5093   u32 tmp;
5094
5095 #define _(n,N) \
5096   if (unformat (input, #n)) { next_index = IP_LOOKUP_NEXT_##N; goto out;}
5097   foreach_ip_next;
5098 #undef _
5099
5100   if (unformat (input, "%d", &tmp))
5101     {
5102       next_index = tmp;
5103       goto out;
5104     }
5105
5106   return 0;
5107
5108 out:
5109   *miss_next_indexp = next_index;
5110   return 1;
5111 }
5112
5113 #define foreach_acl_next                        \
5114 _(deny, DENY)
5115
5116 uword
5117 api_unformat_acl_next_index (unformat_input_t * input, va_list * args)
5118 {
5119   u32 *miss_next_indexp = va_arg (*args, u32 *);
5120   u32 next_index = 0;
5121   u32 tmp;
5122
5123 #define _(n,N) \
5124   if (unformat (input, #n)) { next_index = ACL_NEXT_INDEX_##N; goto out;}
5125   foreach_acl_next;
5126 #undef _
5127
5128   if (unformat (input, "permit"))
5129     {
5130       next_index = ~0;
5131       goto out;
5132     }
5133   else if (unformat (input, "%d", &tmp))
5134     {
5135       next_index = tmp;
5136       goto out;
5137     }
5138
5139   return 0;
5140
5141 out:
5142   *miss_next_indexp = next_index;
5143   return 1;
5144 }
5145
5146 uword
5147 unformat_policer_precolor (unformat_input_t * input, va_list * args)
5148 {
5149   u32 *r = va_arg (*args, u32 *);
5150
5151   if (unformat (input, "conform-color"))
5152     *r = POLICE_CONFORM;
5153   else if (unformat (input, "exceed-color"))
5154     *r = POLICE_EXCEED;
5155   else
5156     return 0;
5157
5158   return 1;
5159 }
5160
5161 #if VPP_API_TEST_BUILTIN == 0
5162 uword
5163 unformat_l4_match (unformat_input_t * input, va_list * args)
5164 {
5165   u8 **matchp = va_arg (*args, u8 **);
5166
5167   u8 *proto_header = 0;
5168   int src_port = 0;
5169   int dst_port = 0;
5170
5171   tcpudp_header_t h;
5172
5173   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5174     {
5175       if (unformat (input, "src_port %d", &src_port))
5176         ;
5177       else if (unformat (input, "dst_port %d", &dst_port))
5178         ;
5179       else
5180         return 0;
5181     }
5182
5183   h.src_port = clib_host_to_net_u16 (src_port);
5184   h.dst_port = clib_host_to_net_u16 (dst_port);
5185   vec_validate (proto_header, sizeof (h) - 1);
5186   memcpy (proto_header, &h, sizeof (h));
5187
5188   *matchp = proto_header;
5189
5190   return 1;
5191 }
5192
5193 uword
5194 unformat_ip4_match (unformat_input_t * input, va_list * args)
5195 {
5196   u8 **matchp = va_arg (*args, u8 **);
5197   u8 *match = 0;
5198   ip4_header_t *ip;
5199   int version = 0;
5200   u32 version_val;
5201   int hdr_length = 0;
5202   u32 hdr_length_val;
5203   int src = 0, dst = 0;
5204   ip4_address_t src_val, dst_val;
5205   int proto = 0;
5206   u32 proto_val;
5207   int tos = 0;
5208   u32 tos_val;
5209   int length = 0;
5210   u32 length_val;
5211   int fragment_id = 0;
5212   u32 fragment_id_val;
5213   int ttl = 0;
5214   int ttl_val;
5215   int checksum = 0;
5216   u32 checksum_val;
5217
5218   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5219     {
5220       if (unformat (input, "version %d", &version_val))
5221         version = 1;
5222       else if (unformat (input, "hdr_length %d", &hdr_length_val))
5223         hdr_length = 1;
5224       else if (unformat (input, "src %U", unformat_ip4_address, &src_val))
5225         src = 1;
5226       else if (unformat (input, "dst %U", unformat_ip4_address, &dst_val))
5227         dst = 1;
5228       else if (unformat (input, "proto %d", &proto_val))
5229         proto = 1;
5230       else if (unformat (input, "tos %d", &tos_val))
5231         tos = 1;
5232       else if (unformat (input, "length %d", &length_val))
5233         length = 1;
5234       else if (unformat (input, "fragment_id %d", &fragment_id_val))
5235         fragment_id = 1;
5236       else if (unformat (input, "ttl %d", &ttl_val))
5237         ttl = 1;
5238       else if (unformat (input, "checksum %d", &checksum_val))
5239         checksum = 1;
5240       else
5241         break;
5242     }
5243
5244   if (version + hdr_length + src + dst + proto + tos + length + fragment_id
5245       + ttl + checksum == 0)
5246     return 0;
5247
5248   /*
5249    * Aligned because we use the real comparison functions
5250    */
5251   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
5252
5253   ip = (ip4_header_t *) match;
5254
5255   /* These are realistically matched in practice */
5256   if (src)
5257     ip->src_address.as_u32 = src_val.as_u32;
5258
5259   if (dst)
5260     ip->dst_address.as_u32 = dst_val.as_u32;
5261
5262   if (proto)
5263     ip->protocol = proto_val;
5264
5265
5266   /* These are not, but they're included for completeness */
5267   if (version)
5268     ip->ip_version_and_header_length |= (version_val & 0xF) << 4;
5269
5270   if (hdr_length)
5271     ip->ip_version_and_header_length |= (hdr_length_val & 0xF);
5272
5273   if (tos)
5274     ip->tos = tos_val;
5275
5276   if (length)
5277     ip->length = clib_host_to_net_u16 (length_val);
5278
5279   if (ttl)
5280     ip->ttl = ttl_val;
5281
5282   if (checksum)
5283     ip->checksum = clib_host_to_net_u16 (checksum_val);
5284
5285   *matchp = match;
5286   return 1;
5287 }
5288
5289 uword
5290 unformat_ip6_match (unformat_input_t * input, va_list * args)
5291 {
5292   u8 **matchp = va_arg (*args, u8 **);
5293   u8 *match = 0;
5294   ip6_header_t *ip;
5295   int version = 0;
5296   u32 version_val;
5297   u8 traffic_class = 0;
5298   u32 traffic_class_val = 0;
5299   u8 flow_label = 0;
5300   u8 flow_label_val;
5301   int src = 0, dst = 0;
5302   ip6_address_t src_val, dst_val;
5303   int proto = 0;
5304   u32 proto_val;
5305   int payload_length = 0;
5306   u32 payload_length_val;
5307   int hop_limit = 0;
5308   int hop_limit_val;
5309   u32 ip_version_traffic_class_and_flow_label;
5310
5311   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5312     {
5313       if (unformat (input, "version %d", &version_val))
5314         version = 1;
5315       else if (unformat (input, "traffic_class %d", &traffic_class_val))
5316         traffic_class = 1;
5317       else if (unformat (input, "flow_label %d", &flow_label_val))
5318         flow_label = 1;
5319       else if (unformat (input, "src %U", unformat_ip6_address, &src_val))
5320         src = 1;
5321       else if (unformat (input, "dst %U", unformat_ip6_address, &dst_val))
5322         dst = 1;
5323       else if (unformat (input, "proto %d", &proto_val))
5324         proto = 1;
5325       else if (unformat (input, "payload_length %d", &payload_length_val))
5326         payload_length = 1;
5327       else if (unformat (input, "hop_limit %d", &hop_limit_val))
5328         hop_limit = 1;
5329       else
5330         break;
5331     }
5332
5333   if (version + traffic_class + flow_label + src + dst + proto +
5334       payload_length + hop_limit == 0)
5335     return 0;
5336
5337   /*
5338    * Aligned because we use the real comparison functions
5339    */
5340   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
5341
5342   ip = (ip6_header_t *) match;
5343
5344   if (src)
5345     clib_memcpy (&ip->src_address, &src_val, sizeof (ip->src_address));
5346
5347   if (dst)
5348     clib_memcpy (&ip->dst_address, &dst_val, sizeof (ip->dst_address));
5349
5350   if (proto)
5351     ip->protocol = proto_val;
5352
5353   ip_version_traffic_class_and_flow_label = 0;
5354
5355   if (version)
5356     ip_version_traffic_class_and_flow_label |= (version_val & 0xF) << 28;
5357
5358   if (traffic_class)
5359     ip_version_traffic_class_and_flow_label |=
5360       (traffic_class_val & 0xFF) << 20;
5361
5362   if (flow_label)
5363     ip_version_traffic_class_and_flow_label |= (flow_label_val & 0xFFFFF);
5364
5365   ip->ip_version_traffic_class_and_flow_label =
5366     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
5367
5368   if (payload_length)
5369     ip->payload_length = clib_host_to_net_u16 (payload_length_val);
5370
5371   if (hop_limit)
5372     ip->hop_limit = hop_limit_val;
5373
5374   *matchp = match;
5375   return 1;
5376 }
5377
5378 uword
5379 unformat_l3_match (unformat_input_t * input, va_list * args)
5380 {
5381   u8 **matchp = va_arg (*args, u8 **);
5382
5383   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5384     {
5385       if (unformat (input, "ip4 %U", unformat_ip4_match, matchp))
5386         return 1;
5387       else if (unformat (input, "ip6 %U", unformat_ip6_match, matchp))
5388         return 1;
5389       else
5390         break;
5391     }
5392   return 0;
5393 }
5394
5395 uword
5396 unformat_vlan_tag (unformat_input_t * input, va_list * args)
5397 {
5398   u8 *tagp = va_arg (*args, u8 *);
5399   u32 tag;
5400
5401   if (unformat (input, "%d", &tag))
5402     {
5403       tagp[0] = (tag >> 8) & 0x0F;
5404       tagp[1] = tag & 0xFF;
5405       return 1;
5406     }
5407
5408   return 0;
5409 }
5410
5411 uword
5412 unformat_l2_match (unformat_input_t * input, va_list * args)
5413 {
5414   u8 **matchp = va_arg (*args, u8 **);
5415   u8 *match = 0;
5416   u8 src = 0;
5417   u8 src_val[6];
5418   u8 dst = 0;
5419   u8 dst_val[6];
5420   u8 proto = 0;
5421   u16 proto_val;
5422   u8 tag1 = 0;
5423   u8 tag1_val[2];
5424   u8 tag2 = 0;
5425   u8 tag2_val[2];
5426   int len = 14;
5427   u8 ignore_tag1 = 0;
5428   u8 ignore_tag2 = 0;
5429   u8 cos1 = 0;
5430   u8 cos2 = 0;
5431   u32 cos1_val = 0;
5432   u32 cos2_val = 0;
5433
5434   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5435     {
5436       if (unformat (input, "src %U", unformat_ethernet_address, &src_val))
5437         src = 1;
5438       else
5439         if (unformat (input, "dst %U", unformat_ethernet_address, &dst_val))
5440         dst = 1;
5441       else if (unformat (input, "proto %U",
5442                          unformat_ethernet_type_host_byte_order, &proto_val))
5443         proto = 1;
5444       else if (unformat (input, "tag1 %U", unformat_vlan_tag, tag1_val))
5445         tag1 = 1;
5446       else if (unformat (input, "tag2 %U", unformat_vlan_tag, tag2_val))
5447         tag2 = 1;
5448       else if (unformat (input, "ignore-tag1"))
5449         ignore_tag1 = 1;
5450       else if (unformat (input, "ignore-tag2"))
5451         ignore_tag2 = 1;
5452       else if (unformat (input, "cos1 %d", &cos1_val))
5453         cos1 = 1;
5454       else if (unformat (input, "cos2 %d", &cos2_val))
5455         cos2 = 1;
5456       else
5457         break;
5458     }
5459   if ((src + dst + proto + tag1 + tag2 +
5460        ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
5461     return 0;
5462
5463   if (tag1 || ignore_tag1 || cos1)
5464     len = 18;
5465   if (tag2 || ignore_tag2 || cos2)
5466     len = 22;
5467
5468   vec_validate_aligned (match, len - 1, sizeof (u32x4));
5469
5470   if (dst)
5471     clib_memcpy (match, dst_val, 6);
5472
5473   if (src)
5474     clib_memcpy (match + 6, src_val, 6);
5475
5476   if (tag2)
5477     {
5478       /* inner vlan tag */
5479       match[19] = tag2_val[1];
5480       match[18] = tag2_val[0];
5481       if (cos2)
5482         match[18] |= (cos2_val & 0x7) << 5;
5483       if (proto)
5484         {
5485           match[21] = proto_val & 0xff;
5486           match[20] = proto_val >> 8;
5487         }
5488       if (tag1)
5489         {
5490           match[15] = tag1_val[1];
5491           match[14] = tag1_val[0];
5492         }
5493       if (cos1)
5494         match[14] |= (cos1_val & 0x7) << 5;
5495       *matchp = match;
5496       return 1;
5497     }
5498   if (tag1)
5499     {
5500       match[15] = tag1_val[1];
5501       match[14] = tag1_val[0];
5502       if (proto)
5503         {
5504           match[17] = proto_val & 0xff;
5505           match[16] = proto_val >> 8;
5506         }
5507       if (cos1)
5508         match[14] |= (cos1_val & 0x7) << 5;
5509
5510       *matchp = match;
5511       return 1;
5512     }
5513   if (cos2)
5514     match[18] |= (cos2_val & 0x7) << 5;
5515   if (cos1)
5516     match[14] |= (cos1_val & 0x7) << 5;
5517   if (proto)
5518     {
5519       match[13] = proto_val & 0xff;
5520       match[12] = proto_val >> 8;
5521     }
5522
5523   *matchp = match;
5524   return 1;
5525 }
5526
5527 uword
5528 unformat_qos_source (unformat_input_t * input, va_list * args)
5529 {
5530   int *qs = va_arg (*args, int *);
5531
5532   if (unformat (input, "ip"))
5533     *qs = QOS_SOURCE_IP;
5534   else if (unformat (input, "mpls"))
5535     *qs = QOS_SOURCE_MPLS;
5536   else if (unformat (input, "ext"))
5537     *qs = QOS_SOURCE_EXT;
5538   else if (unformat (input, "vlan"))
5539     *qs = QOS_SOURCE_VLAN;
5540   else
5541     return 0;
5542
5543   return 1;
5544 }
5545 #endif
5546
5547 uword
5548 api_unformat_classify_match (unformat_input_t * input, va_list * args)
5549 {
5550   u8 **matchp = va_arg (*args, u8 **);
5551   u32 skip_n_vectors = va_arg (*args, u32);
5552   u32 match_n_vectors = va_arg (*args, u32);
5553
5554   u8 *match = 0;
5555   u8 *l2 = 0;
5556   u8 *l3 = 0;
5557   u8 *l4 = 0;
5558
5559   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5560     {
5561       if (unformat (input, "hex %U", unformat_hex_string, &match))
5562         ;
5563       else if (unformat (input, "l2 %U", unformat_l2_match, &l2))
5564         ;
5565       else if (unformat (input, "l3 %U", unformat_l3_match, &l3))
5566         ;
5567       else if (unformat (input, "l4 %U", unformat_l4_match, &l4))
5568         ;
5569       else
5570         break;
5571     }
5572
5573   if (l4 && !l3)
5574     {
5575       vec_free (match);
5576       vec_free (l2);
5577       vec_free (l4);
5578       return 0;
5579     }
5580
5581   if (match || l2 || l3 || l4)
5582     {
5583       if (l2 || l3 || l4)
5584         {
5585           /* "Win a free Ethernet header in every packet" */
5586           if (l2 == 0)
5587             vec_validate_aligned (l2, 13, sizeof (u32x4));
5588           match = l2;
5589           if (vec_len (l3))
5590             {
5591               vec_append_aligned (match, l3, sizeof (u32x4));
5592               vec_free (l3);
5593             }
5594           if (vec_len (l4))
5595             {
5596               vec_append_aligned (match, l4, sizeof (u32x4));
5597               vec_free (l4);
5598             }
5599         }
5600
5601       /* Make sure the vector is big enough even if key is all 0's */
5602       vec_validate_aligned
5603         (match, ((match_n_vectors + skip_n_vectors) * sizeof (u32x4)) - 1,
5604          sizeof (u32x4));
5605
5606       /* Set size, include skipped vectors */
5607       _vec_len (match) = (match_n_vectors + skip_n_vectors) * sizeof (u32x4);
5608
5609       *matchp = match;
5610
5611       return 1;
5612     }
5613
5614   return 0;
5615 }
5616
5617 static int
5618 api_get_node_index (vat_main_t * vam)
5619 {
5620   unformat_input_t *i = vam->input;
5621   vl_api_get_node_index_t *mp;
5622   u8 *name = 0;
5623   int ret;
5624
5625   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5626     {
5627       if (unformat (i, "node %s", &name))
5628         ;
5629       else
5630         break;
5631     }
5632   if (name == 0)
5633     {
5634       errmsg ("node name required");
5635       return -99;
5636     }
5637   if (vec_len (name) >= ARRAY_LEN (mp->node_name))
5638     {
5639       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
5640       return -99;
5641     }
5642
5643   M (GET_NODE_INDEX, mp);
5644   clib_memcpy (mp->node_name, name, vec_len (name));
5645   vec_free (name);
5646
5647   S (mp);
5648   W (ret);
5649   return ret;
5650 }
5651
5652 static int
5653 api_get_next_index (vat_main_t * vam)
5654 {
5655   unformat_input_t *i = vam->input;
5656   vl_api_get_next_index_t *mp;
5657   u8 *node_name = 0, *next_node_name = 0;
5658   int ret;
5659
5660   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5661     {
5662       if (unformat (i, "node-name %s", &node_name))
5663         ;
5664       else if (unformat (i, "next-node-name %s", &next_node_name))
5665         break;
5666     }
5667
5668   if (node_name == 0)
5669     {
5670       errmsg ("node name required");
5671       return -99;
5672     }
5673   if (vec_len (node_name) >= ARRAY_LEN (mp->node_name))
5674     {
5675       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
5676       return -99;
5677     }
5678
5679   if (next_node_name == 0)
5680     {
5681       errmsg ("next node name required");
5682       return -99;
5683     }
5684   if (vec_len (next_node_name) >= ARRAY_LEN (mp->next_name))
5685     {
5686       errmsg ("next node name too long, max %d", ARRAY_LEN (mp->next_name));
5687       return -99;
5688     }
5689
5690   M (GET_NEXT_INDEX, mp);
5691   clib_memcpy (mp->node_name, node_name, vec_len (node_name));
5692   clib_memcpy (mp->next_name, next_node_name, vec_len (next_node_name));
5693   vec_free (node_name);
5694   vec_free (next_node_name);
5695
5696   S (mp);
5697   W (ret);
5698   return ret;
5699 }
5700
5701 static int
5702 api_add_node_next (vat_main_t * vam)
5703 {
5704   unformat_input_t *i = vam->input;
5705   vl_api_add_node_next_t *mp;
5706   u8 *name = 0;
5707   u8 *next = 0;
5708   int ret;
5709
5710   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5711     {
5712       if (unformat (i, "node %s", &name))
5713         ;
5714       else if (unformat (i, "next %s", &next))
5715         ;
5716       else
5717         break;
5718     }
5719   if (name == 0)
5720     {
5721       errmsg ("node name required");
5722       return -99;
5723     }
5724   if (vec_len (name) >= ARRAY_LEN (mp->node_name))
5725     {
5726       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
5727       return -99;
5728     }
5729   if (next == 0)
5730     {
5731       errmsg ("next node required");
5732       return -99;
5733     }
5734   if (vec_len (next) >= ARRAY_LEN (mp->next_name))
5735     {
5736       errmsg ("next name too long, max %d", ARRAY_LEN (mp->next_name));
5737       return -99;
5738     }
5739
5740   M (ADD_NODE_NEXT, mp);
5741   clib_memcpy (mp->node_name, name, vec_len (name));
5742   clib_memcpy (mp->next_name, next, vec_len (next));
5743   vec_free (name);
5744   vec_free (next);
5745
5746   S (mp);
5747   W (ret);
5748   return ret;
5749 }
5750
5751 static int
5752 api_l2_fib_clear_table (vat_main_t * vam)
5753 {
5754 //  unformat_input_t * i = vam->input;
5755   vl_api_l2_fib_clear_table_t *mp;
5756   int ret;
5757
5758   M (L2_FIB_CLEAR_TABLE, mp);
5759
5760   S (mp);
5761   W (ret);
5762   return ret;
5763 }
5764
5765 static int
5766 api_l2_interface_efp_filter (vat_main_t * vam)
5767 {
5768   unformat_input_t *i = vam->input;
5769   vl_api_l2_interface_efp_filter_t *mp;
5770   u32 sw_if_index;
5771   u8 enable = 1;
5772   u8 sw_if_index_set = 0;
5773   int ret;
5774
5775   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5776     {
5777       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5778         sw_if_index_set = 1;
5779       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5780         sw_if_index_set = 1;
5781       else if (unformat (i, "enable"))
5782         enable = 1;
5783       else if (unformat (i, "disable"))
5784         enable = 0;
5785       else
5786         {
5787           clib_warning ("parse error '%U'", format_unformat_error, i);
5788           return -99;
5789         }
5790     }
5791
5792   if (sw_if_index_set == 0)
5793     {
5794       errmsg ("missing sw_if_index");
5795       return -99;
5796     }
5797
5798   M (L2_INTERFACE_EFP_FILTER, mp);
5799
5800   mp->sw_if_index = ntohl (sw_if_index);
5801   mp->enable_disable = enable;
5802
5803   S (mp);
5804   W (ret);
5805   return ret;
5806 }
5807
5808 #define foreach_vtr_op                          \
5809 _("disable",  L2_VTR_DISABLED)                  \
5810 _("push-1",  L2_VTR_PUSH_1)                     \
5811 _("push-2",  L2_VTR_PUSH_2)                     \
5812 _("pop-1",  L2_VTR_POP_1)                       \
5813 _("pop-2",  L2_VTR_POP_2)                       \
5814 _("translate-1-1",  L2_VTR_TRANSLATE_1_1)       \
5815 _("translate-1-2",  L2_VTR_TRANSLATE_1_2)       \
5816 _("translate-2-1",  L2_VTR_TRANSLATE_2_1)       \
5817 _("translate-2-2",  L2_VTR_TRANSLATE_2_2)
5818
5819 static int
5820 api_l2_interface_vlan_tag_rewrite (vat_main_t * vam)
5821 {
5822   unformat_input_t *i = vam->input;
5823   vl_api_l2_interface_vlan_tag_rewrite_t *mp;
5824   u32 sw_if_index;
5825   u8 sw_if_index_set = 0;
5826   u8 vtr_op_set = 0;
5827   u32 vtr_op = 0;
5828   u32 push_dot1q = 1;
5829   u32 tag1 = ~0;
5830   u32 tag2 = ~0;
5831   int ret;
5832
5833   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5834     {
5835       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5836         sw_if_index_set = 1;
5837       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5838         sw_if_index_set = 1;
5839       else if (unformat (i, "vtr_op %d", &vtr_op))
5840         vtr_op_set = 1;
5841 #define _(n,v) else if (unformat(i, n)) {vtr_op = v; vtr_op_set = 1;}
5842       foreach_vtr_op
5843 #undef _
5844         else if (unformat (i, "push_dot1q %d", &push_dot1q))
5845         ;
5846       else if (unformat (i, "tag1 %d", &tag1))
5847         ;
5848       else if (unformat (i, "tag2 %d", &tag2))
5849         ;
5850       else
5851         {
5852           clib_warning ("parse error '%U'", format_unformat_error, i);
5853           return -99;
5854         }
5855     }
5856
5857   if ((sw_if_index_set == 0) || (vtr_op_set == 0))
5858     {
5859       errmsg ("missing vtr operation or sw_if_index");
5860       return -99;
5861     }
5862
5863   M (L2_INTERFACE_VLAN_TAG_REWRITE, mp);
5864   mp->sw_if_index = ntohl (sw_if_index);
5865   mp->vtr_op = ntohl (vtr_op);
5866   mp->push_dot1q = ntohl (push_dot1q);
5867   mp->tag1 = ntohl (tag1);
5868   mp->tag2 = ntohl (tag2);
5869
5870   S (mp);
5871   W (ret);
5872   return ret;
5873 }
5874
5875 static int
5876 api_show_version (vat_main_t *vam)
5877 {
5878   vl_api_show_version_t *mp;
5879   int ret;
5880
5881   M (SHOW_VERSION, mp);
5882
5883   S (mp);
5884   W (ret);
5885   return ret;
5886 }
5887
5888 static void
5889 vl_api_l2_fib_table_details_t_handler (vl_api_l2_fib_table_details_t *mp)
5890 {
5891   vat_main_t *vam = &vat_main;
5892
5893   print (vam->ofp,
5894          "%3" PRIu32 "    %U    %3" PRIu32 "       %d       %d     %d",
5895          ntohl (mp->bd_id), format_ethernet_address, mp->mac,
5896          ntohl (mp->sw_if_index), mp->static_mac, mp->filter_mac, mp->bvi_mac);
5897 }
5898
5899 static void
5900 vl_api_l2_fib_table_details_t_handler_json (vl_api_l2_fib_table_details_t *mp)
5901 {
5902   vat_main_t *vam = &vat_main;
5903   vat_json_node_t *node = NULL;
5904
5905   if (VAT_JSON_ARRAY != vam->json_tree.type)
5906     {
5907       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
5908       vat_json_init_array (&vam->json_tree);
5909     }
5910   node = vat_json_array_add (&vam->json_tree);
5911
5912   vat_json_init_object (node);
5913   vat_json_object_add_uint (node, "bd_id", ntohl (mp->bd_id));
5914   vat_json_object_add_bytes (node, "mac", mp->mac, 6);
5915   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
5916   vat_json_object_add_uint (node, "static_mac", mp->static_mac);
5917   vat_json_object_add_uint (node, "filter_mac", mp->filter_mac);
5918   vat_json_object_add_uint (node, "bvi_mac", mp->bvi_mac);
5919 }
5920
5921 static int
5922 api_l2_fib_table_dump (vat_main_t *vam)
5923 {
5924   unformat_input_t *i = vam->input;
5925   vl_api_l2_fib_table_dump_t *mp;
5926   vl_api_control_ping_t *mp_ping;
5927   u32 bd_id;
5928   u8 bd_id_set = 0;
5929   int ret;
5930
5931   /* Parse args required to build the message */
5932   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5933     {
5934       if (unformat (i, "bd_id %d", &bd_id))
5935         bd_id_set = 1;
5936       else
5937         break;
5938     }
5939
5940   if (bd_id_set == 0)
5941     {
5942       errmsg ("missing bridge domain");
5943       return -99;
5944     }
5945
5946   print (vam->ofp, "BD-ID     Mac Address      sw-ndx  Static  Filter  BVI");
5947
5948   /* Get list of l2 fib entries */
5949   M (L2_FIB_TABLE_DUMP, mp);
5950
5951   mp->bd_id = ntohl (bd_id);
5952   S (mp);
5953
5954   /* Use a control ping for synchronization */
5955   MPING (CONTROL_PING, mp_ping);
5956   S (mp_ping);
5957
5958   W (ret);
5959   return ret;
5960 }
5961
5962 static int
5963 api_interface_name_renumber (vat_main_t *vam)
5964 {
5965   unformat_input_t *line_input = vam->input;
5966   vl_api_interface_name_renumber_t *mp;
5967   u32 sw_if_index = ~0;
5968   u32 new_show_dev_instance = ~0;
5969   int ret;
5970
5971   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
5972     {
5973       if (unformat (line_input, "%U", api_unformat_sw_if_index, vam,
5974                     &sw_if_index))
5975         ;
5976       else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
5977         ;
5978       else if (unformat (line_input, "new_show_dev_instance %d",
5979                          &new_show_dev_instance))
5980         ;
5981       else
5982         break;
5983     }
5984
5985   if (sw_if_index == ~0)
5986     {
5987       errmsg ("missing interface name or sw_if_index");
5988       return -99;
5989     }
5990
5991   if (new_show_dev_instance == ~0)
5992     {
5993       errmsg ("missing new_show_dev_instance");
5994       return -99;
5995     }
5996
5997   M (INTERFACE_NAME_RENUMBER, mp);
5998
5999   mp->sw_if_index = ntohl (sw_if_index);
6000   mp->new_show_dev_instance = ntohl (new_show_dev_instance);
6001
6002   S (mp);
6003   W (ret);
6004   return ret;
6005 }
6006
6007 static int
6008 api_want_l2_macs_events (vat_main_t *vam)
6009 {
6010   unformat_input_t *line_input = vam->input;
6011   vl_api_want_l2_macs_events_t *mp;
6012   u8 enable_disable = 1;
6013   u32 scan_delay = 0;
6014   u32 max_macs_in_event = 0;
6015   u32 learn_limit = 0;
6016   int ret;
6017
6018   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
6019     {
6020       if (unformat (line_input, "learn-limit %d", &learn_limit))
6021         ;
6022       else if (unformat (line_input, "scan-delay %d", &scan_delay))
6023         ;
6024       else if (unformat (line_input, "max-entries %d", &max_macs_in_event))
6025         ;
6026       else if (unformat (line_input, "disable"))
6027         enable_disable = 0;
6028       else
6029         break;
6030     }
6031
6032   M (WANT_L2_MACS_EVENTS, mp);
6033   mp->enable_disable = enable_disable;
6034   mp->pid = htonl (getpid ());
6035   mp->learn_limit = htonl (learn_limit);
6036   mp->scan_delay = (u8) scan_delay;
6037   mp->max_macs_in_event = (u8) (max_macs_in_event / 10);
6038   S (mp);
6039   W (ret);
6040   return ret;
6041 }
6042
6043 static int
6044 api_ip_address_dump (vat_main_t *vam)
6045 {
6046   unformat_input_t *i = vam->input;
6047   vl_api_ip_address_dump_t *mp;
6048   vl_api_control_ping_t *mp_ping;
6049   u32 sw_if_index = ~0;
6050   u8 sw_if_index_set = 0;
6051   u8 ipv4_set = 0;
6052   u8 ipv6_set = 0;
6053   int ret;
6054
6055   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6056     {
6057       if (unformat (i, "sw_if_index %d", &sw_if_index))
6058         sw_if_index_set = 1;
6059       else if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
6060         sw_if_index_set = 1;
6061       else if (unformat (i, "ipv4"))
6062         ipv4_set = 1;
6063       else if (unformat (i, "ipv6"))
6064         ipv6_set = 1;
6065       else
6066         break;
6067     }
6068
6069   if (ipv4_set && ipv6_set)
6070     {
6071       errmsg ("ipv4 and ipv6 flags cannot be both set");
6072       return -99;
6073     }
6074
6075   if ((!ipv4_set) && (!ipv6_set))
6076     {
6077       errmsg ("no ipv4 nor ipv6 flag set");
6078       return -99;
6079     }
6080
6081   if (sw_if_index_set == 0)
6082     {
6083       errmsg ("missing interface name or sw_if_index");
6084       return -99;
6085     }
6086
6087   vam->current_sw_if_index = sw_if_index;
6088   vam->is_ipv6 = ipv6_set;
6089
6090   M (IP_ADDRESS_DUMP, mp);
6091   mp->sw_if_index = ntohl (sw_if_index);
6092   mp->is_ipv6 = ipv6_set;
6093   S (mp);
6094
6095   /* Use a control ping for synchronization */
6096   MPING (CONTROL_PING, mp_ping);
6097   S (mp_ping);
6098
6099   W (ret);
6100   return ret;
6101 }
6102
6103 static int
6104 api_ip_dump (vat_main_t * vam)
6105 {
6106   vl_api_ip_dump_t *mp;
6107   vl_api_control_ping_t *mp_ping;
6108   unformat_input_t *in = vam->input;
6109   int ipv4_set = 0;
6110   int ipv6_set = 0;
6111   int is_ipv6;
6112   int i;
6113   int ret;
6114
6115   while (unformat_check_input (in) != UNFORMAT_END_OF_INPUT)
6116     {
6117       if (unformat (in, "ipv4"))
6118         ipv4_set = 1;
6119       else if (unformat (in, "ipv6"))
6120         ipv6_set = 1;
6121       else
6122         break;
6123     }
6124
6125   if (ipv4_set && ipv6_set)
6126     {
6127       errmsg ("ipv4 and ipv6 flags cannot be both set");
6128       return -99;
6129     }
6130
6131   if ((!ipv4_set) && (!ipv6_set))
6132     {
6133       errmsg ("no ipv4 nor ipv6 flag set");
6134       return -99;
6135     }
6136
6137   is_ipv6 = ipv6_set;
6138   vam->is_ipv6 = is_ipv6;
6139
6140   /* free old data */
6141   for (i = 0; i < vec_len (vam->ip_details_by_sw_if_index[is_ipv6]); i++)
6142     {
6143       vec_free (vam->ip_details_by_sw_if_index[is_ipv6][i].addr);
6144     }
6145   vec_free (vam->ip_details_by_sw_if_index[is_ipv6]);
6146
6147   M (IP_DUMP, mp);
6148   mp->is_ipv6 = ipv6_set;
6149   S (mp);
6150
6151   /* Use a control ping for synchronization */
6152   MPING (CONTROL_PING, mp_ping);
6153   S (mp_ping);
6154
6155   W (ret);
6156   return ret;
6157 }
6158
6159 static int
6160 api_get_first_msg_id (vat_main_t * vam)
6161 {
6162   vl_api_get_first_msg_id_t *mp;
6163   unformat_input_t *i = vam->input;
6164   u8 *name;
6165   u8 name_set = 0;
6166   int ret;
6167
6168   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6169     {
6170       if (unformat (i, "client %s", &name))
6171         name_set = 1;
6172       else
6173         break;
6174     }
6175
6176   if (name_set == 0)
6177     {
6178       errmsg ("missing client name");
6179       return -99;
6180     }
6181   vec_add1 (name, 0);
6182
6183   if (vec_len (name) > 63)
6184     {
6185       errmsg ("client name too long");
6186       return -99;
6187     }
6188
6189   M (GET_FIRST_MSG_ID, mp);
6190   clib_memcpy (mp->name, name, vec_len (name));
6191   S (mp);
6192   W (ret);
6193   return ret;
6194 }
6195
6196 static int
6197 api_get_node_graph (vat_main_t * vam)
6198 {
6199   vl_api_get_node_graph_t *mp;
6200   int ret;
6201
6202   M (GET_NODE_GRAPH, mp);
6203
6204   /* send it... */
6205   S (mp);
6206   /* Wait for the reply */
6207   W (ret);
6208   return ret;
6209 }
6210
6211 static u8 *
6212 format_fib_api_path_nh_proto (u8 * s, va_list * args)
6213 {
6214   vl_api_fib_path_nh_proto_t proto =
6215     va_arg (*args, vl_api_fib_path_nh_proto_t);
6216
6217   switch (proto)
6218     {
6219     case FIB_API_PATH_NH_PROTO_IP4:
6220       s = format (s, "ip4");
6221       break;
6222     case FIB_API_PATH_NH_PROTO_IP6:
6223       s = format (s, "ip6");
6224       break;
6225     case FIB_API_PATH_NH_PROTO_MPLS:
6226       s = format (s, "mpls");
6227       break;
6228     case FIB_API_PATH_NH_PROTO_BIER:
6229       s = format (s, "bier");
6230       break;
6231     case FIB_API_PATH_NH_PROTO_ETHERNET:
6232       s = format (s, "ethernet");
6233       break;
6234     }
6235
6236   return (s);
6237 }
6238
6239 static u8 *
6240 format_vl_api_ip_address_union (u8 * s, va_list * args)
6241 {
6242   vl_api_address_family_t af = va_arg (*args, int);
6243   const vl_api_address_union_t *u = va_arg (*args, vl_api_address_union_t *);
6244
6245   switch (af)
6246     {
6247     case ADDRESS_IP4:
6248       s = format (s, "%U", format_ip4_address, u->ip4);
6249       break;
6250     case ADDRESS_IP6:
6251       s = format (s, "%U", format_ip6_address, u->ip6);
6252       break;
6253     }
6254   return (s);
6255 }
6256
6257 static u8 *
6258 format_vl_api_fib_path_type (u8 * s, va_list * args)
6259 {
6260   vl_api_fib_path_type_t t = va_arg (*args, vl_api_fib_path_type_t);
6261
6262   switch (t)
6263     {
6264     case FIB_API_PATH_TYPE_NORMAL:
6265       s = format (s, "normal");
6266       break;
6267     case FIB_API_PATH_TYPE_LOCAL:
6268       s = format (s, "local");
6269       break;
6270     case FIB_API_PATH_TYPE_DROP:
6271       s = format (s, "drop");
6272       break;
6273     case FIB_API_PATH_TYPE_UDP_ENCAP:
6274       s = format (s, "udp-encap");
6275       break;
6276     case FIB_API_PATH_TYPE_BIER_IMP:
6277       s = format (s, "bier-imp");
6278       break;
6279     case FIB_API_PATH_TYPE_ICMP_UNREACH:
6280       s = format (s, "unreach");
6281       break;
6282     case FIB_API_PATH_TYPE_ICMP_PROHIBIT:
6283       s = format (s, "prohibit");
6284       break;
6285     case FIB_API_PATH_TYPE_SOURCE_LOOKUP:
6286       s = format (s, "src-lookup");
6287       break;
6288     case FIB_API_PATH_TYPE_DVR:
6289       s = format (s, "dvr");
6290       break;
6291     case FIB_API_PATH_TYPE_INTERFACE_RX:
6292       s = format (s, "interface-rx");
6293       break;
6294     case FIB_API_PATH_TYPE_CLASSIFY:
6295       s = format (s, "classify");
6296       break;
6297     }
6298
6299   return (s);
6300 }
6301
6302 static void
6303 vl_api_fib_path_print (vat_main_t * vam, vl_api_fib_path_t * fp)
6304 {
6305   print (vam->ofp,
6306          "  weight %d, sw_if_index %d, type %U, afi %U, next_hop %U",
6307          ntohl (fp->weight), ntohl (fp->sw_if_index),
6308          format_vl_api_fib_path_type, fp->type,
6309          format_fib_api_path_nh_proto, fp->proto,
6310          format_vl_api_ip_address_union, &fp->nh.address);
6311 }
6312
6313 static void
6314 vl_api_mpls_fib_path_json_print (vat_json_node_t * node,
6315                                  vl_api_fib_path_t * fp)
6316 {
6317   struct in_addr ip4;
6318   struct in6_addr ip6;
6319
6320   vat_json_object_add_uint (node, "weight", ntohl (fp->weight));
6321   vat_json_object_add_uint (node, "sw_if_index", ntohl (fp->sw_if_index));
6322   vat_json_object_add_uint (node, "type", fp->type);
6323   vat_json_object_add_uint (node, "next_hop_proto", fp->proto);
6324   if (fp->proto == FIB_API_PATH_NH_PROTO_IP4)
6325     {
6326       clib_memcpy (&ip4, &fp->nh.address.ip4, sizeof (ip4));
6327       vat_json_object_add_ip4 (node, "next_hop", ip4);
6328     }
6329   else if (fp->proto == FIB_API_PATH_NH_PROTO_IP6)
6330     {
6331       clib_memcpy (&ip6, &fp->nh.address.ip6, sizeof (ip6));
6332       vat_json_object_add_ip6 (node, "next_hop", ip6);
6333     }
6334 }
6335
6336 #define vl_api_ip_table_details_t_endian vl_noop_handler
6337 #define vl_api_ip_table_details_t_print vl_noop_handler
6338
6339 static void
6340 vl_api_ip_table_details_t_handler (vl_api_ip_table_details_t * mp)
6341 {
6342   vat_main_t *vam = &vat_main;
6343
6344   print (vam->ofp,
6345          "%s; table-id %d, prefix %U/%d",
6346          mp->table.name, ntohl (mp->table.table_id));
6347 }
6348
6349
6350 static void vl_api_ip_table_details_t_handler_json
6351   (vl_api_ip_table_details_t * mp)
6352 {
6353   vat_main_t *vam = &vat_main;
6354   vat_json_node_t *node = NULL;
6355
6356   if (VAT_JSON_ARRAY != vam->json_tree.type)
6357     {
6358       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
6359       vat_json_init_array (&vam->json_tree);
6360     }
6361   node = vat_json_array_add (&vam->json_tree);
6362
6363   vat_json_init_object (node);
6364   vat_json_object_add_uint (node, "table", ntohl (mp->table.table_id));
6365 }
6366
6367 static int
6368 api_ip_table_dump (vat_main_t * vam)
6369 {
6370   vl_api_ip_table_dump_t *mp;
6371   vl_api_control_ping_t *mp_ping;
6372   int ret;
6373
6374   M (IP_TABLE_DUMP, mp);
6375   S (mp);
6376
6377   /* Use a control ping for synchronization */
6378   MPING (CONTROL_PING, mp_ping);
6379   S (mp_ping);
6380
6381   W (ret);
6382   return ret;
6383 }
6384
6385 static int
6386 api_ip_mtable_dump (vat_main_t * vam)
6387 {
6388   vl_api_ip_mtable_dump_t *mp;
6389   vl_api_control_ping_t *mp_ping;
6390   int ret;
6391
6392   M (IP_MTABLE_DUMP, mp);
6393   S (mp);
6394
6395   /* Use a control ping for synchronization */
6396   MPING (CONTROL_PING, mp_ping);
6397   S (mp_ping);
6398
6399   W (ret);
6400   return ret;
6401 }
6402
6403 static int
6404 api_ip_mroute_dump (vat_main_t * vam)
6405 {
6406   unformat_input_t *input = vam->input;
6407   vl_api_control_ping_t *mp_ping;
6408   vl_api_ip_mroute_dump_t *mp;
6409   int ret, is_ip6;
6410   u32 table_id;
6411
6412   is_ip6 = 0;
6413   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6414     {
6415       if (unformat (input, "table_id %d", &table_id))
6416         ;
6417       else if (unformat (input, "ip6"))
6418         is_ip6 = 1;
6419       else if (unformat (input, "ip4"))
6420         is_ip6 = 0;
6421       else
6422         break;
6423     }
6424   if (table_id == ~0)
6425     {
6426       errmsg ("missing table id");
6427       return -99;
6428     }
6429
6430   M (IP_MROUTE_DUMP, mp);
6431   mp->table.table_id = table_id;
6432   mp->table.is_ip6 = is_ip6;
6433   S (mp);
6434
6435   /* Use a control ping for synchronization */
6436   MPING (CONTROL_PING, mp_ping);
6437   S (mp_ping);
6438
6439   W (ret);
6440   return ret;
6441 }
6442
6443 #define vl_api_ip_route_details_t_endian vl_noop_handler
6444 #define vl_api_ip_route_details_t_print vl_noop_handler
6445
6446 static void
6447 vl_api_ip_route_details_t_handler (vl_api_ip_route_details_t * mp)
6448 {
6449   vat_main_t *vam = &vat_main;
6450   u8 count = mp->route.n_paths;
6451   vl_api_fib_path_t *fp;
6452   int i;
6453
6454   print (vam->ofp,
6455          "table-id %d, prefix %U/%d",
6456          ntohl (mp->route.table_id),
6457          format_ip46_address, mp->route.prefix.address, mp->route.prefix.len);
6458   for (i = 0; i < count; i++)
6459     {
6460       fp = &mp->route.paths[i];
6461
6462       vl_api_fib_path_print (vam, fp);
6463       fp++;
6464     }
6465 }
6466
6467 static void vl_api_ip_route_details_t_handler_json
6468   (vl_api_ip_route_details_t * mp)
6469 {
6470   vat_main_t *vam = &vat_main;
6471   u8 count = mp->route.n_paths;
6472   vat_json_node_t *node = NULL;
6473   struct in_addr ip4;
6474   struct in6_addr ip6;
6475   vl_api_fib_path_t *fp;
6476   int i;
6477
6478   if (VAT_JSON_ARRAY != vam->json_tree.type)
6479     {
6480       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
6481       vat_json_init_array (&vam->json_tree);
6482     }
6483   node = vat_json_array_add (&vam->json_tree);
6484
6485   vat_json_init_object (node);
6486   vat_json_object_add_uint (node, "table", ntohl (mp->route.table_id));
6487   if (ADDRESS_IP6 == mp->route.prefix.address.af)
6488     {
6489       clib_memcpy (&ip6, &mp->route.prefix.address.un.ip6, sizeof (ip6));
6490       vat_json_object_add_ip6 (node, "prefix", ip6);
6491     }
6492   else
6493     {
6494       clib_memcpy (&ip4, &mp->route.prefix.address.un.ip4, sizeof (ip4));
6495       vat_json_object_add_ip4 (node, "prefix", ip4);
6496     }
6497   vat_json_object_add_uint (node, "mask_length", mp->route.prefix.len);
6498   vat_json_object_add_uint (node, "path_count", count);
6499   for (i = 0; i < count; i++)
6500     {
6501       fp = &mp->route.paths[i];
6502       vl_api_mpls_fib_path_json_print (node, fp);
6503     }
6504 }
6505
6506 static int
6507 api_ip_route_dump (vat_main_t * vam)
6508 {
6509   unformat_input_t *input = vam->input;
6510   vl_api_ip_route_dump_t *mp;
6511   vl_api_control_ping_t *mp_ping;
6512   u32 table_id;
6513   u8 is_ip6;
6514   int ret;
6515
6516   is_ip6 = 0;
6517   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6518     {
6519       if (unformat (input, "table_id %d", &table_id))
6520         ;
6521       else if (unformat (input, "ip6"))
6522         is_ip6 = 1;
6523       else if (unformat (input, "ip4"))
6524         is_ip6 = 0;
6525       else
6526         break;
6527     }
6528   if (table_id == ~0)
6529     {
6530       errmsg ("missing table id");
6531       return -99;
6532     }
6533
6534   M (IP_ROUTE_DUMP, mp);
6535
6536   mp->table.table_id = table_id;
6537   mp->table.is_ip6 = is_ip6;
6538
6539   S (mp);
6540
6541   /* Use a control ping for synchronization */
6542   MPING (CONTROL_PING, mp_ping);
6543   S (mp_ping);
6544
6545   W (ret);
6546   return ret;
6547 }
6548
6549 int
6550 api_ip_source_and_port_range_check_add_del (vat_main_t * vam)
6551 {
6552   unformat_input_t *input = vam->input;
6553   vl_api_ip_source_and_port_range_check_add_del_t *mp;
6554
6555   u16 *low_ports = 0;
6556   u16 *high_ports = 0;
6557   u16 this_low;
6558   u16 this_hi;
6559   vl_api_prefix_t prefix;
6560   u32 tmp, tmp2;
6561   u8 prefix_set = 0;
6562   u32 vrf_id = ~0;
6563   u8 is_add = 1;
6564   int ret;
6565
6566   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6567     {
6568       if (unformat (input, "%U", unformat_vl_api_prefix, &prefix))
6569         prefix_set = 1;
6570       else if (unformat (input, "vrf %d", &vrf_id))
6571         ;
6572       else if (unformat (input, "del"))
6573         is_add = 0;
6574       else if (unformat (input, "port %d", &tmp))
6575         {
6576           if (tmp == 0 || tmp > 65535)
6577             {
6578               errmsg ("port %d out of range", tmp);
6579               return -99;
6580             }
6581           this_low = tmp;
6582           this_hi = this_low + 1;
6583           vec_add1 (low_ports, this_low);
6584           vec_add1 (high_ports, this_hi);
6585         }
6586       else if (unformat (input, "range %d - %d", &tmp, &tmp2))
6587         {
6588           if ((tmp > tmp2) || (tmp == 0) || (tmp2 > 65535))
6589             {
6590               errmsg ("incorrect range parameters");
6591               return -99;
6592             }
6593           this_low = tmp;
6594           /* Note: in debug CLI +1 is added to high before
6595              passing to real fn that does "the work"
6596              (ip_source_and_port_range_check_add_del).
6597              This fn is a wrapper around the binary API fn a
6598              control plane will call, which expects this increment
6599              to have occurred. Hence letting the binary API control
6600              plane fn do the increment for consistency between VAT
6601              and other control planes.
6602            */
6603           this_hi = tmp2;
6604           vec_add1 (low_ports, this_low);
6605           vec_add1 (high_ports, this_hi);
6606         }
6607       else
6608         break;
6609     }
6610
6611   if (prefix_set == 0)
6612     {
6613       errmsg ("<address>/<mask> not specified");
6614       return -99;
6615     }
6616
6617   if (vrf_id == ~0)
6618     {
6619       errmsg ("VRF ID required, not specified");
6620       return -99;
6621     }
6622
6623   if (vrf_id == 0)
6624     {
6625       errmsg
6626         ("VRF ID should not be default. Should be distinct VRF for this purpose.");
6627       return -99;
6628     }
6629
6630   if (vec_len (low_ports) == 0)
6631     {
6632       errmsg ("At least one port or port range required");
6633       return -99;
6634     }
6635
6636   M (IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL, mp);
6637
6638   mp->is_add = is_add;
6639
6640   clib_memcpy (&mp->prefix, &prefix, sizeof (prefix));
6641
6642   mp->number_of_ranges = vec_len (low_ports);
6643
6644   clib_memcpy (mp->low_ports, low_ports, vec_len (low_ports));
6645   vec_free (low_ports);
6646
6647   clib_memcpy (mp->high_ports, high_ports, vec_len (high_ports));
6648   vec_free (high_ports);
6649
6650   mp->vrf_id = ntohl (vrf_id);
6651
6652   S (mp);
6653   W (ret);
6654   return ret;
6655 }
6656
6657 int
6658 api_ip_source_and_port_range_check_interface_add_del (vat_main_t * vam)
6659 {
6660   unformat_input_t *input = vam->input;
6661   vl_api_ip_source_and_port_range_check_interface_add_del_t *mp;
6662   u32 sw_if_index = ~0;
6663   int vrf_set = 0;
6664   u32 tcp_out_vrf_id = ~0, udp_out_vrf_id = ~0;
6665   u32 tcp_in_vrf_id = ~0, udp_in_vrf_id = ~0;
6666   u8 is_add = 1;
6667   int ret;
6668
6669   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6670     {
6671       if (unformat (input, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
6672         ;
6673       else if (unformat (input, "sw_if_index %d", &sw_if_index))
6674         ;
6675       else if (unformat (input, "tcp-out-vrf %d", &tcp_out_vrf_id))
6676         vrf_set = 1;
6677       else if (unformat (input, "udp-out-vrf %d", &udp_out_vrf_id))
6678         vrf_set = 1;
6679       else if (unformat (input, "tcp-in-vrf %d", &tcp_in_vrf_id))
6680         vrf_set = 1;
6681       else if (unformat (input, "udp-in-vrf %d", &udp_in_vrf_id))
6682         vrf_set = 1;
6683       else if (unformat (input, "del"))
6684         is_add = 0;
6685       else
6686         break;
6687     }
6688
6689   if (sw_if_index == ~0)
6690     {
6691       errmsg ("Interface required but not specified");
6692       return -99;
6693     }
6694
6695   if (vrf_set == 0)
6696     {
6697       errmsg ("VRF ID required but not specified");
6698       return -99;
6699     }
6700
6701   if (tcp_out_vrf_id == 0
6702       || udp_out_vrf_id == 0 || tcp_in_vrf_id == 0 || udp_in_vrf_id == 0)
6703     {
6704       errmsg
6705         ("VRF ID should not be default. Should be distinct VRF for this purpose.");
6706       return -99;
6707     }
6708
6709   /* Construct the API message */
6710   M (IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL, mp);
6711
6712   mp->sw_if_index = ntohl (sw_if_index);
6713   mp->is_add = is_add;
6714   mp->tcp_out_vrf_id = ntohl (tcp_out_vrf_id);
6715   mp->udp_out_vrf_id = ntohl (udp_out_vrf_id);
6716   mp->tcp_in_vrf_id = ntohl (tcp_in_vrf_id);
6717   mp->udp_in_vrf_id = ntohl (udp_in_vrf_id);
6718
6719   /* send it... */
6720   S (mp);
6721
6722   /* Wait for a reply... */
6723   W (ret);
6724   return ret;
6725 }
6726
6727 static int
6728 api_delete_subif (vat_main_t * vam)
6729 {
6730   unformat_input_t *i = vam->input;
6731   vl_api_delete_subif_t *mp;
6732   u32 sw_if_index = ~0;
6733   int ret;
6734
6735   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6736     {
6737       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
6738         ;
6739       if (unformat (i, "sw_if_index %d", &sw_if_index))
6740         ;
6741       else
6742         break;
6743     }
6744
6745   if (sw_if_index == ~0)
6746     {
6747       errmsg ("missing sw_if_index");
6748       return -99;
6749     }
6750
6751   /* Construct the API message */
6752   M (DELETE_SUBIF, mp);
6753   mp->sw_if_index = ntohl (sw_if_index);
6754
6755   S (mp);
6756   W (ret);
6757   return ret;
6758 }
6759
6760 #define foreach_pbb_vtr_op      \
6761 _("disable",  L2_VTR_DISABLED)  \
6762 _("pop",  L2_VTR_POP_2)         \
6763 _("push",  L2_VTR_PUSH_2)
6764
6765 static int
6766 api_l2_interface_pbb_tag_rewrite (vat_main_t * vam)
6767 {
6768   unformat_input_t *i = vam->input;
6769   vl_api_l2_interface_pbb_tag_rewrite_t *mp;
6770   u32 sw_if_index = ~0, vtr_op = ~0;
6771   u16 outer_tag = ~0;
6772   u8 dmac[6], smac[6];
6773   u8 dmac_set = 0, smac_set = 0;
6774   u16 vlanid = 0;
6775   u32 sid = ~0;
6776   u32 tmp;
6777   int ret;
6778
6779   /* Shut up coverity */
6780   clib_memset (dmac, 0, sizeof (dmac));
6781   clib_memset (smac, 0, sizeof (smac));
6782
6783   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6784     {
6785       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
6786         ;
6787       else if (unformat (i, "sw_if_index %d", &sw_if_index))
6788         ;
6789       else if (unformat (i, "vtr_op %d", &vtr_op))
6790         ;
6791 #define _(n,v) else if (unformat(i, n)) {vtr_op = v;}
6792       foreach_pbb_vtr_op
6793 #undef _
6794         else if (unformat (i, "translate_pbb_stag"))
6795         {
6796           if (unformat (i, "%d", &tmp))
6797             {
6798               vtr_op = L2_VTR_TRANSLATE_2_1;
6799               outer_tag = tmp;
6800             }
6801           else
6802             {
6803               errmsg
6804                 ("translate_pbb_stag operation requires outer tag definition");
6805               return -99;
6806             }
6807         }
6808       else if (unformat (i, "dmac %U", unformat_ethernet_address, dmac))
6809         dmac_set++;
6810       else if (unformat (i, "smac %U", unformat_ethernet_address, smac))
6811         smac_set++;
6812       else if (unformat (i, "sid %d", &sid))
6813         ;
6814       else if (unformat (i, "vlanid %d", &tmp))
6815         vlanid = tmp;
6816       else
6817         {
6818           clib_warning ("parse error '%U'", format_unformat_error, i);
6819           return -99;
6820         }
6821     }
6822
6823   if ((sw_if_index == ~0) || (vtr_op == ~0))
6824     {
6825       errmsg ("missing sw_if_index or vtr operation");
6826       return -99;
6827     }
6828   if (((vtr_op == L2_VTR_PUSH_2) || (vtr_op == L2_VTR_TRANSLATE_2_2))
6829       && ((dmac_set == 0) || (smac_set == 0) || (sid == ~0)))
6830     {
6831       errmsg
6832         ("push and translate_qinq operations require dmac, smac, sid and optionally vlanid");
6833       return -99;
6834     }
6835
6836   M (L2_INTERFACE_PBB_TAG_REWRITE, mp);
6837   mp->sw_if_index = ntohl (sw_if_index);
6838   mp->vtr_op = ntohl (vtr_op);
6839   mp->outer_tag = ntohs (outer_tag);
6840   clib_memcpy (mp->b_dmac, dmac, sizeof (dmac));
6841   clib_memcpy (mp->b_smac, smac, sizeof (smac));
6842   mp->b_vlanid = ntohs (vlanid);
6843   mp->i_sid = ntohl (sid);
6844
6845   S (mp);
6846   W (ret);
6847   return ret;
6848 }
6849
6850 static int
6851 api_sw_interface_tag_add_del (vat_main_t * vam)
6852 {
6853   unformat_input_t *i = vam->input;
6854   vl_api_sw_interface_tag_add_del_t *mp;
6855   u32 sw_if_index = ~0;
6856   u8 *tag = 0;
6857   u8 enable = 1;
6858   int ret;
6859
6860   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6861     {
6862       if (unformat (i, "tag %s", &tag))
6863         ;
6864       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
6865         ;
6866       else if (unformat (i, "sw_if_index %d", &sw_if_index))
6867         ;
6868       else if (unformat (i, "del"))
6869         enable = 0;
6870       else
6871         break;
6872     }
6873
6874   if (sw_if_index == ~0)
6875     {
6876       errmsg ("missing interface name or sw_if_index");
6877       return -99;
6878     }
6879
6880   if (enable && (tag == 0))
6881     {
6882       errmsg ("no tag specified");
6883       return -99;
6884     }
6885
6886   /* Construct the API message */
6887   M (SW_INTERFACE_TAG_ADD_DEL, mp);
6888   mp->sw_if_index = ntohl (sw_if_index);
6889   mp->is_add = enable;
6890   if (enable)
6891     strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
6892   vec_free (tag);
6893
6894   S (mp);
6895   W (ret);
6896   return ret;
6897 }
6898
6899 static int
6900 api_sw_interface_add_del_mac_address (vat_main_t * vam)
6901 {
6902   unformat_input_t *i = vam->input;
6903   vl_api_mac_address_t mac = { 0 };
6904   vl_api_sw_interface_add_del_mac_address_t *mp;
6905   u32 sw_if_index = ~0;
6906   u8 is_add = 1;
6907   u8 mac_set = 0;
6908   int ret;
6909
6910   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6911     {
6912       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
6913         ;
6914       else if (unformat (i, "sw_if_index %d", &sw_if_index))
6915         ;
6916       else if (unformat (i, "%U", unformat_vl_api_mac_address, &mac))
6917         mac_set++;
6918       else if (unformat (i, "del"))
6919         is_add = 0;
6920       else
6921         break;
6922     }
6923
6924   if (sw_if_index == ~0)
6925     {
6926       errmsg ("missing interface name or sw_if_index");
6927       return -99;
6928     }
6929
6930   if (!mac_set)
6931     {
6932       errmsg ("missing MAC address");
6933       return -99;
6934     }
6935
6936   /* Construct the API message */
6937   M (SW_INTERFACE_ADD_DEL_MAC_ADDRESS, mp);
6938   mp->sw_if_index = ntohl (sw_if_index);
6939   mp->is_add = is_add;
6940   clib_memcpy (&mp->addr, &mac, sizeof (mac));
6941
6942   S (mp);
6943   W (ret);
6944   return ret;
6945 }
6946
6947 static void vl_api_l2_xconnect_details_t_handler
6948   (vl_api_l2_xconnect_details_t * mp)
6949 {
6950   vat_main_t *vam = &vat_main;
6951
6952   print (vam->ofp, "%15d%15d",
6953          ntohl (mp->rx_sw_if_index), ntohl (mp->tx_sw_if_index));
6954 }
6955
6956 static void vl_api_l2_xconnect_details_t_handler_json
6957   (vl_api_l2_xconnect_details_t * mp)
6958 {
6959   vat_main_t *vam = &vat_main;
6960   vat_json_node_t *node = NULL;
6961
6962   if (VAT_JSON_ARRAY != vam->json_tree.type)
6963     {
6964       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
6965       vat_json_init_array (&vam->json_tree);
6966     }
6967   node = vat_json_array_add (&vam->json_tree);
6968
6969   vat_json_init_object (node);
6970   vat_json_object_add_uint (node, "rx_sw_if_index",
6971                             ntohl (mp->rx_sw_if_index));
6972   vat_json_object_add_uint (node, "tx_sw_if_index",
6973                             ntohl (mp->tx_sw_if_index));
6974 }
6975
6976 static int
6977 api_l2_xconnect_dump (vat_main_t * vam)
6978 {
6979   vl_api_l2_xconnect_dump_t *mp;
6980   vl_api_control_ping_t *mp_ping;
6981   int ret;
6982
6983   if (!vam->json_output)
6984     {
6985       print (vam->ofp, "%15s%15s", "rx_sw_if_index", "tx_sw_if_index");
6986     }
6987
6988   M (L2_XCONNECT_DUMP, mp);
6989
6990   S (mp);
6991
6992   /* Use a control ping for synchronization */
6993   MPING (CONTROL_PING, mp_ping);
6994   S (mp_ping);
6995
6996   W (ret);
6997   return ret;
6998 }
6999
7000 static int
7001 api_hw_interface_set_mtu (vat_main_t * vam)
7002 {
7003   unformat_input_t *i = vam->input;
7004   vl_api_hw_interface_set_mtu_t *mp;
7005   u32 sw_if_index = ~0;
7006   u32 mtu = 0;
7007   int ret;
7008
7009   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7010     {
7011       if (unformat (i, "mtu %d", &mtu))
7012         ;
7013       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
7014         ;
7015       else if (unformat (i, "sw_if_index %d", &sw_if_index))
7016         ;
7017       else
7018         break;
7019     }
7020
7021   if (sw_if_index == ~0)
7022     {
7023       errmsg ("missing interface name or sw_if_index");
7024       return -99;
7025     }
7026
7027   if (mtu == 0)
7028     {
7029       errmsg ("no mtu specified");
7030       return -99;
7031     }
7032
7033   /* Construct the API message */
7034   M (HW_INTERFACE_SET_MTU, mp);
7035   mp->sw_if_index = ntohl (sw_if_index);
7036   mp->mtu = ntohs ((u16) mtu);
7037
7038   S (mp);
7039   W (ret);
7040   return ret;
7041 }
7042
7043 static void vl_api_app_namespace_add_del_reply_t_handler
7044   (vl_api_app_namespace_add_del_reply_t * mp)
7045 {
7046   vat_main_t *vam = &vat_main;
7047   i32 retval = ntohl (mp->retval);
7048   if (vam->async_mode)
7049     {
7050       vam->async_errors += (retval < 0);
7051     }
7052   else
7053     {
7054       vam->retval = retval;
7055       if (retval == 0)
7056         errmsg ("app ns index %d\n", ntohl (mp->appns_index));
7057       vam->result_ready = 1;
7058     }
7059 }
7060
7061 static void vl_api_app_namespace_add_del_reply_t_handler_json
7062   (vl_api_app_namespace_add_del_reply_t * mp)
7063 {
7064   vat_main_t *vam = &vat_main;
7065   vat_json_node_t node;
7066
7067   vat_json_init_object (&node);
7068   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
7069   vat_json_object_add_uint (&node, "appns_index", ntohl (mp->appns_index));
7070
7071   vat_json_print (vam->ofp, &node);
7072   vat_json_free (&node);
7073
7074   vam->retval = ntohl (mp->retval);
7075   vam->result_ready = 1;
7076 }
7077
7078 static int
7079 api_app_namespace_add_del (vat_main_t * vam)
7080 {
7081   vl_api_app_namespace_add_del_t *mp;
7082   unformat_input_t *i = vam->input;
7083   u8 *ns_id = 0, secret_set = 0, sw_if_index_set = 0;
7084   u32 sw_if_index, ip4_fib_id, ip6_fib_id;
7085   u64 secret;
7086   int ret;
7087
7088   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7089     {
7090       if (unformat (i, "id %_%v%_", &ns_id))
7091         ;
7092       else if (unformat (i, "secret %lu", &secret))
7093         secret_set = 1;
7094       else if (unformat (i, "sw_if_index %d", &sw_if_index))
7095         sw_if_index_set = 1;
7096       else if (unformat (i, "ip4_fib_id %d", &ip4_fib_id))
7097         ;
7098       else if (unformat (i, "ip6_fib_id %d", &ip6_fib_id))
7099         ;
7100       else
7101         break;
7102     }
7103   if (!ns_id || !secret_set || !sw_if_index_set)
7104     {
7105       errmsg ("namespace id, secret and sw_if_index must be set");
7106       return -99;
7107     }
7108   if (vec_len (ns_id) > 64)
7109     {
7110       errmsg ("namespace id too long");
7111       return -99;
7112     }
7113   M (APP_NAMESPACE_ADD_DEL, mp);
7114
7115   vl_api_vec_to_api_string (ns_id, &mp->namespace_id);
7116   mp->secret = clib_host_to_net_u64 (secret);
7117   mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
7118   mp->ip4_fib_id = clib_host_to_net_u32 (ip4_fib_id);
7119   mp->ip6_fib_id = clib_host_to_net_u32 (ip6_fib_id);
7120   vec_free (ns_id);
7121   S (mp);
7122   W (ret);
7123   return ret;
7124 }
7125
7126 static int
7127 api_sock_init_shm (vat_main_t * vam)
7128 {
7129 #if VPP_API_TEST_BUILTIN == 0
7130   unformat_input_t *i = vam->input;
7131   vl_api_shm_elem_config_t *config = 0;
7132   u64 size = 64 << 20;
7133   int rv;
7134
7135   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7136     {
7137       if (unformat (i, "size %U", unformat_memory_size, &size))
7138         ;
7139       else
7140         break;
7141     }
7142
7143   /*
7144    * Canned custom ring allocator config.
7145    * Should probably parse all of this
7146    */
7147   vec_validate (config, 6);
7148   config[0].type = VL_API_VLIB_RING;
7149   config[0].size = 256;
7150   config[0].count = 32;
7151
7152   config[1].type = VL_API_VLIB_RING;
7153   config[1].size = 1024;
7154   config[1].count = 16;
7155
7156   config[2].type = VL_API_VLIB_RING;
7157   config[2].size = 4096;
7158   config[2].count = 2;
7159
7160   config[3].type = VL_API_CLIENT_RING;
7161   config[3].size = 256;
7162   config[3].count = 32;
7163
7164   config[4].type = VL_API_CLIENT_RING;
7165   config[4].size = 1024;
7166   config[4].count = 16;
7167
7168   config[5].type = VL_API_CLIENT_RING;
7169   config[5].size = 4096;
7170   config[5].count = 2;
7171
7172   config[6].type = VL_API_QUEUE;
7173   config[6].count = 128;
7174   config[6].size = sizeof (uword);
7175
7176   rv = vl_socket_client_init_shm (config, 1 /* want_pthread */ );
7177   if (!rv)
7178     vam->client_index_invalid = 1;
7179   return rv;
7180 #else
7181   return -99;
7182 #endif
7183 }
7184
7185 static void
7186 vl_api_session_rules_details_t_handler (vl_api_session_rules_details_t * mp)
7187 {
7188   vat_main_t *vam = &vat_main;
7189   fib_prefix_t lcl, rmt;
7190
7191   ip_prefix_decode (&mp->lcl, &lcl);
7192   ip_prefix_decode (&mp->rmt, &rmt);
7193
7194   if (lcl.fp_proto == FIB_PROTOCOL_IP4)
7195     {
7196       print (vam->ofp,
7197              "appns %u tp %u scope %d %U/%d %d %U/%d %d action: %d tag: %s",
7198              clib_net_to_host_u32 (mp->appns_index), mp->transport_proto,
7199              mp->scope, format_ip4_address, &lcl.fp_addr.ip4, lcl.fp_len,
7200              clib_net_to_host_u16 (mp->lcl_port), format_ip4_address,
7201              &rmt.fp_addr.ip4, rmt.fp_len,
7202              clib_net_to_host_u16 (mp->rmt_port),
7203              clib_net_to_host_u32 (mp->action_index), mp->tag);
7204     }
7205   else
7206     {
7207       print (vam->ofp,
7208              "appns %u tp %u scope %d %U/%d %d %U/%d %d action: %d tag: %s",
7209              clib_net_to_host_u32 (mp->appns_index), mp->transport_proto,
7210              mp->scope, format_ip6_address, &lcl.fp_addr.ip6, lcl.fp_len,
7211              clib_net_to_host_u16 (mp->lcl_port), format_ip6_address,
7212              &rmt.fp_addr.ip6, rmt.fp_len,
7213              clib_net_to_host_u16 (mp->rmt_port),
7214              clib_net_to_host_u32 (mp->action_index), mp->tag);
7215     }
7216 }
7217
7218 static void
7219 vl_api_session_rules_details_t_handler_json (vl_api_session_rules_details_t *
7220                                              mp)
7221 {
7222   vat_main_t *vam = &vat_main;
7223   vat_json_node_t *node = NULL;
7224   struct in6_addr ip6;
7225   struct in_addr ip4;
7226
7227   fib_prefix_t lcl, rmt;
7228
7229   ip_prefix_decode (&mp->lcl, &lcl);
7230   ip_prefix_decode (&mp->rmt, &rmt);
7231
7232   if (VAT_JSON_ARRAY != vam->json_tree.type)
7233     {
7234       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
7235       vat_json_init_array (&vam->json_tree);
7236     }
7237   node = vat_json_array_add (&vam->json_tree);
7238   vat_json_init_object (node);
7239
7240   vat_json_object_add_uint (node, "appns_index",
7241                             clib_net_to_host_u32 (mp->appns_index));
7242   vat_json_object_add_uint (node, "transport_proto", mp->transport_proto);
7243   vat_json_object_add_uint (node, "scope", mp->scope);
7244   vat_json_object_add_uint (node, "action_index",
7245                             clib_net_to_host_u32 (mp->action_index));
7246   vat_json_object_add_uint (node, "lcl_port",
7247                             clib_net_to_host_u16 (mp->lcl_port));
7248   vat_json_object_add_uint (node, "rmt_port",
7249                             clib_net_to_host_u16 (mp->rmt_port));
7250   vat_json_object_add_uint (node, "lcl_plen", lcl.fp_len);
7251   vat_json_object_add_uint (node, "rmt_plen", rmt.fp_len);
7252   vat_json_object_add_string_copy (node, "tag", mp->tag);
7253   if (lcl.fp_proto == FIB_PROTOCOL_IP4)
7254     {
7255       clib_memcpy (&ip4, &lcl.fp_addr.ip4, sizeof (ip4));
7256       vat_json_object_add_ip4 (node, "lcl_ip", ip4);
7257       clib_memcpy (&ip4, &rmt.fp_addr.ip4, sizeof (ip4));
7258       vat_json_object_add_ip4 (node, "rmt_ip", ip4);
7259     }
7260   else
7261     {
7262       clib_memcpy (&ip6, &lcl.fp_addr.ip6, sizeof (ip6));
7263       vat_json_object_add_ip6 (node, "lcl_ip", ip6);
7264       clib_memcpy (&ip6, &rmt.fp_addr.ip6, sizeof (ip6));
7265       vat_json_object_add_ip6 (node, "rmt_ip", ip6);
7266     }
7267 }
7268
7269 static int
7270 api_session_rule_add_del (vat_main_t * vam)
7271 {
7272   vl_api_session_rule_add_del_t *mp;
7273   unformat_input_t *i = vam->input;
7274   u32 proto = ~0, lcl_port, rmt_port, action = 0, lcl_plen, rmt_plen;
7275   u32 appns_index = 0, scope = 0;
7276   ip4_address_t lcl_ip4, rmt_ip4;
7277   ip6_address_t lcl_ip6, rmt_ip6;
7278   u8 is_ip4 = 1, conn_set = 0;
7279   u8 is_add = 1, *tag = 0;
7280   int ret;
7281   fib_prefix_t lcl, rmt;
7282
7283   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7284     {
7285       if (unformat (i, "del"))
7286         is_add = 0;
7287       else if (unformat (i, "add"))
7288         ;
7289       else if (unformat (i, "proto tcp"))
7290         proto = 0;
7291       else if (unformat (i, "proto udp"))
7292         proto = 1;
7293       else if (unformat (i, "appns %d", &appns_index))
7294         ;
7295       else if (unformat (i, "scope %d", &scope))
7296         ;
7297       else if (unformat (i, "tag %_%v%_", &tag))
7298         ;
7299       else
7300         if (unformat
7301             (i, "%U/%d %d %U/%d %d", unformat_ip4_address, &lcl_ip4,
7302              &lcl_plen, &lcl_port, unformat_ip4_address, &rmt_ip4, &rmt_plen,
7303              &rmt_port))
7304         {
7305           is_ip4 = 1;
7306           conn_set = 1;
7307         }
7308       else
7309         if (unformat
7310             (i, "%U/%d %d %U/%d %d", unformat_ip6_address, &lcl_ip6,
7311              &lcl_plen, &lcl_port, unformat_ip6_address, &rmt_ip6, &rmt_plen,
7312              &rmt_port))
7313         {
7314           is_ip4 = 0;
7315           conn_set = 1;
7316         }
7317       else if (unformat (i, "action %d", &action))
7318         ;
7319       else
7320         break;
7321     }
7322   if (proto == ~0 || !conn_set || action == ~0)
7323     {
7324       errmsg ("transport proto, connection and action must be set");
7325       return -99;
7326     }
7327
7328   if (scope > 3)
7329     {
7330       errmsg ("scope should be 0-3");
7331       return -99;
7332     }
7333
7334   M (SESSION_RULE_ADD_DEL, mp);
7335
7336   clib_memset (&lcl, 0, sizeof (lcl));
7337   clib_memset (&rmt, 0, sizeof (rmt));
7338   if (is_ip4)
7339     {
7340       ip_set (&lcl.fp_addr, &lcl_ip4, 1);
7341       ip_set (&rmt.fp_addr, &rmt_ip4, 1);
7342       lcl.fp_len = lcl_plen;
7343       rmt.fp_len = rmt_plen;
7344     }
7345   else
7346     {
7347       ip_set (&lcl.fp_addr, &lcl_ip6, 0);
7348       ip_set (&rmt.fp_addr, &rmt_ip6, 0);
7349       lcl.fp_len = lcl_plen;
7350       rmt.fp_len = rmt_plen;
7351     }
7352
7353
7354   ip_prefix_encode (&lcl, &mp->lcl);
7355   ip_prefix_encode (&rmt, &mp->rmt);
7356   mp->lcl_port = clib_host_to_net_u16 ((u16) lcl_port);
7357   mp->rmt_port = clib_host_to_net_u16 ((u16) rmt_port);
7358   mp->transport_proto =
7359     proto ? TRANSPORT_PROTO_API_UDP : TRANSPORT_PROTO_API_TCP;
7360   mp->action_index = clib_host_to_net_u32 (action);
7361   mp->appns_index = clib_host_to_net_u32 (appns_index);
7362   mp->scope = scope;
7363   mp->is_add = is_add;
7364   if (tag)
7365     {
7366       clib_memcpy (mp->tag, tag, vec_len (tag));
7367       vec_free (tag);
7368     }
7369
7370   S (mp);
7371   W (ret);
7372   return ret;
7373 }
7374
7375 static int
7376 api_session_rules_dump (vat_main_t * vam)
7377 {
7378   vl_api_session_rules_dump_t *mp;
7379   vl_api_control_ping_t *mp_ping;
7380   int ret;
7381
7382   if (!vam->json_output)
7383     {
7384       print (vam->ofp, "%=20s", "Session Rules");
7385     }
7386
7387   M (SESSION_RULES_DUMP, mp);
7388   /* send it... */
7389   S (mp);
7390
7391   /* Use a control ping for synchronization */
7392   MPING (CONTROL_PING, mp_ping);
7393   S (mp_ping);
7394
7395   /* Wait for a reply... */
7396   W (ret);
7397   return ret;
7398 }
7399
7400 static int
7401 api_ip_container_proxy_add_del (vat_main_t * vam)
7402 {
7403   vl_api_ip_container_proxy_add_del_t *mp;
7404   unformat_input_t *i = vam->input;
7405   u32 sw_if_index = ~0;
7406   vl_api_prefix_t pfx = { };
7407   u8 is_add = 1;
7408   int ret;
7409
7410   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7411     {
7412       if (unformat (i, "del"))
7413         is_add = 0;
7414       else if (unformat (i, "add"))
7415         ;
7416       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
7417         ;
7418       else if (unformat (i, "sw_if_index %u", &sw_if_index))
7419         ;
7420       else
7421         break;
7422     }
7423   if (sw_if_index == ~0 || pfx.len == 0)
7424     {
7425       errmsg ("address and sw_if_index must be set");
7426       return -99;
7427     }
7428
7429   M (IP_CONTAINER_PROXY_ADD_DEL, mp);
7430
7431   mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
7432   mp->is_add = is_add;
7433   clib_memcpy (&mp->pfx, &pfx, sizeof (pfx));
7434
7435   S (mp);
7436   W (ret);
7437   return ret;
7438 }
7439
7440 static int
7441 q_or_quit (vat_main_t * vam)
7442 {
7443 #if VPP_API_TEST_BUILTIN == 0
7444   longjmp (vam->jump_buf, 1);
7445 #endif
7446   return 0;                     /* not so much */
7447 }
7448
7449 static int
7450 q (vat_main_t * vam)
7451 {
7452   return q_or_quit (vam);
7453 }
7454
7455 static int
7456 quit (vat_main_t * vam)
7457 {
7458   return q_or_quit (vam);
7459 }
7460
7461 static int
7462 comment (vat_main_t * vam)
7463 {
7464   return 0;
7465 }
7466
7467 static int
7468 elog_save (vat_main_t * vam)
7469 {
7470 #if VPP_API_TEST_BUILTIN == 0
7471   elog_main_t *em = &vam->elog_main;
7472   unformat_input_t *i = vam->input;
7473   char *file, *chroot_file;
7474   clib_error_t *error;
7475
7476   if (!unformat (i, "%s", &file))
7477     {
7478       errmsg ("expected file name, got `%U'", format_unformat_error, i);
7479       return 0;
7480     }
7481
7482   /* It's fairly hard to get "../oopsie" through unformat; just in case */
7483   if (strstr (file, "..") || index (file, '/'))
7484     {
7485       errmsg ("illegal characters in filename '%s'", file);
7486       return 0;
7487     }
7488
7489   chroot_file = (char *) format (0, "/tmp/%s%c", file, 0);
7490
7491   vec_free (file);
7492
7493   errmsg ("Saving %wd of %wd events to %s",
7494           elog_n_events_in_buffer (em),
7495           elog_buffer_capacity (em), chroot_file);
7496
7497   error = elog_write_file (em, chroot_file, 1 /* flush ring */ );
7498   vec_free (chroot_file);
7499
7500   if (error)
7501     clib_error_report (error);
7502 #else
7503   errmsg ("Use the vpp event loger...");
7504 #endif
7505
7506   return 0;
7507 }
7508
7509 static int
7510 elog_setup (vat_main_t * vam)
7511 {
7512 #if VPP_API_TEST_BUILTIN == 0
7513   elog_main_t *em = &vam->elog_main;
7514   unformat_input_t *i = vam->input;
7515   u32 nevents = 128 << 10;
7516
7517   (void) unformat (i, "nevents %d", &nevents);
7518
7519   elog_init (em, nevents);
7520   vl_api_set_elog_main (em);
7521   vl_api_set_elog_trace_api_messages (1);
7522   errmsg ("Event logger initialized with %u events", nevents);
7523 #else
7524   errmsg ("Use the vpp event loger...");
7525 #endif
7526   return 0;
7527 }
7528
7529 static int
7530 elog_enable (vat_main_t * vam)
7531 {
7532 #if VPP_API_TEST_BUILTIN == 0
7533   elog_main_t *em = &vam->elog_main;
7534
7535   elog_enable_disable (em, 1 /* enable */ );
7536   vl_api_set_elog_trace_api_messages (1);
7537   errmsg ("Event logger enabled...");
7538 #else
7539   errmsg ("Use the vpp event loger...");
7540 #endif
7541   return 0;
7542 }
7543
7544 static int
7545 elog_disable (vat_main_t * vam)
7546 {
7547 #if VPP_API_TEST_BUILTIN == 0
7548   elog_main_t *em = &vam->elog_main;
7549
7550   elog_enable_disable (em, 0 /* enable */ );
7551   vl_api_set_elog_trace_api_messages (1);
7552   errmsg ("Event logger disabled...");
7553 #else
7554   errmsg ("Use the vpp event loger...");
7555 #endif
7556   return 0;
7557 }
7558
7559 static int
7560 statseg (vat_main_t * vam)
7561 {
7562   ssvm_private_t *ssvmp = &vam->stat_segment;
7563   ssvm_shared_header_t *shared_header = ssvmp->sh;
7564   vlib_counter_t **counters;
7565   u64 thread0_index1_packets;
7566   u64 thread0_index1_bytes;
7567   f64 vector_rate, input_rate;
7568   uword *p;
7569
7570   uword *counter_vector_by_name;
7571   if (vam->stat_segment_lockp == 0)
7572     {
7573       errmsg ("Stat segment not mapped...");
7574       return -99;
7575     }
7576
7577   /* look up "/if/rx for sw_if_index 1 as a test */
7578
7579   clib_spinlock_lock (vam->stat_segment_lockp);
7580
7581   counter_vector_by_name = (uword *) shared_header->opaque[1];
7582
7583   p = hash_get_mem (counter_vector_by_name, "/if/rx");
7584   if (p == 0)
7585     {
7586       clib_spinlock_unlock (vam->stat_segment_lockp);
7587       errmsg ("/if/tx not found?");
7588       return -99;
7589     }
7590
7591   /* Fish per-thread vector of combined counters from shared memory */
7592   counters = (vlib_counter_t **) p[0];
7593
7594   if (vec_len (counters[0]) < 2)
7595     {
7596       clib_spinlock_unlock (vam->stat_segment_lockp);
7597       errmsg ("/if/tx vector length %d", vec_len (counters[0]));
7598       return -99;
7599     }
7600
7601   /* Read thread 0 sw_if_index 1 counter */
7602   thread0_index1_packets = counters[0][1].packets;
7603   thread0_index1_bytes = counters[0][1].bytes;
7604
7605   p = hash_get_mem (counter_vector_by_name, "vector_rate");
7606   if (p == 0)
7607     {
7608       clib_spinlock_unlock (vam->stat_segment_lockp);
7609       errmsg ("vector_rate not found?");
7610       return -99;
7611     }
7612
7613   vector_rate = *(f64 *) (p[0]);
7614   p = hash_get_mem (counter_vector_by_name, "input_rate");
7615   if (p == 0)
7616     {
7617       clib_spinlock_unlock (vam->stat_segment_lockp);
7618       errmsg ("input_rate not found?");
7619       return -99;
7620     }
7621   input_rate = *(f64 *) (p[0]);
7622
7623   clib_spinlock_unlock (vam->stat_segment_lockp);
7624
7625   print (vam->ofp, "vector_rate %.2f input_rate %.2f",
7626          vector_rate, input_rate);
7627   print (vam->ofp, "thread 0 sw_if_index 1 rx pkts %lld, bytes %lld",
7628          thread0_index1_packets, thread0_index1_bytes);
7629
7630   return 0;
7631 }
7632
7633 static int
7634 cmd_cmp (void *a1, void *a2)
7635 {
7636   u8 **c1 = a1;
7637   u8 **c2 = a2;
7638
7639   return strcmp ((char *) (c1[0]), (char *) (c2[0]));
7640 }
7641
7642 static int
7643 help (vat_main_t * vam)
7644 {
7645   u8 **cmds = 0;
7646   u8 *name = 0;
7647   hash_pair_t *p;
7648   unformat_input_t *i = vam->input;
7649   int j;
7650
7651   if (unformat (i, "%s", &name))
7652     {
7653       uword *hs;
7654
7655       vec_add1 (name, 0);
7656
7657       hs = hash_get_mem (vam->help_by_name, name);
7658       if (hs)
7659         print (vam->ofp, "usage: %s %s", name, hs[0]);
7660       else
7661         print (vam->ofp, "No such msg / command '%s'", name);
7662       vec_free (name);
7663       return 0;
7664     }
7665
7666   print (vam->ofp, "Help is available for the following:");
7667
7668     /* *INDENT-OFF* */
7669     hash_foreach_pair (p, vam->function_by_name,
7670     ({
7671       vec_add1 (cmds, (u8 *)(p->key));
7672     }));
7673     /* *INDENT-ON* */
7674
7675   vec_sort_with_function (cmds, cmd_cmp);
7676
7677   for (j = 0; j < vec_len (cmds); j++)
7678     print (vam->ofp, "%s", cmds[j]);
7679
7680   vec_free (cmds);
7681   return 0;
7682 }
7683
7684 static int
7685 set (vat_main_t * vam)
7686 {
7687   u8 *name = 0, *value = 0;
7688   unformat_input_t *i = vam->input;
7689
7690   if (unformat (i, "%s", &name))
7691     {
7692       /* The input buffer is a vector, not a string. */
7693       value = vec_dup (i->buffer);
7694       vec_delete (value, i->index, 0);
7695       /* Almost certainly has a trailing newline */
7696       if (value[vec_len (value) - 1] == '\n')
7697         value[vec_len (value) - 1] = 0;
7698       /* Make sure it's a proper string, one way or the other */
7699       vec_add1 (value, 0);
7700       (void) clib_macro_set_value (&vam->macro_main,
7701                                    (char *) name, (char *) value);
7702     }
7703   else
7704     errmsg ("usage: set <name> <value>");
7705
7706   vec_free (name);
7707   vec_free (value);
7708   return 0;
7709 }
7710
7711 static int
7712 unset (vat_main_t * vam)
7713 {
7714   u8 *name = 0;
7715
7716   if (unformat (vam->input, "%s", &name))
7717     if (clib_macro_unset (&vam->macro_main, (char *) name) == 1)
7718       errmsg ("unset: %s wasn't set", name);
7719   vec_free (name);
7720   return 0;
7721 }
7722
7723 typedef struct
7724 {
7725   u8 *name;
7726   u8 *value;
7727 } macro_sort_t;
7728
7729
7730 static int
7731 macro_sort_cmp (void *a1, void *a2)
7732 {
7733   macro_sort_t *s1 = a1;
7734   macro_sort_t *s2 = a2;
7735
7736   return strcmp ((char *) (s1->name), (char *) (s2->name));
7737 }
7738
7739 static int
7740 dump_macro_table (vat_main_t * vam)
7741 {
7742   macro_sort_t *sort_me = 0, *sm;
7743   int i;
7744   hash_pair_t *p;
7745
7746     /* *INDENT-OFF* */
7747     hash_foreach_pair (p, vam->macro_main.the_value_table_hash,
7748     ({
7749       vec_add2 (sort_me, sm, 1);
7750       sm->name = (u8 *)(p->key);
7751       sm->value = (u8 *) (p->value[0]);
7752     }));
7753     /* *INDENT-ON* */
7754
7755   vec_sort_with_function (sort_me, macro_sort_cmp);
7756
7757   if (vec_len (sort_me))
7758     print (vam->ofp, "%-15s%s", "Name", "Value");
7759   else
7760     print (vam->ofp, "The macro table is empty...");
7761
7762   for (i = 0; i < vec_len (sort_me); i++)
7763     print (vam->ofp, "%-15s%s", sort_me[i].name, sort_me[i].value);
7764   return 0;
7765 }
7766
7767 static int
7768 dump_node_table (vat_main_t * vam)
7769 {
7770   int i, j;
7771   vlib_node_t *node, *next_node;
7772
7773   if (vec_len (vam->graph_nodes) == 0)
7774     {
7775       print (vam->ofp, "Node table empty, issue get_node_graph...");
7776       return 0;
7777     }
7778
7779   for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
7780     {
7781       node = vam->graph_nodes[0][i];
7782       print (vam->ofp, "[%d] %s", i, node->name);
7783       for (j = 0; j < vec_len (node->next_nodes); j++)
7784         {
7785           if (node->next_nodes[j] != ~0)
7786             {
7787               next_node = vam->graph_nodes[0][node->next_nodes[j]];
7788               print (vam->ofp, "  [%d] %s", j, next_node->name);
7789             }
7790         }
7791     }
7792   return 0;
7793 }
7794
7795 static int
7796 value_sort_cmp (void *a1, void *a2)
7797 {
7798   name_sort_t *n1 = a1;
7799   name_sort_t *n2 = a2;
7800
7801   if (n1->value < n2->value)
7802     return -1;
7803   if (n1->value > n2->value)
7804     return 1;
7805   return 0;
7806 }
7807
7808
7809 static int
7810 dump_msg_api_table (vat_main_t * vam)
7811 {
7812   api_main_t *am = vlibapi_get_main ();
7813   name_sort_t *nses = 0, *ns;
7814   hash_pair_t *hp;
7815   int i;
7816
7817   /* *INDENT-OFF* */
7818   hash_foreach_pair (hp, am->msg_index_by_name_and_crc,
7819   ({
7820     vec_add2 (nses, ns, 1);
7821     ns->name = (u8 *)(hp->key);
7822     ns->value = (u32) hp->value[0];
7823   }));
7824   /* *INDENT-ON* */
7825
7826   vec_sort_with_function (nses, value_sort_cmp);
7827
7828   for (i = 0; i < vec_len (nses); i++)
7829     print (vam->ofp, " [%d]: %s", nses[i].value, nses[i].name);
7830   vec_free (nses);
7831   return 0;
7832 }
7833
7834 static int
7835 get_msg_id (vat_main_t * vam)
7836 {
7837   u8 *name_and_crc;
7838   u32 message_index;
7839
7840   if (unformat (vam->input, "%s", &name_and_crc))
7841     {
7842       message_index = vl_msg_api_get_msg_index (name_and_crc);
7843       if (message_index == ~0)
7844         {
7845           print (vam->ofp, " '%s' not found", name_and_crc);
7846           return 0;
7847         }
7848       print (vam->ofp, " '%s' has message index %d",
7849              name_and_crc, message_index);
7850       return 0;
7851     }
7852   errmsg ("name_and_crc required...");
7853   return 0;
7854 }
7855
7856 static int
7857 search_node_table (vat_main_t * vam)
7858 {
7859   unformat_input_t *line_input = vam->input;
7860   u8 *node_to_find;
7861   int j;
7862   vlib_node_t *node, *next_node;
7863   uword *p;
7864
7865   if (vam->graph_node_index_by_name == 0)
7866     {
7867       print (vam->ofp, "Node table empty, issue get_node_graph...");
7868       return 0;
7869     }
7870
7871   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
7872     {
7873       if (unformat (line_input, "%s", &node_to_find))
7874         {
7875           vec_add1 (node_to_find, 0);
7876           p = hash_get_mem (vam->graph_node_index_by_name, node_to_find);
7877           if (p == 0)
7878             {
7879               print (vam->ofp, "%s not found...", node_to_find);
7880               goto out;
7881             }
7882           node = vam->graph_nodes[0][p[0]];
7883           print (vam->ofp, "[%d] %s", p[0], node->name);
7884           for (j = 0; j < vec_len (node->next_nodes); j++)
7885             {
7886               if (node->next_nodes[j] != ~0)
7887                 {
7888                   next_node = vam->graph_nodes[0][node->next_nodes[j]];
7889                   print (vam->ofp, "  [%d] %s", j, next_node->name);
7890                 }
7891             }
7892         }
7893
7894       else
7895         {
7896           clib_warning ("parse error '%U'", format_unformat_error,
7897                         line_input);
7898           return -99;
7899         }
7900
7901     out:
7902       vec_free (node_to_find);
7903
7904     }
7905
7906   return 0;
7907 }
7908
7909
7910 static int
7911 script (vat_main_t * vam)
7912 {
7913 #if (VPP_API_TEST_BUILTIN==0)
7914   u8 *s = 0;
7915   char *save_current_file;
7916   unformat_input_t save_input;
7917   jmp_buf save_jump_buf;
7918   u32 save_line_number;
7919
7920   FILE *new_fp, *save_ifp;
7921
7922   if (unformat (vam->input, "%s", &s))
7923     {
7924       new_fp = fopen ((char *) s, "r");
7925       if (new_fp == 0)
7926         {
7927           errmsg ("Couldn't open script file %s", s);
7928           vec_free (s);
7929           return -99;
7930         }
7931     }
7932   else
7933     {
7934       errmsg ("Missing script name");
7935       return -99;
7936     }
7937
7938   clib_memcpy (&save_input, &vam->input, sizeof (save_input));
7939   clib_memcpy (&save_jump_buf, &vam->jump_buf, sizeof (save_jump_buf));
7940   save_ifp = vam->ifp;
7941   save_line_number = vam->input_line_number;
7942   save_current_file = (char *) vam->current_file;
7943
7944   vam->input_line_number = 0;
7945   vam->ifp = new_fp;
7946   vam->current_file = s;
7947   do_one_file (vam);
7948
7949   clib_memcpy (&vam->input, &save_input, sizeof (save_input));
7950   clib_memcpy (&vam->jump_buf, &save_jump_buf, sizeof (save_jump_buf));
7951   vam->ifp = save_ifp;
7952   vam->input_line_number = save_line_number;
7953   vam->current_file = (u8 *) save_current_file;
7954   vec_free (s);
7955
7956   return 0;
7957 #else
7958   clib_warning ("use the exec command...");
7959   return -99;
7960 #endif
7961 }
7962
7963 static int
7964 echo (vat_main_t * vam)
7965 {
7966   print (vam->ofp, "%v", vam->input->buffer);
7967   return 0;
7968 }
7969
7970 /* List of API message constructors, CLI names map to api_xxx */
7971 #define foreach_vpe_api_msg                                             \
7972 _(create_loopback,"[mac <mac-addr>] [instance <instance>]")             \
7973 _(sw_interface_dump,"")                                                 \
7974 _(sw_interface_set_flags,                                               \
7975   "<intfc> | sw_if_index <id> admin-up | admin-down link-up | link down") \
7976 _(sw_interface_add_del_address,                                         \
7977   "<intfc> | sw_if_index <id> <ip4-address> | <ip6-address> [del] [del-all] ") \
7978 _(sw_interface_set_rx_mode,                                             \
7979   "<intfc> | sw_if_index <id> [queue <id>] <polling | interrupt | adaptive>") \
7980 _(sw_interface_set_rx_placement,                                        \
7981   "<intfc> | sw_if_index <id> [queue <id>] [worker <id> | main]")       \
7982 _(sw_interface_rx_placement_dump,                                       \
7983   "[<intfc> | sw_if_index <id>]")                                         \
7984 _(sw_interface_set_table,                                               \
7985   "<intfc> | sw_if_index <id> vrf <table-id> [ipv6]")                   \
7986 _(sw_interface_set_vpath,                                               \
7987   "<intfc> | sw_if_index <id> enable | disable")                        \
7988 _(sw_interface_set_l2_xconnect,                                         \
7989   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
7990   "enable | disable")                                                   \
7991 _(sw_interface_set_l2_bridge,                                           \
7992   "{<intfc> | sw_if_index <id>} bd_id <bridge-domain-id>\n"             \
7993   "[shg <split-horizon-group>] [bvi]\n"                                 \
7994   "enable | disable")                                                   \
7995 _(bridge_domain_set_mac_age, "bd_id <bridge-domain-id> mac-age 0-255")  \
7996 _(bridge_domain_add_del,                                                \
7997   "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") \
7998 _(bridge_domain_dump, "[bd_id <bridge-domain-id>]\n")                   \
7999 _(l2fib_add_del,                                                        \
8000   "mac <mac-addr> bd_id <bridge-domain-id> [del] | sw_if <intfc> | sw_if_index <id> [static] [filter] [bvi] [count <nn>]\n") \
8001 _(l2fib_flush_bd, "bd_id <bridge-domain-id>")                           \
8002 _(l2fib_flush_int, "<intfc> | sw_if_index <id>")                        \
8003 _(l2_flags,                                                             \
8004   "sw_if <intfc> | sw_if_index <id> [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \
8005 _(bridge_flags,                                                         \
8006   "bd_id <bridge-domain-id> [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \
8007 _(ip_table_add_del,                                                     \
8008   "table <n> [ipv6] [add | del]\n")                                     \
8009 _(ip_route_add_del,                                                     \
8010   "<addr>/<mask> via <<addr>|<intfc>|sw_if_index <id>|via-label <n>>\n" \
8011   "[table-id <n>] [<intfc> | sw_if_index <id>] [resolve-attempts <n>]\n"\
8012   "[weight <n>] [drop] [local] [classify <n>]  [out-label <n>]\n"       \
8013   "[multipath] [count <n>] [del]")                                      \
8014 _(ip_mroute_add_del,                                                    \
8015   "<src> <grp>/<mask> [table-id <n>]\n"                                 \
8016   "[<intfc> | sw_if_index <id>] [local] [del]")                         \
8017 _(sw_interface_set_unnumbered,                                          \
8018   "<intfc> | sw_if_index <id> unnum_if_index <id> [del]")               \
8019 _(create_vlan_subif, "<intfc> | sw_if_index <id> vlan <n>")             \
8020 _(create_subif, "<intfc> | sw_if_index <id> sub_id <n>\n"               \
8021   "[outer_vlan_id <n>][inner_vlan_id <n>]\n"                            \
8022   "[no_tags][one_tag][two_tags][dot1ad][exact_match][default_sub]\n"    \
8023   "[outer_vlan_id_any][inner_vlan_id_any]")                             \
8024 _(ip_table_replace_begin, "table <n> [ipv6]")                           \
8025 _(ip_table_flush, "table <n> [ipv6]")                                   \
8026 _(ip_table_replace_end, "table <n> [ipv6]")                             \
8027 _(set_ip_flow_hash,                                                     \
8028   "vrf <n> [src] [dst] [sport] [dport] [proto] [reverse] [ipv6]")       \
8029 _(sw_interface_ip6_enable_disable,                                      \
8030   "<intfc> | sw_if_index <id> enable | disable")                        \
8031 _(l2_patch_add_del,                                                     \
8032   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
8033   "enable | disable")                                                   \
8034 _(get_node_index, "node <node-name")                                    \
8035 _(add_node_next, "node <node-name> next <next-node-name>")              \
8036 _(l2_fib_clear_table, "")                                               \
8037 _(l2_interface_efp_filter, "sw_if_index <nn> enable | disable")         \
8038 _(l2_interface_vlan_tag_rewrite,                                        \
8039   "<intfc> | sw_if_index <nn> \n"                                       \
8040   "[disable][push-[1|2]][pop-[1|2]][translate-1-[1|2]] \n"              \
8041   "[translate-2-[1|2]] [push_dot1q 0] tag1 <nn> tag2 <nn>")             \
8042 _(show_version, "")                                                     \
8043 _(show_threads, "")                                                     \
8044 _(l2_fib_table_dump, "bd_id <bridge-domain-id>")                        \
8045 _(interface_name_renumber,                                              \
8046   "<intfc> | sw_if_index <nn> new_show_dev_instance <nn>")              \
8047 _(want_l2_macs_events, "[disable] [learn-limit <n>] [scan-delay <n>] [max-entries <n>]") \
8048 _(ip_address_dump, "(ipv4 | ipv6) (<intfc> | sw_if_index <id>)")        \
8049 _(ip_dump, "ipv4 | ipv6")                                               \
8050 _(delete_loopback,"sw_if_index <nn>")                                   \
8051 _(bd_ip_mac_add_del, "bd_id <bridge-domain-id> <ip4/6-addr> <mac-addr> [del]") \
8052 _(bd_ip_mac_flush, "bd_id <bridge-domain-id>")                          \
8053 _(bd_ip_mac_dump, "[bd_id] <bridge-domain-id>")                         \
8054 _(want_interface_events,  "enable|disable")                             \
8055 _(get_first_msg_id, "client <name>")                                    \
8056 _(get_node_graph, " ")                                                  \
8057 _(sw_interface_clear_stats,"<intfc> | sw_if_index <nn>")                \
8058 _(ioam_enable, "[trace] [pow] [ppc <encap|decap>]")                     \
8059 _(ioam_disable, "")                                                     \
8060 _(get_next_index, "node-name <node-name> next-node-name <node-name>")   \
8061 _(ip_source_and_port_range_check_add_del,                               \
8062   "<ip-addr>/<mask> range <nn>-<nn> vrf <id>")                          \
8063 _(ip_source_and_port_range_check_interface_add_del,                     \
8064   "<intf> | sw_if_index <nn> [tcp-out-vrf <id>] [tcp-in-vrf <id>]"      \
8065   "[udp-in-vrf <id>] [udp-out-vrf <id>]")                               \
8066 _(delete_subif,"<intfc> | sw_if_index <nn>")                            \
8067 _(l2_interface_pbb_tag_rewrite,                                         \
8068   "<intfc> | sw_if_index <nn> \n"                                       \
8069   "[disable | push | pop | translate_pbb_stag <outer_tag>] \n"          \
8070   "dmac <mac> smac <mac> sid <nn> [vlanid <nn>]")                       \
8071 _(ip_table_dump, "")                                                    \
8072 _(ip_route_dump, "table-id [ip4|ip6]")                                  \
8073 _(ip_mtable_dump, "")                                                   \
8074 _(ip_mroute_dump, "table-id [ip4|ip6]")                                 \
8075 _(sw_interface_tag_add_del, "<intfc> | sw_if_index <nn> tag <text>"     \
8076 "[disable]")                                                            \
8077 _(sw_interface_add_del_mac_address, "<intfc> | sw_if_index <nn> "       \
8078   "mac <mac-address> [del]")                                            \
8079 _(l2_xconnect_dump, "")                                                 \
8080 _(hw_interface_set_mtu, "<intfc> | hw_if_index <nn> mtu <nn>")        \
8081 _(sw_interface_get_table, "<intfc> | sw_if_index <id> [ipv6]")          \
8082 _(sock_init_shm, "size <nnn>")                                          \
8083 _(app_namespace_add_del, "[add] id <ns-id> secret <nn> sw_if_index <nn>")\
8084 _(session_rule_add_del, "[add|del] proto <tcp/udp> <lcl-ip>/<plen> "    \
8085   "<lcl-port> <rmt-ip>/<plen> <rmt-port> action <nn>")                  \
8086 _(session_rules_dump, "")                                               \
8087 _(ip_container_proxy_add_del, "[add|del] <address> <sw_if_index>")      \
8088
8089 /* List of command functions, CLI names map directly to functions */
8090 #define foreach_cli_function                                    \
8091 _(comment, "usage: comment <ignore-rest-of-line>")              \
8092 _(dump_interface_table, "usage: dump_interface_table")          \
8093 _(dump_sub_interface_table, "usage: dump_sub_interface_table")  \
8094 _(dump_ipv4_table, "usage: dump_ipv4_table")                    \
8095 _(dump_ipv6_table, "usage: dump_ipv6_table")                    \
8096 _(dump_macro_table, "usage: dump_macro_table ")                 \
8097 _(dump_node_table, "usage: dump_node_table")                    \
8098 _(dump_msg_api_table, "usage: dump_msg_api_table")              \
8099 _(elog_setup, "usage: elog_setup [nevents, default 128K]")      \
8100 _(elog_disable, "usage: elog_disable")                          \
8101 _(elog_enable, "usage: elog_enable")                            \
8102 _(elog_save, "usage: elog_save <filename>")                     \
8103 _(get_msg_id, "usage: get_msg_id name_and_crc")                 \
8104 _(echo, "usage: echo <message>")                                \
8105 _(exec, "usage: exec <vpe-debug-CLI-command>")                  \
8106 _(exec_inband, "usage: exec_inband <vpe-debug-CLI-command>")    \
8107 _(help, "usage: help")                                          \
8108 _(q, "usage: quit")                                             \
8109 _(quit, "usage: quit")                                          \
8110 _(search_node_table, "usage: search_node_table <name>...")      \
8111 _(set, "usage: set <variable-name> <value>")                    \
8112 _(script, "usage: script <file-name>")                          \
8113 _(statseg, "usage: statseg")                                    \
8114 _(unset, "usage: unset <variable-name>")
8115
8116 #define _(N,n)                                  \
8117     static void vl_api_##n##_t_handler_uni      \
8118     (vl_api_##n##_t * mp)                       \
8119     {                                           \
8120         vat_main_t * vam = &vat_main;           \
8121         if (vam->json_output) {                 \
8122             vl_api_##n##_t_handler_json(mp);    \
8123         } else {                                \
8124             vl_api_##n##_t_handler(mp);         \
8125         }                                       \
8126     }
8127 foreach_vpe_api_reply_msg;
8128 #if VPP_API_TEST_BUILTIN == 0
8129 foreach_standalone_reply_msg;
8130 #endif
8131 #undef _
8132
8133 void
8134 vat_api_hookup (vat_main_t * vam)
8135 {
8136 #define _(N,n)                                                  \
8137     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
8138                            vl_api_##n##_t_handler_uni,          \
8139                            vl_noop_handler,                     \
8140                            vl_api_##n##_t_endian,               \
8141                            vl_api_##n##_t_print,                \
8142                            sizeof(vl_api_##n##_t), 1);
8143   foreach_vpe_api_reply_msg;
8144 #if VPP_API_TEST_BUILTIN == 0
8145   foreach_standalone_reply_msg;
8146 #endif
8147 #undef _
8148
8149 #if (VPP_API_TEST_BUILTIN==0)
8150   vl_msg_api_set_first_available_msg_id (VL_MSG_FIRST_AVAILABLE);
8151
8152   vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
8153
8154   vam->function_by_name = hash_create_string (0, sizeof (uword));
8155
8156   vam->help_by_name = hash_create_string (0, sizeof (uword));
8157 #endif
8158
8159   /* API messages we can send */
8160 #define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
8161   foreach_vpe_api_msg;
8162 #undef _
8163
8164   /* Help strings */
8165 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
8166   foreach_vpe_api_msg;
8167 #undef _
8168
8169   /* CLI functions */
8170 #define _(n,h) hash_set_mem (vam->function_by_name, #n, n);
8171   foreach_cli_function;
8172 #undef _
8173
8174   /* Help strings */
8175 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
8176   foreach_cli_function;
8177 #undef _
8178 }
8179
8180 #if VPP_API_TEST_BUILTIN
8181 static clib_error_t *
8182 vat_api_hookup_shim (vlib_main_t * vm)
8183 {
8184   vat_api_hookup (&vat_main);
8185   return 0;
8186 }
8187
8188 VLIB_API_INIT_FUNCTION (vat_api_hookup_shim);
8189 #endif
8190
8191 /*
8192  * fd.io coding-style-patch-verification: ON
8193  *
8194  * Local Variables:
8195  * eval: (c-set-style "gnu")
8196  * End:
8197  */