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