misc: minimize dependencies on udp.h
[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/vxlan/vxlan.h>
31 #include <vnet/gre/gre.h>
32 #include <vnet/vxlan-gpe/vxlan_gpe.h>
33 #include <vnet/udp/udp_local.h>
34
35 #include <vpp/api/vpe_msg_enum.h>
36 #include <vnet/l2/l2_classify.h>
37 #include <vnet/l2/l2_vtr.h>
38 #include <vnet/classify/in_out_acl.h>
39 #include <vnet/classify/policer_classify.h>
40 #include <vnet/classify/flow_classify.h>
41 #include <vnet/mpls/mpls.h>
42 #include <vnet/ipsec/ipsec.h>
43 #include <inttypes.h>
44 #include <vnet/ip/ip6_hop_by_hop.h>
45 #include <vnet/ip/ip_source_and_port_range_check.h>
46 #include <vnet/policer/xlate.h>
47 #include <vnet/span/span.h>
48 #include <vnet/policer/policer.h>
49 #include <vnet/policer/police.h>
50 #include <vnet/mfib/mfib_types.h>
51 #include <vnet/bonding/node.h>
52 #include <vnet/qos/qos_types.h>
53 #include <vnet/ethernet/ethernet_types_api.h>
54 #include <vnet/ip/ip_types_api.h>
55 #include "vat/json_format.h"
56 #include <vnet/ip/ip_types_api.h>
57 #include <vnet/ethernet/ethernet_types_api.h>
58
59 #include <inttypes.h>
60 #include <sys/stat.h>
61
62 #define vl_typedefs             /* define message structures */
63 #include <vpp/api/vpe_all_api_h.h>
64 #undef vl_typedefs
65
66 /* declare message handlers for each api */
67
68 #define vl_endianfun            /* define message structures */
69 #include <vpp/api/vpe_all_api_h.h>
70 #undef vl_endianfun
71
72 /* instantiate all the print functions we know about */
73 #if VPP_API_TEST_BUILTIN == 0
74 #define vl_print(handle, ...)
75 #else
76 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
77 #endif
78 #define vl_printfun
79 #include <vpp/api/vpe_all_api_h.h>
80 #undef vl_printfun
81
82 #define __plugin_msg_base 0
83 #include <vlibapi/vat_helper_macros.h>
84
85 #include <vnet/format_fns.h>
86
87 void vl_api_set_elog_main (elog_main_t * m);
88 int vl_api_set_elog_trace_api_messages (int enable);
89
90 #if VPP_API_TEST_BUILTIN == 0
91 #include <netdb.h>
92
93 u32
94 vl (void *p)
95 {
96   return vec_len (p);
97 }
98
99 int
100 vat_socket_connect (vat_main_t * vam)
101 {
102   int rv;
103   api_main_t *am = vlibapi_get_main ();
104   vam->socket_client_main = &socket_client_main;
105   if ((rv = vl_socket_client_connect ((char *) vam->socket_name,
106                                       "vpp_api_test",
107                                       0 /* default socket rx, tx buffer */ )))
108     return rv;
109
110   /* vpp expects the client index in network order */
111   vam->my_client_index = htonl (socket_client_main.client_index);
112   am->my_client_index = vam->my_client_index;
113   return 0;
114 }
115 #else /* vpp built-in case, we don't do sockets... */
116 int
117 vat_socket_connect (vat_main_t * vam)
118 {
119   return 0;
120 }
121
122 int
123 vl_socket_client_read (int wait)
124 {
125   return -1;
126 };
127
128 int
129 vl_socket_client_write ()
130 {
131   return -1;
132 };
133
134 void *
135 vl_socket_client_msg_alloc (int nbytes)
136 {
137   return 0;
138 }
139 #endif
140
141
142 f64
143 vat_time_now (vat_main_t * vam)
144 {
145 #if VPP_API_TEST_BUILTIN
146   return vlib_time_now (vam->vlib_main);
147 #else
148   return clib_time_now (&vam->clib_time);
149 #endif
150 }
151
152 void
153 errmsg (char *fmt, ...)
154 {
155   vat_main_t *vam = &vat_main;
156   va_list va;
157   u8 *s;
158
159   va_start (va, fmt);
160   s = va_format (0, fmt, &va);
161   va_end (va);
162
163   vec_add1 (s, 0);
164
165 #if VPP_API_TEST_BUILTIN
166   vlib_cli_output (vam->vlib_main, (char *) s);
167 #else
168   {
169     if (vam->ifp != stdin)
170       fformat (vam->ofp, "%s(%d): \n", vam->current_file,
171                vam->input_line_number);
172     else
173       fformat (vam->ofp, "%s\n", (char *) s);
174     fflush (vam->ofp);
175   }
176 #endif
177
178   vec_free (s);
179 }
180
181 #if VPP_API_TEST_BUILTIN == 0
182 static uword
183 api_unformat_sw_if_index (unformat_input_t * input, va_list * args)
184 {
185   vat_main_t *vam = va_arg (*args, vat_main_t *);
186   u32 *result = va_arg (*args, u32 *);
187   u8 *if_name;
188   uword *p;
189
190   if (!unformat (input, "%s", &if_name))
191     return 0;
192
193   p = hash_get_mem (vam->sw_if_index_by_interface_name, if_name);
194   if (p == 0)
195     return 0;
196   *result = p[0];
197   return 1;
198 }
199
200 static uword
201 api_unformat_hw_if_index (unformat_input_t * input, va_list * args)
202 {
203   return 0;
204 }
205
206 /* Parse an IP4 address %d.%d.%d.%d. */
207 uword
208 unformat_ip4_address (unformat_input_t * input, va_list * args)
209 {
210   u8 *result = va_arg (*args, u8 *);
211   unsigned a[4];
212
213   if (!unformat (input, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]))
214     return 0;
215
216   if (a[0] >= 256 || a[1] >= 256 || a[2] >= 256 || a[3] >= 256)
217     return 0;
218
219   result[0] = a[0];
220   result[1] = a[1];
221   result[2] = a[2];
222   result[3] = a[3];
223
224   return 1;
225 }
226
227 uword
228 unformat_ethernet_address (unformat_input_t * input, va_list * args)
229 {
230   u8 *result = va_arg (*args, u8 *);
231   u32 i, a[6];
232
233   if (!unformat (input, "%_%x:%x:%x:%x:%x:%x%_",
234                  &a[0], &a[1], &a[2], &a[3], &a[4], &a[5]))
235     return 0;
236
237   /* Check range. */
238   for (i = 0; i < 6; i++)
239     if (a[i] >= (1 << 8))
240       return 0;
241
242   for (i = 0; i < 6; i++)
243     result[i] = a[i];
244
245   return 1;
246 }
247
248 /* Returns ethernet type as an int in host byte order. */
249 uword
250 unformat_ethernet_type_host_byte_order (unformat_input_t * input,
251                                         va_list * args)
252 {
253   u16 *result = va_arg (*args, u16 *);
254   int type;
255
256   /* Numeric type. */
257   if (unformat (input, "0x%x", &type) || unformat (input, "%d", &type))
258     {
259       if (type >= (1 << 16))
260         return 0;
261       *result = type;
262       return 1;
263     }
264   return 0;
265 }
266
267 /* Parse an IP46 address. */
268 uword
269 unformat_ip46_address (unformat_input_t * input, va_list * args)
270 {
271   ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
272   ip46_type_t type = va_arg (*args, ip46_type_t);
273   if ((type != IP46_TYPE_IP6) &&
274       unformat (input, "%U", unformat_ip4_address, &ip46->ip4))
275     {
276       ip46_address_mask_ip4 (ip46);
277       return 1;
278     }
279   else if ((type != IP46_TYPE_IP4) &&
280            unformat (input, "%U", unformat_ip6_address, &ip46->ip6))
281     {
282       return 1;
283     }
284   return 0;
285 }
286
287 /* Parse an IP6 address. */
288 uword
289 unformat_ip6_address (unformat_input_t * input, va_list * args)
290 {
291   ip6_address_t *result = va_arg (*args, ip6_address_t *);
292   u16 hex_quads[8];
293   uword hex_quad, n_hex_quads, hex_digit, n_hex_digits;
294   uword c, n_colon, double_colon_index;
295
296   n_hex_quads = hex_quad = n_hex_digits = n_colon = 0;
297   double_colon_index = ARRAY_LEN (hex_quads);
298   while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
299     {
300       hex_digit = 16;
301       if (c >= '0' && c <= '9')
302         hex_digit = c - '0';
303       else if (c >= 'a' && c <= 'f')
304         hex_digit = c + 10 - 'a';
305       else if (c >= 'A' && c <= 'F')
306         hex_digit = c + 10 - 'A';
307       else if (c == ':' && n_colon < 2)
308         n_colon++;
309       else
310         {
311           unformat_put_input (input);
312           break;
313         }
314
315       /* Too many hex quads. */
316       if (n_hex_quads >= ARRAY_LEN (hex_quads))
317         return 0;
318
319       if (hex_digit < 16)
320         {
321           hex_quad = (hex_quad << 4) | hex_digit;
322
323           /* Hex quad must fit in 16 bits. */
324           if (n_hex_digits >= 4)
325             return 0;
326
327           n_colon = 0;
328           n_hex_digits++;
329         }
330
331       /* Save position of :: */
332       if (n_colon == 2)
333         {
334           /* More than one :: ? */
335           if (double_colon_index < ARRAY_LEN (hex_quads))
336             return 0;
337           double_colon_index = n_hex_quads;
338         }
339
340       if (n_colon > 0 && n_hex_digits > 0)
341         {
342           hex_quads[n_hex_quads++] = hex_quad;
343           hex_quad = 0;
344           n_hex_digits = 0;
345         }
346     }
347
348   if (n_hex_digits > 0)
349     hex_quads[n_hex_quads++] = hex_quad;
350
351   {
352     word i;
353
354     /* Expand :: to appropriate number of zero hex quads. */
355     if (double_colon_index < ARRAY_LEN (hex_quads))
356       {
357         word n_zero = ARRAY_LEN (hex_quads) - n_hex_quads;
358
359         for (i = n_hex_quads - 1; i >= (signed) double_colon_index; i--)
360           hex_quads[n_zero + i] = hex_quads[i];
361
362         for (i = 0; i < n_zero; i++)
363           hex_quads[double_colon_index + i] = 0;
364
365         n_hex_quads = ARRAY_LEN (hex_quads);
366       }
367
368     /* Too few hex quads given. */
369     if (n_hex_quads < ARRAY_LEN (hex_quads))
370       return 0;
371
372     for (i = 0; i < ARRAY_LEN (hex_quads); i++)
373       result->as_u16[i] = clib_host_to_net_u16 (hex_quads[i]);
374
375     return 1;
376   }
377 }
378
379 uword
380 unformat_ipsec_policy_action (unformat_input_t * input, va_list * args)
381 {
382   u32 *r = va_arg (*args, u32 *);
383
384   if (0);
385 #define _(v,f,s) else if (unformat (input, s)) *r = IPSEC_POLICY_ACTION_##f;
386   foreach_ipsec_policy_action
387 #undef _
388     else
389     return 0;
390   return 1;
391 }
392
393 u8 *
394 format_ipsec_crypto_alg (u8 * s, va_list * args)
395 {
396   u32 i = va_arg (*args, u32);
397   u8 *t = 0;
398
399   switch (i)
400     {
401 #define _(v,f,str) case IPSEC_CRYPTO_ALG_##f: t = (u8 *) str; break;
402       foreach_ipsec_crypto_alg
403 #undef _
404     default:
405       return format (s, "unknown");
406     }
407   return format (s, "%s", t);
408 }
409
410 u8 *
411 format_ipsec_integ_alg (u8 * s, va_list * args)
412 {
413   u32 i = va_arg (*args, u32);
414   u8 *t = 0;
415
416   switch (i)
417     {
418 #define _(v,f,str) case IPSEC_INTEG_ALG_##f: t = (u8 *) str; break;
419       foreach_ipsec_integ_alg
420 #undef _
421     default:
422       return format (s, "unknown");
423     }
424   return format (s, "%s", t);
425 }
426
427 #else /* VPP_API_TEST_BUILTIN == 1 */
428 static uword
429 api_unformat_sw_if_index (unformat_input_t * input, va_list * args)
430 {
431   vat_main_t *vam __clib_unused = va_arg (*args, vat_main_t *);
432   vnet_main_t *vnm = vnet_get_main ();
433   u32 *result = va_arg (*args, u32 *);
434
435   return unformat (input, "%U", unformat_vnet_sw_interface, vnm, result);
436 }
437
438 static uword
439 api_unformat_hw_if_index (unformat_input_t * input, va_list * args)
440 {
441   vat_main_t *vam __clib_unused = va_arg (*args, vat_main_t *);
442   vnet_main_t *vnm = vnet_get_main ();
443   u32 *result = va_arg (*args, u32 *);
444
445   return unformat (input, "%U", unformat_vnet_hw_interface, vnm, result);
446 }
447
448 #endif /* VPP_API_TEST_BUILTIN */
449
450 uword
451 unformat_ipsec_api_crypto_alg (unformat_input_t * input, va_list * args)
452 {
453   u32 *r = va_arg (*args, u32 *);
454
455   if (0);
456 #define _(v,f,s) else if (unformat (input, s)) *r = IPSEC_API_CRYPTO_ALG_##f;
457   foreach_ipsec_crypto_alg
458 #undef _
459     else
460     return 0;
461   return 1;
462 }
463
464 uword
465 unformat_ipsec_api_integ_alg (unformat_input_t * input, va_list * args)
466 {
467   u32 *r = va_arg (*args, u32 *);
468
469   if (0);
470 #define _(v,f,s) else if (unformat (input, s)) *r = IPSEC_API_INTEG_ALG_##f;
471   foreach_ipsec_integ_alg
472 #undef _
473     else
474     return 0;
475   return 1;
476 }
477
478 static uword
479 unformat_policer_rate_type (unformat_input_t * input, va_list * args)
480 {
481   u8 *r = va_arg (*args, u8 *);
482
483   if (unformat (input, "kbps"))
484     *r = SSE2_QOS_RATE_KBPS;
485   else if (unformat (input, "pps"))
486     *r = SSE2_QOS_RATE_PPS;
487   else
488     return 0;
489   return 1;
490 }
491
492 static uword
493 unformat_policer_round_type (unformat_input_t * input, va_list * args)
494 {
495   u8 *r = va_arg (*args, u8 *);
496
497   if (unformat (input, "closest"))
498     *r = SSE2_QOS_ROUND_TO_CLOSEST;
499   else if (unformat (input, "up"))
500     *r = SSE2_QOS_ROUND_TO_UP;
501   else if (unformat (input, "down"))
502     *r = SSE2_QOS_ROUND_TO_DOWN;
503   else
504     return 0;
505   return 1;
506 }
507
508 static uword
509 unformat_policer_type (unformat_input_t * input, va_list * args)
510 {
511   u8 *r = va_arg (*args, u8 *);
512
513   if (unformat (input, "1r2c"))
514     *r = SSE2_QOS_POLICER_TYPE_1R2C;
515   else if (unformat (input, "1r3c"))
516     *r = SSE2_QOS_POLICER_TYPE_1R3C_RFC_2697;
517   else if (unformat (input, "2r3c-2698"))
518     *r = SSE2_QOS_POLICER_TYPE_2R3C_RFC_2698;
519   else if (unformat (input, "2r3c-4115"))
520     *r = SSE2_QOS_POLICER_TYPE_2R3C_RFC_4115;
521   else if (unformat (input, "2r3c-mef5cf1"))
522     *r = SSE2_QOS_POLICER_TYPE_2R3C_RFC_MEF5CF1;
523   else
524     return 0;
525   return 1;
526 }
527
528 static uword
529 unformat_dscp (unformat_input_t * input, va_list * va)
530 {
531   u8 *r = va_arg (*va, u8 *);
532
533   if (0);
534 #define _(v,f,str) else if (unformat (input, str)) *r = VNET_DSCP_##f;
535   foreach_vnet_dscp
536 #undef _
537     else
538     return 0;
539   return 1;
540 }
541
542 static uword
543 unformat_policer_action_type (unformat_input_t * input, va_list * va)
544 {
545   sse2_qos_pol_action_params_st *a
546     = va_arg (*va, sse2_qos_pol_action_params_st *);
547
548   if (unformat (input, "drop"))
549     a->action_type = SSE2_QOS_ACTION_DROP;
550   else if (unformat (input, "transmit"))
551     a->action_type = SSE2_QOS_ACTION_TRANSMIT;
552   else if (unformat (input, "mark-and-transmit %U", unformat_dscp, &a->dscp))
553     a->action_type = SSE2_QOS_ACTION_MARK_AND_TRANSMIT;
554   else
555     return 0;
556   return 1;
557 }
558
559 static uword
560 unformat_policer_classify_table_type (unformat_input_t * input, va_list * va)
561 {
562   u32 *r = va_arg (*va, u32 *);
563   u32 tid;
564
565   if (unformat (input, "ip4"))
566     tid = POLICER_CLASSIFY_TABLE_IP4;
567   else if (unformat (input, "ip6"))
568     tid = POLICER_CLASSIFY_TABLE_IP6;
569   else if (unformat (input, "l2"))
570     tid = POLICER_CLASSIFY_TABLE_L2;
571   else
572     return 0;
573
574   *r = tid;
575   return 1;
576 }
577
578 static uword
579 unformat_flow_classify_table_type (unformat_input_t * input, va_list * va)
580 {
581   u32 *r = va_arg (*va, u32 *);
582   u32 tid;
583
584   if (unformat (input, "ip4"))
585     tid = FLOW_CLASSIFY_TABLE_IP4;
586   else if (unformat (input, "ip6"))
587     tid = FLOW_CLASSIFY_TABLE_IP6;
588   else
589     return 0;
590
591   *r = tid;
592   return 1;
593 }
594
595 #if (VPP_API_TEST_BUILTIN==0)
596
597 static const char *mfib_flag_names[] = MFIB_ENTRY_NAMES_SHORT;
598 static const char *mfib_flag_long_names[] = MFIB_ENTRY_NAMES_LONG;
599 static const char *mfib_itf_flag_long_names[] = MFIB_ITF_NAMES_LONG;
600 static const char *mfib_itf_flag_names[] = MFIB_ITF_NAMES_SHORT;
601
602 uword
603 unformat_mfib_itf_flags (unformat_input_t * input, va_list * args)
604 {
605   mfib_itf_flags_t old, *iflags = va_arg (*args, mfib_itf_flags_t *);
606   mfib_itf_attribute_t attr;
607
608   old = *iflags;
609   FOR_EACH_MFIB_ITF_ATTRIBUTE (attr)
610   {
611     if (unformat (input, mfib_itf_flag_long_names[attr]))
612       *iflags |= (1 << attr);
613   }
614   FOR_EACH_MFIB_ITF_ATTRIBUTE (attr)
615   {
616     if (unformat (input, mfib_itf_flag_names[attr]))
617       *iflags |= (1 << attr);
618   }
619
620   return (old == *iflags ? 0 : 1);
621 }
622
623 uword
624 unformat_mfib_entry_flags (unformat_input_t * input, va_list * args)
625 {
626   mfib_entry_flags_t old, *eflags = va_arg (*args, mfib_entry_flags_t *);
627   mfib_entry_attribute_t attr;
628
629   old = *eflags;
630   FOR_EACH_MFIB_ATTRIBUTE (attr)
631   {
632     if (unformat (input, mfib_flag_long_names[attr]))
633       *eflags |= (1 << attr);
634   }
635   FOR_EACH_MFIB_ATTRIBUTE (attr)
636   {
637     if (unformat (input, mfib_flag_names[attr]))
638       *eflags |= (1 << attr);
639   }
640
641   return (old == *eflags ? 0 : 1);
642 }
643
644 u8 *
645 format_ip4_address (u8 * s, va_list * args)
646 {
647   u8 *a = va_arg (*args, u8 *);
648   return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
649 }
650
651 u8 *
652 format_ip6_address (u8 * s, va_list * args)
653 {
654   ip6_address_t *a = va_arg (*args, ip6_address_t *);
655   u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;
656
657   i_max_n_zero = ARRAY_LEN (a->as_u16);
658   max_n_zeros = 0;
659   i_first_zero = i_max_n_zero;
660   n_zeros = 0;
661   for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
662     {
663       u32 is_zero = a->as_u16[i] == 0;
664       if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16))
665         {
666           i_first_zero = i;
667           n_zeros = 0;
668         }
669       n_zeros += is_zero;
670       if ((!is_zero && n_zeros > max_n_zeros)
671           || (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros))
672         {
673           i_max_n_zero = i_first_zero;
674           max_n_zeros = n_zeros;
675           i_first_zero = ARRAY_LEN (a->as_u16);
676           n_zeros = 0;
677         }
678     }
679
680   last_double_colon = 0;
681   for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
682     {
683       if (i == i_max_n_zero && max_n_zeros > 1)
684         {
685           s = format (s, "::");
686           i += max_n_zeros - 1;
687           last_double_colon = 1;
688         }
689       else
690         {
691           s = format (s, "%s%x",
692                       (last_double_colon || i == 0) ? "" : ":",
693                       clib_net_to_host_u16 (a->as_u16[i]));
694           last_double_colon = 0;
695         }
696     }
697
698   return s;
699 }
700
701 /* Format an IP46 address. */
702 u8 *
703 format_ip46_address (u8 * s, va_list * args)
704 {
705   ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
706   ip46_type_t type = va_arg (*args, ip46_type_t);
707   int is_ip4 = 1;
708
709   switch (type)
710     {
711     case IP46_TYPE_ANY:
712       is_ip4 = ip46_address_is_ip4 (ip46);
713       break;
714     case IP46_TYPE_IP4:
715       is_ip4 = 1;
716       break;
717     case IP46_TYPE_IP6:
718       is_ip4 = 0;
719       break;
720     }
721
722   return is_ip4 ?
723     format (s, "%U", format_ip4_address, &ip46->ip4) :
724     format (s, "%U", format_ip6_address, &ip46->ip6);
725 }
726
727 u8 *
728 format_ethernet_address (u8 * s, va_list * args)
729 {
730   u8 *a = va_arg (*args, u8 *);
731
732   return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
733                  a[0], a[1], a[2], a[3], a[4], a[5]);
734 }
735 #endif
736
737 static void
738 increment_v4_address (vl_api_ip4_address_t * i)
739 {
740   ip4_address_t *a = (ip4_address_t *) i;
741   u32 v;
742
743   v = ntohl (a->as_u32) + 1;
744   a->as_u32 = ntohl (v);
745 }
746
747 static void
748 increment_v6_address (vl_api_ip6_address_t * i)
749 {
750   ip6_address_t *a = (ip6_address_t *) i;
751   u64 v0, v1;
752
753   v0 = clib_net_to_host_u64 (a->as_u64[0]);
754   v1 = clib_net_to_host_u64 (a->as_u64[1]);
755
756   v1 += 1;
757   if (v1 == 0)
758     v0 += 1;
759   a->as_u64[0] = clib_net_to_host_u64 (v0);
760   a->as_u64[1] = clib_net_to_host_u64 (v1);
761 }
762
763 static void
764 increment_address (vl_api_address_t * a)
765 {
766   if (a->af == ADDRESS_IP4)
767     increment_v4_address (&a->un.ip4);
768   else if (a->af == ADDRESS_IP6)
769     increment_v6_address (&a->un.ip6);
770 }
771
772 static void
773 set_ip4_address (vl_api_address_t * a, u32 v)
774 {
775   if (a->af == ADDRESS_IP4)
776     {
777       ip4_address_t *i = (ip4_address_t *) & a->un.ip4;
778       i->as_u32 = v;
779     }
780 }
781
782 void
783 ip_set (ip46_address_t * dst, void *src, u8 is_ip4)
784 {
785   if (is_ip4)
786     dst->ip4.as_u32 = ((ip4_address_t *) src)->as_u32;
787   else
788     clib_memcpy_fast (&dst->ip6, (ip6_address_t *) src,
789                       sizeof (ip6_address_t));
790 }
791
792 static void
793 increment_mac_address (u8 * mac)
794 {
795   u64 tmp = *((u64 *) mac);
796   tmp = clib_net_to_host_u64 (tmp);
797   tmp += 1 << 16;               /* skip unused (least significant) octets */
798   tmp = clib_host_to_net_u64 (tmp);
799
800   clib_memcpy (mac, &tmp, 6);
801 }
802
803 static void
804 vat_json_object_add_address (vat_json_node_t * node,
805                              const char *str, const vl_api_address_t * addr)
806 {
807   if (ADDRESS_IP6 == addr->af)
808     {
809       struct in6_addr ip6;
810
811       clib_memcpy (&ip6, &addr->un.ip6, sizeof (ip6));
812       vat_json_object_add_ip6 (node, str, ip6);
813     }
814   else
815     {
816       struct in_addr ip4;
817
818       clib_memcpy (&ip4, &addr->un.ip4, sizeof (ip4));
819       vat_json_object_add_ip4 (node, str, ip4);
820     }
821 }
822
823 static void
824 vat_json_object_add_prefix (vat_json_node_t * node,
825                             const vl_api_prefix_t * prefix)
826 {
827   vat_json_object_add_uint (node, "len", prefix->len);
828   vat_json_object_add_address (node, "address", &prefix->address);
829 }
830
831 static void vl_api_create_loopback_reply_t_handler
832   (vl_api_create_loopback_reply_t * mp)
833 {
834   vat_main_t *vam = &vat_main;
835   i32 retval = ntohl (mp->retval);
836
837   vam->retval = retval;
838   vam->regenerate_interface_table = 1;
839   vam->sw_if_index = ntohl (mp->sw_if_index);
840   vam->result_ready = 1;
841 }
842
843 static void vl_api_create_loopback_reply_t_handler_json
844   (vl_api_create_loopback_reply_t * mp)
845 {
846   vat_main_t *vam = &vat_main;
847   vat_json_node_t node;
848
849   vat_json_init_object (&node);
850   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
851   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
852
853   vat_json_print (vam->ofp, &node);
854   vat_json_free (&node);
855   vam->retval = ntohl (mp->retval);
856   vam->result_ready = 1;
857 }
858
859 static void vl_api_create_loopback_instance_reply_t_handler
860   (vl_api_create_loopback_instance_reply_t * mp)
861 {
862   vat_main_t *vam = &vat_main;
863   i32 retval = ntohl (mp->retval);
864
865   vam->retval = retval;
866   vam->regenerate_interface_table = 1;
867   vam->sw_if_index = ntohl (mp->sw_if_index);
868   vam->result_ready = 1;
869 }
870
871 static void vl_api_create_loopback_instance_reply_t_handler_json
872   (vl_api_create_loopback_instance_reply_t * mp)
873 {
874   vat_main_t *vam = &vat_main;
875   vat_json_node_t node;
876
877   vat_json_init_object (&node);
878   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
879   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
880
881   vat_json_print (vam->ofp, &node);
882   vat_json_free (&node);
883   vam->retval = ntohl (mp->retval);
884   vam->result_ready = 1;
885 }
886
887 static void vl_api_af_packet_create_reply_t_handler
888   (vl_api_af_packet_create_reply_t * mp)
889 {
890   vat_main_t *vam = &vat_main;
891   i32 retval = ntohl (mp->retval);
892
893   vam->retval = retval;
894   vam->regenerate_interface_table = 1;
895   vam->sw_if_index = ntohl (mp->sw_if_index);
896   vam->result_ready = 1;
897 }
898
899 static void vl_api_af_packet_create_reply_t_handler_json
900   (vl_api_af_packet_create_reply_t * mp)
901 {
902   vat_main_t *vam = &vat_main;
903   vat_json_node_t node;
904
905   vat_json_init_object (&node);
906   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
907   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
908
909   vat_json_print (vam->ofp, &node);
910   vat_json_free (&node);
911
912   vam->retval = ntohl (mp->retval);
913   vam->result_ready = 1;
914 }
915
916 static void vl_api_create_vlan_subif_reply_t_handler
917   (vl_api_create_vlan_subif_reply_t * mp)
918 {
919   vat_main_t *vam = &vat_main;
920   i32 retval = ntohl (mp->retval);
921
922   vam->retval = retval;
923   vam->regenerate_interface_table = 1;
924   vam->sw_if_index = ntohl (mp->sw_if_index);
925   vam->result_ready = 1;
926 }
927
928 static void vl_api_create_vlan_subif_reply_t_handler_json
929   (vl_api_create_vlan_subif_reply_t * mp)
930 {
931   vat_main_t *vam = &vat_main;
932   vat_json_node_t node;
933
934   vat_json_init_object (&node);
935   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
936   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
937
938   vat_json_print (vam->ofp, &node);
939   vat_json_free (&node);
940
941   vam->retval = ntohl (mp->retval);
942   vam->result_ready = 1;
943 }
944
945 static void vl_api_create_subif_reply_t_handler
946   (vl_api_create_subif_reply_t * mp)
947 {
948   vat_main_t *vam = &vat_main;
949   i32 retval = ntohl (mp->retval);
950
951   vam->retval = retval;
952   vam->regenerate_interface_table = 1;
953   vam->sw_if_index = ntohl (mp->sw_if_index);
954   vam->result_ready = 1;
955 }
956
957 static void vl_api_create_subif_reply_t_handler_json
958   (vl_api_create_subif_reply_t * mp)
959 {
960   vat_main_t *vam = &vat_main;
961   vat_json_node_t node;
962
963   vat_json_init_object (&node);
964   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
965   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
966
967   vat_json_print (vam->ofp, &node);
968   vat_json_free (&node);
969
970   vam->retval = ntohl (mp->retval);
971   vam->result_ready = 1;
972 }
973
974 static void vl_api_interface_name_renumber_reply_t_handler
975   (vl_api_interface_name_renumber_reply_t * mp)
976 {
977   vat_main_t *vam = &vat_main;
978   i32 retval = ntohl (mp->retval);
979
980   vam->retval = retval;
981   vam->regenerate_interface_table = 1;
982   vam->result_ready = 1;
983 }
984
985 static void vl_api_interface_name_renumber_reply_t_handler_json
986   (vl_api_interface_name_renumber_reply_t * mp)
987 {
988   vat_main_t *vam = &vat_main;
989   vat_json_node_t node;
990
991   vat_json_init_object (&node);
992   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
993
994   vat_json_print (vam->ofp, &node);
995   vat_json_free (&node);
996
997   vam->retval = ntohl (mp->retval);
998   vam->result_ready = 1;
999 }
1000
1001 /*
1002  * Special-case: build the interface table, maintain
1003  * the next loopback sw_if_index vbl.
1004  */
1005 static void vl_api_sw_interface_details_t_handler
1006   (vl_api_sw_interface_details_t * mp)
1007 {
1008   vat_main_t *vam = &vat_main;
1009   u8 *s = format (0, "%s%c", mp->interface_name, 0);
1010
1011   hash_set_mem (vam->sw_if_index_by_interface_name, s,
1012                 ntohl (mp->sw_if_index));
1013
1014   /* In sub interface case, fill the sub interface table entry */
1015   if (mp->sw_if_index != mp->sup_sw_if_index)
1016     {
1017       sw_interface_subif_t *sub = NULL;
1018
1019       vec_add2 (vam->sw_if_subif_table, sub, 1);
1020
1021       vec_validate (sub->interface_name, strlen ((char *) s) + 1);
1022       strncpy ((char *) sub->interface_name, (char *) s,
1023                vec_len (sub->interface_name));
1024       sub->sw_if_index = ntohl (mp->sw_if_index);
1025       sub->sub_id = ntohl (mp->sub_id);
1026
1027       sub->raw_flags = ntohl (mp->sub_if_flags & SUB_IF_API_FLAG_MASK_VNET);
1028
1029       sub->sub_number_of_tags = mp->sub_number_of_tags;
1030       sub->sub_outer_vlan_id = ntohs (mp->sub_outer_vlan_id);
1031       sub->sub_inner_vlan_id = ntohs (mp->sub_inner_vlan_id);
1032
1033       /* vlan tag rewrite */
1034       sub->vtr_op = ntohl (mp->vtr_op);
1035       sub->vtr_push_dot1q = ntohl (mp->vtr_push_dot1q);
1036       sub->vtr_tag1 = ntohl (mp->vtr_tag1);
1037       sub->vtr_tag2 = ntohl (mp->vtr_tag2);
1038     }
1039 }
1040
1041 static void vl_api_sw_interface_details_t_handler_json
1042   (vl_api_sw_interface_details_t * mp)
1043 {
1044   vat_main_t *vam = &vat_main;
1045   vat_json_node_t *node = NULL;
1046
1047   if (VAT_JSON_ARRAY != vam->json_tree.type)
1048     {
1049       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
1050       vat_json_init_array (&vam->json_tree);
1051     }
1052   node = vat_json_array_add (&vam->json_tree);
1053
1054   vat_json_init_object (node);
1055   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
1056   vat_json_object_add_uint (node, "sup_sw_if_index",
1057                             ntohl (mp->sup_sw_if_index));
1058   vat_json_object_add_bytes (node, "l2_address", mp->l2_address,
1059                              sizeof (mp->l2_address));
1060   vat_json_object_add_string_copy (node, "interface_name",
1061                                    mp->interface_name);
1062   vat_json_object_add_string_copy (node, "interface_dev_type",
1063                                    mp->interface_dev_type);
1064   vat_json_object_add_uint (node, "flags", mp->flags);
1065   vat_json_object_add_uint (node, "link_duplex", mp->link_duplex);
1066   vat_json_object_add_uint (node, "link_speed", mp->link_speed);
1067   vat_json_object_add_uint (node, "mtu", ntohs (mp->link_mtu));
1068   vat_json_object_add_uint (node, "sub_id", ntohl (mp->sub_id));
1069   vat_json_object_add_uint (node, "sub_number_of_tags",
1070                             mp->sub_number_of_tags);
1071   vat_json_object_add_uint (node, "sub_outer_vlan_id",
1072                             ntohs (mp->sub_outer_vlan_id));
1073   vat_json_object_add_uint (node, "sub_inner_vlan_id",
1074                             ntohs (mp->sub_inner_vlan_id));
1075   vat_json_object_add_uint (node, "sub_if_flags", ntohl (mp->sub_if_flags));
1076   vat_json_object_add_uint (node, "vtr_op", ntohl (mp->vtr_op));
1077   vat_json_object_add_uint (node, "vtr_push_dot1q",
1078                             ntohl (mp->vtr_push_dot1q));
1079   vat_json_object_add_uint (node, "vtr_tag1", ntohl (mp->vtr_tag1));
1080   vat_json_object_add_uint (node, "vtr_tag2", ntohl (mp->vtr_tag2));
1081   if (ntohl (mp->sub_if_flags) & SUB_IF_API_FLAG_DOT1AH)
1082     {
1083       vat_json_object_add_string_copy (node, "pbb_vtr_dmac",
1084                                        format (0, "%U",
1085                                                format_ethernet_address,
1086                                                &mp->b_dmac));
1087       vat_json_object_add_string_copy (node, "pbb_vtr_smac",
1088                                        format (0, "%U",
1089                                                format_ethernet_address,
1090                                                &mp->b_smac));
1091       vat_json_object_add_uint (node, "pbb_vtr_b_vlanid", mp->b_vlanid);
1092       vat_json_object_add_uint (node, "pbb_vtr_i_sid", mp->i_sid);
1093     }
1094 }
1095
1096 #if VPP_API_TEST_BUILTIN == 0
1097 static void vl_api_sw_interface_event_t_handler
1098   (vl_api_sw_interface_event_t * mp)
1099 {
1100   vat_main_t *vam = &vat_main;
1101   if (vam->interface_event_display)
1102     errmsg ("interface flags: sw_if_index %d %s %s",
1103             ntohl (mp->sw_if_index),
1104             ((ntohl (mp->flags)) & IF_STATUS_API_FLAG_ADMIN_UP) ?
1105             "admin-up" : "admin-down",
1106             ((ntohl (mp->flags)) & IF_STATUS_API_FLAG_LINK_UP) ?
1107             "link-up" : "link-down");
1108 }
1109 #endif
1110
1111 __clib_unused static void
1112 vl_api_sw_interface_event_t_handler_json (vl_api_sw_interface_event_t * mp)
1113 {
1114   /* JSON output not supported */
1115 }
1116
1117 static void
1118 vl_api_cli_reply_t_handler (vl_api_cli_reply_t * mp)
1119 {
1120   vat_main_t *vam = &vat_main;
1121   i32 retval = ntohl (mp->retval);
1122
1123   vam->retval = retval;
1124   vam->shmem_result = uword_to_pointer (mp->reply_in_shmem, u8 *);
1125   vam->result_ready = 1;
1126 }
1127
1128 static void
1129 vl_api_cli_reply_t_handler_json (vl_api_cli_reply_t * mp)
1130 {
1131   vat_main_t *vam = &vat_main;
1132   vat_json_node_t node;
1133   void *oldheap;
1134   u8 *reply;
1135
1136   vat_json_init_object (&node);
1137   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1138   vat_json_object_add_uint (&node, "reply_in_shmem",
1139                             ntohl (mp->reply_in_shmem));
1140   /* Toss the shared-memory original... */
1141   oldheap = vl_msg_push_heap ();
1142
1143   reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
1144   vec_free (reply);
1145
1146   vl_msg_pop_heap (oldheap);
1147
1148   vat_json_print (vam->ofp, &node);
1149   vat_json_free (&node);
1150
1151   vam->retval = ntohl (mp->retval);
1152   vam->result_ready = 1;
1153 }
1154
1155 static void
1156 vl_api_cli_inband_reply_t_handler (vl_api_cli_inband_reply_t * mp)
1157 {
1158   vat_main_t *vam = &vat_main;
1159   i32 retval = ntohl (mp->retval);
1160
1161   vec_reset_length (vam->cmd_reply);
1162
1163   vam->retval = retval;
1164   if (retval == 0)
1165     vam->cmd_reply = vl_api_from_api_to_new_vec (mp, &mp->reply);
1166   vam->result_ready = 1;
1167 }
1168
1169 static void
1170 vl_api_cli_inband_reply_t_handler_json (vl_api_cli_inband_reply_t * mp)
1171 {
1172   vat_main_t *vam = &vat_main;
1173   vat_json_node_t node;
1174   u8 *reply = 0;                /* reply vector */
1175
1176   reply = vl_api_from_api_to_new_vec (mp, &mp->reply);
1177   vec_reset_length (vam->cmd_reply);
1178
1179   vat_json_init_object (&node);
1180   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1181   vat_json_object_add_string_copy (&node, "reply", reply);
1182
1183   vat_json_print (vam->ofp, &node);
1184   vat_json_free (&node);
1185   vec_free (reply);
1186
1187   vam->retval = ntohl (mp->retval);
1188   vam->result_ready = 1;
1189 }
1190
1191 static void vl_api_classify_add_del_table_reply_t_handler
1192   (vl_api_classify_add_del_table_reply_t * mp)
1193 {
1194   vat_main_t *vam = &vat_main;
1195   i32 retval = ntohl (mp->retval);
1196   if (vam->async_mode)
1197     {
1198       vam->async_errors += (retval < 0);
1199     }
1200   else
1201     {
1202       vam->retval = retval;
1203       if (retval == 0 &&
1204           ((mp->new_table_index != 0xFFFFFFFF) ||
1205            (mp->skip_n_vectors != 0xFFFFFFFF) ||
1206            (mp->match_n_vectors != 0xFFFFFFFF)))
1207         /*
1208          * Note: this is just barely thread-safe, depends on
1209          * the main thread spinning waiting for an answer...
1210          */
1211         errmsg ("new index %d, skip_n_vectors %d, match_n_vectors %d",
1212                 ntohl (mp->new_table_index),
1213                 ntohl (mp->skip_n_vectors), ntohl (mp->match_n_vectors));
1214       vam->result_ready = 1;
1215     }
1216 }
1217
1218 static void vl_api_classify_add_del_table_reply_t_handler_json
1219   (vl_api_classify_add_del_table_reply_t * mp)
1220 {
1221   vat_main_t *vam = &vat_main;
1222   vat_json_node_t node;
1223
1224   vat_json_init_object (&node);
1225   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1226   vat_json_object_add_uint (&node, "new_table_index",
1227                             ntohl (mp->new_table_index));
1228   vat_json_object_add_uint (&node, "skip_n_vectors",
1229                             ntohl (mp->skip_n_vectors));
1230   vat_json_object_add_uint (&node, "match_n_vectors",
1231                             ntohl (mp->match_n_vectors));
1232
1233   vat_json_print (vam->ofp, &node);
1234   vat_json_free (&node);
1235
1236   vam->retval = ntohl (mp->retval);
1237   vam->result_ready = 1;
1238 }
1239
1240 static void vl_api_get_node_index_reply_t_handler
1241   (vl_api_get_node_index_reply_t * mp)
1242 {
1243   vat_main_t *vam = &vat_main;
1244   i32 retval = ntohl (mp->retval);
1245   if (vam->async_mode)
1246     {
1247       vam->async_errors += (retval < 0);
1248     }
1249   else
1250     {
1251       vam->retval = retval;
1252       if (retval == 0)
1253         errmsg ("node index %d", ntohl (mp->node_index));
1254       vam->result_ready = 1;
1255     }
1256 }
1257
1258 static void vl_api_get_node_index_reply_t_handler_json
1259   (vl_api_get_node_index_reply_t * mp)
1260 {
1261   vat_main_t *vam = &vat_main;
1262   vat_json_node_t node;
1263
1264   vat_json_init_object (&node);
1265   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1266   vat_json_object_add_uint (&node, "node_index", ntohl (mp->node_index));
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_get_next_index_reply_t_handler
1276   (vl_api_get_next_index_reply_t * mp)
1277 {
1278   vat_main_t *vam = &vat_main;
1279   i32 retval = ntohl (mp->retval);
1280   if (vam->async_mode)
1281     {
1282       vam->async_errors += (retval < 0);
1283     }
1284   else
1285     {
1286       vam->retval = retval;
1287       if (retval == 0)
1288         errmsg ("next node index %d", ntohl (mp->next_index));
1289       vam->result_ready = 1;
1290     }
1291 }
1292
1293 static void vl_api_get_next_index_reply_t_handler_json
1294   (vl_api_get_next_index_reply_t * mp)
1295 {
1296   vat_main_t *vam = &vat_main;
1297   vat_json_node_t node;
1298
1299   vat_json_init_object (&node);
1300   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1301   vat_json_object_add_uint (&node, "next_index", ntohl (mp->next_index));
1302
1303   vat_json_print (vam->ofp, &node);
1304   vat_json_free (&node);
1305
1306   vam->retval = ntohl (mp->retval);
1307   vam->result_ready = 1;
1308 }
1309
1310 static void vl_api_add_node_next_reply_t_handler
1311   (vl_api_add_node_next_reply_t * mp)
1312 {
1313   vat_main_t *vam = &vat_main;
1314   i32 retval = ntohl (mp->retval);
1315   if (vam->async_mode)
1316     {
1317       vam->async_errors += (retval < 0);
1318     }
1319   else
1320     {
1321       vam->retval = retval;
1322       if (retval == 0)
1323         errmsg ("next index %d", ntohl (mp->next_index));
1324       vam->result_ready = 1;
1325     }
1326 }
1327
1328 static void vl_api_add_node_next_reply_t_handler_json
1329   (vl_api_add_node_next_reply_t * mp)
1330 {
1331   vat_main_t *vam = &vat_main;
1332   vat_json_node_t node;
1333
1334   vat_json_init_object (&node);
1335   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1336   vat_json_object_add_uint (&node, "next_index", ntohl (mp->next_index));
1337
1338   vat_json_print (vam->ofp, &node);
1339   vat_json_free (&node);
1340
1341   vam->retval = ntohl (mp->retval);
1342   vam->result_ready = 1;
1343 }
1344
1345 static void vl_api_show_version_reply_t_handler
1346   (vl_api_show_version_reply_t * mp)
1347 {
1348   vat_main_t *vam = &vat_main;
1349   i32 retval = ntohl (mp->retval);
1350
1351   if (retval >= 0)
1352     {
1353       errmsg ("        program: %s", mp->program);
1354       errmsg ("        version: %s", mp->version);
1355       errmsg ("     build date: %s", mp->build_date);
1356       errmsg ("build directory: %s", mp->build_directory);
1357     }
1358   vam->retval = retval;
1359   vam->result_ready = 1;
1360 }
1361
1362 static void vl_api_show_version_reply_t_handler_json
1363   (vl_api_show_version_reply_t * mp)
1364 {
1365   vat_main_t *vam = &vat_main;
1366   vat_json_node_t node;
1367
1368   vat_json_init_object (&node);
1369   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1370   vat_json_object_add_string_copy (&node, "program", mp->program);
1371   vat_json_object_add_string_copy (&node, "version", mp->version);
1372   vat_json_object_add_string_copy (&node, "build_date", mp->build_date);
1373   vat_json_object_add_string_copy (&node, "build_directory",
1374                                    mp->build_directory);
1375
1376   vat_json_print (vam->ofp, &node);
1377   vat_json_free (&node);
1378
1379   vam->retval = ntohl (mp->retval);
1380   vam->result_ready = 1;
1381 }
1382
1383 static void vl_api_show_threads_reply_t_handler
1384   (vl_api_show_threads_reply_t * mp)
1385 {
1386   vat_main_t *vam = &vat_main;
1387   i32 retval = ntohl (mp->retval);
1388   int i, count = 0;
1389
1390   if (retval >= 0)
1391     count = ntohl (mp->count);
1392
1393   for (i = 0; i < count; i++)
1394     print (vam->ofp,
1395            "\n%-2d %-11s %-11s %-5d %-6d %-4d %-6d",
1396            ntohl (mp->thread_data[i].id), mp->thread_data[i].name,
1397            mp->thread_data[i].type, ntohl (mp->thread_data[i].pid),
1398            ntohl (mp->thread_data[i].cpu_id), ntohl (mp->thread_data[i].core),
1399            ntohl (mp->thread_data[i].cpu_socket));
1400
1401   vam->retval = retval;
1402   vam->result_ready = 1;
1403 }
1404
1405 static void vl_api_show_threads_reply_t_handler_json
1406   (vl_api_show_threads_reply_t * mp)
1407 {
1408   vat_main_t *vam = &vat_main;
1409   vat_json_node_t node;
1410   vl_api_thread_data_t *td;
1411   i32 retval = ntohl (mp->retval);
1412   int i, count = 0;
1413
1414   if (retval >= 0)
1415     count = ntohl (mp->count);
1416
1417   vat_json_init_object (&node);
1418   vat_json_object_add_int (&node, "retval", retval);
1419   vat_json_object_add_uint (&node, "count", count);
1420
1421   for (i = 0; i < count; i++)
1422     {
1423       td = &mp->thread_data[i];
1424       vat_json_object_add_uint (&node, "id", ntohl (td->id));
1425       vat_json_object_add_string_copy (&node, "name", td->name);
1426       vat_json_object_add_string_copy (&node, "type", td->type);
1427       vat_json_object_add_uint (&node, "pid", ntohl (td->pid));
1428       vat_json_object_add_int (&node, "cpu_id", ntohl (td->cpu_id));
1429       vat_json_object_add_int (&node, "core", ntohl (td->id));
1430       vat_json_object_add_int (&node, "cpu_socket", ntohl (td->cpu_socket));
1431     }
1432
1433   vat_json_print (vam->ofp, &node);
1434   vat_json_free (&node);
1435
1436   vam->retval = retval;
1437   vam->result_ready = 1;
1438 }
1439
1440 static int
1441 api_show_threads (vat_main_t * vam)
1442 {
1443   vl_api_show_threads_t *mp;
1444   int ret;
1445
1446   print (vam->ofp,
1447          "\n%-2s %-11s %-11s %-5s %-6s %-4s %-6s",
1448          "ID", "Name", "Type", "LWP", "cpu_id", "Core", "Socket");
1449
1450   M (SHOW_THREADS, mp);
1451
1452   S (mp);
1453   W (ret);
1454   return ret;
1455 }
1456
1457 static void
1458 vl_api_l2_macs_event_t_handler (vl_api_l2_macs_event_t * mp)
1459 {
1460   u32 n_macs = ntohl (mp->n_macs);
1461   errmsg ("L2MAC event received with pid %d cl-idx %d for %d macs: \n",
1462           ntohl (mp->pid), mp->client_index, n_macs);
1463   int i;
1464   for (i = 0; i < n_macs; i++)
1465     {
1466       vl_api_mac_entry_t *mac = &mp->mac[i];
1467       errmsg (" [%d] sw_if_index %d  mac_addr %U  action %d \n",
1468               i + 1, ntohl (mac->sw_if_index),
1469               format_ethernet_address, mac->mac_addr, mac->action);
1470       if (i == 1000)
1471         break;
1472     }
1473 }
1474
1475 static void
1476 vl_api_l2_macs_event_t_handler_json (vl_api_l2_macs_event_t * mp)
1477 {
1478   /* JSON output not supported */
1479 }
1480
1481 #define vl_api_bridge_domain_details_t_endian vl_noop_handler
1482 #define vl_api_bridge_domain_details_t_print vl_noop_handler
1483
1484 /*
1485  * Special-case: build the bridge domain table, maintain
1486  * the next bd id vbl.
1487  */
1488 static void vl_api_bridge_domain_details_t_handler
1489   (vl_api_bridge_domain_details_t * mp)
1490 {
1491   vat_main_t *vam = &vat_main;
1492   u32 n_sw_ifs = ntohl (mp->n_sw_ifs);
1493   int i;
1494
1495   print (vam->ofp, "\n%-3s %-3s %-3s %-3s %-3s %-6s %-3s",
1496          " ID", "LRN", "FWD", "FLD", "BVI", "UU-FWD", "#IF");
1497
1498   print (vam->ofp, "%3d %3d %3d %3d %3d %6d %3d",
1499          ntohl (mp->bd_id), mp->learn, mp->forward,
1500          mp->flood, ntohl (mp->bvi_sw_if_index),
1501          ntohl (mp->uu_fwd_sw_if_index), n_sw_ifs);
1502
1503   if (n_sw_ifs)
1504     {
1505       vl_api_bridge_domain_sw_if_t *sw_ifs;
1506       print (vam->ofp, "\n\n%s %s  %s", "sw_if_index", "SHG",
1507              "Interface Name");
1508
1509       sw_ifs = mp->sw_if_details;
1510       for (i = 0; i < n_sw_ifs; i++)
1511         {
1512           u8 *sw_if_name = 0;
1513           u32 sw_if_index;
1514           hash_pair_t *p;
1515
1516           sw_if_index = ntohl (sw_ifs->sw_if_index);
1517
1518           /* *INDENT-OFF* */
1519           hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
1520                              ({
1521                                if ((u32) p->value[0] == sw_if_index)
1522                                  {
1523                                    sw_if_name = (u8 *)(p->key);
1524                                    break;
1525                                  }
1526                              }));
1527           /* *INDENT-ON* */
1528           print (vam->ofp, "%7d     %3d  %s", sw_if_index,
1529                  sw_ifs->shg, sw_if_name ? (char *) sw_if_name :
1530                  "sw_if_index not found!");
1531
1532           sw_ifs++;
1533         }
1534     }
1535 }
1536
1537 static void vl_api_bridge_domain_details_t_handler_json
1538   (vl_api_bridge_domain_details_t * mp)
1539 {
1540   vat_main_t *vam = &vat_main;
1541   vat_json_node_t *node, *array = NULL;
1542   u32 n_sw_ifs = ntohl (mp->n_sw_ifs);
1543
1544   if (VAT_JSON_ARRAY != vam->json_tree.type)
1545     {
1546       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
1547       vat_json_init_array (&vam->json_tree);
1548     }
1549   node = vat_json_array_add (&vam->json_tree);
1550
1551   vat_json_init_object (node);
1552   vat_json_object_add_uint (node, "bd_id", ntohl (mp->bd_id));
1553   vat_json_object_add_uint (node, "flood", mp->flood);
1554   vat_json_object_add_uint (node, "forward", mp->forward);
1555   vat_json_object_add_uint (node, "learn", mp->learn);
1556   vat_json_object_add_uint (node, "bvi_sw_if_index",
1557                             ntohl (mp->bvi_sw_if_index));
1558   vat_json_object_add_uint (node, "n_sw_ifs", n_sw_ifs);
1559   array = vat_json_object_add (node, "sw_if");
1560   vat_json_init_array (array);
1561
1562
1563
1564   if (n_sw_ifs)
1565     {
1566       vl_api_bridge_domain_sw_if_t *sw_ifs;
1567       int i;
1568
1569       sw_ifs = mp->sw_if_details;
1570       for (i = 0; i < n_sw_ifs; i++)
1571         {
1572           node = vat_json_array_add (array);
1573           vat_json_init_object (node);
1574           vat_json_object_add_uint (node, "sw_if_index",
1575                                     ntohl (sw_ifs->sw_if_index));
1576           vat_json_object_add_uint (node, "shg", sw_ifs->shg);
1577           sw_ifs++;
1578         }
1579     }
1580 }
1581
1582 static void vl_api_control_ping_reply_t_handler
1583   (vl_api_control_ping_reply_t * mp)
1584 {
1585   vat_main_t *vam = &vat_main;
1586   i32 retval = ntohl (mp->retval);
1587   if (vam->async_mode)
1588     {
1589       vam->async_errors += (retval < 0);
1590     }
1591   else
1592     {
1593       vam->retval = retval;
1594       vam->result_ready = 1;
1595     }
1596   if (vam->socket_client_main)
1597     vam->socket_client_main->control_pings_outstanding--;
1598 }
1599
1600 static void vl_api_control_ping_reply_t_handler_json
1601   (vl_api_control_ping_reply_t * mp)
1602 {
1603   vat_main_t *vam = &vat_main;
1604   i32 retval = ntohl (mp->retval);
1605
1606   if (VAT_JSON_NONE != vam->json_tree.type)
1607     {
1608       vat_json_print (vam->ofp, &vam->json_tree);
1609       vat_json_free (&vam->json_tree);
1610       vam->json_tree.type = VAT_JSON_NONE;
1611     }
1612   else
1613     {
1614       /* just print [] */
1615       vat_json_init_array (&vam->json_tree);
1616       vat_json_print (vam->ofp, &vam->json_tree);
1617       vam->json_tree.type = VAT_JSON_NONE;
1618     }
1619
1620   vam->retval = retval;
1621   vam->result_ready = 1;
1622 }
1623
1624 static void
1625   vl_api_bridge_domain_set_mac_age_reply_t_handler
1626   (vl_api_bridge_domain_set_mac_age_reply_t * mp)
1627 {
1628   vat_main_t *vam = &vat_main;
1629   i32 retval = ntohl (mp->retval);
1630   if (vam->async_mode)
1631     {
1632       vam->async_errors += (retval < 0);
1633     }
1634   else
1635     {
1636       vam->retval = retval;
1637       vam->result_ready = 1;
1638     }
1639 }
1640
1641 static void vl_api_bridge_domain_set_mac_age_reply_t_handler_json
1642   (vl_api_bridge_domain_set_mac_age_reply_t * mp)
1643 {
1644   vat_main_t *vam = &vat_main;
1645   vat_json_node_t node;
1646
1647   vat_json_init_object (&node);
1648   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1649
1650   vat_json_print (vam->ofp, &node);
1651   vat_json_free (&node);
1652
1653   vam->retval = ntohl (mp->retval);
1654   vam->result_ready = 1;
1655 }
1656
1657 static void
1658 vl_api_l2_flags_reply_t_handler (vl_api_l2_flags_reply_t * mp)
1659 {
1660   vat_main_t *vam = &vat_main;
1661   i32 retval = ntohl (mp->retval);
1662   if (vam->async_mode)
1663     {
1664       vam->async_errors += (retval < 0);
1665     }
1666   else
1667     {
1668       vam->retval = retval;
1669       vam->result_ready = 1;
1670     }
1671 }
1672
1673 static void vl_api_l2_flags_reply_t_handler_json
1674   (vl_api_l2_flags_reply_t * mp)
1675 {
1676   vat_main_t *vam = &vat_main;
1677   vat_json_node_t node;
1678
1679   vat_json_init_object (&node);
1680   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1681   vat_json_object_add_uint (&node, "resulting_feature_bitmap",
1682                             ntohl (mp->resulting_feature_bitmap));
1683
1684   vat_json_print (vam->ofp, &node);
1685   vat_json_free (&node);
1686
1687   vam->retval = ntohl (mp->retval);
1688   vam->result_ready = 1;
1689 }
1690
1691 static void vl_api_bridge_flags_reply_t_handler
1692   (vl_api_bridge_flags_reply_t * mp)
1693 {
1694   vat_main_t *vam = &vat_main;
1695   i32 retval = ntohl (mp->retval);
1696   if (vam->async_mode)
1697     {
1698       vam->async_errors += (retval < 0);
1699     }
1700   else
1701     {
1702       vam->retval = retval;
1703       vam->result_ready = 1;
1704     }
1705 }
1706
1707 static void vl_api_bridge_flags_reply_t_handler_json
1708   (vl_api_bridge_flags_reply_t * mp)
1709 {
1710   vat_main_t *vam = &vat_main;
1711   vat_json_node_t node;
1712
1713   vat_json_init_object (&node);
1714   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1715   vat_json_object_add_uint (&node, "resulting_feature_bitmap",
1716                             ntohl (mp->resulting_feature_bitmap));
1717
1718   vat_json_print (vam->ofp, &node);
1719   vat_json_free (&node);
1720
1721   vam->retval = ntohl (mp->retval);
1722   vam->result_ready = 1;
1723 }
1724
1725 static void
1726 vl_api_tap_create_v2_reply_t_handler (vl_api_tap_create_v2_reply_t * mp)
1727 {
1728   vat_main_t *vam = &vat_main;
1729   i32 retval = ntohl (mp->retval);
1730   if (vam->async_mode)
1731     {
1732       vam->async_errors += (retval < 0);
1733     }
1734   else
1735     {
1736       vam->retval = retval;
1737       vam->sw_if_index = ntohl (mp->sw_if_index);
1738       vam->result_ready = 1;
1739     }
1740
1741 }
1742
1743 static void vl_api_tap_create_v2_reply_t_handler_json
1744   (vl_api_tap_create_v2_reply_t * mp)
1745 {
1746   vat_main_t *vam = &vat_main;
1747   vat_json_node_t node;
1748
1749   vat_json_init_object (&node);
1750   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1751   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1752
1753   vat_json_print (vam->ofp, &node);
1754   vat_json_free (&node);
1755
1756   vam->retval = ntohl (mp->retval);
1757   vam->result_ready = 1;
1758
1759 }
1760
1761 static void
1762 vl_api_tap_delete_v2_reply_t_handler (vl_api_tap_delete_v2_reply_t * mp)
1763 {
1764   vat_main_t *vam = &vat_main;
1765   i32 retval = ntohl (mp->retval);
1766   if (vam->async_mode)
1767     {
1768       vam->async_errors += (retval < 0);
1769     }
1770   else
1771     {
1772       vam->retval = retval;
1773       vam->result_ready = 1;
1774     }
1775 }
1776
1777 static void vl_api_tap_delete_v2_reply_t_handler_json
1778   (vl_api_tap_delete_v2_reply_t * mp)
1779 {
1780   vat_main_t *vam = &vat_main;
1781   vat_json_node_t node;
1782
1783   vat_json_init_object (&node);
1784   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1785
1786   vat_json_print (vam->ofp, &node);
1787   vat_json_free (&node);
1788
1789   vam->retval = ntohl (mp->retval);
1790   vam->result_ready = 1;
1791 }
1792
1793 static void
1794 vl_api_virtio_pci_create_reply_t_handler (vl_api_virtio_pci_create_reply_t *
1795                                           mp)
1796 {
1797   vat_main_t *vam = &vat_main;
1798   i32 retval = ntohl (mp->retval);
1799   if (vam->async_mode)
1800     {
1801       vam->async_errors += (retval < 0);
1802     }
1803   else
1804     {
1805       vam->retval = retval;
1806       vam->sw_if_index = ntohl (mp->sw_if_index);
1807       vam->result_ready = 1;
1808     }
1809 }
1810
1811 static void vl_api_virtio_pci_create_reply_t_handler_json
1812   (vl_api_virtio_pci_create_reply_t * mp)
1813 {
1814   vat_main_t *vam = &vat_main;
1815   vat_json_node_t node;
1816
1817   vat_json_init_object (&node);
1818   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1819   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1820
1821   vat_json_print (vam->ofp, &node);
1822   vat_json_free (&node);
1823
1824   vam->retval = ntohl (mp->retval);
1825   vam->result_ready = 1;
1826
1827 }
1828
1829 static void
1830   vl_api_virtio_pci_create_v2_reply_t_handler
1831   (vl_api_virtio_pci_create_v2_reply_t * mp)
1832 {
1833   vat_main_t *vam = &vat_main;
1834   i32 retval = ntohl (mp->retval);
1835   if (vam->async_mode)
1836     {
1837       vam->async_errors += (retval < 0);
1838     }
1839   else
1840     {
1841       vam->retval = retval;
1842       vam->sw_if_index = ntohl (mp->sw_if_index);
1843       vam->result_ready = 1;
1844     }
1845 }
1846
1847 static void vl_api_virtio_pci_create_v2_reply_t_handler_json
1848   (vl_api_virtio_pci_create_v2_reply_t * mp)
1849 {
1850   vat_main_t *vam = &vat_main;
1851   vat_json_node_t node;
1852
1853   vat_json_init_object (&node);
1854   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1855   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1856
1857   vat_json_print (vam->ofp, &node);
1858   vat_json_free (&node);
1859
1860   vam->retval = ntohl (mp->retval);
1861   vam->result_ready = 1;
1862 }
1863
1864 static void
1865 vl_api_virtio_pci_delete_reply_t_handler (vl_api_virtio_pci_delete_reply_t *
1866                                           mp)
1867 {
1868   vat_main_t *vam = &vat_main;
1869   i32 retval = ntohl (mp->retval);
1870   if (vam->async_mode)
1871     {
1872       vam->async_errors += (retval < 0);
1873     }
1874   else
1875     {
1876       vam->retval = retval;
1877       vam->result_ready = 1;
1878     }
1879 }
1880
1881 static void vl_api_virtio_pci_delete_reply_t_handler_json
1882   (vl_api_virtio_pci_delete_reply_t * mp)
1883 {
1884   vat_main_t *vam = &vat_main;
1885   vat_json_node_t node;
1886
1887   vat_json_init_object (&node);
1888   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1889
1890   vat_json_print (vam->ofp, &node);
1891   vat_json_free (&node);
1892
1893   vam->retval = ntohl (mp->retval);
1894   vam->result_ready = 1;
1895 }
1896
1897 static void
1898 vl_api_bond_create_reply_t_handler (vl_api_bond_create_reply_t * mp)
1899 {
1900   vat_main_t *vam = &vat_main;
1901   i32 retval = ntohl (mp->retval);
1902
1903   if (vam->async_mode)
1904     {
1905       vam->async_errors += (retval < 0);
1906     }
1907   else
1908     {
1909       vam->retval = retval;
1910       vam->sw_if_index = ntohl (mp->sw_if_index);
1911       vam->result_ready = 1;
1912     }
1913 }
1914
1915 static void vl_api_bond_create_reply_t_handler_json
1916   (vl_api_bond_create_reply_t * mp)
1917 {
1918   vat_main_t *vam = &vat_main;
1919   vat_json_node_t node;
1920
1921   vat_json_init_object (&node);
1922   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1923   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1924
1925   vat_json_print (vam->ofp, &node);
1926   vat_json_free (&node);
1927
1928   vam->retval = ntohl (mp->retval);
1929   vam->result_ready = 1;
1930 }
1931
1932 static void
1933 vl_api_bond_create2_reply_t_handler (vl_api_bond_create2_reply_t * mp)
1934 {
1935   vat_main_t *vam = &vat_main;
1936   i32 retval = ntohl (mp->retval);
1937
1938   if (vam->async_mode)
1939     {
1940       vam->async_errors += (retval < 0);
1941     }
1942   else
1943     {
1944       vam->retval = retval;
1945       vam->sw_if_index = ntohl (mp->sw_if_index);
1946       vam->result_ready = 1;
1947     }
1948 }
1949
1950 static void vl_api_bond_create2_reply_t_handler_json
1951   (vl_api_bond_create2_reply_t * mp)
1952 {
1953   vat_main_t *vam = &vat_main;
1954   vat_json_node_t node;
1955
1956   vat_json_init_object (&node);
1957   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1958   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1959
1960   vat_json_print (vam->ofp, &node);
1961   vat_json_free (&node);
1962
1963   vam->retval = ntohl (mp->retval);
1964   vam->result_ready = 1;
1965 }
1966
1967 static void
1968 vl_api_bond_delete_reply_t_handler (vl_api_bond_delete_reply_t * mp)
1969 {
1970   vat_main_t *vam = &vat_main;
1971   i32 retval = ntohl (mp->retval);
1972
1973   if (vam->async_mode)
1974     {
1975       vam->async_errors += (retval < 0);
1976     }
1977   else
1978     {
1979       vam->retval = retval;
1980       vam->result_ready = 1;
1981     }
1982 }
1983
1984 static void vl_api_bond_delete_reply_t_handler_json
1985   (vl_api_bond_delete_reply_t * mp)
1986 {
1987   vat_main_t *vam = &vat_main;
1988   vat_json_node_t node;
1989
1990   vat_json_init_object (&node);
1991   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1992
1993   vat_json_print (vam->ofp, &node);
1994   vat_json_free (&node);
1995
1996   vam->retval = ntohl (mp->retval);
1997   vam->result_ready = 1;
1998 }
1999
2000 static void
2001 vl_api_bond_add_member_reply_t_handler (vl_api_bond_add_member_reply_t * mp)
2002 {
2003   vat_main_t *vam = &vat_main;
2004   i32 retval = ntohl (mp->retval);
2005
2006   if (vam->async_mode)
2007     {
2008       vam->async_errors += (retval < 0);
2009     }
2010   else
2011     {
2012       vam->retval = retval;
2013       vam->result_ready = 1;
2014     }
2015 }
2016
2017 static void vl_api_bond_add_member_reply_t_handler_json
2018   (vl_api_bond_add_member_reply_t * mp)
2019 {
2020   vat_main_t *vam = &vat_main;
2021   vat_json_node_t node;
2022
2023   vat_json_init_object (&node);
2024   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2025
2026   vat_json_print (vam->ofp, &node);
2027   vat_json_free (&node);
2028
2029   vam->retval = ntohl (mp->retval);
2030   vam->result_ready = 1;
2031 }
2032
2033 static void
2034 vl_api_bond_detach_member_reply_t_handler (vl_api_bond_detach_member_reply_t *
2035                                            mp)
2036 {
2037   vat_main_t *vam = &vat_main;
2038   i32 retval = ntohl (mp->retval);
2039
2040   if (vam->async_mode)
2041     {
2042       vam->async_errors += (retval < 0);
2043     }
2044   else
2045     {
2046       vam->retval = retval;
2047       vam->result_ready = 1;
2048     }
2049 }
2050
2051 static void vl_api_bond_detach_member_reply_t_handler_json
2052   (vl_api_bond_detach_member_reply_t * mp)
2053 {
2054   vat_main_t *vam = &vat_main;
2055   vat_json_node_t node;
2056
2057   vat_json_init_object (&node);
2058   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2059
2060   vat_json_print (vam->ofp, &node);
2061   vat_json_free (&node);
2062
2063   vam->retval = ntohl (mp->retval);
2064   vam->result_ready = 1;
2065 }
2066
2067 static int
2068 api_sw_interface_set_bond_weight (vat_main_t * vam)
2069 {
2070   unformat_input_t *i = vam->input;
2071   vl_api_sw_interface_set_bond_weight_t *mp;
2072   u32 sw_if_index = ~0;
2073   u32 weight = 0;
2074   u8 weight_enter = 0;
2075   int ret;
2076
2077   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2078     {
2079       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2080         ;
2081       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2082         ;
2083       else if (unformat (i, "weight %u", &weight))
2084         weight_enter = 1;
2085       else
2086         break;
2087     }
2088
2089   if (sw_if_index == ~0)
2090     {
2091       errmsg ("missing interface name or sw_if_index");
2092       return -99;
2093     }
2094   if (weight_enter == 0)
2095     {
2096       errmsg ("missing valid weight");
2097       return -99;
2098     }
2099
2100   /* Construct the API message */
2101   M (SW_INTERFACE_SET_BOND_WEIGHT, mp);
2102   mp->sw_if_index = ntohl (sw_if_index);
2103   mp->weight = ntohl (weight);
2104
2105   S (mp);
2106   W (ret);
2107   return ret;
2108 }
2109
2110 static void vl_api_sw_bond_interface_details_t_handler
2111   (vl_api_sw_bond_interface_details_t * mp)
2112 {
2113   vat_main_t *vam = &vat_main;
2114
2115   print (vam->ofp,
2116          "%-16s %-12d %-12U %-13U %-14u %-14u",
2117          mp->interface_name, ntohl (mp->sw_if_index),
2118          format_bond_mode, ntohl (mp->mode), format_bond_load_balance,
2119          ntohl (mp->lb), ntohl (mp->active_members), ntohl (mp->members));
2120 }
2121
2122 static void vl_api_sw_bond_interface_details_t_handler_json
2123   (vl_api_sw_bond_interface_details_t * mp)
2124 {
2125   vat_main_t *vam = &vat_main;
2126   vat_json_node_t *node = NULL;
2127
2128   if (VAT_JSON_ARRAY != vam->json_tree.type)
2129     {
2130       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
2131       vat_json_init_array (&vam->json_tree);
2132     }
2133   node = vat_json_array_add (&vam->json_tree);
2134
2135   vat_json_init_object (node);
2136   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
2137   vat_json_object_add_string_copy (node, "interface_name",
2138                                    mp->interface_name);
2139   vat_json_object_add_uint (node, "mode", ntohl (mp->mode));
2140   vat_json_object_add_uint (node, "load_balance", ntohl (mp->lb));
2141   vat_json_object_add_uint (node, "active_members",
2142                             ntohl (mp->active_members));
2143   vat_json_object_add_uint (node, "members", ntohl (mp->members));
2144 }
2145
2146 static int
2147 api_sw_bond_interface_dump (vat_main_t * vam)
2148 {
2149   unformat_input_t *i = vam->input;
2150   vl_api_sw_bond_interface_dump_t *mp;
2151   vl_api_control_ping_t *mp_ping;
2152   int ret;
2153   u32 sw_if_index = ~0;
2154
2155   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2156     {
2157       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2158         ;
2159       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2160         ;
2161       else
2162         break;
2163     }
2164
2165   print (vam->ofp,
2166          "\n%-16s %-12s %-12s %-13s %-14s %-14s",
2167          "interface name", "sw_if_index", "mode", "load balance",
2168          "active members", "members");
2169
2170   /* Get list of bond interfaces */
2171   M (SW_BOND_INTERFACE_DUMP, mp);
2172   mp->sw_if_index = ntohl (sw_if_index);
2173   S (mp);
2174
2175   /* Use a control ping for synchronization */
2176   MPING (CONTROL_PING, mp_ping);
2177   S (mp_ping);
2178
2179   W (ret);
2180   return ret;
2181 }
2182
2183 static void vl_api_sw_member_interface_details_t_handler
2184   (vl_api_sw_member_interface_details_t * mp)
2185 {
2186   vat_main_t *vam = &vat_main;
2187
2188   print (vam->ofp,
2189          "%-25s %-12d %-7d %-12d %-10d %-10d", mp->interface_name,
2190          ntohl (mp->sw_if_index), mp->is_passive, mp->is_long_timeout,
2191          ntohl (mp->weight), mp->is_local_numa);
2192 }
2193
2194 static void vl_api_sw_member_interface_details_t_handler_json
2195   (vl_api_sw_member_interface_details_t * mp)
2196 {
2197   vat_main_t *vam = &vat_main;
2198   vat_json_node_t *node = NULL;
2199
2200   if (VAT_JSON_ARRAY != vam->json_tree.type)
2201     {
2202       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
2203       vat_json_init_array (&vam->json_tree);
2204     }
2205   node = vat_json_array_add (&vam->json_tree);
2206
2207   vat_json_init_object (node);
2208   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
2209   vat_json_object_add_string_copy (node, "interface_name",
2210                                    mp->interface_name);
2211   vat_json_object_add_uint (node, "passive", mp->is_passive);
2212   vat_json_object_add_uint (node, "long_timeout", mp->is_long_timeout);
2213   vat_json_object_add_uint (node, "weight", ntohl (mp->weight));
2214   vat_json_object_add_uint (node, "is_local_numa", mp->is_local_numa);
2215 }
2216
2217 static int
2218 api_sw_member_interface_dump (vat_main_t * vam)
2219 {
2220   unformat_input_t *i = vam->input;
2221   vl_api_sw_member_interface_dump_t *mp;
2222   vl_api_control_ping_t *mp_ping;
2223   u32 sw_if_index = ~0;
2224   u8 sw_if_index_set = 0;
2225   int ret;
2226
2227   /* Parse args required to build the message */
2228   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2229     {
2230       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2231         sw_if_index_set = 1;
2232       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2233         sw_if_index_set = 1;
2234       else
2235         break;
2236     }
2237
2238   if (sw_if_index_set == 0)
2239     {
2240       errmsg ("missing vpp interface name. ");
2241       return -99;
2242     }
2243
2244   print (vam->ofp,
2245          "\n%-25s %-12s %-7s %-12s %-10s %-10s",
2246          "member interface name", "sw_if_index", "passive", "long_timeout",
2247          "weight", "local numa");
2248
2249   /* Get list of bond interfaces */
2250   M (SW_MEMBER_INTERFACE_DUMP, mp);
2251   mp->sw_if_index = ntohl (sw_if_index);
2252   S (mp);
2253
2254   /* Use a control ping for synchronization */
2255   MPING (CONTROL_PING, mp_ping);
2256   S (mp_ping);
2257
2258   W (ret);
2259   return ret;
2260 }
2261
2262 static void vl_api_mpls_tunnel_add_del_reply_t_handler
2263   (vl_api_mpls_tunnel_add_del_reply_t * mp)
2264 {
2265   vat_main_t *vam = &vat_main;
2266   i32 retval = ntohl (mp->retval);
2267   if (vam->async_mode)
2268     {
2269       vam->async_errors += (retval < 0);
2270     }
2271   else
2272     {
2273       vam->retval = retval;
2274       vam->sw_if_index = ntohl (mp->sw_if_index);
2275       vam->result_ready = 1;
2276     }
2277   vam->regenerate_interface_table = 1;
2278 }
2279
2280 static void vl_api_mpls_tunnel_add_del_reply_t_handler_json
2281   (vl_api_mpls_tunnel_add_del_reply_t * mp)
2282 {
2283   vat_main_t *vam = &vat_main;
2284   vat_json_node_t node;
2285
2286   vat_json_init_object (&node);
2287   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2288   vat_json_object_add_uint (&node, "tunnel_sw_if_index",
2289                             ntohl (mp->sw_if_index));
2290
2291   vat_json_print (vam->ofp, &node);
2292   vat_json_free (&node);
2293
2294   vam->retval = ntohl (mp->retval);
2295   vam->result_ready = 1;
2296 }
2297
2298 static void vl_api_vxlan_add_del_tunnel_reply_t_handler
2299   (vl_api_vxlan_add_del_tunnel_reply_t * mp)
2300 {
2301   vat_main_t *vam = &vat_main;
2302   i32 retval = ntohl (mp->retval);
2303   if (vam->async_mode)
2304     {
2305       vam->async_errors += (retval < 0);
2306     }
2307   else
2308     {
2309       vam->retval = retval;
2310       vam->sw_if_index = ntohl (mp->sw_if_index);
2311       vam->result_ready = 1;
2312     }
2313   vam->regenerate_interface_table = 1;
2314 }
2315
2316 static void vl_api_vxlan_add_del_tunnel_reply_t_handler_json
2317   (vl_api_vxlan_add_del_tunnel_reply_t * mp)
2318 {
2319   vat_main_t *vam = &vat_main;
2320   vat_json_node_t node;
2321
2322   vat_json_init_object (&node);
2323   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2324   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
2325
2326   vat_json_print (vam->ofp, &node);
2327   vat_json_free (&node);
2328
2329   vam->retval = ntohl (mp->retval);
2330   vam->result_ready = 1;
2331 }
2332
2333 static void vl_api_vxlan_offload_rx_reply_t_handler
2334   (vl_api_vxlan_offload_rx_reply_t * mp)
2335 {
2336   vat_main_t *vam = &vat_main;
2337   i32 retval = ntohl (mp->retval);
2338   if (vam->async_mode)
2339     {
2340       vam->async_errors += (retval < 0);
2341     }
2342   else
2343     {
2344       vam->retval = retval;
2345       vam->result_ready = 1;
2346     }
2347 }
2348
2349 static void vl_api_vxlan_offload_rx_reply_t_handler_json
2350   (vl_api_vxlan_offload_rx_reply_t * mp)
2351 {
2352   vat_main_t *vam = &vat_main;
2353   vat_json_node_t node;
2354
2355   vat_json_init_object (&node);
2356   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2357
2358   vat_json_print (vam->ofp, &node);
2359   vat_json_free (&node);
2360
2361   vam->retval = ntohl (mp->retval);
2362   vam->result_ready = 1;
2363 }
2364
2365 static void vl_api_vxlan_gpe_add_del_tunnel_reply_t_handler
2366   (vl_api_vxlan_gpe_add_del_tunnel_reply_t * mp)
2367 {
2368   vat_main_t *vam = &vat_main;
2369   i32 retval = ntohl (mp->retval);
2370   if (vam->async_mode)
2371     {
2372       vam->async_errors += (retval < 0);
2373     }
2374   else
2375     {
2376       vam->retval = retval;
2377       vam->sw_if_index = ntohl (mp->sw_if_index);
2378       vam->result_ready = 1;
2379     }
2380   vam->regenerate_interface_table = 1;
2381 }
2382
2383 static void vl_api_vxlan_gpe_add_del_tunnel_reply_t_handler_json
2384   (vl_api_vxlan_gpe_add_del_tunnel_reply_t * mp)
2385 {
2386   vat_main_t *vam = &vat_main;
2387   vat_json_node_t node;
2388
2389   vat_json_init_object (&node);
2390   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2391   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
2392
2393   vat_json_print (vam->ofp, &node);
2394   vat_json_free (&node);
2395
2396   vam->retval = ntohl (mp->retval);
2397   vam->result_ready = 1;
2398 }
2399
2400 static void vl_api_gre_tunnel_add_del_reply_t_handler
2401   (vl_api_gre_tunnel_add_del_reply_t * mp)
2402 {
2403   vat_main_t *vam = &vat_main;
2404   i32 retval = ntohl (mp->retval);
2405   if (vam->async_mode)
2406     {
2407       vam->async_errors += (retval < 0);
2408     }
2409   else
2410     {
2411       vam->retval = retval;
2412       vam->sw_if_index = ntohl (mp->sw_if_index);
2413       vam->result_ready = 1;
2414     }
2415 }
2416
2417 static void vl_api_gre_tunnel_add_del_reply_t_handler_json
2418   (vl_api_gre_tunnel_add_del_reply_t * mp)
2419 {
2420   vat_main_t *vam = &vat_main;
2421   vat_json_node_t node;
2422
2423   vat_json_init_object (&node);
2424   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2425   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
2426
2427   vat_json_print (vam->ofp, &node);
2428   vat_json_free (&node);
2429
2430   vam->retval = ntohl (mp->retval);
2431   vam->result_ready = 1;
2432 }
2433
2434 static void vl_api_create_vhost_user_if_reply_t_handler
2435   (vl_api_create_vhost_user_if_reply_t * mp)
2436 {
2437   vat_main_t *vam = &vat_main;
2438   i32 retval = ntohl (mp->retval);
2439   if (vam->async_mode)
2440     {
2441       vam->async_errors += (retval < 0);
2442     }
2443   else
2444     {
2445       vam->retval = retval;
2446       vam->sw_if_index = ntohl (mp->sw_if_index);
2447       vam->result_ready = 1;
2448     }
2449   vam->regenerate_interface_table = 1;
2450 }
2451
2452 static void vl_api_create_vhost_user_if_reply_t_handler_json
2453   (vl_api_create_vhost_user_if_reply_t * mp)
2454 {
2455   vat_main_t *vam = &vat_main;
2456   vat_json_node_t node;
2457
2458   vat_json_init_object (&node);
2459   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2460   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
2461
2462   vat_json_print (vam->ofp, &node);
2463   vat_json_free (&node);
2464
2465   vam->retval = ntohl (mp->retval);
2466   vam->result_ready = 1;
2467 }
2468
2469 static void vl_api_ip_address_details_t_handler
2470   (vl_api_ip_address_details_t * mp)
2471 {
2472   vat_main_t *vam = &vat_main;
2473   static ip_address_details_t empty_ip_address_details = { {0} };
2474   ip_address_details_t *address = NULL;
2475   ip_details_t *current_ip_details = NULL;
2476   ip_details_t *details = NULL;
2477
2478   details = vam->ip_details_by_sw_if_index[vam->is_ipv6];
2479
2480   if (!details || vam->current_sw_if_index >= vec_len (details)
2481       || !details[vam->current_sw_if_index].present)
2482     {
2483       errmsg ("ip address details arrived but not stored");
2484       errmsg ("ip_dump should be called first");
2485       return;
2486     }
2487
2488   current_ip_details = vec_elt_at_index (details, vam->current_sw_if_index);
2489
2490 #define addresses (current_ip_details->addr)
2491
2492   vec_validate_init_empty (addresses, vec_len (addresses),
2493                            empty_ip_address_details);
2494
2495   address = vec_elt_at_index (addresses, vec_len (addresses) - 1);
2496
2497   clib_memcpy (&address->ip, &mp->prefix.address.un, sizeof (address->ip));
2498   address->prefix_length = mp->prefix.len;
2499 #undef addresses
2500 }
2501
2502 static void vl_api_ip_address_details_t_handler_json
2503   (vl_api_ip_address_details_t * mp)
2504 {
2505   vat_main_t *vam = &vat_main;
2506   vat_json_node_t *node = NULL;
2507
2508   if (VAT_JSON_ARRAY != vam->json_tree.type)
2509     {
2510       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
2511       vat_json_init_array (&vam->json_tree);
2512     }
2513   node = vat_json_array_add (&vam->json_tree);
2514
2515   vat_json_init_object (node);
2516   vat_json_object_add_prefix (node, &mp->prefix);
2517 }
2518
2519 static void
2520 vl_api_ip_details_t_handler (vl_api_ip_details_t * mp)
2521 {
2522   vat_main_t *vam = &vat_main;
2523   static ip_details_t empty_ip_details = { 0 };
2524   ip_details_t *ip = NULL;
2525   u32 sw_if_index = ~0;
2526
2527   sw_if_index = ntohl (mp->sw_if_index);
2528
2529   vec_validate_init_empty (vam->ip_details_by_sw_if_index[vam->is_ipv6],
2530                            sw_if_index, empty_ip_details);
2531
2532   ip = vec_elt_at_index (vam->ip_details_by_sw_if_index[vam->is_ipv6],
2533                          sw_if_index);
2534
2535   ip->present = 1;
2536 }
2537
2538 static void
2539 vl_api_ip_details_t_handler_json (vl_api_ip_details_t * mp)
2540 {
2541   vat_main_t *vam = &vat_main;
2542
2543   if (VAT_JSON_ARRAY != vam->json_tree.type)
2544     {
2545       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
2546       vat_json_init_array (&vam->json_tree);
2547     }
2548   vat_json_array_add_uint (&vam->json_tree,
2549                            clib_net_to_host_u32 (mp->sw_if_index));
2550 }
2551
2552 static void vl_api_get_first_msg_id_reply_t_handler
2553   (vl_api_get_first_msg_id_reply_t * mp)
2554 {
2555   vat_main_t *vam = &vat_main;
2556   i32 retval = ntohl (mp->retval);
2557
2558   if (vam->async_mode)
2559     {
2560       vam->async_errors += (retval < 0);
2561     }
2562   else
2563     {
2564       vam->retval = retval;
2565       vam->result_ready = 1;
2566     }
2567   if (retval >= 0)
2568     {
2569       errmsg ("first message id %d", ntohs (mp->first_msg_id));
2570     }
2571 }
2572
2573 static void vl_api_get_first_msg_id_reply_t_handler_json
2574   (vl_api_get_first_msg_id_reply_t * mp)
2575 {
2576   vat_main_t *vam = &vat_main;
2577   vat_json_node_t node;
2578
2579   vat_json_init_object (&node);
2580   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2581   vat_json_object_add_uint (&node, "first_msg_id",
2582                             (uint) ntohs (mp->first_msg_id));
2583
2584   vat_json_print (vam->ofp, &node);
2585   vat_json_free (&node);
2586
2587   vam->retval = ntohl (mp->retval);
2588   vam->result_ready = 1;
2589 }
2590
2591 static void vl_api_get_node_graph_reply_t_handler
2592   (vl_api_get_node_graph_reply_t * mp)
2593 {
2594   vat_main_t *vam = &vat_main;
2595   i32 retval = ntohl (mp->retval);
2596   u8 *pvt_copy, *reply;
2597   void *oldheap;
2598   vlib_node_t *node;
2599   int i;
2600
2601   if (vam->async_mode)
2602     {
2603       vam->async_errors += (retval < 0);
2604     }
2605   else
2606     {
2607       vam->retval = retval;
2608       vam->result_ready = 1;
2609     }
2610
2611   /* "Should never happen..." */
2612   if (retval != 0)
2613     return;
2614
2615   reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
2616   pvt_copy = vec_dup (reply);
2617
2618   /* Toss the shared-memory original... */
2619   oldheap = vl_msg_push_heap ();
2620
2621   vec_free (reply);
2622
2623   vl_msg_pop_heap (oldheap);
2624
2625   if (vam->graph_nodes)
2626     {
2627       hash_free (vam->graph_node_index_by_name);
2628
2629       for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
2630         {
2631           node = vam->graph_nodes[0][i];
2632           vec_free (node->name);
2633           vec_free (node->next_nodes);
2634           vec_free (node);
2635         }
2636       vec_free (vam->graph_nodes[0]);
2637       vec_free (vam->graph_nodes);
2638     }
2639
2640   vam->graph_node_index_by_name = hash_create_string (0, sizeof (uword));
2641   vam->graph_nodes = vlib_node_unserialize (pvt_copy);
2642   vec_free (pvt_copy);
2643
2644   for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
2645     {
2646       node = vam->graph_nodes[0][i];
2647       hash_set_mem (vam->graph_node_index_by_name, node->name, i);
2648     }
2649 }
2650
2651 static void vl_api_get_node_graph_reply_t_handler_json
2652   (vl_api_get_node_graph_reply_t * mp)
2653 {
2654   vat_main_t *vam = &vat_main;
2655   void *oldheap;
2656   vat_json_node_t node;
2657   u8 *reply;
2658
2659   /* $$$$ make this real? */
2660   vat_json_init_object (&node);
2661   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2662   vat_json_object_add_uint (&node, "reply_in_shmem", mp->reply_in_shmem);
2663
2664   reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
2665
2666   /* Toss the shared-memory original... */
2667   oldheap = vl_msg_push_heap ();
2668
2669   vec_free (reply);
2670
2671   vl_msg_pop_heap (oldheap);
2672
2673   vat_json_print (vam->ofp, &node);
2674   vat_json_free (&node);
2675
2676   vam->retval = ntohl (mp->retval);
2677   vam->result_ready = 1;
2678 }
2679
2680 static u8 *
2681 format_policer_type (u8 * s, va_list * va)
2682 {
2683   u32 i = va_arg (*va, u32);
2684
2685   if (i == SSE2_QOS_POLICER_TYPE_1R2C)
2686     s = format (s, "1r2c");
2687   else if (i == SSE2_QOS_POLICER_TYPE_1R3C_RFC_2697)
2688     s = format (s, "1r3c");
2689   else if (i == SSE2_QOS_POLICER_TYPE_2R3C_RFC_2698)
2690     s = format (s, "2r3c-2698");
2691   else if (i == SSE2_QOS_POLICER_TYPE_2R3C_RFC_4115)
2692     s = format (s, "2r3c-4115");
2693   else if (i == SSE2_QOS_POLICER_TYPE_2R3C_RFC_MEF5CF1)
2694     s = format (s, "2r3c-mef5cf1");
2695   else
2696     s = format (s, "ILLEGAL");
2697   return s;
2698 }
2699
2700 static u8 *
2701 format_policer_rate_type (u8 * s, va_list * va)
2702 {
2703   u32 i = va_arg (*va, u32);
2704
2705   if (i == SSE2_QOS_RATE_KBPS)
2706     s = format (s, "kbps");
2707   else if (i == SSE2_QOS_RATE_PPS)
2708     s = format (s, "pps");
2709   else
2710     s = format (s, "ILLEGAL");
2711   return s;
2712 }
2713
2714 static u8 *
2715 format_policer_round_type (u8 * s, va_list * va)
2716 {
2717   u32 i = va_arg (*va, u32);
2718
2719   if (i == SSE2_QOS_ROUND_TO_CLOSEST)
2720     s = format (s, "closest");
2721   else if (i == SSE2_QOS_ROUND_TO_UP)
2722     s = format (s, "up");
2723   else if (i == SSE2_QOS_ROUND_TO_DOWN)
2724     s = format (s, "down");
2725   else
2726     s = format (s, "ILLEGAL");
2727   return s;
2728 }
2729
2730 static u8 *
2731 format_policer_action_type (u8 * s, va_list * va)
2732 {
2733   u32 i = va_arg (*va, u32);
2734
2735   if (i == SSE2_QOS_ACTION_DROP)
2736     s = format (s, "drop");
2737   else if (i == SSE2_QOS_ACTION_TRANSMIT)
2738     s = format (s, "transmit");
2739   else if (i == SSE2_QOS_ACTION_MARK_AND_TRANSMIT)
2740     s = format (s, "mark-and-transmit");
2741   else
2742     s = format (s, "ILLEGAL");
2743   return s;
2744 }
2745
2746 static u8 *
2747 format_dscp (u8 * s, va_list * va)
2748 {
2749   u32 i = va_arg (*va, u32);
2750   char *t = 0;
2751
2752   switch (i)
2753     {
2754 #define _(v,f,str) case VNET_DSCP_##f: t = str; break;
2755       foreach_vnet_dscp
2756 #undef _
2757     default:
2758       return format (s, "ILLEGAL");
2759     }
2760   s = format (s, "%s", t);
2761   return s;
2762 }
2763
2764 static void
2765 vl_api_policer_details_t_handler (vl_api_policer_details_t * mp)
2766 {
2767   vat_main_t *vam = &vat_main;
2768   u8 *conform_dscp_str, *exceed_dscp_str, *violate_dscp_str;
2769
2770   if (mp->conform_action.type == SSE2_QOS_ACTION_API_MARK_AND_TRANSMIT)
2771     conform_dscp_str = format (0, "%U", format_dscp, mp->conform_action.dscp);
2772   else
2773     conform_dscp_str = format (0, "");
2774
2775   if (mp->exceed_action.type == SSE2_QOS_ACTION_API_MARK_AND_TRANSMIT)
2776     exceed_dscp_str = format (0, "%U", format_dscp, mp->exceed_action.dscp);
2777   else
2778     exceed_dscp_str = format (0, "");
2779
2780   if (mp->violate_action.type == SSE2_QOS_ACTION_API_MARK_AND_TRANSMIT)
2781     violate_dscp_str = format (0, "%U", format_dscp, mp->violate_action.dscp);
2782   else
2783     violate_dscp_str = format (0, "");
2784
2785   print (vam->ofp, "Name \"%s\", type %U, cir %u, eir %u, cb %u, eb %u, "
2786          "rate type %U, round type %U, %s rate, %s color-aware, "
2787          "cir %u tok/period, pir %u tok/period, scale %u, cur lim %u, "
2788          "cur bkt %u, ext lim %u, ext bkt %u, last update %llu"
2789          "conform action %U%s, exceed action %U%s, violate action %U%s",
2790          mp->name,
2791          format_policer_type, mp->type,
2792          ntohl (mp->cir),
2793          ntohl (mp->eir),
2794          clib_net_to_host_u64 (mp->cb),
2795          clib_net_to_host_u64 (mp->eb),
2796          format_policer_rate_type, mp->rate_type,
2797          format_policer_round_type, mp->round_type,
2798          mp->single_rate ? "single" : "dual",
2799          mp->color_aware ? "is" : "not",
2800          ntohl (mp->cir_tokens_per_period),
2801          ntohl (mp->pir_tokens_per_period),
2802          ntohl (mp->scale),
2803          ntohl (mp->current_limit),
2804          ntohl (mp->current_bucket),
2805          ntohl (mp->extended_limit),
2806          ntohl (mp->extended_bucket),
2807          clib_net_to_host_u64 (mp->last_update_time),
2808          format_policer_action_type, mp->conform_action.type,
2809          conform_dscp_str,
2810          format_policer_action_type, mp->exceed_action.type,
2811          exceed_dscp_str,
2812          format_policer_action_type, mp->violate_action.type,
2813          violate_dscp_str);
2814
2815   vec_free (conform_dscp_str);
2816   vec_free (exceed_dscp_str);
2817   vec_free (violate_dscp_str);
2818 }
2819
2820 static void vl_api_policer_details_t_handler_json
2821   (vl_api_policer_details_t * mp)
2822 {
2823   vat_main_t *vam = &vat_main;
2824   vat_json_node_t *node;
2825   u8 *rate_type_str, *round_type_str, *type_str;
2826   u8 *conform_action_str, *exceed_action_str, *violate_action_str;
2827
2828   rate_type_str = format (0, "%U", format_policer_rate_type, mp->rate_type);
2829   round_type_str =
2830     format (0, "%U", format_policer_round_type, mp->round_type);
2831   type_str = format (0, "%U", format_policer_type, mp->type);
2832   conform_action_str = format (0, "%U", format_policer_action_type,
2833                                mp->conform_action.type);
2834   exceed_action_str = format (0, "%U", format_policer_action_type,
2835                               mp->exceed_action.type);
2836   violate_action_str = format (0, "%U", format_policer_action_type,
2837                                mp->violate_action.type);
2838
2839   if (VAT_JSON_ARRAY != vam->json_tree.type)
2840     {
2841       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
2842       vat_json_init_array (&vam->json_tree);
2843     }
2844   node = vat_json_array_add (&vam->json_tree);
2845
2846   vat_json_init_object (node);
2847   vat_json_object_add_string_copy (node, "name", mp->name);
2848   vat_json_object_add_uint (node, "cir", ntohl (mp->cir));
2849   vat_json_object_add_uint (node, "eir", ntohl (mp->eir));
2850   vat_json_object_add_uint (node, "cb", clib_net_to_host_u64 (mp->cb));
2851   vat_json_object_add_uint (node, "eb", clib_net_to_host_u64 (mp->eb));
2852   vat_json_object_add_string_copy (node, "rate_type", rate_type_str);
2853   vat_json_object_add_string_copy (node, "round_type", round_type_str);
2854   vat_json_object_add_string_copy (node, "type", type_str);
2855   vat_json_object_add_uint (node, "single_rate", mp->single_rate);
2856   vat_json_object_add_uint (node, "color_aware", mp->color_aware);
2857   vat_json_object_add_uint (node, "scale", ntohl (mp->scale));
2858   vat_json_object_add_uint (node, "cir_tokens_per_period",
2859                             ntohl (mp->cir_tokens_per_period));
2860   vat_json_object_add_uint (node, "eir_tokens_per_period",
2861                             ntohl (mp->pir_tokens_per_period));
2862   vat_json_object_add_uint (node, "current_limit", ntohl (mp->current_limit));
2863   vat_json_object_add_uint (node, "current_bucket",
2864                             ntohl (mp->current_bucket));
2865   vat_json_object_add_uint (node, "extended_limit",
2866                             ntohl (mp->extended_limit));
2867   vat_json_object_add_uint (node, "extended_bucket",
2868                             ntohl (mp->extended_bucket));
2869   vat_json_object_add_uint (node, "last_update_time",
2870                             ntohl (mp->last_update_time));
2871   vat_json_object_add_string_copy (node, "conform_action",
2872                                    conform_action_str);
2873   if (mp->conform_action.type == SSE2_QOS_ACTION_API_MARK_AND_TRANSMIT)
2874     {
2875       u8 *dscp_str = format (0, "%U", format_dscp, mp->conform_action.dscp);
2876       vat_json_object_add_string_copy (node, "conform_dscp", dscp_str);
2877       vec_free (dscp_str);
2878     }
2879   vat_json_object_add_string_copy (node, "exceed_action", exceed_action_str);
2880   if (mp->exceed_action.type == SSE2_QOS_ACTION_API_MARK_AND_TRANSMIT)
2881     {
2882       u8 *dscp_str = format (0, "%U", format_dscp, mp->exceed_action.dscp);
2883       vat_json_object_add_string_copy (node, "exceed_dscp", dscp_str);
2884       vec_free (dscp_str);
2885     }
2886   vat_json_object_add_string_copy (node, "violate_action",
2887                                    violate_action_str);
2888   if (mp->violate_action.type == SSE2_QOS_ACTION_API_MARK_AND_TRANSMIT)
2889     {
2890       u8 *dscp_str = format (0, "%U", format_dscp, mp->violate_action.dscp);
2891       vat_json_object_add_string_copy (node, "violate_dscp", dscp_str);
2892       vec_free (dscp_str);
2893     }
2894
2895   vec_free (rate_type_str);
2896   vec_free (round_type_str);
2897   vec_free (type_str);
2898   vec_free (conform_action_str);
2899   vec_free (exceed_action_str);
2900   vec_free (violate_action_str);
2901 }
2902
2903 static void
2904 vl_api_classify_table_ids_reply_t_handler (vl_api_classify_table_ids_reply_t *
2905                                            mp)
2906 {
2907   vat_main_t *vam = &vat_main;
2908   int i, count = ntohl (mp->count);
2909
2910   if (count > 0)
2911     print (vam->ofp, "classify table ids (%d) : ", count);
2912   for (i = 0; i < count; i++)
2913     {
2914       print (vam->ofp, "%d", ntohl (mp->ids[i]));
2915       print (vam->ofp, (i < count - 1) ? "," : "");
2916     }
2917   vam->retval = ntohl (mp->retval);
2918   vam->result_ready = 1;
2919 }
2920
2921 static void
2922   vl_api_classify_table_ids_reply_t_handler_json
2923   (vl_api_classify_table_ids_reply_t * mp)
2924 {
2925   vat_main_t *vam = &vat_main;
2926   int i, count = ntohl (mp->count);
2927
2928   if (count > 0)
2929     {
2930       vat_json_node_t node;
2931
2932       vat_json_init_object (&node);
2933       for (i = 0; i < count; i++)
2934         {
2935           vat_json_object_add_uint (&node, "table_id", ntohl (mp->ids[i]));
2936         }
2937       vat_json_print (vam->ofp, &node);
2938       vat_json_free (&node);
2939     }
2940   vam->retval = ntohl (mp->retval);
2941   vam->result_ready = 1;
2942 }
2943
2944 static void
2945   vl_api_classify_table_by_interface_reply_t_handler
2946   (vl_api_classify_table_by_interface_reply_t * mp)
2947 {
2948   vat_main_t *vam = &vat_main;
2949   u32 table_id;
2950
2951   table_id = ntohl (mp->l2_table_id);
2952   if (table_id != ~0)
2953     print (vam->ofp, "l2 table id : %d", table_id);
2954   else
2955     print (vam->ofp, "l2 table id : No input ACL tables configured");
2956   table_id = ntohl (mp->ip4_table_id);
2957   if (table_id != ~0)
2958     print (vam->ofp, "ip4 table id : %d", table_id);
2959   else
2960     print (vam->ofp, "ip4 table id : No input ACL tables configured");
2961   table_id = ntohl (mp->ip6_table_id);
2962   if (table_id != ~0)
2963     print (vam->ofp, "ip6 table id : %d", table_id);
2964   else
2965     print (vam->ofp, "ip6 table id : No input ACL tables configured");
2966   vam->retval = ntohl (mp->retval);
2967   vam->result_ready = 1;
2968 }
2969
2970 static void
2971   vl_api_classify_table_by_interface_reply_t_handler_json
2972   (vl_api_classify_table_by_interface_reply_t * mp)
2973 {
2974   vat_main_t *vam = &vat_main;
2975   vat_json_node_t node;
2976
2977   vat_json_init_object (&node);
2978
2979   vat_json_object_add_int (&node, "l2_table_id", ntohl (mp->l2_table_id));
2980   vat_json_object_add_int (&node, "ip4_table_id", ntohl (mp->ip4_table_id));
2981   vat_json_object_add_int (&node, "ip6_table_id", ntohl (mp->ip6_table_id));
2982
2983   vat_json_print (vam->ofp, &node);
2984   vat_json_free (&node);
2985
2986   vam->retval = ntohl (mp->retval);
2987   vam->result_ready = 1;
2988 }
2989
2990 static void vl_api_policer_add_del_reply_t_handler
2991   (vl_api_policer_add_del_reply_t * mp)
2992 {
2993   vat_main_t *vam = &vat_main;
2994   i32 retval = ntohl (mp->retval);
2995   if (vam->async_mode)
2996     {
2997       vam->async_errors += (retval < 0);
2998     }
2999   else
3000     {
3001       vam->retval = retval;
3002       vam->result_ready = 1;
3003       if (retval == 0 && mp->policer_index != 0xFFFFFFFF)
3004         /*
3005          * Note: this is just barely thread-safe, depends on
3006          * the main thread spinning waiting for an answer...
3007          */
3008         errmsg ("policer index %d", ntohl (mp->policer_index));
3009     }
3010 }
3011
3012 static void vl_api_policer_add_del_reply_t_handler_json
3013   (vl_api_policer_add_del_reply_t * mp)
3014 {
3015   vat_main_t *vam = &vat_main;
3016   vat_json_node_t node;
3017
3018   vat_json_init_object (&node);
3019   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
3020   vat_json_object_add_uint (&node, "policer_index",
3021                             ntohl (mp->policer_index));
3022
3023   vat_json_print (vam->ofp, &node);
3024   vat_json_free (&node);
3025
3026   vam->retval = ntohl (mp->retval);
3027   vam->result_ready = 1;
3028 }
3029
3030 /* Format hex dump. */
3031 u8 *
3032 format_hex_bytes (u8 * s, va_list * va)
3033 {
3034   u8 *bytes = va_arg (*va, u8 *);
3035   int n_bytes = va_arg (*va, int);
3036   uword i;
3037
3038   /* Print short or long form depending on byte count. */
3039   uword short_form = n_bytes <= 32;
3040   u32 indent = format_get_indent (s);
3041
3042   if (n_bytes == 0)
3043     return s;
3044
3045   for (i = 0; i < n_bytes; i++)
3046     {
3047       if (!short_form && (i % 32) == 0)
3048         s = format (s, "%08x: ", i);
3049       s = format (s, "%02x", bytes[i]);
3050       if (!short_form && ((i + 1) % 32) == 0 && (i + 1) < n_bytes)
3051         s = format (s, "\n%U", format_white_space, indent);
3052     }
3053
3054   return s;
3055 }
3056
3057 static void
3058 vl_api_classify_table_info_reply_t_handler (vl_api_classify_table_info_reply_t
3059                                             * mp)
3060 {
3061   vat_main_t *vam = &vat_main;
3062   i32 retval = ntohl (mp->retval);
3063   if (retval == 0)
3064     {
3065       print (vam->ofp, "classify table info :");
3066       print (vam->ofp, "sessions: %d nexttbl: %d nextnode: %d",
3067              ntohl (mp->active_sessions), ntohl (mp->next_table_index),
3068              ntohl (mp->miss_next_index));
3069       print (vam->ofp, "nbuckets: %d skip: %d match: %d",
3070              ntohl (mp->nbuckets), ntohl (mp->skip_n_vectors),
3071              ntohl (mp->match_n_vectors));
3072       print (vam->ofp, "mask: %U", format_hex_bytes, mp->mask,
3073              ntohl (mp->mask_length));
3074     }
3075   vam->retval = retval;
3076   vam->result_ready = 1;
3077 }
3078
3079 static void
3080   vl_api_classify_table_info_reply_t_handler_json
3081   (vl_api_classify_table_info_reply_t * mp)
3082 {
3083   vat_main_t *vam = &vat_main;
3084   vat_json_node_t node;
3085
3086   i32 retval = ntohl (mp->retval);
3087   if (retval == 0)
3088     {
3089       vat_json_init_object (&node);
3090
3091       vat_json_object_add_int (&node, "sessions",
3092                                ntohl (mp->active_sessions));
3093       vat_json_object_add_int (&node, "nexttbl",
3094                                ntohl (mp->next_table_index));
3095       vat_json_object_add_int (&node, "nextnode",
3096                                ntohl (mp->miss_next_index));
3097       vat_json_object_add_int (&node, "nbuckets", ntohl (mp->nbuckets));
3098       vat_json_object_add_int (&node, "skip", ntohl (mp->skip_n_vectors));
3099       vat_json_object_add_int (&node, "match", ntohl (mp->match_n_vectors));
3100       u8 *s = format (0, "%U%c", format_hex_bytes, mp->mask,
3101                       ntohl (mp->mask_length), 0);
3102       vat_json_object_add_string_copy (&node, "mask", s);
3103
3104       vat_json_print (vam->ofp, &node);
3105       vat_json_free (&node);
3106     }
3107   vam->retval = ntohl (mp->retval);
3108   vam->result_ready = 1;
3109 }
3110
3111 static void
3112 vl_api_classify_session_details_t_handler (vl_api_classify_session_details_t *
3113                                            mp)
3114 {
3115   vat_main_t *vam = &vat_main;
3116
3117   print (vam->ofp, "next_index: %d advance: %d opaque: %d ",
3118          ntohl (mp->hit_next_index), ntohl (mp->advance),
3119          ntohl (mp->opaque_index));
3120   print (vam->ofp, "mask: %U", format_hex_bytes, mp->match,
3121          ntohl (mp->match_length));
3122 }
3123
3124 static void
3125   vl_api_classify_session_details_t_handler_json
3126   (vl_api_classify_session_details_t * mp)
3127 {
3128   vat_main_t *vam = &vat_main;
3129   vat_json_node_t *node = NULL;
3130
3131   if (VAT_JSON_ARRAY != vam->json_tree.type)
3132     {
3133       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
3134       vat_json_init_array (&vam->json_tree);
3135     }
3136   node = vat_json_array_add (&vam->json_tree);
3137
3138   vat_json_init_object (node);
3139   vat_json_object_add_int (node, "next_index", ntohl (mp->hit_next_index));
3140   vat_json_object_add_int (node, "advance", ntohl (mp->advance));
3141   vat_json_object_add_int (node, "opaque", ntohl (mp->opaque_index));
3142   u8 *s =
3143     format (0, "%U%c", format_hex_bytes, mp->match, ntohl (mp->match_length),
3144             0);
3145   vat_json_object_add_string_copy (node, "match", s);
3146 }
3147
3148 static void vl_api_pg_create_interface_reply_t_handler
3149   (vl_api_pg_create_interface_reply_t * mp)
3150 {
3151   vat_main_t *vam = &vat_main;
3152
3153   vam->retval = ntohl (mp->retval);
3154   vam->result_ready = 1;
3155 }
3156
3157 static void vl_api_pg_create_interface_reply_t_handler_json
3158   (vl_api_pg_create_interface_reply_t * mp)
3159 {
3160   vat_main_t *vam = &vat_main;
3161   vat_json_node_t node;
3162
3163   i32 retval = ntohl (mp->retval);
3164   if (retval == 0)
3165     {
3166       vat_json_init_object (&node);
3167
3168       vat_json_object_add_int (&node, "sw_if_index", ntohl (mp->sw_if_index));
3169
3170       vat_json_print (vam->ofp, &node);
3171       vat_json_free (&node);
3172     }
3173   vam->retval = ntohl (mp->retval);
3174   vam->result_ready = 1;
3175 }
3176
3177 static void vl_api_policer_classify_details_t_handler
3178   (vl_api_policer_classify_details_t * mp)
3179 {
3180   vat_main_t *vam = &vat_main;
3181
3182   print (vam->ofp, "%10d%20d", ntohl (mp->sw_if_index),
3183          ntohl (mp->table_index));
3184 }
3185
3186 static void vl_api_policer_classify_details_t_handler_json
3187   (vl_api_policer_classify_details_t * mp)
3188 {
3189   vat_main_t *vam = &vat_main;
3190   vat_json_node_t *node;
3191
3192   if (VAT_JSON_ARRAY != vam->json_tree.type)
3193     {
3194       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
3195       vat_json_init_array (&vam->json_tree);
3196     }
3197   node = vat_json_array_add (&vam->json_tree);
3198
3199   vat_json_init_object (node);
3200   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
3201   vat_json_object_add_uint (node, "table_index", ntohl (mp->table_index));
3202 }
3203
3204 static void vl_api_flow_classify_details_t_handler
3205   (vl_api_flow_classify_details_t * mp)
3206 {
3207   vat_main_t *vam = &vat_main;
3208
3209   print (vam->ofp, "%10d%20d", ntohl (mp->sw_if_index),
3210          ntohl (mp->table_index));
3211 }
3212
3213 static void vl_api_flow_classify_details_t_handler_json
3214   (vl_api_flow_classify_details_t * mp)
3215 {
3216   vat_main_t *vam = &vat_main;
3217   vat_json_node_t *node;
3218
3219   if (VAT_JSON_ARRAY != vam->json_tree.type)
3220     {
3221       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
3222       vat_json_init_array (&vam->json_tree);
3223     }
3224   node = vat_json_array_add (&vam->json_tree);
3225
3226   vat_json_init_object (node);
3227   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
3228   vat_json_object_add_uint (node, "table_index", ntohl (mp->table_index));
3229 }
3230
3231 /*
3232  * Generate boilerplate reply handlers, which
3233  * dig the return value out of the xxx_reply_t API message,
3234  * stick it into vam->retval, and set vam->result_ready
3235  *
3236  * Could also do this by pointing N message decode slots at
3237  * a single function, but that could break in subtle ways.
3238  */
3239
3240 #define foreach_standard_reply_retval_handler           \
3241 _(sw_interface_set_flags_reply)                         \
3242 _(sw_interface_add_del_address_reply)                   \
3243 _(sw_interface_set_rx_mode_reply)                       \
3244 _(sw_interface_set_rx_placement_reply)                  \
3245 _(sw_interface_set_table_reply)                         \
3246 _(sw_interface_set_mpls_enable_reply)                   \
3247 _(sw_interface_set_vpath_reply)                         \
3248 _(sw_interface_set_vxlan_bypass_reply)                  \
3249 _(sw_interface_set_vxlan_gpe_bypass_reply)              \
3250 _(sw_interface_set_l2_bridge_reply)                     \
3251 _(sw_interface_set_bond_weight_reply)                   \
3252 _(bridge_domain_add_del_reply)                          \
3253 _(sw_interface_set_l2_xconnect_reply)                   \
3254 _(l2fib_add_del_reply)                                  \
3255 _(l2fib_flush_int_reply)                                \
3256 _(l2fib_flush_bd_reply)                                 \
3257 _(ip_route_add_del_reply)                               \
3258 _(ip_table_add_del_reply)                               \
3259 _(ip_table_replace_begin_reply)                         \
3260 _(ip_table_flush_reply)                                 \
3261 _(ip_table_replace_end_reply)                           \
3262 _(ip_mroute_add_del_reply)                              \
3263 _(mpls_route_add_del_reply)                             \
3264 _(mpls_table_add_del_reply)                             \
3265 _(mpls_ip_bind_unbind_reply)                            \
3266 _(bier_route_add_del_reply)                             \
3267 _(bier_table_add_del_reply)                             \
3268 _(sw_interface_set_unnumbered_reply)                    \
3269 _(set_ip_flow_hash_reply)                               \
3270 _(sw_interface_ip6_enable_disable_reply)                \
3271 _(l2_patch_add_del_reply)                               \
3272 _(sr_mpls_policy_add_reply)                             \
3273 _(sr_mpls_policy_mod_reply)                             \
3274 _(sr_mpls_policy_del_reply)                             \
3275 _(sr_policy_add_reply)                                  \
3276 _(sr_policy_mod_reply)                                  \
3277 _(sr_policy_del_reply)                                  \
3278 _(sr_localsid_add_del_reply)                            \
3279 _(sr_steering_add_del_reply)                            \
3280 _(classify_add_del_session_reply)                       \
3281 _(classify_set_interface_ip_table_reply)                \
3282 _(classify_set_interface_l2_tables_reply)               \
3283 _(l2_fib_clear_table_reply)                             \
3284 _(l2_interface_efp_filter_reply)                        \
3285 _(l2_interface_vlan_tag_rewrite_reply)                  \
3286 _(modify_vhost_user_if_reply)                           \
3287 _(delete_vhost_user_if_reply)                           \
3288 _(want_l2_macs_events_reply)                            \
3289 _(input_acl_set_interface_reply)                        \
3290 _(ipsec_spd_add_del_reply)                              \
3291 _(ipsec_interface_add_del_spd_reply)                    \
3292 _(ipsec_spd_entry_add_del_reply)                        \
3293 _(ipsec_sad_entry_add_del_reply)                        \
3294 _(ipsec_tunnel_if_add_del_reply)                        \
3295 _(ipsec_tunnel_if_set_sa_reply)                         \
3296 _(delete_loopback_reply)                                \
3297 _(bd_ip_mac_add_del_reply)                              \
3298 _(bd_ip_mac_flush_reply)                                \
3299 _(want_interface_events_reply)                          \
3300 _(cop_interface_enable_disable_reply)                   \
3301 _(cop_whitelist_enable_disable_reply)                   \
3302 _(sw_interface_clear_stats_reply)                       \
3303 _(ioam_enable_reply)                                    \
3304 _(ioam_disable_reply)                                   \
3305 _(af_packet_delete_reply)                               \
3306 _(policer_classify_set_interface_reply)                 \
3307 _(set_ipfix_exporter_reply)                             \
3308 _(set_ipfix_classify_stream_reply)                      \
3309 _(ipfix_classify_table_add_del_reply)                   \
3310 _(flow_classify_set_interface_reply)                    \
3311 _(sw_interface_span_enable_disable_reply)               \
3312 _(pg_capture_reply)                                     \
3313 _(pg_enable_disable_reply)                              \
3314 _(pg_interface_enable_disable_coalesce_reply)           \
3315 _(ip_source_and_port_range_check_add_del_reply)         \
3316 _(ip_source_and_port_range_check_interface_add_del_reply)\
3317 _(delete_subif_reply)                                   \
3318 _(l2_interface_pbb_tag_rewrite_reply)                   \
3319 _(set_punt_reply)                                       \
3320 _(feature_enable_disable_reply)                         \
3321 _(feature_gso_enable_disable_reply)                     \
3322 _(sw_interface_tag_add_del_reply)                       \
3323 _(sw_interface_add_del_mac_address_reply)               \
3324 _(hw_interface_set_mtu_reply)                           \
3325 _(p2p_ethernet_add_reply)                               \
3326 _(p2p_ethernet_del_reply)                               \
3327 _(tcp_configure_src_addresses_reply)                    \
3328 _(session_rule_add_del_reply)                           \
3329 _(ip_container_proxy_add_del_reply)                     \
3330 _(output_acl_set_interface_reply)                       \
3331 _(qos_record_enable_disable_reply)                      \
3332 _(flow_add_reply)
3333
3334 #define _(n)                                    \
3335     static void vl_api_##n##_t_handler          \
3336     (vl_api_##n##_t * mp)                       \
3337     {                                           \
3338         vat_main_t * vam = &vat_main;           \
3339         i32 retval = ntohl(mp->retval);         \
3340         if (vam->async_mode) {                  \
3341             vam->async_errors += (retval < 0);  \
3342         } else {                                \
3343             vam->retval = retval;               \
3344             vam->result_ready = 1;              \
3345         }                                       \
3346     }
3347 foreach_standard_reply_retval_handler;
3348 #undef _
3349
3350 #define _(n)                                    \
3351     static void vl_api_##n##_t_handler_json     \
3352     (vl_api_##n##_t * mp)                       \
3353     {                                           \
3354         vat_main_t * vam = &vat_main;           \
3355         vat_json_node_t node;                   \
3356         vat_json_init_object(&node);            \
3357         vat_json_object_add_int(&node, "retval", ntohl(mp->retval));    \
3358         vat_json_print(vam->ofp, &node);        \
3359         vam->retval = ntohl(mp->retval);        \
3360         vam->result_ready = 1;                  \
3361     }
3362 foreach_standard_reply_retval_handler;
3363 #undef _
3364
3365 /*
3366  * Table of message reply handlers, must include boilerplate handlers
3367  * we just generated
3368  */
3369
3370 #define foreach_vpe_api_reply_msg                                       \
3371 _(CREATE_LOOPBACK_REPLY, create_loopback_reply)                         \
3372 _(CREATE_LOOPBACK_INSTANCE_REPLY, create_loopback_instance_reply)       \
3373 _(SW_INTERFACE_DETAILS, sw_interface_details)                           \
3374 _(SW_INTERFACE_SET_FLAGS_REPLY, sw_interface_set_flags_reply)           \
3375 _(CONTROL_PING_REPLY, control_ping_reply)                               \
3376 _(CLI_REPLY, cli_reply)                                                 \
3377 _(CLI_INBAND_REPLY, cli_inband_reply)                                   \
3378 _(SW_INTERFACE_ADD_DEL_ADDRESS_REPLY,                                   \
3379   sw_interface_add_del_address_reply)                                   \
3380 _(SW_INTERFACE_SET_RX_MODE_REPLY, sw_interface_set_rx_mode_reply)       \
3381 _(SW_INTERFACE_SET_RX_PLACEMENT_REPLY, sw_interface_set_rx_placement_reply)     \
3382 _(SW_INTERFACE_RX_PLACEMENT_DETAILS, sw_interface_rx_placement_details) \
3383 _(SW_INTERFACE_SET_TABLE_REPLY, sw_interface_set_table_reply)           \
3384 _(SW_INTERFACE_SET_MPLS_ENABLE_REPLY, sw_interface_set_mpls_enable_reply) \
3385 _(SW_INTERFACE_SET_VPATH_REPLY, sw_interface_set_vpath_reply)           \
3386 _(SW_INTERFACE_SET_VXLAN_BYPASS_REPLY, sw_interface_set_vxlan_bypass_reply) \
3387 _(SW_INTERFACE_SET_VXLAN_GPE_BYPASS_REPLY, sw_interface_set_vxlan_gpe_bypass_reply) \
3388 _(SW_INTERFACE_SET_L2_XCONNECT_REPLY,                                   \
3389   sw_interface_set_l2_xconnect_reply)                                   \
3390 _(SW_INTERFACE_SET_L2_BRIDGE_REPLY,                                     \
3391   sw_interface_set_l2_bridge_reply)                                     \
3392 _(BRIDGE_DOMAIN_ADD_DEL_REPLY, bridge_domain_add_del_reply)             \
3393 _(BRIDGE_DOMAIN_DETAILS, bridge_domain_details)                         \
3394 _(BRIDGE_DOMAIN_SET_MAC_AGE_REPLY, bridge_domain_set_mac_age_reply)     \
3395 _(L2FIB_ADD_DEL_REPLY, l2fib_add_del_reply)                             \
3396 _(L2FIB_FLUSH_INT_REPLY, l2fib_flush_int_reply)                         \
3397 _(L2FIB_FLUSH_BD_REPLY, l2fib_flush_bd_reply)                           \
3398 _(L2_FLAGS_REPLY, l2_flags_reply)                                       \
3399 _(BRIDGE_FLAGS_REPLY, bridge_flags_reply)                               \
3400 _(TAP_CREATE_V2_REPLY, tap_create_v2_reply)                             \
3401 _(TAP_DELETE_V2_REPLY, tap_delete_v2_reply)                             \
3402 _(SW_INTERFACE_TAP_V2_DETAILS, sw_interface_tap_v2_details)             \
3403 _(VIRTIO_PCI_CREATE_REPLY, virtio_pci_create_reply)                     \
3404 _(VIRTIO_PCI_CREATE_V2_REPLY, virtio_pci_create_v2_reply)               \
3405 _(VIRTIO_PCI_DELETE_REPLY, virtio_pci_delete_reply)                     \
3406 _(SW_INTERFACE_VIRTIO_PCI_DETAILS, sw_interface_virtio_pci_details)     \
3407 _(BOND_CREATE_REPLY, bond_create_reply)                                 \
3408 _(BOND_CREATE2_REPLY, bond_create2_reply)                               \
3409 _(BOND_DELETE_REPLY, bond_delete_reply)                                 \
3410 _(BOND_ADD_MEMBER_REPLY, bond_add_member_reply)                         \
3411 _(BOND_DETACH_MEMBER_REPLY, bond_detach_member_reply)                   \
3412 _(SW_INTERFACE_SET_BOND_WEIGHT_REPLY, sw_interface_set_bond_weight_reply) \
3413 _(SW_BOND_INTERFACE_DETAILS, sw_bond_interface_details)                 \
3414 _(SW_MEMBER_INTERFACE_DETAILS, sw_member_interface_details)               \
3415 _(IP_ROUTE_ADD_DEL_REPLY, ip_route_add_del_reply)                       \
3416 _(IP_TABLE_ADD_DEL_REPLY, ip_table_add_del_reply)                       \
3417 _(IP_TABLE_REPLACE_BEGIN_REPLY, ip_table_replace_begin_reply)           \
3418 _(IP_TABLE_FLUSH_REPLY, ip_table_flush_reply)                           \
3419 _(IP_TABLE_REPLACE_END_REPLY, ip_table_replace_end_reply)               \
3420 _(IP_MROUTE_ADD_DEL_REPLY, ip_mroute_add_del_reply)                     \
3421 _(MPLS_TABLE_ADD_DEL_REPLY, mpls_table_add_del_reply)                   \
3422 _(MPLS_ROUTE_ADD_DEL_REPLY, mpls_route_add_del_reply)                   \
3423 _(MPLS_IP_BIND_UNBIND_REPLY, mpls_ip_bind_unbind_reply)                 \
3424 _(BIER_ROUTE_ADD_DEL_REPLY, bier_route_add_del_reply)                   \
3425 _(BIER_TABLE_ADD_DEL_REPLY, bier_table_add_del_reply)                   \
3426 _(MPLS_TUNNEL_ADD_DEL_REPLY, mpls_tunnel_add_del_reply)                 \
3427 _(SW_INTERFACE_SET_UNNUMBERED_REPLY,                                    \
3428   sw_interface_set_unnumbered_reply)                                    \
3429 _(CREATE_VLAN_SUBIF_REPLY, create_vlan_subif_reply)                     \
3430 _(CREATE_SUBIF_REPLY, create_subif_reply)                               \
3431 _(SET_IP_FLOW_HASH_REPLY, set_ip_flow_hash_reply)                       \
3432 _(SW_INTERFACE_IP6_ENABLE_DISABLE_REPLY,                                \
3433   sw_interface_ip6_enable_disable_reply)                                \
3434 _(L2_PATCH_ADD_DEL_REPLY, l2_patch_add_del_reply)                       \
3435 _(SR_MPLS_POLICY_ADD_REPLY, sr_mpls_policy_add_reply)                   \
3436 _(SR_MPLS_POLICY_MOD_REPLY, sr_mpls_policy_mod_reply)                   \
3437 _(SR_MPLS_POLICY_DEL_REPLY, sr_mpls_policy_del_reply)                   \
3438 _(SR_POLICY_ADD_REPLY, sr_policy_add_reply)                             \
3439 _(SR_POLICY_MOD_REPLY, sr_policy_mod_reply)                             \
3440 _(SR_POLICY_DEL_REPLY, sr_policy_del_reply)                             \
3441 _(SR_LOCALSID_ADD_DEL_REPLY, sr_localsid_add_del_reply)                 \
3442 _(SR_STEERING_ADD_DEL_REPLY, sr_steering_add_del_reply)                 \
3443 _(CLASSIFY_ADD_DEL_TABLE_REPLY, classify_add_del_table_reply)           \
3444 _(CLASSIFY_ADD_DEL_SESSION_REPLY, classify_add_del_session_reply)       \
3445 _(CLASSIFY_SET_INTERFACE_IP_TABLE_REPLY,                                \
3446 classify_set_interface_ip_table_reply)                                  \
3447 _(CLASSIFY_SET_INTERFACE_L2_TABLES_REPLY,                               \
3448   classify_set_interface_l2_tables_reply)                               \
3449 _(GET_NODE_INDEX_REPLY, get_node_index_reply)                           \
3450 _(ADD_NODE_NEXT_REPLY, add_node_next_reply)                             \
3451 _(VXLAN_ADD_DEL_TUNNEL_REPLY, vxlan_add_del_tunnel_reply)               \
3452 _(VXLAN_OFFLOAD_RX_REPLY, vxlan_offload_rx_reply)               \
3453 _(VXLAN_TUNNEL_DETAILS, vxlan_tunnel_details)                           \
3454 _(GRE_TUNNEL_ADD_DEL_REPLY, gre_tunnel_add_del_reply)                   \
3455 _(GRE_TUNNEL_DETAILS, gre_tunnel_details)                               \
3456 _(L2_FIB_CLEAR_TABLE_REPLY, l2_fib_clear_table_reply)                   \
3457 _(L2_INTERFACE_EFP_FILTER_REPLY, l2_interface_efp_filter_reply)         \
3458 _(L2_INTERFACE_VLAN_TAG_REWRITE_REPLY, l2_interface_vlan_tag_rewrite_reply) \
3459 _(SW_INTERFACE_VHOST_USER_DETAILS, sw_interface_vhost_user_details)     \
3460 _(CREATE_VHOST_USER_IF_REPLY, create_vhost_user_if_reply)               \
3461 _(MODIFY_VHOST_USER_IF_REPLY, modify_vhost_user_if_reply)               \
3462 _(DELETE_VHOST_USER_IF_REPLY, delete_vhost_user_if_reply)               \
3463 _(SHOW_VERSION_REPLY, show_version_reply)                               \
3464 _(SHOW_THREADS_REPLY, show_threads_reply)                               \
3465 _(L2_FIB_TABLE_DETAILS, l2_fib_table_details)                           \
3466 _(VXLAN_GPE_ADD_DEL_TUNNEL_REPLY, vxlan_gpe_add_del_tunnel_reply)       \
3467 _(VXLAN_GPE_TUNNEL_DETAILS, vxlan_gpe_tunnel_details)                   \
3468 _(INTERFACE_NAME_RENUMBER_REPLY, interface_name_renumber_reply)         \
3469 _(WANT_L2_MACS_EVENTS_REPLY, want_l2_macs_events_reply)                 \
3470 _(L2_MACS_EVENT, l2_macs_event)                                         \
3471 _(INPUT_ACL_SET_INTERFACE_REPLY, input_acl_set_interface_reply)         \
3472 _(IP_ADDRESS_DETAILS, ip_address_details)                               \
3473 _(IP_DETAILS, ip_details)                                               \
3474 _(IPSEC_SPD_ADD_DEL_REPLY, ipsec_spd_add_del_reply)                     \
3475 _(IPSEC_INTERFACE_ADD_DEL_SPD_REPLY, ipsec_interface_add_del_spd_reply) \
3476 _(IPSEC_SPD_ENTRY_ADD_DEL_REPLY, ipsec_spd_entry_add_del_reply)         \
3477 _(IPSEC_SAD_ENTRY_ADD_DEL_REPLY, ipsec_sad_entry_add_del_reply)         \
3478 _(IPSEC_SA_DETAILS, ipsec_sa_details)                                   \
3479 _(IPSEC_TUNNEL_IF_ADD_DEL_REPLY, ipsec_tunnel_if_add_del_reply)         \
3480 _(IPSEC_TUNNEL_IF_SET_SA_REPLY, ipsec_tunnel_if_set_sa_reply)           \
3481 _(DELETE_LOOPBACK_REPLY, delete_loopback_reply)                         \
3482 _(BD_IP_MAC_ADD_DEL_REPLY, bd_ip_mac_add_del_reply)                     \
3483 _(BD_IP_MAC_FLUSH_REPLY, bd_ip_mac_flush_reply)                         \
3484 _(BD_IP_MAC_DETAILS, bd_ip_mac_details)                                 \
3485 _(WANT_INTERFACE_EVENTS_REPLY, want_interface_events_reply)             \
3486 _(GET_FIRST_MSG_ID_REPLY, get_first_msg_id_reply)                       \
3487 _(COP_INTERFACE_ENABLE_DISABLE_REPLY, cop_interface_enable_disable_reply) \
3488 _(COP_WHITELIST_ENABLE_DISABLE_REPLY, cop_whitelist_enable_disable_reply) \
3489 _(GET_NODE_GRAPH_REPLY, get_node_graph_reply)                           \
3490 _(SW_INTERFACE_CLEAR_STATS_REPLY, sw_interface_clear_stats_reply)      \
3491 _(IOAM_ENABLE_REPLY, ioam_enable_reply)                   \
3492 _(IOAM_DISABLE_REPLY, ioam_disable_reply)                     \
3493 _(AF_PACKET_CREATE_REPLY, af_packet_create_reply)                       \
3494 _(AF_PACKET_DELETE_REPLY, af_packet_delete_reply)                       \
3495 _(AF_PACKET_DETAILS, af_packet_details)                                 \
3496 _(POLICER_ADD_DEL_REPLY, policer_add_del_reply)                         \
3497 _(POLICER_DETAILS, policer_details)                                     \
3498 _(POLICER_CLASSIFY_SET_INTERFACE_REPLY, policer_classify_set_interface_reply) \
3499 _(POLICER_CLASSIFY_DETAILS, policer_classify_details)                   \
3500 _(MPLS_TUNNEL_DETAILS, mpls_tunnel_details)                             \
3501 _(MPLS_TABLE_DETAILS, mpls_table_details)                               \
3502 _(MPLS_ROUTE_DETAILS, mpls_route_details)                               \
3503 _(CLASSIFY_TABLE_IDS_REPLY, classify_table_ids_reply)                   \
3504 _(CLASSIFY_TABLE_BY_INTERFACE_REPLY, classify_table_by_interface_reply) \
3505 _(CLASSIFY_TABLE_INFO_REPLY, classify_table_info_reply)                 \
3506 _(CLASSIFY_SESSION_DETAILS, classify_session_details)                   \
3507 _(SET_IPFIX_EXPORTER_REPLY, set_ipfix_exporter_reply)                   \
3508 _(IPFIX_EXPORTER_DETAILS, ipfix_exporter_details)                       \
3509 _(SET_IPFIX_CLASSIFY_STREAM_REPLY, set_ipfix_classify_stream_reply)     \
3510 _(IPFIX_CLASSIFY_STREAM_DETAILS, ipfix_classify_stream_details)         \
3511 _(IPFIX_CLASSIFY_TABLE_ADD_DEL_REPLY, ipfix_classify_table_add_del_reply) \
3512 _(IPFIX_CLASSIFY_TABLE_DETAILS, ipfix_classify_table_details)           \
3513 _(FLOW_CLASSIFY_SET_INTERFACE_REPLY, flow_classify_set_interface_reply) \
3514 _(FLOW_CLASSIFY_DETAILS, flow_classify_details)                         \
3515 _(SW_INTERFACE_SPAN_ENABLE_DISABLE_REPLY, sw_interface_span_enable_disable_reply) \
3516 _(SW_INTERFACE_SPAN_DETAILS, sw_interface_span_details)                 \
3517 _(GET_NEXT_INDEX_REPLY, get_next_index_reply)                           \
3518 _(PG_CREATE_INTERFACE_REPLY, pg_create_interface_reply)                 \
3519 _(PG_CAPTURE_REPLY, pg_capture_reply)                                   \
3520 _(PG_ENABLE_DISABLE_REPLY, pg_enable_disable_reply)                     \
3521 _(PG_INTERFACE_ENABLE_DISABLE_COALESCE_REPLY, pg_interface_enable_disable_coalesce_reply) \
3522 _(IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL_REPLY,                         \
3523  ip_source_and_port_range_check_add_del_reply)                          \
3524 _(IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL_REPLY,               \
3525  ip_source_and_port_range_check_interface_add_del_reply)                \
3526 _(DELETE_SUBIF_REPLY, delete_subif_reply)                               \
3527 _(L2_INTERFACE_PBB_TAG_REWRITE_REPLY, l2_interface_pbb_tag_rewrite_reply) \
3528 _(SET_PUNT_REPLY, set_punt_reply)                                       \
3529 _(IP_TABLE_DETAILS, ip_table_details)                                   \
3530 _(IP_ROUTE_DETAILS, ip_route_details)                                   \
3531 _(FEATURE_ENABLE_DISABLE_REPLY, feature_enable_disable_reply)           \
3532 _(FEATURE_GSO_ENABLE_DISABLE_REPLY, feature_gso_enable_disable_reply)   \
3533 _(SW_INTERFACE_TAG_ADD_DEL_REPLY, sw_interface_tag_add_del_reply)       \
3534 _(SW_INTERFACE_ADD_DEL_MAC_ADDRESS_REPLY, sw_interface_add_del_mac_address_reply) \
3535 _(L2_XCONNECT_DETAILS, l2_xconnect_details)                             \
3536 _(HW_INTERFACE_SET_MTU_REPLY, hw_interface_set_mtu_reply)               \
3537 _(SW_INTERFACE_GET_TABLE_REPLY, sw_interface_get_table_reply)           \
3538 _(P2P_ETHERNET_ADD_REPLY, p2p_ethernet_add_reply)                       \
3539 _(P2P_ETHERNET_DEL_REPLY, p2p_ethernet_del_reply)                       \
3540 _(TCP_CONFIGURE_SRC_ADDRESSES_REPLY, tcp_configure_src_addresses_reply) \
3541 _(APP_NAMESPACE_ADD_DEL_REPLY, app_namespace_add_del_reply)             \
3542 _(SESSION_RULE_ADD_DEL_REPLY, session_rule_add_del_reply)               \
3543 _(SESSION_RULES_DETAILS, session_rules_details)                         \
3544 _(IP_CONTAINER_PROXY_ADD_DEL_REPLY, ip_container_proxy_add_del_reply)   \
3545 _(OUTPUT_ACL_SET_INTERFACE_REPLY, output_acl_set_interface_reply)       \
3546 _(QOS_RECORD_ENABLE_DISABLE_REPLY, qos_record_enable_disable_reply)             \
3547 _(FLOW_ADD_REPLY, flow_add_reply)   \
3548
3549 #define foreach_standalone_reply_msg                                    \
3550 _(SW_INTERFACE_EVENT, sw_interface_event)
3551
3552 typedef struct
3553 {
3554   u8 *name;
3555   u32 value;
3556 } name_sort_t;
3557
3558 #define STR_VTR_OP_CASE(op)     \
3559     case L2_VTR_ ## op:         \
3560         return "" # op;
3561
3562 static const char *
3563 str_vtr_op (u32 vtr_op)
3564 {
3565   switch (vtr_op)
3566     {
3567       STR_VTR_OP_CASE (DISABLED);
3568       STR_VTR_OP_CASE (PUSH_1);
3569       STR_VTR_OP_CASE (PUSH_2);
3570       STR_VTR_OP_CASE (POP_1);
3571       STR_VTR_OP_CASE (POP_2);
3572       STR_VTR_OP_CASE (TRANSLATE_1_1);
3573       STR_VTR_OP_CASE (TRANSLATE_1_2);
3574       STR_VTR_OP_CASE (TRANSLATE_2_1);
3575       STR_VTR_OP_CASE (TRANSLATE_2_2);
3576     }
3577
3578   return "UNKNOWN";
3579 }
3580
3581 static int
3582 dump_sub_interface_table (vat_main_t * vam)
3583 {
3584   const sw_interface_subif_t *sub = NULL;
3585
3586   if (vam->json_output)
3587     {
3588       clib_warning
3589         ("JSON output supported only for VPE API calls and dump_stats_table");
3590       return -99;
3591     }
3592
3593   print (vam->ofp,
3594          "%-30s%-12s%-11s%-7s%-5s%-9s%-9s%-6s%-8s%-10s%-10s",
3595          "Interface", "sw_if_index",
3596          "sub id", "dot1ad", "tags", "outer id",
3597          "inner id", "exact", "default", "outer any", "inner any");
3598
3599   vec_foreach (sub, vam->sw_if_subif_table)
3600   {
3601     print (vam->ofp,
3602            "%-30s%-12d%-11d%-7s%-5d%-9d%-9d%-6d%-8d%-10d%-10d",
3603            sub->interface_name,
3604            sub->sw_if_index,
3605            sub->sub_id, sub->sub_dot1ad ? "dot1ad" : "dot1q",
3606            sub->sub_number_of_tags, sub->sub_outer_vlan_id,
3607            sub->sub_inner_vlan_id, sub->sub_exact_match, sub->sub_default,
3608            sub->sub_outer_vlan_id_any, sub->sub_inner_vlan_id_any);
3609     if (sub->vtr_op != L2_VTR_DISABLED)
3610       {
3611         print (vam->ofp,
3612                "  vlan-tag-rewrite - op: %-14s [ dot1q: %d "
3613                "tag1: %d tag2: %d ]",
3614                str_vtr_op (sub->vtr_op), sub->vtr_push_dot1q,
3615                sub->vtr_tag1, sub->vtr_tag2);
3616       }
3617   }
3618
3619   return 0;
3620 }
3621
3622 static int
3623 name_sort_cmp (void *a1, void *a2)
3624 {
3625   name_sort_t *n1 = a1;
3626   name_sort_t *n2 = a2;
3627
3628   return strcmp ((char *) n1->name, (char *) n2->name);
3629 }
3630
3631 static int
3632 dump_interface_table (vat_main_t * vam)
3633 {
3634   hash_pair_t *p;
3635   name_sort_t *nses = 0, *ns;
3636
3637   if (vam->json_output)
3638     {
3639       clib_warning
3640         ("JSON output supported only for VPE API calls and dump_stats_table");
3641       return -99;
3642     }
3643
3644   /* *INDENT-OFF* */
3645   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
3646   ({
3647     vec_add2 (nses, ns, 1);
3648     ns->name = (u8 *)(p->key);
3649     ns->value = (u32) p->value[0];
3650   }));
3651   /* *INDENT-ON* */
3652
3653   vec_sort_with_function (nses, name_sort_cmp);
3654
3655   print (vam->ofp, "%-25s%-15s", "Interface", "sw_if_index");
3656   vec_foreach (ns, nses)
3657   {
3658     print (vam->ofp, "%-25s%-15d", ns->name, ns->value);
3659   }
3660   vec_free (nses);
3661   return 0;
3662 }
3663
3664 static int
3665 dump_ip_table (vat_main_t * vam, int is_ipv6)
3666 {
3667   const ip_details_t *det = NULL;
3668   const ip_address_details_t *address = NULL;
3669   u32 i = ~0;
3670
3671   print (vam->ofp, "%-12s", "sw_if_index");
3672
3673   vec_foreach (det, vam->ip_details_by_sw_if_index[is_ipv6])
3674   {
3675     i++;
3676     if (!det->present)
3677       {
3678         continue;
3679       }
3680     print (vam->ofp, "%-12d", i);
3681     print (vam->ofp, "            %-30s%-13s", "Address", "Prefix length");
3682     if (!det->addr)
3683       {
3684         continue;
3685       }
3686     vec_foreach (address, det->addr)
3687     {
3688       print (vam->ofp,
3689              "            %-30U%-13d",
3690              is_ipv6 ? format_ip6_address : format_ip4_address,
3691              address->ip, address->prefix_length);
3692     }
3693   }
3694
3695   return 0;
3696 }
3697
3698 static int
3699 dump_ipv4_table (vat_main_t * vam)
3700 {
3701   if (vam->json_output)
3702     {
3703       clib_warning
3704         ("JSON output supported only for VPE API calls and dump_stats_table");
3705       return -99;
3706     }
3707
3708   return dump_ip_table (vam, 0);
3709 }
3710
3711 static int
3712 dump_ipv6_table (vat_main_t * vam)
3713 {
3714   if (vam->json_output)
3715     {
3716       clib_warning
3717         ("JSON output supported only for VPE API calls and dump_stats_table");
3718       return -99;
3719     }
3720
3721   return dump_ip_table (vam, 1);
3722 }
3723
3724 /*
3725  * Pass CLI buffers directly in the CLI_INBAND API message,
3726  * instead of an additional shared memory area.
3727  */
3728 static int
3729 exec_inband (vat_main_t * vam)
3730 {
3731   vl_api_cli_inband_t *mp;
3732   unformat_input_t *i = vam->input;
3733   int ret;
3734
3735   if (vec_len (i->buffer) == 0)
3736     return -1;
3737
3738   if (vam->exec_mode == 0 && unformat (i, "mode"))
3739     {
3740       vam->exec_mode = 1;
3741       return 0;
3742     }
3743   if (vam->exec_mode == 1 && (unformat (i, "exit") || unformat (i, "quit")))
3744     {
3745       vam->exec_mode = 0;
3746       return 0;
3747     }
3748
3749   /*
3750    * In order for the CLI command to work, it
3751    * must be a vector ending in \n, not a C-string ending
3752    * in \n\0.
3753    */
3754   M2 (CLI_INBAND, mp, vec_len (vam->input->buffer));
3755   vl_api_vec_to_api_string (vam->input->buffer, &mp->cmd);
3756
3757   S (mp);
3758   W (ret);
3759   /* json responses may or may not include a useful reply... */
3760   if (vec_len (vam->cmd_reply))
3761     print (vam->ofp, "%v", (char *) (vam->cmd_reply));
3762   return ret;
3763 }
3764
3765 int
3766 exec (vat_main_t * vam)
3767 {
3768   return exec_inband (vam);
3769 }
3770
3771 static int
3772 api_create_loopback (vat_main_t * vam)
3773 {
3774   unformat_input_t *i = vam->input;
3775   vl_api_create_loopback_t *mp;
3776   vl_api_create_loopback_instance_t *mp_lbi;
3777   u8 mac_address[6];
3778   u8 mac_set = 0;
3779   u8 is_specified = 0;
3780   u32 user_instance = 0;
3781   int ret;
3782
3783   clib_memset (mac_address, 0, sizeof (mac_address));
3784
3785   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3786     {
3787       if (unformat (i, "mac %U", unformat_ethernet_address, mac_address))
3788         mac_set = 1;
3789       if (unformat (i, "instance %d", &user_instance))
3790         is_specified = 1;
3791       else
3792         break;
3793     }
3794
3795   if (is_specified)
3796     {
3797       M (CREATE_LOOPBACK_INSTANCE, mp_lbi);
3798       mp_lbi->is_specified = is_specified;
3799       if (is_specified)
3800         mp_lbi->user_instance = htonl (user_instance);
3801       if (mac_set)
3802         clib_memcpy (mp_lbi->mac_address, mac_address, sizeof (mac_address));
3803       S (mp_lbi);
3804     }
3805   else
3806     {
3807       /* Construct the API message */
3808       M (CREATE_LOOPBACK, mp);
3809       if (mac_set)
3810         clib_memcpy (mp->mac_address, mac_address, sizeof (mac_address));
3811       S (mp);
3812     }
3813
3814   W (ret);
3815   return ret;
3816 }
3817
3818 static int
3819 api_delete_loopback (vat_main_t * vam)
3820 {
3821   unformat_input_t *i = vam->input;
3822   vl_api_delete_loopback_t *mp;
3823   u32 sw_if_index = ~0;
3824   int ret;
3825
3826   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3827     {
3828       if (unformat (i, "sw_if_index %d", &sw_if_index))
3829         ;
3830       else
3831         break;
3832     }
3833
3834   if (sw_if_index == ~0)
3835     {
3836       errmsg ("missing sw_if_index");
3837       return -99;
3838     }
3839
3840   /* Construct the API message */
3841   M (DELETE_LOOPBACK, mp);
3842   mp->sw_if_index = ntohl (sw_if_index);
3843
3844   S (mp);
3845   W (ret);
3846   return ret;
3847 }
3848
3849 static int
3850 api_want_interface_events (vat_main_t * vam)
3851 {
3852   unformat_input_t *i = vam->input;
3853   vl_api_want_interface_events_t *mp;
3854   int enable = -1;
3855   int ret;
3856
3857   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3858     {
3859       if (unformat (i, "enable"))
3860         enable = 1;
3861       else if (unformat (i, "disable"))
3862         enable = 0;
3863       else
3864         break;
3865     }
3866
3867   if (enable == -1)
3868     {
3869       errmsg ("missing enable|disable");
3870       return -99;
3871     }
3872
3873   M (WANT_INTERFACE_EVENTS, mp);
3874   mp->enable_disable = enable;
3875
3876   vam->interface_event_display = enable;
3877
3878   S (mp);
3879   W (ret);
3880   return ret;
3881 }
3882
3883
3884 /* Note: non-static, called once to set up the initial intfc table */
3885 int
3886 api_sw_interface_dump (vat_main_t * vam)
3887 {
3888   vl_api_sw_interface_dump_t *mp;
3889   vl_api_control_ping_t *mp_ping;
3890   hash_pair_t *p;
3891   name_sort_t *nses = 0, *ns;
3892   sw_interface_subif_t *sub = NULL;
3893   int ret;
3894
3895   /* Toss the old name table */
3896   /* *INDENT-OFF* */
3897   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
3898   ({
3899     vec_add2 (nses, ns, 1);
3900     ns->name = (u8 *)(p->key);
3901     ns->value = (u32) p->value[0];
3902   }));
3903   /* *INDENT-ON* */
3904
3905   hash_free (vam->sw_if_index_by_interface_name);
3906
3907   vec_foreach (ns, nses) vec_free (ns->name);
3908
3909   vec_free (nses);
3910
3911   vec_foreach (sub, vam->sw_if_subif_table)
3912   {
3913     vec_free (sub->interface_name);
3914   }
3915   vec_free (vam->sw_if_subif_table);
3916
3917   /* recreate the interface name hash table */
3918   vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
3919
3920   /*
3921    * Ask for all interface names. Otherwise, the epic catalog of
3922    * name filters becomes ridiculously long, and vat ends up needing
3923    * to be taught about new interface types.
3924    */
3925   M (SW_INTERFACE_DUMP, mp);
3926   S (mp);
3927
3928   /* Use a control ping for synchronization */
3929   MPING (CONTROL_PING, mp_ping);
3930   S (mp_ping);
3931
3932   W (ret);
3933   return ret;
3934 }
3935
3936 static int
3937 api_sw_interface_set_flags (vat_main_t * vam)
3938 {
3939   unformat_input_t *i = vam->input;
3940   vl_api_sw_interface_set_flags_t *mp;
3941   u32 sw_if_index;
3942   u8 sw_if_index_set = 0;
3943   u8 admin_up = 0;
3944   int ret;
3945
3946   /* Parse args required to build the message */
3947   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3948     {
3949       if (unformat (i, "admin-up"))
3950         admin_up = 1;
3951       else if (unformat (i, "admin-down"))
3952         admin_up = 0;
3953       else
3954         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3955         sw_if_index_set = 1;
3956       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3957         sw_if_index_set = 1;
3958       else
3959         break;
3960     }
3961
3962   if (sw_if_index_set == 0)
3963     {
3964       errmsg ("missing interface name or sw_if_index");
3965       return -99;
3966     }
3967
3968   /* Construct the API message */
3969   M (SW_INTERFACE_SET_FLAGS, mp);
3970   mp->sw_if_index = ntohl (sw_if_index);
3971   mp->flags = ntohl ((admin_up) ? IF_STATUS_API_FLAG_ADMIN_UP : 0);
3972
3973   /* send it... */
3974   S (mp);
3975
3976   /* Wait for a reply, return the good/bad news... */
3977   W (ret);
3978   return ret;
3979 }
3980
3981 static int
3982 api_sw_interface_set_rx_mode (vat_main_t * vam)
3983 {
3984   unformat_input_t *i = vam->input;
3985   vl_api_sw_interface_set_rx_mode_t *mp;
3986   u32 sw_if_index;
3987   u8 sw_if_index_set = 0;
3988   int ret;
3989   u8 queue_id_valid = 0;
3990   u32 queue_id;
3991   vnet_hw_if_rx_mode mode = VNET_HW_IF_RX_MODE_UNKNOWN;
3992
3993   /* Parse args required to build the message */
3994   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3995     {
3996       if (unformat (i, "queue %d", &queue_id))
3997         queue_id_valid = 1;
3998       else if (unformat (i, "polling"))
3999         mode = VNET_HW_IF_RX_MODE_POLLING;
4000       else if (unformat (i, "interrupt"))
4001         mode = VNET_HW_IF_RX_MODE_INTERRUPT;
4002       else if (unformat (i, "adaptive"))
4003         mode = VNET_HW_IF_RX_MODE_ADAPTIVE;
4004       else
4005         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4006         sw_if_index_set = 1;
4007       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4008         sw_if_index_set = 1;
4009       else
4010         break;
4011     }
4012
4013   if (sw_if_index_set == 0)
4014     {
4015       errmsg ("missing interface name or sw_if_index");
4016       return -99;
4017     }
4018   if (mode == VNET_HW_IF_RX_MODE_UNKNOWN)
4019     {
4020       errmsg ("missing rx-mode");
4021       return -99;
4022     }
4023
4024   /* Construct the API message */
4025   M (SW_INTERFACE_SET_RX_MODE, mp);
4026   mp->sw_if_index = ntohl (sw_if_index);
4027   mp->mode = (vl_api_rx_mode_t) mode;
4028   mp->queue_id_valid = queue_id_valid;
4029   mp->queue_id = queue_id_valid ? ntohl (queue_id) : ~0;
4030
4031   /* send it... */
4032   S (mp);
4033
4034   /* Wait for a reply, return the good/bad news... */
4035   W (ret);
4036   return ret;
4037 }
4038
4039 static int
4040 api_sw_interface_set_rx_placement (vat_main_t * vam)
4041 {
4042   unformat_input_t *i = vam->input;
4043   vl_api_sw_interface_set_rx_placement_t *mp;
4044   u32 sw_if_index;
4045   u8 sw_if_index_set = 0;
4046   int ret;
4047   u8 is_main = 0;
4048   u32 queue_id, thread_index;
4049
4050   /* Parse args required to build the message */
4051   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4052     {
4053       if (unformat (i, "queue %d", &queue_id))
4054         ;
4055       else if (unformat (i, "main"))
4056         is_main = 1;
4057       else if (unformat (i, "worker %d", &thread_index))
4058         ;
4059       else
4060         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4061         sw_if_index_set = 1;
4062       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4063         sw_if_index_set = 1;
4064       else
4065         break;
4066     }
4067
4068   if (sw_if_index_set == 0)
4069     {
4070       errmsg ("missing interface name or sw_if_index");
4071       return -99;
4072     }
4073
4074   if (is_main)
4075     thread_index = 0;
4076   /* Construct the API message */
4077   M (SW_INTERFACE_SET_RX_PLACEMENT, mp);
4078   mp->sw_if_index = ntohl (sw_if_index);
4079   mp->worker_id = ntohl (thread_index);
4080   mp->queue_id = ntohl (queue_id);
4081   mp->is_main = is_main;
4082
4083   /* send it... */
4084   S (mp);
4085   /* Wait for a reply, return the good/bad news... */
4086   W (ret);
4087   return ret;
4088 }
4089
4090 static void vl_api_sw_interface_rx_placement_details_t_handler
4091   (vl_api_sw_interface_rx_placement_details_t * mp)
4092 {
4093   vat_main_t *vam = &vat_main;
4094   u32 worker_id = ntohl (mp->worker_id);
4095
4096   print (vam->ofp,
4097          "\n%-11d %-11s %-6d %-5d %-9s",
4098          ntohl (mp->sw_if_index), (worker_id == 0) ? "main" : "worker",
4099          worker_id, ntohl (mp->queue_id),
4100          (mp->mode ==
4101           1) ? "polling" : ((mp->mode == 2) ? "interrupt" : "adaptive"));
4102 }
4103
4104 static void vl_api_sw_interface_rx_placement_details_t_handler_json
4105   (vl_api_sw_interface_rx_placement_details_t * mp)
4106 {
4107   vat_main_t *vam = &vat_main;
4108   vat_json_node_t *node = NULL;
4109
4110   if (VAT_JSON_ARRAY != vam->json_tree.type)
4111     {
4112       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
4113       vat_json_init_array (&vam->json_tree);
4114     }
4115   node = vat_json_array_add (&vam->json_tree);
4116
4117   vat_json_init_object (node);
4118   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
4119   vat_json_object_add_uint (node, "worker_id", ntohl (mp->worker_id));
4120   vat_json_object_add_uint (node, "queue_id", ntohl (mp->queue_id));
4121   vat_json_object_add_uint (node, "mode", mp->mode);
4122 }
4123
4124 static int
4125 api_sw_interface_rx_placement_dump (vat_main_t * vam)
4126 {
4127   unformat_input_t *i = vam->input;
4128   vl_api_sw_interface_rx_placement_dump_t *mp;
4129   vl_api_control_ping_t *mp_ping;
4130   int ret;
4131   u32 sw_if_index;
4132   u8 sw_if_index_set = 0;
4133
4134   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4135     {
4136       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4137         sw_if_index_set++;
4138       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4139         sw_if_index_set++;
4140       else
4141         break;
4142     }
4143
4144   print (vam->ofp,
4145          "\n%-11s %-11s %-6s %-5s %-4s",
4146          "sw_if_index", "main/worker", "thread", "queue", "mode");
4147
4148   /* Dump Interface rx placement */
4149   M (SW_INTERFACE_RX_PLACEMENT_DUMP, mp);
4150
4151   if (sw_if_index_set)
4152     mp->sw_if_index = htonl (sw_if_index);
4153   else
4154     mp->sw_if_index = ~0;
4155
4156   S (mp);
4157
4158   /* Use a control ping for synchronization */
4159   MPING (CONTROL_PING, mp_ping);
4160   S (mp_ping);
4161
4162   W (ret);
4163   return ret;
4164 }
4165
4166 static int
4167 api_sw_interface_clear_stats (vat_main_t * vam)
4168 {
4169   unformat_input_t *i = vam->input;
4170   vl_api_sw_interface_clear_stats_t *mp;
4171   u32 sw_if_index;
4172   u8 sw_if_index_set = 0;
4173   int ret;
4174
4175   /* Parse args required to build the message */
4176   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4177     {
4178       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4179         sw_if_index_set = 1;
4180       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4181         sw_if_index_set = 1;
4182       else
4183         break;
4184     }
4185
4186   /* Construct the API message */
4187   M (SW_INTERFACE_CLEAR_STATS, mp);
4188
4189   if (sw_if_index_set == 1)
4190     mp->sw_if_index = ntohl (sw_if_index);
4191   else
4192     mp->sw_if_index = ~0;
4193
4194   /* send it... */
4195   S (mp);
4196
4197   /* Wait for a reply, return the good/bad news... */
4198   W (ret);
4199   return ret;
4200 }
4201
4202 static int
4203 api_sw_interface_add_del_address (vat_main_t * vam)
4204 {
4205   unformat_input_t *i = vam->input;
4206   vl_api_sw_interface_add_del_address_t *mp;
4207   u32 sw_if_index;
4208   u8 sw_if_index_set = 0;
4209   u8 is_add = 1, del_all = 0;
4210   u32 address_length = 0;
4211   u8 v4_address_set = 0;
4212   u8 v6_address_set = 0;
4213   ip4_address_t v4address;
4214   ip6_address_t v6address;
4215   int ret;
4216
4217   /* Parse args required to build the message */
4218   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4219     {
4220       if (unformat (i, "del-all"))
4221         del_all = 1;
4222       else if (unformat (i, "del"))
4223         is_add = 0;
4224       else
4225         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4226         sw_if_index_set = 1;
4227       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4228         sw_if_index_set = 1;
4229       else if (unformat (i, "%U/%d",
4230                          unformat_ip4_address, &v4address, &address_length))
4231         v4_address_set = 1;
4232       else if (unformat (i, "%U/%d",
4233                          unformat_ip6_address, &v6address, &address_length))
4234         v6_address_set = 1;
4235       else
4236         break;
4237     }
4238
4239   if (sw_if_index_set == 0)
4240     {
4241       errmsg ("missing interface name or sw_if_index");
4242       return -99;
4243     }
4244   if (v4_address_set && v6_address_set)
4245     {
4246       errmsg ("both v4 and v6 addresses set");
4247       return -99;
4248     }
4249   if (!v4_address_set && !v6_address_set && !del_all)
4250     {
4251       errmsg ("no addresses set");
4252       return -99;
4253     }
4254
4255   /* Construct the API message */
4256   M (SW_INTERFACE_ADD_DEL_ADDRESS, mp);
4257
4258   mp->sw_if_index = ntohl (sw_if_index);
4259   mp->is_add = is_add;
4260   mp->del_all = del_all;
4261   if (v6_address_set)
4262     {
4263       mp->prefix.address.af = ADDRESS_IP6;
4264       clib_memcpy (mp->prefix.address.un.ip6, &v6address, sizeof (v6address));
4265     }
4266   else
4267     {
4268       mp->prefix.address.af = ADDRESS_IP4;
4269       clib_memcpy (mp->prefix.address.un.ip4, &v4address, sizeof (v4address));
4270     }
4271   mp->prefix.len = address_length;
4272
4273   /* send it... */
4274   S (mp);
4275
4276   /* Wait for a reply, return good/bad news  */
4277   W (ret);
4278   return ret;
4279 }
4280
4281 static int
4282 api_sw_interface_set_mpls_enable (vat_main_t * vam)
4283 {
4284   unformat_input_t *i = vam->input;
4285   vl_api_sw_interface_set_mpls_enable_t *mp;
4286   u32 sw_if_index;
4287   u8 sw_if_index_set = 0;
4288   u8 enable = 1;
4289   int ret;
4290
4291   /* Parse args required to build the message */
4292   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4293     {
4294       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4295         sw_if_index_set = 1;
4296       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4297         sw_if_index_set = 1;
4298       else if (unformat (i, "disable"))
4299         enable = 0;
4300       else if (unformat (i, "dis"))
4301         enable = 0;
4302       else
4303         break;
4304     }
4305
4306   if (sw_if_index_set == 0)
4307     {
4308       errmsg ("missing interface name or sw_if_index");
4309       return -99;
4310     }
4311
4312   /* Construct the API message */
4313   M (SW_INTERFACE_SET_MPLS_ENABLE, mp);
4314
4315   mp->sw_if_index = ntohl (sw_if_index);
4316   mp->enable = enable;
4317
4318   /* send it... */
4319   S (mp);
4320
4321   /* Wait for a reply... */
4322   W (ret);
4323   return ret;
4324 }
4325
4326 static int
4327 api_sw_interface_set_table (vat_main_t * vam)
4328 {
4329   unformat_input_t *i = vam->input;
4330   vl_api_sw_interface_set_table_t *mp;
4331   u32 sw_if_index, vrf_id = 0;
4332   u8 sw_if_index_set = 0;
4333   u8 is_ipv6 = 0;
4334   int ret;
4335
4336   /* Parse args required to build the message */
4337   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4338     {
4339       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4340         sw_if_index_set = 1;
4341       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4342         sw_if_index_set = 1;
4343       else if (unformat (i, "vrf %d", &vrf_id))
4344         ;
4345       else if (unformat (i, "ipv6"))
4346         is_ipv6 = 1;
4347       else
4348         break;
4349     }
4350
4351   if (sw_if_index_set == 0)
4352     {
4353       errmsg ("missing interface name or sw_if_index");
4354       return -99;
4355     }
4356
4357   /* Construct the API message */
4358   M (SW_INTERFACE_SET_TABLE, mp);
4359
4360   mp->sw_if_index = ntohl (sw_if_index);
4361   mp->is_ipv6 = is_ipv6;
4362   mp->vrf_id = ntohl (vrf_id);
4363
4364   /* send it... */
4365   S (mp);
4366
4367   /* Wait for a reply... */
4368   W (ret);
4369   return ret;
4370 }
4371
4372 static void vl_api_sw_interface_get_table_reply_t_handler
4373   (vl_api_sw_interface_get_table_reply_t * mp)
4374 {
4375   vat_main_t *vam = &vat_main;
4376
4377   print (vam->ofp, "%d", ntohl (mp->vrf_id));
4378
4379   vam->retval = ntohl (mp->retval);
4380   vam->result_ready = 1;
4381
4382 }
4383
4384 static void vl_api_sw_interface_get_table_reply_t_handler_json
4385   (vl_api_sw_interface_get_table_reply_t * mp)
4386 {
4387   vat_main_t *vam = &vat_main;
4388   vat_json_node_t node;
4389
4390   vat_json_init_object (&node);
4391   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
4392   vat_json_object_add_int (&node, "vrf_id", ntohl (mp->vrf_id));
4393
4394   vat_json_print (vam->ofp, &node);
4395   vat_json_free (&node);
4396
4397   vam->retval = ntohl (mp->retval);
4398   vam->result_ready = 1;
4399 }
4400
4401 static int
4402 api_sw_interface_get_table (vat_main_t * vam)
4403 {
4404   unformat_input_t *i = vam->input;
4405   vl_api_sw_interface_get_table_t *mp;
4406   u32 sw_if_index;
4407   u8 sw_if_index_set = 0;
4408   u8 is_ipv6 = 0;
4409   int ret;
4410
4411   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4412     {
4413       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4414         sw_if_index_set = 1;
4415       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4416         sw_if_index_set = 1;
4417       else if (unformat (i, "ipv6"))
4418         is_ipv6 = 1;
4419       else
4420         break;
4421     }
4422
4423   if (sw_if_index_set == 0)
4424     {
4425       errmsg ("missing interface name or sw_if_index");
4426       return -99;
4427     }
4428
4429   M (SW_INTERFACE_GET_TABLE, mp);
4430   mp->sw_if_index = htonl (sw_if_index);
4431   mp->is_ipv6 = is_ipv6;
4432
4433   S (mp);
4434   W (ret);
4435   return ret;
4436 }
4437
4438 static int
4439 api_sw_interface_set_vpath (vat_main_t * vam)
4440 {
4441   unformat_input_t *i = vam->input;
4442   vl_api_sw_interface_set_vpath_t *mp;
4443   u32 sw_if_index = 0;
4444   u8 sw_if_index_set = 0;
4445   u8 is_enable = 0;
4446   int ret;
4447
4448   /* Parse args required to build the message */
4449   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4450     {
4451       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4452         sw_if_index_set = 1;
4453       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4454         sw_if_index_set = 1;
4455       else if (unformat (i, "enable"))
4456         is_enable = 1;
4457       else if (unformat (i, "disable"))
4458         is_enable = 0;
4459       else
4460         break;
4461     }
4462
4463   if (sw_if_index_set == 0)
4464     {
4465       errmsg ("missing interface name or sw_if_index");
4466       return -99;
4467     }
4468
4469   /* Construct the API message */
4470   M (SW_INTERFACE_SET_VPATH, mp);
4471
4472   mp->sw_if_index = ntohl (sw_if_index);
4473   mp->enable = is_enable;
4474
4475   /* send it... */
4476   S (mp);
4477
4478   /* Wait for a reply... */
4479   W (ret);
4480   return ret;
4481 }
4482
4483 static int
4484 api_sw_interface_set_vxlan_bypass (vat_main_t * vam)
4485 {
4486   unformat_input_t *i = vam->input;
4487   vl_api_sw_interface_set_vxlan_bypass_t *mp;
4488   u32 sw_if_index = 0;
4489   u8 sw_if_index_set = 0;
4490   u8 is_enable = 1;
4491   u8 is_ipv6 = 0;
4492   int ret;
4493
4494   /* Parse args required to build the message */
4495   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4496     {
4497       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4498         sw_if_index_set = 1;
4499       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4500         sw_if_index_set = 1;
4501       else if (unformat (i, "enable"))
4502         is_enable = 1;
4503       else if (unformat (i, "disable"))
4504         is_enable = 0;
4505       else if (unformat (i, "ip4"))
4506         is_ipv6 = 0;
4507       else if (unformat (i, "ip6"))
4508         is_ipv6 = 1;
4509       else
4510         break;
4511     }
4512
4513   if (sw_if_index_set == 0)
4514     {
4515       errmsg ("missing interface name or sw_if_index");
4516       return -99;
4517     }
4518
4519   /* Construct the API message */
4520   M (SW_INTERFACE_SET_VXLAN_BYPASS, mp);
4521
4522   mp->sw_if_index = ntohl (sw_if_index);
4523   mp->enable = is_enable;
4524   mp->is_ipv6 = is_ipv6;
4525
4526   /* send it... */
4527   S (mp);
4528
4529   /* Wait for a reply... */
4530   W (ret);
4531   return ret;
4532 }
4533
4534 static int
4535 api_sw_interface_set_l2_xconnect (vat_main_t * vam)
4536 {
4537   unformat_input_t *i = vam->input;
4538   vl_api_sw_interface_set_l2_xconnect_t *mp;
4539   u32 rx_sw_if_index;
4540   u8 rx_sw_if_index_set = 0;
4541   u32 tx_sw_if_index;
4542   u8 tx_sw_if_index_set = 0;
4543   u8 enable = 1;
4544   int ret;
4545
4546   /* Parse args required to build the message */
4547   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4548     {
4549       if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index))
4550         rx_sw_if_index_set = 1;
4551       else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
4552         tx_sw_if_index_set = 1;
4553       else if (unformat (i, "rx"))
4554         {
4555           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4556             {
4557               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
4558                             &rx_sw_if_index))
4559                 rx_sw_if_index_set = 1;
4560             }
4561           else
4562             break;
4563         }
4564       else if (unformat (i, "tx"))
4565         {
4566           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4567             {
4568               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
4569                             &tx_sw_if_index))
4570                 tx_sw_if_index_set = 1;
4571             }
4572           else
4573             break;
4574         }
4575       else if (unformat (i, "enable"))
4576         enable = 1;
4577       else if (unformat (i, "disable"))
4578         enable = 0;
4579       else
4580         break;
4581     }
4582
4583   if (rx_sw_if_index_set == 0)
4584     {
4585       errmsg ("missing rx interface name or rx_sw_if_index");
4586       return -99;
4587     }
4588
4589   if (enable && (tx_sw_if_index_set == 0))
4590     {
4591       errmsg ("missing tx interface name or tx_sw_if_index");
4592       return -99;
4593     }
4594
4595   M (SW_INTERFACE_SET_L2_XCONNECT, mp);
4596
4597   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
4598   mp->tx_sw_if_index = ntohl (tx_sw_if_index);
4599   mp->enable = enable;
4600
4601   S (mp);
4602   W (ret);
4603   return ret;
4604 }
4605
4606 static int
4607 api_sw_interface_set_l2_bridge (vat_main_t * vam)
4608 {
4609   unformat_input_t *i = vam->input;
4610   vl_api_sw_interface_set_l2_bridge_t *mp;
4611   vl_api_l2_port_type_t port_type;
4612   u32 rx_sw_if_index;
4613   u8 rx_sw_if_index_set = 0;
4614   u32 bd_id;
4615   u8 bd_id_set = 0;
4616   u32 shg = 0;
4617   u8 enable = 1;
4618   int ret;
4619
4620   port_type = L2_API_PORT_TYPE_NORMAL;
4621
4622   /* Parse args required to build the message */
4623   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4624     {
4625       if (unformat (i, "sw_if_index %d", &rx_sw_if_index))
4626         rx_sw_if_index_set = 1;
4627       else if (unformat (i, "bd_id %d", &bd_id))
4628         bd_id_set = 1;
4629       else
4630         if (unformat
4631             (i, "%U", api_unformat_sw_if_index, vam, &rx_sw_if_index))
4632         rx_sw_if_index_set = 1;
4633       else if (unformat (i, "shg %d", &shg))
4634         ;
4635       else if (unformat (i, "bvi"))
4636         port_type = L2_API_PORT_TYPE_BVI;
4637       else if (unformat (i, "uu-fwd"))
4638         port_type = L2_API_PORT_TYPE_UU_FWD;
4639       else if (unformat (i, "enable"))
4640         enable = 1;
4641       else if (unformat (i, "disable"))
4642         enable = 0;
4643       else
4644         break;
4645     }
4646
4647   if (rx_sw_if_index_set == 0)
4648     {
4649       errmsg ("missing rx interface name or sw_if_index");
4650       return -99;
4651     }
4652
4653   if (enable && (bd_id_set == 0))
4654     {
4655       errmsg ("missing bridge domain");
4656       return -99;
4657     }
4658
4659   M (SW_INTERFACE_SET_L2_BRIDGE, mp);
4660
4661   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
4662   mp->bd_id = ntohl (bd_id);
4663   mp->shg = (u8) shg;
4664   mp->port_type = ntohl (port_type);
4665   mp->enable = enable;
4666
4667   S (mp);
4668   W (ret);
4669   return ret;
4670 }
4671
4672 static int
4673 api_bridge_domain_dump (vat_main_t * vam)
4674 {
4675   unformat_input_t *i = vam->input;
4676   vl_api_bridge_domain_dump_t *mp;
4677   vl_api_control_ping_t *mp_ping;
4678   u32 bd_id = ~0;
4679   int ret;
4680
4681   /* Parse args required to build the message */
4682   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4683     {
4684       if (unformat (i, "bd_id %d", &bd_id))
4685         ;
4686       else
4687         break;
4688     }
4689
4690   M (BRIDGE_DOMAIN_DUMP, mp);
4691   mp->bd_id = ntohl (bd_id);
4692   S (mp);
4693
4694   /* Use a control ping for synchronization */
4695   MPING (CONTROL_PING, mp_ping);
4696   S (mp_ping);
4697
4698   W (ret);
4699   return ret;
4700 }
4701
4702 static int
4703 api_bridge_domain_add_del (vat_main_t * vam)
4704 {
4705   unformat_input_t *i = vam->input;
4706   vl_api_bridge_domain_add_del_t *mp;
4707   u32 bd_id = ~0;
4708   u8 is_add = 1;
4709   u32 flood = 1, forward = 1, learn = 1, uu_flood = 1, arp_term = 0;
4710   u8 *bd_tag = NULL;
4711   u32 mac_age = 0;
4712   int ret;
4713
4714   /* Parse args required to build the message */
4715   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4716     {
4717       if (unformat (i, "bd_id %d", &bd_id))
4718         ;
4719       else if (unformat (i, "flood %d", &flood))
4720         ;
4721       else if (unformat (i, "uu-flood %d", &uu_flood))
4722         ;
4723       else if (unformat (i, "forward %d", &forward))
4724         ;
4725       else if (unformat (i, "learn %d", &learn))
4726         ;
4727       else if (unformat (i, "arp-term %d", &arp_term))
4728         ;
4729       else if (unformat (i, "mac-age %d", &mac_age))
4730         ;
4731       else if (unformat (i, "bd-tag %s", &bd_tag))
4732         ;
4733       else if (unformat (i, "del"))
4734         {
4735           is_add = 0;
4736           flood = uu_flood = forward = learn = 0;
4737         }
4738       else
4739         break;
4740     }
4741
4742   if (bd_id == ~0)
4743     {
4744       errmsg ("missing bridge domain");
4745       ret = -99;
4746       goto done;
4747     }
4748
4749   if (mac_age > 255)
4750     {
4751       errmsg ("mac age must be less than 256 ");
4752       ret = -99;
4753       goto done;
4754     }
4755
4756   if ((bd_tag) && (vec_len (bd_tag) > 63))
4757     {
4758       errmsg ("bd-tag cannot be longer than 63");
4759       ret = -99;
4760       goto done;
4761     }
4762
4763   M (BRIDGE_DOMAIN_ADD_DEL, mp);
4764
4765   mp->bd_id = ntohl (bd_id);
4766   mp->flood = flood;
4767   mp->uu_flood = uu_flood;
4768   mp->forward = forward;
4769   mp->learn = learn;
4770   mp->arp_term = arp_term;
4771   mp->is_add = is_add;
4772   mp->mac_age = (u8) mac_age;
4773   if (bd_tag)
4774     {
4775       clib_memcpy (mp->bd_tag, bd_tag, vec_len (bd_tag));
4776       mp->bd_tag[vec_len (bd_tag)] = 0;
4777     }
4778   S (mp);
4779   W (ret);
4780
4781 done:
4782   vec_free (bd_tag);
4783   return ret;
4784 }
4785
4786 static int
4787 api_l2fib_flush_bd (vat_main_t * vam)
4788 {
4789   unformat_input_t *i = vam->input;
4790   vl_api_l2fib_flush_bd_t *mp;
4791   u32 bd_id = ~0;
4792   int ret;
4793
4794   /* Parse args required to build the message */
4795   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4796     {
4797       if (unformat (i, "bd_id %d", &bd_id));
4798       else
4799         break;
4800     }
4801
4802   if (bd_id == ~0)
4803     {
4804       errmsg ("missing bridge domain");
4805       return -99;
4806     }
4807
4808   M (L2FIB_FLUSH_BD, mp);
4809
4810   mp->bd_id = htonl (bd_id);
4811
4812   S (mp);
4813   W (ret);
4814   return ret;
4815 }
4816
4817 static int
4818 api_l2fib_flush_int (vat_main_t * vam)
4819 {
4820   unformat_input_t *i = vam->input;
4821   vl_api_l2fib_flush_int_t *mp;
4822   u32 sw_if_index = ~0;
4823   int ret;
4824
4825   /* Parse args required to build the message */
4826   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4827     {
4828       if (unformat (i, "sw_if_index %d", &sw_if_index));
4829       else
4830         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index));
4831       else
4832         break;
4833     }
4834
4835   if (sw_if_index == ~0)
4836     {
4837       errmsg ("missing interface name or sw_if_index");
4838       return -99;
4839     }
4840
4841   M (L2FIB_FLUSH_INT, mp);
4842
4843   mp->sw_if_index = ntohl (sw_if_index);
4844
4845   S (mp);
4846   W (ret);
4847   return ret;
4848 }
4849
4850 static int
4851 api_l2fib_add_del (vat_main_t * vam)
4852 {
4853   unformat_input_t *i = vam->input;
4854   vl_api_l2fib_add_del_t *mp;
4855   f64 timeout;
4856   u8 mac[6] = { 0 };
4857   u8 mac_set = 0;
4858   u32 bd_id;
4859   u8 bd_id_set = 0;
4860   u32 sw_if_index = 0;
4861   u8 sw_if_index_set = 0;
4862   u8 is_add = 1;
4863   u8 static_mac = 0;
4864   u8 filter_mac = 0;
4865   u8 bvi_mac = 0;
4866   int count = 1;
4867   f64 before = 0;
4868   int j;
4869
4870   /* Parse args required to build the message */
4871   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4872     {
4873       if (unformat (i, "mac %U", unformat_ethernet_address, mac))
4874         mac_set = 1;
4875       else if (unformat (i, "bd_id %d", &bd_id))
4876         bd_id_set = 1;
4877       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4878         sw_if_index_set = 1;
4879       else if (unformat (i, "sw_if"))
4880         {
4881           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4882             {
4883               if (unformat
4884                   (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4885                 sw_if_index_set = 1;
4886             }
4887           else
4888             break;
4889         }
4890       else if (unformat (i, "static"))
4891         static_mac = 1;
4892       else if (unformat (i, "filter"))
4893         {
4894           filter_mac = 1;
4895           static_mac = 1;
4896         }
4897       else if (unformat (i, "bvi"))
4898         {
4899           bvi_mac = 1;
4900           static_mac = 1;
4901         }
4902       else if (unformat (i, "del"))
4903         is_add = 0;
4904       else if (unformat (i, "count %d", &count))
4905         ;
4906       else
4907         break;
4908     }
4909
4910   if (mac_set == 0)
4911     {
4912       errmsg ("missing mac address");
4913       return -99;
4914     }
4915
4916   if (bd_id_set == 0)
4917     {
4918       errmsg ("missing bridge domain");
4919       return -99;
4920     }
4921
4922   if (is_add && sw_if_index_set == 0 && filter_mac == 0)
4923     {
4924       errmsg ("missing interface name or sw_if_index");
4925       return -99;
4926     }
4927
4928   if (count > 1)
4929     {
4930       /* Turn on async mode */
4931       vam->async_mode = 1;
4932       vam->async_errors = 0;
4933       before = vat_time_now (vam);
4934     }
4935
4936   for (j = 0; j < count; j++)
4937     {
4938       M (L2FIB_ADD_DEL, mp);
4939
4940       clib_memcpy (mp->mac, mac, 6);
4941       mp->bd_id = ntohl (bd_id);
4942       mp->is_add = is_add;
4943       mp->sw_if_index = ntohl (sw_if_index);
4944
4945       if (is_add)
4946         {
4947           mp->static_mac = static_mac;
4948           mp->filter_mac = filter_mac;
4949           mp->bvi_mac = bvi_mac;
4950         }
4951       increment_mac_address (mac);
4952       /* send it... */
4953       S (mp);
4954     }
4955
4956   if (count > 1)
4957     {
4958       vl_api_control_ping_t *mp_ping;
4959       f64 after;
4960
4961       /* Shut off async mode */
4962       vam->async_mode = 0;
4963
4964       MPING (CONTROL_PING, mp_ping);
4965       S (mp_ping);
4966
4967       timeout = vat_time_now (vam) + 1.0;
4968       while (vat_time_now (vam) < timeout)
4969         if (vam->result_ready == 1)
4970           goto out;
4971       vam->retval = -99;
4972
4973     out:
4974       if (vam->retval == -99)
4975         errmsg ("timeout");
4976
4977       if (vam->async_errors > 0)
4978         {
4979           errmsg ("%d asynchronous errors", vam->async_errors);
4980           vam->retval = -98;
4981         }
4982       vam->async_errors = 0;
4983       after = vat_time_now (vam);
4984
4985       print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec",
4986              count, after - before, count / (after - before));
4987     }
4988   else
4989     {
4990       int ret;
4991
4992       /* Wait for a reply... */
4993       W (ret);
4994       return ret;
4995     }
4996   /* Return the good/bad news */
4997   return (vam->retval);
4998 }
4999
5000 static int
5001 api_bridge_domain_set_mac_age (vat_main_t * vam)
5002 {
5003   unformat_input_t *i = vam->input;
5004   vl_api_bridge_domain_set_mac_age_t *mp;
5005   u32 bd_id = ~0;
5006   u32 mac_age = 0;
5007   int ret;
5008
5009   /* Parse args required to build the message */
5010   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5011     {
5012       if (unformat (i, "bd_id %d", &bd_id));
5013       else if (unformat (i, "mac-age %d", &mac_age));
5014       else
5015         break;
5016     }
5017
5018   if (bd_id == ~0)
5019     {
5020       errmsg ("missing bridge domain");
5021       return -99;
5022     }
5023
5024   if (mac_age > 255)
5025     {
5026       errmsg ("mac age must be less than 256 ");
5027       return -99;
5028     }
5029
5030   M (BRIDGE_DOMAIN_SET_MAC_AGE, mp);
5031
5032   mp->bd_id = htonl (bd_id);
5033   mp->mac_age = (u8) mac_age;
5034
5035   S (mp);
5036   W (ret);
5037   return ret;
5038 }
5039
5040 static int
5041 api_l2_flags (vat_main_t * vam)
5042 {
5043   unformat_input_t *i = vam->input;
5044   vl_api_l2_flags_t *mp;
5045   u32 sw_if_index;
5046   u32 flags = 0;
5047   u8 sw_if_index_set = 0;
5048   u8 is_set = 0;
5049   int ret;
5050
5051   /* Parse args required to build the message */
5052   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5053     {
5054       if (unformat (i, "sw_if_index %d", &sw_if_index))
5055         sw_if_index_set = 1;
5056       else if (unformat (i, "sw_if"))
5057         {
5058           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5059             {
5060               if (unformat
5061                   (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5062                 sw_if_index_set = 1;
5063             }
5064           else
5065             break;
5066         }
5067       else if (unformat (i, "learn"))
5068         flags |= L2_LEARN;
5069       else if (unformat (i, "forward"))
5070         flags |= L2_FWD;
5071       else if (unformat (i, "flood"))
5072         flags |= L2_FLOOD;
5073       else if (unformat (i, "uu-flood"))
5074         flags |= L2_UU_FLOOD;
5075       else if (unformat (i, "arp-term"))
5076         flags |= L2_ARP_TERM;
5077       else if (unformat (i, "off"))
5078         is_set = 0;
5079       else if (unformat (i, "disable"))
5080         is_set = 0;
5081       else
5082         break;
5083     }
5084
5085   if (sw_if_index_set == 0)
5086     {
5087       errmsg ("missing interface name or sw_if_index");
5088       return -99;
5089     }
5090
5091   M (L2_FLAGS, mp);
5092
5093   mp->sw_if_index = ntohl (sw_if_index);
5094   mp->feature_bitmap = ntohl (flags);
5095   mp->is_set = is_set;
5096
5097   S (mp);
5098   W (ret);
5099   return ret;
5100 }
5101
5102 static int
5103 api_bridge_flags (vat_main_t * vam)
5104 {
5105   unformat_input_t *i = vam->input;
5106   vl_api_bridge_flags_t *mp;
5107   u32 bd_id;
5108   u8 bd_id_set = 0;
5109   u8 is_set = 1;
5110   bd_flags_t flags = 0;
5111   int ret;
5112
5113   /* Parse args required to build the message */
5114   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5115     {
5116       if (unformat (i, "bd_id %d", &bd_id))
5117         bd_id_set = 1;
5118       else if (unformat (i, "learn"))
5119         flags |= BRIDGE_API_FLAG_LEARN;
5120       else if (unformat (i, "forward"))
5121         flags |= BRIDGE_API_FLAG_FWD;
5122       else if (unformat (i, "flood"))
5123         flags |= BRIDGE_API_FLAG_FLOOD;
5124       else if (unformat (i, "uu-flood"))
5125         flags |= BRIDGE_API_FLAG_UU_FLOOD;
5126       else if (unformat (i, "arp-term"))
5127         flags |= BRIDGE_API_FLAG_ARP_TERM;
5128       else if (unformat (i, "off"))
5129         is_set = 0;
5130       else if (unformat (i, "disable"))
5131         is_set = 0;
5132       else
5133         break;
5134     }
5135
5136   if (bd_id_set == 0)
5137     {
5138       errmsg ("missing bridge domain");
5139       return -99;
5140     }
5141
5142   M (BRIDGE_FLAGS, mp);
5143
5144   mp->bd_id = ntohl (bd_id);
5145   mp->flags = ntohl (flags);
5146   mp->is_set = is_set;
5147
5148   S (mp);
5149   W (ret);
5150   return ret;
5151 }
5152
5153 static int
5154 api_bd_ip_mac_add_del (vat_main_t * vam)
5155 {
5156   vl_api_address_t ip = VL_API_ZERO_ADDRESS;
5157   vl_api_mac_address_t mac = { 0 };
5158   unformat_input_t *i = vam->input;
5159   vl_api_bd_ip_mac_add_del_t *mp;
5160   u32 bd_id;
5161   u8 is_add = 1;
5162   u8 bd_id_set = 0;
5163   u8 ip_set = 0;
5164   u8 mac_set = 0;
5165   int ret;
5166
5167
5168   /* Parse args required to build the message */
5169   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5170     {
5171       if (unformat (i, "bd_id %d", &bd_id))
5172         {
5173           bd_id_set++;
5174         }
5175       else if (unformat (i, "%U", unformat_vl_api_address, &ip))
5176         {
5177           ip_set++;
5178         }
5179       else if (unformat (i, "%U", unformat_vl_api_mac_address, &mac))
5180         {
5181           mac_set++;
5182         }
5183       else if (unformat (i, "del"))
5184         is_add = 0;
5185       else
5186         break;
5187     }
5188
5189   if (bd_id_set == 0)
5190     {
5191       errmsg ("missing bridge domain");
5192       return -99;
5193     }
5194   else if (ip_set == 0)
5195     {
5196       errmsg ("missing IP address");
5197       return -99;
5198     }
5199   else if (mac_set == 0)
5200     {
5201       errmsg ("missing MAC address");
5202       return -99;
5203     }
5204
5205   M (BD_IP_MAC_ADD_DEL, mp);
5206
5207   mp->entry.bd_id = ntohl (bd_id);
5208   mp->is_add = is_add;
5209
5210   clib_memcpy (&mp->entry.ip, &ip, sizeof (ip));
5211   clib_memcpy (&mp->entry.mac, &mac, sizeof (mac));
5212
5213   S (mp);
5214   W (ret);
5215   return ret;
5216 }
5217
5218 static int
5219 api_bd_ip_mac_flush (vat_main_t * vam)
5220 {
5221   unformat_input_t *i = vam->input;
5222   vl_api_bd_ip_mac_flush_t *mp;
5223   u32 bd_id;
5224   u8 bd_id_set = 0;
5225   int ret;
5226
5227   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5228     {
5229       if (unformat (i, "bd_id %d", &bd_id))
5230         {
5231           bd_id_set++;
5232         }
5233       else
5234         break;
5235     }
5236
5237   if (bd_id_set == 0)
5238     {
5239       errmsg ("missing bridge domain");
5240       return -99;
5241     }
5242
5243   M (BD_IP_MAC_FLUSH, mp);
5244
5245   mp->bd_id = ntohl (bd_id);
5246
5247   S (mp);
5248   W (ret);
5249   return ret;
5250 }
5251
5252 static void vl_api_bd_ip_mac_details_t_handler
5253   (vl_api_bd_ip_mac_details_t * mp)
5254 {
5255   vat_main_t *vam = &vat_main;
5256
5257   print (vam->ofp,
5258          "\n%-5d %U %U",
5259          ntohl (mp->entry.bd_id),
5260          format_vl_api_mac_address, mp->entry.mac,
5261          format_vl_api_address, &mp->entry.ip);
5262 }
5263
5264 static void vl_api_bd_ip_mac_details_t_handler_json
5265   (vl_api_bd_ip_mac_details_t * mp)
5266 {
5267   vat_main_t *vam = &vat_main;
5268   vat_json_node_t *node = NULL;
5269
5270   if (VAT_JSON_ARRAY != vam->json_tree.type)
5271     {
5272       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
5273       vat_json_init_array (&vam->json_tree);
5274     }
5275   node = vat_json_array_add (&vam->json_tree);
5276
5277   vat_json_init_object (node);
5278   vat_json_object_add_uint (node, "bd_id", ntohl (mp->entry.bd_id));
5279   vat_json_object_add_string_copy (node, "mac_address",
5280                                    format (0, "%U", format_vl_api_mac_address,
5281                                            &mp->entry.mac));
5282   u8 *ip = 0;
5283
5284   ip = format (0, "%U", format_vl_api_address, &mp->entry.ip);
5285   vat_json_object_add_string_copy (node, "ip_address", ip);
5286   vec_free (ip);
5287 }
5288
5289 static int
5290 api_bd_ip_mac_dump (vat_main_t * vam)
5291 {
5292   unformat_input_t *i = vam->input;
5293   vl_api_bd_ip_mac_dump_t *mp;
5294   vl_api_control_ping_t *mp_ping;
5295   int ret;
5296   u32 bd_id;
5297   u8 bd_id_set = 0;
5298
5299   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5300     {
5301       if (unformat (i, "bd_id %d", &bd_id))
5302         {
5303           bd_id_set++;
5304         }
5305       else
5306         break;
5307     }
5308
5309   print (vam->ofp,
5310          "\n%-5s %-7s %-20s %-30s",
5311          "bd_id", "is_ipv6", "mac_address", "ip_address");
5312
5313   /* Dump Bridge Domain Ip to Mac entries */
5314   M (BD_IP_MAC_DUMP, mp);
5315
5316   if (bd_id_set)
5317     mp->bd_id = htonl (bd_id);
5318   else
5319     mp->bd_id = ~0;
5320
5321   S (mp);
5322
5323   /* Use a control ping for synchronization */
5324   MPING (CONTROL_PING, mp_ping);
5325   S (mp_ping);
5326
5327   W (ret);
5328   return ret;
5329 }
5330
5331 static int
5332 api_tap_create_v2 (vat_main_t * vam)
5333 {
5334   unformat_input_t *i = vam->input;
5335   vl_api_tap_create_v2_t *mp;
5336   u8 mac_address[6];
5337   u8 random_mac = 1;
5338   u32 id = ~0;
5339   u32 num_rx_queues = 0;
5340   u8 *host_if_name = 0;
5341   u8 host_if_name_set = 0;
5342   u8 *host_ns = 0;
5343   u8 host_ns_set = 0;
5344   u8 host_mac_addr[6];
5345   u8 host_mac_addr_set = 0;
5346   u8 *host_bridge = 0;
5347   u8 host_bridge_set = 0;
5348   u8 host_ip4_prefix_set = 0;
5349   u8 host_ip6_prefix_set = 0;
5350   ip4_address_t host_ip4_addr;
5351   ip4_address_t host_ip4_gw;
5352   u8 host_ip4_gw_set = 0;
5353   u32 host_ip4_prefix_len = 0;
5354   ip6_address_t host_ip6_addr;
5355   ip6_address_t host_ip6_gw;
5356   u8 host_ip6_gw_set = 0;
5357   u32 host_ip6_prefix_len = 0;
5358   u32 host_mtu_size = 0;
5359   u8 host_mtu_set = 0;
5360   u32 tap_flags = 0;
5361   int ret;
5362   u32 rx_ring_sz = 0, tx_ring_sz = 0;
5363
5364   clib_memset (mac_address, 0, sizeof (mac_address));
5365
5366   /* Parse args required to build the message */
5367   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5368     {
5369       if (unformat (i, "id %u", &id))
5370         ;
5371       else
5372         if (unformat
5373             (i, "hw-addr %U", unformat_ethernet_address, mac_address))
5374         random_mac = 0;
5375       else if (unformat (i, "host-if-name %s", &host_if_name))
5376         host_if_name_set = 1;
5377       else if (unformat (i, "num-rx-queues %u", &num_rx_queues))
5378         ;
5379       else if (unformat (i, "host-ns %s", &host_ns))
5380         host_ns_set = 1;
5381       else if (unformat (i, "host-mac-addr %U", unformat_ethernet_address,
5382                          host_mac_addr))
5383         host_mac_addr_set = 1;
5384       else if (unformat (i, "host-bridge %s", &host_bridge))
5385         host_bridge_set = 1;
5386       else if (unformat (i, "host-ip4-addr %U/%u", unformat_ip4_address,
5387                          &host_ip4_addr, &host_ip4_prefix_len))
5388         host_ip4_prefix_set = 1;
5389       else if (unformat (i, "host-ip6-addr %U/%u", unformat_ip6_address,
5390                          &host_ip6_addr, &host_ip6_prefix_len))
5391         host_ip6_prefix_set = 1;
5392       else if (unformat (i, "host-ip4-gw %U", unformat_ip4_address,
5393                          &host_ip4_gw))
5394         host_ip4_gw_set = 1;
5395       else if (unformat (i, "host-ip6-gw %U", unformat_ip6_address,
5396                          &host_ip6_gw))
5397         host_ip6_gw_set = 1;
5398       else if (unformat (i, "rx-ring-size %u", &rx_ring_sz))
5399         ;
5400       else if (unformat (i, "tx-ring-size %u", &tx_ring_sz))
5401         ;
5402       else if (unformat (i, "host-mtu-size %u", &host_mtu_size))
5403         host_mtu_set = 1;
5404       else if (unformat (i, "no-gso"))
5405         tap_flags &= ~TAP_API_FLAG_GSO;
5406       else if (unformat (i, "gso"))
5407         tap_flags |= TAP_API_FLAG_GSO;
5408       else if (unformat (i, "csum-offload"))
5409         tap_flags |= TAP_API_FLAG_CSUM_OFFLOAD;
5410       else if (unformat (i, "persist"))
5411         tap_flags |= TAP_API_FLAG_PERSIST;
5412       else if (unformat (i, "attach"))
5413         tap_flags |= TAP_API_FLAG_ATTACH;
5414       else if (unformat (i, "tun"))
5415         tap_flags |= TAP_API_FLAG_TUN;
5416       else if (unformat (i, "gro-coalesce"))
5417         tap_flags |= TAP_API_FLAG_GRO_COALESCE;
5418       else if (unformat (i, "packed"))
5419         tap_flags |= TAP_API_FLAG_PACKED;
5420       else if (unformat (i, "in-order"))
5421         tap_flags |= TAP_API_FLAG_IN_ORDER;
5422       else
5423         break;
5424     }
5425
5426   if (vec_len (host_if_name) > 63)
5427     {
5428       errmsg ("tap name too long. ");
5429       return -99;
5430     }
5431   if (vec_len (host_ns) > 63)
5432     {
5433       errmsg ("host name space too long. ");
5434       return -99;
5435     }
5436   if (vec_len (host_bridge) > 63)
5437     {
5438       errmsg ("host bridge name too long. ");
5439       return -99;
5440     }
5441   if (host_ip4_prefix_len > 32)
5442     {
5443       errmsg ("host ip4 prefix length not valid. ");
5444       return -99;
5445     }
5446   if (host_ip6_prefix_len > 128)
5447     {
5448       errmsg ("host ip6 prefix length not valid. ");
5449       return -99;
5450     }
5451   if (!is_pow2 (rx_ring_sz))
5452     {
5453       errmsg ("rx ring size must be power of 2. ");
5454       return -99;
5455     }
5456   if (rx_ring_sz > 32768)
5457     {
5458       errmsg ("rx ring size must be 32768 or lower. ");
5459       return -99;
5460     }
5461   if (!is_pow2 (tx_ring_sz))
5462     {
5463       errmsg ("tx ring size must be power of 2. ");
5464       return -99;
5465     }
5466   if (tx_ring_sz > 32768)
5467     {
5468       errmsg ("tx ring size must be 32768 or lower. ");
5469       return -99;
5470     }
5471   if (host_mtu_set && (host_mtu_size < 64 || host_mtu_size > 65355))
5472     {
5473       errmsg ("host MTU size must be in between 64 and 65355. ");
5474       return -99;
5475     }
5476
5477   /* Construct the API message */
5478   M (TAP_CREATE_V2, mp);
5479
5480   mp->id = ntohl (id);
5481   mp->use_random_mac = random_mac;
5482   mp->num_rx_queues = (u8) num_rx_queues;
5483   mp->tx_ring_sz = ntohs (tx_ring_sz);
5484   mp->rx_ring_sz = ntohs (rx_ring_sz);
5485   mp->host_mtu_set = host_mtu_set;
5486   mp->host_mtu_size = ntohl (host_mtu_size);
5487   mp->host_mac_addr_set = host_mac_addr_set;
5488   mp->host_ip4_prefix_set = host_ip4_prefix_set;
5489   mp->host_ip6_prefix_set = host_ip6_prefix_set;
5490   mp->host_ip4_gw_set = host_ip4_gw_set;
5491   mp->host_ip6_gw_set = host_ip6_gw_set;
5492   mp->tap_flags = ntohl (tap_flags);
5493   mp->host_namespace_set = host_ns_set;
5494   mp->host_if_name_set = host_if_name_set;
5495   mp->host_bridge_set = host_bridge_set;
5496
5497   if (random_mac == 0)
5498     clib_memcpy (mp->mac_address, mac_address, 6);
5499   if (host_mac_addr_set)
5500     clib_memcpy (mp->host_mac_addr, host_mac_addr, 6);
5501   if (host_if_name_set)
5502     clib_memcpy (mp->host_if_name, host_if_name, vec_len (host_if_name));
5503   if (host_ns_set)
5504     clib_memcpy (mp->host_namespace, host_ns, vec_len (host_ns));
5505   if (host_bridge_set)
5506     clib_memcpy (mp->host_bridge, host_bridge, vec_len (host_bridge));
5507   if (host_ip4_prefix_set)
5508     {
5509       clib_memcpy (mp->host_ip4_prefix.address, &host_ip4_addr, 4);
5510       mp->host_ip4_prefix.len = (u8) host_ip4_prefix_len;
5511     }
5512   if (host_ip6_prefix_set)
5513     {
5514       clib_memcpy (mp->host_ip6_prefix.address, &host_ip6_addr, 16);
5515       mp->host_ip6_prefix.len = (u8) host_ip6_prefix_len;
5516     }
5517   if (host_ip4_gw_set)
5518     clib_memcpy (mp->host_ip4_gw, &host_ip4_gw, 4);
5519   if (host_ip6_gw_set)
5520     clib_memcpy (mp->host_ip6_gw, &host_ip6_gw, 16);
5521
5522   vec_free (host_ns);
5523   vec_free (host_if_name);
5524   vec_free (host_bridge);
5525
5526   /* send it... */
5527   S (mp);
5528
5529   /* Wait for a reply... */
5530   W (ret);
5531   return ret;
5532 }
5533
5534 static int
5535 api_tap_delete_v2 (vat_main_t * vam)
5536 {
5537   unformat_input_t *i = vam->input;
5538   vl_api_tap_delete_v2_t *mp;
5539   u32 sw_if_index = ~0;
5540   u8 sw_if_index_set = 0;
5541   int ret;
5542
5543   /* Parse args required to build the message */
5544   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5545     {
5546       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5547         sw_if_index_set = 1;
5548       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5549         sw_if_index_set = 1;
5550       else
5551         break;
5552     }
5553
5554   if (sw_if_index_set == 0)
5555     {
5556       errmsg ("missing vpp interface name. ");
5557       return -99;
5558     }
5559
5560   /* Construct the API message */
5561   M (TAP_DELETE_V2, mp);
5562
5563   mp->sw_if_index = ntohl (sw_if_index);
5564
5565   /* send it... */
5566   S (mp);
5567
5568   /* Wait for a reply... */
5569   W (ret);
5570   return ret;
5571 }
5572
5573 uword
5574 unformat_vlib_pci_addr (unformat_input_t * input, va_list * args)
5575 {
5576   vlib_pci_addr_t *addr = va_arg (*args, vlib_pci_addr_t *);
5577   u32 x[4];
5578
5579   if (!unformat (input, "%x:%x:%x.%x", &x[0], &x[1], &x[2], &x[3]))
5580     return 0;
5581
5582   addr->domain = x[0];
5583   addr->bus = x[1];
5584   addr->slot = x[2];
5585   addr->function = x[3];
5586
5587   return 1;
5588 }
5589
5590 static int
5591 api_virtio_pci_create_v2 (vat_main_t * vam)
5592 {
5593   unformat_input_t *i = vam->input;
5594   vl_api_virtio_pci_create_v2_t *mp;
5595   u8 mac_address[6];
5596   u8 random_mac = 1;
5597   u32 pci_addr = 0;
5598   u64 features = (u64) ~ (0ULL);
5599   u32 virtio_flags = 0;
5600   int ret;
5601
5602   clib_memset (mac_address, 0, sizeof (mac_address));
5603
5604   /* Parse args required to build the message */
5605   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5606     {
5607       if (unformat (i, "hw-addr %U", unformat_ethernet_address, mac_address))
5608         {
5609           random_mac = 0;
5610         }
5611       else if (unformat (i, "pci-addr %U", unformat_vlib_pci_addr, &pci_addr))
5612         ;
5613       else if (unformat (i, "features 0x%llx", &features))
5614         ;
5615       else if (unformat (i, "gso-enabled"))
5616         virtio_flags |= VIRTIO_API_FLAG_GSO;
5617       else if (unformat (i, "csum-offload-enabled"))
5618         virtio_flags |= VIRTIO_API_FLAG_CSUM_OFFLOAD;
5619       else if (unformat (i, "gro-coalesce"))
5620         virtio_flags |= VIRTIO_API_FLAG_GRO_COALESCE;
5621       else if (unformat (i, "packed"))
5622         virtio_flags |= VIRTIO_API_FLAG_PACKED;
5623       else if (unformat (i, "in-order"))
5624         virtio_flags |= VIRTIO_API_FLAG_IN_ORDER;
5625       else if (unformat (i, "buffering"))
5626         virtio_flags |= VIRTIO_API_FLAG_BUFFERING;
5627       else
5628         break;
5629     }
5630
5631   if (pci_addr == 0)
5632     {
5633       errmsg ("pci address must be non zero. ");
5634       return -99;
5635     }
5636
5637   /* Construct the API message */
5638   M (VIRTIO_PCI_CREATE_V2, mp);
5639
5640   mp->use_random_mac = random_mac;
5641
5642   mp->pci_addr.domain = htons (((vlib_pci_addr_t) pci_addr).domain);
5643   mp->pci_addr.bus = ((vlib_pci_addr_t) pci_addr).bus;
5644   mp->pci_addr.slot = ((vlib_pci_addr_t) pci_addr).slot;
5645   mp->pci_addr.function = ((vlib_pci_addr_t) pci_addr).function;
5646
5647   mp->features = clib_host_to_net_u64 (features);
5648   mp->virtio_flags = clib_host_to_net_u32 (virtio_flags);
5649
5650   if (random_mac == 0)
5651     clib_memcpy (mp->mac_address, mac_address, 6);
5652
5653   /* send it... */
5654   S (mp);
5655
5656   /* Wait for a reply... */
5657   W (ret);
5658   return ret;
5659 }
5660
5661 static int
5662 api_virtio_pci_delete (vat_main_t * vam)
5663 {
5664   unformat_input_t *i = vam->input;
5665   vl_api_virtio_pci_delete_t *mp;
5666   u32 sw_if_index = ~0;
5667   u8 sw_if_index_set = 0;
5668   int ret;
5669
5670   /* Parse args required to build the message */
5671   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5672     {
5673       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5674         sw_if_index_set = 1;
5675       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5676         sw_if_index_set = 1;
5677       else
5678         break;
5679     }
5680
5681   if (sw_if_index_set == 0)
5682     {
5683       errmsg ("missing vpp interface name. ");
5684       return -99;
5685     }
5686
5687   /* Construct the API message */
5688   M (VIRTIO_PCI_DELETE, mp);
5689
5690   mp->sw_if_index = htonl (sw_if_index);
5691
5692   /* send it... */
5693   S (mp);
5694
5695   /* Wait for a reply... */
5696   W (ret);
5697   return ret;
5698 }
5699
5700 static int
5701 api_bond_create (vat_main_t * vam)
5702 {
5703   unformat_input_t *i = vam->input;
5704   vl_api_bond_create_t *mp;
5705   u8 mac_address[6];
5706   u8 custom_mac = 0;
5707   int ret;
5708   u8 mode;
5709   u8 lb;
5710   u8 mode_is_set = 0;
5711   u32 id = ~0;
5712   u8 numa_only = 0;
5713
5714   clib_memset (mac_address, 0, sizeof (mac_address));
5715   lb = BOND_LB_L2;
5716
5717   /* Parse args required to build the message */
5718   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5719     {
5720       if (unformat (i, "mode %U", unformat_bond_mode, &mode))
5721         mode_is_set = 1;
5722       else if (((mode == BOND_MODE_LACP) || (mode == BOND_MODE_XOR))
5723                && unformat (i, "lb %U", unformat_bond_load_balance, &lb))
5724         ;
5725       else if (unformat (i, "hw-addr %U", unformat_ethernet_address,
5726                          mac_address))
5727         custom_mac = 1;
5728       else if (unformat (i, "numa-only"))
5729         numa_only = 1;
5730       else if (unformat (i, "id %u", &id))
5731         ;
5732       else
5733         break;
5734     }
5735
5736   if (mode_is_set == 0)
5737     {
5738       errmsg ("Missing bond mode. ");
5739       return -99;
5740     }
5741
5742   /* Construct the API message */
5743   M (BOND_CREATE, mp);
5744
5745   mp->use_custom_mac = custom_mac;
5746
5747   mp->mode = htonl (mode);
5748   mp->lb = htonl (lb);
5749   mp->id = htonl (id);
5750   mp->numa_only = numa_only;
5751
5752   if (custom_mac)
5753     clib_memcpy (mp->mac_address, mac_address, 6);
5754
5755   /* send it... */
5756   S (mp);
5757
5758   /* Wait for a reply... */
5759   W (ret);
5760   return ret;
5761 }
5762
5763 static int
5764 api_bond_create2 (vat_main_t * vam)
5765 {
5766   unformat_input_t *i = vam->input;
5767   vl_api_bond_create2_t *mp;
5768   u8 mac_address[6];
5769   u8 custom_mac = 0;
5770   int ret;
5771   u8 mode;
5772   u8 lb;
5773   u8 mode_is_set = 0;
5774   u32 id = ~0;
5775   u8 numa_only = 0;
5776   u8 gso = 0;
5777
5778   clib_memset (mac_address, 0, sizeof (mac_address));
5779   lb = BOND_LB_L2;
5780
5781   /* Parse args required to build the message */
5782   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5783     {
5784       if (unformat (i, "mode %U", unformat_bond_mode, &mode))
5785         mode_is_set = 1;
5786       else if (((mode == BOND_MODE_LACP) || (mode == BOND_MODE_XOR))
5787                && unformat (i, "lb %U", unformat_bond_load_balance, &lb))
5788         ;
5789       else if (unformat (i, "hw-addr %U", unformat_ethernet_address,
5790                          mac_address))
5791         custom_mac = 1;
5792       else if (unformat (i, "numa-only"))
5793         numa_only = 1;
5794       else if (unformat (i, "gso"))
5795         gso = 1;
5796       else if (unformat (i, "id %u", &id))
5797         ;
5798       else
5799         break;
5800     }
5801
5802   if (mode_is_set == 0)
5803     {
5804       errmsg ("Missing bond mode. ");
5805       return -99;
5806     }
5807
5808   /* Construct the API message */
5809   M (BOND_CREATE2, mp);
5810
5811   mp->use_custom_mac = custom_mac;
5812
5813   mp->mode = htonl (mode);
5814   mp->lb = htonl (lb);
5815   mp->id = htonl (id);
5816   mp->numa_only = numa_only;
5817   mp->enable_gso = gso;
5818
5819   if (custom_mac)
5820     clib_memcpy (mp->mac_address, mac_address, 6);
5821
5822   /* send it... */
5823   S (mp);
5824
5825   /* Wait for a reply... */
5826   W (ret);
5827   return ret;
5828 }
5829
5830 static int
5831 api_bond_delete (vat_main_t * vam)
5832 {
5833   unformat_input_t *i = vam->input;
5834   vl_api_bond_delete_t *mp;
5835   u32 sw_if_index = ~0;
5836   u8 sw_if_index_set = 0;
5837   int ret;
5838
5839   /* Parse args required to build the message */
5840   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5841     {
5842       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5843         sw_if_index_set = 1;
5844       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5845         sw_if_index_set = 1;
5846       else
5847         break;
5848     }
5849
5850   if (sw_if_index_set == 0)
5851     {
5852       errmsg ("missing vpp interface name. ");
5853       return -99;
5854     }
5855
5856   /* Construct the API message */
5857   M (BOND_DELETE, mp);
5858
5859   mp->sw_if_index = ntohl (sw_if_index);
5860
5861   /* send it... */
5862   S (mp);
5863
5864   /* Wait for a reply... */
5865   W (ret);
5866   return ret;
5867 }
5868
5869 static int
5870 api_bond_add_member (vat_main_t * vam)
5871 {
5872   unformat_input_t *i = vam->input;
5873   vl_api_bond_add_member_t *mp;
5874   u32 bond_sw_if_index;
5875   int ret;
5876   u8 is_passive;
5877   u8 is_long_timeout;
5878   u32 bond_sw_if_index_is_set = 0;
5879   u32 sw_if_index;
5880   u8 sw_if_index_is_set = 0;
5881
5882   /* Parse args required to build the message */
5883   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5884     {
5885       if (unformat (i, "sw_if_index %d", &sw_if_index))
5886         sw_if_index_is_set = 1;
5887       else if (unformat (i, "bond %u", &bond_sw_if_index))
5888         bond_sw_if_index_is_set = 1;
5889       else if (unformat (i, "passive %d", &is_passive))
5890         ;
5891       else if (unformat (i, "long-timeout %d", &is_long_timeout))
5892         ;
5893       else
5894         break;
5895     }
5896
5897   if (bond_sw_if_index_is_set == 0)
5898     {
5899       errmsg ("Missing bond sw_if_index. ");
5900       return -99;
5901     }
5902   if (sw_if_index_is_set == 0)
5903     {
5904       errmsg ("Missing member sw_if_index. ");
5905       return -99;
5906     }
5907
5908   /* Construct the API message */
5909   M (BOND_ADD_MEMBER, mp);
5910
5911   mp->bond_sw_if_index = ntohl (bond_sw_if_index);
5912   mp->sw_if_index = ntohl (sw_if_index);
5913   mp->is_long_timeout = is_long_timeout;
5914   mp->is_passive = is_passive;
5915
5916   /* send it... */
5917   S (mp);
5918
5919   /* Wait for a reply... */
5920   W (ret);
5921   return ret;
5922 }
5923
5924 static int
5925 api_bond_detach_member (vat_main_t * vam)
5926 {
5927   unformat_input_t *i = vam->input;
5928   vl_api_bond_detach_member_t *mp;
5929   u32 sw_if_index = ~0;
5930   u8 sw_if_index_set = 0;
5931   int ret;
5932
5933   /* Parse args required to build the message */
5934   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5935     {
5936       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5937         sw_if_index_set = 1;
5938       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5939         sw_if_index_set = 1;
5940       else
5941         break;
5942     }
5943
5944   if (sw_if_index_set == 0)
5945     {
5946       errmsg ("missing vpp interface name. ");
5947       return -99;
5948     }
5949
5950   /* Construct the API message */
5951   M (BOND_DETACH_MEMBER, mp);
5952
5953   mp->sw_if_index = ntohl (sw_if_index);
5954
5955   /* send it... */
5956   S (mp);
5957
5958   /* Wait for a reply... */
5959   W (ret);
5960   return ret;
5961 }
5962
5963 static int
5964 api_ip_table_add_del (vat_main_t * vam)
5965 {
5966   unformat_input_t *i = vam->input;
5967   vl_api_ip_table_add_del_t *mp;
5968   u32 table_id = ~0;
5969   u8 is_ipv6 = 0;
5970   u8 is_add = 1;
5971   int ret = 0;
5972
5973   /* Parse args required to build the message */
5974   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5975     {
5976       if (unformat (i, "ipv6"))
5977         is_ipv6 = 1;
5978       else if (unformat (i, "del"))
5979         is_add = 0;
5980       else if (unformat (i, "add"))
5981         is_add = 1;
5982       else if (unformat (i, "table %d", &table_id))
5983         ;
5984       else
5985         {
5986           clib_warning ("parse error '%U'", format_unformat_error, i);
5987           return -99;
5988         }
5989     }
5990
5991   if (~0 == table_id)
5992     {
5993       errmsg ("missing table-ID");
5994       return -99;
5995     }
5996
5997   /* Construct the API message */
5998   M (IP_TABLE_ADD_DEL, mp);
5999
6000   mp->table.table_id = ntohl (table_id);
6001   mp->table.is_ip6 = is_ipv6;
6002   mp->is_add = is_add;
6003
6004   /* send it... */
6005   S (mp);
6006
6007   /* Wait for a reply... */
6008   W (ret);
6009
6010   return ret;
6011 }
6012
6013 uword
6014 unformat_fib_path (unformat_input_t * input, va_list * args)
6015 {
6016   vat_main_t *vam = va_arg (*args, vat_main_t *);
6017   vl_api_fib_path_t *path = va_arg (*args, vl_api_fib_path_t *);
6018   u32 weight, preference;
6019   mpls_label_t out_label;
6020
6021   clib_memset (path, 0, sizeof (*path));
6022   path->weight = 1;
6023   path->sw_if_index = ~0;
6024   path->rpf_id = ~0;
6025   path->n_labels = 0;
6026
6027   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6028     {
6029       if (unformat (input, "%U %U",
6030                     unformat_vl_api_ip4_address,
6031                     &path->nh.address.ip4,
6032                     api_unformat_sw_if_index, vam, &path->sw_if_index))
6033         {
6034           path->proto = FIB_API_PATH_NH_PROTO_IP4;
6035         }
6036       else if (unformat (input, "%U %U",
6037                          unformat_vl_api_ip6_address,
6038                          &path->nh.address.ip6,
6039                          api_unformat_sw_if_index, vam, &path->sw_if_index))
6040         {
6041           path->proto = FIB_API_PATH_NH_PROTO_IP6;
6042         }
6043       else if (unformat (input, "weight %u", &weight))
6044         {
6045           path->weight = weight;
6046         }
6047       else if (unformat (input, "preference %u", &preference))
6048         {
6049           path->preference = preference;
6050         }
6051       else if (unformat (input, "%U next-hop-table %d",
6052                          unformat_vl_api_ip4_address,
6053                          &path->nh.address.ip4, &path->table_id))
6054         {
6055           path->proto = FIB_API_PATH_NH_PROTO_IP4;
6056         }
6057       else if (unformat (input, "%U next-hop-table %d",
6058                          unformat_vl_api_ip6_address,
6059                          &path->nh.address.ip6, &path->table_id))
6060         {
6061           path->proto = FIB_API_PATH_NH_PROTO_IP6;
6062         }
6063       else if (unformat (input, "%U",
6064                          unformat_vl_api_ip4_address, &path->nh.address.ip4))
6065         {
6066           /*
6067            * the recursive next-hops are by default in the default table
6068            */
6069           path->table_id = 0;
6070           path->sw_if_index = ~0;
6071           path->proto = FIB_API_PATH_NH_PROTO_IP4;
6072         }
6073       else if (unformat (input, "%U",
6074                          unformat_vl_api_ip6_address, &path->nh.address.ip6))
6075         {
6076           /*
6077            * the recursive next-hops are by default in the default table
6078            */
6079           path->table_id = 0;
6080           path->sw_if_index = ~0;
6081           path->proto = FIB_API_PATH_NH_PROTO_IP6;
6082         }
6083       else if (unformat (input, "resolve-via-host"))
6084         {
6085           path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_HOST;
6086         }
6087       else if (unformat (input, "resolve-via-attached"))
6088         {
6089           path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_ATTACHED;
6090         }
6091       else if (unformat (input, "ip4-lookup-in-table %d", &path->table_id))
6092         {
6093           path->type = FIB_API_PATH_TYPE_LOCAL;
6094           path->sw_if_index = ~0;
6095           path->proto = FIB_API_PATH_NH_PROTO_IP4;
6096         }
6097       else if (unformat (input, "ip6-lookup-in-table %d", &path->table_id))
6098         {
6099           path->type = FIB_API_PATH_TYPE_LOCAL;
6100           path->sw_if_index = ~0;
6101           path->proto = FIB_API_PATH_NH_PROTO_IP6;
6102         }
6103       else if (unformat (input, "sw_if_index %d", &path->sw_if_index))
6104         ;
6105       else if (unformat (input, "via-label %d", &path->nh.via_label))
6106         {
6107           path->proto = FIB_API_PATH_NH_PROTO_MPLS;
6108           path->sw_if_index = ~0;
6109         }
6110       else if (unformat (input, "l2-input-on %d", &path->sw_if_index))
6111         {
6112           path->proto = FIB_API_PATH_NH_PROTO_ETHERNET;
6113           path->type = FIB_API_PATH_TYPE_INTERFACE_RX;
6114         }
6115       else if (unformat (input, "local"))
6116         {
6117           path->type = FIB_API_PATH_TYPE_LOCAL;
6118         }
6119       else if (unformat (input, "out-labels"))
6120         {
6121           while (unformat (input, "%d", &out_label))
6122             {
6123               path->label_stack[path->n_labels].label = out_label;
6124               path->label_stack[path->n_labels].is_uniform = 0;
6125               path->label_stack[path->n_labels].ttl = 64;
6126               path->n_labels++;
6127             }
6128         }
6129       else if (unformat (input, "via"))
6130         {
6131           /* new path, back up and return */
6132           unformat_put_input (input);
6133           unformat_put_input (input);
6134           unformat_put_input (input);
6135           unformat_put_input (input);
6136           break;
6137         }
6138       else
6139         {
6140           return (0);
6141         }
6142     }
6143
6144   path->proto = ntohl (path->proto);
6145   path->type = ntohl (path->type);
6146   path->flags = ntohl (path->flags);
6147   path->table_id = ntohl (path->table_id);
6148   path->sw_if_index = ntohl (path->sw_if_index);
6149
6150   return (1);
6151 }
6152
6153 static int
6154 api_ip_route_add_del (vat_main_t * vam)
6155 {
6156   unformat_input_t *i = vam->input;
6157   vl_api_ip_route_add_del_t *mp;
6158   u32 vrf_id = 0;
6159   u8 is_add = 1;
6160   u8 is_multipath = 0;
6161   u8 prefix_set = 0;
6162   u8 path_count = 0;
6163   vl_api_prefix_t pfx = { };
6164   vl_api_fib_path_t paths[8];
6165   int count = 1;
6166   int j;
6167   f64 before = 0;
6168   u32 random_add_del = 0;
6169   u32 *random_vector = 0;
6170   u32 random_seed = 0xdeaddabe;
6171
6172   /* Parse args required to build the message */
6173   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6174     {
6175       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
6176         prefix_set = 1;
6177       else if (unformat (i, "del"))
6178         is_add = 0;
6179       else if (unformat (i, "add"))
6180         is_add = 1;
6181       else if (unformat (i, "vrf %d", &vrf_id))
6182         ;
6183       else if (unformat (i, "count %d", &count))
6184         ;
6185       else if (unformat (i, "random"))
6186         random_add_del = 1;
6187       else if (unformat (i, "multipath"))
6188         is_multipath = 1;
6189       else if (unformat (i, "seed %d", &random_seed))
6190         ;
6191       else
6192         if (unformat
6193             (i, "via %U", unformat_fib_path, vam, &paths[path_count]))
6194         {
6195           path_count++;
6196           if (8 == path_count)
6197             {
6198               errmsg ("max 8 paths");
6199               return -99;
6200             }
6201         }
6202       else
6203         {
6204           clib_warning ("parse error '%U'", format_unformat_error, i);
6205           return -99;
6206         }
6207     }
6208
6209   if (!path_count)
6210     {
6211       errmsg ("specify a path; via ...");
6212       return -99;
6213     }
6214   if (prefix_set == 0)
6215     {
6216       errmsg ("missing prefix");
6217       return -99;
6218     }
6219
6220   /* Generate a pile of unique, random routes */
6221   if (random_add_del)
6222     {
6223       ip4_address_t *i = (ip4_address_t *) & paths[0].nh.address.ip4;
6224       u32 this_random_address;
6225       uword *random_hash;
6226
6227       random_hash = hash_create (count, sizeof (uword));
6228
6229       hash_set (random_hash, i->as_u32, 1);
6230       for (j = 0; j <= count; j++)
6231         {
6232           do
6233             {
6234               this_random_address = random_u32 (&random_seed);
6235               this_random_address =
6236                 clib_host_to_net_u32 (this_random_address);
6237             }
6238           while (hash_get (random_hash, this_random_address));
6239           vec_add1 (random_vector, this_random_address);
6240           hash_set (random_hash, this_random_address, 1);
6241         }
6242       hash_free (random_hash);
6243       set_ip4_address (&pfx.address, random_vector[0]);
6244     }
6245
6246   if (count > 1)
6247     {
6248       /* Turn on async mode */
6249       vam->async_mode = 1;
6250       vam->async_errors = 0;
6251       before = vat_time_now (vam);
6252     }
6253
6254   for (j = 0; j < count; j++)
6255     {
6256       /* Construct the API message */
6257       M2 (IP_ROUTE_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
6258
6259       mp->is_add = is_add;
6260       mp->is_multipath = is_multipath;
6261
6262       clib_memcpy (&mp->route.prefix, &pfx, sizeof (pfx));
6263       mp->route.table_id = ntohl (vrf_id);
6264       mp->route.n_paths = path_count;
6265
6266       clib_memcpy (&mp->route.paths, &paths, sizeof (paths[0]) * path_count);
6267
6268       if (random_add_del)
6269         set_ip4_address (&pfx.address, random_vector[j + 1]);
6270       else
6271         increment_address (&pfx.address);
6272       /* send it... */
6273       S (mp);
6274       /* If we receive SIGTERM, stop now... */
6275       if (vam->do_exit)
6276         break;
6277     }
6278
6279   /* When testing multiple add/del ops, use a control-ping to sync */
6280   if (count > 1)
6281     {
6282       vl_api_control_ping_t *mp_ping;
6283       f64 after;
6284       f64 timeout;
6285
6286       /* Shut off async mode */
6287       vam->async_mode = 0;
6288
6289       MPING (CONTROL_PING, mp_ping);
6290       S (mp_ping);
6291
6292       timeout = vat_time_now (vam) + 1.0;
6293       while (vat_time_now (vam) < timeout)
6294         if (vam->result_ready == 1)
6295           goto out;
6296       vam->retval = -99;
6297
6298     out:
6299       if (vam->retval == -99)
6300         errmsg ("timeout");
6301
6302       if (vam->async_errors > 0)
6303         {
6304           errmsg ("%d asynchronous errors", vam->async_errors);
6305           vam->retval = -98;
6306         }
6307       vam->async_errors = 0;
6308       after = vat_time_now (vam);
6309
6310       /* slim chance, but we might have eaten SIGTERM on the first iteration */
6311       if (j > 0)
6312         count = j;
6313
6314       print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec",
6315              count, after - before, count / (after - before));
6316     }
6317   else
6318     {
6319       int ret;
6320
6321       /* Wait for a reply... */
6322       W (ret);
6323       return ret;
6324     }
6325
6326   /* Return the good/bad news */
6327   return (vam->retval);
6328 }
6329
6330 static int
6331 api_ip_mroute_add_del (vat_main_t * vam)
6332 {
6333   unformat_input_t *i = vam->input;
6334   u8 path_set = 0, prefix_set = 0, is_add = 1;
6335   vl_api_ip_mroute_add_del_t *mp;
6336   mfib_entry_flags_t eflags = 0;
6337   vl_api_mfib_path_t path;
6338   vl_api_mprefix_t pfx = { };
6339   u32 vrf_id = 0;
6340   int ret;
6341
6342   /* Parse args required to build the message */
6343   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6344     {
6345       if (unformat (i, "%U", unformat_vl_api_mprefix, &pfx))
6346         {
6347           prefix_set = 1;
6348           pfx.grp_address_length = htons (pfx.grp_address_length);
6349         }
6350       else if (unformat (i, "del"))
6351         is_add = 0;
6352       else if (unformat (i, "add"))
6353         is_add = 1;
6354       else if (unformat (i, "vrf %d", &vrf_id))
6355         ;
6356       else if (unformat (i, "%U", unformat_mfib_itf_flags, &path.itf_flags))
6357         path.itf_flags = htonl (path.itf_flags);
6358       else if (unformat (i, "%U", unformat_mfib_entry_flags, &eflags))
6359         ;
6360       else if (unformat (i, "via %U", unformat_fib_path, vam, &path.path))
6361         path_set = 1;
6362       else
6363         {
6364           clib_warning ("parse error '%U'", format_unformat_error, i);
6365           return -99;
6366         }
6367     }
6368
6369   if (prefix_set == 0)
6370     {
6371       errmsg ("missing addresses\n");
6372       return -99;
6373     }
6374   if (path_set == 0)
6375     {
6376       errmsg ("missing path\n");
6377       return -99;
6378     }
6379
6380   /* Construct the API message */
6381   M (IP_MROUTE_ADD_DEL, mp);
6382
6383   mp->is_add = is_add;
6384   mp->is_multipath = 1;
6385
6386   clib_memcpy (&mp->route.prefix, &pfx, sizeof (pfx));
6387   mp->route.table_id = htonl (vrf_id);
6388   mp->route.n_paths = 1;
6389   mp->route.entry_flags = htonl (eflags);
6390
6391   clib_memcpy (&mp->route.paths, &path, sizeof (path));
6392
6393   /* send it... */
6394   S (mp);
6395   /* Wait for a reply... */
6396   W (ret);
6397   return ret;
6398 }
6399
6400 static int
6401 api_mpls_table_add_del (vat_main_t * vam)
6402 {
6403   unformat_input_t *i = vam->input;
6404   vl_api_mpls_table_add_del_t *mp;
6405   u32 table_id = ~0;
6406   u8 is_add = 1;
6407   int ret = 0;
6408
6409   /* Parse args required to build the message */
6410   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6411     {
6412       if (unformat (i, "table %d", &table_id))
6413         ;
6414       else if (unformat (i, "del"))
6415         is_add = 0;
6416       else if (unformat (i, "add"))
6417         is_add = 1;
6418       else
6419         {
6420           clib_warning ("parse error '%U'", format_unformat_error, i);
6421           return -99;
6422         }
6423     }
6424
6425   if (~0 == table_id)
6426     {
6427       errmsg ("missing table-ID");
6428       return -99;
6429     }
6430
6431   /* Construct the API message */
6432   M (MPLS_TABLE_ADD_DEL, mp);
6433
6434   mp->mt_table.mt_table_id = ntohl (table_id);
6435   mp->mt_is_add = is_add;
6436
6437   /* send it... */
6438   S (mp);
6439
6440   /* Wait for a reply... */
6441   W (ret);
6442
6443   return ret;
6444 }
6445
6446 static int
6447 api_mpls_route_add_del (vat_main_t * vam)
6448 {
6449   u8 is_add = 1, path_count = 0, is_multipath = 0, is_eos = 0;
6450   mpls_label_t local_label = MPLS_LABEL_INVALID;
6451   unformat_input_t *i = vam->input;
6452   vl_api_mpls_route_add_del_t *mp;
6453   vl_api_fib_path_t paths[8];
6454   int count = 1, j;
6455   f64 before = 0;
6456
6457   /* Parse args required to build the message */
6458   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6459     {
6460       if (unformat (i, "%d", &local_label))
6461         ;
6462       else if (unformat (i, "eos"))
6463         is_eos = 1;
6464       else if (unformat (i, "non-eos"))
6465         is_eos = 0;
6466       else if (unformat (i, "del"))
6467         is_add = 0;
6468       else if (unformat (i, "add"))
6469         is_add = 1;
6470       else if (unformat (i, "multipath"))
6471         is_multipath = 1;
6472       else if (unformat (i, "count %d", &count))
6473         ;
6474       else
6475         if (unformat
6476             (i, "via %U", unformat_fib_path, vam, &paths[path_count]))
6477         {
6478           path_count++;
6479           if (8 == path_count)
6480             {
6481               errmsg ("max 8 paths");
6482               return -99;
6483             }
6484         }
6485       else
6486         {
6487           clib_warning ("parse error '%U'", format_unformat_error, i);
6488           return -99;
6489         }
6490     }
6491
6492   if (!path_count)
6493     {
6494       errmsg ("specify a path; via ...");
6495       return -99;
6496     }
6497
6498   if (MPLS_LABEL_INVALID == local_label)
6499     {
6500       errmsg ("missing label");
6501       return -99;
6502     }
6503
6504   if (count > 1)
6505     {
6506       /* Turn on async mode */
6507       vam->async_mode = 1;
6508       vam->async_errors = 0;
6509       before = vat_time_now (vam);
6510     }
6511
6512   for (j = 0; j < count; j++)
6513     {
6514       /* Construct the API message */
6515       M2 (MPLS_ROUTE_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
6516
6517       mp->mr_is_add = is_add;
6518       mp->mr_is_multipath = is_multipath;
6519
6520       mp->mr_route.mr_label = local_label;
6521       mp->mr_route.mr_eos = is_eos;
6522       mp->mr_route.mr_table_id = 0;
6523       mp->mr_route.mr_n_paths = path_count;
6524
6525       clib_memcpy (&mp->mr_route.mr_paths, paths,
6526                    sizeof (paths[0]) * path_count);
6527
6528       local_label++;
6529
6530       /* send it... */
6531       S (mp);
6532       /* If we receive SIGTERM, stop now... */
6533       if (vam->do_exit)
6534         break;
6535     }
6536
6537   /* When testing multiple add/del ops, use a control-ping to sync */
6538   if (count > 1)
6539     {
6540       vl_api_control_ping_t *mp_ping;
6541       f64 after;
6542       f64 timeout;
6543
6544       /* Shut off async mode */
6545       vam->async_mode = 0;
6546
6547       MPING (CONTROL_PING, mp_ping);
6548       S (mp_ping);
6549
6550       timeout = vat_time_now (vam) + 1.0;
6551       while (vat_time_now (vam) < timeout)
6552         if (vam->result_ready == 1)
6553           goto out;
6554       vam->retval = -99;
6555
6556     out:
6557       if (vam->retval == -99)
6558         errmsg ("timeout");
6559
6560       if (vam->async_errors > 0)
6561         {
6562           errmsg ("%d asynchronous errors", vam->async_errors);
6563           vam->retval = -98;
6564         }
6565       vam->async_errors = 0;
6566       after = vat_time_now (vam);
6567
6568       /* slim chance, but we might have eaten SIGTERM on the first iteration */
6569       if (j > 0)
6570         count = j;
6571
6572       print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec",
6573              count, after - before, count / (after - before));
6574     }
6575   else
6576     {
6577       int ret;
6578
6579       /* Wait for a reply... */
6580       W (ret);
6581       return ret;
6582     }
6583
6584   /* Return the good/bad news */
6585   return (vam->retval);
6586   return (0);
6587 }
6588
6589 static int
6590 api_mpls_ip_bind_unbind (vat_main_t * vam)
6591 {
6592   unformat_input_t *i = vam->input;
6593   vl_api_mpls_ip_bind_unbind_t *mp;
6594   u32 ip_table_id = 0;
6595   u8 is_bind = 1;
6596   vl_api_prefix_t pfx;
6597   u8 prefix_set = 0;
6598   mpls_label_t local_label = MPLS_LABEL_INVALID;
6599   int ret;
6600
6601   /* Parse args required to build the message */
6602   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6603     {
6604       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
6605         prefix_set = 1;
6606       else if (unformat (i, "%d", &local_label))
6607         ;
6608       else if (unformat (i, "table-id %d", &ip_table_id))
6609         ;
6610       else if (unformat (i, "unbind"))
6611         is_bind = 0;
6612       else if (unformat (i, "bind"))
6613         is_bind = 1;
6614       else
6615         {
6616           clib_warning ("parse error '%U'", format_unformat_error, i);
6617           return -99;
6618         }
6619     }
6620
6621   if (!prefix_set)
6622     {
6623       errmsg ("IP prefix not set");
6624       return -99;
6625     }
6626
6627   if (MPLS_LABEL_INVALID == local_label)
6628     {
6629       errmsg ("missing label");
6630       return -99;
6631     }
6632
6633   /* Construct the API message */
6634   M (MPLS_IP_BIND_UNBIND, mp);
6635
6636   mp->mb_is_bind = is_bind;
6637   mp->mb_ip_table_id = ntohl (ip_table_id);
6638   mp->mb_mpls_table_id = 0;
6639   mp->mb_label = ntohl (local_label);
6640   clib_memcpy (&mp->mb_prefix, &pfx, sizeof (pfx));
6641
6642   /* send it... */
6643   S (mp);
6644
6645   /* Wait for a reply... */
6646   W (ret);
6647   return ret;
6648   return (0);
6649 }
6650
6651 static int
6652 api_sr_mpls_policy_add (vat_main_t * vam)
6653 {
6654   unformat_input_t *i = vam->input;
6655   vl_api_sr_mpls_policy_add_t *mp;
6656   u32 bsid = 0;
6657   u32 weight = 1;
6658   u8 type = 0;
6659   u8 n_segments = 0;
6660   u32 sid;
6661   u32 *segments = NULL;
6662   int ret;
6663
6664   /* Parse args required to build the message */
6665   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6666     {
6667       if (unformat (i, "bsid %d", &bsid))
6668         ;
6669       else if (unformat (i, "weight %d", &weight))
6670         ;
6671       else if (unformat (i, "spray"))
6672         type = 1;
6673       else if (unformat (i, "next %d", &sid))
6674         {
6675           n_segments += 1;
6676           vec_add1 (segments, htonl (sid));
6677         }
6678       else
6679         {
6680           clib_warning ("parse error '%U'", format_unformat_error, i);
6681           return -99;
6682         }
6683     }
6684
6685   if (bsid == 0)
6686     {
6687       errmsg ("bsid not set");
6688       return -99;
6689     }
6690
6691   if (n_segments == 0)
6692     {
6693       errmsg ("no sid in segment stack");
6694       return -99;
6695     }
6696
6697   /* Construct the API message */
6698   M2 (SR_MPLS_POLICY_ADD, mp, sizeof (u32) * n_segments);
6699
6700   mp->bsid = htonl (bsid);
6701   mp->weight = htonl (weight);
6702   mp->is_spray = type;
6703   mp->n_segments = n_segments;
6704   memcpy (mp->segments, segments, sizeof (u32) * n_segments);
6705   vec_free (segments);
6706
6707   /* send it... */
6708   S (mp);
6709
6710   /* Wait for a reply... */
6711   W (ret);
6712   return ret;
6713 }
6714
6715 static int
6716 api_sr_mpls_policy_del (vat_main_t * vam)
6717 {
6718   unformat_input_t *i = vam->input;
6719   vl_api_sr_mpls_policy_del_t *mp;
6720   u32 bsid = 0;
6721   int ret;
6722
6723   /* Parse args required to build the message */
6724   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6725     {
6726       if (unformat (i, "bsid %d", &bsid))
6727         ;
6728       else
6729         {
6730           clib_warning ("parse error '%U'", format_unformat_error, i);
6731           return -99;
6732         }
6733     }
6734
6735   if (bsid == 0)
6736     {
6737       errmsg ("bsid not set");
6738       return -99;
6739     }
6740
6741   /* Construct the API message */
6742   M (SR_MPLS_POLICY_DEL, mp);
6743
6744   mp->bsid = htonl (bsid);
6745
6746   /* send it... */
6747   S (mp);
6748
6749   /* Wait for a reply... */
6750   W (ret);
6751   return ret;
6752 }
6753
6754 static int
6755 api_bier_table_add_del (vat_main_t * vam)
6756 {
6757   unformat_input_t *i = vam->input;
6758   vl_api_bier_table_add_del_t *mp;
6759   u8 is_add = 1;
6760   u32 set = 0, sub_domain = 0, hdr_len = 3;
6761   mpls_label_t local_label = MPLS_LABEL_INVALID;
6762   int ret;
6763
6764   /* Parse args required to build the message */
6765   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6766     {
6767       if (unformat (i, "sub-domain %d", &sub_domain))
6768         ;
6769       else if (unformat (i, "set %d", &set))
6770         ;
6771       else if (unformat (i, "label %d", &local_label))
6772         ;
6773       else if (unformat (i, "hdr-len %d", &hdr_len))
6774         ;
6775       else if (unformat (i, "add"))
6776         is_add = 1;
6777       else if (unformat (i, "del"))
6778         is_add = 0;
6779       else
6780         {
6781           clib_warning ("parse error '%U'", format_unformat_error, i);
6782           return -99;
6783         }
6784     }
6785
6786   if (MPLS_LABEL_INVALID == local_label)
6787     {
6788       errmsg ("missing label\n");
6789       return -99;
6790     }
6791
6792   /* Construct the API message */
6793   M (BIER_TABLE_ADD_DEL, mp);
6794
6795   mp->bt_is_add = is_add;
6796   mp->bt_label = ntohl (local_label);
6797   mp->bt_tbl_id.bt_set = set;
6798   mp->bt_tbl_id.bt_sub_domain = sub_domain;
6799   mp->bt_tbl_id.bt_hdr_len_id = hdr_len;
6800
6801   /* send it... */
6802   S (mp);
6803
6804   /* Wait for a reply... */
6805   W (ret);
6806
6807   return (ret);
6808 }
6809
6810 static int
6811 api_bier_route_add_del (vat_main_t * vam)
6812 {
6813   unformat_input_t *i = vam->input;
6814   vl_api_bier_route_add_del_t *mp;
6815   u8 is_add = 1;
6816   u32 set = 0, sub_domain = 0, hdr_len = 3, bp = 0;
6817   ip4_address_t v4_next_hop_address;
6818   ip6_address_t v6_next_hop_address;
6819   u8 next_hop_set = 0;
6820   u8 next_hop_proto_is_ip4 = 1;
6821   mpls_label_t next_hop_out_label = MPLS_LABEL_INVALID;
6822   int ret;
6823
6824   /* Parse args required to build the message */
6825   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6826     {
6827       if (unformat (i, "%U", unformat_ip4_address, &v4_next_hop_address))
6828         {
6829           next_hop_proto_is_ip4 = 1;
6830           next_hop_set = 1;
6831         }
6832       else if (unformat (i, "%U", unformat_ip6_address, &v6_next_hop_address))
6833         {
6834           next_hop_proto_is_ip4 = 0;
6835           next_hop_set = 1;
6836         }
6837       if (unformat (i, "sub-domain %d", &sub_domain))
6838         ;
6839       else if (unformat (i, "set %d", &set))
6840         ;
6841       else if (unformat (i, "hdr-len %d", &hdr_len))
6842         ;
6843       else if (unformat (i, "bp %d", &bp))
6844         ;
6845       else if (unformat (i, "add"))
6846         is_add = 1;
6847       else if (unformat (i, "del"))
6848         is_add = 0;
6849       else if (unformat (i, "out-label %d", &next_hop_out_label))
6850         ;
6851       else
6852         {
6853           clib_warning ("parse error '%U'", format_unformat_error, i);
6854           return -99;
6855         }
6856     }
6857
6858   if (!next_hop_set || (MPLS_LABEL_INVALID == next_hop_out_label))
6859     {
6860       errmsg ("next hop / label set\n");
6861       return -99;
6862     }
6863   if (0 == bp)
6864     {
6865       errmsg ("bit=position not set\n");
6866       return -99;
6867     }
6868
6869   /* Construct the API message */
6870   M2 (BIER_ROUTE_ADD_DEL, mp, sizeof (vl_api_fib_path_t));
6871
6872   mp->br_is_add = is_add;
6873   mp->br_route.br_tbl_id.bt_set = set;
6874   mp->br_route.br_tbl_id.bt_sub_domain = sub_domain;
6875   mp->br_route.br_tbl_id.bt_hdr_len_id = hdr_len;
6876   mp->br_route.br_bp = ntohs (bp);
6877   mp->br_route.br_n_paths = 1;
6878   mp->br_route.br_paths[0].n_labels = 1;
6879   mp->br_route.br_paths[0].label_stack[0].label = ntohl (next_hop_out_label);
6880   mp->br_route.br_paths[0].proto = (next_hop_proto_is_ip4 ?
6881                                     FIB_API_PATH_NH_PROTO_IP4 :
6882                                     FIB_API_PATH_NH_PROTO_IP6);
6883
6884   if (next_hop_proto_is_ip4)
6885     {
6886       clib_memcpy (&mp->br_route.br_paths[0].nh.address.ip4,
6887                    &v4_next_hop_address, sizeof (v4_next_hop_address));
6888     }
6889   else
6890     {
6891       clib_memcpy (&mp->br_route.br_paths[0].nh.address.ip6,
6892                    &v6_next_hop_address, sizeof (v6_next_hop_address));
6893     }
6894
6895   /* send it... */
6896   S (mp);
6897
6898   /* Wait for a reply... */
6899   W (ret);
6900
6901   return (ret);
6902 }
6903
6904 static int
6905 api_mpls_tunnel_add_del (vat_main_t * vam)
6906 {
6907   unformat_input_t *i = vam->input;
6908   vl_api_mpls_tunnel_add_del_t *mp;
6909
6910   vl_api_fib_path_t paths[8];
6911   u32 sw_if_index = ~0;
6912   u8 path_count = 0;
6913   u8 l2_only = 0;
6914   u8 is_add = 1;
6915   int ret;
6916
6917   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6918     {
6919       if (unformat (i, "add"))
6920         is_add = 1;
6921       else
6922         if (unformat
6923             (i, "del %U", api_unformat_sw_if_index, vam, &sw_if_index))
6924         is_add = 0;
6925       else if (unformat (i, "del sw_if_index %d", &sw_if_index))
6926         is_add = 0;
6927       else if (unformat (i, "l2-only"))
6928         l2_only = 1;
6929       else
6930         if (unformat
6931             (i, "via %U", unformat_fib_path, vam, &paths[path_count]))
6932         {
6933           path_count++;
6934           if (8 == path_count)
6935             {
6936               errmsg ("max 8 paths");
6937               return -99;
6938             }
6939         }
6940       else
6941         {
6942           clib_warning ("parse error '%U'", format_unformat_error, i);
6943           return -99;
6944         }
6945     }
6946
6947   M2 (MPLS_TUNNEL_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
6948
6949   mp->mt_is_add = is_add;
6950   mp->mt_tunnel.mt_sw_if_index = ntohl (sw_if_index);
6951   mp->mt_tunnel.mt_l2_only = l2_only;
6952   mp->mt_tunnel.mt_is_multicast = 0;
6953   mp->mt_tunnel.mt_n_paths = path_count;
6954
6955   clib_memcpy (&mp->mt_tunnel.mt_paths, &paths,
6956                sizeof (paths[0]) * path_count);
6957
6958   S (mp);
6959   W (ret);
6960   return ret;
6961 }
6962
6963 static int
6964 api_sw_interface_set_unnumbered (vat_main_t * vam)
6965 {
6966   unformat_input_t *i = vam->input;
6967   vl_api_sw_interface_set_unnumbered_t *mp;
6968   u32 sw_if_index;
6969   u32 unnum_sw_index = ~0;
6970   u8 is_add = 1;
6971   u8 sw_if_index_set = 0;
6972   int ret;
6973
6974   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6975     {
6976       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
6977         sw_if_index_set = 1;
6978       else if (unformat (i, "sw_if_index %d", &sw_if_index))
6979         sw_if_index_set = 1;
6980       else if (unformat (i, "unnum_if_index %d", &unnum_sw_index))
6981         ;
6982       else if (unformat (i, "del"))
6983         is_add = 0;
6984       else
6985         {
6986           clib_warning ("parse error '%U'", format_unformat_error, i);
6987           return -99;
6988         }
6989     }
6990
6991   if (sw_if_index_set == 0)
6992     {
6993       errmsg ("missing interface name or sw_if_index");
6994       return -99;
6995     }
6996
6997   M (SW_INTERFACE_SET_UNNUMBERED, mp);
6998
6999   mp->sw_if_index = ntohl (sw_if_index);
7000   mp->unnumbered_sw_if_index = ntohl (unnum_sw_index);
7001   mp->is_add = is_add;
7002
7003   S (mp);
7004   W (ret);
7005   return ret;
7006 }
7007
7008
7009 static int
7010 api_create_vlan_subif (vat_main_t * vam)
7011 {
7012   unformat_input_t *i = vam->input;
7013   vl_api_create_vlan_subif_t *mp;
7014   u32 sw_if_index;
7015   u8 sw_if_index_set = 0;
7016   u32 vlan_id;
7017   u8 vlan_id_set = 0;
7018   int ret;
7019
7020   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7021     {
7022       if (unformat (i, "sw_if_index %d", &sw_if_index))
7023         sw_if_index_set = 1;
7024       else
7025         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
7026         sw_if_index_set = 1;
7027       else if (unformat (i, "vlan %d", &vlan_id))
7028         vlan_id_set = 1;
7029       else
7030         {
7031           clib_warning ("parse error '%U'", format_unformat_error, i);
7032           return -99;
7033         }
7034     }
7035
7036   if (sw_if_index_set == 0)
7037     {
7038       errmsg ("missing interface name or sw_if_index");
7039       return -99;
7040     }
7041
7042   if (vlan_id_set == 0)
7043     {
7044       errmsg ("missing vlan_id");
7045       return -99;
7046     }
7047   M (CREATE_VLAN_SUBIF, mp);
7048
7049   mp->sw_if_index = ntohl (sw_if_index);
7050   mp->vlan_id = ntohl (vlan_id);
7051
7052   S (mp);
7053   W (ret);
7054   return ret;
7055 }
7056
7057 #define foreach_create_subif_bit                \
7058 _(no_tags)                                      \
7059 _(one_tag)                                      \
7060 _(two_tags)                                     \
7061 _(dot1ad)                                       \
7062 _(exact_match)                                  \
7063 _(default_sub)                                  \
7064 _(outer_vlan_id_any)                            \
7065 _(inner_vlan_id_any)
7066
7067 #define foreach_create_subif_flag               \
7068 _(0, "no_tags")                                 \
7069 _(1, "one_tag")                                 \
7070 _(2, "two_tags")                                \
7071 _(3, "dot1ad")                                  \
7072 _(4, "exact_match")                             \
7073 _(5, "default_sub")                             \
7074 _(6, "outer_vlan_id_any")                       \
7075 _(7, "inner_vlan_id_any")
7076
7077 static int
7078 api_create_subif (vat_main_t * vam)
7079 {
7080   unformat_input_t *i = vam->input;
7081   vl_api_create_subif_t *mp;
7082   u32 sw_if_index;
7083   u8 sw_if_index_set = 0;
7084   u32 sub_id;
7085   u8 sub_id_set = 0;
7086   u32 __attribute__ ((unused)) no_tags = 0;
7087   u32 __attribute__ ((unused)) one_tag = 0;
7088   u32 __attribute__ ((unused)) two_tags = 0;
7089   u32 __attribute__ ((unused)) dot1ad = 0;
7090   u32 __attribute__ ((unused)) exact_match = 0;
7091   u32 __attribute__ ((unused)) default_sub = 0;
7092   u32 __attribute__ ((unused)) outer_vlan_id_any = 0;
7093   u32 __attribute__ ((unused)) inner_vlan_id_any = 0;
7094   u32 tmp;
7095   u16 outer_vlan_id = 0;
7096   u16 inner_vlan_id = 0;
7097   int ret;
7098
7099   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7100     {
7101       if (unformat (i, "sw_if_index %d", &sw_if_index))
7102         sw_if_index_set = 1;
7103       else
7104         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
7105         sw_if_index_set = 1;
7106       else if (unformat (i, "sub_id %d", &sub_id))
7107         sub_id_set = 1;
7108       else if (unformat (i, "outer_vlan_id %d", &tmp))
7109         outer_vlan_id = tmp;
7110       else if (unformat (i, "inner_vlan_id %d", &tmp))
7111         inner_vlan_id = tmp;
7112
7113 #define _(a) else if (unformat (i, #a)) a = 1 ;
7114       foreach_create_subif_bit
7115 #undef _
7116         else
7117         {
7118           clib_warning ("parse error '%U'", format_unformat_error, i);
7119           return -99;
7120         }
7121     }
7122
7123   if (sw_if_index_set == 0)
7124     {
7125       errmsg ("missing interface name or sw_if_index");
7126       return -99;
7127     }
7128
7129   if (sub_id_set == 0)
7130     {
7131       errmsg ("missing sub_id");
7132       return -99;
7133     }
7134   M (CREATE_SUBIF, mp);
7135
7136   mp->sw_if_index = ntohl (sw_if_index);
7137   mp->sub_id = ntohl (sub_id);
7138
7139 #define _(a,b) mp->sub_if_flags |= (1 << a);
7140   foreach_create_subif_flag;
7141 #undef _
7142
7143   mp->outer_vlan_id = ntohs (outer_vlan_id);
7144   mp->inner_vlan_id = ntohs (inner_vlan_id);
7145
7146   S (mp);
7147   W (ret);
7148   return ret;
7149 }
7150
7151 static int
7152 api_ip_table_replace_begin (vat_main_t * vam)
7153 {
7154   unformat_input_t *i = vam->input;
7155   vl_api_ip_table_replace_begin_t *mp;
7156   u32 table_id = 0;
7157   u8 is_ipv6 = 0;
7158
7159   int ret;
7160   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7161     {
7162       if (unformat (i, "table %d", &table_id))
7163         ;
7164       else if (unformat (i, "ipv6"))
7165         is_ipv6 = 1;
7166       else
7167         {
7168           clib_warning ("parse error '%U'", format_unformat_error, i);
7169           return -99;
7170         }
7171     }
7172
7173   M (IP_TABLE_REPLACE_BEGIN, mp);
7174
7175   mp->table.table_id = ntohl (table_id);
7176   mp->table.is_ip6 = is_ipv6;
7177
7178   S (mp);
7179   W (ret);
7180   return ret;
7181 }
7182
7183 static int
7184 api_ip_table_flush (vat_main_t * vam)
7185 {
7186   unformat_input_t *i = vam->input;
7187   vl_api_ip_table_flush_t *mp;
7188   u32 table_id = 0;
7189   u8 is_ipv6 = 0;
7190
7191   int ret;
7192   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7193     {
7194       if (unformat (i, "table %d", &table_id))
7195         ;
7196       else if (unformat (i, "ipv6"))
7197         is_ipv6 = 1;
7198       else
7199         {
7200           clib_warning ("parse error '%U'", format_unformat_error, i);
7201           return -99;
7202         }
7203     }
7204
7205   M (IP_TABLE_FLUSH, mp);
7206
7207   mp->table.table_id = ntohl (table_id);
7208   mp->table.is_ip6 = is_ipv6;
7209
7210   S (mp);
7211   W (ret);
7212   return ret;
7213 }
7214
7215 static int
7216 api_ip_table_replace_end (vat_main_t * vam)
7217 {
7218   unformat_input_t *i = vam->input;
7219   vl_api_ip_table_replace_end_t *mp;
7220   u32 table_id = 0;
7221   u8 is_ipv6 = 0;
7222
7223   int ret;
7224   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7225     {
7226       if (unformat (i, "table %d", &table_id))
7227         ;
7228       else if (unformat (i, "ipv6"))
7229         is_ipv6 = 1;
7230       else
7231         {
7232           clib_warning ("parse error '%U'", format_unformat_error, i);
7233           return -99;
7234         }
7235     }
7236
7237   M (IP_TABLE_REPLACE_END, mp);
7238
7239   mp->table.table_id = ntohl (table_id);
7240   mp->table.is_ip6 = is_ipv6;
7241
7242   S (mp);
7243   W (ret);
7244   return ret;
7245 }
7246
7247 static int
7248 api_set_ip_flow_hash (vat_main_t * vam)
7249 {
7250   unformat_input_t *i = vam->input;
7251   vl_api_set_ip_flow_hash_t *mp;
7252   u32 vrf_id = 0;
7253   u8 is_ipv6 = 0;
7254   u8 vrf_id_set = 0;
7255   u8 src = 0;
7256   u8 dst = 0;
7257   u8 sport = 0;
7258   u8 dport = 0;
7259   u8 proto = 0;
7260   u8 reverse = 0;
7261   int ret;
7262
7263   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7264     {
7265       if (unformat (i, "vrf %d", &vrf_id))
7266         vrf_id_set = 1;
7267       else if (unformat (i, "ipv6"))
7268         is_ipv6 = 1;
7269       else if (unformat (i, "src"))
7270         src = 1;
7271       else if (unformat (i, "dst"))
7272         dst = 1;
7273       else if (unformat (i, "sport"))
7274         sport = 1;
7275       else if (unformat (i, "dport"))
7276         dport = 1;
7277       else if (unformat (i, "proto"))
7278         proto = 1;
7279       else if (unformat (i, "reverse"))
7280         reverse = 1;
7281
7282       else
7283         {
7284           clib_warning ("parse error '%U'", format_unformat_error, i);
7285           return -99;
7286         }
7287     }
7288
7289   if (vrf_id_set == 0)
7290     {
7291       errmsg ("missing vrf id");
7292       return -99;
7293     }
7294
7295   M (SET_IP_FLOW_HASH, mp);
7296   mp->src = src;
7297   mp->dst = dst;
7298   mp->sport = sport;
7299   mp->dport = dport;
7300   mp->proto = proto;
7301   mp->reverse = reverse;
7302   mp->vrf_id = ntohl (vrf_id);
7303   mp->is_ipv6 = is_ipv6;
7304
7305   S (mp);
7306   W (ret);
7307   return ret;
7308 }
7309
7310 static int
7311 api_sw_interface_ip6_enable_disable (vat_main_t * vam)
7312 {
7313   unformat_input_t *i = vam->input;
7314   vl_api_sw_interface_ip6_enable_disable_t *mp;
7315   u32 sw_if_index;
7316   u8 sw_if_index_set = 0;
7317   u8 enable = 0;
7318   int ret;
7319
7320   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7321     {
7322       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
7323         sw_if_index_set = 1;
7324       else if (unformat (i, "sw_if_index %d", &sw_if_index))
7325         sw_if_index_set = 1;
7326       else if (unformat (i, "enable"))
7327         enable = 1;
7328       else if (unformat (i, "disable"))
7329         enable = 0;
7330       else
7331         {
7332           clib_warning ("parse error '%U'", format_unformat_error, i);
7333           return -99;
7334         }
7335     }
7336
7337   if (sw_if_index_set == 0)
7338     {
7339       errmsg ("missing interface name or sw_if_index");
7340       return -99;
7341     }
7342
7343   M (SW_INTERFACE_IP6_ENABLE_DISABLE, mp);
7344
7345   mp->sw_if_index = ntohl (sw_if_index);
7346   mp->enable = enable;
7347
7348   S (mp);
7349   W (ret);
7350   return ret;
7351 }
7352
7353
7354 static int
7355 api_l2_patch_add_del (vat_main_t * vam)
7356 {
7357   unformat_input_t *i = vam->input;
7358   vl_api_l2_patch_add_del_t *mp;
7359   u32 rx_sw_if_index;
7360   u8 rx_sw_if_index_set = 0;
7361   u32 tx_sw_if_index;
7362   u8 tx_sw_if_index_set = 0;
7363   u8 is_add = 1;
7364   int ret;
7365
7366   /* Parse args required to build the message */
7367   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7368     {
7369       if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index))
7370         rx_sw_if_index_set = 1;
7371       else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
7372         tx_sw_if_index_set = 1;
7373       else if (unformat (i, "rx"))
7374         {
7375           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7376             {
7377               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
7378                             &rx_sw_if_index))
7379                 rx_sw_if_index_set = 1;
7380             }
7381           else
7382             break;
7383         }
7384       else if (unformat (i, "tx"))
7385         {
7386           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7387             {
7388               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
7389                             &tx_sw_if_index))
7390                 tx_sw_if_index_set = 1;
7391             }
7392           else
7393             break;
7394         }
7395       else if (unformat (i, "del"))
7396         is_add = 0;
7397       else
7398         break;
7399     }
7400
7401   if (rx_sw_if_index_set == 0)
7402     {
7403       errmsg ("missing rx interface name or rx_sw_if_index");
7404       return -99;
7405     }
7406
7407   if (tx_sw_if_index_set == 0)
7408     {
7409       errmsg ("missing tx interface name or tx_sw_if_index");
7410       return -99;
7411     }
7412
7413   M (L2_PATCH_ADD_DEL, mp);
7414
7415   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
7416   mp->tx_sw_if_index = ntohl (tx_sw_if_index);
7417   mp->is_add = is_add;
7418
7419   S (mp);
7420   W (ret);
7421   return ret;
7422 }
7423
7424 u8 is_del;
7425 u8 localsid_addr[16];
7426 u8 end_psp;
7427 u8 behavior;
7428 u32 sw_if_index;
7429 u32 vlan_index;
7430 u32 fib_table;
7431 u8 nh_addr[16];
7432
7433 static int
7434 api_sr_localsid_add_del (vat_main_t * vam)
7435 {
7436   unformat_input_t *i = vam->input;
7437   vl_api_sr_localsid_add_del_t *mp;
7438
7439   u8 is_del;
7440   ip6_address_t localsid;
7441   u8 end_psp = 0;
7442   u8 behavior = ~0;
7443   u32 sw_if_index;
7444   u32 fib_table = ~(u32) 0;
7445   ip46_address_t nh_addr;
7446   clib_memset (&nh_addr, 0, sizeof (ip46_address_t));
7447
7448   bool nexthop_set = 0;
7449
7450   int ret;
7451
7452   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7453     {
7454       if (unformat (i, "del"))
7455         is_del = 1;
7456       else if (unformat (i, "address %U", unformat_ip6_address, &localsid));
7457       else if (unformat (i, "next-hop %U", unformat_ip46_address, &nh_addr))
7458         nexthop_set = 1;
7459       else if (unformat (i, "behavior %u", &behavior));
7460       else if (unformat (i, "sw_if_index %u", &sw_if_index));
7461       else if (unformat (i, "fib-table %u", &fib_table));
7462       else if (unformat (i, "end.psp %u", &behavior));
7463       else
7464         break;
7465     }
7466
7467   M (SR_LOCALSID_ADD_DEL, mp);
7468
7469   clib_memcpy (mp->localsid, &localsid, sizeof (mp->localsid));
7470
7471   if (nexthop_set)
7472     {
7473       clib_memcpy (&mp->nh_addr.un, &nh_addr, sizeof (mp->nh_addr.un));
7474     }
7475   mp->behavior = behavior;
7476   mp->sw_if_index = ntohl (sw_if_index);
7477   mp->fib_table = ntohl (fib_table);
7478   mp->end_psp = end_psp;
7479   mp->is_del = is_del;
7480
7481   S (mp);
7482   W (ret);
7483   return ret;
7484 }
7485
7486 static int
7487 api_ioam_enable (vat_main_t * vam)
7488 {
7489   unformat_input_t *input = vam->input;
7490   vl_api_ioam_enable_t *mp;
7491   u32 id = 0;
7492   int has_trace_option = 0;
7493   int has_pot_option = 0;
7494   int has_seqno_option = 0;
7495   int has_analyse_option = 0;
7496   int ret;
7497
7498   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7499     {
7500       if (unformat (input, "trace"))
7501         has_trace_option = 1;
7502       else if (unformat (input, "pot"))
7503         has_pot_option = 1;
7504       else if (unformat (input, "seqno"))
7505         has_seqno_option = 1;
7506       else if (unformat (input, "analyse"))
7507         has_analyse_option = 1;
7508       else
7509         break;
7510     }
7511   M (IOAM_ENABLE, mp);
7512   mp->id = htons (id);
7513   mp->seqno = has_seqno_option;
7514   mp->analyse = has_analyse_option;
7515   mp->pot_enable = has_pot_option;
7516   mp->trace_enable = has_trace_option;
7517
7518   S (mp);
7519   W (ret);
7520   return ret;
7521 }
7522
7523
7524 static int
7525 api_ioam_disable (vat_main_t * vam)
7526 {
7527   vl_api_ioam_disable_t *mp;
7528   int ret;
7529
7530   M (IOAM_DISABLE, mp);
7531   S (mp);
7532   W (ret);
7533   return ret;
7534 }
7535
7536 #define foreach_tcp_proto_field                 \
7537 _(src_port)                                     \
7538 _(dst_port)
7539
7540 #define foreach_udp_proto_field                 \
7541 _(src_port)                                     \
7542 _(dst_port)
7543
7544 #define foreach_ip4_proto_field                 \
7545 _(src_address)                                  \
7546 _(dst_address)                                  \
7547 _(tos)                                          \
7548 _(length)                                       \
7549 _(fragment_id)                                  \
7550 _(ttl)                                          \
7551 _(protocol)                                     \
7552 _(checksum)
7553
7554 typedef struct
7555 {
7556   u16 src_port, dst_port;
7557 } tcpudp_header_t;
7558
7559 #if VPP_API_TEST_BUILTIN == 0
7560 uword
7561 unformat_tcp_mask (unformat_input_t * input, va_list * args)
7562 {
7563   u8 **maskp = va_arg (*args, u8 **);
7564   u8 *mask = 0;
7565   u8 found_something = 0;
7566   tcp_header_t *tcp;
7567
7568 #define _(a) u8 a=0;
7569   foreach_tcp_proto_field;
7570 #undef _
7571
7572   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7573     {
7574       if (0);
7575 #define _(a) else if (unformat (input, #a)) a=1;
7576       foreach_tcp_proto_field
7577 #undef _
7578         else
7579         break;
7580     }
7581
7582 #define _(a) found_something += a;
7583   foreach_tcp_proto_field;
7584 #undef _
7585
7586   if (found_something == 0)
7587     return 0;
7588
7589   vec_validate (mask, sizeof (*tcp) - 1);
7590
7591   tcp = (tcp_header_t *) mask;
7592
7593 #define _(a) if (a) clib_memset (&tcp->a, 0xff, sizeof (tcp->a));
7594   foreach_tcp_proto_field;
7595 #undef _
7596
7597   *maskp = mask;
7598   return 1;
7599 }
7600
7601 uword
7602 unformat_udp_mask (unformat_input_t * input, va_list * args)
7603 {
7604   u8 **maskp = va_arg (*args, u8 **);
7605   u8 *mask = 0;
7606   u8 found_something = 0;
7607   udp_header_t *udp;
7608
7609 #define _(a) u8 a=0;
7610   foreach_udp_proto_field;
7611 #undef _
7612
7613   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7614     {
7615       if (0);
7616 #define _(a) else if (unformat (input, #a)) a=1;
7617       foreach_udp_proto_field
7618 #undef _
7619         else
7620         break;
7621     }
7622
7623 #define _(a) found_something += a;
7624   foreach_udp_proto_field;
7625 #undef _
7626
7627   if (found_something == 0)
7628     return 0;
7629
7630   vec_validate (mask, sizeof (*udp) - 1);
7631
7632   udp = (udp_header_t *) mask;
7633
7634 #define _(a) if (a) clib_memset (&udp->a, 0xff, sizeof (udp->a));
7635   foreach_udp_proto_field;
7636 #undef _
7637
7638   *maskp = mask;
7639   return 1;
7640 }
7641
7642 uword
7643 unformat_l4_mask (unformat_input_t * input, va_list * args)
7644 {
7645   u8 **maskp = va_arg (*args, u8 **);
7646   u16 src_port = 0, dst_port = 0;
7647   tcpudp_header_t *tcpudp;
7648
7649   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7650     {
7651       if (unformat (input, "tcp %U", unformat_tcp_mask, maskp))
7652         return 1;
7653       else if (unformat (input, "udp %U", unformat_udp_mask, maskp))
7654         return 1;
7655       else if (unformat (input, "src_port"))
7656         src_port = 0xFFFF;
7657       else if (unformat (input, "dst_port"))
7658         dst_port = 0xFFFF;
7659       else
7660         return 0;
7661     }
7662
7663   if (!src_port && !dst_port)
7664     return 0;
7665
7666   u8 *mask = 0;
7667   vec_validate (mask, sizeof (tcpudp_header_t) - 1);
7668
7669   tcpudp = (tcpudp_header_t *) mask;
7670   tcpudp->src_port = src_port;
7671   tcpudp->dst_port = dst_port;
7672
7673   *maskp = mask;
7674
7675   return 1;
7676 }
7677
7678 uword
7679 unformat_ip4_mask (unformat_input_t * input, va_list * args)
7680 {
7681   u8 **maskp = va_arg (*args, u8 **);
7682   u8 *mask = 0;
7683   u8 found_something = 0;
7684   ip4_header_t *ip;
7685
7686 #define _(a) u8 a=0;
7687   foreach_ip4_proto_field;
7688 #undef _
7689   u8 version = 0;
7690   u8 hdr_length = 0;
7691
7692
7693   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7694     {
7695       if (unformat (input, "version"))
7696         version = 1;
7697       else if (unformat (input, "hdr_length"))
7698         hdr_length = 1;
7699       else if (unformat (input, "src"))
7700         src_address = 1;
7701       else if (unformat (input, "dst"))
7702         dst_address = 1;
7703       else if (unformat (input, "proto"))
7704         protocol = 1;
7705
7706 #define _(a) else if (unformat (input, #a)) a=1;
7707       foreach_ip4_proto_field
7708 #undef _
7709         else
7710         break;
7711     }
7712
7713 #define _(a) found_something += a;
7714   foreach_ip4_proto_field;
7715 #undef _
7716
7717   if (found_something == 0)
7718     return 0;
7719
7720   vec_validate (mask, sizeof (*ip) - 1);
7721
7722   ip = (ip4_header_t *) mask;
7723
7724 #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
7725   foreach_ip4_proto_field;
7726 #undef _
7727
7728   ip->ip_version_and_header_length = 0;
7729
7730   if (version)
7731     ip->ip_version_and_header_length |= 0xF0;
7732
7733   if (hdr_length)
7734     ip->ip_version_and_header_length |= 0x0F;
7735
7736   *maskp = mask;
7737   return 1;
7738 }
7739
7740 #define foreach_ip6_proto_field                 \
7741 _(src_address)                                  \
7742 _(dst_address)                                  \
7743 _(payload_length)                               \
7744 _(hop_limit)                                    \
7745 _(protocol)
7746
7747 uword
7748 unformat_ip6_mask (unformat_input_t * input, va_list * args)
7749 {
7750   u8 **maskp = va_arg (*args, u8 **);
7751   u8 *mask = 0;
7752   u8 found_something = 0;
7753   ip6_header_t *ip;
7754   u32 ip_version_traffic_class_and_flow_label;
7755
7756 #define _(a) u8 a=0;
7757   foreach_ip6_proto_field;
7758 #undef _
7759   u8 version = 0;
7760   u8 traffic_class = 0;
7761   u8 flow_label = 0;
7762
7763   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7764     {
7765       if (unformat (input, "version"))
7766         version = 1;
7767       else if (unformat (input, "traffic-class"))
7768         traffic_class = 1;
7769       else if (unformat (input, "flow-label"))
7770         flow_label = 1;
7771       else if (unformat (input, "src"))
7772         src_address = 1;
7773       else if (unformat (input, "dst"))
7774         dst_address = 1;
7775       else if (unformat (input, "proto"))
7776         protocol = 1;
7777
7778 #define _(a) else if (unformat (input, #a)) a=1;
7779       foreach_ip6_proto_field
7780 #undef _
7781         else
7782         break;
7783     }
7784
7785 #define _(a) found_something += a;
7786   foreach_ip6_proto_field;
7787 #undef _
7788
7789   if (found_something == 0)
7790     return 0;
7791
7792   vec_validate (mask, sizeof (*ip) - 1);
7793
7794   ip = (ip6_header_t *) mask;
7795
7796 #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
7797   foreach_ip6_proto_field;
7798 #undef _
7799
7800   ip_version_traffic_class_and_flow_label = 0;
7801
7802   if (version)
7803     ip_version_traffic_class_and_flow_label |= 0xF0000000;
7804
7805   if (traffic_class)
7806     ip_version_traffic_class_and_flow_label |= 0x0FF00000;
7807
7808   if (flow_label)
7809     ip_version_traffic_class_and_flow_label |= 0x000FFFFF;
7810
7811   ip->ip_version_traffic_class_and_flow_label =
7812     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
7813
7814   *maskp = mask;
7815   return 1;
7816 }
7817
7818 uword
7819 unformat_l3_mask (unformat_input_t * input, va_list * args)
7820 {
7821   u8 **maskp = va_arg (*args, u8 **);
7822
7823   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7824     {
7825       if (unformat (input, "ip4 %U", unformat_ip4_mask, maskp))
7826         return 1;
7827       else if (unformat (input, "ip6 %U", unformat_ip6_mask, maskp))
7828         return 1;
7829       else
7830         break;
7831     }
7832   return 0;
7833 }
7834
7835 uword
7836 unformat_l2_mask (unformat_input_t * input, va_list * args)
7837 {
7838   u8 **maskp = va_arg (*args, u8 **);
7839   u8 *mask = 0;
7840   u8 src = 0;
7841   u8 dst = 0;
7842   u8 proto = 0;
7843   u8 tag1 = 0;
7844   u8 tag2 = 0;
7845   u8 ignore_tag1 = 0;
7846   u8 ignore_tag2 = 0;
7847   u8 cos1 = 0;
7848   u8 cos2 = 0;
7849   u8 dot1q = 0;
7850   u8 dot1ad = 0;
7851   int len = 14;
7852
7853   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7854     {
7855       if (unformat (input, "src"))
7856         src = 1;
7857       else if (unformat (input, "dst"))
7858         dst = 1;
7859       else if (unformat (input, "proto"))
7860         proto = 1;
7861       else if (unformat (input, "tag1"))
7862         tag1 = 1;
7863       else if (unformat (input, "tag2"))
7864         tag2 = 1;
7865       else if (unformat (input, "ignore-tag1"))
7866         ignore_tag1 = 1;
7867       else if (unformat (input, "ignore-tag2"))
7868         ignore_tag2 = 1;
7869       else if (unformat (input, "cos1"))
7870         cos1 = 1;
7871       else if (unformat (input, "cos2"))
7872         cos2 = 1;
7873       else if (unformat (input, "dot1q"))
7874         dot1q = 1;
7875       else if (unformat (input, "dot1ad"))
7876         dot1ad = 1;
7877       else
7878         break;
7879     }
7880   if ((src + dst + proto + tag1 + tag2 + dot1q + dot1ad +
7881        ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
7882     return 0;
7883
7884   if (tag1 || ignore_tag1 || cos1 || dot1q)
7885     len = 18;
7886   if (tag2 || ignore_tag2 || cos2 || dot1ad)
7887     len = 22;
7888
7889   vec_validate (mask, len - 1);
7890
7891   if (dst)
7892     clib_memset (mask, 0xff, 6);
7893
7894   if (src)
7895     clib_memset (mask + 6, 0xff, 6);
7896
7897   if (tag2 || dot1ad)
7898     {
7899       /* inner vlan tag */
7900       if (tag2)
7901         {
7902           mask[19] = 0xff;
7903           mask[18] = 0x0f;
7904         }
7905       if (cos2)
7906         mask[18] |= 0xe0;
7907       if (proto)
7908         mask[21] = mask[20] = 0xff;
7909       if (tag1)
7910         {
7911           mask[15] = 0xff;
7912           mask[14] = 0x0f;
7913         }
7914       if (cos1)
7915         mask[14] |= 0xe0;
7916       *maskp = mask;
7917       return 1;
7918     }
7919   if (tag1 | dot1q)
7920     {
7921       if (tag1)
7922         {
7923           mask[15] = 0xff;
7924           mask[14] = 0x0f;
7925         }
7926       if (cos1)
7927         mask[14] |= 0xe0;
7928       if (proto)
7929         mask[16] = mask[17] = 0xff;
7930
7931       *maskp = mask;
7932       return 1;
7933     }
7934   if (cos2)
7935     mask[18] |= 0xe0;
7936   if (cos1)
7937     mask[14] |= 0xe0;
7938   if (proto)
7939     mask[12] = mask[13] = 0xff;
7940
7941   *maskp = mask;
7942   return 1;
7943 }
7944
7945 uword
7946 unformat_classify_mask (unformat_input_t * input, va_list * args)
7947 {
7948   u8 **maskp = va_arg (*args, u8 **);
7949   u32 *skipp = va_arg (*args, u32 *);
7950   u32 *matchp = va_arg (*args, u32 *);
7951   u32 match;
7952   u8 *mask = 0;
7953   u8 *l2 = 0;
7954   u8 *l3 = 0;
7955   u8 *l4 = 0;
7956   int i;
7957
7958   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7959     {
7960       if (unformat (input, "hex %U", unformat_hex_string, &mask))
7961         ;
7962       else if (unformat (input, "l2 %U", unformat_l2_mask, &l2))
7963         ;
7964       else if (unformat (input, "l3 %U", unformat_l3_mask, &l3))
7965         ;
7966       else if (unformat (input, "l4 %U", unformat_l4_mask, &l4))
7967         ;
7968       else
7969         break;
7970     }
7971
7972   if (l4 && !l3)
7973     {
7974       vec_free (mask);
7975       vec_free (l2);
7976       vec_free (l4);
7977       return 0;
7978     }
7979
7980   if (mask || l2 || l3 || l4)
7981     {
7982       if (l2 || l3 || l4)
7983         {
7984           /* "With a free Ethernet header in every package" */
7985           if (l2 == 0)
7986             vec_validate (l2, 13);
7987           mask = l2;
7988           if (vec_len (l3))
7989             {
7990               vec_append (mask, l3);
7991               vec_free (l3);
7992             }
7993           if (vec_len (l4))
7994             {
7995               vec_append (mask, l4);
7996               vec_free (l4);
7997             }
7998         }
7999
8000       /* Scan forward looking for the first significant mask octet */
8001       for (i = 0; i < vec_len (mask); i++)
8002         if (mask[i])
8003           break;
8004
8005       /* compute (skip, match) params */
8006       *skipp = i / sizeof (u32x4);
8007       vec_delete (mask, *skipp * sizeof (u32x4), 0);
8008
8009       /* Pad mask to an even multiple of the vector size */
8010       while (vec_len (mask) % sizeof (u32x4))
8011         vec_add1 (mask, 0);
8012
8013       match = vec_len (mask) / sizeof (u32x4);
8014
8015       for (i = match * sizeof (u32x4); i > 0; i -= sizeof (u32x4))
8016         {
8017           u64 *tmp = (u64 *) (mask + (i - sizeof (u32x4)));
8018           if (*tmp || *(tmp + 1))
8019             break;
8020           match--;
8021         }
8022       if (match == 0)
8023         clib_warning ("BUG: match 0");
8024
8025       _vec_len (mask) = match * sizeof (u32x4);
8026
8027       *matchp = match;
8028       *maskp = mask;
8029
8030       return 1;
8031     }
8032
8033   return 0;
8034 }
8035 #endif /* VPP_API_TEST_BUILTIN */
8036
8037 #define foreach_l2_next                         \
8038 _(drop, DROP)                                   \
8039 _(ethernet, ETHERNET_INPUT)                     \
8040 _(ip4, IP4_INPUT)                               \
8041 _(ip6, IP6_INPUT)
8042
8043 uword
8044 unformat_l2_next_index (unformat_input_t * input, va_list * args)
8045 {
8046   u32 *miss_next_indexp = va_arg (*args, u32 *);
8047   u32 next_index = 0;
8048   u32 tmp;
8049
8050 #define _(n,N) \
8051   if (unformat (input, #n)) { next_index = L2_INPUT_CLASSIFY_NEXT_##N; goto out;}
8052   foreach_l2_next;
8053 #undef _
8054
8055   if (unformat (input, "%d", &tmp))
8056     {
8057       next_index = tmp;
8058       goto out;
8059     }
8060
8061   return 0;
8062
8063 out:
8064   *miss_next_indexp = next_index;
8065   return 1;
8066 }
8067
8068 #define foreach_ip_next                         \
8069 _(drop, DROP)                                   \
8070 _(local, LOCAL)                                 \
8071 _(rewrite, REWRITE)
8072
8073 uword
8074 api_unformat_ip_next_index (unformat_input_t * input, va_list * args)
8075 {
8076   u32 *miss_next_indexp = va_arg (*args, u32 *);
8077   u32 next_index = 0;
8078   u32 tmp;
8079
8080 #define _(n,N) \
8081   if (unformat (input, #n)) { next_index = IP_LOOKUP_NEXT_##N; goto out;}
8082   foreach_ip_next;
8083 #undef _
8084
8085   if (unformat (input, "%d", &tmp))
8086     {
8087       next_index = tmp;
8088       goto out;
8089     }
8090
8091   return 0;
8092
8093 out:
8094   *miss_next_indexp = next_index;
8095   return 1;
8096 }
8097
8098 #define foreach_acl_next                        \
8099 _(deny, DENY)
8100
8101 uword
8102 api_unformat_acl_next_index (unformat_input_t * input, va_list * args)
8103 {
8104   u32 *miss_next_indexp = va_arg (*args, u32 *);
8105   u32 next_index = 0;
8106   u32 tmp;
8107
8108 #define _(n,N) \
8109   if (unformat (input, #n)) { next_index = ACL_NEXT_INDEX_##N; goto out;}
8110   foreach_acl_next;
8111 #undef _
8112
8113   if (unformat (input, "permit"))
8114     {
8115       next_index = ~0;
8116       goto out;
8117     }
8118   else if (unformat (input, "%d", &tmp))
8119     {
8120       next_index = tmp;
8121       goto out;
8122     }
8123
8124   return 0;
8125
8126 out:
8127   *miss_next_indexp = next_index;
8128   return 1;
8129 }
8130
8131 uword
8132 unformat_policer_precolor (unformat_input_t * input, va_list * args)
8133 {
8134   u32 *r = va_arg (*args, u32 *);
8135
8136   if (unformat (input, "conform-color"))
8137     *r = POLICE_CONFORM;
8138   else if (unformat (input, "exceed-color"))
8139     *r = POLICE_EXCEED;
8140   else
8141     return 0;
8142
8143   return 1;
8144 }
8145
8146 static int
8147 api_classify_add_del_table (vat_main_t * vam)
8148 {
8149   unformat_input_t *i = vam->input;
8150   vl_api_classify_add_del_table_t *mp;
8151
8152   u32 nbuckets = 2;
8153   u32 skip = ~0;
8154   u32 match = ~0;
8155   int is_add = 1;
8156   int del_chain = 0;
8157   u32 table_index = ~0;
8158   u32 next_table_index = ~0;
8159   u32 miss_next_index = ~0;
8160   u32 memory_size = 32 << 20;
8161   u8 *mask = 0;
8162   u32 current_data_flag = 0;
8163   int current_data_offset = 0;
8164   int ret;
8165
8166   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8167     {
8168       if (unformat (i, "del"))
8169         is_add = 0;
8170       else if (unformat (i, "del-chain"))
8171         {
8172           is_add = 0;
8173           del_chain = 1;
8174         }
8175       else if (unformat (i, "buckets %d", &nbuckets))
8176         ;
8177       else if (unformat (i, "memory_size %d", &memory_size))
8178         ;
8179       else if (unformat (i, "skip %d", &skip))
8180         ;
8181       else if (unformat (i, "match %d", &match))
8182         ;
8183       else if (unformat (i, "table %d", &table_index))
8184         ;
8185       else if (unformat (i, "mask %U", unformat_classify_mask,
8186                          &mask, &skip, &match))
8187         ;
8188       else if (unformat (i, "next-table %d", &next_table_index))
8189         ;
8190       else if (unformat (i, "miss-next %U", api_unformat_ip_next_index,
8191                          &miss_next_index))
8192         ;
8193       else if (unformat (i, "l2-miss-next %U", unformat_l2_next_index,
8194                          &miss_next_index))
8195         ;
8196       else if (unformat (i, "acl-miss-next %U", api_unformat_acl_next_index,
8197                          &miss_next_index))
8198         ;
8199       else if (unformat (i, "current-data-flag %d", &current_data_flag))
8200         ;
8201       else if (unformat (i, "current-data-offset %d", &current_data_offset))
8202         ;
8203       else
8204         break;
8205     }
8206
8207   if (is_add && mask == 0)
8208     {
8209       errmsg ("Mask required");
8210       return -99;
8211     }
8212
8213   if (is_add && skip == ~0)
8214     {
8215       errmsg ("skip count required");
8216       return -99;
8217     }
8218
8219   if (is_add && match == ~0)
8220     {
8221       errmsg ("match count required");
8222       return -99;
8223     }
8224
8225   if (!is_add && table_index == ~0)
8226     {
8227       errmsg ("table index required for delete");
8228       return -99;
8229     }
8230
8231   M2 (CLASSIFY_ADD_DEL_TABLE, mp, vec_len (mask));
8232
8233   mp->is_add = is_add;
8234   mp->del_chain = del_chain;
8235   mp->table_index = ntohl (table_index);
8236   mp->nbuckets = ntohl (nbuckets);
8237   mp->memory_size = ntohl (memory_size);
8238   mp->skip_n_vectors = ntohl (skip);
8239   mp->match_n_vectors = ntohl (match);
8240   mp->next_table_index = ntohl (next_table_index);
8241   mp->miss_next_index = ntohl (miss_next_index);
8242   mp->current_data_flag = ntohl (current_data_flag);
8243   mp->current_data_offset = ntohl (current_data_offset);
8244   mp->mask_len = ntohl (vec_len (mask));
8245   clib_memcpy (mp->mask, mask, vec_len (mask));
8246
8247   vec_free (mask);
8248
8249   S (mp);
8250   W (ret);
8251   return ret;
8252 }
8253
8254 #if VPP_API_TEST_BUILTIN == 0
8255 uword
8256 unformat_l4_match (unformat_input_t * input, va_list * args)
8257 {
8258   u8 **matchp = va_arg (*args, u8 **);
8259
8260   u8 *proto_header = 0;
8261   int src_port = 0;
8262   int dst_port = 0;
8263
8264   tcpudp_header_t h;
8265
8266   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
8267     {
8268       if (unformat (input, "src_port %d", &src_port))
8269         ;
8270       else if (unformat (input, "dst_port %d", &dst_port))
8271         ;
8272       else
8273         return 0;
8274     }
8275
8276   h.src_port = clib_host_to_net_u16 (src_port);
8277   h.dst_port = clib_host_to_net_u16 (dst_port);
8278   vec_validate (proto_header, sizeof (h) - 1);
8279   memcpy (proto_header, &h, sizeof (h));
8280
8281   *matchp = proto_header;
8282
8283   return 1;
8284 }
8285
8286 uword
8287 unformat_ip4_match (unformat_input_t * input, va_list * args)
8288 {
8289   u8 **matchp = va_arg (*args, u8 **);
8290   u8 *match = 0;
8291   ip4_header_t *ip;
8292   int version = 0;
8293   u32 version_val;
8294   int hdr_length = 0;
8295   u32 hdr_length_val;
8296   int src = 0, dst = 0;
8297   ip4_address_t src_val, dst_val;
8298   int proto = 0;
8299   u32 proto_val;
8300   int tos = 0;
8301   u32 tos_val;
8302   int length = 0;
8303   u32 length_val;
8304   int fragment_id = 0;
8305   u32 fragment_id_val;
8306   int ttl = 0;
8307   int ttl_val;
8308   int checksum = 0;
8309   u32 checksum_val;
8310
8311   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
8312     {
8313       if (unformat (input, "version %d", &version_val))
8314         version = 1;
8315       else if (unformat (input, "hdr_length %d", &hdr_length_val))
8316         hdr_length = 1;
8317       else if (unformat (input, "src %U", unformat_ip4_address, &src_val))
8318         src = 1;
8319       else if (unformat (input, "dst %U", unformat_ip4_address, &dst_val))
8320         dst = 1;
8321       else if (unformat (input, "proto %d", &proto_val))
8322         proto = 1;
8323       else if (unformat (input, "tos %d", &tos_val))
8324         tos = 1;
8325       else if (unformat (input, "length %d", &length_val))
8326         length = 1;
8327       else if (unformat (input, "fragment_id %d", &fragment_id_val))
8328         fragment_id = 1;
8329       else if (unformat (input, "ttl %d", &ttl_val))
8330         ttl = 1;
8331       else if (unformat (input, "checksum %d", &checksum_val))
8332         checksum = 1;
8333       else
8334         break;
8335     }
8336
8337   if (version + hdr_length + src + dst + proto + tos + length + fragment_id
8338       + ttl + checksum == 0)
8339     return 0;
8340
8341   /*
8342    * Aligned because we use the real comparison functions
8343    */
8344   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
8345
8346   ip = (ip4_header_t *) match;
8347
8348   /* These are realistically matched in practice */
8349   if (src)
8350     ip->src_address.as_u32 = src_val.as_u32;
8351
8352   if (dst)
8353     ip->dst_address.as_u32 = dst_val.as_u32;
8354
8355   if (proto)
8356     ip->protocol = proto_val;
8357
8358
8359   /* These are not, but they're included for completeness */
8360   if (version)
8361     ip->ip_version_and_header_length |= (version_val & 0xF) << 4;
8362
8363   if (hdr_length)
8364     ip->ip_version_and_header_length |= (hdr_length_val & 0xF);
8365
8366   if (tos)
8367     ip->tos = tos_val;
8368
8369   if (length)
8370     ip->length = clib_host_to_net_u16 (length_val);
8371
8372   if (ttl)
8373     ip->ttl = ttl_val;
8374
8375   if (checksum)
8376     ip->checksum = clib_host_to_net_u16 (checksum_val);
8377
8378   *matchp = match;
8379   return 1;
8380 }
8381
8382 uword
8383 unformat_ip6_match (unformat_input_t * input, va_list * args)
8384 {
8385   u8 **matchp = va_arg (*args, u8 **);
8386   u8 *match = 0;
8387   ip6_header_t *ip;
8388   int version = 0;
8389   u32 version_val;
8390   u8 traffic_class = 0;
8391   u32 traffic_class_val = 0;
8392   u8 flow_label = 0;
8393   u8 flow_label_val;
8394   int src = 0, dst = 0;
8395   ip6_address_t src_val, dst_val;
8396   int proto = 0;
8397   u32 proto_val;
8398   int payload_length = 0;
8399   u32 payload_length_val;
8400   int hop_limit = 0;
8401   int hop_limit_val;
8402   u32 ip_version_traffic_class_and_flow_label;
8403
8404   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
8405     {
8406       if (unformat (input, "version %d", &version_val))
8407         version = 1;
8408       else if (unformat (input, "traffic_class %d", &traffic_class_val))
8409         traffic_class = 1;
8410       else if (unformat (input, "flow_label %d", &flow_label_val))
8411         flow_label = 1;
8412       else if (unformat (input, "src %U", unformat_ip6_address, &src_val))
8413         src = 1;
8414       else if (unformat (input, "dst %U", unformat_ip6_address, &dst_val))
8415         dst = 1;
8416       else if (unformat (input, "proto %d", &proto_val))
8417         proto = 1;
8418       else if (unformat (input, "payload_length %d", &payload_length_val))
8419         payload_length = 1;
8420       else if (unformat (input, "hop_limit %d", &hop_limit_val))
8421         hop_limit = 1;
8422       else
8423         break;
8424     }
8425
8426   if (version + traffic_class + flow_label + src + dst + proto +
8427       payload_length + hop_limit == 0)
8428     return 0;
8429
8430   /*
8431    * Aligned because we use the real comparison functions
8432    */
8433   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
8434
8435   ip = (ip6_header_t *) match;
8436
8437   if (src)
8438     clib_memcpy (&ip->src_address, &src_val, sizeof (ip->src_address));
8439
8440   if (dst)
8441     clib_memcpy (&ip->dst_address, &dst_val, sizeof (ip->dst_address));
8442
8443   if (proto)
8444     ip->protocol = proto_val;
8445
8446   ip_version_traffic_class_and_flow_label = 0;
8447
8448   if (version)
8449     ip_version_traffic_class_and_flow_label |= (version_val & 0xF) << 28;
8450
8451   if (traffic_class)
8452     ip_version_traffic_class_and_flow_label |=
8453       (traffic_class_val & 0xFF) << 20;
8454
8455   if (flow_label)
8456     ip_version_traffic_class_and_flow_label |= (flow_label_val & 0xFFFFF);
8457
8458   ip->ip_version_traffic_class_and_flow_label =
8459     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
8460
8461   if (payload_length)
8462     ip->payload_length = clib_host_to_net_u16 (payload_length_val);
8463
8464   if (hop_limit)
8465     ip->hop_limit = hop_limit_val;
8466
8467   *matchp = match;
8468   return 1;
8469 }
8470
8471 uword
8472 unformat_l3_match (unformat_input_t * input, va_list * args)
8473 {
8474   u8 **matchp = va_arg (*args, u8 **);
8475
8476   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
8477     {
8478       if (unformat (input, "ip4 %U", unformat_ip4_match, matchp))
8479         return 1;
8480       else if (unformat (input, "ip6 %U", unformat_ip6_match, matchp))
8481         return 1;
8482       else
8483         break;
8484     }
8485   return 0;
8486 }
8487
8488 uword
8489 unformat_vlan_tag (unformat_input_t * input, va_list * args)
8490 {
8491   u8 *tagp = va_arg (*args, u8 *);
8492   u32 tag;
8493
8494   if (unformat (input, "%d", &tag))
8495     {
8496       tagp[0] = (tag >> 8) & 0x0F;
8497       tagp[1] = tag & 0xFF;
8498       return 1;
8499     }
8500
8501   return 0;
8502 }
8503
8504 uword
8505 unformat_l2_match (unformat_input_t * input, va_list * args)
8506 {
8507   u8 **matchp = va_arg (*args, u8 **);
8508   u8 *match = 0;
8509   u8 src = 0;
8510   u8 src_val[6];
8511   u8 dst = 0;
8512   u8 dst_val[6];
8513   u8 proto = 0;
8514   u16 proto_val;
8515   u8 tag1 = 0;
8516   u8 tag1_val[2];
8517   u8 tag2 = 0;
8518   u8 tag2_val[2];
8519   int len = 14;
8520   u8 ignore_tag1 = 0;
8521   u8 ignore_tag2 = 0;
8522   u8 cos1 = 0;
8523   u8 cos2 = 0;
8524   u32 cos1_val = 0;
8525   u32 cos2_val = 0;
8526
8527   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
8528     {
8529       if (unformat (input, "src %U", unformat_ethernet_address, &src_val))
8530         src = 1;
8531       else
8532         if (unformat (input, "dst %U", unformat_ethernet_address, &dst_val))
8533         dst = 1;
8534       else if (unformat (input, "proto %U",
8535                          unformat_ethernet_type_host_byte_order, &proto_val))
8536         proto = 1;
8537       else if (unformat (input, "tag1 %U", unformat_vlan_tag, tag1_val))
8538         tag1 = 1;
8539       else if (unformat (input, "tag2 %U", unformat_vlan_tag, tag2_val))
8540         tag2 = 1;
8541       else if (unformat (input, "ignore-tag1"))
8542         ignore_tag1 = 1;
8543       else if (unformat (input, "ignore-tag2"))
8544         ignore_tag2 = 1;
8545       else if (unformat (input, "cos1 %d", &cos1_val))
8546         cos1 = 1;
8547       else if (unformat (input, "cos2 %d", &cos2_val))
8548         cos2 = 1;
8549       else
8550         break;
8551     }
8552   if ((src + dst + proto + tag1 + tag2 +
8553        ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
8554     return 0;
8555
8556   if (tag1 || ignore_tag1 || cos1)
8557     len = 18;
8558   if (tag2 || ignore_tag2 || cos2)
8559     len = 22;
8560
8561   vec_validate_aligned (match, len - 1, sizeof (u32x4));
8562
8563   if (dst)
8564     clib_memcpy (match, dst_val, 6);
8565
8566   if (src)
8567     clib_memcpy (match + 6, src_val, 6);
8568
8569   if (tag2)
8570     {
8571       /* inner vlan tag */
8572       match[19] = tag2_val[1];
8573       match[18] = tag2_val[0];
8574       if (cos2)
8575         match[18] |= (cos2_val & 0x7) << 5;
8576       if (proto)
8577         {
8578           match[21] = proto_val & 0xff;
8579           match[20] = proto_val >> 8;
8580         }
8581       if (tag1)
8582         {
8583           match[15] = tag1_val[1];
8584           match[14] = tag1_val[0];
8585         }
8586       if (cos1)
8587         match[14] |= (cos1_val & 0x7) << 5;
8588       *matchp = match;
8589       return 1;
8590     }
8591   if (tag1)
8592     {
8593       match[15] = tag1_val[1];
8594       match[14] = tag1_val[0];
8595       if (proto)
8596         {
8597           match[17] = proto_val & 0xff;
8598           match[16] = proto_val >> 8;
8599         }
8600       if (cos1)
8601         match[14] |= (cos1_val & 0x7) << 5;
8602
8603       *matchp = match;
8604       return 1;
8605     }
8606   if (cos2)
8607     match[18] |= (cos2_val & 0x7) << 5;
8608   if (cos1)
8609     match[14] |= (cos1_val & 0x7) << 5;
8610   if (proto)
8611     {
8612       match[13] = proto_val & 0xff;
8613       match[12] = proto_val >> 8;
8614     }
8615
8616   *matchp = match;
8617   return 1;
8618 }
8619
8620 uword
8621 unformat_qos_source (unformat_input_t * input, va_list * args)
8622 {
8623   int *qs = va_arg (*args, int *);
8624
8625   if (unformat (input, "ip"))
8626     *qs = QOS_SOURCE_IP;
8627   else if (unformat (input, "mpls"))
8628     *qs = QOS_SOURCE_MPLS;
8629   else if (unformat (input, "ext"))
8630     *qs = QOS_SOURCE_EXT;
8631   else if (unformat (input, "vlan"))
8632     *qs = QOS_SOURCE_VLAN;
8633   else
8634     return 0;
8635
8636   return 1;
8637 }
8638 #endif
8639
8640 uword
8641 api_unformat_classify_match (unformat_input_t * input, va_list * args)
8642 {
8643   u8 **matchp = va_arg (*args, u8 **);
8644   u32 skip_n_vectors = va_arg (*args, u32);
8645   u32 match_n_vectors = va_arg (*args, u32);
8646
8647   u8 *match = 0;
8648   u8 *l2 = 0;
8649   u8 *l3 = 0;
8650   u8 *l4 = 0;
8651
8652   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
8653     {
8654       if (unformat (input, "hex %U", unformat_hex_string, &match))
8655         ;
8656       else if (unformat (input, "l2 %U", unformat_l2_match, &l2))
8657         ;
8658       else if (unformat (input, "l3 %U", unformat_l3_match, &l3))
8659         ;
8660       else if (unformat (input, "l4 %U", unformat_l4_match, &l4))
8661         ;
8662       else
8663         break;
8664     }
8665
8666   if (l4 && !l3)
8667     {
8668       vec_free (match);
8669       vec_free (l2);
8670       vec_free (l4);
8671       return 0;
8672     }
8673
8674   if (match || l2 || l3 || l4)
8675     {
8676       if (l2 || l3 || l4)
8677         {
8678           /* "Win a free Ethernet header in every packet" */
8679           if (l2 == 0)
8680             vec_validate_aligned (l2, 13, sizeof (u32x4));
8681           match = l2;
8682           if (vec_len (l3))
8683             {
8684               vec_append_aligned (match, l3, sizeof (u32x4));
8685               vec_free (l3);
8686             }
8687           if (vec_len (l4))
8688             {
8689               vec_append_aligned (match, l4, sizeof (u32x4));
8690               vec_free (l4);
8691             }
8692         }
8693
8694       /* Make sure the vector is big enough even if key is all 0's */
8695       vec_validate_aligned
8696         (match, ((match_n_vectors + skip_n_vectors) * sizeof (u32x4)) - 1,
8697          sizeof (u32x4));
8698
8699       /* Set size, include skipped vectors */
8700       _vec_len (match) = (match_n_vectors + skip_n_vectors) * sizeof (u32x4);
8701
8702       *matchp = match;
8703
8704       return 1;
8705     }
8706
8707   return 0;
8708 }
8709
8710 static int
8711 api_classify_add_del_session (vat_main_t * vam)
8712 {
8713   unformat_input_t *i = vam->input;
8714   vl_api_classify_add_del_session_t *mp;
8715   int is_add = 1;
8716   u32 table_index = ~0;
8717   u32 hit_next_index = ~0;
8718   u32 opaque_index = ~0;
8719   u8 *match = 0;
8720   i32 advance = 0;
8721   u32 skip_n_vectors = 0;
8722   u32 match_n_vectors = 0;
8723   u32 action = 0;
8724   u32 metadata = 0;
8725   int ret;
8726
8727   /*
8728    * Warning: you have to supply skip_n and match_n
8729    * because the API client cant simply look at the classify
8730    * table object.
8731    */
8732
8733   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8734     {
8735       if (unformat (i, "del"))
8736         is_add = 0;
8737       else if (unformat (i, "hit-next %U", api_unformat_ip_next_index,
8738                          &hit_next_index))
8739         ;
8740       else if (unformat (i, "l2-hit-next %U", unformat_l2_next_index,
8741                          &hit_next_index))
8742         ;
8743       else if (unformat (i, "acl-hit-next %U", api_unformat_acl_next_index,
8744                          &hit_next_index))
8745         ;
8746       else if (unformat (i, "policer-hit-next %d", &hit_next_index))
8747         ;
8748       else if (unformat (i, "%U", unformat_policer_precolor, &opaque_index))
8749         ;
8750       else if (unformat (i, "opaque-index %d", &opaque_index))
8751         ;
8752       else if (unformat (i, "skip_n %d", &skip_n_vectors))
8753         ;
8754       else if (unformat (i, "match_n %d", &match_n_vectors))
8755         ;
8756       else if (unformat (i, "match %U", api_unformat_classify_match,
8757                          &match, skip_n_vectors, match_n_vectors))
8758         ;
8759       else if (unformat (i, "advance %d", &advance))
8760         ;
8761       else if (unformat (i, "table-index %d", &table_index))
8762         ;
8763       else if (unformat (i, "action set-ip4-fib-id %d", &metadata))
8764         action = 1;
8765       else if (unformat (i, "action set-ip6-fib-id %d", &metadata))
8766         action = 2;
8767       else if (unformat (i, "action %d", &action))
8768         ;
8769       else if (unformat (i, "metadata %d", &metadata))
8770         ;
8771       else
8772         break;
8773     }
8774
8775   if (table_index == ~0)
8776     {
8777       errmsg ("Table index required");
8778       return -99;
8779     }
8780
8781   if (is_add && match == 0)
8782     {
8783       errmsg ("Match value required");
8784       return -99;
8785     }
8786
8787   M2 (CLASSIFY_ADD_DEL_SESSION, mp, vec_len (match));
8788
8789   mp->is_add = is_add;
8790   mp->table_index = ntohl (table_index);
8791   mp->hit_next_index = ntohl (hit_next_index);
8792   mp->opaque_index = ntohl (opaque_index);
8793   mp->advance = ntohl (advance);
8794   mp->action = action;
8795   mp->metadata = ntohl (metadata);
8796   mp->match_len = ntohl (vec_len (match));
8797   clib_memcpy (mp->match, match, vec_len (match));
8798   vec_free (match);
8799
8800   S (mp);
8801   W (ret);
8802   return ret;
8803 }
8804
8805 static int
8806 api_classify_set_interface_ip_table (vat_main_t * vam)
8807 {
8808   unformat_input_t *i = vam->input;
8809   vl_api_classify_set_interface_ip_table_t *mp;
8810   u32 sw_if_index;
8811   int sw_if_index_set;
8812   u32 table_index = ~0;
8813   u8 is_ipv6 = 0;
8814   int ret;
8815
8816   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8817     {
8818       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8819         sw_if_index_set = 1;
8820       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8821         sw_if_index_set = 1;
8822       else if (unformat (i, "table %d", &table_index))
8823         ;
8824       else
8825         {
8826           clib_warning ("parse error '%U'", format_unformat_error, i);
8827           return -99;
8828         }
8829     }
8830
8831   if (sw_if_index_set == 0)
8832     {
8833       errmsg ("missing interface name or sw_if_index");
8834       return -99;
8835     }
8836
8837
8838   M (CLASSIFY_SET_INTERFACE_IP_TABLE, mp);
8839
8840   mp->sw_if_index = ntohl (sw_if_index);
8841   mp->table_index = ntohl (table_index);
8842   mp->is_ipv6 = is_ipv6;
8843
8844   S (mp);
8845   W (ret);
8846   return ret;
8847 }
8848
8849 static int
8850 api_classify_set_interface_l2_tables (vat_main_t * vam)
8851 {
8852   unformat_input_t *i = vam->input;
8853   vl_api_classify_set_interface_l2_tables_t *mp;
8854   u32 sw_if_index;
8855   int sw_if_index_set;
8856   u32 ip4_table_index = ~0;
8857   u32 ip6_table_index = ~0;
8858   u32 other_table_index = ~0;
8859   u32 is_input = 1;
8860   int ret;
8861
8862   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8863     {
8864       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8865         sw_if_index_set = 1;
8866       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8867         sw_if_index_set = 1;
8868       else if (unformat (i, "ip4-table %d", &ip4_table_index))
8869         ;
8870       else if (unformat (i, "ip6-table %d", &ip6_table_index))
8871         ;
8872       else if (unformat (i, "other-table %d", &other_table_index))
8873         ;
8874       else if (unformat (i, "is-input %d", &is_input))
8875         ;
8876       else
8877         {
8878           clib_warning ("parse error '%U'", format_unformat_error, i);
8879           return -99;
8880         }
8881     }
8882
8883   if (sw_if_index_set == 0)
8884     {
8885       errmsg ("missing interface name or sw_if_index");
8886       return -99;
8887     }
8888
8889
8890   M (CLASSIFY_SET_INTERFACE_L2_TABLES, mp);
8891
8892   mp->sw_if_index = ntohl (sw_if_index);
8893   mp->ip4_table_index = ntohl (ip4_table_index);
8894   mp->ip6_table_index = ntohl (ip6_table_index);
8895   mp->other_table_index = ntohl (other_table_index);
8896   mp->is_input = (u8) is_input;
8897
8898   S (mp);
8899   W (ret);
8900   return ret;
8901 }
8902
8903 static int
8904 api_set_ipfix_exporter (vat_main_t * vam)
8905 {
8906   unformat_input_t *i = vam->input;
8907   vl_api_set_ipfix_exporter_t *mp;
8908   ip4_address_t collector_address;
8909   u8 collector_address_set = 0;
8910   u32 collector_port = ~0;
8911   ip4_address_t src_address;
8912   u8 src_address_set = 0;
8913   u32 vrf_id = ~0;
8914   u32 path_mtu = ~0;
8915   u32 template_interval = ~0;
8916   u8 udp_checksum = 0;
8917   int ret;
8918
8919   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8920     {
8921       if (unformat (i, "collector_address %U", unformat_ip4_address,
8922                     &collector_address))
8923         collector_address_set = 1;
8924       else if (unformat (i, "collector_port %d", &collector_port))
8925         ;
8926       else if (unformat (i, "src_address %U", unformat_ip4_address,
8927                          &src_address))
8928         src_address_set = 1;
8929       else if (unformat (i, "vrf_id %d", &vrf_id))
8930         ;
8931       else if (unformat (i, "path_mtu %d", &path_mtu))
8932         ;
8933       else if (unformat (i, "template_interval %d", &template_interval))
8934         ;
8935       else if (unformat (i, "udp_checksum"))
8936         udp_checksum = 1;
8937       else
8938         break;
8939     }
8940
8941   if (collector_address_set == 0)
8942     {
8943       errmsg ("collector_address required");
8944       return -99;
8945     }
8946
8947   if (src_address_set == 0)
8948     {
8949       errmsg ("src_address required");
8950       return -99;
8951     }
8952
8953   M (SET_IPFIX_EXPORTER, mp);
8954
8955   memcpy (mp->collector_address.un.ip4, collector_address.data,
8956           sizeof (collector_address.data));
8957   mp->collector_port = htons ((u16) collector_port);
8958   memcpy (mp->src_address.un.ip4, src_address.data,
8959           sizeof (src_address.data));
8960   mp->vrf_id = htonl (vrf_id);
8961   mp->path_mtu = htonl (path_mtu);
8962   mp->template_interval = htonl (template_interval);
8963   mp->udp_checksum = udp_checksum;
8964
8965   S (mp);
8966   W (ret);
8967   return ret;
8968 }
8969
8970 static int
8971 api_set_ipfix_classify_stream (vat_main_t * vam)
8972 {
8973   unformat_input_t *i = vam->input;
8974   vl_api_set_ipfix_classify_stream_t *mp;
8975   u32 domain_id = 0;
8976   u32 src_port = UDP_DST_PORT_ipfix;
8977   int ret;
8978
8979   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8980     {
8981       if (unformat (i, "domain %d", &domain_id))
8982         ;
8983       else if (unformat (i, "src_port %d", &src_port))
8984         ;
8985       else
8986         {
8987           errmsg ("unknown input `%U'", format_unformat_error, i);
8988           return -99;
8989         }
8990     }
8991
8992   M (SET_IPFIX_CLASSIFY_STREAM, mp);
8993
8994   mp->domain_id = htonl (domain_id);
8995   mp->src_port = htons ((u16) src_port);
8996
8997   S (mp);
8998   W (ret);
8999   return ret;
9000 }
9001
9002 static int
9003 api_ipfix_classify_table_add_del (vat_main_t * vam)
9004 {
9005   unformat_input_t *i = vam->input;
9006   vl_api_ipfix_classify_table_add_del_t *mp;
9007   int is_add = -1;
9008   u32 classify_table_index = ~0;
9009   u8 ip_version = 0;
9010   u8 transport_protocol = 255;
9011   int ret;
9012
9013   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9014     {
9015       if (unformat (i, "add"))
9016         is_add = 1;
9017       else if (unformat (i, "del"))
9018         is_add = 0;
9019       else if (unformat (i, "table %d", &classify_table_index))
9020         ;
9021       else if (unformat (i, "ip4"))
9022         ip_version = 4;
9023       else if (unformat (i, "ip6"))
9024         ip_version = 6;
9025       else if (unformat (i, "tcp"))
9026         transport_protocol = 6;
9027       else if (unformat (i, "udp"))
9028         transport_protocol = 17;
9029       else
9030         {
9031           errmsg ("unknown input `%U'", format_unformat_error, i);
9032           return -99;
9033         }
9034     }
9035
9036   if (is_add == -1)
9037     {
9038       errmsg ("expecting: add|del");
9039       return -99;
9040     }
9041   if (classify_table_index == ~0)
9042     {
9043       errmsg ("classifier table not specified");
9044       return -99;
9045     }
9046   if (ip_version == 0)
9047     {
9048       errmsg ("IP version not specified");
9049       return -99;
9050     }
9051
9052   M (IPFIX_CLASSIFY_TABLE_ADD_DEL, mp);
9053
9054   mp->is_add = is_add;
9055   mp->table_id = htonl (classify_table_index);
9056   mp->ip_version = ip_version;
9057   mp->transport_protocol = transport_protocol;
9058
9059   S (mp);
9060   W (ret);
9061   return ret;
9062 }
9063
9064 static int
9065 api_get_node_index (vat_main_t * vam)
9066 {
9067   unformat_input_t *i = vam->input;
9068   vl_api_get_node_index_t *mp;
9069   u8 *name = 0;
9070   int ret;
9071
9072   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9073     {
9074       if (unformat (i, "node %s", &name))
9075         ;
9076       else
9077         break;
9078     }
9079   if (name == 0)
9080     {
9081       errmsg ("node name required");
9082       return -99;
9083     }
9084   if (vec_len (name) >= ARRAY_LEN (mp->node_name))
9085     {
9086       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
9087       return -99;
9088     }
9089
9090   M (GET_NODE_INDEX, mp);
9091   clib_memcpy (mp->node_name, name, vec_len (name));
9092   vec_free (name);
9093
9094   S (mp);
9095   W (ret);
9096   return ret;
9097 }
9098
9099 static int
9100 api_get_next_index (vat_main_t * vam)
9101 {
9102   unformat_input_t *i = vam->input;
9103   vl_api_get_next_index_t *mp;
9104   u8 *node_name = 0, *next_node_name = 0;
9105   int ret;
9106
9107   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9108     {
9109       if (unformat (i, "node-name %s", &node_name))
9110         ;
9111       else if (unformat (i, "next-node-name %s", &next_node_name))
9112         break;
9113     }
9114
9115   if (node_name == 0)
9116     {
9117       errmsg ("node name required");
9118       return -99;
9119     }
9120   if (vec_len (node_name) >= ARRAY_LEN (mp->node_name))
9121     {
9122       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
9123       return -99;
9124     }
9125
9126   if (next_node_name == 0)
9127     {
9128       errmsg ("next node name required");
9129       return -99;
9130     }
9131   if (vec_len (next_node_name) >= ARRAY_LEN (mp->next_name))
9132     {
9133       errmsg ("next node name too long, max %d", ARRAY_LEN (mp->next_name));
9134       return -99;
9135     }
9136
9137   M (GET_NEXT_INDEX, mp);
9138   clib_memcpy (mp->node_name, node_name, vec_len (node_name));
9139   clib_memcpy (mp->next_name, next_node_name, vec_len (next_node_name));
9140   vec_free (node_name);
9141   vec_free (next_node_name);
9142
9143   S (mp);
9144   W (ret);
9145   return ret;
9146 }
9147
9148 static int
9149 api_add_node_next (vat_main_t * vam)
9150 {
9151   unformat_input_t *i = vam->input;
9152   vl_api_add_node_next_t *mp;
9153   u8 *name = 0;
9154   u8 *next = 0;
9155   int ret;
9156
9157   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9158     {
9159       if (unformat (i, "node %s", &name))
9160         ;
9161       else if (unformat (i, "next %s", &next))
9162         ;
9163       else
9164         break;
9165     }
9166   if (name == 0)
9167     {
9168       errmsg ("node name required");
9169       return -99;
9170     }
9171   if (vec_len (name) >= ARRAY_LEN (mp->node_name))
9172     {
9173       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
9174       return -99;
9175     }
9176   if (next == 0)
9177     {
9178       errmsg ("next node required");
9179       return -99;
9180     }
9181   if (vec_len (next) >= ARRAY_LEN (mp->next_name))
9182     {
9183       errmsg ("next name too long, max %d", ARRAY_LEN (mp->next_name));
9184       return -99;
9185     }
9186
9187   M (ADD_NODE_NEXT, mp);
9188   clib_memcpy (mp->node_name, name, vec_len (name));
9189   clib_memcpy (mp->next_name, next, vec_len (next));
9190   vec_free (name);
9191   vec_free (next);
9192
9193   S (mp);
9194   W (ret);
9195   return ret;
9196 }
9197
9198 static void vl_api_sw_interface_tap_v2_details_t_handler
9199   (vl_api_sw_interface_tap_v2_details_t * mp)
9200 {
9201   vat_main_t *vam = &vat_main;
9202
9203   u8 *ip4 =
9204     format (0, "%U/%d", format_ip4_address, mp->host_ip4_prefix.address,
9205             mp->host_ip4_prefix.len);
9206   u8 *ip6 =
9207     format (0, "%U/%d", format_ip6_address, mp->host_ip6_prefix.address,
9208             mp->host_ip6_prefix.len);
9209
9210   print (vam->ofp,
9211          "\n%-16s %-12d %-5d %-12d %-12d %-14U %-30s %-20s %-20s %-30s 0x%-08x",
9212          mp->dev_name, ntohl (mp->sw_if_index), ntohl (mp->id),
9213          ntohs (mp->rx_ring_sz), ntohs (mp->tx_ring_sz),
9214          format_ethernet_address, mp->host_mac_addr, mp->host_namespace,
9215          mp->host_bridge, ip4, ip6, ntohl (mp->tap_flags));
9216
9217   vec_free (ip4);
9218   vec_free (ip6);
9219 }
9220
9221 static void vl_api_sw_interface_tap_v2_details_t_handler_json
9222   (vl_api_sw_interface_tap_v2_details_t * mp)
9223 {
9224   vat_main_t *vam = &vat_main;
9225   vat_json_node_t *node = NULL;
9226
9227   if (VAT_JSON_ARRAY != vam->json_tree.type)
9228     {
9229       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9230       vat_json_init_array (&vam->json_tree);
9231     }
9232   node = vat_json_array_add (&vam->json_tree);
9233
9234   vat_json_init_object (node);
9235   vat_json_object_add_uint (node, "id", ntohl (mp->id));
9236   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
9237   vat_json_object_add_uint (node, "tap_flags", ntohl (mp->tap_flags));
9238   vat_json_object_add_string_copy (node, "dev_name", mp->dev_name);
9239   vat_json_object_add_uint (node, "rx_ring_sz", ntohs (mp->rx_ring_sz));
9240   vat_json_object_add_uint (node, "tx_ring_sz", ntohs (mp->tx_ring_sz));
9241   vat_json_object_add_string_copy (node, "host_mac_addr",
9242                                    format (0, "%U", format_ethernet_address,
9243                                            &mp->host_mac_addr));
9244   vat_json_object_add_string_copy (node, "host_namespace",
9245                                    mp->host_namespace);
9246   vat_json_object_add_string_copy (node, "host_bridge", mp->host_bridge);
9247   vat_json_object_add_string_copy (node, "host_ip4_addr",
9248                                    format (0, "%U/%d", format_ip4_address,
9249                                            mp->host_ip4_prefix.address,
9250                                            mp->host_ip4_prefix.len));
9251   vat_json_object_add_string_copy (node, "host_ip6_prefix",
9252                                    format (0, "%U/%d", format_ip6_address,
9253                                            mp->host_ip6_prefix.address,
9254                                            mp->host_ip6_prefix.len));
9255
9256 }
9257
9258 static int
9259 api_sw_interface_tap_v2_dump (vat_main_t * vam)
9260 {
9261   vl_api_sw_interface_tap_v2_dump_t *mp;
9262   vl_api_control_ping_t *mp_ping;
9263   int ret;
9264
9265   print (vam->ofp,
9266          "\n%-16s %-12s %-5s %-12s %-12s %-14s %-30s %-20s %-20s %-30s",
9267          "dev_name", "sw_if_index", "id", "rx_ring_sz", "tx_ring_sz",
9268          "host_mac_addr", "host_namespace", "host_bridge", "host_ip4_addr",
9269          "host_ip6_addr");
9270
9271   /* Get list of tap interfaces */
9272   M (SW_INTERFACE_TAP_V2_DUMP, mp);
9273   S (mp);
9274
9275   /* Use a control ping for synchronization */
9276   MPING (CONTROL_PING, mp_ping);
9277   S (mp_ping);
9278
9279   W (ret);
9280   return ret;
9281 }
9282
9283 static void vl_api_sw_interface_virtio_pci_details_t_handler
9284   (vl_api_sw_interface_virtio_pci_details_t * mp)
9285 {
9286   vat_main_t *vam = &vat_main;
9287
9288   typedef union
9289   {
9290     struct
9291     {
9292       u16 domain;
9293       u8 bus;
9294       u8 slot:5;
9295       u8 function:3;
9296     };
9297     u32 as_u32;
9298   } pci_addr_t;
9299   pci_addr_t addr;
9300
9301   addr.domain = ntohs (mp->pci_addr.domain);
9302   addr.bus = mp->pci_addr.bus;
9303   addr.slot = mp->pci_addr.slot;
9304   addr.function = mp->pci_addr.function;
9305
9306   u8 *pci_addr = format (0, "%04x:%02x:%02x.%x", addr.domain, addr.bus,
9307                          addr.slot, addr.function);
9308
9309   print (vam->ofp,
9310          "\n%-12s %-12d %-12d %-12d %-17U 0x%-08llx",
9311          pci_addr, ntohl (mp->sw_if_index),
9312          ntohs (mp->rx_ring_sz), ntohs (mp->tx_ring_sz),
9313          format_ethernet_address, mp->mac_addr,
9314          clib_net_to_host_u64 (mp->features));
9315   vec_free (pci_addr);
9316 }
9317
9318 static void vl_api_sw_interface_virtio_pci_details_t_handler_json
9319   (vl_api_sw_interface_virtio_pci_details_t * mp)
9320 {
9321   vat_main_t *vam = &vat_main;
9322   vat_json_node_t *node = NULL;
9323   vlib_pci_addr_t pci_addr;
9324
9325   if (VAT_JSON_ARRAY != vam->json_tree.type)
9326     {
9327       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9328       vat_json_init_array (&vam->json_tree);
9329     }
9330   node = vat_json_array_add (&vam->json_tree);
9331
9332   pci_addr.domain = ntohs (mp->pci_addr.domain);
9333   pci_addr.bus = mp->pci_addr.bus;
9334   pci_addr.slot = mp->pci_addr.slot;
9335   pci_addr.function = mp->pci_addr.function;
9336
9337   vat_json_init_object (node);
9338   vat_json_object_add_uint (node, "pci-addr", pci_addr.as_u32);
9339   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
9340   vat_json_object_add_uint (node, "rx_ring_sz", ntohs (mp->rx_ring_sz));
9341   vat_json_object_add_uint (node, "tx_ring_sz", ntohs (mp->tx_ring_sz));
9342   vat_json_object_add_uint (node, "features",
9343                             clib_net_to_host_u64 (mp->features));
9344   vat_json_object_add_string_copy (node, "mac_addr",
9345                                    format (0, "%U", format_ethernet_address,
9346                                            &mp->mac_addr));
9347 }
9348
9349 static int
9350 api_sw_interface_virtio_pci_dump (vat_main_t * vam)
9351 {
9352   vl_api_sw_interface_virtio_pci_dump_t *mp;
9353   vl_api_control_ping_t *mp_ping;
9354   int ret;
9355
9356   print (vam->ofp,
9357          "\n%-12s %-12s %-12s %-12s %-17s %-08s",
9358          "pci_addr", "sw_if_index", "rx_ring_sz", "tx_ring_sz",
9359          "mac_addr", "features");
9360
9361   /* Get list of tap interfaces */
9362   M (SW_INTERFACE_VIRTIO_PCI_DUMP, mp);
9363   S (mp);
9364
9365   /* Use a control ping for synchronization */
9366   MPING (CONTROL_PING, mp_ping);
9367   S (mp_ping);
9368
9369   W (ret);
9370   return ret;
9371 }
9372
9373 static int
9374 api_vxlan_offload_rx (vat_main_t * vam)
9375 {
9376   unformat_input_t *line_input = vam->input;
9377   vl_api_vxlan_offload_rx_t *mp;
9378   u32 hw_if_index = ~0, rx_if_index = ~0;
9379   u8 is_add = 1;
9380   int ret;
9381
9382   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
9383     {
9384       if (unformat (line_input, "del"))
9385         is_add = 0;
9386       else if (unformat (line_input, "hw %U", api_unformat_hw_if_index, vam,
9387                          &hw_if_index))
9388         ;
9389       else if (unformat (line_input, "hw hw_if_index %u", &hw_if_index))
9390         ;
9391       else if (unformat (line_input, "rx %U", api_unformat_sw_if_index, vam,
9392                          &rx_if_index))
9393         ;
9394       else if (unformat (line_input, "rx sw_if_index %u", &rx_if_index))
9395         ;
9396       else
9397         {
9398           errmsg ("parse error '%U'", format_unformat_error, line_input);
9399           return -99;
9400         }
9401     }
9402
9403   if (hw_if_index == ~0)
9404     {
9405       errmsg ("no hw interface");
9406       return -99;
9407     }
9408
9409   if (rx_if_index == ~0)
9410     {
9411       errmsg ("no rx tunnel");
9412       return -99;
9413     }
9414
9415   M (VXLAN_OFFLOAD_RX, mp);
9416
9417   mp->hw_if_index = ntohl (hw_if_index);
9418   mp->sw_if_index = ntohl (rx_if_index);
9419   mp->enable = is_add;
9420
9421   S (mp);
9422   W (ret);
9423   return ret;
9424 }
9425
9426 static uword unformat_vxlan_decap_next
9427   (unformat_input_t * input, va_list * args)
9428 {
9429   u32 *result = va_arg (*args, u32 *);
9430   u32 tmp;
9431
9432   if (unformat (input, "l2"))
9433     *result = VXLAN_INPUT_NEXT_L2_INPUT;
9434   else if (unformat (input, "%d", &tmp))
9435     *result = tmp;
9436   else
9437     return 0;
9438   return 1;
9439 }
9440
9441 static int
9442 api_vxlan_add_del_tunnel (vat_main_t * vam)
9443 {
9444   unformat_input_t *line_input = vam->input;
9445   vl_api_vxlan_add_del_tunnel_t *mp;
9446   ip46_address_t src, dst;
9447   u8 is_add = 1;
9448   u8 ipv4_set = 0, ipv6_set = 0;
9449   u8 src_set = 0;
9450   u8 dst_set = 0;
9451   u8 grp_set = 0;
9452   u32 instance = ~0;
9453   u32 mcast_sw_if_index = ~0;
9454   u32 encap_vrf_id = 0;
9455   u32 decap_next_index = ~0;
9456   u32 vni = 0;
9457   int ret;
9458
9459   /* Can't "universally zero init" (={0}) due to GCC bug 53119 */
9460   clib_memset (&src, 0, sizeof src);
9461   clib_memset (&dst, 0, sizeof dst);
9462
9463   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
9464     {
9465       if (unformat (line_input, "del"))
9466         is_add = 0;
9467       else if (unformat (line_input, "instance %d", &instance))
9468         ;
9469       else
9470         if (unformat (line_input, "src %U", unformat_ip4_address, &src.ip4))
9471         {
9472           ipv4_set = 1;
9473           src_set = 1;
9474         }
9475       else
9476         if (unformat (line_input, "dst %U", unformat_ip4_address, &dst.ip4))
9477         {
9478           ipv4_set = 1;
9479           dst_set = 1;
9480         }
9481       else
9482         if (unformat (line_input, "src %U", unformat_ip6_address, &src.ip6))
9483         {
9484           ipv6_set = 1;
9485           src_set = 1;
9486         }
9487       else
9488         if (unformat (line_input, "dst %U", unformat_ip6_address, &dst.ip6))
9489         {
9490           ipv6_set = 1;
9491           dst_set = 1;
9492         }
9493       else if (unformat (line_input, "group %U %U",
9494                          unformat_ip4_address, &dst.ip4,
9495                          api_unformat_sw_if_index, vam, &mcast_sw_if_index))
9496         {
9497           grp_set = dst_set = 1;
9498           ipv4_set = 1;
9499         }
9500       else if (unformat (line_input, "group %U",
9501                          unformat_ip4_address, &dst.ip4))
9502         {
9503           grp_set = dst_set = 1;
9504           ipv4_set = 1;
9505         }
9506       else if (unformat (line_input, "group %U %U",
9507                          unformat_ip6_address, &dst.ip6,
9508                          api_unformat_sw_if_index, vam, &mcast_sw_if_index))
9509         {
9510           grp_set = dst_set = 1;
9511           ipv6_set = 1;
9512         }
9513       else if (unformat (line_input, "group %U",
9514                          unformat_ip6_address, &dst.ip6))
9515         {
9516           grp_set = dst_set = 1;
9517           ipv6_set = 1;
9518         }
9519       else
9520         if (unformat (line_input, "mcast_sw_if_index %u", &mcast_sw_if_index))
9521         ;
9522       else if (unformat (line_input, "encap-vrf-id %d", &encap_vrf_id))
9523         ;
9524       else if (unformat (line_input, "decap-next %U",
9525                          unformat_vxlan_decap_next, &decap_next_index))
9526         ;
9527       else if (unformat (line_input, "vni %d", &vni))
9528         ;
9529       else
9530         {
9531           errmsg ("parse error '%U'", format_unformat_error, line_input);
9532           return -99;
9533         }
9534     }
9535
9536   if (src_set == 0)
9537     {
9538       errmsg ("tunnel src address not specified");
9539       return -99;
9540     }
9541   if (dst_set == 0)
9542     {
9543       errmsg ("tunnel dst address not specified");
9544       return -99;
9545     }
9546
9547   if (grp_set && !ip46_address_is_multicast (&dst))
9548     {
9549       errmsg ("tunnel group address not multicast");
9550       return -99;
9551     }
9552   if (grp_set && mcast_sw_if_index == ~0)
9553     {
9554       errmsg ("tunnel nonexistent multicast device");
9555       return -99;
9556     }
9557   if (grp_set == 0 && ip46_address_is_multicast (&dst))
9558     {
9559       errmsg ("tunnel dst address must be unicast");
9560       return -99;
9561     }
9562
9563
9564   if (ipv4_set && ipv6_set)
9565     {
9566       errmsg ("both IPv4 and IPv6 addresses specified");
9567       return -99;
9568     }
9569
9570   if ((vni == 0) || (vni >> 24))
9571     {
9572       errmsg ("vni not specified or out of range");
9573       return -99;
9574     }
9575
9576   M (VXLAN_ADD_DEL_TUNNEL, mp);
9577
9578   if (ipv6_set)
9579     {
9580       clib_memcpy (mp->src_address.un.ip6, &src.ip6, sizeof (src.ip6));
9581       clib_memcpy (mp->dst_address.un.ip6, &dst.ip6, sizeof (dst.ip6));
9582     }
9583   else
9584     {
9585       clib_memcpy (mp->src_address.un.ip4, &src.ip4, sizeof (src.ip4));
9586       clib_memcpy (mp->dst_address.un.ip4, &dst.ip4, sizeof (dst.ip4));
9587     }
9588   mp->src_address.af = ipv6_set;
9589   mp->dst_address.af = ipv6_set;
9590
9591   mp->instance = htonl (instance);
9592   mp->encap_vrf_id = ntohl (encap_vrf_id);
9593   mp->decap_next_index = ntohl (decap_next_index);
9594   mp->mcast_sw_if_index = ntohl (mcast_sw_if_index);
9595   mp->vni = ntohl (vni);
9596   mp->is_add = is_add;
9597
9598   S (mp);
9599   W (ret);
9600   return ret;
9601 }
9602
9603 static void vl_api_vxlan_tunnel_details_t_handler
9604   (vl_api_vxlan_tunnel_details_t * mp)
9605 {
9606   vat_main_t *vam = &vat_main;
9607   ip46_address_t src =
9608     to_ip46 (mp->dst_address.af, (u8 *) & mp->dst_address.un);
9609   ip46_address_t dst =
9610     to_ip46 (mp->dst_address.af, (u8 *) & mp->src_address.un);
9611
9612   print (vam->ofp, "%11d%11d%24U%24U%14d%18d%13d%19d",
9613          ntohl (mp->sw_if_index),
9614          ntohl (mp->instance),
9615          format_ip46_address, &src, IP46_TYPE_ANY,
9616          format_ip46_address, &dst, IP46_TYPE_ANY,
9617          ntohl (mp->encap_vrf_id),
9618          ntohl (mp->decap_next_index), ntohl (mp->vni),
9619          ntohl (mp->mcast_sw_if_index));
9620 }
9621
9622 static void vl_api_vxlan_tunnel_details_t_handler_json
9623   (vl_api_vxlan_tunnel_details_t * mp)
9624 {
9625   vat_main_t *vam = &vat_main;
9626   vat_json_node_t *node = NULL;
9627
9628   if (VAT_JSON_ARRAY != vam->json_tree.type)
9629     {
9630       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9631       vat_json_init_array (&vam->json_tree);
9632     }
9633   node = vat_json_array_add (&vam->json_tree);
9634
9635   vat_json_init_object (node);
9636   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
9637
9638   vat_json_object_add_uint (node, "instance", ntohl (mp->instance));
9639
9640   if (mp->src_address.af)
9641     {
9642       struct in6_addr ip6;
9643
9644       clib_memcpy (&ip6, mp->src_address.un.ip6, sizeof (ip6));
9645       vat_json_object_add_ip6 (node, "src_address", ip6);
9646       clib_memcpy (&ip6, mp->dst_address.un.ip6, sizeof (ip6));
9647       vat_json_object_add_ip6 (node, "dst_address", ip6);
9648     }
9649   else
9650     {
9651       struct in_addr ip4;
9652
9653       clib_memcpy (&ip4, mp->src_address.un.ip4, sizeof (ip4));
9654       vat_json_object_add_ip4 (node, "src_address", ip4);
9655       clib_memcpy (&ip4, mp->dst_address.un.ip4, sizeof (ip4));
9656       vat_json_object_add_ip4 (node, "dst_address", ip4);
9657     }
9658   vat_json_object_add_uint (node, "encap_vrf_id", ntohl (mp->encap_vrf_id));
9659   vat_json_object_add_uint (node, "decap_next_index",
9660                             ntohl (mp->decap_next_index));
9661   vat_json_object_add_uint (node, "vni", ntohl (mp->vni));
9662   vat_json_object_add_uint (node, "mcast_sw_if_index",
9663                             ntohl (mp->mcast_sw_if_index));
9664 }
9665
9666 static int
9667 api_vxlan_tunnel_dump (vat_main_t * vam)
9668 {
9669   unformat_input_t *i = vam->input;
9670   vl_api_vxlan_tunnel_dump_t *mp;
9671   vl_api_control_ping_t *mp_ping;
9672   u32 sw_if_index;
9673   u8 sw_if_index_set = 0;
9674   int ret;
9675
9676   /* Parse args required to build the message */
9677   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9678     {
9679       if (unformat (i, "sw_if_index %d", &sw_if_index))
9680         sw_if_index_set = 1;
9681       else
9682         break;
9683     }
9684
9685   if (sw_if_index_set == 0)
9686     {
9687       sw_if_index = ~0;
9688     }
9689
9690   if (!vam->json_output)
9691     {
9692       print (vam->ofp, "%11s%11s%24s%24s%14s%18s%13s%19s",
9693              "sw_if_index", "instance", "src_address", "dst_address",
9694              "encap_vrf_id", "decap_next_index", "vni", "mcast_sw_if_index");
9695     }
9696
9697   /* Get list of vxlan-tunnel interfaces */
9698   M (VXLAN_TUNNEL_DUMP, mp);
9699
9700   mp->sw_if_index = htonl (sw_if_index);
9701
9702   S (mp);
9703
9704   /* Use a control ping for synchronization */
9705   MPING (CONTROL_PING, mp_ping);
9706   S (mp_ping);
9707
9708   W (ret);
9709   return ret;
9710 }
9711
9712 static int
9713 api_gre_tunnel_add_del (vat_main_t * vam)
9714 {
9715   unformat_input_t *line_input = vam->input;
9716   vl_api_address_t src = { }, dst =
9717   {
9718   };
9719   vl_api_gre_tunnel_add_del_t *mp;
9720   vl_api_gre_tunnel_type_t t_type;
9721   u8 is_add = 1;
9722   u8 src_set = 0;
9723   u8 dst_set = 0;
9724   u32 outer_table_id = 0;
9725   u32 session_id = 0;
9726   u32 instance = ~0;
9727   int ret;
9728
9729   t_type = GRE_API_TUNNEL_TYPE_L3;
9730
9731   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
9732     {
9733       if (unformat (line_input, "del"))
9734         is_add = 0;
9735       else if (unformat (line_input, "instance %d", &instance))
9736         ;
9737       else if (unformat (line_input, "src %U", unformat_vl_api_address, &src))
9738         {
9739           src_set = 1;
9740         }
9741       else if (unformat (line_input, "dst %U", unformat_vl_api_address, &dst))
9742         {
9743           dst_set = 1;
9744         }
9745       else if (unformat (line_input, "outer-table-id %d", &outer_table_id))
9746         ;
9747       else if (unformat (line_input, "teb"))
9748         t_type = GRE_API_TUNNEL_TYPE_TEB;
9749       else if (unformat (line_input, "erspan %d", &session_id))
9750         t_type = GRE_API_TUNNEL_TYPE_ERSPAN;
9751       else
9752         {
9753           errmsg ("parse error '%U'", format_unformat_error, line_input);
9754           return -99;
9755         }
9756     }
9757
9758   if (src_set == 0)
9759     {
9760       errmsg ("tunnel src address not specified");
9761       return -99;
9762     }
9763   if (dst_set == 0)
9764     {
9765       errmsg ("tunnel dst address not specified");
9766       return -99;
9767     }
9768
9769   M (GRE_TUNNEL_ADD_DEL, mp);
9770
9771   clib_memcpy (&mp->tunnel.src, &src, sizeof (mp->tunnel.src));
9772   clib_memcpy (&mp->tunnel.dst, &dst, sizeof (mp->tunnel.dst));
9773
9774   mp->tunnel.instance = htonl (instance);
9775   mp->tunnel.outer_table_id = htonl (outer_table_id);
9776   mp->is_add = is_add;
9777   mp->tunnel.session_id = htons ((u16) session_id);
9778   mp->tunnel.type = htonl (t_type);
9779
9780   S (mp);
9781   W (ret);
9782   return ret;
9783 }
9784
9785 static void vl_api_gre_tunnel_details_t_handler
9786   (vl_api_gre_tunnel_details_t * mp)
9787 {
9788   vat_main_t *vam = &vat_main;
9789
9790   print (vam->ofp, "%11d%11d%24U%24U%13d%14d%12d",
9791          ntohl (mp->tunnel.sw_if_index),
9792          ntohl (mp->tunnel.instance),
9793          format_vl_api_address, &mp->tunnel.src,
9794          format_vl_api_address, &mp->tunnel.dst,
9795          mp->tunnel.type, ntohl (mp->tunnel.outer_table_id),
9796          ntohl (mp->tunnel.session_id));
9797 }
9798
9799 static void vl_api_gre_tunnel_details_t_handler_json
9800   (vl_api_gre_tunnel_details_t * mp)
9801 {
9802   vat_main_t *vam = &vat_main;
9803   vat_json_node_t *node = NULL;
9804
9805   if (VAT_JSON_ARRAY != vam->json_tree.type)
9806     {
9807       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9808       vat_json_init_array (&vam->json_tree);
9809     }
9810   node = vat_json_array_add (&vam->json_tree);
9811
9812   vat_json_init_object (node);
9813   vat_json_object_add_uint (node, "sw_if_index",
9814                             ntohl (mp->tunnel.sw_if_index));
9815   vat_json_object_add_uint (node, "instance", ntohl (mp->tunnel.instance));
9816
9817   vat_json_object_add_address (node, "src", &mp->tunnel.src);
9818   vat_json_object_add_address (node, "dst", &mp->tunnel.dst);
9819   vat_json_object_add_uint (node, "tunnel_type", mp->tunnel.type);
9820   vat_json_object_add_uint (node, "outer_table_id",
9821                             ntohl (mp->tunnel.outer_table_id));
9822   vat_json_object_add_uint (node, "session_id", mp->tunnel.session_id);
9823 }
9824
9825 static int
9826 api_gre_tunnel_dump (vat_main_t * vam)
9827 {
9828   unformat_input_t *i = vam->input;
9829   vl_api_gre_tunnel_dump_t *mp;
9830   vl_api_control_ping_t *mp_ping;
9831   u32 sw_if_index;
9832   u8 sw_if_index_set = 0;
9833   int ret;
9834
9835   /* Parse args required to build the message */
9836   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9837     {
9838       if (unformat (i, "sw_if_index %d", &sw_if_index))
9839         sw_if_index_set = 1;
9840       else
9841         break;
9842     }
9843
9844   if (sw_if_index_set == 0)
9845     {
9846       sw_if_index = ~0;
9847     }
9848
9849   if (!vam->json_output)
9850     {
9851       print (vam->ofp, "%11s%11s%24s%24s%13s%14s%12s",
9852              "sw_if_index", "instance", "src_address", "dst_address",
9853              "tunnel_type", "outer_fib_id", "session_id");
9854     }
9855
9856   /* Get list of gre-tunnel interfaces */
9857   M (GRE_TUNNEL_DUMP, mp);
9858
9859   mp->sw_if_index = htonl (sw_if_index);
9860
9861   S (mp);
9862
9863   /* Use a control ping for synchronization */
9864   MPING (CONTROL_PING, mp_ping);
9865   S (mp_ping);
9866
9867   W (ret);
9868   return ret;
9869 }
9870
9871 static int
9872 api_l2_fib_clear_table (vat_main_t * vam)
9873 {
9874 //  unformat_input_t * i = vam->input;
9875   vl_api_l2_fib_clear_table_t *mp;
9876   int ret;
9877
9878   M (L2_FIB_CLEAR_TABLE, mp);
9879
9880   S (mp);
9881   W (ret);
9882   return ret;
9883 }
9884
9885 static int
9886 api_l2_interface_efp_filter (vat_main_t * vam)
9887 {
9888   unformat_input_t *i = vam->input;
9889   vl_api_l2_interface_efp_filter_t *mp;
9890   u32 sw_if_index;
9891   u8 enable = 1;
9892   u8 sw_if_index_set = 0;
9893   int ret;
9894
9895   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9896     {
9897       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
9898         sw_if_index_set = 1;
9899       else if (unformat (i, "sw_if_index %d", &sw_if_index))
9900         sw_if_index_set = 1;
9901       else if (unformat (i, "enable"))
9902         enable = 1;
9903       else if (unformat (i, "disable"))
9904         enable = 0;
9905       else
9906         {
9907           clib_warning ("parse error '%U'", format_unformat_error, i);
9908           return -99;
9909         }
9910     }
9911
9912   if (sw_if_index_set == 0)
9913     {
9914       errmsg ("missing sw_if_index");
9915       return -99;
9916     }
9917
9918   M (L2_INTERFACE_EFP_FILTER, mp);
9919
9920   mp->sw_if_index = ntohl (sw_if_index);
9921   mp->enable_disable = enable;
9922
9923   S (mp);
9924   W (ret);
9925   return ret;
9926 }
9927
9928 #define foreach_vtr_op                          \
9929 _("disable",  L2_VTR_DISABLED)                  \
9930 _("push-1",  L2_VTR_PUSH_1)                     \
9931 _("push-2",  L2_VTR_PUSH_2)                     \
9932 _("pop-1",  L2_VTR_POP_1)                       \
9933 _("pop-2",  L2_VTR_POP_2)                       \
9934 _("translate-1-1",  L2_VTR_TRANSLATE_1_1)       \
9935 _("translate-1-2",  L2_VTR_TRANSLATE_1_2)       \
9936 _("translate-2-1",  L2_VTR_TRANSLATE_2_1)       \
9937 _("translate-2-2",  L2_VTR_TRANSLATE_2_2)
9938
9939 static int
9940 api_l2_interface_vlan_tag_rewrite (vat_main_t * vam)
9941 {
9942   unformat_input_t *i = vam->input;
9943   vl_api_l2_interface_vlan_tag_rewrite_t *mp;
9944   u32 sw_if_index;
9945   u8 sw_if_index_set = 0;
9946   u8 vtr_op_set = 0;
9947   u32 vtr_op = 0;
9948   u32 push_dot1q = 1;
9949   u32 tag1 = ~0;
9950   u32 tag2 = ~0;
9951   int ret;
9952
9953   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9954     {
9955       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
9956         sw_if_index_set = 1;
9957       else if (unformat (i, "sw_if_index %d", &sw_if_index))
9958         sw_if_index_set = 1;
9959       else if (unformat (i, "vtr_op %d", &vtr_op))
9960         vtr_op_set = 1;
9961 #define _(n,v) else if (unformat(i, n)) {vtr_op = v; vtr_op_set = 1;}
9962       foreach_vtr_op
9963 #undef _
9964         else if (unformat (i, "push_dot1q %d", &push_dot1q))
9965         ;
9966       else if (unformat (i, "tag1 %d", &tag1))
9967         ;
9968       else if (unformat (i, "tag2 %d", &tag2))
9969         ;
9970       else
9971         {
9972           clib_warning ("parse error '%U'", format_unformat_error, i);
9973           return -99;
9974         }
9975     }
9976
9977   if ((sw_if_index_set == 0) || (vtr_op_set == 0))
9978     {
9979       errmsg ("missing vtr operation or sw_if_index");
9980       return -99;
9981     }
9982
9983   M (L2_INTERFACE_VLAN_TAG_REWRITE, mp);
9984   mp->sw_if_index = ntohl (sw_if_index);
9985   mp->vtr_op = ntohl (vtr_op);
9986   mp->push_dot1q = ntohl (push_dot1q);
9987   mp->tag1 = ntohl (tag1);
9988   mp->tag2 = ntohl (tag2);
9989
9990   S (mp);
9991   W (ret);
9992   return ret;
9993 }
9994
9995 static int
9996 api_create_vhost_user_if (vat_main_t * vam)
9997 {
9998   unformat_input_t *i = vam->input;
9999   vl_api_create_vhost_user_if_t *mp;
10000   u8 *file_name;
10001   u8 is_server = 0;
10002   u8 file_name_set = 0;
10003   u32 custom_dev_instance = ~0;
10004   u8 hwaddr[6];
10005   u8 use_custom_mac = 0;
10006   u8 disable_mrg_rxbuf = 0;
10007   u8 disable_indirect_desc = 0;
10008   u8 *tag = 0;
10009   u8 enable_gso = 0;
10010   u8 enable_packed = 0;
10011   int ret;
10012
10013   /* Shut up coverity */
10014   clib_memset (hwaddr, 0, sizeof (hwaddr));
10015
10016   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10017     {
10018       if (unformat (i, "socket %s", &file_name))
10019         {
10020           file_name_set = 1;
10021         }
10022       else if (unformat (i, "renumber %" PRIu32, &custom_dev_instance))
10023         ;
10024       else if (unformat (i, "mac %U", unformat_ethernet_address, hwaddr))
10025         use_custom_mac = 1;
10026       else if (unformat (i, "server"))
10027         is_server = 1;
10028       else if (unformat (i, "disable_mrg_rxbuf"))
10029         disable_mrg_rxbuf = 1;
10030       else if (unformat (i, "disable_indirect_desc"))
10031         disable_indirect_desc = 1;
10032       else if (unformat (i, "gso"))
10033         enable_gso = 1;
10034       else if (unformat (i, "packed"))
10035         enable_packed = 1;
10036       else if (unformat (i, "tag %s", &tag))
10037         ;
10038       else
10039         break;
10040     }
10041
10042   if (file_name_set == 0)
10043     {
10044       errmsg ("missing socket file name");
10045       return -99;
10046     }
10047
10048   if (vec_len (file_name) > 255)
10049     {
10050       errmsg ("socket file name too long");
10051       return -99;
10052     }
10053   vec_add1 (file_name, 0);
10054
10055   M (CREATE_VHOST_USER_IF, mp);
10056
10057   mp->is_server = is_server;
10058   mp->disable_mrg_rxbuf = disable_mrg_rxbuf;
10059   mp->disable_indirect_desc = disable_indirect_desc;
10060   mp->enable_gso = enable_gso;
10061   mp->enable_packed = enable_packed;
10062   clib_memcpy (mp->sock_filename, file_name, vec_len (file_name));
10063   vec_free (file_name);
10064   if (custom_dev_instance != ~0)
10065     {
10066       mp->renumber = 1;
10067       mp->custom_dev_instance = ntohl (custom_dev_instance);
10068     }
10069
10070   mp->use_custom_mac = use_custom_mac;
10071   clib_memcpy (mp->mac_address, hwaddr, 6);
10072   if (tag)
10073     strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
10074   vec_free (tag);
10075
10076   S (mp);
10077   W (ret);
10078   return ret;
10079 }
10080
10081 static int
10082 api_modify_vhost_user_if (vat_main_t * vam)
10083 {
10084   unformat_input_t *i = vam->input;
10085   vl_api_modify_vhost_user_if_t *mp;
10086   u8 *file_name;
10087   u8 is_server = 0;
10088   u8 file_name_set = 0;
10089   u32 custom_dev_instance = ~0;
10090   u8 sw_if_index_set = 0;
10091   u32 sw_if_index = (u32) ~ 0;
10092   u8 enable_gso = 0;
10093   u8 enable_packed = 0;
10094   int ret;
10095
10096   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10097     {
10098       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10099         sw_if_index_set = 1;
10100       else if (unformat (i, "sw_if_index %d", &sw_if_index))
10101         sw_if_index_set = 1;
10102       else if (unformat (i, "socket %s", &file_name))
10103         {
10104           file_name_set = 1;
10105         }
10106       else if (unformat (i, "renumber %" PRIu32, &custom_dev_instance))
10107         ;
10108       else if (unformat (i, "server"))
10109         is_server = 1;
10110       else if (unformat (i, "gso"))
10111         enable_gso = 1;
10112       else if (unformat (i, "packed"))
10113         enable_packed = 1;
10114       else
10115         break;
10116     }
10117
10118   if (sw_if_index_set == 0)
10119     {
10120       errmsg ("missing sw_if_index or interface name");
10121       return -99;
10122     }
10123
10124   if (file_name_set == 0)
10125     {
10126       errmsg ("missing socket file name");
10127       return -99;
10128     }
10129
10130   if (vec_len (file_name) > 255)
10131     {
10132       errmsg ("socket file name too long");
10133       return -99;
10134     }
10135   vec_add1 (file_name, 0);
10136
10137   M (MODIFY_VHOST_USER_IF, mp);
10138
10139   mp->sw_if_index = ntohl (sw_if_index);
10140   mp->is_server = is_server;
10141   mp->enable_gso = enable_gso;
10142   mp->enable_packed = enable_packed;
10143   clib_memcpy (mp->sock_filename, file_name, vec_len (file_name));
10144   vec_free (file_name);
10145   if (custom_dev_instance != ~0)
10146     {
10147       mp->renumber = 1;
10148       mp->custom_dev_instance = ntohl (custom_dev_instance);
10149     }
10150
10151   S (mp);
10152   W (ret);
10153   return ret;
10154 }
10155
10156 static int
10157 api_delete_vhost_user_if (vat_main_t * vam)
10158 {
10159   unformat_input_t *i = vam->input;
10160   vl_api_delete_vhost_user_if_t *mp;
10161   u32 sw_if_index = ~0;
10162   u8 sw_if_index_set = 0;
10163   int ret;
10164
10165   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10166     {
10167       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10168         sw_if_index_set = 1;
10169       else if (unformat (i, "sw_if_index %d", &sw_if_index))
10170         sw_if_index_set = 1;
10171       else
10172         break;
10173     }
10174
10175   if (sw_if_index_set == 0)
10176     {
10177       errmsg ("missing sw_if_index or interface name");
10178       return -99;
10179     }
10180
10181
10182   M (DELETE_VHOST_USER_IF, mp);
10183
10184   mp->sw_if_index = ntohl (sw_if_index);
10185
10186   S (mp);
10187   W (ret);
10188   return ret;
10189 }
10190
10191 static void vl_api_sw_interface_vhost_user_details_t_handler
10192   (vl_api_sw_interface_vhost_user_details_t * mp)
10193 {
10194   vat_main_t *vam = &vat_main;
10195   u64 features;
10196
10197   features =
10198     clib_net_to_host_u32 (mp->features_first_32) | ((u64)
10199                                                     clib_net_to_host_u32
10200                                                     (mp->features_last_32) <<
10201                                                     32);
10202
10203   print (vam->ofp, "%-25s %3" PRIu32 " %6" PRIu32 " %8x %6d %7d %s",
10204          (char *) mp->interface_name,
10205          ntohl (mp->sw_if_index), ntohl (mp->virtio_net_hdr_sz),
10206          features, mp->is_server,
10207          ntohl (mp->num_regions), (char *) mp->sock_filename);
10208   print (vam->ofp, "    Status: '%s'", strerror (ntohl (mp->sock_errno)));
10209 }
10210
10211 static void vl_api_sw_interface_vhost_user_details_t_handler_json
10212   (vl_api_sw_interface_vhost_user_details_t * mp)
10213 {
10214   vat_main_t *vam = &vat_main;
10215   vat_json_node_t *node = NULL;
10216
10217   if (VAT_JSON_ARRAY != vam->json_tree.type)
10218     {
10219       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
10220       vat_json_init_array (&vam->json_tree);
10221     }
10222   node = vat_json_array_add (&vam->json_tree);
10223
10224   vat_json_init_object (node);
10225   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
10226   vat_json_object_add_string_copy (node, "interface_name",
10227                                    mp->interface_name);
10228   vat_json_object_add_uint (node, "virtio_net_hdr_sz",
10229                             ntohl (mp->virtio_net_hdr_sz));
10230   vat_json_object_add_uint (node, "features_first_32",
10231                             clib_net_to_host_u32 (mp->features_first_32));
10232   vat_json_object_add_uint (node, "features_last_32",
10233                             clib_net_to_host_u32 (mp->features_last_32));
10234   vat_json_object_add_uint (node, "is_server", mp->is_server);
10235   vat_json_object_add_string_copy (node, "sock_filename", mp->sock_filename);
10236   vat_json_object_add_uint (node, "num_regions", ntohl (mp->num_regions));
10237   vat_json_object_add_uint (node, "sock_errno", ntohl (mp->sock_errno));
10238 }
10239
10240 static int
10241 api_sw_interface_vhost_user_dump (vat_main_t * vam)
10242 {
10243   unformat_input_t *i = vam->input;
10244   vl_api_sw_interface_vhost_user_dump_t *mp;
10245   vl_api_control_ping_t *mp_ping;
10246   int ret;
10247   u32 sw_if_index = ~0;
10248
10249   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10250     {
10251       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10252         ;
10253       else if (unformat (i, "sw_if_index %d", &sw_if_index))
10254         ;
10255       else
10256         break;
10257     }
10258
10259   print (vam->ofp,
10260          "Interface name            idx hdr_sz features server regions filename");
10261
10262   /* Get list of vhost-user interfaces */
10263   M (SW_INTERFACE_VHOST_USER_DUMP, mp);
10264   mp->sw_if_index = ntohl (sw_if_index);
10265   S (mp);
10266
10267   /* Use a control ping for synchronization */
10268   MPING (CONTROL_PING, mp_ping);
10269   S (mp_ping);
10270
10271   W (ret);
10272   return ret;
10273 }
10274
10275 static int
10276 api_show_version (vat_main_t * vam)
10277 {
10278   vl_api_show_version_t *mp;
10279   int ret;
10280
10281   M (SHOW_VERSION, mp);
10282
10283   S (mp);
10284   W (ret);
10285   return ret;
10286 }
10287
10288
10289 static int
10290 api_vxlan_gpe_add_del_tunnel (vat_main_t * vam)
10291 {
10292   unformat_input_t *line_input = vam->input;
10293   vl_api_vxlan_gpe_add_del_tunnel_t *mp;
10294   ip46_address_t local, remote;
10295   u8 is_add = 1;
10296   u8 local_set = 0;
10297   u8 remote_set = 0;
10298   u8 grp_set = 0;
10299   u32 mcast_sw_if_index = ~0;
10300   u32 encap_vrf_id = 0;
10301   u32 decap_vrf_id = 0;
10302   u8 protocol = ~0;
10303   u32 vni;
10304   u8 vni_set = 0;
10305   int ret;
10306
10307   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
10308     {
10309       if (unformat (line_input, "del"))
10310         is_add = 0;
10311       else if (unformat (line_input, "local %U",
10312                          unformat_ip46_address, &local))
10313         {
10314           local_set = 1;
10315         }
10316       else if (unformat (line_input, "remote %U",
10317                          unformat_ip46_address, &remote))
10318         {
10319           remote_set = 1;
10320         }
10321       else if (unformat (line_input, "group %U %U",
10322                          unformat_ip46_address, &remote,
10323                          api_unformat_sw_if_index, vam, &mcast_sw_if_index))
10324         {
10325           grp_set = remote_set = 1;
10326         }
10327       else if (unformat (line_input, "group %U",
10328                          unformat_ip46_address, &remote))
10329         {
10330           grp_set = remote_set = 1;
10331         }
10332       else
10333         if (unformat (line_input, "mcast_sw_if_index %u", &mcast_sw_if_index))
10334         ;
10335       else if (unformat (line_input, "encap-vrf-id %d", &encap_vrf_id))
10336         ;
10337       else if (unformat (line_input, "decap-vrf-id %d", &decap_vrf_id))
10338         ;
10339       else if (unformat (line_input, "vni %d", &vni))
10340         vni_set = 1;
10341       else if (unformat (line_input, "next-ip4"))
10342         protocol = 1;
10343       else if (unformat (line_input, "next-ip6"))
10344         protocol = 2;
10345       else if (unformat (line_input, "next-ethernet"))
10346         protocol = 3;
10347       else if (unformat (line_input, "next-nsh"))
10348         protocol = 4;
10349       else
10350         {
10351           errmsg ("parse error '%U'", format_unformat_error, line_input);
10352           return -99;
10353         }
10354     }
10355
10356   if (local_set == 0)
10357     {
10358       errmsg ("tunnel local address not specified");
10359       return -99;
10360     }
10361   if (remote_set == 0)
10362     {
10363       errmsg ("tunnel remote address not specified");
10364       return -99;
10365     }
10366   if (grp_set && mcast_sw_if_index == ~0)
10367     {
10368       errmsg ("tunnel nonexistent multicast device");
10369       return -99;
10370     }
10371   if (ip46_address_is_ip4 (&local) != ip46_address_is_ip4 (&remote))
10372     {
10373       errmsg ("both IPv4 and IPv6 addresses specified");
10374       return -99;
10375     }
10376
10377   if (vni_set == 0)
10378     {
10379       errmsg ("vni not specified");
10380       return -99;
10381     }
10382
10383   M (VXLAN_GPE_ADD_DEL_TUNNEL, mp);
10384
10385   ip_address_encode (&local,
10386                      ip46_address_is_ip4 (&local) ? IP46_TYPE_IP4 :
10387                      IP46_TYPE_IP6, &mp->local);
10388   ip_address_encode (&remote,
10389                      ip46_address_is_ip4 (&remote) ? IP46_TYPE_IP4 :
10390                      IP46_TYPE_IP6, &mp->remote);
10391
10392   mp->mcast_sw_if_index = ntohl (mcast_sw_if_index);
10393   mp->encap_vrf_id = ntohl (encap_vrf_id);
10394   mp->decap_vrf_id = ntohl (decap_vrf_id);
10395   mp->protocol = protocol;
10396   mp->vni = ntohl (vni);
10397   mp->is_add = is_add;
10398
10399   S (mp);
10400   W (ret);
10401   return ret;
10402 }
10403
10404 static void vl_api_vxlan_gpe_tunnel_details_t_handler
10405   (vl_api_vxlan_gpe_tunnel_details_t * mp)
10406 {
10407   vat_main_t *vam = &vat_main;
10408   ip46_address_t local, remote;
10409
10410   ip_address_decode (&mp->local, &local);
10411   ip_address_decode (&mp->remote, &remote);
10412
10413   print (vam->ofp, "%11d%24U%24U%13d%12d%19d%14d%14d",
10414          ntohl (mp->sw_if_index),
10415          format_ip46_address, &local, IP46_TYPE_ANY,
10416          format_ip46_address, &remote, IP46_TYPE_ANY,
10417          ntohl (mp->vni), mp->protocol,
10418          ntohl (mp->mcast_sw_if_index),
10419          ntohl (mp->encap_vrf_id), ntohl (mp->decap_vrf_id));
10420 }
10421
10422
10423 static void vl_api_vxlan_gpe_tunnel_details_t_handler_json
10424   (vl_api_vxlan_gpe_tunnel_details_t * mp)
10425 {
10426   vat_main_t *vam = &vat_main;
10427   vat_json_node_t *node = NULL;
10428   struct in_addr ip4;
10429   struct in6_addr ip6;
10430   ip46_address_t local, remote;
10431
10432   ip_address_decode (&mp->local, &local);
10433   ip_address_decode (&mp->remote, &remote);
10434
10435   if (VAT_JSON_ARRAY != vam->json_tree.type)
10436     {
10437       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
10438       vat_json_init_array (&vam->json_tree);
10439     }
10440   node = vat_json_array_add (&vam->json_tree);
10441
10442   vat_json_init_object (node);
10443   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
10444   if (ip46_address_is_ip4 (&local))
10445     {
10446       clib_memcpy (&ip4, &local.ip4, sizeof (ip4));
10447       vat_json_object_add_ip4 (node, "local", ip4);
10448       clib_memcpy (&ip4, &remote.ip4, sizeof (ip4));
10449       vat_json_object_add_ip4 (node, "remote", ip4);
10450     }
10451   else
10452     {
10453       clib_memcpy (&ip6, &local.ip6, sizeof (ip6));
10454       vat_json_object_add_ip6 (node, "local", ip6);
10455       clib_memcpy (&ip6, &remote.ip6, sizeof (ip6));
10456       vat_json_object_add_ip6 (node, "remote", ip6);
10457     }
10458   vat_json_object_add_uint (node, "vni", ntohl (mp->vni));
10459   vat_json_object_add_uint (node, "protocol", ntohl (mp->protocol));
10460   vat_json_object_add_uint (node, "mcast_sw_if_index",
10461                             ntohl (mp->mcast_sw_if_index));
10462   vat_json_object_add_uint (node, "encap_vrf_id", ntohl (mp->encap_vrf_id));
10463   vat_json_object_add_uint (node, "decap_vrf_id", ntohl (mp->decap_vrf_id));
10464   vat_json_object_add_uint (node, "is_ipv6", mp->is_ipv6 ? 1 : 0);
10465 }
10466
10467 static int
10468 api_vxlan_gpe_tunnel_dump (vat_main_t * vam)
10469 {
10470   unformat_input_t *i = vam->input;
10471   vl_api_vxlan_gpe_tunnel_dump_t *mp;
10472   vl_api_control_ping_t *mp_ping;
10473   u32 sw_if_index;
10474   u8 sw_if_index_set = 0;
10475   int ret;
10476
10477   /* Parse args required to build the message */
10478   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10479     {
10480       if (unformat (i, "sw_if_index %d", &sw_if_index))
10481         sw_if_index_set = 1;
10482       else
10483         break;
10484     }
10485
10486   if (sw_if_index_set == 0)
10487     {
10488       sw_if_index = ~0;
10489     }
10490
10491   if (!vam->json_output)
10492     {
10493       print (vam->ofp, "%11s%24s%24s%13s%15s%19s%14s%14s",
10494              "sw_if_index", "local", "remote", "vni",
10495              "protocol", "mcast_sw_if_index", "encap_vrf_id", "decap_vrf_id");
10496     }
10497
10498   /* Get list of vxlan-tunnel interfaces */
10499   M (VXLAN_GPE_TUNNEL_DUMP, mp);
10500
10501   mp->sw_if_index = htonl (sw_if_index);
10502
10503   S (mp);
10504
10505   /* Use a control ping for synchronization */
10506   MPING (CONTROL_PING, mp_ping);
10507   S (mp_ping);
10508
10509   W (ret);
10510   return ret;
10511 }
10512
10513 static void vl_api_l2_fib_table_details_t_handler
10514   (vl_api_l2_fib_table_details_t * mp)
10515 {
10516   vat_main_t *vam = &vat_main;
10517
10518   print (vam->ofp, "%3" PRIu32 "    %U    %3" PRIu32
10519          "       %d       %d     %d",
10520          ntohl (mp->bd_id), format_ethernet_address, mp->mac,
10521          ntohl (mp->sw_if_index), mp->static_mac, mp->filter_mac,
10522          mp->bvi_mac);
10523 }
10524
10525 static void vl_api_l2_fib_table_details_t_handler_json
10526   (vl_api_l2_fib_table_details_t * mp)
10527 {
10528   vat_main_t *vam = &vat_main;
10529   vat_json_node_t *node = NULL;
10530
10531   if (VAT_JSON_ARRAY != vam->json_tree.type)
10532     {
10533       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
10534       vat_json_init_array (&vam->json_tree);
10535     }
10536   node = vat_json_array_add (&vam->json_tree);
10537
10538   vat_json_init_object (node);
10539   vat_json_object_add_uint (node, "bd_id", ntohl (mp->bd_id));
10540   vat_json_object_add_bytes (node, "mac", mp->mac, 6);
10541   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
10542   vat_json_object_add_uint (node, "static_mac", mp->static_mac);
10543   vat_json_object_add_uint (node, "filter_mac", mp->filter_mac);
10544   vat_json_object_add_uint (node, "bvi_mac", mp->bvi_mac);
10545 }
10546
10547 static int
10548 api_l2_fib_table_dump (vat_main_t * vam)
10549 {
10550   unformat_input_t *i = vam->input;
10551   vl_api_l2_fib_table_dump_t *mp;
10552   vl_api_control_ping_t *mp_ping;
10553   u32 bd_id;
10554   u8 bd_id_set = 0;
10555   int ret;
10556
10557   /* Parse args required to build the message */
10558   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10559     {
10560       if (unformat (i, "bd_id %d", &bd_id))
10561         bd_id_set = 1;
10562       else
10563         break;
10564     }
10565
10566   if (bd_id_set == 0)
10567     {
10568       errmsg ("missing bridge domain");
10569       return -99;
10570     }
10571
10572   print (vam->ofp, "BD-ID     Mac Address      sw-ndx  Static  Filter  BVI");
10573
10574   /* Get list of l2 fib entries */
10575   M (L2_FIB_TABLE_DUMP, mp);
10576
10577   mp->bd_id = ntohl (bd_id);
10578   S (mp);
10579
10580   /* Use a control ping for synchronization */
10581   MPING (CONTROL_PING, mp_ping);
10582   S (mp_ping);
10583
10584   W (ret);
10585   return ret;
10586 }
10587
10588
10589 static int
10590 api_interface_name_renumber (vat_main_t * vam)
10591 {
10592   unformat_input_t *line_input = vam->input;
10593   vl_api_interface_name_renumber_t *mp;
10594   u32 sw_if_index = ~0;
10595   u32 new_show_dev_instance = ~0;
10596   int ret;
10597
10598   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
10599     {
10600       if (unformat (line_input, "%U", api_unformat_sw_if_index, vam,
10601                     &sw_if_index))
10602         ;
10603       else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
10604         ;
10605       else if (unformat (line_input, "new_show_dev_instance %d",
10606                          &new_show_dev_instance))
10607         ;
10608       else
10609         break;
10610     }
10611
10612   if (sw_if_index == ~0)
10613     {
10614       errmsg ("missing interface name or sw_if_index");
10615       return -99;
10616     }
10617
10618   if (new_show_dev_instance == ~0)
10619     {
10620       errmsg ("missing new_show_dev_instance");
10621       return -99;
10622     }
10623
10624   M (INTERFACE_NAME_RENUMBER, mp);
10625
10626   mp->sw_if_index = ntohl (sw_if_index);
10627   mp->new_show_dev_instance = ntohl (new_show_dev_instance);
10628
10629   S (mp);
10630   W (ret);
10631   return ret;
10632 }
10633
10634 static int
10635 api_want_l2_macs_events (vat_main_t * vam)
10636 {
10637   unformat_input_t *line_input = vam->input;
10638   vl_api_want_l2_macs_events_t *mp;
10639   u8 enable_disable = 1;
10640   u32 scan_delay = 0;
10641   u32 max_macs_in_event = 0;
10642   u32 learn_limit = 0;
10643   int ret;
10644
10645   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
10646     {
10647       if (unformat (line_input, "learn-limit %d", &learn_limit))
10648         ;
10649       else if (unformat (line_input, "scan-delay %d", &scan_delay))
10650         ;
10651       else if (unformat (line_input, "max-entries %d", &max_macs_in_event))
10652         ;
10653       else if (unformat (line_input, "disable"))
10654         enable_disable = 0;
10655       else
10656         break;
10657     }
10658
10659   M (WANT_L2_MACS_EVENTS, mp);
10660   mp->enable_disable = enable_disable;
10661   mp->pid = htonl (getpid ());
10662   mp->learn_limit = htonl (learn_limit);
10663   mp->scan_delay = (u8) scan_delay;
10664   mp->max_macs_in_event = (u8) (max_macs_in_event / 10);
10665   S (mp);
10666   W (ret);
10667   return ret;
10668 }
10669
10670 static int
10671 api_input_acl_set_interface (vat_main_t * vam)
10672 {
10673   unformat_input_t *i = vam->input;
10674   vl_api_input_acl_set_interface_t *mp;
10675   u32 sw_if_index;
10676   int sw_if_index_set;
10677   u32 ip4_table_index = ~0;
10678   u32 ip6_table_index = ~0;
10679   u32 l2_table_index = ~0;
10680   u8 is_add = 1;
10681   int ret;
10682
10683   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10684     {
10685       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10686         sw_if_index_set = 1;
10687       else if (unformat (i, "sw_if_index %d", &sw_if_index))
10688         sw_if_index_set = 1;
10689       else if (unformat (i, "del"))
10690         is_add = 0;
10691       else if (unformat (i, "ip4-table %d", &ip4_table_index))
10692         ;
10693       else if (unformat (i, "ip6-table %d", &ip6_table_index))
10694         ;
10695       else if (unformat (i, "l2-table %d", &l2_table_index))
10696         ;
10697       else
10698         {
10699           clib_warning ("parse error '%U'", format_unformat_error, i);
10700           return -99;
10701         }
10702     }
10703
10704   if (sw_if_index_set == 0)
10705     {
10706       errmsg ("missing interface name or sw_if_index");
10707       return -99;
10708     }
10709
10710   M (INPUT_ACL_SET_INTERFACE, mp);
10711
10712   mp->sw_if_index = ntohl (sw_if_index);
10713   mp->ip4_table_index = ntohl (ip4_table_index);
10714   mp->ip6_table_index = ntohl (ip6_table_index);
10715   mp->l2_table_index = ntohl (l2_table_index);
10716   mp->is_add = is_add;
10717
10718   S (mp);
10719   W (ret);
10720   return ret;
10721 }
10722
10723 static int
10724 api_output_acl_set_interface (vat_main_t * vam)
10725 {
10726   unformat_input_t *i = vam->input;
10727   vl_api_output_acl_set_interface_t *mp;
10728   u32 sw_if_index;
10729   int sw_if_index_set;
10730   u32 ip4_table_index = ~0;
10731   u32 ip6_table_index = ~0;
10732   u32 l2_table_index = ~0;
10733   u8 is_add = 1;
10734   int ret;
10735
10736   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10737     {
10738       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10739         sw_if_index_set = 1;
10740       else if (unformat (i, "sw_if_index %d", &sw_if_index))
10741         sw_if_index_set = 1;
10742       else if (unformat (i, "del"))
10743         is_add = 0;
10744       else if (unformat (i, "ip4-table %d", &ip4_table_index))
10745         ;
10746       else if (unformat (i, "ip6-table %d", &ip6_table_index))
10747         ;
10748       else if (unformat (i, "l2-table %d", &l2_table_index))
10749         ;
10750       else
10751         {
10752           clib_warning ("parse error '%U'", format_unformat_error, i);
10753           return -99;
10754         }
10755     }
10756
10757   if (sw_if_index_set == 0)
10758     {
10759       errmsg ("missing interface name or sw_if_index");
10760       return -99;
10761     }
10762
10763   M (OUTPUT_ACL_SET_INTERFACE, mp);
10764
10765   mp->sw_if_index = ntohl (sw_if_index);
10766   mp->ip4_table_index = ntohl (ip4_table_index);
10767   mp->ip6_table_index = ntohl (ip6_table_index);
10768   mp->l2_table_index = ntohl (l2_table_index);
10769   mp->is_add = is_add;
10770
10771   S (mp);
10772   W (ret);
10773   return ret;
10774 }
10775
10776 static int
10777 api_ip_address_dump (vat_main_t * vam)
10778 {
10779   unformat_input_t *i = vam->input;
10780   vl_api_ip_address_dump_t *mp;
10781   vl_api_control_ping_t *mp_ping;
10782   u32 sw_if_index = ~0;
10783   u8 sw_if_index_set = 0;
10784   u8 ipv4_set = 0;
10785   u8 ipv6_set = 0;
10786   int ret;
10787
10788   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10789     {
10790       if (unformat (i, "sw_if_index %d", &sw_if_index))
10791         sw_if_index_set = 1;
10792       else
10793         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10794         sw_if_index_set = 1;
10795       else if (unformat (i, "ipv4"))
10796         ipv4_set = 1;
10797       else if (unformat (i, "ipv6"))
10798         ipv6_set = 1;
10799       else
10800         break;
10801     }
10802
10803   if (ipv4_set && ipv6_set)
10804     {
10805       errmsg ("ipv4 and ipv6 flags cannot be both set");
10806       return -99;
10807     }
10808
10809   if ((!ipv4_set) && (!ipv6_set))
10810     {
10811       errmsg ("no ipv4 nor ipv6 flag set");
10812       return -99;
10813     }
10814
10815   if (sw_if_index_set == 0)
10816     {
10817       errmsg ("missing interface name or sw_if_index");
10818       return -99;
10819     }
10820
10821   vam->current_sw_if_index = sw_if_index;
10822   vam->is_ipv6 = ipv6_set;
10823
10824   M (IP_ADDRESS_DUMP, mp);
10825   mp->sw_if_index = ntohl (sw_if_index);
10826   mp->is_ipv6 = ipv6_set;
10827   S (mp);
10828
10829   /* Use a control ping for synchronization */
10830   MPING (CONTROL_PING, mp_ping);
10831   S (mp_ping);
10832
10833   W (ret);
10834   return ret;
10835 }
10836
10837 static int
10838 api_ip_dump (vat_main_t * vam)
10839 {
10840   vl_api_ip_dump_t *mp;
10841   vl_api_control_ping_t *mp_ping;
10842   unformat_input_t *in = vam->input;
10843   int ipv4_set = 0;
10844   int ipv6_set = 0;
10845   int is_ipv6;
10846   int i;
10847   int ret;
10848
10849   while (unformat_check_input (in) != UNFORMAT_END_OF_INPUT)
10850     {
10851       if (unformat (in, "ipv4"))
10852         ipv4_set = 1;
10853       else if (unformat (in, "ipv6"))
10854         ipv6_set = 1;
10855       else
10856         break;
10857     }
10858
10859   if (ipv4_set && ipv6_set)
10860     {
10861       errmsg ("ipv4 and ipv6 flags cannot be both set");
10862       return -99;
10863     }
10864
10865   if ((!ipv4_set) && (!ipv6_set))
10866     {
10867       errmsg ("no ipv4 nor ipv6 flag set");
10868       return -99;
10869     }
10870
10871   is_ipv6 = ipv6_set;
10872   vam->is_ipv6 = is_ipv6;
10873
10874   /* free old data */
10875   for (i = 0; i < vec_len (vam->ip_details_by_sw_if_index[is_ipv6]); i++)
10876     {
10877       vec_free (vam->ip_details_by_sw_if_index[is_ipv6][i].addr);
10878     }
10879   vec_free (vam->ip_details_by_sw_if_index[is_ipv6]);
10880
10881   M (IP_DUMP, mp);
10882   mp->is_ipv6 = ipv6_set;
10883   S (mp);
10884
10885   /* Use a control ping for synchronization */
10886   MPING (CONTROL_PING, mp_ping);
10887   S (mp_ping);
10888
10889   W (ret);
10890   return ret;
10891 }
10892
10893 static int
10894 api_ipsec_spd_add_del (vat_main_t * vam)
10895 {
10896   unformat_input_t *i = vam->input;
10897   vl_api_ipsec_spd_add_del_t *mp;
10898   u32 spd_id = ~0;
10899   u8 is_add = 1;
10900   int ret;
10901
10902   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10903     {
10904       if (unformat (i, "spd_id %d", &spd_id))
10905         ;
10906       else if (unformat (i, "del"))
10907         is_add = 0;
10908       else
10909         {
10910           clib_warning ("parse error '%U'", format_unformat_error, i);
10911           return -99;
10912         }
10913     }
10914   if (spd_id == ~0)
10915     {
10916       errmsg ("spd_id must be set");
10917       return -99;
10918     }
10919
10920   M (IPSEC_SPD_ADD_DEL, mp);
10921
10922   mp->spd_id = ntohl (spd_id);
10923   mp->is_add = is_add;
10924
10925   S (mp);
10926   W (ret);
10927   return ret;
10928 }
10929
10930 static int
10931 api_ipsec_interface_add_del_spd (vat_main_t * vam)
10932 {
10933   unformat_input_t *i = vam->input;
10934   vl_api_ipsec_interface_add_del_spd_t *mp;
10935   u32 sw_if_index;
10936   u8 sw_if_index_set = 0;
10937   u32 spd_id = (u32) ~ 0;
10938   u8 is_add = 1;
10939   int ret;
10940
10941   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10942     {
10943       if (unformat (i, "del"))
10944         is_add = 0;
10945       else if (unformat (i, "spd_id %d", &spd_id))
10946         ;
10947       else
10948         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10949         sw_if_index_set = 1;
10950       else if (unformat (i, "sw_if_index %d", &sw_if_index))
10951         sw_if_index_set = 1;
10952       else
10953         {
10954           clib_warning ("parse error '%U'", format_unformat_error, i);
10955           return -99;
10956         }
10957
10958     }
10959
10960   if (spd_id == (u32) ~ 0)
10961     {
10962       errmsg ("spd_id must be set");
10963       return -99;
10964     }
10965
10966   if (sw_if_index_set == 0)
10967     {
10968       errmsg ("missing interface name or sw_if_index");
10969       return -99;
10970     }
10971
10972   M (IPSEC_INTERFACE_ADD_DEL_SPD, mp);
10973
10974   mp->spd_id = ntohl (spd_id);
10975   mp->sw_if_index = ntohl (sw_if_index);
10976   mp->is_add = is_add;
10977
10978   S (mp);
10979   W (ret);
10980   return ret;
10981 }
10982
10983 static int
10984 api_ipsec_spd_entry_add_del (vat_main_t * vam)
10985 {
10986   unformat_input_t *i = vam->input;
10987   vl_api_ipsec_spd_entry_add_del_t *mp;
10988   u8 is_add = 1, is_outbound = 0;
10989   u32 spd_id = 0, sa_id = 0, protocol = 0, policy = 0;
10990   i32 priority = 0;
10991   u32 rport_start = 0, rport_stop = (u32) ~ 0;
10992   u32 lport_start = 0, lport_stop = (u32) ~ 0;
10993   vl_api_address_t laddr_start = { }, laddr_stop =
10994   {
10995   }, raddr_start =
10996   {
10997   }, raddr_stop =
10998   {
10999   };
11000   int ret;
11001
11002   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11003     {
11004       if (unformat (i, "del"))
11005         is_add = 0;
11006       if (unformat (i, "outbound"))
11007         is_outbound = 1;
11008       if (unformat (i, "inbound"))
11009         is_outbound = 0;
11010       else if (unformat (i, "spd_id %d", &spd_id))
11011         ;
11012       else if (unformat (i, "sa_id %d", &sa_id))
11013         ;
11014       else if (unformat (i, "priority %d", &priority))
11015         ;
11016       else if (unformat (i, "protocol %d", &protocol))
11017         ;
11018       else if (unformat (i, "lport_start %d", &lport_start))
11019         ;
11020       else if (unformat (i, "lport_stop %d", &lport_stop))
11021         ;
11022       else if (unformat (i, "rport_start %d", &rport_start))
11023         ;
11024       else if (unformat (i, "rport_stop %d", &rport_stop))
11025         ;
11026       else if (unformat (i, "laddr_start %U",
11027                          unformat_vl_api_address, &laddr_start))
11028         ;
11029       else if (unformat (i, "laddr_stop %U", unformat_vl_api_address,
11030                          &laddr_stop))
11031         ;
11032       else if (unformat (i, "raddr_start %U", unformat_vl_api_address,
11033                          &raddr_start))
11034         ;
11035       else if (unformat (i, "raddr_stop %U", unformat_vl_api_address,
11036                          &raddr_stop))
11037         ;
11038       else
11039         if (unformat (i, "action %U", unformat_ipsec_policy_action, &policy))
11040         {
11041           if (policy == IPSEC_POLICY_ACTION_RESOLVE)
11042             {
11043               clib_warning ("unsupported action: 'resolve'");
11044               return -99;
11045             }
11046         }
11047       else
11048         {
11049           clib_warning ("parse error '%U'", format_unformat_error, i);
11050           return -99;
11051         }
11052
11053     }
11054
11055   M (IPSEC_SPD_ENTRY_ADD_DEL, mp);
11056
11057   mp->is_add = is_add;
11058
11059   mp->entry.spd_id = ntohl (spd_id);
11060   mp->entry.priority = ntohl (priority);
11061   mp->entry.is_outbound = is_outbound;
11062
11063   clib_memcpy (&mp->entry.remote_address_start, &raddr_start,
11064                sizeof (vl_api_address_t));
11065   clib_memcpy (&mp->entry.remote_address_stop, &raddr_stop,
11066                sizeof (vl_api_address_t));
11067   clib_memcpy (&mp->entry.local_address_start, &laddr_start,
11068                sizeof (vl_api_address_t));
11069   clib_memcpy (&mp->entry.local_address_stop, &laddr_stop,
11070                sizeof (vl_api_address_t));
11071
11072   mp->entry.protocol = (u8) protocol;
11073   mp->entry.local_port_start = ntohs ((u16) lport_start);
11074   mp->entry.local_port_stop = ntohs ((u16) lport_stop);
11075   mp->entry.remote_port_start = ntohs ((u16) rport_start);
11076   mp->entry.remote_port_stop = ntohs ((u16) rport_stop);
11077   mp->entry.policy = (u8) policy;
11078   mp->entry.sa_id = ntohl (sa_id);
11079
11080   S (mp);
11081   W (ret);
11082   return ret;
11083 }
11084
11085 static int
11086 api_ipsec_sad_entry_add_del (vat_main_t * vam)
11087 {
11088   unformat_input_t *i = vam->input;
11089   vl_api_ipsec_sad_entry_add_del_t *mp;
11090   u32 sad_id = 0, spi = 0;
11091   u8 *ck = 0, *ik = 0;
11092   u8 is_add = 1;
11093
11094   vl_api_ipsec_crypto_alg_t crypto_alg = IPSEC_API_CRYPTO_ALG_NONE;
11095   vl_api_ipsec_integ_alg_t integ_alg = IPSEC_API_INTEG_ALG_NONE;
11096   vl_api_ipsec_sad_flags_t flags = IPSEC_API_SAD_FLAG_NONE;
11097   vl_api_ipsec_proto_t protocol = IPSEC_API_PROTO_AH;
11098   vl_api_address_t tun_src, tun_dst;
11099   int ret;
11100
11101   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11102     {
11103       if (unformat (i, "del"))
11104         is_add = 0;
11105       else if (unformat (i, "sad_id %d", &sad_id))
11106         ;
11107       else if (unformat (i, "spi %d", &spi))
11108         ;
11109       else if (unformat (i, "esp"))
11110         protocol = IPSEC_API_PROTO_ESP;
11111       else
11112         if (unformat (i, "tunnel_src %U", unformat_vl_api_address, &tun_src))
11113         {
11114           flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL;
11115           if (ADDRESS_IP6 == tun_src.af)
11116             flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL_V6;
11117         }
11118       else
11119         if (unformat (i, "tunnel_dst %U", unformat_vl_api_address, &tun_dst))
11120         {
11121           flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL;
11122           if (ADDRESS_IP6 == tun_src.af)
11123             flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL_V6;
11124         }
11125       else
11126         if (unformat (i, "crypto_alg %U",
11127                       unformat_ipsec_api_crypto_alg, &crypto_alg))
11128         ;
11129       else if (unformat (i, "crypto_key %U", unformat_hex_string, &ck))
11130         ;
11131       else if (unformat (i, "integ_alg %U",
11132                          unformat_ipsec_api_integ_alg, &integ_alg))
11133         ;
11134       else if (unformat (i, "integ_key %U", unformat_hex_string, &ik))
11135         ;
11136       else
11137         {
11138           clib_warning ("parse error '%U'", format_unformat_error, i);
11139           return -99;
11140         }
11141
11142     }
11143
11144   M (IPSEC_SAD_ENTRY_ADD_DEL, mp);
11145
11146   mp->is_add = is_add;
11147   mp->entry.sad_id = ntohl (sad_id);
11148   mp->entry.protocol = protocol;
11149   mp->entry.spi = ntohl (spi);
11150   mp->entry.flags = flags;
11151
11152   mp->entry.crypto_algorithm = crypto_alg;
11153   mp->entry.integrity_algorithm = integ_alg;
11154   mp->entry.crypto_key.length = vec_len (ck);
11155   mp->entry.integrity_key.length = vec_len (ik);
11156
11157   if (mp->entry.crypto_key.length > sizeof (mp->entry.crypto_key.data))
11158     mp->entry.crypto_key.length = sizeof (mp->entry.crypto_key.data);
11159
11160   if (mp->entry.integrity_key.length > sizeof (mp->entry.integrity_key.data))
11161     mp->entry.integrity_key.length = sizeof (mp->entry.integrity_key.data);
11162
11163   if (ck)
11164     clib_memcpy (mp->entry.crypto_key.data, ck, mp->entry.crypto_key.length);
11165   if (ik)
11166     clib_memcpy (mp->entry.integrity_key.data, ik,
11167                  mp->entry.integrity_key.length);
11168
11169   if (flags & IPSEC_API_SAD_FLAG_IS_TUNNEL)
11170     {
11171       clib_memcpy (&mp->entry.tunnel_src, &tun_src,
11172                    sizeof (mp->entry.tunnel_src));
11173       clib_memcpy (&mp->entry.tunnel_dst, &tun_dst,
11174                    sizeof (mp->entry.tunnel_dst));
11175     }
11176
11177   S (mp);
11178   W (ret);
11179   return ret;
11180 }
11181
11182 static int
11183 api_ipsec_tunnel_if_add_del (vat_main_t * vam)
11184 {
11185   unformat_input_t *i = vam->input;
11186   vl_api_ipsec_tunnel_if_add_del_t *mp;
11187   u32 local_spi = 0, remote_spi = 0;
11188   u32 crypto_alg = 0, integ_alg = 0;
11189   u8 *lck = NULL, *rck = NULL;
11190   u8 *lik = NULL, *rik = NULL;
11191   vl_api_address_t local_ip = { 0 };
11192   vl_api_address_t remote_ip = { 0 };
11193   f64 before = 0;
11194   u8 is_add = 1;
11195   u8 esn = 0;
11196   u8 anti_replay = 0;
11197   u8 renumber = 0;
11198   u32 instance = ~0;
11199   u32 count = 1, jj;
11200   int ret = -1;
11201
11202   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11203     {
11204       if (unformat (i, "del"))
11205         is_add = 0;
11206       else if (unformat (i, "esn"))
11207         esn = 1;
11208       else if (unformat (i, "anti-replay"))
11209         anti_replay = 1;
11210       else if (unformat (i, "count %d", &count))
11211         ;
11212       else if (unformat (i, "local_spi %d", &local_spi))
11213         ;
11214       else if (unformat (i, "remote_spi %d", &remote_spi))
11215         ;
11216       else
11217         if (unformat (i, "local_ip %U", unformat_vl_api_address, &local_ip))
11218         ;
11219       else
11220         if (unformat (i, "remote_ip %U", unformat_vl_api_address, &remote_ip))
11221         ;
11222       else if (unformat (i, "local_crypto_key %U", unformat_hex_string, &lck))
11223         ;
11224       else
11225         if (unformat (i, "remote_crypto_key %U", unformat_hex_string, &rck))
11226         ;
11227       else if (unformat (i, "local_integ_key %U", unformat_hex_string, &lik))
11228         ;
11229       else if (unformat (i, "remote_integ_key %U", unformat_hex_string, &rik))
11230         ;
11231       else
11232         if (unformat
11233             (i, "crypto_alg %U", unformat_ipsec_api_crypto_alg, &crypto_alg))
11234         {
11235           if (crypto_alg >= IPSEC_CRYPTO_N_ALG)
11236             {
11237               errmsg ("unsupported crypto-alg: '%U'\n",
11238                       format_ipsec_crypto_alg, crypto_alg);
11239               return -99;
11240             }
11241         }
11242       else
11243         if (unformat
11244             (i, "integ_alg %U", unformat_ipsec_api_integ_alg, &integ_alg))
11245         {
11246           if (integ_alg >= IPSEC_INTEG_N_ALG)
11247             {
11248               errmsg ("unsupported integ-alg: '%U'\n",
11249                       format_ipsec_integ_alg, integ_alg);
11250               return -99;
11251             }
11252         }
11253       else if (unformat (i, "instance %u", &instance))
11254         renumber = 1;
11255       else
11256         {
11257           errmsg ("parse error '%U'\n", format_unformat_error, i);
11258           return -99;
11259         }
11260     }
11261
11262   if (count > 1)
11263     {
11264       /* Turn on async mode */
11265       vam->async_mode = 1;
11266       vam->async_errors = 0;
11267       before = vat_time_now (vam);
11268     }
11269
11270   for (jj = 0; jj < count; jj++)
11271     {
11272       M (IPSEC_TUNNEL_IF_ADD_DEL, mp);
11273
11274       mp->is_add = is_add;
11275       mp->esn = esn;
11276       mp->anti_replay = anti_replay;
11277
11278       if (jj > 0)
11279         increment_address (&remote_ip);
11280
11281       clib_memcpy (&mp->local_ip, &local_ip, sizeof (local_ip));
11282       clib_memcpy (&mp->remote_ip, &remote_ip, sizeof (remote_ip));
11283
11284       mp->local_spi = htonl (local_spi + jj);
11285       mp->remote_spi = htonl (remote_spi + jj);
11286       mp->crypto_alg = (u8) crypto_alg;
11287
11288       mp->local_crypto_key_len = 0;
11289       if (lck)
11290         {
11291           mp->local_crypto_key_len = vec_len (lck);
11292           if (mp->local_crypto_key_len > sizeof (mp->local_crypto_key))
11293             mp->local_crypto_key_len = sizeof (mp->local_crypto_key);
11294           clib_memcpy (mp->local_crypto_key, lck, mp->local_crypto_key_len);
11295         }
11296
11297       mp->remote_crypto_key_len = 0;
11298       if (rck)
11299         {
11300           mp->remote_crypto_key_len = vec_len (rck);
11301           if (mp->remote_crypto_key_len > sizeof (mp->remote_crypto_key))
11302             mp->remote_crypto_key_len = sizeof (mp->remote_crypto_key);
11303           clib_memcpy (mp->remote_crypto_key, rck, mp->remote_crypto_key_len);
11304         }
11305
11306       mp->integ_alg = (u8) integ_alg;
11307
11308       mp->local_integ_key_len = 0;
11309       if (lik)
11310         {
11311           mp->local_integ_key_len = vec_len (lik);
11312           if (mp->local_integ_key_len > sizeof (mp->local_integ_key))
11313             mp->local_integ_key_len = sizeof (mp->local_integ_key);
11314           clib_memcpy (mp->local_integ_key, lik, mp->local_integ_key_len);
11315         }
11316
11317       mp->remote_integ_key_len = 0;
11318       if (rik)
11319         {
11320           mp->remote_integ_key_len = vec_len (rik);
11321           if (mp->remote_integ_key_len > sizeof (mp->remote_integ_key))
11322             mp->remote_integ_key_len = sizeof (mp->remote_integ_key);
11323           clib_memcpy (mp->remote_integ_key, rik, mp->remote_integ_key_len);
11324         }
11325
11326       if (renumber)
11327         {
11328           mp->renumber = renumber;
11329           mp->show_instance = ntohl (instance);
11330         }
11331       S (mp);
11332     }
11333
11334   /* When testing multiple add/del ops, use a control-ping to sync */
11335   if (count > 1)
11336     {
11337       vl_api_control_ping_t *mp_ping;
11338       f64 after;
11339       f64 timeout;
11340
11341       /* Shut off async mode */
11342       vam->async_mode = 0;
11343
11344       MPING (CONTROL_PING, mp_ping);
11345       S (mp_ping);
11346
11347       timeout = vat_time_now (vam) + 1.0;
11348       while (vat_time_now (vam) < timeout)
11349         if (vam->result_ready == 1)
11350           goto out;
11351       vam->retval = -99;
11352
11353     out:
11354       if (vam->retval == -99)
11355         errmsg ("timeout");
11356
11357       if (vam->async_errors > 0)
11358         {
11359           errmsg ("%d asynchronous errors", vam->async_errors);
11360           vam->retval = -98;
11361         }
11362       vam->async_errors = 0;
11363       after = vat_time_now (vam);
11364
11365       /* slim chance, but we might have eaten SIGTERM on the first iteration */
11366       if (jj > 0)
11367         count = jj;
11368
11369       print (vam->ofp, "%d tunnels in %.6f secs, %.2f tunnels/sec",
11370              count, after - before, count / (after - before));
11371     }
11372   else
11373     {
11374       /* Wait for a reply... */
11375       W (ret);
11376       return ret;
11377     }
11378
11379   return ret;
11380 }
11381
11382 static void
11383 vl_api_ipsec_sa_details_t_handler (vl_api_ipsec_sa_details_t * mp)
11384 {
11385   vat_main_t *vam = &vat_main;
11386
11387   print (vam->ofp, "sa_id %u sw_if_index %u spi %u proto %u crypto_alg %u "
11388          "crypto_key %U integ_alg %u integ_key %U flags %x "
11389          "tunnel_src_addr %U tunnel_dst_addr %U "
11390          "salt %u seq_outbound %lu last_seq_inbound %lu "
11391          "replay_window %lu stat_index %u\n",
11392          ntohl (mp->entry.sad_id),
11393          ntohl (mp->sw_if_index),
11394          ntohl (mp->entry.spi),
11395          ntohl (mp->entry.protocol),
11396          ntohl (mp->entry.crypto_algorithm),
11397          format_hex_bytes, mp->entry.crypto_key.data,
11398          mp->entry.crypto_key.length, ntohl (mp->entry.integrity_algorithm),
11399          format_hex_bytes, mp->entry.integrity_key.data,
11400          mp->entry.integrity_key.length, ntohl (mp->entry.flags),
11401          format_vl_api_address, &mp->entry.tunnel_src, format_vl_api_address,
11402          &mp->entry.tunnel_dst, ntohl (mp->salt),
11403          clib_net_to_host_u64 (mp->seq_outbound),
11404          clib_net_to_host_u64 (mp->last_seq_inbound),
11405          clib_net_to_host_u64 (mp->replay_window), ntohl (mp->stat_index));
11406 }
11407
11408 #define vl_api_ipsec_sa_details_t_endian vl_noop_handler
11409 #define vl_api_ipsec_sa_details_t_print vl_noop_handler
11410
11411 static void vl_api_ipsec_sa_details_t_handler_json
11412   (vl_api_ipsec_sa_details_t * mp)
11413 {
11414   vat_main_t *vam = &vat_main;
11415   vat_json_node_t *node = NULL;
11416   vl_api_ipsec_sad_flags_t flags;
11417
11418   if (VAT_JSON_ARRAY != vam->json_tree.type)
11419     {
11420       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
11421       vat_json_init_array (&vam->json_tree);
11422     }
11423   node = vat_json_array_add (&vam->json_tree);
11424
11425   vat_json_init_object (node);
11426   vat_json_object_add_uint (node, "sa_id", ntohl (mp->entry.sad_id));
11427   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
11428   vat_json_object_add_uint (node, "spi", ntohl (mp->entry.spi));
11429   vat_json_object_add_uint (node, "proto", ntohl (mp->entry.protocol));
11430   vat_json_object_add_uint (node, "crypto_alg",
11431                             ntohl (mp->entry.crypto_algorithm));
11432   vat_json_object_add_uint (node, "integ_alg",
11433                             ntohl (mp->entry.integrity_algorithm));
11434   flags = ntohl (mp->entry.flags);
11435   vat_json_object_add_uint (node, "use_esn",
11436                             ! !(flags & IPSEC_API_SAD_FLAG_USE_ESN));
11437   vat_json_object_add_uint (node, "use_anti_replay",
11438                             ! !(flags & IPSEC_API_SAD_FLAG_USE_ANTI_REPLAY));
11439   vat_json_object_add_uint (node, "is_tunnel",
11440                             ! !(flags & IPSEC_API_SAD_FLAG_IS_TUNNEL));
11441   vat_json_object_add_uint (node, "is_tunnel_ip6",
11442                             ! !(flags & IPSEC_API_SAD_FLAG_IS_TUNNEL_V6));
11443   vat_json_object_add_uint (node, "udp_encap",
11444                             ! !(flags & IPSEC_API_SAD_FLAG_UDP_ENCAP));
11445   vat_json_object_add_bytes (node, "crypto_key", mp->entry.crypto_key.data,
11446                              mp->entry.crypto_key.length);
11447   vat_json_object_add_bytes (node, "integ_key", mp->entry.integrity_key.data,
11448                              mp->entry.integrity_key.length);
11449   vat_json_object_add_address (node, "src", &mp->entry.tunnel_src);
11450   vat_json_object_add_address (node, "dst", &mp->entry.tunnel_dst);
11451   vat_json_object_add_uint (node, "replay_window",
11452                             clib_net_to_host_u64 (mp->replay_window));
11453   vat_json_object_add_uint (node, "stat_index", ntohl (mp->stat_index));
11454 }
11455
11456 static int
11457 api_ipsec_sa_dump (vat_main_t * vam)
11458 {
11459   unformat_input_t *i = vam->input;
11460   vl_api_ipsec_sa_dump_t *mp;
11461   vl_api_control_ping_t *mp_ping;
11462   u32 sa_id = ~0;
11463   int ret;
11464
11465   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11466     {
11467       if (unformat (i, "sa_id %d", &sa_id))
11468         ;
11469       else
11470         {
11471           clib_warning ("parse error '%U'", format_unformat_error, i);
11472           return -99;
11473         }
11474     }
11475
11476   M (IPSEC_SA_DUMP, mp);
11477
11478   mp->sa_id = ntohl (sa_id);
11479
11480   S (mp);
11481
11482   /* Use a control ping for synchronization */
11483   M (CONTROL_PING, mp_ping);
11484   S (mp_ping);
11485
11486   W (ret);
11487   return ret;
11488 }
11489
11490 static int
11491 api_ipsec_tunnel_if_set_sa (vat_main_t * vam)
11492 {
11493   unformat_input_t *i = vam->input;
11494   vl_api_ipsec_tunnel_if_set_sa_t *mp;
11495   u32 sw_if_index = ~0;
11496   u32 sa_id = ~0;
11497   u8 is_outbound = (u8) ~ 0;
11498   int ret;
11499
11500   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11501     {
11502       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
11503         ;
11504       else if (unformat (i, "sa_id %d", &sa_id))
11505         ;
11506       else if (unformat (i, "outbound"))
11507         is_outbound = 1;
11508       else if (unformat (i, "inbound"))
11509         is_outbound = 0;
11510       else
11511         {
11512           clib_warning ("parse error '%U'", format_unformat_error, i);
11513           return -99;
11514         }
11515     }
11516
11517   if (sw_if_index == ~0)
11518     {
11519       errmsg ("interface must be specified");
11520       return -99;
11521     }
11522
11523   if (sa_id == ~0)
11524     {
11525       errmsg ("SA ID must be specified");
11526       return -99;
11527     }
11528
11529   M (IPSEC_TUNNEL_IF_SET_SA, mp);
11530
11531   mp->sw_if_index = htonl (sw_if_index);
11532   mp->sa_id = htonl (sa_id);
11533   mp->is_outbound = is_outbound;
11534
11535   S (mp);
11536   W (ret);
11537
11538   return ret;
11539 }
11540
11541 static int
11542 api_get_first_msg_id (vat_main_t * vam)
11543 {
11544   vl_api_get_first_msg_id_t *mp;
11545   unformat_input_t *i = vam->input;
11546   u8 *name;
11547   u8 name_set = 0;
11548   int ret;
11549
11550   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11551     {
11552       if (unformat (i, "client %s", &name))
11553         name_set = 1;
11554       else
11555         break;
11556     }
11557
11558   if (name_set == 0)
11559     {
11560       errmsg ("missing client name");
11561       return -99;
11562     }
11563   vec_add1 (name, 0);
11564
11565   if (vec_len (name) > 63)
11566     {
11567       errmsg ("client name too long");
11568       return -99;
11569     }
11570
11571   M (GET_FIRST_MSG_ID, mp);
11572   clib_memcpy (mp->name, name, vec_len (name));
11573   S (mp);
11574   W (ret);
11575   return ret;
11576 }
11577
11578 static int
11579 api_cop_interface_enable_disable (vat_main_t * vam)
11580 {
11581   unformat_input_t *line_input = vam->input;
11582   vl_api_cop_interface_enable_disable_t *mp;
11583   u32 sw_if_index = ~0;
11584   u8 enable_disable = 1;
11585   int ret;
11586
11587   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
11588     {
11589       if (unformat (line_input, "disable"))
11590         enable_disable = 0;
11591       if (unformat (line_input, "enable"))
11592         enable_disable = 1;
11593       else if (unformat (line_input, "%U", api_unformat_sw_if_index,
11594                          vam, &sw_if_index))
11595         ;
11596       else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
11597         ;
11598       else
11599         break;
11600     }
11601
11602   if (sw_if_index == ~0)
11603     {
11604       errmsg ("missing interface name or sw_if_index");
11605       return -99;
11606     }
11607
11608   /* Construct the API message */
11609   M (COP_INTERFACE_ENABLE_DISABLE, mp);
11610   mp->sw_if_index = ntohl (sw_if_index);
11611   mp->enable_disable = enable_disable;
11612
11613   /* send it... */
11614   S (mp);
11615   /* Wait for the reply */
11616   W (ret);
11617   return ret;
11618 }
11619
11620 static int
11621 api_cop_whitelist_enable_disable (vat_main_t * vam)
11622 {
11623   unformat_input_t *line_input = vam->input;
11624   vl_api_cop_whitelist_enable_disable_t *mp;
11625   u32 sw_if_index = ~0;
11626   u8 ip4 = 0, ip6 = 0, default_cop = 0;
11627   u32 fib_id = 0;
11628   int ret;
11629
11630   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
11631     {
11632       if (unformat (line_input, "ip4"))
11633         ip4 = 1;
11634       else if (unformat (line_input, "ip6"))
11635         ip6 = 1;
11636       else if (unformat (line_input, "default"))
11637         default_cop = 1;
11638       else if (unformat (line_input, "%U", api_unformat_sw_if_index,
11639                          vam, &sw_if_index))
11640         ;
11641       else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
11642         ;
11643       else if (unformat (line_input, "fib-id %d", &fib_id))
11644         ;
11645       else
11646         break;
11647     }
11648
11649   if (sw_if_index == ~0)
11650     {
11651       errmsg ("missing interface name or sw_if_index");
11652       return -99;
11653     }
11654
11655   /* Construct the API message */
11656   M (COP_WHITELIST_ENABLE_DISABLE, mp);
11657   mp->sw_if_index = ntohl (sw_if_index);
11658   mp->fib_id = ntohl (fib_id);
11659   mp->ip4 = ip4;
11660   mp->ip6 = ip6;
11661   mp->default_cop = default_cop;
11662
11663   /* send it... */
11664   S (mp);
11665   /* Wait for the reply */
11666   W (ret);
11667   return ret;
11668 }
11669
11670 static int
11671 api_get_node_graph (vat_main_t * vam)
11672 {
11673   vl_api_get_node_graph_t *mp;
11674   int ret;
11675
11676   M (GET_NODE_GRAPH, mp);
11677
11678   /* send it... */
11679   S (mp);
11680   /* Wait for the reply */
11681   W (ret);
11682   return ret;
11683 }
11684
11685 static int
11686 api_af_packet_create (vat_main_t * vam)
11687 {
11688   unformat_input_t *i = vam->input;
11689   vl_api_af_packet_create_t *mp;
11690   u8 *host_if_name = 0;
11691   u8 hw_addr[6];
11692   u8 random_hw_addr = 1;
11693   int ret;
11694
11695   clib_memset (hw_addr, 0, sizeof (hw_addr));
11696
11697   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11698     {
11699       if (unformat (i, "name %s", &host_if_name))
11700         vec_add1 (host_if_name, 0);
11701       else if (unformat (i, "hw_addr %U", unformat_ethernet_address, hw_addr))
11702         random_hw_addr = 0;
11703       else
11704         break;
11705     }
11706
11707   if (!vec_len (host_if_name))
11708     {
11709       errmsg ("host-interface name must be specified");
11710       return -99;
11711     }
11712
11713   if (vec_len (host_if_name) > 64)
11714     {
11715       errmsg ("host-interface name too long");
11716       return -99;
11717     }
11718
11719   M (AF_PACKET_CREATE, mp);
11720
11721   clib_memcpy (mp->host_if_name, host_if_name, vec_len (host_if_name));
11722   clib_memcpy (mp->hw_addr, hw_addr, 6);
11723   mp->use_random_hw_addr = random_hw_addr;
11724   vec_free (host_if_name);
11725
11726   S (mp);
11727
11728   /* *INDENT-OFF* */
11729   W2 (ret,
11730       ({
11731         if (ret == 0)
11732           fprintf (vam->ofp ? vam->ofp : stderr,
11733                    " new sw_if_index = %d\n", vam->sw_if_index);
11734       }));
11735   /* *INDENT-ON* */
11736   return ret;
11737 }
11738
11739 static int
11740 api_af_packet_delete (vat_main_t * vam)
11741 {
11742   unformat_input_t *i = vam->input;
11743   vl_api_af_packet_delete_t *mp;
11744   u8 *host_if_name = 0;
11745   int ret;
11746
11747   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11748     {
11749       if (unformat (i, "name %s", &host_if_name))
11750         vec_add1 (host_if_name, 0);
11751       else
11752         break;
11753     }
11754
11755   if (!vec_len (host_if_name))
11756     {
11757       errmsg ("host-interface name must be specified");
11758       return -99;
11759     }
11760
11761   if (vec_len (host_if_name) > 64)
11762     {
11763       errmsg ("host-interface name too long");
11764       return -99;
11765     }
11766
11767   M (AF_PACKET_DELETE, mp);
11768
11769   clib_memcpy (mp->host_if_name, host_if_name, vec_len (host_if_name));
11770   vec_free (host_if_name);
11771
11772   S (mp);
11773   W (ret);
11774   return ret;
11775 }
11776
11777 static void vl_api_af_packet_details_t_handler
11778   (vl_api_af_packet_details_t * mp)
11779 {
11780   vat_main_t *vam = &vat_main;
11781
11782   print (vam->ofp, "%-16s %d",
11783          mp->host_if_name, clib_net_to_host_u32 (mp->sw_if_index));
11784 }
11785
11786 static void vl_api_af_packet_details_t_handler_json
11787   (vl_api_af_packet_details_t * mp)
11788 {
11789   vat_main_t *vam = &vat_main;
11790   vat_json_node_t *node = NULL;
11791
11792   if (VAT_JSON_ARRAY != vam->json_tree.type)
11793     {
11794       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
11795       vat_json_init_array (&vam->json_tree);
11796     }
11797   node = vat_json_array_add (&vam->json_tree);
11798
11799   vat_json_init_object (node);
11800   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
11801   vat_json_object_add_string_copy (node, "dev_name", mp->host_if_name);
11802 }
11803
11804 static int
11805 api_af_packet_dump (vat_main_t * vam)
11806 {
11807   vl_api_af_packet_dump_t *mp;
11808   vl_api_control_ping_t *mp_ping;
11809   int ret;
11810
11811   print (vam->ofp, "\n%-16s %s", "dev_name", "sw_if_index");
11812   /* Get list of tap interfaces */
11813   M (AF_PACKET_DUMP, mp);
11814   S (mp);
11815
11816   /* Use a control ping for synchronization */
11817   MPING (CONTROL_PING, mp_ping);
11818   S (mp_ping);
11819
11820   W (ret);
11821   return ret;
11822 }
11823
11824 static int
11825 api_policer_add_del (vat_main_t * vam)
11826 {
11827   unformat_input_t *i = vam->input;
11828   vl_api_policer_add_del_t *mp;
11829   u8 is_add = 1;
11830   u8 *name = 0;
11831   u32 cir = 0;
11832   u32 eir = 0;
11833   u64 cb = 0;
11834   u64 eb = 0;
11835   u8 rate_type = 0;
11836   u8 round_type = 0;
11837   u8 type = 0;
11838   u8 color_aware = 0;
11839   sse2_qos_pol_action_params_st conform_action, exceed_action, violate_action;
11840   int ret;
11841
11842   conform_action.action_type = SSE2_QOS_ACTION_TRANSMIT;
11843   conform_action.dscp = 0;
11844   exceed_action.action_type = SSE2_QOS_ACTION_MARK_AND_TRANSMIT;
11845   exceed_action.dscp = 0;
11846   violate_action.action_type = SSE2_QOS_ACTION_DROP;
11847   violate_action.dscp = 0;
11848
11849   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11850     {
11851       if (unformat (i, "del"))
11852         is_add = 0;
11853       else if (unformat (i, "name %s", &name))
11854         vec_add1 (name, 0);
11855       else if (unformat (i, "cir %u", &cir))
11856         ;
11857       else if (unformat (i, "eir %u", &eir))
11858         ;
11859       else if (unformat (i, "cb %u", &cb))
11860         ;
11861       else if (unformat (i, "eb %u", &eb))
11862         ;
11863       else if (unformat (i, "rate_type %U", unformat_policer_rate_type,
11864                          &rate_type))
11865         ;
11866       else if (unformat (i, "round_type %U", unformat_policer_round_type,
11867                          &round_type))
11868         ;
11869       else if (unformat (i, "type %U", unformat_policer_type, &type))
11870         ;
11871       else if (unformat (i, "conform_action %U", unformat_policer_action_type,
11872                          &conform_action))
11873         ;
11874       else if (unformat (i, "exceed_action %U", unformat_policer_action_type,
11875                          &exceed_action))
11876         ;
11877       else if (unformat (i, "violate_action %U", unformat_policer_action_type,
11878                          &violate_action))
11879         ;
11880       else if (unformat (i, "color-aware"))
11881         color_aware = 1;
11882       else
11883         break;
11884     }
11885
11886   if (!vec_len (name))
11887     {
11888       errmsg ("policer name must be specified");
11889       return -99;
11890     }
11891
11892   if (vec_len (name) > 64)
11893     {
11894       errmsg ("policer name too long");
11895       return -99;
11896     }
11897
11898   M (POLICER_ADD_DEL, mp);
11899
11900   clib_memcpy (mp->name, name, vec_len (name));
11901   vec_free (name);
11902   mp->is_add = is_add;
11903   mp->cir = ntohl (cir);
11904   mp->eir = ntohl (eir);
11905   mp->cb = clib_net_to_host_u64 (cb);
11906   mp->eb = clib_net_to_host_u64 (eb);
11907   mp->rate_type = rate_type;
11908   mp->round_type = round_type;
11909   mp->type = type;
11910   mp->conform_action.type = conform_action.action_type;
11911   mp->conform_action.dscp = conform_action.dscp;
11912   mp->exceed_action.type = exceed_action.action_type;
11913   mp->exceed_action.dscp = exceed_action.dscp;
11914   mp->violate_action.type = violate_action.action_type;
11915   mp->violate_action.dscp = violate_action.dscp;
11916   mp->color_aware = color_aware;
11917
11918   S (mp);
11919   W (ret);
11920   return ret;
11921 }
11922
11923 static int
11924 api_policer_dump (vat_main_t * vam)
11925 {
11926   unformat_input_t *i = vam->input;
11927   vl_api_policer_dump_t *mp;
11928   vl_api_control_ping_t *mp_ping;
11929   u8 *match_name = 0;
11930   u8 match_name_valid = 0;
11931   int ret;
11932
11933   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11934     {
11935       if (unformat (i, "name %s", &match_name))
11936         {
11937           vec_add1 (match_name, 0);
11938           match_name_valid = 1;
11939         }
11940       else
11941         break;
11942     }
11943
11944   M (POLICER_DUMP, mp);
11945   mp->match_name_valid = match_name_valid;
11946   clib_memcpy (mp->match_name, match_name, vec_len (match_name));
11947   vec_free (match_name);
11948   /* send it... */
11949   S (mp);
11950
11951   /* Use a control ping for synchronization */
11952   MPING (CONTROL_PING, mp_ping);
11953   S (mp_ping);
11954
11955   /* Wait for a reply... */
11956   W (ret);
11957   return ret;
11958 }
11959
11960 static int
11961 api_policer_classify_set_interface (vat_main_t * vam)
11962 {
11963   unformat_input_t *i = vam->input;
11964   vl_api_policer_classify_set_interface_t *mp;
11965   u32 sw_if_index;
11966   int sw_if_index_set;
11967   u32 ip4_table_index = ~0;
11968   u32 ip6_table_index = ~0;
11969   u32 l2_table_index = ~0;
11970   u8 is_add = 1;
11971   int ret;
11972
11973   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11974     {
11975       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
11976         sw_if_index_set = 1;
11977       else if (unformat (i, "sw_if_index %d", &sw_if_index))
11978         sw_if_index_set = 1;
11979       else if (unformat (i, "del"))
11980         is_add = 0;
11981       else if (unformat (i, "ip4-table %d", &ip4_table_index))
11982         ;
11983       else if (unformat (i, "ip6-table %d", &ip6_table_index))
11984         ;
11985       else if (unformat (i, "l2-table %d", &l2_table_index))
11986         ;
11987       else
11988         {
11989           clib_warning ("parse error '%U'", format_unformat_error, i);
11990           return -99;
11991         }
11992     }
11993
11994   if (sw_if_index_set == 0)
11995     {
11996       errmsg ("missing interface name or sw_if_index");
11997       return -99;
11998     }
11999
12000   M (POLICER_CLASSIFY_SET_INTERFACE, mp);
12001
12002   mp->sw_if_index = ntohl (sw_if_index);
12003   mp->ip4_table_index = ntohl (ip4_table_index);
12004   mp->ip6_table_index = ntohl (ip6_table_index);
12005   mp->l2_table_index = ntohl (l2_table_index);
12006   mp->is_add = is_add;
12007
12008   S (mp);
12009   W (ret);
12010   return ret;
12011 }
12012
12013 static int
12014 api_policer_classify_dump (vat_main_t * vam)
12015 {
12016   unformat_input_t *i = vam->input;
12017   vl_api_policer_classify_dump_t *mp;
12018   vl_api_control_ping_t *mp_ping;
12019   u8 type = POLICER_CLASSIFY_N_TABLES;
12020   int ret;
12021
12022   if (unformat (i, "type %U", unformat_policer_classify_table_type, &type))
12023     ;
12024   else
12025     {
12026       errmsg ("classify table type must be specified");
12027       return -99;
12028     }
12029
12030   if (!vam->json_output)
12031     {
12032       print (vam->ofp, "%10s%20s", "Intfc idx", "Classify table");
12033     }
12034
12035   M (POLICER_CLASSIFY_DUMP, mp);
12036   mp->type = type;
12037   /* send it... */
12038   S (mp);
12039
12040   /* Use a control ping for synchronization */
12041   MPING (CONTROL_PING, mp_ping);
12042   S (mp_ping);
12043
12044   /* Wait for a reply... */
12045   W (ret);
12046   return ret;
12047 }
12048
12049 static u8 *
12050 format_fib_api_path_nh_proto (u8 * s, va_list * args)
12051 {
12052   vl_api_fib_path_nh_proto_t proto =
12053     va_arg (*args, vl_api_fib_path_nh_proto_t);
12054
12055   switch (proto)
12056     {
12057     case FIB_API_PATH_NH_PROTO_IP4:
12058       s = format (s, "ip4");
12059       break;
12060     case FIB_API_PATH_NH_PROTO_IP6:
12061       s = format (s, "ip6");
12062       break;
12063     case FIB_API_PATH_NH_PROTO_MPLS:
12064       s = format (s, "mpls");
12065       break;
12066     case FIB_API_PATH_NH_PROTO_BIER:
12067       s = format (s, "bier");
12068       break;
12069     case FIB_API_PATH_NH_PROTO_ETHERNET:
12070       s = format (s, "ethernet");
12071       break;
12072     }
12073
12074   return (s);
12075 }
12076
12077 static u8 *
12078 format_vl_api_ip_address_union (u8 * s, va_list * args)
12079 {
12080   vl_api_address_family_t af = va_arg (*args, int);
12081   const vl_api_address_union_t *u = va_arg (*args, vl_api_address_union_t *);
12082
12083   switch (af)
12084     {
12085     case ADDRESS_IP4:
12086       s = format (s, "%U", format_ip4_address, u->ip4);
12087       break;
12088     case ADDRESS_IP6:
12089       s = format (s, "%U", format_ip6_address, u->ip6);
12090       break;
12091     }
12092   return (s);
12093 }
12094
12095 static u8 *
12096 format_vl_api_fib_path_type (u8 * s, va_list * args)
12097 {
12098   vl_api_fib_path_type_t t = va_arg (*args, vl_api_fib_path_type_t);
12099
12100   switch (t)
12101     {
12102     case FIB_API_PATH_TYPE_NORMAL:
12103       s = format (s, "normal");
12104       break;
12105     case FIB_API_PATH_TYPE_LOCAL:
12106       s = format (s, "local");
12107       break;
12108     case FIB_API_PATH_TYPE_DROP:
12109       s = format (s, "drop");
12110       break;
12111     case FIB_API_PATH_TYPE_UDP_ENCAP:
12112       s = format (s, "udp-encap");
12113       break;
12114     case FIB_API_PATH_TYPE_BIER_IMP:
12115       s = format (s, "bier-imp");
12116       break;
12117     case FIB_API_PATH_TYPE_ICMP_UNREACH:
12118       s = format (s, "unreach");
12119       break;
12120     case FIB_API_PATH_TYPE_ICMP_PROHIBIT:
12121       s = format (s, "prohibit");
12122       break;
12123     case FIB_API_PATH_TYPE_SOURCE_LOOKUP:
12124       s = format (s, "src-lookup");
12125       break;
12126     case FIB_API_PATH_TYPE_DVR:
12127       s = format (s, "dvr");
12128       break;
12129     case FIB_API_PATH_TYPE_INTERFACE_RX:
12130       s = format (s, "interface-rx");
12131       break;
12132     case FIB_API_PATH_TYPE_CLASSIFY:
12133       s = format (s, "classify");
12134       break;
12135     }
12136
12137   return (s);
12138 }
12139
12140 static void
12141 vl_api_fib_path_print (vat_main_t * vam, vl_api_fib_path_t * fp)
12142 {
12143   print (vam->ofp,
12144          "  weight %d, sw_if_index %d, type %U, afi %U, next_hop %U",
12145          ntohl (fp->weight), ntohl (fp->sw_if_index),
12146          format_vl_api_fib_path_type, fp->type,
12147          format_fib_api_path_nh_proto, fp->proto,
12148          format_vl_api_ip_address_union, &fp->nh.address);
12149 }
12150
12151 static void
12152 vl_api_mpls_fib_path_json_print (vat_json_node_t * node,
12153                                  vl_api_fib_path_t * fp)
12154 {
12155   struct in_addr ip4;
12156   struct in6_addr ip6;
12157
12158   vat_json_object_add_uint (node, "weight", ntohl (fp->weight));
12159   vat_json_object_add_uint (node, "sw_if_index", ntohl (fp->sw_if_index));
12160   vat_json_object_add_uint (node, "type", fp->type);
12161   vat_json_object_add_uint (node, "next_hop_proto", fp->proto);
12162   if (fp->proto == FIB_API_PATH_NH_PROTO_IP4)
12163     {
12164       clib_memcpy (&ip4, &fp->nh.address.ip4, sizeof (ip4));
12165       vat_json_object_add_ip4 (node, "next_hop", ip4);
12166     }
12167   else if (fp->proto == FIB_API_PATH_NH_PROTO_IP6)
12168     {
12169       clib_memcpy (&ip6, &fp->nh.address.ip6, sizeof (ip6));
12170       vat_json_object_add_ip6 (node, "next_hop", ip6);
12171     }
12172 }
12173
12174 static void
12175 vl_api_mpls_tunnel_details_t_handler (vl_api_mpls_tunnel_details_t * mp)
12176 {
12177   vat_main_t *vam = &vat_main;
12178   int count = ntohl (mp->mt_tunnel.mt_n_paths);
12179   vl_api_fib_path_t *fp;
12180   i32 i;
12181
12182   print (vam->ofp, "sw_if_index %d via:",
12183          ntohl (mp->mt_tunnel.mt_sw_if_index));
12184   fp = mp->mt_tunnel.mt_paths;
12185   for (i = 0; i < count; i++)
12186     {
12187       vl_api_fib_path_print (vam, fp);
12188       fp++;
12189     }
12190
12191   print (vam->ofp, "");
12192 }
12193
12194 #define vl_api_mpls_tunnel_details_t_endian vl_noop_handler
12195 #define vl_api_mpls_tunnel_details_t_print vl_noop_handler
12196
12197 static void
12198 vl_api_mpls_tunnel_details_t_handler_json (vl_api_mpls_tunnel_details_t * mp)
12199 {
12200   vat_main_t *vam = &vat_main;
12201   vat_json_node_t *node = NULL;
12202   int count = ntohl (mp->mt_tunnel.mt_n_paths);
12203   vl_api_fib_path_t *fp;
12204   i32 i;
12205
12206   if (VAT_JSON_ARRAY != vam->json_tree.type)
12207     {
12208       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
12209       vat_json_init_array (&vam->json_tree);
12210     }
12211   node = vat_json_array_add (&vam->json_tree);
12212
12213   vat_json_init_object (node);
12214   vat_json_object_add_uint (node, "sw_if_index",
12215                             ntohl (mp->mt_tunnel.mt_sw_if_index));
12216
12217   vat_json_object_add_uint (node, "l2_only", mp->mt_tunnel.mt_l2_only);
12218
12219   fp = mp->mt_tunnel.mt_paths;
12220   for (i = 0; i < count; i++)
12221     {
12222       vl_api_mpls_fib_path_json_print (node, fp);
12223       fp++;
12224     }
12225 }
12226
12227 static int
12228 api_mpls_tunnel_dump (vat_main_t * vam)
12229 {
12230   vl_api_mpls_tunnel_dump_t *mp;
12231   vl_api_control_ping_t *mp_ping;
12232   int ret;
12233
12234   M (MPLS_TUNNEL_DUMP, mp);
12235
12236   S (mp);
12237
12238   /* Use a control ping for synchronization */
12239   MPING (CONTROL_PING, mp_ping);
12240   S (mp_ping);
12241
12242   W (ret);
12243   return ret;
12244 }
12245
12246 #define vl_api_mpls_table_details_t_endian vl_noop_handler
12247 #define vl_api_mpls_table_details_t_print vl_noop_handler
12248
12249
12250 static void
12251 vl_api_mpls_table_details_t_handler (vl_api_mpls_table_details_t * mp)
12252 {
12253   vat_main_t *vam = &vat_main;
12254
12255   print (vam->ofp, "table-id %d,", ntohl (mp->mt_table.mt_table_id));
12256 }
12257
12258 static void vl_api_mpls_table_details_t_handler_json
12259   (vl_api_mpls_table_details_t * mp)
12260 {
12261   vat_main_t *vam = &vat_main;
12262   vat_json_node_t *node = NULL;
12263
12264   if (VAT_JSON_ARRAY != vam->json_tree.type)
12265     {
12266       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
12267       vat_json_init_array (&vam->json_tree);
12268     }
12269   node = vat_json_array_add (&vam->json_tree);
12270
12271   vat_json_init_object (node);
12272   vat_json_object_add_uint (node, "table", ntohl (mp->mt_table.mt_table_id));
12273 }
12274
12275 static int
12276 api_mpls_table_dump (vat_main_t * vam)
12277 {
12278   vl_api_mpls_table_dump_t *mp;
12279   vl_api_control_ping_t *mp_ping;
12280   int ret;
12281
12282   M (MPLS_TABLE_DUMP, mp);
12283   S (mp);
12284
12285   /* Use a control ping for synchronization */
12286   MPING (CONTROL_PING, mp_ping);
12287   S (mp_ping);
12288
12289   W (ret);
12290   return ret;
12291 }
12292
12293 #define vl_api_mpls_route_details_t_endian vl_noop_handler
12294 #define vl_api_mpls_route_details_t_print vl_noop_handler
12295
12296 static void
12297 vl_api_mpls_route_details_t_handler (vl_api_mpls_route_details_t * mp)
12298 {
12299   vat_main_t *vam = &vat_main;
12300   int count = (int) clib_net_to_host_u32 (mp->mr_route.mr_n_paths);
12301   vl_api_fib_path_t *fp;
12302   int i;
12303
12304   print (vam->ofp,
12305          "table-id %d, label %u, ess_bit %u",
12306          ntohl (mp->mr_route.mr_table_id),
12307          ntohl (mp->mr_route.mr_label), mp->mr_route.mr_eos);
12308   fp = mp->mr_route.mr_paths;
12309   for (i = 0; i < count; i++)
12310     {
12311       vl_api_fib_path_print (vam, fp);
12312       fp++;
12313     }
12314 }
12315
12316 static void vl_api_mpls_route_details_t_handler_json
12317   (vl_api_mpls_route_details_t * mp)
12318 {
12319   vat_main_t *vam = &vat_main;
12320   int count = (int) clib_host_to_net_u32 (mp->mr_route.mr_n_paths);
12321   vat_json_node_t *node = NULL;
12322   vl_api_fib_path_t *fp;
12323   int i;
12324
12325   if (VAT_JSON_ARRAY != vam->json_tree.type)
12326     {
12327       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
12328       vat_json_init_array (&vam->json_tree);
12329     }
12330   node = vat_json_array_add (&vam->json_tree);
12331
12332   vat_json_init_object (node);
12333   vat_json_object_add_uint (node, "table", ntohl (mp->mr_route.mr_table_id));
12334   vat_json_object_add_uint (node, "s_bit", mp->mr_route.mr_eos);
12335   vat_json_object_add_uint (node, "label", ntohl (mp->mr_route.mr_label));
12336   vat_json_object_add_uint (node, "path_count", count);
12337   fp = mp->mr_route.mr_paths;
12338   for (i = 0; i < count; i++)
12339     {
12340       vl_api_mpls_fib_path_json_print (node, fp);
12341       fp++;
12342     }
12343 }
12344
12345 static int
12346 api_mpls_route_dump (vat_main_t * vam)
12347 {
12348   unformat_input_t *input = vam->input;
12349   vl_api_mpls_route_dump_t *mp;
12350   vl_api_control_ping_t *mp_ping;
12351   u32 table_id;
12352   int ret;
12353
12354   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
12355     {
12356       if (unformat (input, "table_id %d", &table_id))
12357         ;
12358       else
12359         break;
12360     }
12361   if (table_id == ~0)
12362     {
12363       errmsg ("missing table id");
12364       return -99;
12365     }
12366
12367   M (MPLS_ROUTE_DUMP, mp);
12368
12369   mp->table.mt_table_id = ntohl (table_id);
12370   S (mp);
12371
12372   /* Use a control ping for synchronization */
12373   MPING (CONTROL_PING, mp_ping);
12374   S (mp_ping);
12375
12376   W (ret);
12377   return ret;
12378 }
12379
12380 #define vl_api_ip_table_details_t_endian vl_noop_handler
12381 #define vl_api_ip_table_details_t_print vl_noop_handler
12382
12383 static void
12384 vl_api_ip_table_details_t_handler (vl_api_ip_table_details_t * mp)
12385 {
12386   vat_main_t *vam = &vat_main;
12387
12388   print (vam->ofp,
12389          "%s; table-id %d, prefix %U/%d",
12390          mp->table.name, ntohl (mp->table.table_id));
12391 }
12392
12393
12394 static void vl_api_ip_table_details_t_handler_json
12395   (vl_api_ip_table_details_t * mp)
12396 {
12397   vat_main_t *vam = &vat_main;
12398   vat_json_node_t *node = NULL;
12399
12400   if (VAT_JSON_ARRAY != vam->json_tree.type)
12401     {
12402       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
12403       vat_json_init_array (&vam->json_tree);
12404     }
12405   node = vat_json_array_add (&vam->json_tree);
12406
12407   vat_json_init_object (node);
12408   vat_json_object_add_uint (node, "table", ntohl (mp->table.table_id));
12409 }
12410
12411 static int
12412 api_ip_table_dump (vat_main_t * vam)
12413 {
12414   vl_api_ip_table_dump_t *mp;
12415   vl_api_control_ping_t *mp_ping;
12416   int ret;
12417
12418   M (IP_TABLE_DUMP, mp);
12419   S (mp);
12420
12421   /* Use a control ping for synchronization */
12422   MPING (CONTROL_PING, mp_ping);
12423   S (mp_ping);
12424
12425   W (ret);
12426   return ret;
12427 }
12428
12429 static int
12430 api_ip_mtable_dump (vat_main_t * vam)
12431 {
12432   vl_api_ip_mtable_dump_t *mp;
12433   vl_api_control_ping_t *mp_ping;
12434   int ret;
12435
12436   M (IP_MTABLE_DUMP, mp);
12437   S (mp);
12438
12439   /* Use a control ping for synchronization */
12440   MPING (CONTROL_PING, mp_ping);
12441   S (mp_ping);
12442
12443   W (ret);
12444   return ret;
12445 }
12446
12447 static int
12448 api_ip_mroute_dump (vat_main_t * vam)
12449 {
12450   unformat_input_t *input = vam->input;
12451   vl_api_control_ping_t *mp_ping;
12452   vl_api_ip_mroute_dump_t *mp;
12453   int ret, is_ip6;
12454   u32 table_id;
12455
12456   is_ip6 = 0;
12457   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
12458     {
12459       if (unformat (input, "table_id %d", &table_id))
12460         ;
12461       else if (unformat (input, "ip6"))
12462         is_ip6 = 1;
12463       else if (unformat (input, "ip4"))
12464         is_ip6 = 0;
12465       else
12466         break;
12467     }
12468   if (table_id == ~0)
12469     {
12470       errmsg ("missing table id");
12471       return -99;
12472     }
12473
12474   M (IP_MROUTE_DUMP, mp);
12475   mp->table.table_id = table_id;
12476   mp->table.is_ip6 = is_ip6;
12477   S (mp);
12478
12479   /* Use a control ping for synchronization */
12480   MPING (CONTROL_PING, mp_ping);
12481   S (mp_ping);
12482
12483   W (ret);
12484   return ret;
12485 }
12486
12487 #define vl_api_ip_route_details_t_endian vl_noop_handler
12488 #define vl_api_ip_route_details_t_print vl_noop_handler
12489
12490 static void
12491 vl_api_ip_route_details_t_handler (vl_api_ip_route_details_t * mp)
12492 {
12493   vat_main_t *vam = &vat_main;
12494   u8 count = mp->route.n_paths;
12495   vl_api_fib_path_t *fp;
12496   int i;
12497
12498   print (vam->ofp,
12499          "table-id %d, prefix %U/%d",
12500          ntohl (mp->route.table_id),
12501          format_ip46_address, mp->route.prefix.address, mp->route.prefix.len);
12502   for (i = 0; i < count; i++)
12503     {
12504       fp = &mp->route.paths[i];
12505
12506       vl_api_fib_path_print (vam, fp);
12507       fp++;
12508     }
12509 }
12510
12511 static void vl_api_ip_route_details_t_handler_json
12512   (vl_api_ip_route_details_t * mp)
12513 {
12514   vat_main_t *vam = &vat_main;
12515   u8 count = mp->route.n_paths;
12516   vat_json_node_t *node = NULL;
12517   struct in_addr ip4;
12518   struct in6_addr ip6;
12519   vl_api_fib_path_t *fp;
12520   int i;
12521
12522   if (VAT_JSON_ARRAY != vam->json_tree.type)
12523     {
12524       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
12525       vat_json_init_array (&vam->json_tree);
12526     }
12527   node = vat_json_array_add (&vam->json_tree);
12528
12529   vat_json_init_object (node);
12530   vat_json_object_add_uint (node, "table", ntohl (mp->route.table_id));
12531   if (ADDRESS_IP6 == mp->route.prefix.address.af)
12532     {
12533       clib_memcpy (&ip6, &mp->route.prefix.address.un.ip6, sizeof (ip6));
12534       vat_json_object_add_ip6 (node, "prefix", ip6);
12535     }
12536   else
12537     {
12538       clib_memcpy (&ip4, &mp->route.prefix.address.un.ip4, sizeof (ip4));
12539       vat_json_object_add_ip4 (node, "prefix", ip4);
12540     }
12541   vat_json_object_add_uint (node, "mask_length", mp->route.prefix.len);
12542   vat_json_object_add_uint (node, "path_count", count);
12543   for (i = 0; i < count; i++)
12544     {
12545       fp = &mp->route.paths[i];
12546       vl_api_mpls_fib_path_json_print (node, fp);
12547     }
12548 }
12549
12550 static int
12551 api_ip_route_dump (vat_main_t * vam)
12552 {
12553   unformat_input_t *input = vam->input;
12554   vl_api_ip_route_dump_t *mp;
12555   vl_api_control_ping_t *mp_ping;
12556   u32 table_id;
12557   u8 is_ip6;
12558   int ret;
12559
12560   is_ip6 = 0;
12561   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
12562     {
12563       if (unformat (input, "table_id %d", &table_id))
12564         ;
12565       else if (unformat (input, "ip6"))
12566         is_ip6 = 1;
12567       else if (unformat (input, "ip4"))
12568         is_ip6 = 0;
12569       else
12570         break;
12571     }
12572   if (table_id == ~0)
12573     {
12574       errmsg ("missing table id");
12575       return -99;
12576     }
12577
12578   M (IP_ROUTE_DUMP, mp);
12579
12580   mp->table.table_id = table_id;
12581   mp->table.is_ip6 = is_ip6;
12582
12583   S (mp);
12584
12585   /* Use a control ping for synchronization */
12586   MPING (CONTROL_PING, mp_ping);
12587   S (mp_ping);
12588
12589   W (ret);
12590   return ret;
12591 }
12592
12593 int
12594 api_classify_table_ids (vat_main_t * vam)
12595 {
12596   vl_api_classify_table_ids_t *mp;
12597   int ret;
12598
12599   /* Construct the API message */
12600   M (CLASSIFY_TABLE_IDS, mp);
12601   mp->context = 0;
12602
12603   S (mp);
12604   W (ret);
12605   return ret;
12606 }
12607
12608 int
12609 api_classify_table_by_interface (vat_main_t * vam)
12610 {
12611   unformat_input_t *input = vam->input;
12612   vl_api_classify_table_by_interface_t *mp;
12613
12614   u32 sw_if_index = ~0;
12615   int ret;
12616   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
12617     {
12618       if (unformat (input, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
12619         ;
12620       else if (unformat (input, "sw_if_index %d", &sw_if_index))
12621         ;
12622       else
12623         break;
12624     }
12625   if (sw_if_index == ~0)
12626     {
12627       errmsg ("missing interface name or sw_if_index");
12628       return -99;
12629     }
12630
12631   /* Construct the API message */
12632   M (CLASSIFY_TABLE_BY_INTERFACE, mp);
12633   mp->context = 0;
12634   mp->sw_if_index = ntohl (sw_if_index);
12635
12636   S (mp);
12637   W (ret);
12638   return ret;
12639 }
12640
12641 int
12642 api_classify_table_info (vat_main_t * vam)
12643 {
12644   unformat_input_t *input = vam->input;
12645   vl_api_classify_table_info_t *mp;
12646
12647   u32 table_id = ~0;
12648   int ret;
12649   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
12650     {
12651       if (unformat (input, "table_id %d", &table_id))
12652         ;
12653       else
12654         break;
12655     }
12656   if (table_id == ~0)
12657     {
12658       errmsg ("missing table id");
12659       return -99;
12660     }
12661
12662   /* Construct the API message */
12663   M (CLASSIFY_TABLE_INFO, mp);
12664   mp->context = 0;
12665   mp->table_id = ntohl (table_id);
12666
12667   S (mp);
12668   W (ret);
12669   return ret;
12670 }
12671
12672 int
12673 api_classify_session_dump (vat_main_t * vam)
12674 {
12675   unformat_input_t *input = vam->input;
12676   vl_api_classify_session_dump_t *mp;
12677   vl_api_control_ping_t *mp_ping;
12678
12679   u32 table_id = ~0;
12680   int ret;
12681   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
12682     {
12683       if (unformat (input, "table_id %d", &table_id))
12684         ;
12685       else
12686         break;
12687     }
12688   if (table_id == ~0)
12689     {
12690       errmsg ("missing table id");
12691       return -99;
12692     }
12693
12694   /* Construct the API message */
12695   M (CLASSIFY_SESSION_DUMP, mp);
12696   mp->context = 0;
12697   mp->table_id = ntohl (table_id);
12698   S (mp);
12699
12700   /* Use a control ping for synchronization */
12701   MPING (CONTROL_PING, mp_ping);
12702   S (mp_ping);
12703
12704   W (ret);
12705   return ret;
12706 }
12707
12708 static void
12709 vl_api_ipfix_exporter_details_t_handler (vl_api_ipfix_exporter_details_t * mp)
12710 {
12711   vat_main_t *vam = &vat_main;
12712
12713   print (vam->ofp, "collector_address %U, collector_port %d, "
12714          "src_address %U, vrf_id %d, path_mtu %u, "
12715          "template_interval %u, udp_checksum %d",
12716          format_ip4_address, mp->collector_address,
12717          ntohs (mp->collector_port),
12718          format_ip4_address, mp->src_address,
12719          ntohl (mp->vrf_id), ntohl (mp->path_mtu),
12720          ntohl (mp->template_interval), mp->udp_checksum);
12721
12722   vam->retval = 0;
12723   vam->result_ready = 1;
12724 }
12725
12726 static void
12727   vl_api_ipfix_exporter_details_t_handler_json
12728   (vl_api_ipfix_exporter_details_t * mp)
12729 {
12730   vat_main_t *vam = &vat_main;
12731   vat_json_node_t node;
12732   struct in_addr collector_address;
12733   struct in_addr src_address;
12734
12735   vat_json_init_object (&node);
12736   clib_memcpy (&collector_address, &mp->collector_address,
12737                sizeof (collector_address));
12738   vat_json_object_add_ip4 (&node, "collector_address", collector_address);
12739   vat_json_object_add_uint (&node, "collector_port",
12740                             ntohs (mp->collector_port));
12741   clib_memcpy (&src_address, &mp->src_address, sizeof (src_address));
12742   vat_json_object_add_ip4 (&node, "src_address", src_address);
12743   vat_json_object_add_int (&node, "vrf_id", ntohl (mp->vrf_id));
12744   vat_json_object_add_uint (&node, "path_mtu", ntohl (mp->path_mtu));
12745   vat_json_object_add_uint (&node, "template_interval",
12746                             ntohl (mp->template_interval));
12747   vat_json_object_add_int (&node, "udp_checksum", mp->udp_checksum);
12748
12749   vat_json_print (vam->ofp, &node);
12750   vat_json_free (&node);
12751   vam->retval = 0;
12752   vam->result_ready = 1;
12753 }
12754
12755 int
12756 api_ipfix_exporter_dump (vat_main_t * vam)
12757 {
12758   vl_api_ipfix_exporter_dump_t *mp;
12759   int ret;
12760
12761   /* Construct the API message */
12762   M (IPFIX_EXPORTER_DUMP, mp);
12763   mp->context = 0;
12764
12765   S (mp);
12766   W (ret);
12767   return ret;
12768 }
12769
12770 static int
12771 api_ipfix_classify_stream_dump (vat_main_t * vam)
12772 {
12773   vl_api_ipfix_classify_stream_dump_t *mp;
12774   int ret;
12775
12776   /* Construct the API message */
12777   M (IPFIX_CLASSIFY_STREAM_DUMP, mp);
12778   mp->context = 0;
12779
12780   S (mp);
12781   W (ret);
12782   return ret;
12783   /* NOTREACHED */
12784   return 0;
12785 }
12786
12787 static void
12788   vl_api_ipfix_classify_stream_details_t_handler
12789   (vl_api_ipfix_classify_stream_details_t * mp)
12790 {
12791   vat_main_t *vam = &vat_main;
12792   print (vam->ofp, "domain_id %d, src_port %d",
12793          ntohl (mp->domain_id), ntohs (mp->src_port));
12794   vam->retval = 0;
12795   vam->result_ready = 1;
12796 }
12797
12798 static void
12799   vl_api_ipfix_classify_stream_details_t_handler_json
12800   (vl_api_ipfix_classify_stream_details_t * mp)
12801 {
12802   vat_main_t *vam = &vat_main;
12803   vat_json_node_t node;
12804
12805   vat_json_init_object (&node);
12806   vat_json_object_add_uint (&node, "domain_id", ntohl (mp->domain_id));
12807   vat_json_object_add_uint (&node, "src_port", ntohs (mp->src_port));
12808
12809   vat_json_print (vam->ofp, &node);
12810   vat_json_free (&node);
12811   vam->retval = 0;
12812   vam->result_ready = 1;
12813 }
12814
12815 static int
12816 api_ipfix_classify_table_dump (vat_main_t * vam)
12817 {
12818   vl_api_ipfix_classify_table_dump_t *mp;
12819   vl_api_control_ping_t *mp_ping;
12820   int ret;
12821
12822   if (!vam->json_output)
12823     {
12824       print (vam->ofp, "%15s%15s%20s", "table_id", "ip_version",
12825              "transport_protocol");
12826     }
12827
12828   /* Construct the API message */
12829   M (IPFIX_CLASSIFY_TABLE_DUMP, mp);
12830
12831   /* send it... */
12832   S (mp);
12833
12834   /* Use a control ping for synchronization */
12835   MPING (CONTROL_PING, mp_ping);
12836   S (mp_ping);
12837
12838   W (ret);
12839   return ret;
12840 }
12841
12842 static void
12843   vl_api_ipfix_classify_table_details_t_handler
12844   (vl_api_ipfix_classify_table_details_t * mp)
12845 {
12846   vat_main_t *vam = &vat_main;
12847   print (vam->ofp, "%15d%15d%20d", ntohl (mp->table_id), mp->ip_version,
12848          mp->transport_protocol);
12849 }
12850
12851 static void
12852   vl_api_ipfix_classify_table_details_t_handler_json
12853   (vl_api_ipfix_classify_table_details_t * mp)
12854 {
12855   vat_json_node_t *node = NULL;
12856   vat_main_t *vam = &vat_main;
12857
12858   if (VAT_JSON_ARRAY != vam->json_tree.type)
12859     {
12860       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
12861       vat_json_init_array (&vam->json_tree);
12862     }
12863
12864   node = vat_json_array_add (&vam->json_tree);
12865   vat_json_init_object (node);
12866
12867   vat_json_object_add_uint (node, "table_id", ntohl (mp->table_id));
12868   vat_json_object_add_uint (node, "ip_version", mp->ip_version);
12869   vat_json_object_add_uint (node, "transport_protocol",
12870                             mp->transport_protocol);
12871 }
12872
12873 static int
12874 api_sw_interface_span_enable_disable (vat_main_t * vam)
12875 {
12876   unformat_input_t *i = vam->input;
12877   vl_api_sw_interface_span_enable_disable_t *mp;
12878   u32 src_sw_if_index = ~0;
12879   u32 dst_sw_if_index = ~0;
12880   u8 state = 3;
12881   int ret;
12882   u8 is_l2 = 0;
12883
12884   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
12885     {
12886       if (unformat
12887           (i, "src %U", api_unformat_sw_if_index, vam, &src_sw_if_index))
12888         ;
12889       else if (unformat (i, "src_sw_if_index %d", &src_sw_if_index))
12890         ;
12891       else
12892         if (unformat
12893             (i, "dst %U", api_unformat_sw_if_index, vam, &dst_sw_if_index))
12894         ;
12895       else if (unformat (i, "dst_sw_if_index %d", &dst_sw_if_index))
12896         ;
12897       else if (unformat (i, "disable"))
12898         state = 0;
12899       else if (unformat (i, "rx"))
12900         state = 1;
12901       else if (unformat (i, "tx"))
12902         state = 2;
12903       else if (unformat (i, "both"))
12904         state = 3;
12905       else if (unformat (i, "l2"))
12906         is_l2 = 1;
12907       else
12908         break;
12909     }
12910
12911   M (SW_INTERFACE_SPAN_ENABLE_DISABLE, mp);
12912
12913   mp->sw_if_index_from = htonl (src_sw_if_index);
12914   mp->sw_if_index_to = htonl (dst_sw_if_index);
12915   mp->state = state;
12916   mp->is_l2 = is_l2;
12917
12918   S (mp);
12919   W (ret);
12920   return ret;
12921 }
12922
12923 static void
12924 vl_api_sw_interface_span_details_t_handler (vl_api_sw_interface_span_details_t
12925                                             * mp)
12926 {
12927   vat_main_t *vam = &vat_main;
12928   u8 *sw_if_from_name = 0;
12929   u8 *sw_if_to_name = 0;
12930   u32 sw_if_index_from = ntohl (mp->sw_if_index_from);
12931   u32 sw_if_index_to = ntohl (mp->sw_if_index_to);
12932   char *states[] = { "none", "rx", "tx", "both" };
12933   hash_pair_t *p;
12934
12935   /* *INDENT-OFF* */
12936   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
12937   ({
12938     if ((u32) p->value[0] == sw_if_index_from)
12939       {
12940         sw_if_from_name = (u8 *)(p->key);
12941         if (sw_if_to_name)
12942           break;
12943       }
12944     if ((u32) p->value[0] == sw_if_index_to)
12945       {
12946         sw_if_to_name = (u8 *)(p->key);
12947         if (sw_if_from_name)
12948           break;
12949       }
12950   }));
12951   /* *INDENT-ON* */
12952   print (vam->ofp, "%20s => %20s (%s) %s",
12953          sw_if_from_name, sw_if_to_name, states[mp->state],
12954          mp->is_l2 ? "l2" : "device");
12955 }
12956
12957 static void
12958   vl_api_sw_interface_span_details_t_handler_json
12959   (vl_api_sw_interface_span_details_t * mp)
12960 {
12961   vat_main_t *vam = &vat_main;
12962   vat_json_node_t *node = NULL;
12963   u8 *sw_if_from_name = 0;
12964   u8 *sw_if_to_name = 0;
12965   u32 sw_if_index_from = ntohl (mp->sw_if_index_from);
12966   u32 sw_if_index_to = ntohl (mp->sw_if_index_to);
12967   hash_pair_t *p;
12968
12969   /* *INDENT-OFF* */
12970   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
12971   ({
12972     if ((u32) p->value[0] == sw_if_index_from)
12973       {
12974         sw_if_from_name = (u8 *)(p->key);
12975         if (sw_if_to_name)
12976           break;
12977       }
12978     if ((u32) p->value[0] == sw_if_index_to)
12979       {
12980         sw_if_to_name = (u8 *)(p->key);
12981         if (sw_if_from_name)
12982           break;
12983       }
12984   }));
12985   /* *INDENT-ON* */
12986
12987   if (VAT_JSON_ARRAY != vam->json_tree.type)
12988     {
12989       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
12990       vat_json_init_array (&vam->json_tree);
12991     }
12992   node = vat_json_array_add (&vam->json_tree);
12993
12994   vat_json_init_object (node);
12995   vat_json_object_add_uint (node, "src-if-index", sw_if_index_from);
12996   vat_json_object_add_string_copy (node, "src-if-name", sw_if_from_name);
12997   vat_json_object_add_uint (node, "dst-if-index", sw_if_index_to);
12998   if (0 != sw_if_to_name)
12999     {
13000       vat_json_object_add_string_copy (node, "dst-if-name", sw_if_to_name);
13001     }
13002   vat_json_object_add_uint (node, "state", mp->state);
13003   vat_json_object_add_uint (node, "is-l2", mp->is_l2);
13004 }
13005
13006 static int
13007 api_sw_interface_span_dump (vat_main_t * vam)
13008 {
13009   unformat_input_t *input = vam->input;
13010   vl_api_sw_interface_span_dump_t *mp;
13011   vl_api_control_ping_t *mp_ping;
13012   u8 is_l2 = 0;
13013   int ret;
13014
13015   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
13016     {
13017       if (unformat (input, "l2"))
13018         is_l2 = 1;
13019       else
13020         break;
13021     }
13022
13023   M (SW_INTERFACE_SPAN_DUMP, mp);
13024   mp->is_l2 = is_l2;
13025   S (mp);
13026
13027   /* Use a control ping for synchronization */
13028   MPING (CONTROL_PING, mp_ping);
13029   S (mp_ping);
13030
13031   W (ret);
13032   return ret;
13033 }
13034
13035 int
13036 api_pg_create_interface (vat_main_t * vam)
13037 {
13038   unformat_input_t *input = vam->input;
13039   vl_api_pg_create_interface_t *mp;
13040
13041   u32 if_id = ~0, gso_size = 0;
13042   u8 gso_enabled = 0;
13043   int ret;
13044   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
13045     {
13046       if (unformat (input, "if_id %d", &if_id))
13047         ;
13048       else if (unformat (input, "gso-enabled"))
13049         {
13050           gso_enabled = 1;
13051           if (unformat (input, "gso-size %u", &gso_size))
13052             ;
13053           else
13054             {
13055               errmsg ("missing gso-size");
13056               return -99;
13057             }
13058         }
13059       else
13060         break;
13061     }
13062   if (if_id == ~0)
13063     {
13064       errmsg ("missing pg interface index");
13065       return -99;
13066     }
13067
13068   /* Construct the API message */
13069   M (PG_CREATE_INTERFACE, mp);
13070   mp->context = 0;
13071   mp->interface_id = ntohl (if_id);
13072   mp->gso_enabled = gso_enabled;
13073
13074   S (mp);
13075   W (ret);
13076   return ret;
13077 }
13078
13079 int
13080 api_pg_capture (vat_main_t * vam)
13081 {
13082   unformat_input_t *input = vam->input;
13083   vl_api_pg_capture_t *mp;
13084
13085   u32 if_id = ~0;
13086   u8 enable = 1;
13087   u32 count = 1;
13088   u8 pcap_file_set = 0;
13089   u8 *pcap_file = 0;
13090   int ret;
13091   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
13092     {
13093       if (unformat (input, "if_id %d", &if_id))
13094         ;
13095       else if (unformat (input, "pcap %s", &pcap_file))
13096         pcap_file_set = 1;
13097       else if (unformat (input, "count %d", &count))
13098         ;
13099       else if (unformat (input, "disable"))
13100         enable = 0;
13101       else
13102         break;
13103     }
13104   if (if_id == ~0)
13105     {
13106       errmsg ("missing pg interface index");
13107       return -99;
13108     }
13109   if (pcap_file_set > 0)
13110     {
13111       if (vec_len (pcap_file) > 255)
13112         {
13113           errmsg ("pcap file name is too long");
13114           return -99;
13115         }
13116     }
13117
13118   /* Construct the API message */
13119   M (PG_CAPTURE, mp);
13120   mp->context = 0;
13121   mp->interface_id = ntohl (if_id);
13122   mp->is_enabled = enable;
13123   mp->count = ntohl (count);
13124   if (pcap_file_set != 0)
13125     {
13126       vl_api_vec_to_api_string (pcap_file, &mp->pcap_file_name);
13127     }
13128   vec_free (pcap_file);
13129
13130   S (mp);
13131   W (ret);
13132   return ret;
13133 }
13134
13135 int
13136 api_pg_enable_disable (vat_main_t * vam)
13137 {
13138   unformat_input_t *input = vam->input;
13139   vl_api_pg_enable_disable_t *mp;
13140
13141   u8 enable = 1;
13142   u8 stream_name_set = 0;
13143   u8 *stream_name = 0;
13144   int ret;
13145   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
13146     {
13147       if (unformat (input, "stream %s", &stream_name))
13148         stream_name_set = 1;
13149       else if (unformat (input, "disable"))
13150         enable = 0;
13151       else
13152         break;
13153     }
13154
13155   if (stream_name_set > 0)
13156     {
13157       if (vec_len (stream_name) > 255)
13158         {
13159           errmsg ("stream name too long");
13160           return -99;
13161         }
13162     }
13163
13164   /* Construct the API message */
13165   M (PG_ENABLE_DISABLE, mp);
13166   mp->context = 0;
13167   mp->is_enabled = enable;
13168   if (stream_name_set != 0)
13169     {
13170       vl_api_vec_to_api_string (stream_name, &mp->stream_name);
13171     }
13172   vec_free (stream_name);
13173
13174   S (mp);
13175   W (ret);
13176   return ret;
13177 }
13178
13179 int
13180 api_pg_interface_enable_disable_coalesce (vat_main_t * vam)
13181 {
13182   unformat_input_t *input = vam->input;
13183   vl_api_pg_interface_enable_disable_coalesce_t *mp;
13184
13185   u32 sw_if_index = ~0;
13186   u8 enable = 1;
13187   int ret;
13188   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
13189     {
13190       if (unformat (input, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13191         ;
13192       else if (unformat (input, "sw_if_index %d", &sw_if_index))
13193         ;
13194       else if (unformat (input, "disable"))
13195         enable = 0;
13196       else
13197         break;
13198     }
13199
13200   if (sw_if_index == ~0)
13201     {
13202       errmsg ("Interface required but not specified");
13203       return -99;
13204     }
13205
13206   /* Construct the API message */
13207   M (PG_INTERFACE_ENABLE_DISABLE_COALESCE, mp);
13208   mp->context = 0;
13209   mp->coalesce_enabled = enable;
13210   mp->sw_if_index = htonl (sw_if_index);
13211
13212   S (mp);
13213   W (ret);
13214   return ret;
13215 }
13216
13217 int
13218 api_ip_source_and_port_range_check_add_del (vat_main_t * vam)
13219 {
13220   unformat_input_t *input = vam->input;
13221   vl_api_ip_source_and_port_range_check_add_del_t *mp;
13222
13223   u16 *low_ports = 0;
13224   u16 *high_ports = 0;
13225   u16 this_low;
13226   u16 this_hi;
13227   vl_api_prefix_t prefix;
13228   u32 tmp, tmp2;
13229   u8 prefix_set = 0;
13230   u32 vrf_id = ~0;
13231   u8 is_add = 1;
13232   int ret;
13233
13234   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
13235     {
13236       if (unformat (input, "%U", unformat_vl_api_prefix, &prefix))
13237         prefix_set = 1;
13238       else if (unformat (input, "vrf %d", &vrf_id))
13239         ;
13240       else if (unformat (input, "del"))
13241         is_add = 0;
13242       else if (unformat (input, "port %d", &tmp))
13243         {
13244           if (tmp == 0 || tmp > 65535)
13245             {
13246               errmsg ("port %d out of range", tmp);
13247               return -99;
13248             }
13249           this_low = tmp;
13250           this_hi = this_low + 1;
13251           vec_add1 (low_ports, this_low);
13252           vec_add1 (high_ports, this_hi);
13253         }
13254       else if (unformat (input, "range %d - %d", &tmp, &tmp2))
13255         {
13256           if ((tmp > tmp2) || (tmp == 0) || (tmp2 > 65535))
13257             {
13258               errmsg ("incorrect range parameters");
13259               return -99;
13260             }
13261           this_low = tmp;
13262           /* Note: in debug CLI +1 is added to high before
13263              passing to real fn that does "the work"
13264              (ip_source_and_port_range_check_add_del).
13265              This fn is a wrapper around the binary API fn a
13266              control plane will call, which expects this increment
13267              to have occurred. Hence letting the binary API control
13268              plane fn do the increment for consistency between VAT
13269              and other control planes.
13270            */
13271           this_hi = tmp2;
13272           vec_add1 (low_ports, this_low);
13273           vec_add1 (high_ports, this_hi);
13274         }
13275       else
13276         break;
13277     }
13278
13279   if (prefix_set == 0)
13280     {
13281       errmsg ("<address>/<mask> not specified");
13282       return -99;
13283     }
13284
13285   if (vrf_id == ~0)
13286     {
13287       errmsg ("VRF ID required, not specified");
13288       return -99;
13289     }
13290
13291   if (vrf_id == 0)
13292     {
13293       errmsg
13294         ("VRF ID should not be default. Should be distinct VRF for this purpose.");
13295       return -99;
13296     }
13297
13298   if (vec_len (low_ports) == 0)
13299     {
13300       errmsg ("At least one port or port range required");
13301       return -99;
13302     }
13303
13304   M (IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL, mp);
13305
13306   mp->is_add = is_add;
13307
13308   clib_memcpy (&mp->prefix, &prefix, sizeof (prefix));
13309
13310   mp->number_of_ranges = vec_len (low_ports);
13311
13312   clib_memcpy (mp->low_ports, low_ports, vec_len (low_ports));
13313   vec_free (low_ports);
13314
13315   clib_memcpy (mp->high_ports, high_ports, vec_len (high_ports));
13316   vec_free (high_ports);
13317
13318   mp->vrf_id = ntohl (vrf_id);
13319
13320   S (mp);
13321   W (ret);
13322   return ret;
13323 }
13324
13325 int
13326 api_ip_source_and_port_range_check_interface_add_del (vat_main_t * vam)
13327 {
13328   unformat_input_t *input = vam->input;
13329   vl_api_ip_source_and_port_range_check_interface_add_del_t *mp;
13330   u32 sw_if_index = ~0;
13331   int vrf_set = 0;
13332   u32 tcp_out_vrf_id = ~0, udp_out_vrf_id = ~0;
13333   u32 tcp_in_vrf_id = ~0, udp_in_vrf_id = ~0;
13334   u8 is_add = 1;
13335   int ret;
13336
13337   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
13338     {
13339       if (unformat (input, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13340         ;
13341       else if (unformat (input, "sw_if_index %d", &sw_if_index))
13342         ;
13343       else if (unformat (input, "tcp-out-vrf %d", &tcp_out_vrf_id))
13344         vrf_set = 1;
13345       else if (unformat (input, "udp-out-vrf %d", &udp_out_vrf_id))
13346         vrf_set = 1;
13347       else if (unformat (input, "tcp-in-vrf %d", &tcp_in_vrf_id))
13348         vrf_set = 1;
13349       else if (unformat (input, "udp-in-vrf %d", &udp_in_vrf_id))
13350         vrf_set = 1;
13351       else if (unformat (input, "del"))
13352         is_add = 0;
13353       else
13354         break;
13355     }
13356
13357   if (sw_if_index == ~0)
13358     {
13359       errmsg ("Interface required but not specified");
13360       return -99;
13361     }
13362
13363   if (vrf_set == 0)
13364     {
13365       errmsg ("VRF ID required but not specified");
13366       return -99;
13367     }
13368
13369   if (tcp_out_vrf_id == 0
13370       || udp_out_vrf_id == 0 || tcp_in_vrf_id == 0 || udp_in_vrf_id == 0)
13371     {
13372       errmsg
13373         ("VRF ID should not be default. Should be distinct VRF for this purpose.");
13374       return -99;
13375     }
13376
13377   /* Construct the API message */
13378   M (IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL, mp);
13379
13380   mp->sw_if_index = ntohl (sw_if_index);
13381   mp->is_add = is_add;
13382   mp->tcp_out_vrf_id = ntohl (tcp_out_vrf_id);
13383   mp->udp_out_vrf_id = ntohl (udp_out_vrf_id);
13384   mp->tcp_in_vrf_id = ntohl (tcp_in_vrf_id);
13385   mp->udp_in_vrf_id = ntohl (udp_in_vrf_id);
13386
13387   /* send it... */
13388   S (mp);
13389
13390   /* Wait for a reply... */
13391   W (ret);
13392   return ret;
13393 }
13394
13395 static int
13396 api_set_punt (vat_main_t * vam)
13397 {
13398   unformat_input_t *i = vam->input;
13399   vl_api_address_family_t af;
13400   vl_api_set_punt_t *mp;
13401   u32 protocol = ~0;
13402   u32 port = ~0;
13403   int is_add = 1;
13404   int ret;
13405
13406   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13407     {
13408       if (unformat (i, "%U", unformat_vl_api_address_family, &af))
13409         ;
13410       else if (unformat (i, "protocol %d", &protocol))
13411         ;
13412       else if (unformat (i, "port %d", &port))
13413         ;
13414       else if (unformat (i, "del"))
13415         is_add = 0;
13416       else
13417         {
13418           clib_warning ("parse error '%U'", format_unformat_error, i);
13419           return -99;
13420         }
13421     }
13422
13423   M (SET_PUNT, mp);
13424
13425   mp->is_add = (u8) is_add;
13426   mp->punt.type = PUNT_API_TYPE_L4;
13427   mp->punt.punt.l4.af = af;
13428   mp->punt.punt.l4.protocol = (u8) protocol;
13429   mp->punt.punt.l4.port = htons ((u16) port);
13430
13431   S (mp);
13432   W (ret);
13433   return ret;
13434 }
13435
13436 static int
13437 api_delete_subif (vat_main_t * vam)
13438 {
13439   unformat_input_t *i = vam->input;
13440   vl_api_delete_subif_t *mp;
13441   u32 sw_if_index = ~0;
13442   int ret;
13443
13444   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13445     {
13446       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13447         ;
13448       if (unformat (i, "sw_if_index %d", &sw_if_index))
13449         ;
13450       else
13451         break;
13452     }
13453
13454   if (sw_if_index == ~0)
13455     {
13456       errmsg ("missing sw_if_index");
13457       return -99;
13458     }
13459
13460   /* Construct the API message */
13461   M (DELETE_SUBIF, mp);
13462   mp->sw_if_index = ntohl (sw_if_index);
13463
13464   S (mp);
13465   W (ret);
13466   return ret;
13467 }
13468
13469 #define foreach_pbb_vtr_op      \
13470 _("disable",  L2_VTR_DISABLED)  \
13471 _("pop",  L2_VTR_POP_2)         \
13472 _("push",  L2_VTR_PUSH_2)
13473
13474 static int
13475 api_l2_interface_pbb_tag_rewrite (vat_main_t * vam)
13476 {
13477   unformat_input_t *i = vam->input;
13478   vl_api_l2_interface_pbb_tag_rewrite_t *mp;
13479   u32 sw_if_index = ~0, vtr_op = ~0;
13480   u16 outer_tag = ~0;
13481   u8 dmac[6], smac[6];
13482   u8 dmac_set = 0, smac_set = 0;
13483   u16 vlanid = 0;
13484   u32 sid = ~0;
13485   u32 tmp;
13486   int ret;
13487
13488   /* Shut up coverity */
13489   clib_memset (dmac, 0, sizeof (dmac));
13490   clib_memset (smac, 0, sizeof (smac));
13491
13492   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13493     {
13494       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13495         ;
13496       else if (unformat (i, "sw_if_index %d", &sw_if_index))
13497         ;
13498       else if (unformat (i, "vtr_op %d", &vtr_op))
13499         ;
13500 #define _(n,v) else if (unformat(i, n)) {vtr_op = v;}
13501       foreach_pbb_vtr_op
13502 #undef _
13503         else if (unformat (i, "translate_pbb_stag"))
13504         {
13505           if (unformat (i, "%d", &tmp))
13506             {
13507               vtr_op = L2_VTR_TRANSLATE_2_1;
13508               outer_tag = tmp;
13509             }
13510           else
13511             {
13512               errmsg
13513                 ("translate_pbb_stag operation requires outer tag definition");
13514               return -99;
13515             }
13516         }
13517       else if (unformat (i, "dmac %U", unformat_ethernet_address, dmac))
13518         dmac_set++;
13519       else if (unformat (i, "smac %U", unformat_ethernet_address, smac))
13520         smac_set++;
13521       else if (unformat (i, "sid %d", &sid))
13522         ;
13523       else if (unformat (i, "vlanid %d", &tmp))
13524         vlanid = tmp;
13525       else
13526         {
13527           clib_warning ("parse error '%U'", format_unformat_error, i);
13528           return -99;
13529         }
13530     }
13531
13532   if ((sw_if_index == ~0) || (vtr_op == ~0))
13533     {
13534       errmsg ("missing sw_if_index or vtr operation");
13535       return -99;
13536     }
13537   if (((vtr_op == L2_VTR_PUSH_2) || (vtr_op == L2_VTR_TRANSLATE_2_2))
13538       && ((dmac_set == 0) || (smac_set == 0) || (sid == ~0)))
13539     {
13540       errmsg
13541         ("push and translate_qinq operations require dmac, smac, sid and optionally vlanid");
13542       return -99;
13543     }
13544
13545   M (L2_INTERFACE_PBB_TAG_REWRITE, mp);
13546   mp->sw_if_index = ntohl (sw_if_index);
13547   mp->vtr_op = ntohl (vtr_op);
13548   mp->outer_tag = ntohs (outer_tag);
13549   clib_memcpy (mp->b_dmac, dmac, sizeof (dmac));
13550   clib_memcpy (mp->b_smac, smac, sizeof (smac));
13551   mp->b_vlanid = ntohs (vlanid);
13552   mp->i_sid = ntohl (sid);
13553
13554   S (mp);
13555   W (ret);
13556   return ret;
13557 }
13558
13559 static int
13560 api_flow_classify_set_interface (vat_main_t * vam)
13561 {
13562   unformat_input_t *i = vam->input;
13563   vl_api_flow_classify_set_interface_t *mp;
13564   u32 sw_if_index;
13565   int sw_if_index_set;
13566   u32 ip4_table_index = ~0;
13567   u32 ip6_table_index = ~0;
13568   u8 is_add = 1;
13569   int ret;
13570
13571   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13572     {
13573       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13574         sw_if_index_set = 1;
13575       else if (unformat (i, "sw_if_index %d", &sw_if_index))
13576         sw_if_index_set = 1;
13577       else if (unformat (i, "del"))
13578         is_add = 0;
13579       else if (unformat (i, "ip4-table %d", &ip4_table_index))
13580         ;
13581       else if (unformat (i, "ip6-table %d", &ip6_table_index))
13582         ;
13583       else
13584         {
13585           clib_warning ("parse error '%U'", format_unformat_error, i);
13586           return -99;
13587         }
13588     }
13589
13590   if (sw_if_index_set == 0)
13591     {
13592       errmsg ("missing interface name or sw_if_index");
13593       return -99;
13594     }
13595
13596   M (FLOW_CLASSIFY_SET_INTERFACE, mp);
13597
13598   mp->sw_if_index = ntohl (sw_if_index);
13599   mp->ip4_table_index = ntohl (ip4_table_index);
13600   mp->ip6_table_index = ntohl (ip6_table_index);
13601   mp->is_add = is_add;
13602
13603   S (mp);
13604   W (ret);
13605   return ret;
13606 }
13607
13608 static int
13609 api_flow_classify_dump (vat_main_t * vam)
13610 {
13611   unformat_input_t *i = vam->input;
13612   vl_api_flow_classify_dump_t *mp;
13613   vl_api_control_ping_t *mp_ping;
13614   u8 type = FLOW_CLASSIFY_N_TABLES;
13615   int ret;
13616
13617   if (unformat (i, "type %U", unformat_flow_classify_table_type, &type))
13618     ;
13619   else
13620     {
13621       errmsg ("classify table type must be specified");
13622       return -99;
13623     }
13624
13625   if (!vam->json_output)
13626     {
13627       print (vam->ofp, "%10s%20s", "Intfc idx", "Classify table");
13628     }
13629
13630   M (FLOW_CLASSIFY_DUMP, mp);
13631   mp->type = type;
13632   /* send it... */
13633   S (mp);
13634
13635   /* Use a control ping for synchronization */
13636   MPING (CONTROL_PING, mp_ping);
13637   S (mp_ping);
13638
13639   /* Wait for a reply... */
13640   W (ret);
13641   return ret;
13642 }
13643
13644 static int
13645 api_feature_enable_disable (vat_main_t * vam)
13646 {
13647   unformat_input_t *i = vam->input;
13648   vl_api_feature_enable_disable_t *mp;
13649   u8 *arc_name = 0;
13650   u8 *feature_name = 0;
13651   u32 sw_if_index = ~0;
13652   u8 enable = 1;
13653   int ret;
13654
13655   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13656     {
13657       if (unformat (i, "arc_name %s", &arc_name))
13658         ;
13659       else if (unformat (i, "feature_name %s", &feature_name))
13660         ;
13661       else
13662         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13663         ;
13664       else if (unformat (i, "sw_if_index %d", &sw_if_index))
13665         ;
13666       else if (unformat (i, "disable"))
13667         enable = 0;
13668       else
13669         break;
13670     }
13671
13672   if (arc_name == 0)
13673     {
13674       errmsg ("missing arc name");
13675       return -99;
13676     }
13677   if (vec_len (arc_name) > 63)
13678     {
13679       errmsg ("arc name too long");
13680     }
13681
13682   if (feature_name == 0)
13683     {
13684       errmsg ("missing feature name");
13685       return -99;
13686     }
13687   if (vec_len (feature_name) > 63)
13688     {
13689       errmsg ("feature name too long");
13690     }
13691
13692   if (sw_if_index == ~0)
13693     {
13694       errmsg ("missing interface name or sw_if_index");
13695       return -99;
13696     }
13697
13698   /* Construct the API message */
13699   M (FEATURE_ENABLE_DISABLE, mp);
13700   mp->sw_if_index = ntohl (sw_if_index);
13701   mp->enable = enable;
13702   clib_memcpy (mp->arc_name, arc_name, vec_len (arc_name));
13703   clib_memcpy (mp->feature_name, feature_name, vec_len (feature_name));
13704   vec_free (arc_name);
13705   vec_free (feature_name);
13706
13707   S (mp);
13708   W (ret);
13709   return ret;
13710 }
13711
13712 static int
13713 api_feature_gso_enable_disable (vat_main_t * vam)
13714 {
13715   unformat_input_t *i = vam->input;
13716   vl_api_feature_gso_enable_disable_t *mp;
13717   u32 sw_if_index = ~0;
13718   u8 enable = 1;
13719   int ret;
13720
13721   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13722     {
13723       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13724         ;
13725       else if (unformat (i, "sw_if_index %d", &sw_if_index))
13726         ;
13727       else if (unformat (i, "enable"))
13728         enable = 1;
13729       else if (unformat (i, "disable"))
13730         enable = 0;
13731       else
13732         break;
13733     }
13734
13735   if (sw_if_index == ~0)
13736     {
13737       errmsg ("missing interface name or sw_if_index");
13738       return -99;
13739     }
13740
13741   /* Construct the API message */
13742   M (FEATURE_GSO_ENABLE_DISABLE, mp);
13743   mp->sw_if_index = ntohl (sw_if_index);
13744   mp->enable_disable = enable;
13745
13746   S (mp);
13747   W (ret);
13748   return ret;
13749 }
13750
13751 static int
13752 api_sw_interface_tag_add_del (vat_main_t * vam)
13753 {
13754   unformat_input_t *i = vam->input;
13755   vl_api_sw_interface_tag_add_del_t *mp;
13756   u32 sw_if_index = ~0;
13757   u8 *tag = 0;
13758   u8 enable = 1;
13759   int ret;
13760
13761   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13762     {
13763       if (unformat (i, "tag %s", &tag))
13764         ;
13765       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13766         ;
13767       else if (unformat (i, "sw_if_index %d", &sw_if_index))
13768         ;
13769       else if (unformat (i, "del"))
13770         enable = 0;
13771       else
13772         break;
13773     }
13774
13775   if (sw_if_index == ~0)
13776     {
13777       errmsg ("missing interface name or sw_if_index");
13778       return -99;
13779     }
13780
13781   if (enable && (tag == 0))
13782     {
13783       errmsg ("no tag specified");
13784       return -99;
13785     }
13786
13787   /* Construct the API message */
13788   M (SW_INTERFACE_TAG_ADD_DEL, mp);
13789   mp->sw_if_index = ntohl (sw_if_index);
13790   mp->is_add = enable;
13791   if (enable)
13792     strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
13793   vec_free (tag);
13794
13795   S (mp);
13796   W (ret);
13797   return ret;
13798 }
13799
13800 static int
13801 api_sw_interface_add_del_mac_address (vat_main_t * vam)
13802 {
13803   unformat_input_t *i = vam->input;
13804   vl_api_mac_address_t mac = { 0 };
13805   vl_api_sw_interface_add_del_mac_address_t *mp;
13806   u32 sw_if_index = ~0;
13807   u8 is_add = 1;
13808   u8 mac_set = 0;
13809   int ret;
13810
13811   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13812     {
13813       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13814         ;
13815       else if (unformat (i, "sw_if_index %d", &sw_if_index))
13816         ;
13817       else if (unformat (i, "%U", unformat_vl_api_mac_address, &mac))
13818         mac_set++;
13819       else if (unformat (i, "del"))
13820         is_add = 0;
13821       else
13822         break;
13823     }
13824
13825   if (sw_if_index == ~0)
13826     {
13827       errmsg ("missing interface name or sw_if_index");
13828       return -99;
13829     }
13830
13831   if (!mac_set)
13832     {
13833       errmsg ("missing MAC address");
13834       return -99;
13835     }
13836
13837   /* Construct the API message */
13838   M (SW_INTERFACE_ADD_DEL_MAC_ADDRESS, mp);
13839   mp->sw_if_index = ntohl (sw_if_index);
13840   mp->is_add = is_add;
13841   clib_memcpy (&mp->addr, &mac, sizeof (mac));
13842
13843   S (mp);
13844   W (ret);
13845   return ret;
13846 }
13847
13848 static void vl_api_l2_xconnect_details_t_handler
13849   (vl_api_l2_xconnect_details_t * mp)
13850 {
13851   vat_main_t *vam = &vat_main;
13852
13853   print (vam->ofp, "%15d%15d",
13854          ntohl (mp->rx_sw_if_index), ntohl (mp->tx_sw_if_index));
13855 }
13856
13857 static void vl_api_l2_xconnect_details_t_handler_json
13858   (vl_api_l2_xconnect_details_t * mp)
13859 {
13860   vat_main_t *vam = &vat_main;
13861   vat_json_node_t *node = NULL;
13862
13863   if (VAT_JSON_ARRAY != vam->json_tree.type)
13864     {
13865       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
13866       vat_json_init_array (&vam->json_tree);
13867     }
13868   node = vat_json_array_add (&vam->json_tree);
13869
13870   vat_json_init_object (node);
13871   vat_json_object_add_uint (node, "rx_sw_if_index",
13872                             ntohl (mp->rx_sw_if_index));
13873   vat_json_object_add_uint (node, "tx_sw_if_index",
13874                             ntohl (mp->tx_sw_if_index));
13875 }
13876
13877 static int
13878 api_l2_xconnect_dump (vat_main_t * vam)
13879 {
13880   vl_api_l2_xconnect_dump_t *mp;
13881   vl_api_control_ping_t *mp_ping;
13882   int ret;
13883
13884   if (!vam->json_output)
13885     {
13886       print (vam->ofp, "%15s%15s", "rx_sw_if_index", "tx_sw_if_index");
13887     }
13888
13889   M (L2_XCONNECT_DUMP, mp);
13890
13891   S (mp);
13892
13893   /* Use a control ping for synchronization */
13894   MPING (CONTROL_PING, mp_ping);
13895   S (mp_ping);
13896
13897   W (ret);
13898   return ret;
13899 }
13900
13901 static int
13902 api_hw_interface_set_mtu (vat_main_t * vam)
13903 {
13904   unformat_input_t *i = vam->input;
13905   vl_api_hw_interface_set_mtu_t *mp;
13906   u32 sw_if_index = ~0;
13907   u32 mtu = 0;
13908   int ret;
13909
13910   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13911     {
13912       if (unformat (i, "mtu %d", &mtu))
13913         ;
13914       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13915         ;
13916       else if (unformat (i, "sw_if_index %d", &sw_if_index))
13917         ;
13918       else
13919         break;
13920     }
13921
13922   if (sw_if_index == ~0)
13923     {
13924       errmsg ("missing interface name or sw_if_index");
13925       return -99;
13926     }
13927
13928   if (mtu == 0)
13929     {
13930       errmsg ("no mtu specified");
13931       return -99;
13932     }
13933
13934   /* Construct the API message */
13935   M (HW_INTERFACE_SET_MTU, mp);
13936   mp->sw_if_index = ntohl (sw_if_index);
13937   mp->mtu = ntohs ((u16) mtu);
13938
13939   S (mp);
13940   W (ret);
13941   return ret;
13942 }
13943
13944 static int
13945 api_p2p_ethernet_add (vat_main_t * vam)
13946 {
13947   unformat_input_t *i = vam->input;
13948   vl_api_p2p_ethernet_add_t *mp;
13949   u32 parent_if_index = ~0;
13950   u32 sub_id = ~0;
13951   u8 remote_mac[6];
13952   u8 mac_set = 0;
13953   int ret;
13954
13955   clib_memset (remote_mac, 0, sizeof (remote_mac));
13956   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13957     {
13958       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &parent_if_index))
13959         ;
13960       else if (unformat (i, "sw_if_index %d", &parent_if_index))
13961         ;
13962       else
13963         if (unformat
13964             (i, "remote_mac %U", unformat_ethernet_address, remote_mac))
13965         mac_set++;
13966       else if (unformat (i, "sub_id %d", &sub_id))
13967         ;
13968       else
13969         {
13970           clib_warning ("parse error '%U'", format_unformat_error, i);
13971           return -99;
13972         }
13973     }
13974
13975   if (parent_if_index == ~0)
13976     {
13977       errmsg ("missing interface name or sw_if_index");
13978       return -99;
13979     }
13980   if (mac_set == 0)
13981     {
13982       errmsg ("missing remote mac address");
13983       return -99;
13984     }
13985   if (sub_id == ~0)
13986     {
13987       errmsg ("missing sub-interface id");
13988       return -99;
13989     }
13990
13991   M (P2P_ETHERNET_ADD, mp);
13992   mp->parent_if_index = ntohl (parent_if_index);
13993   mp->subif_id = ntohl (sub_id);
13994   clib_memcpy (mp->remote_mac, remote_mac, sizeof (remote_mac));
13995
13996   S (mp);
13997   W (ret);
13998   return ret;
13999 }
14000
14001 static int
14002 api_p2p_ethernet_del (vat_main_t * vam)
14003 {
14004   unformat_input_t *i = vam->input;
14005   vl_api_p2p_ethernet_del_t *mp;
14006   u32 parent_if_index = ~0;
14007   u8 remote_mac[6];
14008   u8 mac_set = 0;
14009   int ret;
14010
14011   clib_memset (remote_mac, 0, sizeof (remote_mac));
14012   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
14013     {
14014       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &parent_if_index))
14015         ;
14016       else if (unformat (i, "sw_if_index %d", &parent_if_index))
14017         ;
14018       else
14019         if (unformat
14020             (i, "remote_mac %U", unformat_ethernet_address, remote_mac))
14021         mac_set++;
14022       else
14023         {
14024           clib_warning ("parse error '%U'", format_unformat_error, i);
14025           return -99;
14026         }
14027     }
14028
14029   if (parent_if_index == ~0)
14030     {
14031       errmsg ("missing interface name or sw_if_index");
14032       return -99;
14033     }
14034   if (mac_set == 0)
14035     {
14036       errmsg ("missing remote mac address");
14037       return -99;
14038     }
14039
14040   M (P2P_ETHERNET_DEL, mp);
14041   mp->parent_if_index = ntohl (parent_if_index);
14042   clib_memcpy (mp->remote_mac, remote_mac, sizeof (remote_mac));
14043
14044   S (mp);
14045   W (ret);
14046   return ret;
14047 }
14048
14049 static int
14050 api_tcp_configure_src_addresses (vat_main_t * vam)
14051 {
14052   vl_api_tcp_configure_src_addresses_t *mp;
14053   unformat_input_t *i = vam->input;
14054   vl_api_address_t first, last;
14055   u8 range_set = 0;
14056   u32 vrf_id = 0;
14057   int ret;
14058
14059   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
14060     {
14061       if (unformat (i, "%U - %U",
14062                     unformat_vl_api_address, &first,
14063                     unformat_vl_api_address, &last))
14064         {
14065           if (range_set)
14066             {
14067               errmsg ("one range per message (range already set)");
14068               return -99;
14069             }
14070           range_set = 1;
14071         }
14072       else if (unformat (i, "vrf %d", &vrf_id))
14073         ;
14074       else
14075         break;
14076     }
14077
14078   if (range_set == 0)
14079     {
14080       errmsg ("address range not set");
14081       return -99;
14082     }
14083
14084   M (TCP_CONFIGURE_SRC_ADDRESSES, mp);
14085
14086   mp->vrf_id = ntohl (vrf_id);
14087   clib_memcpy (&mp->first_address, &first, sizeof (first));
14088   clib_memcpy (&mp->last_address, &last, sizeof (last));
14089
14090   S (mp);
14091   W (ret);
14092   return ret;
14093 }
14094
14095 static void vl_api_app_namespace_add_del_reply_t_handler
14096   (vl_api_app_namespace_add_del_reply_t * mp)
14097 {
14098   vat_main_t *vam = &vat_main;
14099   i32 retval = ntohl (mp->retval);
14100   if (vam->async_mode)
14101     {
14102       vam->async_errors += (retval < 0);
14103     }
14104   else
14105     {
14106       vam->retval = retval;
14107       if (retval == 0)
14108         errmsg ("app ns index %d\n", ntohl (mp->appns_index));
14109       vam->result_ready = 1;
14110     }
14111 }
14112
14113 static void vl_api_app_namespace_add_del_reply_t_handler_json
14114   (vl_api_app_namespace_add_del_reply_t * mp)
14115 {
14116   vat_main_t *vam = &vat_main;
14117   vat_json_node_t node;
14118
14119   vat_json_init_object (&node);
14120   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
14121   vat_json_object_add_uint (&node, "appns_index", ntohl (mp->appns_index));
14122
14123   vat_json_print (vam->ofp, &node);
14124   vat_json_free (&node);
14125
14126   vam->retval = ntohl (mp->retval);
14127   vam->result_ready = 1;
14128 }
14129
14130 static int
14131 api_app_namespace_add_del (vat_main_t * vam)
14132 {
14133   vl_api_app_namespace_add_del_t *mp;
14134   unformat_input_t *i = vam->input;
14135   u8 *ns_id = 0, secret_set = 0, sw_if_index_set = 0;
14136   u32 sw_if_index, ip4_fib_id, ip6_fib_id;
14137   u64 secret;
14138   int ret;
14139
14140   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
14141     {
14142       if (unformat (i, "id %_%v%_", &ns_id))
14143         ;
14144       else if (unformat (i, "secret %lu", &secret))
14145         secret_set = 1;
14146       else if (unformat (i, "sw_if_index %d", &sw_if_index))
14147         sw_if_index_set = 1;
14148       else if (unformat (i, "ip4_fib_id %d", &ip4_fib_id))
14149         ;
14150       else if (unformat (i, "ip6_fib_id %d", &ip6_fib_id))
14151         ;
14152       else
14153         break;
14154     }
14155   if (!ns_id || !secret_set || !sw_if_index_set)
14156     {
14157       errmsg ("namespace id, secret and sw_if_index must be set");
14158       return -99;
14159     }
14160   if (vec_len (ns_id) > 64)
14161     {
14162       errmsg ("namespace id too long");
14163       return -99;
14164     }
14165   M (APP_NAMESPACE_ADD_DEL, mp);
14166
14167   vl_api_vec_to_api_string (ns_id, &mp->namespace_id);
14168   mp->secret = clib_host_to_net_u64 (secret);
14169   mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
14170   mp->ip4_fib_id = clib_host_to_net_u32 (ip4_fib_id);
14171   mp->ip6_fib_id = clib_host_to_net_u32 (ip6_fib_id);
14172   vec_free (ns_id);
14173   S (mp);
14174   W (ret);
14175   return ret;
14176 }
14177
14178 static int
14179 api_sock_init_shm (vat_main_t * vam)
14180 {
14181 #if VPP_API_TEST_BUILTIN == 0
14182   unformat_input_t *i = vam->input;
14183   vl_api_shm_elem_config_t *config = 0;
14184   u64 size = 64 << 20;
14185   int rv;
14186
14187   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
14188     {
14189       if (unformat (i, "size %U", unformat_memory_size, &size))
14190         ;
14191       else
14192         break;
14193     }
14194
14195   /*
14196    * Canned custom ring allocator config.
14197    * Should probably parse all of this
14198    */
14199   vec_validate (config, 6);
14200   config[0].type = VL_API_VLIB_RING;
14201   config[0].size = 256;
14202   config[0].count = 32;
14203
14204   config[1].type = VL_API_VLIB_RING;
14205   config[1].size = 1024;
14206   config[1].count = 16;
14207
14208   config[2].type = VL_API_VLIB_RING;
14209   config[2].size = 4096;
14210   config[2].count = 2;
14211
14212   config[3].type = VL_API_CLIENT_RING;
14213   config[3].size = 256;
14214   config[3].count = 32;
14215
14216   config[4].type = VL_API_CLIENT_RING;
14217   config[4].size = 1024;
14218   config[4].count = 16;
14219
14220   config[5].type = VL_API_CLIENT_RING;
14221   config[5].size = 4096;
14222   config[5].count = 2;
14223
14224   config[6].type = VL_API_QUEUE;
14225   config[6].count = 128;
14226   config[6].size = sizeof (uword);
14227
14228   rv = vl_socket_client_init_shm (config, 1 /* want_pthread */ );
14229   if (!rv)
14230     vam->client_index_invalid = 1;
14231   return rv;
14232 #else
14233   return -99;
14234 #endif
14235 }
14236
14237 static void
14238 vl_api_session_rules_details_t_handler (vl_api_session_rules_details_t * mp)
14239 {
14240   vat_main_t *vam = &vat_main;
14241   fib_prefix_t lcl, rmt;
14242
14243   ip_prefix_decode (&mp->lcl, &lcl);
14244   ip_prefix_decode (&mp->rmt, &rmt);
14245
14246   if (lcl.fp_proto == FIB_PROTOCOL_IP4)
14247     {
14248       print (vam->ofp,
14249              "appns %u tp %u scope %d %U/%d %d %U/%d %d action: %d tag: %s",
14250              clib_net_to_host_u32 (mp->appns_index), mp->transport_proto,
14251              mp->scope, format_ip4_address, &lcl.fp_addr.ip4, lcl.fp_len,
14252              clib_net_to_host_u16 (mp->lcl_port), format_ip4_address,
14253              &rmt.fp_addr.ip4, rmt.fp_len,
14254              clib_net_to_host_u16 (mp->rmt_port),
14255              clib_net_to_host_u32 (mp->action_index), mp->tag);
14256     }
14257   else
14258     {
14259       print (vam->ofp,
14260              "appns %u tp %u scope %d %U/%d %d %U/%d %d action: %d tag: %s",
14261              clib_net_to_host_u32 (mp->appns_index), mp->transport_proto,
14262              mp->scope, format_ip6_address, &lcl.fp_addr.ip6, lcl.fp_len,
14263              clib_net_to_host_u16 (mp->lcl_port), format_ip6_address,
14264              &rmt.fp_addr.ip6, rmt.fp_len,
14265              clib_net_to_host_u16 (mp->rmt_port),
14266              clib_net_to_host_u32 (mp->action_index), mp->tag);
14267     }
14268 }
14269
14270 static void
14271 vl_api_session_rules_details_t_handler_json (vl_api_session_rules_details_t *
14272                                              mp)
14273 {
14274   vat_main_t *vam = &vat_main;
14275   vat_json_node_t *node = NULL;
14276   struct in6_addr ip6;
14277   struct in_addr ip4;
14278
14279   fib_prefix_t lcl, rmt;
14280
14281   ip_prefix_decode (&mp->lcl, &lcl);
14282   ip_prefix_decode (&mp->rmt, &rmt);
14283
14284   if (VAT_JSON_ARRAY != vam->json_tree.type)
14285     {
14286       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
14287       vat_json_init_array (&vam->json_tree);
14288     }
14289   node = vat_json_array_add (&vam->json_tree);
14290   vat_json_init_object (node);
14291
14292   vat_json_object_add_uint (node, "appns_index",
14293                             clib_net_to_host_u32 (mp->appns_index));
14294   vat_json_object_add_uint (node, "transport_proto", mp->transport_proto);
14295   vat_json_object_add_uint (node, "scope", mp->scope);
14296   vat_json_object_add_uint (node, "action_index",
14297                             clib_net_to_host_u32 (mp->action_index));
14298   vat_json_object_add_uint (node, "lcl_port",
14299                             clib_net_to_host_u16 (mp->lcl_port));
14300   vat_json_object_add_uint (node, "rmt_port",
14301                             clib_net_to_host_u16 (mp->rmt_port));
14302   vat_json_object_add_uint (node, "lcl_plen", lcl.fp_len);
14303   vat_json_object_add_uint (node, "rmt_plen", rmt.fp_len);
14304   vat_json_object_add_string_copy (node, "tag", mp->tag);
14305   if (lcl.fp_proto == FIB_PROTOCOL_IP4)
14306     {
14307       clib_memcpy (&ip4, &lcl.fp_addr.ip4, sizeof (ip4));
14308       vat_json_object_add_ip4 (node, "lcl_ip", ip4);
14309       clib_memcpy (&ip4, &rmt.fp_addr.ip4, sizeof (ip4));
14310       vat_json_object_add_ip4 (node, "rmt_ip", ip4);
14311     }
14312   else
14313     {
14314       clib_memcpy (&ip6, &lcl.fp_addr.ip6, sizeof (ip6));
14315       vat_json_object_add_ip6 (node, "lcl_ip", ip6);
14316       clib_memcpy (&ip6, &rmt.fp_addr.ip6, sizeof (ip6));
14317       vat_json_object_add_ip6 (node, "rmt_ip", ip6);
14318     }
14319 }
14320
14321 static int
14322 api_session_rule_add_del (vat_main_t * vam)
14323 {
14324   vl_api_session_rule_add_del_t *mp;
14325   unformat_input_t *i = vam->input;
14326   u32 proto = ~0, lcl_port, rmt_port, action = 0, lcl_plen, rmt_plen;
14327   u32 appns_index = 0, scope = 0;
14328   ip4_address_t lcl_ip4, rmt_ip4;
14329   ip6_address_t lcl_ip6, rmt_ip6;
14330   u8 is_ip4 = 1, conn_set = 0;
14331   u8 is_add = 1, *tag = 0;
14332   int ret;
14333   fib_prefix_t lcl, rmt;
14334
14335   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
14336     {
14337       if (unformat (i, "del"))
14338         is_add = 0;
14339       else if (unformat (i, "add"))
14340         ;
14341       else if (unformat (i, "proto tcp"))
14342         proto = 0;
14343       else if (unformat (i, "proto udp"))
14344         proto = 1;
14345       else if (unformat (i, "appns %d", &appns_index))
14346         ;
14347       else if (unformat (i, "scope %d", &scope))
14348         ;
14349       else if (unformat (i, "tag %_%v%_", &tag))
14350         ;
14351       else
14352         if (unformat
14353             (i, "%U/%d %d %U/%d %d", unformat_ip4_address, &lcl_ip4,
14354              &lcl_plen, &lcl_port, unformat_ip4_address, &rmt_ip4, &rmt_plen,
14355              &rmt_port))
14356         {
14357           is_ip4 = 1;
14358           conn_set = 1;
14359         }
14360       else
14361         if (unformat
14362             (i, "%U/%d %d %U/%d %d", unformat_ip6_address, &lcl_ip6,
14363              &lcl_plen, &lcl_port, unformat_ip6_address, &rmt_ip6, &rmt_plen,
14364              &rmt_port))
14365         {
14366           is_ip4 = 0;
14367           conn_set = 1;
14368         }
14369       else if (unformat (i, "action %d", &action))
14370         ;
14371       else
14372         break;
14373     }
14374   if (proto == ~0 || !conn_set || action == ~0)
14375     {
14376       errmsg ("transport proto, connection and action must be set");
14377       return -99;
14378     }
14379
14380   if (scope > 3)
14381     {
14382       errmsg ("scope should be 0-3");
14383       return -99;
14384     }
14385
14386   M (SESSION_RULE_ADD_DEL, mp);
14387
14388   clib_memset (&lcl, 0, sizeof (lcl));
14389   clib_memset (&rmt, 0, sizeof (rmt));
14390   if (is_ip4)
14391     {
14392       ip_set (&lcl.fp_addr, &lcl_ip4, 1);
14393       ip_set (&rmt.fp_addr, &rmt_ip4, 1);
14394       lcl.fp_len = lcl_plen;
14395       rmt.fp_len = rmt_plen;
14396     }
14397   else
14398     {
14399       ip_set (&lcl.fp_addr, &lcl_ip6, 0);
14400       ip_set (&rmt.fp_addr, &rmt_ip6, 0);
14401       lcl.fp_len = lcl_plen;
14402       rmt.fp_len = rmt_plen;
14403     }
14404
14405
14406   ip_prefix_encode (&lcl, &mp->lcl);
14407   ip_prefix_encode (&rmt, &mp->rmt);
14408   mp->lcl_port = clib_host_to_net_u16 ((u16) lcl_port);
14409   mp->rmt_port = clib_host_to_net_u16 ((u16) rmt_port);
14410   mp->transport_proto =
14411     proto ? TRANSPORT_PROTO_API_UDP : TRANSPORT_PROTO_API_TCP;
14412   mp->action_index = clib_host_to_net_u32 (action);
14413   mp->appns_index = clib_host_to_net_u32 (appns_index);
14414   mp->scope = scope;
14415   mp->is_add = is_add;
14416   if (tag)
14417     {
14418       clib_memcpy (mp->tag, tag, vec_len (tag));
14419       vec_free (tag);
14420     }
14421
14422   S (mp);
14423   W (ret);
14424   return ret;
14425 }
14426
14427 static int
14428 api_session_rules_dump (vat_main_t * vam)
14429 {
14430   vl_api_session_rules_dump_t *mp;
14431   vl_api_control_ping_t *mp_ping;
14432   int ret;
14433
14434   if (!vam->json_output)
14435     {
14436       print (vam->ofp, "%=20s", "Session Rules");
14437     }
14438
14439   M (SESSION_RULES_DUMP, mp);
14440   /* send it... */
14441   S (mp);
14442
14443   /* Use a control ping for synchronization */
14444   MPING (CONTROL_PING, mp_ping);
14445   S (mp_ping);
14446
14447   /* Wait for a reply... */
14448   W (ret);
14449   return ret;
14450 }
14451
14452 static int
14453 api_ip_container_proxy_add_del (vat_main_t * vam)
14454 {
14455   vl_api_ip_container_proxy_add_del_t *mp;
14456   unformat_input_t *i = vam->input;
14457   u32 sw_if_index = ~0;
14458   vl_api_prefix_t pfx = { };
14459   u8 is_add = 1;
14460   int ret;
14461
14462   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
14463     {
14464       if (unformat (i, "del"))
14465         is_add = 0;
14466       else if (unformat (i, "add"))
14467         ;
14468       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
14469         ;
14470       else if (unformat (i, "sw_if_index %u", &sw_if_index))
14471         ;
14472       else
14473         break;
14474     }
14475   if (sw_if_index == ~0 || pfx.len == 0)
14476     {
14477       errmsg ("address and sw_if_index must be set");
14478       return -99;
14479     }
14480
14481   M (IP_CONTAINER_PROXY_ADD_DEL, mp);
14482
14483   mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
14484   mp->is_add = is_add;
14485   clib_memcpy (&mp->pfx, &pfx, sizeof (pfx));
14486
14487   S (mp);
14488   W (ret);
14489   return ret;
14490 }
14491
14492 static int
14493 api_qos_record_enable_disable (vat_main_t * vam)
14494 {
14495   unformat_input_t *i = vam->input;
14496   vl_api_qos_record_enable_disable_t *mp;
14497   u32 sw_if_index, qs = 0xff;
14498   u8 sw_if_index_set = 0;
14499   u8 enable = 1;
14500   int ret;
14501
14502   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
14503     {
14504       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
14505         sw_if_index_set = 1;
14506       else if (unformat (i, "sw_if_index %d", &sw_if_index))
14507         sw_if_index_set = 1;
14508       else if (unformat (i, "%U", unformat_qos_source, &qs))
14509         ;
14510       else if (unformat (i, "disable"))
14511         enable = 0;
14512       else
14513         {
14514           clib_warning ("parse error '%U'", format_unformat_error, i);
14515           return -99;
14516         }
14517     }
14518
14519   if (sw_if_index_set == 0)
14520     {
14521       errmsg ("missing interface name or sw_if_index");
14522       return -99;
14523     }
14524   if (qs == 0xff)
14525     {
14526       errmsg ("input location must be specified");
14527       return -99;
14528     }
14529
14530   M (QOS_RECORD_ENABLE_DISABLE, mp);
14531
14532   mp->record.sw_if_index = ntohl (sw_if_index);
14533   mp->record.input_source = qs;
14534   mp->enable = enable;
14535
14536   S (mp);
14537   W (ret);
14538   return ret;
14539 }
14540
14541
14542 static int
14543 q_or_quit (vat_main_t * vam)
14544 {
14545 #if VPP_API_TEST_BUILTIN == 0
14546   longjmp (vam->jump_buf, 1);
14547 #endif
14548   return 0;                     /* not so much */
14549 }
14550
14551 static int
14552 q (vat_main_t * vam)
14553 {
14554   return q_or_quit (vam);
14555 }
14556
14557 static int
14558 quit (vat_main_t * vam)
14559 {
14560   return q_or_quit (vam);
14561 }
14562
14563 static int
14564 comment (vat_main_t * vam)
14565 {
14566   return 0;
14567 }
14568
14569 static int
14570 elog_save (vat_main_t * vam)
14571 {
14572 #if VPP_API_TEST_BUILTIN == 0
14573   elog_main_t *em = &vam->elog_main;
14574   unformat_input_t *i = vam->input;
14575   char *file, *chroot_file;
14576   clib_error_t *error;
14577
14578   if (!unformat (i, "%s", &file))
14579     {
14580       errmsg ("expected file name, got `%U'", format_unformat_error, i);
14581       return 0;
14582     }
14583
14584   /* It's fairly hard to get "../oopsie" through unformat; just in case */
14585   if (strstr (file, "..") || index (file, '/'))
14586     {
14587       errmsg ("illegal characters in filename '%s'", file);
14588       return 0;
14589     }
14590
14591   chroot_file = (char *) format (0, "/tmp/%s%c", file, 0);
14592
14593   vec_free (file);
14594
14595   errmsg ("Saving %wd of %wd events to %s",
14596           elog_n_events_in_buffer (em),
14597           elog_buffer_capacity (em), chroot_file);
14598
14599   error = elog_write_file (em, chroot_file, 1 /* flush ring */ );
14600   vec_free (chroot_file);
14601
14602   if (error)
14603     clib_error_report (error);
14604 #else
14605   errmsg ("Use the vpp event loger...");
14606 #endif
14607
14608   return 0;
14609 }
14610
14611 static int
14612 elog_setup (vat_main_t * vam)
14613 {
14614 #if VPP_API_TEST_BUILTIN == 0
14615   elog_main_t *em = &vam->elog_main;
14616   unformat_input_t *i = vam->input;
14617   u32 nevents = 128 << 10;
14618
14619   (void) unformat (i, "nevents %d", &nevents);
14620
14621   elog_init (em, nevents);
14622   vl_api_set_elog_main (em);
14623   vl_api_set_elog_trace_api_messages (1);
14624   errmsg ("Event logger initialized with %u events", nevents);
14625 #else
14626   errmsg ("Use the vpp event loger...");
14627 #endif
14628   return 0;
14629 }
14630
14631 static int
14632 elog_enable (vat_main_t * vam)
14633 {
14634 #if VPP_API_TEST_BUILTIN == 0
14635   elog_main_t *em = &vam->elog_main;
14636
14637   elog_enable_disable (em, 1 /* enable */ );
14638   vl_api_set_elog_trace_api_messages (1);
14639   errmsg ("Event logger enabled...");
14640 #else
14641   errmsg ("Use the vpp event loger...");
14642 #endif
14643   return 0;
14644 }
14645
14646 static int
14647 elog_disable (vat_main_t * vam)
14648 {
14649 #if VPP_API_TEST_BUILTIN == 0
14650   elog_main_t *em = &vam->elog_main;
14651
14652   elog_enable_disable (em, 0 /* enable */ );
14653   vl_api_set_elog_trace_api_messages (1);
14654   errmsg ("Event logger disabled...");
14655 #else
14656   errmsg ("Use the vpp event loger...");
14657 #endif
14658   return 0;
14659 }
14660
14661 static int
14662 statseg (vat_main_t * vam)
14663 {
14664   ssvm_private_t *ssvmp = &vam->stat_segment;
14665   ssvm_shared_header_t *shared_header = ssvmp->sh;
14666   vlib_counter_t **counters;
14667   u64 thread0_index1_packets;
14668   u64 thread0_index1_bytes;
14669   f64 vector_rate, input_rate;
14670   uword *p;
14671
14672   uword *counter_vector_by_name;
14673   if (vam->stat_segment_lockp == 0)
14674     {
14675       errmsg ("Stat segment not mapped...");
14676       return -99;
14677     }
14678
14679   /* look up "/if/rx for sw_if_index 1 as a test */
14680
14681   clib_spinlock_lock (vam->stat_segment_lockp);
14682
14683   counter_vector_by_name = (uword *) shared_header->opaque[1];
14684
14685   p = hash_get_mem (counter_vector_by_name, "/if/rx");
14686   if (p == 0)
14687     {
14688       clib_spinlock_unlock (vam->stat_segment_lockp);
14689       errmsg ("/if/tx not found?");
14690       return -99;
14691     }
14692
14693   /* Fish per-thread vector of combined counters from shared memory */
14694   counters = (vlib_counter_t **) p[0];
14695
14696   if (vec_len (counters[0]) < 2)
14697     {
14698       clib_spinlock_unlock (vam->stat_segment_lockp);
14699       errmsg ("/if/tx vector length %d", vec_len (counters[0]));
14700       return -99;
14701     }
14702
14703   /* Read thread 0 sw_if_index 1 counter */
14704   thread0_index1_packets = counters[0][1].packets;
14705   thread0_index1_bytes = counters[0][1].bytes;
14706
14707   p = hash_get_mem (counter_vector_by_name, "vector_rate");
14708   if (p == 0)
14709     {
14710       clib_spinlock_unlock (vam->stat_segment_lockp);
14711       errmsg ("vector_rate not found?");
14712       return -99;
14713     }
14714
14715   vector_rate = *(f64 *) (p[0]);
14716   p = hash_get_mem (counter_vector_by_name, "input_rate");
14717   if (p == 0)
14718     {
14719       clib_spinlock_unlock (vam->stat_segment_lockp);
14720       errmsg ("input_rate not found?");
14721       return -99;
14722     }
14723   input_rate = *(f64 *) (p[0]);
14724
14725   clib_spinlock_unlock (vam->stat_segment_lockp);
14726
14727   print (vam->ofp, "vector_rate %.2f input_rate %.2f",
14728          vector_rate, input_rate);
14729   print (vam->ofp, "thread 0 sw_if_index 1 rx pkts %lld, bytes %lld",
14730          thread0_index1_packets, thread0_index1_bytes);
14731
14732   return 0;
14733 }
14734
14735 static int
14736 cmd_cmp (void *a1, void *a2)
14737 {
14738   u8 **c1 = a1;
14739   u8 **c2 = a2;
14740
14741   return strcmp ((char *) (c1[0]), (char *) (c2[0]));
14742 }
14743
14744 static int
14745 help (vat_main_t * vam)
14746 {
14747   u8 **cmds = 0;
14748   u8 *name = 0;
14749   hash_pair_t *p;
14750   unformat_input_t *i = vam->input;
14751   int j;
14752
14753   if (unformat (i, "%s", &name))
14754     {
14755       uword *hs;
14756
14757       vec_add1 (name, 0);
14758
14759       hs = hash_get_mem (vam->help_by_name, name);
14760       if (hs)
14761         print (vam->ofp, "usage: %s %s", name, hs[0]);
14762       else
14763         print (vam->ofp, "No such msg / command '%s'", name);
14764       vec_free (name);
14765       return 0;
14766     }
14767
14768   print (vam->ofp, "Help is available for the following:");
14769
14770     /* *INDENT-OFF* */
14771     hash_foreach_pair (p, vam->function_by_name,
14772     ({
14773       vec_add1 (cmds, (u8 *)(p->key));
14774     }));
14775     /* *INDENT-ON* */
14776
14777   vec_sort_with_function (cmds, cmd_cmp);
14778
14779   for (j = 0; j < vec_len (cmds); j++)
14780     print (vam->ofp, "%s", cmds[j]);
14781
14782   vec_free (cmds);
14783   return 0;
14784 }
14785
14786 static int
14787 set (vat_main_t * vam)
14788 {
14789   u8 *name = 0, *value = 0;
14790   unformat_input_t *i = vam->input;
14791
14792   if (unformat (i, "%s", &name))
14793     {
14794       /* The input buffer is a vector, not a string. */
14795       value = vec_dup (i->buffer);
14796       vec_delete (value, i->index, 0);
14797       /* Almost certainly has a trailing newline */
14798       if (value[vec_len (value) - 1] == '\n')
14799         value[vec_len (value) - 1] = 0;
14800       /* Make sure it's a proper string, one way or the other */
14801       vec_add1 (value, 0);
14802       (void) clib_macro_set_value (&vam->macro_main,
14803                                    (char *) name, (char *) value);
14804     }
14805   else
14806     errmsg ("usage: set <name> <value>");
14807
14808   vec_free (name);
14809   vec_free (value);
14810   return 0;
14811 }
14812
14813 static int
14814 unset (vat_main_t * vam)
14815 {
14816   u8 *name = 0;
14817
14818   if (unformat (vam->input, "%s", &name))
14819     if (clib_macro_unset (&vam->macro_main, (char *) name) == 1)
14820       errmsg ("unset: %s wasn't set", name);
14821   vec_free (name);
14822   return 0;
14823 }
14824
14825 typedef struct
14826 {
14827   u8 *name;
14828   u8 *value;
14829 } macro_sort_t;
14830
14831
14832 static int
14833 macro_sort_cmp (void *a1, void *a2)
14834 {
14835   macro_sort_t *s1 = a1;
14836   macro_sort_t *s2 = a2;
14837
14838   return strcmp ((char *) (s1->name), (char *) (s2->name));
14839 }
14840
14841 static int
14842 dump_macro_table (vat_main_t * vam)
14843 {
14844   macro_sort_t *sort_me = 0, *sm;
14845   int i;
14846   hash_pair_t *p;
14847
14848     /* *INDENT-OFF* */
14849     hash_foreach_pair (p, vam->macro_main.the_value_table_hash,
14850     ({
14851       vec_add2 (sort_me, sm, 1);
14852       sm->name = (u8 *)(p->key);
14853       sm->value = (u8 *) (p->value[0]);
14854     }));
14855     /* *INDENT-ON* */
14856
14857   vec_sort_with_function (sort_me, macro_sort_cmp);
14858
14859   if (vec_len (sort_me))
14860     print (vam->ofp, "%-15s%s", "Name", "Value");
14861   else
14862     print (vam->ofp, "The macro table is empty...");
14863
14864   for (i = 0; i < vec_len (sort_me); i++)
14865     print (vam->ofp, "%-15s%s", sort_me[i].name, sort_me[i].value);
14866   return 0;
14867 }
14868
14869 static int
14870 dump_node_table (vat_main_t * vam)
14871 {
14872   int i, j;
14873   vlib_node_t *node, *next_node;
14874
14875   if (vec_len (vam->graph_nodes) == 0)
14876     {
14877       print (vam->ofp, "Node table empty, issue get_node_graph...");
14878       return 0;
14879     }
14880
14881   for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
14882     {
14883       node = vam->graph_nodes[0][i];
14884       print (vam->ofp, "[%d] %s", i, node->name);
14885       for (j = 0; j < vec_len (node->next_nodes); j++)
14886         {
14887           if (node->next_nodes[j] != ~0)
14888             {
14889               next_node = vam->graph_nodes[0][node->next_nodes[j]];
14890               print (vam->ofp, "  [%d] %s", j, next_node->name);
14891             }
14892         }
14893     }
14894   return 0;
14895 }
14896
14897 static int
14898 value_sort_cmp (void *a1, void *a2)
14899 {
14900   name_sort_t *n1 = a1;
14901   name_sort_t *n2 = a2;
14902
14903   if (n1->value < n2->value)
14904     return -1;
14905   if (n1->value > n2->value)
14906     return 1;
14907   return 0;
14908 }
14909
14910
14911 static int
14912 dump_msg_api_table (vat_main_t * vam)
14913 {
14914   api_main_t *am = vlibapi_get_main ();
14915   name_sort_t *nses = 0, *ns;
14916   hash_pair_t *hp;
14917   int i;
14918
14919   /* *INDENT-OFF* */
14920   hash_foreach_pair (hp, am->msg_index_by_name_and_crc,
14921   ({
14922     vec_add2 (nses, ns, 1);
14923     ns->name = (u8 *)(hp->key);
14924     ns->value = (u32) hp->value[0];
14925   }));
14926   /* *INDENT-ON* */
14927
14928   vec_sort_with_function (nses, value_sort_cmp);
14929
14930   for (i = 0; i < vec_len (nses); i++)
14931     print (vam->ofp, " [%d]: %s", nses[i].value, nses[i].name);
14932   vec_free (nses);
14933   return 0;
14934 }
14935
14936 static int
14937 get_msg_id (vat_main_t * vam)
14938 {
14939   u8 *name_and_crc;
14940   u32 message_index;
14941
14942   if (unformat (vam->input, "%s", &name_and_crc))
14943     {
14944       message_index = vl_msg_api_get_msg_index (name_and_crc);
14945       if (message_index == ~0)
14946         {
14947           print (vam->ofp, " '%s' not found", name_and_crc);
14948           return 0;
14949         }
14950       print (vam->ofp, " '%s' has message index %d",
14951              name_and_crc, message_index);
14952       return 0;
14953     }
14954   errmsg ("name_and_crc required...");
14955   return 0;
14956 }
14957
14958 static int
14959 search_node_table (vat_main_t * vam)
14960 {
14961   unformat_input_t *line_input = vam->input;
14962   u8 *node_to_find;
14963   int j;
14964   vlib_node_t *node, *next_node;
14965   uword *p;
14966
14967   if (vam->graph_node_index_by_name == 0)
14968     {
14969       print (vam->ofp, "Node table empty, issue get_node_graph...");
14970       return 0;
14971     }
14972
14973   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
14974     {
14975       if (unformat (line_input, "%s", &node_to_find))
14976         {
14977           vec_add1 (node_to_find, 0);
14978           p = hash_get_mem (vam->graph_node_index_by_name, node_to_find);
14979           if (p == 0)
14980             {
14981               print (vam->ofp, "%s not found...", node_to_find);
14982               goto out;
14983             }
14984           node = vam->graph_nodes[0][p[0]];
14985           print (vam->ofp, "[%d] %s", p[0], node->name);
14986           for (j = 0; j < vec_len (node->next_nodes); j++)
14987             {
14988               if (node->next_nodes[j] != ~0)
14989                 {
14990                   next_node = vam->graph_nodes[0][node->next_nodes[j]];
14991                   print (vam->ofp, "  [%d] %s", j, next_node->name);
14992                 }
14993             }
14994         }
14995
14996       else
14997         {
14998           clib_warning ("parse error '%U'", format_unformat_error,
14999                         line_input);
15000           return -99;
15001         }
15002
15003     out:
15004       vec_free (node_to_find);
15005
15006     }
15007
15008   return 0;
15009 }
15010
15011
15012 static int
15013 script (vat_main_t * vam)
15014 {
15015 #if (VPP_API_TEST_BUILTIN==0)
15016   u8 *s = 0;
15017   char *save_current_file;
15018   unformat_input_t save_input;
15019   jmp_buf save_jump_buf;
15020   u32 save_line_number;
15021
15022   FILE *new_fp, *save_ifp;
15023
15024   if (unformat (vam->input, "%s", &s))
15025     {
15026       new_fp = fopen ((char *) s, "r");
15027       if (new_fp == 0)
15028         {
15029           errmsg ("Couldn't open script file %s", s);
15030           vec_free (s);
15031           return -99;
15032         }
15033     }
15034   else
15035     {
15036       errmsg ("Missing script name");
15037       return -99;
15038     }
15039
15040   clib_memcpy (&save_input, &vam->input, sizeof (save_input));
15041   clib_memcpy (&save_jump_buf, &vam->jump_buf, sizeof (save_jump_buf));
15042   save_ifp = vam->ifp;
15043   save_line_number = vam->input_line_number;
15044   save_current_file = (char *) vam->current_file;
15045
15046   vam->input_line_number = 0;
15047   vam->ifp = new_fp;
15048   vam->current_file = s;
15049   do_one_file (vam);
15050
15051   clib_memcpy (&vam->input, &save_input, sizeof (save_input));
15052   clib_memcpy (&vam->jump_buf, &save_jump_buf, sizeof (save_jump_buf));
15053   vam->ifp = save_ifp;
15054   vam->input_line_number = save_line_number;
15055   vam->current_file = (u8 *) save_current_file;
15056   vec_free (s);
15057
15058   return 0;
15059 #else
15060   clib_warning ("use the exec command...");
15061   return -99;
15062 #endif
15063 }
15064
15065 static int
15066 echo (vat_main_t * vam)
15067 {
15068   print (vam->ofp, "%v", vam->input->buffer);
15069   return 0;
15070 }
15071
15072 /* List of API message constructors, CLI names map to api_xxx */
15073 #define foreach_vpe_api_msg                                             \
15074 _(create_loopback,"[mac <mac-addr>] [instance <instance>]")             \
15075 _(sw_interface_dump,"")                                                 \
15076 _(sw_interface_set_flags,                                               \
15077   "<intfc> | sw_if_index <id> admin-up | admin-down link-up | link down") \
15078 _(sw_interface_add_del_address,                                         \
15079   "<intfc> | sw_if_index <id> <ip4-address> | <ip6-address> [del] [del-all] ") \
15080 _(sw_interface_set_rx_mode,                                             \
15081   "<intfc> | sw_if_index <id> [queue <id>] <polling | interrupt | adaptive>") \
15082 _(sw_interface_set_rx_placement,                                        \
15083   "<intfc> | sw_if_index <id> [queue <id>] [worker <id> | main]")       \
15084 _(sw_interface_rx_placement_dump,                                       \
15085   "[<intfc> | sw_if_index <id>]")                                         \
15086 _(sw_interface_set_table,                                               \
15087   "<intfc> | sw_if_index <id> vrf <table-id> [ipv6]")                   \
15088 _(sw_interface_set_mpls_enable,                                         \
15089   "<intfc> | sw_if_index [disable | dis]")                              \
15090 _(sw_interface_set_vpath,                                               \
15091   "<intfc> | sw_if_index <id> enable | disable")                        \
15092 _(sw_interface_set_vxlan_bypass,                                        \
15093   "<intfc> | sw_if_index <id> [ip4 | ip6] [enable | disable]")          \
15094 _(sw_interface_set_l2_xconnect,                                         \
15095   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
15096   "enable | disable")                                                   \
15097 _(sw_interface_set_l2_bridge,                                           \
15098   "{<intfc> | sw_if_index <id>} bd_id <bridge-domain-id>\n"             \
15099   "[shg <split-horizon-group>] [bvi]\n"                                 \
15100   "enable | disable")                                                   \
15101 _(bridge_domain_set_mac_age, "bd_id <bridge-domain-id> mac-age 0-255")  \
15102 _(bridge_domain_add_del,                                                \
15103   "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") \
15104 _(bridge_domain_dump, "[bd_id <bridge-domain-id>]\n")                   \
15105 _(l2fib_add_del,                                                        \
15106   "mac <mac-addr> bd_id <bridge-domain-id> [del] | sw_if <intfc> | sw_if_index <id> [static] [filter] [bvi] [count <nn>]\n") \
15107 _(l2fib_flush_bd, "bd_id <bridge-domain-id>")                           \
15108 _(l2fib_flush_int, "<intfc> | sw_if_index <id>")                        \
15109 _(l2_flags,                                                             \
15110   "sw_if <intfc> | sw_if_index <id> [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \
15111 _(bridge_flags,                                                         \
15112   "bd_id <bridge-domain-id> [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \
15113 _(tap_create_v2,                                                        \
15114   "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]") \
15115 _(tap_delete_v2,                                                        \
15116   "<vpp-if-name> | sw_if_index <id>")                                   \
15117 _(sw_interface_tap_v2_dump, "")                                         \
15118 _(virtio_pci_create_v2,                                                    \
15119   "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]") \
15120 _(virtio_pci_delete,                                                    \
15121   "<vpp-if-name> | sw_if_index <id>")                                   \
15122 _(sw_interface_virtio_pci_dump, "")                                     \
15123 _(bond_create,                                                          \
15124   "[hw-addr <mac-addr>] {round-robin | active-backup | "                \
15125   "broadcast | {lacp | xor} [load-balance { l2 | l23 | l34 }]} "        \
15126   "[id <if-id>]")                                                       \
15127 _(bond_create2,                                                         \
15128   "[hw-addr <mac-addr>] {mode round-robin | active-backup | "           \
15129   "broadcast | {lacp | xor} [load-balance { l2 | l23 | l34 }]} "        \
15130   "[id <if-id>] [gso]")                                                 \
15131 _(bond_delete,                                                          \
15132   "<vpp-if-name> | sw_if_index <id>")                                   \
15133 _(bond_add_member,                                                      \
15134   "sw_if_index <n> bond <sw_if_index> [is_passive] [is_long_timeout]")  \
15135 _(bond_detach_member,                                                   \
15136   "sw_if_index <n>")                                                    \
15137  _(sw_interface_set_bond_weight, "<intfc> | sw_if_index <nn> weight <value>") \
15138  _(sw_bond_interface_dump, "<intfc> | sw_if_index <nn>")                \
15139  _(sw_member_interface_dump,                                            \
15140   "<vpp-if-name> | sw_if_index <id>")                                   \
15141 _(ip_table_add_del,                                                     \
15142   "table <n> [ipv6] [add | del]\n")                                     \
15143 _(ip_route_add_del,                                                     \
15144   "<addr>/<mask> via <<addr>|<intfc>|sw_if_index <id>|via-label <n>>\n" \
15145   "[table-id <n>] [<intfc> | sw_if_index <id>] [resolve-attempts <n>]\n"\
15146   "[weight <n>] [drop] [local] [classify <n>]  [out-label <n>]\n"       \
15147   "[multipath] [count <n>] [del]")                                      \
15148 _(ip_mroute_add_del,                                                    \
15149   "<src> <grp>/<mask> [table-id <n>]\n"                                 \
15150   "[<intfc> | sw_if_index <id>] [local] [del]")                         \
15151 _(mpls_table_add_del,                                                   \
15152   "table <n> [add | del]\n")                                            \
15153 _(mpls_route_add_del,                                                   \
15154   "<label> <eos> via <addr | next-hop-table <n> | via-label <n> |\n"    \
15155   "lookup-ip4-table <n> | lookup-in-ip6-table <n> |\n"                  \
15156   "l2-input-on <intfc> | l2-input-on sw_if_index <id>>\n"               \
15157   "[<intfc> | sw_if_index <id>] [resolve-attempts <n>] [weight <n>]\n"  \
15158   "[drop] [local] [classify <n>] [out-label <n>] [multipath]\n"         \
15159   "[count <n>] [del]")                                                  \
15160 _(mpls_ip_bind_unbind,                                                  \
15161   "<label> <addr/len>")                                                 \
15162 _(mpls_tunnel_add_del,                                                  \
15163   "[add | del <intfc | sw_if_index <id>>] via <addr | via-label <n>>\n" \
15164   "[<intfc> | sw_if_index <id> | next-hop-table <id>]\n"                \
15165   "[l2-only]  [out-label <n>]")                                         \
15166 _(sr_mpls_policy_add,                                                   \
15167   "bsid <id> [weight <n>] [spray] next <sid> [next <sid>]")             \
15168 _(sr_mpls_policy_del,                                                   \
15169   "bsid <id>")                                                          \
15170 _(bier_table_add_del,                                                   \
15171   "<label> <sub-domain> <set> <bsl> [del]")                             \
15172 _(bier_route_add_del,                                                   \
15173   "<bit-position> <sub-domain> <set> <bsl> via <addr> [table-id <n>]\n" \
15174   "[<intfc> | sw_if_index <id>]"                                        \
15175   "[weight <n>] [del] [multipath]")                                     \
15176 _(sw_interface_set_unnumbered,                                          \
15177   "<intfc> | sw_if_index <id> unnum_if_index <id> [del]")               \
15178 _(create_vlan_subif, "<intfc> | sw_if_index <id> vlan <n>")             \
15179 _(create_subif, "<intfc> | sw_if_index <id> sub_id <n>\n"               \
15180   "[outer_vlan_id <n>][inner_vlan_id <n>]\n"                            \
15181   "[no_tags][one_tag][two_tags][dot1ad][exact_match][default_sub]\n"    \
15182   "[outer_vlan_id_any][inner_vlan_id_any]")                             \
15183 _(ip_table_replace_begin, "table <n> [ipv6]")                           \
15184 _(ip_table_flush, "table <n> [ipv6]")                                   \
15185 _(ip_table_replace_end, "table <n> [ipv6]")                             \
15186 _(set_ip_flow_hash,                                                     \
15187   "vrf <n> [src] [dst] [sport] [dport] [proto] [reverse] [ipv6]")       \
15188 _(sw_interface_ip6_enable_disable,                                      \
15189   "<intfc> | sw_if_index <id> enable | disable")                        \
15190 _(l2_patch_add_del,                                                     \
15191   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
15192   "enable | disable")                                                   \
15193 _(sr_localsid_add_del,                                                  \
15194   "(del) address <addr> next_hop <addr> behavior <beh>\n"               \
15195   "fib-table <num> (end.psp) sw_if_index <num>")                        \
15196 _(classify_add_del_table,                                               \
15197   "buckets <nn> [skip <n>] [match <n>] [memory_size <nn-bytes>]\n"      \
15198   " [del] [del-chain] mask <mask-value>\n"                              \
15199   " [l2-miss-next | miss-next | acl-miss-next] <name|nn>\n"             \
15200   " [current-data-flag <n>] [current-data-offset <nn>] [table <nn>]")   \
15201 _(classify_add_del_session,                                             \
15202   "[hit-next|l2-hit-next|acl-hit-next|policer-hit-next] <name|nn>\n"    \
15203   "  table-index <nn> skip_n <nn> match_n <nn> match [hex] [l2]\n"      \
15204   "  [l3 [ip4|ip6]] [action set-ip4-fib-id <nn>]\n"                     \
15205   "  [action set-ip6-fib-id <nn> | action <n> metadata <nn>] [del]")    \
15206 _(classify_set_interface_ip_table,                                      \
15207   "<intfc> | sw_if_index <nn> table <nn>")                              \
15208 _(classify_set_interface_l2_tables,                                     \
15209   "<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>]\n"      \
15210   "  [other-table <nn>]")                                               \
15211 _(get_node_index, "node <node-name")                                    \
15212 _(add_node_next, "node <node-name> next <next-node-name>")              \
15213 _(vxlan_offload_rx,                                                     \
15214   "hw { <interface name> | hw_if_index <nn>} "                          \
15215   "rx { <vxlan tunnel name> | sw_if_index <nn> } [del]")                \
15216 _(vxlan_add_del_tunnel,                                                 \
15217   "src <ip-addr> { dst <ip-addr> | group <mcast-ip-addr>\n"             \
15218   "{ <intfc> | mcast_sw_if_index <nn> } [instance <id>]}\n"             \
15219   "vni <vni> [encap-vrf-id <nn>] [decap-next <l2|nn>] [del]")           \
15220 _(vxlan_tunnel_dump, "[<intfc> | sw_if_index <nn>]")                    \
15221 _(gre_tunnel_add_del,                                                   \
15222   "src <ip-addr> dst <ip-addr> [outer-fib-id <nn>] [instance <n>]\n"    \
15223   "[teb | erspan <session-id>] [del]")                                  \
15224 _(gre_tunnel_dump, "[<intfc> | sw_if_index <nn>]")                      \
15225 _(l2_fib_clear_table, "")                                               \
15226 _(l2_interface_efp_filter, "sw_if_index <nn> enable | disable")         \
15227 _(l2_interface_vlan_tag_rewrite,                                        \
15228   "<intfc> | sw_if_index <nn> \n"                                       \
15229   "[disable][push-[1|2]][pop-[1|2]][translate-1-[1|2]] \n"              \
15230   "[translate-2-[1|2]] [push_dot1q 0] tag1 <nn> tag2 <nn>")             \
15231 _(create_vhost_user_if,                                                 \
15232         "socket <filename> [server] [renumber <dev_instance>] "         \
15233         "[disable_mrg_rxbuf] [disable_indirect_desc] [gso] "            \
15234         "[mac <mac_address>] [packed]")                                 \
15235 _(modify_vhost_user_if,                                                 \
15236         "<intfc> | sw_if_index <nn> socket <filename>\n"                \
15237         "[server] [renumber <dev_instance>] [gso] [packed]")            \
15238 _(delete_vhost_user_if, "<intfc> | sw_if_index <nn>")                   \
15239 _(sw_interface_vhost_user_dump, "<intfc> | sw_if_index <nn>")           \
15240 _(show_version, "")                                                     \
15241 _(show_threads, "")                                                     \
15242 _(vxlan_gpe_add_del_tunnel,                                             \
15243   "local <addr> remote <addr>  | group <mcast-ip-addr>\n"               \
15244   "{ <intfc> | mcast_sw_if_index <nn> } }\n"                            \
15245   "vni <nn> [encap-vrf-id <nn>] [decap-vrf-id <nn>]\n"                  \
15246   "[next-ip4][next-ip6][next-ethernet] [next-nsh] [del]\n")             \
15247 _(vxlan_gpe_tunnel_dump, "[<intfc> | sw_if_index <nn>]")                \
15248 _(l2_fib_table_dump, "bd_id <bridge-domain-id>")                        \
15249 _(interface_name_renumber,                                              \
15250   "<intfc> | sw_if_index <nn> new_show_dev_instance <nn>")              \
15251 _(input_acl_set_interface,                                              \
15252   "<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>]\n"      \
15253   "  [l2-table <nn>] [del]")                                            \
15254 _(want_l2_macs_events, "[disable] [learn-limit <n>] [scan-delay <n>] [max-entries <n>]") \
15255 _(ip_address_dump, "(ipv4 | ipv6) (<intfc> | sw_if_index <id>)")        \
15256 _(ip_dump, "ipv4 | ipv6")                                               \
15257 _(ipsec_spd_add_del, "spd_id <n> [del]")                                \
15258 _(ipsec_interface_add_del_spd, "(<intfc> | sw_if_index <id>)\n"         \
15259   "  spid_id <n> ")                                                     \
15260 _(ipsec_sad_entry_add_del, "sad_id <n> spi <n> crypto_alg <alg>\n"      \
15261   "  crypto_key <hex> tunnel_src <ip4|ip6> tunnel_dst <ip4|ip6>\n"      \
15262   "  integ_alg <alg> integ_key <hex>")                                  \
15263 _(ipsec_spd_entry_add_del, "spd_id <n> priority <n> action <action>\n"  \
15264   "  (inbound|outbound) [sa_id <n>] laddr_start <ip4|ip6>\n"            \
15265   "  laddr_stop <ip4|ip6> raddr_start <ip4|ip6> raddr_stop <ip4|ip6>\n" \
15266   "  [lport_start <n> lport_stop <n>] [rport_start <n> rport_stop <n>]" ) \
15267 _(ipsec_tunnel_if_add_del, "local_spi <n> remote_spi <n>\n"             \
15268   "  crypto_alg <alg> local_crypto_key <hex> remote_crypto_key <hex>\n" \
15269   "  integ_alg <alg> local_integ_key <hex> remote_integ_key <hex>\n"    \
15270   "  local_ip <addr> remote_ip <addr> [esn] [anti_replay] [del]\n"      \
15271   "  [instance <n>]")     \
15272 _(ipsec_sa_dump, "[sa_id <n>]")                                         \
15273 _(ipsec_tunnel_if_set_sa, "<intfc> sa_id <n> <inbound|outbound>\n")     \
15274 _(delete_loopback,"sw_if_index <nn>")                                   \
15275 _(bd_ip_mac_add_del, "bd_id <bridge-domain-id> <ip4/6-addr> <mac-addr> [del]") \
15276 _(bd_ip_mac_flush, "bd_id <bridge-domain-id>")                          \
15277 _(bd_ip_mac_dump, "[bd_id] <bridge-domain-id>")                         \
15278 _(want_interface_events,  "enable|disable")                             \
15279 _(get_first_msg_id, "client <name>")                                    \
15280 _(cop_interface_enable_disable, "<intfc> | sw_if_index <nn> [disable]") \
15281 _(cop_whitelist_enable_disable, "<intfc> | sw_if_index <nn>\n"          \
15282   "fib-id <nn> [ip4][ip6][default]")                                    \
15283 _(get_node_graph, " ")                                                  \
15284 _(sw_interface_clear_stats,"<intfc> | sw_if_index <nn>")                \
15285 _(ioam_enable, "[trace] [pow] [ppc <encap|decap>]")                     \
15286 _(ioam_disable, "")                                                     \
15287 _(af_packet_create, "name <host interface name> [hw_addr <mac>]")       \
15288 _(af_packet_delete, "name <host interface name>")                       \
15289 _(af_packet_dump, "")                                                   \
15290 _(policer_add_del, "name <policer name> <params> [del]")                \
15291 _(policer_dump, "[name <policer name>]")                                \
15292 _(policer_classify_set_interface,                                       \
15293   "<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>]\n"      \
15294   "  [l2-table <nn>] [del]")                                            \
15295 _(policer_classify_dump, "type [ip4|ip6|l2]")                           \
15296 _(mpls_tunnel_dump, "tunnel_index <tunnel-id>")                         \
15297 _(mpls_table_dump, "")                                                  \
15298 _(mpls_route_dump, "table-id <ID>")                                     \
15299 _(classify_table_ids, "")                                               \
15300 _(classify_table_by_interface, "sw_if_index <sw_if_index>")             \
15301 _(classify_table_info, "table_id <nn>")                                 \
15302 _(classify_session_dump, "table_id <nn>")                               \
15303 _(set_ipfix_exporter, "collector_address <ip4> [collector_port <nn>] "  \
15304     "src_address <ip4> [vrf_id <nn>] [path_mtu <nn>] "                  \
15305     "[template_interval <nn>] [udp_checksum]")                          \
15306 _(ipfix_exporter_dump, "")                                              \
15307 _(set_ipfix_classify_stream, "[domain <domain-id>] [src_port <src-port>]") \
15308 _(ipfix_classify_stream_dump, "")                                       \
15309 _(ipfix_classify_table_add_del, "table <table-index> ip4|ip6 [tcp|udp]") \
15310 _(ipfix_classify_table_dump, "")                                        \
15311 _(sw_interface_span_enable_disable, "[l2] [src <intfc> | src_sw_if_index <id>] [disable | [[dst <intfc> | dst_sw_if_index <id>] [both|rx|tx]]]") \
15312 _(sw_interface_span_dump, "[l2]")                                           \
15313 _(get_next_index, "node-name <node-name> next-node-name <node-name>")   \
15314 _(pg_create_interface, "if_id <nn> [gso-enabled gso-size <size>]")      \
15315 _(pg_capture, "if_id <nnn> pcap <file_name> count <nnn> [disable]")     \
15316 _(pg_enable_disable, "[stream <id>] disable")                           \
15317 _(pg_interface_enable_disable_coalesce, "<intf> | sw_if_index <nn> enable | disable")  \
15318 _(ip_source_and_port_range_check_add_del,                               \
15319   "<ip-addr>/<mask> range <nn>-<nn> vrf <id>")                          \
15320 _(ip_source_and_port_range_check_interface_add_del,                     \
15321   "<intf> | sw_if_index <nn> [tcp-out-vrf <id>] [tcp-in-vrf <id>]"      \
15322   "[udp-in-vrf <id>] [udp-out-vrf <id>]")                               \
15323 _(delete_subif,"<intfc> | sw_if_index <nn>")                            \
15324 _(l2_interface_pbb_tag_rewrite,                                         \
15325   "<intfc> | sw_if_index <nn> \n"                                       \
15326   "[disable | push | pop | translate_pbb_stag <outer_tag>] \n"          \
15327   "dmac <mac> smac <mac> sid <nn> [vlanid <nn>]")                       \
15328 _(set_punt, "protocol <l4-protocol> [ip <ver>] [port <l4-port>] [del]")     \
15329 _(flow_classify_set_interface,                                          \
15330   "<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>] [del]") \
15331 _(flow_classify_dump, "type [ip4|ip6]")                                 \
15332 _(ip_table_dump, "")                                                    \
15333 _(ip_route_dump, "table-id [ip4|ip6]")                                  \
15334 _(ip_mtable_dump, "")                                                   \
15335 _(ip_mroute_dump, "table-id [ip4|ip6]")                                 \
15336 _(feature_enable_disable, "arc_name <arc_name> "                        \
15337   "feature_name <feature_name> <intfc> | sw_if_index <nn> [disable]")   \
15338 _(feature_gso_enable_disable, "<intfc> | sw_if_index <nn> "             \
15339   "[enable | disable] ")                                                \
15340 _(sw_interface_tag_add_del, "<intfc> | sw_if_index <nn> tag <text>"     \
15341 "[disable]")                                                            \
15342 _(sw_interface_add_del_mac_address, "<intfc> | sw_if_index <nn> "       \
15343   "mac <mac-address> [del]")                                            \
15344 _(l2_xconnect_dump, "")                                                 \
15345 _(hw_interface_set_mtu, "<intfc> | hw_if_index <nn> mtu <nn>")        \
15346 _(sw_interface_get_table, "<intfc> | sw_if_index <id> [ipv6]")          \
15347 _(p2p_ethernet_add, "<intfc> | sw_if_index <nn> remote_mac <mac-address> sub_id <id>") \
15348 _(p2p_ethernet_del, "<intfc> | sw_if_index <nn> remote_mac <mac-address>") \
15349 _(tcp_configure_src_addresses, "<ip4|6>first-<ip4|6>last [vrf <id>]")   \
15350 _(sock_init_shm, "size <nnn>")                                          \
15351 _(app_namespace_add_del, "[add] id <ns-id> secret <nn> sw_if_index <nn>")\
15352 _(session_rule_add_del, "[add|del] proto <tcp/udp> <lcl-ip>/<plen> "    \
15353   "<lcl-port> <rmt-ip>/<plen> <rmt-port> action <nn>")                  \
15354 _(session_rules_dump, "")                                               \
15355 _(ip_container_proxy_add_del, "[add|del] <address> <sw_if_index>")      \
15356 _(output_acl_set_interface,                                             \
15357   "<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>]\n"      \
15358   "  [l2-table <nn>] [del]")                                            \
15359 _(qos_record_enable_disable, "<record-source> <intfc> | sw_if_index <id> [disable]")
15360
15361 /* List of command functions, CLI names map directly to functions */
15362 #define foreach_cli_function                                    \
15363 _(comment, "usage: comment <ignore-rest-of-line>")              \
15364 _(dump_interface_table, "usage: dump_interface_table")          \
15365 _(dump_sub_interface_table, "usage: dump_sub_interface_table")  \
15366 _(dump_ipv4_table, "usage: dump_ipv4_table")                    \
15367 _(dump_ipv6_table, "usage: dump_ipv6_table")                    \
15368 _(dump_macro_table, "usage: dump_macro_table ")                 \
15369 _(dump_node_table, "usage: dump_node_table")                    \
15370 _(dump_msg_api_table, "usage: dump_msg_api_table")              \
15371 _(elog_setup, "usage: elog_setup [nevents, default 128K]")      \
15372 _(elog_disable, "usage: elog_disable")                          \
15373 _(elog_enable, "usage: elog_enable")                            \
15374 _(elog_save, "usage: elog_save <filename>")                     \
15375 _(get_msg_id, "usage: get_msg_id name_and_crc")                 \
15376 _(echo, "usage: echo <message>")                                \
15377 _(exec, "usage: exec <vpe-debug-CLI-command>")                  \
15378 _(exec_inband, "usage: exec_inband <vpe-debug-CLI-command>")    \
15379 _(help, "usage: help")                                          \
15380 _(q, "usage: quit")                                             \
15381 _(quit, "usage: quit")                                          \
15382 _(search_node_table, "usage: search_node_table <name>...")      \
15383 _(set, "usage: set <variable-name> <value>")                    \
15384 _(script, "usage: script <file-name>")                          \
15385 _(statseg, "usage: statseg")                                    \
15386 _(unset, "usage: unset <variable-name>")
15387
15388 #define _(N,n)                                  \
15389     static void vl_api_##n##_t_handler_uni      \
15390     (vl_api_##n##_t * mp)                       \
15391     {                                           \
15392         vat_main_t * vam = &vat_main;           \
15393         if (vam->json_output) {                 \
15394             vl_api_##n##_t_handler_json(mp);    \
15395         } else {                                \
15396             vl_api_##n##_t_handler(mp);         \
15397         }                                       \
15398     }
15399 foreach_vpe_api_reply_msg;
15400 #if VPP_API_TEST_BUILTIN == 0
15401 foreach_standalone_reply_msg;
15402 #endif
15403 #undef _
15404
15405 void
15406 vat_api_hookup (vat_main_t * vam)
15407 {
15408 #define _(N,n)                                                  \
15409     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
15410                            vl_api_##n##_t_handler_uni,          \
15411                            vl_noop_handler,                     \
15412                            vl_api_##n##_t_endian,               \
15413                            vl_api_##n##_t_print,                \
15414                            sizeof(vl_api_##n##_t), 1);
15415   foreach_vpe_api_reply_msg;
15416 #if VPP_API_TEST_BUILTIN == 0
15417   foreach_standalone_reply_msg;
15418 #endif
15419 #undef _
15420
15421 #if (VPP_API_TEST_BUILTIN==0)
15422   vl_msg_api_set_first_available_msg_id (VL_MSG_FIRST_AVAILABLE);
15423
15424   vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
15425
15426   vam->function_by_name = hash_create_string (0, sizeof (uword));
15427
15428   vam->help_by_name = hash_create_string (0, sizeof (uword));
15429 #endif
15430
15431   /* API messages we can send */
15432 #define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
15433   foreach_vpe_api_msg;
15434 #undef _
15435
15436   /* Help strings */
15437 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
15438   foreach_vpe_api_msg;
15439 #undef _
15440
15441   /* CLI functions */
15442 #define _(n,h) hash_set_mem (vam->function_by_name, #n, n);
15443   foreach_cli_function;
15444 #undef _
15445
15446   /* Help strings */
15447 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
15448   foreach_cli_function;
15449 #undef _
15450 }
15451
15452 #if VPP_API_TEST_BUILTIN
15453 static clib_error_t *
15454 vat_api_hookup_shim (vlib_main_t * vm)
15455 {
15456   vat_api_hookup (&vat_main);
15457   return 0;
15458 }
15459
15460 VLIB_API_INIT_FUNCTION (vat_api_hookup_shim);
15461 #endif
15462
15463 /*
15464  * fd.io coding-style-patch-verification: ON
15465  *
15466  * Local Variables:
15467  * eval: (c-set-style "gnu")
15468  * End:
15469  */