virtio: add packet buffering on tx
[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
34 #include <vpp/api/vpe_msg_enum.h>
35 #include <vnet/l2/l2_classify.h>
36 #include <vnet/l2/l2_vtr.h>
37 #include <vnet/classify/in_out_acl.h>
38 #include <vnet/classify/policer_classify.h>
39 #include <vnet/classify/flow_classify.h>
40 #include <vnet/mpls/mpls.h>
41 #include <vnet/ipsec/ipsec.h>
42 #include <inttypes.h>
43 #include <vnet/ip/ip6_hop_by_hop.h>
44 #include <vnet/ip/ip_source_and_port_range_check.h>
45 #include <vnet/policer/xlate.h>
46 #include <vnet/span/span.h>
47 #include <vnet/policer/policer.h>
48 #include <vnet/policer/police.h>
49 #include <vnet/mfib/mfib_types.h>
50 #include <vnet/bonding/node.h>
51 #include <vnet/qos/qos_types.h>
52 #include <vnet/ethernet/ethernet_types_api.h>
53 #include <vnet/ip/ip_types_api.h>
54 #include "vat/json_format.h"
55 #include <vnet/ip/ip_types_api.h>
56 #include <vnet/ethernet/ethernet_types_api.h>
57
58 #include <inttypes.h>
59 #include <sys/stat.h>
60
61 #define vl_typedefs             /* define message structures */
62 #include <vpp/api/vpe_all_api_h.h>
63 #undef vl_typedefs
64
65 /* declare message handlers for each api */
66
67 #define vl_endianfun            /* define message structures */
68 #include <vpp/api/vpe_all_api_h.h>
69 #undef vl_endianfun
70
71 /* instantiate all the print functions we know about */
72 #if VPP_API_TEST_BUILTIN == 0
73 #define vl_print(handle, ...)
74 #else
75 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
76 #endif
77 #define vl_printfun
78 #include <vpp/api/vpe_all_api_h.h>
79 #undef vl_printfun
80
81 #define __plugin_msg_base 0
82 #include <vlibapi/vat_helper_macros.h>
83
84 #include <vnet/format_fns.h>
85
86 void vl_api_set_elog_main (elog_main_t * m);
87 int vl_api_set_elog_trace_api_messages (int enable);
88
89 #if VPP_API_TEST_BUILTIN == 0
90 #include <netdb.h>
91
92 u32
93 vl (void *p)
94 {
95   return vec_len (p);
96 }
97
98 int
99 vat_socket_connect (vat_main_t * vam)
100 {
101   int rv;
102   api_main_t *am = vlibapi_get_main ();
103   vam->socket_client_main = &socket_client_main;
104   if ((rv = vl_socket_client_connect ((char *) vam->socket_name,
105                                       "vpp_api_test",
106                                       0 /* default socket rx, tx buffer */ )))
107     return rv;
108
109   /* vpp expects the client index in network order */
110   vam->my_client_index = htonl (socket_client_main.client_index);
111   am->my_client_index = vam->my_client_index;
112   return 0;
113 }
114 #else /* vpp built-in case, we don't do sockets... */
115 int
116 vat_socket_connect (vat_main_t * vam)
117 {
118   return 0;
119 }
120
121 int
122 vl_socket_client_read (int wait)
123 {
124   return -1;
125 };
126
127 int
128 vl_socket_client_write ()
129 {
130   return -1;
131 };
132
133 void *
134 vl_socket_client_msg_alloc (int nbytes)
135 {
136   return 0;
137 }
138 #endif
139
140
141 f64
142 vat_time_now (vat_main_t * vam)
143 {
144 #if VPP_API_TEST_BUILTIN
145   return vlib_time_now (vam->vlib_main);
146 #else
147   return clib_time_now (&vam->clib_time);
148 #endif
149 }
150
151 void
152 errmsg (char *fmt, ...)
153 {
154   vat_main_t *vam = &vat_main;
155   va_list va;
156   u8 *s;
157
158   va_start (va, fmt);
159   s = va_format (0, fmt, &va);
160   va_end (va);
161
162   vec_add1 (s, 0);
163
164 #if VPP_API_TEST_BUILTIN
165   vlib_cli_output (vam->vlib_main, (char *) s);
166 #else
167   {
168     if (vam->ifp != stdin)
169       fformat (vam->ofp, "%s(%d): \n", vam->current_file,
170                vam->input_line_number);
171     else
172       fformat (vam->ofp, "%s\n", (char *) s);
173     fflush (vam->ofp);
174   }
175 #endif
176
177   vec_free (s);
178 }
179
180 #if VPP_API_TEST_BUILTIN == 0
181 static uword
182 api_unformat_sw_if_index (unformat_input_t * input, va_list * args)
183 {
184   vat_main_t *vam = va_arg (*args, vat_main_t *);
185   u32 *result = va_arg (*args, u32 *);
186   u8 *if_name;
187   uword *p;
188
189   if (!unformat (input, "%s", &if_name))
190     return 0;
191
192   p = hash_get_mem (vam->sw_if_index_by_interface_name, if_name);
193   if (p == 0)
194     return 0;
195   *result = p[0];
196   return 1;
197 }
198
199 static uword
200 api_unformat_hw_if_index (unformat_input_t * input, va_list * args)
201 {
202   return 0;
203 }
204
205 /* Parse an IP4 address %d.%d.%d.%d. */
206 uword
207 unformat_ip4_address (unformat_input_t * input, va_list * args)
208 {
209   u8 *result = va_arg (*args, u8 *);
210   unsigned a[4];
211
212   if (!unformat (input, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]))
213     return 0;
214
215   if (a[0] >= 256 || a[1] >= 256 || a[2] >= 256 || a[3] >= 256)
216     return 0;
217
218   result[0] = a[0];
219   result[1] = a[1];
220   result[2] = a[2];
221   result[3] = a[3];
222
223   return 1;
224 }
225
226 uword
227 unformat_ethernet_address (unformat_input_t * input, va_list * args)
228 {
229   u8 *result = va_arg (*args, u8 *);
230   u32 i, a[6];
231
232   if (!unformat (input, "%_%x:%x:%x:%x:%x:%x%_",
233                  &a[0], &a[1], &a[2], &a[3], &a[4], &a[5]))
234     return 0;
235
236   /* Check range. */
237   for (i = 0; i < 6; i++)
238     if (a[i] >= (1 << 8))
239       return 0;
240
241   for (i = 0; i < 6; i++)
242     result[i] = a[i];
243
244   return 1;
245 }
246
247 /* Returns ethernet type as an int in host byte order. */
248 uword
249 unformat_ethernet_type_host_byte_order (unformat_input_t * input,
250                                         va_list * args)
251 {
252   u16 *result = va_arg (*args, u16 *);
253   int type;
254
255   /* Numeric type. */
256   if (unformat (input, "0x%x", &type) || unformat (input, "%d", &type))
257     {
258       if (type >= (1 << 16))
259         return 0;
260       *result = type;
261       return 1;
262     }
263   return 0;
264 }
265
266 /* Parse an IP46 address. */
267 uword
268 unformat_ip46_address (unformat_input_t * input, va_list * args)
269 {
270   ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
271   ip46_type_t type = va_arg (*args, ip46_type_t);
272   if ((type != IP46_TYPE_IP6) &&
273       unformat (input, "%U", unformat_ip4_address, &ip46->ip4))
274     {
275       ip46_address_mask_ip4 (ip46);
276       return 1;
277     }
278   else if ((type != IP46_TYPE_IP4) &&
279            unformat (input, "%U", unformat_ip6_address, &ip46->ip6))
280     {
281       return 1;
282     }
283   return 0;
284 }
285
286 /* Parse an IP6 address. */
287 uword
288 unformat_ip6_address (unformat_input_t * input, va_list * args)
289 {
290   ip6_address_t *result = va_arg (*args, ip6_address_t *);
291   u16 hex_quads[8];
292   uword hex_quad, n_hex_quads, hex_digit, n_hex_digits;
293   uword c, n_colon, double_colon_index;
294
295   n_hex_quads = hex_quad = n_hex_digits = n_colon = 0;
296   double_colon_index = ARRAY_LEN (hex_quads);
297   while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
298     {
299       hex_digit = 16;
300       if (c >= '0' && c <= '9')
301         hex_digit = c - '0';
302       else if (c >= 'a' && c <= 'f')
303         hex_digit = c + 10 - 'a';
304       else if (c >= 'A' && c <= 'F')
305         hex_digit = c + 10 - 'A';
306       else if (c == ':' && n_colon < 2)
307         n_colon++;
308       else
309         {
310           unformat_put_input (input);
311           break;
312         }
313
314       /* Too many hex quads. */
315       if (n_hex_quads >= ARRAY_LEN (hex_quads))
316         return 0;
317
318       if (hex_digit < 16)
319         {
320           hex_quad = (hex_quad << 4) | hex_digit;
321
322           /* Hex quad must fit in 16 bits. */
323           if (n_hex_digits >= 4)
324             return 0;
325
326           n_colon = 0;
327           n_hex_digits++;
328         }
329
330       /* Save position of :: */
331       if (n_colon == 2)
332         {
333           /* More than one :: ? */
334           if (double_colon_index < ARRAY_LEN (hex_quads))
335             return 0;
336           double_colon_index = n_hex_quads;
337         }
338
339       if (n_colon > 0 && n_hex_digits > 0)
340         {
341           hex_quads[n_hex_quads++] = hex_quad;
342           hex_quad = 0;
343           n_hex_digits = 0;
344         }
345     }
346
347   if (n_hex_digits > 0)
348     hex_quads[n_hex_quads++] = hex_quad;
349
350   {
351     word i;
352
353     /* Expand :: to appropriate number of zero hex quads. */
354     if (double_colon_index < ARRAY_LEN (hex_quads))
355       {
356         word n_zero = ARRAY_LEN (hex_quads) - n_hex_quads;
357
358         for (i = n_hex_quads - 1; i >= (signed) double_colon_index; i--)
359           hex_quads[n_zero + i] = hex_quads[i];
360
361         for (i = 0; i < n_zero; i++)
362           hex_quads[double_colon_index + i] = 0;
363
364         n_hex_quads = ARRAY_LEN (hex_quads);
365       }
366
367     /* Too few hex quads given. */
368     if (n_hex_quads < ARRAY_LEN (hex_quads))
369       return 0;
370
371     for (i = 0; i < ARRAY_LEN (hex_quads); i++)
372       result->as_u16[i] = clib_host_to_net_u16 (hex_quads[i]);
373
374     return 1;
375   }
376 }
377
378 uword
379 unformat_ipsec_policy_action (unformat_input_t * input, va_list * args)
380 {
381   u32 *r = va_arg (*args, u32 *);
382
383   if (0);
384 #define _(v,f,s) else if (unformat (input, s)) *r = IPSEC_POLICY_ACTION_##f;
385   foreach_ipsec_policy_action
386 #undef _
387     else
388     return 0;
389   return 1;
390 }
391
392 u8 *
393 format_ipsec_crypto_alg (u8 * s, va_list * args)
394 {
395   u32 i = va_arg (*args, u32);
396   u8 *t = 0;
397
398   switch (i)
399     {
400 #define _(v,f,str) case IPSEC_CRYPTO_ALG_##f: t = (u8 *) str; break;
401       foreach_ipsec_crypto_alg
402 #undef _
403     default:
404       return format (s, "unknown");
405     }
406   return format (s, "%s", t);
407 }
408
409 u8 *
410 format_ipsec_integ_alg (u8 * s, va_list * args)
411 {
412   u32 i = va_arg (*args, u32);
413   u8 *t = 0;
414
415   switch (i)
416     {
417 #define _(v,f,str) case IPSEC_INTEG_ALG_##f: t = (u8 *) str; break;
418       foreach_ipsec_integ_alg
419 #undef _
420     default:
421       return format (s, "unknown");
422     }
423   return format (s, "%s", t);
424 }
425
426 #else /* VPP_API_TEST_BUILTIN == 1 */
427 static uword
428 api_unformat_sw_if_index (unformat_input_t * input, va_list * args)
429 {
430   vat_main_t *vam __clib_unused = va_arg (*args, vat_main_t *);
431   vnet_main_t *vnm = vnet_get_main ();
432   u32 *result = va_arg (*args, u32 *);
433
434   return unformat (input, "%U", unformat_vnet_sw_interface, vnm, result);
435 }
436
437 static uword
438 api_unformat_hw_if_index (unformat_input_t * input, va_list * args)
439 {
440   vat_main_t *vam __clib_unused = va_arg (*args, vat_main_t *);
441   vnet_main_t *vnm = vnet_get_main ();
442   u32 *result = va_arg (*args, u32 *);
443
444   return unformat (input, "%U", unformat_vnet_hw_interface, vnm, result);
445 }
446
447 #endif /* VPP_API_TEST_BUILTIN */
448
449 uword
450 unformat_ipsec_api_crypto_alg (unformat_input_t * input, va_list * args)
451 {
452   u32 *r = va_arg (*args, u32 *);
453
454   if (0);
455 #define _(v,f,s) else if (unformat (input, s)) *r = IPSEC_API_CRYPTO_ALG_##f;
456   foreach_ipsec_crypto_alg
457 #undef _
458     else
459     return 0;
460   return 1;
461 }
462
463 uword
464 unformat_ipsec_api_integ_alg (unformat_input_t * input, va_list * args)
465 {
466   u32 *r = va_arg (*args, u32 *);
467
468   if (0);
469 #define _(v,f,s) else if (unformat (input, s)) *r = IPSEC_API_INTEG_ALG_##f;
470   foreach_ipsec_integ_alg
471 #undef _
472     else
473     return 0;
474   return 1;
475 }
476
477 static uword
478 unformat_policer_rate_type (unformat_input_t * input, va_list * args)
479 {
480   u8 *r = va_arg (*args, u8 *);
481
482   if (unformat (input, "kbps"))
483     *r = SSE2_QOS_RATE_KBPS;
484   else if (unformat (input, "pps"))
485     *r = SSE2_QOS_RATE_PPS;
486   else
487     return 0;
488   return 1;
489 }
490
491 static uword
492 unformat_policer_round_type (unformat_input_t * input, va_list * args)
493 {
494   u8 *r = va_arg (*args, u8 *);
495
496   if (unformat (input, "closest"))
497     *r = SSE2_QOS_ROUND_TO_CLOSEST;
498   else if (unformat (input, "up"))
499     *r = SSE2_QOS_ROUND_TO_UP;
500   else if (unformat (input, "down"))
501     *r = SSE2_QOS_ROUND_TO_DOWN;
502   else
503     return 0;
504   return 1;
505 }
506
507 static uword
508 unformat_policer_type (unformat_input_t * input, va_list * args)
509 {
510   u8 *r = va_arg (*args, u8 *);
511
512   if (unformat (input, "1r2c"))
513     *r = SSE2_QOS_POLICER_TYPE_1R2C;
514   else if (unformat (input, "1r3c"))
515     *r = SSE2_QOS_POLICER_TYPE_1R3C_RFC_2697;
516   else if (unformat (input, "2r3c-2698"))
517     *r = SSE2_QOS_POLICER_TYPE_2R3C_RFC_2698;
518   else if (unformat (input, "2r3c-4115"))
519     *r = SSE2_QOS_POLICER_TYPE_2R3C_RFC_4115;
520   else if (unformat (input, "2r3c-mef5cf1"))
521     *r = SSE2_QOS_POLICER_TYPE_2R3C_RFC_MEF5CF1;
522   else
523     return 0;
524   return 1;
525 }
526
527 static uword
528 unformat_dscp (unformat_input_t * input, va_list * va)
529 {
530   u8 *r = va_arg (*va, u8 *);
531
532   if (0);
533 #define _(v,f,str) else if (unformat (input, str)) *r = VNET_DSCP_##f;
534   foreach_vnet_dscp
535 #undef _
536     else
537     return 0;
538   return 1;
539 }
540
541 static uword
542 unformat_policer_action_type (unformat_input_t * input, va_list * va)
543 {
544   sse2_qos_pol_action_params_st *a
545     = va_arg (*va, sse2_qos_pol_action_params_st *);
546
547   if (unformat (input, "drop"))
548     a->action_type = SSE2_QOS_ACTION_DROP;
549   else if (unformat (input, "transmit"))
550     a->action_type = SSE2_QOS_ACTION_TRANSMIT;
551   else if (unformat (input, "mark-and-transmit %U", unformat_dscp, &a->dscp))
552     a->action_type = SSE2_QOS_ACTION_MARK_AND_TRANSMIT;
553   else
554     return 0;
555   return 1;
556 }
557
558 static uword
559 unformat_policer_classify_table_type (unformat_input_t * input, va_list * va)
560 {
561   u32 *r = va_arg (*va, u32 *);
562   u32 tid;
563
564   if (unformat (input, "ip4"))
565     tid = POLICER_CLASSIFY_TABLE_IP4;
566   else if (unformat (input, "ip6"))
567     tid = POLICER_CLASSIFY_TABLE_IP6;
568   else if (unformat (input, "l2"))
569     tid = POLICER_CLASSIFY_TABLE_L2;
570   else
571     return 0;
572
573   *r = tid;
574   return 1;
575 }
576
577 static uword
578 unformat_flow_classify_table_type (unformat_input_t * input, va_list * va)
579 {
580   u32 *r = va_arg (*va, u32 *);
581   u32 tid;
582
583   if (unformat (input, "ip4"))
584     tid = FLOW_CLASSIFY_TABLE_IP4;
585   else if (unformat (input, "ip6"))
586     tid = FLOW_CLASSIFY_TABLE_IP6;
587   else
588     return 0;
589
590   *r = tid;
591   return 1;
592 }
593
594 #if (VPP_API_TEST_BUILTIN==0)
595
596 static const char *mfib_flag_names[] = MFIB_ENTRY_NAMES_SHORT;
597 static const char *mfib_flag_long_names[] = MFIB_ENTRY_NAMES_LONG;
598 static const char *mfib_itf_flag_long_names[] = MFIB_ITF_NAMES_LONG;
599 static const char *mfib_itf_flag_names[] = MFIB_ITF_NAMES_SHORT;
600
601 uword
602 unformat_mfib_itf_flags (unformat_input_t * input, va_list * args)
603 {
604   mfib_itf_flags_t old, *iflags = va_arg (*args, mfib_itf_flags_t *);
605   mfib_itf_attribute_t attr;
606
607   old = *iflags;
608   FOR_EACH_MFIB_ITF_ATTRIBUTE (attr)
609   {
610     if (unformat (input, mfib_itf_flag_long_names[attr]))
611       *iflags |= (1 << attr);
612   }
613   FOR_EACH_MFIB_ITF_ATTRIBUTE (attr)
614   {
615     if (unformat (input, mfib_itf_flag_names[attr]))
616       *iflags |= (1 << attr);
617   }
618
619   return (old == *iflags ? 0 : 1);
620 }
621
622 uword
623 unformat_mfib_entry_flags (unformat_input_t * input, va_list * args)
624 {
625   mfib_entry_flags_t old, *eflags = va_arg (*args, mfib_entry_flags_t *);
626   mfib_entry_attribute_t attr;
627
628   old = *eflags;
629   FOR_EACH_MFIB_ATTRIBUTE (attr)
630   {
631     if (unformat (input, mfib_flag_long_names[attr]))
632       *eflags |= (1 << attr);
633   }
634   FOR_EACH_MFIB_ATTRIBUTE (attr)
635   {
636     if (unformat (input, mfib_flag_names[attr]))
637       *eflags |= (1 << attr);
638   }
639
640   return (old == *eflags ? 0 : 1);
641 }
642
643 u8 *
644 format_ip4_address (u8 * s, va_list * args)
645 {
646   u8 *a = va_arg (*args, u8 *);
647   return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
648 }
649
650 u8 *
651 format_ip6_address (u8 * s, va_list * args)
652 {
653   ip6_address_t *a = va_arg (*args, ip6_address_t *);
654   u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;
655
656   i_max_n_zero = ARRAY_LEN (a->as_u16);
657   max_n_zeros = 0;
658   i_first_zero = i_max_n_zero;
659   n_zeros = 0;
660   for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
661     {
662       u32 is_zero = a->as_u16[i] == 0;
663       if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16))
664         {
665           i_first_zero = i;
666           n_zeros = 0;
667         }
668       n_zeros += is_zero;
669       if ((!is_zero && n_zeros > max_n_zeros)
670           || (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros))
671         {
672           i_max_n_zero = i_first_zero;
673           max_n_zeros = n_zeros;
674           i_first_zero = ARRAY_LEN (a->as_u16);
675           n_zeros = 0;
676         }
677     }
678
679   last_double_colon = 0;
680   for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
681     {
682       if (i == i_max_n_zero && max_n_zeros > 1)
683         {
684           s = format (s, "::");
685           i += max_n_zeros - 1;
686           last_double_colon = 1;
687         }
688       else
689         {
690           s = format (s, "%s%x",
691                       (last_double_colon || i == 0) ? "" : ":",
692                       clib_net_to_host_u16 (a->as_u16[i]));
693           last_double_colon = 0;
694         }
695     }
696
697   return s;
698 }
699
700 /* Format an IP46 address. */
701 u8 *
702 format_ip46_address (u8 * s, va_list * args)
703 {
704   ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
705   ip46_type_t type = va_arg (*args, ip46_type_t);
706   int is_ip4 = 1;
707
708   switch (type)
709     {
710     case IP46_TYPE_ANY:
711       is_ip4 = ip46_address_is_ip4 (ip46);
712       break;
713     case IP46_TYPE_IP4:
714       is_ip4 = 1;
715       break;
716     case IP46_TYPE_IP6:
717       is_ip4 = 0;
718       break;
719     }
720
721   return is_ip4 ?
722     format (s, "%U", format_ip4_address, &ip46->ip4) :
723     format (s, "%U", format_ip6_address, &ip46->ip6);
724 }
725
726 u8 *
727 format_ethernet_address (u8 * s, va_list * args)
728 {
729   u8 *a = va_arg (*args, u8 *);
730
731   return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
732                  a[0], a[1], a[2], a[3], a[4], a[5]);
733 }
734 #endif
735
736 static void
737 increment_v4_address (vl_api_ip4_address_t * i)
738 {
739   ip4_address_t *a = (ip4_address_t *) i;
740   u32 v;
741
742   v = ntohl (a->as_u32) + 1;
743   a->as_u32 = ntohl (v);
744 }
745
746 static void
747 increment_v6_address (vl_api_ip6_address_t * i)
748 {
749   ip6_address_t *a = (ip6_address_t *) i;
750   u64 v0, v1;
751
752   v0 = clib_net_to_host_u64 (a->as_u64[0]);
753   v1 = clib_net_to_host_u64 (a->as_u64[1]);
754
755   v1 += 1;
756   if (v1 == 0)
757     v0 += 1;
758   a->as_u64[0] = clib_net_to_host_u64 (v0);
759   a->as_u64[1] = clib_net_to_host_u64 (v1);
760 }
761
762 static void
763 increment_address (vl_api_address_t * a)
764 {
765   if (a->af == ADDRESS_IP4)
766     increment_v4_address (&a->un.ip4);
767   else if (a->af == ADDRESS_IP6)
768     increment_v6_address (&a->un.ip6);
769 }
770
771 static void
772 set_ip4_address (vl_api_address_t * a, u32 v)
773 {
774   if (a->af == ADDRESS_IP4)
775     {
776       ip4_address_t *i = (ip4_address_t *) & a->un.ip4;
777       i->as_u32 = v;
778     }
779 }
780
781 void
782 ip_set (ip46_address_t * dst, void *src, u8 is_ip4)
783 {
784   if (is_ip4)
785     dst->ip4.as_u32 = ((ip4_address_t *) src)->as_u32;
786   else
787     clib_memcpy_fast (&dst->ip6, (ip6_address_t *) src,
788                       sizeof (ip6_address_t));
789 }
790
791 static void
792 increment_mac_address (u8 * mac)
793 {
794   u64 tmp = *((u64 *) mac);
795   tmp = clib_net_to_host_u64 (tmp);
796   tmp += 1 << 16;               /* skip unused (least significant) octets */
797   tmp = clib_host_to_net_u64 (tmp);
798
799   clib_memcpy (mac, &tmp, 6);
800 }
801
802 static void
803 vat_json_object_add_address (vat_json_node_t * node,
804                              const char *str, const vl_api_address_t * addr)
805 {
806   if (ADDRESS_IP6 == addr->af)
807     {
808       struct in6_addr ip6;
809
810       clib_memcpy (&ip6, &addr->un.ip6, sizeof (ip6));
811       vat_json_object_add_ip6 (node, str, ip6);
812     }
813   else
814     {
815       struct in_addr ip4;
816
817       clib_memcpy (&ip4, &addr->un.ip4, sizeof (ip4));
818       vat_json_object_add_ip4 (node, str, ip4);
819     }
820 }
821
822 static void
823 vat_json_object_add_prefix (vat_json_node_t * node,
824                             const vl_api_prefix_t * prefix)
825 {
826   vat_json_object_add_uint (node, "len", prefix->len);
827   vat_json_object_add_address (node, "address", &prefix->address);
828 }
829
830 static void vl_api_create_loopback_reply_t_handler
831   (vl_api_create_loopback_reply_t * mp)
832 {
833   vat_main_t *vam = &vat_main;
834   i32 retval = ntohl (mp->retval);
835
836   vam->retval = retval;
837   vam->regenerate_interface_table = 1;
838   vam->sw_if_index = ntohl (mp->sw_if_index);
839   vam->result_ready = 1;
840 }
841
842 static void vl_api_create_loopback_reply_t_handler_json
843   (vl_api_create_loopback_reply_t * mp)
844 {
845   vat_main_t *vam = &vat_main;
846   vat_json_node_t node;
847
848   vat_json_init_object (&node);
849   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
850   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
851
852   vat_json_print (vam->ofp, &node);
853   vat_json_free (&node);
854   vam->retval = ntohl (mp->retval);
855   vam->result_ready = 1;
856 }
857
858 static void vl_api_create_loopback_instance_reply_t_handler
859   (vl_api_create_loopback_instance_reply_t * mp)
860 {
861   vat_main_t *vam = &vat_main;
862   i32 retval = ntohl (mp->retval);
863
864   vam->retval = retval;
865   vam->regenerate_interface_table = 1;
866   vam->sw_if_index = ntohl (mp->sw_if_index);
867   vam->result_ready = 1;
868 }
869
870 static void vl_api_create_loopback_instance_reply_t_handler_json
871   (vl_api_create_loopback_instance_reply_t * mp)
872 {
873   vat_main_t *vam = &vat_main;
874   vat_json_node_t node;
875
876   vat_json_init_object (&node);
877   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
878   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
879
880   vat_json_print (vam->ofp, &node);
881   vat_json_free (&node);
882   vam->retval = ntohl (mp->retval);
883   vam->result_ready = 1;
884 }
885
886 static void vl_api_af_packet_create_reply_t_handler
887   (vl_api_af_packet_create_reply_t * mp)
888 {
889   vat_main_t *vam = &vat_main;
890   i32 retval = ntohl (mp->retval);
891
892   vam->retval = retval;
893   vam->regenerate_interface_table = 1;
894   vam->sw_if_index = ntohl (mp->sw_if_index);
895   vam->result_ready = 1;
896 }
897
898 static void vl_api_af_packet_create_reply_t_handler_json
899   (vl_api_af_packet_create_reply_t * mp)
900 {
901   vat_main_t *vam = &vat_main;
902   vat_json_node_t node;
903
904   vat_json_init_object (&node);
905   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
906   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
907
908   vat_json_print (vam->ofp, &node);
909   vat_json_free (&node);
910
911   vam->retval = ntohl (mp->retval);
912   vam->result_ready = 1;
913 }
914
915 static void vl_api_create_vlan_subif_reply_t_handler
916   (vl_api_create_vlan_subif_reply_t * mp)
917 {
918   vat_main_t *vam = &vat_main;
919   i32 retval = ntohl (mp->retval);
920
921   vam->retval = retval;
922   vam->regenerate_interface_table = 1;
923   vam->sw_if_index = ntohl (mp->sw_if_index);
924   vam->result_ready = 1;
925 }
926
927 static void vl_api_create_vlan_subif_reply_t_handler_json
928   (vl_api_create_vlan_subif_reply_t * mp)
929 {
930   vat_main_t *vam = &vat_main;
931   vat_json_node_t node;
932
933   vat_json_init_object (&node);
934   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
935   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
936
937   vat_json_print (vam->ofp, &node);
938   vat_json_free (&node);
939
940   vam->retval = ntohl (mp->retval);
941   vam->result_ready = 1;
942 }
943
944 static void vl_api_create_subif_reply_t_handler
945   (vl_api_create_subif_reply_t * mp)
946 {
947   vat_main_t *vam = &vat_main;
948   i32 retval = ntohl (mp->retval);
949
950   vam->retval = retval;
951   vam->regenerate_interface_table = 1;
952   vam->sw_if_index = ntohl (mp->sw_if_index);
953   vam->result_ready = 1;
954 }
955
956 static void vl_api_create_subif_reply_t_handler_json
957   (vl_api_create_subif_reply_t * mp)
958 {
959   vat_main_t *vam = &vat_main;
960   vat_json_node_t node;
961
962   vat_json_init_object (&node);
963   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
964   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
965
966   vat_json_print (vam->ofp, &node);
967   vat_json_free (&node);
968
969   vam->retval = ntohl (mp->retval);
970   vam->result_ready = 1;
971 }
972
973 static void vl_api_interface_name_renumber_reply_t_handler
974   (vl_api_interface_name_renumber_reply_t * mp)
975 {
976   vat_main_t *vam = &vat_main;
977   i32 retval = ntohl (mp->retval);
978
979   vam->retval = retval;
980   vam->regenerate_interface_table = 1;
981   vam->result_ready = 1;
982 }
983
984 static void vl_api_interface_name_renumber_reply_t_handler_json
985   (vl_api_interface_name_renumber_reply_t * mp)
986 {
987   vat_main_t *vam = &vat_main;
988   vat_json_node_t node;
989
990   vat_json_init_object (&node);
991   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
992
993   vat_json_print (vam->ofp, &node);
994   vat_json_free (&node);
995
996   vam->retval = ntohl (mp->retval);
997   vam->result_ready = 1;
998 }
999
1000 /*
1001  * Special-case: build the interface table, maintain
1002  * the next loopback sw_if_index vbl.
1003  */
1004 static void vl_api_sw_interface_details_t_handler
1005   (vl_api_sw_interface_details_t * mp)
1006 {
1007   vat_main_t *vam = &vat_main;
1008   u8 *s = format (0, "%s%c", mp->interface_name, 0);
1009
1010   hash_set_mem (vam->sw_if_index_by_interface_name, s,
1011                 ntohl (mp->sw_if_index));
1012
1013   /* In sub interface case, fill the sub interface table entry */
1014   if (mp->sw_if_index != mp->sup_sw_if_index)
1015     {
1016       sw_interface_subif_t *sub = NULL;
1017
1018       vec_add2 (vam->sw_if_subif_table, sub, 1);
1019
1020       vec_validate (sub->interface_name, strlen ((char *) s) + 1);
1021       strncpy ((char *) sub->interface_name, (char *) s,
1022                vec_len (sub->interface_name));
1023       sub->sw_if_index = ntohl (mp->sw_if_index);
1024       sub->sub_id = ntohl (mp->sub_id);
1025
1026       sub->raw_flags = ntohl (mp->sub_if_flags & SUB_IF_API_FLAG_MASK_VNET);
1027
1028       sub->sub_number_of_tags = mp->sub_number_of_tags;
1029       sub->sub_outer_vlan_id = ntohs (mp->sub_outer_vlan_id);
1030       sub->sub_inner_vlan_id = ntohs (mp->sub_inner_vlan_id);
1031
1032       /* vlan tag rewrite */
1033       sub->vtr_op = ntohl (mp->vtr_op);
1034       sub->vtr_push_dot1q = ntohl (mp->vtr_push_dot1q);
1035       sub->vtr_tag1 = ntohl (mp->vtr_tag1);
1036       sub->vtr_tag2 = ntohl (mp->vtr_tag2);
1037     }
1038 }
1039
1040 static void vl_api_sw_interface_details_t_handler_json
1041   (vl_api_sw_interface_details_t * mp)
1042 {
1043   vat_main_t *vam = &vat_main;
1044   vat_json_node_t *node = NULL;
1045
1046   if (VAT_JSON_ARRAY != vam->json_tree.type)
1047     {
1048       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
1049       vat_json_init_array (&vam->json_tree);
1050     }
1051   node = vat_json_array_add (&vam->json_tree);
1052
1053   vat_json_init_object (node);
1054   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
1055   vat_json_object_add_uint (node, "sup_sw_if_index",
1056                             ntohl (mp->sup_sw_if_index));
1057   vat_json_object_add_bytes (node, "l2_address", mp->l2_address,
1058                              sizeof (mp->l2_address));
1059   vat_json_object_add_string_copy (node, "interface_name",
1060                                    mp->interface_name);
1061   vat_json_object_add_string_copy (node, "interface_dev_type",
1062                                    mp->interface_dev_type);
1063   vat_json_object_add_uint (node, "flags", mp->flags);
1064   vat_json_object_add_uint (node, "link_duplex", mp->link_duplex);
1065   vat_json_object_add_uint (node, "link_speed", mp->link_speed);
1066   vat_json_object_add_uint (node, "mtu", ntohs (mp->link_mtu));
1067   vat_json_object_add_uint (node, "sub_id", ntohl (mp->sub_id));
1068   vat_json_object_add_uint (node, "sub_number_of_tags",
1069                             mp->sub_number_of_tags);
1070   vat_json_object_add_uint (node, "sub_outer_vlan_id",
1071                             ntohs (mp->sub_outer_vlan_id));
1072   vat_json_object_add_uint (node, "sub_inner_vlan_id",
1073                             ntohs (mp->sub_inner_vlan_id));
1074   vat_json_object_add_uint (node, "sub_if_flags", ntohl (mp->sub_if_flags));
1075   vat_json_object_add_uint (node, "vtr_op", ntohl (mp->vtr_op));
1076   vat_json_object_add_uint (node, "vtr_push_dot1q",
1077                             ntohl (mp->vtr_push_dot1q));
1078   vat_json_object_add_uint (node, "vtr_tag1", ntohl (mp->vtr_tag1));
1079   vat_json_object_add_uint (node, "vtr_tag2", ntohl (mp->vtr_tag2));
1080   if (ntohl (mp->sub_if_flags) & SUB_IF_API_FLAG_DOT1AH)
1081     {
1082       vat_json_object_add_string_copy (node, "pbb_vtr_dmac",
1083                                        format (0, "%U",
1084                                                format_ethernet_address,
1085                                                &mp->b_dmac));
1086       vat_json_object_add_string_copy (node, "pbb_vtr_smac",
1087                                        format (0, "%U",
1088                                                format_ethernet_address,
1089                                                &mp->b_smac));
1090       vat_json_object_add_uint (node, "pbb_vtr_b_vlanid", mp->b_vlanid);
1091       vat_json_object_add_uint (node, "pbb_vtr_i_sid", mp->i_sid);
1092     }
1093 }
1094
1095 #if VPP_API_TEST_BUILTIN == 0
1096 static void vl_api_sw_interface_event_t_handler
1097   (vl_api_sw_interface_event_t * mp)
1098 {
1099   vat_main_t *vam = &vat_main;
1100   if (vam->interface_event_display)
1101     errmsg ("interface flags: sw_if_index %d %s %s",
1102             ntohl (mp->sw_if_index),
1103             ((ntohl (mp->flags)) & IF_STATUS_API_FLAG_ADMIN_UP) ?
1104             "admin-up" : "admin-down",
1105             ((ntohl (mp->flags)) & IF_STATUS_API_FLAG_LINK_UP) ?
1106             "link-up" : "link-down");
1107 }
1108 #endif
1109
1110 __clib_unused static void
1111 vl_api_sw_interface_event_t_handler_json (vl_api_sw_interface_event_t * mp)
1112 {
1113   /* JSON output not supported */
1114 }
1115
1116 static void
1117 vl_api_cli_reply_t_handler (vl_api_cli_reply_t * mp)
1118 {
1119   vat_main_t *vam = &vat_main;
1120   i32 retval = ntohl (mp->retval);
1121
1122   vam->retval = retval;
1123   vam->shmem_result = uword_to_pointer (mp->reply_in_shmem, u8 *);
1124   vam->result_ready = 1;
1125 }
1126
1127 static void
1128 vl_api_cli_reply_t_handler_json (vl_api_cli_reply_t * mp)
1129 {
1130   vat_main_t *vam = &vat_main;
1131   vat_json_node_t node;
1132   void *oldheap;
1133   u8 *reply;
1134
1135   vat_json_init_object (&node);
1136   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1137   vat_json_object_add_uint (&node, "reply_in_shmem",
1138                             ntohl (mp->reply_in_shmem));
1139   /* Toss the shared-memory original... */
1140   oldheap = vl_msg_push_heap ();
1141
1142   reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
1143   vec_free (reply);
1144
1145   vl_msg_pop_heap (oldheap);
1146
1147   vat_json_print (vam->ofp, &node);
1148   vat_json_free (&node);
1149
1150   vam->retval = ntohl (mp->retval);
1151   vam->result_ready = 1;
1152 }
1153
1154 static void
1155 vl_api_cli_inband_reply_t_handler (vl_api_cli_inband_reply_t * mp)
1156 {
1157   vat_main_t *vam = &vat_main;
1158   i32 retval = ntohl (mp->retval);
1159
1160   vec_reset_length (vam->cmd_reply);
1161
1162   vam->retval = retval;
1163   if (retval == 0)
1164     vam->cmd_reply = vl_api_from_api_to_new_vec (mp, &mp->reply);
1165   vam->result_ready = 1;
1166 }
1167
1168 static void
1169 vl_api_cli_inband_reply_t_handler_json (vl_api_cli_inband_reply_t * mp)
1170 {
1171   vat_main_t *vam = &vat_main;
1172   vat_json_node_t node;
1173   u8 *reply = 0;                /* reply vector */
1174
1175   reply = vl_api_from_api_to_new_vec (mp, &mp->reply);
1176   vec_reset_length (vam->cmd_reply);
1177
1178   vat_json_init_object (&node);
1179   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1180   vat_json_object_add_string_copy (&node, "reply", reply);
1181
1182   vat_json_print (vam->ofp, &node);
1183   vat_json_free (&node);
1184   vec_free (reply);
1185
1186   vam->retval = ntohl (mp->retval);
1187   vam->result_ready = 1;
1188 }
1189
1190 static void vl_api_classify_add_del_table_reply_t_handler
1191   (vl_api_classify_add_del_table_reply_t * mp)
1192 {
1193   vat_main_t *vam = &vat_main;
1194   i32 retval = ntohl (mp->retval);
1195   if (vam->async_mode)
1196     {
1197       vam->async_errors += (retval < 0);
1198     }
1199   else
1200     {
1201       vam->retval = retval;
1202       if (retval == 0 &&
1203           ((mp->new_table_index != 0xFFFFFFFF) ||
1204            (mp->skip_n_vectors != 0xFFFFFFFF) ||
1205            (mp->match_n_vectors != 0xFFFFFFFF)))
1206         /*
1207          * Note: this is just barely thread-safe, depends on
1208          * the main thread spinning waiting for an answer...
1209          */
1210         errmsg ("new index %d, skip_n_vectors %d, match_n_vectors %d",
1211                 ntohl (mp->new_table_index),
1212                 ntohl (mp->skip_n_vectors), ntohl (mp->match_n_vectors));
1213       vam->result_ready = 1;
1214     }
1215 }
1216
1217 static void vl_api_classify_add_del_table_reply_t_handler_json
1218   (vl_api_classify_add_del_table_reply_t * mp)
1219 {
1220   vat_main_t *vam = &vat_main;
1221   vat_json_node_t node;
1222
1223   vat_json_init_object (&node);
1224   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1225   vat_json_object_add_uint (&node, "new_table_index",
1226                             ntohl (mp->new_table_index));
1227   vat_json_object_add_uint (&node, "skip_n_vectors",
1228                             ntohl (mp->skip_n_vectors));
1229   vat_json_object_add_uint (&node, "match_n_vectors",
1230                             ntohl (mp->match_n_vectors));
1231
1232   vat_json_print (vam->ofp, &node);
1233   vat_json_free (&node);
1234
1235   vam->retval = ntohl (mp->retval);
1236   vam->result_ready = 1;
1237 }
1238
1239 static void vl_api_get_node_index_reply_t_handler
1240   (vl_api_get_node_index_reply_t * mp)
1241 {
1242   vat_main_t *vam = &vat_main;
1243   i32 retval = ntohl (mp->retval);
1244   if (vam->async_mode)
1245     {
1246       vam->async_errors += (retval < 0);
1247     }
1248   else
1249     {
1250       vam->retval = retval;
1251       if (retval == 0)
1252         errmsg ("node index %d", ntohl (mp->node_index));
1253       vam->result_ready = 1;
1254     }
1255 }
1256
1257 static void vl_api_get_node_index_reply_t_handler_json
1258   (vl_api_get_node_index_reply_t * mp)
1259 {
1260   vat_main_t *vam = &vat_main;
1261   vat_json_node_t node;
1262
1263   vat_json_init_object (&node);
1264   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1265   vat_json_object_add_uint (&node, "node_index", ntohl (mp->node_index));
1266
1267   vat_json_print (vam->ofp, &node);
1268   vat_json_free (&node);
1269
1270   vam->retval = ntohl (mp->retval);
1271   vam->result_ready = 1;
1272 }
1273
1274 static void vl_api_get_next_index_reply_t_handler
1275   (vl_api_get_next_index_reply_t * mp)
1276 {
1277   vat_main_t *vam = &vat_main;
1278   i32 retval = ntohl (mp->retval);
1279   if (vam->async_mode)
1280     {
1281       vam->async_errors += (retval < 0);
1282     }
1283   else
1284     {
1285       vam->retval = retval;
1286       if (retval == 0)
1287         errmsg ("next node index %d", ntohl (mp->next_index));
1288       vam->result_ready = 1;
1289     }
1290 }
1291
1292 static void vl_api_get_next_index_reply_t_handler_json
1293   (vl_api_get_next_index_reply_t * mp)
1294 {
1295   vat_main_t *vam = &vat_main;
1296   vat_json_node_t node;
1297
1298   vat_json_init_object (&node);
1299   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1300   vat_json_object_add_uint (&node, "next_index", ntohl (mp->next_index));
1301
1302   vat_json_print (vam->ofp, &node);
1303   vat_json_free (&node);
1304
1305   vam->retval = ntohl (mp->retval);
1306   vam->result_ready = 1;
1307 }
1308
1309 static void vl_api_add_node_next_reply_t_handler
1310   (vl_api_add_node_next_reply_t * mp)
1311 {
1312   vat_main_t *vam = &vat_main;
1313   i32 retval = ntohl (mp->retval);
1314   if (vam->async_mode)
1315     {
1316       vam->async_errors += (retval < 0);
1317     }
1318   else
1319     {
1320       vam->retval = retval;
1321       if (retval == 0)
1322         errmsg ("next index %d", ntohl (mp->next_index));
1323       vam->result_ready = 1;
1324     }
1325 }
1326
1327 static void vl_api_add_node_next_reply_t_handler_json
1328   (vl_api_add_node_next_reply_t * mp)
1329 {
1330   vat_main_t *vam = &vat_main;
1331   vat_json_node_t node;
1332
1333   vat_json_init_object (&node);
1334   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1335   vat_json_object_add_uint (&node, "next_index", ntohl (mp->next_index));
1336
1337   vat_json_print (vam->ofp, &node);
1338   vat_json_free (&node);
1339
1340   vam->retval = ntohl (mp->retval);
1341   vam->result_ready = 1;
1342 }
1343
1344 static void vl_api_show_version_reply_t_handler
1345   (vl_api_show_version_reply_t * mp)
1346 {
1347   vat_main_t *vam = &vat_main;
1348   i32 retval = ntohl (mp->retval);
1349
1350   if (retval >= 0)
1351     {
1352       errmsg ("        program: %s", mp->program);
1353       errmsg ("        version: %s", mp->version);
1354       errmsg ("     build date: %s", mp->build_date);
1355       errmsg ("build directory: %s", mp->build_directory);
1356     }
1357   vam->retval = retval;
1358   vam->result_ready = 1;
1359 }
1360
1361 static void vl_api_show_version_reply_t_handler_json
1362   (vl_api_show_version_reply_t * mp)
1363 {
1364   vat_main_t *vam = &vat_main;
1365   vat_json_node_t node;
1366
1367   vat_json_init_object (&node);
1368   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1369   vat_json_object_add_string_copy (&node, "program", mp->program);
1370   vat_json_object_add_string_copy (&node, "version", mp->version);
1371   vat_json_object_add_string_copy (&node, "build_date", mp->build_date);
1372   vat_json_object_add_string_copy (&node, "build_directory",
1373                                    mp->build_directory);
1374
1375   vat_json_print (vam->ofp, &node);
1376   vat_json_free (&node);
1377
1378   vam->retval = ntohl (mp->retval);
1379   vam->result_ready = 1;
1380 }
1381
1382 static void vl_api_show_threads_reply_t_handler
1383   (vl_api_show_threads_reply_t * mp)
1384 {
1385   vat_main_t *vam = &vat_main;
1386   i32 retval = ntohl (mp->retval);
1387   int i, count = 0;
1388
1389   if (retval >= 0)
1390     count = ntohl (mp->count);
1391
1392   for (i = 0; i < count; i++)
1393     print (vam->ofp,
1394            "\n%-2d %-11s %-11s %-5d %-6d %-4d %-6d",
1395            ntohl (mp->thread_data[i].id), mp->thread_data[i].name,
1396            mp->thread_data[i].type, ntohl (mp->thread_data[i].pid),
1397            ntohl (mp->thread_data[i].cpu_id), ntohl (mp->thread_data[i].core),
1398            ntohl (mp->thread_data[i].cpu_socket));
1399
1400   vam->retval = retval;
1401   vam->result_ready = 1;
1402 }
1403
1404 static void vl_api_show_threads_reply_t_handler_json
1405   (vl_api_show_threads_reply_t * mp)
1406 {
1407   vat_main_t *vam = &vat_main;
1408   vat_json_node_t node;
1409   vl_api_thread_data_t *td;
1410   i32 retval = ntohl (mp->retval);
1411   int i, count = 0;
1412
1413   if (retval >= 0)
1414     count = ntohl (mp->count);
1415
1416   vat_json_init_object (&node);
1417   vat_json_object_add_int (&node, "retval", retval);
1418   vat_json_object_add_uint (&node, "count", count);
1419
1420   for (i = 0; i < count; i++)
1421     {
1422       td = &mp->thread_data[i];
1423       vat_json_object_add_uint (&node, "id", ntohl (td->id));
1424       vat_json_object_add_string_copy (&node, "name", td->name);
1425       vat_json_object_add_string_copy (&node, "type", td->type);
1426       vat_json_object_add_uint (&node, "pid", ntohl (td->pid));
1427       vat_json_object_add_int (&node, "cpu_id", ntohl (td->cpu_id));
1428       vat_json_object_add_int (&node, "core", ntohl (td->id));
1429       vat_json_object_add_int (&node, "cpu_socket", ntohl (td->cpu_socket));
1430     }
1431
1432   vat_json_print (vam->ofp, &node);
1433   vat_json_free (&node);
1434
1435   vam->retval = retval;
1436   vam->result_ready = 1;
1437 }
1438
1439 static int
1440 api_show_threads (vat_main_t * vam)
1441 {
1442   vl_api_show_threads_t *mp;
1443   int ret;
1444
1445   print (vam->ofp,
1446          "\n%-2s %-11s %-11s %-5s %-6s %-4s %-6s",
1447          "ID", "Name", "Type", "LWP", "cpu_id", "Core", "Socket");
1448
1449   M (SHOW_THREADS, mp);
1450
1451   S (mp);
1452   W (ret);
1453   return ret;
1454 }
1455
1456 static void
1457 vl_api_l2_macs_event_t_handler (vl_api_l2_macs_event_t * mp)
1458 {
1459   u32 n_macs = ntohl (mp->n_macs);
1460   errmsg ("L2MAC event received with pid %d cl-idx %d for %d macs: \n",
1461           ntohl (mp->pid), mp->client_index, n_macs);
1462   int i;
1463   for (i = 0; i < n_macs; i++)
1464     {
1465       vl_api_mac_entry_t *mac = &mp->mac[i];
1466       errmsg (" [%d] sw_if_index %d  mac_addr %U  action %d \n",
1467               i + 1, ntohl (mac->sw_if_index),
1468               format_ethernet_address, mac->mac_addr, mac->action);
1469       if (i == 1000)
1470         break;
1471     }
1472 }
1473
1474 static void
1475 vl_api_l2_macs_event_t_handler_json (vl_api_l2_macs_event_t * mp)
1476 {
1477   /* JSON output not supported */
1478 }
1479
1480 #define vl_api_bridge_domain_details_t_endian vl_noop_handler
1481 #define vl_api_bridge_domain_details_t_print vl_noop_handler
1482
1483 /*
1484  * Special-case: build the bridge domain table, maintain
1485  * the next bd id vbl.
1486  */
1487 static void vl_api_bridge_domain_details_t_handler
1488   (vl_api_bridge_domain_details_t * mp)
1489 {
1490   vat_main_t *vam = &vat_main;
1491   u32 n_sw_ifs = ntohl (mp->n_sw_ifs);
1492   int i;
1493
1494   print (vam->ofp, "\n%-3s %-3s %-3s %-3s %-3s %-6s %-3s",
1495          " ID", "LRN", "FWD", "FLD", "BVI", "UU-FWD", "#IF");
1496
1497   print (vam->ofp, "%3d %3d %3d %3d %3d %6d %3d",
1498          ntohl (mp->bd_id), mp->learn, mp->forward,
1499          mp->flood, ntohl (mp->bvi_sw_if_index),
1500          ntohl (mp->uu_fwd_sw_if_index), n_sw_ifs);
1501
1502   if (n_sw_ifs)
1503     {
1504       vl_api_bridge_domain_sw_if_t *sw_ifs;
1505       print (vam->ofp, "\n\n%s %s  %s", "sw_if_index", "SHG",
1506              "Interface Name");
1507
1508       sw_ifs = mp->sw_if_details;
1509       for (i = 0; i < n_sw_ifs; i++)
1510         {
1511           u8 *sw_if_name = 0;
1512           u32 sw_if_index;
1513           hash_pair_t *p;
1514
1515           sw_if_index = ntohl (sw_ifs->sw_if_index);
1516
1517           /* *INDENT-OFF* */
1518           hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
1519                              ({
1520                                if ((u32) p->value[0] == sw_if_index)
1521                                  {
1522                                    sw_if_name = (u8 *)(p->key);
1523                                    break;
1524                                  }
1525                              }));
1526           /* *INDENT-ON* */
1527           print (vam->ofp, "%7d     %3d  %s", sw_if_index,
1528                  sw_ifs->shg, sw_if_name ? (char *) sw_if_name :
1529                  "sw_if_index not found!");
1530
1531           sw_ifs++;
1532         }
1533     }
1534 }
1535
1536 static void vl_api_bridge_domain_details_t_handler_json
1537   (vl_api_bridge_domain_details_t * mp)
1538 {
1539   vat_main_t *vam = &vat_main;
1540   vat_json_node_t *node, *array = NULL;
1541   u32 n_sw_ifs = ntohl (mp->n_sw_ifs);
1542
1543   if (VAT_JSON_ARRAY != vam->json_tree.type)
1544     {
1545       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
1546       vat_json_init_array (&vam->json_tree);
1547     }
1548   node = vat_json_array_add (&vam->json_tree);
1549
1550   vat_json_init_object (node);
1551   vat_json_object_add_uint (node, "bd_id", ntohl (mp->bd_id));
1552   vat_json_object_add_uint (node, "flood", mp->flood);
1553   vat_json_object_add_uint (node, "forward", mp->forward);
1554   vat_json_object_add_uint (node, "learn", mp->learn);
1555   vat_json_object_add_uint (node, "bvi_sw_if_index",
1556                             ntohl (mp->bvi_sw_if_index));
1557   vat_json_object_add_uint (node, "n_sw_ifs", n_sw_ifs);
1558   array = vat_json_object_add (node, "sw_if");
1559   vat_json_init_array (array);
1560
1561
1562
1563   if (n_sw_ifs)
1564     {
1565       vl_api_bridge_domain_sw_if_t *sw_ifs;
1566       int i;
1567
1568       sw_ifs = mp->sw_if_details;
1569       for (i = 0; i < n_sw_ifs; i++)
1570         {
1571           node = vat_json_array_add (array);
1572           vat_json_init_object (node);
1573           vat_json_object_add_uint (node, "sw_if_index",
1574                                     ntohl (sw_ifs->sw_if_index));
1575           vat_json_object_add_uint (node, "shg", sw_ifs->shg);
1576           sw_ifs++;
1577         }
1578     }
1579 }
1580
1581 static void vl_api_control_ping_reply_t_handler
1582   (vl_api_control_ping_reply_t * mp)
1583 {
1584   vat_main_t *vam = &vat_main;
1585   i32 retval = ntohl (mp->retval);
1586   if (vam->async_mode)
1587     {
1588       vam->async_errors += (retval < 0);
1589     }
1590   else
1591     {
1592       vam->retval = retval;
1593       vam->result_ready = 1;
1594     }
1595   if (vam->socket_client_main)
1596     vam->socket_client_main->control_pings_outstanding--;
1597 }
1598
1599 static void vl_api_control_ping_reply_t_handler_json
1600   (vl_api_control_ping_reply_t * mp)
1601 {
1602   vat_main_t *vam = &vat_main;
1603   i32 retval = ntohl (mp->retval);
1604
1605   if (VAT_JSON_NONE != vam->json_tree.type)
1606     {
1607       vat_json_print (vam->ofp, &vam->json_tree);
1608       vat_json_free (&vam->json_tree);
1609       vam->json_tree.type = VAT_JSON_NONE;
1610     }
1611   else
1612     {
1613       /* just print [] */
1614       vat_json_init_array (&vam->json_tree);
1615       vat_json_print (vam->ofp, &vam->json_tree);
1616       vam->json_tree.type = VAT_JSON_NONE;
1617     }
1618
1619   vam->retval = retval;
1620   vam->result_ready = 1;
1621 }
1622
1623 static void
1624   vl_api_bridge_domain_set_mac_age_reply_t_handler
1625   (vl_api_bridge_domain_set_mac_age_reply_t * mp)
1626 {
1627   vat_main_t *vam = &vat_main;
1628   i32 retval = ntohl (mp->retval);
1629   if (vam->async_mode)
1630     {
1631       vam->async_errors += (retval < 0);
1632     }
1633   else
1634     {
1635       vam->retval = retval;
1636       vam->result_ready = 1;
1637     }
1638 }
1639
1640 static void vl_api_bridge_domain_set_mac_age_reply_t_handler_json
1641   (vl_api_bridge_domain_set_mac_age_reply_t * mp)
1642 {
1643   vat_main_t *vam = &vat_main;
1644   vat_json_node_t node;
1645
1646   vat_json_init_object (&node);
1647   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1648
1649   vat_json_print (vam->ofp, &node);
1650   vat_json_free (&node);
1651
1652   vam->retval = ntohl (mp->retval);
1653   vam->result_ready = 1;
1654 }
1655
1656 static void
1657 vl_api_l2_flags_reply_t_handler (vl_api_l2_flags_reply_t * mp)
1658 {
1659   vat_main_t *vam = &vat_main;
1660   i32 retval = ntohl (mp->retval);
1661   if (vam->async_mode)
1662     {
1663       vam->async_errors += (retval < 0);
1664     }
1665   else
1666     {
1667       vam->retval = retval;
1668       vam->result_ready = 1;
1669     }
1670 }
1671
1672 static void vl_api_l2_flags_reply_t_handler_json
1673   (vl_api_l2_flags_reply_t * mp)
1674 {
1675   vat_main_t *vam = &vat_main;
1676   vat_json_node_t node;
1677
1678   vat_json_init_object (&node);
1679   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1680   vat_json_object_add_uint (&node, "resulting_feature_bitmap",
1681                             ntohl (mp->resulting_feature_bitmap));
1682
1683   vat_json_print (vam->ofp, &node);
1684   vat_json_free (&node);
1685
1686   vam->retval = ntohl (mp->retval);
1687   vam->result_ready = 1;
1688 }
1689
1690 static void vl_api_bridge_flags_reply_t_handler
1691   (vl_api_bridge_flags_reply_t * mp)
1692 {
1693   vat_main_t *vam = &vat_main;
1694   i32 retval = ntohl (mp->retval);
1695   if (vam->async_mode)
1696     {
1697       vam->async_errors += (retval < 0);
1698     }
1699   else
1700     {
1701       vam->retval = retval;
1702       vam->result_ready = 1;
1703     }
1704 }
1705
1706 static void vl_api_bridge_flags_reply_t_handler_json
1707   (vl_api_bridge_flags_reply_t * mp)
1708 {
1709   vat_main_t *vam = &vat_main;
1710   vat_json_node_t node;
1711
1712   vat_json_init_object (&node);
1713   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1714   vat_json_object_add_uint (&node, "resulting_feature_bitmap",
1715                             ntohl (mp->resulting_feature_bitmap));
1716
1717   vat_json_print (vam->ofp, &node);
1718   vat_json_free (&node);
1719
1720   vam->retval = ntohl (mp->retval);
1721   vam->result_ready = 1;
1722 }
1723
1724 static void
1725 vl_api_tap_create_v2_reply_t_handler (vl_api_tap_create_v2_reply_t * mp)
1726 {
1727   vat_main_t *vam = &vat_main;
1728   i32 retval = ntohl (mp->retval);
1729   if (vam->async_mode)
1730     {
1731       vam->async_errors += (retval < 0);
1732     }
1733   else
1734     {
1735       vam->retval = retval;
1736       vam->sw_if_index = ntohl (mp->sw_if_index);
1737       vam->result_ready = 1;
1738     }
1739
1740 }
1741
1742 static void vl_api_tap_create_v2_reply_t_handler_json
1743   (vl_api_tap_create_v2_reply_t * mp)
1744 {
1745   vat_main_t *vam = &vat_main;
1746   vat_json_node_t node;
1747
1748   vat_json_init_object (&node);
1749   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1750   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1751
1752   vat_json_print (vam->ofp, &node);
1753   vat_json_free (&node);
1754
1755   vam->retval = ntohl (mp->retval);
1756   vam->result_ready = 1;
1757
1758 }
1759
1760 static void
1761 vl_api_tap_delete_v2_reply_t_handler (vl_api_tap_delete_v2_reply_t * mp)
1762 {
1763   vat_main_t *vam = &vat_main;
1764   i32 retval = ntohl (mp->retval);
1765   if (vam->async_mode)
1766     {
1767       vam->async_errors += (retval < 0);
1768     }
1769   else
1770     {
1771       vam->retval = retval;
1772       vam->result_ready = 1;
1773     }
1774 }
1775
1776 static void vl_api_tap_delete_v2_reply_t_handler_json
1777   (vl_api_tap_delete_v2_reply_t * mp)
1778 {
1779   vat_main_t *vam = &vat_main;
1780   vat_json_node_t node;
1781
1782   vat_json_init_object (&node);
1783   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1784
1785   vat_json_print (vam->ofp, &node);
1786   vat_json_free (&node);
1787
1788   vam->retval = ntohl (mp->retval);
1789   vam->result_ready = 1;
1790 }
1791
1792 static void
1793 vl_api_virtio_pci_create_reply_t_handler (vl_api_virtio_pci_create_reply_t *
1794                                           mp)
1795 {
1796   vat_main_t *vam = &vat_main;
1797   i32 retval = ntohl (mp->retval);
1798   if (vam->async_mode)
1799     {
1800       vam->async_errors += (retval < 0);
1801     }
1802   else
1803     {
1804       vam->retval = retval;
1805       vam->sw_if_index = ntohl (mp->sw_if_index);
1806       vam->result_ready = 1;
1807     }
1808 }
1809
1810 static void vl_api_virtio_pci_create_reply_t_handler_json
1811   (vl_api_virtio_pci_create_reply_t * mp)
1812 {
1813   vat_main_t *vam = &vat_main;
1814   vat_json_node_t node;
1815
1816   vat_json_init_object (&node);
1817   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1818   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1819
1820   vat_json_print (vam->ofp, &node);
1821   vat_json_free (&node);
1822
1823   vam->retval = ntohl (mp->retval);
1824   vam->result_ready = 1;
1825
1826 }
1827
1828 static void
1829   vl_api_virtio_pci_create_v2_reply_t_handler
1830   (vl_api_virtio_pci_create_v2_reply_t * mp)
1831 {
1832   vat_main_t *vam = &vat_main;
1833   i32 retval = ntohl (mp->retval);
1834   if (vam->async_mode)
1835     {
1836       vam->async_errors += (retval < 0);
1837     }
1838   else
1839     {
1840       vam->retval = retval;
1841       vam->sw_if_index = ntohl (mp->sw_if_index);
1842       vam->result_ready = 1;
1843     }
1844 }
1845
1846 static void vl_api_virtio_pci_create_v2_reply_t_handler_json
1847   (vl_api_virtio_pci_create_v2_reply_t * mp)
1848 {
1849   vat_main_t *vam = &vat_main;
1850   vat_json_node_t node;
1851
1852   vat_json_init_object (&node);
1853   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1854   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1855
1856   vat_json_print (vam->ofp, &node);
1857   vat_json_free (&node);
1858
1859   vam->retval = ntohl (mp->retval);
1860   vam->result_ready = 1;
1861 }
1862
1863 static void
1864 vl_api_virtio_pci_delete_reply_t_handler (vl_api_virtio_pci_delete_reply_t *
1865                                           mp)
1866 {
1867   vat_main_t *vam = &vat_main;
1868   i32 retval = ntohl (mp->retval);
1869   if (vam->async_mode)
1870     {
1871       vam->async_errors += (retval < 0);
1872     }
1873   else
1874     {
1875       vam->retval = retval;
1876       vam->result_ready = 1;
1877     }
1878 }
1879
1880 static void vl_api_virtio_pci_delete_reply_t_handler_json
1881   (vl_api_virtio_pci_delete_reply_t * mp)
1882 {
1883   vat_main_t *vam = &vat_main;
1884   vat_json_node_t node;
1885
1886   vat_json_init_object (&node);
1887   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1888
1889   vat_json_print (vam->ofp, &node);
1890   vat_json_free (&node);
1891
1892   vam->retval = ntohl (mp->retval);
1893   vam->result_ready = 1;
1894 }
1895
1896 static void
1897 vl_api_bond_create_reply_t_handler (vl_api_bond_create_reply_t * mp)
1898 {
1899   vat_main_t *vam = &vat_main;
1900   i32 retval = ntohl (mp->retval);
1901
1902   if (vam->async_mode)
1903     {
1904       vam->async_errors += (retval < 0);
1905     }
1906   else
1907     {
1908       vam->retval = retval;
1909       vam->sw_if_index = ntohl (mp->sw_if_index);
1910       vam->result_ready = 1;
1911     }
1912 }
1913
1914 static void vl_api_bond_create_reply_t_handler_json
1915   (vl_api_bond_create_reply_t * mp)
1916 {
1917   vat_main_t *vam = &vat_main;
1918   vat_json_node_t node;
1919
1920   vat_json_init_object (&node);
1921   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1922   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1923
1924   vat_json_print (vam->ofp, &node);
1925   vat_json_free (&node);
1926
1927   vam->retval = ntohl (mp->retval);
1928   vam->result_ready = 1;
1929 }
1930
1931 static void
1932 vl_api_bond_create2_reply_t_handler (vl_api_bond_create2_reply_t * mp)
1933 {
1934   vat_main_t *vam = &vat_main;
1935   i32 retval = ntohl (mp->retval);
1936
1937   if (vam->async_mode)
1938     {
1939       vam->async_errors += (retval < 0);
1940     }
1941   else
1942     {
1943       vam->retval = retval;
1944       vam->sw_if_index = ntohl (mp->sw_if_index);
1945       vam->result_ready = 1;
1946     }
1947 }
1948
1949 static void vl_api_bond_create2_reply_t_handler_json
1950   (vl_api_bond_create2_reply_t * mp)
1951 {
1952   vat_main_t *vam = &vat_main;
1953   vat_json_node_t node;
1954
1955   vat_json_init_object (&node);
1956   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1957   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1958
1959   vat_json_print (vam->ofp, &node);
1960   vat_json_free (&node);
1961
1962   vam->retval = ntohl (mp->retval);
1963   vam->result_ready = 1;
1964 }
1965
1966 static void
1967 vl_api_bond_delete_reply_t_handler (vl_api_bond_delete_reply_t * mp)
1968 {
1969   vat_main_t *vam = &vat_main;
1970   i32 retval = ntohl (mp->retval);
1971
1972   if (vam->async_mode)
1973     {
1974       vam->async_errors += (retval < 0);
1975     }
1976   else
1977     {
1978       vam->retval = retval;
1979       vam->result_ready = 1;
1980     }
1981 }
1982
1983 static void vl_api_bond_delete_reply_t_handler_json
1984   (vl_api_bond_delete_reply_t * mp)
1985 {
1986   vat_main_t *vam = &vat_main;
1987   vat_json_node_t node;
1988
1989   vat_json_init_object (&node);
1990   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1991
1992   vat_json_print (vam->ofp, &node);
1993   vat_json_free (&node);
1994
1995   vam->retval = ntohl (mp->retval);
1996   vam->result_ready = 1;
1997 }
1998
1999 static void
2000 vl_api_bond_add_member_reply_t_handler (vl_api_bond_add_member_reply_t * mp)
2001 {
2002   vat_main_t *vam = &vat_main;
2003   i32 retval = ntohl (mp->retval);
2004
2005   if (vam->async_mode)
2006     {
2007       vam->async_errors += (retval < 0);
2008     }
2009   else
2010     {
2011       vam->retval = retval;
2012       vam->result_ready = 1;
2013     }
2014 }
2015
2016 static void vl_api_bond_add_member_reply_t_handler_json
2017   (vl_api_bond_add_member_reply_t * mp)
2018 {
2019   vat_main_t *vam = &vat_main;
2020   vat_json_node_t node;
2021
2022   vat_json_init_object (&node);
2023   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2024
2025   vat_json_print (vam->ofp, &node);
2026   vat_json_free (&node);
2027
2028   vam->retval = ntohl (mp->retval);
2029   vam->result_ready = 1;
2030 }
2031
2032 static void
2033 vl_api_bond_detach_member_reply_t_handler (vl_api_bond_detach_member_reply_t *
2034                                            mp)
2035 {
2036   vat_main_t *vam = &vat_main;
2037   i32 retval = ntohl (mp->retval);
2038
2039   if (vam->async_mode)
2040     {
2041       vam->async_errors += (retval < 0);
2042     }
2043   else
2044     {
2045       vam->retval = retval;
2046       vam->result_ready = 1;
2047     }
2048 }
2049
2050 static void vl_api_bond_detach_member_reply_t_handler_json
2051   (vl_api_bond_detach_member_reply_t * mp)
2052 {
2053   vat_main_t *vam = &vat_main;
2054   vat_json_node_t node;
2055
2056   vat_json_init_object (&node);
2057   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2058
2059   vat_json_print (vam->ofp, &node);
2060   vat_json_free (&node);
2061
2062   vam->retval = ntohl (mp->retval);
2063   vam->result_ready = 1;
2064 }
2065
2066 static int
2067 api_sw_interface_set_bond_weight (vat_main_t * vam)
2068 {
2069   unformat_input_t *i = vam->input;
2070   vl_api_sw_interface_set_bond_weight_t *mp;
2071   u32 sw_if_index = ~0;
2072   u32 weight = 0;
2073   u8 weight_enter = 0;
2074   int ret;
2075
2076   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2077     {
2078       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2079         ;
2080       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2081         ;
2082       else if (unformat (i, "weight %u", &weight))
2083         weight_enter = 1;
2084       else
2085         break;
2086     }
2087
2088   if (sw_if_index == ~0)
2089     {
2090       errmsg ("missing interface name or sw_if_index");
2091       return -99;
2092     }
2093   if (weight_enter == 0)
2094     {
2095       errmsg ("missing valid weight");
2096       return -99;
2097     }
2098
2099   /* Construct the API message */
2100   M (SW_INTERFACE_SET_BOND_WEIGHT, mp);
2101   mp->sw_if_index = ntohl (sw_if_index);
2102   mp->weight = ntohl (weight);
2103
2104   S (mp);
2105   W (ret);
2106   return ret;
2107 }
2108
2109 static void vl_api_sw_bond_interface_details_t_handler
2110   (vl_api_sw_bond_interface_details_t * mp)
2111 {
2112   vat_main_t *vam = &vat_main;
2113
2114   print (vam->ofp,
2115          "%-16s %-12d %-12U %-13U %-14u %-14u",
2116          mp->interface_name, ntohl (mp->sw_if_index),
2117          format_bond_mode, ntohl (mp->mode), format_bond_load_balance,
2118          ntohl (mp->lb), ntohl (mp->active_members), ntohl (mp->members));
2119 }
2120
2121 static void vl_api_sw_bond_interface_details_t_handler_json
2122   (vl_api_sw_bond_interface_details_t * mp)
2123 {
2124   vat_main_t *vam = &vat_main;
2125   vat_json_node_t *node = NULL;
2126
2127   if (VAT_JSON_ARRAY != vam->json_tree.type)
2128     {
2129       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
2130       vat_json_init_array (&vam->json_tree);
2131     }
2132   node = vat_json_array_add (&vam->json_tree);
2133
2134   vat_json_init_object (node);
2135   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
2136   vat_json_object_add_string_copy (node, "interface_name",
2137                                    mp->interface_name);
2138   vat_json_object_add_uint (node, "mode", ntohl (mp->mode));
2139   vat_json_object_add_uint (node, "load_balance", ntohl (mp->lb));
2140   vat_json_object_add_uint (node, "active_members",
2141                             ntohl (mp->active_members));
2142   vat_json_object_add_uint (node, "members", ntohl (mp->members));
2143 }
2144
2145 static int
2146 api_sw_bond_interface_dump (vat_main_t * vam)
2147 {
2148   unformat_input_t *i = vam->input;
2149   vl_api_sw_bond_interface_dump_t *mp;
2150   vl_api_control_ping_t *mp_ping;
2151   int ret;
2152   u32 sw_if_index = ~0;
2153
2154   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2155     {
2156       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2157         ;
2158       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2159         ;
2160       else
2161         break;
2162     }
2163
2164   print (vam->ofp,
2165          "\n%-16s %-12s %-12s %-13s %-14s %-14s",
2166          "interface name", "sw_if_index", "mode", "load balance",
2167          "active members", "members");
2168
2169   /* Get list of bond interfaces */
2170   M (SW_BOND_INTERFACE_DUMP, mp);
2171   mp->sw_if_index = ntohl (sw_if_index);
2172   S (mp);
2173
2174   /* Use a control ping for synchronization */
2175   MPING (CONTROL_PING, mp_ping);
2176   S (mp_ping);
2177
2178   W (ret);
2179   return ret;
2180 }
2181
2182 static void vl_api_sw_member_interface_details_t_handler
2183   (vl_api_sw_member_interface_details_t * mp)
2184 {
2185   vat_main_t *vam = &vat_main;
2186
2187   print (vam->ofp,
2188          "%-25s %-12d %-7d %-12d %-10d %-10d", mp->interface_name,
2189          ntohl (mp->sw_if_index), mp->is_passive, mp->is_long_timeout,
2190          ntohl (mp->weight), mp->is_local_numa);
2191 }
2192
2193 static void vl_api_sw_member_interface_details_t_handler_json
2194   (vl_api_sw_member_interface_details_t * mp)
2195 {
2196   vat_main_t *vam = &vat_main;
2197   vat_json_node_t *node = NULL;
2198
2199   if (VAT_JSON_ARRAY != vam->json_tree.type)
2200     {
2201       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
2202       vat_json_init_array (&vam->json_tree);
2203     }
2204   node = vat_json_array_add (&vam->json_tree);
2205
2206   vat_json_init_object (node);
2207   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
2208   vat_json_object_add_string_copy (node, "interface_name",
2209                                    mp->interface_name);
2210   vat_json_object_add_uint (node, "passive", mp->is_passive);
2211   vat_json_object_add_uint (node, "long_timeout", mp->is_long_timeout);
2212   vat_json_object_add_uint (node, "weight", ntohl (mp->weight));
2213   vat_json_object_add_uint (node, "is_local_numa", mp->is_local_numa);
2214 }
2215
2216 static int
2217 api_sw_member_interface_dump (vat_main_t * vam)
2218 {
2219   unformat_input_t *i = vam->input;
2220   vl_api_sw_member_interface_dump_t *mp;
2221   vl_api_control_ping_t *mp_ping;
2222   u32 sw_if_index = ~0;
2223   u8 sw_if_index_set = 0;
2224   int ret;
2225
2226   /* Parse args required to build the message */
2227   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2228     {
2229       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2230         sw_if_index_set = 1;
2231       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2232         sw_if_index_set = 1;
2233       else
2234         break;
2235     }
2236
2237   if (sw_if_index_set == 0)
2238     {
2239       errmsg ("missing vpp interface name. ");
2240       return -99;
2241     }
2242
2243   print (vam->ofp,
2244          "\n%-25s %-12s %-7s %-12s %-10s %-10s",
2245          "member interface name", "sw_if_index", "passive", "long_timeout",
2246          "weight", "local numa");
2247
2248   /* Get list of bond interfaces */
2249   M (SW_MEMBER_INTERFACE_DUMP, mp);
2250   mp->sw_if_index = ntohl (sw_if_index);
2251   S (mp);
2252
2253   /* Use a control ping for synchronization */
2254   MPING (CONTROL_PING, mp_ping);
2255   S (mp_ping);
2256
2257   W (ret);
2258   return ret;
2259 }
2260
2261 static void vl_api_mpls_tunnel_add_del_reply_t_handler
2262   (vl_api_mpls_tunnel_add_del_reply_t * mp)
2263 {
2264   vat_main_t *vam = &vat_main;
2265   i32 retval = ntohl (mp->retval);
2266   if (vam->async_mode)
2267     {
2268       vam->async_errors += (retval < 0);
2269     }
2270   else
2271     {
2272       vam->retval = retval;
2273       vam->sw_if_index = ntohl (mp->sw_if_index);
2274       vam->result_ready = 1;
2275     }
2276   vam->regenerate_interface_table = 1;
2277 }
2278
2279 static void vl_api_mpls_tunnel_add_del_reply_t_handler_json
2280   (vl_api_mpls_tunnel_add_del_reply_t * mp)
2281 {
2282   vat_main_t *vam = &vat_main;
2283   vat_json_node_t node;
2284
2285   vat_json_init_object (&node);
2286   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2287   vat_json_object_add_uint (&node, "tunnel_sw_if_index",
2288                             ntohl (mp->sw_if_index));
2289
2290   vat_json_print (vam->ofp, &node);
2291   vat_json_free (&node);
2292
2293   vam->retval = ntohl (mp->retval);
2294   vam->result_ready = 1;
2295 }
2296
2297 static void vl_api_vxlan_add_del_tunnel_reply_t_handler
2298   (vl_api_vxlan_add_del_tunnel_reply_t * mp)
2299 {
2300   vat_main_t *vam = &vat_main;
2301   i32 retval = ntohl (mp->retval);
2302   if (vam->async_mode)
2303     {
2304       vam->async_errors += (retval < 0);
2305     }
2306   else
2307     {
2308       vam->retval = retval;
2309       vam->sw_if_index = ntohl (mp->sw_if_index);
2310       vam->result_ready = 1;
2311     }
2312   vam->regenerate_interface_table = 1;
2313 }
2314
2315 static void vl_api_vxlan_add_del_tunnel_reply_t_handler_json
2316   (vl_api_vxlan_add_del_tunnel_reply_t * mp)
2317 {
2318   vat_main_t *vam = &vat_main;
2319   vat_json_node_t node;
2320
2321   vat_json_init_object (&node);
2322   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2323   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
2324
2325   vat_json_print (vam->ofp, &node);
2326   vat_json_free (&node);
2327
2328   vam->retval = ntohl (mp->retval);
2329   vam->result_ready = 1;
2330 }
2331
2332 static void vl_api_vxlan_offload_rx_reply_t_handler
2333   (vl_api_vxlan_offload_rx_reply_t * mp)
2334 {
2335   vat_main_t *vam = &vat_main;
2336   i32 retval = ntohl (mp->retval);
2337   if (vam->async_mode)
2338     {
2339       vam->async_errors += (retval < 0);
2340     }
2341   else
2342     {
2343       vam->retval = retval;
2344       vam->result_ready = 1;
2345     }
2346 }
2347
2348 static void vl_api_vxlan_offload_rx_reply_t_handler_json
2349   (vl_api_vxlan_offload_rx_reply_t * mp)
2350 {
2351   vat_main_t *vam = &vat_main;
2352   vat_json_node_t node;
2353
2354   vat_json_init_object (&node);
2355   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2356
2357   vat_json_print (vam->ofp, &node);
2358   vat_json_free (&node);
2359
2360   vam->retval = ntohl (mp->retval);
2361   vam->result_ready = 1;
2362 }
2363
2364 static void vl_api_vxlan_gpe_add_del_tunnel_reply_t_handler
2365   (vl_api_vxlan_gpe_add_del_tunnel_reply_t * mp)
2366 {
2367   vat_main_t *vam = &vat_main;
2368   i32 retval = ntohl (mp->retval);
2369   if (vam->async_mode)
2370     {
2371       vam->async_errors += (retval < 0);
2372     }
2373   else
2374     {
2375       vam->retval = retval;
2376       vam->sw_if_index = ntohl (mp->sw_if_index);
2377       vam->result_ready = 1;
2378     }
2379   vam->regenerate_interface_table = 1;
2380 }
2381
2382 static void vl_api_vxlan_gpe_add_del_tunnel_reply_t_handler_json
2383   (vl_api_vxlan_gpe_add_del_tunnel_reply_t * mp)
2384 {
2385   vat_main_t *vam = &vat_main;
2386   vat_json_node_t node;
2387
2388   vat_json_init_object (&node);
2389   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2390   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
2391
2392   vat_json_print (vam->ofp, &node);
2393   vat_json_free (&node);
2394
2395   vam->retval = ntohl (mp->retval);
2396   vam->result_ready = 1;
2397 }
2398
2399 static void vl_api_gre_tunnel_add_del_reply_t_handler
2400   (vl_api_gre_tunnel_add_del_reply_t * mp)
2401 {
2402   vat_main_t *vam = &vat_main;
2403   i32 retval = ntohl (mp->retval);
2404   if (vam->async_mode)
2405     {
2406       vam->async_errors += (retval < 0);
2407     }
2408   else
2409     {
2410       vam->retval = retval;
2411       vam->sw_if_index = ntohl (mp->sw_if_index);
2412       vam->result_ready = 1;
2413     }
2414 }
2415
2416 static void vl_api_gre_tunnel_add_del_reply_t_handler_json
2417   (vl_api_gre_tunnel_add_del_reply_t * mp)
2418 {
2419   vat_main_t *vam = &vat_main;
2420   vat_json_node_t node;
2421
2422   vat_json_init_object (&node);
2423   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2424   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
2425
2426   vat_json_print (vam->ofp, &node);
2427   vat_json_free (&node);
2428
2429   vam->retval = ntohl (mp->retval);
2430   vam->result_ready = 1;
2431 }
2432
2433 static void vl_api_create_vhost_user_if_reply_t_handler
2434   (vl_api_create_vhost_user_if_reply_t * mp)
2435 {
2436   vat_main_t *vam = &vat_main;
2437   i32 retval = ntohl (mp->retval);
2438   if (vam->async_mode)
2439     {
2440       vam->async_errors += (retval < 0);
2441     }
2442   else
2443     {
2444       vam->retval = retval;
2445       vam->sw_if_index = ntohl (mp->sw_if_index);
2446       vam->result_ready = 1;
2447     }
2448   vam->regenerate_interface_table = 1;
2449 }
2450
2451 static void vl_api_create_vhost_user_if_reply_t_handler_json
2452   (vl_api_create_vhost_user_if_reply_t * mp)
2453 {
2454   vat_main_t *vam = &vat_main;
2455   vat_json_node_t node;
2456
2457   vat_json_init_object (&node);
2458   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2459   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
2460
2461   vat_json_print (vam->ofp, &node);
2462   vat_json_free (&node);
2463
2464   vam->retval = ntohl (mp->retval);
2465   vam->result_ready = 1;
2466 }
2467
2468 static void vl_api_ip_address_details_t_handler
2469   (vl_api_ip_address_details_t * mp)
2470 {
2471   vat_main_t *vam = &vat_main;
2472   static ip_address_details_t empty_ip_address_details = { {0} };
2473   ip_address_details_t *address = NULL;
2474   ip_details_t *current_ip_details = NULL;
2475   ip_details_t *details = NULL;
2476
2477   details = vam->ip_details_by_sw_if_index[vam->is_ipv6];
2478
2479   if (!details || vam->current_sw_if_index >= vec_len (details)
2480       || !details[vam->current_sw_if_index].present)
2481     {
2482       errmsg ("ip address details arrived but not stored");
2483       errmsg ("ip_dump should be called first");
2484       return;
2485     }
2486
2487   current_ip_details = vec_elt_at_index (details, vam->current_sw_if_index);
2488
2489 #define addresses (current_ip_details->addr)
2490
2491   vec_validate_init_empty (addresses, vec_len (addresses),
2492                            empty_ip_address_details);
2493
2494   address = vec_elt_at_index (addresses, vec_len (addresses) - 1);
2495
2496   clib_memcpy (&address->ip, &mp->prefix.address.un, sizeof (address->ip));
2497   address->prefix_length = mp->prefix.len;
2498 #undef addresses
2499 }
2500
2501 static void vl_api_ip_address_details_t_handler_json
2502   (vl_api_ip_address_details_t * mp)
2503 {
2504   vat_main_t *vam = &vat_main;
2505   vat_json_node_t *node = NULL;
2506
2507   if (VAT_JSON_ARRAY != vam->json_tree.type)
2508     {
2509       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
2510       vat_json_init_array (&vam->json_tree);
2511     }
2512   node = vat_json_array_add (&vam->json_tree);
2513
2514   vat_json_init_object (node);
2515   vat_json_object_add_prefix (node, &mp->prefix);
2516 }
2517
2518 static void
2519 vl_api_ip_details_t_handler (vl_api_ip_details_t * mp)
2520 {
2521   vat_main_t *vam = &vat_main;
2522   static ip_details_t empty_ip_details = { 0 };
2523   ip_details_t *ip = NULL;
2524   u32 sw_if_index = ~0;
2525
2526   sw_if_index = ntohl (mp->sw_if_index);
2527
2528   vec_validate_init_empty (vam->ip_details_by_sw_if_index[vam->is_ipv6],
2529                            sw_if_index, empty_ip_details);
2530
2531   ip = vec_elt_at_index (vam->ip_details_by_sw_if_index[vam->is_ipv6],
2532                          sw_if_index);
2533
2534   ip->present = 1;
2535 }
2536
2537 static void
2538 vl_api_ip_details_t_handler_json (vl_api_ip_details_t * mp)
2539 {
2540   vat_main_t *vam = &vat_main;
2541
2542   if (VAT_JSON_ARRAY != vam->json_tree.type)
2543     {
2544       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
2545       vat_json_init_array (&vam->json_tree);
2546     }
2547   vat_json_array_add_uint (&vam->json_tree,
2548                            clib_net_to_host_u32 (mp->sw_if_index));
2549 }
2550
2551 static void vl_api_get_first_msg_id_reply_t_handler
2552   (vl_api_get_first_msg_id_reply_t * mp)
2553 {
2554   vat_main_t *vam = &vat_main;
2555   i32 retval = ntohl (mp->retval);
2556
2557   if (vam->async_mode)
2558     {
2559       vam->async_errors += (retval < 0);
2560     }
2561   else
2562     {
2563       vam->retval = retval;
2564       vam->result_ready = 1;
2565     }
2566   if (retval >= 0)
2567     {
2568       errmsg ("first message id %d", ntohs (mp->first_msg_id));
2569     }
2570 }
2571
2572 static void vl_api_get_first_msg_id_reply_t_handler_json
2573   (vl_api_get_first_msg_id_reply_t * mp)
2574 {
2575   vat_main_t *vam = &vat_main;
2576   vat_json_node_t node;
2577
2578   vat_json_init_object (&node);
2579   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2580   vat_json_object_add_uint (&node, "first_msg_id",
2581                             (uint) ntohs (mp->first_msg_id));
2582
2583   vat_json_print (vam->ofp, &node);
2584   vat_json_free (&node);
2585
2586   vam->retval = ntohl (mp->retval);
2587   vam->result_ready = 1;
2588 }
2589
2590 static void vl_api_get_node_graph_reply_t_handler
2591   (vl_api_get_node_graph_reply_t * mp)
2592 {
2593   vat_main_t *vam = &vat_main;
2594   i32 retval = ntohl (mp->retval);
2595   u8 *pvt_copy, *reply;
2596   void *oldheap;
2597   vlib_node_t *node;
2598   int i;
2599
2600   if (vam->async_mode)
2601     {
2602       vam->async_errors += (retval < 0);
2603     }
2604   else
2605     {
2606       vam->retval = retval;
2607       vam->result_ready = 1;
2608     }
2609
2610   /* "Should never happen..." */
2611   if (retval != 0)
2612     return;
2613
2614   reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
2615   pvt_copy = vec_dup (reply);
2616
2617   /* Toss the shared-memory original... */
2618   oldheap = vl_msg_push_heap ();
2619
2620   vec_free (reply);
2621
2622   vl_msg_pop_heap (oldheap);
2623
2624   if (vam->graph_nodes)
2625     {
2626       hash_free (vam->graph_node_index_by_name);
2627
2628       for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
2629         {
2630           node = vam->graph_nodes[0][i];
2631           vec_free (node->name);
2632           vec_free (node->next_nodes);
2633           vec_free (node);
2634         }
2635       vec_free (vam->graph_nodes[0]);
2636       vec_free (vam->graph_nodes);
2637     }
2638
2639   vam->graph_node_index_by_name = hash_create_string (0, sizeof (uword));
2640   vam->graph_nodes = vlib_node_unserialize (pvt_copy);
2641   vec_free (pvt_copy);
2642
2643   for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
2644     {
2645       node = vam->graph_nodes[0][i];
2646       hash_set_mem (vam->graph_node_index_by_name, node->name, i);
2647     }
2648 }
2649
2650 static void vl_api_get_node_graph_reply_t_handler_json
2651   (vl_api_get_node_graph_reply_t * mp)
2652 {
2653   vat_main_t *vam = &vat_main;
2654   void *oldheap;
2655   vat_json_node_t node;
2656   u8 *reply;
2657
2658   /* $$$$ make this real? */
2659   vat_json_init_object (&node);
2660   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2661   vat_json_object_add_uint (&node, "reply_in_shmem", mp->reply_in_shmem);
2662
2663   reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
2664
2665   /* Toss the shared-memory original... */
2666   oldheap = vl_msg_push_heap ();
2667
2668   vec_free (reply);
2669
2670   vl_msg_pop_heap (oldheap);
2671
2672   vat_json_print (vam->ofp, &node);
2673   vat_json_free (&node);
2674
2675   vam->retval = ntohl (mp->retval);
2676   vam->result_ready = 1;
2677 }
2678
2679 static u8 *
2680 format_policer_type (u8 * s, va_list * va)
2681 {
2682   u32 i = va_arg (*va, u32);
2683
2684   if (i == SSE2_QOS_POLICER_TYPE_1R2C)
2685     s = format (s, "1r2c");
2686   else if (i == SSE2_QOS_POLICER_TYPE_1R3C_RFC_2697)
2687     s = format (s, "1r3c");
2688   else if (i == SSE2_QOS_POLICER_TYPE_2R3C_RFC_2698)
2689     s = format (s, "2r3c-2698");
2690   else if (i == SSE2_QOS_POLICER_TYPE_2R3C_RFC_4115)
2691     s = format (s, "2r3c-4115");
2692   else if (i == SSE2_QOS_POLICER_TYPE_2R3C_RFC_MEF5CF1)
2693     s = format (s, "2r3c-mef5cf1");
2694   else
2695     s = format (s, "ILLEGAL");
2696   return s;
2697 }
2698
2699 static u8 *
2700 format_policer_rate_type (u8 * s, va_list * va)
2701 {
2702   u32 i = va_arg (*va, u32);
2703
2704   if (i == SSE2_QOS_RATE_KBPS)
2705     s = format (s, "kbps");
2706   else if (i == SSE2_QOS_RATE_PPS)
2707     s = format (s, "pps");
2708   else
2709     s = format (s, "ILLEGAL");
2710   return s;
2711 }
2712
2713 static u8 *
2714 format_policer_round_type (u8 * s, va_list * va)
2715 {
2716   u32 i = va_arg (*va, u32);
2717
2718   if (i == SSE2_QOS_ROUND_TO_CLOSEST)
2719     s = format (s, "closest");
2720   else if (i == SSE2_QOS_ROUND_TO_UP)
2721     s = format (s, "up");
2722   else if (i == SSE2_QOS_ROUND_TO_DOWN)
2723     s = format (s, "down");
2724   else
2725     s = format (s, "ILLEGAL");
2726   return s;
2727 }
2728
2729 static u8 *
2730 format_policer_action_type (u8 * s, va_list * va)
2731 {
2732   u32 i = va_arg (*va, u32);
2733
2734   if (i == SSE2_QOS_ACTION_DROP)
2735     s = format (s, "drop");
2736   else if (i == SSE2_QOS_ACTION_TRANSMIT)
2737     s = format (s, "transmit");
2738   else if (i == SSE2_QOS_ACTION_MARK_AND_TRANSMIT)
2739     s = format (s, "mark-and-transmit");
2740   else
2741     s = format (s, "ILLEGAL");
2742   return s;
2743 }
2744
2745 static u8 *
2746 format_dscp (u8 * s, va_list * va)
2747 {
2748   u32 i = va_arg (*va, u32);
2749   char *t = 0;
2750
2751   switch (i)
2752     {
2753 #define _(v,f,str) case VNET_DSCP_##f: t = str; break;
2754       foreach_vnet_dscp
2755 #undef _
2756     default:
2757       return format (s, "ILLEGAL");
2758     }
2759   s = format (s, "%s", t);
2760   return s;
2761 }
2762
2763 static void
2764 vl_api_policer_details_t_handler (vl_api_policer_details_t * mp)
2765 {
2766   vat_main_t *vam = &vat_main;
2767   u8 *conform_dscp_str, *exceed_dscp_str, *violate_dscp_str;
2768
2769   if (mp->conform_action.type == SSE2_QOS_ACTION_API_MARK_AND_TRANSMIT)
2770     conform_dscp_str = format (0, "%U", format_dscp, mp->conform_action.dscp);
2771   else
2772     conform_dscp_str = format (0, "");
2773
2774   if (mp->exceed_action.type == SSE2_QOS_ACTION_API_MARK_AND_TRANSMIT)
2775     exceed_dscp_str = format (0, "%U", format_dscp, mp->exceed_action.dscp);
2776   else
2777     exceed_dscp_str = format (0, "");
2778
2779   if (mp->violate_action.type == SSE2_QOS_ACTION_API_MARK_AND_TRANSMIT)
2780     violate_dscp_str = format (0, "%U", format_dscp, mp->violate_action.dscp);
2781   else
2782     violate_dscp_str = format (0, "");
2783
2784   print (vam->ofp, "Name \"%s\", type %U, cir %u, eir %u, cb %u, eb %u, "
2785          "rate type %U, round type %U, %s rate, %s color-aware, "
2786          "cir %u tok/period, pir %u tok/period, scale %u, cur lim %u, "
2787          "cur bkt %u, ext lim %u, ext bkt %u, last update %llu"
2788          "conform action %U%s, exceed action %U%s, violate action %U%s",
2789          mp->name,
2790          format_policer_type, mp->type,
2791          ntohl (mp->cir),
2792          ntohl (mp->eir),
2793          clib_net_to_host_u64 (mp->cb),
2794          clib_net_to_host_u64 (mp->eb),
2795          format_policer_rate_type, mp->rate_type,
2796          format_policer_round_type, mp->round_type,
2797          mp->single_rate ? "single" : "dual",
2798          mp->color_aware ? "is" : "not",
2799          ntohl (mp->cir_tokens_per_period),
2800          ntohl (mp->pir_tokens_per_period),
2801          ntohl (mp->scale),
2802          ntohl (mp->current_limit),
2803          ntohl (mp->current_bucket),
2804          ntohl (mp->extended_limit),
2805          ntohl (mp->extended_bucket),
2806          clib_net_to_host_u64 (mp->last_update_time),
2807          format_policer_action_type, mp->conform_action.type,
2808          conform_dscp_str,
2809          format_policer_action_type, mp->exceed_action.type,
2810          exceed_dscp_str,
2811          format_policer_action_type, mp->violate_action.type,
2812          violate_dscp_str);
2813
2814   vec_free (conform_dscp_str);
2815   vec_free (exceed_dscp_str);
2816   vec_free (violate_dscp_str);
2817 }
2818
2819 static void vl_api_policer_details_t_handler_json
2820   (vl_api_policer_details_t * mp)
2821 {
2822   vat_main_t *vam = &vat_main;
2823   vat_json_node_t *node;
2824   u8 *rate_type_str, *round_type_str, *type_str;
2825   u8 *conform_action_str, *exceed_action_str, *violate_action_str;
2826
2827   rate_type_str = format (0, "%U", format_policer_rate_type, mp->rate_type);
2828   round_type_str =
2829     format (0, "%U", format_policer_round_type, mp->round_type);
2830   type_str = format (0, "%U", format_policer_type, mp->type);
2831   conform_action_str = format (0, "%U", format_policer_action_type,
2832                                mp->conform_action.type);
2833   exceed_action_str = format (0, "%U", format_policer_action_type,
2834                               mp->exceed_action.type);
2835   violate_action_str = format (0, "%U", format_policer_action_type,
2836                                mp->violate_action.type);
2837
2838   if (VAT_JSON_ARRAY != vam->json_tree.type)
2839     {
2840       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
2841       vat_json_init_array (&vam->json_tree);
2842     }
2843   node = vat_json_array_add (&vam->json_tree);
2844
2845   vat_json_init_object (node);
2846   vat_json_object_add_string_copy (node, "name", mp->name);
2847   vat_json_object_add_uint (node, "cir", ntohl (mp->cir));
2848   vat_json_object_add_uint (node, "eir", ntohl (mp->eir));
2849   vat_json_object_add_uint (node, "cb", clib_net_to_host_u64 (mp->cb));
2850   vat_json_object_add_uint (node, "eb", clib_net_to_host_u64 (mp->eb));
2851   vat_json_object_add_string_copy (node, "rate_type", rate_type_str);
2852   vat_json_object_add_string_copy (node, "round_type", round_type_str);
2853   vat_json_object_add_string_copy (node, "type", type_str);
2854   vat_json_object_add_uint (node, "single_rate", mp->single_rate);
2855   vat_json_object_add_uint (node, "color_aware", mp->color_aware);
2856   vat_json_object_add_uint (node, "scale", ntohl (mp->scale));
2857   vat_json_object_add_uint (node, "cir_tokens_per_period",
2858                             ntohl (mp->cir_tokens_per_period));
2859   vat_json_object_add_uint (node, "eir_tokens_per_period",
2860                             ntohl (mp->pir_tokens_per_period));
2861   vat_json_object_add_uint (node, "current_limit", ntohl (mp->current_limit));
2862   vat_json_object_add_uint (node, "current_bucket",
2863                             ntohl (mp->current_bucket));
2864   vat_json_object_add_uint (node, "extended_limit",
2865                             ntohl (mp->extended_limit));
2866   vat_json_object_add_uint (node, "extended_bucket",
2867                             ntohl (mp->extended_bucket));
2868   vat_json_object_add_uint (node, "last_update_time",
2869                             ntohl (mp->last_update_time));
2870   vat_json_object_add_string_copy (node, "conform_action",
2871                                    conform_action_str);
2872   if (mp->conform_action.type == SSE2_QOS_ACTION_API_MARK_AND_TRANSMIT)
2873     {
2874       u8 *dscp_str = format (0, "%U", format_dscp, mp->conform_action.dscp);
2875       vat_json_object_add_string_copy (node, "conform_dscp", dscp_str);
2876       vec_free (dscp_str);
2877     }
2878   vat_json_object_add_string_copy (node, "exceed_action", exceed_action_str);
2879   if (mp->exceed_action.type == SSE2_QOS_ACTION_API_MARK_AND_TRANSMIT)
2880     {
2881       u8 *dscp_str = format (0, "%U", format_dscp, mp->exceed_action.dscp);
2882       vat_json_object_add_string_copy (node, "exceed_dscp", dscp_str);
2883       vec_free (dscp_str);
2884     }
2885   vat_json_object_add_string_copy (node, "violate_action",
2886                                    violate_action_str);
2887   if (mp->violate_action.type == SSE2_QOS_ACTION_API_MARK_AND_TRANSMIT)
2888     {
2889       u8 *dscp_str = format (0, "%U", format_dscp, mp->violate_action.dscp);
2890       vat_json_object_add_string_copy (node, "violate_dscp", dscp_str);
2891       vec_free (dscp_str);
2892     }
2893
2894   vec_free (rate_type_str);
2895   vec_free (round_type_str);
2896   vec_free (type_str);
2897   vec_free (conform_action_str);
2898   vec_free (exceed_action_str);
2899   vec_free (violate_action_str);
2900 }
2901
2902 static void
2903 vl_api_classify_table_ids_reply_t_handler (vl_api_classify_table_ids_reply_t *
2904                                            mp)
2905 {
2906   vat_main_t *vam = &vat_main;
2907   int i, count = ntohl (mp->count);
2908
2909   if (count > 0)
2910     print (vam->ofp, "classify table ids (%d) : ", count);
2911   for (i = 0; i < count; i++)
2912     {
2913       print (vam->ofp, "%d", ntohl (mp->ids[i]));
2914       print (vam->ofp, (i < count - 1) ? "," : "");
2915     }
2916   vam->retval = ntohl (mp->retval);
2917   vam->result_ready = 1;
2918 }
2919
2920 static void
2921   vl_api_classify_table_ids_reply_t_handler_json
2922   (vl_api_classify_table_ids_reply_t * mp)
2923 {
2924   vat_main_t *vam = &vat_main;
2925   int i, count = ntohl (mp->count);
2926
2927   if (count > 0)
2928     {
2929       vat_json_node_t node;
2930
2931       vat_json_init_object (&node);
2932       for (i = 0; i < count; i++)
2933         {
2934           vat_json_object_add_uint (&node, "table_id", ntohl (mp->ids[i]));
2935         }
2936       vat_json_print (vam->ofp, &node);
2937       vat_json_free (&node);
2938     }
2939   vam->retval = ntohl (mp->retval);
2940   vam->result_ready = 1;
2941 }
2942
2943 static void
2944   vl_api_classify_table_by_interface_reply_t_handler
2945   (vl_api_classify_table_by_interface_reply_t * mp)
2946 {
2947   vat_main_t *vam = &vat_main;
2948   u32 table_id;
2949
2950   table_id = ntohl (mp->l2_table_id);
2951   if (table_id != ~0)
2952     print (vam->ofp, "l2 table id : %d", table_id);
2953   else
2954     print (vam->ofp, "l2 table id : No input ACL tables configured");
2955   table_id = ntohl (mp->ip4_table_id);
2956   if (table_id != ~0)
2957     print (vam->ofp, "ip4 table id : %d", table_id);
2958   else
2959     print (vam->ofp, "ip4 table id : No input ACL tables configured");
2960   table_id = ntohl (mp->ip6_table_id);
2961   if (table_id != ~0)
2962     print (vam->ofp, "ip6 table id : %d", table_id);
2963   else
2964     print (vam->ofp, "ip6 table id : No input ACL tables configured");
2965   vam->retval = ntohl (mp->retval);
2966   vam->result_ready = 1;
2967 }
2968
2969 static void
2970   vl_api_classify_table_by_interface_reply_t_handler_json
2971   (vl_api_classify_table_by_interface_reply_t * mp)
2972 {
2973   vat_main_t *vam = &vat_main;
2974   vat_json_node_t node;
2975
2976   vat_json_init_object (&node);
2977
2978   vat_json_object_add_int (&node, "l2_table_id", ntohl (mp->l2_table_id));
2979   vat_json_object_add_int (&node, "ip4_table_id", ntohl (mp->ip4_table_id));
2980   vat_json_object_add_int (&node, "ip6_table_id", ntohl (mp->ip6_table_id));
2981
2982   vat_json_print (vam->ofp, &node);
2983   vat_json_free (&node);
2984
2985   vam->retval = ntohl (mp->retval);
2986   vam->result_ready = 1;
2987 }
2988
2989 static void vl_api_policer_add_del_reply_t_handler
2990   (vl_api_policer_add_del_reply_t * mp)
2991 {
2992   vat_main_t *vam = &vat_main;
2993   i32 retval = ntohl (mp->retval);
2994   if (vam->async_mode)
2995     {
2996       vam->async_errors += (retval < 0);
2997     }
2998   else
2999     {
3000       vam->retval = retval;
3001       vam->result_ready = 1;
3002       if (retval == 0 && mp->policer_index != 0xFFFFFFFF)
3003         /*
3004          * Note: this is just barely thread-safe, depends on
3005          * the main thread spinning waiting for an answer...
3006          */
3007         errmsg ("policer index %d", ntohl (mp->policer_index));
3008     }
3009 }
3010
3011 static void vl_api_policer_add_del_reply_t_handler_json
3012   (vl_api_policer_add_del_reply_t * mp)
3013 {
3014   vat_main_t *vam = &vat_main;
3015   vat_json_node_t node;
3016
3017   vat_json_init_object (&node);
3018   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
3019   vat_json_object_add_uint (&node, "policer_index",
3020                             ntohl (mp->policer_index));
3021
3022   vat_json_print (vam->ofp, &node);
3023   vat_json_free (&node);
3024
3025   vam->retval = ntohl (mp->retval);
3026   vam->result_ready = 1;
3027 }
3028
3029 /* Format hex dump. */
3030 u8 *
3031 format_hex_bytes (u8 * s, va_list * va)
3032 {
3033   u8 *bytes = va_arg (*va, u8 *);
3034   int n_bytes = va_arg (*va, int);
3035   uword i;
3036
3037   /* Print short or long form depending on byte count. */
3038   uword short_form = n_bytes <= 32;
3039   u32 indent = format_get_indent (s);
3040
3041   if (n_bytes == 0)
3042     return s;
3043
3044   for (i = 0; i < n_bytes; i++)
3045     {
3046       if (!short_form && (i % 32) == 0)
3047         s = format (s, "%08x: ", i);
3048       s = format (s, "%02x", bytes[i]);
3049       if (!short_form && ((i + 1) % 32) == 0 && (i + 1) < n_bytes)
3050         s = format (s, "\n%U", format_white_space, indent);
3051     }
3052
3053   return s;
3054 }
3055
3056 static void
3057 vl_api_classify_table_info_reply_t_handler (vl_api_classify_table_info_reply_t
3058                                             * mp)
3059 {
3060   vat_main_t *vam = &vat_main;
3061   i32 retval = ntohl (mp->retval);
3062   if (retval == 0)
3063     {
3064       print (vam->ofp, "classify table info :");
3065       print (vam->ofp, "sessions: %d nexttbl: %d nextnode: %d",
3066              ntohl (mp->active_sessions), ntohl (mp->next_table_index),
3067              ntohl (mp->miss_next_index));
3068       print (vam->ofp, "nbuckets: %d skip: %d match: %d",
3069              ntohl (mp->nbuckets), ntohl (mp->skip_n_vectors),
3070              ntohl (mp->match_n_vectors));
3071       print (vam->ofp, "mask: %U", format_hex_bytes, mp->mask,
3072              ntohl (mp->mask_length));
3073     }
3074   vam->retval = retval;
3075   vam->result_ready = 1;
3076 }
3077
3078 static void
3079   vl_api_classify_table_info_reply_t_handler_json
3080   (vl_api_classify_table_info_reply_t * mp)
3081 {
3082   vat_main_t *vam = &vat_main;
3083   vat_json_node_t node;
3084
3085   i32 retval = ntohl (mp->retval);
3086   if (retval == 0)
3087     {
3088       vat_json_init_object (&node);
3089
3090       vat_json_object_add_int (&node, "sessions",
3091                                ntohl (mp->active_sessions));
3092       vat_json_object_add_int (&node, "nexttbl",
3093                                ntohl (mp->next_table_index));
3094       vat_json_object_add_int (&node, "nextnode",
3095                                ntohl (mp->miss_next_index));
3096       vat_json_object_add_int (&node, "nbuckets", ntohl (mp->nbuckets));
3097       vat_json_object_add_int (&node, "skip", ntohl (mp->skip_n_vectors));
3098       vat_json_object_add_int (&node, "match", ntohl (mp->match_n_vectors));
3099       u8 *s = format (0, "%U%c", format_hex_bytes, mp->mask,
3100                       ntohl (mp->mask_length), 0);
3101       vat_json_object_add_string_copy (&node, "mask", s);
3102
3103       vat_json_print (vam->ofp, &node);
3104       vat_json_free (&node);
3105     }
3106   vam->retval = ntohl (mp->retval);
3107   vam->result_ready = 1;
3108 }
3109
3110 static void
3111 vl_api_classify_session_details_t_handler (vl_api_classify_session_details_t *
3112                                            mp)
3113 {
3114   vat_main_t *vam = &vat_main;
3115
3116   print (vam->ofp, "next_index: %d advance: %d opaque: %d ",
3117          ntohl (mp->hit_next_index), ntohl (mp->advance),
3118          ntohl (mp->opaque_index));
3119   print (vam->ofp, "mask: %U", format_hex_bytes, mp->match,
3120          ntohl (mp->match_length));
3121 }
3122
3123 static void
3124   vl_api_classify_session_details_t_handler_json
3125   (vl_api_classify_session_details_t * mp)
3126 {
3127   vat_main_t *vam = &vat_main;
3128   vat_json_node_t *node = NULL;
3129
3130   if (VAT_JSON_ARRAY != vam->json_tree.type)
3131     {
3132       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
3133       vat_json_init_array (&vam->json_tree);
3134     }
3135   node = vat_json_array_add (&vam->json_tree);
3136
3137   vat_json_init_object (node);
3138   vat_json_object_add_int (node, "next_index", ntohl (mp->hit_next_index));
3139   vat_json_object_add_int (node, "advance", ntohl (mp->advance));
3140   vat_json_object_add_int (node, "opaque", ntohl (mp->opaque_index));
3141   u8 *s =
3142     format (0, "%U%c", format_hex_bytes, mp->match, ntohl (mp->match_length),
3143             0);
3144   vat_json_object_add_string_copy (node, "match", s);
3145 }
3146
3147 static void vl_api_pg_create_interface_reply_t_handler
3148   (vl_api_pg_create_interface_reply_t * mp)
3149 {
3150   vat_main_t *vam = &vat_main;
3151
3152   vam->retval = ntohl (mp->retval);
3153   vam->result_ready = 1;
3154 }
3155
3156 static void vl_api_pg_create_interface_reply_t_handler_json
3157   (vl_api_pg_create_interface_reply_t * mp)
3158 {
3159   vat_main_t *vam = &vat_main;
3160   vat_json_node_t node;
3161
3162   i32 retval = ntohl (mp->retval);
3163   if (retval == 0)
3164     {
3165       vat_json_init_object (&node);
3166
3167       vat_json_object_add_int (&node, "sw_if_index", ntohl (mp->sw_if_index));
3168
3169       vat_json_print (vam->ofp, &node);
3170       vat_json_free (&node);
3171     }
3172   vam->retval = ntohl (mp->retval);
3173   vam->result_ready = 1;
3174 }
3175
3176 static void vl_api_policer_classify_details_t_handler
3177   (vl_api_policer_classify_details_t * mp)
3178 {
3179   vat_main_t *vam = &vat_main;
3180
3181   print (vam->ofp, "%10d%20d", ntohl (mp->sw_if_index),
3182          ntohl (mp->table_index));
3183 }
3184
3185 static void vl_api_policer_classify_details_t_handler_json
3186   (vl_api_policer_classify_details_t * mp)
3187 {
3188   vat_main_t *vam = &vat_main;
3189   vat_json_node_t *node;
3190
3191   if (VAT_JSON_ARRAY != vam->json_tree.type)
3192     {
3193       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
3194       vat_json_init_array (&vam->json_tree);
3195     }
3196   node = vat_json_array_add (&vam->json_tree);
3197
3198   vat_json_init_object (node);
3199   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
3200   vat_json_object_add_uint (node, "table_index", ntohl (mp->table_index));
3201 }
3202
3203 static void vl_api_flow_classify_details_t_handler
3204   (vl_api_flow_classify_details_t * mp)
3205 {
3206   vat_main_t *vam = &vat_main;
3207
3208   print (vam->ofp, "%10d%20d", ntohl (mp->sw_if_index),
3209          ntohl (mp->table_index));
3210 }
3211
3212 static void vl_api_flow_classify_details_t_handler_json
3213   (vl_api_flow_classify_details_t * mp)
3214 {
3215   vat_main_t *vam = &vat_main;
3216   vat_json_node_t *node;
3217
3218   if (VAT_JSON_ARRAY != vam->json_tree.type)
3219     {
3220       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
3221       vat_json_init_array (&vam->json_tree);
3222     }
3223   node = vat_json_array_add (&vam->json_tree);
3224
3225   vat_json_init_object (node);
3226   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
3227   vat_json_object_add_uint (node, "table_index", ntohl (mp->table_index));
3228 }
3229
3230 /*
3231  * Generate boilerplate reply handlers, which
3232  * dig the return value out of the xxx_reply_t API message,
3233  * stick it into vam->retval, and set vam->result_ready
3234  *
3235  * Could also do this by pointing N message decode slots at
3236  * a single function, but that could break in subtle ways.
3237  */
3238
3239 #define foreach_standard_reply_retval_handler           \
3240 _(sw_interface_set_flags_reply)                         \
3241 _(sw_interface_add_del_address_reply)                   \
3242 _(sw_interface_set_rx_mode_reply)                       \
3243 _(sw_interface_set_rx_placement_reply)                  \
3244 _(sw_interface_set_table_reply)                         \
3245 _(sw_interface_set_mpls_enable_reply)                   \
3246 _(sw_interface_set_vpath_reply)                         \
3247 _(sw_interface_set_vxlan_bypass_reply)                  \
3248 _(sw_interface_set_vxlan_gpe_bypass_reply)              \
3249 _(sw_interface_set_l2_bridge_reply)                     \
3250 _(sw_interface_set_bond_weight_reply)                   \
3251 _(bridge_domain_add_del_reply)                          \
3252 _(sw_interface_set_l2_xconnect_reply)                   \
3253 _(l2fib_add_del_reply)                                  \
3254 _(l2fib_flush_int_reply)                                \
3255 _(l2fib_flush_bd_reply)                                 \
3256 _(ip_route_add_del_reply)                               \
3257 _(ip_table_add_del_reply)                               \
3258 _(ip_table_replace_begin_reply)                         \
3259 _(ip_table_flush_reply)                                 \
3260 _(ip_table_replace_end_reply)                           \
3261 _(ip_mroute_add_del_reply)                              \
3262 _(mpls_route_add_del_reply)                             \
3263 _(mpls_table_add_del_reply)                             \
3264 _(mpls_ip_bind_unbind_reply)                            \
3265 _(bier_route_add_del_reply)                             \
3266 _(bier_table_add_del_reply)                             \
3267 _(sw_interface_set_unnumbered_reply)                    \
3268 _(set_ip_flow_hash_reply)                               \
3269 _(sw_interface_ip6_enable_disable_reply)                \
3270 _(l2_patch_add_del_reply)                               \
3271 _(sr_mpls_policy_add_reply)                             \
3272 _(sr_mpls_policy_mod_reply)                             \
3273 _(sr_mpls_policy_del_reply)                             \
3274 _(sr_policy_add_reply)                                  \
3275 _(sr_policy_mod_reply)                                  \
3276 _(sr_policy_del_reply)                                  \
3277 _(sr_localsid_add_del_reply)                            \
3278 _(sr_steering_add_del_reply)                            \
3279 _(classify_add_del_session_reply)                       \
3280 _(classify_set_interface_ip_table_reply)                \
3281 _(classify_set_interface_l2_tables_reply)               \
3282 _(l2_fib_clear_table_reply)                             \
3283 _(l2_interface_efp_filter_reply)                        \
3284 _(l2_interface_vlan_tag_rewrite_reply)                  \
3285 _(modify_vhost_user_if_reply)                           \
3286 _(delete_vhost_user_if_reply)                           \
3287 _(want_l2_macs_events_reply)                            \
3288 _(input_acl_set_interface_reply)                        \
3289 _(ipsec_spd_add_del_reply)                              \
3290 _(ipsec_interface_add_del_spd_reply)                    \
3291 _(ipsec_spd_entry_add_del_reply)                        \
3292 _(ipsec_sad_entry_add_del_reply)                        \
3293 _(ipsec_tunnel_if_add_del_reply)                        \
3294 _(ipsec_tunnel_if_set_sa_reply)                         \
3295 _(delete_loopback_reply)                                \
3296 _(bd_ip_mac_add_del_reply)                              \
3297 _(bd_ip_mac_flush_reply)                                \
3298 _(want_interface_events_reply)                          \
3299 _(cop_interface_enable_disable_reply)                   \
3300 _(cop_whitelist_enable_disable_reply)                   \
3301 _(sw_interface_clear_stats_reply)                       \
3302 _(ioam_enable_reply)                                    \
3303 _(ioam_disable_reply)                                   \
3304 _(af_packet_delete_reply)                               \
3305 _(policer_classify_set_interface_reply)                 \
3306 _(set_ipfix_exporter_reply)                             \
3307 _(set_ipfix_classify_stream_reply)                      \
3308 _(ipfix_classify_table_add_del_reply)                   \
3309 _(flow_classify_set_interface_reply)                    \
3310 _(sw_interface_span_enable_disable_reply)               \
3311 _(pg_capture_reply)                                     \
3312 _(pg_enable_disable_reply)                              \
3313 _(pg_interface_enable_disable_coalesce_reply)           \
3314 _(ip_source_and_port_range_check_add_del_reply)         \
3315 _(ip_source_and_port_range_check_interface_add_del_reply)\
3316 _(delete_subif_reply)                                   \
3317 _(l2_interface_pbb_tag_rewrite_reply)                   \
3318 _(set_punt_reply)                                       \
3319 _(feature_enable_disable_reply)                         \
3320 _(feature_gso_enable_disable_reply)                     \
3321 _(sw_interface_tag_add_del_reply)                       \
3322 _(sw_interface_add_del_mac_address_reply)               \
3323 _(hw_interface_set_mtu_reply)                           \
3324 _(p2p_ethernet_add_reply)                               \
3325 _(p2p_ethernet_del_reply)                               \
3326 _(tcp_configure_src_addresses_reply)                    \
3327 _(session_rule_add_del_reply)                           \
3328 _(ip_container_proxy_add_del_reply)                     \
3329 _(output_acl_set_interface_reply)                       \
3330 _(qos_record_enable_disable_reply)                      \
3331 _(flow_add_reply)
3332
3333 #define _(n)                                    \
3334     static void vl_api_##n##_t_handler          \
3335     (vl_api_##n##_t * mp)                       \
3336     {                                           \
3337         vat_main_t * vam = &vat_main;           \
3338         i32 retval = ntohl(mp->retval);         \
3339         if (vam->async_mode) {                  \
3340             vam->async_errors += (retval < 0);  \
3341         } else {                                \
3342             vam->retval = retval;               \
3343             vam->result_ready = 1;              \
3344         }                                       \
3345     }
3346 foreach_standard_reply_retval_handler;
3347 #undef _
3348
3349 #define _(n)                                    \
3350     static void vl_api_##n##_t_handler_json     \
3351     (vl_api_##n##_t * mp)                       \
3352     {                                           \
3353         vat_main_t * vam = &vat_main;           \
3354         vat_json_node_t node;                   \
3355         vat_json_init_object(&node);            \
3356         vat_json_object_add_int(&node, "retval", ntohl(mp->retval));    \
3357         vat_json_print(vam->ofp, &node);        \
3358         vam->retval = ntohl(mp->retval);        \
3359         vam->result_ready = 1;                  \
3360     }
3361 foreach_standard_reply_retval_handler;
3362 #undef _
3363
3364 /*
3365  * Table of message reply handlers, must include boilerplate handlers
3366  * we just generated
3367  */
3368
3369 #define foreach_vpe_api_reply_msg                                       \
3370 _(CREATE_LOOPBACK_REPLY, create_loopback_reply)                         \
3371 _(CREATE_LOOPBACK_INSTANCE_REPLY, create_loopback_instance_reply)       \
3372 _(SW_INTERFACE_DETAILS, sw_interface_details)                           \
3373 _(SW_INTERFACE_SET_FLAGS_REPLY, sw_interface_set_flags_reply)           \
3374 _(CONTROL_PING_REPLY, control_ping_reply)                               \
3375 _(CLI_REPLY, cli_reply)                                                 \
3376 _(CLI_INBAND_REPLY, cli_inband_reply)                                   \
3377 _(SW_INTERFACE_ADD_DEL_ADDRESS_REPLY,                                   \
3378   sw_interface_add_del_address_reply)                                   \
3379 _(SW_INTERFACE_SET_RX_MODE_REPLY, sw_interface_set_rx_mode_reply)       \
3380 _(SW_INTERFACE_SET_RX_PLACEMENT_REPLY, sw_interface_set_rx_placement_reply)     \
3381 _(SW_INTERFACE_RX_PLACEMENT_DETAILS, sw_interface_rx_placement_details) \
3382 _(SW_INTERFACE_SET_TABLE_REPLY, sw_interface_set_table_reply)           \
3383 _(SW_INTERFACE_SET_MPLS_ENABLE_REPLY, sw_interface_set_mpls_enable_reply) \
3384 _(SW_INTERFACE_SET_VPATH_REPLY, sw_interface_set_vpath_reply)           \
3385 _(SW_INTERFACE_SET_VXLAN_BYPASS_REPLY, sw_interface_set_vxlan_bypass_reply) \
3386 _(SW_INTERFACE_SET_VXLAN_GPE_BYPASS_REPLY, sw_interface_set_vxlan_gpe_bypass_reply) \
3387 _(SW_INTERFACE_SET_L2_XCONNECT_REPLY,                                   \
3388   sw_interface_set_l2_xconnect_reply)                                   \
3389 _(SW_INTERFACE_SET_L2_BRIDGE_REPLY,                                     \
3390   sw_interface_set_l2_bridge_reply)                                     \
3391 _(BRIDGE_DOMAIN_ADD_DEL_REPLY, bridge_domain_add_del_reply)             \
3392 _(BRIDGE_DOMAIN_DETAILS, bridge_domain_details)                         \
3393 _(BRIDGE_DOMAIN_SET_MAC_AGE_REPLY, bridge_domain_set_mac_age_reply)     \
3394 _(L2FIB_ADD_DEL_REPLY, l2fib_add_del_reply)                             \
3395 _(L2FIB_FLUSH_INT_REPLY, l2fib_flush_int_reply)                         \
3396 _(L2FIB_FLUSH_BD_REPLY, l2fib_flush_bd_reply)                           \
3397 _(L2_FLAGS_REPLY, l2_flags_reply)                                       \
3398 _(BRIDGE_FLAGS_REPLY, bridge_flags_reply)                               \
3399 _(TAP_CREATE_V2_REPLY, tap_create_v2_reply)                             \
3400 _(TAP_DELETE_V2_REPLY, tap_delete_v2_reply)                             \
3401 _(SW_INTERFACE_TAP_V2_DETAILS, sw_interface_tap_v2_details)             \
3402 _(VIRTIO_PCI_CREATE_REPLY, virtio_pci_create_reply)                     \
3403 _(VIRTIO_PCI_CREATE_V2_REPLY, virtio_pci_create_v2_reply)               \
3404 _(VIRTIO_PCI_DELETE_REPLY, virtio_pci_delete_reply)                     \
3405 _(SW_INTERFACE_VIRTIO_PCI_DETAILS, sw_interface_virtio_pci_details)     \
3406 _(BOND_CREATE_REPLY, bond_create_reply)                                 \
3407 _(BOND_CREATE2_REPLY, bond_create2_reply)                               \
3408 _(BOND_DELETE_REPLY, bond_delete_reply)                                 \
3409 _(BOND_ADD_MEMBER_REPLY, bond_add_member_reply)                         \
3410 _(BOND_DETACH_MEMBER_REPLY, bond_detach_member_reply)                   \
3411 _(SW_INTERFACE_SET_BOND_WEIGHT_REPLY, sw_interface_set_bond_weight_reply) \
3412 _(SW_BOND_INTERFACE_DETAILS, sw_bond_interface_details)                 \
3413 _(SW_MEMBER_INTERFACE_DETAILS, sw_member_interface_details)               \
3414 _(IP_ROUTE_ADD_DEL_REPLY, ip_route_add_del_reply)                       \
3415 _(IP_TABLE_ADD_DEL_REPLY, ip_table_add_del_reply)                       \
3416 _(IP_TABLE_REPLACE_BEGIN_REPLY, ip_table_replace_begin_reply)           \
3417 _(IP_TABLE_FLUSH_REPLY, ip_table_flush_reply)                           \
3418 _(IP_TABLE_REPLACE_END_REPLY, ip_table_replace_end_reply)               \
3419 _(IP_MROUTE_ADD_DEL_REPLY, ip_mroute_add_del_reply)                     \
3420 _(MPLS_TABLE_ADD_DEL_REPLY, mpls_table_add_del_reply)                   \
3421 _(MPLS_ROUTE_ADD_DEL_REPLY, mpls_route_add_del_reply)                   \
3422 _(MPLS_IP_BIND_UNBIND_REPLY, mpls_ip_bind_unbind_reply)                 \
3423 _(BIER_ROUTE_ADD_DEL_REPLY, bier_route_add_del_reply)                   \
3424 _(BIER_TABLE_ADD_DEL_REPLY, bier_table_add_del_reply)                   \
3425 _(MPLS_TUNNEL_ADD_DEL_REPLY, mpls_tunnel_add_del_reply)                 \
3426 _(SW_INTERFACE_SET_UNNUMBERED_REPLY,                                    \
3427   sw_interface_set_unnumbered_reply)                                    \
3428 _(CREATE_VLAN_SUBIF_REPLY, create_vlan_subif_reply)                     \
3429 _(CREATE_SUBIF_REPLY, create_subif_reply)                               \
3430 _(SET_IP_FLOW_HASH_REPLY, set_ip_flow_hash_reply)                       \
3431 _(SW_INTERFACE_IP6_ENABLE_DISABLE_REPLY,                                \
3432   sw_interface_ip6_enable_disable_reply)                                \
3433 _(L2_PATCH_ADD_DEL_REPLY, l2_patch_add_del_reply)                       \
3434 _(SR_MPLS_POLICY_ADD_REPLY, sr_mpls_policy_add_reply)                   \
3435 _(SR_MPLS_POLICY_MOD_REPLY, sr_mpls_policy_mod_reply)                   \
3436 _(SR_MPLS_POLICY_DEL_REPLY, sr_mpls_policy_del_reply)                   \
3437 _(SR_POLICY_ADD_REPLY, sr_policy_add_reply)                             \
3438 _(SR_POLICY_MOD_REPLY, sr_policy_mod_reply)                             \
3439 _(SR_POLICY_DEL_REPLY, sr_policy_del_reply)                             \
3440 _(SR_LOCALSID_ADD_DEL_REPLY, sr_localsid_add_del_reply)                 \
3441 _(SR_STEERING_ADD_DEL_REPLY, sr_steering_add_del_reply)                 \
3442 _(CLASSIFY_ADD_DEL_TABLE_REPLY, classify_add_del_table_reply)           \
3443 _(CLASSIFY_ADD_DEL_SESSION_REPLY, classify_add_del_session_reply)       \
3444 _(CLASSIFY_SET_INTERFACE_IP_TABLE_REPLY,                                \
3445 classify_set_interface_ip_table_reply)                                  \
3446 _(CLASSIFY_SET_INTERFACE_L2_TABLES_REPLY,                               \
3447   classify_set_interface_l2_tables_reply)                               \
3448 _(GET_NODE_INDEX_REPLY, get_node_index_reply)                           \
3449 _(ADD_NODE_NEXT_REPLY, add_node_next_reply)                             \
3450 _(VXLAN_ADD_DEL_TUNNEL_REPLY, vxlan_add_del_tunnel_reply)               \
3451 _(VXLAN_OFFLOAD_RX_REPLY, vxlan_offload_rx_reply)               \
3452 _(VXLAN_TUNNEL_DETAILS, vxlan_tunnel_details)                           \
3453 _(GRE_TUNNEL_ADD_DEL_REPLY, gre_tunnel_add_del_reply)                   \
3454 _(GRE_TUNNEL_DETAILS, gre_tunnel_details)                               \
3455 _(L2_FIB_CLEAR_TABLE_REPLY, l2_fib_clear_table_reply)                   \
3456 _(L2_INTERFACE_EFP_FILTER_REPLY, l2_interface_efp_filter_reply)         \
3457 _(L2_INTERFACE_VLAN_TAG_REWRITE_REPLY, l2_interface_vlan_tag_rewrite_reply) \
3458 _(SW_INTERFACE_VHOST_USER_DETAILS, sw_interface_vhost_user_details)     \
3459 _(CREATE_VHOST_USER_IF_REPLY, create_vhost_user_if_reply)               \
3460 _(MODIFY_VHOST_USER_IF_REPLY, modify_vhost_user_if_reply)               \
3461 _(DELETE_VHOST_USER_IF_REPLY, delete_vhost_user_if_reply)               \
3462 _(SHOW_VERSION_REPLY, show_version_reply)                               \
3463 _(SHOW_THREADS_REPLY, show_threads_reply)                               \
3464 _(L2_FIB_TABLE_DETAILS, l2_fib_table_details)                           \
3465 _(VXLAN_GPE_ADD_DEL_TUNNEL_REPLY, vxlan_gpe_add_del_tunnel_reply)       \
3466 _(VXLAN_GPE_TUNNEL_DETAILS, vxlan_gpe_tunnel_details)                   \
3467 _(INTERFACE_NAME_RENUMBER_REPLY, interface_name_renumber_reply)         \
3468 _(WANT_L2_MACS_EVENTS_REPLY, want_l2_macs_events_reply)                 \
3469 _(L2_MACS_EVENT, l2_macs_event)                                         \
3470 _(INPUT_ACL_SET_INTERFACE_REPLY, input_acl_set_interface_reply)         \
3471 _(IP_ADDRESS_DETAILS, ip_address_details)                               \
3472 _(IP_DETAILS, ip_details)                                               \
3473 _(IPSEC_SPD_ADD_DEL_REPLY, ipsec_spd_add_del_reply)                     \
3474 _(IPSEC_INTERFACE_ADD_DEL_SPD_REPLY, ipsec_interface_add_del_spd_reply) \
3475 _(IPSEC_SPD_ENTRY_ADD_DEL_REPLY, ipsec_spd_entry_add_del_reply)         \
3476 _(IPSEC_SAD_ENTRY_ADD_DEL_REPLY, ipsec_sad_entry_add_del_reply)         \
3477 _(IPSEC_SA_DETAILS, ipsec_sa_details)                                   \
3478 _(IPSEC_TUNNEL_IF_ADD_DEL_REPLY, ipsec_tunnel_if_add_del_reply)         \
3479 _(IPSEC_TUNNEL_IF_SET_SA_REPLY, ipsec_tunnel_if_set_sa_reply)           \
3480 _(DELETE_LOOPBACK_REPLY, delete_loopback_reply)                         \
3481 _(BD_IP_MAC_ADD_DEL_REPLY, bd_ip_mac_add_del_reply)                     \
3482 _(BD_IP_MAC_FLUSH_REPLY, bd_ip_mac_flush_reply)                         \
3483 _(BD_IP_MAC_DETAILS, bd_ip_mac_details)                                 \
3484 _(WANT_INTERFACE_EVENTS_REPLY, want_interface_events_reply)             \
3485 _(GET_FIRST_MSG_ID_REPLY, get_first_msg_id_reply)                       \
3486 _(COP_INTERFACE_ENABLE_DISABLE_REPLY, cop_interface_enable_disable_reply) \
3487 _(COP_WHITELIST_ENABLE_DISABLE_REPLY, cop_whitelist_enable_disable_reply) \
3488 _(GET_NODE_GRAPH_REPLY, get_node_graph_reply)                           \
3489 _(SW_INTERFACE_CLEAR_STATS_REPLY, sw_interface_clear_stats_reply)      \
3490 _(IOAM_ENABLE_REPLY, ioam_enable_reply)                   \
3491 _(IOAM_DISABLE_REPLY, ioam_disable_reply)                     \
3492 _(AF_PACKET_CREATE_REPLY, af_packet_create_reply)                       \
3493 _(AF_PACKET_DELETE_REPLY, af_packet_delete_reply)                       \
3494 _(AF_PACKET_DETAILS, af_packet_details)                                 \
3495 _(POLICER_ADD_DEL_REPLY, policer_add_del_reply)                         \
3496 _(POLICER_DETAILS, policer_details)                                     \
3497 _(POLICER_CLASSIFY_SET_INTERFACE_REPLY, policer_classify_set_interface_reply) \
3498 _(POLICER_CLASSIFY_DETAILS, policer_classify_details)                   \
3499 _(MPLS_TUNNEL_DETAILS, mpls_tunnel_details)                             \
3500 _(MPLS_TABLE_DETAILS, mpls_table_details)                               \
3501 _(MPLS_ROUTE_DETAILS, mpls_route_details)                               \
3502 _(CLASSIFY_TABLE_IDS_REPLY, classify_table_ids_reply)                   \
3503 _(CLASSIFY_TABLE_BY_INTERFACE_REPLY, classify_table_by_interface_reply) \
3504 _(CLASSIFY_TABLE_INFO_REPLY, classify_table_info_reply)                 \
3505 _(CLASSIFY_SESSION_DETAILS, classify_session_details)                   \
3506 _(SET_IPFIX_EXPORTER_REPLY, set_ipfix_exporter_reply)                   \
3507 _(IPFIX_EXPORTER_DETAILS, ipfix_exporter_details)                       \
3508 _(SET_IPFIX_CLASSIFY_STREAM_REPLY, set_ipfix_classify_stream_reply)     \
3509 _(IPFIX_CLASSIFY_STREAM_DETAILS, ipfix_classify_stream_details)         \
3510 _(IPFIX_CLASSIFY_TABLE_ADD_DEL_REPLY, ipfix_classify_table_add_del_reply) \
3511 _(IPFIX_CLASSIFY_TABLE_DETAILS, ipfix_classify_table_details)           \
3512 _(FLOW_CLASSIFY_SET_INTERFACE_REPLY, flow_classify_set_interface_reply) \
3513 _(FLOW_CLASSIFY_DETAILS, flow_classify_details)                         \
3514 _(SW_INTERFACE_SPAN_ENABLE_DISABLE_REPLY, sw_interface_span_enable_disable_reply) \
3515 _(SW_INTERFACE_SPAN_DETAILS, sw_interface_span_details)                 \
3516 _(GET_NEXT_INDEX_REPLY, get_next_index_reply)                           \
3517 _(PG_CREATE_INTERFACE_REPLY, pg_create_interface_reply)                 \
3518 _(PG_CAPTURE_REPLY, pg_capture_reply)                                   \
3519 _(PG_ENABLE_DISABLE_REPLY, pg_enable_disable_reply)                     \
3520 _(PG_INTERFACE_ENABLE_DISABLE_COALESCE_REPLY, pg_interface_enable_disable_coalesce_reply) \
3521 _(IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL_REPLY,                         \
3522  ip_source_and_port_range_check_add_del_reply)                          \
3523 _(IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL_REPLY,               \
3524  ip_source_and_port_range_check_interface_add_del_reply)                \
3525 _(DELETE_SUBIF_REPLY, delete_subif_reply)                               \
3526 _(L2_INTERFACE_PBB_TAG_REWRITE_REPLY, l2_interface_pbb_tag_rewrite_reply) \
3527 _(SET_PUNT_REPLY, set_punt_reply)                                       \
3528 _(IP_TABLE_DETAILS, ip_table_details)                                   \
3529 _(IP_ROUTE_DETAILS, ip_route_details)                                   \
3530 _(FEATURE_ENABLE_DISABLE_REPLY, feature_enable_disable_reply)           \
3531 _(FEATURE_GSO_ENABLE_DISABLE_REPLY, feature_gso_enable_disable_reply)   \
3532 _(SW_INTERFACE_TAG_ADD_DEL_REPLY, sw_interface_tag_add_del_reply)       \
3533 _(SW_INTERFACE_ADD_DEL_MAC_ADDRESS_REPLY, sw_interface_add_del_mac_address_reply) \
3534 _(L2_XCONNECT_DETAILS, l2_xconnect_details)                             \
3535 _(HW_INTERFACE_SET_MTU_REPLY, hw_interface_set_mtu_reply)               \
3536 _(SW_INTERFACE_GET_TABLE_REPLY, sw_interface_get_table_reply)           \
3537 _(P2P_ETHERNET_ADD_REPLY, p2p_ethernet_add_reply)                       \
3538 _(P2P_ETHERNET_DEL_REPLY, p2p_ethernet_del_reply)                       \
3539 _(TCP_CONFIGURE_SRC_ADDRESSES_REPLY, tcp_configure_src_addresses_reply) \
3540 _(APP_NAMESPACE_ADD_DEL_REPLY, app_namespace_add_del_reply)             \
3541 _(SESSION_RULE_ADD_DEL_REPLY, session_rule_add_del_reply)               \
3542 _(SESSION_RULES_DETAILS, session_rules_details)                         \
3543 _(IP_CONTAINER_PROXY_ADD_DEL_REPLY, ip_container_proxy_add_del_reply)   \
3544 _(OUTPUT_ACL_SET_INTERFACE_REPLY, output_acl_set_interface_reply)       \
3545 _(QOS_RECORD_ENABLE_DISABLE_REPLY, qos_record_enable_disable_reply)             \
3546 _(FLOW_ADD_REPLY, flow_add_reply)   \
3547
3548 #define foreach_standalone_reply_msg                                    \
3549 _(SW_INTERFACE_EVENT, sw_interface_event)
3550
3551 typedef struct
3552 {
3553   u8 *name;
3554   u32 value;
3555 } name_sort_t;
3556
3557 #define STR_VTR_OP_CASE(op)     \
3558     case L2_VTR_ ## op:         \
3559         return "" # op;
3560
3561 static const char *
3562 str_vtr_op (u32 vtr_op)
3563 {
3564   switch (vtr_op)
3565     {
3566       STR_VTR_OP_CASE (DISABLED);
3567       STR_VTR_OP_CASE (PUSH_1);
3568       STR_VTR_OP_CASE (PUSH_2);
3569       STR_VTR_OP_CASE (POP_1);
3570       STR_VTR_OP_CASE (POP_2);
3571       STR_VTR_OP_CASE (TRANSLATE_1_1);
3572       STR_VTR_OP_CASE (TRANSLATE_1_2);
3573       STR_VTR_OP_CASE (TRANSLATE_2_1);
3574       STR_VTR_OP_CASE (TRANSLATE_2_2);
3575     }
3576
3577   return "UNKNOWN";
3578 }
3579
3580 static int
3581 dump_sub_interface_table (vat_main_t * vam)
3582 {
3583   const sw_interface_subif_t *sub = NULL;
3584
3585   if (vam->json_output)
3586     {
3587       clib_warning
3588         ("JSON output supported only for VPE API calls and dump_stats_table");
3589       return -99;
3590     }
3591
3592   print (vam->ofp,
3593          "%-30s%-12s%-11s%-7s%-5s%-9s%-9s%-6s%-8s%-10s%-10s",
3594          "Interface", "sw_if_index",
3595          "sub id", "dot1ad", "tags", "outer id",
3596          "inner id", "exact", "default", "outer any", "inner any");
3597
3598   vec_foreach (sub, vam->sw_if_subif_table)
3599   {
3600     print (vam->ofp,
3601            "%-30s%-12d%-11d%-7s%-5d%-9d%-9d%-6d%-8d%-10d%-10d",
3602            sub->interface_name,
3603            sub->sw_if_index,
3604            sub->sub_id, sub->sub_dot1ad ? "dot1ad" : "dot1q",
3605            sub->sub_number_of_tags, sub->sub_outer_vlan_id,
3606            sub->sub_inner_vlan_id, sub->sub_exact_match, sub->sub_default,
3607            sub->sub_outer_vlan_id_any, sub->sub_inner_vlan_id_any);
3608     if (sub->vtr_op != L2_VTR_DISABLED)
3609       {
3610         print (vam->ofp,
3611                "  vlan-tag-rewrite - op: %-14s [ dot1q: %d "
3612                "tag1: %d tag2: %d ]",
3613                str_vtr_op (sub->vtr_op), sub->vtr_push_dot1q,
3614                sub->vtr_tag1, sub->vtr_tag2);
3615       }
3616   }
3617
3618   return 0;
3619 }
3620
3621 static int
3622 name_sort_cmp (void *a1, void *a2)
3623 {
3624   name_sort_t *n1 = a1;
3625   name_sort_t *n2 = a2;
3626
3627   return strcmp ((char *) n1->name, (char *) n2->name);
3628 }
3629
3630 static int
3631 dump_interface_table (vat_main_t * vam)
3632 {
3633   hash_pair_t *p;
3634   name_sort_t *nses = 0, *ns;
3635
3636   if (vam->json_output)
3637     {
3638       clib_warning
3639         ("JSON output supported only for VPE API calls and dump_stats_table");
3640       return -99;
3641     }
3642
3643   /* *INDENT-OFF* */
3644   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
3645   ({
3646     vec_add2 (nses, ns, 1);
3647     ns->name = (u8 *)(p->key);
3648     ns->value = (u32) p->value[0];
3649   }));
3650   /* *INDENT-ON* */
3651
3652   vec_sort_with_function (nses, name_sort_cmp);
3653
3654   print (vam->ofp, "%-25s%-15s", "Interface", "sw_if_index");
3655   vec_foreach (ns, nses)
3656   {
3657     print (vam->ofp, "%-25s%-15d", ns->name, ns->value);
3658   }
3659   vec_free (nses);
3660   return 0;
3661 }
3662
3663 static int
3664 dump_ip_table (vat_main_t * vam, int is_ipv6)
3665 {
3666   const ip_details_t *det = NULL;
3667   const ip_address_details_t *address = NULL;
3668   u32 i = ~0;
3669
3670   print (vam->ofp, "%-12s", "sw_if_index");
3671
3672   vec_foreach (det, vam->ip_details_by_sw_if_index[is_ipv6])
3673   {
3674     i++;
3675     if (!det->present)
3676       {
3677         continue;
3678       }
3679     print (vam->ofp, "%-12d", i);
3680     print (vam->ofp, "            %-30s%-13s", "Address", "Prefix length");
3681     if (!det->addr)
3682       {
3683         continue;
3684       }
3685     vec_foreach (address, det->addr)
3686     {
3687       print (vam->ofp,
3688              "            %-30U%-13d",
3689              is_ipv6 ? format_ip6_address : format_ip4_address,
3690              address->ip, address->prefix_length);
3691     }
3692   }
3693
3694   return 0;
3695 }
3696
3697 static int
3698 dump_ipv4_table (vat_main_t * vam)
3699 {
3700   if (vam->json_output)
3701     {
3702       clib_warning
3703         ("JSON output supported only for VPE API calls and dump_stats_table");
3704       return -99;
3705     }
3706
3707   return dump_ip_table (vam, 0);
3708 }
3709
3710 static int
3711 dump_ipv6_table (vat_main_t * vam)
3712 {
3713   if (vam->json_output)
3714     {
3715       clib_warning
3716         ("JSON output supported only for VPE API calls and dump_stats_table");
3717       return -99;
3718     }
3719
3720   return dump_ip_table (vam, 1);
3721 }
3722
3723 /*
3724  * Pass CLI buffers directly in the CLI_INBAND API message,
3725  * instead of an additional shared memory area.
3726  */
3727 static int
3728 exec_inband (vat_main_t * vam)
3729 {
3730   vl_api_cli_inband_t *mp;
3731   unformat_input_t *i = vam->input;
3732   int ret;
3733
3734   if (vec_len (i->buffer) == 0)
3735     return -1;
3736
3737   if (vam->exec_mode == 0 && unformat (i, "mode"))
3738     {
3739       vam->exec_mode = 1;
3740       return 0;
3741     }
3742   if (vam->exec_mode == 1 && (unformat (i, "exit") || unformat (i, "quit")))
3743     {
3744       vam->exec_mode = 0;
3745       return 0;
3746     }
3747
3748   /*
3749    * In order for the CLI command to work, it
3750    * must be a vector ending in \n, not a C-string ending
3751    * in \n\0.
3752    */
3753   M2 (CLI_INBAND, mp, vec_len (vam->input->buffer));
3754   vl_api_vec_to_api_string (vam->input->buffer, &mp->cmd);
3755
3756   S (mp);
3757   W (ret);
3758   /* json responses may or may not include a useful reply... */
3759   if (vec_len (vam->cmd_reply))
3760     print (vam->ofp, "%v", (char *) (vam->cmd_reply));
3761   return ret;
3762 }
3763
3764 int
3765 exec (vat_main_t * vam)
3766 {
3767   return exec_inband (vam);
3768 }
3769
3770 static int
3771 api_create_loopback (vat_main_t * vam)
3772 {
3773   unformat_input_t *i = vam->input;
3774   vl_api_create_loopback_t *mp;
3775   vl_api_create_loopback_instance_t *mp_lbi;
3776   u8 mac_address[6];
3777   u8 mac_set = 0;
3778   u8 is_specified = 0;
3779   u32 user_instance = 0;
3780   int ret;
3781
3782   clib_memset (mac_address, 0, sizeof (mac_address));
3783
3784   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3785     {
3786       if (unformat (i, "mac %U", unformat_ethernet_address, mac_address))
3787         mac_set = 1;
3788       if (unformat (i, "instance %d", &user_instance))
3789         is_specified = 1;
3790       else
3791         break;
3792     }
3793
3794   if (is_specified)
3795     {
3796       M (CREATE_LOOPBACK_INSTANCE, mp_lbi);
3797       mp_lbi->is_specified = is_specified;
3798       if (is_specified)
3799         mp_lbi->user_instance = htonl (user_instance);
3800       if (mac_set)
3801         clib_memcpy (mp_lbi->mac_address, mac_address, sizeof (mac_address));
3802       S (mp_lbi);
3803     }
3804   else
3805     {
3806       /* Construct the API message */
3807       M (CREATE_LOOPBACK, mp);
3808       if (mac_set)
3809         clib_memcpy (mp->mac_address, mac_address, sizeof (mac_address));
3810       S (mp);
3811     }
3812
3813   W (ret);
3814   return ret;
3815 }
3816
3817 static int
3818 api_delete_loopback (vat_main_t * vam)
3819 {
3820   unformat_input_t *i = vam->input;
3821   vl_api_delete_loopback_t *mp;
3822   u32 sw_if_index = ~0;
3823   int ret;
3824
3825   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3826     {
3827       if (unformat (i, "sw_if_index %d", &sw_if_index))
3828         ;
3829       else
3830         break;
3831     }
3832
3833   if (sw_if_index == ~0)
3834     {
3835       errmsg ("missing sw_if_index");
3836       return -99;
3837     }
3838
3839   /* Construct the API message */
3840   M (DELETE_LOOPBACK, mp);
3841   mp->sw_if_index = ntohl (sw_if_index);
3842
3843   S (mp);
3844   W (ret);
3845   return ret;
3846 }
3847
3848 static int
3849 api_want_interface_events (vat_main_t * vam)
3850 {
3851   unformat_input_t *i = vam->input;
3852   vl_api_want_interface_events_t *mp;
3853   int enable = -1;
3854   int ret;
3855
3856   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3857     {
3858       if (unformat (i, "enable"))
3859         enable = 1;
3860       else if (unformat (i, "disable"))
3861         enable = 0;
3862       else
3863         break;
3864     }
3865
3866   if (enable == -1)
3867     {
3868       errmsg ("missing enable|disable");
3869       return -99;
3870     }
3871
3872   M (WANT_INTERFACE_EVENTS, mp);
3873   mp->enable_disable = enable;
3874
3875   vam->interface_event_display = enable;
3876
3877   S (mp);
3878   W (ret);
3879   return ret;
3880 }
3881
3882
3883 /* Note: non-static, called once to set up the initial intfc table */
3884 int
3885 api_sw_interface_dump (vat_main_t * vam)
3886 {
3887   vl_api_sw_interface_dump_t *mp;
3888   vl_api_control_ping_t *mp_ping;
3889   hash_pair_t *p;
3890   name_sort_t *nses = 0, *ns;
3891   sw_interface_subif_t *sub = NULL;
3892   int ret;
3893
3894   /* Toss the old name table */
3895   /* *INDENT-OFF* */
3896   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
3897   ({
3898     vec_add2 (nses, ns, 1);
3899     ns->name = (u8 *)(p->key);
3900     ns->value = (u32) p->value[0];
3901   }));
3902   /* *INDENT-ON* */
3903
3904   hash_free (vam->sw_if_index_by_interface_name);
3905
3906   vec_foreach (ns, nses) vec_free (ns->name);
3907
3908   vec_free (nses);
3909
3910   vec_foreach (sub, vam->sw_if_subif_table)
3911   {
3912     vec_free (sub->interface_name);
3913   }
3914   vec_free (vam->sw_if_subif_table);
3915
3916   /* recreate the interface name hash table */
3917   vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
3918
3919   /*
3920    * Ask for all interface names. Otherwise, the epic catalog of
3921    * name filters becomes ridiculously long, and vat ends up needing
3922    * to be taught about new interface types.
3923    */
3924   M (SW_INTERFACE_DUMP, mp);
3925   S (mp);
3926
3927   /* Use a control ping for synchronization */
3928   MPING (CONTROL_PING, mp_ping);
3929   S (mp_ping);
3930
3931   W (ret);
3932   return ret;
3933 }
3934
3935 static int
3936 api_sw_interface_set_flags (vat_main_t * vam)
3937 {
3938   unformat_input_t *i = vam->input;
3939   vl_api_sw_interface_set_flags_t *mp;
3940   u32 sw_if_index;
3941   u8 sw_if_index_set = 0;
3942   u8 admin_up = 0;
3943   int ret;
3944
3945   /* Parse args required to build the message */
3946   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3947     {
3948       if (unformat (i, "admin-up"))
3949         admin_up = 1;
3950       else if (unformat (i, "admin-down"))
3951         admin_up = 0;
3952       else
3953         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3954         sw_if_index_set = 1;
3955       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3956         sw_if_index_set = 1;
3957       else
3958         break;
3959     }
3960
3961   if (sw_if_index_set == 0)
3962     {
3963       errmsg ("missing interface name or sw_if_index");
3964       return -99;
3965     }
3966
3967   /* Construct the API message */
3968   M (SW_INTERFACE_SET_FLAGS, mp);
3969   mp->sw_if_index = ntohl (sw_if_index);
3970   mp->flags = ntohl ((admin_up) ? IF_STATUS_API_FLAG_ADMIN_UP : 0);
3971
3972   /* send it... */
3973   S (mp);
3974
3975   /* Wait for a reply, return the good/bad news... */
3976   W (ret);
3977   return ret;
3978 }
3979
3980 static int
3981 api_sw_interface_set_rx_mode (vat_main_t * vam)
3982 {
3983   unformat_input_t *i = vam->input;
3984   vl_api_sw_interface_set_rx_mode_t *mp;
3985   u32 sw_if_index;
3986   u8 sw_if_index_set = 0;
3987   int ret;
3988   u8 queue_id_valid = 0;
3989   u32 queue_id;
3990   vnet_hw_interface_rx_mode mode = VNET_HW_INTERFACE_RX_MODE_UNKNOWN;
3991
3992   /* Parse args required to build the message */
3993   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3994     {
3995       if (unformat (i, "queue %d", &queue_id))
3996         queue_id_valid = 1;
3997       else if (unformat (i, "polling"))
3998         mode = VNET_HW_INTERFACE_RX_MODE_POLLING;
3999       else if (unformat (i, "interrupt"))
4000         mode = VNET_HW_INTERFACE_RX_MODE_INTERRUPT;
4001       else if (unformat (i, "adaptive"))
4002         mode = VNET_HW_INTERFACE_RX_MODE_ADAPTIVE;
4003       else
4004         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4005         sw_if_index_set = 1;
4006       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4007         sw_if_index_set = 1;
4008       else
4009         break;
4010     }
4011
4012   if (sw_if_index_set == 0)
4013     {
4014       errmsg ("missing interface name or sw_if_index");
4015       return -99;
4016     }
4017   if (mode == VNET_HW_INTERFACE_RX_MODE_UNKNOWN)
4018     {
4019       errmsg ("missing rx-mode");
4020       return -99;
4021     }
4022
4023   /* Construct the API message */
4024   M (SW_INTERFACE_SET_RX_MODE, mp);
4025   mp->sw_if_index = ntohl (sw_if_index);
4026   mp->mode = (vl_api_rx_mode_t) mode;
4027   mp->queue_id_valid = queue_id_valid;
4028   mp->queue_id = queue_id_valid ? ntohl (queue_id) : ~0;
4029
4030   /* send it... */
4031   S (mp);
4032
4033   /* Wait for a reply, return the good/bad news... */
4034   W (ret);
4035   return ret;
4036 }
4037
4038 static int
4039 api_sw_interface_set_rx_placement (vat_main_t * vam)
4040 {
4041   unformat_input_t *i = vam->input;
4042   vl_api_sw_interface_set_rx_placement_t *mp;
4043   u32 sw_if_index;
4044   u8 sw_if_index_set = 0;
4045   int ret;
4046   u8 is_main = 0;
4047   u32 queue_id, thread_index;
4048
4049   /* Parse args required to build the message */
4050   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4051     {
4052       if (unformat (i, "queue %d", &queue_id))
4053         ;
4054       else if (unformat (i, "main"))
4055         is_main = 1;
4056       else if (unformat (i, "worker %d", &thread_index))
4057         ;
4058       else
4059         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4060         sw_if_index_set = 1;
4061       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4062         sw_if_index_set = 1;
4063       else
4064         break;
4065     }
4066
4067   if (sw_if_index_set == 0)
4068     {
4069       errmsg ("missing interface name or sw_if_index");
4070       return -99;
4071     }
4072
4073   if (is_main)
4074     thread_index = 0;
4075   /* Construct the API message */
4076   M (SW_INTERFACE_SET_RX_PLACEMENT, mp);
4077   mp->sw_if_index = ntohl (sw_if_index);
4078   mp->worker_id = ntohl (thread_index);
4079   mp->queue_id = ntohl (queue_id);
4080   mp->is_main = is_main;
4081
4082   /* send it... */
4083   S (mp);
4084   /* Wait for a reply, return the good/bad news... */
4085   W (ret);
4086   return ret;
4087 }
4088
4089 static void vl_api_sw_interface_rx_placement_details_t_handler
4090   (vl_api_sw_interface_rx_placement_details_t * mp)
4091 {
4092   vat_main_t *vam = &vat_main;
4093   u32 worker_id = ntohl (mp->worker_id);
4094
4095   print (vam->ofp,
4096          "\n%-11d %-11s %-6d %-5d %-9s",
4097          ntohl (mp->sw_if_index), (worker_id == 0) ? "main" : "worker",
4098          worker_id, ntohl (mp->queue_id),
4099          (mp->mode ==
4100           1) ? "polling" : ((mp->mode == 2) ? "interrupt" : "adaptive"));
4101 }
4102
4103 static void vl_api_sw_interface_rx_placement_details_t_handler_json
4104   (vl_api_sw_interface_rx_placement_details_t * mp)
4105 {
4106   vat_main_t *vam = &vat_main;
4107   vat_json_node_t *node = NULL;
4108
4109   if (VAT_JSON_ARRAY != vam->json_tree.type)
4110     {
4111       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
4112       vat_json_init_array (&vam->json_tree);
4113     }
4114   node = vat_json_array_add (&vam->json_tree);
4115
4116   vat_json_init_object (node);
4117   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
4118   vat_json_object_add_uint (node, "worker_id", ntohl (mp->worker_id));
4119   vat_json_object_add_uint (node, "queue_id", ntohl (mp->queue_id));
4120   vat_json_object_add_uint (node, "mode", mp->mode);
4121 }
4122
4123 static int
4124 api_sw_interface_rx_placement_dump (vat_main_t * vam)
4125 {
4126   unformat_input_t *i = vam->input;
4127   vl_api_sw_interface_rx_placement_dump_t *mp;
4128   vl_api_control_ping_t *mp_ping;
4129   int ret;
4130   u32 sw_if_index;
4131   u8 sw_if_index_set = 0;
4132
4133   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4134     {
4135       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4136         sw_if_index_set++;
4137       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4138         sw_if_index_set++;
4139       else
4140         break;
4141     }
4142
4143   print (vam->ofp,
4144          "\n%-11s %-11s %-6s %-5s %-4s",
4145          "sw_if_index", "main/worker", "thread", "queue", "mode");
4146
4147   /* Dump Interface rx placement */
4148   M (SW_INTERFACE_RX_PLACEMENT_DUMP, mp);
4149
4150   if (sw_if_index_set)
4151     mp->sw_if_index = htonl (sw_if_index);
4152   else
4153     mp->sw_if_index = ~0;
4154
4155   S (mp);
4156
4157   /* Use a control ping for synchronization */
4158   MPING (CONTROL_PING, mp_ping);
4159   S (mp_ping);
4160
4161   W (ret);
4162   return ret;
4163 }
4164
4165 static int
4166 api_sw_interface_clear_stats (vat_main_t * vam)
4167 {
4168   unformat_input_t *i = vam->input;
4169   vl_api_sw_interface_clear_stats_t *mp;
4170   u32 sw_if_index;
4171   u8 sw_if_index_set = 0;
4172   int ret;
4173
4174   /* Parse args required to build the message */
4175   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4176     {
4177       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4178         sw_if_index_set = 1;
4179       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4180         sw_if_index_set = 1;
4181       else
4182         break;
4183     }
4184
4185   /* Construct the API message */
4186   M (SW_INTERFACE_CLEAR_STATS, mp);
4187
4188   if (sw_if_index_set == 1)
4189     mp->sw_if_index = ntohl (sw_if_index);
4190   else
4191     mp->sw_if_index = ~0;
4192
4193   /* send it... */
4194   S (mp);
4195
4196   /* Wait for a reply, return the good/bad news... */
4197   W (ret);
4198   return ret;
4199 }
4200
4201 static int
4202 api_sw_interface_add_del_address (vat_main_t * vam)
4203 {
4204   unformat_input_t *i = vam->input;
4205   vl_api_sw_interface_add_del_address_t *mp;
4206   u32 sw_if_index;
4207   u8 sw_if_index_set = 0;
4208   u8 is_add = 1, del_all = 0;
4209   u32 address_length = 0;
4210   u8 v4_address_set = 0;
4211   u8 v6_address_set = 0;
4212   ip4_address_t v4address;
4213   ip6_address_t v6address;
4214   int ret;
4215
4216   /* Parse args required to build the message */
4217   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4218     {
4219       if (unformat (i, "del-all"))
4220         del_all = 1;
4221       else if (unformat (i, "del"))
4222         is_add = 0;
4223       else
4224         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4225         sw_if_index_set = 1;
4226       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4227         sw_if_index_set = 1;
4228       else if (unformat (i, "%U/%d",
4229                          unformat_ip4_address, &v4address, &address_length))
4230         v4_address_set = 1;
4231       else if (unformat (i, "%U/%d",
4232                          unformat_ip6_address, &v6address, &address_length))
4233         v6_address_set = 1;
4234       else
4235         break;
4236     }
4237
4238   if (sw_if_index_set == 0)
4239     {
4240       errmsg ("missing interface name or sw_if_index");
4241       return -99;
4242     }
4243   if (v4_address_set && v6_address_set)
4244     {
4245       errmsg ("both v4 and v6 addresses set");
4246       return -99;
4247     }
4248   if (!v4_address_set && !v6_address_set && !del_all)
4249     {
4250       errmsg ("no addresses set");
4251       return -99;
4252     }
4253
4254   /* Construct the API message */
4255   M (SW_INTERFACE_ADD_DEL_ADDRESS, mp);
4256
4257   mp->sw_if_index = ntohl (sw_if_index);
4258   mp->is_add = is_add;
4259   mp->del_all = del_all;
4260   if (v6_address_set)
4261     {
4262       mp->prefix.address.af = ADDRESS_IP6;
4263       clib_memcpy (mp->prefix.address.un.ip6, &v6address, sizeof (v6address));
4264     }
4265   else
4266     {
4267       mp->prefix.address.af = ADDRESS_IP4;
4268       clib_memcpy (mp->prefix.address.un.ip4, &v4address, sizeof (v4address));
4269     }
4270   mp->prefix.len = address_length;
4271
4272   /* send it... */
4273   S (mp);
4274
4275   /* Wait for a reply, return good/bad news  */
4276   W (ret);
4277   return ret;
4278 }
4279
4280 static int
4281 api_sw_interface_set_mpls_enable (vat_main_t * vam)
4282 {
4283   unformat_input_t *i = vam->input;
4284   vl_api_sw_interface_set_mpls_enable_t *mp;
4285   u32 sw_if_index;
4286   u8 sw_if_index_set = 0;
4287   u8 enable = 1;
4288   int ret;
4289
4290   /* Parse args required to build the message */
4291   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4292     {
4293       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4294         sw_if_index_set = 1;
4295       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4296         sw_if_index_set = 1;
4297       else if (unformat (i, "disable"))
4298         enable = 0;
4299       else if (unformat (i, "dis"))
4300         enable = 0;
4301       else
4302         break;
4303     }
4304
4305   if (sw_if_index_set == 0)
4306     {
4307       errmsg ("missing interface name or sw_if_index");
4308       return -99;
4309     }
4310
4311   /* Construct the API message */
4312   M (SW_INTERFACE_SET_MPLS_ENABLE, mp);
4313
4314   mp->sw_if_index = ntohl (sw_if_index);
4315   mp->enable = enable;
4316
4317   /* send it... */
4318   S (mp);
4319
4320   /* Wait for a reply... */
4321   W (ret);
4322   return ret;
4323 }
4324
4325 static int
4326 api_sw_interface_set_table (vat_main_t * vam)
4327 {
4328   unformat_input_t *i = vam->input;
4329   vl_api_sw_interface_set_table_t *mp;
4330   u32 sw_if_index, vrf_id = 0;
4331   u8 sw_if_index_set = 0;
4332   u8 is_ipv6 = 0;
4333   int ret;
4334
4335   /* Parse args required to build the message */
4336   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4337     {
4338       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4339         sw_if_index_set = 1;
4340       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4341         sw_if_index_set = 1;
4342       else if (unformat (i, "vrf %d", &vrf_id))
4343         ;
4344       else if (unformat (i, "ipv6"))
4345         is_ipv6 = 1;
4346       else
4347         break;
4348     }
4349
4350   if (sw_if_index_set == 0)
4351     {
4352       errmsg ("missing interface name or sw_if_index");
4353       return -99;
4354     }
4355
4356   /* Construct the API message */
4357   M (SW_INTERFACE_SET_TABLE, mp);
4358
4359   mp->sw_if_index = ntohl (sw_if_index);
4360   mp->is_ipv6 = is_ipv6;
4361   mp->vrf_id = ntohl (vrf_id);
4362
4363   /* send it... */
4364   S (mp);
4365
4366   /* Wait for a reply... */
4367   W (ret);
4368   return ret;
4369 }
4370
4371 static void vl_api_sw_interface_get_table_reply_t_handler
4372   (vl_api_sw_interface_get_table_reply_t * mp)
4373 {
4374   vat_main_t *vam = &vat_main;
4375
4376   print (vam->ofp, "%d", ntohl (mp->vrf_id));
4377
4378   vam->retval = ntohl (mp->retval);
4379   vam->result_ready = 1;
4380
4381 }
4382
4383 static void vl_api_sw_interface_get_table_reply_t_handler_json
4384   (vl_api_sw_interface_get_table_reply_t * mp)
4385 {
4386   vat_main_t *vam = &vat_main;
4387   vat_json_node_t node;
4388
4389   vat_json_init_object (&node);
4390   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
4391   vat_json_object_add_int (&node, "vrf_id", ntohl (mp->vrf_id));
4392
4393   vat_json_print (vam->ofp, &node);
4394   vat_json_free (&node);
4395
4396   vam->retval = ntohl (mp->retval);
4397   vam->result_ready = 1;
4398 }
4399
4400 static int
4401 api_sw_interface_get_table (vat_main_t * vam)
4402 {
4403   unformat_input_t *i = vam->input;
4404   vl_api_sw_interface_get_table_t *mp;
4405   u32 sw_if_index;
4406   u8 sw_if_index_set = 0;
4407   u8 is_ipv6 = 0;
4408   int ret;
4409
4410   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4411     {
4412       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4413         sw_if_index_set = 1;
4414       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4415         sw_if_index_set = 1;
4416       else if (unformat (i, "ipv6"))
4417         is_ipv6 = 1;
4418       else
4419         break;
4420     }
4421
4422   if (sw_if_index_set == 0)
4423     {
4424       errmsg ("missing interface name or sw_if_index");
4425       return -99;
4426     }
4427
4428   M (SW_INTERFACE_GET_TABLE, mp);
4429   mp->sw_if_index = htonl (sw_if_index);
4430   mp->is_ipv6 = is_ipv6;
4431
4432   S (mp);
4433   W (ret);
4434   return ret;
4435 }
4436
4437 static int
4438 api_sw_interface_set_vpath (vat_main_t * vam)
4439 {
4440   unformat_input_t *i = vam->input;
4441   vl_api_sw_interface_set_vpath_t *mp;
4442   u32 sw_if_index = 0;
4443   u8 sw_if_index_set = 0;
4444   u8 is_enable = 0;
4445   int ret;
4446
4447   /* Parse args required to build the message */
4448   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4449     {
4450       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4451         sw_if_index_set = 1;
4452       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4453         sw_if_index_set = 1;
4454       else if (unformat (i, "enable"))
4455         is_enable = 1;
4456       else if (unformat (i, "disable"))
4457         is_enable = 0;
4458       else
4459         break;
4460     }
4461
4462   if (sw_if_index_set == 0)
4463     {
4464       errmsg ("missing interface name or sw_if_index");
4465       return -99;
4466     }
4467
4468   /* Construct the API message */
4469   M (SW_INTERFACE_SET_VPATH, mp);
4470
4471   mp->sw_if_index = ntohl (sw_if_index);
4472   mp->enable = is_enable;
4473
4474   /* send it... */
4475   S (mp);
4476
4477   /* Wait for a reply... */
4478   W (ret);
4479   return ret;
4480 }
4481
4482 static int
4483 api_sw_interface_set_vxlan_bypass (vat_main_t * vam)
4484 {
4485   unformat_input_t *i = vam->input;
4486   vl_api_sw_interface_set_vxlan_bypass_t *mp;
4487   u32 sw_if_index = 0;
4488   u8 sw_if_index_set = 0;
4489   u8 is_enable = 1;
4490   u8 is_ipv6 = 0;
4491   int ret;
4492
4493   /* Parse args required to build the message */
4494   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4495     {
4496       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4497         sw_if_index_set = 1;
4498       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4499         sw_if_index_set = 1;
4500       else if (unformat (i, "enable"))
4501         is_enable = 1;
4502       else if (unformat (i, "disable"))
4503         is_enable = 0;
4504       else if (unformat (i, "ip4"))
4505         is_ipv6 = 0;
4506       else if (unformat (i, "ip6"))
4507         is_ipv6 = 1;
4508       else
4509         break;
4510     }
4511
4512   if (sw_if_index_set == 0)
4513     {
4514       errmsg ("missing interface name or sw_if_index");
4515       return -99;
4516     }
4517
4518   /* Construct the API message */
4519   M (SW_INTERFACE_SET_VXLAN_BYPASS, mp);
4520
4521   mp->sw_if_index = ntohl (sw_if_index);
4522   mp->enable = is_enable;
4523   mp->is_ipv6 = is_ipv6;
4524
4525   /* send it... */
4526   S (mp);
4527
4528   /* Wait for a reply... */
4529   W (ret);
4530   return ret;
4531 }
4532
4533 static int
4534 api_sw_interface_set_l2_xconnect (vat_main_t * vam)
4535 {
4536   unformat_input_t *i = vam->input;
4537   vl_api_sw_interface_set_l2_xconnect_t *mp;
4538   u32 rx_sw_if_index;
4539   u8 rx_sw_if_index_set = 0;
4540   u32 tx_sw_if_index;
4541   u8 tx_sw_if_index_set = 0;
4542   u8 enable = 1;
4543   int ret;
4544
4545   /* Parse args required to build the message */
4546   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4547     {
4548       if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index))
4549         rx_sw_if_index_set = 1;
4550       else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
4551         tx_sw_if_index_set = 1;
4552       else if (unformat (i, "rx"))
4553         {
4554           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4555             {
4556               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
4557                             &rx_sw_if_index))
4558                 rx_sw_if_index_set = 1;
4559             }
4560           else
4561             break;
4562         }
4563       else if (unformat (i, "tx"))
4564         {
4565           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4566             {
4567               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
4568                             &tx_sw_if_index))
4569                 tx_sw_if_index_set = 1;
4570             }
4571           else
4572             break;
4573         }
4574       else if (unformat (i, "enable"))
4575         enable = 1;
4576       else if (unformat (i, "disable"))
4577         enable = 0;
4578       else
4579         break;
4580     }
4581
4582   if (rx_sw_if_index_set == 0)
4583     {
4584       errmsg ("missing rx interface name or rx_sw_if_index");
4585       return -99;
4586     }
4587
4588   if (enable && (tx_sw_if_index_set == 0))
4589     {
4590       errmsg ("missing tx interface name or tx_sw_if_index");
4591       return -99;
4592     }
4593
4594   M (SW_INTERFACE_SET_L2_XCONNECT, mp);
4595
4596   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
4597   mp->tx_sw_if_index = ntohl (tx_sw_if_index);
4598   mp->enable = enable;
4599
4600   S (mp);
4601   W (ret);
4602   return ret;
4603 }
4604
4605 static int
4606 api_sw_interface_set_l2_bridge (vat_main_t * vam)
4607 {
4608   unformat_input_t *i = vam->input;
4609   vl_api_sw_interface_set_l2_bridge_t *mp;
4610   vl_api_l2_port_type_t port_type;
4611   u32 rx_sw_if_index;
4612   u8 rx_sw_if_index_set = 0;
4613   u32 bd_id;
4614   u8 bd_id_set = 0;
4615   u32 shg = 0;
4616   u8 enable = 1;
4617   int ret;
4618
4619   port_type = L2_API_PORT_TYPE_NORMAL;
4620
4621   /* Parse args required to build the message */
4622   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4623     {
4624       if (unformat (i, "sw_if_index %d", &rx_sw_if_index))
4625         rx_sw_if_index_set = 1;
4626       else if (unformat (i, "bd_id %d", &bd_id))
4627         bd_id_set = 1;
4628       else
4629         if (unformat
4630             (i, "%U", api_unformat_sw_if_index, vam, &rx_sw_if_index))
4631         rx_sw_if_index_set = 1;
4632       else if (unformat (i, "shg %d", &shg))
4633         ;
4634       else if (unformat (i, "bvi"))
4635         port_type = L2_API_PORT_TYPE_BVI;
4636       else if (unformat (i, "uu-fwd"))
4637         port_type = L2_API_PORT_TYPE_UU_FWD;
4638       else if (unformat (i, "enable"))
4639         enable = 1;
4640       else if (unformat (i, "disable"))
4641         enable = 0;
4642       else
4643         break;
4644     }
4645
4646   if (rx_sw_if_index_set == 0)
4647     {
4648       errmsg ("missing rx interface name or sw_if_index");
4649       return -99;
4650     }
4651
4652   if (enable && (bd_id_set == 0))
4653     {
4654       errmsg ("missing bridge domain");
4655       return -99;
4656     }
4657
4658   M (SW_INTERFACE_SET_L2_BRIDGE, mp);
4659
4660   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
4661   mp->bd_id = ntohl (bd_id);
4662   mp->shg = (u8) shg;
4663   mp->port_type = ntohl (port_type);
4664   mp->enable = enable;
4665
4666   S (mp);
4667   W (ret);
4668   return ret;
4669 }
4670
4671 static int
4672 api_bridge_domain_dump (vat_main_t * vam)
4673 {
4674   unformat_input_t *i = vam->input;
4675   vl_api_bridge_domain_dump_t *mp;
4676   vl_api_control_ping_t *mp_ping;
4677   u32 bd_id = ~0;
4678   int ret;
4679
4680   /* Parse args required to build the message */
4681   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4682     {
4683       if (unformat (i, "bd_id %d", &bd_id))
4684         ;
4685       else
4686         break;
4687     }
4688
4689   M (BRIDGE_DOMAIN_DUMP, mp);
4690   mp->bd_id = ntohl (bd_id);
4691   S (mp);
4692
4693   /* Use a control ping for synchronization */
4694   MPING (CONTROL_PING, mp_ping);
4695   S (mp_ping);
4696
4697   W (ret);
4698   return ret;
4699 }
4700
4701 static int
4702 api_bridge_domain_add_del (vat_main_t * vam)
4703 {
4704   unformat_input_t *i = vam->input;
4705   vl_api_bridge_domain_add_del_t *mp;
4706   u32 bd_id = ~0;
4707   u8 is_add = 1;
4708   u32 flood = 1, forward = 1, learn = 1, uu_flood = 1, arp_term = 0;
4709   u8 *bd_tag = NULL;
4710   u32 mac_age = 0;
4711   int ret;
4712
4713   /* Parse args required to build the message */
4714   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4715     {
4716       if (unformat (i, "bd_id %d", &bd_id))
4717         ;
4718       else if (unformat (i, "flood %d", &flood))
4719         ;
4720       else if (unformat (i, "uu-flood %d", &uu_flood))
4721         ;
4722       else if (unformat (i, "forward %d", &forward))
4723         ;
4724       else if (unformat (i, "learn %d", &learn))
4725         ;
4726       else if (unformat (i, "arp-term %d", &arp_term))
4727         ;
4728       else if (unformat (i, "mac-age %d", &mac_age))
4729         ;
4730       else if (unformat (i, "bd-tag %s", &bd_tag))
4731         ;
4732       else if (unformat (i, "del"))
4733         {
4734           is_add = 0;
4735           flood = uu_flood = forward = learn = 0;
4736         }
4737       else
4738         break;
4739     }
4740
4741   if (bd_id == ~0)
4742     {
4743       errmsg ("missing bridge domain");
4744       ret = -99;
4745       goto done;
4746     }
4747
4748   if (mac_age > 255)
4749     {
4750       errmsg ("mac age must be less than 256 ");
4751       ret = -99;
4752       goto done;
4753     }
4754
4755   if ((bd_tag) && (vec_len (bd_tag) > 63))
4756     {
4757       errmsg ("bd-tag cannot be longer than 63");
4758       ret = -99;
4759       goto done;
4760     }
4761
4762   M (BRIDGE_DOMAIN_ADD_DEL, mp);
4763
4764   mp->bd_id = ntohl (bd_id);
4765   mp->flood = flood;
4766   mp->uu_flood = uu_flood;
4767   mp->forward = forward;
4768   mp->learn = learn;
4769   mp->arp_term = arp_term;
4770   mp->is_add = is_add;
4771   mp->mac_age = (u8) mac_age;
4772   if (bd_tag)
4773     {
4774       clib_memcpy (mp->bd_tag, bd_tag, vec_len (bd_tag));
4775       mp->bd_tag[vec_len (bd_tag)] = 0;
4776     }
4777   S (mp);
4778   W (ret);
4779
4780 done:
4781   vec_free (bd_tag);
4782   return ret;
4783 }
4784
4785 static int
4786 api_l2fib_flush_bd (vat_main_t * vam)
4787 {
4788   unformat_input_t *i = vam->input;
4789   vl_api_l2fib_flush_bd_t *mp;
4790   u32 bd_id = ~0;
4791   int ret;
4792
4793   /* Parse args required to build the message */
4794   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4795     {
4796       if (unformat (i, "bd_id %d", &bd_id));
4797       else
4798         break;
4799     }
4800
4801   if (bd_id == ~0)
4802     {
4803       errmsg ("missing bridge domain");
4804       return -99;
4805     }
4806
4807   M (L2FIB_FLUSH_BD, mp);
4808
4809   mp->bd_id = htonl (bd_id);
4810
4811   S (mp);
4812   W (ret);
4813   return ret;
4814 }
4815
4816 static int
4817 api_l2fib_flush_int (vat_main_t * vam)
4818 {
4819   unformat_input_t *i = vam->input;
4820   vl_api_l2fib_flush_int_t *mp;
4821   u32 sw_if_index = ~0;
4822   int ret;
4823
4824   /* Parse args required to build the message */
4825   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4826     {
4827       if (unformat (i, "sw_if_index %d", &sw_if_index));
4828       else
4829         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index));
4830       else
4831         break;
4832     }
4833
4834   if (sw_if_index == ~0)
4835     {
4836       errmsg ("missing interface name or sw_if_index");
4837       return -99;
4838     }
4839
4840   M (L2FIB_FLUSH_INT, mp);
4841
4842   mp->sw_if_index = ntohl (sw_if_index);
4843
4844   S (mp);
4845   W (ret);
4846   return ret;
4847 }
4848
4849 static int
4850 api_l2fib_add_del (vat_main_t * vam)
4851 {
4852   unformat_input_t *i = vam->input;
4853   vl_api_l2fib_add_del_t *mp;
4854   f64 timeout;
4855   u8 mac[6] = { 0 };
4856   u8 mac_set = 0;
4857   u32 bd_id;
4858   u8 bd_id_set = 0;
4859   u32 sw_if_index = 0;
4860   u8 sw_if_index_set = 0;
4861   u8 is_add = 1;
4862   u8 static_mac = 0;
4863   u8 filter_mac = 0;
4864   u8 bvi_mac = 0;
4865   int count = 1;
4866   f64 before = 0;
4867   int j;
4868
4869   /* Parse args required to build the message */
4870   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4871     {
4872       if (unformat (i, "mac %U", unformat_ethernet_address, mac))
4873         mac_set = 1;
4874       else if (unformat (i, "bd_id %d", &bd_id))
4875         bd_id_set = 1;
4876       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4877         sw_if_index_set = 1;
4878       else if (unformat (i, "sw_if"))
4879         {
4880           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4881             {
4882               if (unformat
4883                   (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4884                 sw_if_index_set = 1;
4885             }
4886           else
4887             break;
4888         }
4889       else if (unformat (i, "static"))
4890         static_mac = 1;
4891       else if (unformat (i, "filter"))
4892         {
4893           filter_mac = 1;
4894           static_mac = 1;
4895         }
4896       else if (unformat (i, "bvi"))
4897         {
4898           bvi_mac = 1;
4899           static_mac = 1;
4900         }
4901       else if (unformat (i, "del"))
4902         is_add = 0;
4903       else if (unformat (i, "count %d", &count))
4904         ;
4905       else
4906         break;
4907     }
4908
4909   if (mac_set == 0)
4910     {
4911       errmsg ("missing mac address");
4912       return -99;
4913     }
4914
4915   if (bd_id_set == 0)
4916     {
4917       errmsg ("missing bridge domain");
4918       return -99;
4919     }
4920
4921   if (is_add && sw_if_index_set == 0 && filter_mac == 0)
4922     {
4923       errmsg ("missing interface name or sw_if_index");
4924       return -99;
4925     }
4926
4927   if (count > 1)
4928     {
4929       /* Turn on async mode */
4930       vam->async_mode = 1;
4931       vam->async_errors = 0;
4932       before = vat_time_now (vam);
4933     }
4934
4935   for (j = 0; j < count; j++)
4936     {
4937       M (L2FIB_ADD_DEL, mp);
4938
4939       clib_memcpy (mp->mac, mac, 6);
4940       mp->bd_id = ntohl (bd_id);
4941       mp->is_add = is_add;
4942       mp->sw_if_index = ntohl (sw_if_index);
4943
4944       if (is_add)
4945         {
4946           mp->static_mac = static_mac;
4947           mp->filter_mac = filter_mac;
4948           mp->bvi_mac = bvi_mac;
4949         }
4950       increment_mac_address (mac);
4951       /* send it... */
4952       S (mp);
4953     }
4954
4955   if (count > 1)
4956     {
4957       vl_api_control_ping_t *mp_ping;
4958       f64 after;
4959
4960       /* Shut off async mode */
4961       vam->async_mode = 0;
4962
4963       MPING (CONTROL_PING, mp_ping);
4964       S (mp_ping);
4965
4966       timeout = vat_time_now (vam) + 1.0;
4967       while (vat_time_now (vam) < timeout)
4968         if (vam->result_ready == 1)
4969           goto out;
4970       vam->retval = -99;
4971
4972     out:
4973       if (vam->retval == -99)
4974         errmsg ("timeout");
4975
4976       if (vam->async_errors > 0)
4977         {
4978           errmsg ("%d asynchronous errors", vam->async_errors);
4979           vam->retval = -98;
4980         }
4981       vam->async_errors = 0;
4982       after = vat_time_now (vam);
4983
4984       print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec",
4985              count, after - before, count / (after - before));
4986     }
4987   else
4988     {
4989       int ret;
4990
4991       /* Wait for a reply... */
4992       W (ret);
4993       return ret;
4994     }
4995   /* Return the good/bad news */
4996   return (vam->retval);
4997 }
4998
4999 static int
5000 api_bridge_domain_set_mac_age (vat_main_t * vam)
5001 {
5002   unformat_input_t *i = vam->input;
5003   vl_api_bridge_domain_set_mac_age_t *mp;
5004   u32 bd_id = ~0;
5005   u32 mac_age = 0;
5006   int ret;
5007
5008   /* Parse args required to build the message */
5009   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5010     {
5011       if (unformat (i, "bd_id %d", &bd_id));
5012       else if (unformat (i, "mac-age %d", &mac_age));
5013       else
5014         break;
5015     }
5016
5017   if (bd_id == ~0)
5018     {
5019       errmsg ("missing bridge domain");
5020       return -99;
5021     }
5022
5023   if (mac_age > 255)
5024     {
5025       errmsg ("mac age must be less than 256 ");
5026       return -99;
5027     }
5028
5029   M (BRIDGE_DOMAIN_SET_MAC_AGE, mp);
5030
5031   mp->bd_id = htonl (bd_id);
5032   mp->mac_age = (u8) mac_age;
5033
5034   S (mp);
5035   W (ret);
5036   return ret;
5037 }
5038
5039 static int
5040 api_l2_flags (vat_main_t * vam)
5041 {
5042   unformat_input_t *i = vam->input;
5043   vl_api_l2_flags_t *mp;
5044   u32 sw_if_index;
5045   u32 flags = 0;
5046   u8 sw_if_index_set = 0;
5047   u8 is_set = 0;
5048   int ret;
5049
5050   /* Parse args required to build the message */
5051   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5052     {
5053       if (unformat (i, "sw_if_index %d", &sw_if_index))
5054         sw_if_index_set = 1;
5055       else if (unformat (i, "sw_if"))
5056         {
5057           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5058             {
5059               if (unformat
5060                   (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5061                 sw_if_index_set = 1;
5062             }
5063           else
5064             break;
5065         }
5066       else if (unformat (i, "learn"))
5067         flags |= L2_LEARN;
5068       else if (unformat (i, "forward"))
5069         flags |= L2_FWD;
5070       else if (unformat (i, "flood"))
5071         flags |= L2_FLOOD;
5072       else if (unformat (i, "uu-flood"))
5073         flags |= L2_UU_FLOOD;
5074       else if (unformat (i, "arp-term"))
5075         flags |= L2_ARP_TERM;
5076       else if (unformat (i, "off"))
5077         is_set = 0;
5078       else if (unformat (i, "disable"))
5079         is_set = 0;
5080       else
5081         break;
5082     }
5083
5084   if (sw_if_index_set == 0)
5085     {
5086       errmsg ("missing interface name or sw_if_index");
5087       return -99;
5088     }
5089
5090   M (L2_FLAGS, mp);
5091
5092   mp->sw_if_index = ntohl (sw_if_index);
5093   mp->feature_bitmap = ntohl (flags);
5094   mp->is_set = is_set;
5095
5096   S (mp);
5097   W (ret);
5098   return ret;
5099 }
5100
5101 static int
5102 api_bridge_flags (vat_main_t * vam)
5103 {
5104   unformat_input_t *i = vam->input;
5105   vl_api_bridge_flags_t *mp;
5106   u32 bd_id;
5107   u8 bd_id_set = 0;
5108   u8 is_set = 1;
5109   bd_flags_t flags = 0;
5110   int ret;
5111
5112   /* Parse args required to build the message */
5113   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5114     {
5115       if (unformat (i, "bd_id %d", &bd_id))
5116         bd_id_set = 1;
5117       else if (unformat (i, "learn"))
5118         flags |= BRIDGE_API_FLAG_LEARN;
5119       else if (unformat (i, "forward"))
5120         flags |= BRIDGE_API_FLAG_FWD;
5121       else if (unformat (i, "flood"))
5122         flags |= BRIDGE_API_FLAG_FLOOD;
5123       else if (unformat (i, "uu-flood"))
5124         flags |= BRIDGE_API_FLAG_UU_FLOOD;
5125       else if (unformat (i, "arp-term"))
5126         flags |= BRIDGE_API_FLAG_ARP_TERM;
5127       else if (unformat (i, "off"))
5128         is_set = 0;
5129       else if (unformat (i, "disable"))
5130         is_set = 0;
5131       else
5132         break;
5133     }
5134
5135   if (bd_id_set == 0)
5136     {
5137       errmsg ("missing bridge domain");
5138       return -99;
5139     }
5140
5141   M (BRIDGE_FLAGS, mp);
5142
5143   mp->bd_id = ntohl (bd_id);
5144   mp->flags = ntohl (flags);
5145   mp->is_set = is_set;
5146
5147   S (mp);
5148   W (ret);
5149   return ret;
5150 }
5151
5152 static int
5153 api_bd_ip_mac_add_del (vat_main_t * vam)
5154 {
5155   vl_api_address_t ip = VL_API_ZERO_ADDRESS;
5156   vl_api_mac_address_t mac = { 0 };
5157   unformat_input_t *i = vam->input;
5158   vl_api_bd_ip_mac_add_del_t *mp;
5159   u32 bd_id;
5160   u8 is_add = 1;
5161   u8 bd_id_set = 0;
5162   u8 ip_set = 0;
5163   u8 mac_set = 0;
5164   int ret;
5165
5166
5167   /* Parse args required to build the message */
5168   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5169     {
5170       if (unformat (i, "bd_id %d", &bd_id))
5171         {
5172           bd_id_set++;
5173         }
5174       else if (unformat (i, "%U", unformat_vl_api_address, &ip))
5175         {
5176           ip_set++;
5177         }
5178       else if (unformat (i, "%U", unformat_vl_api_mac_address, &mac))
5179         {
5180           mac_set++;
5181         }
5182       else if (unformat (i, "del"))
5183         is_add = 0;
5184       else
5185         break;
5186     }
5187
5188   if (bd_id_set == 0)
5189     {
5190       errmsg ("missing bridge domain");
5191       return -99;
5192     }
5193   else if (ip_set == 0)
5194     {
5195       errmsg ("missing IP address");
5196       return -99;
5197     }
5198   else if (mac_set == 0)
5199     {
5200       errmsg ("missing MAC address");
5201       return -99;
5202     }
5203
5204   M (BD_IP_MAC_ADD_DEL, mp);
5205
5206   mp->entry.bd_id = ntohl (bd_id);
5207   mp->is_add = is_add;
5208
5209   clib_memcpy (&mp->entry.ip, &ip, sizeof (ip));
5210   clib_memcpy (&mp->entry.mac, &mac, sizeof (mac));
5211
5212   S (mp);
5213   W (ret);
5214   return ret;
5215 }
5216
5217 static int
5218 api_bd_ip_mac_flush (vat_main_t * vam)
5219 {
5220   unformat_input_t *i = vam->input;
5221   vl_api_bd_ip_mac_flush_t *mp;
5222   u32 bd_id;
5223   u8 bd_id_set = 0;
5224   int ret;
5225
5226   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5227     {
5228       if (unformat (i, "bd_id %d", &bd_id))
5229         {
5230           bd_id_set++;
5231         }
5232       else
5233         break;
5234     }
5235
5236   if (bd_id_set == 0)
5237     {
5238       errmsg ("missing bridge domain");
5239       return -99;
5240     }
5241
5242   M (BD_IP_MAC_FLUSH, mp);
5243
5244   mp->bd_id = ntohl (bd_id);
5245
5246   S (mp);
5247   W (ret);
5248   return ret;
5249 }
5250
5251 static void vl_api_bd_ip_mac_details_t_handler
5252   (vl_api_bd_ip_mac_details_t * mp)
5253 {
5254   vat_main_t *vam = &vat_main;
5255
5256   print (vam->ofp,
5257          "\n%-5d %U %U",
5258          ntohl (mp->entry.bd_id),
5259          format_vl_api_mac_address, mp->entry.mac,
5260          format_vl_api_address, &mp->entry.ip);
5261 }
5262
5263 static void vl_api_bd_ip_mac_details_t_handler_json
5264   (vl_api_bd_ip_mac_details_t * mp)
5265 {
5266   vat_main_t *vam = &vat_main;
5267   vat_json_node_t *node = NULL;
5268
5269   if (VAT_JSON_ARRAY != vam->json_tree.type)
5270     {
5271       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
5272       vat_json_init_array (&vam->json_tree);
5273     }
5274   node = vat_json_array_add (&vam->json_tree);
5275
5276   vat_json_init_object (node);
5277   vat_json_object_add_uint (node, "bd_id", ntohl (mp->entry.bd_id));
5278   vat_json_object_add_string_copy (node, "mac_address",
5279                                    format (0, "%U", format_vl_api_mac_address,
5280                                            &mp->entry.mac));
5281   u8 *ip = 0;
5282
5283   ip = format (0, "%U", format_vl_api_address, &mp->entry.ip);
5284   vat_json_object_add_string_copy (node, "ip_address", ip);
5285   vec_free (ip);
5286 }
5287
5288 static int
5289 api_bd_ip_mac_dump (vat_main_t * vam)
5290 {
5291   unformat_input_t *i = vam->input;
5292   vl_api_bd_ip_mac_dump_t *mp;
5293   vl_api_control_ping_t *mp_ping;
5294   int ret;
5295   u32 bd_id;
5296   u8 bd_id_set = 0;
5297
5298   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5299     {
5300       if (unformat (i, "bd_id %d", &bd_id))
5301         {
5302           bd_id_set++;
5303         }
5304       else
5305         break;
5306     }
5307
5308   print (vam->ofp,
5309          "\n%-5s %-7s %-20s %-30s",
5310          "bd_id", "is_ipv6", "mac_address", "ip_address");
5311
5312   /* Dump Bridge Domain Ip to Mac entries */
5313   M (BD_IP_MAC_DUMP, mp);
5314
5315   if (bd_id_set)
5316     mp->bd_id = htonl (bd_id);
5317   else
5318     mp->bd_id = ~0;
5319
5320   S (mp);
5321
5322   /* Use a control ping for synchronization */
5323   MPING (CONTROL_PING, mp_ping);
5324   S (mp_ping);
5325
5326   W (ret);
5327   return ret;
5328 }
5329
5330 static int
5331 api_tap_create_v2 (vat_main_t * vam)
5332 {
5333   unformat_input_t *i = vam->input;
5334   vl_api_tap_create_v2_t *mp;
5335   u8 mac_address[6];
5336   u8 random_mac = 1;
5337   u32 id = ~0;
5338   u32 num_rx_queues = 0;
5339   u8 *host_if_name = 0;
5340   u8 host_if_name_set = 0;
5341   u8 *host_ns = 0;
5342   u8 host_ns_set = 0;
5343   u8 host_mac_addr[6];
5344   u8 host_mac_addr_set = 0;
5345   u8 *host_bridge = 0;
5346   u8 host_bridge_set = 0;
5347   u8 host_ip4_prefix_set = 0;
5348   u8 host_ip6_prefix_set = 0;
5349   ip4_address_t host_ip4_addr;
5350   ip4_address_t host_ip4_gw;
5351   u8 host_ip4_gw_set = 0;
5352   u32 host_ip4_prefix_len = 0;
5353   ip6_address_t host_ip6_addr;
5354   ip6_address_t host_ip6_gw;
5355   u8 host_ip6_gw_set = 0;
5356   u32 host_ip6_prefix_len = 0;
5357   u32 host_mtu_size = 0;
5358   u8 host_mtu_set = 0;
5359   u32 tap_flags = 0;
5360   int ret;
5361   u32 rx_ring_sz = 0, tx_ring_sz = 0;
5362
5363   clib_memset (mac_address, 0, sizeof (mac_address));
5364
5365   /* Parse args required to build the message */
5366   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5367     {
5368       if (unformat (i, "id %u", &id))
5369         ;
5370       else
5371         if (unformat
5372             (i, "hw-addr %U", unformat_ethernet_address, mac_address))
5373         random_mac = 0;
5374       else if (unformat (i, "host-if-name %s", &host_if_name))
5375         host_if_name_set = 1;
5376       else if (unformat (i, "num-rx-queues %u", &num_rx_queues))
5377         ;
5378       else if (unformat (i, "host-ns %s", &host_ns))
5379         host_ns_set = 1;
5380       else if (unformat (i, "host-mac-addr %U", unformat_ethernet_address,
5381                          host_mac_addr))
5382         host_mac_addr_set = 1;
5383       else if (unformat (i, "host-bridge %s", &host_bridge))
5384         host_bridge_set = 1;
5385       else if (unformat (i, "host-ip4-addr %U/%u", unformat_ip4_address,
5386                          &host_ip4_addr, &host_ip4_prefix_len))
5387         host_ip4_prefix_set = 1;
5388       else if (unformat (i, "host-ip6-addr %U/%u", unformat_ip6_address,
5389                          &host_ip6_addr, &host_ip6_prefix_len))
5390         host_ip6_prefix_set = 1;
5391       else if (unformat (i, "host-ip4-gw %U", unformat_ip4_address,
5392                          &host_ip4_gw))
5393         host_ip4_gw_set = 1;
5394       else if (unformat (i, "host-ip6-gw %U", unformat_ip6_address,
5395                          &host_ip6_gw))
5396         host_ip6_gw_set = 1;
5397       else if (unformat (i, "rx-ring-size %u", &rx_ring_sz))
5398         ;
5399       else if (unformat (i, "tx-ring-size %u", &tx_ring_sz))
5400         ;
5401       else if (unformat (i, "host-mtu-size %u", &host_mtu_size))
5402         host_mtu_set = 1;
5403       else if (unformat (i, "no-gso"))
5404         tap_flags &= ~TAP_API_FLAG_GSO;
5405       else if (unformat (i, "gso"))
5406         tap_flags |= TAP_API_FLAG_GSO;
5407       else if (unformat (i, "csum-offload"))
5408         tap_flags |= TAP_API_FLAG_CSUM_OFFLOAD;
5409       else if (unformat (i, "persist"))
5410         tap_flags |= TAP_API_FLAG_PERSIST;
5411       else if (unformat (i, "attach"))
5412         tap_flags |= TAP_API_FLAG_ATTACH;
5413       else if (unformat (i, "tun"))
5414         tap_flags |= TAP_API_FLAG_TUN;
5415       else if (unformat (i, "gro-coalesce"))
5416         tap_flags |= TAP_API_FLAG_GRO_COALESCE;
5417       else if (unformat (i, "packed"))
5418         tap_flags |= TAP_API_FLAG_PACKED;
5419       else if (unformat (i, "in-order"))
5420         tap_flags |= TAP_API_FLAG_IN_ORDER;
5421       else
5422         break;
5423     }
5424
5425   if (vec_len (host_if_name) > 63)
5426     {
5427       errmsg ("tap name too long. ");
5428       return -99;
5429     }
5430   if (vec_len (host_ns) > 63)
5431     {
5432       errmsg ("host name space too long. ");
5433       return -99;
5434     }
5435   if (vec_len (host_bridge) > 63)
5436     {
5437       errmsg ("host bridge name too long. ");
5438       return -99;
5439     }
5440   if (host_ip4_prefix_len > 32)
5441     {
5442       errmsg ("host ip4 prefix length not valid. ");
5443       return -99;
5444     }
5445   if (host_ip6_prefix_len > 128)
5446     {
5447       errmsg ("host ip6 prefix length not valid. ");
5448       return -99;
5449     }
5450   if (!is_pow2 (rx_ring_sz))
5451     {
5452       errmsg ("rx ring size must be power of 2. ");
5453       return -99;
5454     }
5455   if (rx_ring_sz > 32768)
5456     {
5457       errmsg ("rx ring size must be 32768 or lower. ");
5458       return -99;
5459     }
5460   if (!is_pow2 (tx_ring_sz))
5461     {
5462       errmsg ("tx ring size must be power of 2. ");
5463       return -99;
5464     }
5465   if (tx_ring_sz > 32768)
5466     {
5467       errmsg ("tx ring size must be 32768 or lower. ");
5468       return -99;
5469     }
5470   if (host_mtu_set && (host_mtu_size < 64 || host_mtu_size > 65355))
5471     {
5472       errmsg ("host MTU size must be in between 64 and 65355. ");
5473       return -99;
5474     }
5475
5476   /* Construct the API message */
5477   M (TAP_CREATE_V2, mp);
5478
5479   mp->id = ntohl (id);
5480   mp->use_random_mac = random_mac;
5481   mp->num_rx_queues = (u8) num_rx_queues;
5482   mp->tx_ring_sz = ntohs (tx_ring_sz);
5483   mp->rx_ring_sz = ntohs (rx_ring_sz);
5484   mp->host_mtu_set = host_mtu_set;
5485   mp->host_mtu_size = ntohl (host_mtu_size);
5486   mp->host_mac_addr_set = host_mac_addr_set;
5487   mp->host_ip4_prefix_set = host_ip4_prefix_set;
5488   mp->host_ip6_prefix_set = host_ip6_prefix_set;
5489   mp->host_ip4_gw_set = host_ip4_gw_set;
5490   mp->host_ip6_gw_set = host_ip6_gw_set;
5491   mp->tap_flags = ntohl (tap_flags);
5492   mp->host_namespace_set = host_ns_set;
5493   mp->host_if_name_set = host_if_name_set;
5494   mp->host_bridge_set = host_bridge_set;
5495
5496   if (random_mac == 0)
5497     clib_memcpy (mp->mac_address, mac_address, 6);
5498   if (host_mac_addr_set)
5499     clib_memcpy (mp->host_mac_addr, host_mac_addr, 6);
5500   if (host_if_name_set)
5501     clib_memcpy (mp->host_if_name, host_if_name, vec_len (host_if_name));
5502   if (host_ns_set)
5503     clib_memcpy (mp->host_namespace, host_ns, vec_len (host_ns));
5504   if (host_bridge_set)
5505     clib_memcpy (mp->host_bridge, host_bridge, vec_len (host_bridge));
5506   if (host_ip4_prefix_set)
5507     {
5508       clib_memcpy (mp->host_ip4_prefix.address, &host_ip4_addr, 4);
5509       mp->host_ip4_prefix.len = (u8) host_ip4_prefix_len;
5510     }
5511   if (host_ip6_prefix_set)
5512     {
5513       clib_memcpy (mp->host_ip6_prefix.address, &host_ip6_addr, 16);
5514       mp->host_ip6_prefix.len = (u8) host_ip6_prefix_len;
5515     }
5516   if (host_ip4_gw_set)
5517     clib_memcpy (mp->host_ip4_gw, &host_ip4_gw, 4);
5518   if (host_ip6_gw_set)
5519     clib_memcpy (mp->host_ip6_gw, &host_ip6_gw, 16);
5520
5521   vec_free (host_ns);
5522   vec_free (host_if_name);
5523   vec_free (host_bridge);
5524
5525   /* send it... */
5526   S (mp);
5527
5528   /* Wait for a reply... */
5529   W (ret);
5530   return ret;
5531 }
5532
5533 static int
5534 api_tap_delete_v2 (vat_main_t * vam)
5535 {
5536   unformat_input_t *i = vam->input;
5537   vl_api_tap_delete_v2_t *mp;
5538   u32 sw_if_index = ~0;
5539   u8 sw_if_index_set = 0;
5540   int ret;
5541
5542   /* Parse args required to build the message */
5543   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5544     {
5545       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5546         sw_if_index_set = 1;
5547       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5548         sw_if_index_set = 1;
5549       else
5550         break;
5551     }
5552
5553   if (sw_if_index_set == 0)
5554     {
5555       errmsg ("missing vpp interface name. ");
5556       return -99;
5557     }
5558
5559   /* Construct the API message */
5560   M (TAP_DELETE_V2, mp);
5561
5562   mp->sw_if_index = ntohl (sw_if_index);
5563
5564   /* send it... */
5565   S (mp);
5566
5567   /* Wait for a reply... */
5568   W (ret);
5569   return ret;
5570 }
5571
5572 uword
5573 unformat_vlib_pci_addr (unformat_input_t * input, va_list * args)
5574 {
5575   vlib_pci_addr_t *addr = va_arg (*args, vlib_pci_addr_t *);
5576   u32 x[4];
5577
5578   if (!unformat (input, "%x:%x:%x.%x", &x[0], &x[1], &x[2], &x[3]))
5579     return 0;
5580
5581   addr->domain = x[0];
5582   addr->bus = x[1];
5583   addr->slot = x[2];
5584   addr->function = x[3];
5585
5586   return 1;
5587 }
5588
5589 static int
5590 api_virtio_pci_create_v2 (vat_main_t * vam)
5591 {
5592   unformat_input_t *i = vam->input;
5593   vl_api_virtio_pci_create_v2_t *mp;
5594   u8 mac_address[6];
5595   u8 random_mac = 1;
5596   u32 pci_addr = 0;
5597   u64 features = (u64) ~ (0ULL);
5598   u32 virtio_flags = 0;
5599   int ret;
5600
5601   clib_memset (mac_address, 0, sizeof (mac_address));
5602
5603   /* Parse args required to build the message */
5604   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5605     {
5606       if (unformat (i, "hw-addr %U", unformat_ethernet_address, mac_address))
5607         {
5608           random_mac = 0;
5609         }
5610       else if (unformat (i, "pci-addr %U", unformat_vlib_pci_addr, &pci_addr))
5611         ;
5612       else if (unformat (i, "features 0x%llx", &features))
5613         ;
5614       else if (unformat (i, "gso-enabled"))
5615         virtio_flags |= VIRTIO_API_FLAG_GSO;
5616       else if (unformat (i, "csum-offload-enabled"))
5617         virtio_flags |= VIRTIO_API_FLAG_CSUM_OFFLOAD;
5618       else if (unformat (i, "gro-coalesce"))
5619         virtio_flags |= VIRTIO_API_FLAG_GRO_COALESCE;
5620       else if (unformat (i, "packed"))
5621         virtio_flags |= VIRTIO_API_FLAG_PACKED;
5622       else if (unformat (i, "in-order"))
5623         virtio_flags |= VIRTIO_API_FLAG_IN_ORDER;
5624       else if (unformat (i, "buffering"))
5625         virtio_flags |= VIRTIO_API_FLAG_BUFFERING;
5626       else
5627         break;
5628     }
5629
5630   if (pci_addr == 0)
5631     {
5632       errmsg ("pci address must be non zero. ");
5633       return -99;
5634     }
5635
5636   /* Construct the API message */
5637   M (VIRTIO_PCI_CREATE_V2, mp);
5638
5639   mp->use_random_mac = random_mac;
5640
5641   mp->pci_addr.domain = htons (((vlib_pci_addr_t) pci_addr).domain);
5642   mp->pci_addr.bus = ((vlib_pci_addr_t) pci_addr).bus;
5643   mp->pci_addr.slot = ((vlib_pci_addr_t) pci_addr).slot;
5644   mp->pci_addr.function = ((vlib_pci_addr_t) pci_addr).function;
5645
5646   mp->features = clib_host_to_net_u64 (features);
5647   mp->virtio_flags = clib_host_to_net_u32 (virtio_flags);
5648
5649   if (random_mac == 0)
5650     clib_memcpy (mp->mac_address, mac_address, 6);
5651
5652   /* send it... */
5653   S (mp);
5654
5655   /* Wait for a reply... */
5656   W (ret);
5657   return ret;
5658 }
5659
5660 static int
5661 api_virtio_pci_delete (vat_main_t * vam)
5662 {
5663   unformat_input_t *i = vam->input;
5664   vl_api_virtio_pci_delete_t *mp;
5665   u32 sw_if_index = ~0;
5666   u8 sw_if_index_set = 0;
5667   int ret;
5668
5669   /* Parse args required to build the message */
5670   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5671     {
5672       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5673         sw_if_index_set = 1;
5674       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5675         sw_if_index_set = 1;
5676       else
5677         break;
5678     }
5679
5680   if (sw_if_index_set == 0)
5681     {
5682       errmsg ("missing vpp interface name. ");
5683       return -99;
5684     }
5685
5686   /* Construct the API message */
5687   M (VIRTIO_PCI_DELETE, mp);
5688
5689   mp->sw_if_index = htonl (sw_if_index);
5690
5691   /* send it... */
5692   S (mp);
5693
5694   /* Wait for a reply... */
5695   W (ret);
5696   return ret;
5697 }
5698
5699 static int
5700 api_bond_create (vat_main_t * vam)
5701 {
5702   unformat_input_t *i = vam->input;
5703   vl_api_bond_create_t *mp;
5704   u8 mac_address[6];
5705   u8 custom_mac = 0;
5706   int ret;
5707   u8 mode;
5708   u8 lb;
5709   u8 mode_is_set = 0;
5710   u32 id = ~0;
5711   u8 numa_only = 0;
5712
5713   clib_memset (mac_address, 0, sizeof (mac_address));
5714   lb = BOND_LB_L2;
5715
5716   /* Parse args required to build the message */
5717   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5718     {
5719       if (unformat (i, "mode %U", unformat_bond_mode, &mode))
5720         mode_is_set = 1;
5721       else if (((mode == BOND_MODE_LACP) || (mode == BOND_MODE_XOR))
5722                && unformat (i, "lb %U", unformat_bond_load_balance, &lb))
5723         ;
5724       else if (unformat (i, "hw-addr %U", unformat_ethernet_address,
5725                          mac_address))
5726         custom_mac = 1;
5727       else if (unformat (i, "numa-only"))
5728         numa_only = 1;
5729       else if (unformat (i, "id %u", &id))
5730         ;
5731       else
5732         break;
5733     }
5734
5735   if (mode_is_set == 0)
5736     {
5737       errmsg ("Missing bond mode. ");
5738       return -99;
5739     }
5740
5741   /* Construct the API message */
5742   M (BOND_CREATE, mp);
5743
5744   mp->use_custom_mac = custom_mac;
5745
5746   mp->mode = htonl (mode);
5747   mp->lb = htonl (lb);
5748   mp->id = htonl (id);
5749   mp->numa_only = numa_only;
5750
5751   if (custom_mac)
5752     clib_memcpy (mp->mac_address, mac_address, 6);
5753
5754   /* send it... */
5755   S (mp);
5756
5757   /* Wait for a reply... */
5758   W (ret);
5759   return ret;
5760 }
5761
5762 static int
5763 api_bond_create2 (vat_main_t * vam)
5764 {
5765   unformat_input_t *i = vam->input;
5766   vl_api_bond_create2_t *mp;
5767   u8 mac_address[6];
5768   u8 custom_mac = 0;
5769   int ret;
5770   u8 mode;
5771   u8 lb;
5772   u8 mode_is_set = 0;
5773   u32 id = ~0;
5774   u8 numa_only = 0;
5775   u8 gso = 0;
5776
5777   clib_memset (mac_address, 0, sizeof (mac_address));
5778   lb = BOND_LB_L2;
5779
5780   /* Parse args required to build the message */
5781   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5782     {
5783       if (unformat (i, "mode %U", unformat_bond_mode, &mode))
5784         mode_is_set = 1;
5785       else if (((mode == BOND_MODE_LACP) || (mode == BOND_MODE_XOR))
5786                && unformat (i, "lb %U", unformat_bond_load_balance, &lb))
5787         ;
5788       else if (unformat (i, "hw-addr %U", unformat_ethernet_address,
5789                          mac_address))
5790         custom_mac = 1;
5791       else if (unformat (i, "numa-only"))
5792         numa_only = 1;
5793       else if (unformat (i, "gso"))
5794         gso = 1;
5795       else if (unformat (i, "id %u", &id))
5796         ;
5797       else
5798         break;
5799     }
5800
5801   if (mode_is_set == 0)
5802     {
5803       errmsg ("Missing bond mode. ");
5804       return -99;
5805     }
5806
5807   /* Construct the API message */
5808   M (BOND_CREATE2, mp);
5809
5810   mp->use_custom_mac = custom_mac;
5811
5812   mp->mode = htonl (mode);
5813   mp->lb = htonl (lb);
5814   mp->id = htonl (id);
5815   mp->numa_only = numa_only;
5816   mp->enable_gso = gso;
5817
5818   if (custom_mac)
5819     clib_memcpy (mp->mac_address, mac_address, 6);
5820
5821   /* send it... */
5822   S (mp);
5823
5824   /* Wait for a reply... */
5825   W (ret);
5826   return ret;
5827 }
5828
5829 static int
5830 api_bond_delete (vat_main_t * vam)
5831 {
5832   unformat_input_t *i = vam->input;
5833   vl_api_bond_delete_t *mp;
5834   u32 sw_if_index = ~0;
5835   u8 sw_if_index_set = 0;
5836   int ret;
5837
5838   /* Parse args required to build the message */
5839   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5840     {
5841       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5842         sw_if_index_set = 1;
5843       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5844         sw_if_index_set = 1;
5845       else
5846         break;
5847     }
5848
5849   if (sw_if_index_set == 0)
5850     {
5851       errmsg ("missing vpp interface name. ");
5852       return -99;
5853     }
5854
5855   /* Construct the API message */
5856   M (BOND_DELETE, mp);
5857
5858   mp->sw_if_index = ntohl (sw_if_index);
5859
5860   /* send it... */
5861   S (mp);
5862
5863   /* Wait for a reply... */
5864   W (ret);
5865   return ret;
5866 }
5867
5868 static int
5869 api_bond_add_member (vat_main_t * vam)
5870 {
5871   unformat_input_t *i = vam->input;
5872   vl_api_bond_add_member_t *mp;
5873   u32 bond_sw_if_index;
5874   int ret;
5875   u8 is_passive;
5876   u8 is_long_timeout;
5877   u32 bond_sw_if_index_is_set = 0;
5878   u32 sw_if_index;
5879   u8 sw_if_index_is_set = 0;
5880
5881   /* Parse args required to build the message */
5882   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5883     {
5884       if (unformat (i, "sw_if_index %d", &sw_if_index))
5885         sw_if_index_is_set = 1;
5886       else if (unformat (i, "bond %u", &bond_sw_if_index))
5887         bond_sw_if_index_is_set = 1;
5888       else if (unformat (i, "passive %d", &is_passive))
5889         ;
5890       else if (unformat (i, "long-timeout %d", &is_long_timeout))
5891         ;
5892       else
5893         break;
5894     }
5895
5896   if (bond_sw_if_index_is_set == 0)
5897     {
5898       errmsg ("Missing bond sw_if_index. ");
5899       return -99;
5900     }
5901   if (sw_if_index_is_set == 0)
5902     {
5903       errmsg ("Missing member sw_if_index. ");
5904       return -99;
5905     }
5906
5907   /* Construct the API message */
5908   M (BOND_ADD_MEMBER, mp);
5909
5910   mp->bond_sw_if_index = ntohl (bond_sw_if_index);
5911   mp->sw_if_index = ntohl (sw_if_index);
5912   mp->is_long_timeout = is_long_timeout;
5913   mp->is_passive = is_passive;
5914
5915   /* send it... */
5916   S (mp);
5917
5918   /* Wait for a reply... */
5919   W (ret);
5920   return ret;
5921 }
5922
5923 static int
5924 api_bond_detach_member (vat_main_t * vam)
5925 {
5926   unformat_input_t *i = vam->input;
5927   vl_api_bond_detach_member_t *mp;
5928   u32 sw_if_index = ~0;
5929   u8 sw_if_index_set = 0;
5930   int ret;
5931
5932   /* Parse args required to build the message */
5933   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5934     {
5935       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5936         sw_if_index_set = 1;
5937       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5938         sw_if_index_set = 1;
5939       else
5940         break;
5941     }
5942
5943   if (sw_if_index_set == 0)
5944     {
5945       errmsg ("missing vpp interface name. ");
5946       return -99;
5947     }
5948
5949   /* Construct the API message */
5950   M (BOND_DETACH_MEMBER, mp);
5951
5952   mp->sw_if_index = ntohl (sw_if_index);
5953
5954   /* send it... */
5955   S (mp);
5956
5957   /* Wait for a reply... */
5958   W (ret);
5959   return ret;
5960 }
5961
5962 static int
5963 api_ip_table_add_del (vat_main_t * vam)
5964 {
5965   unformat_input_t *i = vam->input;
5966   vl_api_ip_table_add_del_t *mp;
5967   u32 table_id = ~0;
5968   u8 is_ipv6 = 0;
5969   u8 is_add = 1;
5970   int ret = 0;
5971
5972   /* Parse args required to build the message */
5973   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5974     {
5975       if (unformat (i, "ipv6"))
5976         is_ipv6 = 1;
5977       else if (unformat (i, "del"))
5978         is_add = 0;
5979       else if (unformat (i, "add"))
5980         is_add = 1;
5981       else if (unformat (i, "table %d", &table_id))
5982         ;
5983       else
5984         {
5985           clib_warning ("parse error '%U'", format_unformat_error, i);
5986           return -99;
5987         }
5988     }
5989
5990   if (~0 == table_id)
5991     {
5992       errmsg ("missing table-ID");
5993       return -99;
5994     }
5995
5996   /* Construct the API message */
5997   M (IP_TABLE_ADD_DEL, mp);
5998
5999   mp->table.table_id = ntohl (table_id);
6000   mp->table.is_ip6 = is_ipv6;
6001   mp->is_add = is_add;
6002
6003   /* send it... */
6004   S (mp);
6005
6006   /* Wait for a reply... */
6007   W (ret);
6008
6009   return ret;
6010 }
6011
6012 uword
6013 unformat_fib_path (unformat_input_t * input, va_list * args)
6014 {
6015   vat_main_t *vam = va_arg (*args, vat_main_t *);
6016   vl_api_fib_path_t *path = va_arg (*args, vl_api_fib_path_t *);
6017   u32 weight, preference;
6018   mpls_label_t out_label;
6019
6020   clib_memset (path, 0, sizeof (*path));
6021   path->weight = 1;
6022   path->sw_if_index = ~0;
6023   path->rpf_id = ~0;
6024   path->n_labels = 0;
6025
6026   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6027     {
6028       if (unformat (input, "%U %U",
6029                     unformat_vl_api_ip4_address,
6030                     &path->nh.address.ip4,
6031                     api_unformat_sw_if_index, vam, &path->sw_if_index))
6032         {
6033           path->proto = FIB_API_PATH_NH_PROTO_IP4;
6034         }
6035       else if (unformat (input, "%U %U",
6036                          unformat_vl_api_ip6_address,
6037                          &path->nh.address.ip6,
6038                          api_unformat_sw_if_index, vam, &path->sw_if_index))
6039         {
6040           path->proto = FIB_API_PATH_NH_PROTO_IP6;
6041         }
6042       else if (unformat (input, "weight %u", &weight))
6043         {
6044           path->weight = weight;
6045         }
6046       else if (unformat (input, "preference %u", &preference))
6047         {
6048           path->preference = preference;
6049         }
6050       else if (unformat (input, "%U next-hop-table %d",
6051                          unformat_vl_api_ip4_address,
6052                          &path->nh.address.ip4, &path->table_id))
6053         {
6054           path->proto = FIB_API_PATH_NH_PROTO_IP4;
6055         }
6056       else if (unformat (input, "%U next-hop-table %d",
6057                          unformat_vl_api_ip6_address,
6058                          &path->nh.address.ip6, &path->table_id))
6059         {
6060           path->proto = FIB_API_PATH_NH_PROTO_IP6;
6061         }
6062       else if (unformat (input, "%U",
6063                          unformat_vl_api_ip4_address, &path->nh.address.ip4))
6064         {
6065           /*
6066            * the recursive next-hops are by default in the default table
6067            */
6068           path->table_id = 0;
6069           path->sw_if_index = ~0;
6070           path->proto = FIB_API_PATH_NH_PROTO_IP4;
6071         }
6072       else if (unformat (input, "%U",
6073                          unformat_vl_api_ip6_address, &path->nh.address.ip6))
6074         {
6075           /*
6076            * the recursive next-hops are by default in the default table
6077            */
6078           path->table_id = 0;
6079           path->sw_if_index = ~0;
6080           path->proto = FIB_API_PATH_NH_PROTO_IP6;
6081         }
6082       else if (unformat (input, "resolve-via-host"))
6083         {
6084           path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_HOST;
6085         }
6086       else if (unformat (input, "resolve-via-attached"))
6087         {
6088           path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_ATTACHED;
6089         }
6090       else if (unformat (input, "ip4-lookup-in-table %d", &path->table_id))
6091         {
6092           path->type = FIB_API_PATH_TYPE_LOCAL;
6093           path->sw_if_index = ~0;
6094           path->proto = FIB_API_PATH_NH_PROTO_IP4;
6095         }
6096       else if (unformat (input, "ip6-lookup-in-table %d", &path->table_id))
6097         {
6098           path->type = FIB_API_PATH_TYPE_LOCAL;
6099           path->sw_if_index = ~0;
6100           path->proto = FIB_API_PATH_NH_PROTO_IP6;
6101         }
6102       else if (unformat (input, "sw_if_index %d", &path->sw_if_index))
6103         ;
6104       else if (unformat (input, "via-label %d", &path->nh.via_label))
6105         {
6106           path->proto = FIB_API_PATH_NH_PROTO_MPLS;
6107           path->sw_if_index = ~0;
6108         }
6109       else if (unformat (input, "l2-input-on %d", &path->sw_if_index))
6110         {
6111           path->proto = FIB_API_PATH_NH_PROTO_ETHERNET;
6112           path->type = FIB_API_PATH_TYPE_INTERFACE_RX;
6113         }
6114       else if (unformat (input, "local"))
6115         {
6116           path->type = FIB_API_PATH_TYPE_LOCAL;
6117         }
6118       else if (unformat (input, "out-labels"))
6119         {
6120           while (unformat (input, "%d", &out_label))
6121             {
6122               path->label_stack[path->n_labels].label = out_label;
6123               path->label_stack[path->n_labels].is_uniform = 0;
6124               path->label_stack[path->n_labels].ttl = 64;
6125               path->n_labels++;
6126             }
6127         }
6128       else if (unformat (input, "via"))
6129         {
6130           /* new path, back up and return */
6131           unformat_put_input (input);
6132           unformat_put_input (input);
6133           unformat_put_input (input);
6134           unformat_put_input (input);
6135           break;
6136         }
6137       else
6138         {
6139           return (0);
6140         }
6141     }
6142
6143   path->proto = ntohl (path->proto);
6144   path->type = ntohl (path->type);
6145   path->flags = ntohl (path->flags);
6146   path->table_id = ntohl (path->table_id);
6147   path->sw_if_index = ntohl (path->sw_if_index);
6148
6149   return (1);
6150 }
6151
6152 static int
6153 api_ip_route_add_del (vat_main_t * vam)
6154 {
6155   unformat_input_t *i = vam->input;
6156   vl_api_ip_route_add_del_t *mp;
6157   u32 vrf_id = 0;
6158   u8 is_add = 1;
6159   u8 is_multipath = 0;
6160   u8 prefix_set = 0;
6161   u8 path_count = 0;
6162   vl_api_prefix_t pfx = { };
6163   vl_api_fib_path_t paths[8];
6164   int count = 1;
6165   int j;
6166   f64 before = 0;
6167   u32 random_add_del = 0;
6168   u32 *random_vector = 0;
6169   u32 random_seed = 0xdeaddabe;
6170
6171   /* Parse args required to build the message */
6172   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6173     {
6174       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
6175         prefix_set = 1;
6176       else if (unformat (i, "del"))
6177         is_add = 0;
6178       else if (unformat (i, "add"))
6179         is_add = 1;
6180       else if (unformat (i, "vrf %d", &vrf_id))
6181         ;
6182       else if (unformat (i, "count %d", &count))
6183         ;
6184       else if (unformat (i, "random"))
6185         random_add_del = 1;
6186       else if (unformat (i, "multipath"))
6187         is_multipath = 1;
6188       else if (unformat (i, "seed %d", &random_seed))
6189         ;
6190       else
6191         if (unformat
6192             (i, "via %U", unformat_fib_path, vam, &paths[path_count]))
6193         {
6194           path_count++;
6195           if (8 == path_count)
6196             {
6197               errmsg ("max 8 paths");
6198               return -99;
6199             }
6200         }
6201       else
6202         {
6203           clib_warning ("parse error '%U'", format_unformat_error, i);
6204           return -99;
6205         }
6206     }
6207
6208   if (!path_count)
6209     {
6210       errmsg ("specify a path; via ...");
6211       return -99;
6212     }
6213   if (prefix_set == 0)
6214     {
6215       errmsg ("missing prefix");
6216       return -99;
6217     }
6218
6219   /* Generate a pile of unique, random routes */
6220   if (random_add_del)
6221     {
6222       ip4_address_t *i = (ip4_address_t *) & paths[0].nh.address.ip4;
6223       u32 this_random_address;
6224       uword *random_hash;
6225
6226       random_hash = hash_create (count, sizeof (uword));
6227
6228       hash_set (random_hash, i->as_u32, 1);
6229       for (j = 0; j <= count; j++)
6230         {
6231           do
6232             {
6233               this_random_address = random_u32 (&random_seed);
6234               this_random_address =
6235                 clib_host_to_net_u32 (this_random_address);
6236             }
6237           while (hash_get (random_hash, this_random_address));
6238           vec_add1 (random_vector, this_random_address);
6239           hash_set (random_hash, this_random_address, 1);
6240         }
6241       hash_free (random_hash);
6242       set_ip4_address (&pfx.address, random_vector[0]);
6243     }
6244
6245   if (count > 1)
6246     {
6247       /* Turn on async mode */
6248       vam->async_mode = 1;
6249       vam->async_errors = 0;
6250       before = vat_time_now (vam);
6251     }
6252
6253   for (j = 0; j < count; j++)
6254     {
6255       /* Construct the API message */
6256       M2 (IP_ROUTE_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
6257
6258       mp->is_add = is_add;
6259       mp->is_multipath = is_multipath;
6260
6261       clib_memcpy (&mp->route.prefix, &pfx, sizeof (pfx));
6262       mp->route.table_id = ntohl (vrf_id);
6263       mp->route.n_paths = path_count;
6264
6265       clib_memcpy (&mp->route.paths, &paths, sizeof (paths[0]) * path_count);
6266
6267       if (random_add_del)
6268         set_ip4_address (&pfx.address, random_vector[j + 1]);
6269       else
6270         increment_address (&pfx.address);
6271       /* send it... */
6272       S (mp);
6273       /* If we receive SIGTERM, stop now... */
6274       if (vam->do_exit)
6275         break;
6276     }
6277
6278   /* When testing multiple add/del ops, use a control-ping to sync */
6279   if (count > 1)
6280     {
6281       vl_api_control_ping_t *mp_ping;
6282       f64 after;
6283       f64 timeout;
6284
6285       /* Shut off async mode */
6286       vam->async_mode = 0;
6287
6288       MPING (CONTROL_PING, mp_ping);
6289       S (mp_ping);
6290
6291       timeout = vat_time_now (vam) + 1.0;
6292       while (vat_time_now (vam) < timeout)
6293         if (vam->result_ready == 1)
6294           goto out;
6295       vam->retval = -99;
6296
6297     out:
6298       if (vam->retval == -99)
6299         errmsg ("timeout");
6300
6301       if (vam->async_errors > 0)
6302         {
6303           errmsg ("%d asynchronous errors", vam->async_errors);
6304           vam->retval = -98;
6305         }
6306       vam->async_errors = 0;
6307       after = vat_time_now (vam);
6308
6309       /* slim chance, but we might have eaten SIGTERM on the first iteration */
6310       if (j > 0)
6311         count = j;
6312
6313       print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec",
6314              count, after - before, count / (after - before));
6315     }
6316   else
6317     {
6318       int ret;
6319
6320       /* Wait for a reply... */
6321       W (ret);
6322       return ret;
6323     }
6324
6325   /* Return the good/bad news */
6326   return (vam->retval);
6327 }
6328
6329 static int
6330 api_ip_mroute_add_del (vat_main_t * vam)
6331 {
6332   unformat_input_t *i = vam->input;
6333   u8 path_set = 0, prefix_set = 0, is_add = 1;
6334   vl_api_ip_mroute_add_del_t *mp;
6335   mfib_entry_flags_t eflags = 0;
6336   vl_api_mfib_path_t path;
6337   vl_api_mprefix_t pfx = { };
6338   u32 vrf_id = 0;
6339   int ret;
6340
6341   /* Parse args required to build the message */
6342   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6343     {
6344       if (unformat (i, "%U", unformat_vl_api_mprefix, &pfx))
6345         {
6346           prefix_set = 1;
6347           pfx.grp_address_length = htons (pfx.grp_address_length);
6348         }
6349       else if (unformat (i, "del"))
6350         is_add = 0;
6351       else if (unformat (i, "add"))
6352         is_add = 1;
6353       else if (unformat (i, "vrf %d", &vrf_id))
6354         ;
6355       else if (unformat (i, "%U", unformat_mfib_itf_flags, &path.itf_flags))
6356         path.itf_flags = htonl (path.itf_flags);
6357       else if (unformat (i, "%U", unformat_mfib_entry_flags, &eflags))
6358         ;
6359       else if (unformat (i, "via %U", unformat_fib_path, vam, &path.path))
6360         path_set = 1;
6361       else
6362         {
6363           clib_warning ("parse error '%U'", format_unformat_error, i);
6364           return -99;
6365         }
6366     }
6367
6368   if (prefix_set == 0)
6369     {
6370       errmsg ("missing addresses\n");
6371       return -99;
6372     }
6373   if (path_set == 0)
6374     {
6375       errmsg ("missing path\n");
6376       return -99;
6377     }
6378
6379   /* Construct the API message */
6380   M (IP_MROUTE_ADD_DEL, mp);
6381
6382   mp->is_add = is_add;
6383   mp->is_multipath = 1;
6384
6385   clib_memcpy (&mp->route.prefix, &pfx, sizeof (pfx));
6386   mp->route.table_id = htonl (vrf_id);
6387   mp->route.n_paths = 1;
6388   mp->route.entry_flags = htonl (eflags);
6389
6390   clib_memcpy (&mp->route.paths, &path, sizeof (path));
6391
6392   /* send it... */
6393   S (mp);
6394   /* Wait for a reply... */
6395   W (ret);
6396   return ret;
6397 }
6398
6399 static int
6400 api_mpls_table_add_del (vat_main_t * vam)
6401 {
6402   unformat_input_t *i = vam->input;
6403   vl_api_mpls_table_add_del_t *mp;
6404   u32 table_id = ~0;
6405   u8 is_add = 1;
6406   int ret = 0;
6407
6408   /* Parse args required to build the message */
6409   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6410     {
6411       if (unformat (i, "table %d", &table_id))
6412         ;
6413       else if (unformat (i, "del"))
6414         is_add = 0;
6415       else if (unformat (i, "add"))
6416         is_add = 1;
6417       else
6418         {
6419           clib_warning ("parse error '%U'", format_unformat_error, i);
6420           return -99;
6421         }
6422     }
6423
6424   if (~0 == table_id)
6425     {
6426       errmsg ("missing table-ID");
6427       return -99;
6428     }
6429
6430   /* Construct the API message */
6431   M (MPLS_TABLE_ADD_DEL, mp);
6432
6433   mp->mt_table.mt_table_id = ntohl (table_id);
6434   mp->mt_is_add = is_add;
6435
6436   /* send it... */
6437   S (mp);
6438
6439   /* Wait for a reply... */
6440   W (ret);
6441
6442   return ret;
6443 }
6444
6445 static int
6446 api_mpls_route_add_del (vat_main_t * vam)
6447 {
6448   u8 is_add = 1, path_count = 0, is_multipath = 0, is_eos = 0;
6449   mpls_label_t local_label = MPLS_LABEL_INVALID;
6450   unformat_input_t *i = vam->input;
6451   vl_api_mpls_route_add_del_t *mp;
6452   vl_api_fib_path_t paths[8];
6453   int count = 1, j;
6454   f64 before = 0;
6455
6456   /* Parse args required to build the message */
6457   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6458     {
6459       if (unformat (i, "%d", &local_label))
6460         ;
6461       else if (unformat (i, "eos"))
6462         is_eos = 1;
6463       else if (unformat (i, "non-eos"))
6464         is_eos = 0;
6465       else if (unformat (i, "del"))
6466         is_add = 0;
6467       else if (unformat (i, "add"))
6468         is_add = 1;
6469       else if (unformat (i, "multipath"))
6470         is_multipath = 1;
6471       else if (unformat (i, "count %d", &count))
6472         ;
6473       else
6474         if (unformat
6475             (i, "via %U", unformat_fib_path, vam, &paths[path_count]))
6476         {
6477           path_count++;
6478           if (8 == path_count)
6479             {
6480               errmsg ("max 8 paths");
6481               return -99;
6482             }
6483         }
6484       else
6485         {
6486           clib_warning ("parse error '%U'", format_unformat_error, i);
6487           return -99;
6488         }
6489     }
6490
6491   if (!path_count)
6492     {
6493       errmsg ("specify a path; via ...");
6494       return -99;
6495     }
6496
6497   if (MPLS_LABEL_INVALID == local_label)
6498     {
6499       errmsg ("missing label");
6500       return -99;
6501     }
6502
6503   if (count > 1)
6504     {
6505       /* Turn on async mode */
6506       vam->async_mode = 1;
6507       vam->async_errors = 0;
6508       before = vat_time_now (vam);
6509     }
6510
6511   for (j = 0; j < count; j++)
6512     {
6513       /* Construct the API message */
6514       M2 (MPLS_ROUTE_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
6515
6516       mp->mr_is_add = is_add;
6517       mp->mr_is_multipath = is_multipath;
6518
6519       mp->mr_route.mr_label = local_label;
6520       mp->mr_route.mr_eos = is_eos;
6521       mp->mr_route.mr_table_id = 0;
6522       mp->mr_route.mr_n_paths = path_count;
6523
6524       clib_memcpy (&mp->mr_route.mr_paths, paths,
6525                    sizeof (paths[0]) * path_count);
6526
6527       local_label++;
6528
6529       /* send it... */
6530       S (mp);
6531       /* If we receive SIGTERM, stop now... */
6532       if (vam->do_exit)
6533         break;
6534     }
6535
6536   /* When testing multiple add/del ops, use a control-ping to sync */
6537   if (count > 1)
6538     {
6539       vl_api_control_ping_t *mp_ping;
6540       f64 after;
6541       f64 timeout;
6542
6543       /* Shut off async mode */
6544       vam->async_mode = 0;
6545
6546       MPING (CONTROL_PING, mp_ping);
6547       S (mp_ping);
6548
6549       timeout = vat_time_now (vam) + 1.0;
6550       while (vat_time_now (vam) < timeout)
6551         if (vam->result_ready == 1)
6552           goto out;
6553       vam->retval = -99;
6554
6555     out:
6556       if (vam->retval == -99)
6557         errmsg ("timeout");
6558
6559       if (vam->async_errors > 0)
6560         {
6561           errmsg ("%d asynchronous errors", vam->async_errors);
6562           vam->retval = -98;
6563         }
6564       vam->async_errors = 0;
6565       after = vat_time_now (vam);
6566
6567       /* slim chance, but we might have eaten SIGTERM on the first iteration */
6568       if (j > 0)
6569         count = j;
6570
6571       print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec",
6572              count, after - before, count / (after - before));
6573     }
6574   else
6575     {
6576       int ret;
6577
6578       /* Wait for a reply... */
6579       W (ret);
6580       return ret;
6581     }
6582
6583   /* Return the good/bad news */
6584   return (vam->retval);
6585   return (0);
6586 }
6587
6588 static int
6589 api_mpls_ip_bind_unbind (vat_main_t * vam)
6590 {
6591   unformat_input_t *i = vam->input;
6592   vl_api_mpls_ip_bind_unbind_t *mp;
6593   u32 ip_table_id = 0;
6594   u8 is_bind = 1;
6595   vl_api_prefix_t pfx;
6596   u8 prefix_set = 0;
6597   mpls_label_t local_label = MPLS_LABEL_INVALID;
6598   int ret;
6599
6600   /* Parse args required to build the message */
6601   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6602     {
6603       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
6604         prefix_set = 1;
6605       else if (unformat (i, "%d", &local_label))
6606         ;
6607       else if (unformat (i, "table-id %d", &ip_table_id))
6608         ;
6609       else if (unformat (i, "unbind"))
6610         is_bind = 0;
6611       else if (unformat (i, "bind"))
6612         is_bind = 1;
6613       else
6614         {
6615           clib_warning ("parse error '%U'", format_unformat_error, i);
6616           return -99;
6617         }
6618     }
6619
6620   if (!prefix_set)
6621     {
6622       errmsg ("IP prefix not set");
6623       return -99;
6624     }
6625
6626   if (MPLS_LABEL_INVALID == local_label)
6627     {
6628       errmsg ("missing label");
6629       return -99;
6630     }
6631
6632   /* Construct the API message */
6633   M (MPLS_IP_BIND_UNBIND, mp);
6634
6635   mp->mb_is_bind = is_bind;
6636   mp->mb_ip_table_id = ntohl (ip_table_id);
6637   mp->mb_mpls_table_id = 0;
6638   mp->mb_label = ntohl (local_label);
6639   clib_memcpy (&mp->mb_prefix, &pfx, sizeof (pfx));
6640
6641   /* send it... */
6642   S (mp);
6643
6644   /* Wait for a reply... */
6645   W (ret);
6646   return ret;
6647   return (0);
6648 }
6649
6650 static int
6651 api_sr_mpls_policy_add (vat_main_t * vam)
6652 {
6653   unformat_input_t *i = vam->input;
6654   vl_api_sr_mpls_policy_add_t *mp;
6655   u32 bsid = 0;
6656   u32 weight = 1;
6657   u8 type = 0;
6658   u8 n_segments = 0;
6659   u32 sid;
6660   u32 *segments = NULL;
6661   int ret;
6662
6663   /* Parse args required to build the message */
6664   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6665     {
6666       if (unformat (i, "bsid %d", &bsid))
6667         ;
6668       else if (unformat (i, "weight %d", &weight))
6669         ;
6670       else if (unformat (i, "spray"))
6671         type = 1;
6672       else if (unformat (i, "next %d", &sid))
6673         {
6674           n_segments += 1;
6675           vec_add1 (segments, htonl (sid));
6676         }
6677       else
6678         {
6679           clib_warning ("parse error '%U'", format_unformat_error, i);
6680           return -99;
6681         }
6682     }
6683
6684   if (bsid == 0)
6685     {
6686       errmsg ("bsid not set");
6687       return -99;
6688     }
6689
6690   if (n_segments == 0)
6691     {
6692       errmsg ("no sid in segment stack");
6693       return -99;
6694     }
6695
6696   /* Construct the API message */
6697   M2 (SR_MPLS_POLICY_ADD, mp, sizeof (u32) * n_segments);
6698
6699   mp->bsid = htonl (bsid);
6700   mp->weight = htonl (weight);
6701   mp->is_spray = type;
6702   mp->n_segments = n_segments;
6703   memcpy (mp->segments, segments, sizeof (u32) * n_segments);
6704   vec_free (segments);
6705
6706   /* send it... */
6707   S (mp);
6708
6709   /* Wait for a reply... */
6710   W (ret);
6711   return ret;
6712 }
6713
6714 static int
6715 api_sr_mpls_policy_del (vat_main_t * vam)
6716 {
6717   unformat_input_t *i = vam->input;
6718   vl_api_sr_mpls_policy_del_t *mp;
6719   u32 bsid = 0;
6720   int ret;
6721
6722   /* Parse args required to build the message */
6723   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6724     {
6725       if (unformat (i, "bsid %d", &bsid))
6726         ;
6727       else
6728         {
6729           clib_warning ("parse error '%U'", format_unformat_error, i);
6730           return -99;
6731         }
6732     }
6733
6734   if (bsid == 0)
6735     {
6736       errmsg ("bsid not set");
6737       return -99;
6738     }
6739
6740   /* Construct the API message */
6741   M (SR_MPLS_POLICY_DEL, mp);
6742
6743   mp->bsid = htonl (bsid);
6744
6745   /* send it... */
6746   S (mp);
6747
6748   /* Wait for a reply... */
6749   W (ret);
6750   return ret;
6751 }
6752
6753 static int
6754 api_bier_table_add_del (vat_main_t * vam)
6755 {
6756   unformat_input_t *i = vam->input;
6757   vl_api_bier_table_add_del_t *mp;
6758   u8 is_add = 1;
6759   u32 set = 0, sub_domain = 0, hdr_len = 3;
6760   mpls_label_t local_label = MPLS_LABEL_INVALID;
6761   int ret;
6762
6763   /* Parse args required to build the message */
6764   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6765     {
6766       if (unformat (i, "sub-domain %d", &sub_domain))
6767         ;
6768       else if (unformat (i, "set %d", &set))
6769         ;
6770       else if (unformat (i, "label %d", &local_label))
6771         ;
6772       else if (unformat (i, "hdr-len %d", &hdr_len))
6773         ;
6774       else if (unformat (i, "add"))
6775         is_add = 1;
6776       else if (unformat (i, "del"))
6777         is_add = 0;
6778       else
6779         {
6780           clib_warning ("parse error '%U'", format_unformat_error, i);
6781           return -99;
6782         }
6783     }
6784
6785   if (MPLS_LABEL_INVALID == local_label)
6786     {
6787       errmsg ("missing label\n");
6788       return -99;
6789     }
6790
6791   /* Construct the API message */
6792   M (BIER_TABLE_ADD_DEL, mp);
6793
6794   mp->bt_is_add = is_add;
6795   mp->bt_label = ntohl (local_label);
6796   mp->bt_tbl_id.bt_set = set;
6797   mp->bt_tbl_id.bt_sub_domain = sub_domain;
6798   mp->bt_tbl_id.bt_hdr_len_id = hdr_len;
6799
6800   /* send it... */
6801   S (mp);
6802
6803   /* Wait for a reply... */
6804   W (ret);
6805
6806   return (ret);
6807 }
6808
6809 static int
6810 api_bier_route_add_del (vat_main_t * vam)
6811 {
6812   unformat_input_t *i = vam->input;
6813   vl_api_bier_route_add_del_t *mp;
6814   u8 is_add = 1;
6815   u32 set = 0, sub_domain = 0, hdr_len = 3, bp = 0;
6816   ip4_address_t v4_next_hop_address;
6817   ip6_address_t v6_next_hop_address;
6818   u8 next_hop_set = 0;
6819   u8 next_hop_proto_is_ip4 = 1;
6820   mpls_label_t next_hop_out_label = MPLS_LABEL_INVALID;
6821   int ret;
6822
6823   /* Parse args required to build the message */
6824   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6825     {
6826       if (unformat (i, "%U", unformat_ip4_address, &v4_next_hop_address))
6827         {
6828           next_hop_proto_is_ip4 = 1;
6829           next_hop_set = 1;
6830         }
6831       else if (unformat (i, "%U", unformat_ip6_address, &v6_next_hop_address))
6832         {
6833           next_hop_proto_is_ip4 = 0;
6834           next_hop_set = 1;
6835         }
6836       if (unformat (i, "sub-domain %d", &sub_domain))
6837         ;
6838       else if (unformat (i, "set %d", &set))
6839         ;
6840       else if (unformat (i, "hdr-len %d", &hdr_len))
6841         ;
6842       else if (unformat (i, "bp %d", &bp))
6843         ;
6844       else if (unformat (i, "add"))
6845         is_add = 1;
6846       else if (unformat (i, "del"))
6847         is_add = 0;
6848       else if (unformat (i, "out-label %d", &next_hop_out_label))
6849         ;
6850       else
6851         {
6852           clib_warning ("parse error '%U'", format_unformat_error, i);
6853           return -99;
6854         }
6855     }
6856
6857   if (!next_hop_set || (MPLS_LABEL_INVALID == next_hop_out_label))
6858     {
6859       errmsg ("next hop / label set\n");
6860       return -99;
6861     }
6862   if (0 == bp)
6863     {
6864       errmsg ("bit=position not set\n");
6865       return -99;
6866     }
6867
6868   /* Construct the API message */
6869   M2 (BIER_ROUTE_ADD_DEL, mp, sizeof (vl_api_fib_path_t));
6870
6871   mp->br_is_add = is_add;
6872   mp->br_route.br_tbl_id.bt_set = set;
6873   mp->br_route.br_tbl_id.bt_sub_domain = sub_domain;
6874   mp->br_route.br_tbl_id.bt_hdr_len_id = hdr_len;
6875   mp->br_route.br_bp = ntohs (bp);
6876   mp->br_route.br_n_paths = 1;
6877   mp->br_route.br_paths[0].n_labels = 1;
6878   mp->br_route.br_paths[0].label_stack[0].label = ntohl (next_hop_out_label);
6879   mp->br_route.br_paths[0].proto = (next_hop_proto_is_ip4 ?
6880                                     FIB_API_PATH_NH_PROTO_IP4 :
6881                                     FIB_API_PATH_NH_PROTO_IP6);
6882
6883   if (next_hop_proto_is_ip4)
6884     {
6885       clib_memcpy (&mp->br_route.br_paths[0].nh.address.ip4,
6886                    &v4_next_hop_address, sizeof (v4_next_hop_address));
6887     }
6888   else
6889     {
6890       clib_memcpy (&mp->br_route.br_paths[0].nh.address.ip6,
6891                    &v6_next_hop_address, sizeof (v6_next_hop_address));
6892     }
6893
6894   /* send it... */
6895   S (mp);
6896
6897   /* Wait for a reply... */
6898   W (ret);
6899
6900   return (ret);
6901 }
6902
6903 static int
6904 api_mpls_tunnel_add_del (vat_main_t * vam)
6905 {
6906   unformat_input_t *i = vam->input;
6907   vl_api_mpls_tunnel_add_del_t *mp;
6908
6909   vl_api_fib_path_t paths[8];
6910   u32 sw_if_index = ~0;
6911   u8 path_count = 0;
6912   u8 l2_only = 0;
6913   u8 is_add = 1;
6914   int ret;
6915
6916   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6917     {
6918       if (unformat (i, "add"))
6919         is_add = 1;
6920       else
6921         if (unformat
6922             (i, "del %U", api_unformat_sw_if_index, vam, &sw_if_index))
6923         is_add = 0;
6924       else if (unformat (i, "del sw_if_index %d", &sw_if_index))
6925         is_add = 0;
6926       else if (unformat (i, "l2-only"))
6927         l2_only = 1;
6928       else
6929         if (unformat
6930             (i, "via %U", unformat_fib_path, vam, &paths[path_count]))
6931         {
6932           path_count++;
6933           if (8 == path_count)
6934             {
6935               errmsg ("max 8 paths");
6936               return -99;
6937             }
6938         }
6939       else
6940         {
6941           clib_warning ("parse error '%U'", format_unformat_error, i);
6942           return -99;
6943         }
6944     }
6945
6946   M2 (MPLS_TUNNEL_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
6947
6948   mp->mt_is_add = is_add;
6949   mp->mt_tunnel.mt_sw_if_index = ntohl (sw_if_index);
6950   mp->mt_tunnel.mt_l2_only = l2_only;
6951   mp->mt_tunnel.mt_is_multicast = 0;
6952   mp->mt_tunnel.mt_n_paths = path_count;
6953
6954   clib_memcpy (&mp->mt_tunnel.mt_paths, &paths,
6955                sizeof (paths[0]) * path_count);
6956
6957   S (mp);
6958   W (ret);
6959   return ret;
6960 }
6961
6962 static int
6963 api_sw_interface_set_unnumbered (vat_main_t * vam)
6964 {
6965   unformat_input_t *i = vam->input;
6966   vl_api_sw_interface_set_unnumbered_t *mp;
6967   u32 sw_if_index;
6968   u32 unnum_sw_index = ~0;
6969   u8 is_add = 1;
6970   u8 sw_if_index_set = 0;
6971   int ret;
6972
6973   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6974     {
6975       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
6976         sw_if_index_set = 1;
6977       else if (unformat (i, "sw_if_index %d", &sw_if_index))
6978         sw_if_index_set = 1;
6979       else if (unformat (i, "unnum_if_index %d", &unnum_sw_index))
6980         ;
6981       else if (unformat (i, "del"))
6982         is_add = 0;
6983       else
6984         {
6985           clib_warning ("parse error '%U'", format_unformat_error, i);
6986           return -99;
6987         }
6988     }
6989
6990   if (sw_if_index_set == 0)
6991     {
6992       errmsg ("missing interface name or sw_if_index");
6993       return -99;
6994     }
6995
6996   M (SW_INTERFACE_SET_UNNUMBERED, mp);
6997
6998   mp->sw_if_index = ntohl (sw_if_index);
6999   mp->unnumbered_sw_if_index = ntohl (unnum_sw_index);
7000   mp->is_add = is_add;
7001
7002   S (mp);
7003   W (ret);
7004   return ret;
7005 }
7006
7007
7008 static int
7009 api_create_vlan_subif (vat_main_t * vam)
7010 {
7011   unformat_input_t *i = vam->input;
7012   vl_api_create_vlan_subif_t *mp;
7013   u32 sw_if_index;
7014   u8 sw_if_index_set = 0;
7015   u32 vlan_id;
7016   u8 vlan_id_set = 0;
7017   int ret;
7018
7019   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7020     {
7021       if (unformat (i, "sw_if_index %d", &sw_if_index))
7022         sw_if_index_set = 1;
7023       else
7024         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
7025         sw_if_index_set = 1;
7026       else if (unformat (i, "vlan %d", &vlan_id))
7027         vlan_id_set = 1;
7028       else
7029         {
7030           clib_warning ("parse error '%U'", format_unformat_error, i);
7031           return -99;
7032         }
7033     }
7034
7035   if (sw_if_index_set == 0)
7036     {
7037       errmsg ("missing interface name or sw_if_index");
7038       return -99;
7039     }
7040
7041   if (vlan_id_set == 0)
7042     {
7043       errmsg ("missing vlan_id");
7044       return -99;
7045     }
7046   M (CREATE_VLAN_SUBIF, mp);
7047
7048   mp->sw_if_index = ntohl (sw_if_index);
7049   mp->vlan_id = ntohl (vlan_id);
7050
7051   S (mp);
7052   W (ret);
7053   return ret;
7054 }
7055
7056 #define foreach_create_subif_bit                \
7057 _(no_tags)                                      \
7058 _(one_tag)                                      \
7059 _(two_tags)                                     \
7060 _(dot1ad)                                       \
7061 _(exact_match)                                  \
7062 _(default_sub)                                  \
7063 _(outer_vlan_id_any)                            \
7064 _(inner_vlan_id_any)
7065
7066 #define foreach_create_subif_flag               \
7067 _(0, "no_tags")                                 \
7068 _(1, "one_tag")                                 \
7069 _(2, "two_tags")                                \
7070 _(3, "dot1ad")                                  \
7071 _(4, "exact_match")                             \
7072 _(5, "default_sub")                             \
7073 _(6, "outer_vlan_id_any")                       \
7074 _(7, "inner_vlan_id_any")
7075
7076 static int
7077 api_create_subif (vat_main_t * vam)
7078 {
7079   unformat_input_t *i = vam->input;
7080   vl_api_create_subif_t *mp;
7081   u32 sw_if_index;
7082   u8 sw_if_index_set = 0;
7083   u32 sub_id;
7084   u8 sub_id_set = 0;
7085   u32 __attribute__ ((unused)) no_tags = 0;
7086   u32 __attribute__ ((unused)) one_tag = 0;
7087   u32 __attribute__ ((unused)) two_tags = 0;
7088   u32 __attribute__ ((unused)) dot1ad = 0;
7089   u32 __attribute__ ((unused)) exact_match = 0;
7090   u32 __attribute__ ((unused)) default_sub = 0;
7091   u32 __attribute__ ((unused)) outer_vlan_id_any = 0;
7092   u32 __attribute__ ((unused)) inner_vlan_id_any = 0;
7093   u32 tmp;
7094   u16 outer_vlan_id = 0;
7095   u16 inner_vlan_id = 0;
7096   int ret;
7097
7098   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7099     {
7100       if (unformat (i, "sw_if_index %d", &sw_if_index))
7101         sw_if_index_set = 1;
7102       else
7103         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
7104         sw_if_index_set = 1;
7105       else if (unformat (i, "sub_id %d", &sub_id))
7106         sub_id_set = 1;
7107       else if (unformat (i, "outer_vlan_id %d", &tmp))
7108         outer_vlan_id = tmp;
7109       else if (unformat (i, "inner_vlan_id %d", &tmp))
7110         inner_vlan_id = tmp;
7111
7112 #define _(a) else if (unformat (i, #a)) a = 1 ;
7113       foreach_create_subif_bit
7114 #undef _
7115         else
7116         {
7117           clib_warning ("parse error '%U'", format_unformat_error, i);
7118           return -99;
7119         }
7120     }
7121
7122   if (sw_if_index_set == 0)
7123     {
7124       errmsg ("missing interface name or sw_if_index");
7125       return -99;
7126     }
7127
7128   if (sub_id_set == 0)
7129     {
7130       errmsg ("missing sub_id");
7131       return -99;
7132     }
7133   M (CREATE_SUBIF, mp);
7134
7135   mp->sw_if_index = ntohl (sw_if_index);
7136   mp->sub_id = ntohl (sub_id);
7137
7138 #define _(a,b) mp->sub_if_flags |= (1 << a);
7139   foreach_create_subif_flag;
7140 #undef _
7141
7142   mp->outer_vlan_id = ntohs (outer_vlan_id);
7143   mp->inner_vlan_id = ntohs (inner_vlan_id);
7144
7145   S (mp);
7146   W (ret);
7147   return ret;
7148 }
7149
7150 static int
7151 api_ip_table_replace_begin (vat_main_t * vam)
7152 {
7153   unformat_input_t *i = vam->input;
7154   vl_api_ip_table_replace_begin_t *mp;
7155   u32 table_id = 0;
7156   u8 is_ipv6 = 0;
7157
7158   int ret;
7159   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7160     {
7161       if (unformat (i, "table %d", &table_id))
7162         ;
7163       else if (unformat (i, "ipv6"))
7164         is_ipv6 = 1;
7165       else
7166         {
7167           clib_warning ("parse error '%U'", format_unformat_error, i);
7168           return -99;
7169         }
7170     }
7171
7172   M (IP_TABLE_REPLACE_BEGIN, mp);
7173
7174   mp->table.table_id = ntohl (table_id);
7175   mp->table.is_ip6 = is_ipv6;
7176
7177   S (mp);
7178   W (ret);
7179   return ret;
7180 }
7181
7182 static int
7183 api_ip_table_flush (vat_main_t * vam)
7184 {
7185   unformat_input_t *i = vam->input;
7186   vl_api_ip_table_flush_t *mp;
7187   u32 table_id = 0;
7188   u8 is_ipv6 = 0;
7189
7190   int ret;
7191   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7192     {
7193       if (unformat (i, "table %d", &table_id))
7194         ;
7195       else if (unformat (i, "ipv6"))
7196         is_ipv6 = 1;
7197       else
7198         {
7199           clib_warning ("parse error '%U'", format_unformat_error, i);
7200           return -99;
7201         }
7202     }
7203
7204   M (IP_TABLE_FLUSH, mp);
7205
7206   mp->table.table_id = ntohl (table_id);
7207   mp->table.is_ip6 = is_ipv6;
7208
7209   S (mp);
7210   W (ret);
7211   return ret;
7212 }
7213
7214 static int
7215 api_ip_table_replace_end (vat_main_t * vam)
7216 {
7217   unformat_input_t *i = vam->input;
7218   vl_api_ip_table_replace_end_t *mp;
7219   u32 table_id = 0;
7220   u8 is_ipv6 = 0;
7221
7222   int ret;
7223   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7224     {
7225       if (unformat (i, "table %d", &table_id))
7226         ;
7227       else if (unformat (i, "ipv6"))
7228         is_ipv6 = 1;
7229       else
7230         {
7231           clib_warning ("parse error '%U'", format_unformat_error, i);
7232           return -99;
7233         }
7234     }
7235
7236   M (IP_TABLE_REPLACE_END, mp);
7237
7238   mp->table.table_id = ntohl (table_id);
7239   mp->table.is_ip6 = is_ipv6;
7240
7241   S (mp);
7242   W (ret);
7243   return ret;
7244 }
7245
7246 static int
7247 api_set_ip_flow_hash (vat_main_t * vam)
7248 {
7249   unformat_input_t *i = vam->input;
7250   vl_api_set_ip_flow_hash_t *mp;
7251   u32 vrf_id = 0;
7252   u8 is_ipv6 = 0;
7253   u8 vrf_id_set = 0;
7254   u8 src = 0;
7255   u8 dst = 0;
7256   u8 sport = 0;
7257   u8 dport = 0;
7258   u8 proto = 0;
7259   u8 reverse = 0;
7260   int ret;
7261
7262   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7263     {
7264       if (unformat (i, "vrf %d", &vrf_id))
7265         vrf_id_set = 1;
7266       else if (unformat (i, "ipv6"))
7267         is_ipv6 = 1;
7268       else if (unformat (i, "src"))
7269         src = 1;
7270       else if (unformat (i, "dst"))
7271         dst = 1;
7272       else if (unformat (i, "sport"))
7273         sport = 1;
7274       else if (unformat (i, "dport"))
7275         dport = 1;
7276       else if (unformat (i, "proto"))
7277         proto = 1;
7278       else if (unformat (i, "reverse"))
7279         reverse = 1;
7280
7281       else
7282         {
7283           clib_warning ("parse error '%U'", format_unformat_error, i);
7284           return -99;
7285         }
7286     }
7287
7288   if (vrf_id_set == 0)
7289     {
7290       errmsg ("missing vrf id");
7291       return -99;
7292     }
7293
7294   M (SET_IP_FLOW_HASH, mp);
7295   mp->src = src;
7296   mp->dst = dst;
7297   mp->sport = sport;
7298   mp->dport = dport;
7299   mp->proto = proto;
7300   mp->reverse = reverse;
7301   mp->vrf_id = ntohl (vrf_id);
7302   mp->is_ipv6 = is_ipv6;
7303
7304   S (mp);
7305   W (ret);
7306   return ret;
7307 }
7308
7309 static int
7310 api_sw_interface_ip6_enable_disable (vat_main_t * vam)
7311 {
7312   unformat_input_t *i = vam->input;
7313   vl_api_sw_interface_ip6_enable_disable_t *mp;
7314   u32 sw_if_index;
7315   u8 sw_if_index_set = 0;
7316   u8 enable = 0;
7317   int ret;
7318
7319   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7320     {
7321       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
7322         sw_if_index_set = 1;
7323       else if (unformat (i, "sw_if_index %d", &sw_if_index))
7324         sw_if_index_set = 1;
7325       else if (unformat (i, "enable"))
7326         enable = 1;
7327       else if (unformat (i, "disable"))
7328         enable = 0;
7329       else
7330         {
7331           clib_warning ("parse error '%U'", format_unformat_error, i);
7332           return -99;
7333         }
7334     }
7335
7336   if (sw_if_index_set == 0)
7337     {
7338       errmsg ("missing interface name or sw_if_index");
7339       return -99;
7340     }
7341
7342   M (SW_INTERFACE_IP6_ENABLE_DISABLE, mp);
7343
7344   mp->sw_if_index = ntohl (sw_if_index);
7345   mp->enable = enable;
7346
7347   S (mp);
7348   W (ret);
7349   return ret;
7350 }
7351
7352
7353 static int
7354 api_l2_patch_add_del (vat_main_t * vam)
7355 {
7356   unformat_input_t *i = vam->input;
7357   vl_api_l2_patch_add_del_t *mp;
7358   u32 rx_sw_if_index;
7359   u8 rx_sw_if_index_set = 0;
7360   u32 tx_sw_if_index;
7361   u8 tx_sw_if_index_set = 0;
7362   u8 is_add = 1;
7363   int ret;
7364
7365   /* Parse args required to build the message */
7366   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7367     {
7368       if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index))
7369         rx_sw_if_index_set = 1;
7370       else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
7371         tx_sw_if_index_set = 1;
7372       else if (unformat (i, "rx"))
7373         {
7374           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7375             {
7376               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
7377                             &rx_sw_if_index))
7378                 rx_sw_if_index_set = 1;
7379             }
7380           else
7381             break;
7382         }
7383       else if (unformat (i, "tx"))
7384         {
7385           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7386             {
7387               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
7388                             &tx_sw_if_index))
7389                 tx_sw_if_index_set = 1;
7390             }
7391           else
7392             break;
7393         }
7394       else if (unformat (i, "del"))
7395         is_add = 0;
7396       else
7397         break;
7398     }
7399
7400   if (rx_sw_if_index_set == 0)
7401     {
7402       errmsg ("missing rx interface name or rx_sw_if_index");
7403       return -99;
7404     }
7405
7406   if (tx_sw_if_index_set == 0)
7407     {
7408       errmsg ("missing tx interface name or tx_sw_if_index");
7409       return -99;
7410     }
7411
7412   M (L2_PATCH_ADD_DEL, mp);
7413
7414   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
7415   mp->tx_sw_if_index = ntohl (tx_sw_if_index);
7416   mp->is_add = is_add;
7417
7418   S (mp);
7419   W (ret);
7420   return ret;
7421 }
7422
7423 u8 is_del;
7424 u8 localsid_addr[16];
7425 u8 end_psp;
7426 u8 behavior;
7427 u32 sw_if_index;
7428 u32 vlan_index;
7429 u32 fib_table;
7430 u8 nh_addr[16];
7431
7432 static int
7433 api_sr_localsid_add_del (vat_main_t * vam)
7434 {
7435   unformat_input_t *i = vam->input;
7436   vl_api_sr_localsid_add_del_t *mp;
7437
7438   u8 is_del;
7439   ip6_address_t localsid;
7440   u8 end_psp = 0;
7441   u8 behavior = ~0;
7442   u32 sw_if_index;
7443   u32 fib_table = ~(u32) 0;
7444   ip46_address_t nh_addr;
7445   clib_memset (&nh_addr, 0, sizeof (ip46_address_t));
7446
7447   bool nexthop_set = 0;
7448
7449   int ret;
7450
7451   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7452     {
7453       if (unformat (i, "del"))
7454         is_del = 1;
7455       else if (unformat (i, "address %U", unformat_ip6_address, &localsid));
7456       else if (unformat (i, "next-hop %U", unformat_ip46_address, &nh_addr))
7457         nexthop_set = 1;
7458       else if (unformat (i, "behavior %u", &behavior));
7459       else if (unformat (i, "sw_if_index %u", &sw_if_index));
7460       else if (unformat (i, "fib-table %u", &fib_table));
7461       else if (unformat (i, "end.psp %u", &behavior));
7462       else
7463         break;
7464     }
7465
7466   M (SR_LOCALSID_ADD_DEL, mp);
7467
7468   clib_memcpy (mp->localsid, &localsid, sizeof (mp->localsid));
7469
7470   if (nexthop_set)
7471     {
7472       clib_memcpy (&mp->nh_addr.un, &nh_addr, sizeof (mp->nh_addr.un));
7473     }
7474   mp->behavior = behavior;
7475   mp->sw_if_index = ntohl (sw_if_index);
7476   mp->fib_table = ntohl (fib_table);
7477   mp->end_psp = end_psp;
7478   mp->is_del = is_del;
7479
7480   S (mp);
7481   W (ret);
7482   return ret;
7483 }
7484
7485 static int
7486 api_ioam_enable (vat_main_t * vam)
7487 {
7488   unformat_input_t *input = vam->input;
7489   vl_api_ioam_enable_t *mp;
7490   u32 id = 0;
7491   int has_trace_option = 0;
7492   int has_pot_option = 0;
7493   int has_seqno_option = 0;
7494   int has_analyse_option = 0;
7495   int ret;
7496
7497   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7498     {
7499       if (unformat (input, "trace"))
7500         has_trace_option = 1;
7501       else if (unformat (input, "pot"))
7502         has_pot_option = 1;
7503       else if (unformat (input, "seqno"))
7504         has_seqno_option = 1;
7505       else if (unformat (input, "analyse"))
7506         has_analyse_option = 1;
7507       else
7508         break;
7509     }
7510   M (IOAM_ENABLE, mp);
7511   mp->id = htons (id);
7512   mp->seqno = has_seqno_option;
7513   mp->analyse = has_analyse_option;
7514   mp->pot_enable = has_pot_option;
7515   mp->trace_enable = has_trace_option;
7516
7517   S (mp);
7518   W (ret);
7519   return ret;
7520 }
7521
7522
7523 static int
7524 api_ioam_disable (vat_main_t * vam)
7525 {
7526   vl_api_ioam_disable_t *mp;
7527   int ret;
7528
7529   M (IOAM_DISABLE, mp);
7530   S (mp);
7531   W (ret);
7532   return ret;
7533 }
7534
7535 #define foreach_tcp_proto_field                 \
7536 _(src_port)                                     \
7537 _(dst_port)
7538
7539 #define foreach_udp_proto_field                 \
7540 _(src_port)                                     \
7541 _(dst_port)
7542
7543 #define foreach_ip4_proto_field                 \
7544 _(src_address)                                  \
7545 _(dst_address)                                  \
7546 _(tos)                                          \
7547 _(length)                                       \
7548 _(fragment_id)                                  \
7549 _(ttl)                                          \
7550 _(protocol)                                     \
7551 _(checksum)
7552
7553 typedef struct
7554 {
7555   u16 src_port, dst_port;
7556 } tcpudp_header_t;
7557
7558 #if VPP_API_TEST_BUILTIN == 0
7559 uword
7560 unformat_tcp_mask (unformat_input_t * input, va_list * args)
7561 {
7562   u8 **maskp = va_arg (*args, u8 **);
7563   u8 *mask = 0;
7564   u8 found_something = 0;
7565   tcp_header_t *tcp;
7566
7567 #define _(a) u8 a=0;
7568   foreach_tcp_proto_field;
7569 #undef _
7570
7571   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7572     {
7573       if (0);
7574 #define _(a) else if (unformat (input, #a)) a=1;
7575       foreach_tcp_proto_field
7576 #undef _
7577         else
7578         break;
7579     }
7580
7581 #define _(a) found_something += a;
7582   foreach_tcp_proto_field;
7583 #undef _
7584
7585   if (found_something == 0)
7586     return 0;
7587
7588   vec_validate (mask, sizeof (*tcp) - 1);
7589
7590   tcp = (tcp_header_t *) mask;
7591
7592 #define _(a) if (a) clib_memset (&tcp->a, 0xff, sizeof (tcp->a));
7593   foreach_tcp_proto_field;
7594 #undef _
7595
7596   *maskp = mask;
7597   return 1;
7598 }
7599
7600 uword
7601 unformat_udp_mask (unformat_input_t * input, va_list * args)
7602 {
7603   u8 **maskp = va_arg (*args, u8 **);
7604   u8 *mask = 0;
7605   u8 found_something = 0;
7606   udp_header_t *udp;
7607
7608 #define _(a) u8 a=0;
7609   foreach_udp_proto_field;
7610 #undef _
7611
7612   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7613     {
7614       if (0);
7615 #define _(a) else if (unformat (input, #a)) a=1;
7616       foreach_udp_proto_field
7617 #undef _
7618         else
7619         break;
7620     }
7621
7622 #define _(a) found_something += a;
7623   foreach_udp_proto_field;
7624 #undef _
7625
7626   if (found_something == 0)
7627     return 0;
7628
7629   vec_validate (mask, sizeof (*udp) - 1);
7630
7631   udp = (udp_header_t *) mask;
7632
7633 #define _(a) if (a) clib_memset (&udp->a, 0xff, sizeof (udp->a));
7634   foreach_udp_proto_field;
7635 #undef _
7636
7637   *maskp = mask;
7638   return 1;
7639 }
7640
7641 uword
7642 unformat_l4_mask (unformat_input_t * input, va_list * args)
7643 {
7644   u8 **maskp = va_arg (*args, u8 **);
7645   u16 src_port = 0, dst_port = 0;
7646   tcpudp_header_t *tcpudp;
7647
7648   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7649     {
7650       if (unformat (input, "tcp %U", unformat_tcp_mask, maskp))
7651         return 1;
7652       else if (unformat (input, "udp %U", unformat_udp_mask, maskp))
7653         return 1;
7654       else if (unformat (input, "src_port"))
7655         src_port = 0xFFFF;
7656       else if (unformat (input, "dst_port"))
7657         dst_port = 0xFFFF;
7658       else
7659         return 0;
7660     }
7661
7662   if (!src_port && !dst_port)
7663     return 0;
7664
7665   u8 *mask = 0;
7666   vec_validate (mask, sizeof (tcpudp_header_t) - 1);
7667
7668   tcpudp = (tcpudp_header_t *) mask;
7669   tcpudp->src_port = src_port;
7670   tcpudp->dst_port = dst_port;
7671
7672   *maskp = mask;
7673
7674   return 1;
7675 }
7676
7677 uword
7678 unformat_ip4_mask (unformat_input_t * input, va_list * args)
7679 {
7680   u8 **maskp = va_arg (*args, u8 **);
7681   u8 *mask = 0;
7682   u8 found_something = 0;
7683   ip4_header_t *ip;
7684
7685 #define _(a) u8 a=0;
7686   foreach_ip4_proto_field;
7687 #undef _
7688   u8 version = 0;
7689   u8 hdr_length = 0;
7690
7691
7692   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7693     {
7694       if (unformat (input, "version"))
7695         version = 1;
7696       else if (unformat (input, "hdr_length"))
7697         hdr_length = 1;
7698       else if (unformat (input, "src"))
7699         src_address = 1;
7700       else if (unformat (input, "dst"))
7701         dst_address = 1;
7702       else if (unformat (input, "proto"))
7703         protocol = 1;
7704
7705 #define _(a) else if (unformat (input, #a)) a=1;
7706       foreach_ip4_proto_field
7707 #undef _
7708         else
7709         break;
7710     }
7711
7712 #define _(a) found_something += a;
7713   foreach_ip4_proto_field;
7714 #undef _
7715
7716   if (found_something == 0)
7717     return 0;
7718
7719   vec_validate (mask, sizeof (*ip) - 1);
7720
7721   ip = (ip4_header_t *) mask;
7722
7723 #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
7724   foreach_ip4_proto_field;
7725 #undef _
7726
7727   ip->ip_version_and_header_length = 0;
7728
7729   if (version)
7730     ip->ip_version_and_header_length |= 0xF0;
7731
7732   if (hdr_length)
7733     ip->ip_version_and_header_length |= 0x0F;
7734
7735   *maskp = mask;
7736   return 1;
7737 }
7738
7739 #define foreach_ip6_proto_field                 \
7740 _(src_address)                                  \
7741 _(dst_address)                                  \
7742 _(payload_length)                               \
7743 _(hop_limit)                                    \
7744 _(protocol)
7745
7746 uword
7747 unformat_ip6_mask (unformat_input_t * input, va_list * args)
7748 {
7749   u8 **maskp = va_arg (*args, u8 **);
7750   u8 *mask = 0;
7751   u8 found_something = 0;
7752   ip6_header_t *ip;
7753   u32 ip_version_traffic_class_and_flow_label;
7754
7755 #define _(a) u8 a=0;
7756   foreach_ip6_proto_field;
7757 #undef _
7758   u8 version = 0;
7759   u8 traffic_class = 0;
7760   u8 flow_label = 0;
7761
7762   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7763     {
7764       if (unformat (input, "version"))
7765         version = 1;
7766       else if (unformat (input, "traffic-class"))
7767         traffic_class = 1;
7768       else if (unformat (input, "flow-label"))
7769         flow_label = 1;
7770       else if (unformat (input, "src"))
7771         src_address = 1;
7772       else if (unformat (input, "dst"))
7773         dst_address = 1;
7774       else if (unformat (input, "proto"))
7775         protocol = 1;
7776
7777 #define _(a) else if (unformat (input, #a)) a=1;
7778       foreach_ip6_proto_field
7779 #undef _
7780         else
7781         break;
7782     }
7783
7784 #define _(a) found_something += a;
7785   foreach_ip6_proto_field;
7786 #undef _
7787
7788   if (found_something == 0)
7789     return 0;
7790
7791   vec_validate (mask, sizeof (*ip) - 1);
7792
7793   ip = (ip6_header_t *) mask;
7794
7795 #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
7796   foreach_ip6_proto_field;
7797 #undef _
7798
7799   ip_version_traffic_class_and_flow_label = 0;
7800
7801   if (version)
7802     ip_version_traffic_class_and_flow_label |= 0xF0000000;
7803
7804   if (traffic_class)
7805     ip_version_traffic_class_and_flow_label |= 0x0FF00000;
7806
7807   if (flow_label)
7808     ip_version_traffic_class_and_flow_label |= 0x000FFFFF;
7809
7810   ip->ip_version_traffic_class_and_flow_label =
7811     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
7812
7813   *maskp = mask;
7814   return 1;
7815 }
7816
7817 uword
7818 unformat_l3_mask (unformat_input_t * input, va_list * args)
7819 {
7820   u8 **maskp = va_arg (*args, u8 **);
7821
7822   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7823     {
7824       if (unformat (input, "ip4 %U", unformat_ip4_mask, maskp))
7825         return 1;
7826       else if (unformat (input, "ip6 %U", unformat_ip6_mask, maskp))
7827         return 1;
7828       else
7829         break;
7830     }
7831   return 0;
7832 }
7833
7834 uword
7835 unformat_l2_mask (unformat_input_t * input, va_list * args)
7836 {
7837   u8 **maskp = va_arg (*args, u8 **);
7838   u8 *mask = 0;
7839   u8 src = 0;
7840   u8 dst = 0;
7841   u8 proto = 0;
7842   u8 tag1 = 0;
7843   u8 tag2 = 0;
7844   u8 ignore_tag1 = 0;
7845   u8 ignore_tag2 = 0;
7846   u8 cos1 = 0;
7847   u8 cos2 = 0;
7848   u8 dot1q = 0;
7849   u8 dot1ad = 0;
7850   int len = 14;
7851
7852   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7853     {
7854       if (unformat (input, "src"))
7855         src = 1;
7856       else if (unformat (input, "dst"))
7857         dst = 1;
7858       else if (unformat (input, "proto"))
7859         proto = 1;
7860       else if (unformat (input, "tag1"))
7861         tag1 = 1;
7862       else if (unformat (input, "tag2"))
7863         tag2 = 1;
7864       else if (unformat (input, "ignore-tag1"))
7865         ignore_tag1 = 1;
7866       else if (unformat (input, "ignore-tag2"))
7867         ignore_tag2 = 1;
7868       else if (unformat (input, "cos1"))
7869         cos1 = 1;
7870       else if (unformat (input, "cos2"))
7871         cos2 = 1;
7872       else if (unformat (input, "dot1q"))
7873         dot1q = 1;
7874       else if (unformat (input, "dot1ad"))
7875         dot1ad = 1;
7876       else
7877         break;
7878     }
7879   if ((src + dst + proto + tag1 + tag2 + dot1q + dot1ad +
7880        ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
7881     return 0;
7882
7883   if (tag1 || ignore_tag1 || cos1 || dot1q)
7884     len = 18;
7885   if (tag2 || ignore_tag2 || cos2 || dot1ad)
7886     len = 22;
7887
7888   vec_validate (mask, len - 1);
7889
7890   if (dst)
7891     clib_memset (mask, 0xff, 6);
7892
7893   if (src)
7894     clib_memset (mask + 6, 0xff, 6);
7895
7896   if (tag2 || dot1ad)
7897     {
7898       /* inner vlan tag */
7899       if (tag2)
7900         {
7901           mask[19] = 0xff;
7902           mask[18] = 0x0f;
7903         }
7904       if (cos2)
7905         mask[18] |= 0xe0;
7906       if (proto)
7907         mask[21] = mask[20] = 0xff;
7908       if (tag1)
7909         {
7910           mask[15] = 0xff;
7911           mask[14] = 0x0f;
7912         }
7913       if (cos1)
7914         mask[14] |= 0xe0;
7915       *maskp = mask;
7916       return 1;
7917     }
7918   if (tag1 | dot1q)
7919     {
7920       if (tag1)
7921         {
7922           mask[15] = 0xff;
7923           mask[14] = 0x0f;
7924         }
7925       if (cos1)
7926         mask[14] |= 0xe0;
7927       if (proto)
7928         mask[16] = mask[17] = 0xff;
7929
7930       *maskp = mask;
7931       return 1;
7932     }
7933   if (cos2)
7934     mask[18] |= 0xe0;
7935   if (cos1)
7936     mask[14] |= 0xe0;
7937   if (proto)
7938     mask[12] = mask[13] = 0xff;
7939
7940   *maskp = mask;
7941   return 1;
7942 }
7943
7944 uword
7945 unformat_classify_mask (unformat_input_t * input, va_list * args)
7946 {
7947   u8 **maskp = va_arg (*args, u8 **);
7948   u32 *skipp = va_arg (*args, u32 *);
7949   u32 *matchp = va_arg (*args, u32 *);
7950   u32 match;
7951   u8 *mask = 0;
7952   u8 *l2 = 0;
7953   u8 *l3 = 0;
7954   u8 *l4 = 0;
7955   int i;
7956
7957   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7958     {
7959       if (unformat (input, "hex %U", unformat_hex_string, &mask))
7960         ;
7961       else if (unformat (input, "l2 %U", unformat_l2_mask, &l2))
7962         ;
7963       else if (unformat (input, "l3 %U", unformat_l3_mask, &l3))
7964         ;
7965       else if (unformat (input, "l4 %U", unformat_l4_mask, &l4))
7966         ;
7967       else
7968         break;
7969     }
7970
7971   if (l4 && !l3)
7972     {
7973       vec_free (mask);
7974       vec_free (l2);
7975       vec_free (l4);
7976       return 0;
7977     }
7978
7979   if (mask || l2 || l3 || l4)
7980     {
7981       if (l2 || l3 || l4)
7982         {
7983           /* "With a free Ethernet header in every package" */
7984           if (l2 == 0)
7985             vec_validate (l2, 13);
7986           mask = l2;
7987           if (vec_len (l3))
7988             {
7989               vec_append (mask, l3);
7990               vec_free (l3);
7991             }
7992           if (vec_len (l4))
7993             {
7994               vec_append (mask, l4);
7995               vec_free (l4);
7996             }
7997         }
7998
7999       /* Scan forward looking for the first significant mask octet */
8000       for (i = 0; i < vec_len (mask); i++)
8001         if (mask[i])
8002           break;
8003
8004       /* compute (skip, match) params */
8005       *skipp = i / sizeof (u32x4);
8006       vec_delete (mask, *skipp * sizeof (u32x4), 0);
8007
8008       /* Pad mask to an even multiple of the vector size */
8009       while (vec_len (mask) % sizeof (u32x4))
8010         vec_add1 (mask, 0);
8011
8012       match = vec_len (mask) / sizeof (u32x4);
8013
8014       for (i = match * sizeof (u32x4); i > 0; i -= sizeof (u32x4))
8015         {
8016           u64 *tmp = (u64 *) (mask + (i - sizeof (u32x4)));
8017           if (*tmp || *(tmp + 1))
8018             break;
8019           match--;
8020         }
8021       if (match == 0)
8022         clib_warning ("BUG: match 0");
8023
8024       _vec_len (mask) = match * sizeof (u32x4);
8025
8026       *matchp = match;
8027       *maskp = mask;
8028
8029       return 1;
8030     }
8031
8032   return 0;
8033 }
8034 #endif /* VPP_API_TEST_BUILTIN */
8035
8036 #define foreach_l2_next                         \
8037 _(drop, DROP)                                   \
8038 _(ethernet, ETHERNET_INPUT)                     \
8039 _(ip4, IP4_INPUT)                               \
8040 _(ip6, IP6_INPUT)
8041
8042 uword
8043 unformat_l2_next_index (unformat_input_t * input, va_list * args)
8044 {
8045   u32 *miss_next_indexp = va_arg (*args, u32 *);
8046   u32 next_index = 0;
8047   u32 tmp;
8048
8049 #define _(n,N) \
8050   if (unformat (input, #n)) { next_index = L2_INPUT_CLASSIFY_NEXT_##N; goto out;}
8051   foreach_l2_next;
8052 #undef _
8053
8054   if (unformat (input, "%d", &tmp))
8055     {
8056       next_index = tmp;
8057       goto out;
8058     }
8059
8060   return 0;
8061
8062 out:
8063   *miss_next_indexp = next_index;
8064   return 1;
8065 }
8066
8067 #define foreach_ip_next                         \
8068 _(drop, DROP)                                   \
8069 _(local, LOCAL)                                 \
8070 _(rewrite, REWRITE)
8071
8072 uword
8073 api_unformat_ip_next_index (unformat_input_t * input, va_list * args)
8074 {
8075   u32 *miss_next_indexp = va_arg (*args, u32 *);
8076   u32 next_index = 0;
8077   u32 tmp;
8078
8079 #define _(n,N) \
8080   if (unformat (input, #n)) { next_index = IP_LOOKUP_NEXT_##N; goto out;}
8081   foreach_ip_next;
8082 #undef _
8083
8084   if (unformat (input, "%d", &tmp))
8085     {
8086       next_index = tmp;
8087       goto out;
8088     }
8089
8090   return 0;
8091
8092 out:
8093   *miss_next_indexp = next_index;
8094   return 1;
8095 }
8096
8097 #define foreach_acl_next                        \
8098 _(deny, DENY)
8099
8100 uword
8101 api_unformat_acl_next_index (unformat_input_t * input, va_list * args)
8102 {
8103   u32 *miss_next_indexp = va_arg (*args, u32 *);
8104   u32 next_index = 0;
8105   u32 tmp;
8106
8107 #define _(n,N) \
8108   if (unformat (input, #n)) { next_index = ACL_NEXT_INDEX_##N; goto out;}
8109   foreach_acl_next;
8110 #undef _
8111
8112   if (unformat (input, "permit"))
8113     {
8114       next_index = ~0;
8115       goto out;
8116     }
8117   else if (unformat (input, "%d", &tmp))
8118     {
8119       next_index = tmp;
8120       goto out;
8121     }
8122
8123   return 0;
8124
8125 out:
8126   *miss_next_indexp = next_index;
8127   return 1;
8128 }
8129
8130 uword
8131 unformat_policer_precolor (unformat_input_t * input, va_list * args)
8132 {
8133   u32 *r = va_arg (*args, u32 *);
8134
8135   if (unformat (input, "conform-color"))
8136     *r = POLICE_CONFORM;
8137   else if (unformat (input, "exceed-color"))
8138     *r = POLICE_EXCEED;
8139   else
8140     return 0;
8141
8142   return 1;
8143 }
8144
8145 static int
8146 api_classify_add_del_table (vat_main_t * vam)
8147 {
8148   unformat_input_t *i = vam->input;
8149   vl_api_classify_add_del_table_t *mp;
8150
8151   u32 nbuckets = 2;
8152   u32 skip = ~0;
8153   u32 match = ~0;
8154   int is_add = 1;
8155   int del_chain = 0;
8156   u32 table_index = ~0;
8157   u32 next_table_index = ~0;
8158   u32 miss_next_index = ~0;
8159   u32 memory_size = 32 << 20;
8160   u8 *mask = 0;
8161   u32 current_data_flag = 0;
8162   int current_data_offset = 0;
8163   int ret;
8164
8165   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8166     {
8167       if (unformat (i, "del"))
8168         is_add = 0;
8169       else if (unformat (i, "del-chain"))
8170         {
8171           is_add = 0;
8172           del_chain = 1;
8173         }
8174       else if (unformat (i, "buckets %d", &nbuckets))
8175         ;
8176       else if (unformat (i, "memory_size %d", &memory_size))
8177         ;
8178       else if (unformat (i, "skip %d", &skip))
8179         ;
8180       else if (unformat (i, "match %d", &match))
8181         ;
8182       else if (unformat (i, "table %d", &table_index))
8183         ;
8184       else if (unformat (i, "mask %U", unformat_classify_mask,
8185                          &mask, &skip, &match))
8186         ;
8187       else if (unformat (i, "next-table %d", &next_table_index))
8188         ;
8189       else if (unformat (i, "miss-next %U", api_unformat_ip_next_index,
8190                          &miss_next_index))
8191         ;
8192       else if (unformat (i, "l2-miss-next %U", unformat_l2_next_index,
8193                          &miss_next_index))
8194         ;
8195       else if (unformat (i, "acl-miss-next %U", api_unformat_acl_next_index,
8196                          &miss_next_index))
8197         ;
8198       else if (unformat (i, "current-data-flag %d", &current_data_flag))
8199         ;
8200       else if (unformat (i, "current-data-offset %d", &current_data_offset))
8201         ;
8202       else
8203         break;
8204     }
8205
8206   if (is_add && mask == 0)
8207     {
8208       errmsg ("Mask required");
8209       return -99;
8210     }
8211
8212   if (is_add && skip == ~0)
8213     {
8214       errmsg ("skip count required");
8215       return -99;
8216     }
8217
8218   if (is_add && match == ~0)
8219     {
8220       errmsg ("match count required");
8221       return -99;
8222     }
8223
8224   if (!is_add && table_index == ~0)
8225     {
8226       errmsg ("table index required for delete");
8227       return -99;
8228     }
8229
8230   M2 (CLASSIFY_ADD_DEL_TABLE, mp, vec_len (mask));
8231
8232   mp->is_add = is_add;
8233   mp->del_chain = del_chain;
8234   mp->table_index = ntohl (table_index);
8235   mp->nbuckets = ntohl (nbuckets);
8236   mp->memory_size = ntohl (memory_size);
8237   mp->skip_n_vectors = ntohl (skip);
8238   mp->match_n_vectors = ntohl (match);
8239   mp->next_table_index = ntohl (next_table_index);
8240   mp->miss_next_index = ntohl (miss_next_index);
8241   mp->current_data_flag = ntohl (current_data_flag);
8242   mp->current_data_offset = ntohl (current_data_offset);
8243   mp->mask_len = ntohl (vec_len (mask));
8244   clib_memcpy (mp->mask, mask, vec_len (mask));
8245
8246   vec_free (mask);
8247
8248   S (mp);
8249   W (ret);
8250   return ret;
8251 }
8252
8253 #if VPP_API_TEST_BUILTIN == 0
8254 uword
8255 unformat_l4_match (unformat_input_t * input, va_list * args)
8256 {
8257   u8 **matchp = va_arg (*args, u8 **);
8258
8259   u8 *proto_header = 0;
8260   int src_port = 0;
8261   int dst_port = 0;
8262
8263   tcpudp_header_t h;
8264
8265   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
8266     {
8267       if (unformat (input, "src_port %d", &src_port))
8268         ;
8269       else if (unformat (input, "dst_port %d", &dst_port))
8270         ;
8271       else
8272         return 0;
8273     }
8274
8275   h.src_port = clib_host_to_net_u16 (src_port);
8276   h.dst_port = clib_host_to_net_u16 (dst_port);
8277   vec_validate (proto_header, sizeof (h) - 1);
8278   memcpy (proto_header, &h, sizeof (h));
8279
8280   *matchp = proto_header;
8281
8282   return 1;
8283 }
8284
8285 uword
8286 unformat_ip4_match (unformat_input_t * input, va_list * args)
8287 {
8288   u8 **matchp = va_arg (*args, u8 **);
8289   u8 *match = 0;
8290   ip4_header_t *ip;
8291   int version = 0;
8292   u32 version_val;
8293   int hdr_length = 0;
8294   u32 hdr_length_val;
8295   int src = 0, dst = 0;
8296   ip4_address_t src_val, dst_val;
8297   int proto = 0;
8298   u32 proto_val;
8299   int tos = 0;
8300   u32 tos_val;
8301   int length = 0;
8302   u32 length_val;
8303   int fragment_id = 0;
8304   u32 fragment_id_val;
8305   int ttl = 0;
8306   int ttl_val;
8307   int checksum = 0;
8308   u32 checksum_val;
8309
8310   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
8311     {
8312       if (unformat (input, "version %d", &version_val))
8313         version = 1;
8314       else if (unformat (input, "hdr_length %d", &hdr_length_val))
8315         hdr_length = 1;
8316       else if (unformat (input, "src %U", unformat_ip4_address, &src_val))
8317         src = 1;
8318       else if (unformat (input, "dst %U", unformat_ip4_address, &dst_val))
8319         dst = 1;
8320       else if (unformat (input, "proto %d", &proto_val))
8321         proto = 1;
8322       else if (unformat (input, "tos %d", &tos_val))
8323         tos = 1;
8324       else if (unformat (input, "length %d", &length_val))
8325         length = 1;
8326       else if (unformat (input, "fragment_id %d", &fragment_id_val))
8327         fragment_id = 1;
8328       else if (unformat (input, "ttl %d", &ttl_val))
8329         ttl = 1;
8330       else if (unformat (input, "checksum %d", &checksum_val))
8331         checksum = 1;
8332       else
8333         break;
8334     }
8335
8336   if (version + hdr_length + src + dst + proto + tos + length + fragment_id
8337       + ttl + checksum == 0)
8338     return 0;
8339
8340   /*
8341    * Aligned because we use the real comparison functions
8342    */
8343   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
8344
8345   ip = (ip4_header_t *) match;
8346
8347   /* These are realistically matched in practice */
8348   if (src)
8349     ip->src_address.as_u32 = src_val.as_u32;
8350
8351   if (dst)
8352     ip->dst_address.as_u32 = dst_val.as_u32;
8353
8354   if (proto)
8355     ip->protocol = proto_val;
8356
8357
8358   /* These are not, but they're included for completeness */
8359   if (version)
8360     ip->ip_version_and_header_length |= (version_val & 0xF) << 4;
8361
8362   if (hdr_length)
8363     ip->ip_version_and_header_length |= (hdr_length_val & 0xF);
8364
8365   if (tos)
8366     ip->tos = tos_val;
8367
8368   if (length)
8369     ip->length = clib_host_to_net_u16 (length_val);
8370
8371   if (ttl)
8372     ip->ttl = ttl_val;
8373
8374   if (checksum)
8375     ip->checksum = clib_host_to_net_u16 (checksum_val);
8376
8377   *matchp = match;
8378   return 1;
8379 }
8380
8381 uword
8382 unformat_ip6_match (unformat_input_t * input, va_list * args)
8383 {
8384   u8 **matchp = va_arg (*args, u8 **);
8385   u8 *match = 0;
8386   ip6_header_t *ip;
8387   int version = 0;
8388   u32 version_val;
8389   u8 traffic_class = 0;
8390   u32 traffic_class_val = 0;
8391   u8 flow_label = 0;
8392   u8 flow_label_val;
8393   int src = 0, dst = 0;
8394   ip6_address_t src_val, dst_val;
8395   int proto = 0;
8396   u32 proto_val;
8397   int payload_length = 0;
8398   u32 payload_length_val;
8399   int hop_limit = 0;
8400   int hop_limit_val;
8401   u32 ip_version_traffic_class_and_flow_label;
8402
8403   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
8404     {
8405       if (unformat (input, "version %d", &version_val))
8406         version = 1;
8407       else if (unformat (input, "traffic_class %d", &traffic_class_val))
8408         traffic_class = 1;
8409       else if (unformat (input, "flow_label %d", &flow_label_val))
8410         flow_label = 1;
8411       else if (unformat (input, "src %U", unformat_ip6_address, &src_val))
8412         src = 1;
8413       else if (unformat (input, "dst %U", unformat_ip6_address, &dst_val))
8414         dst = 1;
8415       else if (unformat (input, "proto %d", &proto_val))
8416         proto = 1;
8417       else if (unformat (input, "payload_length %d", &payload_length_val))
8418         payload_length = 1;
8419       else if (unformat (input, "hop_limit %d", &hop_limit_val))
8420         hop_limit = 1;
8421       else
8422         break;
8423     }
8424
8425   if (version + traffic_class + flow_label + src + dst + proto +
8426       payload_length + hop_limit == 0)
8427     return 0;
8428
8429   /*
8430    * Aligned because we use the real comparison functions
8431    */
8432   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
8433
8434   ip = (ip6_header_t *) match;
8435
8436   if (src)
8437     clib_memcpy (&ip->src_address, &src_val, sizeof (ip->src_address));
8438
8439   if (dst)
8440     clib_memcpy (&ip->dst_address, &dst_val, sizeof (ip->dst_address));
8441
8442   if (proto)
8443     ip->protocol = proto_val;
8444
8445   ip_version_traffic_class_and_flow_label = 0;
8446
8447   if (version)
8448     ip_version_traffic_class_and_flow_label |= (version_val & 0xF) << 28;
8449
8450   if (traffic_class)
8451     ip_version_traffic_class_and_flow_label |=
8452       (traffic_class_val & 0xFF) << 20;
8453
8454   if (flow_label)
8455     ip_version_traffic_class_and_flow_label |= (flow_label_val & 0xFFFFF);
8456
8457   ip->ip_version_traffic_class_and_flow_label =
8458     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
8459
8460   if (payload_length)
8461     ip->payload_length = clib_host_to_net_u16 (payload_length_val);
8462
8463   if (hop_limit)
8464     ip->hop_limit = hop_limit_val;
8465
8466   *matchp = match;
8467   return 1;
8468 }
8469
8470 uword
8471 unformat_l3_match (unformat_input_t * input, va_list * args)
8472 {
8473   u8 **matchp = va_arg (*args, u8 **);
8474
8475   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
8476     {
8477       if (unformat (input, "ip4 %U", unformat_ip4_match, matchp))
8478         return 1;
8479       else if (unformat (input, "ip6 %U", unformat_ip6_match, matchp))
8480         return 1;
8481       else
8482         break;
8483     }
8484   return 0;
8485 }
8486
8487 uword
8488 unformat_vlan_tag (unformat_input_t * input, va_list * args)
8489 {
8490   u8 *tagp = va_arg (*args, u8 *);
8491   u32 tag;
8492
8493   if (unformat (input, "%d", &tag))
8494     {
8495       tagp[0] = (tag >> 8) & 0x0F;
8496       tagp[1] = tag & 0xFF;
8497       return 1;
8498     }
8499
8500   return 0;
8501 }
8502
8503 uword
8504 unformat_l2_match (unformat_input_t * input, va_list * args)
8505 {
8506   u8 **matchp = va_arg (*args, u8 **);
8507   u8 *match = 0;
8508   u8 src = 0;
8509   u8 src_val[6];
8510   u8 dst = 0;
8511   u8 dst_val[6];
8512   u8 proto = 0;
8513   u16 proto_val;
8514   u8 tag1 = 0;
8515   u8 tag1_val[2];
8516   u8 tag2 = 0;
8517   u8 tag2_val[2];
8518   int len = 14;
8519   u8 ignore_tag1 = 0;
8520   u8 ignore_tag2 = 0;
8521   u8 cos1 = 0;
8522   u8 cos2 = 0;
8523   u32 cos1_val = 0;
8524   u32 cos2_val = 0;
8525
8526   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
8527     {
8528       if (unformat (input, "src %U", unformat_ethernet_address, &src_val))
8529         src = 1;
8530       else
8531         if (unformat (input, "dst %U", unformat_ethernet_address, &dst_val))
8532         dst = 1;
8533       else if (unformat (input, "proto %U",
8534                          unformat_ethernet_type_host_byte_order, &proto_val))
8535         proto = 1;
8536       else if (unformat (input, "tag1 %U", unformat_vlan_tag, tag1_val))
8537         tag1 = 1;
8538       else if (unformat (input, "tag2 %U", unformat_vlan_tag, tag2_val))
8539         tag2 = 1;
8540       else if (unformat (input, "ignore-tag1"))
8541         ignore_tag1 = 1;
8542       else if (unformat (input, "ignore-tag2"))
8543         ignore_tag2 = 1;
8544       else if (unformat (input, "cos1 %d", &cos1_val))
8545         cos1 = 1;
8546       else if (unformat (input, "cos2 %d", &cos2_val))
8547         cos2 = 1;
8548       else
8549         break;
8550     }
8551   if ((src + dst + proto + tag1 + tag2 +
8552        ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
8553     return 0;
8554
8555   if (tag1 || ignore_tag1 || cos1)
8556     len = 18;
8557   if (tag2 || ignore_tag2 || cos2)
8558     len = 22;
8559
8560   vec_validate_aligned (match, len - 1, sizeof (u32x4));
8561
8562   if (dst)
8563     clib_memcpy (match, dst_val, 6);
8564
8565   if (src)
8566     clib_memcpy (match + 6, src_val, 6);
8567
8568   if (tag2)
8569     {
8570       /* inner vlan tag */
8571       match[19] = tag2_val[1];
8572       match[18] = tag2_val[0];
8573       if (cos2)
8574         match[18] |= (cos2_val & 0x7) << 5;
8575       if (proto)
8576         {
8577           match[21] = proto_val & 0xff;
8578           match[20] = proto_val >> 8;
8579         }
8580       if (tag1)
8581         {
8582           match[15] = tag1_val[1];
8583           match[14] = tag1_val[0];
8584         }
8585       if (cos1)
8586         match[14] |= (cos1_val & 0x7) << 5;
8587       *matchp = match;
8588       return 1;
8589     }
8590   if (tag1)
8591     {
8592       match[15] = tag1_val[1];
8593       match[14] = tag1_val[0];
8594       if (proto)
8595         {
8596           match[17] = proto_val & 0xff;
8597           match[16] = proto_val >> 8;
8598         }
8599       if (cos1)
8600         match[14] |= (cos1_val & 0x7) << 5;
8601
8602       *matchp = match;
8603       return 1;
8604     }
8605   if (cos2)
8606     match[18] |= (cos2_val & 0x7) << 5;
8607   if (cos1)
8608     match[14] |= (cos1_val & 0x7) << 5;
8609   if (proto)
8610     {
8611       match[13] = proto_val & 0xff;
8612       match[12] = proto_val >> 8;
8613     }
8614
8615   *matchp = match;
8616   return 1;
8617 }
8618
8619 uword
8620 unformat_qos_source (unformat_input_t * input, va_list * args)
8621 {
8622   int *qs = va_arg (*args, int *);
8623
8624   if (unformat (input, "ip"))
8625     *qs = QOS_SOURCE_IP;
8626   else if (unformat (input, "mpls"))
8627     *qs = QOS_SOURCE_MPLS;
8628   else if (unformat (input, "ext"))
8629     *qs = QOS_SOURCE_EXT;
8630   else if (unformat (input, "vlan"))
8631     *qs = QOS_SOURCE_VLAN;
8632   else
8633     return 0;
8634
8635   return 1;
8636 }
8637 #endif
8638
8639 uword
8640 api_unformat_classify_match (unformat_input_t * input, va_list * args)
8641 {
8642   u8 **matchp = va_arg (*args, u8 **);
8643   u32 skip_n_vectors = va_arg (*args, u32);
8644   u32 match_n_vectors = va_arg (*args, u32);
8645
8646   u8 *match = 0;
8647   u8 *l2 = 0;
8648   u8 *l3 = 0;
8649   u8 *l4 = 0;
8650
8651   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
8652     {
8653       if (unformat (input, "hex %U", unformat_hex_string, &match))
8654         ;
8655       else if (unformat (input, "l2 %U", unformat_l2_match, &l2))
8656         ;
8657       else if (unformat (input, "l3 %U", unformat_l3_match, &l3))
8658         ;
8659       else if (unformat (input, "l4 %U", unformat_l4_match, &l4))
8660         ;
8661       else
8662         break;
8663     }
8664
8665   if (l4 && !l3)
8666     {
8667       vec_free (match);
8668       vec_free (l2);
8669       vec_free (l4);
8670       return 0;
8671     }
8672
8673   if (match || l2 || l3 || l4)
8674     {
8675       if (l2 || l3 || l4)
8676         {
8677           /* "Win a free Ethernet header in every packet" */
8678           if (l2 == 0)
8679             vec_validate_aligned (l2, 13, sizeof (u32x4));
8680           match = l2;
8681           if (vec_len (l3))
8682             {
8683               vec_append_aligned (match, l3, sizeof (u32x4));
8684               vec_free (l3);
8685             }
8686           if (vec_len (l4))
8687             {
8688               vec_append_aligned (match, l4, sizeof (u32x4));
8689               vec_free (l4);
8690             }
8691         }
8692
8693       /* Make sure the vector is big enough even if key is all 0's */
8694       vec_validate_aligned
8695         (match, ((match_n_vectors + skip_n_vectors) * sizeof (u32x4)) - 1,
8696          sizeof (u32x4));
8697
8698       /* Set size, include skipped vectors */
8699       _vec_len (match) = (match_n_vectors + skip_n_vectors) * sizeof (u32x4);
8700
8701       *matchp = match;
8702
8703       return 1;
8704     }
8705
8706   return 0;
8707 }
8708
8709 static int
8710 api_classify_add_del_session (vat_main_t * vam)
8711 {
8712   unformat_input_t *i = vam->input;
8713   vl_api_classify_add_del_session_t *mp;
8714   int is_add = 1;
8715   u32 table_index = ~0;
8716   u32 hit_next_index = ~0;
8717   u32 opaque_index = ~0;
8718   u8 *match = 0;
8719   i32 advance = 0;
8720   u32 skip_n_vectors = 0;
8721   u32 match_n_vectors = 0;
8722   u32 action = 0;
8723   u32 metadata = 0;
8724   int ret;
8725
8726   /*
8727    * Warning: you have to supply skip_n and match_n
8728    * because the API client cant simply look at the classify
8729    * table object.
8730    */
8731
8732   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8733     {
8734       if (unformat (i, "del"))
8735         is_add = 0;
8736       else if (unformat (i, "hit-next %U", api_unformat_ip_next_index,
8737                          &hit_next_index))
8738         ;
8739       else if (unformat (i, "l2-hit-next %U", unformat_l2_next_index,
8740                          &hit_next_index))
8741         ;
8742       else if (unformat (i, "acl-hit-next %U", api_unformat_acl_next_index,
8743                          &hit_next_index))
8744         ;
8745       else if (unformat (i, "policer-hit-next %d", &hit_next_index))
8746         ;
8747       else if (unformat (i, "%U", unformat_policer_precolor, &opaque_index))
8748         ;
8749       else if (unformat (i, "opaque-index %d", &opaque_index))
8750         ;
8751       else if (unformat (i, "skip_n %d", &skip_n_vectors))
8752         ;
8753       else if (unformat (i, "match_n %d", &match_n_vectors))
8754         ;
8755       else if (unformat (i, "match %U", api_unformat_classify_match,
8756                          &match, skip_n_vectors, match_n_vectors))
8757         ;
8758       else if (unformat (i, "advance %d", &advance))
8759         ;
8760       else if (unformat (i, "table-index %d", &table_index))
8761         ;
8762       else if (unformat (i, "action set-ip4-fib-id %d", &metadata))
8763         action = 1;
8764       else if (unformat (i, "action set-ip6-fib-id %d", &metadata))
8765         action = 2;
8766       else if (unformat (i, "action %d", &action))
8767         ;
8768       else if (unformat (i, "metadata %d", &metadata))
8769         ;
8770       else
8771         break;
8772     }
8773
8774   if (table_index == ~0)
8775     {
8776       errmsg ("Table index required");
8777       return -99;
8778     }
8779
8780   if (is_add && match == 0)
8781     {
8782       errmsg ("Match value required");
8783       return -99;
8784     }
8785
8786   M2 (CLASSIFY_ADD_DEL_SESSION, mp, vec_len (match));
8787
8788   mp->is_add = is_add;
8789   mp->table_index = ntohl (table_index);
8790   mp->hit_next_index = ntohl (hit_next_index);
8791   mp->opaque_index = ntohl (opaque_index);
8792   mp->advance = ntohl (advance);
8793   mp->action = action;
8794   mp->metadata = ntohl (metadata);
8795   mp->match_len = ntohl (vec_len (match));
8796   clib_memcpy (mp->match, match, vec_len (match));
8797   vec_free (match);
8798
8799   S (mp);
8800   W (ret);
8801   return ret;
8802 }
8803
8804 static int
8805 api_classify_set_interface_ip_table (vat_main_t * vam)
8806 {
8807   unformat_input_t *i = vam->input;
8808   vl_api_classify_set_interface_ip_table_t *mp;
8809   u32 sw_if_index;
8810   int sw_if_index_set;
8811   u32 table_index = ~0;
8812   u8 is_ipv6 = 0;
8813   int ret;
8814
8815   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8816     {
8817       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8818         sw_if_index_set = 1;
8819       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8820         sw_if_index_set = 1;
8821       else if (unformat (i, "table %d", &table_index))
8822         ;
8823       else
8824         {
8825           clib_warning ("parse error '%U'", format_unformat_error, i);
8826           return -99;
8827         }
8828     }
8829
8830   if (sw_if_index_set == 0)
8831     {
8832       errmsg ("missing interface name or sw_if_index");
8833       return -99;
8834     }
8835
8836
8837   M (CLASSIFY_SET_INTERFACE_IP_TABLE, mp);
8838
8839   mp->sw_if_index = ntohl (sw_if_index);
8840   mp->table_index = ntohl (table_index);
8841   mp->is_ipv6 = is_ipv6;
8842
8843   S (mp);
8844   W (ret);
8845   return ret;
8846 }
8847
8848 static int
8849 api_classify_set_interface_l2_tables (vat_main_t * vam)
8850 {
8851   unformat_input_t *i = vam->input;
8852   vl_api_classify_set_interface_l2_tables_t *mp;
8853   u32 sw_if_index;
8854   int sw_if_index_set;
8855   u32 ip4_table_index = ~0;
8856   u32 ip6_table_index = ~0;
8857   u32 other_table_index = ~0;
8858   u32 is_input = 1;
8859   int ret;
8860
8861   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8862     {
8863       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8864         sw_if_index_set = 1;
8865       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8866         sw_if_index_set = 1;
8867       else if (unformat (i, "ip4-table %d", &ip4_table_index))
8868         ;
8869       else if (unformat (i, "ip6-table %d", &ip6_table_index))
8870         ;
8871       else if (unformat (i, "other-table %d", &other_table_index))
8872         ;
8873       else if (unformat (i, "is-input %d", &is_input))
8874         ;
8875       else
8876         {
8877           clib_warning ("parse error '%U'", format_unformat_error, i);
8878           return -99;
8879         }
8880     }
8881
8882   if (sw_if_index_set == 0)
8883     {
8884       errmsg ("missing interface name or sw_if_index");
8885       return -99;
8886     }
8887
8888
8889   M (CLASSIFY_SET_INTERFACE_L2_TABLES, mp);
8890
8891   mp->sw_if_index = ntohl (sw_if_index);
8892   mp->ip4_table_index = ntohl (ip4_table_index);
8893   mp->ip6_table_index = ntohl (ip6_table_index);
8894   mp->other_table_index = ntohl (other_table_index);
8895   mp->is_input = (u8) is_input;
8896
8897   S (mp);
8898   W (ret);
8899   return ret;
8900 }
8901
8902 static int
8903 api_set_ipfix_exporter (vat_main_t * vam)
8904 {
8905   unformat_input_t *i = vam->input;
8906   vl_api_set_ipfix_exporter_t *mp;
8907   ip4_address_t collector_address;
8908   u8 collector_address_set = 0;
8909   u32 collector_port = ~0;
8910   ip4_address_t src_address;
8911   u8 src_address_set = 0;
8912   u32 vrf_id = ~0;
8913   u32 path_mtu = ~0;
8914   u32 template_interval = ~0;
8915   u8 udp_checksum = 0;
8916   int ret;
8917
8918   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8919     {
8920       if (unformat (i, "collector_address %U", unformat_ip4_address,
8921                     &collector_address))
8922         collector_address_set = 1;
8923       else if (unformat (i, "collector_port %d", &collector_port))
8924         ;
8925       else if (unformat (i, "src_address %U", unformat_ip4_address,
8926                          &src_address))
8927         src_address_set = 1;
8928       else if (unformat (i, "vrf_id %d", &vrf_id))
8929         ;
8930       else if (unformat (i, "path_mtu %d", &path_mtu))
8931         ;
8932       else if (unformat (i, "template_interval %d", &template_interval))
8933         ;
8934       else if (unformat (i, "udp_checksum"))
8935         udp_checksum = 1;
8936       else
8937         break;
8938     }
8939
8940   if (collector_address_set == 0)
8941     {
8942       errmsg ("collector_address required");
8943       return -99;
8944     }
8945
8946   if (src_address_set == 0)
8947     {
8948       errmsg ("src_address required");
8949       return -99;
8950     }
8951
8952   M (SET_IPFIX_EXPORTER, mp);
8953
8954   memcpy (mp->collector_address.un.ip4, collector_address.data,
8955           sizeof (collector_address.data));
8956   mp->collector_port = htons ((u16) collector_port);
8957   memcpy (mp->src_address.un.ip4, src_address.data,
8958           sizeof (src_address.data));
8959   mp->vrf_id = htonl (vrf_id);
8960   mp->path_mtu = htonl (path_mtu);
8961   mp->template_interval = htonl (template_interval);
8962   mp->udp_checksum = udp_checksum;
8963
8964   S (mp);
8965   W (ret);
8966   return ret;
8967 }
8968
8969 static int
8970 api_set_ipfix_classify_stream (vat_main_t * vam)
8971 {
8972   unformat_input_t *i = vam->input;
8973   vl_api_set_ipfix_classify_stream_t *mp;
8974   u32 domain_id = 0;
8975   u32 src_port = UDP_DST_PORT_ipfix;
8976   int ret;
8977
8978   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8979     {
8980       if (unformat (i, "domain %d", &domain_id))
8981         ;
8982       else if (unformat (i, "src_port %d", &src_port))
8983         ;
8984       else
8985         {
8986           errmsg ("unknown input `%U'", format_unformat_error, i);
8987           return -99;
8988         }
8989     }
8990
8991   M (SET_IPFIX_CLASSIFY_STREAM, mp);
8992
8993   mp->domain_id = htonl (domain_id);
8994   mp->src_port = htons ((u16) src_port);
8995
8996   S (mp);
8997   W (ret);
8998   return ret;
8999 }
9000
9001 static int
9002 api_ipfix_classify_table_add_del (vat_main_t * vam)
9003 {
9004   unformat_input_t *i = vam->input;
9005   vl_api_ipfix_classify_table_add_del_t *mp;
9006   int is_add = -1;
9007   u32 classify_table_index = ~0;
9008   u8 ip_version = 0;
9009   u8 transport_protocol = 255;
9010   int ret;
9011
9012   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9013     {
9014       if (unformat (i, "add"))
9015         is_add = 1;
9016       else if (unformat (i, "del"))
9017         is_add = 0;
9018       else if (unformat (i, "table %d", &classify_table_index))
9019         ;
9020       else if (unformat (i, "ip4"))
9021         ip_version = 4;
9022       else if (unformat (i, "ip6"))
9023         ip_version = 6;
9024       else if (unformat (i, "tcp"))
9025         transport_protocol = 6;
9026       else if (unformat (i, "udp"))
9027         transport_protocol = 17;
9028       else
9029         {
9030           errmsg ("unknown input `%U'", format_unformat_error, i);
9031           return -99;
9032         }
9033     }
9034
9035   if (is_add == -1)
9036     {
9037       errmsg ("expecting: add|del");
9038       return -99;
9039     }
9040   if (classify_table_index == ~0)
9041     {
9042       errmsg ("classifier table not specified");
9043       return -99;
9044     }
9045   if (ip_version == 0)
9046     {
9047       errmsg ("IP version not specified");
9048       return -99;
9049     }
9050
9051   M (IPFIX_CLASSIFY_TABLE_ADD_DEL, mp);
9052
9053   mp->is_add = is_add;
9054   mp->table_id = htonl (classify_table_index);
9055   mp->ip_version = ip_version;
9056   mp->transport_protocol = transport_protocol;
9057
9058   S (mp);
9059   W (ret);
9060   return ret;
9061 }
9062
9063 static int
9064 api_get_node_index (vat_main_t * vam)
9065 {
9066   unformat_input_t *i = vam->input;
9067   vl_api_get_node_index_t *mp;
9068   u8 *name = 0;
9069   int ret;
9070
9071   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9072     {
9073       if (unformat (i, "node %s", &name))
9074         ;
9075       else
9076         break;
9077     }
9078   if (name == 0)
9079     {
9080       errmsg ("node name required");
9081       return -99;
9082     }
9083   if (vec_len (name) >= ARRAY_LEN (mp->node_name))
9084     {
9085       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
9086       return -99;
9087     }
9088
9089   M (GET_NODE_INDEX, mp);
9090   clib_memcpy (mp->node_name, name, vec_len (name));
9091   vec_free (name);
9092
9093   S (mp);
9094   W (ret);
9095   return ret;
9096 }
9097
9098 static int
9099 api_get_next_index (vat_main_t * vam)
9100 {
9101   unformat_input_t *i = vam->input;
9102   vl_api_get_next_index_t *mp;
9103   u8 *node_name = 0, *next_node_name = 0;
9104   int ret;
9105
9106   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9107     {
9108       if (unformat (i, "node-name %s", &node_name))
9109         ;
9110       else if (unformat (i, "next-node-name %s", &next_node_name))
9111         break;
9112     }
9113
9114   if (node_name == 0)
9115     {
9116       errmsg ("node name required");
9117       return -99;
9118     }
9119   if (vec_len (node_name) >= ARRAY_LEN (mp->node_name))
9120     {
9121       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
9122       return -99;
9123     }
9124
9125   if (next_node_name == 0)
9126     {
9127       errmsg ("next node name required");
9128       return -99;
9129     }
9130   if (vec_len (next_node_name) >= ARRAY_LEN (mp->next_name))
9131     {
9132       errmsg ("next node name too long, max %d", ARRAY_LEN (mp->next_name));
9133       return -99;
9134     }
9135
9136   M (GET_NEXT_INDEX, mp);
9137   clib_memcpy (mp->node_name, node_name, vec_len (node_name));
9138   clib_memcpy (mp->next_name, next_node_name, vec_len (next_node_name));
9139   vec_free (node_name);
9140   vec_free (next_node_name);
9141
9142   S (mp);
9143   W (ret);
9144   return ret;
9145 }
9146
9147 static int
9148 api_add_node_next (vat_main_t * vam)
9149 {
9150   unformat_input_t *i = vam->input;
9151   vl_api_add_node_next_t *mp;
9152   u8 *name = 0;
9153   u8 *next = 0;
9154   int ret;
9155
9156   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9157     {
9158       if (unformat (i, "node %s", &name))
9159         ;
9160       else if (unformat (i, "next %s", &next))
9161         ;
9162       else
9163         break;
9164     }
9165   if (name == 0)
9166     {
9167       errmsg ("node name required");
9168       return -99;
9169     }
9170   if (vec_len (name) >= ARRAY_LEN (mp->node_name))
9171     {
9172       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
9173       return -99;
9174     }
9175   if (next == 0)
9176     {
9177       errmsg ("next node required");
9178       return -99;
9179     }
9180   if (vec_len (next) >= ARRAY_LEN (mp->next_name))
9181     {
9182       errmsg ("next name too long, max %d", ARRAY_LEN (mp->next_name));
9183       return -99;
9184     }
9185
9186   M (ADD_NODE_NEXT, mp);
9187   clib_memcpy (mp->node_name, name, vec_len (name));
9188   clib_memcpy (mp->next_name, next, vec_len (next));
9189   vec_free (name);
9190   vec_free (next);
9191
9192   S (mp);
9193   W (ret);
9194   return ret;
9195 }
9196
9197 static void vl_api_sw_interface_tap_v2_details_t_handler
9198   (vl_api_sw_interface_tap_v2_details_t * mp)
9199 {
9200   vat_main_t *vam = &vat_main;
9201
9202   u8 *ip4 =
9203     format (0, "%U/%d", format_ip4_address, mp->host_ip4_prefix.address,
9204             mp->host_ip4_prefix.len);
9205   u8 *ip6 =
9206     format (0, "%U/%d", format_ip6_address, mp->host_ip6_prefix.address,
9207             mp->host_ip6_prefix.len);
9208
9209   print (vam->ofp,
9210          "\n%-16s %-12d %-5d %-12d %-12d %-14U %-30s %-20s %-20s %-30s 0x%-08x",
9211          mp->dev_name, ntohl (mp->sw_if_index), ntohl (mp->id),
9212          ntohs (mp->rx_ring_sz), ntohs (mp->tx_ring_sz),
9213          format_ethernet_address, mp->host_mac_addr, mp->host_namespace,
9214          mp->host_bridge, ip4, ip6, ntohl (mp->tap_flags));
9215
9216   vec_free (ip4);
9217   vec_free (ip6);
9218 }
9219
9220 static void vl_api_sw_interface_tap_v2_details_t_handler_json
9221   (vl_api_sw_interface_tap_v2_details_t * mp)
9222 {
9223   vat_main_t *vam = &vat_main;
9224   vat_json_node_t *node = NULL;
9225
9226   if (VAT_JSON_ARRAY != vam->json_tree.type)
9227     {
9228       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9229       vat_json_init_array (&vam->json_tree);
9230     }
9231   node = vat_json_array_add (&vam->json_tree);
9232
9233   vat_json_init_object (node);
9234   vat_json_object_add_uint (node, "id", ntohl (mp->id));
9235   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
9236   vat_json_object_add_uint (node, "tap_flags", ntohl (mp->tap_flags));
9237   vat_json_object_add_string_copy (node, "dev_name", mp->dev_name);
9238   vat_json_object_add_uint (node, "rx_ring_sz", ntohs (mp->rx_ring_sz));
9239   vat_json_object_add_uint (node, "tx_ring_sz", ntohs (mp->tx_ring_sz));
9240   vat_json_object_add_string_copy (node, "host_mac_addr",
9241                                    format (0, "%U", format_ethernet_address,
9242                                            &mp->host_mac_addr));
9243   vat_json_object_add_string_copy (node, "host_namespace",
9244                                    mp->host_namespace);
9245   vat_json_object_add_string_copy (node, "host_bridge", mp->host_bridge);
9246   vat_json_object_add_string_copy (node, "host_ip4_addr",
9247                                    format (0, "%U/%d", format_ip4_address,
9248                                            mp->host_ip4_prefix.address,
9249                                            mp->host_ip4_prefix.len));
9250   vat_json_object_add_string_copy (node, "host_ip6_prefix",
9251                                    format (0, "%U/%d", format_ip6_address,
9252                                            mp->host_ip6_prefix.address,
9253                                            mp->host_ip6_prefix.len));
9254
9255 }
9256
9257 static int
9258 api_sw_interface_tap_v2_dump (vat_main_t * vam)
9259 {
9260   vl_api_sw_interface_tap_v2_dump_t *mp;
9261   vl_api_control_ping_t *mp_ping;
9262   int ret;
9263
9264   print (vam->ofp,
9265          "\n%-16s %-12s %-5s %-12s %-12s %-14s %-30s %-20s %-20s %-30s",
9266          "dev_name", "sw_if_index", "id", "rx_ring_sz", "tx_ring_sz",
9267          "host_mac_addr", "host_namespace", "host_bridge", "host_ip4_addr",
9268          "host_ip6_addr");
9269
9270   /* Get list of tap interfaces */
9271   M (SW_INTERFACE_TAP_V2_DUMP, mp);
9272   S (mp);
9273
9274   /* Use a control ping for synchronization */
9275   MPING (CONTROL_PING, mp_ping);
9276   S (mp_ping);
9277
9278   W (ret);
9279   return ret;
9280 }
9281
9282 static void vl_api_sw_interface_virtio_pci_details_t_handler
9283   (vl_api_sw_interface_virtio_pci_details_t * mp)
9284 {
9285   vat_main_t *vam = &vat_main;
9286
9287   typedef union
9288   {
9289     struct
9290     {
9291       u16 domain;
9292       u8 bus;
9293       u8 slot:5;
9294       u8 function:3;
9295     };
9296     u32 as_u32;
9297   } pci_addr_t;
9298   pci_addr_t addr;
9299
9300   addr.domain = ntohs (mp->pci_addr.domain);
9301   addr.bus = mp->pci_addr.bus;
9302   addr.slot = mp->pci_addr.slot;
9303   addr.function = mp->pci_addr.function;
9304
9305   u8 *pci_addr = format (0, "%04x:%02x:%02x.%x", addr.domain, addr.bus,
9306                          addr.slot, addr.function);
9307
9308   print (vam->ofp,
9309          "\n%-12s %-12d %-12d %-12d %-17U 0x%-08llx",
9310          pci_addr, ntohl (mp->sw_if_index),
9311          ntohs (mp->rx_ring_sz), ntohs (mp->tx_ring_sz),
9312          format_ethernet_address, mp->mac_addr,
9313          clib_net_to_host_u64 (mp->features));
9314   vec_free (pci_addr);
9315 }
9316
9317 static void vl_api_sw_interface_virtio_pci_details_t_handler_json
9318   (vl_api_sw_interface_virtio_pci_details_t * mp)
9319 {
9320   vat_main_t *vam = &vat_main;
9321   vat_json_node_t *node = NULL;
9322   vlib_pci_addr_t pci_addr;
9323
9324   if (VAT_JSON_ARRAY != vam->json_tree.type)
9325     {
9326       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9327       vat_json_init_array (&vam->json_tree);
9328     }
9329   node = vat_json_array_add (&vam->json_tree);
9330
9331   pci_addr.domain = ntohs (mp->pci_addr.domain);
9332   pci_addr.bus = mp->pci_addr.bus;
9333   pci_addr.slot = mp->pci_addr.slot;
9334   pci_addr.function = mp->pci_addr.function;
9335
9336   vat_json_init_object (node);
9337   vat_json_object_add_uint (node, "pci-addr", pci_addr.as_u32);
9338   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
9339   vat_json_object_add_uint (node, "rx_ring_sz", ntohs (mp->rx_ring_sz));
9340   vat_json_object_add_uint (node, "tx_ring_sz", ntohs (mp->tx_ring_sz));
9341   vat_json_object_add_uint (node, "features",
9342                             clib_net_to_host_u64 (mp->features));
9343   vat_json_object_add_string_copy (node, "mac_addr",
9344                                    format (0, "%U", format_ethernet_address,
9345                                            &mp->mac_addr));
9346 }
9347
9348 static int
9349 api_sw_interface_virtio_pci_dump (vat_main_t * vam)
9350 {
9351   vl_api_sw_interface_virtio_pci_dump_t *mp;
9352   vl_api_control_ping_t *mp_ping;
9353   int ret;
9354
9355   print (vam->ofp,
9356          "\n%-12s %-12s %-12s %-12s %-17s %-08s",
9357          "pci_addr", "sw_if_index", "rx_ring_sz", "tx_ring_sz",
9358          "mac_addr", "features");
9359
9360   /* Get list of tap interfaces */
9361   M (SW_INTERFACE_VIRTIO_PCI_DUMP, mp);
9362   S (mp);
9363
9364   /* Use a control ping for synchronization */
9365   MPING (CONTROL_PING, mp_ping);
9366   S (mp_ping);
9367
9368   W (ret);
9369   return ret;
9370 }
9371
9372 static int
9373 api_vxlan_offload_rx (vat_main_t * vam)
9374 {
9375   unformat_input_t *line_input = vam->input;
9376   vl_api_vxlan_offload_rx_t *mp;
9377   u32 hw_if_index = ~0, rx_if_index = ~0;
9378   u8 is_add = 1;
9379   int ret;
9380
9381   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
9382     {
9383       if (unformat (line_input, "del"))
9384         is_add = 0;
9385       else if (unformat (line_input, "hw %U", api_unformat_hw_if_index, vam,
9386                          &hw_if_index))
9387         ;
9388       else if (unformat (line_input, "hw hw_if_index %u", &hw_if_index))
9389         ;
9390       else if (unformat (line_input, "rx %U", api_unformat_sw_if_index, vam,
9391                          &rx_if_index))
9392         ;
9393       else if (unformat (line_input, "rx sw_if_index %u", &rx_if_index))
9394         ;
9395       else
9396         {
9397           errmsg ("parse error '%U'", format_unformat_error, line_input);
9398           return -99;
9399         }
9400     }
9401
9402   if (hw_if_index == ~0)
9403     {
9404       errmsg ("no hw interface");
9405       return -99;
9406     }
9407
9408   if (rx_if_index == ~0)
9409     {
9410       errmsg ("no rx tunnel");
9411       return -99;
9412     }
9413
9414   M (VXLAN_OFFLOAD_RX, mp);
9415
9416   mp->hw_if_index = ntohl (hw_if_index);
9417   mp->sw_if_index = ntohl (rx_if_index);
9418   mp->enable = is_add;
9419
9420   S (mp);
9421   W (ret);
9422   return ret;
9423 }
9424
9425 static uword unformat_vxlan_decap_next
9426   (unformat_input_t * input, va_list * args)
9427 {
9428   u32 *result = va_arg (*args, u32 *);
9429   u32 tmp;
9430
9431   if (unformat (input, "l2"))
9432     *result = VXLAN_INPUT_NEXT_L2_INPUT;
9433   else if (unformat (input, "%d", &tmp))
9434     *result = tmp;
9435   else
9436     return 0;
9437   return 1;
9438 }
9439
9440 static int
9441 api_vxlan_add_del_tunnel (vat_main_t * vam)
9442 {
9443   unformat_input_t *line_input = vam->input;
9444   vl_api_vxlan_add_del_tunnel_t *mp;
9445   ip46_address_t src, dst;
9446   u8 is_add = 1;
9447   u8 ipv4_set = 0, ipv6_set = 0;
9448   u8 src_set = 0;
9449   u8 dst_set = 0;
9450   u8 grp_set = 0;
9451   u32 instance = ~0;
9452   u32 mcast_sw_if_index = ~0;
9453   u32 encap_vrf_id = 0;
9454   u32 decap_next_index = ~0;
9455   u32 vni = 0;
9456   int ret;
9457
9458   /* Can't "universally zero init" (={0}) due to GCC bug 53119 */
9459   clib_memset (&src, 0, sizeof src);
9460   clib_memset (&dst, 0, sizeof dst);
9461
9462   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
9463     {
9464       if (unformat (line_input, "del"))
9465         is_add = 0;
9466       else if (unformat (line_input, "instance %d", &instance))
9467         ;
9468       else
9469         if (unformat (line_input, "src %U", unformat_ip4_address, &src.ip4))
9470         {
9471           ipv4_set = 1;
9472           src_set = 1;
9473         }
9474       else
9475         if (unformat (line_input, "dst %U", unformat_ip4_address, &dst.ip4))
9476         {
9477           ipv4_set = 1;
9478           dst_set = 1;
9479         }
9480       else
9481         if (unformat (line_input, "src %U", unformat_ip6_address, &src.ip6))
9482         {
9483           ipv6_set = 1;
9484           src_set = 1;
9485         }
9486       else
9487         if (unformat (line_input, "dst %U", unformat_ip6_address, &dst.ip6))
9488         {
9489           ipv6_set = 1;
9490           dst_set = 1;
9491         }
9492       else if (unformat (line_input, "group %U %U",
9493                          unformat_ip4_address, &dst.ip4,
9494                          api_unformat_sw_if_index, vam, &mcast_sw_if_index))
9495         {
9496           grp_set = dst_set = 1;
9497           ipv4_set = 1;
9498         }
9499       else if (unformat (line_input, "group %U",
9500                          unformat_ip4_address, &dst.ip4))
9501         {
9502           grp_set = dst_set = 1;
9503           ipv4_set = 1;
9504         }
9505       else if (unformat (line_input, "group %U %U",
9506                          unformat_ip6_address, &dst.ip6,
9507                          api_unformat_sw_if_index, vam, &mcast_sw_if_index))
9508         {
9509           grp_set = dst_set = 1;
9510           ipv6_set = 1;
9511         }
9512       else if (unformat (line_input, "group %U",
9513                          unformat_ip6_address, &dst.ip6))
9514         {
9515           grp_set = dst_set = 1;
9516           ipv6_set = 1;
9517         }
9518       else
9519         if (unformat (line_input, "mcast_sw_if_index %u", &mcast_sw_if_index))
9520         ;
9521       else if (unformat (line_input, "encap-vrf-id %d", &encap_vrf_id))
9522         ;
9523       else if (unformat (line_input, "decap-next %U",
9524                          unformat_vxlan_decap_next, &decap_next_index))
9525         ;
9526       else if (unformat (line_input, "vni %d", &vni))
9527         ;
9528       else
9529         {
9530           errmsg ("parse error '%U'", format_unformat_error, line_input);
9531           return -99;
9532         }
9533     }
9534
9535   if (src_set == 0)
9536     {
9537       errmsg ("tunnel src address not specified");
9538       return -99;
9539     }
9540   if (dst_set == 0)
9541     {
9542       errmsg ("tunnel dst address not specified");
9543       return -99;
9544     }
9545
9546   if (grp_set && !ip46_address_is_multicast (&dst))
9547     {
9548       errmsg ("tunnel group address not multicast");
9549       return -99;
9550     }
9551   if (grp_set && mcast_sw_if_index == ~0)
9552     {
9553       errmsg ("tunnel nonexistent multicast device");
9554       return -99;
9555     }
9556   if (grp_set == 0 && ip46_address_is_multicast (&dst))
9557     {
9558       errmsg ("tunnel dst address must be unicast");
9559       return -99;
9560     }
9561
9562
9563   if (ipv4_set && ipv6_set)
9564     {
9565       errmsg ("both IPv4 and IPv6 addresses specified");
9566       return -99;
9567     }
9568
9569   if ((vni == 0) || (vni >> 24))
9570     {
9571       errmsg ("vni not specified or out of range");
9572       return -99;
9573     }
9574
9575   M (VXLAN_ADD_DEL_TUNNEL, mp);
9576
9577   if (ipv6_set)
9578     {
9579       clib_memcpy (mp->src_address.un.ip6, &src.ip6, sizeof (src.ip6));
9580       clib_memcpy (mp->dst_address.un.ip6, &dst.ip6, sizeof (dst.ip6));
9581     }
9582   else
9583     {
9584       clib_memcpy (mp->src_address.un.ip4, &src.ip4, sizeof (src.ip4));
9585       clib_memcpy (mp->dst_address.un.ip4, &dst.ip4, sizeof (dst.ip4));
9586     }
9587   mp->src_address.af = ipv6_set;
9588   mp->dst_address.af = ipv6_set;
9589
9590   mp->instance = htonl (instance);
9591   mp->encap_vrf_id = ntohl (encap_vrf_id);
9592   mp->decap_next_index = ntohl (decap_next_index);
9593   mp->mcast_sw_if_index = ntohl (mcast_sw_if_index);
9594   mp->vni = ntohl (vni);
9595   mp->is_add = is_add;
9596
9597   S (mp);
9598   W (ret);
9599   return ret;
9600 }
9601
9602 static void vl_api_vxlan_tunnel_details_t_handler
9603   (vl_api_vxlan_tunnel_details_t * mp)
9604 {
9605   vat_main_t *vam = &vat_main;
9606   ip46_address_t src =
9607     to_ip46 (mp->dst_address.af, (u8 *) & mp->dst_address.un);
9608   ip46_address_t dst =
9609     to_ip46 (mp->dst_address.af, (u8 *) & mp->src_address.un);
9610
9611   print (vam->ofp, "%11d%11d%24U%24U%14d%18d%13d%19d",
9612          ntohl (mp->sw_if_index),
9613          ntohl (mp->instance),
9614          format_ip46_address, &src, IP46_TYPE_ANY,
9615          format_ip46_address, &dst, IP46_TYPE_ANY,
9616          ntohl (mp->encap_vrf_id),
9617          ntohl (mp->decap_next_index), ntohl (mp->vni),
9618          ntohl (mp->mcast_sw_if_index));
9619 }
9620
9621 static void vl_api_vxlan_tunnel_details_t_handler_json
9622   (vl_api_vxlan_tunnel_details_t * mp)
9623 {
9624   vat_main_t *vam = &vat_main;
9625   vat_json_node_t *node = NULL;
9626
9627   if (VAT_JSON_ARRAY != vam->json_tree.type)
9628     {
9629       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9630       vat_json_init_array (&vam->json_tree);
9631     }
9632   node = vat_json_array_add (&vam->json_tree);
9633
9634   vat_json_init_object (node);
9635   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
9636
9637   vat_json_object_add_uint (node, "instance", ntohl (mp->instance));
9638
9639   if (mp->src_address.af)
9640     {
9641       struct in6_addr ip6;
9642
9643       clib_memcpy (&ip6, mp->src_address.un.ip6, sizeof (ip6));
9644       vat_json_object_add_ip6 (node, "src_address", ip6);
9645       clib_memcpy (&ip6, mp->dst_address.un.ip6, sizeof (ip6));
9646       vat_json_object_add_ip6 (node, "dst_address", ip6);
9647     }
9648   else
9649     {
9650       struct in_addr ip4;
9651
9652       clib_memcpy (&ip4, mp->src_address.un.ip4, sizeof (ip4));
9653       vat_json_object_add_ip4 (node, "src_address", ip4);
9654       clib_memcpy (&ip4, mp->dst_address.un.ip4, sizeof (ip4));
9655       vat_json_object_add_ip4 (node, "dst_address", ip4);
9656     }
9657   vat_json_object_add_uint (node, "encap_vrf_id", ntohl (mp->encap_vrf_id));
9658   vat_json_object_add_uint (node, "decap_next_index",
9659                             ntohl (mp->decap_next_index));
9660   vat_json_object_add_uint (node, "vni", ntohl (mp->vni));
9661   vat_json_object_add_uint (node, "mcast_sw_if_index",
9662                             ntohl (mp->mcast_sw_if_index));
9663 }
9664
9665 static int
9666 api_vxlan_tunnel_dump (vat_main_t * vam)
9667 {
9668   unformat_input_t *i = vam->input;
9669   vl_api_vxlan_tunnel_dump_t *mp;
9670   vl_api_control_ping_t *mp_ping;
9671   u32 sw_if_index;
9672   u8 sw_if_index_set = 0;
9673   int ret;
9674
9675   /* Parse args required to build the message */
9676   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9677     {
9678       if (unformat (i, "sw_if_index %d", &sw_if_index))
9679         sw_if_index_set = 1;
9680       else
9681         break;
9682     }
9683
9684   if (sw_if_index_set == 0)
9685     {
9686       sw_if_index = ~0;
9687     }
9688
9689   if (!vam->json_output)
9690     {
9691       print (vam->ofp, "%11s%11s%24s%24s%14s%18s%13s%19s",
9692              "sw_if_index", "instance", "src_address", "dst_address",
9693              "encap_vrf_id", "decap_next_index", "vni", "mcast_sw_if_index");
9694     }
9695
9696   /* Get list of vxlan-tunnel interfaces */
9697   M (VXLAN_TUNNEL_DUMP, mp);
9698
9699   mp->sw_if_index = htonl (sw_if_index);
9700
9701   S (mp);
9702
9703   /* Use a control ping for synchronization */
9704   MPING (CONTROL_PING, mp_ping);
9705   S (mp_ping);
9706
9707   W (ret);
9708   return ret;
9709 }
9710
9711 static int
9712 api_gre_tunnel_add_del (vat_main_t * vam)
9713 {
9714   unformat_input_t *line_input = vam->input;
9715   vl_api_address_t src = { }, dst =
9716   {
9717   };
9718   vl_api_gre_tunnel_add_del_t *mp;
9719   vl_api_gre_tunnel_type_t t_type;
9720   u8 is_add = 1;
9721   u8 src_set = 0;
9722   u8 dst_set = 0;
9723   u32 outer_table_id = 0;
9724   u32 session_id = 0;
9725   u32 instance = ~0;
9726   int ret;
9727
9728   t_type = GRE_API_TUNNEL_TYPE_L3;
9729
9730   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
9731     {
9732       if (unformat (line_input, "del"))
9733         is_add = 0;
9734       else if (unformat (line_input, "instance %d", &instance))
9735         ;
9736       else if (unformat (line_input, "src %U", unformat_vl_api_address, &src))
9737         {
9738           src_set = 1;
9739         }
9740       else if (unformat (line_input, "dst %U", unformat_vl_api_address, &dst))
9741         {
9742           dst_set = 1;
9743         }
9744       else if (unformat (line_input, "outer-table-id %d", &outer_table_id))
9745         ;
9746       else if (unformat (line_input, "teb"))
9747         t_type = GRE_API_TUNNEL_TYPE_TEB;
9748       else if (unformat (line_input, "erspan %d", &session_id))
9749         t_type = GRE_API_TUNNEL_TYPE_ERSPAN;
9750       else
9751         {
9752           errmsg ("parse error '%U'", format_unformat_error, line_input);
9753           return -99;
9754         }
9755     }
9756
9757   if (src_set == 0)
9758     {
9759       errmsg ("tunnel src address not specified");
9760       return -99;
9761     }
9762   if (dst_set == 0)
9763     {
9764       errmsg ("tunnel dst address not specified");
9765       return -99;
9766     }
9767
9768   M (GRE_TUNNEL_ADD_DEL, mp);
9769
9770   clib_memcpy (&mp->tunnel.src, &src, sizeof (mp->tunnel.src));
9771   clib_memcpy (&mp->tunnel.dst, &dst, sizeof (mp->tunnel.dst));
9772
9773   mp->tunnel.instance = htonl (instance);
9774   mp->tunnel.outer_table_id = htonl (outer_table_id);
9775   mp->is_add = is_add;
9776   mp->tunnel.session_id = htons ((u16) session_id);
9777   mp->tunnel.type = htonl (t_type);
9778
9779   S (mp);
9780   W (ret);
9781   return ret;
9782 }
9783
9784 static void vl_api_gre_tunnel_details_t_handler
9785   (vl_api_gre_tunnel_details_t * mp)
9786 {
9787   vat_main_t *vam = &vat_main;
9788
9789   print (vam->ofp, "%11d%11d%24U%24U%13d%14d%12d",
9790          ntohl (mp->tunnel.sw_if_index),
9791          ntohl (mp->tunnel.instance),
9792          format_vl_api_address, &mp->tunnel.src,
9793          format_vl_api_address, &mp->tunnel.dst,
9794          mp->tunnel.type, ntohl (mp->tunnel.outer_table_id),
9795          ntohl (mp->tunnel.session_id));
9796 }
9797
9798 static void vl_api_gre_tunnel_details_t_handler_json
9799   (vl_api_gre_tunnel_details_t * mp)
9800 {
9801   vat_main_t *vam = &vat_main;
9802   vat_json_node_t *node = NULL;
9803
9804   if (VAT_JSON_ARRAY != vam->json_tree.type)
9805     {
9806       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9807       vat_json_init_array (&vam->json_tree);
9808     }
9809   node = vat_json_array_add (&vam->json_tree);
9810
9811   vat_json_init_object (node);
9812   vat_json_object_add_uint (node, "sw_if_index",
9813                             ntohl (mp->tunnel.sw_if_index));
9814   vat_json_object_add_uint (node, "instance", ntohl (mp->tunnel.instance));
9815
9816   vat_json_object_add_address (node, "src", &mp->tunnel.src);
9817   vat_json_object_add_address (node, "dst", &mp->tunnel.dst);
9818   vat_json_object_add_uint (node, "tunnel_type", mp->tunnel.type);
9819   vat_json_object_add_uint (node, "outer_table_id",
9820                             ntohl (mp->tunnel.outer_table_id));
9821   vat_json_object_add_uint (node, "session_id", mp->tunnel.session_id);
9822 }
9823
9824 static int
9825 api_gre_tunnel_dump (vat_main_t * vam)
9826 {
9827   unformat_input_t *i = vam->input;
9828   vl_api_gre_tunnel_dump_t *mp;
9829   vl_api_control_ping_t *mp_ping;
9830   u32 sw_if_index;
9831   u8 sw_if_index_set = 0;
9832   int ret;
9833
9834   /* Parse args required to build the message */
9835   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9836     {
9837       if (unformat (i, "sw_if_index %d", &sw_if_index))
9838         sw_if_index_set = 1;
9839       else
9840         break;
9841     }
9842
9843   if (sw_if_index_set == 0)
9844     {
9845       sw_if_index = ~0;
9846     }
9847
9848   if (!vam->json_output)
9849     {
9850       print (vam->ofp, "%11s%11s%24s%24s%13s%14s%12s",
9851              "sw_if_index", "instance", "src_address", "dst_address",
9852              "tunnel_type", "outer_fib_id", "session_id");
9853     }
9854
9855   /* Get list of gre-tunnel interfaces */
9856   M (GRE_TUNNEL_DUMP, mp);
9857
9858   mp->sw_if_index = htonl (sw_if_index);
9859
9860   S (mp);
9861
9862   /* Use a control ping for synchronization */
9863   MPING (CONTROL_PING, mp_ping);
9864   S (mp_ping);
9865
9866   W (ret);
9867   return ret;
9868 }
9869
9870 static int
9871 api_l2_fib_clear_table (vat_main_t * vam)
9872 {
9873 //  unformat_input_t * i = vam->input;
9874   vl_api_l2_fib_clear_table_t *mp;
9875   int ret;
9876
9877   M (L2_FIB_CLEAR_TABLE, mp);
9878
9879   S (mp);
9880   W (ret);
9881   return ret;
9882 }
9883
9884 static int
9885 api_l2_interface_efp_filter (vat_main_t * vam)
9886 {
9887   unformat_input_t *i = vam->input;
9888   vl_api_l2_interface_efp_filter_t *mp;
9889   u32 sw_if_index;
9890   u8 enable = 1;
9891   u8 sw_if_index_set = 0;
9892   int ret;
9893
9894   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9895     {
9896       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
9897         sw_if_index_set = 1;
9898       else if (unformat (i, "sw_if_index %d", &sw_if_index))
9899         sw_if_index_set = 1;
9900       else if (unformat (i, "enable"))
9901         enable = 1;
9902       else if (unformat (i, "disable"))
9903         enable = 0;
9904       else
9905         {
9906           clib_warning ("parse error '%U'", format_unformat_error, i);
9907           return -99;
9908         }
9909     }
9910
9911   if (sw_if_index_set == 0)
9912     {
9913       errmsg ("missing sw_if_index");
9914       return -99;
9915     }
9916
9917   M (L2_INTERFACE_EFP_FILTER, mp);
9918
9919   mp->sw_if_index = ntohl (sw_if_index);
9920   mp->enable_disable = enable;
9921
9922   S (mp);
9923   W (ret);
9924   return ret;
9925 }
9926
9927 #define foreach_vtr_op                          \
9928 _("disable",  L2_VTR_DISABLED)                  \
9929 _("push-1",  L2_VTR_PUSH_1)                     \
9930 _("push-2",  L2_VTR_PUSH_2)                     \
9931 _("pop-1",  L2_VTR_POP_1)                       \
9932 _("pop-2",  L2_VTR_POP_2)                       \
9933 _("translate-1-1",  L2_VTR_TRANSLATE_1_1)       \
9934 _("translate-1-2",  L2_VTR_TRANSLATE_1_2)       \
9935 _("translate-2-1",  L2_VTR_TRANSLATE_2_1)       \
9936 _("translate-2-2",  L2_VTR_TRANSLATE_2_2)
9937
9938 static int
9939 api_l2_interface_vlan_tag_rewrite (vat_main_t * vam)
9940 {
9941   unformat_input_t *i = vam->input;
9942   vl_api_l2_interface_vlan_tag_rewrite_t *mp;
9943   u32 sw_if_index;
9944   u8 sw_if_index_set = 0;
9945   u8 vtr_op_set = 0;
9946   u32 vtr_op = 0;
9947   u32 push_dot1q = 1;
9948   u32 tag1 = ~0;
9949   u32 tag2 = ~0;
9950   int ret;
9951
9952   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9953     {
9954       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
9955         sw_if_index_set = 1;
9956       else if (unformat (i, "sw_if_index %d", &sw_if_index))
9957         sw_if_index_set = 1;
9958       else if (unformat (i, "vtr_op %d", &vtr_op))
9959         vtr_op_set = 1;
9960 #define _(n,v) else if (unformat(i, n)) {vtr_op = v; vtr_op_set = 1;}
9961       foreach_vtr_op
9962 #undef _
9963         else if (unformat (i, "push_dot1q %d", &push_dot1q))
9964         ;
9965       else if (unformat (i, "tag1 %d", &tag1))
9966         ;
9967       else if (unformat (i, "tag2 %d", &tag2))
9968         ;
9969       else
9970         {
9971           clib_warning ("parse error '%U'", format_unformat_error, i);
9972           return -99;
9973         }
9974     }
9975
9976   if ((sw_if_index_set == 0) || (vtr_op_set == 0))
9977     {
9978       errmsg ("missing vtr operation or sw_if_index");
9979       return -99;
9980     }
9981
9982   M (L2_INTERFACE_VLAN_TAG_REWRITE, mp);
9983   mp->sw_if_index = ntohl (sw_if_index);
9984   mp->vtr_op = ntohl (vtr_op);
9985   mp->push_dot1q = ntohl (push_dot1q);
9986   mp->tag1 = ntohl (tag1);
9987   mp->tag2 = ntohl (tag2);
9988
9989   S (mp);
9990   W (ret);
9991   return ret;
9992 }
9993
9994 static int
9995 api_create_vhost_user_if (vat_main_t * vam)
9996 {
9997   unformat_input_t *i = vam->input;
9998   vl_api_create_vhost_user_if_t *mp;
9999   u8 *file_name;
10000   u8 is_server = 0;
10001   u8 file_name_set = 0;
10002   u32 custom_dev_instance = ~0;
10003   u8 hwaddr[6];
10004   u8 use_custom_mac = 0;
10005   u8 disable_mrg_rxbuf = 0;
10006   u8 disable_indirect_desc = 0;
10007   u8 *tag = 0;
10008   u8 enable_gso = 0;
10009   u8 enable_packed = 0;
10010   int ret;
10011
10012   /* Shut up coverity */
10013   clib_memset (hwaddr, 0, sizeof (hwaddr));
10014
10015   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10016     {
10017       if (unformat (i, "socket %s", &file_name))
10018         {
10019           file_name_set = 1;
10020         }
10021       else if (unformat (i, "renumber %" PRIu32, &custom_dev_instance))
10022         ;
10023       else if (unformat (i, "mac %U", unformat_ethernet_address, hwaddr))
10024         use_custom_mac = 1;
10025       else if (unformat (i, "server"))
10026         is_server = 1;
10027       else if (unformat (i, "disable_mrg_rxbuf"))
10028         disable_mrg_rxbuf = 1;
10029       else if (unformat (i, "disable_indirect_desc"))
10030         disable_indirect_desc = 1;
10031       else if (unformat (i, "gso"))
10032         enable_gso = 1;
10033       else if (unformat (i, "packed"))
10034         enable_packed = 1;
10035       else if (unformat (i, "tag %s", &tag))
10036         ;
10037       else
10038         break;
10039     }
10040
10041   if (file_name_set == 0)
10042     {
10043       errmsg ("missing socket file name");
10044       return -99;
10045     }
10046
10047   if (vec_len (file_name) > 255)
10048     {
10049       errmsg ("socket file name too long");
10050       return -99;
10051     }
10052   vec_add1 (file_name, 0);
10053
10054   M (CREATE_VHOST_USER_IF, mp);
10055
10056   mp->is_server = is_server;
10057   mp->disable_mrg_rxbuf = disable_mrg_rxbuf;
10058   mp->disable_indirect_desc = disable_indirect_desc;
10059   mp->enable_gso = enable_gso;
10060   mp->enable_packed = enable_packed;
10061   clib_memcpy (mp->sock_filename, file_name, vec_len (file_name));
10062   vec_free (file_name);
10063   if (custom_dev_instance != ~0)
10064     {
10065       mp->renumber = 1;
10066       mp->custom_dev_instance = ntohl (custom_dev_instance);
10067     }
10068
10069   mp->use_custom_mac = use_custom_mac;
10070   clib_memcpy (mp->mac_address, hwaddr, 6);
10071   if (tag)
10072     strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
10073   vec_free (tag);
10074
10075   S (mp);
10076   W (ret);
10077   return ret;
10078 }
10079
10080 static int
10081 api_modify_vhost_user_if (vat_main_t * vam)
10082 {
10083   unformat_input_t *i = vam->input;
10084   vl_api_modify_vhost_user_if_t *mp;
10085   u8 *file_name;
10086   u8 is_server = 0;
10087   u8 file_name_set = 0;
10088   u32 custom_dev_instance = ~0;
10089   u8 sw_if_index_set = 0;
10090   u32 sw_if_index = (u32) ~ 0;
10091   u8 enable_gso = 0;
10092   u8 enable_packed = 0;
10093   int ret;
10094
10095   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10096     {
10097       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10098         sw_if_index_set = 1;
10099       else if (unformat (i, "sw_if_index %d", &sw_if_index))
10100         sw_if_index_set = 1;
10101       else if (unformat (i, "socket %s", &file_name))
10102         {
10103           file_name_set = 1;
10104         }
10105       else if (unformat (i, "renumber %" PRIu32, &custom_dev_instance))
10106         ;
10107       else if (unformat (i, "server"))
10108         is_server = 1;
10109       else if (unformat (i, "gso"))
10110         enable_gso = 1;
10111       else if (unformat (i, "packed"))
10112         enable_packed = 1;
10113       else
10114         break;
10115     }
10116
10117   if (sw_if_index_set == 0)
10118     {
10119       errmsg ("missing sw_if_index or interface name");
10120       return -99;
10121     }
10122
10123   if (file_name_set == 0)
10124     {
10125       errmsg ("missing socket file name");
10126       return -99;
10127     }
10128
10129   if (vec_len (file_name) > 255)
10130     {
10131       errmsg ("socket file name too long");
10132       return -99;
10133     }
10134   vec_add1 (file_name, 0);
10135
10136   M (MODIFY_VHOST_USER_IF, mp);
10137
10138   mp->sw_if_index = ntohl (sw_if_index);
10139   mp->is_server = is_server;
10140   mp->enable_gso = enable_gso;
10141   mp->enable_packed = enable_packed;
10142   clib_memcpy (mp->sock_filename, file_name, vec_len (file_name));
10143   vec_free (file_name);
10144   if (custom_dev_instance != ~0)
10145     {
10146       mp->renumber = 1;
10147       mp->custom_dev_instance = ntohl (custom_dev_instance);
10148     }
10149
10150   S (mp);
10151   W (ret);
10152   return ret;
10153 }
10154
10155 static int
10156 api_delete_vhost_user_if (vat_main_t * vam)
10157 {
10158   unformat_input_t *i = vam->input;
10159   vl_api_delete_vhost_user_if_t *mp;
10160   u32 sw_if_index = ~0;
10161   u8 sw_if_index_set = 0;
10162   int ret;
10163
10164   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10165     {
10166       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10167         sw_if_index_set = 1;
10168       else if (unformat (i, "sw_if_index %d", &sw_if_index))
10169         sw_if_index_set = 1;
10170       else
10171         break;
10172     }
10173
10174   if (sw_if_index_set == 0)
10175     {
10176       errmsg ("missing sw_if_index or interface name");
10177       return -99;
10178     }
10179
10180
10181   M (DELETE_VHOST_USER_IF, mp);
10182
10183   mp->sw_if_index = ntohl (sw_if_index);
10184
10185   S (mp);
10186   W (ret);
10187   return ret;
10188 }
10189
10190 static void vl_api_sw_interface_vhost_user_details_t_handler
10191   (vl_api_sw_interface_vhost_user_details_t * mp)
10192 {
10193   vat_main_t *vam = &vat_main;
10194   u64 features;
10195
10196   features =
10197     clib_net_to_host_u32 (mp->features_first_32) | ((u64)
10198                                                     clib_net_to_host_u32
10199                                                     (mp->features_last_32) <<
10200                                                     32);
10201
10202   print (vam->ofp, "%-25s %3" PRIu32 " %6" PRIu32 " %8x %6d %7d %s",
10203          (char *) mp->interface_name,
10204          ntohl (mp->sw_if_index), ntohl (mp->virtio_net_hdr_sz),
10205          features, mp->is_server,
10206          ntohl (mp->num_regions), (char *) mp->sock_filename);
10207   print (vam->ofp, "    Status: '%s'", strerror (ntohl (mp->sock_errno)));
10208 }
10209
10210 static void vl_api_sw_interface_vhost_user_details_t_handler_json
10211   (vl_api_sw_interface_vhost_user_details_t * mp)
10212 {
10213   vat_main_t *vam = &vat_main;
10214   vat_json_node_t *node = NULL;
10215
10216   if (VAT_JSON_ARRAY != vam->json_tree.type)
10217     {
10218       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
10219       vat_json_init_array (&vam->json_tree);
10220     }
10221   node = vat_json_array_add (&vam->json_tree);
10222
10223   vat_json_init_object (node);
10224   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
10225   vat_json_object_add_string_copy (node, "interface_name",
10226                                    mp->interface_name);
10227   vat_json_object_add_uint (node, "virtio_net_hdr_sz",
10228                             ntohl (mp->virtio_net_hdr_sz));
10229   vat_json_object_add_uint (node, "features_first_32",
10230                             clib_net_to_host_u32 (mp->features_first_32));
10231   vat_json_object_add_uint (node, "features_last_32",
10232                             clib_net_to_host_u32 (mp->features_last_32));
10233   vat_json_object_add_uint (node, "is_server", mp->is_server);
10234   vat_json_object_add_string_copy (node, "sock_filename", mp->sock_filename);
10235   vat_json_object_add_uint (node, "num_regions", ntohl (mp->num_regions));
10236   vat_json_object_add_uint (node, "sock_errno", ntohl (mp->sock_errno));
10237 }
10238
10239 static int
10240 api_sw_interface_vhost_user_dump (vat_main_t * vam)
10241 {
10242   unformat_input_t *i = vam->input;
10243   vl_api_sw_interface_vhost_user_dump_t *mp;
10244   vl_api_control_ping_t *mp_ping;
10245   int ret;
10246   u32 sw_if_index = ~0;
10247
10248   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10249     {
10250       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10251         ;
10252       else if (unformat (i, "sw_if_index %d", &sw_if_index))
10253         ;
10254       else
10255         break;
10256     }
10257
10258   print (vam->ofp,
10259          "Interface name            idx hdr_sz features server regions filename");
10260
10261   /* Get list of vhost-user interfaces */
10262   M (SW_INTERFACE_VHOST_USER_DUMP, mp);
10263   mp->sw_if_index = ntohl (sw_if_index);
10264   S (mp);
10265
10266   /* Use a control ping for synchronization */
10267   MPING (CONTROL_PING, mp_ping);
10268   S (mp_ping);
10269
10270   W (ret);
10271   return ret;
10272 }
10273
10274 static int
10275 api_show_version (vat_main_t * vam)
10276 {
10277   vl_api_show_version_t *mp;
10278   int ret;
10279
10280   M (SHOW_VERSION, mp);
10281
10282   S (mp);
10283   W (ret);
10284   return ret;
10285 }
10286
10287
10288 static int
10289 api_vxlan_gpe_add_del_tunnel (vat_main_t * vam)
10290 {
10291   unformat_input_t *line_input = vam->input;
10292   vl_api_vxlan_gpe_add_del_tunnel_t *mp;
10293   ip46_address_t local, remote;
10294   u8 is_add = 1;
10295   u8 local_set = 0;
10296   u8 remote_set = 0;
10297   u8 grp_set = 0;
10298   u32 mcast_sw_if_index = ~0;
10299   u32 encap_vrf_id = 0;
10300   u32 decap_vrf_id = 0;
10301   u8 protocol = ~0;
10302   u32 vni;
10303   u8 vni_set = 0;
10304   int ret;
10305
10306   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
10307     {
10308       if (unformat (line_input, "del"))
10309         is_add = 0;
10310       else if (unformat (line_input, "local %U",
10311                          unformat_ip46_address, &local))
10312         {
10313           local_set = 1;
10314         }
10315       else if (unformat (line_input, "remote %U",
10316                          unformat_ip46_address, &remote))
10317         {
10318           remote_set = 1;
10319         }
10320       else if (unformat (line_input, "group %U %U",
10321                          unformat_ip46_address, &remote,
10322                          api_unformat_sw_if_index, vam, &mcast_sw_if_index))
10323         {
10324           grp_set = remote_set = 1;
10325         }
10326       else if (unformat (line_input, "group %U",
10327                          unformat_ip46_address, &remote))
10328         {
10329           grp_set = remote_set = 1;
10330         }
10331       else
10332         if (unformat (line_input, "mcast_sw_if_index %u", &mcast_sw_if_index))
10333         ;
10334       else if (unformat (line_input, "encap-vrf-id %d", &encap_vrf_id))
10335         ;
10336       else if (unformat (line_input, "decap-vrf-id %d", &decap_vrf_id))
10337         ;
10338       else if (unformat (line_input, "vni %d", &vni))
10339         vni_set = 1;
10340       else if (unformat (line_input, "next-ip4"))
10341         protocol = 1;
10342       else if (unformat (line_input, "next-ip6"))
10343         protocol = 2;
10344       else if (unformat (line_input, "next-ethernet"))
10345         protocol = 3;
10346       else if (unformat (line_input, "next-nsh"))
10347         protocol = 4;
10348       else
10349         {
10350           errmsg ("parse error '%U'", format_unformat_error, line_input);
10351           return -99;
10352         }
10353     }
10354
10355   if (local_set == 0)
10356     {
10357       errmsg ("tunnel local address not specified");
10358       return -99;
10359     }
10360   if (remote_set == 0)
10361     {
10362       errmsg ("tunnel remote address not specified");
10363       return -99;
10364     }
10365   if (grp_set && mcast_sw_if_index == ~0)
10366     {
10367       errmsg ("tunnel nonexistent multicast device");
10368       return -99;
10369     }
10370   if (ip46_address_is_ip4 (&local) != ip46_address_is_ip4 (&remote))
10371     {
10372       errmsg ("both IPv4 and IPv6 addresses specified");
10373       return -99;
10374     }
10375
10376   if (vni_set == 0)
10377     {
10378       errmsg ("vni not specified");
10379       return -99;
10380     }
10381
10382   M (VXLAN_GPE_ADD_DEL_TUNNEL, mp);
10383
10384   ip_address_encode (&local,
10385                      ip46_address_is_ip4 (&local) ? IP46_TYPE_IP4 :
10386                      IP46_TYPE_IP6, &mp->local);
10387   ip_address_encode (&remote,
10388                      ip46_address_is_ip4 (&remote) ? IP46_TYPE_IP4 :
10389                      IP46_TYPE_IP6, &mp->remote);
10390
10391   mp->mcast_sw_if_index = ntohl (mcast_sw_if_index);
10392   mp->encap_vrf_id = ntohl (encap_vrf_id);
10393   mp->decap_vrf_id = ntohl (decap_vrf_id);
10394   mp->protocol = protocol;
10395   mp->vni = ntohl (vni);
10396   mp->is_add = is_add;
10397
10398   S (mp);
10399   W (ret);
10400   return ret;
10401 }
10402
10403 static void vl_api_vxlan_gpe_tunnel_details_t_handler
10404   (vl_api_vxlan_gpe_tunnel_details_t * mp)
10405 {
10406   vat_main_t *vam = &vat_main;
10407   ip46_address_t local, remote;
10408
10409   ip_address_decode (&mp->local, &local);
10410   ip_address_decode (&mp->remote, &remote);
10411
10412   print (vam->ofp, "%11d%24U%24U%13d%12d%19d%14d%14d",
10413          ntohl (mp->sw_if_index),
10414          format_ip46_address, &local, IP46_TYPE_ANY,
10415          format_ip46_address, &remote, IP46_TYPE_ANY,
10416          ntohl (mp->vni), mp->protocol,
10417          ntohl (mp->mcast_sw_if_index),
10418          ntohl (mp->encap_vrf_id), ntohl (mp->decap_vrf_id));
10419 }
10420
10421
10422 static void vl_api_vxlan_gpe_tunnel_details_t_handler_json
10423   (vl_api_vxlan_gpe_tunnel_details_t * mp)
10424 {
10425   vat_main_t *vam = &vat_main;
10426   vat_json_node_t *node = NULL;
10427   struct in_addr ip4;
10428   struct in6_addr ip6;
10429   ip46_address_t local, remote;
10430
10431   ip_address_decode (&mp->local, &local);
10432   ip_address_decode (&mp->remote, &remote);
10433
10434   if (VAT_JSON_ARRAY != vam->json_tree.type)
10435     {
10436       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
10437       vat_json_init_array (&vam->json_tree);
10438     }
10439   node = vat_json_array_add (&vam->json_tree);
10440
10441   vat_json_init_object (node);
10442   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
10443   if (ip46_address_is_ip4 (&local))
10444     {
10445       clib_memcpy (&ip4, &local.ip4, sizeof (ip4));
10446       vat_json_object_add_ip4 (node, "local", ip4);
10447       clib_memcpy (&ip4, &remote.ip4, sizeof (ip4));
10448       vat_json_object_add_ip4 (node, "remote", ip4);
10449     }
10450   else
10451     {
10452       clib_memcpy (&ip6, &local.ip6, sizeof (ip6));
10453       vat_json_object_add_ip6 (node, "local", ip6);
10454       clib_memcpy (&ip6, &remote.ip6, sizeof (ip6));
10455       vat_json_object_add_ip6 (node, "remote", ip6);
10456     }
10457   vat_json_object_add_uint (node, "vni", ntohl (mp->vni));
10458   vat_json_object_add_uint (node, "protocol", ntohl (mp->protocol));
10459   vat_json_object_add_uint (node, "mcast_sw_if_index",
10460                             ntohl (mp->mcast_sw_if_index));
10461   vat_json_object_add_uint (node, "encap_vrf_id", ntohl (mp->encap_vrf_id));
10462   vat_json_object_add_uint (node, "decap_vrf_id", ntohl (mp->decap_vrf_id));
10463   vat_json_object_add_uint (node, "is_ipv6", mp->is_ipv6 ? 1 : 0);
10464 }
10465
10466 static int
10467 api_vxlan_gpe_tunnel_dump (vat_main_t * vam)
10468 {
10469   unformat_input_t *i = vam->input;
10470   vl_api_vxlan_gpe_tunnel_dump_t *mp;
10471   vl_api_control_ping_t *mp_ping;
10472   u32 sw_if_index;
10473   u8 sw_if_index_set = 0;
10474   int ret;
10475
10476   /* Parse args required to build the message */
10477   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10478     {
10479       if (unformat (i, "sw_if_index %d", &sw_if_index))
10480         sw_if_index_set = 1;
10481       else
10482         break;
10483     }
10484
10485   if (sw_if_index_set == 0)
10486     {
10487       sw_if_index = ~0;
10488     }
10489
10490   if (!vam->json_output)
10491     {
10492       print (vam->ofp, "%11s%24s%24s%13s%15s%19s%14s%14s",
10493              "sw_if_index", "local", "remote", "vni",
10494              "protocol", "mcast_sw_if_index", "encap_vrf_id", "decap_vrf_id");
10495     }
10496
10497   /* Get list of vxlan-tunnel interfaces */
10498   M (VXLAN_GPE_TUNNEL_DUMP, mp);
10499
10500   mp->sw_if_index = htonl (sw_if_index);
10501
10502   S (mp);
10503
10504   /* Use a control ping for synchronization */
10505   MPING (CONTROL_PING, mp_ping);
10506   S (mp_ping);
10507
10508   W (ret);
10509   return ret;
10510 }
10511
10512 static void vl_api_l2_fib_table_details_t_handler
10513   (vl_api_l2_fib_table_details_t * mp)
10514 {
10515   vat_main_t *vam = &vat_main;
10516
10517   print (vam->ofp, "%3" PRIu32 "    %U    %3" PRIu32
10518          "       %d       %d     %d",
10519          ntohl (mp->bd_id), format_ethernet_address, mp->mac,
10520          ntohl (mp->sw_if_index), mp->static_mac, mp->filter_mac,
10521          mp->bvi_mac);
10522 }
10523
10524 static void vl_api_l2_fib_table_details_t_handler_json
10525   (vl_api_l2_fib_table_details_t * mp)
10526 {
10527   vat_main_t *vam = &vat_main;
10528   vat_json_node_t *node = NULL;
10529
10530   if (VAT_JSON_ARRAY != vam->json_tree.type)
10531     {
10532       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
10533       vat_json_init_array (&vam->json_tree);
10534     }
10535   node = vat_json_array_add (&vam->json_tree);
10536
10537   vat_json_init_object (node);
10538   vat_json_object_add_uint (node, "bd_id", ntohl (mp->bd_id));
10539   vat_json_object_add_bytes (node, "mac", mp->mac, 6);
10540   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
10541   vat_json_object_add_uint (node, "static_mac", mp->static_mac);
10542   vat_json_object_add_uint (node, "filter_mac", mp->filter_mac);
10543   vat_json_object_add_uint (node, "bvi_mac", mp->bvi_mac);
10544 }
10545
10546 static int
10547 api_l2_fib_table_dump (vat_main_t * vam)
10548 {
10549   unformat_input_t *i = vam->input;
10550   vl_api_l2_fib_table_dump_t *mp;
10551   vl_api_control_ping_t *mp_ping;
10552   u32 bd_id;
10553   u8 bd_id_set = 0;
10554   int ret;
10555
10556   /* Parse args required to build the message */
10557   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10558     {
10559       if (unformat (i, "bd_id %d", &bd_id))
10560         bd_id_set = 1;
10561       else
10562         break;
10563     }
10564
10565   if (bd_id_set == 0)
10566     {
10567       errmsg ("missing bridge domain");
10568       return -99;
10569     }
10570
10571   print (vam->ofp, "BD-ID     Mac Address      sw-ndx  Static  Filter  BVI");
10572
10573   /* Get list of l2 fib entries */
10574   M (L2_FIB_TABLE_DUMP, mp);
10575
10576   mp->bd_id = ntohl (bd_id);
10577   S (mp);
10578
10579   /* Use a control ping for synchronization */
10580   MPING (CONTROL_PING, mp_ping);
10581   S (mp_ping);
10582
10583   W (ret);
10584   return ret;
10585 }
10586
10587
10588 static int
10589 api_interface_name_renumber (vat_main_t * vam)
10590 {
10591   unformat_input_t *line_input = vam->input;
10592   vl_api_interface_name_renumber_t *mp;
10593   u32 sw_if_index = ~0;
10594   u32 new_show_dev_instance = ~0;
10595   int ret;
10596
10597   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
10598     {
10599       if (unformat (line_input, "%U", api_unformat_sw_if_index, vam,
10600                     &sw_if_index))
10601         ;
10602       else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
10603         ;
10604       else if (unformat (line_input, "new_show_dev_instance %d",
10605                          &new_show_dev_instance))
10606         ;
10607       else
10608         break;
10609     }
10610
10611   if (sw_if_index == ~0)
10612     {
10613       errmsg ("missing interface name or sw_if_index");
10614       return -99;
10615     }
10616
10617   if (new_show_dev_instance == ~0)
10618     {
10619       errmsg ("missing new_show_dev_instance");
10620       return -99;
10621     }
10622
10623   M (INTERFACE_NAME_RENUMBER, mp);
10624
10625   mp->sw_if_index = ntohl (sw_if_index);
10626   mp->new_show_dev_instance = ntohl (new_show_dev_instance);
10627
10628   S (mp);
10629   W (ret);
10630   return ret;
10631 }
10632
10633 static int
10634 api_want_l2_macs_events (vat_main_t * vam)
10635 {
10636   unformat_input_t *line_input = vam->input;
10637   vl_api_want_l2_macs_events_t *mp;
10638   u8 enable_disable = 1;
10639   u32 scan_delay = 0;
10640   u32 max_macs_in_event = 0;
10641   u32 learn_limit = 0;
10642   int ret;
10643
10644   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
10645     {
10646       if (unformat (line_input, "learn-limit %d", &learn_limit))
10647         ;
10648       else if (unformat (line_input, "scan-delay %d", &scan_delay))
10649         ;
10650       else if (unformat (line_input, "max-entries %d", &max_macs_in_event))
10651         ;
10652       else if (unformat (line_input, "disable"))
10653         enable_disable = 0;
10654       else
10655         break;
10656     }
10657
10658   M (WANT_L2_MACS_EVENTS, mp);
10659   mp->enable_disable = enable_disable;
10660   mp->pid = htonl (getpid ());
10661   mp->learn_limit = htonl (learn_limit);
10662   mp->scan_delay = (u8) scan_delay;
10663   mp->max_macs_in_event = (u8) (max_macs_in_event / 10);
10664   S (mp);
10665   W (ret);
10666   return ret;
10667 }
10668
10669 static int
10670 api_input_acl_set_interface (vat_main_t * vam)
10671 {
10672   unformat_input_t *i = vam->input;
10673   vl_api_input_acl_set_interface_t *mp;
10674   u32 sw_if_index;
10675   int sw_if_index_set;
10676   u32 ip4_table_index = ~0;
10677   u32 ip6_table_index = ~0;
10678   u32 l2_table_index = ~0;
10679   u8 is_add = 1;
10680   int ret;
10681
10682   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10683     {
10684       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10685         sw_if_index_set = 1;
10686       else if (unformat (i, "sw_if_index %d", &sw_if_index))
10687         sw_if_index_set = 1;
10688       else if (unformat (i, "del"))
10689         is_add = 0;
10690       else if (unformat (i, "ip4-table %d", &ip4_table_index))
10691         ;
10692       else if (unformat (i, "ip6-table %d", &ip6_table_index))
10693         ;
10694       else if (unformat (i, "l2-table %d", &l2_table_index))
10695         ;
10696       else
10697         {
10698           clib_warning ("parse error '%U'", format_unformat_error, i);
10699           return -99;
10700         }
10701     }
10702
10703   if (sw_if_index_set == 0)
10704     {
10705       errmsg ("missing interface name or sw_if_index");
10706       return -99;
10707     }
10708
10709   M (INPUT_ACL_SET_INTERFACE, mp);
10710
10711   mp->sw_if_index = ntohl (sw_if_index);
10712   mp->ip4_table_index = ntohl (ip4_table_index);
10713   mp->ip6_table_index = ntohl (ip6_table_index);
10714   mp->l2_table_index = ntohl (l2_table_index);
10715   mp->is_add = is_add;
10716
10717   S (mp);
10718   W (ret);
10719   return ret;
10720 }
10721
10722 static int
10723 api_output_acl_set_interface (vat_main_t * vam)
10724 {
10725   unformat_input_t *i = vam->input;
10726   vl_api_output_acl_set_interface_t *mp;
10727   u32 sw_if_index;
10728   int sw_if_index_set;
10729   u32 ip4_table_index = ~0;
10730   u32 ip6_table_index = ~0;
10731   u32 l2_table_index = ~0;
10732   u8 is_add = 1;
10733   int ret;
10734
10735   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10736     {
10737       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10738         sw_if_index_set = 1;
10739       else if (unformat (i, "sw_if_index %d", &sw_if_index))
10740         sw_if_index_set = 1;
10741       else if (unformat (i, "del"))
10742         is_add = 0;
10743       else if (unformat (i, "ip4-table %d", &ip4_table_index))
10744         ;
10745       else if (unformat (i, "ip6-table %d", &ip6_table_index))
10746         ;
10747       else if (unformat (i, "l2-table %d", &l2_table_index))
10748         ;
10749       else
10750         {
10751           clib_warning ("parse error '%U'", format_unformat_error, i);
10752           return -99;
10753         }
10754     }
10755
10756   if (sw_if_index_set == 0)
10757     {
10758       errmsg ("missing interface name or sw_if_index");
10759       return -99;
10760     }
10761
10762   M (OUTPUT_ACL_SET_INTERFACE, mp);
10763
10764   mp->sw_if_index = ntohl (sw_if_index);
10765   mp->ip4_table_index = ntohl (ip4_table_index);
10766   mp->ip6_table_index = ntohl (ip6_table_index);
10767   mp->l2_table_index = ntohl (l2_table_index);
10768   mp->is_add = is_add;
10769
10770   S (mp);
10771   W (ret);
10772   return ret;
10773 }
10774
10775 static int
10776 api_ip_address_dump (vat_main_t * vam)
10777 {
10778   unformat_input_t *i = vam->input;
10779   vl_api_ip_address_dump_t *mp;
10780   vl_api_control_ping_t *mp_ping;
10781   u32 sw_if_index = ~0;
10782   u8 sw_if_index_set = 0;
10783   u8 ipv4_set = 0;
10784   u8 ipv6_set = 0;
10785   int ret;
10786
10787   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10788     {
10789       if (unformat (i, "sw_if_index %d", &sw_if_index))
10790         sw_if_index_set = 1;
10791       else
10792         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10793         sw_if_index_set = 1;
10794       else if (unformat (i, "ipv4"))
10795         ipv4_set = 1;
10796       else if (unformat (i, "ipv6"))
10797         ipv6_set = 1;
10798       else
10799         break;
10800     }
10801
10802   if (ipv4_set && ipv6_set)
10803     {
10804       errmsg ("ipv4 and ipv6 flags cannot be both set");
10805       return -99;
10806     }
10807
10808   if ((!ipv4_set) && (!ipv6_set))
10809     {
10810       errmsg ("no ipv4 nor ipv6 flag set");
10811       return -99;
10812     }
10813
10814   if (sw_if_index_set == 0)
10815     {
10816       errmsg ("missing interface name or sw_if_index");
10817       return -99;
10818     }
10819
10820   vam->current_sw_if_index = sw_if_index;
10821   vam->is_ipv6 = ipv6_set;
10822
10823   M (IP_ADDRESS_DUMP, mp);
10824   mp->sw_if_index = ntohl (sw_if_index);
10825   mp->is_ipv6 = ipv6_set;
10826   S (mp);
10827
10828   /* Use a control ping for synchronization */
10829   MPING (CONTROL_PING, mp_ping);
10830   S (mp_ping);
10831
10832   W (ret);
10833   return ret;
10834 }
10835
10836 static int
10837 api_ip_dump (vat_main_t * vam)
10838 {
10839   vl_api_ip_dump_t *mp;
10840   vl_api_control_ping_t *mp_ping;
10841   unformat_input_t *in = vam->input;
10842   int ipv4_set = 0;
10843   int ipv6_set = 0;
10844   int is_ipv6;
10845   int i;
10846   int ret;
10847
10848   while (unformat_check_input (in) != UNFORMAT_END_OF_INPUT)
10849     {
10850       if (unformat (in, "ipv4"))
10851         ipv4_set = 1;
10852       else if (unformat (in, "ipv6"))
10853         ipv6_set = 1;
10854       else
10855         break;
10856     }
10857
10858   if (ipv4_set && ipv6_set)
10859     {
10860       errmsg ("ipv4 and ipv6 flags cannot be both set");
10861       return -99;
10862     }
10863
10864   if ((!ipv4_set) && (!ipv6_set))
10865     {
10866       errmsg ("no ipv4 nor ipv6 flag set");
10867       return -99;
10868     }
10869
10870   is_ipv6 = ipv6_set;
10871   vam->is_ipv6 = is_ipv6;
10872
10873   /* free old data */
10874   for (i = 0; i < vec_len (vam->ip_details_by_sw_if_index[is_ipv6]); i++)
10875     {
10876       vec_free (vam->ip_details_by_sw_if_index[is_ipv6][i].addr);
10877     }
10878   vec_free (vam->ip_details_by_sw_if_index[is_ipv6]);
10879
10880   M (IP_DUMP, mp);
10881   mp->is_ipv6 = ipv6_set;
10882   S (mp);
10883
10884   /* Use a control ping for synchronization */
10885   MPING (CONTROL_PING, mp_ping);
10886   S (mp_ping);
10887
10888   W (ret);
10889   return ret;
10890 }
10891
10892 static int
10893 api_ipsec_spd_add_del (vat_main_t * vam)
10894 {
10895   unformat_input_t *i = vam->input;
10896   vl_api_ipsec_spd_add_del_t *mp;
10897   u32 spd_id = ~0;
10898   u8 is_add = 1;
10899   int ret;
10900
10901   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10902     {
10903       if (unformat (i, "spd_id %d", &spd_id))
10904         ;
10905       else if (unformat (i, "del"))
10906         is_add = 0;
10907       else
10908         {
10909           clib_warning ("parse error '%U'", format_unformat_error, i);
10910           return -99;
10911         }
10912     }
10913   if (spd_id == ~0)
10914     {
10915       errmsg ("spd_id must be set");
10916       return -99;
10917     }
10918
10919   M (IPSEC_SPD_ADD_DEL, mp);
10920
10921   mp->spd_id = ntohl (spd_id);
10922   mp->is_add = is_add;
10923
10924   S (mp);
10925   W (ret);
10926   return ret;
10927 }
10928
10929 static int
10930 api_ipsec_interface_add_del_spd (vat_main_t * vam)
10931 {
10932   unformat_input_t *i = vam->input;
10933   vl_api_ipsec_interface_add_del_spd_t *mp;
10934   u32 sw_if_index;
10935   u8 sw_if_index_set = 0;
10936   u32 spd_id = (u32) ~ 0;
10937   u8 is_add = 1;
10938   int ret;
10939
10940   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10941     {
10942       if (unformat (i, "del"))
10943         is_add = 0;
10944       else if (unformat (i, "spd_id %d", &spd_id))
10945         ;
10946       else
10947         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10948         sw_if_index_set = 1;
10949       else if (unformat (i, "sw_if_index %d", &sw_if_index))
10950         sw_if_index_set = 1;
10951       else
10952         {
10953           clib_warning ("parse error '%U'", format_unformat_error, i);
10954           return -99;
10955         }
10956
10957     }
10958
10959   if (spd_id == (u32) ~ 0)
10960     {
10961       errmsg ("spd_id must be set");
10962       return -99;
10963     }
10964
10965   if (sw_if_index_set == 0)
10966     {
10967       errmsg ("missing interface name or sw_if_index");
10968       return -99;
10969     }
10970
10971   M (IPSEC_INTERFACE_ADD_DEL_SPD, mp);
10972
10973   mp->spd_id = ntohl (spd_id);
10974   mp->sw_if_index = ntohl (sw_if_index);
10975   mp->is_add = is_add;
10976
10977   S (mp);
10978   W (ret);
10979   return ret;
10980 }
10981
10982 static int
10983 api_ipsec_spd_entry_add_del (vat_main_t * vam)
10984 {
10985   unformat_input_t *i = vam->input;
10986   vl_api_ipsec_spd_entry_add_del_t *mp;
10987   u8 is_add = 1, is_outbound = 0;
10988   u32 spd_id = 0, sa_id = 0, protocol = 0, policy = 0;
10989   i32 priority = 0;
10990   u32 rport_start = 0, rport_stop = (u32) ~ 0;
10991   u32 lport_start = 0, lport_stop = (u32) ~ 0;
10992   vl_api_address_t laddr_start = { }, laddr_stop =
10993   {
10994   }, raddr_start =
10995   {
10996   }, raddr_stop =
10997   {
10998   };
10999   int ret;
11000
11001   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11002     {
11003       if (unformat (i, "del"))
11004         is_add = 0;
11005       if (unformat (i, "outbound"))
11006         is_outbound = 1;
11007       if (unformat (i, "inbound"))
11008         is_outbound = 0;
11009       else if (unformat (i, "spd_id %d", &spd_id))
11010         ;
11011       else if (unformat (i, "sa_id %d", &sa_id))
11012         ;
11013       else if (unformat (i, "priority %d", &priority))
11014         ;
11015       else if (unformat (i, "protocol %d", &protocol))
11016         ;
11017       else if (unformat (i, "lport_start %d", &lport_start))
11018         ;
11019       else if (unformat (i, "lport_stop %d", &lport_stop))
11020         ;
11021       else if (unformat (i, "rport_start %d", &rport_start))
11022         ;
11023       else if (unformat (i, "rport_stop %d", &rport_stop))
11024         ;
11025       else if (unformat (i, "laddr_start %U",
11026                          unformat_vl_api_address, &laddr_start))
11027         ;
11028       else if (unformat (i, "laddr_stop %U", unformat_vl_api_address,
11029                          &laddr_stop))
11030         ;
11031       else if (unformat (i, "raddr_start %U", unformat_vl_api_address,
11032                          &raddr_start))
11033         ;
11034       else if (unformat (i, "raddr_stop %U", unformat_vl_api_address,
11035                          &raddr_stop))
11036         ;
11037       else
11038         if (unformat (i, "action %U", unformat_ipsec_policy_action, &policy))
11039         {
11040           if (policy == IPSEC_POLICY_ACTION_RESOLVE)
11041             {
11042               clib_warning ("unsupported action: 'resolve'");
11043               return -99;
11044             }
11045         }
11046       else
11047         {
11048           clib_warning ("parse error '%U'", format_unformat_error, i);
11049           return -99;
11050         }
11051
11052     }
11053
11054   M (IPSEC_SPD_ENTRY_ADD_DEL, mp);
11055
11056   mp->is_add = is_add;
11057
11058   mp->entry.spd_id = ntohl (spd_id);
11059   mp->entry.priority = ntohl (priority);
11060   mp->entry.is_outbound = is_outbound;
11061
11062   clib_memcpy (&mp->entry.remote_address_start, &raddr_start,
11063                sizeof (vl_api_address_t));
11064   clib_memcpy (&mp->entry.remote_address_stop, &raddr_stop,
11065                sizeof (vl_api_address_t));
11066   clib_memcpy (&mp->entry.local_address_start, &laddr_start,
11067                sizeof (vl_api_address_t));
11068   clib_memcpy (&mp->entry.local_address_stop, &laddr_stop,
11069                sizeof (vl_api_address_t));
11070
11071   mp->entry.protocol = (u8) protocol;
11072   mp->entry.local_port_start = ntohs ((u16) lport_start);
11073   mp->entry.local_port_stop = ntohs ((u16) lport_stop);
11074   mp->entry.remote_port_start = ntohs ((u16) rport_start);
11075   mp->entry.remote_port_stop = ntohs ((u16) rport_stop);
11076   mp->entry.policy = (u8) policy;
11077   mp->entry.sa_id = ntohl (sa_id);
11078
11079   S (mp);
11080   W (ret);
11081   return ret;
11082 }
11083
11084 static int
11085 api_ipsec_sad_entry_add_del (vat_main_t * vam)
11086 {
11087   unformat_input_t *i = vam->input;
11088   vl_api_ipsec_sad_entry_add_del_t *mp;
11089   u32 sad_id = 0, spi = 0;
11090   u8 *ck = 0, *ik = 0;
11091   u8 is_add = 1;
11092
11093   vl_api_ipsec_crypto_alg_t crypto_alg = IPSEC_API_CRYPTO_ALG_NONE;
11094   vl_api_ipsec_integ_alg_t integ_alg = IPSEC_API_INTEG_ALG_NONE;
11095   vl_api_ipsec_sad_flags_t flags = IPSEC_API_SAD_FLAG_NONE;
11096   vl_api_ipsec_proto_t protocol = IPSEC_API_PROTO_AH;
11097   vl_api_address_t tun_src, tun_dst;
11098   int ret;
11099
11100   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11101     {
11102       if (unformat (i, "del"))
11103         is_add = 0;
11104       else if (unformat (i, "sad_id %d", &sad_id))
11105         ;
11106       else if (unformat (i, "spi %d", &spi))
11107         ;
11108       else if (unformat (i, "esp"))
11109         protocol = IPSEC_API_PROTO_ESP;
11110       else
11111         if (unformat (i, "tunnel_src %U", unformat_vl_api_address, &tun_src))
11112         {
11113           flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL;
11114           if (ADDRESS_IP6 == tun_src.af)
11115             flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL_V6;
11116         }
11117       else
11118         if (unformat (i, "tunnel_dst %U", unformat_vl_api_address, &tun_dst))
11119         {
11120           flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL;
11121           if (ADDRESS_IP6 == tun_src.af)
11122             flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL_V6;
11123         }
11124       else
11125         if (unformat (i, "crypto_alg %U",
11126                       unformat_ipsec_api_crypto_alg, &crypto_alg))
11127         ;
11128       else if (unformat (i, "crypto_key %U", unformat_hex_string, &ck))
11129         ;
11130       else if (unformat (i, "integ_alg %U",
11131                          unformat_ipsec_api_integ_alg, &integ_alg))
11132         ;
11133       else if (unformat (i, "integ_key %U", unformat_hex_string, &ik))
11134         ;
11135       else
11136         {
11137           clib_warning ("parse error '%U'", format_unformat_error, i);
11138           return -99;
11139         }
11140
11141     }
11142
11143   M (IPSEC_SAD_ENTRY_ADD_DEL, mp);
11144
11145   mp->is_add = is_add;
11146   mp->entry.sad_id = ntohl (sad_id);
11147   mp->entry.protocol = protocol;
11148   mp->entry.spi = ntohl (spi);
11149   mp->entry.flags = flags;
11150
11151   mp->entry.crypto_algorithm = crypto_alg;
11152   mp->entry.integrity_algorithm = integ_alg;
11153   mp->entry.crypto_key.length = vec_len (ck);
11154   mp->entry.integrity_key.length = vec_len (ik);
11155
11156   if (mp->entry.crypto_key.length > sizeof (mp->entry.crypto_key.data))
11157     mp->entry.crypto_key.length = sizeof (mp->entry.crypto_key.data);
11158
11159   if (mp->entry.integrity_key.length > sizeof (mp->entry.integrity_key.data))
11160     mp->entry.integrity_key.length = sizeof (mp->entry.integrity_key.data);
11161
11162   if (ck)
11163     clib_memcpy (mp->entry.crypto_key.data, ck, mp->entry.crypto_key.length);
11164   if (ik)
11165     clib_memcpy (mp->entry.integrity_key.data, ik,
11166                  mp->entry.integrity_key.length);
11167
11168   if (flags & IPSEC_API_SAD_FLAG_IS_TUNNEL)
11169     {
11170       clib_memcpy (&mp->entry.tunnel_src, &tun_src,
11171                    sizeof (mp->entry.tunnel_src));
11172       clib_memcpy (&mp->entry.tunnel_dst, &tun_dst,
11173                    sizeof (mp->entry.tunnel_dst));
11174     }
11175
11176   S (mp);
11177   W (ret);
11178   return ret;
11179 }
11180
11181 static int
11182 api_ipsec_tunnel_if_add_del (vat_main_t * vam)
11183 {
11184   unformat_input_t *i = vam->input;
11185   vl_api_ipsec_tunnel_if_add_del_t *mp;
11186   u32 local_spi = 0, remote_spi = 0;
11187   u32 crypto_alg = 0, integ_alg = 0;
11188   u8 *lck = NULL, *rck = NULL;
11189   u8 *lik = NULL, *rik = NULL;
11190   vl_api_address_t local_ip = { 0 };
11191   vl_api_address_t remote_ip = { 0 };
11192   f64 before = 0;
11193   u8 is_add = 1;
11194   u8 esn = 0;
11195   u8 anti_replay = 0;
11196   u8 renumber = 0;
11197   u32 instance = ~0;
11198   u32 count = 1, jj;
11199   int ret = -1;
11200
11201   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11202     {
11203       if (unformat (i, "del"))
11204         is_add = 0;
11205       else if (unformat (i, "esn"))
11206         esn = 1;
11207       else if (unformat (i, "anti-replay"))
11208         anti_replay = 1;
11209       else if (unformat (i, "count %d", &count))
11210         ;
11211       else if (unformat (i, "local_spi %d", &local_spi))
11212         ;
11213       else if (unformat (i, "remote_spi %d", &remote_spi))
11214         ;
11215       else
11216         if (unformat (i, "local_ip %U", unformat_vl_api_address, &local_ip))
11217         ;
11218       else
11219         if (unformat (i, "remote_ip %U", unformat_vl_api_address, &remote_ip))
11220         ;
11221       else if (unformat (i, "local_crypto_key %U", unformat_hex_string, &lck))
11222         ;
11223       else
11224         if (unformat (i, "remote_crypto_key %U", unformat_hex_string, &rck))
11225         ;
11226       else if (unformat (i, "local_integ_key %U", unformat_hex_string, &lik))
11227         ;
11228       else if (unformat (i, "remote_integ_key %U", unformat_hex_string, &rik))
11229         ;
11230       else
11231         if (unformat
11232             (i, "crypto_alg %U", unformat_ipsec_api_crypto_alg, &crypto_alg))
11233         {
11234           if (crypto_alg >= IPSEC_CRYPTO_N_ALG)
11235             {
11236               errmsg ("unsupported crypto-alg: '%U'\n",
11237                       format_ipsec_crypto_alg, crypto_alg);
11238               return -99;
11239             }
11240         }
11241       else
11242         if (unformat
11243             (i, "integ_alg %U", unformat_ipsec_api_integ_alg, &integ_alg))
11244         {
11245           if (integ_alg >= IPSEC_INTEG_N_ALG)
11246             {
11247               errmsg ("unsupported integ-alg: '%U'\n",
11248                       format_ipsec_integ_alg, integ_alg);
11249               return -99;
11250             }
11251         }
11252       else if (unformat (i, "instance %u", &instance))
11253         renumber = 1;
11254       else
11255         {
11256           errmsg ("parse error '%U'\n", format_unformat_error, i);
11257           return -99;
11258         }
11259     }
11260
11261   if (count > 1)
11262     {
11263       /* Turn on async mode */
11264       vam->async_mode = 1;
11265       vam->async_errors = 0;
11266       before = vat_time_now (vam);
11267     }
11268
11269   for (jj = 0; jj < count; jj++)
11270     {
11271       M (IPSEC_TUNNEL_IF_ADD_DEL, mp);
11272
11273       mp->is_add = is_add;
11274       mp->esn = esn;
11275       mp->anti_replay = anti_replay;
11276
11277       if (jj > 0)
11278         increment_address (&remote_ip);
11279
11280       clib_memcpy (&mp->local_ip, &local_ip, sizeof (local_ip));
11281       clib_memcpy (&mp->remote_ip, &remote_ip, sizeof (remote_ip));
11282
11283       mp->local_spi = htonl (local_spi + jj);
11284       mp->remote_spi = htonl (remote_spi + jj);
11285       mp->crypto_alg = (u8) crypto_alg;
11286
11287       mp->local_crypto_key_len = 0;
11288       if (lck)
11289         {
11290           mp->local_crypto_key_len = vec_len (lck);
11291           if (mp->local_crypto_key_len > sizeof (mp->local_crypto_key))
11292             mp->local_crypto_key_len = sizeof (mp->local_crypto_key);
11293           clib_memcpy (mp->local_crypto_key, lck, mp->local_crypto_key_len);
11294         }
11295
11296       mp->remote_crypto_key_len = 0;
11297       if (rck)
11298         {
11299           mp->remote_crypto_key_len = vec_len (rck);
11300           if (mp->remote_crypto_key_len > sizeof (mp->remote_crypto_key))
11301             mp->remote_crypto_key_len = sizeof (mp->remote_crypto_key);
11302           clib_memcpy (mp->remote_crypto_key, rck, mp->remote_crypto_key_len);
11303         }
11304
11305       mp->integ_alg = (u8) integ_alg;
11306
11307       mp->local_integ_key_len = 0;
11308       if (lik)
11309         {
11310           mp->local_integ_key_len = vec_len (lik);
11311           if (mp->local_integ_key_len > sizeof (mp->local_integ_key))
11312             mp->local_integ_key_len = sizeof (mp->local_integ_key);
11313           clib_memcpy (mp->local_integ_key, lik, mp->local_integ_key_len);
11314         }
11315
11316       mp->remote_integ_key_len = 0;
11317       if (rik)
11318         {
11319           mp->remote_integ_key_len = vec_len (rik);
11320           if (mp->remote_integ_key_len > sizeof (mp->remote_integ_key))
11321             mp->remote_integ_key_len = sizeof (mp->remote_integ_key);
11322           clib_memcpy (mp->remote_integ_key, rik, mp->remote_integ_key_len);
11323         }
11324
11325       if (renumber)
11326         {
11327           mp->renumber = renumber;
11328           mp->show_instance = ntohl (instance);
11329         }
11330       S (mp);
11331     }
11332
11333   /* When testing multiple add/del ops, use a control-ping to sync */
11334   if (count > 1)
11335     {
11336       vl_api_control_ping_t *mp_ping;
11337       f64 after;
11338       f64 timeout;
11339
11340       /* Shut off async mode */
11341       vam->async_mode = 0;
11342
11343       MPING (CONTROL_PING, mp_ping);
11344       S (mp_ping);
11345
11346       timeout = vat_time_now (vam) + 1.0;
11347       while (vat_time_now (vam) < timeout)
11348         if (vam->result_ready == 1)
11349           goto out;
11350       vam->retval = -99;
11351
11352     out:
11353       if (vam->retval == -99)
11354         errmsg ("timeout");
11355
11356       if (vam->async_errors > 0)
11357         {
11358           errmsg ("%d asynchronous errors", vam->async_errors);
11359           vam->retval = -98;
11360         }
11361       vam->async_errors = 0;
11362       after = vat_time_now (vam);
11363
11364       /* slim chance, but we might have eaten SIGTERM on the first iteration */
11365       if (jj > 0)
11366         count = jj;
11367
11368       print (vam->ofp, "%d tunnels in %.6f secs, %.2f tunnels/sec",
11369              count, after - before, count / (after - before));
11370     }
11371   else
11372     {
11373       /* Wait for a reply... */
11374       W (ret);
11375       return ret;
11376     }
11377
11378   return ret;
11379 }
11380
11381 static void
11382 vl_api_ipsec_sa_details_t_handler (vl_api_ipsec_sa_details_t * mp)
11383 {
11384   vat_main_t *vam = &vat_main;
11385
11386   print (vam->ofp, "sa_id %u sw_if_index %u spi %u proto %u crypto_alg %u "
11387          "crypto_key %U integ_alg %u integ_key %U flags %x "
11388          "tunnel_src_addr %U tunnel_dst_addr %U "
11389          "salt %u seq_outbound %lu last_seq_inbound %lu "
11390          "replay_window %lu stat_index %u\n",
11391          ntohl (mp->entry.sad_id),
11392          ntohl (mp->sw_if_index),
11393          ntohl (mp->entry.spi),
11394          ntohl (mp->entry.protocol),
11395          ntohl (mp->entry.crypto_algorithm),
11396          format_hex_bytes, mp->entry.crypto_key.data,
11397          mp->entry.crypto_key.length, ntohl (mp->entry.integrity_algorithm),
11398          format_hex_bytes, mp->entry.integrity_key.data,
11399          mp->entry.integrity_key.length, ntohl (mp->entry.flags),
11400          format_vl_api_address, &mp->entry.tunnel_src, format_vl_api_address,
11401          &mp->entry.tunnel_dst, ntohl (mp->salt),
11402          clib_net_to_host_u64 (mp->seq_outbound),
11403          clib_net_to_host_u64 (mp->last_seq_inbound),
11404          clib_net_to_host_u64 (mp->replay_window), ntohl (mp->stat_index));
11405 }
11406
11407 #define vl_api_ipsec_sa_details_t_endian vl_noop_handler
11408 #define vl_api_ipsec_sa_details_t_print vl_noop_handler
11409
11410 static void vl_api_ipsec_sa_details_t_handler_json
11411   (vl_api_ipsec_sa_details_t * mp)
11412 {
11413   vat_main_t *vam = &vat_main;
11414   vat_json_node_t *node = NULL;
11415   vl_api_ipsec_sad_flags_t flags;
11416
11417   if (VAT_JSON_ARRAY != vam->json_tree.type)
11418     {
11419       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
11420       vat_json_init_array (&vam->json_tree);
11421     }
11422   node = vat_json_array_add (&vam->json_tree);
11423
11424   vat_json_init_object (node);
11425   vat_json_object_add_uint (node, "sa_id", ntohl (mp->entry.sad_id));
11426   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
11427   vat_json_object_add_uint (node, "spi", ntohl (mp->entry.spi));
11428   vat_json_object_add_uint (node, "proto", ntohl (mp->entry.protocol));
11429   vat_json_object_add_uint (node, "crypto_alg",
11430                             ntohl (mp->entry.crypto_algorithm));
11431   vat_json_object_add_uint (node, "integ_alg",
11432                             ntohl (mp->entry.integrity_algorithm));
11433   flags = ntohl (mp->entry.flags);
11434   vat_json_object_add_uint (node, "use_esn",
11435                             ! !(flags & IPSEC_API_SAD_FLAG_USE_ESN));
11436   vat_json_object_add_uint (node, "use_anti_replay",
11437                             ! !(flags & IPSEC_API_SAD_FLAG_USE_ANTI_REPLAY));
11438   vat_json_object_add_uint (node, "is_tunnel",
11439                             ! !(flags & IPSEC_API_SAD_FLAG_IS_TUNNEL));
11440   vat_json_object_add_uint (node, "is_tunnel_ip6",
11441                             ! !(flags & IPSEC_API_SAD_FLAG_IS_TUNNEL_V6));
11442   vat_json_object_add_uint (node, "udp_encap",
11443                             ! !(flags & IPSEC_API_SAD_FLAG_UDP_ENCAP));
11444   vat_json_object_add_bytes (node, "crypto_key", mp->entry.crypto_key.data,
11445                              mp->entry.crypto_key.length);
11446   vat_json_object_add_bytes (node, "integ_key", mp->entry.integrity_key.data,
11447                              mp->entry.integrity_key.length);
11448   vat_json_object_add_address (node, "src", &mp->entry.tunnel_src);
11449   vat_json_object_add_address (node, "dst", &mp->entry.tunnel_dst);
11450   vat_json_object_add_uint (node, "replay_window",
11451                             clib_net_to_host_u64 (mp->replay_window));
11452   vat_json_object_add_uint (node, "stat_index", ntohl (mp->stat_index));
11453 }
11454
11455 static int
11456 api_ipsec_sa_dump (vat_main_t * vam)
11457 {
11458   unformat_input_t *i = vam->input;
11459   vl_api_ipsec_sa_dump_t *mp;
11460   vl_api_control_ping_t *mp_ping;
11461   u32 sa_id = ~0;
11462   int ret;
11463
11464   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11465     {
11466       if (unformat (i, "sa_id %d", &sa_id))
11467         ;
11468       else
11469         {
11470           clib_warning ("parse error '%U'", format_unformat_error, i);
11471           return -99;
11472         }
11473     }
11474
11475   M (IPSEC_SA_DUMP, mp);
11476
11477   mp->sa_id = ntohl (sa_id);
11478
11479   S (mp);
11480
11481   /* Use a control ping for synchronization */
11482   M (CONTROL_PING, mp_ping);
11483   S (mp_ping);
11484
11485   W (ret);
11486   return ret;
11487 }
11488
11489 static int
11490 api_ipsec_tunnel_if_set_sa (vat_main_t * vam)
11491 {
11492   unformat_input_t *i = vam->input;
11493   vl_api_ipsec_tunnel_if_set_sa_t *mp;
11494   u32 sw_if_index = ~0;
11495   u32 sa_id = ~0;
11496   u8 is_outbound = (u8) ~ 0;
11497   int ret;
11498
11499   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11500     {
11501       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
11502         ;
11503       else if (unformat (i, "sa_id %d", &sa_id))
11504         ;
11505       else if (unformat (i, "outbound"))
11506         is_outbound = 1;
11507       else if (unformat (i, "inbound"))
11508         is_outbound = 0;
11509       else
11510         {
11511           clib_warning ("parse error '%U'", format_unformat_error, i);
11512           return -99;
11513         }
11514     }
11515
11516   if (sw_if_index == ~0)
11517     {
11518       errmsg ("interface must be specified");
11519       return -99;
11520     }
11521
11522   if (sa_id == ~0)
11523     {
11524       errmsg ("SA ID must be specified");
11525       return -99;
11526     }
11527
11528   M (IPSEC_TUNNEL_IF_SET_SA, mp);
11529
11530   mp->sw_if_index = htonl (sw_if_index);
11531   mp->sa_id = htonl (sa_id);
11532   mp->is_outbound = is_outbound;
11533
11534   S (mp);
11535   W (ret);
11536
11537   return ret;
11538 }
11539
11540 static int
11541 api_get_first_msg_id (vat_main_t * vam)
11542 {
11543   vl_api_get_first_msg_id_t *mp;
11544   unformat_input_t *i = vam->input;
11545   u8 *name;
11546   u8 name_set = 0;
11547   int ret;
11548
11549   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11550     {
11551       if (unformat (i, "client %s", &name))
11552         name_set = 1;
11553       else
11554         break;
11555     }
11556
11557   if (name_set == 0)
11558     {
11559       errmsg ("missing client name");
11560       return -99;
11561     }
11562   vec_add1 (name, 0);
11563
11564   if (vec_len (name) > 63)
11565     {
11566       errmsg ("client name too long");
11567       return -99;
11568     }
11569
11570   M (GET_FIRST_MSG_ID, mp);
11571   clib_memcpy (mp->name, name, vec_len (name));
11572   S (mp);
11573   W (ret);
11574   return ret;
11575 }
11576
11577 static int
11578 api_cop_interface_enable_disable (vat_main_t * vam)
11579 {
11580   unformat_input_t *line_input = vam->input;
11581   vl_api_cop_interface_enable_disable_t *mp;
11582   u32 sw_if_index = ~0;
11583   u8 enable_disable = 1;
11584   int ret;
11585
11586   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
11587     {
11588       if (unformat (line_input, "disable"))
11589         enable_disable = 0;
11590       if (unformat (line_input, "enable"))
11591         enable_disable = 1;
11592       else if (unformat (line_input, "%U", api_unformat_sw_if_index,
11593                          vam, &sw_if_index))
11594         ;
11595       else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
11596         ;
11597       else
11598         break;
11599     }
11600
11601   if (sw_if_index == ~0)
11602     {
11603       errmsg ("missing interface name or sw_if_index");
11604       return -99;
11605     }
11606
11607   /* Construct the API message */
11608   M (COP_INTERFACE_ENABLE_DISABLE, mp);
11609   mp->sw_if_index = ntohl (sw_if_index);
11610   mp->enable_disable = enable_disable;
11611
11612   /* send it... */
11613   S (mp);
11614   /* Wait for the reply */
11615   W (ret);
11616   return ret;
11617 }
11618
11619 static int
11620 api_cop_whitelist_enable_disable (vat_main_t * vam)
11621 {
11622   unformat_input_t *line_input = vam->input;
11623   vl_api_cop_whitelist_enable_disable_t *mp;
11624   u32 sw_if_index = ~0;
11625   u8 ip4 = 0, ip6 = 0, default_cop = 0;
11626   u32 fib_id = 0;
11627   int ret;
11628
11629   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
11630     {
11631       if (unformat (line_input, "ip4"))
11632         ip4 = 1;
11633       else if (unformat (line_input, "ip6"))
11634         ip6 = 1;
11635       else if (unformat (line_input, "default"))
11636         default_cop = 1;
11637       else if (unformat (line_input, "%U", api_unformat_sw_if_index,
11638                          vam, &sw_if_index))
11639         ;
11640       else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
11641         ;
11642       else if (unformat (line_input, "fib-id %d", &fib_id))
11643         ;
11644       else
11645         break;
11646     }
11647
11648   if (sw_if_index == ~0)
11649     {
11650       errmsg ("missing interface name or sw_if_index");
11651       return -99;
11652     }
11653
11654   /* Construct the API message */
11655   M (COP_WHITELIST_ENABLE_DISABLE, mp);
11656   mp->sw_if_index = ntohl (sw_if_index);
11657   mp->fib_id = ntohl (fib_id);
11658   mp->ip4 = ip4;
11659   mp->ip6 = ip6;
11660   mp->default_cop = default_cop;
11661
11662   /* send it... */
11663   S (mp);
11664   /* Wait for the reply */
11665   W (ret);
11666   return ret;
11667 }
11668
11669 static int
11670 api_get_node_graph (vat_main_t * vam)
11671 {
11672   vl_api_get_node_graph_t *mp;
11673   int ret;
11674
11675   M (GET_NODE_GRAPH, mp);
11676
11677   /* send it... */
11678   S (mp);
11679   /* Wait for the reply */
11680   W (ret);
11681   return ret;
11682 }
11683
11684 static int
11685 api_af_packet_create (vat_main_t * vam)
11686 {
11687   unformat_input_t *i = vam->input;
11688   vl_api_af_packet_create_t *mp;
11689   u8 *host_if_name = 0;
11690   u8 hw_addr[6];
11691   u8 random_hw_addr = 1;
11692   int ret;
11693
11694   clib_memset (hw_addr, 0, sizeof (hw_addr));
11695
11696   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11697     {
11698       if (unformat (i, "name %s", &host_if_name))
11699         vec_add1 (host_if_name, 0);
11700       else if (unformat (i, "hw_addr %U", unformat_ethernet_address, hw_addr))
11701         random_hw_addr = 0;
11702       else
11703         break;
11704     }
11705
11706   if (!vec_len (host_if_name))
11707     {
11708       errmsg ("host-interface name must be specified");
11709       return -99;
11710     }
11711
11712   if (vec_len (host_if_name) > 64)
11713     {
11714       errmsg ("host-interface name too long");
11715       return -99;
11716     }
11717
11718   M (AF_PACKET_CREATE, mp);
11719
11720   clib_memcpy (mp->host_if_name, host_if_name, vec_len (host_if_name));
11721   clib_memcpy (mp->hw_addr, hw_addr, 6);
11722   mp->use_random_hw_addr = random_hw_addr;
11723   vec_free (host_if_name);
11724
11725   S (mp);
11726
11727   /* *INDENT-OFF* */
11728   W2 (ret,
11729       ({
11730         if (ret == 0)
11731           fprintf (vam->ofp ? vam->ofp : stderr,
11732                    " new sw_if_index = %d\n", vam->sw_if_index);
11733       }));
11734   /* *INDENT-ON* */
11735   return ret;
11736 }
11737
11738 static int
11739 api_af_packet_delete (vat_main_t * vam)
11740 {
11741   unformat_input_t *i = vam->input;
11742   vl_api_af_packet_delete_t *mp;
11743   u8 *host_if_name = 0;
11744   int ret;
11745
11746   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11747     {
11748       if (unformat (i, "name %s", &host_if_name))
11749         vec_add1 (host_if_name, 0);
11750       else
11751         break;
11752     }
11753
11754   if (!vec_len (host_if_name))
11755     {
11756       errmsg ("host-interface name must be specified");
11757       return -99;
11758     }
11759
11760   if (vec_len (host_if_name) > 64)
11761     {
11762       errmsg ("host-interface name too long");
11763       return -99;
11764     }
11765
11766   M (AF_PACKET_DELETE, mp);
11767
11768   clib_memcpy (mp->host_if_name, host_if_name, vec_len (host_if_name));
11769   vec_free (host_if_name);
11770
11771   S (mp);
11772   W (ret);
11773   return ret;
11774 }
11775
11776 static void vl_api_af_packet_details_t_handler
11777   (vl_api_af_packet_details_t * mp)
11778 {
11779   vat_main_t *vam = &vat_main;
11780
11781   print (vam->ofp, "%-16s %d",
11782          mp->host_if_name, clib_net_to_host_u32 (mp->sw_if_index));
11783 }
11784
11785 static void vl_api_af_packet_details_t_handler_json
11786   (vl_api_af_packet_details_t * mp)
11787 {
11788   vat_main_t *vam = &vat_main;
11789   vat_json_node_t *node = NULL;
11790
11791   if (VAT_JSON_ARRAY != vam->json_tree.type)
11792     {
11793       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
11794       vat_json_init_array (&vam->json_tree);
11795     }
11796   node = vat_json_array_add (&vam->json_tree);
11797
11798   vat_json_init_object (node);
11799   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
11800   vat_json_object_add_string_copy (node, "dev_name", mp->host_if_name);
11801 }
11802
11803 static int
11804 api_af_packet_dump (vat_main_t * vam)
11805 {
11806   vl_api_af_packet_dump_t *mp;
11807   vl_api_control_ping_t *mp_ping;
11808   int ret;
11809
11810   print (vam->ofp, "\n%-16s %s", "dev_name", "sw_if_index");
11811   /* Get list of tap interfaces */
11812   M (AF_PACKET_DUMP, mp);
11813   S (mp);
11814
11815   /* Use a control ping for synchronization */
11816   MPING (CONTROL_PING, mp_ping);
11817   S (mp_ping);
11818
11819   W (ret);
11820   return ret;
11821 }
11822
11823 static int
11824 api_policer_add_del (vat_main_t * vam)
11825 {
11826   unformat_input_t *i = vam->input;
11827   vl_api_policer_add_del_t *mp;
11828   u8 is_add = 1;
11829   u8 *name = 0;
11830   u32 cir = 0;
11831   u32 eir = 0;
11832   u64 cb = 0;
11833   u64 eb = 0;
11834   u8 rate_type = 0;
11835   u8 round_type = 0;
11836   u8 type = 0;
11837   u8 color_aware = 0;
11838   sse2_qos_pol_action_params_st conform_action, exceed_action, violate_action;
11839   int ret;
11840
11841   conform_action.action_type = SSE2_QOS_ACTION_TRANSMIT;
11842   conform_action.dscp = 0;
11843   exceed_action.action_type = SSE2_QOS_ACTION_MARK_AND_TRANSMIT;
11844   exceed_action.dscp = 0;
11845   violate_action.action_type = SSE2_QOS_ACTION_DROP;
11846   violate_action.dscp = 0;
11847
11848   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11849     {
11850       if (unformat (i, "del"))
11851         is_add = 0;
11852       else if (unformat (i, "name %s", &name))
11853         vec_add1 (name, 0);
11854       else if (unformat (i, "cir %u", &cir))
11855         ;
11856       else if (unformat (i, "eir %u", &eir))
11857         ;
11858       else if (unformat (i, "cb %u", &cb))
11859         ;
11860       else if (unformat (i, "eb %u", &eb))
11861         ;
11862       else if (unformat (i, "rate_type %U", unformat_policer_rate_type,
11863                          &rate_type))
11864         ;
11865       else if (unformat (i, "round_type %U", unformat_policer_round_type,
11866                          &round_type))
11867         ;
11868       else if (unformat (i, "type %U", unformat_policer_type, &type))
11869         ;
11870       else if (unformat (i, "conform_action %U", unformat_policer_action_type,
11871                          &conform_action))
11872         ;
11873       else if (unformat (i, "exceed_action %U", unformat_policer_action_type,
11874                          &exceed_action))
11875         ;
11876       else if (unformat (i, "violate_action %U", unformat_policer_action_type,
11877                          &violate_action))
11878         ;
11879       else if (unformat (i, "color-aware"))
11880         color_aware = 1;
11881       else
11882         break;
11883     }
11884
11885   if (!vec_len (name))
11886     {
11887       errmsg ("policer name must be specified");
11888       return -99;
11889     }
11890
11891   if (vec_len (name) > 64)
11892     {
11893       errmsg ("policer name too long");
11894       return -99;
11895     }
11896
11897   M (POLICER_ADD_DEL, mp);
11898
11899   clib_memcpy (mp->name, name, vec_len (name));
11900   vec_free (name);
11901   mp->is_add = is_add;
11902   mp->cir = ntohl (cir);
11903   mp->eir = ntohl (eir);
11904   mp->cb = clib_net_to_host_u64 (cb);
11905   mp->eb = clib_net_to_host_u64 (eb);
11906   mp->rate_type = rate_type;
11907   mp->round_type = round_type;
11908   mp->type = type;
11909   mp->conform_action.type = conform_action.action_type;
11910   mp->conform_action.dscp = conform_action.dscp;
11911   mp->exceed_action.type = exceed_action.action_type;
11912   mp->exceed_action.dscp = exceed_action.dscp;
11913   mp->violate_action.type = violate_action.action_type;
11914   mp->violate_action.dscp = violate_action.dscp;
11915   mp->color_aware = color_aware;
11916
11917   S (mp);
11918   W (ret);
11919   return ret;
11920 }
11921
11922 static int
11923 api_policer_dump (vat_main_t * vam)
11924 {
11925   unformat_input_t *i = vam->input;
11926   vl_api_policer_dump_t *mp;
11927   vl_api_control_ping_t *mp_ping;
11928   u8 *match_name = 0;
11929   u8 match_name_valid = 0;
11930   int ret;
11931
11932   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11933     {
11934       if (unformat (i, "name %s", &match_name))
11935         {
11936           vec_add1 (match_name, 0);
11937           match_name_valid = 1;
11938         }
11939       else
11940         break;
11941     }
11942
11943   M (POLICER_DUMP, mp);
11944   mp->match_name_valid = match_name_valid;
11945   clib_memcpy (mp->match_name, match_name, vec_len (match_name));
11946   vec_free (match_name);
11947   /* send it... */
11948   S (mp);
11949
11950   /* Use a control ping for synchronization */
11951   MPING (CONTROL_PING, mp_ping);
11952   S (mp_ping);
11953
11954   /* Wait for a reply... */
11955   W (ret);
11956   return ret;
11957 }
11958
11959 static int
11960 api_policer_classify_set_interface (vat_main_t * vam)
11961 {
11962   unformat_input_t *i = vam->input;
11963   vl_api_policer_classify_set_interface_t *mp;
11964   u32 sw_if_index;
11965   int sw_if_index_set;
11966   u32 ip4_table_index = ~0;
11967   u32 ip6_table_index = ~0;
11968   u32 l2_table_index = ~0;
11969   u8 is_add = 1;
11970   int ret;
11971
11972   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11973     {
11974       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
11975         sw_if_index_set = 1;
11976       else if (unformat (i, "sw_if_index %d", &sw_if_index))
11977         sw_if_index_set = 1;
11978       else if (unformat (i, "del"))
11979         is_add = 0;
11980       else if (unformat (i, "ip4-table %d", &ip4_table_index))
11981         ;
11982       else if (unformat (i, "ip6-table %d", &ip6_table_index))
11983         ;
11984       else if (unformat (i, "l2-table %d", &l2_table_index))
11985         ;
11986       else
11987         {
11988           clib_warning ("parse error '%U'", format_unformat_error, i);
11989           return -99;
11990         }
11991     }
11992
11993   if (sw_if_index_set == 0)
11994     {
11995       errmsg ("missing interface name or sw_if_index");
11996       return -99;
11997     }
11998
11999   M (POLICER_CLASSIFY_SET_INTERFACE, mp);
12000
12001   mp->sw_if_index = ntohl (sw_if_index);
12002   mp->ip4_table_index = ntohl (ip4_table_index);
12003   mp->ip6_table_index = ntohl (ip6_table_index);
12004   mp->l2_table_index = ntohl (l2_table_index);
12005   mp->is_add = is_add;
12006
12007   S (mp);
12008   W (ret);
12009   return ret;
12010 }
12011
12012 static int
12013 api_policer_classify_dump (vat_main_t * vam)
12014 {
12015   unformat_input_t *i = vam->input;
12016   vl_api_policer_classify_dump_t *mp;
12017   vl_api_control_ping_t *mp_ping;
12018   u8 type = POLICER_CLASSIFY_N_TABLES;
12019   int ret;
12020
12021   if (unformat (i, "type %U", unformat_policer_classify_table_type, &type))
12022     ;
12023   else
12024     {
12025       errmsg ("classify table type must be specified");
12026       return -99;
12027     }
12028
12029   if (!vam->json_output)
12030     {
12031       print (vam->ofp, "%10s%20s", "Intfc idx", "Classify table");
12032     }
12033
12034   M (POLICER_CLASSIFY_DUMP, mp);
12035   mp->type = type;
12036   /* send it... */
12037   S (mp);
12038
12039   /* Use a control ping for synchronization */
12040   MPING (CONTROL_PING, mp_ping);
12041   S (mp_ping);
12042
12043   /* Wait for a reply... */
12044   W (ret);
12045   return ret;
12046 }
12047
12048 static u8 *
12049 format_fib_api_path_nh_proto (u8 * s, va_list * args)
12050 {
12051   vl_api_fib_path_nh_proto_t proto =
12052     va_arg (*args, vl_api_fib_path_nh_proto_t);
12053
12054   switch (proto)
12055     {
12056     case FIB_API_PATH_NH_PROTO_IP4:
12057       s = format (s, "ip4");
12058       break;
12059     case FIB_API_PATH_NH_PROTO_IP6:
12060       s = format (s, "ip6");
12061       break;
12062     case FIB_API_PATH_NH_PROTO_MPLS:
12063       s = format (s, "mpls");
12064       break;
12065     case FIB_API_PATH_NH_PROTO_BIER:
12066       s = format (s, "bier");
12067       break;
12068     case FIB_API_PATH_NH_PROTO_ETHERNET:
12069       s = format (s, "ethernet");
12070       break;
12071     }
12072
12073   return (s);
12074 }
12075
12076 static u8 *
12077 format_vl_api_ip_address_union (u8 * s, va_list * args)
12078 {
12079   vl_api_address_family_t af = va_arg (*args, int);
12080   const vl_api_address_union_t *u = va_arg (*args, vl_api_address_union_t *);
12081
12082   switch (af)
12083     {
12084     case ADDRESS_IP4:
12085       s = format (s, "%U", format_ip4_address, u->ip4);
12086       break;
12087     case ADDRESS_IP6:
12088       s = format (s, "%U", format_ip6_address, u->ip6);
12089       break;
12090     }
12091   return (s);
12092 }
12093
12094 static u8 *
12095 format_vl_api_fib_path_type (u8 * s, va_list * args)
12096 {
12097   vl_api_fib_path_type_t t = va_arg (*args, vl_api_fib_path_type_t);
12098
12099   switch (t)
12100     {
12101     case FIB_API_PATH_TYPE_NORMAL:
12102       s = format (s, "normal");
12103       break;
12104     case FIB_API_PATH_TYPE_LOCAL:
12105       s = format (s, "local");
12106       break;
12107     case FIB_API_PATH_TYPE_DROP:
12108       s = format (s, "drop");
12109       break;
12110     case FIB_API_PATH_TYPE_UDP_ENCAP:
12111       s = format (s, "udp-encap");
12112       break;
12113     case FIB_API_PATH_TYPE_BIER_IMP:
12114       s = format (s, "bier-imp");
12115       break;
12116     case FIB_API_PATH_TYPE_ICMP_UNREACH:
12117       s = format (s, "unreach");
12118       break;
12119     case FIB_API_PATH_TYPE_ICMP_PROHIBIT:
12120       s = format (s, "prohibit");
12121       break;
12122     case FIB_API_PATH_TYPE_SOURCE_LOOKUP:
12123       s = format (s, "src-lookup");
12124       break;
12125     case FIB_API_PATH_TYPE_DVR:
12126       s = format (s, "dvr");
12127       break;
12128     case FIB_API_PATH_TYPE_INTERFACE_RX:
12129       s = format (s, "interface-rx");
12130       break;
12131     case FIB_API_PATH_TYPE_CLASSIFY:
12132       s = format (s, "classify");
12133       break;
12134     }
12135
12136   return (s);
12137 }
12138
12139 static void
12140 vl_api_fib_path_print (vat_main_t * vam, vl_api_fib_path_t * fp)
12141 {
12142   print (vam->ofp,
12143          "  weight %d, sw_if_index %d, type %U, afi %U, next_hop %U",
12144          ntohl (fp->weight), ntohl (fp->sw_if_index),
12145          format_vl_api_fib_path_type, fp->type,
12146          format_fib_api_path_nh_proto, fp->proto,
12147          format_vl_api_ip_address_union, &fp->nh.address);
12148 }
12149
12150 static void
12151 vl_api_mpls_fib_path_json_print (vat_json_node_t * node,
12152                                  vl_api_fib_path_t * fp)
12153 {
12154   struct in_addr ip4;
12155   struct in6_addr ip6;
12156
12157   vat_json_object_add_uint (node, "weight", ntohl (fp->weight));
12158   vat_json_object_add_uint (node, "sw_if_index", ntohl (fp->sw_if_index));
12159   vat_json_object_add_uint (node, "type", fp->type);
12160   vat_json_object_add_uint (node, "next_hop_proto", fp->proto);
12161   if (fp->proto == FIB_API_PATH_NH_PROTO_IP4)
12162     {
12163       clib_memcpy (&ip4, &fp->nh.address.ip4, sizeof (ip4));
12164       vat_json_object_add_ip4 (node, "next_hop", ip4);
12165     }
12166   else if (fp->proto == FIB_API_PATH_NH_PROTO_IP6)
12167     {
12168       clib_memcpy (&ip6, &fp->nh.address.ip6, sizeof (ip6));
12169       vat_json_object_add_ip6 (node, "next_hop", ip6);
12170     }
12171 }
12172
12173 static void
12174 vl_api_mpls_tunnel_details_t_handler (vl_api_mpls_tunnel_details_t * mp)
12175 {
12176   vat_main_t *vam = &vat_main;
12177   int count = ntohl (mp->mt_tunnel.mt_n_paths);
12178   vl_api_fib_path_t *fp;
12179   i32 i;
12180
12181   print (vam->ofp, "sw_if_index %d via:",
12182          ntohl (mp->mt_tunnel.mt_sw_if_index));
12183   fp = mp->mt_tunnel.mt_paths;
12184   for (i = 0; i < count; i++)
12185     {
12186       vl_api_fib_path_print (vam, fp);
12187       fp++;
12188     }
12189
12190   print (vam->ofp, "");
12191 }
12192
12193 #define vl_api_mpls_tunnel_details_t_endian vl_noop_handler
12194 #define vl_api_mpls_tunnel_details_t_print vl_noop_handler
12195
12196 static void
12197 vl_api_mpls_tunnel_details_t_handler_json (vl_api_mpls_tunnel_details_t * mp)
12198 {
12199   vat_main_t *vam = &vat_main;
12200   vat_json_node_t *node = NULL;
12201   int count = ntohl (mp->mt_tunnel.mt_n_paths);
12202   vl_api_fib_path_t *fp;
12203   i32 i;
12204
12205   if (VAT_JSON_ARRAY != vam->json_tree.type)
12206     {
12207       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
12208       vat_json_init_array (&vam->json_tree);
12209     }
12210   node = vat_json_array_add (&vam->json_tree);
12211
12212   vat_json_init_object (node);
12213   vat_json_object_add_uint (node, "sw_if_index",
12214                             ntohl (mp->mt_tunnel.mt_sw_if_index));
12215
12216   vat_json_object_add_uint (node, "l2_only", mp->mt_tunnel.mt_l2_only);
12217
12218   fp = mp->mt_tunnel.mt_paths;
12219   for (i = 0; i < count; i++)
12220     {
12221       vl_api_mpls_fib_path_json_print (node, fp);
12222       fp++;
12223     }
12224 }
12225
12226 static int
12227 api_mpls_tunnel_dump (vat_main_t * vam)
12228 {
12229   vl_api_mpls_tunnel_dump_t *mp;
12230   vl_api_control_ping_t *mp_ping;
12231   int ret;
12232
12233   M (MPLS_TUNNEL_DUMP, mp);
12234
12235   S (mp);
12236
12237   /* Use a control ping for synchronization */
12238   MPING (CONTROL_PING, mp_ping);
12239   S (mp_ping);
12240
12241   W (ret);
12242   return ret;
12243 }
12244
12245 #define vl_api_mpls_table_details_t_endian vl_noop_handler
12246 #define vl_api_mpls_table_details_t_print vl_noop_handler
12247
12248
12249 static void
12250 vl_api_mpls_table_details_t_handler (vl_api_mpls_table_details_t * mp)
12251 {
12252   vat_main_t *vam = &vat_main;
12253
12254   print (vam->ofp, "table-id %d,", ntohl (mp->mt_table.mt_table_id));
12255 }
12256
12257 static void vl_api_mpls_table_details_t_handler_json
12258   (vl_api_mpls_table_details_t * mp)
12259 {
12260   vat_main_t *vam = &vat_main;
12261   vat_json_node_t *node = NULL;
12262
12263   if (VAT_JSON_ARRAY != vam->json_tree.type)
12264     {
12265       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
12266       vat_json_init_array (&vam->json_tree);
12267     }
12268   node = vat_json_array_add (&vam->json_tree);
12269
12270   vat_json_init_object (node);
12271   vat_json_object_add_uint (node, "table", ntohl (mp->mt_table.mt_table_id));
12272 }
12273
12274 static int
12275 api_mpls_table_dump (vat_main_t * vam)
12276 {
12277   vl_api_mpls_table_dump_t *mp;
12278   vl_api_control_ping_t *mp_ping;
12279   int ret;
12280
12281   M (MPLS_TABLE_DUMP, mp);
12282   S (mp);
12283
12284   /* Use a control ping for synchronization */
12285   MPING (CONTROL_PING, mp_ping);
12286   S (mp_ping);
12287
12288   W (ret);
12289   return ret;
12290 }
12291
12292 #define vl_api_mpls_route_details_t_endian vl_noop_handler
12293 #define vl_api_mpls_route_details_t_print vl_noop_handler
12294
12295 static void
12296 vl_api_mpls_route_details_t_handler (vl_api_mpls_route_details_t * mp)
12297 {
12298   vat_main_t *vam = &vat_main;
12299   int count = (int) clib_net_to_host_u32 (mp->mr_route.mr_n_paths);
12300   vl_api_fib_path_t *fp;
12301   int i;
12302
12303   print (vam->ofp,
12304          "table-id %d, label %u, ess_bit %u",
12305          ntohl (mp->mr_route.mr_table_id),
12306          ntohl (mp->mr_route.mr_label), mp->mr_route.mr_eos);
12307   fp = mp->mr_route.mr_paths;
12308   for (i = 0; i < count; i++)
12309     {
12310       vl_api_fib_path_print (vam, fp);
12311       fp++;
12312     }
12313 }
12314
12315 static void vl_api_mpls_route_details_t_handler_json
12316   (vl_api_mpls_route_details_t * mp)
12317 {
12318   vat_main_t *vam = &vat_main;
12319   int count = (int) clib_host_to_net_u32 (mp->mr_route.mr_n_paths);
12320   vat_json_node_t *node = NULL;
12321   vl_api_fib_path_t *fp;
12322   int i;
12323
12324   if (VAT_JSON_ARRAY != vam->json_tree.type)
12325     {
12326       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
12327       vat_json_init_array (&vam->json_tree);
12328     }
12329   node = vat_json_array_add (&vam->json_tree);
12330
12331   vat_json_init_object (node);
12332   vat_json_object_add_uint (node, "table", ntohl (mp->mr_route.mr_table_id));
12333   vat_json_object_add_uint (node, "s_bit", mp->mr_route.mr_eos);
12334   vat_json_object_add_uint (node, "label", ntohl (mp->mr_route.mr_label));
12335   vat_json_object_add_uint (node, "path_count", count);
12336   fp = mp->mr_route.mr_paths;
12337   for (i = 0; i < count; i++)
12338     {
12339       vl_api_mpls_fib_path_json_print (node, fp);
12340       fp++;
12341     }
12342 }
12343
12344 static int
12345 api_mpls_route_dump (vat_main_t * vam)
12346 {
12347   unformat_input_t *input = vam->input;
12348   vl_api_mpls_route_dump_t *mp;
12349   vl_api_control_ping_t *mp_ping;
12350   u32 table_id;
12351   int ret;
12352
12353   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
12354     {
12355       if (unformat (input, "table_id %d", &table_id))
12356         ;
12357       else
12358         break;
12359     }
12360   if (table_id == ~0)
12361     {
12362       errmsg ("missing table id");
12363       return -99;
12364     }
12365
12366   M (MPLS_ROUTE_DUMP, mp);
12367
12368   mp->table.mt_table_id = ntohl (table_id);
12369   S (mp);
12370
12371   /* Use a control ping for synchronization */
12372   MPING (CONTROL_PING, mp_ping);
12373   S (mp_ping);
12374
12375   W (ret);
12376   return ret;
12377 }
12378
12379 #define vl_api_ip_table_details_t_endian vl_noop_handler
12380 #define vl_api_ip_table_details_t_print vl_noop_handler
12381
12382 static void
12383 vl_api_ip_table_details_t_handler (vl_api_ip_table_details_t * mp)
12384 {
12385   vat_main_t *vam = &vat_main;
12386
12387   print (vam->ofp,
12388          "%s; table-id %d, prefix %U/%d",
12389          mp->table.name, ntohl (mp->table.table_id));
12390 }
12391
12392
12393 static void vl_api_ip_table_details_t_handler_json
12394   (vl_api_ip_table_details_t * mp)
12395 {
12396   vat_main_t *vam = &vat_main;
12397   vat_json_node_t *node = NULL;
12398
12399   if (VAT_JSON_ARRAY != vam->json_tree.type)
12400     {
12401       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
12402       vat_json_init_array (&vam->json_tree);
12403     }
12404   node = vat_json_array_add (&vam->json_tree);
12405
12406   vat_json_init_object (node);
12407   vat_json_object_add_uint (node, "table", ntohl (mp->table.table_id));
12408 }
12409
12410 static int
12411 api_ip_table_dump (vat_main_t * vam)
12412 {
12413   vl_api_ip_table_dump_t *mp;
12414   vl_api_control_ping_t *mp_ping;
12415   int ret;
12416
12417   M (IP_TABLE_DUMP, mp);
12418   S (mp);
12419
12420   /* Use a control ping for synchronization */
12421   MPING (CONTROL_PING, mp_ping);
12422   S (mp_ping);
12423
12424   W (ret);
12425   return ret;
12426 }
12427
12428 static int
12429 api_ip_mtable_dump (vat_main_t * vam)
12430 {
12431   vl_api_ip_mtable_dump_t *mp;
12432   vl_api_control_ping_t *mp_ping;
12433   int ret;
12434
12435   M (IP_MTABLE_DUMP, mp);
12436   S (mp);
12437
12438   /* Use a control ping for synchronization */
12439   MPING (CONTROL_PING, mp_ping);
12440   S (mp_ping);
12441
12442   W (ret);
12443   return ret;
12444 }
12445
12446 static int
12447 api_ip_mroute_dump (vat_main_t * vam)
12448 {
12449   unformat_input_t *input = vam->input;
12450   vl_api_control_ping_t *mp_ping;
12451   vl_api_ip_mroute_dump_t *mp;
12452   int ret, is_ip6;
12453   u32 table_id;
12454
12455   is_ip6 = 0;
12456   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
12457     {
12458       if (unformat (input, "table_id %d", &table_id))
12459         ;
12460       else if (unformat (input, "ip6"))
12461         is_ip6 = 1;
12462       else if (unformat (input, "ip4"))
12463         is_ip6 = 0;
12464       else
12465         break;
12466     }
12467   if (table_id == ~0)
12468     {
12469       errmsg ("missing table id");
12470       return -99;
12471     }
12472
12473   M (IP_MROUTE_DUMP, mp);
12474   mp->table.table_id = table_id;
12475   mp->table.is_ip6 = is_ip6;
12476   S (mp);
12477
12478   /* Use a control ping for synchronization */
12479   MPING (CONTROL_PING, mp_ping);
12480   S (mp_ping);
12481
12482   W (ret);
12483   return ret;
12484 }
12485
12486 #define vl_api_ip_route_details_t_endian vl_noop_handler
12487 #define vl_api_ip_route_details_t_print vl_noop_handler
12488
12489 static void
12490 vl_api_ip_route_details_t_handler (vl_api_ip_route_details_t * mp)
12491 {
12492   vat_main_t *vam = &vat_main;
12493   u8 count = mp->route.n_paths;
12494   vl_api_fib_path_t *fp;
12495   int i;
12496
12497   print (vam->ofp,
12498          "table-id %d, prefix %U/%d",
12499          ntohl (mp->route.table_id),
12500          format_ip46_address, mp->route.prefix.address, mp->route.prefix.len);
12501   for (i = 0; i < count; i++)
12502     {
12503       fp = &mp->route.paths[i];
12504
12505       vl_api_fib_path_print (vam, fp);
12506       fp++;
12507     }
12508 }
12509
12510 static void vl_api_ip_route_details_t_handler_json
12511   (vl_api_ip_route_details_t * mp)
12512 {
12513   vat_main_t *vam = &vat_main;
12514   u8 count = mp->route.n_paths;
12515   vat_json_node_t *node = NULL;
12516   struct in_addr ip4;
12517   struct in6_addr ip6;
12518   vl_api_fib_path_t *fp;
12519   int i;
12520
12521   if (VAT_JSON_ARRAY != vam->json_tree.type)
12522     {
12523       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
12524       vat_json_init_array (&vam->json_tree);
12525     }
12526   node = vat_json_array_add (&vam->json_tree);
12527
12528   vat_json_init_object (node);
12529   vat_json_object_add_uint (node, "table", ntohl (mp->route.table_id));
12530   if (ADDRESS_IP6 == mp->route.prefix.address.af)
12531     {
12532       clib_memcpy (&ip6, &mp->route.prefix.address.un.ip6, sizeof (ip6));
12533       vat_json_object_add_ip6 (node, "prefix", ip6);
12534     }
12535   else
12536     {
12537       clib_memcpy (&ip4, &mp->route.prefix.address.un.ip4, sizeof (ip4));
12538       vat_json_object_add_ip4 (node, "prefix", ip4);
12539     }
12540   vat_json_object_add_uint (node, "mask_length", mp->route.prefix.len);
12541   vat_json_object_add_uint (node, "path_count", count);
12542   for (i = 0; i < count; i++)
12543     {
12544       fp = &mp->route.paths[i];
12545       vl_api_mpls_fib_path_json_print (node, fp);
12546     }
12547 }
12548
12549 static int
12550 api_ip_route_dump (vat_main_t * vam)
12551 {
12552   unformat_input_t *input = vam->input;
12553   vl_api_ip_route_dump_t *mp;
12554   vl_api_control_ping_t *mp_ping;
12555   u32 table_id;
12556   u8 is_ip6;
12557   int ret;
12558
12559   is_ip6 = 0;
12560   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
12561     {
12562       if (unformat (input, "table_id %d", &table_id))
12563         ;
12564       else if (unformat (input, "ip6"))
12565         is_ip6 = 1;
12566       else if (unformat (input, "ip4"))
12567         is_ip6 = 0;
12568       else
12569         break;
12570     }
12571   if (table_id == ~0)
12572     {
12573       errmsg ("missing table id");
12574       return -99;
12575     }
12576
12577   M (IP_ROUTE_DUMP, mp);
12578
12579   mp->table.table_id = table_id;
12580   mp->table.is_ip6 = is_ip6;
12581
12582   S (mp);
12583
12584   /* Use a control ping for synchronization */
12585   MPING (CONTROL_PING, mp_ping);
12586   S (mp_ping);
12587
12588   W (ret);
12589   return ret;
12590 }
12591
12592 int
12593 api_classify_table_ids (vat_main_t * vam)
12594 {
12595   vl_api_classify_table_ids_t *mp;
12596   int ret;
12597
12598   /* Construct the API message */
12599   M (CLASSIFY_TABLE_IDS, mp);
12600   mp->context = 0;
12601
12602   S (mp);
12603   W (ret);
12604   return ret;
12605 }
12606
12607 int
12608 api_classify_table_by_interface (vat_main_t * vam)
12609 {
12610   unformat_input_t *input = vam->input;
12611   vl_api_classify_table_by_interface_t *mp;
12612
12613   u32 sw_if_index = ~0;
12614   int ret;
12615   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
12616     {
12617       if (unformat (input, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
12618         ;
12619       else if (unformat (input, "sw_if_index %d", &sw_if_index))
12620         ;
12621       else
12622         break;
12623     }
12624   if (sw_if_index == ~0)
12625     {
12626       errmsg ("missing interface name or sw_if_index");
12627       return -99;
12628     }
12629
12630   /* Construct the API message */
12631   M (CLASSIFY_TABLE_BY_INTERFACE, mp);
12632   mp->context = 0;
12633   mp->sw_if_index = ntohl (sw_if_index);
12634
12635   S (mp);
12636   W (ret);
12637   return ret;
12638 }
12639
12640 int
12641 api_classify_table_info (vat_main_t * vam)
12642 {
12643   unformat_input_t *input = vam->input;
12644   vl_api_classify_table_info_t *mp;
12645
12646   u32 table_id = ~0;
12647   int ret;
12648   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
12649     {
12650       if (unformat (input, "table_id %d", &table_id))
12651         ;
12652       else
12653         break;
12654     }
12655   if (table_id == ~0)
12656     {
12657       errmsg ("missing table id");
12658       return -99;
12659     }
12660
12661   /* Construct the API message */
12662   M (CLASSIFY_TABLE_INFO, mp);
12663   mp->context = 0;
12664   mp->table_id = ntohl (table_id);
12665
12666   S (mp);
12667   W (ret);
12668   return ret;
12669 }
12670
12671 int
12672 api_classify_session_dump (vat_main_t * vam)
12673 {
12674   unformat_input_t *input = vam->input;
12675   vl_api_classify_session_dump_t *mp;
12676   vl_api_control_ping_t *mp_ping;
12677
12678   u32 table_id = ~0;
12679   int ret;
12680   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
12681     {
12682       if (unformat (input, "table_id %d", &table_id))
12683         ;
12684       else
12685         break;
12686     }
12687   if (table_id == ~0)
12688     {
12689       errmsg ("missing table id");
12690       return -99;
12691     }
12692
12693   /* Construct the API message */
12694   M (CLASSIFY_SESSION_DUMP, mp);
12695   mp->context = 0;
12696   mp->table_id = ntohl (table_id);
12697   S (mp);
12698
12699   /* Use a control ping for synchronization */
12700   MPING (CONTROL_PING, mp_ping);
12701   S (mp_ping);
12702
12703   W (ret);
12704   return ret;
12705 }
12706
12707 static void
12708 vl_api_ipfix_exporter_details_t_handler (vl_api_ipfix_exporter_details_t * mp)
12709 {
12710   vat_main_t *vam = &vat_main;
12711
12712   print (vam->ofp, "collector_address %U, collector_port %d, "
12713          "src_address %U, vrf_id %d, path_mtu %u, "
12714          "template_interval %u, udp_checksum %d",
12715          format_ip4_address, mp->collector_address,
12716          ntohs (mp->collector_port),
12717          format_ip4_address, mp->src_address,
12718          ntohl (mp->vrf_id), ntohl (mp->path_mtu),
12719          ntohl (mp->template_interval), mp->udp_checksum);
12720
12721   vam->retval = 0;
12722   vam->result_ready = 1;
12723 }
12724
12725 static void
12726   vl_api_ipfix_exporter_details_t_handler_json
12727   (vl_api_ipfix_exporter_details_t * mp)
12728 {
12729   vat_main_t *vam = &vat_main;
12730   vat_json_node_t node;
12731   struct in_addr collector_address;
12732   struct in_addr src_address;
12733
12734   vat_json_init_object (&node);
12735   clib_memcpy (&collector_address, &mp->collector_address,
12736                sizeof (collector_address));
12737   vat_json_object_add_ip4 (&node, "collector_address", collector_address);
12738   vat_json_object_add_uint (&node, "collector_port",
12739                             ntohs (mp->collector_port));
12740   clib_memcpy (&src_address, &mp->src_address, sizeof (src_address));
12741   vat_json_object_add_ip4 (&node, "src_address", src_address);
12742   vat_json_object_add_int (&node, "vrf_id", ntohl (mp->vrf_id));
12743   vat_json_object_add_uint (&node, "path_mtu", ntohl (mp->path_mtu));
12744   vat_json_object_add_uint (&node, "template_interval",
12745                             ntohl (mp->template_interval));
12746   vat_json_object_add_int (&node, "udp_checksum", mp->udp_checksum);
12747
12748   vat_json_print (vam->ofp, &node);
12749   vat_json_free (&node);
12750   vam->retval = 0;
12751   vam->result_ready = 1;
12752 }
12753
12754 int
12755 api_ipfix_exporter_dump (vat_main_t * vam)
12756 {
12757   vl_api_ipfix_exporter_dump_t *mp;
12758   int ret;
12759
12760   /* Construct the API message */
12761   M (IPFIX_EXPORTER_DUMP, mp);
12762   mp->context = 0;
12763
12764   S (mp);
12765   W (ret);
12766   return ret;
12767 }
12768
12769 static int
12770 api_ipfix_classify_stream_dump (vat_main_t * vam)
12771 {
12772   vl_api_ipfix_classify_stream_dump_t *mp;
12773   int ret;
12774
12775   /* Construct the API message */
12776   M (IPFIX_CLASSIFY_STREAM_DUMP, mp);
12777   mp->context = 0;
12778
12779   S (mp);
12780   W (ret);
12781   return ret;
12782   /* NOTREACHED */
12783   return 0;
12784 }
12785
12786 static void
12787   vl_api_ipfix_classify_stream_details_t_handler
12788   (vl_api_ipfix_classify_stream_details_t * mp)
12789 {
12790   vat_main_t *vam = &vat_main;
12791   print (vam->ofp, "domain_id %d, src_port %d",
12792          ntohl (mp->domain_id), ntohs (mp->src_port));
12793   vam->retval = 0;
12794   vam->result_ready = 1;
12795 }
12796
12797 static void
12798   vl_api_ipfix_classify_stream_details_t_handler_json
12799   (vl_api_ipfix_classify_stream_details_t * mp)
12800 {
12801   vat_main_t *vam = &vat_main;
12802   vat_json_node_t node;
12803
12804   vat_json_init_object (&node);
12805   vat_json_object_add_uint (&node, "domain_id", ntohl (mp->domain_id));
12806   vat_json_object_add_uint (&node, "src_port", ntohs (mp->src_port));
12807
12808   vat_json_print (vam->ofp, &node);
12809   vat_json_free (&node);
12810   vam->retval = 0;
12811   vam->result_ready = 1;
12812 }
12813
12814 static int
12815 api_ipfix_classify_table_dump (vat_main_t * vam)
12816 {
12817   vl_api_ipfix_classify_table_dump_t *mp;
12818   vl_api_control_ping_t *mp_ping;
12819   int ret;
12820
12821   if (!vam->json_output)
12822     {
12823       print (vam->ofp, "%15s%15s%20s", "table_id", "ip_version",
12824              "transport_protocol");
12825     }
12826
12827   /* Construct the API message */
12828   M (IPFIX_CLASSIFY_TABLE_DUMP, mp);
12829
12830   /* send it... */
12831   S (mp);
12832
12833   /* Use a control ping for synchronization */
12834   MPING (CONTROL_PING, mp_ping);
12835   S (mp_ping);
12836
12837   W (ret);
12838   return ret;
12839 }
12840
12841 static void
12842   vl_api_ipfix_classify_table_details_t_handler
12843   (vl_api_ipfix_classify_table_details_t * mp)
12844 {
12845   vat_main_t *vam = &vat_main;
12846   print (vam->ofp, "%15d%15d%20d", ntohl (mp->table_id), mp->ip_version,
12847          mp->transport_protocol);
12848 }
12849
12850 static void
12851   vl_api_ipfix_classify_table_details_t_handler_json
12852   (vl_api_ipfix_classify_table_details_t * mp)
12853 {
12854   vat_json_node_t *node = NULL;
12855   vat_main_t *vam = &vat_main;
12856
12857   if (VAT_JSON_ARRAY != vam->json_tree.type)
12858     {
12859       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
12860       vat_json_init_array (&vam->json_tree);
12861     }
12862
12863   node = vat_json_array_add (&vam->json_tree);
12864   vat_json_init_object (node);
12865
12866   vat_json_object_add_uint (node, "table_id", ntohl (mp->table_id));
12867   vat_json_object_add_uint (node, "ip_version", mp->ip_version);
12868   vat_json_object_add_uint (node, "transport_protocol",
12869                             mp->transport_protocol);
12870 }
12871
12872 static int
12873 api_sw_interface_span_enable_disable (vat_main_t * vam)
12874 {
12875   unformat_input_t *i = vam->input;
12876   vl_api_sw_interface_span_enable_disable_t *mp;
12877   u32 src_sw_if_index = ~0;
12878   u32 dst_sw_if_index = ~0;
12879   u8 state = 3;
12880   int ret;
12881   u8 is_l2 = 0;
12882
12883   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
12884     {
12885       if (unformat
12886           (i, "src %U", api_unformat_sw_if_index, vam, &src_sw_if_index))
12887         ;
12888       else if (unformat (i, "src_sw_if_index %d", &src_sw_if_index))
12889         ;
12890       else
12891         if (unformat
12892             (i, "dst %U", api_unformat_sw_if_index, vam, &dst_sw_if_index))
12893         ;
12894       else if (unformat (i, "dst_sw_if_index %d", &dst_sw_if_index))
12895         ;
12896       else if (unformat (i, "disable"))
12897         state = 0;
12898       else if (unformat (i, "rx"))
12899         state = 1;
12900       else if (unformat (i, "tx"))
12901         state = 2;
12902       else if (unformat (i, "both"))
12903         state = 3;
12904       else if (unformat (i, "l2"))
12905         is_l2 = 1;
12906       else
12907         break;
12908     }
12909
12910   M (SW_INTERFACE_SPAN_ENABLE_DISABLE, mp);
12911
12912   mp->sw_if_index_from = htonl (src_sw_if_index);
12913   mp->sw_if_index_to = htonl (dst_sw_if_index);
12914   mp->state = state;
12915   mp->is_l2 = is_l2;
12916
12917   S (mp);
12918   W (ret);
12919   return ret;
12920 }
12921
12922 static void
12923 vl_api_sw_interface_span_details_t_handler (vl_api_sw_interface_span_details_t
12924                                             * mp)
12925 {
12926   vat_main_t *vam = &vat_main;
12927   u8 *sw_if_from_name = 0;
12928   u8 *sw_if_to_name = 0;
12929   u32 sw_if_index_from = ntohl (mp->sw_if_index_from);
12930   u32 sw_if_index_to = ntohl (mp->sw_if_index_to);
12931   char *states[] = { "none", "rx", "tx", "both" };
12932   hash_pair_t *p;
12933
12934   /* *INDENT-OFF* */
12935   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
12936   ({
12937     if ((u32) p->value[0] == sw_if_index_from)
12938       {
12939         sw_if_from_name = (u8 *)(p->key);
12940         if (sw_if_to_name)
12941           break;
12942       }
12943     if ((u32) p->value[0] == sw_if_index_to)
12944       {
12945         sw_if_to_name = (u8 *)(p->key);
12946         if (sw_if_from_name)
12947           break;
12948       }
12949   }));
12950   /* *INDENT-ON* */
12951   print (vam->ofp, "%20s => %20s (%s) %s",
12952          sw_if_from_name, sw_if_to_name, states[mp->state],
12953          mp->is_l2 ? "l2" : "device");
12954 }
12955
12956 static void
12957   vl_api_sw_interface_span_details_t_handler_json
12958   (vl_api_sw_interface_span_details_t * mp)
12959 {
12960   vat_main_t *vam = &vat_main;
12961   vat_json_node_t *node = NULL;
12962   u8 *sw_if_from_name = 0;
12963   u8 *sw_if_to_name = 0;
12964   u32 sw_if_index_from = ntohl (mp->sw_if_index_from);
12965   u32 sw_if_index_to = ntohl (mp->sw_if_index_to);
12966   hash_pair_t *p;
12967
12968   /* *INDENT-OFF* */
12969   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
12970   ({
12971     if ((u32) p->value[0] == sw_if_index_from)
12972       {
12973         sw_if_from_name = (u8 *)(p->key);
12974         if (sw_if_to_name)
12975           break;
12976       }
12977     if ((u32) p->value[0] == sw_if_index_to)
12978       {
12979         sw_if_to_name = (u8 *)(p->key);
12980         if (sw_if_from_name)
12981           break;
12982       }
12983   }));
12984   /* *INDENT-ON* */
12985
12986   if (VAT_JSON_ARRAY != vam->json_tree.type)
12987     {
12988       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
12989       vat_json_init_array (&vam->json_tree);
12990     }
12991   node = vat_json_array_add (&vam->json_tree);
12992
12993   vat_json_init_object (node);
12994   vat_json_object_add_uint (node, "src-if-index", sw_if_index_from);
12995   vat_json_object_add_string_copy (node, "src-if-name", sw_if_from_name);
12996   vat_json_object_add_uint (node, "dst-if-index", sw_if_index_to);
12997   if (0 != sw_if_to_name)
12998     {
12999       vat_json_object_add_string_copy (node, "dst-if-name", sw_if_to_name);
13000     }
13001   vat_json_object_add_uint (node, "state", mp->state);
13002   vat_json_object_add_uint (node, "is-l2", mp->is_l2);
13003 }
13004
13005 static int
13006 api_sw_interface_span_dump (vat_main_t * vam)
13007 {
13008   unformat_input_t *input = vam->input;
13009   vl_api_sw_interface_span_dump_t *mp;
13010   vl_api_control_ping_t *mp_ping;
13011   u8 is_l2 = 0;
13012   int ret;
13013
13014   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
13015     {
13016       if (unformat (input, "l2"))
13017         is_l2 = 1;
13018       else
13019         break;
13020     }
13021
13022   M (SW_INTERFACE_SPAN_DUMP, mp);
13023   mp->is_l2 = is_l2;
13024   S (mp);
13025
13026   /* Use a control ping for synchronization */
13027   MPING (CONTROL_PING, mp_ping);
13028   S (mp_ping);
13029
13030   W (ret);
13031   return ret;
13032 }
13033
13034 int
13035 api_pg_create_interface (vat_main_t * vam)
13036 {
13037   unformat_input_t *input = vam->input;
13038   vl_api_pg_create_interface_t *mp;
13039
13040   u32 if_id = ~0, gso_size = 0;
13041   u8 gso_enabled = 0;
13042   int ret;
13043   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
13044     {
13045       if (unformat (input, "if_id %d", &if_id))
13046         ;
13047       else if (unformat (input, "gso-enabled"))
13048         {
13049           gso_enabled = 1;
13050           if (unformat (input, "gso-size %u", &gso_size))
13051             ;
13052           else
13053             {
13054               errmsg ("missing gso-size");
13055               return -99;
13056             }
13057         }
13058       else
13059         break;
13060     }
13061   if (if_id == ~0)
13062     {
13063       errmsg ("missing pg interface index");
13064       return -99;
13065     }
13066
13067   /* Construct the API message */
13068   M (PG_CREATE_INTERFACE, mp);
13069   mp->context = 0;
13070   mp->interface_id = ntohl (if_id);
13071   mp->gso_enabled = gso_enabled;
13072
13073   S (mp);
13074   W (ret);
13075   return ret;
13076 }
13077
13078 int
13079 api_pg_capture (vat_main_t * vam)
13080 {
13081   unformat_input_t *input = vam->input;
13082   vl_api_pg_capture_t *mp;
13083
13084   u32 if_id = ~0;
13085   u8 enable = 1;
13086   u32 count = 1;
13087   u8 pcap_file_set = 0;
13088   u8 *pcap_file = 0;
13089   int ret;
13090   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
13091     {
13092       if (unformat (input, "if_id %d", &if_id))
13093         ;
13094       else if (unformat (input, "pcap %s", &pcap_file))
13095         pcap_file_set = 1;
13096       else if (unformat (input, "count %d", &count))
13097         ;
13098       else if (unformat (input, "disable"))
13099         enable = 0;
13100       else
13101         break;
13102     }
13103   if (if_id == ~0)
13104     {
13105       errmsg ("missing pg interface index");
13106       return -99;
13107     }
13108   if (pcap_file_set > 0)
13109     {
13110       if (vec_len (pcap_file) > 255)
13111         {
13112           errmsg ("pcap file name is too long");
13113           return -99;
13114         }
13115     }
13116
13117   /* Construct the API message */
13118   M (PG_CAPTURE, mp);
13119   mp->context = 0;
13120   mp->interface_id = ntohl (if_id);
13121   mp->is_enabled = enable;
13122   mp->count = ntohl (count);
13123   if (pcap_file_set != 0)
13124     {
13125       vl_api_vec_to_api_string (pcap_file, &mp->pcap_file_name);
13126     }
13127   vec_free (pcap_file);
13128
13129   S (mp);
13130   W (ret);
13131   return ret;
13132 }
13133
13134 int
13135 api_pg_enable_disable (vat_main_t * vam)
13136 {
13137   unformat_input_t *input = vam->input;
13138   vl_api_pg_enable_disable_t *mp;
13139
13140   u8 enable = 1;
13141   u8 stream_name_set = 0;
13142   u8 *stream_name = 0;
13143   int ret;
13144   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
13145     {
13146       if (unformat (input, "stream %s", &stream_name))
13147         stream_name_set = 1;
13148       else if (unformat (input, "disable"))
13149         enable = 0;
13150       else
13151         break;
13152     }
13153
13154   if (stream_name_set > 0)
13155     {
13156       if (vec_len (stream_name) > 255)
13157         {
13158           errmsg ("stream name too long");
13159           return -99;
13160         }
13161     }
13162
13163   /* Construct the API message */
13164   M (PG_ENABLE_DISABLE, mp);
13165   mp->context = 0;
13166   mp->is_enabled = enable;
13167   if (stream_name_set != 0)
13168     {
13169       vl_api_vec_to_api_string (stream_name, &mp->stream_name);
13170     }
13171   vec_free (stream_name);
13172
13173   S (mp);
13174   W (ret);
13175   return ret;
13176 }
13177
13178 int
13179 api_pg_interface_enable_disable_coalesce (vat_main_t * vam)
13180 {
13181   unformat_input_t *input = vam->input;
13182   vl_api_pg_interface_enable_disable_coalesce_t *mp;
13183
13184   u32 sw_if_index = ~0;
13185   u8 enable = 1;
13186   int ret;
13187   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
13188     {
13189       if (unformat (input, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13190         ;
13191       else if (unformat (input, "sw_if_index %d", &sw_if_index))
13192         ;
13193       else if (unformat (input, "disable"))
13194         enable = 0;
13195       else
13196         break;
13197     }
13198
13199   if (sw_if_index == ~0)
13200     {
13201       errmsg ("Interface required but not specified");
13202       return -99;
13203     }
13204
13205   /* Construct the API message */
13206   M (PG_INTERFACE_ENABLE_DISABLE_COALESCE, mp);
13207   mp->context = 0;
13208   mp->coalesce_enabled = enable;
13209   mp->sw_if_index = htonl (sw_if_index);
13210
13211   S (mp);
13212   W (ret);
13213   return ret;
13214 }
13215
13216 int
13217 api_ip_source_and_port_range_check_add_del (vat_main_t * vam)
13218 {
13219   unformat_input_t *input = vam->input;
13220   vl_api_ip_source_and_port_range_check_add_del_t *mp;
13221
13222   u16 *low_ports = 0;
13223   u16 *high_ports = 0;
13224   u16 this_low;
13225   u16 this_hi;
13226   vl_api_prefix_t prefix;
13227   u32 tmp, tmp2;
13228   u8 prefix_set = 0;
13229   u32 vrf_id = ~0;
13230   u8 is_add = 1;
13231   int ret;
13232
13233   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
13234     {
13235       if (unformat (input, "%U", unformat_vl_api_prefix, &prefix))
13236         prefix_set = 1;
13237       else if (unformat (input, "vrf %d", &vrf_id))
13238         ;
13239       else if (unformat (input, "del"))
13240         is_add = 0;
13241       else if (unformat (input, "port %d", &tmp))
13242         {
13243           if (tmp == 0 || tmp > 65535)
13244             {
13245               errmsg ("port %d out of range", tmp);
13246               return -99;
13247             }
13248           this_low = tmp;
13249           this_hi = this_low + 1;
13250           vec_add1 (low_ports, this_low);
13251           vec_add1 (high_ports, this_hi);
13252         }
13253       else if (unformat (input, "range %d - %d", &tmp, &tmp2))
13254         {
13255           if ((tmp > tmp2) || (tmp == 0) || (tmp2 > 65535))
13256             {
13257               errmsg ("incorrect range parameters");
13258               return -99;
13259             }
13260           this_low = tmp;
13261           /* Note: in debug CLI +1 is added to high before
13262              passing to real fn that does "the work"
13263              (ip_source_and_port_range_check_add_del).
13264              This fn is a wrapper around the binary API fn a
13265              control plane will call, which expects this increment
13266              to have occurred. Hence letting the binary API control
13267              plane fn do the increment for consistency between VAT
13268              and other control planes.
13269            */
13270           this_hi = tmp2;
13271           vec_add1 (low_ports, this_low);
13272           vec_add1 (high_ports, this_hi);
13273         }
13274       else
13275         break;
13276     }
13277
13278   if (prefix_set == 0)
13279     {
13280       errmsg ("<address>/<mask> not specified");
13281       return -99;
13282     }
13283
13284   if (vrf_id == ~0)
13285     {
13286       errmsg ("VRF ID required, not specified");
13287       return -99;
13288     }
13289
13290   if (vrf_id == 0)
13291     {
13292       errmsg
13293         ("VRF ID should not be default. Should be distinct VRF for this purpose.");
13294       return -99;
13295     }
13296
13297   if (vec_len (low_ports) == 0)
13298     {
13299       errmsg ("At least one port or port range required");
13300       return -99;
13301     }
13302
13303   M (IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL, mp);
13304
13305   mp->is_add = is_add;
13306
13307   clib_memcpy (&mp->prefix, &prefix, sizeof (prefix));
13308
13309   mp->number_of_ranges = vec_len (low_ports);
13310
13311   clib_memcpy (mp->low_ports, low_ports, vec_len (low_ports));
13312   vec_free (low_ports);
13313
13314   clib_memcpy (mp->high_ports, high_ports, vec_len (high_ports));
13315   vec_free (high_ports);
13316
13317   mp->vrf_id = ntohl (vrf_id);
13318
13319   S (mp);
13320   W (ret);
13321   return ret;
13322 }
13323
13324 int
13325 api_ip_source_and_port_range_check_interface_add_del (vat_main_t * vam)
13326 {
13327   unformat_input_t *input = vam->input;
13328   vl_api_ip_source_and_port_range_check_interface_add_del_t *mp;
13329   u32 sw_if_index = ~0;
13330   int vrf_set = 0;
13331   u32 tcp_out_vrf_id = ~0, udp_out_vrf_id = ~0;
13332   u32 tcp_in_vrf_id = ~0, udp_in_vrf_id = ~0;
13333   u8 is_add = 1;
13334   int ret;
13335
13336   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
13337     {
13338       if (unformat (input, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13339         ;
13340       else if (unformat (input, "sw_if_index %d", &sw_if_index))
13341         ;
13342       else if (unformat (input, "tcp-out-vrf %d", &tcp_out_vrf_id))
13343         vrf_set = 1;
13344       else if (unformat (input, "udp-out-vrf %d", &udp_out_vrf_id))
13345         vrf_set = 1;
13346       else if (unformat (input, "tcp-in-vrf %d", &tcp_in_vrf_id))
13347         vrf_set = 1;
13348       else if (unformat (input, "udp-in-vrf %d", &udp_in_vrf_id))
13349         vrf_set = 1;
13350       else if (unformat (input, "del"))
13351         is_add = 0;
13352       else
13353         break;
13354     }
13355
13356   if (sw_if_index == ~0)
13357     {
13358       errmsg ("Interface required but not specified");
13359       return -99;
13360     }
13361
13362   if (vrf_set == 0)
13363     {
13364       errmsg ("VRF ID required but not specified");
13365       return -99;
13366     }
13367
13368   if (tcp_out_vrf_id == 0
13369       || udp_out_vrf_id == 0 || tcp_in_vrf_id == 0 || udp_in_vrf_id == 0)
13370     {
13371       errmsg
13372         ("VRF ID should not be default. Should be distinct VRF for this purpose.");
13373       return -99;
13374     }
13375
13376   /* Construct the API message */
13377   M (IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL, mp);
13378
13379   mp->sw_if_index = ntohl (sw_if_index);
13380   mp->is_add = is_add;
13381   mp->tcp_out_vrf_id = ntohl (tcp_out_vrf_id);
13382   mp->udp_out_vrf_id = ntohl (udp_out_vrf_id);
13383   mp->tcp_in_vrf_id = ntohl (tcp_in_vrf_id);
13384   mp->udp_in_vrf_id = ntohl (udp_in_vrf_id);
13385
13386   /* send it... */
13387   S (mp);
13388
13389   /* Wait for a reply... */
13390   W (ret);
13391   return ret;
13392 }
13393
13394 static int
13395 api_set_punt (vat_main_t * vam)
13396 {
13397   unformat_input_t *i = vam->input;
13398   vl_api_address_family_t af;
13399   vl_api_set_punt_t *mp;
13400   u32 protocol = ~0;
13401   u32 port = ~0;
13402   int is_add = 1;
13403   int ret;
13404
13405   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13406     {
13407       if (unformat (i, "%U", unformat_vl_api_address_family, &af))
13408         ;
13409       else if (unformat (i, "protocol %d", &protocol))
13410         ;
13411       else if (unformat (i, "port %d", &port))
13412         ;
13413       else if (unformat (i, "del"))
13414         is_add = 0;
13415       else
13416         {
13417           clib_warning ("parse error '%U'", format_unformat_error, i);
13418           return -99;
13419         }
13420     }
13421
13422   M (SET_PUNT, mp);
13423
13424   mp->is_add = (u8) is_add;
13425   mp->punt.type = PUNT_API_TYPE_L4;
13426   mp->punt.punt.l4.af = af;
13427   mp->punt.punt.l4.protocol = (u8) protocol;
13428   mp->punt.punt.l4.port = htons ((u16) port);
13429
13430   S (mp);
13431   W (ret);
13432   return ret;
13433 }
13434
13435 static int
13436 api_delete_subif (vat_main_t * vam)
13437 {
13438   unformat_input_t *i = vam->input;
13439   vl_api_delete_subif_t *mp;
13440   u32 sw_if_index = ~0;
13441   int ret;
13442
13443   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13444     {
13445       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13446         ;
13447       if (unformat (i, "sw_if_index %d", &sw_if_index))
13448         ;
13449       else
13450         break;
13451     }
13452
13453   if (sw_if_index == ~0)
13454     {
13455       errmsg ("missing sw_if_index");
13456       return -99;
13457     }
13458
13459   /* Construct the API message */
13460   M (DELETE_SUBIF, mp);
13461   mp->sw_if_index = ntohl (sw_if_index);
13462
13463   S (mp);
13464   W (ret);
13465   return ret;
13466 }
13467
13468 #define foreach_pbb_vtr_op      \
13469 _("disable",  L2_VTR_DISABLED)  \
13470 _("pop",  L2_VTR_POP_2)         \
13471 _("push",  L2_VTR_PUSH_2)
13472
13473 static int
13474 api_l2_interface_pbb_tag_rewrite (vat_main_t * vam)
13475 {
13476   unformat_input_t *i = vam->input;
13477   vl_api_l2_interface_pbb_tag_rewrite_t *mp;
13478   u32 sw_if_index = ~0, vtr_op = ~0;
13479   u16 outer_tag = ~0;
13480   u8 dmac[6], smac[6];
13481   u8 dmac_set = 0, smac_set = 0;
13482   u16 vlanid = 0;
13483   u32 sid = ~0;
13484   u32 tmp;
13485   int ret;
13486
13487   /* Shut up coverity */
13488   clib_memset (dmac, 0, sizeof (dmac));
13489   clib_memset (smac, 0, sizeof (smac));
13490
13491   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13492     {
13493       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13494         ;
13495       else if (unformat (i, "sw_if_index %d", &sw_if_index))
13496         ;
13497       else if (unformat (i, "vtr_op %d", &vtr_op))
13498         ;
13499 #define _(n,v) else if (unformat(i, n)) {vtr_op = v;}
13500       foreach_pbb_vtr_op
13501 #undef _
13502         else if (unformat (i, "translate_pbb_stag"))
13503         {
13504           if (unformat (i, "%d", &tmp))
13505             {
13506               vtr_op = L2_VTR_TRANSLATE_2_1;
13507               outer_tag = tmp;
13508             }
13509           else
13510             {
13511               errmsg
13512                 ("translate_pbb_stag operation requires outer tag definition");
13513               return -99;
13514             }
13515         }
13516       else if (unformat (i, "dmac %U", unformat_ethernet_address, dmac))
13517         dmac_set++;
13518       else if (unformat (i, "smac %U", unformat_ethernet_address, smac))
13519         smac_set++;
13520       else if (unformat (i, "sid %d", &sid))
13521         ;
13522       else if (unformat (i, "vlanid %d", &tmp))
13523         vlanid = tmp;
13524       else
13525         {
13526           clib_warning ("parse error '%U'", format_unformat_error, i);
13527           return -99;
13528         }
13529     }
13530
13531   if ((sw_if_index == ~0) || (vtr_op == ~0))
13532     {
13533       errmsg ("missing sw_if_index or vtr operation");
13534       return -99;
13535     }
13536   if (((vtr_op == L2_VTR_PUSH_2) || (vtr_op == L2_VTR_TRANSLATE_2_2))
13537       && ((dmac_set == 0) || (smac_set == 0) || (sid == ~0)))
13538     {
13539       errmsg
13540         ("push and translate_qinq operations require dmac, smac, sid and optionally vlanid");
13541       return -99;
13542     }
13543
13544   M (L2_INTERFACE_PBB_TAG_REWRITE, mp);
13545   mp->sw_if_index = ntohl (sw_if_index);
13546   mp->vtr_op = ntohl (vtr_op);
13547   mp->outer_tag = ntohs (outer_tag);
13548   clib_memcpy (mp->b_dmac, dmac, sizeof (dmac));
13549   clib_memcpy (mp->b_smac, smac, sizeof (smac));
13550   mp->b_vlanid = ntohs (vlanid);
13551   mp->i_sid = ntohl (sid);
13552
13553   S (mp);
13554   W (ret);
13555   return ret;
13556 }
13557
13558 static int
13559 api_flow_classify_set_interface (vat_main_t * vam)
13560 {
13561   unformat_input_t *i = vam->input;
13562   vl_api_flow_classify_set_interface_t *mp;
13563   u32 sw_if_index;
13564   int sw_if_index_set;
13565   u32 ip4_table_index = ~0;
13566   u32 ip6_table_index = ~0;
13567   u8 is_add = 1;
13568   int ret;
13569
13570   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13571     {
13572       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13573         sw_if_index_set = 1;
13574       else if (unformat (i, "sw_if_index %d", &sw_if_index))
13575         sw_if_index_set = 1;
13576       else if (unformat (i, "del"))
13577         is_add = 0;
13578       else if (unformat (i, "ip4-table %d", &ip4_table_index))
13579         ;
13580       else if (unformat (i, "ip6-table %d", &ip6_table_index))
13581         ;
13582       else
13583         {
13584           clib_warning ("parse error '%U'", format_unformat_error, i);
13585           return -99;
13586         }
13587     }
13588
13589   if (sw_if_index_set == 0)
13590     {
13591       errmsg ("missing interface name or sw_if_index");
13592       return -99;
13593     }
13594
13595   M (FLOW_CLASSIFY_SET_INTERFACE, mp);
13596
13597   mp->sw_if_index = ntohl (sw_if_index);
13598   mp->ip4_table_index = ntohl (ip4_table_index);
13599   mp->ip6_table_index = ntohl (ip6_table_index);
13600   mp->is_add = is_add;
13601
13602   S (mp);
13603   W (ret);
13604   return ret;
13605 }
13606
13607 static int
13608 api_flow_classify_dump (vat_main_t * vam)
13609 {
13610   unformat_input_t *i = vam->input;
13611   vl_api_flow_classify_dump_t *mp;
13612   vl_api_control_ping_t *mp_ping;
13613   u8 type = FLOW_CLASSIFY_N_TABLES;
13614   int ret;
13615
13616   if (unformat (i, "type %U", unformat_flow_classify_table_type, &type))
13617     ;
13618   else
13619     {
13620       errmsg ("classify table type must be specified");
13621       return -99;
13622     }
13623
13624   if (!vam->json_output)
13625     {
13626       print (vam->ofp, "%10s%20s", "Intfc idx", "Classify table");
13627     }
13628
13629   M (FLOW_CLASSIFY_DUMP, mp);
13630   mp->type = type;
13631   /* send it... */
13632   S (mp);
13633
13634   /* Use a control ping for synchronization */
13635   MPING (CONTROL_PING, mp_ping);
13636   S (mp_ping);
13637
13638   /* Wait for a reply... */
13639   W (ret);
13640   return ret;
13641 }
13642
13643 static int
13644 api_feature_enable_disable (vat_main_t * vam)
13645 {
13646   unformat_input_t *i = vam->input;
13647   vl_api_feature_enable_disable_t *mp;
13648   u8 *arc_name = 0;
13649   u8 *feature_name = 0;
13650   u32 sw_if_index = ~0;
13651   u8 enable = 1;
13652   int ret;
13653
13654   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13655     {
13656       if (unformat (i, "arc_name %s", &arc_name))
13657         ;
13658       else if (unformat (i, "feature_name %s", &feature_name))
13659         ;
13660       else
13661         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13662         ;
13663       else if (unformat (i, "sw_if_index %d", &sw_if_index))
13664         ;
13665       else if (unformat (i, "disable"))
13666         enable = 0;
13667       else
13668         break;
13669     }
13670
13671   if (arc_name == 0)
13672     {
13673       errmsg ("missing arc name");
13674       return -99;
13675     }
13676   if (vec_len (arc_name) > 63)
13677     {
13678       errmsg ("arc name too long");
13679     }
13680
13681   if (feature_name == 0)
13682     {
13683       errmsg ("missing feature name");
13684       return -99;
13685     }
13686   if (vec_len (feature_name) > 63)
13687     {
13688       errmsg ("feature name too long");
13689     }
13690
13691   if (sw_if_index == ~0)
13692     {
13693       errmsg ("missing interface name or sw_if_index");
13694       return -99;
13695     }
13696
13697   /* Construct the API message */
13698   M (FEATURE_ENABLE_DISABLE, mp);
13699   mp->sw_if_index = ntohl (sw_if_index);
13700   mp->enable = enable;
13701   clib_memcpy (mp->arc_name, arc_name, vec_len (arc_name));
13702   clib_memcpy (mp->feature_name, feature_name, vec_len (feature_name));
13703   vec_free (arc_name);
13704   vec_free (feature_name);
13705
13706   S (mp);
13707   W (ret);
13708   return ret;
13709 }
13710
13711 static int
13712 api_feature_gso_enable_disable (vat_main_t * vam)
13713 {
13714   unformat_input_t *i = vam->input;
13715   vl_api_feature_gso_enable_disable_t *mp;
13716   u32 sw_if_index = ~0;
13717   u8 enable = 1;
13718   int ret;
13719
13720   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13721     {
13722       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13723         ;
13724       else if (unformat (i, "sw_if_index %d", &sw_if_index))
13725         ;
13726       else if (unformat (i, "enable"))
13727         enable = 1;
13728       else if (unformat (i, "disable"))
13729         enable = 0;
13730       else
13731         break;
13732     }
13733
13734   if (sw_if_index == ~0)
13735     {
13736       errmsg ("missing interface name or sw_if_index");
13737       return -99;
13738     }
13739
13740   /* Construct the API message */
13741   M (FEATURE_GSO_ENABLE_DISABLE, mp);
13742   mp->sw_if_index = ntohl (sw_if_index);
13743   mp->enable_disable = enable;
13744
13745   S (mp);
13746   W (ret);
13747   return ret;
13748 }
13749
13750 static int
13751 api_sw_interface_tag_add_del (vat_main_t * vam)
13752 {
13753   unformat_input_t *i = vam->input;
13754   vl_api_sw_interface_tag_add_del_t *mp;
13755   u32 sw_if_index = ~0;
13756   u8 *tag = 0;
13757   u8 enable = 1;
13758   int ret;
13759
13760   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13761     {
13762       if (unformat (i, "tag %s", &tag))
13763         ;
13764       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13765         ;
13766       else if (unformat (i, "sw_if_index %d", &sw_if_index))
13767         ;
13768       else if (unformat (i, "del"))
13769         enable = 0;
13770       else
13771         break;
13772     }
13773
13774   if (sw_if_index == ~0)
13775     {
13776       errmsg ("missing interface name or sw_if_index");
13777       return -99;
13778     }
13779
13780   if (enable && (tag == 0))
13781     {
13782       errmsg ("no tag specified");
13783       return -99;
13784     }
13785
13786   /* Construct the API message */
13787   M (SW_INTERFACE_TAG_ADD_DEL, mp);
13788   mp->sw_if_index = ntohl (sw_if_index);
13789   mp->is_add = enable;
13790   if (enable)
13791     strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
13792   vec_free (tag);
13793
13794   S (mp);
13795   W (ret);
13796   return ret;
13797 }
13798
13799 static int
13800 api_sw_interface_add_del_mac_address (vat_main_t * vam)
13801 {
13802   unformat_input_t *i = vam->input;
13803   vl_api_mac_address_t mac = { 0 };
13804   vl_api_sw_interface_add_del_mac_address_t *mp;
13805   u32 sw_if_index = ~0;
13806   u8 is_add = 1;
13807   u8 mac_set = 0;
13808   int ret;
13809
13810   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13811     {
13812       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13813         ;
13814       else if (unformat (i, "sw_if_index %d", &sw_if_index))
13815         ;
13816       else if (unformat (i, "%U", unformat_vl_api_mac_address, &mac))
13817         mac_set++;
13818       else if (unformat (i, "del"))
13819         is_add = 0;
13820       else
13821         break;
13822     }
13823
13824   if (sw_if_index == ~0)
13825     {
13826       errmsg ("missing interface name or sw_if_index");
13827       return -99;
13828     }
13829
13830   if (!mac_set)
13831     {
13832       errmsg ("missing MAC address");
13833       return -99;
13834     }
13835
13836   /* Construct the API message */
13837   M (SW_INTERFACE_ADD_DEL_MAC_ADDRESS, mp);
13838   mp->sw_if_index = ntohl (sw_if_index);
13839   mp->is_add = is_add;
13840   clib_memcpy (&mp->addr, &mac, sizeof (mac));
13841
13842   S (mp);
13843   W (ret);
13844   return ret;
13845 }
13846
13847 static void vl_api_l2_xconnect_details_t_handler
13848   (vl_api_l2_xconnect_details_t * mp)
13849 {
13850   vat_main_t *vam = &vat_main;
13851
13852   print (vam->ofp, "%15d%15d",
13853          ntohl (mp->rx_sw_if_index), ntohl (mp->tx_sw_if_index));
13854 }
13855
13856 static void vl_api_l2_xconnect_details_t_handler_json
13857   (vl_api_l2_xconnect_details_t * mp)
13858 {
13859   vat_main_t *vam = &vat_main;
13860   vat_json_node_t *node = NULL;
13861
13862   if (VAT_JSON_ARRAY != vam->json_tree.type)
13863     {
13864       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
13865       vat_json_init_array (&vam->json_tree);
13866     }
13867   node = vat_json_array_add (&vam->json_tree);
13868
13869   vat_json_init_object (node);
13870   vat_json_object_add_uint (node, "rx_sw_if_index",
13871                             ntohl (mp->rx_sw_if_index));
13872   vat_json_object_add_uint (node, "tx_sw_if_index",
13873                             ntohl (mp->tx_sw_if_index));
13874 }
13875
13876 static int
13877 api_l2_xconnect_dump (vat_main_t * vam)
13878 {
13879   vl_api_l2_xconnect_dump_t *mp;
13880   vl_api_control_ping_t *mp_ping;
13881   int ret;
13882
13883   if (!vam->json_output)
13884     {
13885       print (vam->ofp, "%15s%15s", "rx_sw_if_index", "tx_sw_if_index");
13886     }
13887
13888   M (L2_XCONNECT_DUMP, mp);
13889
13890   S (mp);
13891
13892   /* Use a control ping for synchronization */
13893   MPING (CONTROL_PING, mp_ping);
13894   S (mp_ping);
13895
13896   W (ret);
13897   return ret;
13898 }
13899
13900 static int
13901 api_hw_interface_set_mtu (vat_main_t * vam)
13902 {
13903   unformat_input_t *i = vam->input;
13904   vl_api_hw_interface_set_mtu_t *mp;
13905   u32 sw_if_index = ~0;
13906   u32 mtu = 0;
13907   int ret;
13908
13909   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13910     {
13911       if (unformat (i, "mtu %d", &mtu))
13912         ;
13913       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13914         ;
13915       else if (unformat (i, "sw_if_index %d", &sw_if_index))
13916         ;
13917       else
13918         break;
13919     }
13920
13921   if (sw_if_index == ~0)
13922     {
13923       errmsg ("missing interface name or sw_if_index");
13924       return -99;
13925     }
13926
13927   if (mtu == 0)
13928     {
13929       errmsg ("no mtu specified");
13930       return -99;
13931     }
13932
13933   /* Construct the API message */
13934   M (HW_INTERFACE_SET_MTU, mp);
13935   mp->sw_if_index = ntohl (sw_if_index);
13936   mp->mtu = ntohs ((u16) mtu);
13937
13938   S (mp);
13939   W (ret);
13940   return ret;
13941 }
13942
13943 static int
13944 api_p2p_ethernet_add (vat_main_t * vam)
13945 {
13946   unformat_input_t *i = vam->input;
13947   vl_api_p2p_ethernet_add_t *mp;
13948   u32 parent_if_index = ~0;
13949   u32 sub_id = ~0;
13950   u8 remote_mac[6];
13951   u8 mac_set = 0;
13952   int ret;
13953
13954   clib_memset (remote_mac, 0, sizeof (remote_mac));
13955   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13956     {
13957       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &parent_if_index))
13958         ;
13959       else if (unformat (i, "sw_if_index %d", &parent_if_index))
13960         ;
13961       else
13962         if (unformat
13963             (i, "remote_mac %U", unformat_ethernet_address, remote_mac))
13964         mac_set++;
13965       else if (unformat (i, "sub_id %d", &sub_id))
13966         ;
13967       else
13968         {
13969           clib_warning ("parse error '%U'", format_unformat_error, i);
13970           return -99;
13971         }
13972     }
13973
13974   if (parent_if_index == ~0)
13975     {
13976       errmsg ("missing interface name or sw_if_index");
13977       return -99;
13978     }
13979   if (mac_set == 0)
13980     {
13981       errmsg ("missing remote mac address");
13982       return -99;
13983     }
13984   if (sub_id == ~0)
13985     {
13986       errmsg ("missing sub-interface id");
13987       return -99;
13988     }
13989
13990   M (P2P_ETHERNET_ADD, mp);
13991   mp->parent_if_index = ntohl (parent_if_index);
13992   mp->subif_id = ntohl (sub_id);
13993   clib_memcpy (mp->remote_mac, remote_mac, sizeof (remote_mac));
13994
13995   S (mp);
13996   W (ret);
13997   return ret;
13998 }
13999
14000 static int
14001 api_p2p_ethernet_del (vat_main_t * vam)
14002 {
14003   unformat_input_t *i = vam->input;
14004   vl_api_p2p_ethernet_del_t *mp;
14005   u32 parent_if_index = ~0;
14006   u8 remote_mac[6];
14007   u8 mac_set = 0;
14008   int ret;
14009
14010   clib_memset (remote_mac, 0, sizeof (remote_mac));
14011   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
14012     {
14013       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &parent_if_index))
14014         ;
14015       else if (unformat (i, "sw_if_index %d", &parent_if_index))
14016         ;
14017       else
14018         if (unformat
14019             (i, "remote_mac %U", unformat_ethernet_address, remote_mac))
14020         mac_set++;
14021       else
14022         {
14023           clib_warning ("parse error '%U'", format_unformat_error, i);
14024           return -99;
14025         }
14026     }
14027
14028   if (parent_if_index == ~0)
14029     {
14030       errmsg ("missing interface name or sw_if_index");
14031       return -99;
14032     }
14033   if (mac_set == 0)
14034     {
14035       errmsg ("missing remote mac address");
14036       return -99;
14037     }
14038
14039   M (P2P_ETHERNET_DEL, mp);
14040   mp->parent_if_index = ntohl (parent_if_index);
14041   clib_memcpy (mp->remote_mac, remote_mac, sizeof (remote_mac));
14042
14043   S (mp);
14044   W (ret);
14045   return ret;
14046 }
14047
14048 static int
14049 api_tcp_configure_src_addresses (vat_main_t * vam)
14050 {
14051   vl_api_tcp_configure_src_addresses_t *mp;
14052   unformat_input_t *i = vam->input;
14053   vl_api_address_t first, last;
14054   u8 range_set = 0;
14055   u32 vrf_id = 0;
14056   int ret;
14057
14058   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
14059     {
14060       if (unformat (i, "%U - %U",
14061                     unformat_vl_api_address, &first,
14062                     unformat_vl_api_address, &last))
14063         {
14064           if (range_set)
14065             {
14066               errmsg ("one range per message (range already set)");
14067               return -99;
14068             }
14069           range_set = 1;
14070         }
14071       else if (unformat (i, "vrf %d", &vrf_id))
14072         ;
14073       else
14074         break;
14075     }
14076
14077   if (range_set == 0)
14078     {
14079       errmsg ("address range not set");
14080       return -99;
14081     }
14082
14083   M (TCP_CONFIGURE_SRC_ADDRESSES, mp);
14084
14085   mp->vrf_id = ntohl (vrf_id);
14086   clib_memcpy (&mp->first_address, &first, sizeof (first));
14087   clib_memcpy (&mp->last_address, &last, sizeof (last));
14088
14089   S (mp);
14090   W (ret);
14091   return ret;
14092 }
14093
14094 static void vl_api_app_namespace_add_del_reply_t_handler
14095   (vl_api_app_namespace_add_del_reply_t * mp)
14096 {
14097   vat_main_t *vam = &vat_main;
14098   i32 retval = ntohl (mp->retval);
14099   if (vam->async_mode)
14100     {
14101       vam->async_errors += (retval < 0);
14102     }
14103   else
14104     {
14105       vam->retval = retval;
14106       if (retval == 0)
14107         errmsg ("app ns index %d\n", ntohl (mp->appns_index));
14108       vam->result_ready = 1;
14109     }
14110 }
14111
14112 static void vl_api_app_namespace_add_del_reply_t_handler_json
14113   (vl_api_app_namespace_add_del_reply_t * mp)
14114 {
14115   vat_main_t *vam = &vat_main;
14116   vat_json_node_t node;
14117
14118   vat_json_init_object (&node);
14119   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
14120   vat_json_object_add_uint (&node, "appns_index", ntohl (mp->appns_index));
14121
14122   vat_json_print (vam->ofp, &node);
14123   vat_json_free (&node);
14124
14125   vam->retval = ntohl (mp->retval);
14126   vam->result_ready = 1;
14127 }
14128
14129 static int
14130 api_app_namespace_add_del (vat_main_t * vam)
14131 {
14132   vl_api_app_namespace_add_del_t *mp;
14133   unformat_input_t *i = vam->input;
14134   u8 *ns_id = 0, secret_set = 0, sw_if_index_set = 0;
14135   u32 sw_if_index, ip4_fib_id, ip6_fib_id;
14136   u64 secret;
14137   int ret;
14138
14139   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
14140     {
14141       if (unformat (i, "id %_%v%_", &ns_id))
14142         ;
14143       else if (unformat (i, "secret %lu", &secret))
14144         secret_set = 1;
14145       else if (unformat (i, "sw_if_index %d", &sw_if_index))
14146         sw_if_index_set = 1;
14147       else if (unformat (i, "ip4_fib_id %d", &ip4_fib_id))
14148         ;
14149       else if (unformat (i, "ip6_fib_id %d", &ip6_fib_id))
14150         ;
14151       else
14152         break;
14153     }
14154   if (!ns_id || !secret_set || !sw_if_index_set)
14155     {
14156       errmsg ("namespace id, secret and sw_if_index must be set");
14157       return -99;
14158     }
14159   if (vec_len (ns_id) > 64)
14160     {
14161       errmsg ("namespace id too long");
14162       return -99;
14163     }
14164   M (APP_NAMESPACE_ADD_DEL, mp);
14165
14166   vl_api_vec_to_api_string (ns_id, &mp->namespace_id);
14167   mp->secret = clib_host_to_net_u64 (secret);
14168   mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
14169   mp->ip4_fib_id = clib_host_to_net_u32 (ip4_fib_id);
14170   mp->ip6_fib_id = clib_host_to_net_u32 (ip6_fib_id);
14171   vec_free (ns_id);
14172   S (mp);
14173   W (ret);
14174   return ret;
14175 }
14176
14177 static int
14178 api_sock_init_shm (vat_main_t * vam)
14179 {
14180 #if VPP_API_TEST_BUILTIN == 0
14181   unformat_input_t *i = vam->input;
14182   vl_api_shm_elem_config_t *config = 0;
14183   u64 size = 64 << 20;
14184   int rv;
14185
14186   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
14187     {
14188       if (unformat (i, "size %U", unformat_memory_size, &size))
14189         ;
14190       else
14191         break;
14192     }
14193
14194   /*
14195    * Canned custom ring allocator config.
14196    * Should probably parse all of this
14197    */
14198   vec_validate (config, 6);
14199   config[0].type = VL_API_VLIB_RING;
14200   config[0].size = 256;
14201   config[0].count = 32;
14202
14203   config[1].type = VL_API_VLIB_RING;
14204   config[1].size = 1024;
14205   config[1].count = 16;
14206
14207   config[2].type = VL_API_VLIB_RING;
14208   config[2].size = 4096;
14209   config[2].count = 2;
14210
14211   config[3].type = VL_API_CLIENT_RING;
14212   config[3].size = 256;
14213   config[3].count = 32;
14214
14215   config[4].type = VL_API_CLIENT_RING;
14216   config[4].size = 1024;
14217   config[4].count = 16;
14218
14219   config[5].type = VL_API_CLIENT_RING;
14220   config[5].size = 4096;
14221   config[5].count = 2;
14222
14223   config[6].type = VL_API_QUEUE;
14224   config[6].count = 128;
14225   config[6].size = sizeof (uword);
14226
14227   rv = vl_socket_client_init_shm (config, 1 /* want_pthread */ );
14228   if (!rv)
14229     vam->client_index_invalid = 1;
14230   return rv;
14231 #else
14232   return -99;
14233 #endif
14234 }
14235
14236 static void
14237 vl_api_session_rules_details_t_handler (vl_api_session_rules_details_t * mp)
14238 {
14239   vat_main_t *vam = &vat_main;
14240   fib_prefix_t lcl, rmt;
14241
14242   ip_prefix_decode (&mp->lcl, &lcl);
14243   ip_prefix_decode (&mp->rmt, &rmt);
14244
14245   if (lcl.fp_proto == FIB_PROTOCOL_IP4)
14246     {
14247       print (vam->ofp,
14248              "appns %u tp %u scope %d %U/%d %d %U/%d %d action: %d tag: %s",
14249              clib_net_to_host_u32 (mp->appns_index), mp->transport_proto,
14250              mp->scope, format_ip4_address, &lcl.fp_addr.ip4, lcl.fp_len,
14251              clib_net_to_host_u16 (mp->lcl_port), format_ip4_address,
14252              &rmt.fp_addr.ip4, rmt.fp_len,
14253              clib_net_to_host_u16 (mp->rmt_port),
14254              clib_net_to_host_u32 (mp->action_index), mp->tag);
14255     }
14256   else
14257     {
14258       print (vam->ofp,
14259              "appns %u tp %u scope %d %U/%d %d %U/%d %d action: %d tag: %s",
14260              clib_net_to_host_u32 (mp->appns_index), mp->transport_proto,
14261              mp->scope, format_ip6_address, &lcl.fp_addr.ip6, lcl.fp_len,
14262              clib_net_to_host_u16 (mp->lcl_port), format_ip6_address,
14263              &rmt.fp_addr.ip6, rmt.fp_len,
14264              clib_net_to_host_u16 (mp->rmt_port),
14265              clib_net_to_host_u32 (mp->action_index), mp->tag);
14266     }
14267 }
14268
14269 static void
14270 vl_api_session_rules_details_t_handler_json (vl_api_session_rules_details_t *
14271                                              mp)
14272 {
14273   vat_main_t *vam = &vat_main;
14274   vat_json_node_t *node = NULL;
14275   struct in6_addr ip6;
14276   struct in_addr ip4;
14277
14278   fib_prefix_t lcl, rmt;
14279
14280   ip_prefix_decode (&mp->lcl, &lcl);
14281   ip_prefix_decode (&mp->rmt, &rmt);
14282
14283   if (VAT_JSON_ARRAY != vam->json_tree.type)
14284     {
14285       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
14286       vat_json_init_array (&vam->json_tree);
14287     }
14288   node = vat_json_array_add (&vam->json_tree);
14289   vat_json_init_object (node);
14290
14291   vat_json_object_add_uint (node, "appns_index",
14292                             clib_net_to_host_u32 (mp->appns_index));
14293   vat_json_object_add_uint (node, "transport_proto", mp->transport_proto);
14294   vat_json_object_add_uint (node, "scope", mp->scope);
14295   vat_json_object_add_uint (node, "action_index",
14296                             clib_net_to_host_u32 (mp->action_index));
14297   vat_json_object_add_uint (node, "lcl_port",
14298                             clib_net_to_host_u16 (mp->lcl_port));
14299   vat_json_object_add_uint (node, "rmt_port",
14300                             clib_net_to_host_u16 (mp->rmt_port));
14301   vat_json_object_add_uint (node, "lcl_plen", lcl.fp_len);
14302   vat_json_object_add_uint (node, "rmt_plen", rmt.fp_len);
14303   vat_json_object_add_string_copy (node, "tag", mp->tag);
14304   if (lcl.fp_proto == FIB_PROTOCOL_IP4)
14305     {
14306       clib_memcpy (&ip4, &lcl.fp_addr.ip4, sizeof (ip4));
14307       vat_json_object_add_ip4 (node, "lcl_ip", ip4);
14308       clib_memcpy (&ip4, &rmt.fp_addr.ip4, sizeof (ip4));
14309       vat_json_object_add_ip4 (node, "rmt_ip", ip4);
14310     }
14311   else
14312     {
14313       clib_memcpy (&ip6, &lcl.fp_addr.ip6, sizeof (ip6));
14314       vat_json_object_add_ip6 (node, "lcl_ip", ip6);
14315       clib_memcpy (&ip6, &rmt.fp_addr.ip6, sizeof (ip6));
14316       vat_json_object_add_ip6 (node, "rmt_ip", ip6);
14317     }
14318 }
14319
14320 static int
14321 api_session_rule_add_del (vat_main_t * vam)
14322 {
14323   vl_api_session_rule_add_del_t *mp;
14324   unformat_input_t *i = vam->input;
14325   u32 proto = ~0, lcl_port, rmt_port, action = 0, lcl_plen, rmt_plen;
14326   u32 appns_index = 0, scope = 0;
14327   ip4_address_t lcl_ip4, rmt_ip4;
14328   ip6_address_t lcl_ip6, rmt_ip6;
14329   u8 is_ip4 = 1, conn_set = 0;
14330   u8 is_add = 1, *tag = 0;
14331   int ret;
14332   fib_prefix_t lcl, rmt;
14333
14334   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
14335     {
14336       if (unformat (i, "del"))
14337         is_add = 0;
14338       else if (unformat (i, "add"))
14339         ;
14340       else if (unformat (i, "proto tcp"))
14341         proto = 0;
14342       else if (unformat (i, "proto udp"))
14343         proto = 1;
14344       else if (unformat (i, "appns %d", &appns_index))
14345         ;
14346       else if (unformat (i, "scope %d", &scope))
14347         ;
14348       else if (unformat (i, "tag %_%v%_", &tag))
14349         ;
14350       else
14351         if (unformat
14352             (i, "%U/%d %d %U/%d %d", unformat_ip4_address, &lcl_ip4,
14353              &lcl_plen, &lcl_port, unformat_ip4_address, &rmt_ip4, &rmt_plen,
14354              &rmt_port))
14355         {
14356           is_ip4 = 1;
14357           conn_set = 1;
14358         }
14359       else
14360         if (unformat
14361             (i, "%U/%d %d %U/%d %d", unformat_ip6_address, &lcl_ip6,
14362              &lcl_plen, &lcl_port, unformat_ip6_address, &rmt_ip6, &rmt_plen,
14363              &rmt_port))
14364         {
14365           is_ip4 = 0;
14366           conn_set = 1;
14367         }
14368       else if (unformat (i, "action %d", &action))
14369         ;
14370       else
14371         break;
14372     }
14373   if (proto == ~0 || !conn_set || action == ~0)
14374     {
14375       errmsg ("transport proto, connection and action must be set");
14376       return -99;
14377     }
14378
14379   if (scope > 3)
14380     {
14381       errmsg ("scope should be 0-3");
14382       return -99;
14383     }
14384
14385   M (SESSION_RULE_ADD_DEL, mp);
14386
14387   clib_memset (&lcl, 0, sizeof (lcl));
14388   clib_memset (&rmt, 0, sizeof (rmt));
14389   if (is_ip4)
14390     {
14391       ip_set (&lcl.fp_addr, &lcl_ip4, 1);
14392       ip_set (&rmt.fp_addr, &rmt_ip4, 1);
14393       lcl.fp_len = lcl_plen;
14394       rmt.fp_len = rmt_plen;
14395     }
14396   else
14397     {
14398       ip_set (&lcl.fp_addr, &lcl_ip6, 0);
14399       ip_set (&rmt.fp_addr, &rmt_ip6, 0);
14400       lcl.fp_len = lcl_plen;
14401       rmt.fp_len = rmt_plen;
14402     }
14403
14404
14405   ip_prefix_encode (&lcl, &mp->lcl);
14406   ip_prefix_encode (&rmt, &mp->rmt);
14407   mp->lcl_port = clib_host_to_net_u16 ((u16) lcl_port);
14408   mp->rmt_port = clib_host_to_net_u16 ((u16) rmt_port);
14409   mp->transport_proto =
14410     proto ? TRANSPORT_PROTO_API_UDP : TRANSPORT_PROTO_API_TCP;
14411   mp->action_index = clib_host_to_net_u32 (action);
14412   mp->appns_index = clib_host_to_net_u32 (appns_index);
14413   mp->scope = scope;
14414   mp->is_add = is_add;
14415   if (tag)
14416     {
14417       clib_memcpy (mp->tag, tag, vec_len (tag));
14418       vec_free (tag);
14419     }
14420
14421   S (mp);
14422   W (ret);
14423   return ret;
14424 }
14425
14426 static int
14427 api_session_rules_dump (vat_main_t * vam)
14428 {
14429   vl_api_session_rules_dump_t *mp;
14430   vl_api_control_ping_t *mp_ping;
14431   int ret;
14432
14433   if (!vam->json_output)
14434     {
14435       print (vam->ofp, "%=20s", "Session Rules");
14436     }
14437
14438   M (SESSION_RULES_DUMP, mp);
14439   /* send it... */
14440   S (mp);
14441
14442   /* Use a control ping for synchronization */
14443   MPING (CONTROL_PING, mp_ping);
14444   S (mp_ping);
14445
14446   /* Wait for a reply... */
14447   W (ret);
14448   return ret;
14449 }
14450
14451 static int
14452 api_ip_container_proxy_add_del (vat_main_t * vam)
14453 {
14454   vl_api_ip_container_proxy_add_del_t *mp;
14455   unformat_input_t *i = vam->input;
14456   u32 sw_if_index = ~0;
14457   vl_api_prefix_t pfx = { };
14458   u8 is_add = 1;
14459   int ret;
14460
14461   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
14462     {
14463       if (unformat (i, "del"))
14464         is_add = 0;
14465       else if (unformat (i, "add"))
14466         ;
14467       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
14468         ;
14469       else if (unformat (i, "sw_if_index %u", &sw_if_index))
14470         ;
14471       else
14472         break;
14473     }
14474   if (sw_if_index == ~0 || pfx.len == 0)
14475     {
14476       errmsg ("address and sw_if_index must be set");
14477       return -99;
14478     }
14479
14480   M (IP_CONTAINER_PROXY_ADD_DEL, mp);
14481
14482   mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
14483   mp->is_add = is_add;
14484   clib_memcpy (&mp->pfx, &pfx, sizeof (pfx));
14485
14486   S (mp);
14487   W (ret);
14488   return ret;
14489 }
14490
14491 static int
14492 api_qos_record_enable_disable (vat_main_t * vam)
14493 {
14494   unformat_input_t *i = vam->input;
14495   vl_api_qos_record_enable_disable_t *mp;
14496   u32 sw_if_index, qs = 0xff;
14497   u8 sw_if_index_set = 0;
14498   u8 enable = 1;
14499   int ret;
14500
14501   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
14502     {
14503       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
14504         sw_if_index_set = 1;
14505       else if (unformat (i, "sw_if_index %d", &sw_if_index))
14506         sw_if_index_set = 1;
14507       else if (unformat (i, "%U", unformat_qos_source, &qs))
14508         ;
14509       else if (unformat (i, "disable"))
14510         enable = 0;
14511       else
14512         {
14513           clib_warning ("parse error '%U'", format_unformat_error, i);
14514           return -99;
14515         }
14516     }
14517
14518   if (sw_if_index_set == 0)
14519     {
14520       errmsg ("missing interface name or sw_if_index");
14521       return -99;
14522     }
14523   if (qs == 0xff)
14524     {
14525       errmsg ("input location must be specified");
14526       return -99;
14527     }
14528
14529   M (QOS_RECORD_ENABLE_DISABLE, mp);
14530
14531   mp->record.sw_if_index = ntohl (sw_if_index);
14532   mp->record.input_source = qs;
14533   mp->enable = enable;
14534
14535   S (mp);
14536   W (ret);
14537   return ret;
14538 }
14539
14540
14541 static int
14542 q_or_quit (vat_main_t * vam)
14543 {
14544 #if VPP_API_TEST_BUILTIN == 0
14545   longjmp (vam->jump_buf, 1);
14546 #endif
14547   return 0;                     /* not so much */
14548 }
14549
14550 static int
14551 q (vat_main_t * vam)
14552 {
14553   return q_or_quit (vam);
14554 }
14555
14556 static int
14557 quit (vat_main_t * vam)
14558 {
14559   return q_or_quit (vam);
14560 }
14561
14562 static int
14563 comment (vat_main_t * vam)
14564 {
14565   return 0;
14566 }
14567
14568 static int
14569 elog_save (vat_main_t * vam)
14570 {
14571 #if VPP_API_TEST_BUILTIN == 0
14572   elog_main_t *em = &vam->elog_main;
14573   unformat_input_t *i = vam->input;
14574   char *file, *chroot_file;
14575   clib_error_t *error;
14576
14577   if (!unformat (i, "%s", &file))
14578     {
14579       errmsg ("expected file name, got `%U'", format_unformat_error, i);
14580       return 0;
14581     }
14582
14583   /* It's fairly hard to get "../oopsie" through unformat; just in case */
14584   if (strstr (file, "..") || index (file, '/'))
14585     {
14586       errmsg ("illegal characters in filename '%s'", file);
14587       return 0;
14588     }
14589
14590   chroot_file = (char *) format (0, "/tmp/%s%c", file, 0);
14591
14592   vec_free (file);
14593
14594   errmsg ("Saving %wd of %wd events to %s",
14595           elog_n_events_in_buffer (em),
14596           elog_buffer_capacity (em), chroot_file);
14597
14598   error = elog_write_file (em, chroot_file, 1 /* flush ring */ );
14599   vec_free (chroot_file);
14600
14601   if (error)
14602     clib_error_report (error);
14603 #else
14604   errmsg ("Use the vpp event loger...");
14605 #endif
14606
14607   return 0;
14608 }
14609
14610 static int
14611 elog_setup (vat_main_t * vam)
14612 {
14613 #if VPP_API_TEST_BUILTIN == 0
14614   elog_main_t *em = &vam->elog_main;
14615   unformat_input_t *i = vam->input;
14616   u32 nevents = 128 << 10;
14617
14618   (void) unformat (i, "nevents %d", &nevents);
14619
14620   elog_init (em, nevents);
14621   vl_api_set_elog_main (em);
14622   vl_api_set_elog_trace_api_messages (1);
14623   errmsg ("Event logger initialized with %u events", nevents);
14624 #else
14625   errmsg ("Use the vpp event loger...");
14626 #endif
14627   return 0;
14628 }
14629
14630 static int
14631 elog_enable (vat_main_t * vam)
14632 {
14633 #if VPP_API_TEST_BUILTIN == 0
14634   elog_main_t *em = &vam->elog_main;
14635
14636   elog_enable_disable (em, 1 /* enable */ );
14637   vl_api_set_elog_trace_api_messages (1);
14638   errmsg ("Event logger enabled...");
14639 #else
14640   errmsg ("Use the vpp event loger...");
14641 #endif
14642   return 0;
14643 }
14644
14645 static int
14646 elog_disable (vat_main_t * vam)
14647 {
14648 #if VPP_API_TEST_BUILTIN == 0
14649   elog_main_t *em = &vam->elog_main;
14650
14651   elog_enable_disable (em, 0 /* enable */ );
14652   vl_api_set_elog_trace_api_messages (1);
14653   errmsg ("Event logger disabled...");
14654 #else
14655   errmsg ("Use the vpp event loger...");
14656 #endif
14657   return 0;
14658 }
14659
14660 static int
14661 statseg (vat_main_t * vam)
14662 {
14663   ssvm_private_t *ssvmp = &vam->stat_segment;
14664   ssvm_shared_header_t *shared_header = ssvmp->sh;
14665   vlib_counter_t **counters;
14666   u64 thread0_index1_packets;
14667   u64 thread0_index1_bytes;
14668   f64 vector_rate, input_rate;
14669   uword *p;
14670
14671   uword *counter_vector_by_name;
14672   if (vam->stat_segment_lockp == 0)
14673     {
14674       errmsg ("Stat segment not mapped...");
14675       return -99;
14676     }
14677
14678   /* look up "/if/rx for sw_if_index 1 as a test */
14679
14680   clib_spinlock_lock (vam->stat_segment_lockp);
14681
14682   counter_vector_by_name = (uword *) shared_header->opaque[1];
14683
14684   p = hash_get_mem (counter_vector_by_name, "/if/rx");
14685   if (p == 0)
14686     {
14687       clib_spinlock_unlock (vam->stat_segment_lockp);
14688       errmsg ("/if/tx not found?");
14689       return -99;
14690     }
14691
14692   /* Fish per-thread vector of combined counters from shared memory */
14693   counters = (vlib_counter_t **) p[0];
14694
14695   if (vec_len (counters[0]) < 2)
14696     {
14697       clib_spinlock_unlock (vam->stat_segment_lockp);
14698       errmsg ("/if/tx vector length %d", vec_len (counters[0]));
14699       return -99;
14700     }
14701
14702   /* Read thread 0 sw_if_index 1 counter */
14703   thread0_index1_packets = counters[0][1].packets;
14704   thread0_index1_bytes = counters[0][1].bytes;
14705
14706   p = hash_get_mem (counter_vector_by_name, "vector_rate");
14707   if (p == 0)
14708     {
14709       clib_spinlock_unlock (vam->stat_segment_lockp);
14710       errmsg ("vector_rate not found?");
14711       return -99;
14712     }
14713
14714   vector_rate = *(f64 *) (p[0]);
14715   p = hash_get_mem (counter_vector_by_name, "input_rate");
14716   if (p == 0)
14717     {
14718       clib_spinlock_unlock (vam->stat_segment_lockp);
14719       errmsg ("input_rate not found?");
14720       return -99;
14721     }
14722   input_rate = *(f64 *) (p[0]);
14723
14724   clib_spinlock_unlock (vam->stat_segment_lockp);
14725
14726   print (vam->ofp, "vector_rate %.2f input_rate %.2f",
14727          vector_rate, input_rate);
14728   print (vam->ofp, "thread 0 sw_if_index 1 rx pkts %lld, bytes %lld",
14729          thread0_index1_packets, thread0_index1_bytes);
14730
14731   return 0;
14732 }
14733
14734 static int
14735 cmd_cmp (void *a1, void *a2)
14736 {
14737   u8 **c1 = a1;
14738   u8 **c2 = a2;
14739
14740   return strcmp ((char *) (c1[0]), (char *) (c2[0]));
14741 }
14742
14743 static int
14744 help (vat_main_t * vam)
14745 {
14746   u8 **cmds = 0;
14747   u8 *name = 0;
14748   hash_pair_t *p;
14749   unformat_input_t *i = vam->input;
14750   int j;
14751
14752   if (unformat (i, "%s", &name))
14753     {
14754       uword *hs;
14755
14756       vec_add1 (name, 0);
14757
14758       hs = hash_get_mem (vam->help_by_name, name);
14759       if (hs)
14760         print (vam->ofp, "usage: %s %s", name, hs[0]);
14761       else
14762         print (vam->ofp, "No such msg / command '%s'", name);
14763       vec_free (name);
14764       return 0;
14765     }
14766
14767   print (vam->ofp, "Help is available for the following:");
14768
14769     /* *INDENT-OFF* */
14770     hash_foreach_pair (p, vam->function_by_name,
14771     ({
14772       vec_add1 (cmds, (u8 *)(p->key));
14773     }));
14774     /* *INDENT-ON* */
14775
14776   vec_sort_with_function (cmds, cmd_cmp);
14777
14778   for (j = 0; j < vec_len (cmds); j++)
14779     print (vam->ofp, "%s", cmds[j]);
14780
14781   vec_free (cmds);
14782   return 0;
14783 }
14784
14785 static int
14786 set (vat_main_t * vam)
14787 {
14788   u8 *name = 0, *value = 0;
14789   unformat_input_t *i = vam->input;
14790
14791   if (unformat (i, "%s", &name))
14792     {
14793       /* The input buffer is a vector, not a string. */
14794       value = vec_dup (i->buffer);
14795       vec_delete (value, i->index, 0);
14796       /* Almost certainly has a trailing newline */
14797       if (value[vec_len (value) - 1] == '\n')
14798         value[vec_len (value) - 1] = 0;
14799       /* Make sure it's a proper string, one way or the other */
14800       vec_add1 (value, 0);
14801       (void) clib_macro_set_value (&vam->macro_main,
14802                                    (char *) name, (char *) value);
14803     }
14804   else
14805     errmsg ("usage: set <name> <value>");
14806
14807   vec_free (name);
14808   vec_free (value);
14809   return 0;
14810 }
14811
14812 static int
14813 unset (vat_main_t * vam)
14814 {
14815   u8 *name = 0;
14816
14817   if (unformat (vam->input, "%s", &name))
14818     if (clib_macro_unset (&vam->macro_main, (char *) name) == 1)
14819       errmsg ("unset: %s wasn't set", name);
14820   vec_free (name);
14821   return 0;
14822 }
14823
14824 typedef struct
14825 {
14826   u8 *name;
14827   u8 *value;
14828 } macro_sort_t;
14829
14830
14831 static int
14832 macro_sort_cmp (void *a1, void *a2)
14833 {
14834   macro_sort_t *s1 = a1;
14835   macro_sort_t *s2 = a2;
14836
14837   return strcmp ((char *) (s1->name), (char *) (s2->name));
14838 }
14839
14840 static int
14841 dump_macro_table (vat_main_t * vam)
14842 {
14843   macro_sort_t *sort_me = 0, *sm;
14844   int i;
14845   hash_pair_t *p;
14846
14847     /* *INDENT-OFF* */
14848     hash_foreach_pair (p, vam->macro_main.the_value_table_hash,
14849     ({
14850       vec_add2 (sort_me, sm, 1);
14851       sm->name = (u8 *)(p->key);
14852       sm->value = (u8 *) (p->value[0]);
14853     }));
14854     /* *INDENT-ON* */
14855
14856   vec_sort_with_function (sort_me, macro_sort_cmp);
14857
14858   if (vec_len (sort_me))
14859     print (vam->ofp, "%-15s%s", "Name", "Value");
14860   else
14861     print (vam->ofp, "The macro table is empty...");
14862
14863   for (i = 0; i < vec_len (sort_me); i++)
14864     print (vam->ofp, "%-15s%s", sort_me[i].name, sort_me[i].value);
14865   return 0;
14866 }
14867
14868 static int
14869 dump_node_table (vat_main_t * vam)
14870 {
14871   int i, j;
14872   vlib_node_t *node, *next_node;
14873
14874   if (vec_len (vam->graph_nodes) == 0)
14875     {
14876       print (vam->ofp, "Node table empty, issue get_node_graph...");
14877       return 0;
14878     }
14879
14880   for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
14881     {
14882       node = vam->graph_nodes[0][i];
14883       print (vam->ofp, "[%d] %s", i, node->name);
14884       for (j = 0; j < vec_len (node->next_nodes); j++)
14885         {
14886           if (node->next_nodes[j] != ~0)
14887             {
14888               next_node = vam->graph_nodes[0][node->next_nodes[j]];
14889               print (vam->ofp, "  [%d] %s", j, next_node->name);
14890             }
14891         }
14892     }
14893   return 0;
14894 }
14895
14896 static int
14897 value_sort_cmp (void *a1, void *a2)
14898 {
14899   name_sort_t *n1 = a1;
14900   name_sort_t *n2 = a2;
14901
14902   if (n1->value < n2->value)
14903     return -1;
14904   if (n1->value > n2->value)
14905     return 1;
14906   return 0;
14907 }
14908
14909
14910 static int
14911 dump_msg_api_table (vat_main_t * vam)
14912 {
14913   api_main_t *am = vlibapi_get_main ();
14914   name_sort_t *nses = 0, *ns;
14915   hash_pair_t *hp;
14916   int i;
14917
14918   /* *INDENT-OFF* */
14919   hash_foreach_pair (hp, am->msg_index_by_name_and_crc,
14920   ({
14921     vec_add2 (nses, ns, 1);
14922     ns->name = (u8 *)(hp->key);
14923     ns->value = (u32) hp->value[0];
14924   }));
14925   /* *INDENT-ON* */
14926
14927   vec_sort_with_function (nses, value_sort_cmp);
14928
14929   for (i = 0; i < vec_len (nses); i++)
14930     print (vam->ofp, " [%d]: %s", nses[i].value, nses[i].name);
14931   vec_free (nses);
14932   return 0;
14933 }
14934
14935 static int
14936 get_msg_id (vat_main_t * vam)
14937 {
14938   u8 *name_and_crc;
14939   u32 message_index;
14940
14941   if (unformat (vam->input, "%s", &name_and_crc))
14942     {
14943       message_index = vl_msg_api_get_msg_index (name_and_crc);
14944       if (message_index == ~0)
14945         {
14946           print (vam->ofp, " '%s' not found", name_and_crc);
14947           return 0;
14948         }
14949       print (vam->ofp, " '%s' has message index %d",
14950              name_and_crc, message_index);
14951       return 0;
14952     }
14953   errmsg ("name_and_crc required...");
14954   return 0;
14955 }
14956
14957 static int
14958 search_node_table (vat_main_t * vam)
14959 {
14960   unformat_input_t *line_input = vam->input;
14961   u8 *node_to_find;
14962   int j;
14963   vlib_node_t *node, *next_node;
14964   uword *p;
14965
14966   if (vam->graph_node_index_by_name == 0)
14967     {
14968       print (vam->ofp, "Node table empty, issue get_node_graph...");
14969       return 0;
14970     }
14971
14972   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
14973     {
14974       if (unformat (line_input, "%s", &node_to_find))
14975         {
14976           vec_add1 (node_to_find, 0);
14977           p = hash_get_mem (vam->graph_node_index_by_name, node_to_find);
14978           if (p == 0)
14979             {
14980               print (vam->ofp, "%s not found...", node_to_find);
14981               goto out;
14982             }
14983           node = vam->graph_nodes[0][p[0]];
14984           print (vam->ofp, "[%d] %s", p[0], node->name);
14985           for (j = 0; j < vec_len (node->next_nodes); j++)
14986             {
14987               if (node->next_nodes[j] != ~0)
14988                 {
14989                   next_node = vam->graph_nodes[0][node->next_nodes[j]];
14990                   print (vam->ofp, "  [%d] %s", j, next_node->name);
14991                 }
14992             }
14993         }
14994
14995       else
14996         {
14997           clib_warning ("parse error '%U'", format_unformat_error,
14998                         line_input);
14999           return -99;
15000         }
15001
15002     out:
15003       vec_free (node_to_find);
15004
15005     }
15006
15007   return 0;
15008 }
15009
15010
15011 static int
15012 script (vat_main_t * vam)
15013 {
15014 #if (VPP_API_TEST_BUILTIN==0)
15015   u8 *s = 0;
15016   char *save_current_file;
15017   unformat_input_t save_input;
15018   jmp_buf save_jump_buf;
15019   u32 save_line_number;
15020
15021   FILE *new_fp, *save_ifp;
15022
15023   if (unformat (vam->input, "%s", &s))
15024     {
15025       new_fp = fopen ((char *) s, "r");
15026       if (new_fp == 0)
15027         {
15028           errmsg ("Couldn't open script file %s", s);
15029           vec_free (s);
15030           return -99;
15031         }
15032     }
15033   else
15034     {
15035       errmsg ("Missing script name");
15036       return -99;
15037     }
15038
15039   clib_memcpy (&save_input, &vam->input, sizeof (save_input));
15040   clib_memcpy (&save_jump_buf, &vam->jump_buf, sizeof (save_jump_buf));
15041   save_ifp = vam->ifp;
15042   save_line_number = vam->input_line_number;
15043   save_current_file = (char *) vam->current_file;
15044
15045   vam->input_line_number = 0;
15046   vam->ifp = new_fp;
15047   vam->current_file = s;
15048   do_one_file (vam);
15049
15050   clib_memcpy (&vam->input, &save_input, sizeof (save_input));
15051   clib_memcpy (&vam->jump_buf, &save_jump_buf, sizeof (save_jump_buf));
15052   vam->ifp = save_ifp;
15053   vam->input_line_number = save_line_number;
15054   vam->current_file = (u8 *) save_current_file;
15055   vec_free (s);
15056
15057   return 0;
15058 #else
15059   clib_warning ("use the exec command...");
15060   return -99;
15061 #endif
15062 }
15063
15064 static int
15065 echo (vat_main_t * vam)
15066 {
15067   print (vam->ofp, "%v", vam->input->buffer);
15068   return 0;
15069 }
15070
15071 /* List of API message constructors, CLI names map to api_xxx */
15072 #define foreach_vpe_api_msg                                             \
15073 _(create_loopback,"[mac <mac-addr>] [instance <instance>]")             \
15074 _(sw_interface_dump,"")                                                 \
15075 _(sw_interface_set_flags,                                               \
15076   "<intfc> | sw_if_index <id> admin-up | admin-down link-up | link down") \
15077 _(sw_interface_add_del_address,                                         \
15078   "<intfc> | sw_if_index <id> <ip4-address> | <ip6-address> [del] [del-all] ") \
15079 _(sw_interface_set_rx_mode,                                             \
15080   "<intfc> | sw_if_index <id> [queue <id>] <polling | interrupt | adaptive>") \
15081 _(sw_interface_set_rx_placement,                                        \
15082   "<intfc> | sw_if_index <id> [queue <id>] [worker <id> | main]")       \
15083 _(sw_interface_rx_placement_dump,                                       \
15084   "[<intfc> | sw_if_index <id>]")                                         \
15085 _(sw_interface_set_table,                                               \
15086   "<intfc> | sw_if_index <id> vrf <table-id> [ipv6]")                   \
15087 _(sw_interface_set_mpls_enable,                                         \
15088   "<intfc> | sw_if_index [disable | dis]")                              \
15089 _(sw_interface_set_vpath,                                               \
15090   "<intfc> | sw_if_index <id> enable | disable")                        \
15091 _(sw_interface_set_vxlan_bypass,                                        \
15092   "<intfc> | sw_if_index <id> [ip4 | ip6] [enable | disable]")          \
15093 _(sw_interface_set_l2_xconnect,                                         \
15094   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
15095   "enable | disable")                                                   \
15096 _(sw_interface_set_l2_bridge,                                           \
15097   "{<intfc> | sw_if_index <id>} bd_id <bridge-domain-id>\n"             \
15098   "[shg <split-horizon-group>] [bvi]\n"                                 \
15099   "enable | disable")                                                   \
15100 _(bridge_domain_set_mac_age, "bd_id <bridge-domain-id> mac-age 0-255")  \
15101 _(bridge_domain_add_del,                                                \
15102   "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") \
15103 _(bridge_domain_dump, "[bd_id <bridge-domain-id>]\n")                   \
15104 _(l2fib_add_del,                                                        \
15105   "mac <mac-addr> bd_id <bridge-domain-id> [del] | sw_if <intfc> | sw_if_index <id> [static] [filter] [bvi] [count <nn>]\n") \
15106 _(l2fib_flush_bd, "bd_id <bridge-domain-id>")                           \
15107 _(l2fib_flush_int, "<intfc> | sw_if_index <id>")                        \
15108 _(l2_flags,                                                             \
15109   "sw_if <intfc> | sw_if_index <id> [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \
15110 _(bridge_flags,                                                         \
15111   "bd_id <bridge-domain-id> [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \
15112 _(tap_create_v2,                                                        \
15113   "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]") \
15114 _(tap_delete_v2,                                                        \
15115   "<vpp-if-name> | sw_if_index <id>")                                   \
15116 _(sw_interface_tap_v2_dump, "")                                         \
15117 _(virtio_pci_create_v2,                                                    \
15118   "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]") \
15119 _(virtio_pci_delete,                                                    \
15120   "<vpp-if-name> | sw_if_index <id>")                                   \
15121 _(sw_interface_virtio_pci_dump, "")                                     \
15122 _(bond_create,                                                          \
15123   "[hw-addr <mac-addr>] {round-robin | active-backup | "                \
15124   "broadcast | {lacp | xor} [load-balance { l2 | l23 | l34 }]} "        \
15125   "[id <if-id>]")                                                       \
15126 _(bond_create2,                                                         \
15127   "[hw-addr <mac-addr>] {mode round-robin | active-backup | "           \
15128   "broadcast | {lacp | xor} [load-balance { l2 | l23 | l34 }]} "        \
15129   "[id <if-id>] [gso]")                                                 \
15130 _(bond_delete,                                                          \
15131   "<vpp-if-name> | sw_if_index <id>")                                   \
15132 _(bond_add_member,                                                      \
15133   "sw_if_index <n> bond <sw_if_index> [is_passive] [is_long_timeout]")  \
15134 _(bond_detach_member,                                                   \
15135   "sw_if_index <n>")                                                    \
15136  _(sw_interface_set_bond_weight, "<intfc> | sw_if_index <nn> weight <value>") \
15137  _(sw_bond_interface_dump, "<intfc> | sw_if_index <nn>")                \
15138  _(sw_member_interface_dump,                                            \
15139   "<vpp-if-name> | sw_if_index <id>")                                   \
15140 _(ip_table_add_del,                                                     \
15141   "table <n> [ipv6] [add | del]\n")                                     \
15142 _(ip_route_add_del,                                                     \
15143   "<addr>/<mask> via <<addr>|<intfc>|sw_if_index <id>|via-label <n>>\n" \
15144   "[table-id <n>] [<intfc> | sw_if_index <id>] [resolve-attempts <n>]\n"\
15145   "[weight <n>] [drop] [local] [classify <n>]  [out-label <n>]\n"       \
15146   "[multipath] [count <n>] [del]")                                      \
15147 _(ip_mroute_add_del,                                                    \
15148   "<src> <grp>/<mask> [table-id <n>]\n"                                 \
15149   "[<intfc> | sw_if_index <id>] [local] [del]")                         \
15150 _(mpls_table_add_del,                                                   \
15151   "table <n> [add | del]\n")                                            \
15152 _(mpls_route_add_del,                                                   \
15153   "<label> <eos> via <addr | next-hop-table <n> | via-label <n> |\n"    \
15154   "lookup-ip4-table <n> | lookup-in-ip6-table <n> |\n"                  \
15155   "l2-input-on <intfc> | l2-input-on sw_if_index <id>>\n"               \
15156   "[<intfc> | sw_if_index <id>] [resolve-attempts <n>] [weight <n>]\n"  \
15157   "[drop] [local] [classify <n>] [out-label <n>] [multipath]\n"         \
15158   "[count <n>] [del]")                                                  \
15159 _(mpls_ip_bind_unbind,                                                  \
15160   "<label> <addr/len>")                                                 \
15161 _(mpls_tunnel_add_del,                                                  \
15162   "[add | del <intfc | sw_if_index <id>>] via <addr | via-label <n>>\n" \
15163   "[<intfc> | sw_if_index <id> | next-hop-table <id>]\n"                \
15164   "[l2-only]  [out-label <n>]")                                         \
15165 _(sr_mpls_policy_add,                                                   \
15166   "bsid <id> [weight <n>] [spray] next <sid> [next <sid>]")             \
15167 _(sr_mpls_policy_del,                                                   \
15168   "bsid <id>")                                                          \
15169 _(bier_table_add_del,                                                   \
15170   "<label> <sub-domain> <set> <bsl> [del]")                             \
15171 _(bier_route_add_del,                                                   \
15172   "<bit-position> <sub-domain> <set> <bsl> via <addr> [table-id <n>]\n" \
15173   "[<intfc> | sw_if_index <id>]"                                        \
15174   "[weight <n>] [del] [multipath]")                                     \
15175 _(sw_interface_set_unnumbered,                                          \
15176   "<intfc> | sw_if_index <id> unnum_if_index <id> [del]")               \
15177 _(create_vlan_subif, "<intfc> | sw_if_index <id> vlan <n>")             \
15178 _(create_subif, "<intfc> | sw_if_index <id> sub_id <n>\n"               \
15179   "[outer_vlan_id <n>][inner_vlan_id <n>]\n"                            \
15180   "[no_tags][one_tag][two_tags][dot1ad][exact_match][default_sub]\n"    \
15181   "[outer_vlan_id_any][inner_vlan_id_any]")                             \
15182 _(ip_table_replace_begin, "table <n> [ipv6]")                           \
15183 _(ip_table_flush, "table <n> [ipv6]")                                   \
15184 _(ip_table_replace_end, "table <n> [ipv6]")                             \
15185 _(set_ip_flow_hash,                                                     \
15186   "vrf <n> [src] [dst] [sport] [dport] [proto] [reverse] [ipv6]")       \
15187 _(sw_interface_ip6_enable_disable,                                      \
15188   "<intfc> | sw_if_index <id> enable | disable")                        \
15189 _(l2_patch_add_del,                                                     \
15190   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
15191   "enable | disable")                                                   \
15192 _(sr_localsid_add_del,                                                  \
15193   "(del) address <addr> next_hop <addr> behavior <beh>\n"               \
15194   "fib-table <num> (end.psp) sw_if_index <num>")                        \
15195 _(classify_add_del_table,                                               \
15196   "buckets <nn> [skip <n>] [match <n>] [memory_size <nn-bytes>]\n"      \
15197   " [del] [del-chain] mask <mask-value>\n"                              \
15198   " [l2-miss-next | miss-next | acl-miss-next] <name|nn>\n"             \
15199   " [current-data-flag <n>] [current-data-offset <nn>] [table <nn>]")   \
15200 _(classify_add_del_session,                                             \
15201   "[hit-next|l2-hit-next|acl-hit-next|policer-hit-next] <name|nn>\n"    \
15202   "  table-index <nn> skip_n <nn> match_n <nn> match [hex] [l2]\n"      \
15203   "  [l3 [ip4|ip6]] [action set-ip4-fib-id <nn>]\n"                     \
15204   "  [action set-ip6-fib-id <nn> | action <n> metadata <nn>] [del]")    \
15205 _(classify_set_interface_ip_table,                                      \
15206   "<intfc> | sw_if_index <nn> table <nn>")                              \
15207 _(classify_set_interface_l2_tables,                                     \
15208   "<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>]\n"      \
15209   "  [other-table <nn>]")                                               \
15210 _(get_node_index, "node <node-name")                                    \
15211 _(add_node_next, "node <node-name> next <next-node-name>")              \
15212 _(vxlan_offload_rx,                                                     \
15213   "hw { <interface name> | hw_if_index <nn>} "                          \
15214   "rx { <vxlan tunnel name> | sw_if_index <nn> } [del]")                \
15215 _(vxlan_add_del_tunnel,                                                 \
15216   "src <ip-addr> { dst <ip-addr> | group <mcast-ip-addr>\n"             \
15217   "{ <intfc> | mcast_sw_if_index <nn> } [instance <id>]}\n"             \
15218   "vni <vni> [encap-vrf-id <nn>] [decap-next <l2|nn>] [del]")           \
15219 _(vxlan_tunnel_dump, "[<intfc> | sw_if_index <nn>]")                    \
15220 _(gre_tunnel_add_del,                                                   \
15221   "src <ip-addr> dst <ip-addr> [outer-fib-id <nn>] [instance <n>]\n"    \
15222   "[teb | erspan <session-id>] [del]")                                  \
15223 _(gre_tunnel_dump, "[<intfc> | sw_if_index <nn>]")                      \
15224 _(l2_fib_clear_table, "")                                               \
15225 _(l2_interface_efp_filter, "sw_if_index <nn> enable | disable")         \
15226 _(l2_interface_vlan_tag_rewrite,                                        \
15227   "<intfc> | sw_if_index <nn> \n"                                       \
15228   "[disable][push-[1|2]][pop-[1|2]][translate-1-[1|2]] \n"              \
15229   "[translate-2-[1|2]] [push_dot1q 0] tag1 <nn> tag2 <nn>")             \
15230 _(create_vhost_user_if,                                                 \
15231         "socket <filename> [server] [renumber <dev_instance>] "         \
15232         "[disable_mrg_rxbuf] [disable_indirect_desc] [gso] "            \
15233         "[mac <mac_address>] [packed]")                                 \
15234 _(modify_vhost_user_if,                                                 \
15235         "<intfc> | sw_if_index <nn> socket <filename>\n"                \
15236         "[server] [renumber <dev_instance>] [gso] [packed]")            \
15237 _(delete_vhost_user_if, "<intfc> | sw_if_index <nn>")                   \
15238 _(sw_interface_vhost_user_dump, "<intfc> | sw_if_index <nn>")           \
15239 _(show_version, "")                                                     \
15240 _(show_threads, "")                                                     \
15241 _(vxlan_gpe_add_del_tunnel,                                             \
15242   "local <addr> remote <addr>  | group <mcast-ip-addr>\n"               \
15243   "{ <intfc> | mcast_sw_if_index <nn> } }\n"                            \
15244   "vni <nn> [encap-vrf-id <nn>] [decap-vrf-id <nn>]\n"                  \
15245   "[next-ip4][next-ip6][next-ethernet] [next-nsh] [del]\n")             \
15246 _(vxlan_gpe_tunnel_dump, "[<intfc> | sw_if_index <nn>]")                \
15247 _(l2_fib_table_dump, "bd_id <bridge-domain-id>")                        \
15248 _(interface_name_renumber,                                              \
15249   "<intfc> | sw_if_index <nn> new_show_dev_instance <nn>")              \
15250 _(input_acl_set_interface,                                              \
15251   "<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>]\n"      \
15252   "  [l2-table <nn>] [del]")                                            \
15253 _(want_l2_macs_events, "[disable] [learn-limit <n>] [scan-delay <n>] [max-entries <n>]") \
15254 _(ip_address_dump, "(ipv4 | ipv6) (<intfc> | sw_if_index <id>)")        \
15255 _(ip_dump, "ipv4 | ipv6")                                               \
15256 _(ipsec_spd_add_del, "spd_id <n> [del]")                                \
15257 _(ipsec_interface_add_del_spd, "(<intfc> | sw_if_index <id>)\n"         \
15258   "  spid_id <n> ")                                                     \
15259 _(ipsec_sad_entry_add_del, "sad_id <n> spi <n> crypto_alg <alg>\n"      \
15260   "  crypto_key <hex> tunnel_src <ip4|ip6> tunnel_dst <ip4|ip6>\n"      \
15261   "  integ_alg <alg> integ_key <hex>")                                  \
15262 _(ipsec_spd_entry_add_del, "spd_id <n> priority <n> action <action>\n"  \
15263   "  (inbound|outbound) [sa_id <n>] laddr_start <ip4|ip6>\n"            \
15264   "  laddr_stop <ip4|ip6> raddr_start <ip4|ip6> raddr_stop <ip4|ip6>\n" \
15265   "  [lport_start <n> lport_stop <n>] [rport_start <n> rport_stop <n>]" ) \
15266 _(ipsec_tunnel_if_add_del, "local_spi <n> remote_spi <n>\n"             \
15267   "  crypto_alg <alg> local_crypto_key <hex> remote_crypto_key <hex>\n" \
15268   "  integ_alg <alg> local_integ_key <hex> remote_integ_key <hex>\n"    \
15269   "  local_ip <addr> remote_ip <addr> [esn] [anti_replay] [del]\n"      \
15270   "  [instance <n>]")     \
15271 _(ipsec_sa_dump, "[sa_id <n>]")                                         \
15272 _(ipsec_tunnel_if_set_sa, "<intfc> sa_id <n> <inbound|outbound>\n")     \
15273 _(delete_loopback,"sw_if_index <nn>")                                   \
15274 _(bd_ip_mac_add_del, "bd_id <bridge-domain-id> <ip4/6-addr> <mac-addr> [del]") \
15275 _(bd_ip_mac_flush, "bd_id <bridge-domain-id>")                          \
15276 _(bd_ip_mac_dump, "[bd_id] <bridge-domain-id>")                         \
15277 _(want_interface_events,  "enable|disable")                             \
15278 _(get_first_msg_id, "client <name>")                                    \
15279 _(cop_interface_enable_disable, "<intfc> | sw_if_index <nn> [disable]") \
15280 _(cop_whitelist_enable_disable, "<intfc> | sw_if_index <nn>\n"          \
15281   "fib-id <nn> [ip4][ip6][default]")                                    \
15282 _(get_node_graph, " ")                                                  \
15283 _(sw_interface_clear_stats,"<intfc> | sw_if_index <nn>")                \
15284 _(ioam_enable, "[trace] [pow] [ppc <encap|decap>]")                     \
15285 _(ioam_disable, "")                                                     \
15286 _(af_packet_create, "name <host interface name> [hw_addr <mac>]")       \
15287 _(af_packet_delete, "name <host interface name>")                       \
15288 _(af_packet_dump, "")                                                   \
15289 _(policer_add_del, "name <policer name> <params> [del]")                \
15290 _(policer_dump, "[name <policer name>]")                                \
15291 _(policer_classify_set_interface,                                       \
15292   "<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>]\n"      \
15293   "  [l2-table <nn>] [del]")                                            \
15294 _(policer_classify_dump, "type [ip4|ip6|l2]")                           \
15295 _(mpls_tunnel_dump, "tunnel_index <tunnel-id>")                         \
15296 _(mpls_table_dump, "")                                                  \
15297 _(mpls_route_dump, "table-id <ID>")                                     \
15298 _(classify_table_ids, "")                                               \
15299 _(classify_table_by_interface, "sw_if_index <sw_if_index>")             \
15300 _(classify_table_info, "table_id <nn>")                                 \
15301 _(classify_session_dump, "table_id <nn>")                               \
15302 _(set_ipfix_exporter, "collector_address <ip4> [collector_port <nn>] "  \
15303     "src_address <ip4> [vrf_id <nn>] [path_mtu <nn>] "                  \
15304     "[template_interval <nn>] [udp_checksum]")                          \
15305 _(ipfix_exporter_dump, "")                                              \
15306 _(set_ipfix_classify_stream, "[domain <domain-id>] [src_port <src-port>]") \
15307 _(ipfix_classify_stream_dump, "")                                       \
15308 _(ipfix_classify_table_add_del, "table <table-index> ip4|ip6 [tcp|udp]") \
15309 _(ipfix_classify_table_dump, "")                                        \
15310 _(sw_interface_span_enable_disable, "[l2] [src <intfc> | src_sw_if_index <id>] [disable | [[dst <intfc> | dst_sw_if_index <id>] [both|rx|tx]]]") \
15311 _(sw_interface_span_dump, "[l2]")                                           \
15312 _(get_next_index, "node-name <node-name> next-node-name <node-name>")   \
15313 _(pg_create_interface, "if_id <nn> [gso-enabled gso-size <size>]")      \
15314 _(pg_capture, "if_id <nnn> pcap <file_name> count <nnn> [disable]")     \
15315 _(pg_enable_disable, "[stream <id>] disable")                           \
15316 _(pg_interface_enable_disable_coalesce, "<intf> | sw_if_index <nn> enable | disable")  \
15317 _(ip_source_and_port_range_check_add_del,                               \
15318   "<ip-addr>/<mask> range <nn>-<nn> vrf <id>")                          \
15319 _(ip_source_and_port_range_check_interface_add_del,                     \
15320   "<intf> | sw_if_index <nn> [tcp-out-vrf <id>] [tcp-in-vrf <id>]"      \
15321   "[udp-in-vrf <id>] [udp-out-vrf <id>]")                               \
15322 _(delete_subif,"<intfc> | sw_if_index <nn>")                            \
15323 _(l2_interface_pbb_tag_rewrite,                                         \
15324   "<intfc> | sw_if_index <nn> \n"                                       \
15325   "[disable | push | pop | translate_pbb_stag <outer_tag>] \n"          \
15326   "dmac <mac> smac <mac> sid <nn> [vlanid <nn>]")                       \
15327 _(set_punt, "protocol <l4-protocol> [ip <ver>] [port <l4-port>] [del]")     \
15328 _(flow_classify_set_interface,                                          \
15329   "<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>] [del]") \
15330 _(flow_classify_dump, "type [ip4|ip6]")                                 \
15331 _(ip_table_dump, "")                                                    \
15332 _(ip_route_dump, "table-id [ip4|ip6]")                                  \
15333 _(ip_mtable_dump, "")                                                   \
15334 _(ip_mroute_dump, "table-id [ip4|ip6]")                                 \
15335 _(feature_enable_disable, "arc_name <arc_name> "                        \
15336   "feature_name <feature_name> <intfc> | sw_if_index <nn> [disable]")   \
15337 _(feature_gso_enable_disable, "<intfc> | sw_if_index <nn> "             \
15338   "[enable | disable] ")                                                \
15339 _(sw_interface_tag_add_del, "<intfc> | sw_if_index <nn> tag <text>"     \
15340 "[disable]")                                                            \
15341 _(sw_interface_add_del_mac_address, "<intfc> | sw_if_index <nn> "       \
15342   "mac <mac-address> [del]")                                            \
15343 _(l2_xconnect_dump, "")                                                 \
15344 _(hw_interface_set_mtu, "<intfc> | hw_if_index <nn> mtu <nn>")        \
15345 _(sw_interface_get_table, "<intfc> | sw_if_index <id> [ipv6]")          \
15346 _(p2p_ethernet_add, "<intfc> | sw_if_index <nn> remote_mac <mac-address> sub_id <id>") \
15347 _(p2p_ethernet_del, "<intfc> | sw_if_index <nn> remote_mac <mac-address>") \
15348 _(tcp_configure_src_addresses, "<ip4|6>first-<ip4|6>last [vrf <id>]")   \
15349 _(sock_init_shm, "size <nnn>")                                          \
15350 _(app_namespace_add_del, "[add] id <ns-id> secret <nn> sw_if_index <nn>")\
15351 _(session_rule_add_del, "[add|del] proto <tcp/udp> <lcl-ip>/<plen> "    \
15352   "<lcl-port> <rmt-ip>/<plen> <rmt-port> action <nn>")                  \
15353 _(session_rules_dump, "")                                               \
15354 _(ip_container_proxy_add_del, "[add|del] <address> <sw_if_index>")      \
15355 _(output_acl_set_interface,                                             \
15356   "<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>]\n"      \
15357   "  [l2-table <nn>] [del]")                                            \
15358 _(qos_record_enable_disable, "<record-source> <intfc> | sw_if_index <id> [disable]")
15359
15360 /* List of command functions, CLI names map directly to functions */
15361 #define foreach_cli_function                                    \
15362 _(comment, "usage: comment <ignore-rest-of-line>")              \
15363 _(dump_interface_table, "usage: dump_interface_table")          \
15364 _(dump_sub_interface_table, "usage: dump_sub_interface_table")  \
15365 _(dump_ipv4_table, "usage: dump_ipv4_table")                    \
15366 _(dump_ipv6_table, "usage: dump_ipv6_table")                    \
15367 _(dump_macro_table, "usage: dump_macro_table ")                 \
15368 _(dump_node_table, "usage: dump_node_table")                    \
15369 _(dump_msg_api_table, "usage: dump_msg_api_table")              \
15370 _(elog_setup, "usage: elog_setup [nevents, default 128K]")      \
15371 _(elog_disable, "usage: elog_disable")                          \
15372 _(elog_enable, "usage: elog_enable")                            \
15373 _(elog_save, "usage: elog_save <filename>")                     \
15374 _(get_msg_id, "usage: get_msg_id name_and_crc")                 \
15375 _(echo, "usage: echo <message>")                                \
15376 _(exec, "usage: exec <vpe-debug-CLI-command>")                  \
15377 _(exec_inband, "usage: exec_inband <vpe-debug-CLI-command>")    \
15378 _(help, "usage: help")                                          \
15379 _(q, "usage: quit")                                             \
15380 _(quit, "usage: quit")                                          \
15381 _(search_node_table, "usage: search_node_table <name>...")      \
15382 _(set, "usage: set <variable-name> <value>")                    \
15383 _(script, "usage: script <file-name>")                          \
15384 _(statseg, "usage: statseg")                                    \
15385 _(unset, "usage: unset <variable-name>")
15386
15387 #define _(N,n)                                  \
15388     static void vl_api_##n##_t_handler_uni      \
15389     (vl_api_##n##_t * mp)                       \
15390     {                                           \
15391         vat_main_t * vam = &vat_main;           \
15392         if (vam->json_output) {                 \
15393             vl_api_##n##_t_handler_json(mp);    \
15394         } else {                                \
15395             vl_api_##n##_t_handler(mp);         \
15396         }                                       \
15397     }
15398 foreach_vpe_api_reply_msg;
15399 #if VPP_API_TEST_BUILTIN == 0
15400 foreach_standalone_reply_msg;
15401 #endif
15402 #undef _
15403
15404 void
15405 vat_api_hookup (vat_main_t * vam)
15406 {
15407 #define _(N,n)                                                  \
15408     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
15409                            vl_api_##n##_t_handler_uni,          \
15410                            vl_noop_handler,                     \
15411                            vl_api_##n##_t_endian,               \
15412                            vl_api_##n##_t_print,                \
15413                            sizeof(vl_api_##n##_t), 1);
15414   foreach_vpe_api_reply_msg;
15415 #if VPP_API_TEST_BUILTIN == 0
15416   foreach_standalone_reply_msg;
15417 #endif
15418 #undef _
15419
15420 #if (VPP_API_TEST_BUILTIN==0)
15421   vl_msg_api_set_first_available_msg_id (VL_MSG_FIRST_AVAILABLE);
15422
15423   vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
15424
15425   vam->function_by_name = hash_create_string (0, sizeof (uword));
15426
15427   vam->help_by_name = hash_create_string (0, sizeof (uword));
15428 #endif
15429
15430   /* API messages we can send */
15431 #define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
15432   foreach_vpe_api_msg;
15433 #undef _
15434
15435   /* Help strings */
15436 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
15437   foreach_vpe_api_msg;
15438 #undef _
15439
15440   /* CLI functions */
15441 #define _(n,h) hash_set_mem (vam->function_by_name, #n, n);
15442   foreach_cli_function;
15443 #undef _
15444
15445   /* Help strings */
15446 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
15447   foreach_cli_function;
15448 #undef _
15449 }
15450
15451 #if VPP_API_TEST_BUILTIN
15452 static clib_error_t *
15453 vat_api_hookup_shim (vlib_main_t * vm)
15454 {
15455   vat_api_hookup (&vat_main);
15456   return 0;
15457 }
15458
15459 VLIB_API_INIT_FUNCTION (vat_api_hookup_shim);
15460 #endif
15461
15462 /*
15463  * fd.io coding-style-patch-verification: ON
15464  *
15465  * Local Variables:
15466  * eval: (c-set-style "gnu")
15467  * End:
15468  */