flow: 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 uword
430 unformat_ipsec_api_crypto_alg (unformat_input_t * input, va_list * args)
431 {
432   u32 *r = va_arg (*args, u32 *);
433
434   if (0);
435 #define _(v,f,s) else if (unformat (input, s)) *r = IPSEC_API_CRYPTO_ALG_##f;
436   foreach_ipsec_crypto_alg
437 #undef _
438     else
439     return 0;
440   return 1;
441 }
442
443 uword
444 unformat_ipsec_api_integ_alg (unformat_input_t * input, va_list * args)
445 {
446   u32 *r = va_arg (*args, u32 *);
447
448   if (0);
449 #define _(v,f,s) else if (unformat (input, s)) *r = IPSEC_API_INTEG_ALG_##f;
450   foreach_ipsec_integ_alg
451 #undef _
452     else
453     return 0;
454   return 1;
455 }
456
457 static uword
458 unformat_policer_rate_type (unformat_input_t * input, va_list * args)
459 {
460   u8 *r = va_arg (*args, u8 *);
461
462   if (unformat (input, "kbps"))
463     *r = QOS_RATE_KBPS;
464   else if (unformat (input, "pps"))
465     *r = QOS_RATE_PPS;
466   else
467     return 0;
468   return 1;
469 }
470
471 static uword
472 unformat_policer_round_type (unformat_input_t * input, va_list * args)
473 {
474   u8 *r = va_arg (*args, u8 *);
475
476   if (unformat (input, "closest"))
477     *r = QOS_ROUND_TO_CLOSEST;
478   else if (unformat (input, "up"))
479     *r = QOS_ROUND_TO_UP;
480   else if (unformat (input, "down"))
481     *r = QOS_ROUND_TO_DOWN;
482   else
483     return 0;
484   return 1;
485 }
486
487 static uword
488 unformat_policer_type (unformat_input_t * input, va_list * args)
489 {
490   u8 *r = va_arg (*args, u8 *);
491
492   if (unformat (input, "1r2c"))
493     *r = QOS_POLICER_TYPE_1R2C;
494   else if (unformat (input, "1r3c"))
495     *r = QOS_POLICER_TYPE_1R3C_RFC_2697;
496   else if (unformat (input, "2r3c-2698"))
497     *r = QOS_POLICER_TYPE_2R3C_RFC_2698;
498   else if (unformat (input, "2r3c-4115"))
499     *r = QOS_POLICER_TYPE_2R3C_RFC_4115;
500   else if (unformat (input, "2r3c-mef5cf1"))
501     *r = QOS_POLICER_TYPE_2R3C_RFC_MEF5CF1;
502   else
503     return 0;
504   return 1;
505 }
506
507 static uword
508 unformat_dscp (unformat_input_t * input, va_list * va)
509 {
510   u8 *r = va_arg (*va, u8 *);
511
512   if (0);
513 #define _(v, f) else if (unformat (input, #f)) *r = IP_DSCP_##f;
514   foreach_ip_dscp
515 #undef _
516     else return 0;
517   return 1;
518 }
519
520 static uword
521 unformat_policer_action_type (unformat_input_t * input, va_list * va)
522 {
523   qos_pol_action_params_st *a = va_arg (*va, qos_pol_action_params_st *);
524
525   if (unformat (input, "drop"))
526     a->action_type = QOS_ACTION_DROP;
527   else if (unformat (input, "transmit"))
528     a->action_type = QOS_ACTION_TRANSMIT;
529   else if (unformat (input, "mark-and-transmit %U", unformat_dscp, &a->dscp))
530     a->action_type = QOS_ACTION_MARK_AND_TRANSMIT;
531   else
532     return 0;
533   return 1;
534 }
535
536 #if (VPP_API_TEST_BUILTIN==0)
537
538 static const char *mfib_flag_names[] = MFIB_ENTRY_NAMES_SHORT;
539 static const char *mfib_flag_long_names[] = MFIB_ENTRY_NAMES_LONG;
540 static const char *mfib_itf_flag_long_names[] = MFIB_ITF_NAMES_LONG;
541 static const char *mfib_itf_flag_names[] = MFIB_ITF_NAMES_SHORT;
542
543 uword
544 unformat_mfib_itf_flags (unformat_input_t * input, va_list * args)
545 {
546   mfib_itf_flags_t old, *iflags = va_arg (*args, mfib_itf_flags_t *);
547   mfib_itf_attribute_t attr;
548
549   old = *iflags;
550   FOR_EACH_MFIB_ITF_ATTRIBUTE (attr)
551   {
552     if (unformat (input, mfib_itf_flag_long_names[attr]))
553       *iflags |= (1 << attr);
554   }
555   FOR_EACH_MFIB_ITF_ATTRIBUTE (attr)
556   {
557     if (unformat (input, mfib_itf_flag_names[attr]))
558       *iflags |= (1 << attr);
559   }
560
561   return (old == *iflags ? 0 : 1);
562 }
563
564 uword
565 unformat_mfib_entry_flags (unformat_input_t * input, va_list * args)
566 {
567   mfib_entry_flags_t old, *eflags = va_arg (*args, mfib_entry_flags_t *);
568   mfib_entry_attribute_t attr;
569
570   old = *eflags;
571   FOR_EACH_MFIB_ATTRIBUTE (attr)
572   {
573     if (unformat (input, mfib_flag_long_names[attr]))
574       *eflags |= (1 << attr);
575   }
576   FOR_EACH_MFIB_ATTRIBUTE (attr)
577   {
578     if (unformat (input, mfib_flag_names[attr]))
579       *eflags |= (1 << attr);
580   }
581
582   return (old == *eflags ? 0 : 1);
583 }
584
585 u8 *
586 format_ip4_address (u8 * s, va_list * args)
587 {
588   u8 *a = va_arg (*args, u8 *);
589   return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
590 }
591
592 u8 *
593 format_ip6_address (u8 * s, va_list * args)
594 {
595   ip6_address_t *a = va_arg (*args, ip6_address_t *);
596   u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;
597
598   i_max_n_zero = ARRAY_LEN (a->as_u16);
599   max_n_zeros = 0;
600   i_first_zero = i_max_n_zero;
601   n_zeros = 0;
602   for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
603     {
604       u32 is_zero = a->as_u16[i] == 0;
605       if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16))
606         {
607           i_first_zero = i;
608           n_zeros = 0;
609         }
610       n_zeros += is_zero;
611       if ((!is_zero && n_zeros > max_n_zeros)
612           || (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros))
613         {
614           i_max_n_zero = i_first_zero;
615           max_n_zeros = n_zeros;
616           i_first_zero = ARRAY_LEN (a->as_u16);
617           n_zeros = 0;
618         }
619     }
620
621   last_double_colon = 0;
622   for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
623     {
624       if (i == i_max_n_zero && max_n_zeros > 1)
625         {
626           s = format (s, "::");
627           i += max_n_zeros - 1;
628           last_double_colon = 1;
629         }
630       else
631         {
632           s = format (s, "%s%x",
633                       (last_double_colon || i == 0) ? "" : ":",
634                       clib_net_to_host_u16 (a->as_u16[i]));
635           last_double_colon = 0;
636         }
637     }
638
639   return s;
640 }
641
642 /* Format an IP46 address. */
643 u8 *
644 format_ip46_address (u8 * s, va_list * args)
645 {
646   ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
647   ip46_type_t type = va_arg (*args, ip46_type_t);
648   int is_ip4 = 1;
649
650   switch (type)
651     {
652     case IP46_TYPE_ANY:
653       is_ip4 = ip46_address_is_ip4 (ip46);
654       break;
655     case IP46_TYPE_IP4:
656       is_ip4 = 1;
657       break;
658     case IP46_TYPE_IP6:
659       is_ip4 = 0;
660       break;
661     }
662
663   return is_ip4 ?
664     format (s, "%U", format_ip4_address, &ip46->ip4) :
665     format (s, "%U", format_ip6_address, &ip46->ip6);
666 }
667
668 u8 *
669 format_ethernet_address (u8 * s, va_list * args)
670 {
671   u8 *a = va_arg (*args, u8 *);
672
673   return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
674                  a[0], a[1], a[2], a[3], a[4], a[5]);
675 }
676 #endif
677
678 static void
679 increment_v4_address (vl_api_ip4_address_t * i)
680 {
681   ip4_address_t *a = (ip4_address_t *) i;
682   u32 v;
683
684   v = ntohl (a->as_u32) + 1;
685   a->as_u32 = ntohl (v);
686 }
687
688 static void
689 increment_v6_address (vl_api_ip6_address_t * i)
690 {
691   ip6_address_t *a = (ip6_address_t *) i;
692   u64 v0, v1;
693
694   v0 = clib_net_to_host_u64 (a->as_u64[0]);
695   v1 = clib_net_to_host_u64 (a->as_u64[1]);
696
697   v1 += 1;
698   if (v1 == 0)
699     v0 += 1;
700   a->as_u64[0] = clib_net_to_host_u64 (v0);
701   a->as_u64[1] = clib_net_to_host_u64 (v1);
702 }
703
704 static void
705 increment_address (vl_api_address_t * a)
706 {
707   if (a->af == ADDRESS_IP4)
708     increment_v4_address (&a->un.ip4);
709   else if (a->af == ADDRESS_IP6)
710     increment_v6_address (&a->un.ip6);
711 }
712
713 static void
714 set_ip4_address (vl_api_address_t * a, u32 v)
715 {
716   if (a->af == ADDRESS_IP4)
717     {
718       ip4_address_t *i = (ip4_address_t *) & a->un.ip4;
719       i->as_u32 = v;
720     }
721 }
722
723 void
724 ip_set (ip46_address_t * dst, void *src, u8 is_ip4)
725 {
726   if (is_ip4)
727     dst->ip4.as_u32 = ((ip4_address_t *) src)->as_u32;
728   else
729     clib_memcpy_fast (&dst->ip6, (ip6_address_t *) src,
730                       sizeof (ip6_address_t));
731 }
732
733 static void
734 increment_mac_address (u8 * mac)
735 {
736   u64 tmp = *((u64 *) mac);
737   tmp = clib_net_to_host_u64 (tmp);
738   tmp += 1 << 16;               /* skip unused (least significant) octets */
739   tmp = clib_host_to_net_u64 (tmp);
740
741   clib_memcpy (mac, &tmp, 6);
742 }
743
744 static void
745 vat_json_object_add_address (vat_json_node_t * node,
746                              const char *str, const vl_api_address_t * addr)
747 {
748   if (ADDRESS_IP6 == addr->af)
749     {
750       struct in6_addr ip6;
751
752       clib_memcpy (&ip6, &addr->un.ip6, sizeof (ip6));
753       vat_json_object_add_ip6 (node, str, ip6);
754     }
755   else
756     {
757       struct in_addr ip4;
758
759       clib_memcpy (&ip4, &addr->un.ip4, sizeof (ip4));
760       vat_json_object_add_ip4 (node, str, ip4);
761     }
762 }
763
764 static void
765 vat_json_object_add_prefix (vat_json_node_t * node,
766                             const vl_api_prefix_t * prefix)
767 {
768   vat_json_object_add_uint (node, "len", prefix->len);
769   vat_json_object_add_address (node, "address", &prefix->address);
770 }
771
772 static void vl_api_create_loopback_reply_t_handler
773   (vl_api_create_loopback_reply_t * mp)
774 {
775   vat_main_t *vam = &vat_main;
776   i32 retval = ntohl (mp->retval);
777
778   vam->retval = retval;
779   vam->regenerate_interface_table = 1;
780   vam->sw_if_index = ntohl (mp->sw_if_index);
781   vam->result_ready = 1;
782 }
783
784 static void vl_api_create_loopback_reply_t_handler_json
785   (vl_api_create_loopback_reply_t * mp)
786 {
787   vat_main_t *vam = &vat_main;
788   vat_json_node_t node;
789
790   vat_json_init_object (&node);
791   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
792   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
793
794   vat_json_print (vam->ofp, &node);
795   vat_json_free (&node);
796   vam->retval = ntohl (mp->retval);
797   vam->result_ready = 1;
798 }
799
800 static void vl_api_create_loopback_instance_reply_t_handler
801   (vl_api_create_loopback_instance_reply_t * mp)
802 {
803   vat_main_t *vam = &vat_main;
804   i32 retval = ntohl (mp->retval);
805
806   vam->retval = retval;
807   vam->regenerate_interface_table = 1;
808   vam->sw_if_index = ntohl (mp->sw_if_index);
809   vam->result_ready = 1;
810 }
811
812 static void vl_api_create_loopback_instance_reply_t_handler_json
813   (vl_api_create_loopback_instance_reply_t * mp)
814 {
815   vat_main_t *vam = &vat_main;
816   vat_json_node_t node;
817
818   vat_json_init_object (&node);
819   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
820   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
821
822   vat_json_print (vam->ofp, &node);
823   vat_json_free (&node);
824   vam->retval = ntohl (mp->retval);
825   vam->result_ready = 1;
826 }
827
828 static void vl_api_af_packet_create_reply_t_handler
829   (vl_api_af_packet_create_reply_t * mp)
830 {
831   vat_main_t *vam = &vat_main;
832   i32 retval = ntohl (mp->retval);
833
834   vam->retval = retval;
835   vam->regenerate_interface_table = 1;
836   vam->sw_if_index = ntohl (mp->sw_if_index);
837   vam->result_ready = 1;
838 }
839
840 static void vl_api_af_packet_create_reply_t_handler_json
841   (vl_api_af_packet_create_reply_t * mp)
842 {
843   vat_main_t *vam = &vat_main;
844   vat_json_node_t node;
845
846   vat_json_init_object (&node);
847   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
848   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
849
850   vat_json_print (vam->ofp, &node);
851   vat_json_free (&node);
852
853   vam->retval = ntohl (mp->retval);
854   vam->result_ready = 1;
855 }
856
857 static void vl_api_create_vlan_subif_reply_t_handler
858   (vl_api_create_vlan_subif_reply_t * mp)
859 {
860   vat_main_t *vam = &vat_main;
861   i32 retval = ntohl (mp->retval);
862
863   vam->retval = retval;
864   vam->regenerate_interface_table = 1;
865   vam->sw_if_index = ntohl (mp->sw_if_index);
866   vam->result_ready = 1;
867 }
868
869 static void vl_api_create_vlan_subif_reply_t_handler_json
870   (vl_api_create_vlan_subif_reply_t * mp)
871 {
872   vat_main_t *vam = &vat_main;
873   vat_json_node_t node;
874
875   vat_json_init_object (&node);
876   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
877   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
878
879   vat_json_print (vam->ofp, &node);
880   vat_json_free (&node);
881
882   vam->retval = ntohl (mp->retval);
883   vam->result_ready = 1;
884 }
885
886 static void vl_api_create_subif_reply_t_handler
887   (vl_api_create_subif_reply_t * mp)
888 {
889   vat_main_t *vam = &vat_main;
890   i32 retval = ntohl (mp->retval);
891
892   vam->retval = retval;
893   vam->regenerate_interface_table = 1;
894   vam->sw_if_index = ntohl (mp->sw_if_index);
895   vam->result_ready = 1;
896 }
897
898 static void vl_api_create_subif_reply_t_handler_json
899   (vl_api_create_subif_reply_t * mp)
900 {
901   vat_main_t *vam = &vat_main;
902   vat_json_node_t node;
903
904   vat_json_init_object (&node);
905   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
906   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
907
908   vat_json_print (vam->ofp, &node);
909   vat_json_free (&node);
910
911   vam->retval = ntohl (mp->retval);
912   vam->result_ready = 1;
913 }
914
915 static void vl_api_interface_name_renumber_reply_t_handler
916   (vl_api_interface_name_renumber_reply_t * mp)
917 {
918   vat_main_t *vam = &vat_main;
919   i32 retval = ntohl (mp->retval);
920
921   vam->retval = retval;
922   vam->regenerate_interface_table = 1;
923   vam->result_ready = 1;
924 }
925
926 static void vl_api_interface_name_renumber_reply_t_handler_json
927   (vl_api_interface_name_renumber_reply_t * mp)
928 {
929   vat_main_t *vam = &vat_main;
930   vat_json_node_t node;
931
932   vat_json_init_object (&node);
933   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
934
935   vat_json_print (vam->ofp, &node);
936   vat_json_free (&node);
937
938   vam->retval = ntohl (mp->retval);
939   vam->result_ready = 1;
940 }
941
942 /*
943  * Special-case: build the interface table, maintain
944  * the next loopback sw_if_index vbl.
945  */
946 static void vl_api_sw_interface_details_t_handler
947   (vl_api_sw_interface_details_t * mp)
948 {
949   vat_main_t *vam = &vat_main;
950   u8 *s = format (0, "%s%c", mp->interface_name, 0);
951
952   hash_set_mem (vam->sw_if_index_by_interface_name, s,
953                 ntohl (mp->sw_if_index));
954
955   /* In sub interface case, fill the sub interface table entry */
956   if (mp->sw_if_index != mp->sup_sw_if_index)
957     {
958       sw_interface_subif_t *sub = NULL;
959
960       vec_add2 (vam->sw_if_subif_table, sub, 1);
961
962       vec_validate (sub->interface_name, strlen ((char *) s) + 1);
963       strncpy ((char *) sub->interface_name, (char *) s,
964                vec_len (sub->interface_name));
965       sub->sw_if_index = ntohl (mp->sw_if_index);
966       sub->sub_id = ntohl (mp->sub_id);
967
968       sub->raw_flags = ntohl (mp->sub_if_flags & SUB_IF_API_FLAG_MASK_VNET);
969
970       sub->sub_number_of_tags = mp->sub_number_of_tags;
971       sub->sub_outer_vlan_id = ntohs (mp->sub_outer_vlan_id);
972       sub->sub_inner_vlan_id = ntohs (mp->sub_inner_vlan_id);
973
974       /* vlan tag rewrite */
975       sub->vtr_op = ntohl (mp->vtr_op);
976       sub->vtr_push_dot1q = ntohl (mp->vtr_push_dot1q);
977       sub->vtr_tag1 = ntohl (mp->vtr_tag1);
978       sub->vtr_tag2 = ntohl (mp->vtr_tag2);
979     }
980 }
981
982 static void vl_api_sw_interface_details_t_handler_json
983   (vl_api_sw_interface_details_t * mp)
984 {
985   vat_main_t *vam = &vat_main;
986   vat_json_node_t *node = NULL;
987
988   if (VAT_JSON_ARRAY != vam->json_tree.type)
989     {
990       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
991       vat_json_init_array (&vam->json_tree);
992     }
993   node = vat_json_array_add (&vam->json_tree);
994
995   vat_json_init_object (node);
996   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
997   vat_json_object_add_uint (node, "sup_sw_if_index",
998                             ntohl (mp->sup_sw_if_index));
999   vat_json_object_add_bytes (node, "l2_address", mp->l2_address,
1000                              sizeof (mp->l2_address));
1001   vat_json_object_add_string_copy (node, "interface_name",
1002                                    mp->interface_name);
1003   vat_json_object_add_string_copy (node, "interface_dev_type",
1004                                    mp->interface_dev_type);
1005   vat_json_object_add_uint (node, "flags", mp->flags);
1006   vat_json_object_add_uint (node, "link_duplex", mp->link_duplex);
1007   vat_json_object_add_uint (node, "link_speed", mp->link_speed);
1008   vat_json_object_add_uint (node, "mtu", ntohs (mp->link_mtu));
1009   vat_json_object_add_uint (node, "sub_id", ntohl (mp->sub_id));
1010   vat_json_object_add_uint (node, "sub_number_of_tags",
1011                             mp->sub_number_of_tags);
1012   vat_json_object_add_uint (node, "sub_outer_vlan_id",
1013                             ntohs (mp->sub_outer_vlan_id));
1014   vat_json_object_add_uint (node, "sub_inner_vlan_id",
1015                             ntohs (mp->sub_inner_vlan_id));
1016   vat_json_object_add_uint (node, "sub_if_flags", ntohl (mp->sub_if_flags));
1017   vat_json_object_add_uint (node, "vtr_op", ntohl (mp->vtr_op));
1018   vat_json_object_add_uint (node, "vtr_push_dot1q",
1019                             ntohl (mp->vtr_push_dot1q));
1020   vat_json_object_add_uint (node, "vtr_tag1", ntohl (mp->vtr_tag1));
1021   vat_json_object_add_uint (node, "vtr_tag2", ntohl (mp->vtr_tag2));
1022   if (ntohl (mp->sub_if_flags) & SUB_IF_API_FLAG_DOT1AH)
1023     {
1024       vat_json_object_add_string_copy (node, "pbb_vtr_dmac",
1025                                        format (0, "%U",
1026                                                format_ethernet_address,
1027                                                &mp->b_dmac));
1028       vat_json_object_add_string_copy (node, "pbb_vtr_smac",
1029                                        format (0, "%U",
1030                                                format_ethernet_address,
1031                                                &mp->b_smac));
1032       vat_json_object_add_uint (node, "pbb_vtr_b_vlanid", mp->b_vlanid);
1033       vat_json_object_add_uint (node, "pbb_vtr_i_sid", mp->i_sid);
1034     }
1035 }
1036
1037 #if VPP_API_TEST_BUILTIN == 0
1038 static void vl_api_sw_interface_event_t_handler
1039   (vl_api_sw_interface_event_t * mp)
1040 {
1041   vat_main_t *vam = &vat_main;
1042   if (vam->interface_event_display)
1043     errmsg ("interface flags: sw_if_index %d %s %s",
1044             ntohl (mp->sw_if_index),
1045             ((ntohl (mp->flags)) & IF_STATUS_API_FLAG_ADMIN_UP) ?
1046             "admin-up" : "admin-down",
1047             ((ntohl (mp->flags)) & IF_STATUS_API_FLAG_LINK_UP) ?
1048             "link-up" : "link-down");
1049 }
1050 #endif
1051
1052 __clib_unused static void
1053 vl_api_sw_interface_event_t_handler_json (vl_api_sw_interface_event_t * mp)
1054 {
1055   /* JSON output not supported */
1056 }
1057
1058 static void
1059 vl_api_cli_reply_t_handler (vl_api_cli_reply_t * mp)
1060 {
1061   vat_main_t *vam = &vat_main;
1062   i32 retval = ntohl (mp->retval);
1063
1064   vam->retval = retval;
1065   vam->shmem_result = uword_to_pointer (mp->reply_in_shmem, u8 *);
1066   vam->result_ready = 1;
1067 }
1068
1069 static void
1070 vl_api_cli_reply_t_handler_json (vl_api_cli_reply_t * mp)
1071 {
1072   vat_main_t *vam = &vat_main;
1073   vat_json_node_t node;
1074   void *oldheap;
1075   u8 *reply;
1076
1077   vat_json_init_object (&node);
1078   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1079   vat_json_object_add_uint (&node, "reply_in_shmem",
1080                             ntohl (mp->reply_in_shmem));
1081   /* Toss the shared-memory original... */
1082   oldheap = vl_msg_push_heap ();
1083
1084   reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
1085   vec_free (reply);
1086
1087   vl_msg_pop_heap (oldheap);
1088
1089   vat_json_print (vam->ofp, &node);
1090   vat_json_free (&node);
1091
1092   vam->retval = ntohl (mp->retval);
1093   vam->result_ready = 1;
1094 }
1095
1096 static void
1097 vl_api_cli_inband_reply_t_handler (vl_api_cli_inband_reply_t * mp)
1098 {
1099   vat_main_t *vam = &vat_main;
1100   i32 retval = ntohl (mp->retval);
1101
1102   vec_reset_length (vam->cmd_reply);
1103
1104   vam->retval = retval;
1105   if (retval == 0)
1106     vam->cmd_reply = vl_api_from_api_to_new_vec (mp, &mp->reply);
1107   vam->result_ready = 1;
1108 }
1109
1110 static void
1111 vl_api_cli_inband_reply_t_handler_json (vl_api_cli_inband_reply_t * mp)
1112 {
1113   vat_main_t *vam = &vat_main;
1114   vat_json_node_t node;
1115   u8 *reply = 0;                /* reply vector */
1116
1117   reply = vl_api_from_api_to_new_vec (mp, &mp->reply);
1118   vec_reset_length (vam->cmd_reply);
1119
1120   vat_json_init_object (&node);
1121   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1122   vat_json_object_add_string_copy (&node, "reply", reply);
1123
1124   vat_json_print (vam->ofp, &node);
1125   vat_json_free (&node);
1126   vec_free (reply);
1127
1128   vam->retval = ntohl (mp->retval);
1129   vam->result_ready = 1;
1130 }
1131
1132 static void vl_api_get_node_index_reply_t_handler
1133   (vl_api_get_node_index_reply_t * mp)
1134 {
1135   vat_main_t *vam = &vat_main;
1136   i32 retval = ntohl (mp->retval);
1137   if (vam->async_mode)
1138     {
1139       vam->async_errors += (retval < 0);
1140     }
1141   else
1142     {
1143       vam->retval = retval;
1144       if (retval == 0)
1145         errmsg ("node index %d", ntohl (mp->node_index));
1146       vam->result_ready = 1;
1147     }
1148 }
1149
1150 static void vl_api_get_node_index_reply_t_handler_json
1151   (vl_api_get_node_index_reply_t * mp)
1152 {
1153   vat_main_t *vam = &vat_main;
1154   vat_json_node_t node;
1155
1156   vat_json_init_object (&node);
1157   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1158   vat_json_object_add_uint (&node, "node_index", ntohl (mp->node_index));
1159
1160   vat_json_print (vam->ofp, &node);
1161   vat_json_free (&node);
1162
1163   vam->retval = ntohl (mp->retval);
1164   vam->result_ready = 1;
1165 }
1166
1167 static void vl_api_get_next_index_reply_t_handler
1168   (vl_api_get_next_index_reply_t * mp)
1169 {
1170   vat_main_t *vam = &vat_main;
1171   i32 retval = ntohl (mp->retval);
1172   if (vam->async_mode)
1173     {
1174       vam->async_errors += (retval < 0);
1175     }
1176   else
1177     {
1178       vam->retval = retval;
1179       if (retval == 0)
1180         errmsg ("next node index %d", ntohl (mp->next_index));
1181       vam->result_ready = 1;
1182     }
1183 }
1184
1185 static void vl_api_get_next_index_reply_t_handler_json
1186   (vl_api_get_next_index_reply_t * mp)
1187 {
1188   vat_main_t *vam = &vat_main;
1189   vat_json_node_t node;
1190
1191   vat_json_init_object (&node);
1192   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1193   vat_json_object_add_uint (&node, "next_index", ntohl (mp->next_index));
1194
1195   vat_json_print (vam->ofp, &node);
1196   vat_json_free (&node);
1197
1198   vam->retval = ntohl (mp->retval);
1199   vam->result_ready = 1;
1200 }
1201
1202 static void vl_api_add_node_next_reply_t_handler
1203   (vl_api_add_node_next_reply_t * mp)
1204 {
1205   vat_main_t *vam = &vat_main;
1206   i32 retval = ntohl (mp->retval);
1207   if (vam->async_mode)
1208     {
1209       vam->async_errors += (retval < 0);
1210     }
1211   else
1212     {
1213       vam->retval = retval;
1214       if (retval == 0)
1215         errmsg ("next index %d", ntohl (mp->next_index));
1216       vam->result_ready = 1;
1217     }
1218 }
1219
1220 static void vl_api_add_node_next_reply_t_handler_json
1221   (vl_api_add_node_next_reply_t * mp)
1222 {
1223   vat_main_t *vam = &vat_main;
1224   vat_json_node_t node;
1225
1226   vat_json_init_object (&node);
1227   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1228   vat_json_object_add_uint (&node, "next_index", ntohl (mp->next_index));
1229
1230   vat_json_print (vam->ofp, &node);
1231   vat_json_free (&node);
1232
1233   vam->retval = ntohl (mp->retval);
1234   vam->result_ready = 1;
1235 }
1236
1237 static void vl_api_show_version_reply_t_handler
1238   (vl_api_show_version_reply_t * mp)
1239 {
1240   vat_main_t *vam = &vat_main;
1241   i32 retval = ntohl (mp->retval);
1242
1243   if (retval >= 0)
1244     {
1245       errmsg ("        program: %s", mp->program);
1246       errmsg ("        version: %s", mp->version);
1247       errmsg ("     build date: %s", mp->build_date);
1248       errmsg ("build directory: %s", mp->build_directory);
1249     }
1250   vam->retval = retval;
1251   vam->result_ready = 1;
1252 }
1253
1254 static void vl_api_show_version_reply_t_handler_json
1255   (vl_api_show_version_reply_t * mp)
1256 {
1257   vat_main_t *vam = &vat_main;
1258   vat_json_node_t node;
1259
1260   vat_json_init_object (&node);
1261   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1262   vat_json_object_add_string_copy (&node, "program", mp->program);
1263   vat_json_object_add_string_copy (&node, "version", mp->version);
1264   vat_json_object_add_string_copy (&node, "build_date", mp->build_date);
1265   vat_json_object_add_string_copy (&node, "build_directory",
1266                                    mp->build_directory);
1267
1268   vat_json_print (vam->ofp, &node);
1269   vat_json_free (&node);
1270
1271   vam->retval = ntohl (mp->retval);
1272   vam->result_ready = 1;
1273 }
1274
1275 static void vl_api_show_threads_reply_t_handler
1276   (vl_api_show_threads_reply_t * mp)
1277 {
1278   vat_main_t *vam = &vat_main;
1279   i32 retval = ntohl (mp->retval);
1280   int i, count = 0;
1281
1282   if (retval >= 0)
1283     count = ntohl (mp->count);
1284
1285   for (i = 0; i < count; i++)
1286     print (vam->ofp,
1287            "\n%-2d %-11s %-11s %-5d %-6d %-4d %-6d",
1288            ntohl (mp->thread_data[i].id), mp->thread_data[i].name,
1289            mp->thread_data[i].type, ntohl (mp->thread_data[i].pid),
1290            ntohl (mp->thread_data[i].cpu_id), ntohl (mp->thread_data[i].core),
1291            ntohl (mp->thread_data[i].cpu_socket));
1292
1293   vam->retval = retval;
1294   vam->result_ready = 1;
1295 }
1296
1297 static void vl_api_show_threads_reply_t_handler_json
1298   (vl_api_show_threads_reply_t * mp)
1299 {
1300   vat_main_t *vam = &vat_main;
1301   vat_json_node_t node;
1302   vl_api_thread_data_t *td;
1303   i32 retval = ntohl (mp->retval);
1304   int i, count = 0;
1305
1306   if (retval >= 0)
1307     count = ntohl (mp->count);
1308
1309   vat_json_init_object (&node);
1310   vat_json_object_add_int (&node, "retval", retval);
1311   vat_json_object_add_uint (&node, "count", count);
1312
1313   for (i = 0; i < count; i++)
1314     {
1315       td = &mp->thread_data[i];
1316       vat_json_object_add_uint (&node, "id", ntohl (td->id));
1317       vat_json_object_add_string_copy (&node, "name", td->name);
1318       vat_json_object_add_string_copy (&node, "type", td->type);
1319       vat_json_object_add_uint (&node, "pid", ntohl (td->pid));
1320       vat_json_object_add_int (&node, "cpu_id", ntohl (td->cpu_id));
1321       vat_json_object_add_int (&node, "core", ntohl (td->id));
1322       vat_json_object_add_int (&node, "cpu_socket", ntohl (td->cpu_socket));
1323     }
1324
1325   vat_json_print (vam->ofp, &node);
1326   vat_json_free (&node);
1327
1328   vam->retval = retval;
1329   vam->result_ready = 1;
1330 }
1331
1332 static int
1333 api_show_threads (vat_main_t * vam)
1334 {
1335   vl_api_show_threads_t *mp;
1336   int ret;
1337
1338   print (vam->ofp,
1339          "\n%-2s %-11s %-11s %-5s %-6s %-4s %-6s",
1340          "ID", "Name", "Type", "LWP", "cpu_id", "Core", "Socket");
1341
1342   M (SHOW_THREADS, mp);
1343
1344   S (mp);
1345   W (ret);
1346   return ret;
1347 }
1348
1349 static void
1350 vl_api_l2_macs_event_t_handler (vl_api_l2_macs_event_t * mp)
1351 {
1352   u32 n_macs = ntohl (mp->n_macs);
1353   errmsg ("L2MAC event received with pid %d cl-idx %d for %d macs: \n",
1354           ntohl (mp->pid), mp->client_index, n_macs);
1355   int i;
1356   for (i = 0; i < n_macs; i++)
1357     {
1358       vl_api_mac_entry_t *mac = &mp->mac[i];
1359       errmsg (" [%d] sw_if_index %d  mac_addr %U  action %d \n",
1360               i + 1, ntohl (mac->sw_if_index),
1361               format_ethernet_address, mac->mac_addr, mac->action);
1362       if (i == 1000)
1363         break;
1364     }
1365 }
1366
1367 static void
1368 vl_api_l2_macs_event_t_handler_json (vl_api_l2_macs_event_t * mp)
1369 {
1370   /* JSON output not supported */
1371 }
1372
1373 #define vl_api_bridge_domain_details_t_endian vl_noop_handler
1374 #define vl_api_bridge_domain_details_t_print vl_noop_handler
1375
1376 /*
1377  * Special-case: build the bridge domain table, maintain
1378  * the next bd id vbl.
1379  */
1380 static void vl_api_bridge_domain_details_t_handler
1381   (vl_api_bridge_domain_details_t * mp)
1382 {
1383   vat_main_t *vam = &vat_main;
1384   u32 n_sw_ifs = ntohl (mp->n_sw_ifs);
1385   int i;
1386
1387   print (vam->ofp, "\n%-3s %-3s %-3s %-3s %-3s %-6s %-3s",
1388          " ID", "LRN", "FWD", "FLD", "BVI", "UU-FWD", "#IF");
1389
1390   print (vam->ofp, "%3d %3d %3d %3d %3d %6d %3d",
1391          ntohl (mp->bd_id), mp->learn, mp->forward,
1392          mp->flood, ntohl (mp->bvi_sw_if_index),
1393          ntohl (mp->uu_fwd_sw_if_index), n_sw_ifs);
1394
1395   if (n_sw_ifs)
1396     {
1397       vl_api_bridge_domain_sw_if_t *sw_ifs;
1398       print (vam->ofp, "\n\n%s %s  %s", "sw_if_index", "SHG",
1399              "Interface Name");
1400
1401       sw_ifs = mp->sw_if_details;
1402       for (i = 0; i < n_sw_ifs; i++)
1403         {
1404           u8 *sw_if_name = 0;
1405           u32 sw_if_index;
1406           hash_pair_t *p;
1407
1408           sw_if_index = ntohl (sw_ifs->sw_if_index);
1409
1410           /* *INDENT-OFF* */
1411           hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
1412                              ({
1413                                if ((u32) p->value[0] == sw_if_index)
1414                                  {
1415                                    sw_if_name = (u8 *)(p->key);
1416                                    break;
1417                                  }
1418                              }));
1419           /* *INDENT-ON* */
1420           print (vam->ofp, "%7d     %3d  %s", sw_if_index,
1421                  sw_ifs->shg, sw_if_name ? (char *) sw_if_name :
1422                  "sw_if_index not found!");
1423
1424           sw_ifs++;
1425         }
1426     }
1427 }
1428
1429 static void vl_api_bridge_domain_details_t_handler_json
1430   (vl_api_bridge_domain_details_t * mp)
1431 {
1432   vat_main_t *vam = &vat_main;
1433   vat_json_node_t *node, *array = NULL;
1434   u32 n_sw_ifs = ntohl (mp->n_sw_ifs);
1435
1436   if (VAT_JSON_ARRAY != vam->json_tree.type)
1437     {
1438       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
1439       vat_json_init_array (&vam->json_tree);
1440     }
1441   node = vat_json_array_add (&vam->json_tree);
1442
1443   vat_json_init_object (node);
1444   vat_json_object_add_uint (node, "bd_id", ntohl (mp->bd_id));
1445   vat_json_object_add_uint (node, "flood", mp->flood);
1446   vat_json_object_add_uint (node, "forward", mp->forward);
1447   vat_json_object_add_uint (node, "learn", mp->learn);
1448   vat_json_object_add_uint (node, "bvi_sw_if_index",
1449                             ntohl (mp->bvi_sw_if_index));
1450   vat_json_object_add_uint (node, "n_sw_ifs", n_sw_ifs);
1451   array = vat_json_object_add (node, "sw_if");
1452   vat_json_init_array (array);
1453
1454
1455
1456   if (n_sw_ifs)
1457     {
1458       vl_api_bridge_domain_sw_if_t *sw_ifs;
1459       int i;
1460
1461       sw_ifs = mp->sw_if_details;
1462       for (i = 0; i < n_sw_ifs; i++)
1463         {
1464           node = vat_json_array_add (array);
1465           vat_json_init_object (node);
1466           vat_json_object_add_uint (node, "sw_if_index",
1467                                     ntohl (sw_ifs->sw_if_index));
1468           vat_json_object_add_uint (node, "shg", sw_ifs->shg);
1469           sw_ifs++;
1470         }
1471     }
1472 }
1473
1474 static void vl_api_control_ping_reply_t_handler
1475   (vl_api_control_ping_reply_t * mp)
1476 {
1477   vat_main_t *vam = &vat_main;
1478   i32 retval = ntohl (mp->retval);
1479   if (vam->async_mode)
1480     {
1481       vam->async_errors += (retval < 0);
1482     }
1483   else
1484     {
1485       vam->retval = retval;
1486       vam->result_ready = 1;
1487     }
1488   if (vam->socket_client_main)
1489     vam->socket_client_main->control_pings_outstanding--;
1490 }
1491
1492 static void vl_api_control_ping_reply_t_handler_json
1493   (vl_api_control_ping_reply_t * mp)
1494 {
1495   vat_main_t *vam = &vat_main;
1496   i32 retval = ntohl (mp->retval);
1497
1498   if (VAT_JSON_NONE != vam->json_tree.type)
1499     {
1500       vat_json_print (vam->ofp, &vam->json_tree);
1501       vat_json_free (&vam->json_tree);
1502       vam->json_tree.type = VAT_JSON_NONE;
1503     }
1504   else
1505     {
1506       /* just print [] */
1507       vat_json_init_array (&vam->json_tree);
1508       vat_json_print (vam->ofp, &vam->json_tree);
1509       vam->json_tree.type = VAT_JSON_NONE;
1510     }
1511
1512   vam->retval = retval;
1513   vam->result_ready = 1;
1514 }
1515
1516 static void
1517   vl_api_bridge_domain_set_mac_age_reply_t_handler
1518   (vl_api_bridge_domain_set_mac_age_reply_t * mp)
1519 {
1520   vat_main_t *vam = &vat_main;
1521   i32 retval = ntohl (mp->retval);
1522   if (vam->async_mode)
1523     {
1524       vam->async_errors += (retval < 0);
1525     }
1526   else
1527     {
1528       vam->retval = retval;
1529       vam->result_ready = 1;
1530     }
1531 }
1532
1533 static void vl_api_bridge_domain_set_mac_age_reply_t_handler_json
1534   (vl_api_bridge_domain_set_mac_age_reply_t * mp)
1535 {
1536   vat_main_t *vam = &vat_main;
1537   vat_json_node_t node;
1538
1539   vat_json_init_object (&node);
1540   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1541
1542   vat_json_print (vam->ofp, &node);
1543   vat_json_free (&node);
1544
1545   vam->retval = ntohl (mp->retval);
1546   vam->result_ready = 1;
1547 }
1548
1549 static void
1550 vl_api_l2_flags_reply_t_handler (vl_api_l2_flags_reply_t * mp)
1551 {
1552   vat_main_t *vam = &vat_main;
1553   i32 retval = ntohl (mp->retval);
1554   if (vam->async_mode)
1555     {
1556       vam->async_errors += (retval < 0);
1557     }
1558   else
1559     {
1560       vam->retval = retval;
1561       vam->result_ready = 1;
1562     }
1563 }
1564
1565 static void vl_api_l2_flags_reply_t_handler_json
1566   (vl_api_l2_flags_reply_t * mp)
1567 {
1568   vat_main_t *vam = &vat_main;
1569   vat_json_node_t node;
1570
1571   vat_json_init_object (&node);
1572   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1573   vat_json_object_add_uint (&node, "resulting_feature_bitmap",
1574                             ntohl (mp->resulting_feature_bitmap));
1575
1576   vat_json_print (vam->ofp, &node);
1577   vat_json_free (&node);
1578
1579   vam->retval = ntohl (mp->retval);
1580   vam->result_ready = 1;
1581 }
1582
1583 static void vl_api_bridge_flags_reply_t_handler
1584   (vl_api_bridge_flags_reply_t * mp)
1585 {
1586   vat_main_t *vam = &vat_main;
1587   i32 retval = ntohl (mp->retval);
1588   if (vam->async_mode)
1589     {
1590       vam->async_errors += (retval < 0);
1591     }
1592   else
1593     {
1594       vam->retval = retval;
1595       vam->result_ready = 1;
1596     }
1597 }
1598
1599 static void vl_api_bridge_flags_reply_t_handler_json
1600   (vl_api_bridge_flags_reply_t * mp)
1601 {
1602   vat_main_t *vam = &vat_main;
1603   vat_json_node_t node;
1604
1605   vat_json_init_object (&node);
1606   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1607   vat_json_object_add_uint (&node, "resulting_feature_bitmap",
1608                             ntohl (mp->resulting_feature_bitmap));
1609
1610   vat_json_print (vam->ofp, &node);
1611   vat_json_free (&node);
1612
1613   vam->retval = ntohl (mp->retval);
1614   vam->result_ready = 1;
1615 }
1616
1617 static void
1618 vl_api_tap_create_v2_reply_t_handler (vl_api_tap_create_v2_reply_t * mp)
1619 {
1620   vat_main_t *vam = &vat_main;
1621   i32 retval = ntohl (mp->retval);
1622   if (vam->async_mode)
1623     {
1624       vam->async_errors += (retval < 0);
1625     }
1626   else
1627     {
1628       vam->retval = retval;
1629       vam->sw_if_index = ntohl (mp->sw_if_index);
1630       vam->result_ready = 1;
1631     }
1632
1633 }
1634
1635 static void vl_api_tap_create_v2_reply_t_handler_json
1636   (vl_api_tap_create_v2_reply_t * mp)
1637 {
1638   vat_main_t *vam = &vat_main;
1639   vat_json_node_t node;
1640
1641   vat_json_init_object (&node);
1642   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1643   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1644
1645   vat_json_print (vam->ofp, &node);
1646   vat_json_free (&node);
1647
1648   vam->retval = ntohl (mp->retval);
1649   vam->result_ready = 1;
1650
1651 }
1652
1653 static void
1654 vl_api_tap_delete_v2_reply_t_handler (vl_api_tap_delete_v2_reply_t * mp)
1655 {
1656   vat_main_t *vam = &vat_main;
1657   i32 retval = ntohl (mp->retval);
1658   if (vam->async_mode)
1659     {
1660       vam->async_errors += (retval < 0);
1661     }
1662   else
1663     {
1664       vam->retval = retval;
1665       vam->result_ready = 1;
1666     }
1667 }
1668
1669 static void vl_api_tap_delete_v2_reply_t_handler_json
1670   (vl_api_tap_delete_v2_reply_t * mp)
1671 {
1672   vat_main_t *vam = &vat_main;
1673   vat_json_node_t node;
1674
1675   vat_json_init_object (&node);
1676   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1677
1678   vat_json_print (vam->ofp, &node);
1679   vat_json_free (&node);
1680
1681   vam->retval = ntohl (mp->retval);
1682   vam->result_ready = 1;
1683 }
1684
1685 static void
1686 vl_api_virtio_pci_create_reply_t_handler (vl_api_virtio_pci_create_reply_t *
1687                                           mp)
1688 {
1689   vat_main_t *vam = &vat_main;
1690   i32 retval = ntohl (mp->retval);
1691   if (vam->async_mode)
1692     {
1693       vam->async_errors += (retval < 0);
1694     }
1695   else
1696     {
1697       vam->retval = retval;
1698       vam->sw_if_index = ntohl (mp->sw_if_index);
1699       vam->result_ready = 1;
1700     }
1701 }
1702
1703 static void vl_api_virtio_pci_create_reply_t_handler_json
1704   (vl_api_virtio_pci_create_reply_t * mp)
1705 {
1706   vat_main_t *vam = &vat_main;
1707   vat_json_node_t node;
1708
1709   vat_json_init_object (&node);
1710   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1711   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1712
1713   vat_json_print (vam->ofp, &node);
1714   vat_json_free (&node);
1715
1716   vam->retval = ntohl (mp->retval);
1717   vam->result_ready = 1;
1718
1719 }
1720
1721 static void
1722   vl_api_virtio_pci_create_v2_reply_t_handler
1723   (vl_api_virtio_pci_create_v2_reply_t * mp)
1724 {
1725   vat_main_t *vam = &vat_main;
1726   i32 retval = ntohl (mp->retval);
1727   if (vam->async_mode)
1728     {
1729       vam->async_errors += (retval < 0);
1730     }
1731   else
1732     {
1733       vam->retval = retval;
1734       vam->sw_if_index = ntohl (mp->sw_if_index);
1735       vam->result_ready = 1;
1736     }
1737 }
1738
1739 static void vl_api_virtio_pci_create_v2_reply_t_handler_json
1740   (vl_api_virtio_pci_create_v2_reply_t * mp)
1741 {
1742   vat_main_t *vam = &vat_main;
1743   vat_json_node_t node;
1744
1745   vat_json_init_object (&node);
1746   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1747   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1748
1749   vat_json_print (vam->ofp, &node);
1750   vat_json_free (&node);
1751
1752   vam->retval = ntohl (mp->retval);
1753   vam->result_ready = 1;
1754 }
1755
1756 static void
1757 vl_api_virtio_pci_delete_reply_t_handler (vl_api_virtio_pci_delete_reply_t *
1758                                           mp)
1759 {
1760   vat_main_t *vam = &vat_main;
1761   i32 retval = ntohl (mp->retval);
1762   if (vam->async_mode)
1763     {
1764       vam->async_errors += (retval < 0);
1765     }
1766   else
1767     {
1768       vam->retval = retval;
1769       vam->result_ready = 1;
1770     }
1771 }
1772
1773 static void vl_api_virtio_pci_delete_reply_t_handler_json
1774   (vl_api_virtio_pci_delete_reply_t * mp)
1775 {
1776   vat_main_t *vam = &vat_main;
1777   vat_json_node_t node;
1778
1779   vat_json_init_object (&node);
1780   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1781
1782   vat_json_print (vam->ofp, &node);
1783   vat_json_free (&node);
1784
1785   vam->retval = ntohl (mp->retval);
1786   vam->result_ready = 1;
1787 }
1788
1789 static void
1790 vl_api_bond_create_reply_t_handler (vl_api_bond_create_reply_t * mp)
1791 {
1792   vat_main_t *vam = &vat_main;
1793   i32 retval = ntohl (mp->retval);
1794
1795   if (vam->async_mode)
1796     {
1797       vam->async_errors += (retval < 0);
1798     }
1799   else
1800     {
1801       vam->retval = retval;
1802       vam->sw_if_index = ntohl (mp->sw_if_index);
1803       vam->result_ready = 1;
1804     }
1805 }
1806
1807 static void vl_api_bond_create_reply_t_handler_json
1808   (vl_api_bond_create_reply_t * mp)
1809 {
1810   vat_main_t *vam = &vat_main;
1811   vat_json_node_t node;
1812
1813   vat_json_init_object (&node);
1814   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1815   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1816
1817   vat_json_print (vam->ofp, &node);
1818   vat_json_free (&node);
1819
1820   vam->retval = ntohl (mp->retval);
1821   vam->result_ready = 1;
1822 }
1823
1824 static void
1825 vl_api_bond_create2_reply_t_handler (vl_api_bond_create2_reply_t * mp)
1826 {
1827   vat_main_t *vam = &vat_main;
1828   i32 retval = ntohl (mp->retval);
1829
1830   if (vam->async_mode)
1831     {
1832       vam->async_errors += (retval < 0);
1833     }
1834   else
1835     {
1836       vam->retval = retval;
1837       vam->sw_if_index = ntohl (mp->sw_if_index);
1838       vam->result_ready = 1;
1839     }
1840 }
1841
1842 static void vl_api_bond_create2_reply_t_handler_json
1843   (vl_api_bond_create2_reply_t * mp)
1844 {
1845   vat_main_t *vam = &vat_main;
1846   vat_json_node_t node;
1847
1848   vat_json_init_object (&node);
1849   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1850   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1851
1852   vat_json_print (vam->ofp, &node);
1853   vat_json_free (&node);
1854
1855   vam->retval = ntohl (mp->retval);
1856   vam->result_ready = 1;
1857 }
1858
1859 static void
1860 vl_api_bond_delete_reply_t_handler (vl_api_bond_delete_reply_t * mp)
1861 {
1862   vat_main_t *vam = &vat_main;
1863   i32 retval = ntohl (mp->retval);
1864
1865   if (vam->async_mode)
1866     {
1867       vam->async_errors += (retval < 0);
1868     }
1869   else
1870     {
1871       vam->retval = retval;
1872       vam->result_ready = 1;
1873     }
1874 }
1875
1876 static void vl_api_bond_delete_reply_t_handler_json
1877   (vl_api_bond_delete_reply_t * mp)
1878 {
1879   vat_main_t *vam = &vat_main;
1880   vat_json_node_t node;
1881
1882   vat_json_init_object (&node);
1883   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1884
1885   vat_json_print (vam->ofp, &node);
1886   vat_json_free (&node);
1887
1888   vam->retval = ntohl (mp->retval);
1889   vam->result_ready = 1;
1890 }
1891
1892 static void
1893 vl_api_bond_add_member_reply_t_handler (vl_api_bond_add_member_reply_t * mp)
1894 {
1895   vat_main_t *vam = &vat_main;
1896   i32 retval = ntohl (mp->retval);
1897
1898   if (vam->async_mode)
1899     {
1900       vam->async_errors += (retval < 0);
1901     }
1902   else
1903     {
1904       vam->retval = retval;
1905       vam->result_ready = 1;
1906     }
1907 }
1908
1909 static void vl_api_bond_add_member_reply_t_handler_json
1910   (vl_api_bond_add_member_reply_t * mp)
1911 {
1912   vat_main_t *vam = &vat_main;
1913   vat_json_node_t node;
1914
1915   vat_json_init_object (&node);
1916   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1917
1918   vat_json_print (vam->ofp, &node);
1919   vat_json_free (&node);
1920
1921   vam->retval = ntohl (mp->retval);
1922   vam->result_ready = 1;
1923 }
1924
1925 static void
1926 vl_api_bond_detach_member_reply_t_handler (vl_api_bond_detach_member_reply_t *
1927                                            mp)
1928 {
1929   vat_main_t *vam = &vat_main;
1930   i32 retval = ntohl (mp->retval);
1931
1932   if (vam->async_mode)
1933     {
1934       vam->async_errors += (retval < 0);
1935     }
1936   else
1937     {
1938       vam->retval = retval;
1939       vam->result_ready = 1;
1940     }
1941 }
1942
1943 static void vl_api_bond_detach_member_reply_t_handler_json
1944   (vl_api_bond_detach_member_reply_t * mp)
1945 {
1946   vat_main_t *vam = &vat_main;
1947   vat_json_node_t node;
1948
1949   vat_json_init_object (&node);
1950   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1951
1952   vat_json_print (vam->ofp, &node);
1953   vat_json_free (&node);
1954
1955   vam->retval = ntohl (mp->retval);
1956   vam->result_ready = 1;
1957 }
1958
1959 static int
1960 api_sw_interface_set_bond_weight (vat_main_t * vam)
1961 {
1962   unformat_input_t *i = vam->input;
1963   vl_api_sw_interface_set_bond_weight_t *mp;
1964   u32 sw_if_index = ~0;
1965   u32 weight = 0;
1966   u8 weight_enter = 0;
1967   int ret;
1968
1969   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1970     {
1971       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
1972         ;
1973       else if (unformat (i, "sw_if_index %d", &sw_if_index))
1974         ;
1975       else if (unformat (i, "weight %u", &weight))
1976         weight_enter = 1;
1977       else
1978         break;
1979     }
1980
1981   if (sw_if_index == ~0)
1982     {
1983       errmsg ("missing interface name or sw_if_index");
1984       return -99;
1985     }
1986   if (weight_enter == 0)
1987     {
1988       errmsg ("missing valid weight");
1989       return -99;
1990     }
1991
1992   /* Construct the API message */
1993   M (SW_INTERFACE_SET_BOND_WEIGHT, mp);
1994   mp->sw_if_index = ntohl (sw_if_index);
1995   mp->weight = ntohl (weight);
1996
1997   S (mp);
1998   W (ret);
1999   return ret;
2000 }
2001
2002 static void vl_api_sw_bond_interface_details_t_handler
2003   (vl_api_sw_bond_interface_details_t * mp)
2004 {
2005   vat_main_t *vam = &vat_main;
2006
2007   print (vam->ofp,
2008          "%-16s %-12d %-12U %-13U %-14u %-14u",
2009          mp->interface_name, ntohl (mp->sw_if_index),
2010          format_bond_mode, ntohl (mp->mode), format_bond_load_balance,
2011          ntohl (mp->lb), ntohl (mp->active_members), ntohl (mp->members));
2012 }
2013
2014 static void vl_api_sw_bond_interface_details_t_handler_json
2015   (vl_api_sw_bond_interface_details_t * mp)
2016 {
2017   vat_main_t *vam = &vat_main;
2018   vat_json_node_t *node = NULL;
2019
2020   if (VAT_JSON_ARRAY != vam->json_tree.type)
2021     {
2022       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
2023       vat_json_init_array (&vam->json_tree);
2024     }
2025   node = vat_json_array_add (&vam->json_tree);
2026
2027   vat_json_init_object (node);
2028   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
2029   vat_json_object_add_string_copy (node, "interface_name",
2030                                    mp->interface_name);
2031   vat_json_object_add_uint (node, "mode", ntohl (mp->mode));
2032   vat_json_object_add_uint (node, "load_balance", ntohl (mp->lb));
2033   vat_json_object_add_uint (node, "active_members",
2034                             ntohl (mp->active_members));
2035   vat_json_object_add_uint (node, "members", ntohl (mp->members));
2036 }
2037
2038 static int
2039 api_sw_bond_interface_dump (vat_main_t * vam)
2040 {
2041   unformat_input_t *i = vam->input;
2042   vl_api_sw_bond_interface_dump_t *mp;
2043   vl_api_control_ping_t *mp_ping;
2044   int ret;
2045   u32 sw_if_index = ~0;
2046
2047   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2048     {
2049       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2050         ;
2051       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2052         ;
2053       else
2054         break;
2055     }
2056
2057   print (vam->ofp,
2058          "\n%-16s %-12s %-12s %-13s %-14s %-14s",
2059          "interface name", "sw_if_index", "mode", "load balance",
2060          "active members", "members");
2061
2062   /* Get list of bond interfaces */
2063   M (SW_BOND_INTERFACE_DUMP, mp);
2064   mp->sw_if_index = ntohl (sw_if_index);
2065   S (mp);
2066
2067   /* Use a control ping for synchronization */
2068   MPING (CONTROL_PING, mp_ping);
2069   S (mp_ping);
2070
2071   W (ret);
2072   return ret;
2073 }
2074
2075 static void vl_api_sw_member_interface_details_t_handler
2076   (vl_api_sw_member_interface_details_t * mp)
2077 {
2078   vat_main_t *vam = &vat_main;
2079
2080   print (vam->ofp,
2081          "%-25s %-12d %-7d %-12d %-10d %-10d", mp->interface_name,
2082          ntohl (mp->sw_if_index), mp->is_passive, mp->is_long_timeout,
2083          ntohl (mp->weight), mp->is_local_numa);
2084 }
2085
2086 static void vl_api_sw_member_interface_details_t_handler_json
2087   (vl_api_sw_member_interface_details_t * mp)
2088 {
2089   vat_main_t *vam = &vat_main;
2090   vat_json_node_t *node = NULL;
2091
2092   if (VAT_JSON_ARRAY != vam->json_tree.type)
2093     {
2094       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
2095       vat_json_init_array (&vam->json_tree);
2096     }
2097   node = vat_json_array_add (&vam->json_tree);
2098
2099   vat_json_init_object (node);
2100   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
2101   vat_json_object_add_string_copy (node, "interface_name",
2102                                    mp->interface_name);
2103   vat_json_object_add_uint (node, "passive", mp->is_passive);
2104   vat_json_object_add_uint (node, "long_timeout", mp->is_long_timeout);
2105   vat_json_object_add_uint (node, "weight", ntohl (mp->weight));
2106   vat_json_object_add_uint (node, "is_local_numa", mp->is_local_numa);
2107 }
2108
2109 static int
2110 api_sw_member_interface_dump (vat_main_t * vam)
2111 {
2112   unformat_input_t *i = vam->input;
2113   vl_api_sw_member_interface_dump_t *mp;
2114   vl_api_control_ping_t *mp_ping;
2115   u32 sw_if_index = ~0;
2116   u8 sw_if_index_set = 0;
2117   int ret;
2118
2119   /* Parse args required to build the message */
2120   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2121     {
2122       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2123         sw_if_index_set = 1;
2124       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2125         sw_if_index_set = 1;
2126       else
2127         break;
2128     }
2129
2130   if (sw_if_index_set == 0)
2131     {
2132       errmsg ("missing vpp interface name. ");
2133       return -99;
2134     }
2135
2136   print (vam->ofp,
2137          "\n%-25s %-12s %-7s %-12s %-10s %-10s",
2138          "member interface name", "sw_if_index", "passive", "long_timeout",
2139          "weight", "local numa");
2140
2141   /* Get list of bond interfaces */
2142   M (SW_MEMBER_INTERFACE_DUMP, mp);
2143   mp->sw_if_index = ntohl (sw_if_index);
2144   S (mp);
2145
2146   /* Use a control ping for synchronization */
2147   MPING (CONTROL_PING, mp_ping);
2148   S (mp_ping);
2149
2150   W (ret);
2151   return ret;
2152 }
2153
2154 static void vl_api_mpls_tunnel_add_del_reply_t_handler
2155   (vl_api_mpls_tunnel_add_del_reply_t * mp)
2156 {
2157   vat_main_t *vam = &vat_main;
2158   i32 retval = ntohl (mp->retval);
2159   if (vam->async_mode)
2160     {
2161       vam->async_errors += (retval < 0);
2162     }
2163   else
2164     {
2165       vam->retval = retval;
2166       vam->sw_if_index = ntohl (mp->sw_if_index);
2167       vam->result_ready = 1;
2168     }
2169   vam->regenerate_interface_table = 1;
2170 }
2171
2172 static void vl_api_mpls_tunnel_add_del_reply_t_handler_json
2173   (vl_api_mpls_tunnel_add_del_reply_t * mp)
2174 {
2175   vat_main_t *vam = &vat_main;
2176   vat_json_node_t node;
2177
2178   vat_json_init_object (&node);
2179   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2180   vat_json_object_add_uint (&node, "tunnel_sw_if_index",
2181                             ntohl (mp->sw_if_index));
2182
2183   vat_json_print (vam->ofp, &node);
2184   vat_json_free (&node);
2185
2186   vam->retval = ntohl (mp->retval);
2187   vam->result_ready = 1;
2188 }
2189
2190 static void vl_api_create_vhost_user_if_reply_t_handler
2191   (vl_api_create_vhost_user_if_reply_t * mp)
2192 {
2193   vat_main_t *vam = &vat_main;
2194   i32 retval = ntohl (mp->retval);
2195   if (vam->async_mode)
2196     {
2197       vam->async_errors += (retval < 0);
2198     }
2199   else
2200     {
2201       vam->retval = retval;
2202       vam->sw_if_index = ntohl (mp->sw_if_index);
2203       vam->result_ready = 1;
2204     }
2205   vam->regenerate_interface_table = 1;
2206 }
2207
2208 static void vl_api_create_vhost_user_if_reply_t_handler_json
2209   (vl_api_create_vhost_user_if_reply_t * mp)
2210 {
2211   vat_main_t *vam = &vat_main;
2212   vat_json_node_t node;
2213
2214   vat_json_init_object (&node);
2215   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2216   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
2217
2218   vat_json_print (vam->ofp, &node);
2219   vat_json_free (&node);
2220
2221   vam->retval = ntohl (mp->retval);
2222   vam->result_ready = 1;
2223 }
2224
2225 static void vl_api_create_vhost_user_if_v2_reply_t_handler
2226   (vl_api_create_vhost_user_if_v2_reply_t * mp)
2227 {
2228   vat_main_t *vam = &vat_main;
2229   i32 retval = ntohl (mp->retval);
2230   if (vam->async_mode)
2231     {
2232       vam->async_errors += (retval < 0);
2233     }
2234   else
2235     {
2236       vam->retval = retval;
2237       vam->sw_if_index = ntohl (mp->sw_if_index);
2238       vam->result_ready = 1;
2239     }
2240   vam->regenerate_interface_table = 1;
2241 }
2242
2243 static void vl_api_create_vhost_user_if_v2_reply_t_handler_json
2244   (vl_api_create_vhost_user_if_v2_reply_t * mp)
2245 {
2246   vat_main_t *vam = &vat_main;
2247   vat_json_node_t node;
2248
2249   vat_json_init_object (&node);
2250   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2251   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
2252
2253   vat_json_print (vam->ofp, &node);
2254   vat_json_free (&node);
2255
2256   vam->retval = ntohl (mp->retval);
2257   vam->result_ready = 1;
2258 }
2259
2260 static void vl_api_ip_address_details_t_handler
2261   (vl_api_ip_address_details_t * mp)
2262 {
2263   vat_main_t *vam = &vat_main;
2264   static ip_address_details_t empty_ip_address_details = { {0} };
2265   ip_address_details_t *address = NULL;
2266   ip_details_t *current_ip_details = NULL;
2267   ip_details_t *details = NULL;
2268
2269   details = vam->ip_details_by_sw_if_index[vam->is_ipv6];
2270
2271   if (!details || vam->current_sw_if_index >= vec_len (details)
2272       || !details[vam->current_sw_if_index].present)
2273     {
2274       errmsg ("ip address details arrived but not stored");
2275       errmsg ("ip_dump should be called first");
2276       return;
2277     }
2278
2279   current_ip_details = vec_elt_at_index (details, vam->current_sw_if_index);
2280
2281 #define addresses (current_ip_details->addr)
2282
2283   vec_validate_init_empty (addresses, vec_len (addresses),
2284                            empty_ip_address_details);
2285
2286   address = vec_elt_at_index (addresses, vec_len (addresses) - 1);
2287
2288   clib_memcpy (&address->ip, &mp->prefix.address.un, sizeof (address->ip));
2289   address->prefix_length = mp->prefix.len;
2290 #undef addresses
2291 }
2292
2293 static void vl_api_ip_address_details_t_handler_json
2294   (vl_api_ip_address_details_t * mp)
2295 {
2296   vat_main_t *vam = &vat_main;
2297   vat_json_node_t *node = NULL;
2298
2299   if (VAT_JSON_ARRAY != vam->json_tree.type)
2300     {
2301       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
2302       vat_json_init_array (&vam->json_tree);
2303     }
2304   node = vat_json_array_add (&vam->json_tree);
2305
2306   vat_json_init_object (node);
2307   vat_json_object_add_prefix (node, &mp->prefix);
2308 }
2309
2310 static void
2311 vl_api_ip_details_t_handler (vl_api_ip_details_t * mp)
2312 {
2313   vat_main_t *vam = &vat_main;
2314   static ip_details_t empty_ip_details = { 0 };
2315   ip_details_t *ip = NULL;
2316   u32 sw_if_index = ~0;
2317
2318   sw_if_index = ntohl (mp->sw_if_index);
2319
2320   vec_validate_init_empty (vam->ip_details_by_sw_if_index[vam->is_ipv6],
2321                            sw_if_index, empty_ip_details);
2322
2323   ip = vec_elt_at_index (vam->ip_details_by_sw_if_index[vam->is_ipv6],
2324                          sw_if_index);
2325
2326   ip->present = 1;
2327 }
2328
2329 static void
2330 vl_api_ip_details_t_handler_json (vl_api_ip_details_t * mp)
2331 {
2332   vat_main_t *vam = &vat_main;
2333
2334   if (VAT_JSON_ARRAY != vam->json_tree.type)
2335     {
2336       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
2337       vat_json_init_array (&vam->json_tree);
2338     }
2339   vat_json_array_add_uint (&vam->json_tree,
2340                            clib_net_to_host_u32 (mp->sw_if_index));
2341 }
2342
2343 static void vl_api_get_first_msg_id_reply_t_handler
2344   (vl_api_get_first_msg_id_reply_t * mp)
2345 {
2346   vat_main_t *vam = &vat_main;
2347   i32 retval = ntohl (mp->retval);
2348
2349   if (vam->async_mode)
2350     {
2351       vam->async_errors += (retval < 0);
2352     }
2353   else
2354     {
2355       vam->retval = retval;
2356       vam->result_ready = 1;
2357     }
2358   if (retval >= 0)
2359     {
2360       errmsg ("first message id %d", ntohs (mp->first_msg_id));
2361     }
2362 }
2363
2364 static void vl_api_get_first_msg_id_reply_t_handler_json
2365   (vl_api_get_first_msg_id_reply_t * mp)
2366 {
2367   vat_main_t *vam = &vat_main;
2368   vat_json_node_t node;
2369
2370   vat_json_init_object (&node);
2371   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2372   vat_json_object_add_uint (&node, "first_msg_id",
2373                             (uint) ntohs (mp->first_msg_id));
2374
2375   vat_json_print (vam->ofp, &node);
2376   vat_json_free (&node);
2377
2378   vam->retval = ntohl (mp->retval);
2379   vam->result_ready = 1;
2380 }
2381
2382 static void vl_api_get_node_graph_reply_t_handler
2383   (vl_api_get_node_graph_reply_t * mp)
2384 {
2385   vat_main_t *vam = &vat_main;
2386   i32 retval = ntohl (mp->retval);
2387   u8 *pvt_copy, *reply;
2388   void *oldheap;
2389   vlib_node_t *node;
2390   int i;
2391
2392   if (vam->async_mode)
2393     {
2394       vam->async_errors += (retval < 0);
2395     }
2396   else
2397     {
2398       vam->retval = retval;
2399       vam->result_ready = 1;
2400     }
2401
2402   /* "Should never happen..." */
2403   if (retval != 0)
2404     return;
2405
2406   reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
2407   pvt_copy = vec_dup (reply);
2408
2409   /* Toss the shared-memory original... */
2410   oldheap = vl_msg_push_heap ();
2411
2412   vec_free (reply);
2413
2414   vl_msg_pop_heap (oldheap);
2415
2416   if (vam->graph_nodes)
2417     {
2418       hash_free (vam->graph_node_index_by_name);
2419
2420       for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
2421         {
2422           node = vam->graph_nodes[0][i];
2423           vec_free (node->name);
2424           vec_free (node->next_nodes);
2425           vec_free (node);
2426         }
2427       vec_free (vam->graph_nodes[0]);
2428       vec_free (vam->graph_nodes);
2429     }
2430
2431   vam->graph_node_index_by_name = hash_create_string (0, sizeof (uword));
2432   vam->graph_nodes = vlib_node_unserialize (pvt_copy);
2433   vec_free (pvt_copy);
2434
2435   for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
2436     {
2437       node = vam->graph_nodes[0][i];
2438       hash_set_mem (vam->graph_node_index_by_name, node->name, i);
2439     }
2440 }
2441
2442 static void vl_api_get_node_graph_reply_t_handler_json
2443   (vl_api_get_node_graph_reply_t * mp)
2444 {
2445   vat_main_t *vam = &vat_main;
2446   void *oldheap;
2447   vat_json_node_t node;
2448   u8 *reply;
2449
2450   /* $$$$ make this real? */
2451   vat_json_init_object (&node);
2452   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2453   vat_json_object_add_uint (&node, "reply_in_shmem", mp->reply_in_shmem);
2454
2455   reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
2456
2457   /* Toss the shared-memory original... */
2458   oldheap = vl_msg_push_heap ();
2459
2460   vec_free (reply);
2461
2462   vl_msg_pop_heap (oldheap);
2463
2464   vat_json_print (vam->ofp, &node);
2465   vat_json_free (&node);
2466
2467   vam->retval = ntohl (mp->retval);
2468   vam->result_ready = 1;
2469 }
2470
2471 static u8 *
2472 format_policer_type (u8 * s, va_list * va)
2473 {
2474   u32 i = va_arg (*va, u32);
2475
2476   if (i == QOS_POLICER_TYPE_1R2C)
2477     s = format (s, "1r2c");
2478   else if (i == QOS_POLICER_TYPE_1R3C_RFC_2697)
2479     s = format (s, "1r3c");
2480   else if (i == QOS_POLICER_TYPE_2R3C_RFC_2698)
2481     s = format (s, "2r3c-2698");
2482   else if (i == QOS_POLICER_TYPE_2R3C_RFC_4115)
2483     s = format (s, "2r3c-4115");
2484   else if (i == QOS_POLICER_TYPE_2R3C_RFC_MEF5CF1)
2485     s = format (s, "2r3c-mef5cf1");
2486   else
2487     s = format (s, "ILLEGAL");
2488   return s;
2489 }
2490
2491 static u8 *
2492 format_policer_rate_type (u8 * s, va_list * va)
2493 {
2494   u32 i = va_arg (*va, u32);
2495
2496   if (i == QOS_RATE_KBPS)
2497     s = format (s, "kbps");
2498   else if (i == QOS_RATE_PPS)
2499     s = format (s, "pps");
2500   else
2501     s = format (s, "ILLEGAL");
2502   return s;
2503 }
2504
2505 static u8 *
2506 format_policer_round_type (u8 * s, va_list * va)
2507 {
2508   u32 i = va_arg (*va, u32);
2509
2510   if (i == QOS_ROUND_TO_CLOSEST)
2511     s = format (s, "closest");
2512   else if (i == QOS_ROUND_TO_UP)
2513     s = format (s, "up");
2514   else if (i == QOS_ROUND_TO_DOWN)
2515     s = format (s, "down");
2516   else
2517     s = format (s, "ILLEGAL");
2518   return s;
2519 }
2520
2521 static u8 *
2522 format_policer_action_type (u8 * s, va_list * va)
2523 {
2524   u32 i = va_arg (*va, u32);
2525
2526   if (i == QOS_ACTION_DROP)
2527     s = format (s, "drop");
2528   else if (i == QOS_ACTION_TRANSMIT)
2529     s = format (s, "transmit");
2530   else if (i == QOS_ACTION_MARK_AND_TRANSMIT)
2531     s = format (s, "mark-and-transmit");
2532   else
2533     s = format (s, "ILLEGAL");
2534   return s;
2535 }
2536
2537 static u8 *
2538 format_dscp (u8 * s, va_list * va)
2539 {
2540   u32 i = va_arg (*va, u32);
2541   char *t = 0;
2542
2543   switch (i)
2544     {
2545 #define _(v, f)                                                               \
2546   case IP_DSCP_##f:                                                           \
2547     return (format (s, "%s", #f));
2548       foreach_ip_dscp
2549 #undef _
2550     }
2551   s = format (s, "%s", t);
2552   return (format (s, "ILLEGAL"));
2553 }
2554
2555 static void
2556 vl_api_policer_details_t_handler (vl_api_policer_details_t * mp)
2557 {
2558   vat_main_t *vam = &vat_main;
2559   u8 *conform_dscp_str, *exceed_dscp_str, *violate_dscp_str;
2560
2561   if (mp->conform_action.type == SSE2_QOS_ACTION_API_MARK_AND_TRANSMIT)
2562     conform_dscp_str = format (0, "%U", format_dscp, mp->conform_action.dscp);
2563   else
2564     conform_dscp_str = format (0, "");
2565
2566   if (mp->exceed_action.type == SSE2_QOS_ACTION_API_MARK_AND_TRANSMIT)
2567     exceed_dscp_str = format (0, "%U", format_dscp, mp->exceed_action.dscp);
2568   else
2569     exceed_dscp_str = format (0, "");
2570
2571   if (mp->violate_action.type == SSE2_QOS_ACTION_API_MARK_AND_TRANSMIT)
2572     violate_dscp_str = format (0, "%U", format_dscp, mp->violate_action.dscp);
2573   else
2574     violate_dscp_str = format (0, "");
2575
2576   print (vam->ofp, "Name \"%s\", type %U, cir %u, eir %u, cb %u, eb %u, "
2577          "rate type %U, round type %U, %s rate, %s color-aware, "
2578          "cir %u tok/period, pir %u tok/period, scale %u, cur lim %u, "
2579          "cur bkt %u, ext lim %u, ext bkt %u, last update %llu"
2580          "conform action %U%s, exceed action %U%s, violate action %U%s",
2581          mp->name,
2582          format_policer_type, mp->type,
2583          ntohl (mp->cir),
2584          ntohl (mp->eir),
2585          clib_net_to_host_u64 (mp->cb),
2586          clib_net_to_host_u64 (mp->eb),
2587          format_policer_rate_type, mp->rate_type,
2588          format_policer_round_type, mp->round_type,
2589          mp->single_rate ? "single" : "dual",
2590          mp->color_aware ? "is" : "not",
2591          ntohl (mp->cir_tokens_per_period),
2592          ntohl (mp->pir_tokens_per_period),
2593          ntohl (mp->scale),
2594          ntohl (mp->current_limit),
2595          ntohl (mp->current_bucket),
2596          ntohl (mp->extended_limit),
2597          ntohl (mp->extended_bucket),
2598          clib_net_to_host_u64 (mp->last_update_time),
2599          format_policer_action_type, mp->conform_action.type,
2600          conform_dscp_str,
2601          format_policer_action_type, mp->exceed_action.type,
2602          exceed_dscp_str,
2603          format_policer_action_type, mp->violate_action.type,
2604          violate_dscp_str);
2605
2606   vec_free (conform_dscp_str);
2607   vec_free (exceed_dscp_str);
2608   vec_free (violate_dscp_str);
2609 }
2610
2611 static void vl_api_policer_details_t_handler_json
2612   (vl_api_policer_details_t * mp)
2613 {
2614   vat_main_t *vam = &vat_main;
2615   vat_json_node_t *node;
2616   u8 *rate_type_str, *round_type_str, *type_str;
2617   u8 *conform_action_str, *exceed_action_str, *violate_action_str;
2618
2619   rate_type_str = format (0, "%U", format_policer_rate_type, mp->rate_type);
2620   round_type_str =
2621     format (0, "%U", format_policer_round_type, mp->round_type);
2622   type_str = format (0, "%U", format_policer_type, mp->type);
2623   conform_action_str = format (0, "%U", format_policer_action_type,
2624                                mp->conform_action.type);
2625   exceed_action_str = format (0, "%U", format_policer_action_type,
2626                               mp->exceed_action.type);
2627   violate_action_str = format (0, "%U", format_policer_action_type,
2628                                mp->violate_action.type);
2629
2630   if (VAT_JSON_ARRAY != vam->json_tree.type)
2631     {
2632       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
2633       vat_json_init_array (&vam->json_tree);
2634     }
2635   node = vat_json_array_add (&vam->json_tree);
2636
2637   vat_json_init_object (node);
2638   vat_json_object_add_string_copy (node, "name", mp->name);
2639   vat_json_object_add_uint (node, "cir", ntohl (mp->cir));
2640   vat_json_object_add_uint (node, "eir", ntohl (mp->eir));
2641   vat_json_object_add_uint (node, "cb", clib_net_to_host_u64 (mp->cb));
2642   vat_json_object_add_uint (node, "eb", clib_net_to_host_u64 (mp->eb));
2643   vat_json_object_add_string_copy (node, "rate_type", rate_type_str);
2644   vat_json_object_add_string_copy (node, "round_type", round_type_str);
2645   vat_json_object_add_string_copy (node, "type", type_str);
2646   vat_json_object_add_uint (node, "single_rate", mp->single_rate);
2647   vat_json_object_add_uint (node, "color_aware", mp->color_aware);
2648   vat_json_object_add_uint (node, "scale", ntohl (mp->scale));
2649   vat_json_object_add_uint (node, "cir_tokens_per_period",
2650                             ntohl (mp->cir_tokens_per_period));
2651   vat_json_object_add_uint (node, "eir_tokens_per_period",
2652                             ntohl (mp->pir_tokens_per_period));
2653   vat_json_object_add_uint (node, "current_limit", ntohl (mp->current_limit));
2654   vat_json_object_add_uint (node, "current_bucket",
2655                             ntohl (mp->current_bucket));
2656   vat_json_object_add_uint (node, "extended_limit",
2657                             ntohl (mp->extended_limit));
2658   vat_json_object_add_uint (node, "extended_bucket",
2659                             ntohl (mp->extended_bucket));
2660   vat_json_object_add_uint (node, "last_update_time",
2661                             ntohl (mp->last_update_time));
2662   vat_json_object_add_string_copy (node, "conform_action",
2663                                    conform_action_str);
2664   if (mp->conform_action.type == SSE2_QOS_ACTION_API_MARK_AND_TRANSMIT)
2665     {
2666       u8 *dscp_str = format (0, "%U", format_dscp, mp->conform_action.dscp);
2667       vat_json_object_add_string_copy (node, "conform_dscp", dscp_str);
2668       vec_free (dscp_str);
2669     }
2670   vat_json_object_add_string_copy (node, "exceed_action", exceed_action_str);
2671   if (mp->exceed_action.type == SSE2_QOS_ACTION_API_MARK_AND_TRANSMIT)
2672     {
2673       u8 *dscp_str = format (0, "%U", format_dscp, mp->exceed_action.dscp);
2674       vat_json_object_add_string_copy (node, "exceed_dscp", dscp_str);
2675       vec_free (dscp_str);
2676     }
2677   vat_json_object_add_string_copy (node, "violate_action",
2678                                    violate_action_str);
2679   if (mp->violate_action.type == SSE2_QOS_ACTION_API_MARK_AND_TRANSMIT)
2680     {
2681       u8 *dscp_str = format (0, "%U", format_dscp, mp->violate_action.dscp);
2682       vat_json_object_add_string_copy (node, "violate_dscp", dscp_str);
2683       vec_free (dscp_str);
2684     }
2685
2686   vec_free (rate_type_str);
2687   vec_free (round_type_str);
2688   vec_free (type_str);
2689   vec_free (conform_action_str);
2690   vec_free (exceed_action_str);
2691   vec_free (violate_action_str);
2692 }
2693
2694 static void vl_api_policer_add_del_reply_t_handler
2695   (vl_api_policer_add_del_reply_t * mp)
2696 {
2697   vat_main_t *vam = &vat_main;
2698   i32 retval = ntohl (mp->retval);
2699   if (vam->async_mode)
2700     {
2701       vam->async_errors += (retval < 0);
2702     }
2703   else
2704     {
2705       vam->retval = retval;
2706       vam->result_ready = 1;
2707       if (retval == 0 && mp->policer_index != 0xFFFFFFFF)
2708         /*
2709          * Note: this is just barely thread-safe, depends on
2710          * the main thread spinning waiting for an answer...
2711          */
2712         errmsg ("policer index %d", ntohl (mp->policer_index));
2713     }
2714 }
2715
2716 static void vl_api_policer_add_del_reply_t_handler_json
2717   (vl_api_policer_add_del_reply_t * mp)
2718 {
2719   vat_main_t *vam = &vat_main;
2720   vat_json_node_t node;
2721
2722   vat_json_init_object (&node);
2723   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2724   vat_json_object_add_uint (&node, "policer_index",
2725                             ntohl (mp->policer_index));
2726
2727   vat_json_print (vam->ofp, &node);
2728   vat_json_free (&node);
2729
2730   vam->retval = ntohl (mp->retval);
2731   vam->result_ready = 1;
2732 }
2733
2734 /* Format hex dump. */
2735 u8 *
2736 format_hex_bytes (u8 * s, va_list * va)
2737 {
2738   u8 *bytes = va_arg (*va, u8 *);
2739   int n_bytes = va_arg (*va, int);
2740   uword i;
2741
2742   /* Print short or long form depending on byte count. */
2743   uword short_form = n_bytes <= 32;
2744   u32 indent = format_get_indent (s);
2745
2746   if (n_bytes == 0)
2747     return s;
2748
2749   for (i = 0; i < n_bytes; i++)
2750     {
2751       if (!short_form && (i % 32) == 0)
2752         s = format (s, "%08x: ", i);
2753       s = format (s, "%02x", bytes[i]);
2754       if (!short_form && ((i + 1) % 32) == 0 && (i + 1) < n_bytes)
2755         s = format (s, "\n%U", format_white_space, indent);
2756     }
2757
2758   return s;
2759 }
2760
2761 static void vl_api_pg_create_interface_reply_t_handler
2762   (vl_api_pg_create_interface_reply_t * mp)
2763 {
2764   vat_main_t *vam = &vat_main;
2765
2766   vam->retval = ntohl (mp->retval);
2767   vam->result_ready = 1;
2768 }
2769
2770 static void vl_api_pg_create_interface_reply_t_handler_json
2771   (vl_api_pg_create_interface_reply_t * mp)
2772 {
2773   vat_main_t *vam = &vat_main;
2774   vat_json_node_t node;
2775
2776   i32 retval = ntohl (mp->retval);
2777   if (retval == 0)
2778     {
2779       vat_json_init_object (&node);
2780
2781       vat_json_object_add_int (&node, "sw_if_index", ntohl (mp->sw_if_index));
2782
2783       vat_json_print (vam->ofp, &node);
2784       vat_json_free (&node);
2785     }
2786   vam->retval = ntohl (mp->retval);
2787   vam->result_ready = 1;
2788 }
2789
2790 /*
2791  * Generate boilerplate reply handlers, which
2792  * dig the return value out of the xxx_reply_t API message,
2793  * stick it into vam->retval, and set vam->result_ready
2794  *
2795  * Could also do this by pointing N message decode slots at
2796  * a single function, but that could break in subtle ways.
2797  */
2798
2799 #define foreach_standard_reply_retval_handler           \
2800 _(sw_interface_set_flags_reply)                         \
2801 _(sw_interface_add_del_address_reply)                   \
2802 _(sw_interface_set_rx_mode_reply)                       \
2803 _(sw_interface_set_rx_placement_reply)                  \
2804 _(sw_interface_set_table_reply)                         \
2805 _(sw_interface_set_mpls_enable_reply)                   \
2806 _(sw_interface_set_vpath_reply)                         \
2807 _(sw_interface_set_l2_bridge_reply)                     \
2808 _(sw_interface_set_bond_weight_reply)                   \
2809 _(bridge_domain_add_del_reply)                          \
2810 _(sw_interface_set_l2_xconnect_reply)                   \
2811 _(l2fib_add_del_reply)                                  \
2812 _(l2fib_flush_int_reply)                                \
2813 _(l2fib_flush_bd_reply)                                 \
2814 _(ip_route_add_del_reply)                               \
2815 _(ip_table_add_del_reply)                               \
2816 _(ip_table_replace_begin_reply)                         \
2817 _(ip_table_flush_reply)                                 \
2818 _(ip_table_replace_end_reply)                           \
2819 _(ip_mroute_add_del_reply)                              \
2820 _(mpls_route_add_del_reply)                             \
2821 _(mpls_table_add_del_reply)                             \
2822 _(mpls_ip_bind_unbind_reply)                            \
2823 _(sw_interface_set_unnumbered_reply)                    \
2824 _(set_ip_flow_hash_reply)                               \
2825 _(sw_interface_ip6_enable_disable_reply)                \
2826 _(l2_patch_add_del_reply)                               \
2827 _(sr_mpls_policy_add_reply)                             \
2828 _(sr_mpls_policy_mod_reply)                             \
2829 _(sr_mpls_policy_del_reply)                             \
2830 _(sr_policy_add_reply)                                  \
2831 _(sr_policy_mod_reply)                                  \
2832 _(sr_policy_del_reply)                                  \
2833 _(sr_localsid_add_del_reply)                            \
2834 _(sr_steering_add_del_reply)                            \
2835 _(l2_fib_clear_table_reply)                             \
2836 _(l2_interface_efp_filter_reply)                        \
2837 _(l2_interface_vlan_tag_rewrite_reply)                  \
2838 _(modify_vhost_user_if_reply)                           \
2839 _(modify_vhost_user_if_v2_reply)                        \
2840 _(delete_vhost_user_if_reply)                           \
2841 _(want_l2_macs_events_reply)                            \
2842 _(ipsec_spd_add_del_reply)                              \
2843 _(ipsec_interface_add_del_spd_reply)                    \
2844 _(ipsec_spd_entry_add_del_reply)                        \
2845 _(ipsec_sad_entry_add_del_reply)                        \
2846 _(delete_loopback_reply)                                \
2847 _(bd_ip_mac_add_del_reply)                              \
2848 _(bd_ip_mac_flush_reply)                                \
2849 _(want_interface_events_reply)                          \
2850 _(sw_interface_clear_stats_reply)                       \
2851 _(ioam_enable_reply)                                    \
2852 _(ioam_disable_reply)                                   \
2853 _(af_packet_delete_reply)                               \
2854 _(set_ipfix_exporter_reply)                             \
2855 _(set_ipfix_classify_stream_reply)                      \
2856 _(ipfix_classify_table_add_del_reply)                   \
2857 _(sw_interface_span_enable_disable_reply)               \
2858 _(pg_capture_reply)                                     \
2859 _(pg_enable_disable_reply)                              \
2860 _(pg_interface_enable_disable_coalesce_reply)           \
2861 _(ip_source_and_port_range_check_add_del_reply)         \
2862 _(ip_source_and_port_range_check_interface_add_del_reply)\
2863 _(delete_subif_reply)                                   \
2864 _(l2_interface_pbb_tag_rewrite_reply)                   \
2865 _(set_punt_reply)                                       \
2866 _(feature_enable_disable_reply)                         \
2867 _(sw_interface_tag_add_del_reply)                       \
2868 _(sw_interface_add_del_mac_address_reply)               \
2869 _(hw_interface_set_mtu_reply)                           \
2870 _(p2p_ethernet_add_reply)                               \
2871 _(p2p_ethernet_del_reply)                               \
2872 _(tcp_configure_src_addresses_reply)                    \
2873 _(session_rule_add_del_reply)                           \
2874 _(ip_container_proxy_add_del_reply)                     \
2875 _(qos_record_enable_disable_reply)                      \
2876
2877 #define _(n)                                    \
2878     static void vl_api_##n##_t_handler          \
2879     (vl_api_##n##_t * mp)                       \
2880     {                                           \
2881         vat_main_t * vam = &vat_main;           \
2882         i32 retval = ntohl(mp->retval);         \
2883         if (vam->async_mode) {                  \
2884             vam->async_errors += (retval < 0);  \
2885         } else {                                \
2886             vam->retval = retval;               \
2887             vam->result_ready = 1;              \
2888         }                                       \
2889     }
2890 foreach_standard_reply_retval_handler;
2891 #undef _
2892
2893 #define _(n)                                    \
2894     static void vl_api_##n##_t_handler_json     \
2895     (vl_api_##n##_t * mp)                       \
2896     {                                           \
2897         vat_main_t * vam = &vat_main;           \
2898         vat_json_node_t node;                   \
2899         vat_json_init_object(&node);            \
2900         vat_json_object_add_int(&node, "retval", ntohl(mp->retval));    \
2901         vat_json_print(vam->ofp, &node);        \
2902         vam->retval = ntohl(mp->retval);        \
2903         vam->result_ready = 1;                  \
2904     }
2905 foreach_standard_reply_retval_handler;
2906 #undef _
2907
2908 /*
2909  * Table of message reply handlers, must include boilerplate handlers
2910  * we just generated
2911  */
2912
2913 #define foreach_vpe_api_reply_msg                                       \
2914 _(CREATE_LOOPBACK_REPLY, create_loopback_reply)                         \
2915 _(CREATE_LOOPBACK_INSTANCE_REPLY, create_loopback_instance_reply)       \
2916 _(SW_INTERFACE_DETAILS, sw_interface_details)                           \
2917 _(SW_INTERFACE_SET_FLAGS_REPLY, sw_interface_set_flags_reply)           \
2918 _(CONTROL_PING_REPLY, control_ping_reply)                               \
2919 _(CLI_REPLY, cli_reply)                                                 \
2920 _(CLI_INBAND_REPLY, cli_inband_reply)                                   \
2921 _(SW_INTERFACE_ADD_DEL_ADDRESS_REPLY,                                   \
2922   sw_interface_add_del_address_reply)                                   \
2923 _(SW_INTERFACE_SET_RX_MODE_REPLY, sw_interface_set_rx_mode_reply)       \
2924 _(SW_INTERFACE_SET_RX_PLACEMENT_REPLY, sw_interface_set_rx_placement_reply)     \
2925 _(SW_INTERFACE_RX_PLACEMENT_DETAILS, sw_interface_rx_placement_details) \
2926 _(SW_INTERFACE_SET_TABLE_REPLY, sw_interface_set_table_reply)           \
2927 _(SW_INTERFACE_SET_MPLS_ENABLE_REPLY, sw_interface_set_mpls_enable_reply) \
2928 _(SW_INTERFACE_SET_VPATH_REPLY, sw_interface_set_vpath_reply)           \
2929 _(SW_INTERFACE_SET_L2_XCONNECT_REPLY,                                   \
2930   sw_interface_set_l2_xconnect_reply)                                   \
2931 _(SW_INTERFACE_SET_L2_BRIDGE_REPLY,                                     \
2932   sw_interface_set_l2_bridge_reply)                                     \
2933 _(BRIDGE_DOMAIN_ADD_DEL_REPLY, bridge_domain_add_del_reply)             \
2934 _(BRIDGE_DOMAIN_DETAILS, bridge_domain_details)                         \
2935 _(BRIDGE_DOMAIN_SET_MAC_AGE_REPLY, bridge_domain_set_mac_age_reply)     \
2936 _(L2FIB_ADD_DEL_REPLY, l2fib_add_del_reply)                             \
2937 _(L2FIB_FLUSH_INT_REPLY, l2fib_flush_int_reply)                         \
2938 _(L2FIB_FLUSH_BD_REPLY, l2fib_flush_bd_reply)                           \
2939 _(L2_FLAGS_REPLY, l2_flags_reply)                                       \
2940 _(BRIDGE_FLAGS_REPLY, bridge_flags_reply)                               \
2941 _(TAP_CREATE_V2_REPLY, tap_create_v2_reply)                             \
2942 _(TAP_DELETE_V2_REPLY, tap_delete_v2_reply)                             \
2943 _(SW_INTERFACE_TAP_V2_DETAILS, sw_interface_tap_v2_details)             \
2944 _(VIRTIO_PCI_CREATE_REPLY, virtio_pci_create_reply)                     \
2945 _(VIRTIO_PCI_CREATE_V2_REPLY, virtio_pci_create_v2_reply)               \
2946 _(VIRTIO_PCI_DELETE_REPLY, virtio_pci_delete_reply)                     \
2947 _(SW_INTERFACE_VIRTIO_PCI_DETAILS, sw_interface_virtio_pci_details)     \
2948 _(BOND_CREATE_REPLY, bond_create_reply)                                 \
2949 _(BOND_CREATE2_REPLY, bond_create2_reply)                               \
2950 _(BOND_DELETE_REPLY, bond_delete_reply)                                 \
2951 _(BOND_ADD_MEMBER_REPLY, bond_add_member_reply)                         \
2952 _(BOND_DETACH_MEMBER_REPLY, bond_detach_member_reply)                   \
2953 _(SW_INTERFACE_SET_BOND_WEIGHT_REPLY, sw_interface_set_bond_weight_reply) \
2954 _(SW_BOND_INTERFACE_DETAILS, sw_bond_interface_details)                 \
2955 _(SW_MEMBER_INTERFACE_DETAILS, sw_member_interface_details)               \
2956 _(IP_ROUTE_ADD_DEL_REPLY, ip_route_add_del_reply)                       \
2957 _(IP_TABLE_ADD_DEL_REPLY, ip_table_add_del_reply)                       \
2958 _(IP_TABLE_REPLACE_BEGIN_REPLY, ip_table_replace_begin_reply)           \
2959 _(IP_TABLE_FLUSH_REPLY, ip_table_flush_reply)                           \
2960 _(IP_TABLE_REPLACE_END_REPLY, ip_table_replace_end_reply)               \
2961 _(IP_MROUTE_ADD_DEL_REPLY, ip_mroute_add_del_reply)                     \
2962 _(MPLS_TABLE_ADD_DEL_REPLY, mpls_table_add_del_reply)                   \
2963 _(MPLS_ROUTE_ADD_DEL_REPLY, mpls_route_add_del_reply)                   \
2964 _(MPLS_IP_BIND_UNBIND_REPLY, mpls_ip_bind_unbind_reply)                 \
2965 _(MPLS_TUNNEL_ADD_DEL_REPLY, mpls_tunnel_add_del_reply)                 \
2966 _(SW_INTERFACE_SET_UNNUMBERED_REPLY,                                    \
2967   sw_interface_set_unnumbered_reply)                                    \
2968 _(CREATE_VLAN_SUBIF_REPLY, create_vlan_subif_reply)                     \
2969 _(CREATE_SUBIF_REPLY, create_subif_reply)                               \
2970 _(SET_IP_FLOW_HASH_REPLY, set_ip_flow_hash_reply)                       \
2971 _(SW_INTERFACE_IP6_ENABLE_DISABLE_REPLY,                                \
2972   sw_interface_ip6_enable_disable_reply)                                \
2973 _(L2_PATCH_ADD_DEL_REPLY, l2_patch_add_del_reply)                       \
2974 _(SR_MPLS_POLICY_ADD_REPLY, sr_mpls_policy_add_reply)                   \
2975 _(SR_MPLS_POLICY_MOD_REPLY, sr_mpls_policy_mod_reply)                   \
2976 _(SR_MPLS_POLICY_DEL_REPLY, sr_mpls_policy_del_reply)                   \
2977 _(SR_POLICY_ADD_REPLY, sr_policy_add_reply)                             \
2978 _(SR_POLICY_MOD_REPLY, sr_policy_mod_reply)                             \
2979 _(SR_POLICY_DEL_REPLY, sr_policy_del_reply)                             \
2980 _(SR_LOCALSID_ADD_DEL_REPLY, sr_localsid_add_del_reply)                 \
2981 _(SR_STEERING_ADD_DEL_REPLY, sr_steering_add_del_reply)                 \
2982 _(GET_NODE_INDEX_REPLY, get_node_index_reply)                           \
2983 _(ADD_NODE_NEXT_REPLY, add_node_next_reply)                             \
2984 _(L2_FIB_CLEAR_TABLE_REPLY, l2_fib_clear_table_reply)                   \
2985 _(L2_INTERFACE_EFP_FILTER_REPLY, l2_interface_efp_filter_reply)         \
2986 _(L2_INTERFACE_VLAN_TAG_REWRITE_REPLY, l2_interface_vlan_tag_rewrite_reply) \
2987 _(SW_INTERFACE_VHOST_USER_DETAILS, sw_interface_vhost_user_details)     \
2988 _(CREATE_VHOST_USER_IF_REPLY, create_vhost_user_if_reply)               \
2989 _(MODIFY_VHOST_USER_IF_REPLY, modify_vhost_user_if_reply)               \
2990 _(CREATE_VHOST_USER_IF_V2_REPLY, create_vhost_user_if_v2_reply)         \
2991 _(MODIFY_VHOST_USER_IF_V2_REPLY, modify_vhost_user_if_v2_reply)         \
2992 _(DELETE_VHOST_USER_IF_REPLY, delete_vhost_user_if_reply)               \
2993 _(SHOW_VERSION_REPLY, show_version_reply)                               \
2994 _(SHOW_THREADS_REPLY, show_threads_reply)                               \
2995 _(L2_FIB_TABLE_DETAILS, l2_fib_table_details)                           \
2996 _(INTERFACE_NAME_RENUMBER_REPLY, interface_name_renumber_reply)         \
2997 _(WANT_L2_MACS_EVENTS_REPLY, want_l2_macs_events_reply)                 \
2998 _(L2_MACS_EVENT, l2_macs_event)                                         \
2999 _(IP_ADDRESS_DETAILS, ip_address_details)                               \
3000 _(IP_DETAILS, ip_details)                                               \
3001 _(IPSEC_SPD_ADD_DEL_REPLY, ipsec_spd_add_del_reply)                     \
3002 _(IPSEC_INTERFACE_ADD_DEL_SPD_REPLY, ipsec_interface_add_del_spd_reply) \
3003 _(IPSEC_SPD_ENTRY_ADD_DEL_REPLY, ipsec_spd_entry_add_del_reply)         \
3004 _(IPSEC_SAD_ENTRY_ADD_DEL_REPLY, ipsec_sad_entry_add_del_reply)         \
3005 _(IPSEC_SA_DETAILS, ipsec_sa_details)                                   \
3006 _(DELETE_LOOPBACK_REPLY, delete_loopback_reply)                         \
3007 _(BD_IP_MAC_ADD_DEL_REPLY, bd_ip_mac_add_del_reply)                     \
3008 _(BD_IP_MAC_FLUSH_REPLY, bd_ip_mac_flush_reply)                         \
3009 _(BD_IP_MAC_DETAILS, bd_ip_mac_details)                                 \
3010 _(WANT_INTERFACE_EVENTS_REPLY, want_interface_events_reply)             \
3011 _(GET_FIRST_MSG_ID_REPLY, get_first_msg_id_reply)                       \
3012 _(GET_NODE_GRAPH_REPLY, get_node_graph_reply)                           \
3013 _(SW_INTERFACE_CLEAR_STATS_REPLY, sw_interface_clear_stats_reply)      \
3014 _(IOAM_ENABLE_REPLY, ioam_enable_reply)                   \
3015 _(IOAM_DISABLE_REPLY, ioam_disable_reply)                     \
3016 _(AF_PACKET_CREATE_REPLY, af_packet_create_reply)                       \
3017 _(AF_PACKET_DELETE_REPLY, af_packet_delete_reply)                       \
3018 _(AF_PACKET_DETAILS, af_packet_details)                                 \
3019 _(POLICER_ADD_DEL_REPLY, policer_add_del_reply)                         \
3020 _(POLICER_DETAILS, policer_details)                                     \
3021 _(MPLS_TUNNEL_DETAILS, mpls_tunnel_details)                             \
3022 _(MPLS_TABLE_DETAILS, mpls_table_details)                               \
3023 _(MPLS_ROUTE_DETAILS, mpls_route_details)                               \
3024 _(SET_IPFIX_EXPORTER_REPLY, set_ipfix_exporter_reply)                   \
3025 _(IPFIX_EXPORTER_DETAILS, ipfix_exporter_details)                       \
3026 _(SET_IPFIX_CLASSIFY_STREAM_REPLY, set_ipfix_classify_stream_reply)     \
3027 _(IPFIX_CLASSIFY_STREAM_DETAILS, ipfix_classify_stream_details)         \
3028 _(IPFIX_CLASSIFY_TABLE_ADD_DEL_REPLY, ipfix_classify_table_add_del_reply) \
3029 _(IPFIX_CLASSIFY_TABLE_DETAILS, ipfix_classify_table_details)           \
3030 _(SW_INTERFACE_SPAN_ENABLE_DISABLE_REPLY, sw_interface_span_enable_disable_reply) \
3031 _(SW_INTERFACE_SPAN_DETAILS, sw_interface_span_details)                 \
3032 _(GET_NEXT_INDEX_REPLY, get_next_index_reply)                           \
3033 _(PG_CREATE_INTERFACE_REPLY, pg_create_interface_reply)                 \
3034 _(PG_CAPTURE_REPLY, pg_capture_reply)                                   \
3035 _(PG_ENABLE_DISABLE_REPLY, pg_enable_disable_reply)                     \
3036 _(PG_INTERFACE_ENABLE_DISABLE_COALESCE_REPLY, pg_interface_enable_disable_coalesce_reply) \
3037 _(IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL_REPLY,                         \
3038  ip_source_and_port_range_check_add_del_reply)                          \
3039 _(IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL_REPLY,               \
3040  ip_source_and_port_range_check_interface_add_del_reply)                \
3041 _(DELETE_SUBIF_REPLY, delete_subif_reply)                               \
3042 _(L2_INTERFACE_PBB_TAG_REWRITE_REPLY, l2_interface_pbb_tag_rewrite_reply) \
3043 _(SET_PUNT_REPLY, set_punt_reply)                                       \
3044 _(IP_TABLE_DETAILS, ip_table_details)                                   \
3045 _(IP_ROUTE_DETAILS, ip_route_details)                                   \
3046 _(FEATURE_ENABLE_DISABLE_REPLY, feature_enable_disable_reply)           \
3047 _(SW_INTERFACE_TAG_ADD_DEL_REPLY, sw_interface_tag_add_del_reply)       \
3048 _(SW_INTERFACE_ADD_DEL_MAC_ADDRESS_REPLY, sw_interface_add_del_mac_address_reply) \
3049 _(L2_XCONNECT_DETAILS, l2_xconnect_details)                             \
3050 _(HW_INTERFACE_SET_MTU_REPLY, hw_interface_set_mtu_reply)               \
3051 _(SW_INTERFACE_GET_TABLE_REPLY, sw_interface_get_table_reply)           \
3052 _(P2P_ETHERNET_ADD_REPLY, p2p_ethernet_add_reply)                       \
3053 _(P2P_ETHERNET_DEL_REPLY, p2p_ethernet_del_reply)                       \
3054 _(TCP_CONFIGURE_SRC_ADDRESSES_REPLY, tcp_configure_src_addresses_reply) \
3055 _(APP_NAMESPACE_ADD_DEL_REPLY, app_namespace_add_del_reply)             \
3056 _(SESSION_RULE_ADD_DEL_REPLY, session_rule_add_del_reply)               \
3057 _(SESSION_RULES_DETAILS, session_rules_details)                         \
3058 _(IP_CONTAINER_PROXY_ADD_DEL_REPLY, ip_container_proxy_add_del_reply)   \
3059 _(QOS_RECORD_ENABLE_DISABLE_REPLY, qos_record_enable_disable_reply)             \
3060
3061 #define foreach_standalone_reply_msg                                    \
3062 _(SW_INTERFACE_EVENT, sw_interface_event)
3063
3064 typedef struct
3065 {
3066   u8 *name;
3067   u32 value;
3068 } name_sort_t;
3069
3070 #define STR_VTR_OP_CASE(op)     \
3071     case L2_VTR_ ## op:         \
3072         return "" # op;
3073
3074 static const char *
3075 str_vtr_op (u32 vtr_op)
3076 {
3077   switch (vtr_op)
3078     {
3079       STR_VTR_OP_CASE (DISABLED);
3080       STR_VTR_OP_CASE (PUSH_1);
3081       STR_VTR_OP_CASE (PUSH_2);
3082       STR_VTR_OP_CASE (POP_1);
3083       STR_VTR_OP_CASE (POP_2);
3084       STR_VTR_OP_CASE (TRANSLATE_1_1);
3085       STR_VTR_OP_CASE (TRANSLATE_1_2);
3086       STR_VTR_OP_CASE (TRANSLATE_2_1);
3087       STR_VTR_OP_CASE (TRANSLATE_2_2);
3088     }
3089
3090   return "UNKNOWN";
3091 }
3092
3093 static int
3094 dump_sub_interface_table (vat_main_t * vam)
3095 {
3096   const sw_interface_subif_t *sub = NULL;
3097
3098   if (vam->json_output)
3099     {
3100       clib_warning
3101         ("JSON output supported only for VPE API calls and dump_stats_table");
3102       return -99;
3103     }
3104
3105   print (vam->ofp,
3106          "%-30s%-12s%-11s%-7s%-5s%-9s%-9s%-6s%-8s%-10s%-10s",
3107          "Interface", "sw_if_index",
3108          "sub id", "dot1ad", "tags", "outer id",
3109          "inner id", "exact", "default", "outer any", "inner any");
3110
3111   vec_foreach (sub, vam->sw_if_subif_table)
3112   {
3113     print (vam->ofp,
3114            "%-30s%-12d%-11d%-7s%-5d%-9d%-9d%-6d%-8d%-10d%-10d",
3115            sub->interface_name,
3116            sub->sw_if_index,
3117            sub->sub_id, sub->sub_dot1ad ? "dot1ad" : "dot1q",
3118            sub->sub_number_of_tags, sub->sub_outer_vlan_id,
3119            sub->sub_inner_vlan_id, sub->sub_exact_match, sub->sub_default,
3120            sub->sub_outer_vlan_id_any, sub->sub_inner_vlan_id_any);
3121     if (sub->vtr_op != L2_VTR_DISABLED)
3122       {
3123         print (vam->ofp,
3124                "  vlan-tag-rewrite - op: %-14s [ dot1q: %d "
3125                "tag1: %d tag2: %d ]",
3126                str_vtr_op (sub->vtr_op), sub->vtr_push_dot1q,
3127                sub->vtr_tag1, sub->vtr_tag2);
3128       }
3129   }
3130
3131   return 0;
3132 }
3133
3134 static int
3135 name_sort_cmp (void *a1, void *a2)
3136 {
3137   name_sort_t *n1 = a1;
3138   name_sort_t *n2 = a2;
3139
3140   return strcmp ((char *) n1->name, (char *) n2->name);
3141 }
3142
3143 static int
3144 dump_interface_table (vat_main_t * vam)
3145 {
3146   hash_pair_t *p;
3147   name_sort_t *nses = 0, *ns;
3148
3149   if (vam->json_output)
3150     {
3151       clib_warning
3152         ("JSON output supported only for VPE API calls and dump_stats_table");
3153       return -99;
3154     }
3155
3156   /* *INDENT-OFF* */
3157   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
3158   ({
3159     vec_add2 (nses, ns, 1);
3160     ns->name = (u8 *)(p->key);
3161     ns->value = (u32) p->value[0];
3162   }));
3163   /* *INDENT-ON* */
3164
3165   vec_sort_with_function (nses, name_sort_cmp);
3166
3167   print (vam->ofp, "%-25s%-15s", "Interface", "sw_if_index");
3168   vec_foreach (ns, nses)
3169   {
3170     print (vam->ofp, "%-25s%-15d", ns->name, ns->value);
3171   }
3172   vec_free (nses);
3173   return 0;
3174 }
3175
3176 static int
3177 dump_ip_table (vat_main_t * vam, int is_ipv6)
3178 {
3179   const ip_details_t *det = NULL;
3180   const ip_address_details_t *address = NULL;
3181   u32 i = ~0;
3182
3183   print (vam->ofp, "%-12s", "sw_if_index");
3184
3185   vec_foreach (det, vam->ip_details_by_sw_if_index[is_ipv6])
3186   {
3187     i++;
3188     if (!det->present)
3189       {
3190         continue;
3191       }
3192     print (vam->ofp, "%-12d", i);
3193     print (vam->ofp, "            %-30s%-13s", "Address", "Prefix length");
3194     if (!det->addr)
3195       {
3196         continue;
3197       }
3198     vec_foreach (address, det->addr)
3199     {
3200       print (vam->ofp,
3201              "            %-30U%-13d",
3202              is_ipv6 ? format_ip6_address : format_ip4_address,
3203              address->ip, address->prefix_length);
3204     }
3205   }
3206
3207   return 0;
3208 }
3209
3210 static int
3211 dump_ipv4_table (vat_main_t * vam)
3212 {
3213   if (vam->json_output)
3214     {
3215       clib_warning
3216         ("JSON output supported only for VPE API calls and dump_stats_table");
3217       return -99;
3218     }
3219
3220   return dump_ip_table (vam, 0);
3221 }
3222
3223 static int
3224 dump_ipv6_table (vat_main_t * vam)
3225 {
3226   if (vam->json_output)
3227     {
3228       clib_warning
3229         ("JSON output supported only for VPE API calls and dump_stats_table");
3230       return -99;
3231     }
3232
3233   return dump_ip_table (vam, 1);
3234 }
3235
3236 /*
3237  * Pass CLI buffers directly in the CLI_INBAND API message,
3238  * instead of an additional shared memory area.
3239  */
3240 static int
3241 exec_inband (vat_main_t * vam)
3242 {
3243   vl_api_cli_inband_t *mp;
3244   unformat_input_t *i = vam->input;
3245   int ret;
3246
3247   if (vec_len (i->buffer) == 0)
3248     return -1;
3249
3250   if (vam->exec_mode == 0 && unformat (i, "mode"))
3251     {
3252       vam->exec_mode = 1;
3253       return 0;
3254     }
3255   if (vam->exec_mode == 1 && (unformat (i, "exit") || unformat (i, "quit")))
3256     {
3257       vam->exec_mode = 0;
3258       return 0;
3259     }
3260
3261   /*
3262    * In order for the CLI command to work, it
3263    * must be a vector ending in \n, not a C-string ending
3264    * in \n\0.
3265    */
3266   M2 (CLI_INBAND, mp, vec_len (vam->input->buffer));
3267   vl_api_vec_to_api_string (vam->input->buffer, &mp->cmd);
3268
3269   S (mp);
3270   W (ret);
3271   /* json responses may or may not include a useful reply... */
3272   if (vec_len (vam->cmd_reply))
3273     print (vam->ofp, "%v", (char *) (vam->cmd_reply));
3274   return ret;
3275 }
3276
3277 int
3278 exec (vat_main_t * vam)
3279 {
3280   return exec_inband (vam);
3281 }
3282
3283 static int
3284 api_create_loopback (vat_main_t * vam)
3285 {
3286   unformat_input_t *i = vam->input;
3287   vl_api_create_loopback_t *mp;
3288   vl_api_create_loopback_instance_t *mp_lbi;
3289   u8 mac_address[6];
3290   u8 mac_set = 0;
3291   u8 is_specified = 0;
3292   u32 user_instance = 0;
3293   int ret;
3294
3295   clib_memset (mac_address, 0, sizeof (mac_address));
3296
3297   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3298     {
3299       if (unformat (i, "mac %U", unformat_ethernet_address, mac_address))
3300         mac_set = 1;
3301       if (unformat (i, "instance %d", &user_instance))
3302         is_specified = 1;
3303       else
3304         break;
3305     }
3306
3307   if (is_specified)
3308     {
3309       M (CREATE_LOOPBACK_INSTANCE, mp_lbi);
3310       mp_lbi->is_specified = is_specified;
3311       if (is_specified)
3312         mp_lbi->user_instance = htonl (user_instance);
3313       if (mac_set)
3314         clib_memcpy (mp_lbi->mac_address, mac_address, sizeof (mac_address));
3315       S (mp_lbi);
3316     }
3317   else
3318     {
3319       /* Construct the API message */
3320       M (CREATE_LOOPBACK, mp);
3321       if (mac_set)
3322         clib_memcpy (mp->mac_address, mac_address, sizeof (mac_address));
3323       S (mp);
3324     }
3325
3326   W (ret);
3327   return ret;
3328 }
3329
3330 static int
3331 api_delete_loopback (vat_main_t * vam)
3332 {
3333   unformat_input_t *i = vam->input;
3334   vl_api_delete_loopback_t *mp;
3335   u32 sw_if_index = ~0;
3336   int ret;
3337
3338   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3339     {
3340       if (unformat (i, "sw_if_index %d", &sw_if_index))
3341         ;
3342       else
3343         break;
3344     }
3345
3346   if (sw_if_index == ~0)
3347     {
3348       errmsg ("missing sw_if_index");
3349       return -99;
3350     }
3351
3352   /* Construct the API message */
3353   M (DELETE_LOOPBACK, mp);
3354   mp->sw_if_index = ntohl (sw_if_index);
3355
3356   S (mp);
3357   W (ret);
3358   return ret;
3359 }
3360
3361 static int
3362 api_want_interface_events (vat_main_t * vam)
3363 {
3364   unformat_input_t *i = vam->input;
3365   vl_api_want_interface_events_t *mp;
3366   int enable = -1;
3367   int ret;
3368
3369   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3370     {
3371       if (unformat (i, "enable"))
3372         enable = 1;
3373       else if (unformat (i, "disable"))
3374         enable = 0;
3375       else
3376         break;
3377     }
3378
3379   if (enable == -1)
3380     {
3381       errmsg ("missing enable|disable");
3382       return -99;
3383     }
3384
3385   M (WANT_INTERFACE_EVENTS, mp);
3386   mp->enable_disable = enable;
3387
3388   vam->interface_event_display = enable;
3389
3390   S (mp);
3391   W (ret);
3392   return ret;
3393 }
3394
3395
3396 /* Note: non-static, called once to set up the initial intfc table */
3397 int
3398 api_sw_interface_dump (vat_main_t * vam)
3399 {
3400   vl_api_sw_interface_dump_t *mp;
3401   vl_api_control_ping_t *mp_ping;
3402   hash_pair_t *p;
3403   name_sort_t *nses = 0, *ns;
3404   sw_interface_subif_t *sub = NULL;
3405   int ret;
3406
3407   /* Toss the old name table */
3408   /* *INDENT-OFF* */
3409   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
3410   ({
3411     vec_add2 (nses, ns, 1);
3412     ns->name = (u8 *)(p->key);
3413     ns->value = (u32) p->value[0];
3414   }));
3415   /* *INDENT-ON* */
3416
3417   hash_free (vam->sw_if_index_by_interface_name);
3418
3419   vec_foreach (ns, nses) vec_free (ns->name);
3420
3421   vec_free (nses);
3422
3423   vec_foreach (sub, vam->sw_if_subif_table)
3424   {
3425     vec_free (sub->interface_name);
3426   }
3427   vec_free (vam->sw_if_subif_table);
3428
3429   /* recreate the interface name hash table */
3430   vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
3431
3432   /*
3433    * Ask for all interface names. Otherwise, the epic catalog of
3434    * name filters becomes ridiculously long, and vat ends up needing
3435    * to be taught about new interface types.
3436    */
3437   M (SW_INTERFACE_DUMP, mp);
3438   S (mp);
3439
3440   /* Use a control ping for synchronization */
3441   MPING (CONTROL_PING, mp_ping);
3442   S (mp_ping);
3443
3444   W (ret);
3445   return ret;
3446 }
3447
3448 static int
3449 api_sw_interface_set_flags (vat_main_t * vam)
3450 {
3451   unformat_input_t *i = vam->input;
3452   vl_api_sw_interface_set_flags_t *mp;
3453   u32 sw_if_index;
3454   u8 sw_if_index_set = 0;
3455   u8 admin_up = 0;
3456   int ret;
3457
3458   /* Parse args required to build the message */
3459   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3460     {
3461       if (unformat (i, "admin-up"))
3462         admin_up = 1;
3463       else if (unformat (i, "admin-down"))
3464         admin_up = 0;
3465       else
3466         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3467         sw_if_index_set = 1;
3468       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3469         sw_if_index_set = 1;
3470       else
3471         break;
3472     }
3473
3474   if (sw_if_index_set == 0)
3475     {
3476       errmsg ("missing interface name or sw_if_index");
3477       return -99;
3478     }
3479
3480   /* Construct the API message */
3481   M (SW_INTERFACE_SET_FLAGS, mp);
3482   mp->sw_if_index = ntohl (sw_if_index);
3483   mp->flags = ntohl ((admin_up) ? IF_STATUS_API_FLAG_ADMIN_UP : 0);
3484
3485   /* send it... */
3486   S (mp);
3487
3488   /* Wait for a reply, return the good/bad news... */
3489   W (ret);
3490   return ret;
3491 }
3492
3493 static int
3494 api_sw_interface_set_rx_mode (vat_main_t * vam)
3495 {
3496   unformat_input_t *i = vam->input;
3497   vl_api_sw_interface_set_rx_mode_t *mp;
3498   u32 sw_if_index;
3499   u8 sw_if_index_set = 0;
3500   int ret;
3501   u8 queue_id_valid = 0;
3502   u32 queue_id;
3503   vnet_hw_if_rx_mode mode = VNET_HW_IF_RX_MODE_UNKNOWN;
3504
3505   /* Parse args required to build the message */
3506   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3507     {
3508       if (unformat (i, "queue %d", &queue_id))
3509         queue_id_valid = 1;
3510       else if (unformat (i, "polling"))
3511         mode = VNET_HW_IF_RX_MODE_POLLING;
3512       else if (unformat (i, "interrupt"))
3513         mode = VNET_HW_IF_RX_MODE_INTERRUPT;
3514       else if (unformat (i, "adaptive"))
3515         mode = VNET_HW_IF_RX_MODE_ADAPTIVE;
3516       else
3517         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3518         sw_if_index_set = 1;
3519       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3520         sw_if_index_set = 1;
3521       else
3522         break;
3523     }
3524
3525   if (sw_if_index_set == 0)
3526     {
3527       errmsg ("missing interface name or sw_if_index");
3528       return -99;
3529     }
3530   if (mode == VNET_HW_IF_RX_MODE_UNKNOWN)
3531     {
3532       errmsg ("missing rx-mode");
3533       return -99;
3534     }
3535
3536   /* Construct the API message */
3537   M (SW_INTERFACE_SET_RX_MODE, mp);
3538   mp->sw_if_index = ntohl (sw_if_index);
3539   mp->mode = (vl_api_rx_mode_t) mode;
3540   mp->queue_id_valid = queue_id_valid;
3541   mp->queue_id = queue_id_valid ? ntohl (queue_id) : ~0;
3542
3543   /* send it... */
3544   S (mp);
3545
3546   /* Wait for a reply, return the good/bad news... */
3547   W (ret);
3548   return ret;
3549 }
3550
3551 static int
3552 api_sw_interface_set_rx_placement (vat_main_t * vam)
3553 {
3554   unformat_input_t *i = vam->input;
3555   vl_api_sw_interface_set_rx_placement_t *mp;
3556   u32 sw_if_index;
3557   u8 sw_if_index_set = 0;
3558   int ret;
3559   u8 is_main = 0;
3560   u32 queue_id, thread_index;
3561
3562   /* Parse args required to build the message */
3563   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3564     {
3565       if (unformat (i, "queue %d", &queue_id))
3566         ;
3567       else if (unformat (i, "main"))
3568         is_main = 1;
3569       else if (unformat (i, "worker %d", &thread_index))
3570         ;
3571       else
3572         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3573         sw_if_index_set = 1;
3574       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3575         sw_if_index_set = 1;
3576       else
3577         break;
3578     }
3579
3580   if (sw_if_index_set == 0)
3581     {
3582       errmsg ("missing interface name or sw_if_index");
3583       return -99;
3584     }
3585
3586   if (is_main)
3587     thread_index = 0;
3588   /* Construct the API message */
3589   M (SW_INTERFACE_SET_RX_PLACEMENT, mp);
3590   mp->sw_if_index = ntohl (sw_if_index);
3591   mp->worker_id = ntohl (thread_index);
3592   mp->queue_id = ntohl (queue_id);
3593   mp->is_main = is_main;
3594
3595   /* send it... */
3596   S (mp);
3597   /* Wait for a reply, return the good/bad news... */
3598   W (ret);
3599   return ret;
3600 }
3601
3602 static void vl_api_sw_interface_rx_placement_details_t_handler
3603   (vl_api_sw_interface_rx_placement_details_t * mp)
3604 {
3605   vat_main_t *vam = &vat_main;
3606   u32 worker_id = ntohl (mp->worker_id);
3607
3608   print (vam->ofp,
3609          "\n%-11d %-11s %-6d %-5d %-9s",
3610          ntohl (mp->sw_if_index), (worker_id == 0) ? "main" : "worker",
3611          worker_id, ntohl (mp->queue_id),
3612          (mp->mode ==
3613           1) ? "polling" : ((mp->mode == 2) ? "interrupt" : "adaptive"));
3614 }
3615
3616 static void vl_api_sw_interface_rx_placement_details_t_handler_json
3617   (vl_api_sw_interface_rx_placement_details_t * mp)
3618 {
3619   vat_main_t *vam = &vat_main;
3620   vat_json_node_t *node = NULL;
3621
3622   if (VAT_JSON_ARRAY != vam->json_tree.type)
3623     {
3624       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
3625       vat_json_init_array (&vam->json_tree);
3626     }
3627   node = vat_json_array_add (&vam->json_tree);
3628
3629   vat_json_init_object (node);
3630   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
3631   vat_json_object_add_uint (node, "worker_id", ntohl (mp->worker_id));
3632   vat_json_object_add_uint (node, "queue_id", ntohl (mp->queue_id));
3633   vat_json_object_add_uint (node, "mode", mp->mode);
3634 }
3635
3636 static int
3637 api_sw_interface_rx_placement_dump (vat_main_t * vam)
3638 {
3639   unformat_input_t *i = vam->input;
3640   vl_api_sw_interface_rx_placement_dump_t *mp;
3641   vl_api_control_ping_t *mp_ping;
3642   int ret;
3643   u32 sw_if_index;
3644   u8 sw_if_index_set = 0;
3645
3646   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3647     {
3648       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3649         sw_if_index_set++;
3650       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3651         sw_if_index_set++;
3652       else
3653         break;
3654     }
3655
3656   print (vam->ofp,
3657          "\n%-11s %-11s %-6s %-5s %-4s",
3658          "sw_if_index", "main/worker", "thread", "queue", "mode");
3659
3660   /* Dump Interface rx placement */
3661   M (SW_INTERFACE_RX_PLACEMENT_DUMP, mp);
3662
3663   if (sw_if_index_set)
3664     mp->sw_if_index = htonl (sw_if_index);
3665   else
3666     mp->sw_if_index = ~0;
3667
3668   S (mp);
3669
3670   /* Use a control ping for synchronization */
3671   MPING (CONTROL_PING, mp_ping);
3672   S (mp_ping);
3673
3674   W (ret);
3675   return ret;
3676 }
3677
3678 static int
3679 api_sw_interface_clear_stats (vat_main_t * vam)
3680 {
3681   unformat_input_t *i = vam->input;
3682   vl_api_sw_interface_clear_stats_t *mp;
3683   u32 sw_if_index;
3684   u8 sw_if_index_set = 0;
3685   int ret;
3686
3687   /* Parse args required to build the message */
3688   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3689     {
3690       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3691         sw_if_index_set = 1;
3692       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3693         sw_if_index_set = 1;
3694       else
3695         break;
3696     }
3697
3698   /* Construct the API message */
3699   M (SW_INTERFACE_CLEAR_STATS, mp);
3700
3701   if (sw_if_index_set == 1)
3702     mp->sw_if_index = ntohl (sw_if_index);
3703   else
3704     mp->sw_if_index = ~0;
3705
3706   /* send it... */
3707   S (mp);
3708
3709   /* Wait for a reply, return the good/bad news... */
3710   W (ret);
3711   return ret;
3712 }
3713
3714 static int
3715 api_sw_interface_add_del_address (vat_main_t * vam)
3716 {
3717   unformat_input_t *i = vam->input;
3718   vl_api_sw_interface_add_del_address_t *mp;
3719   u32 sw_if_index;
3720   u8 sw_if_index_set = 0;
3721   u8 is_add = 1, del_all = 0;
3722   u32 address_length = 0;
3723   u8 v4_address_set = 0;
3724   u8 v6_address_set = 0;
3725   ip4_address_t v4address;
3726   ip6_address_t v6address;
3727   int ret;
3728
3729   /* Parse args required to build the message */
3730   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3731     {
3732       if (unformat (i, "del-all"))
3733         del_all = 1;
3734       else if (unformat (i, "del"))
3735         is_add = 0;
3736       else
3737         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3738         sw_if_index_set = 1;
3739       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3740         sw_if_index_set = 1;
3741       else if (unformat (i, "%U/%d",
3742                          unformat_ip4_address, &v4address, &address_length))
3743         v4_address_set = 1;
3744       else if (unformat (i, "%U/%d",
3745                          unformat_ip6_address, &v6address, &address_length))
3746         v6_address_set = 1;
3747       else
3748         break;
3749     }
3750
3751   if (sw_if_index_set == 0)
3752     {
3753       errmsg ("missing interface name or sw_if_index");
3754       return -99;
3755     }
3756   if (v4_address_set && v6_address_set)
3757     {
3758       errmsg ("both v4 and v6 addresses set");
3759       return -99;
3760     }
3761   if (!v4_address_set && !v6_address_set && !del_all)
3762     {
3763       errmsg ("no addresses set");
3764       return -99;
3765     }
3766
3767   /* Construct the API message */
3768   M (SW_INTERFACE_ADD_DEL_ADDRESS, mp);
3769
3770   mp->sw_if_index = ntohl (sw_if_index);
3771   mp->is_add = is_add;
3772   mp->del_all = del_all;
3773   if (v6_address_set)
3774     {
3775       mp->prefix.address.af = ADDRESS_IP6;
3776       clib_memcpy (mp->prefix.address.un.ip6, &v6address, sizeof (v6address));
3777     }
3778   else
3779     {
3780       mp->prefix.address.af = ADDRESS_IP4;
3781       clib_memcpy (mp->prefix.address.un.ip4, &v4address, sizeof (v4address));
3782     }
3783   mp->prefix.len = address_length;
3784
3785   /* send it... */
3786   S (mp);
3787
3788   /* Wait for a reply, return good/bad news  */
3789   W (ret);
3790   return ret;
3791 }
3792
3793 static int
3794 api_sw_interface_set_mpls_enable (vat_main_t * vam)
3795 {
3796   unformat_input_t *i = vam->input;
3797   vl_api_sw_interface_set_mpls_enable_t *mp;
3798   u32 sw_if_index;
3799   u8 sw_if_index_set = 0;
3800   u8 enable = 1;
3801   int ret;
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", api_unformat_sw_if_index, vam, &sw_if_index))
3807         sw_if_index_set = 1;
3808       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3809         sw_if_index_set = 1;
3810       else if (unformat (i, "disable"))
3811         enable = 0;
3812       else if (unformat (i, "dis"))
3813         enable = 0;
3814       else
3815         break;
3816     }
3817
3818   if (sw_if_index_set == 0)
3819     {
3820       errmsg ("missing interface name or sw_if_index");
3821       return -99;
3822     }
3823
3824   /* Construct the API message */
3825   M (SW_INTERFACE_SET_MPLS_ENABLE, mp);
3826
3827   mp->sw_if_index = ntohl (sw_if_index);
3828   mp->enable = enable;
3829
3830   /* send it... */
3831   S (mp);
3832
3833   /* Wait for a reply... */
3834   W (ret);
3835   return ret;
3836 }
3837
3838 static int
3839 api_sw_interface_set_table (vat_main_t * vam)
3840 {
3841   unformat_input_t *i = vam->input;
3842   vl_api_sw_interface_set_table_t *mp;
3843   u32 sw_if_index, vrf_id = 0;
3844   u8 sw_if_index_set = 0;
3845   u8 is_ipv6 = 0;
3846   int ret;
3847
3848   /* Parse args required to build the message */
3849   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3850     {
3851       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3852         sw_if_index_set = 1;
3853       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3854         sw_if_index_set = 1;
3855       else if (unformat (i, "vrf %d", &vrf_id))
3856         ;
3857       else if (unformat (i, "ipv6"))
3858         is_ipv6 = 1;
3859       else
3860         break;
3861     }
3862
3863   if (sw_if_index_set == 0)
3864     {
3865       errmsg ("missing interface name or sw_if_index");
3866       return -99;
3867     }
3868
3869   /* Construct the API message */
3870   M (SW_INTERFACE_SET_TABLE, mp);
3871
3872   mp->sw_if_index = ntohl (sw_if_index);
3873   mp->is_ipv6 = is_ipv6;
3874   mp->vrf_id = ntohl (vrf_id);
3875
3876   /* send it... */
3877   S (mp);
3878
3879   /* Wait for a reply... */
3880   W (ret);
3881   return ret;
3882 }
3883
3884 static void vl_api_sw_interface_get_table_reply_t_handler
3885   (vl_api_sw_interface_get_table_reply_t * mp)
3886 {
3887   vat_main_t *vam = &vat_main;
3888
3889   print (vam->ofp, "%d", ntohl (mp->vrf_id));
3890
3891   vam->retval = ntohl (mp->retval);
3892   vam->result_ready = 1;
3893
3894 }
3895
3896 static void vl_api_sw_interface_get_table_reply_t_handler_json
3897   (vl_api_sw_interface_get_table_reply_t * mp)
3898 {
3899   vat_main_t *vam = &vat_main;
3900   vat_json_node_t node;
3901
3902   vat_json_init_object (&node);
3903   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
3904   vat_json_object_add_int (&node, "vrf_id", ntohl (mp->vrf_id));
3905
3906   vat_json_print (vam->ofp, &node);
3907   vat_json_free (&node);
3908
3909   vam->retval = ntohl (mp->retval);
3910   vam->result_ready = 1;
3911 }
3912
3913 static int
3914 api_sw_interface_get_table (vat_main_t * vam)
3915 {
3916   unformat_input_t *i = vam->input;
3917   vl_api_sw_interface_get_table_t *mp;
3918   u32 sw_if_index;
3919   u8 sw_if_index_set = 0;
3920   u8 is_ipv6 = 0;
3921   int ret;
3922
3923   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3924     {
3925       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3926         sw_if_index_set = 1;
3927       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3928         sw_if_index_set = 1;
3929       else if (unformat (i, "ipv6"))
3930         is_ipv6 = 1;
3931       else
3932         break;
3933     }
3934
3935   if (sw_if_index_set == 0)
3936     {
3937       errmsg ("missing interface name or sw_if_index");
3938       return -99;
3939     }
3940
3941   M (SW_INTERFACE_GET_TABLE, mp);
3942   mp->sw_if_index = htonl (sw_if_index);
3943   mp->is_ipv6 = is_ipv6;
3944
3945   S (mp);
3946   W (ret);
3947   return ret;
3948 }
3949
3950 static int
3951 api_sw_interface_set_vpath (vat_main_t * vam)
3952 {
3953   unformat_input_t *i = vam->input;
3954   vl_api_sw_interface_set_vpath_t *mp;
3955   u32 sw_if_index = 0;
3956   u8 sw_if_index_set = 0;
3957   u8 is_enable = 0;
3958   int ret;
3959
3960   /* Parse args required to build the message */
3961   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3962     {
3963       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3964         sw_if_index_set = 1;
3965       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3966         sw_if_index_set = 1;
3967       else if (unformat (i, "enable"))
3968         is_enable = 1;
3969       else if (unformat (i, "disable"))
3970         is_enable = 0;
3971       else
3972         break;
3973     }
3974
3975   if (sw_if_index_set == 0)
3976     {
3977       errmsg ("missing interface name or sw_if_index");
3978       return -99;
3979     }
3980
3981   /* Construct the API message */
3982   M (SW_INTERFACE_SET_VPATH, mp);
3983
3984   mp->sw_if_index = ntohl (sw_if_index);
3985   mp->enable = is_enable;
3986
3987   /* send it... */
3988   S (mp);
3989
3990   /* Wait for a reply... */
3991   W (ret);
3992   return ret;
3993 }
3994
3995 static int
3996 api_sw_interface_set_l2_xconnect (vat_main_t * vam)
3997 {
3998   unformat_input_t *i = vam->input;
3999   vl_api_sw_interface_set_l2_xconnect_t *mp;
4000   u32 rx_sw_if_index;
4001   u8 rx_sw_if_index_set = 0;
4002   u32 tx_sw_if_index;
4003   u8 tx_sw_if_index_set = 0;
4004   u8 enable = 1;
4005   int ret;
4006
4007   /* Parse args required to build the message */
4008   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4009     {
4010       if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index))
4011         rx_sw_if_index_set = 1;
4012       else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
4013         tx_sw_if_index_set = 1;
4014       else if (unformat (i, "rx"))
4015         {
4016           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4017             {
4018               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
4019                             &rx_sw_if_index))
4020                 rx_sw_if_index_set = 1;
4021             }
4022           else
4023             break;
4024         }
4025       else if (unformat (i, "tx"))
4026         {
4027           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4028             {
4029               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
4030                             &tx_sw_if_index))
4031                 tx_sw_if_index_set = 1;
4032             }
4033           else
4034             break;
4035         }
4036       else if (unformat (i, "enable"))
4037         enable = 1;
4038       else if (unformat (i, "disable"))
4039         enable = 0;
4040       else
4041         break;
4042     }
4043
4044   if (rx_sw_if_index_set == 0)
4045     {
4046       errmsg ("missing rx interface name or rx_sw_if_index");
4047       return -99;
4048     }
4049
4050   if (enable && (tx_sw_if_index_set == 0))
4051     {
4052       errmsg ("missing tx interface name or tx_sw_if_index");
4053       return -99;
4054     }
4055
4056   M (SW_INTERFACE_SET_L2_XCONNECT, mp);
4057
4058   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
4059   mp->tx_sw_if_index = ntohl (tx_sw_if_index);
4060   mp->enable = enable;
4061
4062   S (mp);
4063   W (ret);
4064   return ret;
4065 }
4066
4067 static int
4068 api_sw_interface_set_l2_bridge (vat_main_t * vam)
4069 {
4070   unformat_input_t *i = vam->input;
4071   vl_api_sw_interface_set_l2_bridge_t *mp;
4072   vl_api_l2_port_type_t port_type;
4073   u32 rx_sw_if_index;
4074   u8 rx_sw_if_index_set = 0;
4075   u32 bd_id;
4076   u8 bd_id_set = 0;
4077   u32 shg = 0;
4078   u8 enable = 1;
4079   int ret;
4080
4081   port_type = L2_API_PORT_TYPE_NORMAL;
4082
4083   /* Parse args required to build the message */
4084   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4085     {
4086       if (unformat (i, "sw_if_index %d", &rx_sw_if_index))
4087         rx_sw_if_index_set = 1;
4088       else if (unformat (i, "bd_id %d", &bd_id))
4089         bd_id_set = 1;
4090       else
4091         if (unformat
4092             (i, "%U", api_unformat_sw_if_index, vam, &rx_sw_if_index))
4093         rx_sw_if_index_set = 1;
4094       else if (unformat (i, "shg %d", &shg))
4095         ;
4096       else if (unformat (i, "bvi"))
4097         port_type = L2_API_PORT_TYPE_BVI;
4098       else if (unformat (i, "uu-fwd"))
4099         port_type = L2_API_PORT_TYPE_UU_FWD;
4100       else if (unformat (i, "enable"))
4101         enable = 1;
4102       else if (unformat (i, "disable"))
4103         enable = 0;
4104       else
4105         break;
4106     }
4107
4108   if (rx_sw_if_index_set == 0)
4109     {
4110       errmsg ("missing rx interface name or sw_if_index");
4111       return -99;
4112     }
4113
4114   if (enable && (bd_id_set == 0))
4115     {
4116       errmsg ("missing bridge domain");
4117       return -99;
4118     }
4119
4120   M (SW_INTERFACE_SET_L2_BRIDGE, mp);
4121
4122   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
4123   mp->bd_id = ntohl (bd_id);
4124   mp->shg = (u8) shg;
4125   mp->port_type = ntohl (port_type);
4126   mp->enable = enable;
4127
4128   S (mp);
4129   W (ret);
4130   return ret;
4131 }
4132
4133 static int
4134 api_bridge_domain_dump (vat_main_t * vam)
4135 {
4136   unformat_input_t *i = vam->input;
4137   vl_api_bridge_domain_dump_t *mp;
4138   vl_api_control_ping_t *mp_ping;
4139   u32 bd_id = ~0;
4140   int ret;
4141
4142   /* Parse args required to build the message */
4143   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4144     {
4145       if (unformat (i, "bd_id %d", &bd_id))
4146         ;
4147       else
4148         break;
4149     }
4150
4151   M (BRIDGE_DOMAIN_DUMP, mp);
4152   mp->bd_id = ntohl (bd_id);
4153   S (mp);
4154
4155   /* Use a control ping for synchronization */
4156   MPING (CONTROL_PING, mp_ping);
4157   S (mp_ping);
4158
4159   W (ret);
4160   return ret;
4161 }
4162
4163 static int
4164 api_bridge_domain_add_del (vat_main_t * vam)
4165 {
4166   unformat_input_t *i = vam->input;
4167   vl_api_bridge_domain_add_del_t *mp;
4168   u32 bd_id = ~0;
4169   u8 is_add = 1;
4170   u32 flood = 1, forward = 1, learn = 1, uu_flood = 1, arp_term = 0;
4171   u8 *bd_tag = NULL;
4172   u32 mac_age = 0;
4173   int ret;
4174
4175   /* Parse args required to build the message */
4176   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4177     {
4178       if (unformat (i, "bd_id %d", &bd_id))
4179         ;
4180       else if (unformat (i, "flood %d", &flood))
4181         ;
4182       else if (unformat (i, "uu-flood %d", &uu_flood))
4183         ;
4184       else if (unformat (i, "forward %d", &forward))
4185         ;
4186       else if (unformat (i, "learn %d", &learn))
4187         ;
4188       else if (unformat (i, "arp-term %d", &arp_term))
4189         ;
4190       else if (unformat (i, "mac-age %d", &mac_age))
4191         ;
4192       else if (unformat (i, "bd-tag %s", &bd_tag))
4193         ;
4194       else if (unformat (i, "del"))
4195         {
4196           is_add = 0;
4197           flood = uu_flood = forward = learn = 0;
4198         }
4199       else
4200         break;
4201     }
4202
4203   if (bd_id == ~0)
4204     {
4205       errmsg ("missing bridge domain");
4206       ret = -99;
4207       goto done;
4208     }
4209
4210   if (mac_age > 255)
4211     {
4212       errmsg ("mac age must be less than 256 ");
4213       ret = -99;
4214       goto done;
4215     }
4216
4217   if ((bd_tag) && (vec_len (bd_tag) > 63))
4218     {
4219       errmsg ("bd-tag cannot be longer than 63");
4220       ret = -99;
4221       goto done;
4222     }
4223
4224   M (BRIDGE_DOMAIN_ADD_DEL, mp);
4225
4226   mp->bd_id = ntohl (bd_id);
4227   mp->flood = flood;
4228   mp->uu_flood = uu_flood;
4229   mp->forward = forward;
4230   mp->learn = learn;
4231   mp->arp_term = arp_term;
4232   mp->is_add = is_add;
4233   mp->mac_age = (u8) mac_age;
4234   if (bd_tag)
4235     {
4236       clib_memcpy (mp->bd_tag, bd_tag, vec_len (bd_tag));
4237       mp->bd_tag[vec_len (bd_tag)] = 0;
4238     }
4239   S (mp);
4240   W (ret);
4241
4242 done:
4243   vec_free (bd_tag);
4244   return ret;
4245 }
4246
4247 static int
4248 api_l2fib_flush_bd (vat_main_t * vam)
4249 {
4250   unformat_input_t *i = vam->input;
4251   vl_api_l2fib_flush_bd_t *mp;
4252   u32 bd_id = ~0;
4253   int ret;
4254
4255   /* Parse args required to build the message */
4256   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4257     {
4258       if (unformat (i, "bd_id %d", &bd_id));
4259       else
4260         break;
4261     }
4262
4263   if (bd_id == ~0)
4264     {
4265       errmsg ("missing bridge domain");
4266       return -99;
4267     }
4268
4269   M (L2FIB_FLUSH_BD, mp);
4270
4271   mp->bd_id = htonl (bd_id);
4272
4273   S (mp);
4274   W (ret);
4275   return ret;
4276 }
4277
4278 static int
4279 api_l2fib_flush_int (vat_main_t * vam)
4280 {
4281   unformat_input_t *i = vam->input;
4282   vl_api_l2fib_flush_int_t *mp;
4283   u32 sw_if_index = ~0;
4284   int ret;
4285
4286   /* Parse args required to build the message */
4287   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4288     {
4289       if (unformat (i, "sw_if_index %d", &sw_if_index));
4290       else
4291         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index));
4292       else
4293         break;
4294     }
4295
4296   if (sw_if_index == ~0)
4297     {
4298       errmsg ("missing interface name or sw_if_index");
4299       return -99;
4300     }
4301
4302   M (L2FIB_FLUSH_INT, mp);
4303
4304   mp->sw_if_index = ntohl (sw_if_index);
4305
4306   S (mp);
4307   W (ret);
4308   return ret;
4309 }
4310
4311 static int
4312 api_l2fib_add_del (vat_main_t * vam)
4313 {
4314   unformat_input_t *i = vam->input;
4315   vl_api_l2fib_add_del_t *mp;
4316   f64 timeout;
4317   u8 mac[6] = { 0 };
4318   u8 mac_set = 0;
4319   u32 bd_id;
4320   u8 bd_id_set = 0;
4321   u32 sw_if_index = 0;
4322   u8 sw_if_index_set = 0;
4323   u8 is_add = 1;
4324   u8 static_mac = 0;
4325   u8 filter_mac = 0;
4326   u8 bvi_mac = 0;
4327   int count = 1;
4328   f64 before = 0;
4329   int j;
4330
4331   /* Parse args required to build the message */
4332   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4333     {
4334       if (unformat (i, "mac %U", unformat_ethernet_address, mac))
4335         mac_set = 1;
4336       else if (unformat (i, "bd_id %d", &bd_id))
4337         bd_id_set = 1;
4338       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4339         sw_if_index_set = 1;
4340       else if (unformat (i, "sw_if"))
4341         {
4342           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4343             {
4344               if (unformat
4345                   (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4346                 sw_if_index_set = 1;
4347             }
4348           else
4349             break;
4350         }
4351       else if (unformat (i, "static"))
4352         static_mac = 1;
4353       else if (unformat (i, "filter"))
4354         {
4355           filter_mac = 1;
4356           static_mac = 1;
4357         }
4358       else if (unformat (i, "bvi"))
4359         {
4360           bvi_mac = 1;
4361           static_mac = 1;
4362         }
4363       else if (unformat (i, "del"))
4364         is_add = 0;
4365       else if (unformat (i, "count %d", &count))
4366         ;
4367       else
4368         break;
4369     }
4370
4371   if (mac_set == 0)
4372     {
4373       errmsg ("missing mac address");
4374       return -99;
4375     }
4376
4377   if (bd_id_set == 0)
4378     {
4379       errmsg ("missing bridge domain");
4380       return -99;
4381     }
4382
4383   if (is_add && sw_if_index_set == 0 && filter_mac == 0)
4384     {
4385       errmsg ("missing interface name or sw_if_index");
4386       return -99;
4387     }
4388
4389   if (count > 1)
4390     {
4391       /* Turn on async mode */
4392       vam->async_mode = 1;
4393       vam->async_errors = 0;
4394       before = vat_time_now (vam);
4395     }
4396
4397   for (j = 0; j < count; j++)
4398     {
4399       M (L2FIB_ADD_DEL, mp);
4400
4401       clib_memcpy (mp->mac, mac, 6);
4402       mp->bd_id = ntohl (bd_id);
4403       mp->is_add = is_add;
4404       mp->sw_if_index = ntohl (sw_if_index);
4405
4406       if (is_add)
4407         {
4408           mp->static_mac = static_mac;
4409           mp->filter_mac = filter_mac;
4410           mp->bvi_mac = bvi_mac;
4411         }
4412       increment_mac_address (mac);
4413       /* send it... */
4414       S (mp);
4415     }
4416
4417   if (count > 1)
4418     {
4419       vl_api_control_ping_t *mp_ping;
4420       f64 after;
4421
4422       /* Shut off async mode */
4423       vam->async_mode = 0;
4424
4425       MPING (CONTROL_PING, mp_ping);
4426       S (mp_ping);
4427
4428       timeout = vat_time_now (vam) + 1.0;
4429       while (vat_time_now (vam) < timeout)
4430         if (vam->result_ready == 1)
4431           goto out;
4432       vam->retval = -99;
4433
4434     out:
4435       if (vam->retval == -99)
4436         errmsg ("timeout");
4437
4438       if (vam->async_errors > 0)
4439         {
4440           errmsg ("%d asynchronous errors", vam->async_errors);
4441           vam->retval = -98;
4442         }
4443       vam->async_errors = 0;
4444       after = vat_time_now (vam);
4445
4446       print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec",
4447              count, after - before, count / (after - before));
4448     }
4449   else
4450     {
4451       int ret;
4452
4453       /* Wait for a reply... */
4454       W (ret);
4455       return ret;
4456     }
4457   /* Return the good/bad news */
4458   return (vam->retval);
4459 }
4460
4461 static int
4462 api_bridge_domain_set_mac_age (vat_main_t * vam)
4463 {
4464   unformat_input_t *i = vam->input;
4465   vl_api_bridge_domain_set_mac_age_t *mp;
4466   u32 bd_id = ~0;
4467   u32 mac_age = 0;
4468   int ret;
4469
4470   /* Parse args required to build the message */
4471   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4472     {
4473       if (unformat (i, "bd_id %d", &bd_id));
4474       else if (unformat (i, "mac-age %d", &mac_age));
4475       else
4476         break;
4477     }
4478
4479   if (bd_id == ~0)
4480     {
4481       errmsg ("missing bridge domain");
4482       return -99;
4483     }
4484
4485   if (mac_age > 255)
4486     {
4487       errmsg ("mac age must be less than 256 ");
4488       return -99;
4489     }
4490
4491   M (BRIDGE_DOMAIN_SET_MAC_AGE, mp);
4492
4493   mp->bd_id = htonl (bd_id);
4494   mp->mac_age = (u8) mac_age;
4495
4496   S (mp);
4497   W (ret);
4498   return ret;
4499 }
4500
4501 static int
4502 api_l2_flags (vat_main_t * vam)
4503 {
4504   unformat_input_t *i = vam->input;
4505   vl_api_l2_flags_t *mp;
4506   u32 sw_if_index;
4507   u32 flags = 0;
4508   u8 sw_if_index_set = 0;
4509   u8 is_set = 0;
4510   int ret;
4511
4512   /* Parse args required to build the message */
4513   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4514     {
4515       if (unformat (i, "sw_if_index %d", &sw_if_index))
4516         sw_if_index_set = 1;
4517       else if (unformat (i, "sw_if"))
4518         {
4519           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4520             {
4521               if (unformat
4522                   (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4523                 sw_if_index_set = 1;
4524             }
4525           else
4526             break;
4527         }
4528       else if (unformat (i, "learn"))
4529         flags |= L2_LEARN;
4530       else if (unformat (i, "forward"))
4531         flags |= L2_FWD;
4532       else if (unformat (i, "flood"))
4533         flags |= L2_FLOOD;
4534       else if (unformat (i, "uu-flood"))
4535         flags |= L2_UU_FLOOD;
4536       else if (unformat (i, "arp-term"))
4537         flags |= L2_ARP_TERM;
4538       else if (unformat (i, "off"))
4539         is_set = 0;
4540       else if (unformat (i, "disable"))
4541         is_set = 0;
4542       else
4543         break;
4544     }
4545
4546   if (sw_if_index_set == 0)
4547     {
4548       errmsg ("missing interface name or sw_if_index");
4549       return -99;
4550     }
4551
4552   M (L2_FLAGS, mp);
4553
4554   mp->sw_if_index = ntohl (sw_if_index);
4555   mp->feature_bitmap = ntohl (flags);
4556   mp->is_set = is_set;
4557
4558   S (mp);
4559   W (ret);
4560   return ret;
4561 }
4562
4563 static int
4564 api_bridge_flags (vat_main_t * vam)
4565 {
4566   unformat_input_t *i = vam->input;
4567   vl_api_bridge_flags_t *mp;
4568   u32 bd_id;
4569   u8 bd_id_set = 0;
4570   u8 is_set = 1;
4571   bd_flags_t flags = 0;
4572   int ret;
4573
4574   /* Parse args required to build the message */
4575   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4576     {
4577       if (unformat (i, "bd_id %d", &bd_id))
4578         bd_id_set = 1;
4579       else if (unformat (i, "learn"))
4580         flags |= BRIDGE_API_FLAG_LEARN;
4581       else if (unformat (i, "forward"))
4582         flags |= BRIDGE_API_FLAG_FWD;
4583       else if (unformat (i, "flood"))
4584         flags |= BRIDGE_API_FLAG_FLOOD;
4585       else if (unformat (i, "uu-flood"))
4586         flags |= BRIDGE_API_FLAG_UU_FLOOD;
4587       else if (unformat (i, "arp-term"))
4588         flags |= BRIDGE_API_FLAG_ARP_TERM;
4589       else if (unformat (i, "off"))
4590         is_set = 0;
4591       else if (unformat (i, "disable"))
4592         is_set = 0;
4593       else
4594         break;
4595     }
4596
4597   if (bd_id_set == 0)
4598     {
4599       errmsg ("missing bridge domain");
4600       return -99;
4601     }
4602
4603   M (BRIDGE_FLAGS, mp);
4604
4605   mp->bd_id = ntohl (bd_id);
4606   mp->flags = ntohl (flags);
4607   mp->is_set = is_set;
4608
4609   S (mp);
4610   W (ret);
4611   return ret;
4612 }
4613
4614 static int
4615 api_bd_ip_mac_add_del (vat_main_t * vam)
4616 {
4617   vl_api_address_t ip = VL_API_ZERO_ADDRESS;
4618   vl_api_mac_address_t mac = { 0 };
4619   unformat_input_t *i = vam->input;
4620   vl_api_bd_ip_mac_add_del_t *mp;
4621   u32 bd_id;
4622   u8 is_add = 1;
4623   u8 bd_id_set = 0;
4624   u8 ip_set = 0;
4625   u8 mac_set = 0;
4626   int ret;
4627
4628
4629   /* Parse args required to build the message */
4630   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4631     {
4632       if (unformat (i, "bd_id %d", &bd_id))
4633         {
4634           bd_id_set++;
4635         }
4636       else if (unformat (i, "%U", unformat_vl_api_address, &ip))
4637         {
4638           ip_set++;
4639         }
4640       else if (unformat (i, "%U", unformat_vl_api_mac_address, &mac))
4641         {
4642           mac_set++;
4643         }
4644       else if (unformat (i, "del"))
4645         is_add = 0;
4646       else
4647         break;
4648     }
4649
4650   if (bd_id_set == 0)
4651     {
4652       errmsg ("missing bridge domain");
4653       return -99;
4654     }
4655   else if (ip_set == 0)
4656     {
4657       errmsg ("missing IP address");
4658       return -99;
4659     }
4660   else if (mac_set == 0)
4661     {
4662       errmsg ("missing MAC address");
4663       return -99;
4664     }
4665
4666   M (BD_IP_MAC_ADD_DEL, mp);
4667
4668   mp->entry.bd_id = ntohl (bd_id);
4669   mp->is_add = is_add;
4670
4671   clib_memcpy (&mp->entry.ip, &ip, sizeof (ip));
4672   clib_memcpy (&mp->entry.mac, &mac, sizeof (mac));
4673
4674   S (mp);
4675   W (ret);
4676   return ret;
4677 }
4678
4679 static int
4680 api_bd_ip_mac_flush (vat_main_t * vam)
4681 {
4682   unformat_input_t *i = vam->input;
4683   vl_api_bd_ip_mac_flush_t *mp;
4684   u32 bd_id;
4685   u8 bd_id_set = 0;
4686   int ret;
4687
4688   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4689     {
4690       if (unformat (i, "bd_id %d", &bd_id))
4691         {
4692           bd_id_set++;
4693         }
4694       else
4695         break;
4696     }
4697
4698   if (bd_id_set == 0)
4699     {
4700       errmsg ("missing bridge domain");
4701       return -99;
4702     }
4703
4704   M (BD_IP_MAC_FLUSH, mp);
4705
4706   mp->bd_id = ntohl (bd_id);
4707
4708   S (mp);
4709   W (ret);
4710   return ret;
4711 }
4712
4713 static void vl_api_bd_ip_mac_details_t_handler
4714   (vl_api_bd_ip_mac_details_t * mp)
4715 {
4716   vat_main_t *vam = &vat_main;
4717
4718   print (vam->ofp,
4719          "\n%-5d %U %U",
4720          ntohl (mp->entry.bd_id),
4721          format_vl_api_mac_address, mp->entry.mac,
4722          format_vl_api_address, &mp->entry.ip);
4723 }
4724
4725 static void vl_api_bd_ip_mac_details_t_handler_json
4726   (vl_api_bd_ip_mac_details_t * mp)
4727 {
4728   vat_main_t *vam = &vat_main;
4729   vat_json_node_t *node = NULL;
4730
4731   if (VAT_JSON_ARRAY != vam->json_tree.type)
4732     {
4733       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
4734       vat_json_init_array (&vam->json_tree);
4735     }
4736   node = vat_json_array_add (&vam->json_tree);
4737
4738   vat_json_init_object (node);
4739   vat_json_object_add_uint (node, "bd_id", ntohl (mp->entry.bd_id));
4740   vat_json_object_add_string_copy (node, "mac_address",
4741                                    format (0, "%U", format_vl_api_mac_address,
4742                                            &mp->entry.mac));
4743   u8 *ip = 0;
4744
4745   ip = format (0, "%U", format_vl_api_address, &mp->entry.ip);
4746   vat_json_object_add_string_copy (node, "ip_address", ip);
4747   vec_free (ip);
4748 }
4749
4750 static int
4751 api_bd_ip_mac_dump (vat_main_t * vam)
4752 {
4753   unformat_input_t *i = vam->input;
4754   vl_api_bd_ip_mac_dump_t *mp;
4755   vl_api_control_ping_t *mp_ping;
4756   int ret;
4757   u32 bd_id;
4758   u8 bd_id_set = 0;
4759
4760   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4761     {
4762       if (unformat (i, "bd_id %d", &bd_id))
4763         {
4764           bd_id_set++;
4765         }
4766       else
4767         break;
4768     }
4769
4770   print (vam->ofp,
4771          "\n%-5s %-7s %-20s %-30s",
4772          "bd_id", "is_ipv6", "mac_address", "ip_address");
4773
4774   /* Dump Bridge Domain Ip to Mac entries */
4775   M (BD_IP_MAC_DUMP, mp);
4776
4777   if (bd_id_set)
4778     mp->bd_id = htonl (bd_id);
4779   else
4780     mp->bd_id = ~0;
4781
4782   S (mp);
4783
4784   /* Use a control ping for synchronization */
4785   MPING (CONTROL_PING, mp_ping);
4786   S (mp_ping);
4787
4788   W (ret);
4789   return ret;
4790 }
4791
4792 static int
4793 api_tap_create_v2 (vat_main_t * vam)
4794 {
4795   unformat_input_t *i = vam->input;
4796   vl_api_tap_create_v2_t *mp;
4797   u8 mac_address[6];
4798   u8 random_mac = 1;
4799   u32 id = ~0;
4800   u32 num_rx_queues = 0;
4801   u8 *host_if_name = 0;
4802   u8 host_if_name_set = 0;
4803   u8 *host_ns = 0;
4804   u8 host_ns_set = 0;
4805   u8 host_mac_addr[6];
4806   u8 host_mac_addr_set = 0;
4807   u8 *host_bridge = 0;
4808   u8 host_bridge_set = 0;
4809   u8 host_ip4_prefix_set = 0;
4810   u8 host_ip6_prefix_set = 0;
4811   ip4_address_t host_ip4_addr;
4812   ip4_address_t host_ip4_gw;
4813   u8 host_ip4_gw_set = 0;
4814   u32 host_ip4_prefix_len = 0;
4815   ip6_address_t host_ip6_addr;
4816   ip6_address_t host_ip6_gw;
4817   u8 host_ip6_gw_set = 0;
4818   u32 host_ip6_prefix_len = 0;
4819   u32 host_mtu_size = 0;
4820   u8 host_mtu_set = 0;
4821   u32 tap_flags = 0;
4822   int ret;
4823   u32 rx_ring_sz = 0, tx_ring_sz = 0;
4824
4825   clib_memset (mac_address, 0, sizeof (mac_address));
4826
4827   /* Parse args required to build the message */
4828   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4829     {
4830       if (unformat (i, "id %u", &id))
4831         ;
4832       else
4833         if (unformat
4834             (i, "hw-addr %U", unformat_ethernet_address, mac_address))
4835         random_mac = 0;
4836       else if (unformat (i, "host-if-name %s", &host_if_name))
4837         host_if_name_set = 1;
4838       else if (unformat (i, "num-rx-queues %u", &num_rx_queues))
4839         ;
4840       else if (unformat (i, "host-ns %s", &host_ns))
4841         host_ns_set = 1;
4842       else if (unformat (i, "host-mac-addr %U", unformat_ethernet_address,
4843                          host_mac_addr))
4844         host_mac_addr_set = 1;
4845       else if (unformat (i, "host-bridge %s", &host_bridge))
4846         host_bridge_set = 1;
4847       else if (unformat (i, "host-ip4-addr %U/%u", unformat_ip4_address,
4848                          &host_ip4_addr, &host_ip4_prefix_len))
4849         host_ip4_prefix_set = 1;
4850       else if (unformat (i, "host-ip6-addr %U/%u", unformat_ip6_address,
4851                          &host_ip6_addr, &host_ip6_prefix_len))
4852         host_ip6_prefix_set = 1;
4853       else if (unformat (i, "host-ip4-gw %U", unformat_ip4_address,
4854                          &host_ip4_gw))
4855         host_ip4_gw_set = 1;
4856       else if (unformat (i, "host-ip6-gw %U", unformat_ip6_address,
4857                          &host_ip6_gw))
4858         host_ip6_gw_set = 1;
4859       else if (unformat (i, "rx-ring-size %u", &rx_ring_sz))
4860         ;
4861       else if (unformat (i, "tx-ring-size %u", &tx_ring_sz))
4862         ;
4863       else if (unformat (i, "host-mtu-size %u", &host_mtu_size))
4864         host_mtu_set = 1;
4865       else if (unformat (i, "no-gso"))
4866         tap_flags &= ~TAP_API_FLAG_GSO;
4867       else if (unformat (i, "gso"))
4868         tap_flags |= TAP_API_FLAG_GSO;
4869       else if (unformat (i, "csum-offload"))
4870         tap_flags |= TAP_API_FLAG_CSUM_OFFLOAD;
4871       else if (unformat (i, "persist"))
4872         tap_flags |= TAP_API_FLAG_PERSIST;
4873       else if (unformat (i, "attach"))
4874         tap_flags |= TAP_API_FLAG_ATTACH;
4875       else if (unformat (i, "tun"))
4876         tap_flags |= TAP_API_FLAG_TUN;
4877       else if (unformat (i, "gro-coalesce"))
4878         tap_flags |= TAP_API_FLAG_GRO_COALESCE;
4879       else if (unformat (i, "packed"))
4880         tap_flags |= TAP_API_FLAG_PACKED;
4881       else if (unformat (i, "in-order"))
4882         tap_flags |= TAP_API_FLAG_IN_ORDER;
4883       else
4884         break;
4885     }
4886
4887   if (vec_len (host_if_name) > 63)
4888     {
4889       errmsg ("tap name too long. ");
4890       return -99;
4891     }
4892   if (vec_len (host_ns) > 63)
4893     {
4894       errmsg ("host name space too long. ");
4895       return -99;
4896     }
4897   if (vec_len (host_bridge) > 63)
4898     {
4899       errmsg ("host bridge name too long. ");
4900       return -99;
4901     }
4902   if (host_ip4_prefix_len > 32)
4903     {
4904       errmsg ("host ip4 prefix length not valid. ");
4905       return -99;
4906     }
4907   if (host_ip6_prefix_len > 128)
4908     {
4909       errmsg ("host ip6 prefix length not valid. ");
4910       return -99;
4911     }
4912   if (!is_pow2 (rx_ring_sz))
4913     {
4914       errmsg ("rx ring size must be power of 2. ");
4915       return -99;
4916     }
4917   if (rx_ring_sz > 32768)
4918     {
4919       errmsg ("rx ring size must be 32768 or lower. ");
4920       return -99;
4921     }
4922   if (!is_pow2 (tx_ring_sz))
4923     {
4924       errmsg ("tx ring size must be power of 2. ");
4925       return -99;
4926     }
4927   if (tx_ring_sz > 32768)
4928     {
4929       errmsg ("tx ring size must be 32768 or lower. ");
4930       return -99;
4931     }
4932   if (host_mtu_set && (host_mtu_size < 64 || host_mtu_size > 65355))
4933     {
4934       errmsg ("host MTU size must be in between 64 and 65355. ");
4935       return -99;
4936     }
4937
4938   /* Construct the API message */
4939   M (TAP_CREATE_V2, mp);
4940
4941   mp->id = ntohl (id);
4942   mp->use_random_mac = random_mac;
4943   mp->num_rx_queues = (u8) num_rx_queues;
4944   mp->tx_ring_sz = ntohs (tx_ring_sz);
4945   mp->rx_ring_sz = ntohs (rx_ring_sz);
4946   mp->host_mtu_set = host_mtu_set;
4947   mp->host_mtu_size = ntohl (host_mtu_size);
4948   mp->host_mac_addr_set = host_mac_addr_set;
4949   mp->host_ip4_prefix_set = host_ip4_prefix_set;
4950   mp->host_ip6_prefix_set = host_ip6_prefix_set;
4951   mp->host_ip4_gw_set = host_ip4_gw_set;
4952   mp->host_ip6_gw_set = host_ip6_gw_set;
4953   mp->tap_flags = ntohl (tap_flags);
4954   mp->host_namespace_set = host_ns_set;
4955   mp->host_if_name_set = host_if_name_set;
4956   mp->host_bridge_set = host_bridge_set;
4957
4958   if (random_mac == 0)
4959     clib_memcpy (mp->mac_address, mac_address, 6);
4960   if (host_mac_addr_set)
4961     clib_memcpy (mp->host_mac_addr, host_mac_addr, 6);
4962   if (host_if_name_set)
4963     clib_memcpy (mp->host_if_name, host_if_name, vec_len (host_if_name));
4964   if (host_ns_set)
4965     clib_memcpy (mp->host_namespace, host_ns, vec_len (host_ns));
4966   if (host_bridge_set)
4967     clib_memcpy (mp->host_bridge, host_bridge, vec_len (host_bridge));
4968   if (host_ip4_prefix_set)
4969     {
4970       clib_memcpy (mp->host_ip4_prefix.address, &host_ip4_addr, 4);
4971       mp->host_ip4_prefix.len = (u8) host_ip4_prefix_len;
4972     }
4973   if (host_ip6_prefix_set)
4974     {
4975       clib_memcpy (mp->host_ip6_prefix.address, &host_ip6_addr, 16);
4976       mp->host_ip6_prefix.len = (u8) host_ip6_prefix_len;
4977     }
4978   if (host_ip4_gw_set)
4979     clib_memcpy (mp->host_ip4_gw, &host_ip4_gw, 4);
4980   if (host_ip6_gw_set)
4981     clib_memcpy (mp->host_ip6_gw, &host_ip6_gw, 16);
4982
4983   vec_free (host_ns);
4984   vec_free (host_if_name);
4985   vec_free (host_bridge);
4986
4987   /* send it... */
4988   S (mp);
4989
4990   /* Wait for a reply... */
4991   W (ret);
4992   return ret;
4993 }
4994
4995 static int
4996 api_tap_delete_v2 (vat_main_t * vam)
4997 {
4998   unformat_input_t *i = vam->input;
4999   vl_api_tap_delete_v2_t *mp;
5000   u32 sw_if_index = ~0;
5001   u8 sw_if_index_set = 0;
5002   int ret;
5003
5004   /* Parse args required to build the message */
5005   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5006     {
5007       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5008         sw_if_index_set = 1;
5009       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5010         sw_if_index_set = 1;
5011       else
5012         break;
5013     }
5014
5015   if (sw_if_index_set == 0)
5016     {
5017       errmsg ("missing vpp interface name. ");
5018       return -99;
5019     }
5020
5021   /* Construct the API message */
5022   M (TAP_DELETE_V2, mp);
5023
5024   mp->sw_if_index = ntohl (sw_if_index);
5025
5026   /* send it... */
5027   S (mp);
5028
5029   /* Wait for a reply... */
5030   W (ret);
5031   return ret;
5032 }
5033
5034 uword
5035 unformat_vlib_pci_addr (unformat_input_t * input, va_list * args)
5036 {
5037   vlib_pci_addr_t *addr = va_arg (*args, vlib_pci_addr_t *);
5038   u32 x[4];
5039
5040   if (!unformat (input, "%x:%x:%x.%x", &x[0], &x[1], &x[2], &x[3]))
5041     return 0;
5042
5043   addr->domain = x[0];
5044   addr->bus = x[1];
5045   addr->slot = x[2];
5046   addr->function = x[3];
5047
5048   return 1;
5049 }
5050
5051 static int
5052 api_virtio_pci_create_v2 (vat_main_t * vam)
5053 {
5054   unformat_input_t *i = vam->input;
5055   vl_api_virtio_pci_create_v2_t *mp;
5056   u8 mac_address[6];
5057   u8 random_mac = 1;
5058   u32 pci_addr = 0;
5059   u64 features = (u64) ~ (0ULL);
5060   u32 virtio_flags = 0;
5061   int ret;
5062
5063   clib_memset (mac_address, 0, sizeof (mac_address));
5064
5065   /* Parse args required to build the message */
5066   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5067     {
5068       if (unformat (i, "hw-addr %U", unformat_ethernet_address, mac_address))
5069         {
5070           random_mac = 0;
5071         }
5072       else if (unformat (i, "pci-addr %U", unformat_vlib_pci_addr, &pci_addr))
5073         ;
5074       else if (unformat (i, "features 0x%llx", &features))
5075         ;
5076       else if (unformat (i, "gso-enabled"))
5077         virtio_flags |= VIRTIO_API_FLAG_GSO;
5078       else if (unformat (i, "csum-offload-enabled"))
5079         virtio_flags |= VIRTIO_API_FLAG_CSUM_OFFLOAD;
5080       else if (unformat (i, "gro-coalesce"))
5081         virtio_flags |= VIRTIO_API_FLAG_GRO_COALESCE;
5082       else if (unformat (i, "packed"))
5083         virtio_flags |= VIRTIO_API_FLAG_PACKED;
5084       else if (unformat (i, "in-order"))
5085         virtio_flags |= VIRTIO_API_FLAG_IN_ORDER;
5086       else if (unformat (i, "buffering"))
5087         virtio_flags |= VIRTIO_API_FLAG_BUFFERING;
5088       else
5089         break;
5090     }
5091
5092   if (pci_addr == 0)
5093     {
5094       errmsg ("pci address must be non zero. ");
5095       return -99;
5096     }
5097
5098   /* Construct the API message */
5099   M (VIRTIO_PCI_CREATE_V2, mp);
5100
5101   mp->use_random_mac = random_mac;
5102
5103   mp->pci_addr.domain = htons (((vlib_pci_addr_t) pci_addr).domain);
5104   mp->pci_addr.bus = ((vlib_pci_addr_t) pci_addr).bus;
5105   mp->pci_addr.slot = ((vlib_pci_addr_t) pci_addr).slot;
5106   mp->pci_addr.function = ((vlib_pci_addr_t) pci_addr).function;
5107
5108   mp->features = clib_host_to_net_u64 (features);
5109   mp->virtio_flags = clib_host_to_net_u32 (virtio_flags);
5110
5111   if (random_mac == 0)
5112     clib_memcpy (mp->mac_address, mac_address, 6);
5113
5114   /* send it... */
5115   S (mp);
5116
5117   /* Wait for a reply... */
5118   W (ret);
5119   return ret;
5120 }
5121
5122 static int
5123 api_virtio_pci_delete (vat_main_t * vam)
5124 {
5125   unformat_input_t *i = vam->input;
5126   vl_api_virtio_pci_delete_t *mp;
5127   u32 sw_if_index = ~0;
5128   u8 sw_if_index_set = 0;
5129   int ret;
5130
5131   /* Parse args required to build the message */
5132   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5133     {
5134       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5135         sw_if_index_set = 1;
5136       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5137         sw_if_index_set = 1;
5138       else
5139         break;
5140     }
5141
5142   if (sw_if_index_set == 0)
5143     {
5144       errmsg ("missing vpp interface name. ");
5145       return -99;
5146     }
5147
5148   /* Construct the API message */
5149   M (VIRTIO_PCI_DELETE, mp);
5150
5151   mp->sw_if_index = htonl (sw_if_index);
5152
5153   /* send it... */
5154   S (mp);
5155
5156   /* Wait for a reply... */
5157   W (ret);
5158   return ret;
5159 }
5160
5161 static int
5162 api_bond_create (vat_main_t * vam)
5163 {
5164   unformat_input_t *i = vam->input;
5165   vl_api_bond_create_t *mp;
5166   u8 mac_address[6];
5167   u8 custom_mac = 0;
5168   int ret;
5169   u8 mode;
5170   u8 lb;
5171   u8 mode_is_set = 0;
5172   u32 id = ~0;
5173   u8 numa_only = 0;
5174
5175   clib_memset (mac_address, 0, sizeof (mac_address));
5176   lb = BOND_LB_L2;
5177
5178   /* Parse args required to build the message */
5179   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5180     {
5181       if (unformat (i, "mode %U", unformat_bond_mode, &mode))
5182         mode_is_set = 1;
5183       else if (((mode == BOND_MODE_LACP) || (mode == BOND_MODE_XOR))
5184                && unformat (i, "lb %U", unformat_bond_load_balance, &lb))
5185         ;
5186       else if (unformat (i, "hw-addr %U", unformat_ethernet_address,
5187                          mac_address))
5188         custom_mac = 1;
5189       else if (unformat (i, "numa-only"))
5190         numa_only = 1;
5191       else if (unformat (i, "id %u", &id))
5192         ;
5193       else
5194         break;
5195     }
5196
5197   if (mode_is_set == 0)
5198     {
5199       errmsg ("Missing bond mode. ");
5200       return -99;
5201     }
5202
5203   /* Construct the API message */
5204   M (BOND_CREATE, mp);
5205
5206   mp->use_custom_mac = custom_mac;
5207
5208   mp->mode = htonl (mode);
5209   mp->lb = htonl (lb);
5210   mp->id = htonl (id);
5211   mp->numa_only = numa_only;
5212
5213   if (custom_mac)
5214     clib_memcpy (mp->mac_address, mac_address, 6);
5215
5216   /* send it... */
5217   S (mp);
5218
5219   /* Wait for a reply... */
5220   W (ret);
5221   return ret;
5222 }
5223
5224 static int
5225 api_bond_create2 (vat_main_t * vam)
5226 {
5227   unformat_input_t *i = vam->input;
5228   vl_api_bond_create2_t *mp;
5229   u8 mac_address[6];
5230   u8 custom_mac = 0;
5231   int ret;
5232   u8 mode;
5233   u8 lb;
5234   u8 mode_is_set = 0;
5235   u32 id = ~0;
5236   u8 numa_only = 0;
5237   u8 gso = 0;
5238
5239   clib_memset (mac_address, 0, sizeof (mac_address));
5240   lb = BOND_LB_L2;
5241
5242   /* Parse args required to build the message */
5243   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5244     {
5245       if (unformat (i, "mode %U", unformat_bond_mode, &mode))
5246         mode_is_set = 1;
5247       else if (((mode == BOND_MODE_LACP) || (mode == BOND_MODE_XOR))
5248                && unformat (i, "lb %U", unformat_bond_load_balance, &lb))
5249         ;
5250       else if (unformat (i, "hw-addr %U", unformat_ethernet_address,
5251                          mac_address))
5252         custom_mac = 1;
5253       else if (unformat (i, "numa-only"))
5254         numa_only = 1;
5255       else if (unformat (i, "gso"))
5256         gso = 1;
5257       else if (unformat (i, "id %u", &id))
5258         ;
5259       else
5260         break;
5261     }
5262
5263   if (mode_is_set == 0)
5264     {
5265       errmsg ("Missing bond mode. ");
5266       return -99;
5267     }
5268
5269   /* Construct the API message */
5270   M (BOND_CREATE2, mp);
5271
5272   mp->use_custom_mac = custom_mac;
5273
5274   mp->mode = htonl (mode);
5275   mp->lb = htonl (lb);
5276   mp->id = htonl (id);
5277   mp->numa_only = numa_only;
5278   mp->enable_gso = gso;
5279
5280   if (custom_mac)
5281     clib_memcpy (mp->mac_address, mac_address, 6);
5282
5283   /* send it... */
5284   S (mp);
5285
5286   /* Wait for a reply... */
5287   W (ret);
5288   return ret;
5289 }
5290
5291 static int
5292 api_bond_delete (vat_main_t * vam)
5293 {
5294   unformat_input_t *i = vam->input;
5295   vl_api_bond_delete_t *mp;
5296   u32 sw_if_index = ~0;
5297   u8 sw_if_index_set = 0;
5298   int ret;
5299
5300   /* Parse args required to build the message */
5301   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5302     {
5303       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5304         sw_if_index_set = 1;
5305       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5306         sw_if_index_set = 1;
5307       else
5308         break;
5309     }
5310
5311   if (sw_if_index_set == 0)
5312     {
5313       errmsg ("missing vpp interface name. ");
5314       return -99;
5315     }
5316
5317   /* Construct the API message */
5318   M (BOND_DELETE, mp);
5319
5320   mp->sw_if_index = ntohl (sw_if_index);
5321
5322   /* send it... */
5323   S (mp);
5324
5325   /* Wait for a reply... */
5326   W (ret);
5327   return ret;
5328 }
5329
5330 static int
5331 api_bond_add_member (vat_main_t * vam)
5332 {
5333   unformat_input_t *i = vam->input;
5334   vl_api_bond_add_member_t *mp;
5335   u32 bond_sw_if_index;
5336   int ret;
5337   u8 is_passive;
5338   u8 is_long_timeout;
5339   u32 bond_sw_if_index_is_set = 0;
5340   u32 sw_if_index;
5341   u8 sw_if_index_is_set = 0;
5342
5343   /* Parse args required to build the message */
5344   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5345     {
5346       if (unformat (i, "sw_if_index %d", &sw_if_index))
5347         sw_if_index_is_set = 1;
5348       else if (unformat (i, "bond %u", &bond_sw_if_index))
5349         bond_sw_if_index_is_set = 1;
5350       else if (unformat (i, "passive %d", &is_passive))
5351         ;
5352       else if (unformat (i, "long-timeout %d", &is_long_timeout))
5353         ;
5354       else
5355         break;
5356     }
5357
5358   if (bond_sw_if_index_is_set == 0)
5359     {
5360       errmsg ("Missing bond sw_if_index. ");
5361       return -99;
5362     }
5363   if (sw_if_index_is_set == 0)
5364     {
5365       errmsg ("Missing member sw_if_index. ");
5366       return -99;
5367     }
5368
5369   /* Construct the API message */
5370   M (BOND_ADD_MEMBER, mp);
5371
5372   mp->bond_sw_if_index = ntohl (bond_sw_if_index);
5373   mp->sw_if_index = ntohl (sw_if_index);
5374   mp->is_long_timeout = is_long_timeout;
5375   mp->is_passive = is_passive;
5376
5377   /* send it... */
5378   S (mp);
5379
5380   /* Wait for a reply... */
5381   W (ret);
5382   return ret;
5383 }
5384
5385 static int
5386 api_bond_detach_member (vat_main_t * vam)
5387 {
5388   unformat_input_t *i = vam->input;
5389   vl_api_bond_detach_member_t *mp;
5390   u32 sw_if_index = ~0;
5391   u8 sw_if_index_set = 0;
5392   int ret;
5393
5394   /* Parse args required to build the message */
5395   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5396     {
5397       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5398         sw_if_index_set = 1;
5399       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5400         sw_if_index_set = 1;
5401       else
5402         break;
5403     }
5404
5405   if (sw_if_index_set == 0)
5406     {
5407       errmsg ("missing vpp interface name. ");
5408       return -99;
5409     }
5410
5411   /* Construct the API message */
5412   M (BOND_DETACH_MEMBER, mp);
5413
5414   mp->sw_if_index = ntohl (sw_if_index);
5415
5416   /* send it... */
5417   S (mp);
5418
5419   /* Wait for a reply... */
5420   W (ret);
5421   return ret;
5422 }
5423
5424 static int
5425 api_ip_table_add_del (vat_main_t * vam)
5426 {
5427   unformat_input_t *i = vam->input;
5428   vl_api_ip_table_add_del_t *mp;
5429   u32 table_id = ~0;
5430   u8 is_ipv6 = 0;
5431   u8 is_add = 1;
5432   int ret = 0;
5433
5434   /* Parse args required to build the message */
5435   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5436     {
5437       if (unformat (i, "ipv6"))
5438         is_ipv6 = 1;
5439       else if (unformat (i, "del"))
5440         is_add = 0;
5441       else if (unformat (i, "add"))
5442         is_add = 1;
5443       else if (unformat (i, "table %d", &table_id))
5444         ;
5445       else
5446         {
5447           clib_warning ("parse error '%U'", format_unformat_error, i);
5448           return -99;
5449         }
5450     }
5451
5452   if (~0 == table_id)
5453     {
5454       errmsg ("missing table-ID");
5455       return -99;
5456     }
5457
5458   /* Construct the API message */
5459   M (IP_TABLE_ADD_DEL, mp);
5460
5461   mp->table.table_id = ntohl (table_id);
5462   mp->table.is_ip6 = is_ipv6;
5463   mp->is_add = is_add;
5464
5465   /* send it... */
5466   S (mp);
5467
5468   /* Wait for a reply... */
5469   W (ret);
5470
5471   return ret;
5472 }
5473
5474 uword
5475 unformat_fib_path (unformat_input_t * input, va_list * args)
5476 {
5477   vat_main_t *vam = va_arg (*args, vat_main_t *);
5478   vl_api_fib_path_t *path = va_arg (*args, vl_api_fib_path_t *);
5479   u32 weight, preference;
5480   mpls_label_t out_label;
5481
5482   clib_memset (path, 0, sizeof (*path));
5483   path->weight = 1;
5484   path->sw_if_index = ~0;
5485   path->rpf_id = ~0;
5486   path->n_labels = 0;
5487
5488   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5489     {
5490       if (unformat (input, "%U %U",
5491                     unformat_vl_api_ip4_address,
5492                     &path->nh.address.ip4,
5493                     api_unformat_sw_if_index, vam, &path->sw_if_index))
5494         {
5495           path->proto = FIB_API_PATH_NH_PROTO_IP4;
5496         }
5497       else if (unformat (input, "%U %U",
5498                          unformat_vl_api_ip6_address,
5499                          &path->nh.address.ip6,
5500                          api_unformat_sw_if_index, vam, &path->sw_if_index))
5501         {
5502           path->proto = FIB_API_PATH_NH_PROTO_IP6;
5503         }
5504       else if (unformat (input, "weight %u", &weight))
5505         {
5506           path->weight = weight;
5507         }
5508       else if (unformat (input, "preference %u", &preference))
5509         {
5510           path->preference = preference;
5511         }
5512       else if (unformat (input, "%U next-hop-table %d",
5513                          unformat_vl_api_ip4_address,
5514                          &path->nh.address.ip4, &path->table_id))
5515         {
5516           path->proto = FIB_API_PATH_NH_PROTO_IP4;
5517         }
5518       else if (unformat (input, "%U next-hop-table %d",
5519                          unformat_vl_api_ip6_address,
5520                          &path->nh.address.ip6, &path->table_id))
5521         {
5522           path->proto = FIB_API_PATH_NH_PROTO_IP6;
5523         }
5524       else if (unformat (input, "%U",
5525                          unformat_vl_api_ip4_address, &path->nh.address.ip4))
5526         {
5527           /*
5528            * the recursive next-hops are by default in the default table
5529            */
5530           path->table_id = 0;
5531           path->sw_if_index = ~0;
5532           path->proto = FIB_API_PATH_NH_PROTO_IP4;
5533         }
5534       else if (unformat (input, "%U",
5535                          unformat_vl_api_ip6_address, &path->nh.address.ip6))
5536         {
5537           /*
5538            * the recursive next-hops are by default in the default table
5539            */
5540           path->table_id = 0;
5541           path->sw_if_index = ~0;
5542           path->proto = FIB_API_PATH_NH_PROTO_IP6;
5543         }
5544       else if (unformat (input, "resolve-via-host"))
5545         {
5546           path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_HOST;
5547         }
5548       else if (unformat (input, "resolve-via-attached"))
5549         {
5550           path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_ATTACHED;
5551         }
5552       else if (unformat (input, "ip4-lookup-in-table %d", &path->table_id))
5553         {
5554           path->type = FIB_API_PATH_TYPE_LOCAL;
5555           path->sw_if_index = ~0;
5556           path->proto = FIB_API_PATH_NH_PROTO_IP4;
5557         }
5558       else if (unformat (input, "ip6-lookup-in-table %d", &path->table_id))
5559         {
5560           path->type = FIB_API_PATH_TYPE_LOCAL;
5561           path->sw_if_index = ~0;
5562           path->proto = FIB_API_PATH_NH_PROTO_IP6;
5563         }
5564       else if (unformat (input, "sw_if_index %d", &path->sw_if_index))
5565         ;
5566       else if (unformat (input, "via-label %d", &path->nh.via_label))
5567         {
5568           path->proto = FIB_API_PATH_NH_PROTO_MPLS;
5569           path->sw_if_index = ~0;
5570         }
5571       else if (unformat (input, "l2-input-on %d", &path->sw_if_index))
5572         {
5573           path->proto = FIB_API_PATH_NH_PROTO_ETHERNET;
5574           path->type = FIB_API_PATH_TYPE_INTERFACE_RX;
5575         }
5576       else if (unformat (input, "local"))
5577         {
5578           path->type = FIB_API_PATH_TYPE_LOCAL;
5579         }
5580       else if (unformat (input, "out-labels"))
5581         {
5582           while (unformat (input, "%d", &out_label))
5583             {
5584               path->label_stack[path->n_labels].label = out_label;
5585               path->label_stack[path->n_labels].is_uniform = 0;
5586               path->label_stack[path->n_labels].ttl = 64;
5587               path->n_labels++;
5588             }
5589         }
5590       else if (unformat (input, "via"))
5591         {
5592           /* new path, back up and return */
5593           unformat_put_input (input);
5594           unformat_put_input (input);
5595           unformat_put_input (input);
5596           unformat_put_input (input);
5597           break;
5598         }
5599       else
5600         {
5601           return (0);
5602         }
5603     }
5604
5605   path->proto = ntohl (path->proto);
5606   path->type = ntohl (path->type);
5607   path->flags = ntohl (path->flags);
5608   path->table_id = ntohl (path->table_id);
5609   path->sw_if_index = ntohl (path->sw_if_index);
5610
5611   return (1);
5612 }
5613
5614 static int
5615 api_ip_route_add_del (vat_main_t * vam)
5616 {
5617   unformat_input_t *i = vam->input;
5618   vl_api_ip_route_add_del_t *mp;
5619   u32 vrf_id = 0;
5620   u8 is_add = 1;
5621   u8 is_multipath = 0;
5622   u8 prefix_set = 0;
5623   u8 path_count = 0;
5624   vl_api_prefix_t pfx = { };
5625   vl_api_fib_path_t paths[8];
5626   int count = 1;
5627   int j;
5628   f64 before = 0;
5629   u32 random_add_del = 0;
5630   u32 *random_vector = 0;
5631   u32 random_seed = 0xdeaddabe;
5632
5633   /* Parse args required to build the message */
5634   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5635     {
5636       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
5637         prefix_set = 1;
5638       else if (unformat (i, "del"))
5639         is_add = 0;
5640       else if (unformat (i, "add"))
5641         is_add = 1;
5642       else if (unformat (i, "vrf %d", &vrf_id))
5643         ;
5644       else if (unformat (i, "count %d", &count))
5645         ;
5646       else if (unformat (i, "random"))
5647         random_add_del = 1;
5648       else if (unformat (i, "multipath"))
5649         is_multipath = 1;
5650       else if (unformat (i, "seed %d", &random_seed))
5651         ;
5652       else
5653         if (unformat
5654             (i, "via %U", unformat_fib_path, vam, &paths[path_count]))
5655         {
5656           path_count++;
5657           if (8 == path_count)
5658             {
5659               errmsg ("max 8 paths");
5660               return -99;
5661             }
5662         }
5663       else
5664         {
5665           clib_warning ("parse error '%U'", format_unformat_error, i);
5666           return -99;
5667         }
5668     }
5669
5670   if (!path_count)
5671     {
5672       errmsg ("specify a path; via ...");
5673       return -99;
5674     }
5675   if (prefix_set == 0)
5676     {
5677       errmsg ("missing prefix");
5678       return -99;
5679     }
5680
5681   /* Generate a pile of unique, random routes */
5682   if (random_add_del)
5683     {
5684       ip4_address_t *i = (ip4_address_t *) & paths[0].nh.address.ip4;
5685       u32 this_random_address;
5686       uword *random_hash;
5687
5688       random_hash = hash_create (count, sizeof (uword));
5689
5690       hash_set (random_hash, i->as_u32, 1);
5691       for (j = 0; j <= count; j++)
5692         {
5693           do
5694             {
5695               this_random_address = random_u32 (&random_seed);
5696               this_random_address =
5697                 clib_host_to_net_u32 (this_random_address);
5698             }
5699           while (hash_get (random_hash, this_random_address));
5700           vec_add1 (random_vector, this_random_address);
5701           hash_set (random_hash, this_random_address, 1);
5702         }
5703       hash_free (random_hash);
5704       set_ip4_address (&pfx.address, random_vector[0]);
5705     }
5706
5707   if (count > 1)
5708     {
5709       /* Turn on async mode */
5710       vam->async_mode = 1;
5711       vam->async_errors = 0;
5712       before = vat_time_now (vam);
5713     }
5714
5715   for (j = 0; j < count; j++)
5716     {
5717       /* Construct the API message */
5718       M2 (IP_ROUTE_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
5719
5720       mp->is_add = is_add;
5721       mp->is_multipath = is_multipath;
5722
5723       clib_memcpy (&mp->route.prefix, &pfx, sizeof (pfx));
5724       mp->route.table_id = ntohl (vrf_id);
5725       mp->route.n_paths = path_count;
5726
5727       clib_memcpy (&mp->route.paths, &paths, sizeof (paths[0]) * path_count);
5728
5729       if (random_add_del)
5730         set_ip4_address (&pfx.address, random_vector[j + 1]);
5731       else
5732         increment_address (&pfx.address);
5733       /* send it... */
5734       S (mp);
5735       /* If we receive SIGTERM, stop now... */
5736       if (vam->do_exit)
5737         break;
5738     }
5739
5740   /* When testing multiple add/del ops, use a control-ping to sync */
5741   if (count > 1)
5742     {
5743       vl_api_control_ping_t *mp_ping;
5744       f64 after;
5745       f64 timeout;
5746
5747       /* Shut off async mode */
5748       vam->async_mode = 0;
5749
5750       MPING (CONTROL_PING, mp_ping);
5751       S (mp_ping);
5752
5753       timeout = vat_time_now (vam) + 1.0;
5754       while (vat_time_now (vam) < timeout)
5755         if (vam->result_ready == 1)
5756           goto out;
5757       vam->retval = -99;
5758
5759     out:
5760       if (vam->retval == -99)
5761         errmsg ("timeout");
5762
5763       if (vam->async_errors > 0)
5764         {
5765           errmsg ("%d asynchronous errors", vam->async_errors);
5766           vam->retval = -98;
5767         }
5768       vam->async_errors = 0;
5769       after = vat_time_now (vam);
5770
5771       /* slim chance, but we might have eaten SIGTERM on the first iteration */
5772       if (j > 0)
5773         count = j;
5774
5775       print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec",
5776              count, after - before, count / (after - before));
5777     }
5778   else
5779     {
5780       int ret;
5781
5782       /* Wait for a reply... */
5783       W (ret);
5784       return ret;
5785     }
5786
5787   /* Return the good/bad news */
5788   return (vam->retval);
5789 }
5790
5791 static int
5792 api_ip_mroute_add_del (vat_main_t * vam)
5793 {
5794   unformat_input_t *i = vam->input;
5795   u8 path_set = 0, prefix_set = 0, is_add = 1;
5796   vl_api_ip_mroute_add_del_t *mp;
5797   mfib_entry_flags_t eflags = 0;
5798   vl_api_mfib_path_t path;
5799   vl_api_mprefix_t pfx = { };
5800   u32 vrf_id = 0;
5801   int ret;
5802
5803   /* Parse args required to build the message */
5804   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5805     {
5806       if (unformat (i, "%U", unformat_vl_api_mprefix, &pfx))
5807         {
5808           prefix_set = 1;
5809           pfx.grp_address_length = htons (pfx.grp_address_length);
5810         }
5811       else if (unformat (i, "del"))
5812         is_add = 0;
5813       else if (unformat (i, "add"))
5814         is_add = 1;
5815       else if (unformat (i, "vrf %d", &vrf_id))
5816         ;
5817       else if (unformat (i, "%U", unformat_mfib_itf_flags, &path.itf_flags))
5818         path.itf_flags = htonl (path.itf_flags);
5819       else if (unformat (i, "%U", unformat_mfib_entry_flags, &eflags))
5820         ;
5821       else if (unformat (i, "via %U", unformat_fib_path, vam, &path.path))
5822         path_set = 1;
5823       else
5824         {
5825           clib_warning ("parse error '%U'", format_unformat_error, i);
5826           return -99;
5827         }
5828     }
5829
5830   if (prefix_set == 0)
5831     {
5832       errmsg ("missing addresses\n");
5833       return -99;
5834     }
5835   if (path_set == 0)
5836     {
5837       errmsg ("missing path\n");
5838       return -99;
5839     }
5840
5841   /* Construct the API message */
5842   M (IP_MROUTE_ADD_DEL, mp);
5843
5844   mp->is_add = is_add;
5845   mp->is_multipath = 1;
5846
5847   clib_memcpy (&mp->route.prefix, &pfx, sizeof (pfx));
5848   mp->route.table_id = htonl (vrf_id);
5849   mp->route.n_paths = 1;
5850   mp->route.entry_flags = htonl (eflags);
5851
5852   clib_memcpy (&mp->route.paths, &path, sizeof (path));
5853
5854   /* send it... */
5855   S (mp);
5856   /* Wait for a reply... */
5857   W (ret);
5858   return ret;
5859 }
5860
5861 static int
5862 api_mpls_table_add_del (vat_main_t * vam)
5863 {
5864   unformat_input_t *i = vam->input;
5865   vl_api_mpls_table_add_del_t *mp;
5866   u32 table_id = ~0;
5867   u8 is_add = 1;
5868   int ret = 0;
5869
5870   /* Parse args required to build the message */
5871   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5872     {
5873       if (unformat (i, "table %d", &table_id))
5874         ;
5875       else if (unformat (i, "del"))
5876         is_add = 0;
5877       else if (unformat (i, "add"))
5878         is_add = 1;
5879       else
5880         {
5881           clib_warning ("parse error '%U'", format_unformat_error, i);
5882           return -99;
5883         }
5884     }
5885
5886   if (~0 == table_id)
5887     {
5888       errmsg ("missing table-ID");
5889       return -99;
5890     }
5891
5892   /* Construct the API message */
5893   M (MPLS_TABLE_ADD_DEL, mp);
5894
5895   mp->mt_table.mt_table_id = ntohl (table_id);
5896   mp->mt_is_add = is_add;
5897
5898   /* send it... */
5899   S (mp);
5900
5901   /* Wait for a reply... */
5902   W (ret);
5903
5904   return ret;
5905 }
5906
5907 static int
5908 api_mpls_route_add_del (vat_main_t * vam)
5909 {
5910   u8 is_add = 1, path_count = 0, is_multipath = 0, is_eos = 0;
5911   mpls_label_t local_label = MPLS_LABEL_INVALID;
5912   unformat_input_t *i = vam->input;
5913   vl_api_mpls_route_add_del_t *mp;
5914   vl_api_fib_path_t paths[8];
5915   int count = 1, j;
5916   f64 before = 0;
5917
5918   /* Parse args required to build the message */
5919   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5920     {
5921       if (unformat (i, "%d", &local_label))
5922         ;
5923       else if (unformat (i, "eos"))
5924         is_eos = 1;
5925       else if (unformat (i, "non-eos"))
5926         is_eos = 0;
5927       else if (unformat (i, "del"))
5928         is_add = 0;
5929       else if (unformat (i, "add"))
5930         is_add = 1;
5931       else if (unformat (i, "multipath"))
5932         is_multipath = 1;
5933       else if (unformat (i, "count %d", &count))
5934         ;
5935       else
5936         if (unformat
5937             (i, "via %U", unformat_fib_path, vam, &paths[path_count]))
5938         {
5939           path_count++;
5940           if (8 == path_count)
5941             {
5942               errmsg ("max 8 paths");
5943               return -99;
5944             }
5945         }
5946       else
5947         {
5948           clib_warning ("parse error '%U'", format_unformat_error, i);
5949           return -99;
5950         }
5951     }
5952
5953   if (!path_count)
5954     {
5955       errmsg ("specify a path; via ...");
5956       return -99;
5957     }
5958
5959   if (MPLS_LABEL_INVALID == local_label)
5960     {
5961       errmsg ("missing label");
5962       return -99;
5963     }
5964
5965   if (count > 1)
5966     {
5967       /* Turn on async mode */
5968       vam->async_mode = 1;
5969       vam->async_errors = 0;
5970       before = vat_time_now (vam);
5971     }
5972
5973   for (j = 0; j < count; j++)
5974     {
5975       /* Construct the API message */
5976       M2 (MPLS_ROUTE_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
5977
5978       mp->mr_is_add = is_add;
5979       mp->mr_is_multipath = is_multipath;
5980
5981       mp->mr_route.mr_label = local_label;
5982       mp->mr_route.mr_eos = is_eos;
5983       mp->mr_route.mr_table_id = 0;
5984       mp->mr_route.mr_n_paths = path_count;
5985
5986       clib_memcpy (&mp->mr_route.mr_paths, paths,
5987                    sizeof (paths[0]) * path_count);
5988
5989       local_label++;
5990
5991       /* send it... */
5992       S (mp);
5993       /* If we receive SIGTERM, stop now... */
5994       if (vam->do_exit)
5995         break;
5996     }
5997
5998   /* When testing multiple add/del ops, use a control-ping to sync */
5999   if (count > 1)
6000     {
6001       vl_api_control_ping_t *mp_ping;
6002       f64 after;
6003       f64 timeout;
6004
6005       /* Shut off async mode */
6006       vam->async_mode = 0;
6007
6008       MPING (CONTROL_PING, mp_ping);
6009       S (mp_ping);
6010
6011       timeout = vat_time_now (vam) + 1.0;
6012       while (vat_time_now (vam) < timeout)
6013         if (vam->result_ready == 1)
6014           goto out;
6015       vam->retval = -99;
6016
6017     out:
6018       if (vam->retval == -99)
6019         errmsg ("timeout");
6020
6021       if (vam->async_errors > 0)
6022         {
6023           errmsg ("%d asynchronous errors", vam->async_errors);
6024           vam->retval = -98;
6025         }
6026       vam->async_errors = 0;
6027       after = vat_time_now (vam);
6028
6029       /* slim chance, but we might have eaten SIGTERM on the first iteration */
6030       if (j > 0)
6031         count = j;
6032
6033       print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec",
6034              count, after - before, count / (after - before));
6035     }
6036   else
6037     {
6038       int ret;
6039
6040       /* Wait for a reply... */
6041       W (ret);
6042       return ret;
6043     }
6044
6045   /* Return the good/bad news */
6046   return (vam->retval);
6047   return (0);
6048 }
6049
6050 static int
6051 api_mpls_ip_bind_unbind (vat_main_t * vam)
6052 {
6053   unformat_input_t *i = vam->input;
6054   vl_api_mpls_ip_bind_unbind_t *mp;
6055   u32 ip_table_id = 0;
6056   u8 is_bind = 1;
6057   vl_api_prefix_t pfx;
6058   u8 prefix_set = 0;
6059   mpls_label_t local_label = MPLS_LABEL_INVALID;
6060   int ret;
6061
6062   /* Parse args required to build the message */
6063   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6064     {
6065       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
6066         prefix_set = 1;
6067       else if (unformat (i, "%d", &local_label))
6068         ;
6069       else if (unformat (i, "table-id %d", &ip_table_id))
6070         ;
6071       else if (unformat (i, "unbind"))
6072         is_bind = 0;
6073       else if (unformat (i, "bind"))
6074         is_bind = 1;
6075       else
6076         {
6077           clib_warning ("parse error '%U'", format_unformat_error, i);
6078           return -99;
6079         }
6080     }
6081
6082   if (!prefix_set)
6083     {
6084       errmsg ("IP prefix not set");
6085       return -99;
6086     }
6087
6088   if (MPLS_LABEL_INVALID == local_label)
6089     {
6090       errmsg ("missing label");
6091       return -99;
6092     }
6093
6094   /* Construct the API message */
6095   M (MPLS_IP_BIND_UNBIND, mp);
6096
6097   mp->mb_is_bind = is_bind;
6098   mp->mb_ip_table_id = ntohl (ip_table_id);
6099   mp->mb_mpls_table_id = 0;
6100   mp->mb_label = ntohl (local_label);
6101   clib_memcpy (&mp->mb_prefix, &pfx, sizeof (pfx));
6102
6103   /* send it... */
6104   S (mp);
6105
6106   /* Wait for a reply... */
6107   W (ret);
6108   return ret;
6109   return (0);
6110 }
6111
6112 static int
6113 api_sr_mpls_policy_add (vat_main_t * vam)
6114 {
6115   unformat_input_t *i = vam->input;
6116   vl_api_sr_mpls_policy_add_t *mp;
6117   u32 bsid = 0;
6118   u32 weight = 1;
6119   u8 type = 0;
6120   u8 n_segments = 0;
6121   u32 sid;
6122   u32 *segments = NULL;
6123   int ret;
6124
6125   /* Parse args required to build the message */
6126   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6127     {
6128       if (unformat (i, "bsid %d", &bsid))
6129         ;
6130       else if (unformat (i, "weight %d", &weight))
6131         ;
6132       else if (unformat (i, "spray"))
6133         type = 1;
6134       else if (unformat (i, "next %d", &sid))
6135         {
6136           n_segments += 1;
6137           vec_add1 (segments, htonl (sid));
6138         }
6139       else
6140         {
6141           clib_warning ("parse error '%U'", format_unformat_error, i);
6142           return -99;
6143         }
6144     }
6145
6146   if (bsid == 0)
6147     {
6148       errmsg ("bsid not set");
6149       return -99;
6150     }
6151
6152   if (n_segments == 0)
6153     {
6154       errmsg ("no sid in segment stack");
6155       return -99;
6156     }
6157
6158   /* Construct the API message */
6159   M2 (SR_MPLS_POLICY_ADD, mp, sizeof (u32) * n_segments);
6160
6161   mp->bsid = htonl (bsid);
6162   mp->weight = htonl (weight);
6163   mp->is_spray = type;
6164   mp->n_segments = n_segments;
6165   memcpy (mp->segments, segments, sizeof (u32) * n_segments);
6166   vec_free (segments);
6167
6168   /* send it... */
6169   S (mp);
6170
6171   /* Wait for a reply... */
6172   W (ret);
6173   return ret;
6174 }
6175
6176 static int
6177 api_sr_mpls_policy_del (vat_main_t * vam)
6178 {
6179   unformat_input_t *i = vam->input;
6180   vl_api_sr_mpls_policy_del_t *mp;
6181   u32 bsid = 0;
6182   int ret;
6183
6184   /* Parse args required to build the message */
6185   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6186     {
6187       if (unformat (i, "bsid %d", &bsid))
6188         ;
6189       else
6190         {
6191           clib_warning ("parse error '%U'", format_unformat_error, i);
6192           return -99;
6193         }
6194     }
6195
6196   if (bsid == 0)
6197     {
6198       errmsg ("bsid not set");
6199       return -99;
6200     }
6201
6202   /* Construct the API message */
6203   M (SR_MPLS_POLICY_DEL, mp);
6204
6205   mp->bsid = htonl (bsid);
6206
6207   /* send it... */
6208   S (mp);
6209
6210   /* Wait for a reply... */
6211   W (ret);
6212   return ret;
6213 }
6214
6215 static int
6216 api_mpls_tunnel_add_del (vat_main_t * vam)
6217 {
6218   unformat_input_t *i = vam->input;
6219   vl_api_mpls_tunnel_add_del_t *mp;
6220
6221   vl_api_fib_path_t paths[8];
6222   u32 sw_if_index = ~0;
6223   u8 path_count = 0;
6224   u8 l2_only = 0;
6225   u8 is_add = 1;
6226   int ret;
6227
6228   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6229     {
6230       if (unformat (i, "add"))
6231         is_add = 1;
6232       else
6233         if (unformat
6234             (i, "del %U", api_unformat_sw_if_index, vam, &sw_if_index))
6235         is_add = 0;
6236       else if (unformat (i, "del sw_if_index %d", &sw_if_index))
6237         is_add = 0;
6238       else if (unformat (i, "l2-only"))
6239         l2_only = 1;
6240       else
6241         if (unformat
6242             (i, "via %U", unformat_fib_path, vam, &paths[path_count]))
6243         {
6244           path_count++;
6245           if (8 == path_count)
6246             {
6247               errmsg ("max 8 paths");
6248               return -99;
6249             }
6250         }
6251       else
6252         {
6253           clib_warning ("parse error '%U'", format_unformat_error, i);
6254           return -99;
6255         }
6256     }
6257
6258   M2 (MPLS_TUNNEL_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
6259
6260   mp->mt_is_add = is_add;
6261   mp->mt_tunnel.mt_sw_if_index = ntohl (sw_if_index);
6262   mp->mt_tunnel.mt_l2_only = l2_only;
6263   mp->mt_tunnel.mt_is_multicast = 0;
6264   mp->mt_tunnel.mt_n_paths = path_count;
6265
6266   clib_memcpy (&mp->mt_tunnel.mt_paths, &paths,
6267                sizeof (paths[0]) * path_count);
6268
6269   S (mp);
6270   W (ret);
6271   return ret;
6272 }
6273
6274 static int
6275 api_sw_interface_set_unnumbered (vat_main_t * vam)
6276 {
6277   unformat_input_t *i = vam->input;
6278   vl_api_sw_interface_set_unnumbered_t *mp;
6279   u32 sw_if_index;
6280   u32 unnum_sw_index = ~0;
6281   u8 is_add = 1;
6282   u8 sw_if_index_set = 0;
6283   int ret;
6284
6285   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6286     {
6287       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
6288         sw_if_index_set = 1;
6289       else if (unformat (i, "sw_if_index %d", &sw_if_index))
6290         sw_if_index_set = 1;
6291       else if (unformat (i, "unnum_if_index %d", &unnum_sw_index))
6292         ;
6293       else if (unformat (i, "del"))
6294         is_add = 0;
6295       else
6296         {
6297           clib_warning ("parse error '%U'", format_unformat_error, i);
6298           return -99;
6299         }
6300     }
6301
6302   if (sw_if_index_set == 0)
6303     {
6304       errmsg ("missing interface name or sw_if_index");
6305       return -99;
6306     }
6307
6308   M (SW_INTERFACE_SET_UNNUMBERED, mp);
6309
6310   mp->sw_if_index = ntohl (sw_if_index);
6311   mp->unnumbered_sw_if_index = ntohl (unnum_sw_index);
6312   mp->is_add = is_add;
6313
6314   S (mp);
6315   W (ret);
6316   return ret;
6317 }
6318
6319
6320 static int
6321 api_create_vlan_subif (vat_main_t * vam)
6322 {
6323   unformat_input_t *i = vam->input;
6324   vl_api_create_vlan_subif_t *mp;
6325   u32 sw_if_index;
6326   u8 sw_if_index_set = 0;
6327   u32 vlan_id;
6328   u8 vlan_id_set = 0;
6329   int ret;
6330
6331   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6332     {
6333       if (unformat (i, "sw_if_index %d", &sw_if_index))
6334         sw_if_index_set = 1;
6335       else
6336         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
6337         sw_if_index_set = 1;
6338       else if (unformat (i, "vlan %d", &vlan_id))
6339         vlan_id_set = 1;
6340       else
6341         {
6342           clib_warning ("parse error '%U'", format_unformat_error, i);
6343           return -99;
6344         }
6345     }
6346
6347   if (sw_if_index_set == 0)
6348     {
6349       errmsg ("missing interface name or sw_if_index");
6350       return -99;
6351     }
6352
6353   if (vlan_id_set == 0)
6354     {
6355       errmsg ("missing vlan_id");
6356       return -99;
6357     }
6358   M (CREATE_VLAN_SUBIF, mp);
6359
6360   mp->sw_if_index = ntohl (sw_if_index);
6361   mp->vlan_id = ntohl (vlan_id);
6362
6363   S (mp);
6364   W (ret);
6365   return ret;
6366 }
6367
6368 #define foreach_create_subif_bit                \
6369 _(no_tags)                                      \
6370 _(one_tag)                                      \
6371 _(two_tags)                                     \
6372 _(dot1ad)                                       \
6373 _(exact_match)                                  \
6374 _(default_sub)                                  \
6375 _(outer_vlan_id_any)                            \
6376 _(inner_vlan_id_any)
6377
6378 #define foreach_create_subif_flag               \
6379 _(0, "no_tags")                                 \
6380 _(1, "one_tag")                                 \
6381 _(2, "two_tags")                                \
6382 _(3, "dot1ad")                                  \
6383 _(4, "exact_match")                             \
6384 _(5, "default_sub")                             \
6385 _(6, "outer_vlan_id_any")                       \
6386 _(7, "inner_vlan_id_any")
6387
6388 static int
6389 api_create_subif (vat_main_t * vam)
6390 {
6391   unformat_input_t *i = vam->input;
6392   vl_api_create_subif_t *mp;
6393   u32 sw_if_index;
6394   u8 sw_if_index_set = 0;
6395   u32 sub_id;
6396   u8 sub_id_set = 0;
6397   u32 __attribute__ ((unused)) no_tags = 0;
6398   u32 __attribute__ ((unused)) one_tag = 0;
6399   u32 __attribute__ ((unused)) two_tags = 0;
6400   u32 __attribute__ ((unused)) dot1ad = 0;
6401   u32 __attribute__ ((unused)) exact_match = 0;
6402   u32 __attribute__ ((unused)) default_sub = 0;
6403   u32 __attribute__ ((unused)) outer_vlan_id_any = 0;
6404   u32 __attribute__ ((unused)) inner_vlan_id_any = 0;
6405   u32 tmp;
6406   u16 outer_vlan_id = 0;
6407   u16 inner_vlan_id = 0;
6408   int ret;
6409
6410   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6411     {
6412       if (unformat (i, "sw_if_index %d", &sw_if_index))
6413         sw_if_index_set = 1;
6414       else
6415         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
6416         sw_if_index_set = 1;
6417       else if (unformat (i, "sub_id %d", &sub_id))
6418         sub_id_set = 1;
6419       else if (unformat (i, "outer_vlan_id %d", &tmp))
6420         outer_vlan_id = tmp;
6421       else if (unformat (i, "inner_vlan_id %d", &tmp))
6422         inner_vlan_id = tmp;
6423
6424 #define _(a) else if (unformat (i, #a)) a = 1 ;
6425       foreach_create_subif_bit
6426 #undef _
6427         else
6428         {
6429           clib_warning ("parse error '%U'", format_unformat_error, i);
6430           return -99;
6431         }
6432     }
6433
6434   if (sw_if_index_set == 0)
6435     {
6436       errmsg ("missing interface name or sw_if_index");
6437       return -99;
6438     }
6439
6440   if (sub_id_set == 0)
6441     {
6442       errmsg ("missing sub_id");
6443       return -99;
6444     }
6445   M (CREATE_SUBIF, mp);
6446
6447   mp->sw_if_index = ntohl (sw_if_index);
6448   mp->sub_id = ntohl (sub_id);
6449
6450 #define _(a,b) mp->sub_if_flags |= (1 << a);
6451   foreach_create_subif_flag;
6452 #undef _
6453
6454   mp->outer_vlan_id = ntohs (outer_vlan_id);
6455   mp->inner_vlan_id = ntohs (inner_vlan_id);
6456
6457   S (mp);
6458   W (ret);
6459   return ret;
6460 }
6461
6462 static int
6463 api_ip_table_replace_begin (vat_main_t * vam)
6464 {
6465   unformat_input_t *i = vam->input;
6466   vl_api_ip_table_replace_begin_t *mp;
6467   u32 table_id = 0;
6468   u8 is_ipv6 = 0;
6469
6470   int ret;
6471   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6472     {
6473       if (unformat (i, "table %d", &table_id))
6474         ;
6475       else if (unformat (i, "ipv6"))
6476         is_ipv6 = 1;
6477       else
6478         {
6479           clib_warning ("parse error '%U'", format_unformat_error, i);
6480           return -99;
6481         }
6482     }
6483
6484   M (IP_TABLE_REPLACE_BEGIN, mp);
6485
6486   mp->table.table_id = ntohl (table_id);
6487   mp->table.is_ip6 = is_ipv6;
6488
6489   S (mp);
6490   W (ret);
6491   return ret;
6492 }
6493
6494 static int
6495 api_ip_table_flush (vat_main_t * vam)
6496 {
6497   unformat_input_t *i = vam->input;
6498   vl_api_ip_table_flush_t *mp;
6499   u32 table_id = 0;
6500   u8 is_ipv6 = 0;
6501
6502   int ret;
6503   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6504     {
6505       if (unformat (i, "table %d", &table_id))
6506         ;
6507       else if (unformat (i, "ipv6"))
6508         is_ipv6 = 1;
6509       else
6510         {
6511           clib_warning ("parse error '%U'", format_unformat_error, i);
6512           return -99;
6513         }
6514     }
6515
6516   M (IP_TABLE_FLUSH, mp);
6517
6518   mp->table.table_id = ntohl (table_id);
6519   mp->table.is_ip6 = is_ipv6;
6520
6521   S (mp);
6522   W (ret);
6523   return ret;
6524 }
6525
6526 static int
6527 api_ip_table_replace_end (vat_main_t * vam)
6528 {
6529   unformat_input_t *i = vam->input;
6530   vl_api_ip_table_replace_end_t *mp;
6531   u32 table_id = 0;
6532   u8 is_ipv6 = 0;
6533
6534   int ret;
6535   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6536     {
6537       if (unformat (i, "table %d", &table_id))
6538         ;
6539       else if (unformat (i, "ipv6"))
6540         is_ipv6 = 1;
6541       else
6542         {
6543           clib_warning ("parse error '%U'", format_unformat_error, i);
6544           return -99;
6545         }
6546     }
6547
6548   M (IP_TABLE_REPLACE_END, mp);
6549
6550   mp->table.table_id = ntohl (table_id);
6551   mp->table.is_ip6 = is_ipv6;
6552
6553   S (mp);
6554   W (ret);
6555   return ret;
6556 }
6557
6558 static int
6559 api_set_ip_flow_hash (vat_main_t * vam)
6560 {
6561   unformat_input_t *i = vam->input;
6562   vl_api_set_ip_flow_hash_t *mp;
6563   u32 vrf_id = 0;
6564   u8 is_ipv6 = 0;
6565   u8 vrf_id_set = 0;
6566   u8 src = 0;
6567   u8 dst = 0;
6568   u8 sport = 0;
6569   u8 dport = 0;
6570   u8 proto = 0;
6571   u8 reverse = 0;
6572   int ret;
6573
6574   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6575     {
6576       if (unformat (i, "vrf %d", &vrf_id))
6577         vrf_id_set = 1;
6578       else if (unformat (i, "ipv6"))
6579         is_ipv6 = 1;
6580       else if (unformat (i, "src"))
6581         src = 1;
6582       else if (unformat (i, "dst"))
6583         dst = 1;
6584       else if (unformat (i, "sport"))
6585         sport = 1;
6586       else if (unformat (i, "dport"))
6587         dport = 1;
6588       else if (unformat (i, "proto"))
6589         proto = 1;
6590       else if (unformat (i, "reverse"))
6591         reverse = 1;
6592
6593       else
6594         {
6595           clib_warning ("parse error '%U'", format_unformat_error, i);
6596           return -99;
6597         }
6598     }
6599
6600   if (vrf_id_set == 0)
6601     {
6602       errmsg ("missing vrf id");
6603       return -99;
6604     }
6605
6606   M (SET_IP_FLOW_HASH, mp);
6607   mp->src = src;
6608   mp->dst = dst;
6609   mp->sport = sport;
6610   mp->dport = dport;
6611   mp->proto = proto;
6612   mp->reverse = reverse;
6613   mp->vrf_id = ntohl (vrf_id);
6614   mp->is_ipv6 = is_ipv6;
6615
6616   S (mp);
6617   W (ret);
6618   return ret;
6619 }
6620
6621 static int
6622 api_sw_interface_ip6_enable_disable (vat_main_t * vam)
6623 {
6624   unformat_input_t *i = vam->input;
6625   vl_api_sw_interface_ip6_enable_disable_t *mp;
6626   u32 sw_if_index;
6627   u8 sw_if_index_set = 0;
6628   u8 enable = 0;
6629   int ret;
6630
6631   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6632     {
6633       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
6634         sw_if_index_set = 1;
6635       else if (unformat (i, "sw_if_index %d", &sw_if_index))
6636         sw_if_index_set = 1;
6637       else if (unformat (i, "enable"))
6638         enable = 1;
6639       else if (unformat (i, "disable"))
6640         enable = 0;
6641       else
6642         {
6643           clib_warning ("parse error '%U'", format_unformat_error, i);
6644           return -99;
6645         }
6646     }
6647
6648   if (sw_if_index_set == 0)
6649     {
6650       errmsg ("missing interface name or sw_if_index");
6651       return -99;
6652     }
6653
6654   M (SW_INTERFACE_IP6_ENABLE_DISABLE, mp);
6655
6656   mp->sw_if_index = ntohl (sw_if_index);
6657   mp->enable = enable;
6658
6659   S (mp);
6660   W (ret);
6661   return ret;
6662 }
6663
6664
6665 static int
6666 api_l2_patch_add_del (vat_main_t * vam)
6667 {
6668   unformat_input_t *i = vam->input;
6669   vl_api_l2_patch_add_del_t *mp;
6670   u32 rx_sw_if_index;
6671   u8 rx_sw_if_index_set = 0;
6672   u32 tx_sw_if_index;
6673   u8 tx_sw_if_index_set = 0;
6674   u8 is_add = 1;
6675   int ret;
6676
6677   /* Parse args required to build the message */
6678   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6679     {
6680       if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index))
6681         rx_sw_if_index_set = 1;
6682       else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
6683         tx_sw_if_index_set = 1;
6684       else if (unformat (i, "rx"))
6685         {
6686           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6687             {
6688               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
6689                             &rx_sw_if_index))
6690                 rx_sw_if_index_set = 1;
6691             }
6692           else
6693             break;
6694         }
6695       else if (unformat (i, "tx"))
6696         {
6697           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6698             {
6699               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
6700                             &tx_sw_if_index))
6701                 tx_sw_if_index_set = 1;
6702             }
6703           else
6704             break;
6705         }
6706       else if (unformat (i, "del"))
6707         is_add = 0;
6708       else
6709         break;
6710     }
6711
6712   if (rx_sw_if_index_set == 0)
6713     {
6714       errmsg ("missing rx interface name or rx_sw_if_index");
6715       return -99;
6716     }
6717
6718   if (tx_sw_if_index_set == 0)
6719     {
6720       errmsg ("missing tx interface name or tx_sw_if_index");
6721       return -99;
6722     }
6723
6724   M (L2_PATCH_ADD_DEL, mp);
6725
6726   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
6727   mp->tx_sw_if_index = ntohl (tx_sw_if_index);
6728   mp->is_add = is_add;
6729
6730   S (mp);
6731   W (ret);
6732   return ret;
6733 }
6734
6735 u8 is_del;
6736 u8 localsid_addr[16];
6737 u8 end_psp;
6738 u8 behavior;
6739 u32 sw_if_index;
6740 u32 vlan_index;
6741 u32 fib_table;
6742 u8 nh_addr[16];
6743
6744 static int
6745 api_sr_localsid_add_del (vat_main_t * vam)
6746 {
6747   unformat_input_t *i = vam->input;
6748   vl_api_sr_localsid_add_del_t *mp;
6749
6750   u8 is_del;
6751   ip6_address_t localsid;
6752   u8 end_psp = 0;
6753   u8 behavior = ~0;
6754   u32 sw_if_index;
6755   u32 fib_table = ~(u32) 0;
6756   ip46_address_t nh_addr;
6757   clib_memset (&nh_addr, 0, sizeof (ip46_address_t));
6758
6759   bool nexthop_set = 0;
6760
6761   int ret;
6762
6763   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6764     {
6765       if (unformat (i, "del"))
6766         is_del = 1;
6767       else if (unformat (i, "address %U", unformat_ip6_address, &localsid));
6768       else if (unformat (i, "next-hop %U", unformat_ip46_address, &nh_addr))
6769         nexthop_set = 1;
6770       else if (unformat (i, "behavior %u", &behavior));
6771       else if (unformat (i, "sw_if_index %u", &sw_if_index));
6772       else if (unformat (i, "fib-table %u", &fib_table));
6773       else if (unformat (i, "end.psp %u", &behavior));
6774       else
6775         break;
6776     }
6777
6778   M (SR_LOCALSID_ADD_DEL, mp);
6779
6780   clib_memcpy (mp->localsid, &localsid, sizeof (mp->localsid));
6781
6782   if (nexthop_set)
6783     {
6784       clib_memcpy (&mp->nh_addr.un, &nh_addr, sizeof (mp->nh_addr.un));
6785     }
6786   mp->behavior = behavior;
6787   mp->sw_if_index = ntohl (sw_if_index);
6788   mp->fib_table = ntohl (fib_table);
6789   mp->end_psp = end_psp;
6790   mp->is_del = is_del;
6791
6792   S (mp);
6793   W (ret);
6794   return ret;
6795 }
6796
6797 static int
6798 api_ioam_enable (vat_main_t * vam)
6799 {
6800   unformat_input_t *input = vam->input;
6801   vl_api_ioam_enable_t *mp;
6802   u32 id = 0;
6803   int has_trace_option = 0;
6804   int has_pot_option = 0;
6805   int has_seqno_option = 0;
6806   int has_analyse_option = 0;
6807   int ret;
6808
6809   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6810     {
6811       if (unformat (input, "trace"))
6812         has_trace_option = 1;
6813       else if (unformat (input, "pot"))
6814         has_pot_option = 1;
6815       else if (unformat (input, "seqno"))
6816         has_seqno_option = 1;
6817       else if (unformat (input, "analyse"))
6818         has_analyse_option = 1;
6819       else
6820         break;
6821     }
6822   M (IOAM_ENABLE, mp);
6823   mp->id = htons (id);
6824   mp->seqno = has_seqno_option;
6825   mp->analyse = has_analyse_option;
6826   mp->pot_enable = has_pot_option;
6827   mp->trace_enable = has_trace_option;
6828
6829   S (mp);
6830   W (ret);
6831   return ret;
6832 }
6833
6834
6835 static int
6836 api_ioam_disable (vat_main_t * vam)
6837 {
6838   vl_api_ioam_disable_t *mp;
6839   int ret;
6840
6841   M (IOAM_DISABLE, mp);
6842   S (mp);
6843   W (ret);
6844   return ret;
6845 }
6846
6847 #define foreach_tcp_proto_field                 \
6848 _(src_port)                                     \
6849 _(dst_port)
6850
6851 #define foreach_udp_proto_field                 \
6852 _(src_port)                                     \
6853 _(dst_port)
6854
6855 #define foreach_ip4_proto_field                 \
6856 _(src_address)                                  \
6857 _(dst_address)                                  \
6858 _(tos)                                          \
6859 _(length)                                       \
6860 _(fragment_id)                                  \
6861 _(ttl)                                          \
6862 _(protocol)                                     \
6863 _(checksum)
6864
6865 typedef struct
6866 {
6867   u16 src_port, dst_port;
6868 } tcpudp_header_t;
6869
6870 #if VPP_API_TEST_BUILTIN == 0
6871 uword
6872 unformat_tcp_mask (unformat_input_t * input, va_list * args)
6873 {
6874   u8 **maskp = va_arg (*args, u8 **);
6875   u8 *mask = 0;
6876   u8 found_something = 0;
6877   tcp_header_t *tcp;
6878
6879 #define _(a) u8 a=0;
6880   foreach_tcp_proto_field;
6881 #undef _
6882
6883   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6884     {
6885       if (0);
6886 #define _(a) else if (unformat (input, #a)) a=1;
6887       foreach_tcp_proto_field
6888 #undef _
6889         else
6890         break;
6891     }
6892
6893 #define _(a) found_something += a;
6894   foreach_tcp_proto_field;
6895 #undef _
6896
6897   if (found_something == 0)
6898     return 0;
6899
6900   vec_validate (mask, sizeof (*tcp) - 1);
6901
6902   tcp = (tcp_header_t *) mask;
6903
6904 #define _(a) if (a) clib_memset (&tcp->a, 0xff, sizeof (tcp->a));
6905   foreach_tcp_proto_field;
6906 #undef _
6907
6908   *maskp = mask;
6909   return 1;
6910 }
6911
6912 uword
6913 unformat_udp_mask (unformat_input_t * input, va_list * args)
6914 {
6915   u8 **maskp = va_arg (*args, u8 **);
6916   u8 *mask = 0;
6917   u8 found_something = 0;
6918   udp_header_t *udp;
6919
6920 #define _(a) u8 a=0;
6921   foreach_udp_proto_field;
6922 #undef _
6923
6924   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6925     {
6926       if (0);
6927 #define _(a) else if (unformat (input, #a)) a=1;
6928       foreach_udp_proto_field
6929 #undef _
6930         else
6931         break;
6932     }
6933
6934 #define _(a) found_something += a;
6935   foreach_udp_proto_field;
6936 #undef _
6937
6938   if (found_something == 0)
6939     return 0;
6940
6941   vec_validate (mask, sizeof (*udp) - 1);
6942
6943   udp = (udp_header_t *) mask;
6944
6945 #define _(a) if (a) clib_memset (&udp->a, 0xff, sizeof (udp->a));
6946   foreach_udp_proto_field;
6947 #undef _
6948
6949   *maskp = mask;
6950   return 1;
6951 }
6952
6953 uword
6954 unformat_l4_mask (unformat_input_t * input, va_list * args)
6955 {
6956   u8 **maskp = va_arg (*args, u8 **);
6957   u16 src_port = 0, dst_port = 0;
6958   tcpudp_header_t *tcpudp;
6959
6960   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6961     {
6962       if (unformat (input, "tcp %U", unformat_tcp_mask, maskp))
6963         return 1;
6964       else if (unformat (input, "udp %U", unformat_udp_mask, maskp))
6965         return 1;
6966       else if (unformat (input, "src_port"))
6967         src_port = 0xFFFF;
6968       else if (unformat (input, "dst_port"))
6969         dst_port = 0xFFFF;
6970       else
6971         return 0;
6972     }
6973
6974   if (!src_port && !dst_port)
6975     return 0;
6976
6977   u8 *mask = 0;
6978   vec_validate (mask, sizeof (tcpudp_header_t) - 1);
6979
6980   tcpudp = (tcpudp_header_t *) mask;
6981   tcpudp->src_port = src_port;
6982   tcpudp->dst_port = dst_port;
6983
6984   *maskp = mask;
6985
6986   return 1;
6987 }
6988
6989 uword
6990 unformat_ip4_mask (unformat_input_t * input, va_list * args)
6991 {
6992   u8 **maskp = va_arg (*args, u8 **);
6993   u8 *mask = 0;
6994   u8 found_something = 0;
6995   ip4_header_t *ip;
6996
6997 #define _(a) u8 a=0;
6998   foreach_ip4_proto_field;
6999 #undef _
7000   u8 version = 0;
7001   u8 hdr_length = 0;
7002
7003
7004   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7005     {
7006       if (unformat (input, "version"))
7007         version = 1;
7008       else if (unformat (input, "hdr_length"))
7009         hdr_length = 1;
7010       else if (unformat (input, "src"))
7011         src_address = 1;
7012       else if (unformat (input, "dst"))
7013         dst_address = 1;
7014       else if (unformat (input, "proto"))
7015         protocol = 1;
7016
7017 #define _(a) else if (unformat (input, #a)) a=1;
7018       foreach_ip4_proto_field
7019 #undef _
7020         else
7021         break;
7022     }
7023
7024 #define _(a) found_something += a;
7025   foreach_ip4_proto_field;
7026 #undef _
7027
7028   if (found_something == 0)
7029     return 0;
7030
7031   vec_validate (mask, sizeof (*ip) - 1);
7032
7033   ip = (ip4_header_t *) mask;
7034
7035 #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
7036   foreach_ip4_proto_field;
7037 #undef _
7038
7039   ip->ip_version_and_header_length = 0;
7040
7041   if (version)
7042     ip->ip_version_and_header_length |= 0xF0;
7043
7044   if (hdr_length)
7045     ip->ip_version_and_header_length |= 0x0F;
7046
7047   *maskp = mask;
7048   return 1;
7049 }
7050
7051 #define foreach_ip6_proto_field                 \
7052 _(src_address)                                  \
7053 _(dst_address)                                  \
7054 _(payload_length)                               \
7055 _(hop_limit)                                    \
7056 _(protocol)
7057
7058 uword
7059 unformat_ip6_mask (unformat_input_t * input, va_list * args)
7060 {
7061   u8 **maskp = va_arg (*args, u8 **);
7062   u8 *mask = 0;
7063   u8 found_something = 0;
7064   ip6_header_t *ip;
7065   u32 ip_version_traffic_class_and_flow_label;
7066
7067 #define _(a) u8 a=0;
7068   foreach_ip6_proto_field;
7069 #undef _
7070   u8 version = 0;
7071   u8 traffic_class = 0;
7072   u8 flow_label = 0;
7073
7074   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7075     {
7076       if (unformat (input, "version"))
7077         version = 1;
7078       else if (unformat (input, "traffic-class"))
7079         traffic_class = 1;
7080       else if (unformat (input, "flow-label"))
7081         flow_label = 1;
7082       else if (unformat (input, "src"))
7083         src_address = 1;
7084       else if (unformat (input, "dst"))
7085         dst_address = 1;
7086       else if (unformat (input, "proto"))
7087         protocol = 1;
7088
7089 #define _(a) else if (unformat (input, #a)) a=1;
7090       foreach_ip6_proto_field
7091 #undef _
7092         else
7093         break;
7094     }
7095
7096 #define _(a) found_something += a;
7097   foreach_ip6_proto_field;
7098 #undef _
7099
7100   if (found_something == 0)
7101     return 0;
7102
7103   vec_validate (mask, sizeof (*ip) - 1);
7104
7105   ip = (ip6_header_t *) mask;
7106
7107 #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
7108   foreach_ip6_proto_field;
7109 #undef _
7110
7111   ip_version_traffic_class_and_flow_label = 0;
7112
7113   if (version)
7114     ip_version_traffic_class_and_flow_label |= 0xF0000000;
7115
7116   if (traffic_class)
7117     ip_version_traffic_class_and_flow_label |= 0x0FF00000;
7118
7119   if (flow_label)
7120     ip_version_traffic_class_and_flow_label |= 0x000FFFFF;
7121
7122   ip->ip_version_traffic_class_and_flow_label =
7123     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
7124
7125   *maskp = mask;
7126   return 1;
7127 }
7128
7129 uword
7130 unformat_l3_mask (unformat_input_t * input, va_list * args)
7131 {
7132   u8 **maskp = va_arg (*args, u8 **);
7133
7134   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7135     {
7136       if (unformat (input, "ip4 %U", unformat_ip4_mask, maskp))
7137         return 1;
7138       else if (unformat (input, "ip6 %U", unformat_ip6_mask, maskp))
7139         return 1;
7140       else
7141         break;
7142     }
7143   return 0;
7144 }
7145
7146 uword
7147 unformat_l2_mask (unformat_input_t * input, va_list * args)
7148 {
7149   u8 **maskp = va_arg (*args, u8 **);
7150   u8 *mask = 0;
7151   u8 src = 0;
7152   u8 dst = 0;
7153   u8 proto = 0;
7154   u8 tag1 = 0;
7155   u8 tag2 = 0;
7156   u8 ignore_tag1 = 0;
7157   u8 ignore_tag2 = 0;
7158   u8 cos1 = 0;
7159   u8 cos2 = 0;
7160   u8 dot1q = 0;
7161   u8 dot1ad = 0;
7162   int len = 14;
7163
7164   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7165     {
7166       if (unformat (input, "src"))
7167         src = 1;
7168       else if (unformat (input, "dst"))
7169         dst = 1;
7170       else if (unformat (input, "proto"))
7171         proto = 1;
7172       else if (unformat (input, "tag1"))
7173         tag1 = 1;
7174       else if (unformat (input, "tag2"))
7175         tag2 = 1;
7176       else if (unformat (input, "ignore-tag1"))
7177         ignore_tag1 = 1;
7178       else if (unformat (input, "ignore-tag2"))
7179         ignore_tag2 = 1;
7180       else if (unformat (input, "cos1"))
7181         cos1 = 1;
7182       else if (unformat (input, "cos2"))
7183         cos2 = 1;
7184       else if (unformat (input, "dot1q"))
7185         dot1q = 1;
7186       else if (unformat (input, "dot1ad"))
7187         dot1ad = 1;
7188       else
7189         break;
7190     }
7191   if ((src + dst + proto + tag1 + tag2 + dot1q + dot1ad +
7192        ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
7193     return 0;
7194
7195   if (tag1 || ignore_tag1 || cos1 || dot1q)
7196     len = 18;
7197   if (tag2 || ignore_tag2 || cos2 || dot1ad)
7198     len = 22;
7199
7200   vec_validate (mask, len - 1);
7201
7202   if (dst)
7203     clib_memset (mask, 0xff, 6);
7204
7205   if (src)
7206     clib_memset (mask + 6, 0xff, 6);
7207
7208   if (tag2 || dot1ad)
7209     {
7210       /* inner vlan tag */
7211       if (tag2)
7212         {
7213           mask[19] = 0xff;
7214           mask[18] = 0x0f;
7215         }
7216       if (cos2)
7217         mask[18] |= 0xe0;
7218       if (proto)
7219         mask[21] = mask[20] = 0xff;
7220       if (tag1)
7221         {
7222           mask[15] = 0xff;
7223           mask[14] = 0x0f;
7224         }
7225       if (cos1)
7226         mask[14] |= 0xe0;
7227       *maskp = mask;
7228       return 1;
7229     }
7230   if (tag1 | dot1q)
7231     {
7232       if (tag1)
7233         {
7234           mask[15] = 0xff;
7235           mask[14] = 0x0f;
7236         }
7237       if (cos1)
7238         mask[14] |= 0xe0;
7239       if (proto)
7240         mask[16] = mask[17] = 0xff;
7241
7242       *maskp = mask;
7243       return 1;
7244     }
7245   if (cos2)
7246     mask[18] |= 0xe0;
7247   if (cos1)
7248     mask[14] |= 0xe0;
7249   if (proto)
7250     mask[12] = mask[13] = 0xff;
7251
7252   *maskp = mask;
7253   return 1;
7254 }
7255
7256 uword
7257 unformat_classify_mask (unformat_input_t * input, va_list * args)
7258 {
7259   u8 **maskp = va_arg (*args, u8 **);
7260   u32 *skipp = va_arg (*args, u32 *);
7261   u32 *matchp = va_arg (*args, u32 *);
7262   u32 match;
7263   u8 *mask = 0;
7264   u8 *l2 = 0;
7265   u8 *l3 = 0;
7266   u8 *l4 = 0;
7267   int i;
7268
7269   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7270     {
7271       if (unformat (input, "hex %U", unformat_hex_string, &mask))
7272         ;
7273       else if (unformat (input, "l2 %U", unformat_l2_mask, &l2))
7274         ;
7275       else if (unformat (input, "l3 %U", unformat_l3_mask, &l3))
7276         ;
7277       else if (unformat (input, "l4 %U", unformat_l4_mask, &l4))
7278         ;
7279       else
7280         break;
7281     }
7282
7283   if (l4 && !l3)
7284     {
7285       vec_free (mask);
7286       vec_free (l2);
7287       vec_free (l4);
7288       return 0;
7289     }
7290
7291   if (mask || l2 || l3 || l4)
7292     {
7293       if (l2 || l3 || l4)
7294         {
7295           /* "With a free Ethernet header in every package" */
7296           if (l2 == 0)
7297             vec_validate (l2, 13);
7298           mask = l2;
7299           if (vec_len (l3))
7300             {
7301               vec_append (mask, l3);
7302               vec_free (l3);
7303             }
7304           if (vec_len (l4))
7305             {
7306               vec_append (mask, l4);
7307               vec_free (l4);
7308             }
7309         }
7310
7311       /* Scan forward looking for the first significant mask octet */
7312       for (i = 0; i < vec_len (mask); i++)
7313         if (mask[i])
7314           break;
7315
7316       /* compute (skip, match) params */
7317       *skipp = i / sizeof (u32x4);
7318       vec_delete (mask, *skipp * sizeof (u32x4), 0);
7319
7320       /* Pad mask to an even multiple of the vector size */
7321       while (vec_len (mask) % sizeof (u32x4))
7322         vec_add1 (mask, 0);
7323
7324       match = vec_len (mask) / sizeof (u32x4);
7325
7326       for (i = match * sizeof (u32x4); i > 0; i -= sizeof (u32x4))
7327         {
7328           u64 *tmp = (u64 *) (mask + (i - sizeof (u32x4)));
7329           if (*tmp || *(tmp + 1))
7330             break;
7331           match--;
7332         }
7333       if (match == 0)
7334         clib_warning ("BUG: match 0");
7335
7336       _vec_len (mask) = match * sizeof (u32x4);
7337
7338       *matchp = match;
7339       *maskp = mask;
7340
7341       return 1;
7342     }
7343
7344   return 0;
7345 }
7346 #endif /* VPP_API_TEST_BUILTIN */
7347
7348 #define foreach_l2_next                         \
7349 _(drop, DROP)                                   \
7350 _(ethernet, ETHERNET_INPUT)                     \
7351 _(ip4, IP4_INPUT)                               \
7352 _(ip6, IP6_INPUT)
7353
7354 uword
7355 unformat_l2_next_index (unformat_input_t * input, va_list * args)
7356 {
7357   u32 *miss_next_indexp = va_arg (*args, u32 *);
7358   u32 next_index = 0;
7359   u32 tmp;
7360
7361 #define _(n,N) \
7362   if (unformat (input, #n)) { next_index = L2_INPUT_CLASSIFY_NEXT_##N; goto out;}
7363   foreach_l2_next;
7364 #undef _
7365
7366   if (unformat (input, "%d", &tmp))
7367     {
7368       next_index = tmp;
7369       goto out;
7370     }
7371
7372   return 0;
7373
7374 out:
7375   *miss_next_indexp = next_index;
7376   return 1;
7377 }
7378
7379 #define foreach_ip_next                         \
7380 _(drop, DROP)                                   \
7381 _(local, LOCAL)                                 \
7382 _(rewrite, REWRITE)
7383
7384 uword
7385 api_unformat_ip_next_index (unformat_input_t * input, va_list * args)
7386 {
7387   u32 *miss_next_indexp = va_arg (*args, u32 *);
7388   u32 next_index = 0;
7389   u32 tmp;
7390
7391 #define _(n,N) \
7392   if (unformat (input, #n)) { next_index = IP_LOOKUP_NEXT_##N; goto out;}
7393   foreach_ip_next;
7394 #undef _
7395
7396   if (unformat (input, "%d", &tmp))
7397     {
7398       next_index = tmp;
7399       goto out;
7400     }
7401
7402   return 0;
7403
7404 out:
7405   *miss_next_indexp = next_index;
7406   return 1;
7407 }
7408
7409 #define foreach_acl_next                        \
7410 _(deny, DENY)
7411
7412 uword
7413 api_unformat_acl_next_index (unformat_input_t * input, va_list * args)
7414 {
7415   u32 *miss_next_indexp = va_arg (*args, u32 *);
7416   u32 next_index = 0;
7417   u32 tmp;
7418
7419 #define _(n,N) \
7420   if (unformat (input, #n)) { next_index = ACL_NEXT_INDEX_##N; goto out;}
7421   foreach_acl_next;
7422 #undef _
7423
7424   if (unformat (input, "permit"))
7425     {
7426       next_index = ~0;
7427       goto out;
7428     }
7429   else if (unformat (input, "%d", &tmp))
7430     {
7431       next_index = tmp;
7432       goto out;
7433     }
7434
7435   return 0;
7436
7437 out:
7438   *miss_next_indexp = next_index;
7439   return 1;
7440 }
7441
7442 uword
7443 unformat_policer_precolor (unformat_input_t * input, va_list * args)
7444 {
7445   u32 *r = va_arg (*args, u32 *);
7446
7447   if (unformat (input, "conform-color"))
7448     *r = POLICE_CONFORM;
7449   else if (unformat (input, "exceed-color"))
7450     *r = POLICE_EXCEED;
7451   else
7452     return 0;
7453
7454   return 1;
7455 }
7456
7457 #if VPP_API_TEST_BUILTIN == 0
7458 uword
7459 unformat_l4_match (unformat_input_t * input, va_list * args)
7460 {
7461   u8 **matchp = va_arg (*args, u8 **);
7462
7463   u8 *proto_header = 0;
7464   int src_port = 0;
7465   int dst_port = 0;
7466
7467   tcpudp_header_t h;
7468
7469   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7470     {
7471       if (unformat (input, "src_port %d", &src_port))
7472         ;
7473       else if (unformat (input, "dst_port %d", &dst_port))
7474         ;
7475       else
7476         return 0;
7477     }
7478
7479   h.src_port = clib_host_to_net_u16 (src_port);
7480   h.dst_port = clib_host_to_net_u16 (dst_port);
7481   vec_validate (proto_header, sizeof (h) - 1);
7482   memcpy (proto_header, &h, sizeof (h));
7483
7484   *matchp = proto_header;
7485
7486   return 1;
7487 }
7488
7489 uword
7490 unformat_ip4_match (unformat_input_t * input, va_list * args)
7491 {
7492   u8 **matchp = va_arg (*args, u8 **);
7493   u8 *match = 0;
7494   ip4_header_t *ip;
7495   int version = 0;
7496   u32 version_val;
7497   int hdr_length = 0;
7498   u32 hdr_length_val;
7499   int src = 0, dst = 0;
7500   ip4_address_t src_val, dst_val;
7501   int proto = 0;
7502   u32 proto_val;
7503   int tos = 0;
7504   u32 tos_val;
7505   int length = 0;
7506   u32 length_val;
7507   int fragment_id = 0;
7508   u32 fragment_id_val;
7509   int ttl = 0;
7510   int ttl_val;
7511   int checksum = 0;
7512   u32 checksum_val;
7513
7514   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7515     {
7516       if (unformat (input, "version %d", &version_val))
7517         version = 1;
7518       else if (unformat (input, "hdr_length %d", &hdr_length_val))
7519         hdr_length = 1;
7520       else if (unformat (input, "src %U", unformat_ip4_address, &src_val))
7521         src = 1;
7522       else if (unformat (input, "dst %U", unformat_ip4_address, &dst_val))
7523         dst = 1;
7524       else if (unformat (input, "proto %d", &proto_val))
7525         proto = 1;
7526       else if (unformat (input, "tos %d", &tos_val))
7527         tos = 1;
7528       else if (unformat (input, "length %d", &length_val))
7529         length = 1;
7530       else if (unformat (input, "fragment_id %d", &fragment_id_val))
7531         fragment_id = 1;
7532       else if (unformat (input, "ttl %d", &ttl_val))
7533         ttl = 1;
7534       else if (unformat (input, "checksum %d", &checksum_val))
7535         checksum = 1;
7536       else
7537         break;
7538     }
7539
7540   if (version + hdr_length + src + dst + proto + tos + length + fragment_id
7541       + ttl + checksum == 0)
7542     return 0;
7543
7544   /*
7545    * Aligned because we use the real comparison functions
7546    */
7547   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
7548
7549   ip = (ip4_header_t *) match;
7550
7551   /* These are realistically matched in practice */
7552   if (src)
7553     ip->src_address.as_u32 = src_val.as_u32;
7554
7555   if (dst)
7556     ip->dst_address.as_u32 = dst_val.as_u32;
7557
7558   if (proto)
7559     ip->protocol = proto_val;
7560
7561
7562   /* These are not, but they're included for completeness */
7563   if (version)
7564     ip->ip_version_and_header_length |= (version_val & 0xF) << 4;
7565
7566   if (hdr_length)
7567     ip->ip_version_and_header_length |= (hdr_length_val & 0xF);
7568
7569   if (tos)
7570     ip->tos = tos_val;
7571
7572   if (length)
7573     ip->length = clib_host_to_net_u16 (length_val);
7574
7575   if (ttl)
7576     ip->ttl = ttl_val;
7577
7578   if (checksum)
7579     ip->checksum = clib_host_to_net_u16 (checksum_val);
7580
7581   *matchp = match;
7582   return 1;
7583 }
7584
7585 uword
7586 unformat_ip6_match (unformat_input_t * input, va_list * args)
7587 {
7588   u8 **matchp = va_arg (*args, u8 **);
7589   u8 *match = 0;
7590   ip6_header_t *ip;
7591   int version = 0;
7592   u32 version_val;
7593   u8 traffic_class = 0;
7594   u32 traffic_class_val = 0;
7595   u8 flow_label = 0;
7596   u8 flow_label_val;
7597   int src = 0, dst = 0;
7598   ip6_address_t src_val, dst_val;
7599   int proto = 0;
7600   u32 proto_val;
7601   int payload_length = 0;
7602   u32 payload_length_val;
7603   int hop_limit = 0;
7604   int hop_limit_val;
7605   u32 ip_version_traffic_class_and_flow_label;
7606
7607   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7608     {
7609       if (unformat (input, "version %d", &version_val))
7610         version = 1;
7611       else if (unformat (input, "traffic_class %d", &traffic_class_val))
7612         traffic_class = 1;
7613       else if (unformat (input, "flow_label %d", &flow_label_val))
7614         flow_label = 1;
7615       else if (unformat (input, "src %U", unformat_ip6_address, &src_val))
7616         src = 1;
7617       else if (unformat (input, "dst %U", unformat_ip6_address, &dst_val))
7618         dst = 1;
7619       else if (unformat (input, "proto %d", &proto_val))
7620         proto = 1;
7621       else if (unformat (input, "payload_length %d", &payload_length_val))
7622         payload_length = 1;
7623       else if (unformat (input, "hop_limit %d", &hop_limit_val))
7624         hop_limit = 1;
7625       else
7626         break;
7627     }
7628
7629   if (version + traffic_class + flow_label + src + dst + proto +
7630       payload_length + hop_limit == 0)
7631     return 0;
7632
7633   /*
7634    * Aligned because we use the real comparison functions
7635    */
7636   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
7637
7638   ip = (ip6_header_t *) match;
7639
7640   if (src)
7641     clib_memcpy (&ip->src_address, &src_val, sizeof (ip->src_address));
7642
7643   if (dst)
7644     clib_memcpy (&ip->dst_address, &dst_val, sizeof (ip->dst_address));
7645
7646   if (proto)
7647     ip->protocol = proto_val;
7648
7649   ip_version_traffic_class_and_flow_label = 0;
7650
7651   if (version)
7652     ip_version_traffic_class_and_flow_label |= (version_val & 0xF) << 28;
7653
7654   if (traffic_class)
7655     ip_version_traffic_class_and_flow_label |=
7656       (traffic_class_val & 0xFF) << 20;
7657
7658   if (flow_label)
7659     ip_version_traffic_class_and_flow_label |= (flow_label_val & 0xFFFFF);
7660
7661   ip->ip_version_traffic_class_and_flow_label =
7662     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
7663
7664   if (payload_length)
7665     ip->payload_length = clib_host_to_net_u16 (payload_length_val);
7666
7667   if (hop_limit)
7668     ip->hop_limit = hop_limit_val;
7669
7670   *matchp = match;
7671   return 1;
7672 }
7673
7674 uword
7675 unformat_l3_match (unformat_input_t * input, va_list * args)
7676 {
7677   u8 **matchp = va_arg (*args, u8 **);
7678
7679   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7680     {
7681       if (unformat (input, "ip4 %U", unformat_ip4_match, matchp))
7682         return 1;
7683       else if (unformat (input, "ip6 %U", unformat_ip6_match, matchp))
7684         return 1;
7685       else
7686         break;
7687     }
7688   return 0;
7689 }
7690
7691 uword
7692 unformat_vlan_tag (unformat_input_t * input, va_list * args)
7693 {
7694   u8 *tagp = va_arg (*args, u8 *);
7695   u32 tag;
7696
7697   if (unformat (input, "%d", &tag))
7698     {
7699       tagp[0] = (tag >> 8) & 0x0F;
7700       tagp[1] = tag & 0xFF;
7701       return 1;
7702     }
7703
7704   return 0;
7705 }
7706
7707 uword
7708 unformat_l2_match (unformat_input_t * input, va_list * args)
7709 {
7710   u8 **matchp = va_arg (*args, u8 **);
7711   u8 *match = 0;
7712   u8 src = 0;
7713   u8 src_val[6];
7714   u8 dst = 0;
7715   u8 dst_val[6];
7716   u8 proto = 0;
7717   u16 proto_val;
7718   u8 tag1 = 0;
7719   u8 tag1_val[2];
7720   u8 tag2 = 0;
7721   u8 tag2_val[2];
7722   int len = 14;
7723   u8 ignore_tag1 = 0;
7724   u8 ignore_tag2 = 0;
7725   u8 cos1 = 0;
7726   u8 cos2 = 0;
7727   u32 cos1_val = 0;
7728   u32 cos2_val = 0;
7729
7730   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7731     {
7732       if (unformat (input, "src %U", unformat_ethernet_address, &src_val))
7733         src = 1;
7734       else
7735         if (unformat (input, "dst %U", unformat_ethernet_address, &dst_val))
7736         dst = 1;
7737       else if (unformat (input, "proto %U",
7738                          unformat_ethernet_type_host_byte_order, &proto_val))
7739         proto = 1;
7740       else if (unformat (input, "tag1 %U", unformat_vlan_tag, tag1_val))
7741         tag1 = 1;
7742       else if (unformat (input, "tag2 %U", unformat_vlan_tag, tag2_val))
7743         tag2 = 1;
7744       else if (unformat (input, "ignore-tag1"))
7745         ignore_tag1 = 1;
7746       else if (unformat (input, "ignore-tag2"))
7747         ignore_tag2 = 1;
7748       else if (unformat (input, "cos1 %d", &cos1_val))
7749         cos1 = 1;
7750       else if (unformat (input, "cos2 %d", &cos2_val))
7751         cos2 = 1;
7752       else
7753         break;
7754     }
7755   if ((src + dst + proto + tag1 + tag2 +
7756        ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
7757     return 0;
7758
7759   if (tag1 || ignore_tag1 || cos1)
7760     len = 18;
7761   if (tag2 || ignore_tag2 || cos2)
7762     len = 22;
7763
7764   vec_validate_aligned (match, len - 1, sizeof (u32x4));
7765
7766   if (dst)
7767     clib_memcpy (match, dst_val, 6);
7768
7769   if (src)
7770     clib_memcpy (match + 6, src_val, 6);
7771
7772   if (tag2)
7773     {
7774       /* inner vlan tag */
7775       match[19] = tag2_val[1];
7776       match[18] = tag2_val[0];
7777       if (cos2)
7778         match[18] |= (cos2_val & 0x7) << 5;
7779       if (proto)
7780         {
7781           match[21] = proto_val & 0xff;
7782           match[20] = proto_val >> 8;
7783         }
7784       if (tag1)
7785         {
7786           match[15] = tag1_val[1];
7787           match[14] = tag1_val[0];
7788         }
7789       if (cos1)
7790         match[14] |= (cos1_val & 0x7) << 5;
7791       *matchp = match;
7792       return 1;
7793     }
7794   if (tag1)
7795     {
7796       match[15] = tag1_val[1];
7797       match[14] = tag1_val[0];
7798       if (proto)
7799         {
7800           match[17] = proto_val & 0xff;
7801           match[16] = proto_val >> 8;
7802         }
7803       if (cos1)
7804         match[14] |= (cos1_val & 0x7) << 5;
7805
7806       *matchp = match;
7807       return 1;
7808     }
7809   if (cos2)
7810     match[18] |= (cos2_val & 0x7) << 5;
7811   if (cos1)
7812     match[14] |= (cos1_val & 0x7) << 5;
7813   if (proto)
7814     {
7815       match[13] = proto_val & 0xff;
7816       match[12] = proto_val >> 8;
7817     }
7818
7819   *matchp = match;
7820   return 1;
7821 }
7822
7823 uword
7824 unformat_qos_source (unformat_input_t * input, va_list * args)
7825 {
7826   int *qs = va_arg (*args, int *);
7827
7828   if (unformat (input, "ip"))
7829     *qs = QOS_SOURCE_IP;
7830   else if (unformat (input, "mpls"))
7831     *qs = QOS_SOURCE_MPLS;
7832   else if (unformat (input, "ext"))
7833     *qs = QOS_SOURCE_EXT;
7834   else if (unformat (input, "vlan"))
7835     *qs = QOS_SOURCE_VLAN;
7836   else
7837     return 0;
7838
7839   return 1;
7840 }
7841 #endif
7842
7843 uword
7844 api_unformat_classify_match (unformat_input_t * input, va_list * args)
7845 {
7846   u8 **matchp = va_arg (*args, u8 **);
7847   u32 skip_n_vectors = va_arg (*args, u32);
7848   u32 match_n_vectors = va_arg (*args, u32);
7849
7850   u8 *match = 0;
7851   u8 *l2 = 0;
7852   u8 *l3 = 0;
7853   u8 *l4 = 0;
7854
7855   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7856     {
7857       if (unformat (input, "hex %U", unformat_hex_string, &match))
7858         ;
7859       else if (unformat (input, "l2 %U", unformat_l2_match, &l2))
7860         ;
7861       else if (unformat (input, "l3 %U", unformat_l3_match, &l3))
7862         ;
7863       else if (unformat (input, "l4 %U", unformat_l4_match, &l4))
7864         ;
7865       else
7866         break;
7867     }
7868
7869   if (l4 && !l3)
7870     {
7871       vec_free (match);
7872       vec_free (l2);
7873       vec_free (l4);
7874       return 0;
7875     }
7876
7877   if (match || l2 || l3 || l4)
7878     {
7879       if (l2 || l3 || l4)
7880         {
7881           /* "Win a free Ethernet header in every packet" */
7882           if (l2 == 0)
7883             vec_validate_aligned (l2, 13, sizeof (u32x4));
7884           match = l2;
7885           if (vec_len (l3))
7886             {
7887               vec_append_aligned (match, l3, sizeof (u32x4));
7888               vec_free (l3);
7889             }
7890           if (vec_len (l4))
7891             {
7892               vec_append_aligned (match, l4, sizeof (u32x4));
7893               vec_free (l4);
7894             }
7895         }
7896
7897       /* Make sure the vector is big enough even if key is all 0's */
7898       vec_validate_aligned
7899         (match, ((match_n_vectors + skip_n_vectors) * sizeof (u32x4)) - 1,
7900          sizeof (u32x4));
7901
7902       /* Set size, include skipped vectors */
7903       _vec_len (match) = (match_n_vectors + skip_n_vectors) * sizeof (u32x4);
7904
7905       *matchp = match;
7906
7907       return 1;
7908     }
7909
7910   return 0;
7911 }
7912
7913 static int
7914 api_set_ipfix_exporter (vat_main_t *vam)
7915 {
7916   unformat_input_t *i = vam->input;
7917   vl_api_set_ipfix_exporter_t *mp;
7918   ip4_address_t collector_address;
7919   u8 collector_address_set = 0;
7920   u32 collector_port = ~0;
7921   ip4_address_t src_address;
7922   u8 src_address_set = 0;
7923   u32 vrf_id = ~0;
7924   u32 path_mtu = ~0;
7925   u32 template_interval = ~0;
7926   u8 udp_checksum = 0;
7927   int ret;
7928
7929   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7930     {
7931       if (unformat (i, "collector_address %U", unformat_ip4_address,
7932                     &collector_address))
7933         collector_address_set = 1;
7934       else if (unformat (i, "collector_port %d", &collector_port))
7935         ;
7936       else if (unformat (i, "src_address %U", unformat_ip4_address,
7937                          &src_address))
7938         src_address_set = 1;
7939       else if (unformat (i, "vrf_id %d", &vrf_id))
7940         ;
7941       else if (unformat (i, "path_mtu %d", &path_mtu))
7942         ;
7943       else if (unformat (i, "template_interval %d", &template_interval))
7944         ;
7945       else if (unformat (i, "udp_checksum"))
7946         udp_checksum = 1;
7947       else
7948         break;
7949     }
7950
7951   if (collector_address_set == 0)
7952     {
7953       errmsg ("collector_address required");
7954       return -99;
7955     }
7956
7957   if (src_address_set == 0)
7958     {
7959       errmsg ("src_address required");
7960       return -99;
7961     }
7962
7963   M (SET_IPFIX_EXPORTER, mp);
7964
7965   memcpy (mp->collector_address.un.ip4, collector_address.data,
7966           sizeof (collector_address.data));
7967   mp->collector_port = htons ((u16) collector_port);
7968   memcpy (mp->src_address.un.ip4, src_address.data,
7969           sizeof (src_address.data));
7970   mp->vrf_id = htonl (vrf_id);
7971   mp->path_mtu = htonl (path_mtu);
7972   mp->template_interval = htonl (template_interval);
7973   mp->udp_checksum = udp_checksum;
7974
7975   S (mp);
7976   W (ret);
7977   return ret;
7978 }
7979
7980 static int
7981 api_set_ipfix_classify_stream (vat_main_t * vam)
7982 {
7983   unformat_input_t *i = vam->input;
7984   vl_api_set_ipfix_classify_stream_t *mp;
7985   u32 domain_id = 0;
7986   u32 src_port = UDP_DST_PORT_ipfix;
7987   int ret;
7988
7989   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7990     {
7991       if (unformat (i, "domain %d", &domain_id))
7992         ;
7993       else if (unformat (i, "src_port %d", &src_port))
7994         ;
7995       else
7996         {
7997           errmsg ("unknown input `%U'", format_unformat_error, i);
7998           return -99;
7999         }
8000     }
8001
8002   M (SET_IPFIX_CLASSIFY_STREAM, mp);
8003
8004   mp->domain_id = htonl (domain_id);
8005   mp->src_port = htons ((u16) src_port);
8006
8007   S (mp);
8008   W (ret);
8009   return ret;
8010 }
8011
8012 static int
8013 api_ipfix_classify_table_add_del (vat_main_t * vam)
8014 {
8015   unformat_input_t *i = vam->input;
8016   vl_api_ipfix_classify_table_add_del_t *mp;
8017   int is_add = -1;
8018   u32 classify_table_index = ~0;
8019   u8 ip_version = 0;
8020   u8 transport_protocol = 255;
8021   int ret;
8022
8023   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8024     {
8025       if (unformat (i, "add"))
8026         is_add = 1;
8027       else if (unformat (i, "del"))
8028         is_add = 0;
8029       else if (unformat (i, "table %d", &classify_table_index))
8030         ;
8031       else if (unformat (i, "ip4"))
8032         ip_version = 4;
8033       else if (unformat (i, "ip6"))
8034         ip_version = 6;
8035       else if (unformat (i, "tcp"))
8036         transport_protocol = 6;
8037       else if (unformat (i, "udp"))
8038         transport_protocol = 17;
8039       else
8040         {
8041           errmsg ("unknown input `%U'", format_unformat_error, i);
8042           return -99;
8043         }
8044     }
8045
8046   if (is_add == -1)
8047     {
8048       errmsg ("expecting: add|del");
8049       return -99;
8050     }
8051   if (classify_table_index == ~0)
8052     {
8053       errmsg ("classifier table not specified");
8054       return -99;
8055     }
8056   if (ip_version == 0)
8057     {
8058       errmsg ("IP version not specified");
8059       return -99;
8060     }
8061
8062   M (IPFIX_CLASSIFY_TABLE_ADD_DEL, mp);
8063
8064   mp->is_add = is_add;
8065   mp->table_id = htonl (classify_table_index);
8066   mp->ip_version = ip_version;
8067   mp->transport_protocol = transport_protocol;
8068
8069   S (mp);
8070   W (ret);
8071   return ret;
8072 }
8073
8074 static int
8075 api_get_node_index (vat_main_t * vam)
8076 {
8077   unformat_input_t *i = vam->input;
8078   vl_api_get_node_index_t *mp;
8079   u8 *name = 0;
8080   int ret;
8081
8082   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8083     {
8084       if (unformat (i, "node %s", &name))
8085         ;
8086       else
8087         break;
8088     }
8089   if (name == 0)
8090     {
8091       errmsg ("node name required");
8092       return -99;
8093     }
8094   if (vec_len (name) >= ARRAY_LEN (mp->node_name))
8095     {
8096       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
8097       return -99;
8098     }
8099
8100   M (GET_NODE_INDEX, mp);
8101   clib_memcpy (mp->node_name, name, vec_len (name));
8102   vec_free (name);
8103
8104   S (mp);
8105   W (ret);
8106   return ret;
8107 }
8108
8109 static int
8110 api_get_next_index (vat_main_t * vam)
8111 {
8112   unformat_input_t *i = vam->input;
8113   vl_api_get_next_index_t *mp;
8114   u8 *node_name = 0, *next_node_name = 0;
8115   int ret;
8116
8117   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8118     {
8119       if (unformat (i, "node-name %s", &node_name))
8120         ;
8121       else if (unformat (i, "next-node-name %s", &next_node_name))
8122         break;
8123     }
8124
8125   if (node_name == 0)
8126     {
8127       errmsg ("node name required");
8128       return -99;
8129     }
8130   if (vec_len (node_name) >= ARRAY_LEN (mp->node_name))
8131     {
8132       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
8133       return -99;
8134     }
8135
8136   if (next_node_name == 0)
8137     {
8138       errmsg ("next node name required");
8139       return -99;
8140     }
8141   if (vec_len (next_node_name) >= ARRAY_LEN (mp->next_name))
8142     {
8143       errmsg ("next node name too long, max %d", ARRAY_LEN (mp->next_name));
8144       return -99;
8145     }
8146
8147   M (GET_NEXT_INDEX, mp);
8148   clib_memcpy (mp->node_name, node_name, vec_len (node_name));
8149   clib_memcpy (mp->next_name, next_node_name, vec_len (next_node_name));
8150   vec_free (node_name);
8151   vec_free (next_node_name);
8152
8153   S (mp);
8154   W (ret);
8155   return ret;
8156 }
8157
8158 static int
8159 api_add_node_next (vat_main_t * vam)
8160 {
8161   unformat_input_t *i = vam->input;
8162   vl_api_add_node_next_t *mp;
8163   u8 *name = 0;
8164   u8 *next = 0;
8165   int ret;
8166
8167   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8168     {
8169       if (unformat (i, "node %s", &name))
8170         ;
8171       else if (unformat (i, "next %s", &next))
8172         ;
8173       else
8174         break;
8175     }
8176   if (name == 0)
8177     {
8178       errmsg ("node name required");
8179       return -99;
8180     }
8181   if (vec_len (name) >= ARRAY_LEN (mp->node_name))
8182     {
8183       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
8184       return -99;
8185     }
8186   if (next == 0)
8187     {
8188       errmsg ("next node required");
8189       return -99;
8190     }
8191   if (vec_len (next) >= ARRAY_LEN (mp->next_name))
8192     {
8193       errmsg ("next name too long, max %d", ARRAY_LEN (mp->next_name));
8194       return -99;
8195     }
8196
8197   M (ADD_NODE_NEXT, mp);
8198   clib_memcpy (mp->node_name, name, vec_len (name));
8199   clib_memcpy (mp->next_name, next, vec_len (next));
8200   vec_free (name);
8201   vec_free (next);
8202
8203   S (mp);
8204   W (ret);
8205   return ret;
8206 }
8207
8208 static void vl_api_sw_interface_tap_v2_details_t_handler
8209   (vl_api_sw_interface_tap_v2_details_t * mp)
8210 {
8211   vat_main_t *vam = &vat_main;
8212
8213   u8 *ip4 =
8214     format (0, "%U/%d", format_ip4_address, mp->host_ip4_prefix.address,
8215             mp->host_ip4_prefix.len);
8216   u8 *ip6 =
8217     format (0, "%U/%d", format_ip6_address, mp->host_ip6_prefix.address,
8218             mp->host_ip6_prefix.len);
8219
8220   print (vam->ofp,
8221          "\n%-16s %-12d %-5d %-12d %-12d %-14U %-30s %-20s %-20s %-30s 0x%-08x",
8222          mp->dev_name, ntohl (mp->sw_if_index), ntohl (mp->id),
8223          ntohs (mp->rx_ring_sz), ntohs (mp->tx_ring_sz),
8224          format_ethernet_address, mp->host_mac_addr, mp->host_namespace,
8225          mp->host_bridge, ip4, ip6, ntohl (mp->tap_flags));
8226
8227   vec_free (ip4);
8228   vec_free (ip6);
8229 }
8230
8231 static void vl_api_sw_interface_tap_v2_details_t_handler_json
8232   (vl_api_sw_interface_tap_v2_details_t * mp)
8233 {
8234   vat_main_t *vam = &vat_main;
8235   vat_json_node_t *node = NULL;
8236
8237   if (VAT_JSON_ARRAY != vam->json_tree.type)
8238     {
8239       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
8240       vat_json_init_array (&vam->json_tree);
8241     }
8242   node = vat_json_array_add (&vam->json_tree);
8243
8244   vat_json_init_object (node);
8245   vat_json_object_add_uint (node, "id", ntohl (mp->id));
8246   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
8247   vat_json_object_add_uint (node, "tap_flags", ntohl (mp->tap_flags));
8248   vat_json_object_add_string_copy (node, "dev_name", mp->dev_name);
8249   vat_json_object_add_uint (node, "rx_ring_sz", ntohs (mp->rx_ring_sz));
8250   vat_json_object_add_uint (node, "tx_ring_sz", ntohs (mp->tx_ring_sz));
8251   vat_json_object_add_string_copy (node, "host_mac_addr",
8252                                    format (0, "%U", format_ethernet_address,
8253                                            &mp->host_mac_addr));
8254   vat_json_object_add_string_copy (node, "host_namespace",
8255                                    mp->host_namespace);
8256   vat_json_object_add_string_copy (node, "host_bridge", mp->host_bridge);
8257   vat_json_object_add_string_copy (node, "host_ip4_addr",
8258                                    format (0, "%U/%d", format_ip4_address,
8259                                            mp->host_ip4_prefix.address,
8260                                            mp->host_ip4_prefix.len));
8261   vat_json_object_add_string_copy (node, "host_ip6_prefix",
8262                                    format (0, "%U/%d", format_ip6_address,
8263                                            mp->host_ip6_prefix.address,
8264                                            mp->host_ip6_prefix.len));
8265
8266 }
8267
8268 static int
8269 api_sw_interface_tap_v2_dump (vat_main_t * vam)
8270 {
8271   vl_api_sw_interface_tap_v2_dump_t *mp;
8272   vl_api_control_ping_t *mp_ping;
8273   int ret;
8274
8275   print (vam->ofp,
8276          "\n%-16s %-12s %-5s %-12s %-12s %-14s %-30s %-20s %-20s %-30s",
8277          "dev_name", "sw_if_index", "id", "rx_ring_sz", "tx_ring_sz",
8278          "host_mac_addr", "host_namespace", "host_bridge", "host_ip4_addr",
8279          "host_ip6_addr");
8280
8281   /* Get list of tap interfaces */
8282   M (SW_INTERFACE_TAP_V2_DUMP, mp);
8283   S (mp);
8284
8285   /* Use a control ping for synchronization */
8286   MPING (CONTROL_PING, mp_ping);
8287   S (mp_ping);
8288
8289   W (ret);
8290   return ret;
8291 }
8292
8293 static void vl_api_sw_interface_virtio_pci_details_t_handler
8294   (vl_api_sw_interface_virtio_pci_details_t * mp)
8295 {
8296   vat_main_t *vam = &vat_main;
8297
8298   typedef union
8299   {
8300     struct
8301     {
8302       u16 domain;
8303       u8 bus;
8304       u8 slot:5;
8305       u8 function:3;
8306     };
8307     u32 as_u32;
8308   } pci_addr_t;
8309   pci_addr_t addr;
8310
8311   addr.domain = ntohs (mp->pci_addr.domain);
8312   addr.bus = mp->pci_addr.bus;
8313   addr.slot = mp->pci_addr.slot;
8314   addr.function = mp->pci_addr.function;
8315
8316   u8 *pci_addr = format (0, "%04x:%02x:%02x.%x", addr.domain, addr.bus,
8317                          addr.slot, addr.function);
8318
8319   print (vam->ofp,
8320          "\n%-12s %-12d %-12d %-12d %-17U 0x%-08llx",
8321          pci_addr, ntohl (mp->sw_if_index),
8322          ntohs (mp->rx_ring_sz), ntohs (mp->tx_ring_sz),
8323          format_ethernet_address, mp->mac_addr,
8324          clib_net_to_host_u64 (mp->features));
8325   vec_free (pci_addr);
8326 }
8327
8328 static void vl_api_sw_interface_virtio_pci_details_t_handler_json
8329   (vl_api_sw_interface_virtio_pci_details_t * mp)
8330 {
8331   vat_main_t *vam = &vat_main;
8332   vat_json_node_t *node = NULL;
8333   vlib_pci_addr_t pci_addr;
8334
8335   if (VAT_JSON_ARRAY != vam->json_tree.type)
8336     {
8337       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
8338       vat_json_init_array (&vam->json_tree);
8339     }
8340   node = vat_json_array_add (&vam->json_tree);
8341
8342   pci_addr.domain = ntohs (mp->pci_addr.domain);
8343   pci_addr.bus = mp->pci_addr.bus;
8344   pci_addr.slot = mp->pci_addr.slot;
8345   pci_addr.function = mp->pci_addr.function;
8346
8347   vat_json_init_object (node);
8348   vat_json_object_add_uint (node, "pci-addr", pci_addr.as_u32);
8349   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
8350   vat_json_object_add_uint (node, "rx_ring_sz", ntohs (mp->rx_ring_sz));
8351   vat_json_object_add_uint (node, "tx_ring_sz", ntohs (mp->tx_ring_sz));
8352   vat_json_object_add_uint (node, "features",
8353                             clib_net_to_host_u64 (mp->features));
8354   vat_json_object_add_string_copy (node, "mac_addr",
8355                                    format (0, "%U", format_ethernet_address,
8356                                            &mp->mac_addr));
8357 }
8358
8359 static int
8360 api_sw_interface_virtio_pci_dump (vat_main_t * vam)
8361 {
8362   vl_api_sw_interface_virtio_pci_dump_t *mp;
8363   vl_api_control_ping_t *mp_ping;
8364   int ret;
8365
8366   print (vam->ofp,
8367          "\n%-12s %-12s %-12s %-12s %-17s %-08s",
8368          "pci_addr", "sw_if_index", "rx_ring_sz", "tx_ring_sz",
8369          "mac_addr", "features");
8370
8371   /* Get list of tap interfaces */
8372   M (SW_INTERFACE_VIRTIO_PCI_DUMP, mp);
8373   S (mp);
8374
8375   /* Use a control ping for synchronization */
8376   MPING (CONTROL_PING, mp_ping);
8377   S (mp_ping);
8378
8379   W (ret);
8380   return ret;
8381 }
8382
8383 static int
8384 api_l2_fib_clear_table (vat_main_t * vam)
8385 {
8386 //  unformat_input_t * i = vam->input;
8387   vl_api_l2_fib_clear_table_t *mp;
8388   int ret;
8389
8390   M (L2_FIB_CLEAR_TABLE, mp);
8391
8392   S (mp);
8393   W (ret);
8394   return ret;
8395 }
8396
8397 static int
8398 api_l2_interface_efp_filter (vat_main_t * vam)
8399 {
8400   unformat_input_t *i = vam->input;
8401   vl_api_l2_interface_efp_filter_t *mp;
8402   u32 sw_if_index;
8403   u8 enable = 1;
8404   u8 sw_if_index_set = 0;
8405   int ret;
8406
8407   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8408     {
8409       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8410         sw_if_index_set = 1;
8411       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8412         sw_if_index_set = 1;
8413       else if (unformat (i, "enable"))
8414         enable = 1;
8415       else if (unformat (i, "disable"))
8416         enable = 0;
8417       else
8418         {
8419           clib_warning ("parse error '%U'", format_unformat_error, i);
8420           return -99;
8421         }
8422     }
8423
8424   if (sw_if_index_set == 0)
8425     {
8426       errmsg ("missing sw_if_index");
8427       return -99;
8428     }
8429
8430   M (L2_INTERFACE_EFP_FILTER, mp);
8431
8432   mp->sw_if_index = ntohl (sw_if_index);
8433   mp->enable_disable = enable;
8434
8435   S (mp);
8436   W (ret);
8437   return ret;
8438 }
8439
8440 #define foreach_vtr_op                          \
8441 _("disable",  L2_VTR_DISABLED)                  \
8442 _("push-1",  L2_VTR_PUSH_1)                     \
8443 _("push-2",  L2_VTR_PUSH_2)                     \
8444 _("pop-1",  L2_VTR_POP_1)                       \
8445 _("pop-2",  L2_VTR_POP_2)                       \
8446 _("translate-1-1",  L2_VTR_TRANSLATE_1_1)       \
8447 _("translate-1-2",  L2_VTR_TRANSLATE_1_2)       \
8448 _("translate-2-1",  L2_VTR_TRANSLATE_2_1)       \
8449 _("translate-2-2",  L2_VTR_TRANSLATE_2_2)
8450
8451 static int
8452 api_l2_interface_vlan_tag_rewrite (vat_main_t * vam)
8453 {
8454   unformat_input_t *i = vam->input;
8455   vl_api_l2_interface_vlan_tag_rewrite_t *mp;
8456   u32 sw_if_index;
8457   u8 sw_if_index_set = 0;
8458   u8 vtr_op_set = 0;
8459   u32 vtr_op = 0;
8460   u32 push_dot1q = 1;
8461   u32 tag1 = ~0;
8462   u32 tag2 = ~0;
8463   int ret;
8464
8465   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8466     {
8467       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8468         sw_if_index_set = 1;
8469       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8470         sw_if_index_set = 1;
8471       else if (unformat (i, "vtr_op %d", &vtr_op))
8472         vtr_op_set = 1;
8473 #define _(n,v) else if (unformat(i, n)) {vtr_op = v; vtr_op_set = 1;}
8474       foreach_vtr_op
8475 #undef _
8476         else if (unformat (i, "push_dot1q %d", &push_dot1q))
8477         ;
8478       else if (unformat (i, "tag1 %d", &tag1))
8479         ;
8480       else if (unformat (i, "tag2 %d", &tag2))
8481         ;
8482       else
8483         {
8484           clib_warning ("parse error '%U'", format_unformat_error, i);
8485           return -99;
8486         }
8487     }
8488
8489   if ((sw_if_index_set == 0) || (vtr_op_set == 0))
8490     {
8491       errmsg ("missing vtr operation or sw_if_index");
8492       return -99;
8493     }
8494
8495   M (L2_INTERFACE_VLAN_TAG_REWRITE, mp);
8496   mp->sw_if_index = ntohl (sw_if_index);
8497   mp->vtr_op = ntohl (vtr_op);
8498   mp->push_dot1q = ntohl (push_dot1q);
8499   mp->tag1 = ntohl (tag1);
8500   mp->tag2 = ntohl (tag2);
8501
8502   S (mp);
8503   W (ret);
8504   return ret;
8505 }
8506
8507 static int
8508 api_create_vhost_user_if (vat_main_t * vam)
8509 {
8510   unformat_input_t *i = vam->input;
8511   vl_api_create_vhost_user_if_t *mp;
8512   u8 *file_name;
8513   u8 is_server = 0;
8514   u8 file_name_set = 0;
8515   u32 custom_dev_instance = ~0;
8516   u8 hwaddr[6];
8517   u8 use_custom_mac = 0;
8518   u8 disable_mrg_rxbuf = 0;
8519   u8 disable_indirect_desc = 0;
8520   u8 *tag = 0;
8521   u8 enable_gso = 0;
8522   u8 enable_packed = 0;
8523   int ret;
8524
8525   /* Shut up coverity */
8526   clib_memset (hwaddr, 0, sizeof (hwaddr));
8527
8528   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8529     {
8530       if (unformat (i, "socket %s", &file_name))
8531         {
8532           file_name_set = 1;
8533         }
8534       else if (unformat (i, "renumber %" PRIu32, &custom_dev_instance))
8535         ;
8536       else if (unformat (i, "mac %U", unformat_ethernet_address, hwaddr))
8537         use_custom_mac = 1;
8538       else if (unformat (i, "server"))
8539         is_server = 1;
8540       else if (unformat (i, "disable_mrg_rxbuf"))
8541         disable_mrg_rxbuf = 1;
8542       else if (unformat (i, "disable_indirect_desc"))
8543         disable_indirect_desc = 1;
8544       else if (unformat (i, "gso"))
8545         enable_gso = 1;
8546       else if (unformat (i, "packed"))
8547         enable_packed = 1;
8548       else if (unformat (i, "tag %s", &tag))
8549         ;
8550       else
8551         break;
8552     }
8553
8554   if (file_name_set == 0)
8555     {
8556       errmsg ("missing socket file name");
8557       return -99;
8558     }
8559
8560   if (vec_len (file_name) > 255)
8561     {
8562       errmsg ("socket file name too long");
8563       return -99;
8564     }
8565   vec_add1 (file_name, 0);
8566
8567   M (CREATE_VHOST_USER_IF, mp);
8568
8569   mp->is_server = is_server;
8570   mp->disable_mrg_rxbuf = disable_mrg_rxbuf;
8571   mp->disable_indirect_desc = disable_indirect_desc;
8572   mp->enable_gso = enable_gso;
8573   mp->enable_packed = enable_packed;
8574   mp->custom_dev_instance = ntohl (custom_dev_instance);
8575   clib_memcpy (mp->sock_filename, file_name, vec_len (file_name));
8576   vec_free (file_name);
8577   if (custom_dev_instance != ~0)
8578     mp->renumber = 1;
8579
8580   mp->use_custom_mac = use_custom_mac;
8581   clib_memcpy (mp->mac_address, hwaddr, 6);
8582   if (tag)
8583     strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
8584   vec_free (tag);
8585
8586   S (mp);
8587   W (ret);
8588   return ret;
8589 }
8590
8591 static int
8592 api_modify_vhost_user_if (vat_main_t * vam)
8593 {
8594   unformat_input_t *i = vam->input;
8595   vl_api_modify_vhost_user_if_t *mp;
8596   u8 *file_name;
8597   u8 is_server = 0;
8598   u8 file_name_set = 0;
8599   u32 custom_dev_instance = ~0;
8600   u8 sw_if_index_set = 0;
8601   u32 sw_if_index = (u32) ~ 0;
8602   u8 enable_gso = 0;
8603   u8 enable_packed = 0;
8604   int ret;
8605
8606   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8607     {
8608       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8609         sw_if_index_set = 1;
8610       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8611         sw_if_index_set = 1;
8612       else if (unformat (i, "socket %s", &file_name))
8613         {
8614           file_name_set = 1;
8615         }
8616       else if (unformat (i, "renumber %" PRIu32, &custom_dev_instance))
8617         ;
8618       else if (unformat (i, "server"))
8619         is_server = 1;
8620       else if (unformat (i, "gso"))
8621         enable_gso = 1;
8622       else if (unformat (i, "packed"))
8623         enable_packed = 1;
8624       else
8625         break;
8626     }
8627
8628   if (sw_if_index_set == 0)
8629     {
8630       errmsg ("missing sw_if_index or interface name");
8631       return -99;
8632     }
8633
8634   if (file_name_set == 0)
8635     {
8636       errmsg ("missing socket file name");
8637       return -99;
8638     }
8639
8640   if (vec_len (file_name) > 255)
8641     {
8642       errmsg ("socket file name too long");
8643       return -99;
8644     }
8645   vec_add1 (file_name, 0);
8646
8647   M (MODIFY_VHOST_USER_IF, mp);
8648
8649   mp->sw_if_index = ntohl (sw_if_index);
8650   mp->is_server = is_server;
8651   mp->enable_gso = enable_gso;
8652   mp->enable_packed = enable_packed;
8653   mp->custom_dev_instance = ntohl (custom_dev_instance);
8654   clib_memcpy (mp->sock_filename, file_name, vec_len (file_name));
8655   vec_free (file_name);
8656   if (custom_dev_instance != ~0)
8657     mp->renumber = 1;
8658
8659   S (mp);
8660   W (ret);
8661   return ret;
8662 }
8663
8664 static int
8665 api_create_vhost_user_if_v2 (vat_main_t * vam)
8666 {
8667   unformat_input_t *i = vam->input;
8668   vl_api_create_vhost_user_if_v2_t *mp;
8669   u8 *file_name;
8670   u8 is_server = 0;
8671   u8 file_name_set = 0;
8672   u32 custom_dev_instance = ~0;
8673   u8 hwaddr[6];
8674   u8 use_custom_mac = 0;
8675   u8 disable_mrg_rxbuf = 0;
8676   u8 disable_indirect_desc = 0;
8677   u8 *tag = 0;
8678   u8 enable_gso = 0;
8679   u8 enable_packed = 0;
8680   u8 enable_event_idx = 0;
8681   int ret;
8682
8683   /* Shut up coverity */
8684   clib_memset (hwaddr, 0, sizeof (hwaddr));
8685
8686   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8687     {
8688       if (unformat (i, "socket %s", &file_name))
8689         {
8690           file_name_set = 1;
8691         }
8692       else if (unformat (i, "renumber %" PRIu32, &custom_dev_instance))
8693         ;
8694       else if (unformat (i, "mac %U", unformat_ethernet_address, hwaddr))
8695         use_custom_mac = 1;
8696       else if (unformat (i, "server"))
8697         is_server = 1;
8698       else if (unformat (i, "disable_mrg_rxbuf"))
8699         disable_mrg_rxbuf = 1;
8700       else if (unformat (i, "disable_indirect_desc"))
8701         disable_indirect_desc = 1;
8702       else if (unformat (i, "gso"))
8703         enable_gso = 1;
8704       else if (unformat (i, "packed"))
8705         enable_packed = 1;
8706       else if (unformat (i, "event-idx"))
8707         enable_event_idx = 1;
8708       else if (unformat (i, "tag %s", &tag))
8709         ;
8710       else
8711         break;
8712     }
8713
8714   if (file_name_set == 0)
8715     {
8716       errmsg ("missing socket file name");
8717       return -99;
8718     }
8719
8720   if (vec_len (file_name) > 255)
8721     {
8722       errmsg ("socket file name too long");
8723       return -99;
8724     }
8725   vec_add1 (file_name, 0);
8726
8727   M (CREATE_VHOST_USER_IF_V2, mp);
8728
8729   mp->is_server = is_server;
8730   mp->disable_mrg_rxbuf = disable_mrg_rxbuf;
8731   mp->disable_indirect_desc = disable_indirect_desc;
8732   mp->enable_gso = enable_gso;
8733   mp->enable_packed = enable_packed;
8734   mp->enable_event_idx = enable_event_idx;
8735   mp->custom_dev_instance = ntohl (custom_dev_instance);
8736   clib_memcpy (mp->sock_filename, file_name, vec_len (file_name));
8737   vec_free (file_name);
8738   if (custom_dev_instance != ~0)
8739     mp->renumber = 1;
8740
8741   mp->use_custom_mac = use_custom_mac;
8742   clib_memcpy (mp->mac_address, hwaddr, 6);
8743   if (tag)
8744     strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
8745   vec_free (tag);
8746
8747   S (mp);
8748   W (ret);
8749   return ret;
8750 }
8751
8752 static int
8753 api_modify_vhost_user_if_v2 (vat_main_t * vam)
8754 {
8755   unformat_input_t *i = vam->input;
8756   vl_api_modify_vhost_user_if_v2_t *mp;
8757   u8 *file_name;
8758   u8 is_server = 0;
8759   u8 file_name_set = 0;
8760   u32 custom_dev_instance = ~0;
8761   u8 sw_if_index_set = 0;
8762   u32 sw_if_index = (u32) ~ 0;
8763   u8 enable_gso = 0;
8764   u8 enable_packed = 0;
8765   u8 enable_event_idx = 0;
8766   int ret;
8767
8768   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8769     {
8770       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8771         sw_if_index_set = 1;
8772       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8773         sw_if_index_set = 1;
8774       else if (unformat (i, "socket %s", &file_name))
8775         {
8776           file_name_set = 1;
8777         }
8778       else if (unformat (i, "renumber %" PRIu32, &custom_dev_instance))
8779         ;
8780       else if (unformat (i, "server"))
8781         is_server = 1;
8782       else if (unformat (i, "gso"))
8783         enable_gso = 1;
8784       else if (unformat (i, "packed"))
8785         enable_packed = 1;
8786       else if (unformat (i, "event-idx"))
8787         enable_event_idx = 1;
8788       else
8789         break;
8790     }
8791
8792   if (sw_if_index_set == 0)
8793     {
8794       errmsg ("missing sw_if_index or interface name");
8795       return -99;
8796     }
8797
8798   if (file_name_set == 0)
8799     {
8800       errmsg ("missing socket file name");
8801       return -99;
8802     }
8803
8804   if (vec_len (file_name) > 255)
8805     {
8806       errmsg ("socket file name too long");
8807       return -99;
8808     }
8809   vec_add1 (file_name, 0);
8810
8811   M (MODIFY_VHOST_USER_IF_V2, mp);
8812
8813   mp->sw_if_index = ntohl (sw_if_index);
8814   mp->is_server = is_server;
8815   mp->enable_gso = enable_gso;
8816   mp->enable_packed = enable_packed;
8817   mp->enable_event_idx = enable_event_idx;
8818   mp->custom_dev_instance = ntohl (custom_dev_instance);
8819   clib_memcpy (mp->sock_filename, file_name, vec_len (file_name));
8820   vec_free (file_name);
8821   if (custom_dev_instance != ~0)
8822     mp->renumber = 1;
8823
8824   S (mp);
8825   W (ret);
8826   return ret;
8827 }
8828
8829 static int
8830 api_delete_vhost_user_if (vat_main_t * vam)
8831 {
8832   unformat_input_t *i = vam->input;
8833   vl_api_delete_vhost_user_if_t *mp;
8834   u32 sw_if_index = ~0;
8835   u8 sw_if_index_set = 0;
8836   int ret;
8837
8838   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8839     {
8840       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8841         sw_if_index_set = 1;
8842       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8843         sw_if_index_set = 1;
8844       else
8845         break;
8846     }
8847
8848   if (sw_if_index_set == 0)
8849     {
8850       errmsg ("missing sw_if_index or interface name");
8851       return -99;
8852     }
8853
8854
8855   M (DELETE_VHOST_USER_IF, mp);
8856
8857   mp->sw_if_index = ntohl (sw_if_index);
8858
8859   S (mp);
8860   W (ret);
8861   return ret;
8862 }
8863
8864 static void vl_api_sw_interface_vhost_user_details_t_handler
8865   (vl_api_sw_interface_vhost_user_details_t * mp)
8866 {
8867   vat_main_t *vam = &vat_main;
8868   u64 features;
8869
8870   features =
8871     clib_net_to_host_u32 (mp->features_first_32) | ((u64)
8872                                                     clib_net_to_host_u32
8873                                                     (mp->features_last_32) <<
8874                                                     32);
8875
8876   print (vam->ofp, "%-25s %3" PRIu32 " %6" PRIu32 " %16llx %6d %7d %s",
8877          (char *) mp->interface_name, ntohl (mp->sw_if_index),
8878          ntohl (mp->virtio_net_hdr_sz), features, mp->is_server,
8879          ntohl (mp->num_regions), (char *) mp->sock_filename);
8880   print (vam->ofp, "    Status: '%s'", strerror (ntohl (mp->sock_errno)));
8881 }
8882
8883 static void vl_api_sw_interface_vhost_user_details_t_handler_json
8884   (vl_api_sw_interface_vhost_user_details_t * mp)
8885 {
8886   vat_main_t *vam = &vat_main;
8887   vat_json_node_t *node = NULL;
8888
8889   if (VAT_JSON_ARRAY != vam->json_tree.type)
8890     {
8891       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
8892       vat_json_init_array (&vam->json_tree);
8893     }
8894   node = vat_json_array_add (&vam->json_tree);
8895
8896   vat_json_init_object (node);
8897   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
8898   vat_json_object_add_string_copy (node, "interface_name",
8899                                    mp->interface_name);
8900   vat_json_object_add_uint (node, "virtio_net_hdr_sz",
8901                             ntohl (mp->virtio_net_hdr_sz));
8902   vat_json_object_add_uint (node, "features_first_32",
8903                             clib_net_to_host_u32 (mp->features_first_32));
8904   vat_json_object_add_uint (node, "features_last_32",
8905                             clib_net_to_host_u32 (mp->features_last_32));
8906   vat_json_object_add_uint (node, "is_server", mp->is_server);
8907   vat_json_object_add_string_copy (node, "sock_filename", mp->sock_filename);
8908   vat_json_object_add_uint (node, "num_regions", ntohl (mp->num_regions));
8909   vat_json_object_add_uint (node, "sock_errno", ntohl (mp->sock_errno));
8910 }
8911
8912 static int
8913 api_sw_interface_vhost_user_dump (vat_main_t * vam)
8914 {
8915   unformat_input_t *i = vam->input;
8916   vl_api_sw_interface_vhost_user_dump_t *mp;
8917   vl_api_control_ping_t *mp_ping;
8918   int ret;
8919   u32 sw_if_index = ~0;
8920
8921   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8922     {
8923       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8924         ;
8925       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8926         ;
8927       else
8928         break;
8929     }
8930
8931   print (vam->ofp, "Interface name            idx hdr_sz         features "
8932                    "server regions filename");
8933
8934   /* Get list of vhost-user interfaces */
8935   M (SW_INTERFACE_VHOST_USER_DUMP, mp);
8936   mp->sw_if_index = ntohl (sw_if_index);
8937   S (mp);
8938
8939   /* Use a control ping for synchronization */
8940   MPING (CONTROL_PING, mp_ping);
8941   S (mp_ping);
8942
8943   W (ret);
8944   return ret;
8945 }
8946
8947 static int
8948 api_show_version (vat_main_t * vam)
8949 {
8950   vl_api_show_version_t *mp;
8951   int ret;
8952
8953   M (SHOW_VERSION, mp);
8954
8955   S (mp);
8956   W (ret);
8957   return ret;
8958 }
8959
8960 static void vl_api_l2_fib_table_details_t_handler
8961   (vl_api_l2_fib_table_details_t * mp)
8962 {
8963   vat_main_t *vam = &vat_main;
8964
8965   print (vam->ofp, "%3" PRIu32 "    %U    %3" PRIu32
8966          "       %d       %d     %d",
8967          ntohl (mp->bd_id), format_ethernet_address, mp->mac,
8968          ntohl (mp->sw_if_index), mp->static_mac, mp->filter_mac,
8969          mp->bvi_mac);
8970 }
8971
8972 static void vl_api_l2_fib_table_details_t_handler_json
8973   (vl_api_l2_fib_table_details_t * mp)
8974 {
8975   vat_main_t *vam = &vat_main;
8976   vat_json_node_t *node = NULL;
8977
8978   if (VAT_JSON_ARRAY != vam->json_tree.type)
8979     {
8980       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
8981       vat_json_init_array (&vam->json_tree);
8982     }
8983   node = vat_json_array_add (&vam->json_tree);
8984
8985   vat_json_init_object (node);
8986   vat_json_object_add_uint (node, "bd_id", ntohl (mp->bd_id));
8987   vat_json_object_add_bytes (node, "mac", mp->mac, 6);
8988   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
8989   vat_json_object_add_uint (node, "static_mac", mp->static_mac);
8990   vat_json_object_add_uint (node, "filter_mac", mp->filter_mac);
8991   vat_json_object_add_uint (node, "bvi_mac", mp->bvi_mac);
8992 }
8993
8994 static int
8995 api_l2_fib_table_dump (vat_main_t * vam)
8996 {
8997   unformat_input_t *i = vam->input;
8998   vl_api_l2_fib_table_dump_t *mp;
8999   vl_api_control_ping_t *mp_ping;
9000   u32 bd_id;
9001   u8 bd_id_set = 0;
9002   int ret;
9003
9004   /* Parse args required to build the message */
9005   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9006     {
9007       if (unformat (i, "bd_id %d", &bd_id))
9008         bd_id_set = 1;
9009       else
9010         break;
9011     }
9012
9013   if (bd_id_set == 0)
9014     {
9015       errmsg ("missing bridge domain");
9016       return -99;
9017     }
9018
9019   print (vam->ofp, "BD-ID     Mac Address      sw-ndx  Static  Filter  BVI");
9020
9021   /* Get list of l2 fib entries */
9022   M (L2_FIB_TABLE_DUMP, mp);
9023
9024   mp->bd_id = ntohl (bd_id);
9025   S (mp);
9026
9027   /* Use a control ping for synchronization */
9028   MPING (CONTROL_PING, mp_ping);
9029   S (mp_ping);
9030
9031   W (ret);
9032   return ret;
9033 }
9034
9035
9036 static int
9037 api_interface_name_renumber (vat_main_t * vam)
9038 {
9039   unformat_input_t *line_input = vam->input;
9040   vl_api_interface_name_renumber_t *mp;
9041   u32 sw_if_index = ~0;
9042   u32 new_show_dev_instance = ~0;
9043   int ret;
9044
9045   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
9046     {
9047       if (unformat (line_input, "%U", api_unformat_sw_if_index, vam,
9048                     &sw_if_index))
9049         ;
9050       else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
9051         ;
9052       else if (unformat (line_input, "new_show_dev_instance %d",
9053                          &new_show_dev_instance))
9054         ;
9055       else
9056         break;
9057     }
9058
9059   if (sw_if_index == ~0)
9060     {
9061       errmsg ("missing interface name or sw_if_index");
9062       return -99;
9063     }
9064
9065   if (new_show_dev_instance == ~0)
9066     {
9067       errmsg ("missing new_show_dev_instance");
9068       return -99;
9069     }
9070
9071   M (INTERFACE_NAME_RENUMBER, mp);
9072
9073   mp->sw_if_index = ntohl (sw_if_index);
9074   mp->new_show_dev_instance = ntohl (new_show_dev_instance);
9075
9076   S (mp);
9077   W (ret);
9078   return ret;
9079 }
9080
9081 static int
9082 api_want_l2_macs_events (vat_main_t * vam)
9083 {
9084   unformat_input_t *line_input = vam->input;
9085   vl_api_want_l2_macs_events_t *mp;
9086   u8 enable_disable = 1;
9087   u32 scan_delay = 0;
9088   u32 max_macs_in_event = 0;
9089   u32 learn_limit = 0;
9090   int ret;
9091
9092   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
9093     {
9094       if (unformat (line_input, "learn-limit %d", &learn_limit))
9095         ;
9096       else if (unformat (line_input, "scan-delay %d", &scan_delay))
9097         ;
9098       else if (unformat (line_input, "max-entries %d", &max_macs_in_event))
9099         ;
9100       else if (unformat (line_input, "disable"))
9101         enable_disable = 0;
9102       else
9103         break;
9104     }
9105
9106   M (WANT_L2_MACS_EVENTS, mp);
9107   mp->enable_disable = enable_disable;
9108   mp->pid = htonl (getpid ());
9109   mp->learn_limit = htonl (learn_limit);
9110   mp->scan_delay = (u8) scan_delay;
9111   mp->max_macs_in_event = (u8) (max_macs_in_event / 10);
9112   S (mp);
9113   W (ret);
9114   return ret;
9115 }
9116
9117 static int
9118 api_ip_address_dump (vat_main_t * vam)
9119 {
9120   unformat_input_t *i = vam->input;
9121   vl_api_ip_address_dump_t *mp;
9122   vl_api_control_ping_t *mp_ping;
9123   u32 sw_if_index = ~0;
9124   u8 sw_if_index_set = 0;
9125   u8 ipv4_set = 0;
9126   u8 ipv6_set = 0;
9127   int ret;
9128
9129   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9130     {
9131       if (unformat (i, "sw_if_index %d", &sw_if_index))
9132         sw_if_index_set = 1;
9133       else
9134         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
9135         sw_if_index_set = 1;
9136       else if (unformat (i, "ipv4"))
9137         ipv4_set = 1;
9138       else if (unformat (i, "ipv6"))
9139         ipv6_set = 1;
9140       else
9141         break;
9142     }
9143
9144   if (ipv4_set && ipv6_set)
9145     {
9146       errmsg ("ipv4 and ipv6 flags cannot be both set");
9147       return -99;
9148     }
9149
9150   if ((!ipv4_set) && (!ipv6_set))
9151     {
9152       errmsg ("no ipv4 nor ipv6 flag set");
9153       return -99;
9154     }
9155
9156   if (sw_if_index_set == 0)
9157     {
9158       errmsg ("missing interface name or sw_if_index");
9159       return -99;
9160     }
9161
9162   vam->current_sw_if_index = sw_if_index;
9163   vam->is_ipv6 = ipv6_set;
9164
9165   M (IP_ADDRESS_DUMP, mp);
9166   mp->sw_if_index = ntohl (sw_if_index);
9167   mp->is_ipv6 = ipv6_set;
9168   S (mp);
9169
9170   /* Use a control ping for synchronization */
9171   MPING (CONTROL_PING, mp_ping);
9172   S (mp_ping);
9173
9174   W (ret);
9175   return ret;
9176 }
9177
9178 static int
9179 api_ip_dump (vat_main_t * vam)
9180 {
9181   vl_api_ip_dump_t *mp;
9182   vl_api_control_ping_t *mp_ping;
9183   unformat_input_t *in = vam->input;
9184   int ipv4_set = 0;
9185   int ipv6_set = 0;
9186   int is_ipv6;
9187   int i;
9188   int ret;
9189
9190   while (unformat_check_input (in) != UNFORMAT_END_OF_INPUT)
9191     {
9192       if (unformat (in, "ipv4"))
9193         ipv4_set = 1;
9194       else if (unformat (in, "ipv6"))
9195         ipv6_set = 1;
9196       else
9197         break;
9198     }
9199
9200   if (ipv4_set && ipv6_set)
9201     {
9202       errmsg ("ipv4 and ipv6 flags cannot be both set");
9203       return -99;
9204     }
9205
9206   if ((!ipv4_set) && (!ipv6_set))
9207     {
9208       errmsg ("no ipv4 nor ipv6 flag set");
9209       return -99;
9210     }
9211
9212   is_ipv6 = ipv6_set;
9213   vam->is_ipv6 = is_ipv6;
9214
9215   /* free old data */
9216   for (i = 0; i < vec_len (vam->ip_details_by_sw_if_index[is_ipv6]); i++)
9217     {
9218       vec_free (vam->ip_details_by_sw_if_index[is_ipv6][i].addr);
9219     }
9220   vec_free (vam->ip_details_by_sw_if_index[is_ipv6]);
9221
9222   M (IP_DUMP, mp);
9223   mp->is_ipv6 = ipv6_set;
9224   S (mp);
9225
9226   /* Use a control ping for synchronization */
9227   MPING (CONTROL_PING, mp_ping);
9228   S (mp_ping);
9229
9230   W (ret);
9231   return ret;
9232 }
9233
9234 static int
9235 api_ipsec_spd_add_del (vat_main_t * vam)
9236 {
9237   unformat_input_t *i = vam->input;
9238   vl_api_ipsec_spd_add_del_t *mp;
9239   u32 spd_id = ~0;
9240   u8 is_add = 1;
9241   int ret;
9242
9243   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9244     {
9245       if (unformat (i, "spd_id %d", &spd_id))
9246         ;
9247       else if (unformat (i, "del"))
9248         is_add = 0;
9249       else
9250         {
9251           clib_warning ("parse error '%U'", format_unformat_error, i);
9252           return -99;
9253         }
9254     }
9255   if (spd_id == ~0)
9256     {
9257       errmsg ("spd_id must be set");
9258       return -99;
9259     }
9260
9261   M (IPSEC_SPD_ADD_DEL, mp);
9262
9263   mp->spd_id = ntohl (spd_id);
9264   mp->is_add = is_add;
9265
9266   S (mp);
9267   W (ret);
9268   return ret;
9269 }
9270
9271 static int
9272 api_ipsec_interface_add_del_spd (vat_main_t * vam)
9273 {
9274   unformat_input_t *i = vam->input;
9275   vl_api_ipsec_interface_add_del_spd_t *mp;
9276   u32 sw_if_index;
9277   u8 sw_if_index_set = 0;
9278   u32 spd_id = (u32) ~ 0;
9279   u8 is_add = 1;
9280   int ret;
9281
9282   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9283     {
9284       if (unformat (i, "del"))
9285         is_add = 0;
9286       else if (unformat (i, "spd_id %d", &spd_id))
9287         ;
9288       else
9289         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
9290         sw_if_index_set = 1;
9291       else if (unformat (i, "sw_if_index %d", &sw_if_index))
9292         sw_if_index_set = 1;
9293       else
9294         {
9295           clib_warning ("parse error '%U'", format_unformat_error, i);
9296           return -99;
9297         }
9298
9299     }
9300
9301   if (spd_id == (u32) ~ 0)
9302     {
9303       errmsg ("spd_id must be set");
9304       return -99;
9305     }
9306
9307   if (sw_if_index_set == 0)
9308     {
9309       errmsg ("missing interface name or sw_if_index");
9310       return -99;
9311     }
9312
9313   M (IPSEC_INTERFACE_ADD_DEL_SPD, mp);
9314
9315   mp->spd_id = ntohl (spd_id);
9316   mp->sw_if_index = ntohl (sw_if_index);
9317   mp->is_add = is_add;
9318
9319   S (mp);
9320   W (ret);
9321   return ret;
9322 }
9323
9324 static int
9325 api_ipsec_spd_entry_add_del (vat_main_t * vam)
9326 {
9327   unformat_input_t *i = vam->input;
9328   vl_api_ipsec_spd_entry_add_del_t *mp;
9329   u8 is_add = 1, is_outbound = 0;
9330   u32 spd_id = 0, sa_id = 0, protocol = 0, policy = 0;
9331   i32 priority = 0;
9332   u32 rport_start = 0, rport_stop = (u32) ~ 0;
9333   u32 lport_start = 0, lport_stop = (u32) ~ 0;
9334   vl_api_address_t laddr_start = { }, laddr_stop =
9335   {
9336   }, raddr_start =
9337   {
9338   }, raddr_stop =
9339   {
9340   };
9341   int ret;
9342
9343   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9344     {
9345       if (unformat (i, "del"))
9346         is_add = 0;
9347       if (unformat (i, "outbound"))
9348         is_outbound = 1;
9349       if (unformat (i, "inbound"))
9350         is_outbound = 0;
9351       else if (unformat (i, "spd_id %d", &spd_id))
9352         ;
9353       else if (unformat (i, "sa_id %d", &sa_id))
9354         ;
9355       else if (unformat (i, "priority %d", &priority))
9356         ;
9357       else if (unformat (i, "protocol %d", &protocol))
9358         ;
9359       else if (unformat (i, "lport_start %d", &lport_start))
9360         ;
9361       else if (unformat (i, "lport_stop %d", &lport_stop))
9362         ;
9363       else if (unformat (i, "rport_start %d", &rport_start))
9364         ;
9365       else if (unformat (i, "rport_stop %d", &rport_stop))
9366         ;
9367       else if (unformat (i, "laddr_start %U",
9368                          unformat_vl_api_address, &laddr_start))
9369         ;
9370       else if (unformat (i, "laddr_stop %U", unformat_vl_api_address,
9371                          &laddr_stop))
9372         ;
9373       else if (unformat (i, "raddr_start %U", unformat_vl_api_address,
9374                          &raddr_start))
9375         ;
9376       else if (unformat (i, "raddr_stop %U", unformat_vl_api_address,
9377                          &raddr_stop))
9378         ;
9379       else
9380         if (unformat (i, "action %U", unformat_ipsec_policy_action, &policy))
9381         {
9382           if (policy == IPSEC_POLICY_ACTION_RESOLVE)
9383             {
9384               clib_warning ("unsupported action: 'resolve'");
9385               return -99;
9386             }
9387         }
9388       else
9389         {
9390           clib_warning ("parse error '%U'", format_unformat_error, i);
9391           return -99;
9392         }
9393
9394     }
9395
9396   M (IPSEC_SPD_ENTRY_ADD_DEL, mp);
9397
9398   mp->is_add = is_add;
9399
9400   mp->entry.spd_id = ntohl (spd_id);
9401   mp->entry.priority = ntohl (priority);
9402   mp->entry.is_outbound = is_outbound;
9403
9404   clib_memcpy (&mp->entry.remote_address_start, &raddr_start,
9405                sizeof (vl_api_address_t));
9406   clib_memcpy (&mp->entry.remote_address_stop, &raddr_stop,
9407                sizeof (vl_api_address_t));
9408   clib_memcpy (&mp->entry.local_address_start, &laddr_start,
9409                sizeof (vl_api_address_t));
9410   clib_memcpy (&mp->entry.local_address_stop, &laddr_stop,
9411                sizeof (vl_api_address_t));
9412
9413   mp->entry.protocol = (u8) protocol;
9414   mp->entry.local_port_start = ntohs ((u16) lport_start);
9415   mp->entry.local_port_stop = ntohs ((u16) lport_stop);
9416   mp->entry.remote_port_start = ntohs ((u16) rport_start);
9417   mp->entry.remote_port_stop = ntohs ((u16) rport_stop);
9418   mp->entry.policy = (u8) policy;
9419   mp->entry.sa_id = ntohl (sa_id);
9420
9421   S (mp);
9422   W (ret);
9423   return ret;
9424 }
9425
9426 static int
9427 api_ipsec_sad_entry_add_del (vat_main_t * vam)
9428 {
9429   unformat_input_t *i = vam->input;
9430   vl_api_ipsec_sad_entry_add_del_t *mp;
9431   u32 sad_id = 0, spi = 0;
9432   u8 *ck = 0, *ik = 0;
9433   u8 is_add = 1;
9434
9435   vl_api_ipsec_crypto_alg_t crypto_alg = IPSEC_API_CRYPTO_ALG_NONE;
9436   vl_api_ipsec_integ_alg_t integ_alg = IPSEC_API_INTEG_ALG_NONE;
9437   vl_api_ipsec_sad_flags_t flags = IPSEC_API_SAD_FLAG_NONE;
9438   vl_api_ipsec_proto_t protocol = IPSEC_API_PROTO_AH;
9439   vl_api_address_t tun_src, tun_dst;
9440   int ret;
9441
9442   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9443     {
9444       if (unformat (i, "del"))
9445         is_add = 0;
9446       else if (unformat (i, "sad_id %d", &sad_id))
9447         ;
9448       else if (unformat (i, "spi %d", &spi))
9449         ;
9450       else if (unformat (i, "esp"))
9451         protocol = IPSEC_API_PROTO_ESP;
9452       else
9453         if (unformat (i, "tunnel_src %U", unformat_vl_api_address, &tun_src))
9454         {
9455           flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL;
9456           if (ADDRESS_IP6 == tun_src.af)
9457             flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL_V6;
9458         }
9459       else
9460         if (unformat (i, "tunnel_dst %U", unformat_vl_api_address, &tun_dst))
9461         {
9462           flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL;
9463           if (ADDRESS_IP6 == tun_src.af)
9464             flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL_V6;
9465         }
9466       else
9467         if (unformat (i, "crypto_alg %U",
9468                       unformat_ipsec_api_crypto_alg, &crypto_alg))
9469         ;
9470       else if (unformat (i, "crypto_key %U", unformat_hex_string, &ck))
9471         ;
9472       else if (unformat (i, "integ_alg %U",
9473                          unformat_ipsec_api_integ_alg, &integ_alg))
9474         ;
9475       else if (unformat (i, "integ_key %U", unformat_hex_string, &ik))
9476         ;
9477       else
9478         {
9479           clib_warning ("parse error '%U'", format_unformat_error, i);
9480           return -99;
9481         }
9482
9483     }
9484
9485   M (IPSEC_SAD_ENTRY_ADD_DEL, mp);
9486
9487   mp->is_add = is_add;
9488   mp->entry.sad_id = ntohl (sad_id);
9489   mp->entry.protocol = protocol;
9490   mp->entry.spi = ntohl (spi);
9491   mp->entry.flags = flags;
9492
9493   mp->entry.crypto_algorithm = crypto_alg;
9494   mp->entry.integrity_algorithm = integ_alg;
9495   mp->entry.crypto_key.length = vec_len (ck);
9496   mp->entry.integrity_key.length = vec_len (ik);
9497
9498   if (mp->entry.crypto_key.length > sizeof (mp->entry.crypto_key.data))
9499     mp->entry.crypto_key.length = sizeof (mp->entry.crypto_key.data);
9500
9501   if (mp->entry.integrity_key.length > sizeof (mp->entry.integrity_key.data))
9502     mp->entry.integrity_key.length = sizeof (mp->entry.integrity_key.data);
9503
9504   if (ck)
9505     clib_memcpy (mp->entry.crypto_key.data, ck, mp->entry.crypto_key.length);
9506   if (ik)
9507     clib_memcpy (mp->entry.integrity_key.data, ik,
9508                  mp->entry.integrity_key.length);
9509
9510   if (flags & IPSEC_API_SAD_FLAG_IS_TUNNEL)
9511     {
9512       clib_memcpy (&mp->entry.tunnel_src, &tun_src,
9513                    sizeof (mp->entry.tunnel_src));
9514       clib_memcpy (&mp->entry.tunnel_dst, &tun_dst,
9515                    sizeof (mp->entry.tunnel_dst));
9516     }
9517
9518   S (mp);
9519   W (ret);
9520   return ret;
9521 }
9522
9523 static void
9524 vl_api_ipsec_sa_details_t_handler (vl_api_ipsec_sa_details_t * mp)
9525 {
9526   vat_main_t *vam = &vat_main;
9527
9528   print (vam->ofp, "sa_id %u sw_if_index %u spi %u proto %u crypto_alg %u "
9529          "crypto_key %U integ_alg %u integ_key %U flags %x "
9530          "tunnel_src_addr %U tunnel_dst_addr %U "
9531          "salt %u seq_outbound %lu last_seq_inbound %lu "
9532          "replay_window %lu stat_index %u\n",
9533          ntohl (mp->entry.sad_id),
9534          ntohl (mp->sw_if_index),
9535          ntohl (mp->entry.spi),
9536          ntohl (mp->entry.protocol),
9537          ntohl (mp->entry.crypto_algorithm),
9538          format_hex_bytes, mp->entry.crypto_key.data,
9539          mp->entry.crypto_key.length, ntohl (mp->entry.integrity_algorithm),
9540          format_hex_bytes, mp->entry.integrity_key.data,
9541          mp->entry.integrity_key.length, ntohl (mp->entry.flags),
9542          format_vl_api_address, &mp->entry.tunnel_src, format_vl_api_address,
9543          &mp->entry.tunnel_dst, ntohl (mp->salt),
9544          clib_net_to_host_u64 (mp->seq_outbound),
9545          clib_net_to_host_u64 (mp->last_seq_inbound),
9546          clib_net_to_host_u64 (mp->replay_window), ntohl (mp->stat_index));
9547 }
9548
9549 #define vl_api_ipsec_sa_details_t_endian vl_noop_handler
9550 #define vl_api_ipsec_sa_details_t_print vl_noop_handler
9551
9552 static void vl_api_ipsec_sa_details_t_handler_json
9553   (vl_api_ipsec_sa_details_t * mp)
9554 {
9555   vat_main_t *vam = &vat_main;
9556   vat_json_node_t *node = NULL;
9557   vl_api_ipsec_sad_flags_t flags;
9558
9559   if (VAT_JSON_ARRAY != vam->json_tree.type)
9560     {
9561       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9562       vat_json_init_array (&vam->json_tree);
9563     }
9564   node = vat_json_array_add (&vam->json_tree);
9565
9566   vat_json_init_object (node);
9567   vat_json_object_add_uint (node, "sa_id", ntohl (mp->entry.sad_id));
9568   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
9569   vat_json_object_add_uint (node, "spi", ntohl (mp->entry.spi));
9570   vat_json_object_add_uint (node, "proto", ntohl (mp->entry.protocol));
9571   vat_json_object_add_uint (node, "crypto_alg",
9572                             ntohl (mp->entry.crypto_algorithm));
9573   vat_json_object_add_uint (node, "integ_alg",
9574                             ntohl (mp->entry.integrity_algorithm));
9575   flags = ntohl (mp->entry.flags);
9576   vat_json_object_add_uint (node, "use_esn",
9577                             ! !(flags & IPSEC_API_SAD_FLAG_USE_ESN));
9578   vat_json_object_add_uint (node, "use_anti_replay",
9579                             ! !(flags & IPSEC_API_SAD_FLAG_USE_ANTI_REPLAY));
9580   vat_json_object_add_uint (node, "is_tunnel",
9581                             ! !(flags & IPSEC_API_SAD_FLAG_IS_TUNNEL));
9582   vat_json_object_add_uint (node, "is_tunnel_ip6",
9583                             ! !(flags & IPSEC_API_SAD_FLAG_IS_TUNNEL_V6));
9584   vat_json_object_add_uint (node, "udp_encap",
9585                             ! !(flags & IPSEC_API_SAD_FLAG_UDP_ENCAP));
9586   vat_json_object_add_bytes (node, "crypto_key", mp->entry.crypto_key.data,
9587                              mp->entry.crypto_key.length);
9588   vat_json_object_add_bytes (node, "integ_key", mp->entry.integrity_key.data,
9589                              mp->entry.integrity_key.length);
9590   vat_json_object_add_address (node, "src", &mp->entry.tunnel_src);
9591   vat_json_object_add_address (node, "dst", &mp->entry.tunnel_dst);
9592   vat_json_object_add_uint (node, "replay_window",
9593                             clib_net_to_host_u64 (mp->replay_window));
9594   vat_json_object_add_uint (node, "stat_index", ntohl (mp->stat_index));
9595 }
9596
9597 static int
9598 api_ipsec_sa_dump (vat_main_t * vam)
9599 {
9600   unformat_input_t *i = vam->input;
9601   vl_api_ipsec_sa_dump_t *mp;
9602   vl_api_control_ping_t *mp_ping;
9603   u32 sa_id = ~0;
9604   int ret;
9605
9606   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9607     {
9608       if (unformat (i, "sa_id %d", &sa_id))
9609         ;
9610       else
9611         {
9612           clib_warning ("parse error '%U'", format_unformat_error, i);
9613           return -99;
9614         }
9615     }
9616
9617   M (IPSEC_SA_DUMP, mp);
9618
9619   mp->sa_id = ntohl (sa_id);
9620
9621   S (mp);
9622
9623   /* Use a control ping for synchronization */
9624   M (CONTROL_PING, mp_ping);
9625   S (mp_ping);
9626
9627   W (ret);
9628   return ret;
9629 }
9630
9631 static int
9632 api_get_first_msg_id (vat_main_t * vam)
9633 {
9634   vl_api_get_first_msg_id_t *mp;
9635   unformat_input_t *i = vam->input;
9636   u8 *name;
9637   u8 name_set = 0;
9638   int ret;
9639
9640   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9641     {
9642       if (unformat (i, "client %s", &name))
9643         name_set = 1;
9644       else
9645         break;
9646     }
9647
9648   if (name_set == 0)
9649     {
9650       errmsg ("missing client name");
9651       return -99;
9652     }
9653   vec_add1 (name, 0);
9654
9655   if (vec_len (name) > 63)
9656     {
9657       errmsg ("client name too long");
9658       return -99;
9659     }
9660
9661   M (GET_FIRST_MSG_ID, mp);
9662   clib_memcpy (mp->name, name, vec_len (name));
9663   S (mp);
9664   W (ret);
9665   return ret;
9666 }
9667
9668 static int
9669 api_get_node_graph (vat_main_t * vam)
9670 {
9671   vl_api_get_node_graph_t *mp;
9672   int ret;
9673
9674   M (GET_NODE_GRAPH, mp);
9675
9676   /* send it... */
9677   S (mp);
9678   /* Wait for the reply */
9679   W (ret);
9680   return ret;
9681 }
9682
9683 static int
9684 api_af_packet_create (vat_main_t * vam)
9685 {
9686   unformat_input_t *i = vam->input;
9687   vl_api_af_packet_create_t *mp;
9688   u8 *host_if_name = 0;
9689   u8 hw_addr[6];
9690   u8 random_hw_addr = 1;
9691   int ret;
9692
9693   clib_memset (hw_addr, 0, sizeof (hw_addr));
9694
9695   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9696     {
9697       if (unformat (i, "name %s", &host_if_name))
9698         vec_add1 (host_if_name, 0);
9699       else if (unformat (i, "hw_addr %U", unformat_ethernet_address, hw_addr))
9700         random_hw_addr = 0;
9701       else
9702         break;
9703     }
9704
9705   if (!vec_len (host_if_name))
9706     {
9707       errmsg ("host-interface name must be specified");
9708       return -99;
9709     }
9710
9711   if (vec_len (host_if_name) > 64)
9712     {
9713       errmsg ("host-interface name too long");
9714       return -99;
9715     }
9716
9717   M (AF_PACKET_CREATE, mp);
9718
9719   clib_memcpy (mp->host_if_name, host_if_name, vec_len (host_if_name));
9720   clib_memcpy (mp->hw_addr, hw_addr, 6);
9721   mp->use_random_hw_addr = random_hw_addr;
9722   vec_free (host_if_name);
9723
9724   S (mp);
9725
9726   /* *INDENT-OFF* */
9727   W2 (ret,
9728       ({
9729         if (ret == 0)
9730           fprintf (vam->ofp ? vam->ofp : stderr,
9731                    " new sw_if_index = %d\n", vam->sw_if_index);
9732       }));
9733   /* *INDENT-ON* */
9734   return ret;
9735 }
9736
9737 static int
9738 api_af_packet_delete (vat_main_t * vam)
9739 {
9740   unformat_input_t *i = vam->input;
9741   vl_api_af_packet_delete_t *mp;
9742   u8 *host_if_name = 0;
9743   int ret;
9744
9745   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9746     {
9747       if (unformat (i, "name %s", &host_if_name))
9748         vec_add1 (host_if_name, 0);
9749       else
9750         break;
9751     }
9752
9753   if (!vec_len (host_if_name))
9754     {
9755       errmsg ("host-interface name must be specified");
9756       return -99;
9757     }
9758
9759   if (vec_len (host_if_name) > 64)
9760     {
9761       errmsg ("host-interface name too long");
9762       return -99;
9763     }
9764
9765   M (AF_PACKET_DELETE, mp);
9766
9767   clib_memcpy (mp->host_if_name, host_if_name, vec_len (host_if_name));
9768   vec_free (host_if_name);
9769
9770   S (mp);
9771   W (ret);
9772   return ret;
9773 }
9774
9775 static void vl_api_af_packet_details_t_handler
9776   (vl_api_af_packet_details_t * mp)
9777 {
9778   vat_main_t *vam = &vat_main;
9779
9780   print (vam->ofp, "%-16s %d",
9781          mp->host_if_name, clib_net_to_host_u32 (mp->sw_if_index));
9782 }
9783
9784 static void vl_api_af_packet_details_t_handler_json
9785   (vl_api_af_packet_details_t * mp)
9786 {
9787   vat_main_t *vam = &vat_main;
9788   vat_json_node_t *node = NULL;
9789
9790   if (VAT_JSON_ARRAY != vam->json_tree.type)
9791     {
9792       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9793       vat_json_init_array (&vam->json_tree);
9794     }
9795   node = vat_json_array_add (&vam->json_tree);
9796
9797   vat_json_init_object (node);
9798   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
9799   vat_json_object_add_string_copy (node, "dev_name", mp->host_if_name);
9800 }
9801
9802 static int
9803 api_af_packet_dump (vat_main_t * vam)
9804 {
9805   vl_api_af_packet_dump_t *mp;
9806   vl_api_control_ping_t *mp_ping;
9807   int ret;
9808
9809   print (vam->ofp, "\n%-16s %s", "dev_name", "sw_if_index");
9810   /* Get list of tap interfaces */
9811   M (AF_PACKET_DUMP, mp);
9812   S (mp);
9813
9814   /* Use a control ping for synchronization */
9815   MPING (CONTROL_PING, mp_ping);
9816   S (mp_ping);
9817
9818   W (ret);
9819   return ret;
9820 }
9821
9822 static int
9823 api_policer_add_del (vat_main_t * vam)
9824 {
9825   unformat_input_t *i = vam->input;
9826   vl_api_policer_add_del_t *mp;
9827   u8 is_add = 1;
9828   u8 *name = 0;
9829   u32 cir = 0;
9830   u32 eir = 0;
9831   u64 cb = 0;
9832   u64 eb = 0;
9833   u8 rate_type = 0;
9834   u8 round_type = 0;
9835   u8 type = 0;
9836   u8 color_aware = 0;
9837   qos_pol_action_params_st conform_action, exceed_action, violate_action;
9838   int ret;
9839
9840   conform_action.action_type = QOS_ACTION_TRANSMIT;
9841   conform_action.dscp = 0;
9842   exceed_action.action_type = QOS_ACTION_MARK_AND_TRANSMIT;
9843   exceed_action.dscp = 0;
9844   violate_action.action_type = QOS_ACTION_DROP;
9845   violate_action.dscp = 0;
9846
9847   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9848     {
9849       if (unformat (i, "del"))
9850         is_add = 0;
9851       else if (unformat (i, "name %s", &name))
9852         vec_add1 (name, 0);
9853       else if (unformat (i, "cir %u", &cir))
9854         ;
9855       else if (unformat (i, "eir %u", &eir))
9856         ;
9857       else if (unformat (i, "cb %u", &cb))
9858         ;
9859       else if (unformat (i, "eb %u", &eb))
9860         ;
9861       else if (unformat (i, "rate_type %U", unformat_policer_rate_type,
9862                          &rate_type))
9863         ;
9864       else if (unformat (i, "round_type %U", unformat_policer_round_type,
9865                          &round_type))
9866         ;
9867       else if (unformat (i, "type %U", unformat_policer_type, &type))
9868         ;
9869       else if (unformat (i, "conform_action %U", unformat_policer_action_type,
9870                          &conform_action))
9871         ;
9872       else if (unformat (i, "exceed_action %U", unformat_policer_action_type,
9873                          &exceed_action))
9874         ;
9875       else if (unformat (i, "violate_action %U", unformat_policer_action_type,
9876                          &violate_action))
9877         ;
9878       else if (unformat (i, "color-aware"))
9879         color_aware = 1;
9880       else
9881         break;
9882     }
9883
9884   if (!vec_len (name))
9885     {
9886       errmsg ("policer name must be specified");
9887       return -99;
9888     }
9889
9890   if (vec_len (name) > 64)
9891     {
9892       errmsg ("policer name too long");
9893       return -99;
9894     }
9895
9896   M (POLICER_ADD_DEL, mp);
9897
9898   clib_memcpy (mp->name, name, vec_len (name));
9899   vec_free (name);
9900   mp->is_add = is_add;
9901   mp->cir = ntohl (cir);
9902   mp->eir = ntohl (eir);
9903   mp->cb = clib_net_to_host_u64 (cb);
9904   mp->eb = clib_net_to_host_u64 (eb);
9905   mp->rate_type = rate_type;
9906   mp->round_type = round_type;
9907   mp->type = type;
9908   mp->conform_action.type =
9909     (vl_api_sse2_qos_action_type_t) conform_action.action_type;
9910   mp->conform_action.dscp = conform_action.dscp;
9911   mp->exceed_action.type =
9912     (vl_api_sse2_qos_action_type_t) exceed_action.action_type;
9913   mp->exceed_action.dscp = exceed_action.dscp;
9914   mp->violate_action.type =
9915     (vl_api_sse2_qos_action_type_t) violate_action.action_type;
9916   mp->violate_action.dscp = violate_action.dscp;
9917   mp->color_aware = color_aware;
9918
9919   S (mp);
9920   W (ret);
9921   return ret;
9922 }
9923
9924 static int
9925 api_policer_dump (vat_main_t * vam)
9926 {
9927   unformat_input_t *i = vam->input;
9928   vl_api_policer_dump_t *mp;
9929   vl_api_control_ping_t *mp_ping;
9930   u8 *match_name = 0;
9931   u8 match_name_valid = 0;
9932   int ret;
9933
9934   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9935     {
9936       if (unformat (i, "name %s", &match_name))
9937         {
9938           vec_add1 (match_name, 0);
9939           match_name_valid = 1;
9940         }
9941       else
9942         break;
9943     }
9944
9945   M (POLICER_DUMP, mp);
9946   mp->match_name_valid = match_name_valid;
9947   clib_memcpy (mp->match_name, match_name, vec_len (match_name));
9948   vec_free (match_name);
9949   /* send it... */
9950   S (mp);
9951
9952   /* Use a control ping for synchronization */
9953   MPING (CONTROL_PING, mp_ping);
9954   S (mp_ping);
9955
9956   /* Wait for a reply... */
9957   W (ret);
9958   return ret;
9959 }
9960
9961 static u8 *
9962 format_fib_api_path_nh_proto (u8 * s, va_list * args)
9963 {
9964   vl_api_fib_path_nh_proto_t proto =
9965     va_arg (*args, vl_api_fib_path_nh_proto_t);
9966
9967   switch (proto)
9968     {
9969     case FIB_API_PATH_NH_PROTO_IP4:
9970       s = format (s, "ip4");
9971       break;
9972     case FIB_API_PATH_NH_PROTO_IP6:
9973       s = format (s, "ip6");
9974       break;
9975     case FIB_API_PATH_NH_PROTO_MPLS:
9976       s = format (s, "mpls");
9977       break;
9978     case FIB_API_PATH_NH_PROTO_BIER:
9979       s = format (s, "bier");
9980       break;
9981     case FIB_API_PATH_NH_PROTO_ETHERNET:
9982       s = format (s, "ethernet");
9983       break;
9984     }
9985
9986   return (s);
9987 }
9988
9989 static u8 *
9990 format_vl_api_ip_address_union (u8 * s, va_list * args)
9991 {
9992   vl_api_address_family_t af = va_arg (*args, int);
9993   const vl_api_address_union_t *u = va_arg (*args, vl_api_address_union_t *);
9994
9995   switch (af)
9996     {
9997     case ADDRESS_IP4:
9998       s = format (s, "%U", format_ip4_address, u->ip4);
9999       break;
10000     case ADDRESS_IP6:
10001       s = format (s, "%U", format_ip6_address, u->ip6);
10002       break;
10003     }
10004   return (s);
10005 }
10006
10007 static u8 *
10008 format_vl_api_fib_path_type (u8 * s, va_list * args)
10009 {
10010   vl_api_fib_path_type_t t = va_arg (*args, vl_api_fib_path_type_t);
10011
10012   switch (t)
10013     {
10014     case FIB_API_PATH_TYPE_NORMAL:
10015       s = format (s, "normal");
10016       break;
10017     case FIB_API_PATH_TYPE_LOCAL:
10018       s = format (s, "local");
10019       break;
10020     case FIB_API_PATH_TYPE_DROP:
10021       s = format (s, "drop");
10022       break;
10023     case FIB_API_PATH_TYPE_UDP_ENCAP:
10024       s = format (s, "udp-encap");
10025       break;
10026     case FIB_API_PATH_TYPE_BIER_IMP:
10027       s = format (s, "bier-imp");
10028       break;
10029     case FIB_API_PATH_TYPE_ICMP_UNREACH:
10030       s = format (s, "unreach");
10031       break;
10032     case FIB_API_PATH_TYPE_ICMP_PROHIBIT:
10033       s = format (s, "prohibit");
10034       break;
10035     case FIB_API_PATH_TYPE_SOURCE_LOOKUP:
10036       s = format (s, "src-lookup");
10037       break;
10038     case FIB_API_PATH_TYPE_DVR:
10039       s = format (s, "dvr");
10040       break;
10041     case FIB_API_PATH_TYPE_INTERFACE_RX:
10042       s = format (s, "interface-rx");
10043       break;
10044     case FIB_API_PATH_TYPE_CLASSIFY:
10045       s = format (s, "classify");
10046       break;
10047     }
10048
10049   return (s);
10050 }
10051
10052 static void
10053 vl_api_fib_path_print (vat_main_t * vam, vl_api_fib_path_t * fp)
10054 {
10055   print (vam->ofp,
10056          "  weight %d, sw_if_index %d, type %U, afi %U, next_hop %U",
10057          ntohl (fp->weight), ntohl (fp->sw_if_index),
10058          format_vl_api_fib_path_type, fp->type,
10059          format_fib_api_path_nh_proto, fp->proto,
10060          format_vl_api_ip_address_union, &fp->nh.address);
10061 }
10062
10063 static void
10064 vl_api_mpls_fib_path_json_print (vat_json_node_t * node,
10065                                  vl_api_fib_path_t * fp)
10066 {
10067   struct in_addr ip4;
10068   struct in6_addr ip6;
10069
10070   vat_json_object_add_uint (node, "weight", ntohl (fp->weight));
10071   vat_json_object_add_uint (node, "sw_if_index", ntohl (fp->sw_if_index));
10072   vat_json_object_add_uint (node, "type", fp->type);
10073   vat_json_object_add_uint (node, "next_hop_proto", fp->proto);
10074   if (fp->proto == FIB_API_PATH_NH_PROTO_IP4)
10075     {
10076       clib_memcpy (&ip4, &fp->nh.address.ip4, sizeof (ip4));
10077       vat_json_object_add_ip4 (node, "next_hop", ip4);
10078     }
10079   else if (fp->proto == FIB_API_PATH_NH_PROTO_IP6)
10080     {
10081       clib_memcpy (&ip6, &fp->nh.address.ip6, sizeof (ip6));
10082       vat_json_object_add_ip6 (node, "next_hop", ip6);
10083     }
10084 }
10085
10086 static void
10087 vl_api_mpls_tunnel_details_t_handler (vl_api_mpls_tunnel_details_t * mp)
10088 {
10089   vat_main_t *vam = &vat_main;
10090   int count = ntohl (mp->mt_tunnel.mt_n_paths);
10091   vl_api_fib_path_t *fp;
10092   i32 i;
10093
10094   print (vam->ofp, "sw_if_index %d via:",
10095          ntohl (mp->mt_tunnel.mt_sw_if_index));
10096   fp = mp->mt_tunnel.mt_paths;
10097   for (i = 0; i < count; i++)
10098     {
10099       vl_api_fib_path_print (vam, fp);
10100       fp++;
10101     }
10102
10103   print (vam->ofp, "");
10104 }
10105
10106 #define vl_api_mpls_tunnel_details_t_endian vl_noop_handler
10107 #define vl_api_mpls_tunnel_details_t_print vl_noop_handler
10108
10109 static void
10110 vl_api_mpls_tunnel_details_t_handler_json (vl_api_mpls_tunnel_details_t * mp)
10111 {
10112   vat_main_t *vam = &vat_main;
10113   vat_json_node_t *node = NULL;
10114   int count = ntohl (mp->mt_tunnel.mt_n_paths);
10115   vl_api_fib_path_t *fp;
10116   i32 i;
10117
10118   if (VAT_JSON_ARRAY != vam->json_tree.type)
10119     {
10120       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
10121       vat_json_init_array (&vam->json_tree);
10122     }
10123   node = vat_json_array_add (&vam->json_tree);
10124
10125   vat_json_init_object (node);
10126   vat_json_object_add_uint (node, "sw_if_index",
10127                             ntohl (mp->mt_tunnel.mt_sw_if_index));
10128
10129   vat_json_object_add_uint (node, "l2_only", mp->mt_tunnel.mt_l2_only);
10130
10131   fp = mp->mt_tunnel.mt_paths;
10132   for (i = 0; i < count; i++)
10133     {
10134       vl_api_mpls_fib_path_json_print (node, fp);
10135       fp++;
10136     }
10137 }
10138
10139 static int
10140 api_mpls_tunnel_dump (vat_main_t * vam)
10141 {
10142   vl_api_mpls_tunnel_dump_t *mp;
10143   vl_api_control_ping_t *mp_ping;
10144   int ret;
10145
10146   M (MPLS_TUNNEL_DUMP, mp);
10147
10148   S (mp);
10149
10150   /* Use a control ping for synchronization */
10151   MPING (CONTROL_PING, mp_ping);
10152   S (mp_ping);
10153
10154   W (ret);
10155   return ret;
10156 }
10157
10158 #define vl_api_mpls_table_details_t_endian vl_noop_handler
10159 #define vl_api_mpls_table_details_t_print vl_noop_handler
10160
10161
10162 static void
10163 vl_api_mpls_table_details_t_handler (vl_api_mpls_table_details_t * mp)
10164 {
10165   vat_main_t *vam = &vat_main;
10166
10167   print (vam->ofp, "table-id %d,", ntohl (mp->mt_table.mt_table_id));
10168 }
10169
10170 static void vl_api_mpls_table_details_t_handler_json
10171   (vl_api_mpls_table_details_t * mp)
10172 {
10173   vat_main_t *vam = &vat_main;
10174   vat_json_node_t *node = NULL;
10175
10176   if (VAT_JSON_ARRAY != vam->json_tree.type)
10177     {
10178       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
10179       vat_json_init_array (&vam->json_tree);
10180     }
10181   node = vat_json_array_add (&vam->json_tree);
10182
10183   vat_json_init_object (node);
10184   vat_json_object_add_uint (node, "table", ntohl (mp->mt_table.mt_table_id));
10185 }
10186
10187 static int
10188 api_mpls_table_dump (vat_main_t * vam)
10189 {
10190   vl_api_mpls_table_dump_t *mp;
10191   vl_api_control_ping_t *mp_ping;
10192   int ret;
10193
10194   M (MPLS_TABLE_DUMP, mp);
10195   S (mp);
10196
10197   /* Use a control ping for synchronization */
10198   MPING (CONTROL_PING, mp_ping);
10199   S (mp_ping);
10200
10201   W (ret);
10202   return ret;
10203 }
10204
10205 #define vl_api_mpls_route_details_t_endian vl_noop_handler
10206 #define vl_api_mpls_route_details_t_print vl_noop_handler
10207
10208 static void
10209 vl_api_mpls_route_details_t_handler (vl_api_mpls_route_details_t * mp)
10210 {
10211   vat_main_t *vam = &vat_main;
10212   int count = (int) clib_net_to_host_u32 (mp->mr_route.mr_n_paths);
10213   vl_api_fib_path_t *fp;
10214   int i;
10215
10216   print (vam->ofp,
10217          "table-id %d, label %u, ess_bit %u",
10218          ntohl (mp->mr_route.mr_table_id),
10219          ntohl (mp->mr_route.mr_label), mp->mr_route.mr_eos);
10220   fp = mp->mr_route.mr_paths;
10221   for (i = 0; i < count; i++)
10222     {
10223       vl_api_fib_path_print (vam, fp);
10224       fp++;
10225     }
10226 }
10227
10228 static void vl_api_mpls_route_details_t_handler_json
10229   (vl_api_mpls_route_details_t * mp)
10230 {
10231   vat_main_t *vam = &vat_main;
10232   int count = (int) clib_host_to_net_u32 (mp->mr_route.mr_n_paths);
10233   vat_json_node_t *node = NULL;
10234   vl_api_fib_path_t *fp;
10235   int i;
10236
10237   if (VAT_JSON_ARRAY != vam->json_tree.type)
10238     {
10239       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
10240       vat_json_init_array (&vam->json_tree);
10241     }
10242   node = vat_json_array_add (&vam->json_tree);
10243
10244   vat_json_init_object (node);
10245   vat_json_object_add_uint (node, "table", ntohl (mp->mr_route.mr_table_id));
10246   vat_json_object_add_uint (node, "s_bit", mp->mr_route.mr_eos);
10247   vat_json_object_add_uint (node, "label", ntohl (mp->mr_route.mr_label));
10248   vat_json_object_add_uint (node, "path_count", count);
10249   fp = mp->mr_route.mr_paths;
10250   for (i = 0; i < count; i++)
10251     {
10252       vl_api_mpls_fib_path_json_print (node, fp);
10253       fp++;
10254     }
10255 }
10256
10257 static int
10258 api_mpls_route_dump (vat_main_t * vam)
10259 {
10260   unformat_input_t *input = vam->input;
10261   vl_api_mpls_route_dump_t *mp;
10262   vl_api_control_ping_t *mp_ping;
10263   u32 table_id;
10264   int ret;
10265
10266   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
10267     {
10268       if (unformat (input, "table_id %d", &table_id))
10269         ;
10270       else
10271         break;
10272     }
10273   if (table_id == ~0)
10274     {
10275       errmsg ("missing table id");
10276       return -99;
10277     }
10278
10279   M (MPLS_ROUTE_DUMP, mp);
10280
10281   mp->table.mt_table_id = ntohl (table_id);
10282   S (mp);
10283
10284   /* Use a control ping for synchronization */
10285   MPING (CONTROL_PING, mp_ping);
10286   S (mp_ping);
10287
10288   W (ret);
10289   return ret;
10290 }
10291
10292 #define vl_api_ip_table_details_t_endian vl_noop_handler
10293 #define vl_api_ip_table_details_t_print vl_noop_handler
10294
10295 static void
10296 vl_api_ip_table_details_t_handler (vl_api_ip_table_details_t * mp)
10297 {
10298   vat_main_t *vam = &vat_main;
10299
10300   print (vam->ofp,
10301          "%s; table-id %d, prefix %U/%d",
10302          mp->table.name, ntohl (mp->table.table_id));
10303 }
10304
10305
10306 static void vl_api_ip_table_details_t_handler_json
10307   (vl_api_ip_table_details_t * mp)
10308 {
10309   vat_main_t *vam = &vat_main;
10310   vat_json_node_t *node = NULL;
10311
10312   if (VAT_JSON_ARRAY != vam->json_tree.type)
10313     {
10314       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
10315       vat_json_init_array (&vam->json_tree);
10316     }
10317   node = vat_json_array_add (&vam->json_tree);
10318
10319   vat_json_init_object (node);
10320   vat_json_object_add_uint (node, "table", ntohl (mp->table.table_id));
10321 }
10322
10323 static int
10324 api_ip_table_dump (vat_main_t * vam)
10325 {
10326   vl_api_ip_table_dump_t *mp;
10327   vl_api_control_ping_t *mp_ping;
10328   int ret;
10329
10330   M (IP_TABLE_DUMP, mp);
10331   S (mp);
10332
10333   /* Use a control ping for synchronization */
10334   MPING (CONTROL_PING, mp_ping);
10335   S (mp_ping);
10336
10337   W (ret);
10338   return ret;
10339 }
10340
10341 static int
10342 api_ip_mtable_dump (vat_main_t * vam)
10343 {
10344   vl_api_ip_mtable_dump_t *mp;
10345   vl_api_control_ping_t *mp_ping;
10346   int ret;
10347
10348   M (IP_MTABLE_DUMP, mp);
10349   S (mp);
10350
10351   /* Use a control ping for synchronization */
10352   MPING (CONTROL_PING, mp_ping);
10353   S (mp_ping);
10354
10355   W (ret);
10356   return ret;
10357 }
10358
10359 static int
10360 api_ip_mroute_dump (vat_main_t * vam)
10361 {
10362   unformat_input_t *input = vam->input;
10363   vl_api_control_ping_t *mp_ping;
10364   vl_api_ip_mroute_dump_t *mp;
10365   int ret, is_ip6;
10366   u32 table_id;
10367
10368   is_ip6 = 0;
10369   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
10370     {
10371       if (unformat (input, "table_id %d", &table_id))
10372         ;
10373       else if (unformat (input, "ip6"))
10374         is_ip6 = 1;
10375       else if (unformat (input, "ip4"))
10376         is_ip6 = 0;
10377       else
10378         break;
10379     }
10380   if (table_id == ~0)
10381     {
10382       errmsg ("missing table id");
10383       return -99;
10384     }
10385
10386   M (IP_MROUTE_DUMP, mp);
10387   mp->table.table_id = table_id;
10388   mp->table.is_ip6 = is_ip6;
10389   S (mp);
10390
10391   /* Use a control ping for synchronization */
10392   MPING (CONTROL_PING, mp_ping);
10393   S (mp_ping);
10394
10395   W (ret);
10396   return ret;
10397 }
10398
10399 #define vl_api_ip_route_details_t_endian vl_noop_handler
10400 #define vl_api_ip_route_details_t_print vl_noop_handler
10401
10402 static void
10403 vl_api_ip_route_details_t_handler (vl_api_ip_route_details_t * mp)
10404 {
10405   vat_main_t *vam = &vat_main;
10406   u8 count = mp->route.n_paths;
10407   vl_api_fib_path_t *fp;
10408   int i;
10409
10410   print (vam->ofp,
10411          "table-id %d, prefix %U/%d",
10412          ntohl (mp->route.table_id),
10413          format_ip46_address, mp->route.prefix.address, mp->route.prefix.len);
10414   for (i = 0; i < count; i++)
10415     {
10416       fp = &mp->route.paths[i];
10417
10418       vl_api_fib_path_print (vam, fp);
10419       fp++;
10420     }
10421 }
10422
10423 static void vl_api_ip_route_details_t_handler_json
10424   (vl_api_ip_route_details_t * mp)
10425 {
10426   vat_main_t *vam = &vat_main;
10427   u8 count = mp->route.n_paths;
10428   vat_json_node_t *node = NULL;
10429   struct in_addr ip4;
10430   struct in6_addr ip6;
10431   vl_api_fib_path_t *fp;
10432   int i;
10433
10434   if (VAT_JSON_ARRAY != vam->json_tree.type)
10435     {
10436       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
10437       vat_json_init_array (&vam->json_tree);
10438     }
10439   node = vat_json_array_add (&vam->json_tree);
10440
10441   vat_json_init_object (node);
10442   vat_json_object_add_uint (node, "table", ntohl (mp->route.table_id));
10443   if (ADDRESS_IP6 == mp->route.prefix.address.af)
10444     {
10445       clib_memcpy (&ip6, &mp->route.prefix.address.un.ip6, sizeof (ip6));
10446       vat_json_object_add_ip6 (node, "prefix", ip6);
10447     }
10448   else
10449     {
10450       clib_memcpy (&ip4, &mp->route.prefix.address.un.ip4, sizeof (ip4));
10451       vat_json_object_add_ip4 (node, "prefix", ip4);
10452     }
10453   vat_json_object_add_uint (node, "mask_length", mp->route.prefix.len);
10454   vat_json_object_add_uint (node, "path_count", count);
10455   for (i = 0; i < count; i++)
10456     {
10457       fp = &mp->route.paths[i];
10458       vl_api_mpls_fib_path_json_print (node, fp);
10459     }
10460 }
10461
10462 static int
10463 api_ip_route_dump (vat_main_t * vam)
10464 {
10465   unformat_input_t *input = vam->input;
10466   vl_api_ip_route_dump_t *mp;
10467   vl_api_control_ping_t *mp_ping;
10468   u32 table_id;
10469   u8 is_ip6;
10470   int ret;
10471
10472   is_ip6 = 0;
10473   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
10474     {
10475       if (unformat (input, "table_id %d", &table_id))
10476         ;
10477       else if (unformat (input, "ip6"))
10478         is_ip6 = 1;
10479       else if (unformat (input, "ip4"))
10480         is_ip6 = 0;
10481       else
10482         break;
10483     }
10484   if (table_id == ~0)
10485     {
10486       errmsg ("missing table id");
10487       return -99;
10488     }
10489
10490   M (IP_ROUTE_DUMP, mp);
10491
10492   mp->table.table_id = table_id;
10493   mp->table.is_ip6 = is_ip6;
10494
10495   S (mp);
10496
10497   /* Use a control ping for synchronization */
10498   MPING (CONTROL_PING, mp_ping);
10499   S (mp_ping);
10500
10501   W (ret);
10502   return ret;
10503 }
10504
10505 static void
10506 vl_api_ipfix_exporter_details_t_handler (vl_api_ipfix_exporter_details_t * mp)
10507 {
10508   vat_main_t *vam = &vat_main;
10509
10510   print (vam->ofp, "collector_address %U, collector_port %d, "
10511          "src_address %U, vrf_id %d, path_mtu %u, "
10512          "template_interval %u, udp_checksum %d",
10513          format_ip4_address, mp->collector_address,
10514          ntohs (mp->collector_port),
10515          format_ip4_address, mp->src_address,
10516          ntohl (mp->vrf_id), ntohl (mp->path_mtu),
10517          ntohl (mp->template_interval), mp->udp_checksum);
10518
10519   vam->retval = 0;
10520   vam->result_ready = 1;
10521 }
10522
10523 static void
10524   vl_api_ipfix_exporter_details_t_handler_json
10525   (vl_api_ipfix_exporter_details_t * mp)
10526 {
10527   vat_main_t *vam = &vat_main;
10528   vat_json_node_t node;
10529   struct in_addr collector_address;
10530   struct in_addr src_address;
10531
10532   vat_json_init_object (&node);
10533   clib_memcpy (&collector_address, &mp->collector_address,
10534                sizeof (collector_address));
10535   vat_json_object_add_ip4 (&node, "collector_address", collector_address);
10536   vat_json_object_add_uint (&node, "collector_port",
10537                             ntohs (mp->collector_port));
10538   clib_memcpy (&src_address, &mp->src_address, sizeof (src_address));
10539   vat_json_object_add_ip4 (&node, "src_address", src_address);
10540   vat_json_object_add_int (&node, "vrf_id", ntohl (mp->vrf_id));
10541   vat_json_object_add_uint (&node, "path_mtu", ntohl (mp->path_mtu));
10542   vat_json_object_add_uint (&node, "template_interval",
10543                             ntohl (mp->template_interval));
10544   vat_json_object_add_int (&node, "udp_checksum", mp->udp_checksum);
10545
10546   vat_json_print (vam->ofp, &node);
10547   vat_json_free (&node);
10548   vam->retval = 0;
10549   vam->result_ready = 1;
10550 }
10551
10552 int
10553 api_ipfix_exporter_dump (vat_main_t * vam)
10554 {
10555   vl_api_ipfix_exporter_dump_t *mp;
10556   int ret;
10557
10558   /* Construct the API message */
10559   M (IPFIX_EXPORTER_DUMP, mp);
10560   mp->context = 0;
10561
10562   S (mp);
10563   W (ret);
10564   return ret;
10565 }
10566
10567 static int
10568 api_ipfix_classify_stream_dump (vat_main_t * vam)
10569 {
10570   vl_api_ipfix_classify_stream_dump_t *mp;
10571   int ret;
10572
10573   /* Construct the API message */
10574   M (IPFIX_CLASSIFY_STREAM_DUMP, mp);
10575   mp->context = 0;
10576
10577   S (mp);
10578   W (ret);
10579   return ret;
10580   /* NOTREACHED */
10581   return 0;
10582 }
10583
10584 static void
10585   vl_api_ipfix_classify_stream_details_t_handler
10586   (vl_api_ipfix_classify_stream_details_t * mp)
10587 {
10588   vat_main_t *vam = &vat_main;
10589   print (vam->ofp, "domain_id %d, src_port %d",
10590          ntohl (mp->domain_id), ntohs (mp->src_port));
10591   vam->retval = 0;
10592   vam->result_ready = 1;
10593 }
10594
10595 static void
10596   vl_api_ipfix_classify_stream_details_t_handler_json
10597   (vl_api_ipfix_classify_stream_details_t * mp)
10598 {
10599   vat_main_t *vam = &vat_main;
10600   vat_json_node_t node;
10601
10602   vat_json_init_object (&node);
10603   vat_json_object_add_uint (&node, "domain_id", ntohl (mp->domain_id));
10604   vat_json_object_add_uint (&node, "src_port", ntohs (mp->src_port));
10605
10606   vat_json_print (vam->ofp, &node);
10607   vat_json_free (&node);
10608   vam->retval = 0;
10609   vam->result_ready = 1;
10610 }
10611
10612 static int
10613 api_ipfix_classify_table_dump (vat_main_t * vam)
10614 {
10615   vl_api_ipfix_classify_table_dump_t *mp;
10616   vl_api_control_ping_t *mp_ping;
10617   int ret;
10618
10619   if (!vam->json_output)
10620     {
10621       print (vam->ofp, "%15s%15s%20s", "table_id", "ip_version",
10622              "transport_protocol");
10623     }
10624
10625   /* Construct the API message */
10626   M (IPFIX_CLASSIFY_TABLE_DUMP, mp);
10627
10628   /* send it... */
10629   S (mp);
10630
10631   /* Use a control ping for synchronization */
10632   MPING (CONTROL_PING, mp_ping);
10633   S (mp_ping);
10634
10635   W (ret);
10636   return ret;
10637 }
10638
10639 static void
10640   vl_api_ipfix_classify_table_details_t_handler
10641   (vl_api_ipfix_classify_table_details_t * mp)
10642 {
10643   vat_main_t *vam = &vat_main;
10644   print (vam->ofp, "%15d%15d%20d", ntohl (mp->table_id), mp->ip_version,
10645          mp->transport_protocol);
10646 }
10647
10648 static void
10649   vl_api_ipfix_classify_table_details_t_handler_json
10650   (vl_api_ipfix_classify_table_details_t * mp)
10651 {
10652   vat_json_node_t *node = NULL;
10653   vat_main_t *vam = &vat_main;
10654
10655   if (VAT_JSON_ARRAY != vam->json_tree.type)
10656     {
10657       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
10658       vat_json_init_array (&vam->json_tree);
10659     }
10660
10661   node = vat_json_array_add (&vam->json_tree);
10662   vat_json_init_object (node);
10663
10664   vat_json_object_add_uint (node, "table_id", ntohl (mp->table_id));
10665   vat_json_object_add_uint (node, "ip_version", mp->ip_version);
10666   vat_json_object_add_uint (node, "transport_protocol",
10667                             mp->transport_protocol);
10668 }
10669
10670 static int
10671 api_sw_interface_span_enable_disable (vat_main_t * vam)
10672 {
10673   unformat_input_t *i = vam->input;
10674   vl_api_sw_interface_span_enable_disable_t *mp;
10675   u32 src_sw_if_index = ~0;
10676   u32 dst_sw_if_index = ~0;
10677   u8 state = 3;
10678   int ret;
10679   u8 is_l2 = 0;
10680
10681   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10682     {
10683       if (unformat
10684           (i, "src %U", api_unformat_sw_if_index, vam, &src_sw_if_index))
10685         ;
10686       else if (unformat (i, "src_sw_if_index %d", &src_sw_if_index))
10687         ;
10688       else
10689         if (unformat
10690             (i, "dst %U", api_unformat_sw_if_index, vam, &dst_sw_if_index))
10691         ;
10692       else if (unformat (i, "dst_sw_if_index %d", &dst_sw_if_index))
10693         ;
10694       else if (unformat (i, "disable"))
10695         state = 0;
10696       else if (unformat (i, "rx"))
10697         state = 1;
10698       else if (unformat (i, "tx"))
10699         state = 2;
10700       else if (unformat (i, "both"))
10701         state = 3;
10702       else if (unformat (i, "l2"))
10703         is_l2 = 1;
10704       else
10705         break;
10706     }
10707
10708   M (SW_INTERFACE_SPAN_ENABLE_DISABLE, mp);
10709
10710   mp->sw_if_index_from = htonl (src_sw_if_index);
10711   mp->sw_if_index_to = htonl (dst_sw_if_index);
10712   mp->state = state;
10713   mp->is_l2 = is_l2;
10714
10715   S (mp);
10716   W (ret);
10717   return ret;
10718 }
10719
10720 static void
10721 vl_api_sw_interface_span_details_t_handler (vl_api_sw_interface_span_details_t
10722                                             * mp)
10723 {
10724   vat_main_t *vam = &vat_main;
10725   u8 *sw_if_from_name = 0;
10726   u8 *sw_if_to_name = 0;
10727   u32 sw_if_index_from = ntohl (mp->sw_if_index_from);
10728   u32 sw_if_index_to = ntohl (mp->sw_if_index_to);
10729   char *states[] = { "none", "rx", "tx", "both" };
10730   hash_pair_t *p;
10731
10732   /* *INDENT-OFF* */
10733   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
10734   ({
10735     if ((u32) p->value[0] == sw_if_index_from)
10736       {
10737         sw_if_from_name = (u8 *)(p->key);
10738         if (sw_if_to_name)
10739           break;
10740       }
10741     if ((u32) p->value[0] == sw_if_index_to)
10742       {
10743         sw_if_to_name = (u8 *)(p->key);
10744         if (sw_if_from_name)
10745           break;
10746       }
10747   }));
10748   /* *INDENT-ON* */
10749   print (vam->ofp, "%20s => %20s (%s) %s",
10750          sw_if_from_name, sw_if_to_name, states[mp->state],
10751          mp->is_l2 ? "l2" : "device");
10752 }
10753
10754 static void
10755   vl_api_sw_interface_span_details_t_handler_json
10756   (vl_api_sw_interface_span_details_t * mp)
10757 {
10758   vat_main_t *vam = &vat_main;
10759   vat_json_node_t *node = NULL;
10760   u8 *sw_if_from_name = 0;
10761   u8 *sw_if_to_name = 0;
10762   u32 sw_if_index_from = ntohl (mp->sw_if_index_from);
10763   u32 sw_if_index_to = ntohl (mp->sw_if_index_to);
10764   hash_pair_t *p;
10765
10766   /* *INDENT-OFF* */
10767   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
10768   ({
10769     if ((u32) p->value[0] == sw_if_index_from)
10770       {
10771         sw_if_from_name = (u8 *)(p->key);
10772         if (sw_if_to_name)
10773           break;
10774       }
10775     if ((u32) p->value[0] == sw_if_index_to)
10776       {
10777         sw_if_to_name = (u8 *)(p->key);
10778         if (sw_if_from_name)
10779           break;
10780       }
10781   }));
10782   /* *INDENT-ON* */
10783
10784   if (VAT_JSON_ARRAY != vam->json_tree.type)
10785     {
10786       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
10787       vat_json_init_array (&vam->json_tree);
10788     }
10789   node = vat_json_array_add (&vam->json_tree);
10790
10791   vat_json_init_object (node);
10792   vat_json_object_add_uint (node, "src-if-index", sw_if_index_from);
10793   vat_json_object_add_string_copy (node, "src-if-name", sw_if_from_name);
10794   vat_json_object_add_uint (node, "dst-if-index", sw_if_index_to);
10795   if (0 != sw_if_to_name)
10796     {
10797       vat_json_object_add_string_copy (node, "dst-if-name", sw_if_to_name);
10798     }
10799   vat_json_object_add_uint (node, "state", mp->state);
10800   vat_json_object_add_uint (node, "is-l2", mp->is_l2);
10801 }
10802
10803 static int
10804 api_sw_interface_span_dump (vat_main_t * vam)
10805 {
10806   unformat_input_t *input = vam->input;
10807   vl_api_sw_interface_span_dump_t *mp;
10808   vl_api_control_ping_t *mp_ping;
10809   u8 is_l2 = 0;
10810   int ret;
10811
10812   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
10813     {
10814       if (unformat (input, "l2"))
10815         is_l2 = 1;
10816       else
10817         break;
10818     }
10819
10820   M (SW_INTERFACE_SPAN_DUMP, mp);
10821   mp->is_l2 = is_l2;
10822   S (mp);
10823
10824   /* Use a control ping for synchronization */
10825   MPING (CONTROL_PING, mp_ping);
10826   S (mp_ping);
10827
10828   W (ret);
10829   return ret;
10830 }
10831
10832 int
10833 api_pg_create_interface (vat_main_t * vam)
10834 {
10835   unformat_input_t *input = vam->input;
10836   vl_api_pg_create_interface_t *mp;
10837
10838   u32 if_id = ~0, gso_size = 0;
10839   u8 gso_enabled = 0;
10840   int ret;
10841   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
10842     {
10843       if (unformat (input, "if_id %d", &if_id))
10844         ;
10845       else if (unformat (input, "gso-enabled"))
10846         {
10847           gso_enabled = 1;
10848           if (unformat (input, "gso-size %u", &gso_size))
10849             ;
10850           else
10851             {
10852               errmsg ("missing gso-size");
10853               return -99;
10854             }
10855         }
10856       else
10857         break;
10858     }
10859   if (if_id == ~0)
10860     {
10861       errmsg ("missing pg interface index");
10862       return -99;
10863     }
10864
10865   /* Construct the API message */
10866   M (PG_CREATE_INTERFACE, mp);
10867   mp->context = 0;
10868   mp->interface_id = ntohl (if_id);
10869   mp->gso_enabled = gso_enabled;
10870
10871   S (mp);
10872   W (ret);
10873   return ret;
10874 }
10875
10876 int
10877 api_pg_capture (vat_main_t * vam)
10878 {
10879   unformat_input_t *input = vam->input;
10880   vl_api_pg_capture_t *mp;
10881
10882   u32 if_id = ~0;
10883   u8 enable = 1;
10884   u32 count = 1;
10885   u8 pcap_file_set = 0;
10886   u8 *pcap_file = 0;
10887   int ret;
10888   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
10889     {
10890       if (unformat (input, "if_id %d", &if_id))
10891         ;
10892       else if (unformat (input, "pcap %s", &pcap_file))
10893         pcap_file_set = 1;
10894       else if (unformat (input, "count %d", &count))
10895         ;
10896       else if (unformat (input, "disable"))
10897         enable = 0;
10898       else
10899         break;
10900     }
10901   if (if_id == ~0)
10902     {
10903       errmsg ("missing pg interface index");
10904       return -99;
10905     }
10906   if (pcap_file_set > 0)
10907     {
10908       if (vec_len (pcap_file) > 255)
10909         {
10910           errmsg ("pcap file name is too long");
10911           return -99;
10912         }
10913     }
10914
10915   /* Construct the API message */
10916   M (PG_CAPTURE, mp);
10917   mp->context = 0;
10918   mp->interface_id = ntohl (if_id);
10919   mp->is_enabled = enable;
10920   mp->count = ntohl (count);
10921   if (pcap_file_set != 0)
10922     {
10923       vl_api_vec_to_api_string (pcap_file, &mp->pcap_file_name);
10924     }
10925   vec_free (pcap_file);
10926
10927   S (mp);
10928   W (ret);
10929   return ret;
10930 }
10931
10932 int
10933 api_pg_enable_disable (vat_main_t * vam)
10934 {
10935   unformat_input_t *input = vam->input;
10936   vl_api_pg_enable_disable_t *mp;
10937
10938   u8 enable = 1;
10939   u8 stream_name_set = 0;
10940   u8 *stream_name = 0;
10941   int ret;
10942   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
10943     {
10944       if (unformat (input, "stream %s", &stream_name))
10945         stream_name_set = 1;
10946       else if (unformat (input, "disable"))
10947         enable = 0;
10948       else
10949         break;
10950     }
10951
10952   if (stream_name_set > 0)
10953     {
10954       if (vec_len (stream_name) > 255)
10955         {
10956           errmsg ("stream name too long");
10957           return -99;
10958         }
10959     }
10960
10961   /* Construct the API message */
10962   M (PG_ENABLE_DISABLE, mp);
10963   mp->context = 0;
10964   mp->is_enabled = enable;
10965   if (stream_name_set != 0)
10966     {
10967       vl_api_vec_to_api_string (stream_name, &mp->stream_name);
10968     }
10969   vec_free (stream_name);
10970
10971   S (mp);
10972   W (ret);
10973   return ret;
10974 }
10975
10976 int
10977 api_pg_interface_enable_disable_coalesce (vat_main_t * vam)
10978 {
10979   unformat_input_t *input = vam->input;
10980   vl_api_pg_interface_enable_disable_coalesce_t *mp;
10981
10982   u32 sw_if_index = ~0;
10983   u8 enable = 1;
10984   int ret;
10985   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
10986     {
10987       if (unformat (input, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10988         ;
10989       else if (unformat (input, "sw_if_index %d", &sw_if_index))
10990         ;
10991       else if (unformat (input, "disable"))
10992         enable = 0;
10993       else
10994         break;
10995     }
10996
10997   if (sw_if_index == ~0)
10998     {
10999       errmsg ("Interface required but not specified");
11000       return -99;
11001     }
11002
11003   /* Construct the API message */
11004   M (PG_INTERFACE_ENABLE_DISABLE_COALESCE, mp);
11005   mp->context = 0;
11006   mp->coalesce_enabled = enable;
11007   mp->sw_if_index = htonl (sw_if_index);
11008
11009   S (mp);
11010   W (ret);
11011   return ret;
11012 }
11013
11014 int
11015 api_ip_source_and_port_range_check_add_del (vat_main_t * vam)
11016 {
11017   unformat_input_t *input = vam->input;
11018   vl_api_ip_source_and_port_range_check_add_del_t *mp;
11019
11020   u16 *low_ports = 0;
11021   u16 *high_ports = 0;
11022   u16 this_low;
11023   u16 this_hi;
11024   vl_api_prefix_t prefix;
11025   u32 tmp, tmp2;
11026   u8 prefix_set = 0;
11027   u32 vrf_id = ~0;
11028   u8 is_add = 1;
11029   int ret;
11030
11031   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
11032     {
11033       if (unformat (input, "%U", unformat_vl_api_prefix, &prefix))
11034         prefix_set = 1;
11035       else if (unformat (input, "vrf %d", &vrf_id))
11036         ;
11037       else if (unformat (input, "del"))
11038         is_add = 0;
11039       else if (unformat (input, "port %d", &tmp))
11040         {
11041           if (tmp == 0 || tmp > 65535)
11042             {
11043               errmsg ("port %d out of range", tmp);
11044               return -99;
11045             }
11046           this_low = tmp;
11047           this_hi = this_low + 1;
11048           vec_add1 (low_ports, this_low);
11049           vec_add1 (high_ports, this_hi);
11050         }
11051       else if (unformat (input, "range %d - %d", &tmp, &tmp2))
11052         {
11053           if ((tmp > tmp2) || (tmp == 0) || (tmp2 > 65535))
11054             {
11055               errmsg ("incorrect range parameters");
11056               return -99;
11057             }
11058           this_low = tmp;
11059           /* Note: in debug CLI +1 is added to high before
11060              passing to real fn that does "the work"
11061              (ip_source_and_port_range_check_add_del).
11062              This fn is a wrapper around the binary API fn a
11063              control plane will call, which expects this increment
11064              to have occurred. Hence letting the binary API control
11065              plane fn do the increment for consistency between VAT
11066              and other control planes.
11067            */
11068           this_hi = tmp2;
11069           vec_add1 (low_ports, this_low);
11070           vec_add1 (high_ports, this_hi);
11071         }
11072       else
11073         break;
11074     }
11075
11076   if (prefix_set == 0)
11077     {
11078       errmsg ("<address>/<mask> not specified");
11079       return -99;
11080     }
11081
11082   if (vrf_id == ~0)
11083     {
11084       errmsg ("VRF ID required, not specified");
11085       return -99;
11086     }
11087
11088   if (vrf_id == 0)
11089     {
11090       errmsg
11091         ("VRF ID should not be default. Should be distinct VRF for this purpose.");
11092       return -99;
11093     }
11094
11095   if (vec_len (low_ports) == 0)
11096     {
11097       errmsg ("At least one port or port range required");
11098       return -99;
11099     }
11100
11101   M (IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL, mp);
11102
11103   mp->is_add = is_add;
11104
11105   clib_memcpy (&mp->prefix, &prefix, sizeof (prefix));
11106
11107   mp->number_of_ranges = vec_len (low_ports);
11108
11109   clib_memcpy (mp->low_ports, low_ports, vec_len (low_ports));
11110   vec_free (low_ports);
11111
11112   clib_memcpy (mp->high_ports, high_ports, vec_len (high_ports));
11113   vec_free (high_ports);
11114
11115   mp->vrf_id = ntohl (vrf_id);
11116
11117   S (mp);
11118   W (ret);
11119   return ret;
11120 }
11121
11122 int
11123 api_ip_source_and_port_range_check_interface_add_del (vat_main_t * vam)
11124 {
11125   unformat_input_t *input = vam->input;
11126   vl_api_ip_source_and_port_range_check_interface_add_del_t *mp;
11127   u32 sw_if_index = ~0;
11128   int vrf_set = 0;
11129   u32 tcp_out_vrf_id = ~0, udp_out_vrf_id = ~0;
11130   u32 tcp_in_vrf_id = ~0, udp_in_vrf_id = ~0;
11131   u8 is_add = 1;
11132   int ret;
11133
11134   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
11135     {
11136       if (unformat (input, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
11137         ;
11138       else if (unformat (input, "sw_if_index %d", &sw_if_index))
11139         ;
11140       else if (unformat (input, "tcp-out-vrf %d", &tcp_out_vrf_id))
11141         vrf_set = 1;
11142       else if (unformat (input, "udp-out-vrf %d", &udp_out_vrf_id))
11143         vrf_set = 1;
11144       else if (unformat (input, "tcp-in-vrf %d", &tcp_in_vrf_id))
11145         vrf_set = 1;
11146       else if (unformat (input, "udp-in-vrf %d", &udp_in_vrf_id))
11147         vrf_set = 1;
11148       else if (unformat (input, "del"))
11149         is_add = 0;
11150       else
11151         break;
11152     }
11153
11154   if (sw_if_index == ~0)
11155     {
11156       errmsg ("Interface required but not specified");
11157       return -99;
11158     }
11159
11160   if (vrf_set == 0)
11161     {
11162       errmsg ("VRF ID required but not specified");
11163       return -99;
11164     }
11165
11166   if (tcp_out_vrf_id == 0
11167       || udp_out_vrf_id == 0 || tcp_in_vrf_id == 0 || udp_in_vrf_id == 0)
11168     {
11169       errmsg
11170         ("VRF ID should not be default. Should be distinct VRF for this purpose.");
11171       return -99;
11172     }
11173
11174   /* Construct the API message */
11175   M (IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL, mp);
11176
11177   mp->sw_if_index = ntohl (sw_if_index);
11178   mp->is_add = is_add;
11179   mp->tcp_out_vrf_id = ntohl (tcp_out_vrf_id);
11180   mp->udp_out_vrf_id = ntohl (udp_out_vrf_id);
11181   mp->tcp_in_vrf_id = ntohl (tcp_in_vrf_id);
11182   mp->udp_in_vrf_id = ntohl (udp_in_vrf_id);
11183
11184   /* send it... */
11185   S (mp);
11186
11187   /* Wait for a reply... */
11188   W (ret);
11189   return ret;
11190 }
11191
11192 static int
11193 api_set_punt (vat_main_t * vam)
11194 {
11195   unformat_input_t *i = vam->input;
11196   vl_api_address_family_t af;
11197   vl_api_set_punt_t *mp;
11198   u32 protocol = ~0;
11199   u32 port = ~0;
11200   int is_add = 1;
11201   int ret;
11202
11203   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11204     {
11205       if (unformat (i, "%U", unformat_vl_api_address_family, &af))
11206         ;
11207       else if (unformat (i, "protocol %d", &protocol))
11208         ;
11209       else if (unformat (i, "port %d", &port))
11210         ;
11211       else if (unformat (i, "del"))
11212         is_add = 0;
11213       else
11214         {
11215           clib_warning ("parse error '%U'", format_unformat_error, i);
11216           return -99;
11217         }
11218     }
11219
11220   M (SET_PUNT, mp);
11221
11222   mp->is_add = (u8) is_add;
11223   mp->punt.type = PUNT_API_TYPE_L4;
11224   mp->punt.punt.l4.af = af;
11225   mp->punt.punt.l4.protocol = (u8) protocol;
11226   mp->punt.punt.l4.port = htons ((u16) port);
11227
11228   S (mp);
11229   W (ret);
11230   return ret;
11231 }
11232
11233 static int
11234 api_delete_subif (vat_main_t * vam)
11235 {
11236   unformat_input_t *i = vam->input;
11237   vl_api_delete_subif_t *mp;
11238   u32 sw_if_index = ~0;
11239   int ret;
11240
11241   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11242     {
11243       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
11244         ;
11245       if (unformat (i, "sw_if_index %d", &sw_if_index))
11246         ;
11247       else
11248         break;
11249     }
11250
11251   if (sw_if_index == ~0)
11252     {
11253       errmsg ("missing sw_if_index");
11254       return -99;
11255     }
11256
11257   /* Construct the API message */
11258   M (DELETE_SUBIF, mp);
11259   mp->sw_if_index = ntohl (sw_if_index);
11260
11261   S (mp);
11262   W (ret);
11263   return ret;
11264 }
11265
11266 #define foreach_pbb_vtr_op      \
11267 _("disable",  L2_VTR_DISABLED)  \
11268 _("pop",  L2_VTR_POP_2)         \
11269 _("push",  L2_VTR_PUSH_2)
11270
11271 static int
11272 api_l2_interface_pbb_tag_rewrite (vat_main_t * vam)
11273 {
11274   unformat_input_t *i = vam->input;
11275   vl_api_l2_interface_pbb_tag_rewrite_t *mp;
11276   u32 sw_if_index = ~0, vtr_op = ~0;
11277   u16 outer_tag = ~0;
11278   u8 dmac[6], smac[6];
11279   u8 dmac_set = 0, smac_set = 0;
11280   u16 vlanid = 0;
11281   u32 sid = ~0;
11282   u32 tmp;
11283   int ret;
11284
11285   /* Shut up coverity */
11286   clib_memset (dmac, 0, sizeof (dmac));
11287   clib_memset (smac, 0, sizeof (smac));
11288
11289   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11290     {
11291       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
11292         ;
11293       else if (unformat (i, "sw_if_index %d", &sw_if_index))
11294         ;
11295       else if (unformat (i, "vtr_op %d", &vtr_op))
11296         ;
11297 #define _(n,v) else if (unformat(i, n)) {vtr_op = v;}
11298       foreach_pbb_vtr_op
11299 #undef _
11300         else if (unformat (i, "translate_pbb_stag"))
11301         {
11302           if (unformat (i, "%d", &tmp))
11303             {
11304               vtr_op = L2_VTR_TRANSLATE_2_1;
11305               outer_tag = tmp;
11306             }
11307           else
11308             {
11309               errmsg
11310                 ("translate_pbb_stag operation requires outer tag definition");
11311               return -99;
11312             }
11313         }
11314       else if (unformat (i, "dmac %U", unformat_ethernet_address, dmac))
11315         dmac_set++;
11316       else if (unformat (i, "smac %U", unformat_ethernet_address, smac))
11317         smac_set++;
11318       else if (unformat (i, "sid %d", &sid))
11319         ;
11320       else if (unformat (i, "vlanid %d", &tmp))
11321         vlanid = tmp;
11322       else
11323         {
11324           clib_warning ("parse error '%U'", format_unformat_error, i);
11325           return -99;
11326         }
11327     }
11328
11329   if ((sw_if_index == ~0) || (vtr_op == ~0))
11330     {
11331       errmsg ("missing sw_if_index or vtr operation");
11332       return -99;
11333     }
11334   if (((vtr_op == L2_VTR_PUSH_2) || (vtr_op == L2_VTR_TRANSLATE_2_2))
11335       && ((dmac_set == 0) || (smac_set == 0) || (sid == ~0)))
11336     {
11337       errmsg
11338         ("push and translate_qinq operations require dmac, smac, sid and optionally vlanid");
11339       return -99;
11340     }
11341
11342   M (L2_INTERFACE_PBB_TAG_REWRITE, mp);
11343   mp->sw_if_index = ntohl (sw_if_index);
11344   mp->vtr_op = ntohl (vtr_op);
11345   mp->outer_tag = ntohs (outer_tag);
11346   clib_memcpy (mp->b_dmac, dmac, sizeof (dmac));
11347   clib_memcpy (mp->b_smac, smac, sizeof (smac));
11348   mp->b_vlanid = ntohs (vlanid);
11349   mp->i_sid = ntohl (sid);
11350
11351   S (mp);
11352   W (ret);
11353   return ret;
11354 }
11355
11356 static int
11357 api_feature_enable_disable (vat_main_t * vam)
11358 {
11359   unformat_input_t *i = vam->input;
11360   vl_api_feature_enable_disable_t *mp;
11361   u8 *arc_name = 0;
11362   u8 *feature_name = 0;
11363   u32 sw_if_index = ~0;
11364   u8 enable = 1;
11365   int ret;
11366
11367   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11368     {
11369       if (unformat (i, "arc_name %s", &arc_name))
11370         ;
11371       else if (unformat (i, "feature_name %s", &feature_name))
11372         ;
11373       else
11374         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
11375         ;
11376       else if (unformat (i, "sw_if_index %d", &sw_if_index))
11377         ;
11378       else if (unformat (i, "disable"))
11379         enable = 0;
11380       else
11381         break;
11382     }
11383
11384   if (arc_name == 0)
11385     {
11386       errmsg ("missing arc name");
11387       return -99;
11388     }
11389   if (vec_len (arc_name) > 63)
11390     {
11391       errmsg ("arc name too long");
11392     }
11393
11394   if (feature_name == 0)
11395     {
11396       errmsg ("missing feature name");
11397       return -99;
11398     }
11399   if (vec_len (feature_name) > 63)
11400     {
11401       errmsg ("feature name too long");
11402     }
11403
11404   if (sw_if_index == ~0)
11405     {
11406       errmsg ("missing interface name or sw_if_index");
11407       return -99;
11408     }
11409
11410   /* Construct the API message */
11411   M (FEATURE_ENABLE_DISABLE, mp);
11412   mp->sw_if_index = ntohl (sw_if_index);
11413   mp->enable = enable;
11414   clib_memcpy (mp->arc_name, arc_name, vec_len (arc_name));
11415   clib_memcpy (mp->feature_name, feature_name, vec_len (feature_name));
11416   vec_free (arc_name);
11417   vec_free (feature_name);
11418
11419   S (mp);
11420   W (ret);
11421   return ret;
11422 }
11423
11424 static int
11425 api_sw_interface_tag_add_del (vat_main_t * vam)
11426 {
11427   unformat_input_t *i = vam->input;
11428   vl_api_sw_interface_tag_add_del_t *mp;
11429   u32 sw_if_index = ~0;
11430   u8 *tag = 0;
11431   u8 enable = 1;
11432   int ret;
11433
11434   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11435     {
11436       if (unformat (i, "tag %s", &tag))
11437         ;
11438       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
11439         ;
11440       else if (unformat (i, "sw_if_index %d", &sw_if_index))
11441         ;
11442       else if (unformat (i, "del"))
11443         enable = 0;
11444       else
11445         break;
11446     }
11447
11448   if (sw_if_index == ~0)
11449     {
11450       errmsg ("missing interface name or sw_if_index");
11451       return -99;
11452     }
11453
11454   if (enable && (tag == 0))
11455     {
11456       errmsg ("no tag specified");
11457       return -99;
11458     }
11459
11460   /* Construct the API message */
11461   M (SW_INTERFACE_TAG_ADD_DEL, mp);
11462   mp->sw_if_index = ntohl (sw_if_index);
11463   mp->is_add = enable;
11464   if (enable)
11465     strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
11466   vec_free (tag);
11467
11468   S (mp);
11469   W (ret);
11470   return ret;
11471 }
11472
11473 static int
11474 api_sw_interface_add_del_mac_address (vat_main_t * vam)
11475 {
11476   unformat_input_t *i = vam->input;
11477   vl_api_mac_address_t mac = { 0 };
11478   vl_api_sw_interface_add_del_mac_address_t *mp;
11479   u32 sw_if_index = ~0;
11480   u8 is_add = 1;
11481   u8 mac_set = 0;
11482   int ret;
11483
11484   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11485     {
11486       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
11487         ;
11488       else if (unformat (i, "sw_if_index %d", &sw_if_index))
11489         ;
11490       else if (unformat (i, "%U", unformat_vl_api_mac_address, &mac))
11491         mac_set++;
11492       else if (unformat (i, "del"))
11493         is_add = 0;
11494       else
11495         break;
11496     }
11497
11498   if (sw_if_index == ~0)
11499     {
11500       errmsg ("missing interface name or sw_if_index");
11501       return -99;
11502     }
11503
11504   if (!mac_set)
11505     {
11506       errmsg ("missing MAC address");
11507       return -99;
11508     }
11509
11510   /* Construct the API message */
11511   M (SW_INTERFACE_ADD_DEL_MAC_ADDRESS, mp);
11512   mp->sw_if_index = ntohl (sw_if_index);
11513   mp->is_add = is_add;
11514   clib_memcpy (&mp->addr, &mac, sizeof (mac));
11515
11516   S (mp);
11517   W (ret);
11518   return ret;
11519 }
11520
11521 static void vl_api_l2_xconnect_details_t_handler
11522   (vl_api_l2_xconnect_details_t * mp)
11523 {
11524   vat_main_t *vam = &vat_main;
11525
11526   print (vam->ofp, "%15d%15d",
11527          ntohl (mp->rx_sw_if_index), ntohl (mp->tx_sw_if_index));
11528 }
11529
11530 static void vl_api_l2_xconnect_details_t_handler_json
11531   (vl_api_l2_xconnect_details_t * mp)
11532 {
11533   vat_main_t *vam = &vat_main;
11534   vat_json_node_t *node = NULL;
11535
11536   if (VAT_JSON_ARRAY != vam->json_tree.type)
11537     {
11538       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
11539       vat_json_init_array (&vam->json_tree);
11540     }
11541   node = vat_json_array_add (&vam->json_tree);
11542
11543   vat_json_init_object (node);
11544   vat_json_object_add_uint (node, "rx_sw_if_index",
11545                             ntohl (mp->rx_sw_if_index));
11546   vat_json_object_add_uint (node, "tx_sw_if_index",
11547                             ntohl (mp->tx_sw_if_index));
11548 }
11549
11550 static int
11551 api_l2_xconnect_dump (vat_main_t * vam)
11552 {
11553   vl_api_l2_xconnect_dump_t *mp;
11554   vl_api_control_ping_t *mp_ping;
11555   int ret;
11556
11557   if (!vam->json_output)
11558     {
11559       print (vam->ofp, "%15s%15s", "rx_sw_if_index", "tx_sw_if_index");
11560     }
11561
11562   M (L2_XCONNECT_DUMP, mp);
11563
11564   S (mp);
11565
11566   /* Use a control ping for synchronization */
11567   MPING (CONTROL_PING, mp_ping);
11568   S (mp_ping);
11569
11570   W (ret);
11571   return ret;
11572 }
11573
11574 static int
11575 api_hw_interface_set_mtu (vat_main_t * vam)
11576 {
11577   unformat_input_t *i = vam->input;
11578   vl_api_hw_interface_set_mtu_t *mp;
11579   u32 sw_if_index = ~0;
11580   u32 mtu = 0;
11581   int ret;
11582
11583   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11584     {
11585       if (unformat (i, "mtu %d", &mtu))
11586         ;
11587       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
11588         ;
11589       else if (unformat (i, "sw_if_index %d", &sw_if_index))
11590         ;
11591       else
11592         break;
11593     }
11594
11595   if (sw_if_index == ~0)
11596     {
11597       errmsg ("missing interface name or sw_if_index");
11598       return -99;
11599     }
11600
11601   if (mtu == 0)
11602     {
11603       errmsg ("no mtu specified");
11604       return -99;
11605     }
11606
11607   /* Construct the API message */
11608   M (HW_INTERFACE_SET_MTU, mp);
11609   mp->sw_if_index = ntohl (sw_if_index);
11610   mp->mtu = ntohs ((u16) mtu);
11611
11612   S (mp);
11613   W (ret);
11614   return ret;
11615 }
11616
11617 static int
11618 api_p2p_ethernet_add (vat_main_t * vam)
11619 {
11620   unformat_input_t *i = vam->input;
11621   vl_api_p2p_ethernet_add_t *mp;
11622   u32 parent_if_index = ~0;
11623   u32 sub_id = ~0;
11624   u8 remote_mac[6];
11625   u8 mac_set = 0;
11626   int ret;
11627
11628   clib_memset (remote_mac, 0, sizeof (remote_mac));
11629   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11630     {
11631       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &parent_if_index))
11632         ;
11633       else if (unformat (i, "sw_if_index %d", &parent_if_index))
11634         ;
11635       else
11636         if (unformat
11637             (i, "remote_mac %U", unformat_ethernet_address, remote_mac))
11638         mac_set++;
11639       else if (unformat (i, "sub_id %d", &sub_id))
11640         ;
11641       else
11642         {
11643           clib_warning ("parse error '%U'", format_unformat_error, i);
11644           return -99;
11645         }
11646     }
11647
11648   if (parent_if_index == ~0)
11649     {
11650       errmsg ("missing interface name or sw_if_index");
11651       return -99;
11652     }
11653   if (mac_set == 0)
11654     {
11655       errmsg ("missing remote mac address");
11656       return -99;
11657     }
11658   if (sub_id == ~0)
11659     {
11660       errmsg ("missing sub-interface id");
11661       return -99;
11662     }
11663
11664   M (P2P_ETHERNET_ADD, mp);
11665   mp->parent_if_index = ntohl (parent_if_index);
11666   mp->subif_id = ntohl (sub_id);
11667   clib_memcpy (mp->remote_mac, remote_mac, sizeof (remote_mac));
11668
11669   S (mp);
11670   W (ret);
11671   return ret;
11672 }
11673
11674 static int
11675 api_p2p_ethernet_del (vat_main_t * vam)
11676 {
11677   unformat_input_t *i = vam->input;
11678   vl_api_p2p_ethernet_del_t *mp;
11679   u32 parent_if_index = ~0;
11680   u8 remote_mac[6];
11681   u8 mac_set = 0;
11682   int ret;
11683
11684   clib_memset (remote_mac, 0, sizeof (remote_mac));
11685   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11686     {
11687       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &parent_if_index))
11688         ;
11689       else if (unformat (i, "sw_if_index %d", &parent_if_index))
11690         ;
11691       else
11692         if (unformat
11693             (i, "remote_mac %U", unformat_ethernet_address, remote_mac))
11694         mac_set++;
11695       else
11696         {
11697           clib_warning ("parse error '%U'", format_unformat_error, i);
11698           return -99;
11699         }
11700     }
11701
11702   if (parent_if_index == ~0)
11703     {
11704       errmsg ("missing interface name or sw_if_index");
11705       return -99;
11706     }
11707   if (mac_set == 0)
11708     {
11709       errmsg ("missing remote mac address");
11710       return -99;
11711     }
11712
11713   M (P2P_ETHERNET_DEL, mp);
11714   mp->parent_if_index = ntohl (parent_if_index);
11715   clib_memcpy (mp->remote_mac, remote_mac, sizeof (remote_mac));
11716
11717   S (mp);
11718   W (ret);
11719   return ret;
11720 }
11721
11722 static int
11723 api_tcp_configure_src_addresses (vat_main_t * vam)
11724 {
11725   vl_api_tcp_configure_src_addresses_t *mp;
11726   unformat_input_t *i = vam->input;
11727   vl_api_address_t first, last;
11728   u8 range_set = 0;
11729   u32 vrf_id = 0;
11730   int ret;
11731
11732   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11733     {
11734       if (unformat (i, "%U - %U",
11735                     unformat_vl_api_address, &first,
11736                     unformat_vl_api_address, &last))
11737         {
11738           if (range_set)
11739             {
11740               errmsg ("one range per message (range already set)");
11741               return -99;
11742             }
11743           range_set = 1;
11744         }
11745       else if (unformat (i, "vrf %d", &vrf_id))
11746         ;
11747       else
11748         break;
11749     }
11750
11751   if (range_set == 0)
11752     {
11753       errmsg ("address range not set");
11754       return -99;
11755     }
11756
11757   M (TCP_CONFIGURE_SRC_ADDRESSES, mp);
11758
11759   mp->vrf_id = ntohl (vrf_id);
11760   clib_memcpy (&mp->first_address, &first, sizeof (first));
11761   clib_memcpy (&mp->last_address, &last, sizeof (last));
11762
11763   S (mp);
11764   W (ret);
11765   return ret;
11766 }
11767
11768 static void vl_api_app_namespace_add_del_reply_t_handler
11769   (vl_api_app_namespace_add_del_reply_t * mp)
11770 {
11771   vat_main_t *vam = &vat_main;
11772   i32 retval = ntohl (mp->retval);
11773   if (vam->async_mode)
11774     {
11775       vam->async_errors += (retval < 0);
11776     }
11777   else
11778     {
11779       vam->retval = retval;
11780       if (retval == 0)
11781         errmsg ("app ns index %d\n", ntohl (mp->appns_index));
11782       vam->result_ready = 1;
11783     }
11784 }
11785
11786 static void vl_api_app_namespace_add_del_reply_t_handler_json
11787   (vl_api_app_namespace_add_del_reply_t * mp)
11788 {
11789   vat_main_t *vam = &vat_main;
11790   vat_json_node_t node;
11791
11792   vat_json_init_object (&node);
11793   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
11794   vat_json_object_add_uint (&node, "appns_index", ntohl (mp->appns_index));
11795
11796   vat_json_print (vam->ofp, &node);
11797   vat_json_free (&node);
11798
11799   vam->retval = ntohl (mp->retval);
11800   vam->result_ready = 1;
11801 }
11802
11803 static int
11804 api_app_namespace_add_del (vat_main_t * vam)
11805 {
11806   vl_api_app_namespace_add_del_t *mp;
11807   unformat_input_t *i = vam->input;
11808   u8 *ns_id = 0, secret_set = 0, sw_if_index_set = 0;
11809   u32 sw_if_index, ip4_fib_id, ip6_fib_id;
11810   u64 secret;
11811   int ret;
11812
11813   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11814     {
11815       if (unformat (i, "id %_%v%_", &ns_id))
11816         ;
11817       else if (unformat (i, "secret %lu", &secret))
11818         secret_set = 1;
11819       else if (unformat (i, "sw_if_index %d", &sw_if_index))
11820         sw_if_index_set = 1;
11821       else if (unformat (i, "ip4_fib_id %d", &ip4_fib_id))
11822         ;
11823       else if (unformat (i, "ip6_fib_id %d", &ip6_fib_id))
11824         ;
11825       else
11826         break;
11827     }
11828   if (!ns_id || !secret_set || !sw_if_index_set)
11829     {
11830       errmsg ("namespace id, secret and sw_if_index must be set");
11831       return -99;
11832     }
11833   if (vec_len (ns_id) > 64)
11834     {
11835       errmsg ("namespace id too long");
11836       return -99;
11837     }
11838   M (APP_NAMESPACE_ADD_DEL, mp);
11839
11840   vl_api_vec_to_api_string (ns_id, &mp->namespace_id);
11841   mp->secret = clib_host_to_net_u64 (secret);
11842   mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
11843   mp->ip4_fib_id = clib_host_to_net_u32 (ip4_fib_id);
11844   mp->ip6_fib_id = clib_host_to_net_u32 (ip6_fib_id);
11845   vec_free (ns_id);
11846   S (mp);
11847   W (ret);
11848   return ret;
11849 }
11850
11851 static int
11852 api_sock_init_shm (vat_main_t * vam)
11853 {
11854 #if VPP_API_TEST_BUILTIN == 0
11855   unformat_input_t *i = vam->input;
11856   vl_api_shm_elem_config_t *config = 0;
11857   u64 size = 64 << 20;
11858   int rv;
11859
11860   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11861     {
11862       if (unformat (i, "size %U", unformat_memory_size, &size))
11863         ;
11864       else
11865         break;
11866     }
11867
11868   /*
11869    * Canned custom ring allocator config.
11870    * Should probably parse all of this
11871    */
11872   vec_validate (config, 6);
11873   config[0].type = VL_API_VLIB_RING;
11874   config[0].size = 256;
11875   config[0].count = 32;
11876
11877   config[1].type = VL_API_VLIB_RING;
11878   config[1].size = 1024;
11879   config[1].count = 16;
11880
11881   config[2].type = VL_API_VLIB_RING;
11882   config[2].size = 4096;
11883   config[2].count = 2;
11884
11885   config[3].type = VL_API_CLIENT_RING;
11886   config[3].size = 256;
11887   config[3].count = 32;
11888
11889   config[4].type = VL_API_CLIENT_RING;
11890   config[4].size = 1024;
11891   config[4].count = 16;
11892
11893   config[5].type = VL_API_CLIENT_RING;
11894   config[5].size = 4096;
11895   config[5].count = 2;
11896
11897   config[6].type = VL_API_QUEUE;
11898   config[6].count = 128;
11899   config[6].size = sizeof (uword);
11900
11901   rv = vl_socket_client_init_shm (config, 1 /* want_pthread */ );
11902   if (!rv)
11903     vam->client_index_invalid = 1;
11904   return rv;
11905 #else
11906   return -99;
11907 #endif
11908 }
11909
11910 static void
11911 vl_api_session_rules_details_t_handler (vl_api_session_rules_details_t * mp)
11912 {
11913   vat_main_t *vam = &vat_main;
11914   fib_prefix_t lcl, rmt;
11915
11916   ip_prefix_decode (&mp->lcl, &lcl);
11917   ip_prefix_decode (&mp->rmt, &rmt);
11918
11919   if (lcl.fp_proto == FIB_PROTOCOL_IP4)
11920     {
11921       print (vam->ofp,
11922              "appns %u tp %u scope %d %U/%d %d %U/%d %d action: %d tag: %s",
11923              clib_net_to_host_u32 (mp->appns_index), mp->transport_proto,
11924              mp->scope, format_ip4_address, &lcl.fp_addr.ip4, lcl.fp_len,
11925              clib_net_to_host_u16 (mp->lcl_port), format_ip4_address,
11926              &rmt.fp_addr.ip4, rmt.fp_len,
11927              clib_net_to_host_u16 (mp->rmt_port),
11928              clib_net_to_host_u32 (mp->action_index), mp->tag);
11929     }
11930   else
11931     {
11932       print (vam->ofp,
11933              "appns %u tp %u scope %d %U/%d %d %U/%d %d action: %d tag: %s",
11934              clib_net_to_host_u32 (mp->appns_index), mp->transport_proto,
11935              mp->scope, format_ip6_address, &lcl.fp_addr.ip6, lcl.fp_len,
11936              clib_net_to_host_u16 (mp->lcl_port), format_ip6_address,
11937              &rmt.fp_addr.ip6, rmt.fp_len,
11938              clib_net_to_host_u16 (mp->rmt_port),
11939              clib_net_to_host_u32 (mp->action_index), mp->tag);
11940     }
11941 }
11942
11943 static void
11944 vl_api_session_rules_details_t_handler_json (vl_api_session_rules_details_t *
11945                                              mp)
11946 {
11947   vat_main_t *vam = &vat_main;
11948   vat_json_node_t *node = NULL;
11949   struct in6_addr ip6;
11950   struct in_addr ip4;
11951
11952   fib_prefix_t lcl, rmt;
11953
11954   ip_prefix_decode (&mp->lcl, &lcl);
11955   ip_prefix_decode (&mp->rmt, &rmt);
11956
11957   if (VAT_JSON_ARRAY != vam->json_tree.type)
11958     {
11959       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
11960       vat_json_init_array (&vam->json_tree);
11961     }
11962   node = vat_json_array_add (&vam->json_tree);
11963   vat_json_init_object (node);
11964
11965   vat_json_object_add_uint (node, "appns_index",
11966                             clib_net_to_host_u32 (mp->appns_index));
11967   vat_json_object_add_uint (node, "transport_proto", mp->transport_proto);
11968   vat_json_object_add_uint (node, "scope", mp->scope);
11969   vat_json_object_add_uint (node, "action_index",
11970                             clib_net_to_host_u32 (mp->action_index));
11971   vat_json_object_add_uint (node, "lcl_port",
11972                             clib_net_to_host_u16 (mp->lcl_port));
11973   vat_json_object_add_uint (node, "rmt_port",
11974                             clib_net_to_host_u16 (mp->rmt_port));
11975   vat_json_object_add_uint (node, "lcl_plen", lcl.fp_len);
11976   vat_json_object_add_uint (node, "rmt_plen", rmt.fp_len);
11977   vat_json_object_add_string_copy (node, "tag", mp->tag);
11978   if (lcl.fp_proto == FIB_PROTOCOL_IP4)
11979     {
11980       clib_memcpy (&ip4, &lcl.fp_addr.ip4, sizeof (ip4));
11981       vat_json_object_add_ip4 (node, "lcl_ip", ip4);
11982       clib_memcpy (&ip4, &rmt.fp_addr.ip4, sizeof (ip4));
11983       vat_json_object_add_ip4 (node, "rmt_ip", ip4);
11984     }
11985   else
11986     {
11987       clib_memcpy (&ip6, &lcl.fp_addr.ip6, sizeof (ip6));
11988       vat_json_object_add_ip6 (node, "lcl_ip", ip6);
11989       clib_memcpy (&ip6, &rmt.fp_addr.ip6, sizeof (ip6));
11990       vat_json_object_add_ip6 (node, "rmt_ip", ip6);
11991     }
11992 }
11993
11994 static int
11995 api_session_rule_add_del (vat_main_t * vam)
11996 {
11997   vl_api_session_rule_add_del_t *mp;
11998   unformat_input_t *i = vam->input;
11999   u32 proto = ~0, lcl_port, rmt_port, action = 0, lcl_plen, rmt_plen;
12000   u32 appns_index = 0, scope = 0;
12001   ip4_address_t lcl_ip4, rmt_ip4;
12002   ip6_address_t lcl_ip6, rmt_ip6;
12003   u8 is_ip4 = 1, conn_set = 0;
12004   u8 is_add = 1, *tag = 0;
12005   int ret;
12006   fib_prefix_t lcl, rmt;
12007
12008   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
12009     {
12010       if (unformat (i, "del"))
12011         is_add = 0;
12012       else if (unformat (i, "add"))
12013         ;
12014       else if (unformat (i, "proto tcp"))
12015         proto = 0;
12016       else if (unformat (i, "proto udp"))
12017         proto = 1;
12018       else if (unformat (i, "appns %d", &appns_index))
12019         ;
12020       else if (unformat (i, "scope %d", &scope))
12021         ;
12022       else if (unformat (i, "tag %_%v%_", &tag))
12023         ;
12024       else
12025         if (unformat
12026             (i, "%U/%d %d %U/%d %d", unformat_ip4_address, &lcl_ip4,
12027              &lcl_plen, &lcl_port, unformat_ip4_address, &rmt_ip4, &rmt_plen,
12028              &rmt_port))
12029         {
12030           is_ip4 = 1;
12031           conn_set = 1;
12032         }
12033       else
12034         if (unformat
12035             (i, "%U/%d %d %U/%d %d", unformat_ip6_address, &lcl_ip6,
12036              &lcl_plen, &lcl_port, unformat_ip6_address, &rmt_ip6, &rmt_plen,
12037              &rmt_port))
12038         {
12039           is_ip4 = 0;
12040           conn_set = 1;
12041         }
12042       else if (unformat (i, "action %d", &action))
12043         ;
12044       else
12045         break;
12046     }
12047   if (proto == ~0 || !conn_set || action == ~0)
12048     {
12049       errmsg ("transport proto, connection and action must be set");
12050       return -99;
12051     }
12052
12053   if (scope > 3)
12054     {
12055       errmsg ("scope should be 0-3");
12056       return -99;
12057     }
12058
12059   M (SESSION_RULE_ADD_DEL, mp);
12060
12061   clib_memset (&lcl, 0, sizeof (lcl));
12062   clib_memset (&rmt, 0, sizeof (rmt));
12063   if (is_ip4)
12064     {
12065       ip_set (&lcl.fp_addr, &lcl_ip4, 1);
12066       ip_set (&rmt.fp_addr, &rmt_ip4, 1);
12067       lcl.fp_len = lcl_plen;
12068       rmt.fp_len = rmt_plen;
12069     }
12070   else
12071     {
12072       ip_set (&lcl.fp_addr, &lcl_ip6, 0);
12073       ip_set (&rmt.fp_addr, &rmt_ip6, 0);
12074       lcl.fp_len = lcl_plen;
12075       rmt.fp_len = rmt_plen;
12076     }
12077
12078
12079   ip_prefix_encode (&lcl, &mp->lcl);
12080   ip_prefix_encode (&rmt, &mp->rmt);
12081   mp->lcl_port = clib_host_to_net_u16 ((u16) lcl_port);
12082   mp->rmt_port = clib_host_to_net_u16 ((u16) rmt_port);
12083   mp->transport_proto =
12084     proto ? TRANSPORT_PROTO_API_UDP : TRANSPORT_PROTO_API_TCP;
12085   mp->action_index = clib_host_to_net_u32 (action);
12086   mp->appns_index = clib_host_to_net_u32 (appns_index);
12087   mp->scope = scope;
12088   mp->is_add = is_add;
12089   if (tag)
12090     {
12091       clib_memcpy (mp->tag, tag, vec_len (tag));
12092       vec_free (tag);
12093     }
12094
12095   S (mp);
12096   W (ret);
12097   return ret;
12098 }
12099
12100 static int
12101 api_session_rules_dump (vat_main_t * vam)
12102 {
12103   vl_api_session_rules_dump_t *mp;
12104   vl_api_control_ping_t *mp_ping;
12105   int ret;
12106
12107   if (!vam->json_output)
12108     {
12109       print (vam->ofp, "%=20s", "Session Rules");
12110     }
12111
12112   M (SESSION_RULES_DUMP, mp);
12113   /* send it... */
12114   S (mp);
12115
12116   /* Use a control ping for synchronization */
12117   MPING (CONTROL_PING, mp_ping);
12118   S (mp_ping);
12119
12120   /* Wait for a reply... */
12121   W (ret);
12122   return ret;
12123 }
12124
12125 static int
12126 api_ip_container_proxy_add_del (vat_main_t * vam)
12127 {
12128   vl_api_ip_container_proxy_add_del_t *mp;
12129   unformat_input_t *i = vam->input;
12130   u32 sw_if_index = ~0;
12131   vl_api_prefix_t pfx = { };
12132   u8 is_add = 1;
12133   int ret;
12134
12135   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
12136     {
12137       if (unformat (i, "del"))
12138         is_add = 0;
12139       else if (unformat (i, "add"))
12140         ;
12141       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
12142         ;
12143       else if (unformat (i, "sw_if_index %u", &sw_if_index))
12144         ;
12145       else
12146         break;
12147     }
12148   if (sw_if_index == ~0 || pfx.len == 0)
12149     {
12150       errmsg ("address and sw_if_index must be set");
12151       return -99;
12152     }
12153
12154   M (IP_CONTAINER_PROXY_ADD_DEL, mp);
12155
12156   mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
12157   mp->is_add = is_add;
12158   clib_memcpy (&mp->pfx, &pfx, sizeof (pfx));
12159
12160   S (mp);
12161   W (ret);
12162   return ret;
12163 }
12164
12165 static int
12166 api_qos_record_enable_disable (vat_main_t * vam)
12167 {
12168   unformat_input_t *i = vam->input;
12169   vl_api_qos_record_enable_disable_t *mp;
12170   u32 sw_if_index, qs = 0xff;
12171   u8 sw_if_index_set = 0;
12172   u8 enable = 1;
12173   int ret;
12174
12175   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
12176     {
12177       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
12178         sw_if_index_set = 1;
12179       else if (unformat (i, "sw_if_index %d", &sw_if_index))
12180         sw_if_index_set = 1;
12181       else if (unformat (i, "%U", unformat_qos_source, &qs))
12182         ;
12183       else if (unformat (i, "disable"))
12184         enable = 0;
12185       else
12186         {
12187           clib_warning ("parse error '%U'", format_unformat_error, i);
12188           return -99;
12189         }
12190     }
12191
12192   if (sw_if_index_set == 0)
12193     {
12194       errmsg ("missing interface name or sw_if_index");
12195       return -99;
12196     }
12197   if (qs == 0xff)
12198     {
12199       errmsg ("input location must be specified");
12200       return -99;
12201     }
12202
12203   M (QOS_RECORD_ENABLE_DISABLE, mp);
12204
12205   mp->record.sw_if_index = ntohl (sw_if_index);
12206   mp->record.input_source = qs;
12207   mp->enable = enable;
12208
12209   S (mp);
12210   W (ret);
12211   return ret;
12212 }
12213
12214
12215 static int
12216 q_or_quit (vat_main_t * vam)
12217 {
12218 #if VPP_API_TEST_BUILTIN == 0
12219   longjmp (vam->jump_buf, 1);
12220 #endif
12221   return 0;                     /* not so much */
12222 }
12223
12224 static int
12225 q (vat_main_t * vam)
12226 {
12227   return q_or_quit (vam);
12228 }
12229
12230 static int
12231 quit (vat_main_t * vam)
12232 {
12233   return q_or_quit (vam);
12234 }
12235
12236 static int
12237 comment (vat_main_t * vam)
12238 {
12239   return 0;
12240 }
12241
12242 static int
12243 elog_save (vat_main_t * vam)
12244 {
12245 #if VPP_API_TEST_BUILTIN == 0
12246   elog_main_t *em = &vam->elog_main;
12247   unformat_input_t *i = vam->input;
12248   char *file, *chroot_file;
12249   clib_error_t *error;
12250
12251   if (!unformat (i, "%s", &file))
12252     {
12253       errmsg ("expected file name, got `%U'", format_unformat_error, i);
12254       return 0;
12255     }
12256
12257   /* It's fairly hard to get "../oopsie" through unformat; just in case */
12258   if (strstr (file, "..") || index (file, '/'))
12259     {
12260       errmsg ("illegal characters in filename '%s'", file);
12261       return 0;
12262     }
12263
12264   chroot_file = (char *) format (0, "/tmp/%s%c", file, 0);
12265
12266   vec_free (file);
12267
12268   errmsg ("Saving %wd of %wd events to %s",
12269           elog_n_events_in_buffer (em),
12270           elog_buffer_capacity (em), chroot_file);
12271
12272   error = elog_write_file (em, chroot_file, 1 /* flush ring */ );
12273   vec_free (chroot_file);
12274
12275   if (error)
12276     clib_error_report (error);
12277 #else
12278   errmsg ("Use the vpp event loger...");
12279 #endif
12280
12281   return 0;
12282 }
12283
12284 static int
12285 elog_setup (vat_main_t * vam)
12286 {
12287 #if VPP_API_TEST_BUILTIN == 0
12288   elog_main_t *em = &vam->elog_main;
12289   unformat_input_t *i = vam->input;
12290   u32 nevents = 128 << 10;
12291
12292   (void) unformat (i, "nevents %d", &nevents);
12293
12294   elog_init (em, nevents);
12295   vl_api_set_elog_main (em);
12296   vl_api_set_elog_trace_api_messages (1);
12297   errmsg ("Event logger initialized with %u events", nevents);
12298 #else
12299   errmsg ("Use the vpp event loger...");
12300 #endif
12301   return 0;
12302 }
12303
12304 static int
12305 elog_enable (vat_main_t * vam)
12306 {
12307 #if VPP_API_TEST_BUILTIN == 0
12308   elog_main_t *em = &vam->elog_main;
12309
12310   elog_enable_disable (em, 1 /* enable */ );
12311   vl_api_set_elog_trace_api_messages (1);
12312   errmsg ("Event logger enabled...");
12313 #else
12314   errmsg ("Use the vpp event loger...");
12315 #endif
12316   return 0;
12317 }
12318
12319 static int
12320 elog_disable (vat_main_t * vam)
12321 {
12322 #if VPP_API_TEST_BUILTIN == 0
12323   elog_main_t *em = &vam->elog_main;
12324
12325   elog_enable_disable (em, 0 /* enable */ );
12326   vl_api_set_elog_trace_api_messages (1);
12327   errmsg ("Event logger disabled...");
12328 #else
12329   errmsg ("Use the vpp event loger...");
12330 #endif
12331   return 0;
12332 }
12333
12334 static int
12335 statseg (vat_main_t * vam)
12336 {
12337   ssvm_private_t *ssvmp = &vam->stat_segment;
12338   ssvm_shared_header_t *shared_header = ssvmp->sh;
12339   vlib_counter_t **counters;
12340   u64 thread0_index1_packets;
12341   u64 thread0_index1_bytes;
12342   f64 vector_rate, input_rate;
12343   uword *p;
12344
12345   uword *counter_vector_by_name;
12346   if (vam->stat_segment_lockp == 0)
12347     {
12348       errmsg ("Stat segment not mapped...");
12349       return -99;
12350     }
12351
12352   /* look up "/if/rx for sw_if_index 1 as a test */
12353
12354   clib_spinlock_lock (vam->stat_segment_lockp);
12355
12356   counter_vector_by_name = (uword *) shared_header->opaque[1];
12357
12358   p = hash_get_mem (counter_vector_by_name, "/if/rx");
12359   if (p == 0)
12360     {
12361       clib_spinlock_unlock (vam->stat_segment_lockp);
12362       errmsg ("/if/tx not found?");
12363       return -99;
12364     }
12365
12366   /* Fish per-thread vector of combined counters from shared memory */
12367   counters = (vlib_counter_t **) p[0];
12368
12369   if (vec_len (counters[0]) < 2)
12370     {
12371       clib_spinlock_unlock (vam->stat_segment_lockp);
12372       errmsg ("/if/tx vector length %d", vec_len (counters[0]));
12373       return -99;
12374     }
12375
12376   /* Read thread 0 sw_if_index 1 counter */
12377   thread0_index1_packets = counters[0][1].packets;
12378   thread0_index1_bytes = counters[0][1].bytes;
12379
12380   p = hash_get_mem (counter_vector_by_name, "vector_rate");
12381   if (p == 0)
12382     {
12383       clib_spinlock_unlock (vam->stat_segment_lockp);
12384       errmsg ("vector_rate not found?");
12385       return -99;
12386     }
12387
12388   vector_rate = *(f64 *) (p[0]);
12389   p = hash_get_mem (counter_vector_by_name, "input_rate");
12390   if (p == 0)
12391     {
12392       clib_spinlock_unlock (vam->stat_segment_lockp);
12393       errmsg ("input_rate not found?");
12394       return -99;
12395     }
12396   input_rate = *(f64 *) (p[0]);
12397
12398   clib_spinlock_unlock (vam->stat_segment_lockp);
12399
12400   print (vam->ofp, "vector_rate %.2f input_rate %.2f",
12401          vector_rate, input_rate);
12402   print (vam->ofp, "thread 0 sw_if_index 1 rx pkts %lld, bytes %lld",
12403          thread0_index1_packets, thread0_index1_bytes);
12404
12405   return 0;
12406 }
12407
12408 static int
12409 cmd_cmp (void *a1, void *a2)
12410 {
12411   u8 **c1 = a1;
12412   u8 **c2 = a2;
12413
12414   return strcmp ((char *) (c1[0]), (char *) (c2[0]));
12415 }
12416
12417 static int
12418 help (vat_main_t * vam)
12419 {
12420   u8 **cmds = 0;
12421   u8 *name = 0;
12422   hash_pair_t *p;
12423   unformat_input_t *i = vam->input;
12424   int j;
12425
12426   if (unformat (i, "%s", &name))
12427     {
12428       uword *hs;
12429
12430       vec_add1 (name, 0);
12431
12432       hs = hash_get_mem (vam->help_by_name, name);
12433       if (hs)
12434         print (vam->ofp, "usage: %s %s", name, hs[0]);
12435       else
12436         print (vam->ofp, "No such msg / command '%s'", name);
12437       vec_free (name);
12438       return 0;
12439     }
12440
12441   print (vam->ofp, "Help is available for the following:");
12442
12443     /* *INDENT-OFF* */
12444     hash_foreach_pair (p, vam->function_by_name,
12445     ({
12446       vec_add1 (cmds, (u8 *)(p->key));
12447     }));
12448     /* *INDENT-ON* */
12449
12450   vec_sort_with_function (cmds, cmd_cmp);
12451
12452   for (j = 0; j < vec_len (cmds); j++)
12453     print (vam->ofp, "%s", cmds[j]);
12454
12455   vec_free (cmds);
12456   return 0;
12457 }
12458
12459 static int
12460 set (vat_main_t * vam)
12461 {
12462   u8 *name = 0, *value = 0;
12463   unformat_input_t *i = vam->input;
12464
12465   if (unformat (i, "%s", &name))
12466     {
12467       /* The input buffer is a vector, not a string. */
12468       value = vec_dup (i->buffer);
12469       vec_delete (value, i->index, 0);
12470       /* Almost certainly has a trailing newline */
12471       if (value[vec_len (value) - 1] == '\n')
12472         value[vec_len (value) - 1] = 0;
12473       /* Make sure it's a proper string, one way or the other */
12474       vec_add1 (value, 0);
12475       (void) clib_macro_set_value (&vam->macro_main,
12476                                    (char *) name, (char *) value);
12477     }
12478   else
12479     errmsg ("usage: set <name> <value>");
12480
12481   vec_free (name);
12482   vec_free (value);
12483   return 0;
12484 }
12485
12486 static int
12487 unset (vat_main_t * vam)
12488 {
12489   u8 *name = 0;
12490
12491   if (unformat (vam->input, "%s", &name))
12492     if (clib_macro_unset (&vam->macro_main, (char *) name) == 1)
12493       errmsg ("unset: %s wasn't set", name);
12494   vec_free (name);
12495   return 0;
12496 }
12497
12498 typedef struct
12499 {
12500   u8 *name;
12501   u8 *value;
12502 } macro_sort_t;
12503
12504
12505 static int
12506 macro_sort_cmp (void *a1, void *a2)
12507 {
12508   macro_sort_t *s1 = a1;
12509   macro_sort_t *s2 = a2;
12510
12511   return strcmp ((char *) (s1->name), (char *) (s2->name));
12512 }
12513
12514 static int
12515 dump_macro_table (vat_main_t * vam)
12516 {
12517   macro_sort_t *sort_me = 0, *sm;
12518   int i;
12519   hash_pair_t *p;
12520
12521     /* *INDENT-OFF* */
12522     hash_foreach_pair (p, vam->macro_main.the_value_table_hash,
12523     ({
12524       vec_add2 (sort_me, sm, 1);
12525       sm->name = (u8 *)(p->key);
12526       sm->value = (u8 *) (p->value[0]);
12527     }));
12528     /* *INDENT-ON* */
12529
12530   vec_sort_with_function (sort_me, macro_sort_cmp);
12531
12532   if (vec_len (sort_me))
12533     print (vam->ofp, "%-15s%s", "Name", "Value");
12534   else
12535     print (vam->ofp, "The macro table is empty...");
12536
12537   for (i = 0; i < vec_len (sort_me); i++)
12538     print (vam->ofp, "%-15s%s", sort_me[i].name, sort_me[i].value);
12539   return 0;
12540 }
12541
12542 static int
12543 dump_node_table (vat_main_t * vam)
12544 {
12545   int i, j;
12546   vlib_node_t *node, *next_node;
12547
12548   if (vec_len (vam->graph_nodes) == 0)
12549     {
12550       print (vam->ofp, "Node table empty, issue get_node_graph...");
12551       return 0;
12552     }
12553
12554   for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
12555     {
12556       node = vam->graph_nodes[0][i];
12557       print (vam->ofp, "[%d] %s", i, node->name);
12558       for (j = 0; j < vec_len (node->next_nodes); j++)
12559         {
12560           if (node->next_nodes[j] != ~0)
12561             {
12562               next_node = vam->graph_nodes[0][node->next_nodes[j]];
12563               print (vam->ofp, "  [%d] %s", j, next_node->name);
12564             }
12565         }
12566     }
12567   return 0;
12568 }
12569
12570 static int
12571 value_sort_cmp (void *a1, void *a2)
12572 {
12573   name_sort_t *n1 = a1;
12574   name_sort_t *n2 = a2;
12575
12576   if (n1->value < n2->value)
12577     return -1;
12578   if (n1->value > n2->value)
12579     return 1;
12580   return 0;
12581 }
12582
12583
12584 static int
12585 dump_msg_api_table (vat_main_t * vam)
12586 {
12587   api_main_t *am = vlibapi_get_main ();
12588   name_sort_t *nses = 0, *ns;
12589   hash_pair_t *hp;
12590   int i;
12591
12592   /* *INDENT-OFF* */
12593   hash_foreach_pair (hp, am->msg_index_by_name_and_crc,
12594   ({
12595     vec_add2 (nses, ns, 1);
12596     ns->name = (u8 *)(hp->key);
12597     ns->value = (u32) hp->value[0];
12598   }));
12599   /* *INDENT-ON* */
12600
12601   vec_sort_with_function (nses, value_sort_cmp);
12602
12603   for (i = 0; i < vec_len (nses); i++)
12604     print (vam->ofp, " [%d]: %s", nses[i].value, nses[i].name);
12605   vec_free (nses);
12606   return 0;
12607 }
12608
12609 static int
12610 get_msg_id (vat_main_t * vam)
12611 {
12612   u8 *name_and_crc;
12613   u32 message_index;
12614
12615   if (unformat (vam->input, "%s", &name_and_crc))
12616     {
12617       message_index = vl_msg_api_get_msg_index (name_and_crc);
12618       if (message_index == ~0)
12619         {
12620           print (vam->ofp, " '%s' not found", name_and_crc);
12621           return 0;
12622         }
12623       print (vam->ofp, " '%s' has message index %d",
12624              name_and_crc, message_index);
12625       return 0;
12626     }
12627   errmsg ("name_and_crc required...");
12628   return 0;
12629 }
12630
12631 static int
12632 search_node_table (vat_main_t * vam)
12633 {
12634   unformat_input_t *line_input = vam->input;
12635   u8 *node_to_find;
12636   int j;
12637   vlib_node_t *node, *next_node;
12638   uword *p;
12639
12640   if (vam->graph_node_index_by_name == 0)
12641     {
12642       print (vam->ofp, "Node table empty, issue get_node_graph...");
12643       return 0;
12644     }
12645
12646   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
12647     {
12648       if (unformat (line_input, "%s", &node_to_find))
12649         {
12650           vec_add1 (node_to_find, 0);
12651           p = hash_get_mem (vam->graph_node_index_by_name, node_to_find);
12652           if (p == 0)
12653             {
12654               print (vam->ofp, "%s not found...", node_to_find);
12655               goto out;
12656             }
12657           node = vam->graph_nodes[0][p[0]];
12658           print (vam->ofp, "[%d] %s", p[0], node->name);
12659           for (j = 0; j < vec_len (node->next_nodes); j++)
12660             {
12661               if (node->next_nodes[j] != ~0)
12662                 {
12663                   next_node = vam->graph_nodes[0][node->next_nodes[j]];
12664                   print (vam->ofp, "  [%d] %s", j, next_node->name);
12665                 }
12666             }
12667         }
12668
12669       else
12670         {
12671           clib_warning ("parse error '%U'", format_unformat_error,
12672                         line_input);
12673           return -99;
12674         }
12675
12676     out:
12677       vec_free (node_to_find);
12678
12679     }
12680
12681   return 0;
12682 }
12683
12684
12685 static int
12686 script (vat_main_t * vam)
12687 {
12688 #if (VPP_API_TEST_BUILTIN==0)
12689   u8 *s = 0;
12690   char *save_current_file;
12691   unformat_input_t save_input;
12692   jmp_buf save_jump_buf;
12693   u32 save_line_number;
12694
12695   FILE *new_fp, *save_ifp;
12696
12697   if (unformat (vam->input, "%s", &s))
12698     {
12699       new_fp = fopen ((char *) s, "r");
12700       if (new_fp == 0)
12701         {
12702           errmsg ("Couldn't open script file %s", s);
12703           vec_free (s);
12704           return -99;
12705         }
12706     }
12707   else
12708     {
12709       errmsg ("Missing script name");
12710       return -99;
12711     }
12712
12713   clib_memcpy (&save_input, &vam->input, sizeof (save_input));
12714   clib_memcpy (&save_jump_buf, &vam->jump_buf, sizeof (save_jump_buf));
12715   save_ifp = vam->ifp;
12716   save_line_number = vam->input_line_number;
12717   save_current_file = (char *) vam->current_file;
12718
12719   vam->input_line_number = 0;
12720   vam->ifp = new_fp;
12721   vam->current_file = s;
12722   do_one_file (vam);
12723
12724   clib_memcpy (&vam->input, &save_input, sizeof (save_input));
12725   clib_memcpy (&vam->jump_buf, &save_jump_buf, sizeof (save_jump_buf));
12726   vam->ifp = save_ifp;
12727   vam->input_line_number = save_line_number;
12728   vam->current_file = (u8 *) save_current_file;
12729   vec_free (s);
12730
12731   return 0;
12732 #else
12733   clib_warning ("use the exec command...");
12734   return -99;
12735 #endif
12736 }
12737
12738 static int
12739 echo (vat_main_t * vam)
12740 {
12741   print (vam->ofp, "%v", vam->input->buffer);
12742   return 0;
12743 }
12744
12745 /* List of API message constructors, CLI names map to api_xxx */
12746 #define foreach_vpe_api_msg                                             \
12747 _(create_loopback,"[mac <mac-addr>] [instance <instance>]")             \
12748 _(sw_interface_dump,"")                                                 \
12749 _(sw_interface_set_flags,                                               \
12750   "<intfc> | sw_if_index <id> admin-up | admin-down link-up | link down") \
12751 _(sw_interface_add_del_address,                                         \
12752   "<intfc> | sw_if_index <id> <ip4-address> | <ip6-address> [del] [del-all] ") \
12753 _(sw_interface_set_rx_mode,                                             \
12754   "<intfc> | sw_if_index <id> [queue <id>] <polling | interrupt | adaptive>") \
12755 _(sw_interface_set_rx_placement,                                        \
12756   "<intfc> | sw_if_index <id> [queue <id>] [worker <id> | main]")       \
12757 _(sw_interface_rx_placement_dump,                                       \
12758   "[<intfc> | sw_if_index <id>]")                                         \
12759 _(sw_interface_set_table,                                               \
12760   "<intfc> | sw_if_index <id> vrf <table-id> [ipv6]")                   \
12761 _(sw_interface_set_mpls_enable,                                         \
12762   "<intfc> | sw_if_index [disable | dis]")                              \
12763 _(sw_interface_set_vpath,                                               \
12764   "<intfc> | sw_if_index <id> enable | disable")                        \
12765 _(sw_interface_set_l2_xconnect,                                         \
12766   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
12767   "enable | disable")                                                   \
12768 _(sw_interface_set_l2_bridge,                                           \
12769   "{<intfc> | sw_if_index <id>} bd_id <bridge-domain-id>\n"             \
12770   "[shg <split-horizon-group>] [bvi]\n"                                 \
12771   "enable | disable")                                                   \
12772 _(bridge_domain_set_mac_age, "bd_id <bridge-domain-id> mac-age 0-255")  \
12773 _(bridge_domain_add_del,                                                \
12774   "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") \
12775 _(bridge_domain_dump, "[bd_id <bridge-domain-id>]\n")                   \
12776 _(l2fib_add_del,                                                        \
12777   "mac <mac-addr> bd_id <bridge-domain-id> [del] | sw_if <intfc> | sw_if_index <id> [static] [filter] [bvi] [count <nn>]\n") \
12778 _(l2fib_flush_bd, "bd_id <bridge-domain-id>")                           \
12779 _(l2fib_flush_int, "<intfc> | sw_if_index <id>")                        \
12780 _(l2_flags,                                                             \
12781   "sw_if <intfc> | sw_if_index <id> [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \
12782 _(bridge_flags,                                                         \
12783   "bd_id <bridge-domain-id> [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \
12784 _(tap_create_v2,                                                        \
12785   "id <num> [hw-addr <mac-addr>] [host-if-name <name>] [host-ns <name>] [num-rx-queues <num>] [rx-ring-size <num>] [tx-ring-size <num>] [host-bridge <name>] [host-mac-addr <mac-addr>] [host-ip4-addr <ip4addr/mask>] [host-ip6-addr <ip6addr/mask>] [host-mtu-size <mtu>] [gso | no-gso | csum-offload | gro-coalesce] [persist] [attach] [tun] [packed] [in-order]") \
12786 _(tap_delete_v2,                                                        \
12787   "<vpp-if-name> | sw_if_index <id>")                                   \
12788 _(sw_interface_tap_v2_dump, "")                                         \
12789 _(virtio_pci_create_v2,                                                    \
12790   "pci-addr <pci-address> [use_random_mac | hw-addr <mac-addr>] [features <hex-value>] [gso-enabled [gro-coalesce] | csum-offload-enabled] [packed] [in-order] [buffering]") \
12791 _(virtio_pci_delete,                                                    \
12792   "<vpp-if-name> | sw_if_index <id>")                                   \
12793 _(sw_interface_virtio_pci_dump, "")                                     \
12794 _(bond_create,                                                          \
12795   "[hw-addr <mac-addr>] {round-robin | active-backup | "                \
12796   "broadcast | {lacp | xor} [load-balance { l2 | l23 | l34 }]} "        \
12797   "[id <if-id>]")                                                       \
12798 _(bond_create2,                                                         \
12799   "[hw-addr <mac-addr>] {mode round-robin | active-backup | "           \
12800   "broadcast | {lacp | xor} [load-balance { l2 | l23 | l34 }]} "        \
12801   "[id <if-id>] [gso]")                                                 \
12802 _(bond_delete,                                                          \
12803   "<vpp-if-name> | sw_if_index <id>")                                   \
12804 _(bond_add_member,                                                      \
12805   "sw_if_index <n> bond <sw_if_index> [is_passive] [is_long_timeout]")  \
12806 _(bond_detach_member,                                                   \
12807   "sw_if_index <n>")                                                    \
12808  _(sw_interface_set_bond_weight, "<intfc> | sw_if_index <nn> weight <value>") \
12809  _(sw_bond_interface_dump, "<intfc> | sw_if_index <nn>")                \
12810  _(sw_member_interface_dump,                                            \
12811   "<vpp-if-name> | sw_if_index <id>")                                   \
12812 _(ip_table_add_del,                                                     \
12813   "table <n> [ipv6] [add | del]\n")                                     \
12814 _(ip_route_add_del,                                                     \
12815   "<addr>/<mask> via <<addr>|<intfc>|sw_if_index <id>|via-label <n>>\n" \
12816   "[table-id <n>] [<intfc> | sw_if_index <id>] [resolve-attempts <n>]\n"\
12817   "[weight <n>] [drop] [local] [classify <n>]  [out-label <n>]\n"       \
12818   "[multipath] [count <n>] [del]")                                      \
12819 _(ip_mroute_add_del,                                                    \
12820   "<src> <grp>/<mask> [table-id <n>]\n"                                 \
12821   "[<intfc> | sw_if_index <id>] [local] [del]")                         \
12822 _(mpls_table_add_del,                                                   \
12823   "table <n> [add | del]\n")                                            \
12824 _(mpls_route_add_del,                                                   \
12825   "<label> <eos> via <addr | next-hop-table <n> | via-label <n> |\n"    \
12826   "lookup-ip4-table <n> | lookup-in-ip6-table <n> |\n"                  \
12827   "l2-input-on <intfc> | l2-input-on sw_if_index <id>>\n"               \
12828   "[<intfc> | sw_if_index <id>] [resolve-attempts <n>] [weight <n>]\n"  \
12829   "[drop] [local] [classify <n>] [out-label <n>] [multipath]\n"         \
12830   "[count <n>] [del]")                                                  \
12831 _(mpls_ip_bind_unbind,                                                  \
12832   "<label> <addr/len>")                                                 \
12833 _(mpls_tunnel_add_del,                                                  \
12834   "[add | del <intfc | sw_if_index <id>>] via <addr | via-label <n>>\n" \
12835   "[<intfc> | sw_if_index <id> | next-hop-table <id>]\n"                \
12836   "[l2-only]  [out-label <n>]")                                         \
12837 _(sr_mpls_policy_add,                                                   \
12838   "bsid <id> [weight <n>] [spray] next <sid> [next <sid>]")             \
12839 _(sr_mpls_policy_del,                                                   \
12840   "bsid <id>")                                                          \
12841 _(sw_interface_set_unnumbered,                                          \
12842   "<intfc> | sw_if_index <id> unnum_if_index <id> [del]")               \
12843 _(create_vlan_subif, "<intfc> | sw_if_index <id> vlan <n>")             \
12844 _(create_subif, "<intfc> | sw_if_index <id> sub_id <n>\n"               \
12845   "[outer_vlan_id <n>][inner_vlan_id <n>]\n"                            \
12846   "[no_tags][one_tag][two_tags][dot1ad][exact_match][default_sub]\n"    \
12847   "[outer_vlan_id_any][inner_vlan_id_any]")                             \
12848 _(ip_table_replace_begin, "table <n> [ipv6]")                           \
12849 _(ip_table_flush, "table <n> [ipv6]")                                   \
12850 _(ip_table_replace_end, "table <n> [ipv6]")                             \
12851 _(set_ip_flow_hash,                                                     \
12852   "vrf <n> [src] [dst] [sport] [dport] [proto] [reverse] [ipv6]")       \
12853 _(sw_interface_ip6_enable_disable,                                      \
12854   "<intfc> | sw_if_index <id> enable | disable")                        \
12855 _(l2_patch_add_del,                                                     \
12856   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
12857   "enable | disable")                                                   \
12858 _(sr_localsid_add_del,                                                  \
12859   "(del) address <addr> next_hop <addr> behavior <beh>\n"               \
12860   "fib-table <num> (end.psp) sw_if_index <num>")                        \
12861 _(get_node_index, "node <node-name")                                    \
12862 _(add_node_next, "node <node-name> next <next-node-name>")              \
12863 _(l2_fib_clear_table, "")                                               \
12864 _(l2_interface_efp_filter, "sw_if_index <nn> enable | disable")         \
12865 _(l2_interface_vlan_tag_rewrite,                                        \
12866   "<intfc> | sw_if_index <nn> \n"                                       \
12867   "[disable][push-[1|2]][pop-[1|2]][translate-1-[1|2]] \n"              \
12868   "[translate-2-[1|2]] [push_dot1q 0] tag1 <nn> tag2 <nn>")             \
12869 _(create_vhost_user_if,                                                 \
12870         "socket <filename> [server] [renumber <dev_instance>] "         \
12871         "[disable_mrg_rxbuf] [disable_indirect_desc] [gso] "            \
12872         "[mac <mac_address>] [packed]")                                 \
12873 _(modify_vhost_user_if,                                                 \
12874         "<intfc> | sw_if_index <nn> socket <filename>\n"                \
12875         "[server] [renumber <dev_instance>] [gso] [packed]")            \
12876 _(create_vhost_user_if_v2,                                              \
12877         "socket <filename> [server] [renumber <dev_instance>] "         \
12878         "[disable_mrg_rxbuf] [disable_indirect_desc] [gso] "            \
12879         "[mac <mac_address>] [packed] [event-idx]")                     \
12880 _(modify_vhost_user_if_v2,                                              \
12881         "<intfc> | sw_if_index <nn> socket <filename>\n"                \
12882         "[server] [renumber <dev_instance>] [gso] [packed] [event-idx]")\
12883 _(delete_vhost_user_if, "<intfc> | sw_if_index <nn>")                   \
12884 _(sw_interface_vhost_user_dump, "<intfc> | sw_if_index <nn>")           \
12885 _(show_version, "")                                                     \
12886 _(show_threads, "")                                                     \
12887 _(l2_fib_table_dump, "bd_id <bridge-domain-id>")                        \
12888 _(interface_name_renumber,                                              \
12889   "<intfc> | sw_if_index <nn> new_show_dev_instance <nn>")              \
12890 _(want_l2_macs_events, "[disable] [learn-limit <n>] [scan-delay <n>] [max-entries <n>]") \
12891 _(ip_address_dump, "(ipv4 | ipv6) (<intfc> | sw_if_index <id>)")        \
12892 _(ip_dump, "ipv4 | ipv6")                                               \
12893 _(ipsec_spd_add_del, "spd_id <n> [del]")                                \
12894 _(ipsec_interface_add_del_spd, "(<intfc> | sw_if_index <id>)\n"         \
12895   "  spid_id <n> ")                                                     \
12896 _(ipsec_sad_entry_add_del, "sad_id <n> spi <n> crypto_alg <alg>\n"      \
12897   "  crypto_key <hex> tunnel_src <ip4|ip6> tunnel_dst <ip4|ip6>\n"      \
12898   "  integ_alg <alg> integ_key <hex>")                                  \
12899 _(ipsec_spd_entry_add_del, "spd_id <n> priority <n> action <action>\n"  \
12900   "  (inbound|outbound) [sa_id <n>] laddr_start <ip4|ip6>\n"            \
12901   "  laddr_stop <ip4|ip6> raddr_start <ip4|ip6> raddr_stop <ip4|ip6>\n" \
12902   "  [lport_start <n> lport_stop <n>] [rport_start <n> rport_stop <n>]" ) \
12903 _(ipsec_sa_dump, "[sa_id <n>]")                                         \
12904 _(delete_loopback,"sw_if_index <nn>")                                   \
12905 _(bd_ip_mac_add_del, "bd_id <bridge-domain-id> <ip4/6-addr> <mac-addr> [del]") \
12906 _(bd_ip_mac_flush, "bd_id <bridge-domain-id>")                          \
12907 _(bd_ip_mac_dump, "[bd_id] <bridge-domain-id>")                         \
12908 _(want_interface_events,  "enable|disable")                             \
12909 _(get_first_msg_id, "client <name>")                                    \
12910 _(get_node_graph, " ")                                                  \
12911 _(sw_interface_clear_stats,"<intfc> | sw_if_index <nn>")                \
12912 _(ioam_enable, "[trace] [pow] [ppc <encap|decap>]")                     \
12913 _(ioam_disable, "")                                                     \
12914 _(af_packet_create, "name <host interface name> [hw_addr <mac>]")       \
12915 _(af_packet_delete, "name <host interface name>")                       \
12916 _(af_packet_dump, "")                                                   \
12917 _(policer_add_del, "name <policer name> <params> [del]")                \
12918 _(policer_dump, "[name <policer name>]")                                \
12919 _(mpls_tunnel_dump, "tunnel_index <tunnel-id>")                         \
12920 _(mpls_table_dump, "")                                                  \
12921 _(mpls_route_dump, "table-id <ID>")                                     \
12922 _(set_ipfix_exporter, "collector_address <ip4> [collector_port <nn>] "  \
12923     "src_address <ip4> [vrf_id <nn>] [path_mtu <nn>] "                  \
12924     "[template_interval <nn>] [udp_checksum]")                          \
12925 _(ipfix_exporter_dump, "")                                              \
12926 _(set_ipfix_classify_stream, "[domain <domain-id>] [src_port <src-port>]") \
12927 _(ipfix_classify_stream_dump, "")                                       \
12928 _(ipfix_classify_table_add_del, "table <table-index> ip4|ip6 [tcp|udp]") \
12929 _(ipfix_classify_table_dump, "")                                        \
12930 _(sw_interface_span_enable_disable, "[l2] [src <intfc> | src_sw_if_index <id>] [disable | [[dst <intfc> | dst_sw_if_index <id>] [both|rx|tx]]]") \
12931 _(sw_interface_span_dump, "[l2]")                                           \
12932 _(get_next_index, "node-name <node-name> next-node-name <node-name>")   \
12933 _(pg_create_interface, "if_id <nn> [gso-enabled gso-size <size>]")      \
12934 _(pg_capture, "if_id <nnn> pcap <file_name> count <nnn> [disable]")     \
12935 _(pg_enable_disable, "[stream <id>] disable")                           \
12936 _(pg_interface_enable_disable_coalesce, "<intf> | sw_if_index <nn> enable | disable")  \
12937 _(ip_source_and_port_range_check_add_del,                               \
12938   "<ip-addr>/<mask> range <nn>-<nn> vrf <id>")                          \
12939 _(ip_source_and_port_range_check_interface_add_del,                     \
12940   "<intf> | sw_if_index <nn> [tcp-out-vrf <id>] [tcp-in-vrf <id>]"      \
12941   "[udp-in-vrf <id>] [udp-out-vrf <id>]")                               \
12942 _(delete_subif,"<intfc> | sw_if_index <nn>")                            \
12943 _(l2_interface_pbb_tag_rewrite,                                         \
12944   "<intfc> | sw_if_index <nn> \n"                                       \
12945   "[disable | push | pop | translate_pbb_stag <outer_tag>] \n"          \
12946   "dmac <mac> smac <mac> sid <nn> [vlanid <nn>]")                       \
12947 _(set_punt, "protocol <l4-protocol> [ip <ver>] [port <l4-port>] [del]")     \
12948 _(ip_table_dump, "")                                                    \
12949 _(ip_route_dump, "table-id [ip4|ip6]")                                  \
12950 _(ip_mtable_dump, "")                                                   \
12951 _(ip_mroute_dump, "table-id [ip4|ip6]")                                 \
12952 _(feature_enable_disable, "arc_name <arc_name> "                        \
12953   "feature_name <feature_name> <intfc> | sw_if_index <nn> [disable]")   \
12954 _(sw_interface_tag_add_del, "<intfc> | sw_if_index <nn> tag <text>"     \
12955 "[disable]")                                                            \
12956 _(sw_interface_add_del_mac_address, "<intfc> | sw_if_index <nn> "       \
12957   "mac <mac-address> [del]")                                            \
12958 _(l2_xconnect_dump, "")                                                 \
12959 _(hw_interface_set_mtu, "<intfc> | hw_if_index <nn> mtu <nn>")        \
12960 _(sw_interface_get_table, "<intfc> | sw_if_index <id> [ipv6]")          \
12961 _(p2p_ethernet_add, "<intfc> | sw_if_index <nn> remote_mac <mac-address> sub_id <id>") \
12962 _(p2p_ethernet_del, "<intfc> | sw_if_index <nn> remote_mac <mac-address>") \
12963 _(tcp_configure_src_addresses, "<ip4|6>first-<ip4|6>last [vrf <id>]")   \
12964 _(sock_init_shm, "size <nnn>")                                          \
12965 _(app_namespace_add_del, "[add] id <ns-id> secret <nn> sw_if_index <nn>")\
12966 _(session_rule_add_del, "[add|del] proto <tcp/udp> <lcl-ip>/<plen> "    \
12967   "<lcl-port> <rmt-ip>/<plen> <rmt-port> action <nn>")                  \
12968 _(session_rules_dump, "")                                               \
12969 _(ip_container_proxy_add_del, "[add|del] <address> <sw_if_index>")      \
12970 _(qos_record_enable_disable, "<record-source> <intfc> | sw_if_index <id> [disable]")
12971
12972 /* List of command functions, CLI names map directly to functions */
12973 #define foreach_cli_function                                    \
12974 _(comment, "usage: comment <ignore-rest-of-line>")              \
12975 _(dump_interface_table, "usage: dump_interface_table")          \
12976 _(dump_sub_interface_table, "usage: dump_sub_interface_table")  \
12977 _(dump_ipv4_table, "usage: dump_ipv4_table")                    \
12978 _(dump_ipv6_table, "usage: dump_ipv6_table")                    \
12979 _(dump_macro_table, "usage: dump_macro_table ")                 \
12980 _(dump_node_table, "usage: dump_node_table")                    \
12981 _(dump_msg_api_table, "usage: dump_msg_api_table")              \
12982 _(elog_setup, "usage: elog_setup [nevents, default 128K]")      \
12983 _(elog_disable, "usage: elog_disable")                          \
12984 _(elog_enable, "usage: elog_enable")                            \
12985 _(elog_save, "usage: elog_save <filename>")                     \
12986 _(get_msg_id, "usage: get_msg_id name_and_crc")                 \
12987 _(echo, "usage: echo <message>")                                \
12988 _(exec, "usage: exec <vpe-debug-CLI-command>")                  \
12989 _(exec_inband, "usage: exec_inband <vpe-debug-CLI-command>")    \
12990 _(help, "usage: help")                                          \
12991 _(q, "usage: quit")                                             \
12992 _(quit, "usage: quit")                                          \
12993 _(search_node_table, "usage: search_node_table <name>...")      \
12994 _(set, "usage: set <variable-name> <value>")                    \
12995 _(script, "usage: script <file-name>")                          \
12996 _(statseg, "usage: statseg")                                    \
12997 _(unset, "usage: unset <variable-name>")
12998
12999 #define _(N,n)                                  \
13000     static void vl_api_##n##_t_handler_uni      \
13001     (vl_api_##n##_t * mp)                       \
13002     {                                           \
13003         vat_main_t * vam = &vat_main;           \
13004         if (vam->json_output) {                 \
13005             vl_api_##n##_t_handler_json(mp);    \
13006         } else {                                \
13007             vl_api_##n##_t_handler(mp);         \
13008         }                                       \
13009     }
13010 foreach_vpe_api_reply_msg;
13011 #if VPP_API_TEST_BUILTIN == 0
13012 foreach_standalone_reply_msg;
13013 #endif
13014 #undef _
13015
13016 void
13017 vat_api_hookup (vat_main_t * vam)
13018 {
13019 #define _(N,n)                                                  \
13020     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
13021                            vl_api_##n##_t_handler_uni,          \
13022                            vl_noop_handler,                     \
13023                            vl_api_##n##_t_endian,               \
13024                            vl_api_##n##_t_print,                \
13025                            sizeof(vl_api_##n##_t), 1);
13026   foreach_vpe_api_reply_msg;
13027 #if VPP_API_TEST_BUILTIN == 0
13028   foreach_standalone_reply_msg;
13029 #endif
13030 #undef _
13031
13032 #if (VPP_API_TEST_BUILTIN==0)
13033   vl_msg_api_set_first_available_msg_id (VL_MSG_FIRST_AVAILABLE);
13034
13035   vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
13036
13037   vam->function_by_name = hash_create_string (0, sizeof (uword));
13038
13039   vam->help_by_name = hash_create_string (0, sizeof (uword));
13040 #endif
13041
13042   /* API messages we can send */
13043 #define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
13044   foreach_vpe_api_msg;
13045 #undef _
13046
13047   /* Help strings */
13048 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
13049   foreach_vpe_api_msg;
13050 #undef _
13051
13052   /* CLI functions */
13053 #define _(n,h) hash_set_mem (vam->function_by_name, #n, n);
13054   foreach_cli_function;
13055 #undef _
13056
13057   /* Help strings */
13058 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
13059   foreach_cli_function;
13060 #undef _
13061 }
13062
13063 #if VPP_API_TEST_BUILTIN
13064 static clib_error_t *
13065 vat_api_hookup_shim (vlib_main_t * vm)
13066 {
13067   vat_api_hookup (&vat_main);
13068   return 0;
13069 }
13070
13071 VLIB_API_INIT_FUNCTION (vat_api_hookup_shim);
13072 #endif
13073
13074 /*
13075  * fd.io coding-style-patch-verification: ON
13076  *
13077  * Local Variables:
13078  * eval: (c-set-style "gnu")
13079  * End:
13080  */